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