umleditor.cpp

来自「uml编辑器很牛」· C++ 代码 · 共 1,677 行 · 第 1/4 页

CPP
1,677
字号

	// Click on the arrow up icon
	CString package = GetPackage();
	int size = round( 20 * GetZoom() );
	if( package.GetLength() && point.x < size && point.y < size )
	{
		CUMLEntity* obj = GetAllNamedObject( package );
		if( obj )
			SetPackage( obj->GetPackage() );
		else
			SetPackage( _T( "" ) );

		RedrawWindow();
		return;
	}

	// Store the line being drawn, if any
	CPoint virtpoint( point );
	ScreenToVirtual( virtpoint );
	CUMLLineSegment* seg = NULL;
	if( m_drawingLine && GetInteractMode() == MODE_RESIZING )
		seg = dynamic_cast< CUMLLineSegment* >( GetSelectedObject() );

	// If we are starting to draw a new link, we save the object 
	// link point under the cursor, as we want to set the start 
	// of the link to this object.
	int type = LINK_NONE;
	int savedtype = LINK_NONE;
	CUMLEntity* obj = NULL;
	CUMLEntity* mainobj = NULL;
	if( GetInteractMode() == MODE_DRAWING )
	{
		m_drawingLine = FALSE;
		CUMLLineSegment* seg = dynamic_cast< CUMLLineSegment* >( GetDrawingObject() );
		if( seg )
		{
			int count = 0;
			while( ( obj = GetObjectAt( count++ ) ) )
			{
				if( obj->GetPackage() == GetPackage() )
				{
					type = obj->GetLinkCode( virtpoint );
					if( type & LINK_ALL )
					{
						mainobj = obj;
						m_drawingLine = TRUE;
						savedtype = type;
						count = -2;
					}
				}
			}

			// there was no object under the cursor, and we 
			// will not be able to draw a link
			if( !m_drawingLine )
				SetInteractMode( MODE_NONE );
		}
	}

	CDiagramEditor::OnLButtonDown( nFlags, point );

	if( GetInteractMode() == MODE_RESIZING && m_drawingLine && mainobj && savedtype != LINK_NONE )
	{
		// We have added a line segment, and set the link start point to it
		CUMLLineSegment* seg = dynamic_cast< CUMLLineSegment* >( GetSelectedObject() );
		if( seg )
		{
			seg->SetLink( LINK_START, mainobj->GetName() );
			seg->SetLinkType( LINK_START, savedtype );

			int diff = 0;
			if( savedtype == LINK_TOP || savedtype == LINK_BOTTOM )
			{
				diff = virtpoint.x - static_cast< int >( mainobj->GetLeft() );
				if( GetSnapToGrid() )
					diff = SnapX( diff );
			}
			else if( savedtype == LINK_LEFT || savedtype == LINK_RIGHT )
			{
				diff = virtpoint.y - static_cast< int >( mainobj->GetTop() );
				if( GetSnapToGrid() )
					diff = SnapY( diff );
			}

			seg->SetOffset( LINK_START, diff );

			if( savedtype == LINK_END )
			{
				CUMLLineSegment* line = dynamic_cast< CUMLLineSegment* >( mainobj );
				line->SetLink( LINK_END, seg->GetName() );
				line->SetLinkType( LINK_END, LINK_START );
			}
			else
			{
				CSize minsize = mainobj->GetMinimumSize();
				if( savedtype == LINK_TOP || savedtype == LINK_BOTTOM )
				{
					if( minsize.cx < diff )
						mainobj->SetMinimumSize( CSize( diff, minsize.cy ) );
				}
				else
					if( minsize.cy < diff )
						mainobj->SetMinimumSize( CSize( minsize.cx, diff ) );
			}
		}
	}

	if( GetInteractMode() == MODE_RUBBERBANDING && m_drawingLine )
	{
		// Clicked outside the link point. Force continue drawing.
		if( !seg )
			m_drawingLine = FALSE;
		else
		{
			if( seg->IsHorizontal() )
				seg->SetRight( virtpoint.x );
			else
				seg->SetBottom( virtpoint.y );
			seg->Select( TRUE );
			SetInteractMode( MODE_RESIZING, DEHT_BOTTOMRIGHT );
		}
	}

	SetCursor( point );

}

void CUMLEditor::OnLButtonUp( UINT nFlags, CPoint point )
/* ============================================================
	Function :		CUMLEditor::OnLButtonUp
	Description :	Handler for "WM_LBUTTONUP" message.
	Access :		Protected

	Return :		void
	Parameters :	UINT nFlags		-	Not used
					CPoint point	-	Position of mouse cursor
					
	Usage :			Called from MFC. Used to link lines if we 
					are drawing lines.

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

	// We get this before the base class implementation
	// to avoid any unselects in there. 
	CUMLEntityContainer* objs = GetUMLEntityContainer();
	CUMLLineSegment* selobj = dynamic_cast< CUMLLineSegment* >( GetSelectedObject() );

	CDiagramEditor::OnLButtonUp( nFlags, point );

	if( selobj && m_drawingLine )
	{
		if( selobj->GetRight() == selobj->GetLeft() && selobj->GetTop() == selobj->GetBottom() )
			// If we have a zero-size line, we force resizing
			SetInteractMode( MODE_RESIZING, DEHT_BOTTOMRIGHT );
		else
		{
			// We try to find a link point to attach this line to
			UnselectAll();

			// Check if we can attatch to a link point.
			BOOL attached = FALSE;
			int count = 0;
			CUMLEntity* obj;
			point = selobj->GetRect().BottomRight();

			while( ( obj = GetObjectAt( count++ ) ) )
			{
				if( obj->GetPackage() == GetPackage() )
				{
					int linkCode = obj->GetLinkCode( point );
					if( linkCode != LINK_NONE && obj != selobj )
					{
						if( ( selobj->IsHorizontal() && ( linkCode == LINK_LEFT || linkCode == LINK_RIGHT ) ) ||
							( !selobj->IsHorizontal() && ( linkCode == LINK_TOP || linkCode == LINK_BOTTOM ) ) )
						{
							// We have a hit
							// Attach to an object
							attached = TRUE;
							selobj->SetLink( LINK_END, obj->GetName() );
							selobj->SetLinkType( LINK_END, linkCode );

							int diff = 0;
							if( linkCode == LINK_TOP || linkCode == LINK_BOTTOM )
							{
								diff = point.x - static_cast< int >( obj->GetLeft() );
								if( GetSnapToGrid() )
									diff = SnapX( diff );
							}
							else if( linkCode == LINK_LEFT || linkCode == LINK_RIGHT )
							{
								diff = point.y - static_cast< int >( obj->GetTop() );
								if( GetSnapToGrid() )
									diff = SnapY( diff );
							}

							selobj->SetOffset( LINK_END, diff );

							if( linkCode == LINK_START || linkCode == LINK_END )
							{
								CUMLLineSegment* line = dynamic_cast< CUMLLineSegment* >( obj );
								if( line )
								{
									line->SetLink( LINK_START, selobj->GetName() );
									line->SetLinkType( LINK_START, LINK_END );
								}
							}
							else
							{
								CSize minsize = obj->GetMinimumSize();
								if( linkCode == LINK_TOP || linkCode == LINK_BOTTOM )
								{
									if( minsize.cx < diff )
										obj->SetMinimumSize( CSize( diff, minsize.cy ) );
								}
								else
									if( minsize.cy < diff )
										obj->SetMinimumSize( CSize( minsize.cx, diff ) );
							}

							objs->ReduceLine( selobj );
							objs->SetDefaultLineStyle( selobj );
							RedrawWindow();
							count = -2;
						}
					}
				}
			}

			if( !attached )
			{

				CUMLLineSegment* line = static_cast< CUMLLineSegment* >( GetDrawingObject()->Clone() );
				CRect rect = selobj->GetRect();
				CPoint virtpoint( rect.BottomRight() );
				line->SetRect( CRect( virtpoint.x, virtpoint.y, virtpoint.x , virtpoint.y ) );
				line->Select( TRUE );

				// Create a link between selobj and newobj
				selobj->SetLinkType( LINK_END, LINK_START );
				selobj->SetLink( LINK_END, line->GetName() );

				line->SetLink( LINK_START, selobj->GetName() );
				line->SetLinkType( LINK_START, LINK_END );

				objs->ReduceLine( selobj );

				// Add the object to the container
				objs->Add( line );
				SetInteractMode( MODE_RESIZING, DEHT_BOTTOMRIGHT );

			}
			else
				m_drawingLine = FALSE;
		}
	}

	if( GetInteractMode() == MODE_NONE || GetInteractMode() == MODE_RUBBERBANDING )
	{
		GetUMLEntityContainer()->DeleteDanglingLines();
		RedrawWindow();
	}

	SetCursor( point );

}

void CUMLEditor::OnMouseMove( UINT nFlags, CPoint point )
/* ============================================================
	Function :		CUMLEditor::OnMouseMove
	Description :	Handler for the "WM_MOUSEMOVE" message. 
	Access :		Protected
					
	Return :		void
	Parameters :	UINT nFlags		-	Not used
					CPoint point	-	Not used
					
	Usage :			Called from MFC. We add handling 
					to close screen redraws as we are moving 
					lots of stuff (all the attached objects in 
					addition to the primarily moved). We also 
					do secondary movements here - that is, 
					objects linked to the one(s) being moved 
					must be moved as well, even if they are 
					not selected.

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

	SetCursor( point );

	// We want to skip mouse movement handling if a couple 
	// of lines are selected.
	if( !PartialLinesSelected() )
	{
		CRect rect;
		CUMLLineSegment* savedobj = NULL;
		if( ( GetInteractMode() == MODE_MOVING || GetInteractMode() == MODE_RESIZING ) )
		{
			SetRedraw( FALSE );
			if( GetSelectCount() == 1 )
			{

				CUMLLineSegment* obj = dynamic_cast< CUMLLineSegment* >( GetSelectedObject() );
				if( obj )
				{
					if( IsConnected( obj ) )
					{
						rect = obj->GetRect();
						savedobj = obj;
					}
				}
			}
		}

		CDiagramEditor::OnMouseMove( nFlags, point );

		// We want to stop movement of connected lines in the line direction.
		// This is accomplished here, by resetting either the horizontal or 
		// vertical coordinates.
		if( ( GetInteractMode() == MODE_MOVING || GetInteractMode() == MODE_RESIZING ) )
		{
			if( savedobj )
			{
				// Forced move
				if( rect.top == rect.bottom )
				{
					savedobj->SetLeft( rect.left );
					savedobj->SetRight( rect.right );
				}
				else
				{
					savedobj->SetTop( rect.top );
					savedobj->SetBottom( rect.bottom );
				}	
			}

			ModifyLinkedPositions();
			SetRedraw( TRUE );
			RedrawWindow();
		}
	}
}

void CUMLEditor::OnKeyDown( UINT nChar, UINT nRepCnt, UINT nFlags ) 
/* ============================================================
	Function :		CUMLEditor::OnKeyDown
	Description :	Handles the WM_KEYDOWN-message. 
	Access :		Protected
					
	Return :		void
	Parameters :	UINT nChar		-	Not used
					UINT nRepCnt	-	Not used
					UINT nFlags		-	Not used
					
	Usage :			Called from MFC. We override this as 
					objects might be moved and we will have 
					to move unlinked objects as well.

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

	if( !PartialLinesSelected() || nChar == VK_DELETE )
	{
		SetRedraw( FALSE );

		CRect rect;
		CUMLLineSegment* savedobj = NULL;
		if( GetSelectCount() == 1 )
		{
			CUMLLineSegment* obj = dynamic_cast< CUMLLineSegment* >( GetSelectedObject() );
			if( obj && IsConnected( obj ) )
			{
				rect = obj->GetRect();
				savedobj = obj;
			}
		}

		CDiagramEditor::OnKeyDown( nChar, nRepCnt, nFlags );

		if( nChar != VK_DELETE )
		{
			if( savedobj )
			{
				// Forced move
				if( rect.top == rect.bottom )
				{
					savedobj->SetLeft( rect.left );
					savedobj->SetRight( rect.right );
				}
				else
				{
					savedobj->SetTop( rect.top );
					savedobj->SetBottom( rect.bottom );
				}	
			}
		}

		ModifyLinkedPositions();
		SetRedraw( TRUE );
		RedrawWindow();
	}

}

BOOL CUMLEditor::OnSetCursor( CWnd* pWnd, UINT nHitTest, UINT message ) 
/* ============================================================
	Function :		CUMLEditor::OnSetCursor
	Description :	Handler for the "WM_SETCURSOR" message.
	Access :		Protected

	Return :		BOOL			-	"TRUE" if handled
	Parameters :	CWnd* pWnd		-	Not used
					UINT nHitTest	-	Not used
					UINT message	-	Not used
					
	Usage :			Called from MFC. We set out custom cursors.

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

⌨️ 快捷键说明

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