home *** CD-ROM | disk | FTP | other *** search
/ QBasic & Borland Pascal & C / Delphi5.iso / C / BC_502 / DRAWCL.PAK / DRAWTOOL.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1997-05-06  |  10.9 KB  |  472 lines

  1. // drawtool.cpp - implementation for drawing tools
  2. //
  3. // This is a part of the Microsoft Foundation Classes C++ library.
  4. // Copyright (C) 1992-1995 Microsoft Corporation
  5. // All rights reserved.
  6. //
  7. // This source code is only intended as a supplement to the
  8. // Microsoft Foundation Classes Reference and related
  9. // electronic documentation provided with the library.
  10. // See these sources for detailed information regarding the
  11. // Microsoft Foundation Classes product.
  12.  
  13.  
  14. #include "stdafx.h"
  15. #include "drawcli.h"
  16. #include "drawdoc.h"
  17. #include "drawvw.h"
  18. #include "drawobj.h"
  19. #include "drawtool.h"
  20.  
  21. /////////////////////////////////////////////////////////////////////////////
  22. // CDrawTool implementation
  23.  
  24. CPtrList CDrawTool::c_tools;
  25.  
  26. static CSelectTool selectTool;
  27. static CRectTool lineTool(line);
  28. static CRectTool rectTool(rect);
  29. static CRectTool roundRectTool(roundRect);
  30. static CRectTool ellipseTool(ellipse);
  31. static CPolyTool polyTool;
  32.  
  33. CPoint CDrawTool::c_down;
  34. UINT CDrawTool::c_nDownFlags;
  35. CPoint CDrawTool::c_last;
  36. DrawShape CDrawTool::c_drawShape = selection;
  37.  
  38. CDrawTool::CDrawTool(DrawShape drawShape)
  39. {
  40.     m_drawShape = drawShape;
  41.     c_tools.AddTail(this);
  42. }
  43.  
  44. CDrawTool* CDrawTool::FindTool(DrawShape drawShape)
  45. {
  46.     POSITION pos = c_tools.GetHeadPosition();
  47.     while (pos != NULL)
  48.     {
  49.         CDrawTool* pTool = (CDrawTool*)c_tools.GetNext(pos);
  50.         if (pTool->m_drawShape == drawShape)
  51.             return pTool;
  52.     }
  53.  
  54.     return NULL;
  55. }
  56.  
  57. void CDrawTool::OnLButtonDown(CDrawView* pView, UINT nFlags, const CPoint& point)
  58. {
  59.     // deactivate any in-place active item on this view!
  60.     COleClientItem* pActiveItem = pView->GetDocument()->GetInPlaceActiveItem(pView);
  61.     if (pActiveItem != NULL)
  62.     {
  63.         pActiveItem->Close();
  64.         ASSERT(pView->GetDocument()->GetInPlaceActiveItem(pView) == NULL);
  65.     }
  66.  
  67.     pView->SetCapture();
  68.     c_nDownFlags = nFlags;
  69.     c_down = point;
  70.     c_last = point;
  71. }
  72.  
  73. void CDrawTool::OnLButtonDblClk(CDrawView* /*pView*/, UINT /*nFlags*/, const CPoint& /*point*/)
  74. {
  75. }
  76.  
  77. void CDrawTool::OnLButtonUp(CDrawView* /*pView*/, UINT /*nFlags*/, const CPoint& point)
  78. {
  79.     ReleaseCapture();
  80.  
  81.     if (point == c_down)
  82.         c_drawShape = selection;
  83. }
  84.  
  85. void CDrawTool::OnMouseMove(CDrawView* /*pView*/, UINT /*nFlags*/, const CPoint& point)
  86. {
  87.     c_last = point;
  88.     SetCursor(AfxGetApp()->LoadStandardCursor(IDC_ARROW));
  89. }
  90.  
  91. void CDrawTool::OnEditProperties(CDrawView* /*pView*/)
  92. {
  93. }
  94.  
  95. void CDrawTool::OnCancel()
  96. {
  97.     c_drawShape = selection;
  98. }
  99.  
  100. ////////////////////////////////////////////////////////////////////////////
  101. // CResizeTool
  102.  
  103. enum SelectMode
  104. {
  105.     none,
  106.     netSelect,
  107.     move,
  108.     size
  109. };
  110.  
  111. SelectMode selectMode = none;
  112. int nDragHandle;
  113.  
  114. CPoint lastPoint;
  115.  
  116. CSelectTool::CSelectTool()
  117.     : CDrawTool(selection)
  118. {
  119. }
  120.  
  121. void CSelectTool::OnLButtonDown(CDrawView* pView, UINT nFlags, const CPoint& point)
  122. {
  123.     CPoint local = point;
  124.     pView->ClientToDoc(local);
  125.  
  126.     CDrawObj* pObj;
  127.     selectMode = none;
  128.  
  129.     // Check for resizing (only allowed on single selections)
  130.     if (pView->m_selection.GetCount() == 1)
  131.     {
  132.         pObj = pView->m_selection.GetHead();
  133.         nDragHandle = pObj->HitTest(local, pView, TRUE);
  134.         if (nDragHandle != 0)
  135.             selectMode = size;
  136.     }
  137.  
  138.     // See if the click was on an object, select and start move if so
  139.     if (selectMode == none)
  140.     {
  141.         pObj = pView->GetDocument()->ObjectAt(local);
  142.  
  143.         if (pObj != NULL)
  144.         {
  145.             selectMode = move;
  146.  
  147.             if (!pView->IsSelected(pObj))
  148.                 pView->Select(pObj, (nFlags & MK_SHIFT) != 0);
  149.  
  150.             // Ctrl+Click clones the selection...
  151. #ifndef _MAC            
  152.             if ((nFlags & MK_CONTROL) != 0)
  153. #else
  154.             if ((nFlags & MK_OPTION) != 0)
  155. #endif            
  156.                 pView->CloneSelection();
  157.         }
  158.     }
  159.  
  160.     // Click on background, start a net-selection
  161.     if (selectMode == none)
  162.     {
  163.         if ((nFlags & MK_SHIFT) == 0)
  164.             pView->Select(NULL);
  165.  
  166.         selectMode = netSelect;
  167.  
  168.         CClientDC dc(pView);
  169.         CRect rect(point.x, point.y, point.x, point.y);
  170.         rect.NormalizeRect();
  171.         dc.DrawFocusRect(rect);
  172.     }
  173.  
  174.     lastPoint = local;
  175.     CDrawTool::OnLButtonDown(pView, nFlags, point);
  176. }
  177.  
  178. void CSelectTool::OnLButtonDblClk(CDrawView* pView, UINT nFlags, const CPoint& point)
  179. {
  180.     if ((nFlags & MK_SHIFT) != 0)
  181.     {
  182.         // Shift+DblClk deselects object...
  183.         CPoint local = point;
  184.         pView->ClientToDoc(local);
  185.         CDrawObj* pObj = pView->GetDocument()->ObjectAt(local);
  186.         if (pObj != NULL)
  187.             pView->Deselect(pObj);
  188.     }
  189.     else
  190.     {
  191.         // "Normal" DblClk opens properties, or OLE server...
  192.         if (pView->m_selection.GetCount() == 1)
  193.             pView->m_selection.GetHead()->OnOpen(pView);
  194.     }
  195.  
  196.     CDrawTool::OnLButtonDblClk(pView, nFlags, point);
  197. }
  198.  
  199. void CSelectTool::OnEditProperties(CDrawView* pView)
  200. {
  201.     if (pView->m_selection.GetCount() == 1)
  202.         pView->m_selection.GetHead()->OnEditProperties();
  203. }
  204.  
  205. void CSelectTool::OnLButtonUp(CDrawView* pView, UINT nFlags, const CPoint& point)
  206. {
  207.     if (pView->GetCapture() == pView)
  208.     {
  209.         if (selectMode == netSelect)
  210.         {
  211.             CClientDC dc(pView);
  212.             CRect rect(c_down.x, c_down.y, c_last.x, c_last.y);
  213.             rect.NormalizeRect();
  214.             dc.DrawFocusRect(rect);
  215.  
  216.             pView->SelectWithinRect(rect, TRUE);
  217.         }
  218.         else if (selectMode != none)
  219.         {
  220.             pView->GetDocument()->UpdateAllViews(pView);
  221.         }
  222.     }
  223.  
  224.     CDrawTool::OnLButtonUp(pView, nFlags, point);
  225. }
  226.  
  227. void CSelectTool::OnMouseMove(CDrawView* pView, UINT nFlags, const CPoint& point)
  228. {
  229.     if (pView->GetCapture() != pView)
  230.     {
  231.         if (c_drawShape == selection && pView->m_selection.GetCount() == 1)
  232.         {
  233.             CDrawObj* pObj = pView->m_selection.GetHead();
  234.             CPoint local = point;
  235.             pView->ClientToDoc(local);
  236.             int nHandle = pObj->HitTest(local, pView, TRUE);
  237.             if (nHandle != 0)
  238.             {
  239.                 SetCursor(pObj->GetHandleCursor(nHandle));
  240.                 return; // bypass CDrawTool
  241.             }
  242.         }
  243.         if (c_drawShape == selection)
  244.             CDrawTool::OnMouseMove(pView, nFlags, point);
  245.         return;
  246.     }
  247.  
  248.     if (selectMode == netSelect)
  249.     {
  250.         CClientDC dc(pView);
  251.         CRect rect(c_down.x, c_down.y, c_last.x, c_last.y);
  252.         rect.NormalizeRect();
  253.         dc.DrawFocusRect(rect);
  254.         rect.SetRect(c_down.x, c_down.y, point.x, point.y);
  255.         rect.NormalizeRect();
  256.         dc.DrawFocusRect(rect);
  257.  
  258.         CDrawTool::OnMouseMove(pView, nFlags, point);
  259.         return;
  260.     }
  261.  
  262.     CPoint local = point;
  263.     pView->ClientToDoc(local);
  264.     CPoint delta = (CPoint)(local - lastPoint);
  265.  
  266.     POSITION pos = pView->m_selection.GetHeadPosition();
  267.     while (pos != NULL)
  268.     {
  269.         CDrawObj* pObj = pView->m_selection.GetNext(pos);
  270.         CRect position = pObj->m_position;
  271.  
  272.         if (selectMode == move)
  273.         {
  274.             position += delta;
  275.             pObj->MoveTo(position, pView);
  276.         }
  277.         else if (nDragHandle != 0)
  278.         {
  279.             pObj->MoveHandleTo(nDragHandle, local, pView);
  280.         }
  281.     }
  282.  
  283.     lastPoint = local;
  284.  
  285.     if (selectMode == size && c_drawShape == selection)
  286.     {
  287.         c_last = point;
  288.         SetCursor(pView->m_selection.GetHead()->GetHandleCursor(nDragHandle));
  289.         return; // bypass CDrawTool
  290.     }
  291.  
  292.     c_last = point;
  293.  
  294.     if (c_drawShape == selection)
  295.         CDrawTool::OnMouseMove(pView, nFlags, point);
  296. }
  297.  
  298. ////////////////////////////////////////////////////////////////////////////
  299. // CRectTool (does rectangles, round-rectangles, and ellipses)
  300.  
  301. CRectTool::CRectTool(DrawShape drawShape)
  302.     : CDrawTool(drawShape)
  303. {
  304. }
  305.  
  306. void CRectTool::OnLButtonDown(CDrawView* pView, UINT nFlags, const CPoint& point)
  307. {
  308.     CDrawTool::OnLButtonDown(pView, nFlags, point);
  309.  
  310.     CPoint local = point;
  311.     pView->ClientToDoc(local);
  312.  
  313.     CDrawRect* pObj = new CDrawRect(CRect(local, CSize(0, 0)));
  314.     switch (m_drawShape)
  315.     {
  316.     default:
  317.         ASSERT(FALSE); // unsuported shape!
  318.  
  319.     case rect:
  320.         pObj->m_nShape = CDrawRect::rectangle;
  321.         break;
  322.  
  323.     case roundRect:
  324.         pObj->m_nShape = CDrawRect::roundRectangle;
  325.         break;
  326.  
  327.     case ellipse:
  328.         pObj->m_nShape = CDrawRect::ellipse;
  329.         break;
  330.  
  331.     case line:
  332.         pObj->m_nShape = CDrawRect::line;
  333.         break;
  334.     }
  335.     pView->GetDocument()->Add(pObj);
  336.     pView->Select(pObj);
  337.  
  338.     selectMode = size;
  339.     nDragHandle = 1;
  340.     lastPoint = local;
  341. }
  342.  
  343. void CRectTool::OnLButtonDblClk(CDrawView* pView, UINT nFlags, const CPoint& point)
  344. {
  345.     CDrawTool::OnLButtonDblClk(pView, nFlags, point);
  346. }
  347.  
  348. void CRectTool::OnLButtonUp(CDrawView* pView, UINT nFlags, const CPoint& point)
  349. {
  350.     if (point == c_down)
  351.     {
  352.         // Don't create empty objects...
  353.         CDrawObj *pObj = pView->m_selection.GetTail();
  354.         pView->GetDocument()->Remove(pObj);
  355.         pObj->Remove();
  356.         selectTool.OnLButtonDown(pView, nFlags, point); // try a select!
  357.     }
  358.  
  359.     selectTool.OnLButtonUp(pView, nFlags, point);
  360. }
  361.  
  362. void CRectTool::OnMouseMove(CDrawView* pView, UINT nFlags, const CPoint& point)
  363. {
  364.     SetCursor(AfxGetApp()->LoadStandardCursor(IDC_CROSS));
  365.     selectTool.OnMouseMove(pView, nFlags, point);
  366. }
  367.  
  368.  
  369. ////////////////////////////////////////////////////////////////////////////
  370. // CPolyTool
  371.  
  372. CPolyTool::CPolyTool()
  373.     : CDrawTool(poly)
  374. {
  375.     m_pDrawObj = NULL;
  376. }
  377.  
  378. void CPolyTool::OnLButtonDown(CDrawView* pView, UINT nFlags, const CPoint& point)
  379. {
  380.     CDrawTool::OnLButtonDown(pView, nFlags, point);
  381.  
  382.     CPoint local = point;
  383.     pView->ClientToDoc(local);
  384.  
  385.     if (m_pDrawObj == NULL)
  386.     {
  387.         pView->SetCapture();
  388.  
  389.         m_pDrawObj = new CDrawPoly(CRect(local, CSize(0, 0)));
  390.         pView->GetDocument()->Add(m_pDrawObj);
  391.         pView->Select(m_pDrawObj);
  392.         m_pDrawObj->AddPoint(local, pView);
  393.     }
  394.     else if (local == m_pDrawObj->m_points[0])
  395.     {
  396.         // Stop when the first point is repeated...
  397.         ReleaseCapture();
  398.         m_pDrawObj->m_nPoints -= 1;
  399.         if (m_pDrawObj->m_nPoints < 2)
  400.         {
  401.             m_pDrawObj->Remove();
  402.         }
  403.         else
  404.         {
  405.             pView->InvalObj(m_pDrawObj);
  406.         }
  407.         m_pDrawObj = NULL;
  408.         c_drawShape = selection;
  409.         return;
  410.     }
  411.  
  412.     local.x += 1; // adjacent points can't be the same!
  413.     m_pDrawObj->AddPoint(local, pView);
  414.  
  415.     selectMode = size;
  416.     nDragHandle = m_pDrawObj->GetHandleCount();
  417.     lastPoint = local;
  418. }
  419.  
  420. void CPolyTool::OnLButtonUp(CDrawView* /*pView*/, UINT /*nFlags*/, const CPoint& /*point*/)
  421. {
  422.     // Don't release capture yet!
  423. }
  424.  
  425. void CPolyTool::OnMouseMove(CDrawView* pView, UINT nFlags, const CPoint& point)
  426. {
  427.     if (m_pDrawObj != NULL && (nFlags & MK_LBUTTON) != 0)
  428.     {
  429.         CPoint local = point;
  430.         pView->ClientToDoc(local);
  431.         m_pDrawObj->AddPoint(local);
  432.         nDragHandle = m_pDrawObj->GetHandleCount();
  433.         lastPoint = local;
  434.         c_last = point;
  435.         SetCursor(AfxGetApp()->LoadCursor(IDC_PENCIL));
  436.     }
  437.     else
  438.     {
  439.         SetCursor(AfxGetApp()->LoadStandardCursor(IDC_CROSS));
  440.         selectTool.OnMouseMove(pView, nFlags, point);
  441.     }
  442. }
  443.  
  444. void CPolyTool::OnLButtonDblClk(CDrawView* pView, UINT , const CPoint& )
  445. {
  446.     ReleaseCapture();
  447.  
  448.     int nPoints = m_pDrawObj->m_nPoints;
  449.     if (nPoints > 2 &&
  450.         (m_pDrawObj->m_points[nPoints - 1] == m_pDrawObj->m_points[nPoints - 2] ||
  451.         m_pDrawObj->m_points[nPoints - 1].x - 1 == m_pDrawObj->m_points[nPoints - 2].x &&
  452.         m_pDrawObj->m_points[nPoints - 1].y == m_pDrawObj->m_points[nPoints - 2].y))
  453.  
  454.     {
  455.         // Nuke the last point if it's the same as the next to last...
  456.         m_pDrawObj->m_nPoints -= 1;
  457.         pView->InvalObj(m_pDrawObj);
  458.     }
  459.  
  460.     m_pDrawObj = NULL;
  461.     c_drawShape = selection;
  462. }
  463.  
  464. void CPolyTool::OnCancel()
  465. {
  466.     CDrawTool::OnCancel();
  467.  
  468.     m_pDrawObj = NULL;
  469. }
  470.  
  471. /////////////////////////////////////////////////////////////////////////////
  472.