1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: Implements view functionality
4 // Author: Julian Smart
8 // Copyright: (c) Julian Smart
10 /////////////////////////////////////////////////////////////////////////////
13 // #pragma implementation
16 // For compilers that support precompilation, includes "wx.h".
17 #include "wx/wxprec.h"
27 #include <wx/colordlg.h>
29 #if !wxUSE_DOC_VIEW_ARCHITECTURE
30 #error You must set wxUSE_DOC_VIEW_ARCHITECTURE to 1 in wx_setup.h!
36 #include "cspalette.h"
39 #include <wx/ogl/basicp.h>
40 #include <wx/ogl/linesp.h>
42 IMPLEMENT_DYNAMIC_CLASS(csDiagramView
, wxView
)
44 BEGIN_EVENT_TABLE(csDiagramView
, wxView
)
45 EVT_MENU(wxID_CUT
, csDiagramView::OnCut
)
46 EVT_MENU(wxID_COPY
, csDiagramView::OnCopy
)
47 EVT_MENU(wxID_CLEAR
, csDiagramView::OnClear
)
48 EVT_MENU(wxID_PASTE
, csDiagramView::OnPaste
)
49 EVT_MENU(wxID_DUPLICATE
, csDiagramView::OnDuplicate
)
50 EVT_MENU(ID_CS_CHANGE_BACKGROUND_COLOUR
, csDiagramView::OnChangeBackgroundColour
)
51 EVT_MENU(ID_CS_EDIT_PROPERTIES
, csDiagramView::OnEditProperties
)
52 EVT_MENU(ID_CS_SELECT_ALL
, csDiagramView::OnSelectAll
)
53 EVT_TOOL(DIAGRAM_TOOLBAR_LINE_ARROW
, csDiagramView::OnToggleArrowTool
)
54 EVT_COMBOBOX(ID_WINDOW_POINT_SIZE_COMBOBOX
, csDiagramView::OnPointSizeComboSel
)
55 EVT_COMBOBOX(ID_WINDOW_ZOOM_COMBOBOX
, csDiagramView::OnZoomSel
)
56 EVT_TEXT(ID_WINDOW_POINT_SIZE_COMBOBOX
, csDiagramView::OnPointSizeComboText
)
57 EVT_TOOL(DIAGRAM_TOOLBAR_ALIGNL
, csDiagramView::OnAlign
)
58 EVT_TOOL(DIAGRAM_TOOLBAR_ALIGNR
, csDiagramView::OnAlign
)
59 EVT_TOOL(DIAGRAM_TOOLBAR_ALIGNB
, csDiagramView::OnAlign
)
60 EVT_TOOL(DIAGRAM_TOOLBAR_ALIGNT
, csDiagramView::OnAlign
)
61 EVT_TOOL(DIAGRAM_TOOLBAR_ALIGN_HORIZ
, csDiagramView::OnAlign
)
62 EVT_TOOL(DIAGRAM_TOOLBAR_ALIGN_VERT
, csDiagramView::OnAlign
)
63 EVT_TOOL(DIAGRAM_TOOLBAR_COPY_SIZE
, csDiagramView::OnAlign
)
64 EVT_TOOL(DIAGRAM_TOOLBAR_NEW_POINT
, csDiagramView::OnNewLinePoint
)
65 EVT_TOOL(DIAGRAM_TOOLBAR_CUT_POINT
, csDiagramView::OnCutLinePoint
)
66 EVT_TOOL(DIAGRAM_TOOLBAR_STRAIGHTEN
, csDiagramView::OnStraightenLines
)
67 EVT_UPDATE_UI(DIAGRAM_TOOLBAR_ALIGNL
, csDiagramView::OnAlignUpdate
)
68 EVT_UPDATE_UI(DIAGRAM_TOOLBAR_ALIGNR
, csDiagramView::OnAlignUpdate
)
69 EVT_UPDATE_UI(DIAGRAM_TOOLBAR_ALIGNB
, csDiagramView::OnAlignUpdate
)
70 EVT_UPDATE_UI(DIAGRAM_TOOLBAR_ALIGNT
, csDiagramView::OnAlignUpdate
)
71 EVT_UPDATE_UI(DIAGRAM_TOOLBAR_ALIGN_HORIZ
, csDiagramView::OnAlignUpdate
)
72 EVT_UPDATE_UI(DIAGRAM_TOOLBAR_ALIGN_VERT
, csDiagramView::OnAlignUpdate
)
73 EVT_UPDATE_UI(DIAGRAM_TOOLBAR_COPY_SIZE
, csDiagramView::OnAlignUpdate
)
74 EVT_UPDATE_UI(DIAGRAM_TOOLBAR_NEW_POINT
, csDiagramView::OnNewLinePointUpdate
)
75 EVT_UPDATE_UI(DIAGRAM_TOOLBAR_CUT_POINT
, csDiagramView::OnCutLinePointUpdate
)
76 EVT_UPDATE_UI(DIAGRAM_TOOLBAR_STRAIGHTEN
, csDiagramView::OnStraightenLinesUpdate
)
77 EVT_UPDATE_UI(DIAGRAM_TOOLBAR_LINE_ARROW
, csDiagramView::OnToggleArrowToolUpdate
)
78 EVT_UPDATE_UI(wxID_CUT
, csDiagramView::OnCutUpdate
)
79 EVT_UPDATE_UI(wxID_COPY
, csDiagramView::OnCopyUpdate
)
80 EVT_UPDATE_UI(wxID_CLEAR
, csDiagramView::OnClearUpdate
)
81 EVT_UPDATE_UI(wxID_PASTE
, csDiagramView::OnPasteUpdate
)
82 EVT_UPDATE_UI(wxID_DUPLICATE
, csDiagramView::OnDuplicateUpdate
)
83 EVT_UPDATE_UI(ID_CS_EDIT_PROPERTIES
, csDiagramView::OnEditPropertiesUpdate
)
84 EVT_UPDATE_UI(wxID_UNDO
, csDiagramView::OnUndoUpdate
)
85 EVT_UPDATE_UI(wxID_REDO
, csDiagramView::OnRedoUpdate
)
88 // What to do when a view is created. Creates actual
89 // windows for displaying the view.
90 bool csDiagramView::OnCreate(wxDocument
*doc
, long flags
)
93 frame
= wxGetApp().CreateChildFrame(doc
, this, &editMenu
);
94 canvas
= wxGetApp().CreateCanvas(this, frame
);
95 canvas
->SetView(this);
100 // Initialize the edit menu Undo and Redo items
101 doc
->GetCommandProcessor()->SetEditMenu(editMenu
);
102 doc
->GetCommandProcessor()->Initialize();
104 wxShapeCanvas
*shapeCanvas
= (wxShapeCanvas
*)canvas
;
105 csDiagramDocument
*diagramDoc
= (csDiagramDocument
*)doc
;
106 shapeCanvas
->SetDiagram(diagramDoc
->GetDiagram());
107 diagramDoc
->GetDiagram()->SetCanvas(shapeCanvas
);
109 diagramDoc
->GetDiagram()->SetGridSpacing((double) wxGetApp().GetGridSpacing());
111 switch (wxGetApp().GetGridStyle())
113 case csGRID_STYLE_NONE
:
115 diagramDoc
->GetDiagram()->SetSnapToGrid(FALSE
);
118 case csGRID_STYLE_INVISIBLE
:
120 diagramDoc
->GetDiagram()->SetSnapToGrid(TRUE
);
123 case csGRID_STYLE_DOTTED
:
125 // TODO (not implemented in OGL)
134 csDiagramView::~csDiagramView(void)
138 ((wxDocMDIChildFrame
*)frame
)->SetView(NULL
);
142 // Sneakily gets used for default print/preview
143 // as well as drawing on the screen.
144 void csDiagramView::OnDraw(wxDC
*dc
)
148 void csDiagramView::OnUpdate(wxView
*sender
, wxObject
*hint
)
154 // Clean up windows used for displaying the view.
155 bool csDiagramView::OnClose(bool deleteWindow
)
157 if (!GetDocument()->Close())
160 csDiagramDocument
*diagramDoc
= (csDiagramDocument
*)GetDocument();
161 diagramDoc
->GetDiagram()->SetCanvas(NULL
);
163 canvas
->ClearBackground();
164 canvas
->SetDiagram(NULL
);
165 canvas
->SetView(NULL
);
168 wxMenu
* fileMenu
= frame
->GetMenuBar()->GetMenu(0);
170 // Remove file menu from those managed by the command history
171 wxGetApp().GetDocManager()->FileHistoryRemoveMenu(fileMenu
);
184 // Adds or removes shape from m_selections
185 void csDiagramView::SelectShape(wxShape
* shape
, bool select
)
187 if (select
&& !m_selections
.Member(shape
))
188 m_selections
.Append(shape
);
190 m_selections
.DeleteObject(shape
);
193 void csDiagramView::OnSelectAll(wxCommandEvent
& event
)
198 wxShape
*csDiagramView::FindFirstSelectedShape(void)
200 csDiagramDocument
*doc
= (csDiagramDocument
*)GetDocument();
201 wxShape
*theShape
= NULL
;
202 wxNode
*node
= doc
->GetDiagram()->GetShapeList()->First();
205 wxShape
*eachShape
= (wxShape
*)node
->Data();
206 if ((eachShape
->GetParent() == NULL
) && !eachShape
->IsKindOf(CLASSINFO(wxLabelShape
)) && eachShape
->Selected())
208 theShape
= eachShape
;
211 else node
= node
->Next();
216 void csDiagramView::FindSelectedShapes(wxList
& selections
, wxClassInfo
* toFind
)
218 csDiagramDocument
*doc
= (csDiagramDocument
*)GetDocument();
219 wxNode
*node
= doc
->GetDiagram()->GetShapeList()->First();
222 wxShape
*eachShape
= (wxShape
*)node
->Data();
223 if ((eachShape
->GetParent() == NULL
) && !eachShape
->IsKindOf(CLASSINFO(wxLabelShape
)) && eachShape
->Selected() && ((toFind
== NULL
) || (eachShape
->IsKindOf(toFind
))))
225 selections
.Append(eachShape
);
231 void csDiagramView::OnUndoUpdate(wxUpdateUIEvent
& event
)
233 csDiagramDocument
*doc
= (csDiagramDocument
*)GetDocument();
234 event
.Enable(doc
->GetCommandProcessor()->CanUndo());
237 void csDiagramView::OnRedoUpdate(wxUpdateUIEvent
& event
)
239 csDiagramDocument
*doc
= (csDiagramDocument
*)GetDocument();
240 event
.Enable(doc
->GetCommandProcessor()->CanRedo());
243 void csDiagramView::OnCut(wxCommandEvent
& event
)
245 csDiagramDocument
*doc
= (csDiagramDocument
*)GetDocument();
247 // Copy the shapes to the clipboard
248 wxGetApp().GetDiagramClipboard().Copy(doc
->GetDiagram());
251 FindSelectedShapes(selections
);
256 void csDiagramView::OnClear(wxCommandEvent
& event
)
259 FindSelectedShapes(selections
);
264 void csDiagramView::OnCopy(wxCommandEvent
& event
)
266 csDiagramDocument
*doc
= (csDiagramDocument
*)GetDocument();
268 // Copy the shapes to the clipboard
269 if (wxGetApp().GetDiagramClipboard().Copy(doc
->GetDiagram()))
272 // Copy to the Windows clipboard
273 wxGetApp().GetDiagramClipboard().CopyToClipboard(1.0);
278 void csDiagramView::OnPaste(wxCommandEvent
& event
)
280 csDiagramDocument
*doc
= (csDiagramDocument
*)GetDocument();
282 wxGetApp().GetDiagramClipboard().Paste(doc
->GetDiagram());
285 void csDiagramView::OnDuplicate(wxCommandEvent
& event
)
287 csDiagramDocument
*doc
= (csDiagramDocument
*)GetDocument();
289 // Do a copy, then a paste
290 wxGetApp().GetDiagramClipboard().Copy(doc
->GetDiagram());
292 // Apply an offset. Really, this offset should keep being incremented,
293 // but where do we reset it again?
294 wxGetApp().GetDiagramClipboard().Paste(doc
->GetDiagram(), NULL
, 20, 20);
297 void csDiagramView::OnCutUpdate(wxUpdateUIEvent
& event
)
299 event
.Enable( (m_selections
.Number() > 0) );
302 void csDiagramView::OnClearUpdate(wxUpdateUIEvent
& event
)
304 event
.Enable( (m_selections
.Number() > 0) );
307 void csDiagramView::OnCopyUpdate(wxUpdateUIEvent
& event
)
309 event
.Enable( (m_selections
.Number() > 0) );
312 void csDiagramView::OnPasteUpdate(wxUpdateUIEvent
& event
)
314 csDiagramDocument
*doc
= (csDiagramDocument
*)GetDocument();
316 int n
= wxGetApp().GetDiagramClipboard().GetCount();
318 event
.Enable( (n
> 0) );
321 void csDiagramView::OnDuplicateUpdate(wxUpdateUIEvent
& event
)
323 event
.Enable( (m_selections
.Number() > 0) );
326 void csDiagramView::DoCut(wxList
& shapes
)
328 csDiagramDocument
*doc
= (csDiagramDocument
*)GetDocument();
330 if (shapes
.Number() > 0)
332 csDiagramCommand
* cmd
= new csDiagramCommand("Cut", doc
);
334 wxNode
* node
= shapes
.First();
337 wxShape
*theShape
= (wxShape
*) node
->Data();
338 csCommandState
* state
= new csCommandState(ID_CS_CUT
, NULL
, theShape
);
340 // Insert lines at the front, so they are cut first.
341 // Otherwise we may try to remove a shape with a line still
343 if (theShape
->IsKindOf(CLASSINFO(wxLineShape
)))
344 cmd
->InsertState(state
);
346 cmd
->AddState(state
);
350 cmd
->RemoveLines(); // Schedule any connected lines, not already mentioned,
351 // to be removed first
353 doc
->GetCommandProcessor()->Submit(cmd
);
357 // Generalised command
358 void csDiagramView::DoCmd(wxList
& shapes
, wxList
& oldShapes
, int cmd
, const wxString
& op
)
360 csDiagramDocument
*doc
= (csDiagramDocument
*)GetDocument();
362 if (shapes
.Number() > 0)
364 csDiagramCommand
* command
= new csDiagramCommand(op
, doc
);
366 wxNode
* node
= shapes
.First();
367 wxNode
* node1
= oldShapes
.First();
368 while (node
&& node1
)
370 wxShape
*theShape
= (wxShape
*) node
->Data();
371 wxShape
*oldShape
= (wxShape
*) node1
->Data();
372 csCommandState
* state
= new csCommandState(cmd
, theShape
, oldShape
);
373 command
->AddState(state
);
376 node1
= node1
->Next();
378 doc
->GetCommandProcessor()->Submit(command
);
382 void csDiagramView::OnChangeBackgroundColour(wxCommandEvent
& event
)
384 csDiagramDocument
*doc
= (csDiagramDocument
*)GetDocument();
387 FindSelectedShapes(selections
);
389 if (selections
.Number() > 0)
392 data
.SetChooseFull(TRUE
);
393 if (selections
.Number() == 1)
395 wxShape
* firstShape
= (wxShape
*) selections
.First()->Data();
396 data
.SetColour(firstShape
->GetBrush()->GetColour());
399 wxColourDialog
*dialog
= new wxColourDialog(frame
, &data
);
400 wxBrush
*theBrush
= NULL
;
401 if (dialog
->ShowModal() == wxID_OK
)
403 wxColourData retData
= dialog
->GetColourData();
404 wxColour col
= retData
.GetColour();
405 theBrush
= wxTheBrushList
->FindOrCreateBrush(col
, wxSOLID
);
411 csDiagramCommand
* cmd
= new csDiagramCommand("Change colour", doc
);
413 wxNode
* node
= selections
.First();
416 wxShape
*theShape
= (wxShape
*) node
->Data();
417 wxShape
* newShape
= theShape
->CreateNewCopy();
418 newShape
->SetBrush(theBrush
);
420 csCommandState
* state
= new csCommandState(ID_CS_CHANGE_BACKGROUND_COLOUR
, newShape
, theShape
);
421 cmd
->AddState(state
);
425 doc
->GetCommandProcessor()->Submit(cmd
);
429 void csDiagramView::OnEditProperties(wxCommandEvent
& event
)
431 wxShape
*theShape
= FindFirstSelectedShape();
433 ((csEvtHandler
*)theShape
->GetEventHandler())->EditProperties();
436 void csDiagramView::OnEditPropertiesUpdate(wxUpdateUIEvent
& event
)
439 FindSelectedShapes(selections
);
440 event
.Enable( (selections
.Number() > 0) );
443 void csDiagramView::OnPointSizeComboSel(wxCommandEvent
& event
)
445 wxComboBox
* combo
= (wxComboBox
*) event
.GetEventObject();
446 wxASSERT( combo
!= NULL
);
448 int newPointSize
= (combo
->GetSelection() + 1);
450 ApplyPointSize(newPointSize
);
454 // TODO: must find out how to intercept the Return key, rather than
455 // every key stroke. But for now, do every key stroke.
456 void csDiagramView::OnPointSizeComboText(wxCommandEvent
& event
)
458 wxComboBox
* combo
= (wxComboBox
*) event
.GetEventObject();
459 wxASSERT( combo
!= NULL
);
461 wxString
str(combo
->GetValue());
462 int newPointSize
= atoi((const char*) str
);
464 if (newPointSize
< 2)
467 ApplyPointSize(newPointSize
);
470 void csDiagramView::ApplyPointSize(int pointSize
)
472 csDiagramDocument
*doc
= (csDiagramDocument
*)GetDocument();
475 FindSelectedShapes(selections
);
477 if (selections
.Number() > 0)
479 csDiagramCommand
* cmd
= new csDiagramCommand("Point size", doc
);
481 wxNode
* node
= selections
.First();
484 wxShape
*theShape
= (wxShape
*) node
->Data();
485 wxShape
*newShape
= theShape
->CreateNewCopy();
487 wxFont
* newFont
= wxTheFontList
->FindOrCreateFont(pointSize
,
488 theShape
->GetFont()->GetFamily(),
489 theShape
->GetFont()->GetStyle(),
490 theShape
->GetFont()->GetWeight(),
491 theShape
->GetFont()->GetUnderlined(),
492 theShape
->GetFont()->GetFaceName());
494 newShape
->SetFont(newFont
);
496 csCommandState
* state
= new csCommandState(ID_CS_FONT_CHANGE
, newShape
, theShape
);
498 cmd
->AddState(state
);
502 doc
->GetCommandProcessor()->Submit(cmd
);
506 void csDiagramView::OnZoomSel(wxCommandEvent
& event
)
511 int noStrings
= (maxZoom
- minZoom
)/inc
;
513 wxComboBox
* combo
= (wxComboBox
*) event
.GetEventObject();
514 wxASSERT( combo
!= NULL
);
516 int scale
= (int) ((noStrings
- combo
->GetSelection() - 1)*inc
+ minZoom
);
518 canvas
->SetScale((double) (scale
/100.0), (double) (scale
/100.0));
522 // Select or deselect all
523 void csDiagramView::SelectAll(bool select
)
525 wxClientDC
dc(canvas
);
526 canvas
->PrepareDC(dc
);
531 FindSelectedShapes(selections
);
533 wxNode
* node
= selections
.First();
536 wxShape
*theShape
= (wxShape
*) node
->Data();
537 theShape
->Select(FALSE
, &dc
);
538 SelectShape(theShape
, FALSE
);
545 csDiagramDocument
*doc
= (csDiagramDocument
*)GetDocument();
546 wxNode
*node
= doc
->GetDiagram()->GetShapeList()->First();
549 wxShape
*eachShape
= (wxShape
*)node
->Data();
550 if (eachShape
->GetParent() == NULL
&&
551 !eachShape
->IsKindOf(CLASSINFO(wxControlPoint
)) &&
552 !eachShape
->IsKindOf(CLASSINFO(wxLabelShape
)))
554 eachShape
->Select(TRUE
, &dc
);
555 SelectShape(eachShape
, TRUE
);
563 void csDiagramView::OnToggleArrowTool(wxCommandEvent
& event
)
565 csDiagramDocument
*doc
= (csDiagramDocument
*)GetDocument();
567 bool state
= wxGetApp().GetDiagramToolBar()->GetToolState(DIAGRAM_TOOLBAR_LINE_ARROW
);
570 stateName
= "Arrow on";
572 stateName
= "Arrow off";
575 FindSelectedShapes(selections
, CLASSINFO(wxLineShape
));
577 if (selections
.Number() > 0)
579 csDiagramCommand
* cmd
= new csDiagramCommand(stateName
, doc
);
581 wxNode
* node
= selections
.First();
584 wxLineShape
*theShape
= (wxLineShape
*) node
->Data();
585 wxLineShape
*newShape
= NULL
;
590 if (theShape
->GetArrows().Number() == 0)
592 newShape
= (wxLineShape
*) theShape
->CreateNewCopy();
593 newShape
->AddArrow(ARROW_ARROW
, ARROW_POSITION_MIDDLE
, 10.0, 0.0, "Normal arrowhead");
598 if (theShape
->GetArrows().Number() > 0)
600 newShape
= (wxLineShape
*) theShape
->CreateNewCopy();
601 newShape
->ClearArrowsAtPosition();
605 // If the new state is the same as the old, don't bother adding it to the command state.
608 csCommandState
* state
= new csCommandState(ID_CS_ARROW_CHANGE
, newShape
, theShape
);
609 cmd
->AddState(state
);
614 doc
->GetCommandProcessor()->Submit(cmd
);
618 void csDiagramView::OnToggleArrowToolUpdate(wxUpdateUIEvent
& event
)
621 FindSelectedShapes(selections
, CLASSINFO(wxLineShape
));
622 event
.Enable( (selections
.Number() > 0) );
625 // Make the point size combobox reflect this
626 void csDiagramView::ReflectPointSize(int pointSize
)
628 wxComboBox
* comboBox
= wxGetApp().GetPointSizeComboBox();
629 comboBox
->SetSelection(pointSize
-1);
632 // Make the arrow toggle button reflect the state of the line
633 void csDiagramView::ReflectArrowState(wxLineShape
* lineShape
)
635 bool haveArrow
= FALSE
;
636 wxNode
*node
= lineShape
->GetArrows().First();
639 wxArrowHead
*arrow
= (wxArrowHead
*)node
->Data();
640 if (ARROW_POSITION_MIDDLE
== arrow
->GetArrowEnd())
645 wxGetApp().GetDiagramToolBar()->ToggleTool(DIAGRAM_TOOLBAR_LINE_ARROW
, haveArrow
);
648 void csDiagramView::OnAlign(wxCommandEvent
& event
)
650 // Make a copy of the selections, keeping only those shapes
651 // that are top-level non-line shapes.
653 wxNode
* node
= GetSelectionList().First();
656 wxShape
* shape
= (wxShape
*) node
->Data();
657 if ((shape
->GetParent() == NULL
) && (!shape
->IsKindOf(CLASSINFO(wxLineShape
))))
659 selections
.Append(shape
);
664 if (selections
.Number() == 0)
667 csDiagramDocument
*doc
= (csDiagramDocument
*)GetDocument();
668 csDiagramCommand
* cmd
= new csDiagramCommand("Align", doc
);
670 node
= selections
.First();
671 wxShape
* firstShape
= (wxShape
*) node
->Data();
673 double x
= firstShape
->GetX();
674 double y
= firstShape
->GetY();
675 double width
, height
;
676 firstShape
->GetBoundingBoxMax(&width
, &height
);
678 node
= selections
.First();
681 wxShape
* shape
= (wxShape
*) node
->Data();
682 if (shape
!= firstShape
)
684 double x1
= shape
->GetX();
685 double y1
= shape
->GetY();
686 double width1
, height1
;
687 shape
->GetBoundingBoxMax(& width1
, & height1
);
689 wxShape
* newShape
= shape
->CreateNewCopy();
691 switch (event
.GetId())
693 case DIAGRAM_TOOLBAR_ALIGNL
:
695 double x2
= (double)(x
- (width
/2.0) + (width1
/2.0));
699 case DIAGRAM_TOOLBAR_ALIGNR
:
701 double x2
= (double)(x
+ (width
/2.0) - (width1
/2.0));
705 case DIAGRAM_TOOLBAR_ALIGNB
:
707 double y2
= (double)(y
+ (height
/2.0) - (height1
/2.0));
711 case DIAGRAM_TOOLBAR_ALIGNT
:
713 double y2
= (double)(y
- (height
/2.0) + (height1
/2.0));
717 case DIAGRAM_TOOLBAR_ALIGN_HORIZ
:
722 case DIAGRAM_TOOLBAR_ALIGN_VERT
:
727 case DIAGRAM_TOOLBAR_COPY_SIZE
:
729 newShape
->SetSize(width
, height
);
733 csCommandState
* state
= new csCommandState(ID_CS_ALIGN
, newShape
, shape
);
734 cmd
->AddState(state
);
738 doc
->GetCommandProcessor()->Submit(cmd
);
741 void csDiagramView::OnAlignUpdate(wxUpdateUIEvent
& event
)
743 // This is an approximation, since there may be lines
744 // amongst the selections.
745 event
.Enable( (m_selections
.Number() > 1) ) ;
748 void csDiagramView::OnNewLinePoint(wxCommandEvent
& event
)
750 csDiagramDocument
*doc
= (csDiagramDocument
*)GetDocument();
751 csDiagramCommand
* cmd
= new csDiagramCommand("New line point", doc
);
753 wxNode
* node
= m_selections
.First();
756 wxShape
* shape
= (wxShape
*) node
->Data();
757 if (shape
->IsKindOf(CLASSINFO(wxLineShape
)))
759 wxShape
* newShape
= shape
->CreateNewCopy();
760 ((wxLineShape
*)newShape
)->InsertLineControlPoint(NULL
);
761 csCommandState
* state
= new csCommandState(ID_CS_NEW_POINT
, newShape
, shape
);
762 cmd
->AddState(state
);
766 doc
->GetCommandProcessor()->Submit(cmd
);
769 void csDiagramView::OnCutLinePoint(wxCommandEvent
& event
)
771 csDiagramDocument
*doc
= (csDiagramDocument
*)GetDocument();
772 csDiagramCommand
* cmd
= new csDiagramCommand("Cut line point", doc
);
774 wxNode
* node
= m_selections
.First();
777 wxShape
* shape
= (wxShape
*) node
->Data();
778 if (shape
->IsKindOf(CLASSINFO(wxLineShape
)))
780 wxShape
* newShape
= shape
->CreateNewCopy();
781 ((wxLineShape
*)newShape
)->DeleteLineControlPoint();
782 csCommandState
* state
= new csCommandState(ID_CS_CUT_POINT
, newShape
, shape
);
783 cmd
->AddState(state
);
787 doc
->GetCommandProcessor()->Submit(cmd
);
790 void csDiagramView::OnStraightenLines(wxCommandEvent
& event
)
792 csDiagramDocument
*doc
= (csDiagramDocument
*)GetDocument();
793 csDiagramCommand
* cmd
= new csDiagramCommand("Straighten lines", doc
);
795 wxNode
* node
= m_selections
.First();
798 wxShape
* shape
= (wxShape
*) node
->Data();
799 if (shape
->IsKindOf(CLASSINFO(wxLineShape
)))
801 wxShape
* newShape
= shape
->CreateNewCopy();
802 ((wxLineShape
*)newShape
)->Straighten();
803 csCommandState
* state
= new csCommandState(ID_CS_STRAIGHTEN
, newShape
, shape
);
804 cmd
->AddState(state
);
808 doc
->GetCommandProcessor()->Submit(cmd
);
811 void csDiagramView::OnNewLinePointUpdate(wxUpdateUIEvent
& event
)
814 FindSelectedShapes(selections
, CLASSINFO(wxLineShape
));
815 event
.Enable( (selections
.Number() > 0) );
818 void csDiagramView::OnCutLinePointUpdate(wxUpdateUIEvent
& event
)
821 FindSelectedShapes(selections
, CLASSINFO(wxLineShape
));
822 event
.Enable( (selections
.Number() > 0) );
825 void csDiagramView::OnStraightenLinesUpdate(wxUpdateUIEvent
& event
)
828 FindSelectedShapes(selections
, CLASSINFO(wxLineShape
));
829 event
.Enable( (selections
.Number() > 0) );
833 * Window implementations
836 IMPLEMENT_CLASS(csCanvas
, wxShapeCanvas
)
838 BEGIN_EVENT_TABLE(csCanvas
, wxShapeCanvas
)
839 EVT_MOUSE_EVENTS(csCanvas::OnMouseEvent
)
840 EVT_PAINT(csCanvas::OnPaint
)
843 // Define a constructor for my canvas
844 csCanvas::csCanvas(csDiagramView
*v
, wxWindow
*parent
, wxWindowID id
, const wxPoint
& pos
,
845 const wxSize
& size
, long style
):
846 wxShapeCanvas(parent
, id
, pos
, size
, style
)
851 csCanvas::~csCanvas(void)
855 void csCanvas::DrawOutline(wxDC
& dc
, double x1
, double y1
, double x2
, double y2
)
857 wxPen
dottedPen(wxColour(0, 0, 0), 1, wxDOT
);
858 dc
.SetPen(dottedPen
);
859 dc
.SetBrush(* wxTRANSPARENT_BRUSH
);
861 dc
.DrawRectangle((long) x1
, (long) y1
, (long) (x2
- x1
), (long) (y2
- y1
));
864 void csCanvas::OnLeftClick(double x
, double y
, int keys
)
866 csEditorToolPalette
*palette
= wxGetApp().GetDiagramPalette();
868 if (palette
->GetSelection() == PALETTE_ARROW
)
870 GetView()->SelectAll(FALSE
);
879 if (palette
->GetSelection() == PALETTE_TEXT_TOOL
)
881 // Ask for a label and create a new free-floating text region
882 csLabelEditingDialog
* dialog
= new csLabelEditingDialog(GetParent());
884 dialog
->SetShapeLabel("");
885 dialog
->SetTitle("New text box");
886 if (dialog
->ShowModal() == wxID_CANCEL
)
892 wxString newLabel
= dialog
->GetShapeLabel();
895 wxShape
* shape
= new csTextBoxShape
;
896 shape
->AssignNewIds();
897 shape
->SetEventHandler(new csEvtHandler(shape
, shape
, newLabel
));
899 wxComboBox
* comboBox
= wxGetApp().GetPointSizeComboBox();
900 wxString
str(comboBox
->GetValue());
901 int pointSize
= atoi((const char*) str
);
903 wxFont
* newFont
= wxTheFontList
->FindOrCreateFont(pointSize
,
904 shape
->GetFont()->GetFamily(),
905 shape
->GetFont()->GetStyle(),
906 shape
->GetFont()->GetWeight(),
907 shape
->GetFont()->GetUnderlined(),
908 shape
->GetFont()->GetFaceName());
910 shape
->SetFont(newFont
);
915 csDiagramCommand
* cmd
= new csDiagramCommand("Text box",
916 (csDiagramDocument
*)GetView()->GetDocument(),
917 new csCommandState(ID_CS_ADD_SHAPE
, shape
, NULL
));
918 GetView()->GetDocument()->GetCommandProcessor()->Submit(cmd
);
920 palette
->SetSelection(PALETTE_ARROW
);
925 csSymbol
* symbol
= wxGetApp().GetSymbolDatabase()->FindSymbol(palette
->GetSelection());
928 wxShape
* theShape
= symbol
->GetShape()->CreateNewCopy();
930 wxComboBox
* comboBox
= wxGetApp().GetPointSizeComboBox();
931 wxString
str(comboBox
->GetValue());
932 int pointSize
= atoi((const char*) str
);
934 wxFont
* newFont
= wxTheFontList
->FindOrCreateFont(pointSize
,
935 symbol
->GetShape()->GetFont()->GetFamily(),
936 symbol
->GetShape()->GetFont()->GetStyle(),
937 symbol
->GetShape()->GetFont()->GetWeight(),
938 symbol
->GetShape()->GetFont()->GetUnderlined(),
939 symbol
->GetShape()->GetFont()->GetFaceName());
941 theShape
->SetFont(newFont
);
943 theShape
->AssignNewIds();
947 csDiagramCommand
* cmd
= new csDiagramCommand(symbol
->GetName(),
948 (csDiagramDocument
*)GetView()->GetDocument(),
949 new csCommandState(ID_CS_ADD_SHAPE
, theShape
, NULL
));
950 GetView()->GetDocument()->GetCommandProcessor()->Submit(cmd
);
952 palette
->SetSelection(PALETTE_ARROW
);
956 void csCanvas::OnRightClick(double x
, double y
, int keys
)
961 static double sg_initialX
, sg_initialY
;
963 void csCanvas::OnDragLeft(bool draw
, double x
, double y
, int keys
)
968 dc
.SetLogicalFunction(OGLRBLF
);
969 DrawOutline(dc
, sg_initialX
, sg_initialY
, x
, y
);
972 void csCanvas::OnBeginDragLeft(double x
, double y
, int keys
)
980 dc
.SetLogicalFunction(OGLRBLF
);
981 DrawOutline(dc
, sg_initialX
, sg_initialY
, x
, y
);
985 void csCanvas::OnEndDragLeft(double x
, double y
, int keys
)
992 // Select all images within the rectangle
993 float min_x
, max_x
, min_y
, max_y
;
994 min_x
= wxMin(x
, sg_initialX
);
995 max_x
= wxMax(x
, sg_initialX
);
996 min_y
= wxMin(y
, sg_initialY
);
997 max_y
= wxMax(y
, sg_initialY
);
999 wxNode
*node
= GetDiagram()->GetShapeList()->First();
1002 wxShape
*shape
= (wxShape
*)node
->Data();
1003 if (shape
->GetParent() == NULL
&& !shape
->IsKindOf(CLASSINFO(wxControlPoint
)))
1005 float image_x
= shape
->GetX();
1006 float image_y
= shape
->GetY();
1007 if (image_x
>= min_x
&& image_x
<= max_x
&&
1008 image_y
>= min_y
&& image_y
<= max_y
)
1010 shape
->Select(TRUE
, &dc
);
1011 GetView()->SelectShape(shape
, TRUE
);
1014 node
= node
->Next();
1018 void csCanvas::OnDragRight(bool draw
, double x
, double y
, int keys
)
1022 void csCanvas::OnBeginDragRight(double x
, double y
, int keys
)
1026 void csCanvas::OnEndDragRight(double x
, double y
, int keys
)
1030 void csCanvas::OnMouseEvent(wxMouseEvent
& event
)
1032 wxShapeCanvas::OnMouseEvent(event
);
1035 void csCanvas::OnPaint(wxPaintEvent
& event
)
1037 // if (GetDiagram())
1038 wxShapeCanvas::OnPaint(event
);