⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 textdiagram.cpp

📁 TabBars的开源源码
💻 CPP
📖 第 1 页 / 共 4 页
字号:
// TextDiagram.cpp: implementation of the CTextDiagram class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "TextDiagram.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

// rects
#define CHAR_TOP '-'
#define CHAR_RIGHT '|'
#define CHAR_BOTTOM '-'
#define CHAR_LEFT '|'

// connections
#define CHAR_HORZ '-'
#define CHAR_VERT '|'
#define CHAR_END '*'
#define CHAR_ENDUP '^'
#define CHAR_ENDDOWN 'v'
#define CHAR_ENDLEFT '<'
#define CHAR_ENDRIGHT '>'
#define CHAR_CROSSOVER '+'
#define CHAR_START '#' 

// misc
#define ENDL '\n'
#define SPACE ' '

const int MAXITERATIONS = 1000;

//////////////////////////////////////////////////////////////////////

CTDRect::CTDRect(const CRect& rect, LPCTSTR szText) : CRect(rect), m_sText(szText)
{
}

CTDRect::CTDRect()
{ 
	SetRectEmpty(); 
}

CTDRect::~CTDRect()
{
}

const CTDRect& CTDRect::operator=(const CTDRect& rect)
{
	CopyRect(rect);
	SetText(rect.GetText());

	return *this;
}
/*
BOOL CTDRect::operator==(const CTDRect& rect)
{
	return EqualRect(rect);
}

BOOL CTDRect::operator!=(const CTDRect& rect)
{
	return !EqualRect(rect);
}
*/
int CTDRect::GetSide(CPoint point)
{
	if (point.x == left)
		return RECT_LEFT;

	else if (point.x == right)
		return RECT_RIGHT;

	else if (point.y == top)
		return RECT_TOP;

	else if (point.y == bottom)
		return RECT_BOTTOM;

	else
		return NONE;
}

//////////////////////////////////////////////////////////////////////

CTDConnection::CTDConnection(int nRectFrom, int nRectTo, int nSideFrom) :
	m_nRectFrom(nRectFrom), m_nRectTo(nRectTo), m_nSideFrom(nSideFrom), m_ptFrom(0, 0)
{
}

CTDConnection::CTDConnection() : m_nRectFrom(0), m_nRectTo(0), m_ptFrom(0, 0)
{
}

CTDConnection::~CTDConnection()
{
}

const CTDConnection& CTDConnection::operator=(const CTDConnection& conn)
{
	m_nRectFrom = conn.m_nRectFrom;
	m_nRectTo = conn.m_nRectTo;
	m_nSideFrom = conn.m_nSideFrom;
	m_ptFrom = conn.m_ptFrom;
	m_aSegments.Copy(conn.m_aSegments);

	return *this;
}
/*
BOOL CTDConnection::operator==(const CTDConnection& conn)
{
	// note: we don't rect indices because these can change
	// instead we check the actual character positions
	if (m_nSideFrom != conn.m_nSideFrom)
		return FALSE;

	if (m_ptFrom != conn.m_ptFrom)
		return FALSE;

	if (NumSegments() != conn.NumSegments())
		return FALSE;

	for (int nSegment = 0; nSegment < NumSegments(); nSegment++)
	{
		if (m_aSegments[nSegment] != conn.m_aSegments[nSegment])
		return FALSE;
	}

	return TRUE;
}

BOOL CTDConnection::operator!=(const CTDConnection& conn)
{
	return (!(*this == conn));
}
*/
CPoint CTDConnection::GetEndPos(int nNextSegment) const
{
	CPoint ptEnd = GetSegmentPos(NumSegments() - 1);
	int nDir = GetEndDirection(nNextSegment);

	// nNextSegment
	switch (nDir)
	{
	case CONN_UP:
	case CONN_DOWN:
		ptEnd.y += nNextSegment;
		break;
		
	case CONN_RIGHT:
	case CONN_LEFT:
		ptEnd.x += nNextSegment;
		break;
	}

	return ptEnd;
}

CPoint CTDConnection::GetSegmentPos(int nSegment) const
{
	if (nSegment < 0)
		return GetStartPos();

	int nDir = GetStartDirection();
	CPoint ptEnd = GetStartPos();

	int nLastSegment = min(nSegment, NumSegments() - 1);

	for (nSegment = 0; nSegment <= nLastSegment; nSegment++)
	{
		switch (nDir)
		{
		case CONN_UP:
		case CONN_DOWN:
			ptEnd.y += m_aSegments[nSegment];
			nDir = CONN_LEFT; // same effect as CONN_RIGHT
			break;

		case CONN_RIGHT:
		case CONN_LEFT:
			ptEnd.x += m_aSegments[nSegment];
			nDir = CONN_UP; // same effect as CONN_DOWN
			break;
		}
	}

	return ptEnd;
}

int CTDConnection::GetLength() const
{
	int nLength = 0;
	int nSegment = NumSegments();

	while (nSegment--)
		nLength += abs(Segment(nSegment));

	return nLength;
}

int CTDConnection::GetEndDirection(int nNextSegment) const
{
	int nDir = GetStartDirection();

	for (int nSegment = 1; nSegment < NumSegments(); nSegment++)
	{
		switch (nDir)
		{
		case CONN_UP:
		case CONN_DOWN:
			nDir = m_aSegments[nSegment] < 0 ? CONN_LEFT : CONN_RIGHT;
			break;

		case CONN_RIGHT:
		case CONN_LEFT:
			nDir = m_aSegments[nSegment] < 0 ? CONN_UP : CONN_DOWN;
			break;
		}
	}

	// nNextSegment
	if (nNextSegment && NumSegments())
	{
		switch (nDir)
		{
		case CONN_UP:
		case CONN_DOWN:
			nDir = nNextSegment < 0 ? CONN_LEFT : CONN_RIGHT;
			break;

		case CONN_RIGHT:
		case CONN_LEFT:
			nDir = nNextSegment < 0 ? CONN_UP : CONN_DOWN;
			break;
		}
	}

	return nDir;
}

CRect CTDConnection::GetBoundingRect() const
{
	CRect rBounds(m_ptFrom, CSize(0, 0));

	for (int nSegment = 1; nSegment < NumSegments(); nSegment++)
	{
		CPoint ptEnd = GetSegmentPos(nSegment);

		if (rBounds.left > ptEnd.x)
			rBounds.left = ptEnd.x;

		if (rBounds.right < ptEnd.x)
			rBounds.right = ptEnd.x;

		if (rBounds.top > ptEnd.y)
			rBounds.top = ptEnd.y;

		if (rBounds.bottom < ptEnd.y)
			rBounds.bottom = ptEnd.y;
	}

	return rBounds;
}

int CTDConnection::GetStartDirection() const
{
	switch (m_nSideFrom)
	{
	case RECT_TOP:
		return CONN_UP;

	case RECT_RIGHT:
		return CONN_RIGHT;

	case RECT_BOTTOM:
		return CONN_DOWN;

	case RECT_LEFT:
		return CONN_LEFT;
	}

	return -1;
}

void CTDConnection::Increment(int& nSegment)
{
	ASSERT (nSegment);
	nSegment += (nSegment < 0) ? -1 : 1;
}

void CTDConnection::Decrement(int& nSegment)
{
	ASSERT (nSegment);
	nSegment -= (nSegment < 0) ? -1 : 1;
}

void CTDConnection::AddSegment(int nSegment)
{
	m_aSegments.Add(nSegment);
}

void CTDConnection::IncrementLastSegment()
{
	ASSERT (NumSegments());

	if (NumSegments())
		Increment(m_aSegments[NumSegments() - 1]);
}

BOOL CTDConnection::PtInConn(CPoint point, BOOL bHorz) const
{
	// iterate all the segments testing each one for an overlap in the requested orientation
	int nDir = GetStartDirection();

	CPoint ptStart, ptEnd = GetStartPos();

	for (int nSegment = 0; nSegment < NumSegments(); nSegment++)
	{
		ptStart = ptEnd;

		switch (nDir)
		{
		case CONN_UP:
		case CONN_DOWN:
			ptEnd.y += m_aSegments[nSegment];

			// test
			if (!bHorz && point.x == ptEnd.x)
			{
				if ((point.y >= ptStart.y && point.y <= ptEnd.y) ||
					(point.y >= ptEnd.y && point.y <= ptStart.y))
				{
					return TRUE;
				}
			}
			nDir = CONN_LEFT; // same effect as CONN_RIGHT
			break;

		case CONN_RIGHT:
		case CONN_LEFT:
			ptEnd.x += m_aSegments[nSegment];

			// test
			if (bHorz && point.y == ptEnd.y)
			{
				if ((point.x >= ptStart.x && point.x <= ptEnd.x) ||
					(point.x >= ptEnd.x && point.x <= ptStart.x))
				{
					return TRUE;
				}
			}
			nDir = CONN_UP; // same effect as CONN_DOWN
			break;
		}
	}

	return FALSE;
}

//////////////////////////////////////////////////////////////////////

CTextDiagram::CTextDiagram(LPCTSTR szDiagram) : m_size(0, 0)
{
	SetDiagram(szDiagram);
}

CTextDiagram::~CTextDiagram()
{

}

void CTextDiagram::ResetDiagram()
{
	m_sTitle.Empty();
	m_size.cx = m_size.cy = 0;

	m_aRects.RemoveAll();
	m_aConns.RemoveAll();
}

void CTextDiagram::SetDiagram(const CTextDiagram& diagram)
{
	*this = diagram;
}

void CTextDiagram::SetDiagram(LPCTSTR szDiagram)
{
	CStringArray diagram;

	ConvertDiagram(szDiagram, diagram);
	SetDiagram(diagram);
}

void CTextDiagram::SetDiagram(const CStringArray& diagram)
{
	ResetDiagram();
	ProcessDiagram(diagram);
}

int CTextDiagram::ConvertDiagram(LPCTSTR szDiagram, CStringArray& diagram)
{
	// convert text into array of lines
	CString sDiagram(szDiagram);
	diagram.RemoveAll(); 

	while (!sDiagram.IsEmpty())
	{
		int nFind = sDiagram.Find(ENDL);
		CString sLine;

		if (nFind != -1)
		{
			sLine = sDiagram.Left(nFind);
			sDiagram = sDiagram.Mid(nFind + 1);
		}
		else
		{
			sLine = sDiagram;
			sDiagram.Empty();
		}

		sLine.TrimRight();
		ExpandTabs(sLine);

		diagram.Add(sLine);
	}

	return diagram.GetSize();
}

BOOL CTextDiagram::GetDiagram(CStringArray& diagram, BOOL bVerify) const
{
	if (bVerify && !VerifyDiagram())
		return FALSE;

	BuildDiagram(diagram);
	return TRUE;
}

BOOL CTextDiagram::GetDiagram(CString& sDiagram, BOOL bVerify) const
{
	CStringArray diagram;

	if (!GetDiagram(diagram, bVerify))
		return FALSE;

	sDiagram.Empty();

	for (int nLine = 0; nLine < diagram.GetSize(); nLine++)
	{
		sDiagram += diagram.GetAt(nLine);
		sDiagram += "\r\n";
	}

	return TRUE;
}

void CTextDiagram::BuildDiagram(CStringArray& diagram) const
{
	diagram.RemoveAll();

	if (m_size.cx && m_size.cy)
	{
		// initialize the diagram to match the current size
		for (int nY = 0; nY < m_size.cy + 1; nY++)
			diagram.Add(CString(SPACE, m_size.cx + 1));

		// draw each rect
		CTDRect rect;
		int nRect = 0;

		while (GetRect(nRect, rect))
		{
			DrawRect(diagram, rect);
			nRect++;
		}

		// draw each conn
		CTDConnection conn;
		int nConn = 0;

		while (GetConnection(nConn, conn))
		{
			DrawConn(diagram, conn);
			nConn++;
		}

		// add title at the end because this alters the y-coordinates
		AddTitle(diagram);

		// finally remove excess whitespace
		int nLine = diagram.GetSize();

		while (nLine--)
			diagram[nLine].TrimRight();
	}
}

void CTextDiagram::AddTitle(CStringArray& diagram) const
{
	CStringArray aTitle;
	CString sTitle(m_sTitle);

	sTitle.TrimRight(); // remove trailing carriage returns

	if (!sTitle.IsEmpty())
	{
		CString sLine(": ");
		int nChar = 0, nLineChar = 0;

		// walk the characters till we hit a new line character
		while (nChar < sTitle.GetLength())
		{
			char c = sTitle[nChar];
			
			// new line?
			if (c == '\r')
			{
				sLine.TrimRight();

				if (aTitle.GetSize() || sLine.GetLength() > 2)
					aTitle.Add(sLine);

				sLine = ": ";
				nLineChar = 0;
				nChar++; // jump '\n' too
			}
			else
			{
				sLine += c;
				nLineChar++;
			}

			nChar++;
		}

		// add whatever's left
		sLine.TrimRight();

		if (sLine.GetLength() > 2)
			aTitle.Add(sLine);
	}

	// insert a blank line above if we have a none empty title
	if (aTitle.GetSize())
		aTitle.InsertAt(0, "");

	diagram.InsertAt(0, &aTitle);
}

void CTextDiagram::DrawRect(CStringArray& diagram, const CTDRect& rect) const
{
	// right
	DrawLine(diagram, CPoint(rect.right, rect.top), CPoint(rect.right, rect.bottom));

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -