]> git.saurik.com Git - wxWidgets.git/blame_incremental - contrib/samples/ogl/studio/view.cpp
Fixed stream test.
[wxWidgets.git] / contrib / samples / ogl / studio / view.cpp
... / ...
CommitLineData
1/////////////////////////////////////////////////////////////////////////////
2// Name: view.cpp
3// Purpose: Implements view functionality
4// Author: Julian Smart
5// Modified by:
6// Created: 12/07/98
7// RCS-ID: $Id$
8// Copyright: (c) Julian Smart
9// 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#include <wx/colordlg.h>
28
29#if !wxUSE_DOC_VIEW_ARCHITECTURE
30#error You must set wxUSE_DOC_VIEW_ARCHITECTURE to 1 in wx_setup.h!
31#endif
32
33#include "studio.h"
34#include "doc.h"
35#include "view.h"
36#include "cspalette.h"
37#include "symbols.h"
38#include "dialogs.h"
39#include <wx/ogl/basicp.h>
40#include <wx/ogl/linesp.h>
41
42IMPLEMENT_DYNAMIC_CLASS(csDiagramView, wxView)
43
44BEGIN_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)
86END_EVENT_TABLE()
87
88// What to do when a view is created. Creates actual
89// windows for displaying the view.
90bool csDiagramView::OnCreate(wxDocument *doc, long WXUNUSED(flags))
91{
92 wxMenu* editMenu;
93 frame = wxGetApp().CreateChildFrame(doc, this, &editMenu);
94 canvas = wxGetApp().CreateCanvas(this, frame);
95 canvas->SetView(this);
96
97 SetFrame(frame);
98 Activate(true);
99
100 // Initialize the edit menu Undo and Redo items
101 doc->GetCommandProcessor()->SetEditMenu(editMenu);
102 doc->GetCommandProcessor()->Initialize();
103
104 wxShapeCanvas *shapeCanvas = (wxShapeCanvas *)canvas;
105 csDiagramDocument *diagramDoc = (csDiagramDocument *)doc;
106 shapeCanvas->SetDiagram(diagramDoc->GetDiagram());
107 diagramDoc->GetDiagram()->SetCanvas(shapeCanvas);
108
109 diagramDoc->GetDiagram()->SetGridSpacing((double) wxGetApp().GetGridSpacing());
110
111 switch (wxGetApp().GetGridStyle())
112 {
113 case csGRID_STYLE_NONE:
114 {
115 diagramDoc->GetDiagram()->SetSnapToGrid(false);
116 break;
117 }
118 case csGRID_STYLE_INVISIBLE:
119 {
120 diagramDoc->GetDiagram()->SetSnapToGrid(true);
121 break;
122 }
123 case csGRID_STYLE_DOTTED:
124 {
125 // TODO (not implemented in OGL)
126 break;
127 }
128 }
129
130
131 return true;
132}
133
134csDiagramView::~csDiagramView(void)
135{
136 if (frame)
137 {
138 ((wxDocMDIChildFrame*)frame)->SetView(NULL);
139 }
140}
141
142// Sneakily gets used for default print/preview
143// as well as drawing on the screen.
144void csDiagramView::OnDraw(wxDC *WXUNUSED(dc))
145{
146}
147
148void csDiagramView::OnUpdate(wxView *WXUNUSED(sender), wxObject *WXUNUSED(hint))
149{
150 if (canvas)
151 canvas->Refresh();
152}
153
154// Clean up windows used for displaying the view.
155bool csDiagramView::OnClose(bool deleteWindow)
156{
157 if (!GetDocument()->Close())
158 return false;
159
160 csDiagramDocument *diagramDoc = (csDiagramDocument *)GetDocument();
161 diagramDoc->GetDiagram()->SetCanvas(NULL);
162
163 canvas->ClearBackground();
164 canvas->SetDiagram(NULL);
165 canvas->SetView(NULL);
166 canvas = NULL;
167
168 wxMenu* fileMenu = frame->GetMenuBar()->GetMenu(0);
169
170 // Remove file menu from those managed by the command history
171 wxGetApp().GetDocManager()->FileHistoryRemoveMenu(fileMenu);
172
173 Activate(false);
174 frame->Show(false);
175
176 if (deleteWindow)
177 {
178 frame->Destroy();
179 }
180
181 return true;
182}
183
184// Adds or removes shape from m_selections
185void csDiagramView::SelectShape(wxShape* shape, bool select)
186{
187 if (select && !m_selections.Member(shape))
188 m_selections.Append(shape);
189 else if (!select)
190 m_selections.DeleteObject(shape);
191}
192
193void csDiagramView::OnSelectAll(wxCommandEvent& WXUNUSED(event))
194{
195 SelectAll(true);
196}
197
198wxShape *csDiagramView::FindFirstSelectedShape(void)
199{
200 csDiagramDocument *doc = (csDiagramDocument *)GetDocument();
201 wxShape *theShape = NULL;
202 wxNode *node = doc->GetDiagram()->GetShapeList()->GetFirst();
203 while (node)
204 {
205 wxShape *eachShape = (wxShape *)node->GetData();
206 if ((eachShape->GetParent() == NULL) && !eachShape->IsKindOf(CLASSINFO(wxLabelShape)) && eachShape->Selected())
207 {
208 theShape = eachShape;
209 node = NULL;
210 }
211 else node = node->GetNext();
212 }
213 return theShape;
214}
215
216void csDiagramView::FindSelectedShapes(wxList& selections, wxClassInfo* toFind)
217{
218 csDiagramDocument *doc = (csDiagramDocument *)GetDocument();
219 wxNode *node = doc->GetDiagram()->GetShapeList()->GetFirst();
220 while (node)
221 {
222 wxShape *eachShape = (wxShape *)node->GetData();
223 if ((eachShape->GetParent() == NULL) && !eachShape->IsKindOf(CLASSINFO(wxLabelShape)) && eachShape->Selected() && ((toFind == NULL) || (eachShape->IsKindOf(toFind))))
224 {
225 selections.Append(eachShape);
226 }
227 node = node->GetNext();
228 }
229}
230
231void csDiagramView::OnUndoUpdate(wxUpdateUIEvent& event)
232{
233 csDiagramDocument *doc = (csDiagramDocument *)GetDocument();
234 event.Enable(doc->GetCommandProcessor()->CanUndo());
235}
236
237void csDiagramView::OnRedoUpdate(wxUpdateUIEvent& event)
238{
239 csDiagramDocument *doc = (csDiagramDocument *)GetDocument();
240 event.Enable(doc->GetCommandProcessor()->CanRedo());
241}
242
243void csDiagramView::OnCut(wxCommandEvent& WXUNUSED(event))
244{
245 csDiagramDocument *doc = (csDiagramDocument *)GetDocument();
246
247 // Copy the shapes to the clipboard
248 wxGetApp().GetDiagramClipboard().Copy(doc->GetDiagram());
249
250 wxList selections;
251 FindSelectedShapes(selections);
252
253 DoCut(selections);
254}
255
256void csDiagramView::OnClear(wxCommandEvent& WXUNUSED(event))
257{
258 wxList selections;
259 FindSelectedShapes(selections);
260
261 DoCut(selections);
262}
263
264void csDiagramView::OnCopy(wxCommandEvent& WXUNUSED(event))
265{
266 csDiagramDocument *doc = (csDiagramDocument *)GetDocument();
267
268 // Copy the shapes to the clipboard
269 if (wxGetApp().GetDiagramClipboard().Copy(doc->GetDiagram()))
270 {
271#ifdef __WXMSW__
272 // Copy to the Windows clipboard
273 wxGetApp().GetDiagramClipboard().CopyToClipboard(1.0);
274#endif
275 }
276}
277
278void csDiagramView::OnPaste(wxCommandEvent& WXUNUSED(event))
279{
280 csDiagramDocument *doc = (csDiagramDocument *)GetDocument();
281
282 wxGetApp().GetDiagramClipboard().Paste(doc->GetDiagram());
283}
284
285void csDiagramView::OnDuplicate(wxCommandEvent& WXUNUSED(event))
286{
287 csDiagramDocument *doc = (csDiagramDocument *)GetDocument();
288
289 // Do a copy, then a paste
290 wxGetApp().GetDiagramClipboard().Copy(doc->GetDiagram());
291
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);
295}
296
297void csDiagramView::OnCutUpdate(wxUpdateUIEvent& event)
298{
299 event.Enable( (m_selections.GetCount() > 0) );
300}
301
302void csDiagramView::OnClearUpdate(wxUpdateUIEvent& event)
303{
304 event.Enable( (m_selections.GetCount() > 0) );
305}
306
307void csDiagramView::OnCopyUpdate(wxUpdateUIEvent& event)
308{
309 event.Enable( (m_selections.GetCount() > 0) );
310}
311
312void csDiagramView::OnPasteUpdate(wxUpdateUIEvent& event)
313{
314 /* csDiagramDocument *doc = */ (csDiagramDocument *)GetDocument();
315
316 int n = wxGetApp().GetDiagramClipboard().GetCount();
317
318 event.Enable( (n > 0) );
319}
320
321void csDiagramView::OnDuplicateUpdate(wxUpdateUIEvent& event)
322{
323 event.Enable( (m_selections.GetCount() > 0) );
324}
325
326void csDiagramView::DoCut(wxList& shapes)
327{
328 csDiagramDocument *doc = (csDiagramDocument *)GetDocument();
329
330 if (shapes.GetCount() > 0)
331 {
332 csDiagramCommand* cmd = new csDiagramCommand(_T("Cut"), doc);
333
334 wxNode* node = shapes.GetFirst();
335 while (node)
336 {
337 wxShape *theShape = (wxShape*) node->GetData();
338 csCommandState* state = new csCommandState(ID_CS_CUT, NULL, theShape);
339
340 // Insert lines at the front, so they are cut first.
341 // Otherwise we may try to remove a shape with a line still
342 // attached.
343 if (theShape->IsKindOf(CLASSINFO(wxLineShape)))
344 cmd->InsertState(state);
345 else
346 cmd->AddState(state);
347
348 node = node->GetNext();
349 }
350 cmd->RemoveLines(); // Schedule any connected lines, not already mentioned,
351 // to be removed first
352
353 doc->GetCommandProcessor()->Submit(cmd);
354 }
355}
356
357// Generalised command
358void csDiagramView::DoCmd(wxList& shapes, wxList& oldShapes, int cmd, const wxString& op)
359{
360 csDiagramDocument *doc = (csDiagramDocument *)GetDocument();
361
362 if (shapes.GetCount() > 0)
363 {
364 csDiagramCommand* command = new csDiagramCommand(op, doc);
365
366 wxNode* node = shapes.GetFirst();
367 wxNode* node1 = oldShapes.GetFirst();
368 while (node && node1)
369 {
370 wxShape *theShape = (wxShape*) node->GetData();
371 wxShape *oldShape = (wxShape*) node1->GetData();
372 csCommandState* state = new csCommandState(cmd, theShape, oldShape);
373 command->AddState(state);
374
375 node = node->GetNext();
376 node1 = node1->GetNext();
377 }
378 doc->GetCommandProcessor()->Submit(command);
379 }
380}
381
382void csDiagramView::OnChangeBackgroundColour(wxCommandEvent& WXUNUSED(event))
383{
384 csDiagramDocument *doc = (csDiagramDocument *)GetDocument();
385
386 wxList selections;
387 FindSelectedShapes(selections);
388
389 if (selections.GetCount() > 0)
390 {
391 wxColourData data;
392 data.SetChooseFull(true);
393 if (selections.GetCount() == 1)
394 {
395 wxShape* firstShape = (wxShape*) selections.GetFirst()->GetData();
396 data.SetColour(firstShape->GetBrush()->GetColour());
397 }
398
399 wxColourDialog *dialog = new wxColourDialog(frame, &data);
400 wxBrush *theBrush = NULL;
401 if (dialog->ShowModal() == wxID_OK)
402 {
403 wxColourData retData = dialog->GetColourData();
404 wxColour col = retData.GetColour();
405 theBrush = wxTheBrushList->FindOrCreateBrush(col, wxSOLID);
406 }
407 dialog->Close(true);
408 if (!theBrush)
409 return;
410
411 csDiagramCommand* cmd = new csDiagramCommand(_T("Change colour"), doc);
412
413 wxNode* node = selections.GetFirst();
414 while (node)
415 {
416 wxShape *theShape = (wxShape*) node->GetData();
417 wxShape* newShape = theShape->CreateNewCopy();
418 newShape->SetBrush(theBrush);
419
420 csCommandState* state = new csCommandState(ID_CS_CHANGE_BACKGROUND_COLOUR, newShape, theShape);
421 cmd->AddState(state);
422
423 node = node->GetNext();
424 }
425 doc->GetCommandProcessor()->Submit(cmd);
426 }
427}
428
429void csDiagramView::OnEditProperties(wxCommandEvent& WXUNUSED(event))
430{
431 wxShape *theShape = FindFirstSelectedShape();
432 if (theShape)
433 ((csEvtHandler *)theShape->GetEventHandler())->EditProperties();
434}
435
436void csDiagramView::OnEditPropertiesUpdate(wxUpdateUIEvent& event)
437{
438 wxList selections;
439 FindSelectedShapes(selections);
440 event.Enable( (selections.GetCount() > 0) );
441}
442
443void csDiagramView::OnPointSizeComboSel(wxCommandEvent& event)
444{
445 wxComboBox* combo = (wxComboBox*) event.GetEventObject();
446 wxASSERT( combo != NULL );
447
448 int newPointSize = (combo->GetSelection() + 1);
449
450 ApplyPointSize(newPointSize);
451
452}
453
454// TODO: must find out how to intercept the Return key, rather than
455// every key stroke. But for now, do every key stroke.
456void csDiagramView::OnPointSizeComboText(wxCommandEvent& event)
457{
458 wxComboBox* combo = (wxComboBox*) event.GetEventObject();
459 wxASSERT( combo != NULL );
460
461 wxString str(combo->GetValue());
462 long newPointSize;
463 str.ToLong( &newPointSize );
464
465 if (newPointSize < 2)
466 return;
467
468 ApplyPointSize(newPointSize);
469}
470
471void csDiagramView::ApplyPointSize(int pointSize)
472{
473 csDiagramDocument *doc = (csDiagramDocument *)GetDocument();
474
475 wxList selections;
476 FindSelectedShapes(selections);
477
478 if (selections.GetCount() > 0)
479 {
480 csDiagramCommand* cmd = new csDiagramCommand(_T("Point size"), doc);
481
482 wxNode* node = selections.GetFirst();
483 while (node)
484 {
485 wxShape *theShape = (wxShape*) node->GetData();
486 wxShape *newShape = theShape->CreateNewCopy();
487
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());
494
495 newShape->SetFont(newFont);
496
497 csCommandState* state = new csCommandState(ID_CS_FONT_CHANGE, newShape, theShape);
498
499 cmd->AddState(state);
500
501 node = node->GetNext();
502 }
503 doc->GetCommandProcessor()->Submit(cmd);
504 }
505}
506
507void csDiagramView::OnZoomSel(wxCommandEvent& event)
508{
509 int maxZoom = 200;
510 int minZoom = 5;
511 int inc = 5;
512 int noStrings = (maxZoom - minZoom)/inc ;
513
514 wxComboBox* combo = (wxComboBox*) event.GetEventObject();
515 wxASSERT( combo != NULL );
516
517 int scale = (int) ((noStrings - combo->GetSelection() - 1)*inc + minZoom);
518
519 canvas->SetScale((double) (scale/100.0), (double) (scale/100.0));
520 canvas->Refresh();
521}
522
523// Select or deselect all
524void csDiagramView::SelectAll(bool select)
525{
526 wxClientDC dc(canvas);
527 canvas->PrepareDC(dc);
528
529 if (!select)
530 {
531 wxList selections;
532 FindSelectedShapes(selections);
533
534 wxNode* node = selections.GetFirst();
535 while (node)
536 {
537 wxShape *theShape = (wxShape*) node->GetData();
538 theShape->Select(false, &dc);
539 SelectShape(theShape, false);
540
541 node = node->GetNext();
542 }
543 }
544 else
545 {
546 csDiagramDocument *doc = (csDiagramDocument *)GetDocument();
547 wxNode *node = doc->GetDiagram()->GetShapeList()->GetFirst();
548 while (node)
549 {
550 wxShape *eachShape = (wxShape *)node->GetData();
551 if (eachShape->GetParent() == NULL &&
552 !eachShape->IsKindOf(CLASSINFO(wxControlPoint)) &&
553 !eachShape->IsKindOf(CLASSINFO(wxLabelShape)))
554 {
555 eachShape->Select(true, &dc);
556 SelectShape(eachShape, true);
557 }
558 node = node->GetNext();
559 }
560 }
561}
562
563
564void csDiagramView::OnToggleArrowTool(wxCommandEvent& WXUNUSED(event))
565{
566 csDiagramDocument *doc = (csDiagramDocument *)GetDocument();
567
568 bool state = wxGetApp().GetDiagramToolBar()->GetToolState(DIAGRAM_TOOLBAR_LINE_ARROW);
569 wxString stateName;
570 if (state)
571 stateName = _T("Arrow on");
572 else
573 stateName = _T("Arrow off");
574
575 wxList selections;
576 FindSelectedShapes(selections, CLASSINFO(wxLineShape));
577
578 if (selections.GetCount() > 0)
579 {
580 csDiagramCommand* cmd = new csDiagramCommand(stateName, doc);
581
582 wxNode* node = selections.GetFirst();
583 while (node)
584 {
585 wxLineShape *theShape = (wxLineShape*) node->GetData();
586 wxLineShape *newShape = NULL;
587
588 if (state)
589 {
590 // Add arrow
591 if (theShape->GetArrows().GetCount() == 0)
592 {
593 newShape = (wxLineShape*) theShape->CreateNewCopy();
594 newShape->AddArrow(ARROW_ARROW, ARROW_POSITION_MIDDLE, 10.0, 0.0, _T("Normal arrowhead"));
595 }
596 }
597 else
598 {
599 if (theShape->GetArrows().GetCount() > 0)
600 {
601 newShape = (wxLineShape*) theShape->CreateNewCopy();
602 newShape->ClearArrowsAtPosition();
603 }
604 }
605
606 // If the new state is the same as the old, don't bother adding it to the command state.
607 if (newShape)
608 {
609 csCommandState* state = new csCommandState(ID_CS_ARROW_CHANGE, newShape, theShape);
610 cmd->AddState(state);
611 }
612
613 node = node->GetNext();
614 }
615 doc->GetCommandProcessor()->Submit(cmd);
616 }
617}
618
619void csDiagramView::OnToggleArrowToolUpdate(wxUpdateUIEvent& event)
620{
621 wxList selections;
622 FindSelectedShapes(selections, CLASSINFO(wxLineShape));
623 event.Enable( (selections.GetCount() > 0) );
624}
625
626// Make the point size combobox reflect this
627void csDiagramView::ReflectPointSize(int pointSize)
628{
629 wxComboBox* comboBox = wxGetApp().GetPointSizeComboBox();
630 comboBox->SetSelection(pointSize -1);
631}
632
633// Make the arrow toggle button reflect the state of the line
634void csDiagramView::ReflectArrowState(wxLineShape* lineShape)
635{
636 bool haveArrow = false;
637 wxNode *node = lineShape->GetArrows().GetFirst();
638 while (node)
639 {
640 wxArrowHead *arrow = (wxArrowHead *)node->GetData();
641 if (ARROW_POSITION_MIDDLE == arrow->GetArrowEnd())
642 haveArrow = true;
643 node = node->GetNext();
644 }
645
646 wxGetApp().GetDiagramToolBar()->ToggleTool(DIAGRAM_TOOLBAR_LINE_ARROW, haveArrow);
647}
648
649void csDiagramView::OnAlign(wxCommandEvent& event)
650{
651 // Make a copy of the selections, keeping only those shapes
652 // that are top-level non-line shapes.
653 wxList selections;
654 wxNode* node = GetSelectionList().GetFirst();
655 while (node)
656 {
657 wxShape* shape = (wxShape*) node->GetData();
658 if ((shape->GetParent() == NULL) && (!shape->IsKindOf(CLASSINFO(wxLineShape))))
659 {
660 selections.Append(shape);
661 }
662 node = node->GetNext();
663 }
664
665 if (selections.GetCount() == 0)
666 return;
667
668 csDiagramDocument *doc = (csDiagramDocument *)GetDocument();
669 csDiagramCommand* cmd = new csDiagramCommand(_T("Align"), doc);
670
671 node = selections.GetFirst();
672 wxShape* firstShape = (wxShape*) node->GetData();
673
674 double x = firstShape->GetX();
675 double y = firstShape->GetY();
676 double width, height;
677 firstShape->GetBoundingBoxMax(&width, &height);
678
679 node = selections.GetFirst();
680 while (node)
681 {
682 wxShape* shape = (wxShape*) node->GetData();
683 if (shape != firstShape)
684 {
685 /* double x1 = */ shape->GetX();
686 /* double y1 = */ shape->GetY();
687 double width1, height1;
688 shape->GetBoundingBoxMax(& width1, & height1);
689
690 wxShape* newShape = shape->CreateNewCopy();
691
692 switch (event.GetId())
693 {
694 case DIAGRAM_TOOLBAR_ALIGNL:
695 {
696 double x2 = (double)(x - (width/2.0) + (width1/2.0));
697 newShape->SetX(x2);
698 break;
699 }
700 case DIAGRAM_TOOLBAR_ALIGNR:
701 {
702 double x2 = (double)(x + (width/2.0) - (width1/2.0));
703 newShape->SetX(x2);
704 break;
705 }
706 case DIAGRAM_TOOLBAR_ALIGNB:
707 {
708 double y2 = (double)(y + (height/2.0) - (height1/2.0));
709 newShape->SetY(y2);
710 break;
711 }
712 case DIAGRAM_TOOLBAR_ALIGNT:
713 {
714 double y2 = (double)(y - (height/2.0) + (height1/2.0));
715 newShape->SetY(y2);
716 break;
717 }
718 case DIAGRAM_TOOLBAR_ALIGN_HORIZ:
719 {
720 newShape->SetX(x);
721 break;
722 }
723 case DIAGRAM_TOOLBAR_ALIGN_VERT:
724 {
725 newShape->SetY(y);
726 break;
727 }
728 case DIAGRAM_TOOLBAR_COPY_SIZE:
729 {
730 newShape->SetSize(width, height);
731 break;
732 }
733 }
734 csCommandState* state = new csCommandState(ID_CS_ALIGN, newShape, shape);
735 cmd->AddState(state);
736 }
737 node = node->GetNext();
738 }
739 doc->GetCommandProcessor()->Submit(cmd);
740}
741
742void csDiagramView::OnAlignUpdate(wxUpdateUIEvent& event)
743{
744 // This is an approximation, since there may be lines
745 // amongst the selections.
746 event.Enable( (m_selections.GetCount() > 1) ) ;
747}
748
749void csDiagramView::OnNewLinePoint(wxCommandEvent& WXUNUSED(event))
750{
751 csDiagramDocument *doc = (csDiagramDocument *)GetDocument();
752 csDiagramCommand* cmd = new csDiagramCommand(_T("New line point"), doc);
753
754 wxNode* node = m_selections.GetFirst();
755 while (node)
756 {
757 wxShape* shape = (wxShape*) node->GetData();
758 if (shape->IsKindOf(CLASSINFO(wxLineShape)))
759 {
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);
764 }
765 node = node->GetNext();
766 }
767 doc->GetCommandProcessor()->Submit(cmd);
768}
769
770void csDiagramView::OnCutLinePoint(wxCommandEvent& WXUNUSED(event))
771{
772 csDiagramDocument *doc = (csDiagramDocument *)GetDocument();
773 csDiagramCommand* cmd = new csDiagramCommand(_T("Cut line point"), doc);
774
775 wxNode* node = m_selections.GetFirst();
776 while (node)
777 {
778 wxShape* shape = (wxShape*) node->GetData();
779 if (shape->IsKindOf(CLASSINFO(wxLineShape)))
780 {
781 wxShape* newShape = shape->CreateNewCopy();
782 ((wxLineShape*)newShape)->DeleteLineControlPoint();
783 csCommandState* state = new csCommandState(ID_CS_CUT_POINT, newShape, shape);
784 cmd->AddState(state);
785 }
786 node = node->GetNext();
787 }
788 doc->GetCommandProcessor()->Submit(cmd);
789}
790
791void csDiagramView::OnStraightenLines(wxCommandEvent& WXUNUSED(event))
792{
793 csDiagramDocument *doc = (csDiagramDocument *)GetDocument();
794 csDiagramCommand* cmd = new csDiagramCommand(_T("Straighten lines"), doc);
795
796 wxNode* node = m_selections.GetFirst();
797 while (node)
798 {
799 wxShape* shape = (wxShape*) node->GetData();
800 if (shape->IsKindOf(CLASSINFO(wxLineShape)))
801 {
802 wxShape* newShape = shape->CreateNewCopy();
803 ((wxLineShape*)newShape)->Straighten();
804 csCommandState* state = new csCommandState(ID_CS_STRAIGHTEN, newShape, shape);
805 cmd->AddState(state);
806 }
807 node = node->GetNext();
808 }
809 doc->GetCommandProcessor()->Submit(cmd);
810}
811
812void csDiagramView::OnNewLinePointUpdate(wxUpdateUIEvent& event)
813{
814 wxList selections;
815 FindSelectedShapes(selections, CLASSINFO(wxLineShape));
816 event.Enable( (selections.GetCount() > 0) );
817}
818
819void csDiagramView::OnCutLinePointUpdate(wxUpdateUIEvent& event)
820{
821 wxList selections;
822 FindSelectedShapes(selections, CLASSINFO(wxLineShape));
823 event.Enable( (selections.GetCount() > 0) );
824}
825
826void csDiagramView::OnStraightenLinesUpdate(wxUpdateUIEvent& event)
827{
828 wxList selections;
829 FindSelectedShapes(selections, CLASSINFO(wxLineShape));
830 event.Enable( (selections.GetCount() > 0) );
831}
832
833/*
834 * Window implementations
835 */
836
837IMPLEMENT_CLASS(csCanvas, wxShapeCanvas)
838
839BEGIN_EVENT_TABLE(csCanvas, wxShapeCanvas)
840 EVT_MOUSE_EVENTS(csCanvas::OnMouseEvent)
841 EVT_PAINT(csCanvas::OnPaint)
842END_EVENT_TABLE()
843
844// Define a constructor for my canvas
845csCanvas::csCanvas(csDiagramView *v, wxWindow *parent, wxWindowID id, const wxPoint& pos,
846 const wxSize& size, long style):
847 wxShapeCanvas(parent, id, pos, size, style)
848{
849 m_view = v;
850}
851
852csCanvas::~csCanvas(void)
853{
854}
855
856void csCanvas::DrawOutline(wxDC& dc, double x1, double y1, double x2, double y2)
857{
858 wxPen dottedPen(wxColour(0, 0, 0), 1, wxDOT);
859 dc.SetPen(dottedPen);
860 dc.SetBrush(* wxTRANSPARENT_BRUSH);
861
862 dc.DrawRectangle((long) x1, (long) y1, (long) (x2 - x1), (long) (y2 - y1));
863}
864
865void csCanvas::OnLeftClick(double x, double y, int WXUNUSED(keys))
866{
867 csEditorToolPalette *palette = wxGetApp().GetDiagramPalette();
868
869 if (palette->GetSelection() == PALETTE_ARROW)
870 {
871 GetView()->SelectAll(false);
872
873 wxClientDC dc(this);
874 PrepareDC(dc);
875
876 Redraw(dc);
877 return;
878 }
879
880 if (palette->GetSelection() == PALETTE_TEXT_TOOL)
881 {
882 // Ask for a label and create a new free-floating text region
883 csLabelEditingDialog* dialog = new csLabelEditingDialog(GetParent());
884
885 dialog->SetShapeLabel( wxEmptyString );
886 dialog->SetTitle(_T("New text box"));
887 if (dialog->ShowModal() == wxID_CANCEL)
888 {
889 dialog->Destroy();
890 return;
891 }
892
893 wxString newLabel = dialog->GetShapeLabel();
894 dialog->Destroy();
895
896 wxShape* shape = new csTextBoxShape;
897 shape->AssignNewIds();
898 shape->SetEventHandler(new csEvtHandler(shape, shape, newLabel));
899
900 wxComboBox* comboBox = wxGetApp().GetPointSizeComboBox();
901 wxString str(comboBox->GetValue());
902 long pointSize;
903 str.ToLong( &pointSize );
904
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());
911
912 shape->SetFont(newFont);
913
914 shape->SetX(x);
915 shape->SetY(y);
916
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);
921
922 palette->SetSelection(PALETTE_ARROW);
923
924 return;
925 }
926
927 csSymbol* symbol = wxGetApp().GetSymbolDatabase()->FindSymbol(palette->GetSelection());
928 if (symbol)
929 {
930 wxShape* theShape = symbol->GetShape()->CreateNewCopy();
931
932 wxComboBox* comboBox = wxGetApp().GetPointSizeComboBox();
933 wxString str(comboBox->GetValue());
934 long pointSize;
935 str.ToLong( &pointSize );
936
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());
943
944 theShape->SetFont(newFont);
945
946 theShape->AssignNewIds();
947 theShape->SetX(x);
948 theShape->SetY(y);
949
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);
954
955 palette->SetSelection(PALETTE_ARROW);
956 }
957}
958
959void csCanvas::OnRightClick(double WXUNUSED(x), double WXUNUSED(y), int WXUNUSED(keys))
960{
961}
962
963// Initial point
964static double sg_initialX, sg_initialY;
965
966void csCanvas::OnDragLeft(bool WXUNUSED(draw), double x, double y, int WXUNUSED(keys))
967{
968 wxClientDC dc(this);
969 PrepareDC(dc);
970
971 dc.SetLogicalFunction(OGLRBLF);
972 DrawOutline(dc, sg_initialX, sg_initialY, x, y);
973}
974
975void csCanvas::OnBeginDragLeft(double x, double y, int WXUNUSED(keys))
976{
977 sg_initialX = x;
978 sg_initialY = y;
979
980 wxClientDC dc(this);
981 PrepareDC(dc);
982
983 dc.SetLogicalFunction(OGLRBLF);
984 DrawOutline(dc, sg_initialX, sg_initialY, x, y);
985 CaptureMouse();
986}
987
988void csCanvas::OnEndDragLeft(double x, double y, int WXUNUSED(keys))
989{
990 ReleaseMouse();
991
992 wxClientDC dc(this);
993 PrepareDC(dc);
994
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);
1001
1002 wxNode *node = GetDiagram()->GetShapeList()->GetFirst();
1003 while (node)
1004 {
1005 wxShape *shape = (wxShape *)node->GetData();
1006 if (shape->GetParent() == NULL && !shape->IsKindOf(CLASSINFO(wxControlPoint)))
1007 {
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)
1012 {
1013 shape->Select(true, &dc);
1014 GetView()->SelectShape(shape, true);
1015 }
1016 }
1017 node = node->GetNext();
1018 }
1019}
1020
1021void csCanvas::OnDragRight(bool WXUNUSED(draw), double WXUNUSED(x), double WXUNUSED(y), int WXUNUSED(keys))
1022{
1023}
1024
1025void csCanvas::OnBeginDragRight(double WXUNUSED(x), double WXUNUSED(y), int WXUNUSED(keys))
1026{
1027}
1028
1029void csCanvas::OnEndDragRight(double WXUNUSED(x), double WXUNUSED(y), int WXUNUSED(keys))
1030{
1031}
1032
1033void csCanvas::OnMouseEvent(wxMouseEvent& event)
1034{
1035 wxShapeCanvas::OnMouseEvent(event);
1036}
1037
1038void csCanvas::OnPaint(wxPaintEvent& event)
1039{
1040// if (GetDiagram())
1041 wxShapeCanvas::OnPaint(event);
1042}