umleditor.cpp

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

CPP
1,677
字号
/* ==========================================================================
	Class :			CUMLEditor

	Author :		Johan Rosengren, Abstrakt Mekanik AB

	Date :			2004-06-28

	Purpose :		"CUMLEditor" is the main editor class of the UML-editor, 
					derived from "CDiagramEditor".

	Description :	"CUMLEditor" manages the drawing and contains the 
					interface to the application (together with 
					"CUMLEntityContainer"). In addition to the features of 
					"CDiagramEditor", it manages line-drawing with links 
					(the "CUMLLineSegment" class). It also handles the 
					display and navigation of packages.

	Usage :			Use as a "CDiagramEditor".
   ========================================================================
	Changes :		4/8 2004	Added "Export only header files" support 
								(ikolev)
					4/8 2004	Setting package to current when pasting 
								items (ikolev)
					4/8 2004	Saving the destination between exports
								(ikolev)
					4/8 2004	Added initialization list from class 
								attributes to ctors.
					5/8 2004	Corrected jog-drawing when zoomed.
   ========================================================================*/

#include "stdafx.h"
#include "UMLEditor.h"
#include "UMLEntityContainer.h"
#include "UMLMenu.h"
#include "UMLLineSegment.h"
#include "UMLEntityPackage.h"
#include "TextFile/TextFile.h"
#include "DiskObject/DiskObject.h"

#include <math.h>
#include <shlobj.h>

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

#pragma warning( disable : 4706 )

int CALLBACK BFFCallbackProc( HWND hwnd, UINT uMsg, LPARAM /*lParam*/, LPARAM lpData )
{
	if( uMsg == BFFM_INITIALIZED )
		::SendMessage( hwnd, BFFM_SETSELECTION, TRUE, lpData );
	return 0;
}

/////////////////////////////////////////////////////////////////////////////
// CUMLEditor

CUMLEditor::CUMLEditor()
/* ============================================================
	Function :		CUMLEditor::CUMLEditor
	Description :	Constructor
	Access :		Public

	Return :		void
	Parameters :	none

	Usage :			

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

	SetBackgroundColor( RGB( 250, 250, 230 ) );
	SetSnapToGrid( TRUE );
	ShowGrid( FALSE );
	SetRestraints( RESTRAINT_MARGIN );
	SetMarginColor( RGB( 128, 128, 128 ) );

	SetPopupMenu( new CUMLMenu );

	m_drawingLine = FALSE;

	m_curDrawLine = ::LoadCursor( AfxGetResourceHandle(), MAKEINTRESOURCE( IDC_UML_CURSOR_DRAW ) );
	m_curAttach = ::LoadCursor( AfxGetResourceHandle(), MAKEINTRESOURCE( IDC_UML_CURSOR_ATTACH ) );
	m_curUp = ::LoadCursor( AfxGetResourceHandle(), MAKEINTRESOURCE( IDC_UML_CURSOR_UP ) );
	m_currentCursor = NULL;

}

CUMLEditor::~CUMLEditor()
/* ============================================================
	Function :		CUMLEditor::~CUMLEditor
	Description :	Destructor
	Access :		Public

	Return :		void
	Parameters :	none

	Usage :			

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

	delete m_data;

}

/////////////////////////////////////////////////////////////////////////////
// CUMLEditor overrides

BOOL CUMLEditor::Create( DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, CDiagramEntityContainer* data )
/* ============================================================
	Function :		CUMLEditor::Create
	Description :	Creates the editor.
	Access :		Public

	Return :		BOOL							-	"TRUE" if created ok.
	Parameters :	DWORD dwStyle					-	Style of editor
					const RECT& rect				-	Position of editor
					CWnd* pParentWnd				-	Parent of editor
					CDiagramEntityContainer* data	-	Data container
					
	Usage :			Call to create an editor.

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

	m_data = NULL;
	if( data == NULL )
	{
		m_data = new CUMLEntityContainer;
		data = m_data;
	}

	return CDiagramEditor::Create( dwStyle, rect, pParentWnd, data );

}

void CUMLEditor::DrawObjects( CDC* dc, double zoom ) const
/* ============================================================
	Function :		CUMLEditor::DrawObjects
	Description :	Draws the objects in the editor
	Access :		Protected

	Return :		void
	Parameters :	CDC* dc		-	"CDC" to draw to
					double zoom	-	Zoom factor. Might not be 
									the same as the editor zoom 
									(for print previews, for 
									example)
					
	Usage :			Call to draw the objects of the editor. 
					Also draws package information and jogs.

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

	CString package = GetPackage();
	if( package.GetLength() )
	{
		int place = round( 4 * zoom );
		int size = round( 32 * zoom );
		if( !dc->IsPrinting() )
		{
			HICON icon = ( HICON ) ::LoadImage( AfxGetResourceHandle(), MAKEINTRESOURCE( IDI_UML_ICON_UP ), IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR );
			if( icon )
				::DrawIconEx( dc->m_hDC, place, place, icon, size, size, 0, NULL, DI_NORMAL );
		}

		CString path;
		CString level( package );
		while( level.GetLength() )
		{
			CUMLEntity* obj = GetAllNamedObject( level );
			if( obj )
			{
				path = obj->GetTitle() + _T( ":" ) + path;
				level = obj->GetPackage();
			}
			else
				level = _T( "" );
		}

		if( path.GetLength() )
			path = path.Left( path.GetLength() - 1 );

		CFont font;
		font.CreateFont( -round( 12 * zoom ), 0, 0, 0, FW_NORMAL, 0, 0, 0, 0, 0, 0, 0, 0, _T( "Arial" ) );
		dc->SelectObject( &font );
		dc->TextOut( 7 * place, place, path );
		dc->SelectStockObject( ANSI_VAR_FONT );
	}

	int count = GetObjectCount();
	for( int i = 0 ; i < count ; i++ )
	{
		CUMLEntity* obj = GetObjectAt( i );
		if( obj && package == obj->GetPackage() )
			obj->DrawObject( dc, zoom );
	}

	CPen gridPen;
	gridPen.CreatePen( PS_SOLID, 0, GetGridColor() );
	CPen bgPen;
	bgPen.CreatePen( PS_SOLID, 0, GetBackgroundColor() );

	double x = static_cast< double >( GetMarkerSize().cx ) * GetZoom();
	double y = static_cast< double >( GetMarkerSize().cy ) * GetZoom();

	for( i = 0 ; i < count ; i++ )
	{

		CUMLLineSegment* obj = dynamic_cast< CUMLLineSegment* >( GetObjectAt( i ) );
		if( obj && package == obj->GetPackage() )
		{
			// Drawing tunnels
			BOOL horz = obj->IsHorizontal();
			for( int t = i + 1 ; t < count ; t++ )
			{
				CUMLLineSegment* line = dynamic_cast< CUMLLineSegment* >( GetObjectAt( t ) );
				if( line )
				{
					dc->SelectStockObject( NULL_BRUSH );
					if( horz && !line->IsHorizontal() )
					{
						if( min( obj->GetLeft(), obj->GetRight() ) < line->GetLeft() &&
							max( obj->GetLeft(), obj->GetRight() ) > line->GetLeft() &&
							min( line->GetTop(), line->GetBottom() ) < obj->GetTop() &&
							max( line->GetTop(), line->GetBottom() ) > obj->GetTop() )
						{

							CRect rect( round( line->GetLeft() - x ), 
										round( obj->GetTop() - y ), 
										round( line->GetLeft() + x ), 
										round( obj->GetTop() + y ) );

							rect.InflateRect( -1, -1 );

							if( IsGridVisible() )
								dc->SelectObject( &gridPen );
							else
								dc->SelectObject( &bgPen );

							CRect seg( rect );
							seg.top = round( (double)seg.top * GetZoom() );
							seg.bottom = round( (double)seg.bottom * GetZoom() );
							seg.left = round( (double)seg.left * GetZoom() );
							seg.right = round( (double)seg.right * GetZoom() );
							int left = round( line->GetLeft() * GetZoom() );

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

							dc->MoveTo( left, seg.top + seg.Height() / 2 + 1 );
							dc->LineTo( left, seg.bottom );

							CRgn rgn;
							CRect rgnrect( rect );
							VirtualToScreen( rgnrect );

							rgn.CreateRectRgn( rgnrect.left, rgnrect.top, rgnrect.left + rgnrect.Width() / 2, rgnrect.bottom );
							dc->SelectClipRgn( &rgn, RGN_AND );


							dc->SelectStockObject( BLACK_PEN );
							dc->Ellipse( rgnrect );

							dc->SelectClipRgn( NULL );

						}
					}
					else if( !horz && ( line->IsHorizontal() ) )
					{
						if( min( line->GetLeft(), line->GetRight() ) < obj->GetLeft() &&
							max( line->GetLeft(), line->GetRight() ) > obj->GetLeft() &&
							min( obj->GetTop(), obj->GetBottom() ) < line->GetTop() &&
							max( obj->GetTop(), obj->GetBottom() ) > line->GetTop() )
						{
							CRect rect( round( obj->GetLeft() - x ), 
										round( line->GetTop() - y ), 
										round( obj->GetLeft() + x ), 
										round( line->GetTop() + y ) );
							rect.InflateRect( -1, -1 );
							if( IsGridVisible() )
								dc->SelectObject( &gridPen );
							else
								dc->SelectObject( &bgPen );

							CRect seg( rect );
							seg.top = round( (double)seg.top * GetZoom() );
							seg.bottom = round( (double)seg.bottom * GetZoom() );
							seg.left = round( (double)seg.left * GetZoom() );
							seg.right = round( (double)seg.right * GetZoom() );
							int top = round( (double) line->GetTop() * GetZoom() );
							dc->MoveTo( seg.left, top );
							dc->LineTo( seg.left + seg.Width() / 2, top );

							dc->MoveTo( seg.left + seg.Width() / 2 + 1, top );
							dc->LineTo( seg.right, top );

							CRgn rgn;
							CRect rgnrect( rect );
							VirtualToScreen( rgnrect );
							rgn.CreateRectRgn( rgnrect.left, rgnrect.top, rgnrect.right, rgnrect.top + rgnrect.Height() / 2 );
							dc->SelectClipRgn( &rgn, RGN_AND );
							dc->SelectStockObject( BLACK_PEN );
							dc->Ellipse( rgnrect );
							dc->SelectClipRgn( NULL );

						}
					}
				}
			}
		}
	}

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

}

void CUMLEditor::StartDrawingObject( CDiagramEntity* obj )
/* ============================================================
	Function :		CUMLEditor::StartDrawingObject
	Description :	Starts drawing an object in the editor
	Access :		Public

	Return :		void
	Parameters :	CDiagramEntity* obj	-	Object to draw
					
	Usage :			Call to start drawing an object. The editor 
					takes ownership of the object.

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

	UnselectAll();

	CUMLEntity* uml = static_cast< CUMLEntity* >( obj );
	uml->SetPackage( GetPackage() );
	uml->SetDisplayOptions( GetDisplayOptions() );

	CDiagramEditor::StartDrawingObject( obj );

}

void CUMLEditor::OnObjectCommand( UINT nID )
/* ============================================================
	Function :		CUMLEditor::OnObjectCommand
	Description :	Command handler for the commands issued 
					from an object popup menu.
	Access :		Protected

	Return :		void
	Parameters :	UINT nID	-	ID of command
					
	Usage :			Called from MFC. We check and execute the 
					package Open command here.

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

	CUMLEntityPackage* package = dynamic_cast< CUMLEntityPackage* >( GetSelectedObject() );
	if( package && nID == CMD_OPEN )
	{
		UnselectAll();
		SetPackage( package->GetName() );
		RedrawWindow();
	}
	else
		CDiagramEditor::OnObjectCommand( nID );

}

void CUMLEditor::SelectAll()
/* ============================================================
	Function :		CUMLEditor::SelectAll
	Description :	Selects all objects in the current package.
	Access :		Public

	Return :		void
	Parameters :	none

	Usage :			Call to select all objects.

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

	int count = 0;
	CUMLEntity* obj;
	while( ( obj = GetObjectAt( count++ ) ) )
		if( obj->GetPackage() == GetPackage() )
			obj->Select( TRUE );

	RedrawWindow();

}

/////////////////////////////////////////////////////////////////////////////
// CUMLEditor message handlers
//

void CUMLEditor::OnLButtonDown( UINT nFlags, CPoint point )
/* ============================================================
	Function :		CUMLEditor::OnLButtonDown
	Description :	Command handler for the "WM_LBUTTONDOWN" 
					message.
	Access :		Protected

	Return :		void
	Parameters :	UINT nFlags		-	Not used
					CPoint point	-	Mouse position
					
	Usage :			Called from MFC. Extra processing is made 
					here regarding links and packages.

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

⌨️ 快捷键说明

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