• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-R7000-V1.0.7.12_1.2.5/ap/gpl/amule/wxWidgets-2.8.12/contrib/samples/ogl/studio/
1/////////////////////////////////////////////////////////////////////////////
2// Name:        contrib/samples/ogl/studio/view.cpp
3// Purpose:     Implements view functionality
4// Author:      Julian Smart
5// Modified by:
6// Created:     12/07/98
7// RCS-ID:      $Id: view.cpp 37440 2006-02-10 11:59:52Z ABX $
8// Copyright:   (c) Julian Smart
9// Licence:     wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
12// For compilers that support precompilation, includes "wx.h".
13#include "wx/wxprec.h"
14
15#ifdef __BORLANDC__
16#pragma hdrstop
17#endif
18
19#ifndef WX_PRECOMP
20#include "wx/wx.h"
21#endif
22
23#include "wx/colordlg.h"
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"
35#include "wx/ogl/basicp.h"
36#include "wx/ogl/linesp.h"
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.
86bool csDiagramView::OnCreate(wxDocument *doc, long WXUNUSED(flags))
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);
94  Activate(true);
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        {
111            diagramDoc->GetDiagram()->SetSnapToGrid(false);
112            break;
113        }
114        case csGRID_STYLE_INVISIBLE:
115        {
116            diagramDoc->GetDiagram()->SetSnapToGrid(true);
117            break;
118        }
119        case csGRID_STYLE_DOTTED:
120        {
121            // TODO (not implemented in OGL)
122            break;
123        }
124    }
125
126
127  return true;
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.
140void csDiagramView::OnDraw(wxDC *WXUNUSED(dc))
141{
142}
143
144void csDiagramView::OnUpdate(wxView *WXUNUSED(sender), wxObject *WXUNUSED(hint))
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())
154    return false;
155
156  csDiagramDocument *diagramDoc = (csDiagramDocument *)GetDocument();
157  diagramDoc->GetDiagram()->SetCanvas(NULL);
158
159  canvas->ClearBackground();
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
169  Activate(false);
170  frame->Show(false);
171
172  if (deleteWindow)
173  {
174    frame->Destroy();
175  }
176
177  return true;
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
189void csDiagramView::OnSelectAll(wxCommandEvent& WXUNUSED(event))
190{
191    SelectAll(true);
192}
193
194wxShape *csDiagramView::FindFirstSelectedShape(void)
195{
196  csDiagramDocument *doc = (csDiagramDocument *)GetDocument();
197  wxObjectList::compatibility_iterator node = doc->GetDiagram()->GetShapeList()->GetFirst();
198  while (node)
199  {
200    wxShape *eachShape = (wxShape *)node->GetData();
201    if ((eachShape->GetParent() == NULL) && !eachShape->IsKindOf(CLASSINFO(wxLabelShape)) && eachShape->Selected())
202    {
203      return eachShape;
204    }
205    else node = node->GetNext();
206  }
207  return NULL;
208}
209
210void csDiagramView::FindSelectedShapes(wxList& selections, wxClassInfo* toFind)
211{
212  csDiagramDocument *doc = (csDiagramDocument *)GetDocument();
213  wxObjectList::compatibility_iterator node = doc->GetDiagram()->GetShapeList()->GetFirst();
214  while (node)
215  {
216    wxShape *eachShape = (wxShape *)node->GetData();
217    if ((eachShape->GetParent() == NULL) && !eachShape->IsKindOf(CLASSINFO(wxLabelShape)) && eachShape->Selected() && ((toFind == NULL) || (eachShape->IsKindOf(toFind))))
218    {
219      selections.Append(eachShape);
220    }
221    node = node->GetNext();
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
237void csDiagramView::OnCut(wxCommandEvent& WXUNUSED(event))
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
250void csDiagramView::OnClear(wxCommandEvent& WXUNUSED(event))
251{
252    wxList selections;
253    FindSelectedShapes(selections);
254
255    DoCut(selections);
256}
257
258void csDiagramView::OnCopy(wxCommandEvent& WXUNUSED(event))
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
272void csDiagramView::OnPaste(wxCommandEvent& WXUNUSED(event))
273{
274    csDiagramDocument *doc = (csDiagramDocument *)GetDocument();
275
276    wxGetApp().GetDiagramClipboard().Paste(doc->GetDiagram());
277}
278
279void csDiagramView::OnDuplicate(wxCommandEvent& WXUNUSED(event))
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{
293    event.Enable( (m_selections.GetCount() > 0) );
294}
295
296void csDiagramView::OnClearUpdate(wxUpdateUIEvent& event)
297{
298    event.Enable( (m_selections.GetCount() > 0) );
299}
300
301void csDiagramView::OnCopyUpdate(wxUpdateUIEvent& event)
302{
303    event.Enable( (m_selections.GetCount() > 0) );
304}
305
306void csDiagramView::OnPasteUpdate(wxUpdateUIEvent& event)
307{
308    int n = wxGetApp().GetDiagramClipboard().GetCount();
309
310    event.Enable( (n > 0) );
311}
312
313void csDiagramView::OnDuplicateUpdate(wxUpdateUIEvent& event)
314{
315    event.Enable( (m_selections.GetCount() > 0) );
316}
317
318void csDiagramView::DoCut(wxList& shapes)
319{
320    csDiagramDocument *doc = (csDiagramDocument *)GetDocument();
321
322    if (shapes.GetCount() > 0)
323    {
324        csDiagramCommand* cmd = new csDiagramCommand(_T("Cut"), doc);
325
326        wxObjectList::compatibility_iterator node = shapes.GetFirst();
327        while (node)
328        {
329            wxShape *theShape = (wxShape*) node->GetData();
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
340            node = node->GetNext();
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
354    if (shapes.GetCount() > 0)
355    {
356        csDiagramCommand* command = new csDiagramCommand(op, doc);
357
358        wxObjectList::compatibility_iterator node = shapes.GetFirst();
359        wxObjectList::compatibility_iterator node1 = oldShapes.GetFirst();
360        while (node && node1)
361        {
362            wxShape *theShape = (wxShape*) node->GetData();
363            wxShape *oldShape = (wxShape*) node1->GetData();
364            csCommandState* state = new csCommandState(cmd, theShape, oldShape);
365            command->AddState(state);
366
367            node = node->GetNext();
368            node1 = node1->GetNext();
369        }
370        doc->GetCommandProcessor()->Submit(command);
371    }
372}
373
374void csDiagramView::OnChangeBackgroundColour(wxCommandEvent& WXUNUSED(event))
375{
376    csDiagramDocument *doc = (csDiagramDocument *)GetDocument();
377
378    wxList selections;
379    FindSelectedShapes(selections);
380
381    if (selections.GetCount() > 0)
382    {
383        wxColourData data;
384        data.SetChooseFull(true);
385        if (selections.GetCount() == 1)
386        {
387            wxShape* firstShape = (wxShape*) selections.GetFirst()->GetData();
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        }
399        dialog->Close(true);
400        if (!theBrush)
401            return;
402
403        csDiagramCommand* cmd = new csDiagramCommand(_T("Change colour"), doc);
404
405        wxObjectList::compatibility_iterator node = selections.GetFirst();
406        while (node)
407        {
408            wxShape *theShape = (wxShape*) node->GetData();
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
415            node = node->GetNext();
416        }
417        doc->GetCommandProcessor()->Submit(cmd);
418    }
419}
420
421void csDiagramView::OnEditProperties(wxCommandEvent& WXUNUSED(event))
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);
432    event.Enable( (selections.GetCount() > 0) );
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());
454    long newPointSize;
455    str.ToLong( &newPointSize );
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
470    if (selections.GetCount() > 0)
471    {
472        csDiagramCommand* cmd = new csDiagramCommand(_T("Point size"), doc);
473
474        wxObjectList::compatibility_iterator node = selections.GetFirst();
475        while (node)
476        {
477            wxShape *theShape = (wxShape*) node->GetData();
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
493            node = node->GetNext();
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
526        wxObjectList::compatibility_iterator node = selections.GetFirst();
527        while (node)
528        {
529            wxShape *theShape = (wxShape*) node->GetData();
530            theShape->Select(false, &dc);
531            SelectShape(theShape, false);
532
533            node = node->GetNext();
534        }
535    }
536    else
537    {
538        csDiagramDocument *doc = (csDiagramDocument *)GetDocument();
539        wxObjectList::compatibility_iterator node = doc->GetDiagram()->GetShapeList()->GetFirst();
540        while (node)
541        {
542            wxShape *eachShape = (wxShape *)node->GetData();
543            if (eachShape->GetParent() == NULL &&
544                !eachShape->IsKindOf(CLASSINFO(wxControlPoint)) &&
545                !eachShape->IsKindOf(CLASSINFO(wxLabelShape)))
546            {
547                eachShape->Select(true, &dc);
548                SelectShape(eachShape, true);
549            }
550            node = node->GetNext();
551        }
552    }
553}
554
555
556void csDiagramView::OnToggleArrowTool(wxCommandEvent& WXUNUSED(event))
557{
558    csDiagramDocument *doc = (csDiagramDocument *)GetDocument();
559
560    bool state = wxGetApp().GetDiagramToolBar()->GetToolState(DIAGRAM_TOOLBAR_LINE_ARROW);
561    wxString stateName;
562    if (state)
563        stateName = _T("Arrow on");
564    else
565        stateName = _T("Arrow off");
566
567    wxList selections;
568    FindSelectedShapes(selections, CLASSINFO(wxLineShape));
569
570    if (selections.GetCount() > 0)
571    {
572        csDiagramCommand* cmd = new csDiagramCommand(stateName, doc);
573
574        wxObjectList::compatibility_iterator node = selections.GetFirst();
575        while (node)
576        {
577            wxLineShape *theShape = (wxLineShape*) node->GetData();
578            wxLineShape *newShape = NULL;
579
580            if (state)
581            {
582                // Add arrow
583                if (theShape->GetArrows().GetCount() == 0)
584                {
585                    newShape = (wxLineShape*) theShape->CreateNewCopy();
586                    newShape->AddArrow(ARROW_ARROW, ARROW_POSITION_MIDDLE, 10.0, 0.0, _T("Normal arrowhead"));
587                }
588            }
589            else
590            {
591                if (theShape->GetArrows().GetCount() > 0)
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
605            node = node->GetNext();
606        }
607        doc->GetCommandProcessor()->Submit(cmd);
608    }
609}
610
611void csDiagramView::OnToggleArrowToolUpdate(wxUpdateUIEvent& event)
612{
613    wxList selections;
614    FindSelectedShapes(selections, CLASSINFO(wxLineShape));
615    event.Enable( (selections.GetCount() > 0) );
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{
628    bool haveArrow = false;
629    wxObjectList::compatibility_iterator node = lineShape->GetArrows().GetFirst();
630    while (node)
631    {
632      wxArrowHead *arrow = (wxArrowHead *)node->GetData();
633      if (ARROW_POSITION_MIDDLE == arrow->GetArrowEnd())
634        haveArrow = true;
635      node = node->GetNext();
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;
646    wxObjectList::compatibility_iterator node = GetSelectionList().GetFirst();
647    while (node)
648    {
649        wxShape* shape = (wxShape*) node->GetData();
650        if ((shape->GetParent() == NULL) && (!shape->IsKindOf(CLASSINFO(wxLineShape))))
651        {
652            selections.Append(shape);
653        }
654        node = node->GetNext();
655    }
656
657    if (selections.GetCount() == 0)
658        return;
659
660    csDiagramDocument *doc = (csDiagramDocument *)GetDocument();
661    csDiagramCommand* cmd = new csDiagramCommand(_T("Align"), doc);
662
663    node = selections.GetFirst();
664    wxShape* firstShape = (wxShape*) node->GetData();
665
666    double x = firstShape->GetX();
667    double y = firstShape->GetY();
668    double width, height;
669    firstShape->GetBoundingBoxMax(&width, &height);
670
671    node = selections.GetFirst();
672    while (node)
673    {
674        wxShape* shape = (wxShape*) node->GetData();
675        if (shape != firstShape)
676        {
677            /* double x1 = */ shape->GetX();
678            /* double y1 = */ shape->GetY();
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        }
729        node = node->GetNext();
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.
738    event.Enable( (m_selections.GetCount() > 1) ) ;
739}
740
741void csDiagramView::OnNewLinePoint(wxCommandEvent& WXUNUSED(event))
742{
743    csDiagramDocument *doc = (csDiagramDocument *)GetDocument();
744    csDiagramCommand* cmd = new csDiagramCommand(_T("New line point"), doc);
745
746    wxObjectList::compatibility_iterator node = m_selections.GetFirst();
747    while (node)
748    {
749        wxShape* shape = (wxShape*) node->GetData();
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        }
757        node = node->GetNext();
758    }
759    doc->GetCommandProcessor()->Submit(cmd);
760}
761
762void csDiagramView::OnCutLinePoint(wxCommandEvent& WXUNUSED(event))
763{
764    csDiagramDocument *doc = (csDiagramDocument *)GetDocument();
765    csDiagramCommand* cmd = new csDiagramCommand(_T("Cut line point"), doc);
766
767    wxObjectList::compatibility_iterator node = m_selections.GetFirst();
768    while (node)
769    {
770        wxShape* shape = (wxShape*) node->GetData();
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        }
778        node = node->GetNext();
779    }
780    doc->GetCommandProcessor()->Submit(cmd);
781}
782
783void csDiagramView::OnStraightenLines(wxCommandEvent& WXUNUSED(event))
784{
785    csDiagramDocument *doc = (csDiagramDocument *)GetDocument();
786    csDiagramCommand* cmd = new csDiagramCommand(_T("Straighten lines"), doc);
787
788    wxObjectList::compatibility_iterator node = m_selections.GetFirst();
789    while (node)
790    {
791        wxShape* shape = (wxShape*) node->GetData();
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        }
799        node = node->GetNext();
800    }
801    doc->GetCommandProcessor()->Submit(cmd);
802}
803
804void csDiagramView::OnNewLinePointUpdate(wxUpdateUIEvent& event)
805{
806    wxList selections;
807    FindSelectedShapes(selections, CLASSINFO(wxLineShape));
808    event.Enable( (selections.GetCount() > 0) );
809}
810
811void csDiagramView::OnCutLinePointUpdate(wxUpdateUIEvent& event)
812{
813    wxList selections;
814    FindSelectedShapes(selections, CLASSINFO(wxLineShape));
815    event.Enable( (selections.GetCount() > 0) );
816}
817
818void csDiagramView::OnStraightenLinesUpdate(wxUpdateUIEvent& event)
819{
820    wxList selections;
821    FindSelectedShapes(selections, CLASSINFO(wxLineShape));
822    event.Enable( (selections.GetCount() > 0) );
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{
850    wxPen dottedPen(*wxBLACK, 1, wxDOT);
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
857void csCanvas::OnLeftClick(double x, double y, int WXUNUSED(keys))
858{
859    csEditorToolPalette *palette = wxGetApp().GetDiagramPalette();
860
861    if (palette->GetSelection() == PALETTE_ARROW)
862    {
863        GetView()->SelectAll(false);
864
865        wxClientDC dc(this);
866        PrepareDC(dc);
867
868        Redraw(dc);
869        return;
870    }
871
872    if (palette->GetSelection() == PALETTE_TEXT_TOOL)
873    {
874        wxString newLabel;
875
876#if wxUSE_WX_RESOURCES
877        // Ask for a label and create a new free-floating text region
878        csLabelEditingDialog* dialog = new csLabelEditingDialog(GetParent());
879
880        dialog->SetShapeLabel( wxEmptyString );
881        dialog->SetTitle(_T("New text box"));
882        if (dialog->ShowModal() == wxID_CANCEL)
883        {
884            dialog->Destroy();
885            return;
886        }
887
888        newLabel = dialog->GetShapeLabel();
889        dialog->Destroy();
890#endif // wxUSE_WX_RESOURCES
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());
898        long pointSize;
899        str.ToLong( &pointSize );
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
913        csDiagramCommand* cmd = new csDiagramCommand(_T("Text box"),
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());
930        long pointSize;
931        str.ToLong( &pointSize );
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
955void csCanvas::OnRightClick(double WXUNUSED(x), double WXUNUSED(y), int WXUNUSED(keys))
956{
957}
958
959// Initial point
960static double sg_initialX, sg_initialY;
961
962void csCanvas::OnDragLeft(bool WXUNUSED(draw), double x, double y, int WXUNUSED(keys))
963{
964    wxClientDC dc(this);
965    PrepareDC(dc);
966
967    dc.SetLogicalFunction(OGLRBLF);
968    DrawOutline(dc, sg_initialX, sg_initialY, x, y);
969}
970
971void csCanvas::OnBeginDragLeft(double x, double y, int WXUNUSED(keys))
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
984void csCanvas::OnEndDragLeft(double x, double y, int WXUNUSED(keys))
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
998    wxObjectList::compatibility_iterator node = GetDiagram()->GetShapeList()->GetFirst();
999    while (node)
1000    {
1001        wxShape *shape = (wxShape *)node->GetData();
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            {
1009                shape->Select(true, &dc);
1010                GetView()->SelectShape(shape, true);
1011            }
1012        }
1013        node = node->GetNext();
1014    }
1015}
1016
1017void csCanvas::OnDragRight(bool WXUNUSED(draw), double WXUNUSED(x), double WXUNUSED(y), int WXUNUSED(keys))
1018{
1019}
1020
1021void csCanvas::OnBeginDragRight(double WXUNUSED(x), double WXUNUSED(y), int WXUNUSED(keys))
1022{
1023}
1024
1025void csCanvas::OnEndDragRight(double WXUNUSED(x), double WXUNUSED(y), int WXUNUSED(keys))
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}
1039