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

📄 textdiagram.cpp

📁 TabBars的开源源码
💻 CPP
📖 第 1 页 / 共 4 页
字号:
		else if (TestChar(diagram, nX, nY + 1, CHAR_VERT, CHAR_CROSSOVER))
		{
			nY++;
			return CONN_DOWN;
		}
		// 4. test for change of direction (up)
		else if (TestChar(diagram, nX, nY - 1, CHAR_VERT, CHAR_CROSSOVER))
		{
			nY--;
			return CONN_UP;
		}
		// 5. test for termination (down)
		else if (TestChar(diagram, nX, nY + 1, CHAR_END/*, CHAR_ENDDOWN*/))
		{
			nY++;
			return CONN_END;
		}
		// 6. test for termination (up)
		else if (TestChar(diagram, nX, nY - 1, CHAR_END/*, CHAR_ENDUP*/))
		{
			nY--;
			return CONN_END;
		}
		break;
		
	case CONN_UP:
		if (TestChar(diagram, nX, nY - 1, CHAR_HORZ))
		{
			nY--;

			// which way does it go?
			if (TestChar(diagram, nX + 1, nY, CHAR_HORZ, CHAR_CROSSOVER, CHAR_END))
				return CONN_RIGHT;
			else
				return CONN_LEFT;
		}
		else if (TestChar(diagram, nX, nY - 1, CHAR_CROSSOVER))
		{
			nY--;
			return CONN_UP;
		}
		else if (TestChar(diagram, nX, nY - 1, CHAR_END/*, CHAR_ENDUP*/))
		{
			nY--;
			return CONN_END;
		}
		else if (TestChar(diagram, nX, nY - 1, CHAR_VERT))
		{
			nY--;
			return CONN_UP;
		}
		break;
		
	case CONN_DOWN:
		if (TestChar(diagram, nX, nY + 1, CHAR_HORZ))
		{
			nY++;

			// which way does it go?
			if (TestChar(diagram, nX + 1, nY, CHAR_HORZ, CHAR_CROSSOVER, CHAR_END))
				return CONN_RIGHT;
			else
				return CONN_LEFT;
		}
		else if (TestChar(diagram, nX, nY + 1, CHAR_CROSSOVER))
		{
			nY++;
			return CONN_DOWN;
		}
		else if (TestChar(diagram, nX, nY + 1, CHAR_END/*, CHAR_ENDDOWN*/))
		{
			nY++;
			return CONN_END;
		}
		else if (TestChar(diagram, nX, nY + 1, CHAR_VERT))
		{
			nY++;
			return CONN_DOWN;
		}
		break;
	}
	
	return NONE;
}

void CTextDiagram::AddConn(const CStringArray& diagram, int nX, int nY)
{
	TDPOS nPos = ConnStartChar(diagram, nX, nY);

	if (nPos == CONN_START)
	{
		CPoint ptStart(nX, nY);
		int nFromRect = IntersectRect(nX, nY);

		BOOL bDone = FALSE;
		TDPOS nPosOrg = nPos;

		int nIteration = 0; // for catching infinite loops

		while (nPos != NONE && !bDone && nIteration < MAXITERATIONS)
		{
			nIteration++;
			nPos = ConnGetNextChar(diagram, nPos, nX, nY);

			// are we done yet?
			bDone = (nPos == CONN_END);
		}

		if (bDone)
		{
			int nToRect = IntersectRect(nX, nY);

			if (nToRect != -1 && nToRect != nFromRect)
			{
				CTDRect rect;

				GetRect(nFromRect, rect);
				int nSideFrom = rect.GetSide(ptStart);

				ASSERT (nSideFrom != NONE);

				AddConnection(nFromRect, nToRect, nSideFrom);
			}
		}
	}
}

BOOL CTextDiagram::PtInRect(int nX, int nY) const
{
	return (IntersectRect(nX, nY) != -1);
}

int CTextDiagram::IntersectRect(int nX, int nY) const
{
	if (!m_aRects.GetSize())
		return -1;

	// else
	for (int nRect = 0; nRect < m_aRects.GetSize(); nRect++)
	{
		CRect rect = m_aRects[nRect];

		rect.right++; // inclusive
		rect.bottom++; // inclusive

		if (rect.PtInRect(CPoint(nX, nY)))
			return nRect;
	}

	return -1;
}

BOOL CTextDiagram::PtInConn(int nX, int nY, BOOL bHorz) const
{
	return (IntersectConn(CPoint(nX, nY), bHorz) != -1);
}

int CTextDiagram::IntersectConn(CPoint point, BOOL bHorz) const
{
	int nConn = m_aConns.GetSize();

	while (nConn--)
	{
		if (m_aConns[nConn].PtInConn(point, bHorz))
			return nConn;
	}

	return -1; // not found
}

BOOL CTextDiagram::IntersectRect(const CRect& rect, int nIgnoreRect) const
{
	if (!m_aRects.GetSize())
		return FALSE;

	// else
	CRect rTest(rect);
	rTest.right++; // inclusive
	rTest.bottom++; // inclusive

	for (int nRect = 0; nRect < m_aRects.GetSize(); nRect++)
	{
		CRect r = m_aRects[nRect];

		r.right++; // inclusive
		r.bottom++; // inclusive

		if (CRect().IntersectRect(r, rTest) && nRect != nIgnoreRect)
			return TRUE;
	}

	return FALSE;
}

void CTextDiagram::AddRect(const CStringArray& diagram, int nX, int nY)
{
	TDPOS nPos = RectStartChar(diagram, nX, nY);

	if (nPos != NONE)
	{
		CPoint ptOrg(nX, nY);
		CRect rect(nX, nY, nX, nY);

		BOOL bDone = FALSE;
		TDPOS nPosOrg = nPos;

		int nIteration = 0; // for catching infinite loops

		while (nPos != NONE && !bDone && nIteration < MAXITERATIONS)
		{
			nIteration++;
			nPos = RectGetNextChar(diagram, nPos, nX, nY);

			if (nPos != NONE)
			{
				rect.left = min(rect.left, nX);
				rect.top = min(rect.top, nY);
				rect.right = max(rect.right, nX);
				rect.bottom = max(rect.bottom, nY);

				// are we done yet?
				bDone = (nPos == nPosOrg && nX == ptOrg.x && nY == ptOrg.y);
			}
		}

		// get rect text
		if (bDone)
		{
			CString sText;

			for (nY = rect.top + 1; nY < rect.bottom; nY++)
			{
				for (nX = rect.left + 1; nX < rect.right; nX++)
				{
					sText += GetChar(diagram, nX, nY);
				}
				
				// if the last char is a space then insert a carriage return
				if (sText.Right(1) == " ")
				{
					sText.TrimRight();
					sText += "\r\n";
				}
			}

			sText.TrimRight();
			AddRect(rect, sText);
		}
	}
}

int CTextDiagram::GetRectCount() const
{
	return m_aRects.GetSize();
}

int CTextDiagram::GetConnectionCount() const
{
	return m_aConns.GetSize();
}

BOOL CTextDiagram::GetRect(int nRect, CTDRect& rect) const
{
	if (nRect < 0 || nRect >= GetRectCount())
		return FALSE;

	// else
	rect = m_aRects[nRect];
	return TRUE;
}

BOOL CTextDiagram::GetRect(int nRect, CRect& rect) const
{
	CTDRect tdRect;

	if (GetRect(nRect, tdRect))
	{
		rect = tdRect;
		return TRUE;
	}

	return FALSE;
}


BOOL CTextDiagram::DeleteRect(int nRect)
{
	if (nRect < 0 || nRect >= GetRectCount())
		return FALSE;

	// modify all connections referencing rects after this one
	// to take account of the removal
	// and remove all connections which reference this rect
	int nConn = m_aConns.GetSize();

	while (nConn--)
	{
		CTDConnection& conn = m_aConns[nConn];

		int nRectFrom = conn.RectFrom();
		int nRectTo = conn.RectTo();

		if (nRectFrom == nRect || nRectTo == nRect)
			m_aConns.RemoveAt(nConn);
		else
		{
			if (nRectFrom > nRect)
				conn.SetRectFrom(nRectFrom - 1);

			if (nRectTo > nRect)
				conn.SetRectTo(nRectTo - 1);
		}
	}

	m_aRects.RemoveAt(nRect);
	RebuildConnections();

	return TRUE;
}

BOOL CTextDiagram::DeleteConnection(int nConn)
{
	if (nConn < 0 || nConn >= GetConnectionCount())
		return FALSE;

	m_aConns.RemoveAt(nConn);
	return TRUE;
}

BOOL CTextDiagram::GetConnection(int nConn, CTDConnection& conn) const
{
	if (nConn < 0 || nConn >= GetConnectionCount())
		return FALSE;

	// else
	conn = m_aConns[nConn];
	return TRUE;
}

BOOL CTextDiagram::SetRect(int nRect, const CTDRect& rect)
{
	if (nRect < 0 || nRect >= GetRectCount())
		return FALSE;

	// validate the rect
	if (rect.left <= 0 || rect.top <= 0 || rect.Width() < 2 || rect.Height() < 2)
		return FALSE;

	// make sure it doesn't overlap any other rect
	// don't let it come too close either
	CRect r(rect);
	r.InflateRect(1, 1);

	if (IntersectRect(r, nRect))
		return FALSE;

	// save current state in case this fails
	CTextDiagram diagramBackup(*this);

	m_aRects[nRect] = rect;

	// rebuild all connections to ensure no overlaps
	if (RebuildConnections())
	{
		// update the diagram size
		RecalcSize();

		return TRUE;
	}

	// else restore the backup
	SetDiagram(diagramBackup);
	return FALSE;
}

BOOL CTextDiagram::SetText(int nRect, LPCTSTR szText)
{
	if (nRect < 0 || nRect >= GetRectCount())
		return FALSE;

	m_aRects[nRect].SetText(szText);
	return TRUE;
}

BOOL CTextDiagram::GetText(int nRect, CString& sText)
{
	if (nRect < 0 || nRect >= GetRectCount())
		return FALSE;

	sText = m_aRects[nRect].GetText();
	return TRUE;
}

BOOL CTextDiagram::RebuildConnections()
{
	// save a copy of existing connections
	CArray<CTDConnection, CTDConnection&> aConns;
	aConns.Copy(m_aConns);

	// delete all connections and re-add
	m_aConns.RemoveAll();

	for (int nConn = 0; nConn < aConns.GetSize(); nConn++)
	{
		// defensive programming
		CTDConnection conn = aConns[nConn];

		if (AddConnection(conn.RectFrom(), conn.RectTo(), conn.SideFrom()) == -1)
			return FALSE;
	}

	return TRUE;
}

int CTextDiagram::AddRect(LPCRECT pRect, LPCTSTR szText)
{
	if (!pRect)
		return NewRect();

	// validate the rect
	CRect rect(pRect);

	if (rect.left <= 0 || rect.top <= 0 || rect.Width() < 2 || rect.Height() < 2)
		return -1;

	// make sure it doesn't overlap any other rect
	// don't let it come too close either
	CRect r(rect);
	r.InflateRect(1, 1);

	if (IntersectRect(r))
		return -1;

	// don't let it overlap or touch any connections
	if (IntersectConn(rect))
		return -1;

	// save current state in case this fails
	CTextDiagram diagramBackup(*this);

	int nRect = m_aRects.Add(CTDRect(rect, szText));

	// rebuild all connections to ensure no overlaps
	if (nRect >= 0 && RebuildConnections())
	{
		// update the diagram size
		RecalcSize();

		return nRect;
	}

	// else restore backup
	SetDiagram(diagramBackup);
	return -1;
}

int CTextDiagram::FindConnection(int nRectFrom, int nRectTo) const
{
	int nConn = m_aConns.GetSize();

	while (nConn--)
	{
		if (m_aConns[nConn].RectFrom() == nRectFrom && m_aConns[nConn].RectTo() == nRectTo)
			return nConn;
	}

	return -1; // not found
}

int CTextDiagram::AddConnection(int nRectFrom, int nRectTo, int nSideFrom)
{
	if (FindConnection(nRectFrom, nRectTo) != -1)
		return -1;

	CTDConnection conn(nRectFrom, nRectTo, nSideFrom);

	if (BuildPath(conn, -1))
	{
		int nConn = m_aConns.Add(conn);

		// update the diagram size
		RecalcSize();

		return nConn;
	}

	return -1;
}

BOOL CTextDiagram::SetConnection(int nConn, const CTDConnection& conn)
{
	CTDConnection connExist;

	// retrieve existing connection
	if (!GetConnection(nConn, connExist))
		return FALSE;

	// ensure requested connection is not already taken
	int nCurConn = FindConnection(conn.RectFrom(), conn.RectTo());

	if (nCurConn != -1 && nCurConn != nConn)
		return FALSE;

	// save current state in case this fails
	CTextDiagram diagramBackup(*this);

	// update existing connection
	m_aConns.SetAt(nConn, CTDConnection(conn));

	if (RebuildConnections())
	{
		// update the diagram size
		RecalcSize();
		return TRUE;
	}

	// restore backup
	SetDiagram(diagramBackup);
	return FALSE;
}

void CTextDiagram::GetRelationship(const CRect& rFrom, const CRect& rTo, int& nHorz, int& nVert)
{
	GetRelationship(rFrom.CenterPoint(), rTo.CenterPoint(), nHorz, nVert);
}

void CTextDiagram::GetRelationship(CPoint ptFrom, const CRect& rTo, int& nHorz, int& nVert)
{
	// horz
	if (ptFrom.x >= rTo.left && ptFrom.x <= rTo.right)
		nHorz = 0; // 'to' is aligned with 'from'

	else if (ptFrom.x < rTo.left)
		nHorz = 1; // 'to' is to the right of 'from'

	else
		nHorz = -1; // 'to' is to the left of 'from'

	// vert
	if (ptFrom.y >= rTo.top && ptFrom.y <= rTo.bottom)
		nVert = 0; // 'to' is aligned with 'from'

	else if (ptFrom.y < rTo.top)
		nVert = 1; // 'to' is below 'from'

	else
		nVert = -1; // 'to' is above 'from'
}

void CTextDiagram::GetRelationship(CPoint ptFrom, CPoint ptTo, int& nHorz, int& nVert)
{
	// horz
	if (ptFrom.x == ptTo.x)
		nHorz = 0; // 'to' is aligned with 'from'

	else if (ptFrom.x < ptTo.x)
		nHorz = 1; // 'to' is to the right of 'from'

⌨️ 快捷键说明

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