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 WXUNUSED(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
*WXUNUSED(dc
))
148 void csDiagramView::OnUpdate(wxView
*WXUNUSED(sender
), wxObject
*WXUNUSED(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
& WXUNUSED(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
& WXUNUSED(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
& WXUNUSED(event
))
259 FindSelectedShapes(selections
);
264 void csDiagramView::OnCopy(wxCommandEvent
& WXUNUSED(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
& WXUNUSED(event
))
280 csDiagramDocument
*doc
= (csDiagramDocument
*)GetDocument();
282 wxGetApp().GetDiagramClipboard().Paste(doc
->GetDiagram());
285 void csDiagramView::OnDuplicate(wxCommandEvent
& WXUNUSED(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(_T("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
& WXUNUSED(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(_T("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
& WXUNUSED(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());
463 str
.ToLong( &newPointSize
);
465 if (newPointSize
< 2)
468 ApplyPointSize(newPointSize
);
471 void csDiagramView::ApplyPointSize(int pointSize
)
473 csDiagramDocument
*doc
= (csDiagramDocument
*)GetDocument();
476 FindSelectedShapes(selections
);
478 if (selections
.Number() > 0)
480 csDiagramCommand
* cmd
= new csDiagramCommand(_T("Point size"), doc
);
482 wxNode
* node
= selections
.First();
485 wxShape
*theShape
= (wxShape
*) node
->Data();
486 wxShape
*newShape
= theShape
->CreateNewCopy();
488 wxFont
* newFont
= wxTheFontList
->FindOrCreateFont(pointSize
,
489 theShape
->GetFont()->GetFamily(),
490 theShape
->GetFont()->GetStyle(),
491 theShape
->GetFont()->GetWeight(),
492 theShape
->GetFont()->GetUnderlined(),
493 theShape
->GetFont()->GetFaceName());
495 newShape
->SetFont(newFont
);
497 csCommandState
* state
= new csCommandState(ID_CS_FONT_CHANGE
, newShape
, theShape
);
499 cmd
->AddState(state
);
503 doc
->GetCommandProcessor()->Submit(cmd
);
507 void csDiagramView::OnZoomSel(wxCommandEvent
& event
)
512 int noStrings
= (maxZoom
- minZoom
)/inc
;
514 wxComboBox
* combo
= (wxComboBox
*) event
.GetEventObject();
515 wxASSERT( combo
!= NULL
);
517 int scale
= (int) ((noStrings
- combo
->GetSelection() - 1)*inc
+ minZoom
);
519 canvas
->SetScale((double) (scale
/100.0), (double) (scale
/100.0));
523 // Select or deselect all
524 void csDiagramView::SelectAll(bool select
)
526 wxClientDC
dc(canvas
);
527 canvas
->PrepareDC(dc
);
532 FindSelectedShapes(selections
);
534 wxNode
* node
= selections
.First();
537 wxShape
*theShape
= (wxShape
*) node
->Data();
538 theShape
->Select(FALSE
, &dc
);
539 SelectShape(theShape
, FALSE
);
546 csDiagramDocument
*doc
= (csDiagramDocument
*)GetDocument();
547 wxNode
*node
= doc
->GetDiagram()->GetShapeList()->First();
550 wxShape
*eachShape
= (wxShape
*)node
->Data();
551 if (eachShape
->GetParent() == NULL
&&
552 !eachShape
->IsKindOf(CLASSINFO(wxControlPoint
)) &&
553 !eachShape
->IsKindOf(CLASSINFO(wxLabelShape
)))
555 eachShape
->Select(TRUE
, &dc
);
556 SelectShape(eachShape
, TRUE
);
564 void csDiagramView::OnToggleArrowTool(wxCommandEvent
& WXUNUSED(event
))
566 csDiagramDocument
*doc
= (csDiagramDocument
*)GetDocument();
568 bool state
= wxGetApp().GetDiagramToolBar()->GetToolState(DIAGRAM_TOOLBAR_LINE_ARROW
);
571 stateName
= _T("Arrow on");
573 stateName
= _T("Arrow off");
576 FindSelectedShapes(selections
, CLASSINFO(wxLineShape
));
578 if (selections
.Number() > 0)
580 csDiagramCommand
* cmd
= new csDiagramCommand(stateName
, doc
);
582 wxNode
* node
= selections
.First();
585 wxLineShape
*theShape
= (wxLineShape
*) node
->Data();
586 wxLineShape
*newShape
= NULL
;
591 if (theShape
->GetArrows().Number() == 0)
593 newShape
= (wxLineShape
*) theShape
->CreateNewCopy();
594 newShape
->AddArrow(ARROW_ARROW
, ARROW_POSITION_MIDDLE
, 10.0, 0.0, _T("Normal arrowhead"));
599 if (theShape
->GetArrows().Number() > 0)
601 newShape
= (wxLineShape
*) theShape
->CreateNewCopy();
602 newShape
->ClearArrowsAtPosition();
606 // If the new state is the same as the old, don't bother adding it to the command state.
609 csCommandState
* state
= new csCommandState(ID_CS_ARROW_CHANGE
, newShape
, theShape
);
610 cmd
->AddState(state
);
615 doc
->GetCommandProcessor()->Submit(cmd
);
619 void csDiagramView::OnToggleArrowToolUpdate(wxUpdateUIEvent
& event
)
622 FindSelectedShapes(selections
, CLASSINFO(wxLineShape
));
623 event
.Enable( (selections
.Number() > 0) );
626 // Make the point size combobox reflect this
627 void csDiagramView::ReflectPointSize(int pointSize
)
629 wxComboBox
* comboBox
= wxGetApp().GetPointSizeComboBox();
630 comboBox
->SetSelection(pointSize
-1);
633 // Make the arrow toggle button reflect the state of the line
634 void csDiagramView::ReflectArrowState(wxLineShape
* lineShape
)
636 bool haveArrow
= FALSE
;
637 wxNode
*node
= lineShape
->GetArrows().First();
640 wxArrowHead
*arrow
= (wxArrowHead
*)node
->Data();
641 if (ARROW_POSITION_MIDDLE
== arrow
->GetArrowEnd())
646 wxGetApp().GetDiagramToolBar()->ToggleTool(DIAGRAM_TOOLBAR_LINE_ARROW
, haveArrow
);
649 void csDiagramView::OnAlign(wxCommandEvent
& event
)
651 // Make a copy of the selections, keeping only those shapes
652 // that are top-level non-line shapes.
654 wxNode
* node
= GetSelectionList().First();
657 wxShape
* shape
= (wxShape
*) node
->Data();
658 if ((shape
->GetParent() == NULL
) && (!shape
->IsKindOf(CLASSINFO(wxLineShape
))))
660 selections
.Append(shape
);
665 if (selections
.Number() == 0)
668 csDiagramDocument
*doc
= (csDiagramDocument
*)GetDocument();
669 csDiagramCommand
* cmd
= new csDiagramCommand(_T("Align"), doc
);
671 node
= selections
.First();
672 wxShape
* firstShape
= (wxShape
*) node
->Data();
674 double x
= firstShape
->GetX();
675 double y
= firstShape
->GetY();
676 double width
, height
;
677 firstShape
->GetBoundingBoxMax(&width
, &height
);
679 node
= selections
.First();
682 wxShape
* shape
= (wxShape
*) node
->Data();
683 if (shape
!= firstShape
)
685 /* double x1 = */ shape
->GetX();
686 /* double y1 = */ shape
->GetY();
687 double width1
, height1
;
688 shape
->GetBoundingBoxMax(& width1
, & height1
);
690 wxShape
* newShape
= shape
->CreateNewCopy();
692 switch (event
.GetId())
694 case DIAGRAM_TOOLBAR_ALIGNL
:
696 double x2
= (double)(x
- (width
/2.0) + (width1
/2.0));
700 case DIAGRAM_TOOLBAR_ALIGNR
:
702 double x2
= (double)(x
+ (width
/2.0) - (width1
/2.0));
706 case DIAGRAM_TOOLBAR_ALIGNB
:
708 double y2
= (double)(y
+ (height
/2.0) - (height1
/2.0));
712 case DIAGRAM_TOOLBAR_ALIGNT
:
714 double y2
= (double)(y
- (height
/2.0) + (height1
/2.0));
718 case DIAGRAM_TOOLBAR_ALIGN_HORIZ
:
723 case DIAGRAM_TOOLBAR_ALIGN_VERT
:
728 case DIAGRAM_TOOLBAR_COPY_SIZE
:
730 newShape
->SetSize(width
, height
);
734 csCommandState
* state
= new csCommandState(ID_CS_ALIGN
, newShape
, shape
);
735 cmd
->AddState(state
);
739 doc
->GetCommandProcessor()->Submit(cmd
);
742 void csDiagramView::OnAlignUpdate(wxUpdateUIEvent
& event
)
744 // This is an approximation, since there may be lines
745 // amongst the selections.
746 event
.Enable( (m_selections
.Number() > 1) ) ;
749 void csDiagramView::OnNewLinePoint(wxCommandEvent
& WXUNUSED(event
))
751 csDiagramDocument
*doc
= (csDiagramDocument
*)GetDocument();
752 csDiagramCommand
* cmd
= new csDiagramCommand(_T("New line point"), doc
);
754 wxNode
* node
= m_selections
.First();
757 wxShape
* shape
= (wxShape
*) node
->Data();
758 if (shape
->IsKindOf(CLASSINFO(wxLineShape
)))
760 wxShape
* newShape
= shape
->CreateNewCopy();
761 ((wxLineShape
*)newShape
)->InsertLineControlPoint(NULL
);
762 csCommandState
* state
= new csCommandState(ID_CS_NEW_POINT
, newShape
, shape
);
763 cmd
->AddState(state
);
767 doc
->GetCommandProcessor()->Submit(cmd
);
770 void csDiagramView::OnCutLinePoint(wxCommandEvent
& WXUNUSED(event
))
772 csDiagramDocument
*doc
= (csDiagramDocument
*)GetDocument();
773 csDiagramCommand
* cmd
= new csDiagramCommand(_T("Cut line point"), doc
);
775 wxNode
* node
= m_selections
.First();
778 wxShape
* shape
= (wxShape
*) node
->Data();
779 if (shape
->IsKindOf(CLASSINFO(wxLineShape
)))
781 wxShape
* newShape
= shape
->CreateNewCopy();
782 ((wxLineShape
*)newShape
)->DeleteLineControlPoint();
783 csCommandState
* state
= new csCommandState(ID_CS_CUT_POINT
, newShape
, shape
);
784 cmd
->AddState(state
);
788 doc
->GetCommandProcessor()->Submit(cmd
);
791 void csDiagramView::OnStraightenLines(wxCommandEvent
& WXUNUSED(event
))
793 csDiagramDocument
*doc
= (csDiagramDocument
*)GetDocument();
794 csDiagramCommand
* cmd
= new csDiagramCommand(_T("Straighten lines"), doc
);
796 wxNode
* node
= m_selections
.First();
799 wxShape
* shape
= (wxShape
*) node
->Data();
800 if (shape
->IsKindOf(CLASSINFO(wxLineShape
)))
802 wxShape
* newShape
= shape
->CreateNewCopy();
803 ((wxLineShape
*)newShape
)->Straighten();
804 csCommandState
* state
= new csCommandState(ID_CS_STRAIGHTEN
, newShape
, shape
);
805 cmd
->AddState(state
);
809 doc
->GetCommandProcessor()->Submit(cmd
);
812 void csDiagramView::OnNewLinePointUpdate(wxUpdateUIEvent
& event
)
815 FindSelectedShapes(selections
, CLASSINFO(wxLineShape
));
816 event
.Enable( (selections
.Number() > 0) );
819 void csDiagramView::OnCutLinePointUpdate(wxUpdateUIEvent
& event
)
822 FindSelectedShapes(selections
, CLASSINFO(wxLineShape
));
823 event
.Enable( (selections
.Number() > 0) );
826 void csDiagramView::OnStraightenLinesUpdate(wxUpdateUIEvent
& event
)
829 FindSelectedShapes(selections
, CLASSINFO(wxLineShape
));
830 event
.Enable( (selections
.Number() > 0) );
834 * Window implementations
837 IMPLEMENT_CLASS(csCanvas
, wxShapeCanvas
)
839 BEGIN_EVENT_TABLE(csCanvas
, wxShapeCanvas
)
840 EVT_MOUSE_EVENTS(csCanvas::OnMouseEvent
)
841 EVT_PAINT(csCanvas::OnPaint
)
844 // Define a constructor for my canvas
845 csCanvas::csCanvas(csDiagramView
*v
, wxWindow
*parent
, wxWindowID id
, const wxPoint
& pos
,
846 const wxSize
& size
, long style
):
847 wxShapeCanvas(parent
, id
, pos
, size
, style
)
852 csCanvas::~csCanvas(void)
856 void csCanvas::DrawOutline(wxDC
& dc
, double x1
, double y1
, double x2
, double y2
)
858 wxPen
dottedPen(wxColour(0, 0, 0), 1, wxDOT
);
859 dc
.SetPen(dottedPen
);
860 dc
.SetBrush(* wxTRANSPARENT_BRUSH
);
862 dc
.DrawRectangle((long) x1
, (long) y1
, (long) (x2
- x1
), (long) (y2
- y1
));
865 void csCanvas::OnLeftClick(double x
, double y
, int WXUNUSED(keys
))
867 csEditorToolPalette
*palette
= wxGetApp().GetDiagramPalette();
869 if (palette
->GetSelection() == PALETTE_ARROW
)
871 GetView()->SelectAll(FALSE
);
880 if (palette
->GetSelection() == PALETTE_TEXT_TOOL
)
882 // Ask for a label and create a new free-floating text region
883 csLabelEditingDialog
* dialog
= new csLabelEditingDialog(GetParent());
885 dialog
->SetShapeLabel( wxEmptyString
);
886 dialog
->SetTitle(_T("New text box"));
887 if (dialog
->ShowModal() == wxID_CANCEL
)
893 wxString newLabel
= dialog
->GetShapeLabel();
896 wxShape
* shape
= new csTextBoxShape
;
897 shape
->AssignNewIds();
898 shape
->SetEventHandler(new csEvtHandler(shape
, shape
, newLabel
));
900 wxComboBox
* comboBox
= wxGetApp().GetPointSizeComboBox();
901 wxString
str(comboBox
->GetValue());
903 str
.ToLong( &pointSize
);
905 wxFont
* newFont
= wxTheFontList
->FindOrCreateFont(pointSize
,
906 shape
->GetFont()->GetFamily(),
907 shape
->GetFont()->GetStyle(),
908 shape
->GetFont()->GetWeight(),
909 shape
->GetFont()->GetUnderlined(),
910 shape
->GetFont()->GetFaceName());
912 shape
->SetFont(newFont
);
917 csDiagramCommand
* cmd
= new csDiagramCommand(_T("Text box"),
918 (csDiagramDocument
*)GetView()->GetDocument(),
919 new csCommandState(ID_CS_ADD_SHAPE
, shape
, NULL
));
920 GetView()->GetDocument()->GetCommandProcessor()->Submit(cmd
);
922 palette
->SetSelection(PALETTE_ARROW
);
927 csSymbol
* symbol
= wxGetApp().GetSymbolDatabase()->FindSymbol(palette
->GetSelection());
930 wxShape
* theShape
= symbol
->GetShape()->CreateNewCopy();
932 wxComboBox
* comboBox
= wxGetApp().GetPointSizeComboBox();
933 wxString
str(comboBox
->GetValue());
935 str
.ToLong( &pointSize
);
937 wxFont
* newFont
= wxTheFontList
->FindOrCreateFont(pointSize
,
938 symbol
->GetShape()->GetFont()->GetFamily(),
939 symbol
->GetShape()->GetFont()->GetStyle(),
940 symbol
->GetShape()->GetFont()->GetWeight(),
941 symbol
->GetShape()->GetFont()->GetUnderlined(),
942 symbol
->GetShape()->GetFont()->GetFaceName());
944 theShape
->SetFont(newFont
);
946 theShape
->AssignNewIds();
950 csDiagramCommand
* cmd
= new csDiagramCommand(symbol
->GetName(),
951 (csDiagramDocument
*)GetView()->GetDocument(),
952 new csCommandState(ID_CS_ADD_SHAPE
, theShape
, NULL
));
953 GetView()->GetDocument()->GetCommandProcessor()->Submit(cmd
);
955 palette
->SetSelection(PALETTE_ARROW
);
959 void csCanvas::OnRightClick(double WXUNUSED(x
), double WXUNUSED(y
), int WXUNUSED(keys
))
964 static double sg_initialX
, sg_initialY
;
966 void csCanvas::OnDragLeft(bool WXUNUSED(draw
), double x
, double y
, int WXUNUSED(keys
))
971 dc
.SetLogicalFunction(OGLRBLF
);
972 DrawOutline(dc
, sg_initialX
, sg_initialY
, x
, y
);
975 void csCanvas::OnBeginDragLeft(double x
, double y
, int WXUNUSED(keys
))
983 dc
.SetLogicalFunction(OGLRBLF
);
984 DrawOutline(dc
, sg_initialX
, sg_initialY
, x
, y
);
988 void csCanvas::OnEndDragLeft(double x
, double y
, int WXUNUSED(keys
))
995 // Select all images within the rectangle
996 float min_x
, max_x
, min_y
, max_y
;
997 min_x
= wxMin(x
, sg_initialX
);
998 max_x
= wxMax(x
, sg_initialX
);
999 min_y
= wxMin(y
, sg_initialY
);
1000 max_y
= wxMax(y
, sg_initialY
);
1002 wxNode
*node
= GetDiagram()->GetShapeList()->First();
1005 wxShape
*shape
= (wxShape
*)node
->Data();
1006 if (shape
->GetParent() == NULL
&& !shape
->IsKindOf(CLASSINFO(wxControlPoint
)))
1008 float image_x
= shape
->GetX();
1009 float image_y
= shape
->GetY();
1010 if (image_x
>= min_x
&& image_x
<= max_x
&&
1011 image_y
>= min_y
&& image_y
<= max_y
)
1013 shape
->Select(TRUE
, &dc
);
1014 GetView()->SelectShape(shape
, TRUE
);
1017 node
= node
->Next();
1021 void csCanvas::OnDragRight(bool WXUNUSED(draw
), double WXUNUSED(x
), double WXUNUSED(y
), int WXUNUSED(keys
))
1025 void csCanvas::OnBeginDragRight(double WXUNUSED(x
), double WXUNUSED(y
), int WXUNUSED(keys
))
1029 void csCanvas::OnEndDragRight(double WXUNUSED(x
), double WXUNUSED(y
), int WXUNUSED(keys
))
1033 void csCanvas::OnMouseEvent(wxMouseEvent
& event
)
1035 wxShapeCanvas::OnMouseEvent(event
);
1038 void csCanvas::OnPaint(wxPaintEvent
& event
)
1040 // if (GetDiagram())
1041 wxShapeCanvas::OnPaint(event
);