mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
474 lines
10 KiB
474 lines
10 KiB
// drawtool.cpp - implementation for drawing tools
|
|
//
|
|
// This is a part of the Microsoft Foundation Classes C++ library.
|
|
// Copyright (C) 1992-1993 Microsoft Corporation
|
|
// All rights reserved.
|
|
//
|
|
// This source code is only intended as a supplement to the
|
|
// Microsoft Foundation Classes Reference and Microsoft
|
|
// QuickHelp and/or WinHelp documentation provided with the library.
|
|
// See these sources for detailed information regarding the
|
|
// Microsoft Foundation Classes product.
|
|
|
|
|
|
#include "stdafx.h"
|
|
#include "SepEdt.h"
|
|
#include "drawdoc.h"
|
|
#include "drawvw.h"
|
|
#include "drawobj.h"
|
|
#include "drawtool.h"
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CDrawTool implementation
|
|
|
|
CPtrList CDrawTool::c_tools;
|
|
|
|
static CSelectTool selectTool;
|
|
static CRectTool lineTool(line);
|
|
static CRectTool rectTool(rect);
|
|
static CRectTool roundRectTool(roundRect);
|
|
static CRectTool ellipseTool(ellipse);
|
|
static CRectTool textTool(text);
|
|
static CPolyTool polyTool;
|
|
|
|
CPoint CDrawTool::c_down;
|
|
UINT CDrawTool::c_nDownFlags;
|
|
CPoint CDrawTool::c_last;
|
|
DrawShape CDrawTool::c_drawShape = selection;
|
|
|
|
CDrawTool::CDrawTool(DrawShape drawShape)
|
|
{
|
|
m_drawShape = drawShape;
|
|
c_tools.AddTail(this);
|
|
}
|
|
|
|
CDrawTool* CDrawTool::FindTool(DrawShape drawShape)
|
|
{
|
|
POSITION pos = c_tools.GetHeadPosition();
|
|
while (pos != NULL)
|
|
{
|
|
CDrawTool* pTool = (CDrawTool*)c_tools.GetNext(pos);
|
|
if (pTool->m_drawShape == drawShape)
|
|
return pTool;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
void CDrawTool::OnLButtonDown(CDrawView* pView, UINT nFlags, const CPoint& point)
|
|
{
|
|
// deactivate any in-place active item on this view!
|
|
COleClientItem* pActiveItem = pView->GetDocument()->GetInPlaceActiveItem(pView);
|
|
if (pActiveItem != NULL)
|
|
{
|
|
pActiveItem->Close();
|
|
ASSERT(pView->GetDocument()->GetInPlaceActiveItem(pView) == NULL);
|
|
}
|
|
|
|
pView->CloseEdit(); // close edit when necessary
|
|
|
|
if (!pActiveItem) pView->SetCapture();
|
|
c_nDownFlags = nFlags;
|
|
c_down = point;
|
|
c_last = point;
|
|
}
|
|
|
|
void CDrawTool::OnLButtonDblClk(CDrawView*, UINT, const CPoint&)
|
|
{
|
|
}
|
|
|
|
void CDrawTool::OnLButtonUp(CDrawView*, UINT, const CPoint& point)
|
|
{
|
|
ReleaseCapture();
|
|
|
|
// if (point == c_down)
|
|
c_drawShape = selection;
|
|
}
|
|
|
|
void CDrawTool::OnMouseMove(CDrawView*, UINT, const CPoint& point)
|
|
{
|
|
c_last = point;
|
|
SetCursor(AfxGetApp()->LoadStandardCursor(IDC_ARROW));
|
|
}
|
|
|
|
void CDrawTool::OnCancel()
|
|
{
|
|
c_drawShape = selection;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
// CSelectTool
|
|
|
|
enum SelectMode
|
|
{
|
|
none,
|
|
netSelect,
|
|
move,
|
|
size
|
|
};
|
|
|
|
SelectMode selectMode = none;
|
|
int nDragHandle;
|
|
|
|
CPoint lastPoint;
|
|
|
|
CSelectTool::CSelectTool()
|
|
: CDrawTool(selection)
|
|
{
|
|
}
|
|
|
|
void CSelectTool::OnLButtonDown(CDrawView* pView, UINT nFlags, const CPoint& point)
|
|
{
|
|
BOOL closeedit=TRUE;
|
|
CPoint local = point;
|
|
pView->ClientToDoc(local);
|
|
|
|
CDrawObj* pObj;
|
|
selectMode = none;
|
|
|
|
// Check for resizing (only allowed on single selections)
|
|
if (pView->m_selection.GetCount() == 1)
|
|
{
|
|
pObj = pView->m_selection.GetHead();
|
|
nDragHandle = pObj->HitTest(local, pView, TRUE);
|
|
if (nDragHandle != 0)
|
|
{
|
|
selectMode = size;
|
|
closeedit = (pObj!=pView->m_ptext);
|
|
}
|
|
}
|
|
|
|
// if (closeedit)
|
|
// pView->CloseEdit(); // close edit if not sizing it
|
|
|
|
|
|
// See if the click was on an object, select and start move if so
|
|
if (selectMode == none)
|
|
{
|
|
pObj = pView->GetDocument()->ObjectAt(local);
|
|
|
|
if (pObj != NULL)
|
|
{
|
|
selectMode = move;
|
|
|
|
if (!pView->IsSelected(pObj))
|
|
pView->Select(pObj, (nFlags & MK_SHIFT) != 0);
|
|
|
|
// Ctrl+Click clones the selection...
|
|
if ((nFlags & MK_CONTROL) != 0)
|
|
pView->CloneSelection();
|
|
}
|
|
}
|
|
|
|
// Click on background, start a net-selection
|
|
if (selectMode == none)
|
|
{
|
|
if ((nFlags & MK_SHIFT) == 0)
|
|
pView->Select(NULL); // remove all current selections
|
|
|
|
selectMode = netSelect;
|
|
|
|
CClientDC dc(pView);
|
|
CRect rect(point.x, point.y, point.x, point.y);
|
|
rect.NormalizeRect();
|
|
dc.DrawFocusRect(rect);
|
|
}
|
|
|
|
lastPoint = local;
|
|
CDrawTool::OnLButtonDown(pView, nFlags, point);
|
|
}
|
|
|
|
void CSelectTool::OnLButtonDblClk(CDrawView* pView, UINT nFlags, const CPoint& point)
|
|
{
|
|
if ((nFlags & MK_SHIFT) != 0)
|
|
{
|
|
// Shift+DblClk deselects object...
|
|
CPoint local = point;
|
|
pView->ClientToDoc(local);
|
|
CDrawObj* pObj = pView->GetDocument()->ObjectAt(local);
|
|
if (pObj != NULL)
|
|
pView->Deselect(pObj);
|
|
}
|
|
else
|
|
{
|
|
// "Normal" DblClk opens properties, or OLE server...
|
|
if (pView->m_selection.GetCount() == 1)
|
|
pView->m_selection.GetHead()->OnOpen(pView);
|
|
}
|
|
|
|
CDrawTool::OnLButtonDblClk(pView, nFlags, point);
|
|
}
|
|
|
|
void CSelectTool::OnLButtonUp(CDrawView* pView, UINT nFlags, const CPoint& point)
|
|
{
|
|
if (pView->GetCapture() == pView)
|
|
{
|
|
if (selectMode == netSelect)
|
|
{
|
|
CClientDC dc(pView);
|
|
CRect rect(c_down.x, c_down.y, c_last.x, c_last.y);
|
|
rect.NormalizeRect();
|
|
dc.DrawFocusRect(rect);
|
|
|
|
pView->SelectWithinRect(rect, TRUE);
|
|
}
|
|
else if (selectMode != none)
|
|
{
|
|
pView->GetDocument()->UpdateAllViews(pView);
|
|
}
|
|
}
|
|
|
|
CDrawTool::OnLButtonUp(pView, nFlags, point);
|
|
}
|
|
|
|
void CSelectTool::OnMouseMove(CDrawView* pView, UINT nFlags, const CPoint& point)
|
|
{
|
|
if (pView->GetCapture() != pView)
|
|
{
|
|
if (c_drawShape == selection && pView->m_selection.GetCount() == 1)
|
|
{
|
|
CDrawObj* pObj = pView->m_selection.GetHead();
|
|
CPoint local = point;
|
|
pView->ClientToDoc(local);
|
|
int nHandle = pObj->HitTest(local, pView, TRUE);
|
|
if (nHandle != 0)
|
|
{
|
|
SetCursor(pObj->GetHandleCursor(nHandle));
|
|
return; // bypass CDrawTool
|
|
}
|
|
}
|
|
if (c_drawShape == selection)
|
|
CDrawTool::OnMouseMove(pView, nFlags, point);
|
|
return;
|
|
}
|
|
|
|
if (selectMode == netSelect)
|
|
{
|
|
CClientDC dc(pView);
|
|
CRect rect(c_down.x, c_down.y, c_last.x, c_last.y);
|
|
rect.NormalizeRect();
|
|
dc.DrawFocusRect(rect);
|
|
rect.SetRect(c_down.x, c_down.y, point.x, point.y);
|
|
rect.NormalizeRect();
|
|
dc.DrawFocusRect(rect);
|
|
|
|
CDrawTool::OnMouseMove(pView, nFlags, point);
|
|
return;
|
|
}
|
|
|
|
CPoint local = point;
|
|
pView->ClientToDoc(local);
|
|
CPoint delta = (CPoint)(local - lastPoint);
|
|
|
|
POSITION pos = pView->m_selection.GetHeadPosition();
|
|
while (pos != NULL)
|
|
{
|
|
CDrawObj* pObj = pView->m_selection.GetNext(pos);
|
|
CRect position = pObj->m_position;
|
|
|
|
if (selectMode == move)
|
|
{
|
|
position += delta;
|
|
pObj->MoveTo(position, pView);
|
|
}
|
|
else if (nDragHandle != 0)
|
|
{
|
|
pObj->MoveHandleTo(nDragHandle, local, pView);
|
|
}
|
|
}
|
|
|
|
lastPoint = local;
|
|
|
|
if (selectMode == size && c_drawShape == selection)
|
|
{
|
|
c_last = point;
|
|
SetCursor(pView->m_selection.GetHead()->GetHandleCursor(nDragHandle));
|
|
return; // bypass CDrawTool
|
|
}
|
|
|
|
c_last = point;
|
|
|
|
if (c_drawShape == selection)
|
|
CDrawTool::OnMouseMove(pView, nFlags, point);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
// CRectTool (does rectangles, round-rectangles, and ellipses)
|
|
|
|
CRectTool::CRectTool(DrawShape drawShape)
|
|
: CDrawTool(drawShape)
|
|
{
|
|
}
|
|
|
|
void CRectTool::OnLButtonDown(CDrawView* pView, UINT nFlags, const CPoint& point)
|
|
{
|
|
CDrawTool::OnLButtonDown(pView, nFlags, point);
|
|
|
|
CPoint local = point;
|
|
pView->ClientToDoc(local);
|
|
|
|
CDrawRect* pObj = new CDrawRect(CRect(local, CSize(0, 0)));
|
|
switch (m_drawShape)
|
|
{
|
|
default:
|
|
ASSERT(FALSE); // unsuported shape!
|
|
|
|
case rect:
|
|
pObj->m_nShape = CDrawRect::rectangle;
|
|
break;
|
|
|
|
case roundRect:
|
|
pObj->m_nShape = CDrawRect::roundRectangle;
|
|
break;
|
|
|
|
case ellipse:
|
|
pObj->m_nShape = CDrawRect::ellipse;
|
|
break;
|
|
|
|
case line:
|
|
pObj->m_nShape = CDrawRect::line;
|
|
break;
|
|
|
|
case text:
|
|
delete pObj;
|
|
pObj = new CDrawText(CRect(local, CSize(0, 0))); // construct a text obj
|
|
pObj->m_nShape = CDrawRect::text;
|
|
break;
|
|
}
|
|
pView->GetDocument()->Add(pObj);
|
|
pView->Select(pObj);
|
|
|
|
selectMode = size;
|
|
nDragHandle = 1;
|
|
lastPoint = local;
|
|
}
|
|
|
|
void CRectTool::OnLButtonDblClk(CDrawView* pView, UINT nFlags, const CPoint& point)
|
|
{
|
|
CDrawTool::OnLButtonDblClk(pView, nFlags, point);
|
|
}
|
|
|
|
void CRectTool::OnLButtonUp(CDrawView* pView, UINT nFlags, const CPoint& point)
|
|
{
|
|
if (point == c_down)
|
|
{
|
|
// Don't create empty objects...
|
|
CDrawObj *pObj = pView->m_selection.GetTail();
|
|
pView->GetDocument()->Remove(pObj);
|
|
pObj->Remove();
|
|
selectTool.OnLButtonDown(pView, nFlags, point); // try a select!
|
|
}
|
|
|
|
selectTool.OnLButtonUp(pView, nFlags, point);
|
|
}
|
|
|
|
void CRectTool::OnMouseMove(CDrawView* pView, UINT nFlags, const CPoint& point)
|
|
{
|
|
SetCursor(AfxGetApp()->LoadStandardCursor(IDC_CROSS));
|
|
selectTool.OnMouseMove(pView, nFlags, point);
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
// CPolyTool
|
|
|
|
CPolyTool::CPolyTool()
|
|
: CDrawTool(poly)
|
|
{
|
|
m_pDrawObj = NULL;
|
|
}
|
|
|
|
void CPolyTool::OnLButtonDown(CDrawView* pView, UINT nFlags, const CPoint& point)
|
|
{
|
|
CDrawTool::OnLButtonDown(pView, nFlags, point);
|
|
|
|
CPoint local = point;
|
|
pView->ClientToDoc(local);
|
|
|
|
if (m_pDrawObj == NULL)
|
|
{
|
|
pView->SetCapture();
|
|
|
|
m_pDrawObj = new CDrawPoly(CRect(local, CSize(0, 0)));
|
|
pView->GetDocument()->Add(m_pDrawObj);
|
|
pView->Select(m_pDrawObj);
|
|
m_pDrawObj->AddPoint(local, pView);
|
|
}
|
|
else if (local == m_pDrawObj->m_points[0])
|
|
{
|
|
// Stop when the first point is repeated...
|
|
ReleaseCapture();
|
|
m_pDrawObj->m_nPoints -= 1;
|
|
if (m_pDrawObj->m_nPoints < 2)
|
|
{
|
|
m_pDrawObj->Remove();
|
|
}
|
|
else
|
|
{
|
|
pView->InvalObj(m_pDrawObj);
|
|
}
|
|
m_pDrawObj = NULL;
|
|
c_drawShape = selection;
|
|
return;
|
|
}
|
|
|
|
local.x += 1; // adjacent points can't be the same!
|
|
m_pDrawObj->AddPoint(local, pView);
|
|
|
|
selectMode = size;
|
|
nDragHandle = m_pDrawObj->GetHandleCount();
|
|
lastPoint = local;
|
|
}
|
|
|
|
void CPolyTool::OnLButtonUp(CDrawView* , UINT , const CPoint& )
|
|
{
|
|
// Don't release capture yet!
|
|
}
|
|
|
|
void CPolyTool::OnMouseMove(CDrawView* pView, UINT nFlags, const CPoint& point)
|
|
{
|
|
if (m_pDrawObj != NULL && (nFlags & MK_LBUTTON) != 0)
|
|
{
|
|
CPoint local = point;
|
|
pView->ClientToDoc(local);
|
|
m_pDrawObj->AddPoint(local);
|
|
nDragHandle = m_pDrawObj->GetHandleCount();
|
|
lastPoint = local;
|
|
c_last = point;
|
|
SetCursor(AfxGetApp()->LoadCursor(IDC_PENCIL));
|
|
}
|
|
else
|
|
{
|
|
SetCursor(AfxGetApp()->LoadStandardCursor(IDC_CROSS));
|
|
selectTool.OnMouseMove(pView, nFlags, point);
|
|
}
|
|
}
|
|
|
|
void CPolyTool::OnLButtonDblClk(CDrawView* pView, UINT , const CPoint& )
|
|
{
|
|
ReleaseCapture();
|
|
|
|
int nPoints = m_pDrawObj->m_nPoints;
|
|
if (nPoints > 2 &&
|
|
(m_pDrawObj->m_points[nPoints - 1] == m_pDrawObj->m_points[nPoints - 2] ||
|
|
m_pDrawObj->m_points[nPoints - 1].x - 1 == m_pDrawObj->m_points[nPoints - 2].x &&
|
|
m_pDrawObj->m_points[nPoints - 1].y == m_pDrawObj->m_points[nPoints - 2].y))
|
|
|
|
{
|
|
// Nuke the last point if it's the same as the next to last...
|
|
m_pDrawObj->m_nPoints -= 1;
|
|
pView->InvalObj(m_pDrawObj);
|
|
}
|
|
|
|
m_pDrawObj = NULL;
|
|
c_drawShape = selection;
|
|
}
|
|
|
|
void CPolyTool::OnCancel()
|
|
{
|
|
CDrawTool::OnCancel();
|
|
|
|
m_pDrawObj = NULL;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|