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

📄 umllinesegment.cpp

📁 uml编辑器很牛
💻 CPP
📖 第 1 页 / 共 5 页
字号:
/* ==========================================================================
	Class :			CUMLLineSegment

	Author :		Johan Rosengren, Abstrakt Mekanik AB

	Date :			2004-04-29

	Purpose :		"CUMLLineSegment" is a "CUMLEntity"-
					derived class, representing a line that can be linked 
					to other "CUMLEntity"-derived objects.

	Description :	The implementation is based on "CDiagramLine", even though 
					not derived from it. The class allows two link point, 
					"LINK_START" and "LINK_END" - the top-left and bottom-right 
					corners. 
					The links can be attached to any link point on some 
					objects, and contains offset values to the top or left 
					to make it possible to move the segment along with the 
					linked object.

	Usage :			Create with "CUMLControlFactory::CreateFromString" or 
					add an instance to the editor "StartDrawingObject".

   ========================================================================
	Changes:
		8/7 2004	Support for the Interface line type added.
		5/8 2004	Fixed bug in GetOffset - zoom should *not* be applied.
   ========================================================================*/
#include "stdafx.h"
#include "UMLLineSegment.h"
#include "UMLEntityContainer.h"
#include "DiagramEditor/DiagramLine.h"
#include "DiagramEditor/Tokenizer.h"
#include "StringHelpers.h"

#include <math.h>

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


//////////////////////////////////////////
// LineDDA callbacks from CDiagramLine
//

VOID CALLBACK HitTest( int X, int Y, LPARAM data );
VOID CALLBACK HitTestRect( int X, int Y, LPARAM data );

CUMLLineSegment::CUMLLineSegment()
/* ============================================================
	Function :		CUMLLineSegment::CUMLLineSegment
	Description :	Constructor
	Access :		Public
					
	Return :		void
	Parameters :	none

	Usage :			Create either through "CUMLControlFactory" or
					by calling "new" and adding the pointer to the
					editor via "StartDrawingObject"

   ============================================================*/
{

	SetPropertyDialog( &m_dlg, CUMLLinkPropertyDialog::IDD );

	SetLinkType( LINK_START, 0 );
	SetLinkType( LINK_END, 0 );

	SetMinimumSize( CSize( -1, -1 ) );
	SetMaximumSize( CSize( -1, -1 ) );
	SetType( _T( "uml_line" ) );
	SetTitle( _T( "" ) );
	SetStyle( 0 );
	SetStartLabel( _T( "" ) );
	SetEndLabel( _T( "" ) );

	SetOffset( LINK_START, 0 );
	SetOffset( LINK_END, 0 );

}

CUMLLineSegment::~CUMLLineSegment()
/* ============================================================
	Function :		CUMLLineSegment::~CUMLLineSegment
	Description :	Destructor
	Access :		Public
					
	Return :		void
	Parameters :	none

	Usage :			Note that objects will normally be deleted by
					the container.

   ============================================================*/
{

	if( m_dlg.m_hWnd )
		m_dlg.DestroyWindow();

}

CDiagramEntity* CUMLLineSegment::Clone()
/* ============================================================
	Function :		CUMLLineSegment::Clone
	Description :	Clone this object to a new object.
	Access :		Public
					
	Return :		CDiagramEntity*	-	The new object.
	Parameters :	none

	Usage :			Call to create a clone of the object. The 
					caller will have to delete the object.

   ============================================================*/
{

	CUMLLineSegment* obj = new CUMLLineSegment;
	obj->Copy( this );
	return obj;

}

void CUMLLineSegment::Draw( CDC* dc, CRect rect )
/* ============================================================
	Function :		CUMLLineSegment::Draw
	Description :	Draws the object.
	Access :		Public

	Return :		void
	Parameters :	CDC* dc		-	The "CDC" to draw to. 
					CRect rect	-	The real rectangle of the 
									object.

	Usage :			The function should clean up all selected 
					objects. Note that the "CDC" is a memory "CDC", 
					so creating a memory "CDC" in this function 
					will probably not speed up the function.

   ============================================================*/
{

	int mode = dc->SetBkMode( TRANSPARENT );

	if( !( GetStyle() & STYLE_INVISIBLE ) )
	{
		CPen pen;
		if( GetStyle() & STYLE_DASHED )
			pen.CreatePen( PS_DOT, 0, RGB( 0, 0, 0 ) );
		else
			pen.CreatePen( PS_SOLID, 0, RGB( 0, 0, 0 ) );

		CPen* oldpen = dc->SelectObject( &pen );

		// Draw line
		dc->MoveTo( rect.TopLeft() );
		dc->LineTo( rect.BottomRight() );

		dc->SelectObject( oldpen );
	}

	dc->SelectStockObject( BLACK_PEN );
	dc->SelectStockObject( BLACK_BRUSH );

	int cut = round( static_cast< double >( GetMarkerSize().cx ) * GetZoom() / 2 );
	int cy = round( 14.0 * GetZoom() );

	CFont font;
	font.CreateFont( -round( 12.0 * GetZoom() ), 0,0,0,FW_NORMAL,0,0,0,0,0,0,0,0, GetFont() );
	CFont* oldfont = dc->SelectObject( &font );

	/////////////////////////////////////////////////////////////
	// Draw title

	CString str = GetTitle();
	if( str.GetLength() )
	{

		CRect rectTemp( rect );
		rectTemp.NormalizeRect();
		CRect r( rect.right - cut, rect.top, rect.right - ( rectTemp.Width() + cut ), rect.bottom );
		if( IsHorizontal() )
		{
			CRect r( rect.left, rect.top - ( cy + cut ), rect.right, rect.bottom );
			r.NormalizeRect();
			dc->DrawText( str, r, DT_NOPREFIX | DT_SINGLELINE | DT_CENTER );
		}
		else
		{
			CRect r( rect.right - ( dc->GetTextExtent( str ).cx + cut * 2 ), rect.top, rect.right - cut, rect.bottom );
			r.NormalizeRect();
			dc->DrawText( str, r, DT_NOPREFIX | DT_SINGLELINE | DT_VCENTER | DT_RIGHT );
		}

	}

	/////////////////////////////////////////////////////////////
	// Draw labels

	str = GetStartLabel();
	if( str.GetLength() )
	{
		CRect rectTemp( rect );
		if( IsHorizontal() )
		{
			rectTemp.bottom = rectTemp.top - cut;
			rectTemp.top -= cy + cut;

			if( rectTemp.left < rectTemp.right )
			{
				rectTemp.left += cut;
				rectTemp.right -= cut;
				dc->DrawText( str, rectTemp, DT_NOPREFIX | DT_SINGLELINE | DT_VCENTER | DT_LEFT );
			}
			else
			{
				int temp = rectTemp.left;
				rectTemp.left = rectTemp.right + cut;
				rectTemp.right = temp - cut;
				dc->DrawText( str, rectTemp, DT_NOPREFIX | DT_SINGLELINE | DT_VCENTER | DT_RIGHT );
			}

		}
		else
		{
			rectTemp.left -= dc->GetTextExtent( str ).cx + 2 * cut;
			rectTemp.right -= cut;
			if( rectTemp.top < rectTemp.bottom )
				rectTemp.bottom = rectTemp.top + cy;
			else
			{
				rectTemp.top -= cy;
				rectTemp.bottom = rectTemp.top + cy;
			}

			dc->DrawText( str, rectTemp, DT_NOPREFIX | DT_SINGLELINE | DT_VCENTER | DT_RIGHT );
		}

	}

	str = GetSecondaryStartLabel();
	if( str.GetLength() )
	{
		CRect rectTemp( rect );
		if( IsHorizontal() )
		{
			rectTemp.bottom += cy + cut;
			rectTemp.top += cut;

			if( rectTemp.left < rectTemp.right )
			{
				rectTemp.left += cut;
				rectTemp.right -= cut;
				dc->DrawText( str, rectTemp, DT_NOPREFIX | DT_SINGLELINE | DT_VCENTER | DT_LEFT );
			}
			else
			{
				int temp = rectTemp.left;
				rectTemp.left = rectTemp.right + cut;
				rectTemp.right = temp - cut;
				dc->DrawText( str, rectTemp, DT_NOPREFIX | DT_SINGLELINE | DT_VCENTER | DT_RIGHT );
			}

		}
		else
		{
			rectTemp.right += dc->GetTextExtent( str ).cx + 2 * cut;
			rectTemp.left += cut;

			if( rectTemp.top < rectTemp.bottom )
				rectTemp.bottom = rectTemp.top + cy;
			else
			{
				rectTemp.top -= cy;
				rectTemp.bottom = rectTemp.top + cy;
			}

			dc->DrawText( str, rectTemp, DT_NOPREFIX | DT_SINGLELINE | DT_VCENTER | DT_RIGHT );
		}

	}

	str = GetEndLabel();
	if( str.GetLength() )
	{
		CRect rectTemp( rect );
		if( IsHorizontal() )
		{
			rectTemp.bottom = rectTemp.top - cut;
			rectTemp.top -= cy + cut;

			if( rectTemp.left < rectTemp.right )
			{
				rectTemp.left += cut;
				rectTemp.right -= cut;
				dc->DrawText( str, rectTemp, DT_NOPREFIX | DT_SINGLELINE | DT_VCENTER | DT_RIGHT );
			}
			else
			{
				int temp = rectTemp.left;
				rectTemp.left = rectTemp.right + cut;
				rectTemp.right = temp - cut;
				dc->DrawText( str, rectTemp, DT_NOPREFIX | DT_SINGLELINE | DT_VCENTER | DT_LEFT );
			}

		}
		else
		{
			rectTemp.left -= dc->GetTextExtent( str ).cx + 2 * cut;
			rectTemp.right -= cut;
			if( rectTemp.top < rectTemp.bottom )
				rectTemp.top = rectTemp.bottom - cy;
			else
			{
				rectTemp.top = rectTemp.bottom;
				rectTemp.bottom = rectTemp.top + cy;
			}
			dc->DrawText( str, rectTemp, DT_NOPREFIX | DT_SINGLELINE | DT_VCENTER | DT_RIGHT );
		}
	}

	str = GetSecondaryEndLabel();
	if( str.GetLength() )
	{
		CRect rectTemp( rect );
		if( IsHorizontal() )
		{
			rectTemp.bottom += cy + cut;
			rectTemp.top += cut;

			if( rectTemp.left < rectTemp.right )
			{
				rectTemp.left += cut;
				rectTemp.right -= cut;
				dc->DrawText( str, rectTemp, DT_NOPREFIX | DT_SINGLELINE | DT_VCENTER | DT_RIGHT );
			}
			else
			{
				int temp = rectTemp.left;
				rectTemp.left = rectTemp.right + cut;
				rectTemp.right = temp - cut;
				dc->DrawText( str, rectTemp, DT_NOPREFIX | DT_SINGLELINE | DT_VCENTER | DT_LEFT );
			}

		}
		else
		{
			rectTemp.right += dc->GetTextExtent( str ).cx + 2 * cut;
			rectTemp.left += cut;
			if( rectTemp.top < rectTemp.bottom )
				rectTemp.top = rectTemp.bottom - cy;
			else
			{
				rectTemp.top = rectTemp.bottom;
				rectTemp.bottom = rectTemp.top + cy;
			}
			dc->DrawText( str, rectTemp, DT_NOPREFIX | DT_SINGLELINE | DT_VCENTER | DT_RIGHT );
		}
	}

	/////////////////////////////////////////////////////////////
	// Draw markers

	int hgt = GetMarkerSize().cy / 2;
	if( GetStyle() & STYLE_FILLED_DIAMOND )
	{
		CRect diamond;

		double x2 = GetLeft();
		double x1 = GetRight();
		double y2 = GetTop();
		double y1 = GetBottom();

		if( !( GetLinkType( LINK_END ) & LINK_ALL ) && 
			( GetLinkType( LINK_START ) & LINK_ALL ) )
		{
			x2 = GetRight();
			x1 = GetLeft();
			y2 = GetBottom();
			y1 = GetTop();
		}

		if( IsHorizontal() )
		{
			diamond.left = round( x1 * GetZoom() );
			diamond.top = round( ( y1 - hgt ) * GetZoom() );
			diamond.bottom = diamond.top + round( hgt * 2 * GetZoom() );
			if( x1 < x2 )
				diamond.right = diamond.left + round( hgt * 4 * GetZoom() );
			else
				diamond.right = diamond.left - round( hgt * 4 * GetZoom() );

			diamond.NormalizeRect();

		}
		else
		{

			diamond.top = round( y1 * GetZoom() );
			diamond.left = round( ( x1 - hgt ) * GetZoom() );
			diamond.right = diamond.left + round( hgt * 2 * GetZoom() );
			if( y1 < y2 )
				diamond.bottom = diamond.top + round( hgt * 4 * GetZoom() );
			else
				diamond.bottom = diamond.top - round( hgt * 4 * GetZoom() );

			rect.NormalizeRect();

		}

		DrawDiamond( dc, diamond );
	}

	if( GetStyle() & STYLE_CIRCLECROSS )
	{

		CSize marker( 16, 16 );
		CPoint pos = GetStyleMarkerRect( LINK_END, marker );
		CRect circ( round( static_cast< double >( pos.x ) * GetZoom() ), round( static_cast< double >( pos.y ) * GetZoom() ), round( static_cast< double >( pos.x + marker.cx ) * GetZoom() ), round( static_cast< double >( pos.y + marker.cy ) * GetZoom() ) );

		dc->SelectStockObject( BLACK_PEN );
		dc->SelectStockObject( WHITE_BRUSH );

		dc->Ellipse( &circ );

		dc->MoveTo( circ.left + circ.Width() / 2, circ.top );
		dc->LineTo( circ.left + circ.Width() / 2, circ.bottom );

		dc->MoveTo( circ.left, circ.top + circ.Height() / 2 );
		dc->LineTo( circ.right, circ.top + circ.Height() / 2 );

	}

	if( GetStyle() & STYLE_ARROWHEAD )
		DrawInheritanceArrow( dc );

	if( GetStyle() & STYLE_FILLED_ARROWHEAD )
		DrawDirectionArrow( dc );

	/////////////////////////////////////////////////////////////
	// Cleaning up

	dc->SetBkMode( mode );
	dc->SelectObject( oldfont );
	dc->SelectStockObject( WHITE_BRUSH );

}

CDiagramEntity* CUMLLineSegment::CreateFromString( const CString& str )
/* ============================================================
	Function :		CUMLLineSegment::CreateFromString
	Description :	Static factory function that creates and 
					returns an instance of this class if "str" 
					is a valid representation.
	Access :		Public
					
	Return :		CDiagramEntity*		-	The object, or "NULL" 
											if "str" is not a 
											representation of 
											this type.
	Parameters :	const CString& str	-	The string to create 
											from.
					
	Usage :			Can be used as a factory for text file loads. 
					Each object type should have its own 
					version - the default one is a model 
					implementation.

   ============================================================*/
{

	CUMLLineSegment* obj = new CUMLLineSegment;
	if(!obj->FromString( str ) )
	{
		delete obj;
		obj = NULL;
	}

	return obj;

}

int CUMLLineSegment::GetHitCode( CPoint point ) const

⌨️ 快捷键说明

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