home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / wxos2233.zip / wxOS2-2_3_3.zip / wxWindows-2.3.3 / contrib / samples / ogl / ogledit / doc.cpp next >
C/C++ Source or Header  |  2001-10-30  |  15KB  |  612 lines

  1. /////////////////////////////////////////////////////////////////////////////
  2. // Name:        doc.cpp
  3. // Purpose:     Implements document functionality in OGLEdit
  4. // Author:      Julian Smart
  5. // Modified by:
  6. // Created:     12/07/98
  7. // RCS-ID:      $Id: doc.cpp,v 1.3 2001/10/30 13:28:45 GT Exp $
  8. // Copyright:   (c) Julian Smart
  9. // Licence:       wxWindows licence
  10. /////////////////////////////////////////////////////////////////////////////
  11.  
  12. #ifdef __GNUG__
  13. // #pragma implementation
  14. #endif
  15.  
  16. // For compilers that support precompilation, includes "wx.h".
  17. #include "wx/wxprec.h"
  18.  
  19. #ifdef __BORLANDC__
  20. #pragma hdrstop
  21. #endif
  22.  
  23. #ifndef WX_PRECOMP
  24. #include <wx/wx.h>
  25. #endif
  26.  
  27. #if !wxUSE_DOC_VIEW_ARCHITECTURE
  28. #error You must set wxUSE_DOC_VIEW_ARCHITECTURE to 1 in wx_setup.h!
  29. #endif
  30.  
  31. #include <wx/wxexpr.h>
  32. #include "ogledit.h"
  33. #include "doc.h"
  34. #include "view.h"
  35.  
  36. #if wxUSE_STD_IOSTREAM
  37. #include <ioswrap.h>
  38. #endif
  39.  
  40. IMPLEMENT_DYNAMIC_CLASS(DiagramDocument, wxDocument)
  41.  
  42. DiagramDocument::DiagramDocument(void)
  43. {
  44. }
  45.  
  46. DiagramDocument::~DiagramDocument(void)
  47. {
  48. }
  49.  
  50. bool DiagramDocument::OnCloseDocument(void)
  51. {
  52.   diagram.DeleteAllShapes();
  53.   return TRUE;
  54. }
  55.  
  56. #if wxUSE_STD_IOSTREAM
  57. wxSTD ostream& DiagramDocument::SaveObject(wxSTD ostream& stream)
  58. {
  59.   wxDocument::SaveObject(stream);
  60.   
  61.   char buf[400];
  62.   (void) wxGetTempFileName("diag", buf);
  63.  
  64.   diagram.SaveFile(buf);
  65.   wxTransferFileToStream(buf, stream);
  66.  
  67.   wxRemoveFile(buf);
  68.   
  69.   return stream;
  70. }
  71.  
  72. wxSTD istream& DiagramDocument::LoadObject(wxSTD istream& stream)
  73. {
  74.   wxDocument::LoadObject(stream);
  75.  
  76.   char buf[400];
  77.   (void) wxGetTempFileName("diag", buf);
  78.  
  79.   wxTransferStreamToFile(stream, buf);
  80.  
  81.   diagram.DeleteAllShapes();
  82.   diagram.LoadFile(buf);
  83.   wxRemoveFile(buf);
  84.  
  85.   return stream;
  86. }
  87. #else
  88.  
  89. wxOutputStream& DiagramDocument::SaveObject(wxOutputStream& stream)
  90. {
  91.   wxDocument::SaveObject(stream);
  92.   char buf[400];
  93.   (void) wxGetTempFileName("diag", buf);
  94.  
  95.   diagram.SaveFile(buf);
  96.  
  97.   wxTransferFileToStream(buf, stream);
  98.  
  99.   wxRemoveFile(buf);
  100.   
  101.  
  102.   return stream;
  103. }
  104.  
  105. wxInputStream& DiagramDocument::LoadObject(wxInputStream& stream)
  106. {
  107.   wxDocument::LoadObject(stream);
  108.  
  109.  
  110.   char buf[400];
  111.   (void) wxGetTempFileName("diag", buf);
  112.  
  113.   wxTransferStreamToFile(stream, buf);
  114.  
  115.   diagram.DeleteAllShapes();
  116.   diagram.LoadFile(buf);
  117.   wxRemoveFile(buf);
  118.  
  119.   return stream;
  120. }
  121.  
  122. #endif
  123.  
  124. /*
  125.  * Implementation of drawing command
  126.  */
  127.  
  128. DiagramCommand::DiagramCommand(char *name, int command, DiagramDocument *ddoc, wxClassInfo *info, double xx, double yy,
  129.   bool sel, wxShape *theShape, wxShape *fs, wxShape *ts):
  130.   wxCommand(TRUE, name)
  131. {
  132.   doc = ddoc;
  133.   cmd = command;
  134.   shape = theShape;
  135.   fromShape = fs;
  136.   toShape = ts;
  137.   shapeInfo = info;
  138.   shapeBrush = NULL;
  139.   shapePen = NULL;
  140.   x = xx;
  141.   y = yy;
  142.   selected = sel;
  143.   deleteShape = FALSE;
  144. }
  145.  
  146. DiagramCommand::DiagramCommand(char *name, int command, DiagramDocument *ddoc, wxBrush *backgroundColour, wxShape *theShape):
  147.   wxCommand(TRUE, name)
  148. {
  149.   doc = ddoc;
  150.   cmd = command;
  151.   shape = theShape;
  152.   fromShape = NULL;
  153.   toShape = NULL;
  154.   shapeInfo = NULL;
  155.   x = 0.0;
  156.   y = 0.0;
  157.   selected = FALSE;
  158.   deleteShape = FALSE;
  159.   shapeBrush = backgroundColour;
  160.   shapePen = NULL;
  161. }
  162.  
  163. DiagramCommand::DiagramCommand(char *name, int command, DiagramDocument *ddoc, const wxString& lab, wxShape *theShape):
  164.   wxCommand(TRUE, name)
  165. {
  166.   doc = ddoc;
  167.   cmd = command;
  168.   shape = theShape;
  169.   fromShape = NULL;
  170.   toShape = NULL;
  171.   shapeInfo = NULL;
  172.   x = 0.0;
  173.   y = 0.0;
  174.   selected = FALSE;
  175.   deleteShape = FALSE;
  176.   shapeBrush = NULL;
  177.   shapePen = NULL;
  178.   shapeLabel = lab;
  179. }
  180.  
  181. DiagramCommand::~DiagramCommand(void)
  182. {
  183.   if (shape && deleteShape)
  184.   {
  185.     shape->SetCanvas(NULL);
  186.     delete shape;
  187.   }
  188. }
  189.  
  190. bool DiagramCommand::Do(void)
  191. {
  192.   switch (cmd)
  193.   {
  194.     case OGLEDIT_CUT:
  195.     {
  196.       if (shape)
  197.       {
  198.         deleteShape = TRUE;
  199.         
  200.         shape->Select(FALSE);
  201.         
  202.         // Generate commands to explicitly remove each connected line.
  203.         RemoveLines(shape);
  204.         
  205.         doc->GetDiagram()->RemoveShape(shape);
  206.         if (shape->IsKindOf(CLASSINFO(wxLineShape)))
  207.         {
  208.           wxLineShape *lineShape = (wxLineShape *)shape;
  209.           fromShape = lineShape->GetFrom();
  210.           toShape = lineShape->GetTo();
  211.         }
  212.         shape->Unlink();
  213.         
  214.         doc->Modify(TRUE);
  215.         doc->UpdateAllViews();
  216.       }
  217.  
  218.       break;
  219.     }
  220.     case OGLEDIT_ADD_SHAPE:
  221.     {
  222.       wxShape *theShape = NULL;
  223.       if (shape)
  224.         theShape = shape; // Saved from undoing the shape
  225.       else
  226.       {
  227.         theShape = (wxShape *)shapeInfo->CreateObject();
  228.         theShape->AssignNewIds();
  229.         theShape->SetEventHandler(new MyEvtHandler(theShape, theShape, wxString("")));
  230.         theShape->SetCentreResize(FALSE);
  231.         theShape->SetPen(wxBLACK_PEN);
  232.         theShape->SetBrush(wxCYAN_BRUSH);
  233.       
  234.         theShape->SetSize(60, 60);
  235.       }
  236.       doc->GetDiagram()->AddShape(theShape);
  237.       theShape->Show(TRUE);
  238.  
  239.       wxClientDC dc(theShape->GetCanvas());
  240.       theShape->GetCanvas()->PrepareDC(dc);
  241.  
  242.       theShape->Move(dc, x, y);
  243.       
  244.       shape = theShape;
  245.       deleteShape = FALSE;
  246.  
  247.       doc->Modify(TRUE);
  248.       doc->UpdateAllViews();
  249.       break;
  250.     }
  251.     case OGLEDIT_ADD_LINE:
  252.     {
  253.       wxShape *theShape = NULL;
  254.       if (shape)
  255.         theShape = shape; // Saved from undoing the line
  256.       else
  257.       {
  258.         theShape = (wxShape *)shapeInfo->CreateObject();
  259.         theShape->AssignNewIds();
  260.         theShape->SetEventHandler(new MyEvtHandler(theShape, theShape, wxString("")));
  261.         theShape->SetPen(wxBLACK_PEN);
  262.         theShape->SetBrush(wxRED_BRUSH);
  263.  
  264.         wxLineShape *lineShape = (wxLineShape *)theShape;
  265.  
  266.         // Yes, you can have more than 2 control points, in which case
  267.         // it becomes a multi-segment line.
  268.         lineShape->MakeLineControlPoints(2);
  269.         lineShape->AddArrow(ARROW_ARROW, ARROW_POSITION_END, 10.0, 0.0, "Normal arrowhead");
  270.       }
  271.       
  272.       doc->GetDiagram()->AddShape(theShape);
  273.       
  274.       fromShape->AddLine((wxLineShape *)theShape, toShape);
  275.       
  276.       theShape->Show(TRUE);
  277.  
  278.       wxClientDC dc(theShape->GetCanvas());
  279.       theShape->GetCanvas()->PrepareDC(dc);
  280.  
  281.       // It won't get drawn properly unless you move both
  282.       // connected images
  283.       fromShape->Move(dc, fromShape->GetX(), fromShape->GetY());
  284.       toShape->Move(dc, toShape->GetX(), toShape->GetY());
  285.       
  286.       shape = theShape;
  287.       deleteShape = FALSE;
  288.  
  289.       doc->Modify(TRUE);
  290.       doc->UpdateAllViews();
  291.       break;
  292.     }
  293.     case OGLEDIT_CHANGE_BACKGROUND_COLOUR:
  294.     {
  295.       if (shape)
  296.       {
  297.         wxClientDC dc(shape->GetCanvas());
  298.         shape->GetCanvas()->PrepareDC(dc);
  299.  
  300.         wxBrush *oldBrush = shape->GetBrush();
  301.         shape->SetBrush(shapeBrush);
  302.         shapeBrush = oldBrush;
  303.         shape->Draw(dc);
  304.         
  305.         doc->Modify(TRUE);
  306.         doc->UpdateAllViews();
  307.       }
  308.  
  309.       break;
  310.     }
  311.     case OGLEDIT_EDIT_LABEL:
  312.     {
  313.       if (shape)
  314.       {
  315.         MyEvtHandler *myHandler = (MyEvtHandler *)shape->GetEventHandler();
  316.         wxString oldLabel(myHandler->label);
  317.         myHandler->label = shapeLabel;
  318.         shapeLabel = oldLabel;
  319.  
  320.         wxClientDC dc(shape->GetCanvas());
  321.         shape->GetCanvas()->PrepareDC(dc);
  322.  
  323.         shape->FormatText(dc, (char*) (const char*) myHandler->label);
  324.         shape->Draw(dc);
  325.         
  326.         doc->Modify(TRUE);
  327.         doc->UpdateAllViews();
  328.       }
  329.  
  330.       break;
  331.     }
  332.   }
  333.   return TRUE;
  334. }
  335.  
  336. bool DiagramCommand::Undo(void)
  337. {
  338.   switch (cmd)
  339.   {
  340.     case OGLEDIT_CUT:
  341.     {
  342.       if (shape)
  343.       {
  344.         doc->GetDiagram()->AddShape(shape);
  345.         shape->Show(TRUE);
  346.  
  347.         if (shape->IsKindOf(CLASSINFO(wxLineShape)))
  348.         {
  349.           wxLineShape *lineShape = (wxLineShape *)shape;
  350.  
  351.           fromShape->AddLine(lineShape, toShape);
  352.         }
  353.         if (selected)
  354.           shape->Select(TRUE);
  355.  
  356.         deleteShape = FALSE;
  357.       }
  358.       doc->Modify(TRUE);
  359.       doc->UpdateAllViews();
  360.       break;
  361.     }
  362.     case OGLEDIT_ADD_SHAPE:
  363.     case OGLEDIT_ADD_LINE:
  364.     {
  365.       if (shape)
  366.       {
  367.         wxClientDC dc(shape->GetCanvas());
  368.         shape->GetCanvas()->PrepareDC(dc);
  369.  
  370.         shape->Select(FALSE, &dc);
  371.         doc->GetDiagram()->RemoveShape(shape);
  372.         shape->Unlink();
  373.         deleteShape = TRUE;
  374.       }
  375.       doc->Modify(TRUE);
  376.       doc->UpdateAllViews();
  377.       break;
  378.     }
  379.     case OGLEDIT_CHANGE_BACKGROUND_COLOUR:
  380.     {
  381.       if (shape)
  382.       {
  383.         wxClientDC dc(shape->GetCanvas());
  384.         shape->GetCanvas()->PrepareDC(dc);
  385.  
  386.         wxBrush *oldBrush = shape->GetBrush();
  387.         shape->SetBrush(shapeBrush);
  388.         shapeBrush = oldBrush;
  389.         shape->Draw(dc);
  390.         
  391.         doc->Modify(TRUE);
  392.         doc->UpdateAllViews();
  393.       }
  394.       break;
  395.     }
  396.     case OGLEDIT_EDIT_LABEL:
  397.     {
  398.       if (shape)
  399.       {
  400.         MyEvtHandler *myHandler = (MyEvtHandler *)shape->GetEventHandler();
  401.         wxString oldLabel(myHandler->label);
  402.         myHandler->label = shapeLabel;
  403.         shapeLabel = oldLabel;
  404.  
  405.         wxClientDC dc(shape->GetCanvas());
  406.         shape->GetCanvas()->PrepareDC(dc);
  407.  
  408.         shape->FormatText(dc, (char*) (const char*) myHandler->label);
  409.         shape->Draw(dc);
  410.         
  411.         doc->Modify(TRUE);
  412.         doc->UpdateAllViews();
  413.       }
  414.  
  415.       break;
  416.     }
  417.   }
  418.   return TRUE;
  419. }
  420.  
  421. // Remove each individual line connected to a shape by sending a command.
  422. void DiagramCommand::RemoveLines(wxShape *shape)
  423. {
  424.   wxNode *node = shape->GetLines().First();
  425.   while (node)
  426.   {
  427.     wxLineShape *line = (wxLineShape *)node->Data();
  428.     doc->GetCommandProcessor()->Submit(new DiagramCommand("Cut", OGLEDIT_CUT, doc, NULL, 0.0, 0.0, line->Selected(), line));
  429.     
  430.     node = shape->GetLines().First();
  431.   }
  432. }
  433.  
  434. /*
  435.  * MyEvtHandler: an event handler class for all shapes
  436.  */
  437.  
  438. void MyEvtHandler::OnLeftClick(double x, double y, int keys, int attachment)
  439. {
  440.   wxClientDC dc(GetShape()->GetCanvas());
  441.   GetShape()->GetCanvas()->PrepareDC(dc);
  442.  
  443.   if (keys == 0)
  444.   {
  445.     // Selection is a concept the library knows about
  446.     if (GetShape()->Selected())
  447.     {
  448.       GetShape()->Select(FALSE, &dc);
  449.       GetShape()->GetCanvas()->Redraw(dc); // Redraw because bits of objects will be are missing
  450.     }
  451.     else
  452.     {
  453.       // Ensure no other shape is selected, to simplify Undo/Redo code
  454.       bool redraw = FALSE;
  455.       wxNode *node = GetShape()->GetCanvas()->GetDiagram()->GetShapeList()->First();
  456.       while (node)
  457.       {
  458.         wxShape *eachShape = (wxShape *)node->Data();
  459.         if (eachShape->GetParent() == NULL)
  460.         {
  461.           if (eachShape->Selected())
  462.           {
  463.             eachShape->Select(FALSE, &dc);
  464.             redraw = TRUE;
  465.           }
  466.         }
  467.         node = node->Next();
  468.       }
  469.       GetShape()->Select(TRUE, &dc);
  470.       if (redraw)
  471.         GetShape()->GetCanvas()->Redraw(dc);
  472.     }
  473.   }
  474.   else if (keys & KEY_CTRL)
  475.   {
  476.     // Do something for CONTROL
  477.   }
  478.   else
  479.   {
  480.     wxGetApp().frame->SetStatusText(label);
  481.   }
  482. }
  483.  
  484. /*
  485.  * Implement connection of two shapes by right-dragging between them.
  486.  */
  487.  
  488. void MyEvtHandler::OnBeginDragRight(double x, double y, int keys, int attachment)
  489. {
  490.   // Force attachment to be zero for now. Eventually we can deal with
  491.   // the actual attachment point, e.g. a rectangle side if attachment mode is on.
  492.   attachment = 0;
  493.   
  494.   wxClientDC dc(GetShape()->GetCanvas());
  495.   GetShape()->GetCanvas()->PrepareDC(dc);
  496.  
  497.   wxPen dottedPen(wxColour(0, 0, 0), 1, wxDOT);
  498.   dc.SetLogicalFunction(OGLRBLF);
  499.   dc.SetPen(dottedPen);
  500.   double xp, yp;
  501.   GetShape()->GetAttachmentPosition(attachment, &xp, &yp);
  502.   dc.DrawLine((long) xp, (long) yp, (long) x, (long) y);
  503.   GetShape()->GetCanvas()->CaptureMouse();
  504. }
  505.  
  506. void MyEvtHandler::OnDragRight(bool draw, double x, double y, int keys, int attachment)
  507. {
  508.   // Force attachment to be zero for now
  509.   attachment = 0;
  510.  
  511.   wxClientDC dc(GetShape()->GetCanvas());
  512.   GetShape()->GetCanvas()->PrepareDC(dc);
  513.  
  514.   wxPen dottedPen(wxColour(0, 0, 0), 1, wxDOT);
  515.   dc.SetLogicalFunction(OGLRBLF);
  516.   dc.SetPen(dottedPen);
  517.   double xp, yp;
  518.   GetShape()->GetAttachmentPosition(attachment, &xp, &yp);
  519.   dc.DrawLine((long) xp, (long) yp, (long) x, (long) y);
  520. }
  521.  
  522. void MyEvtHandler::OnEndDragRight(double x, double y, int keys, int attachment)
  523. {
  524.   GetShape()->GetCanvas()->ReleaseMouse();
  525.   MyCanvas *canvas = (MyCanvas *)GetShape()->GetCanvas();
  526.  
  527.   // Check if we're on an object
  528.   int new_attachment;
  529.   wxShape *otherShape = canvas->FindFirstSensitiveShape(x, y, &new_attachment, OP_DRAG_RIGHT);
  530.   
  531.   if (otherShape && !otherShape->IsKindOf(CLASSINFO(wxLineShape)))
  532.   {
  533.     canvas->view->GetDocument()->GetCommandProcessor()->Submit(
  534.       new DiagramCommand("wxLineShape", OGLEDIT_ADD_LINE, (DiagramDocument *)canvas->view->GetDocument(), CLASSINFO(wxLineShape),
  535.       0.0, 0.0, FALSE, NULL, GetShape(), otherShape));
  536.   }
  537. }
  538.  
  539. void MyEvtHandler::OnEndSize(double x, double y)
  540. {
  541.   wxClientDC dc(GetShape()->GetCanvas());
  542.   GetShape()->GetCanvas()->PrepareDC(dc);
  543.  
  544.   GetShape()->FormatText(dc, (char*) (const char*) label);
  545. }
  546.  
  547. /*
  548.  * Diagram
  549.  */
  550.  
  551. bool MyDiagram::OnShapeSave(wxExprDatabase& db, wxShape& shape, wxExpr& expr)
  552. {
  553.   wxDiagram::OnShapeSave(db, shape, expr);
  554.   MyEvtHandler *handler = (MyEvtHandler *)shape.GetEventHandler();
  555.   expr.AddAttributeValueString("label", handler->label);
  556.   return TRUE;
  557. }
  558.  
  559. bool MyDiagram::OnShapeLoad(wxExprDatabase& db, wxShape& shape, wxExpr& expr)
  560. {
  561.   wxDiagram::OnShapeLoad(db, shape, expr);
  562.   char *label = NULL;
  563.   expr.AssignAttributeValue("label", &label);
  564.   MyEvtHandler *handler = new MyEvtHandler(&shape, &shape, wxString(label));
  565.   shape.SetEventHandler(handler);
  566.   
  567.   if (label)
  568.     delete[] label;
  569.   return TRUE;
  570. }
  571.  
  572. /*
  573.  * New shapes
  574.  */
  575.  
  576. IMPLEMENT_DYNAMIC_CLASS(wxRoundedRectangleShape, wxRectangleShape)
  577.  
  578. wxRoundedRectangleShape::wxRoundedRectangleShape(double w, double h):
  579.  wxRectangleShape(w, h)
  580. {
  581.   // 0.3 of the smaller rectangle dimension
  582.   SetCornerRadius((double) -0.3);
  583. }
  584.  
  585. IMPLEMENT_DYNAMIC_CLASS(wxDiamondShape, wxPolygonShape)
  586.  
  587. wxDiamondShape::wxDiamondShape(double w, double h):
  588.   wxPolygonShape()
  589. {
  590.   // wxPolygonShape::SetSize relies on the shape having non-zero
  591.   // size initially.
  592.   if (w == 0.0)
  593.     w = 60.0;
  594.   if (h == 0.0)
  595.     h = 60.0;
  596.     
  597.   wxList *thePoints = new wxList;
  598.   wxRealPoint *point = new wxRealPoint(0.0, (-h/2.0));
  599.   thePoints->Append((wxObject*) point);
  600.  
  601.   point = new wxRealPoint((w/2.0), 0.0);
  602.   thePoints->Append((wxObject*) point);
  603.  
  604.   point = new wxRealPoint(0.0, (h/2.0));
  605.   thePoints->Append((wxObject*) point);
  606.  
  607.   point = new wxRealPoint((-w/2.0), 0.0);
  608.   thePoints->Append((wxObject*) point);
  609.  
  610.   Create(thePoints);
  611. }
  612.