]> git.saurik.com Git - wxWidgets.git/blame - contrib/samples/ogl/studio/shapes.cpp
Sample update - wxTE_AUTO_URL from Mart R. [patch 1126182]
[wxWidgets.git] / contrib / samples / ogl / studio / shapes.cpp
CommitLineData
1fc25a89
JS
1/////////////////////////////////////////////////////////////////////////////
2// Name: shapes.cpp
3// Purpose: Implements Studio shapes
4// Author: Julian Smart
5// Modified by:
6// Created: 12/07/98
7// RCS-ID: $Id$
8// Copyright: (c) Julian Smart
2ba06d5a 9// Licence: wxWindows licence
1fc25a89
JS
10/////////////////////////////////////////////////////////////////////////////
11
12#ifdef __GNUG__
13// #pragma implementation
14#endif
15
16// For compilers that support precompilation, includes "wx.h".
92a19c2e 17#include "wx/wxprec.h"
1fc25a89
JS
18
19#ifdef __BORLANDC__
20#pragma hdrstop
21#endif
22
23#ifndef WX_PRECOMP
24#include <wx/wx.h>
25#endif
26
27#if !wxUSE_DOC_VIEW_ARCHITECTURE
28#error You must set wxUSE_DOC_VIEW_ARCHITECTURE to 1 in wx_setup.h!
29#endif
30
7c9955d1
JS
31#include <wx/deprecated/setup.h>
32#include <wx/deprecated/wxexpr.h>
1fc25a89
JS
33
34#include "studio.h"
35#include "doc.h"
36#include "shapes.h"
37#include "view.h"
38#include <wx/ogl/basicp.h>
39#include <wx/ogl/linesp.h>
40#include "cspalette.h"
41#include "dialogs.h"
42
43#define csSTANDARD_SHAPE_WIDTH 100
44
45IMPLEMENT_CLASS(csDiagram, wxDiagram)
46
47csDiagram::~csDiagram()
48{
49 DeleteAllShapes();
50}
51
52void csDiagram::Redraw(wxDC& dc)
53{
54 wxDiagram::Redraw(dc);
55
56 // Draw line crossings
57 wxLineCrossings lineCrossings;
58 lineCrossings.FindCrossings(*this);
59 lineCrossings.DrawCrossings(*this, dc);
60}
61
62/*
63 * csEvtHandler: an event handler class for all shapes
64 */
65
66IMPLEMENT_DYNAMIC_CLASS(csEvtHandler, wxShapeEvtHandler)
67
68csEvtHandler::csEvtHandler(wxShapeEvtHandler *prev, wxShape *shape, const wxString& lab):
69 wxShapeEvtHandler(prev, shape)
70{
71 m_label = lab;
72}
73
74csEvtHandler::~csEvtHandler()
75{
76}
77
78// Copy any event handler data
79void csEvtHandler::CopyData(wxShapeEvtHandler& copy)
80{
81 wxShapeEvtHandler::CopyData(copy);
82
83 csEvtHandler& csCopy = (csEvtHandler&) copy;
84 csCopy.m_label = m_label;
85}
3454ecd5 86
1484b5cc 87void csEvtHandler::OnLeftClick(double WXUNUSED(x), double WXUNUSED(y), int keys, int WXUNUSED(attachment))
1fc25a89
JS
88{
89 wxClientDC dc(GetShape()->GetCanvas());
90 GetShape()->GetCanvas()->PrepareDC(dc);
91
92 csDiagramView* view = ((csCanvas*)GetShape()->GetCanvas())->GetView();
93 view->ReflectPointSize(GetShape()->GetFont()->GetPointSize());
94
95 if (GetShape()->IsKindOf(CLASSINFO(wxLineShape)))
96 view->ReflectArrowState((wxLineShape*) GetShape());
97
98 csEditorToolPalette *palette = wxGetApp().GetDiagramPalette();
99 if (palette->GetSelection() == PALETTE_TEXT_TOOL)
100 {
101 view->ReflectPointSize(GetShape()->GetFont()->GetPointSize());
102
103 EditProperties();
104#if 0
105 csLabelEditingDialog* dialog = new csLabelEditingDialog(GetShape()->GetCanvas()->GetParent());
106 dialog->SetShapeLabel(m_label);
107 if (dialog->ShowModal() == wxID_CANCEL)
108 {
109 dialog->Destroy();
110 return;
111 }
112
113 wxString newLabel = dialog->GetShapeLabel();
114 dialog->Destroy();
115
116 wxShape* newShape = GetShape()->CreateNewCopy();
117
118 csEvtHandler* handler = (csEvtHandler *)newShape->GetEventHandler();
119 handler->m_label = newLabel;
120
121 view->GetDocument()->GetCommandProcessor()->Submit(new csDiagramCommand("Edit label", (csDiagramDocument*) view->GetDocument(),
122 new csCommandState(ID_CS_EDIT_PROPERTIES, newShape, GetShape())));
123#endif
124 return;
125 }
126
127 if (keys == 0)
128 {
129 // If no shift key, then everything is deselected.
130 // If the shape was selected, deselect it and vice versa.
131 bool selected = GetShape()->Selected();
132
2ba06d5a 133 view->SelectAll(false);
1fc25a89
JS
134
135 selected = !selected;
136
137 GetShape()->Select(selected, &dc);
138 GetShape()->GetCanvas()->Redraw(dc); // Redraw because bits of objects will be missing
139
140 view->SelectShape(GetShape(), selected);
141 }
142 else if (keys & KEY_SHIFT)
143 {
144 if (GetShape()->Selected())
145 {
2ba06d5a
WS
146 GetShape()->Select(false, &dc);
147 view->SelectShape(GetShape(), false);
1fc25a89
JS
148 }
149 else
150 {
2ba06d5a
WS
151 GetShape()->Select(true, &dc);
152 view->SelectShape(GetShape(), true);
1fc25a89
JS
153 }
154 GetShape()->GetCanvas()->Redraw(dc); // Redraw because bits of objects will be missing
155 }
156 else if (keys & KEY_CTRL)
157 {
158 // Do something for CONTROL
159 }
160 else
161 {
d96cdd4a 162#if wxUSE_STATUSBAR
1fc25a89 163 ((wxFrame*)wxGetApp().GetTopWindow())->SetStatusText(m_label);
d96cdd4a 164#endif // wxUSE_STATUSBAR
1fc25a89
JS
165 }
166}
167
1484b5cc 168void csEvtHandler::OnRightClick(double x, double y, int WXUNUSED(keys), int WXUNUSED(attachment))
1fc25a89
JS
169{
170 // Have to convert back to physical coordinates from logical coordinates.
171
172 int viewStartX, viewStartY;
173 int unitX, unitY;
a059a1f2 174 GetShape()->GetCanvas()->GetViewStart(& viewStartX, & viewStartY);
1fc25a89
JS
175 GetShape()->GetCanvas()->GetScrollPixelsPerUnit(& unitX, & unitY);
176
177 int x1 = (int)(x * GetShape()->GetCanvas()->GetScaleX());
178 int y1 = (int)(y * GetShape()->GetCanvas()->GetScaleY());
179
180 int menuX = (int) (x1 - (viewStartX * unitX)) ;
181 int menuY = (int) (y1 - (viewStartY * unitY));
182
183 wxGetApp().GetShapeEditMenu()->SetClientData((char*) GetShape());
184 wxGetApp().GetShapeEditMenu()->Enable(ID_CS_ROTATE_CLOCKWISE, !GetShape()->IsKindOf(CLASSINFO(wxLineShape)));
185 wxGetApp().GetShapeEditMenu()->Enable(ID_CS_ROTATE_ANTICLOCKWISE, !GetShape()->IsKindOf(CLASSINFO(wxLineShape)));
186
187 GetShape()->GetCanvas()->PopupMenu(wxGetApp().GetShapeEditMenu(), menuX, menuY);
188}
189
190/*
191 * Implement connection of two shapes by right-dragging between them.
192 */
193
1484b5cc 194void csEvtHandler::OnBeginDragRight(double x, double y, int WXUNUSED(keys), int attachment)
1fc25a89
JS
195{
196 wxClientDC dc(GetShape()->GetCanvas());
197 GetShape()->GetCanvas()->PrepareDC(dc);
198
199 wxPen dottedPen(wxColour(0, 0, 0), 1, wxDOT);
200 dc.SetLogicalFunction(OGLRBLF);
201 dc.SetPen(dottedPen);
202 double xp, yp;
203 GetShape()->GetAttachmentPositionEdge(attachment, &xp, &yp);
8552e6f0 204 dc.DrawLine((wxCoord)xp, (wxCoord)yp, (wxCoord)x, (wxCoord)y);
1fc25a89
JS
205 GetShape()->GetCanvas()->CaptureMouse();
206}
207
1484b5cc 208void csEvtHandler::OnDragRight(bool WXUNUSED(draw), double x, double y, int WXUNUSED(keys), int attachment)
1fc25a89
JS
209{
210 wxClientDC dc(GetShape()->GetCanvas());
211 GetShape()->GetCanvas()->PrepareDC(dc);
212
213 wxPen dottedPen(wxColour(0, 0, 0), 1, wxDOT);
214 dc.SetLogicalFunction(OGLRBLF);
215 dc.SetPen(dottedPen);
216 double xp, yp;
217 GetShape()->GetAttachmentPositionEdge(attachment, &xp, &yp);
8552e6f0 218 dc.DrawLine((wxCoord)xp, (wxCoord)yp, (wxCoord)x, (wxCoord)y);
1fc25a89
JS
219}
220
1484b5cc 221void csEvtHandler::OnEndDragRight(double x, double y, int WXUNUSED(keys), int attachment)
1fc25a89
JS
222{
223 GetShape()->GetCanvas()->ReleaseMouse();
224 csCanvas *canvas = (csCanvas *)GetShape()->GetCanvas();
225
226 // Check if we're on an object
227 int new_attachment;
228 wxShape *otherShape = canvas->FindFirstSensitiveShape(x, y, &new_attachment, OP_DRAG_RIGHT);
3454ecd5 229
1fc25a89
JS
230 if (otherShape && !otherShape->IsKindOf(CLASSINFO(wxLineShape)))
231 {
232 wxLineShape* theShape = new csLineShape;
233
234 theShape->AssignNewIds();
1484b5cc 235 theShape->SetEventHandler(new csEvtHandler(theShape, theShape, wxEmptyString));
1fc25a89
JS
236 theShape->SetPen(wxBLACK_PEN);
237 theShape->SetBrush(wxRED_BRUSH);
238
239 wxToolBar* toolbar = wxGetApp().GetDiagramToolBar();
240 bool haveArrow = toolbar->GetToolState(DIAGRAM_TOOLBAR_LINE_ARROW);
241
242 wxLineShape *lineShape = (wxLineShape *)theShape;
243
244 // Yes, you can have more than 2 control points, in which case
245 // it becomes a multi-segment line.
246 lineShape->MakeLineControlPoints(2);
247
248 if (haveArrow)
1484b5cc 249 lineShape->AddArrow(ARROW_ARROW, ARROW_POSITION_MIDDLE, 10.0, 0.0, _T("Normal arrowhead"));
1fc25a89
JS
250
251 lineShape->SetFrom(GetShape());
252 lineShape->SetTo(otherShape);
253 lineShape->SetAttachments(attachment, new_attachment);
254
255 canvas->GetView()->GetDocument()->GetCommandProcessor()->Submit(
1484b5cc 256 new csDiagramCommand(_T("Line"), (csDiagramDocument *)canvas->GetView()->GetDocument(),
1fc25a89
JS
257 new csCommandState(ID_CS_ADD_LINE, lineShape, NULL)));
258 }
259}
260
261static double g_DragOffsetX = 0.0;
262static double g_DragOffsetY = 0.0;
263static double g_DragStartX = 0.0;
264static double g_DragStartY = 0.0;
265
266void csEvtHandler::OnDragLeft(bool draw, double x, double y, int keys, int attachment)
267{
268 if ((GetShape()->GetSensitivityFilter() & OP_DRAG_LEFT) != OP_DRAG_LEFT)
269 {
270 attachment = 0;
271 double dist;
272 if (GetShape()->GetParent())
273 {
274 GetShape()->GetParent()->HitTest(x, y, &attachment, &dist);
275 GetShape()->GetParent()->GetEventHandler()->OnDragLeft(draw, x, y, keys, attachment);
276 }
277 return;
278 }
279
280 wxClientDC dc(GetShape()->GetCanvas());
281 GetShape()->GetCanvas()->PrepareDC(dc);
282
283 dc.SetLogicalFunction(OGLRBLF);
284
285 wxPen dottedPen(wxColour(0, 0, 0), 1, wxDOT);
286 dc.SetPen(dottedPen);
287 dc.SetBrush(* wxTRANSPARENT_BRUSH);
288
289 double xx, yy;
290 xx = x + g_DragOffsetX;
291 yy = y + g_DragOffsetY;
292
293 GetShape()->GetCanvas()->Snap(&xx, &yy);
294
295 double offsetX = xx - g_DragStartX;
296 double offsetY = yy - g_DragStartY;
297
298// m_xpos = xx; m_ypos = yy;
299 double w, h;
300 GetShape()->GetBoundingBoxMax(&w, &h);
301 GetShape()->GetEventHandler()->OnDrawOutline(dc, xx, yy, w, h);
302
303 // Draw bounding box for other selected shapes
36ca94a2 304 wxObjectList::compatibility_iterator node = GetShape()->GetCanvas()->GetDiagram()->GetShapeList()->GetFirst();
1fc25a89
JS
305 while (node)
306 {
8552e6f0 307 wxShape* shape = (wxShape*) node->GetData();
1fc25a89
JS
308 if (shape->Selected() && !shape->IsKindOf(CLASSINFO(wxLineShape)) && (shape != GetShape()))
309 {
310 shape->GetBoundingBoxMax(&w, &h);
311 shape->OnDrawOutline(dc, shape->GetX() + offsetX, shape->GetY() + offsetY, w, h);
312 }
8552e6f0 313 node = node->GetNext();
1fc25a89
JS
314 }
315}
316
317void csEvtHandler::OnBeginDragLeft(double x, double y, int keys, int attachment)
318{
319 if ((GetShape()->GetSensitivityFilter() & OP_DRAG_LEFT) != OP_DRAG_LEFT)
320 {
321 attachment = 0;
322 double dist;
323 if (GetShape()->GetParent())
324 {
325 GetShape()->GetParent()->HitTest(x, y, &attachment, &dist);
326 GetShape()->GetParent()->GetEventHandler()->OnBeginDragLeft(x, y, keys, attachment);
327 }
328 return;
329 }
330
331 wxClientDC dc(GetShape()->GetCanvas());
332 GetShape()->GetCanvas()->PrepareDC(dc);
333
334 // New policy: don't erase shape until end of drag.
335// Erase(dc);
336
337 g_DragOffsetX = GetShape()->GetX() - x;
338 g_DragOffsetY = GetShape()->GetY() - y;
339
340 double xx, yy;
341 xx = x + g_DragOffsetX;
342 yy = y + g_DragOffsetY;
343
344 GetShape()->GetCanvas()->Snap(&xx, &yy);
345
346 g_DragStartX = GetShape()->GetX();
347 g_DragStartY = GetShape()->GetY();
348
349 double offsetX = xx - g_DragStartX;
350 double offsetY = yy - g_DragStartY;
351
352 dc.SetLogicalFunction(OGLRBLF);
353
354 wxPen dottedPen(wxColour(0, 0, 0), 1, wxDOT);
355 dc.SetPen(dottedPen);
356 dc.SetBrush((* wxTRANSPARENT_BRUSH));
357
358 double w, h;
359 GetShape()->GetBoundingBoxMax(&w, &h);
360 GetShape()->GetEventHandler()->OnDrawOutline(dc, xx, yy, w, h);
361
362 // Draw bounding box for other selected shapes
36ca94a2 363 wxObjectList::compatibility_iterator node = GetShape()->GetCanvas()->GetDiagram()->GetShapeList()->GetFirst();
1fc25a89
JS
364 while (node)
365 {
8552e6f0 366 wxShape* shape = (wxShape*) node->GetData();
1fc25a89
JS
367 if (shape->Selected() && !shape->IsKindOf(CLASSINFO(wxLineShape)) && (shape != GetShape()))
368 {
369 shape->GetBoundingBoxMax(&w, &h);
370 shape->OnDrawOutline(dc, shape->GetX() + offsetX, shape->GetY() + offsetY, w, h);
371 }
8552e6f0 372 node = node->GetNext();
1fc25a89
JS
373 }
374
375 GetShape()->GetCanvas()->CaptureMouse();
376}
377
378
379void csEvtHandler::OnEndDragLeft(double x, double y, int keys, int attachment)
380{
381 csCanvas *canvas = (csCanvas *)GetShape()->GetCanvas();
382
383 canvas->ReleaseMouse();
384 if ((GetShape()->GetSensitivityFilter() & OP_DRAG_LEFT) != OP_DRAG_LEFT)
385 {
386 attachment = 0;
387 double dist;
388 if (GetShape()->GetParent())
389 {
390 GetShape()->GetParent()->HitTest(x, y, &attachment, &dist);
391 GetShape()->GetParent()->GetEventHandler()->OnEndDragLeft(x, y, keys, attachment);
392 }
393 return;
394 }
395
396 wxClientDC dc(canvas);
397 canvas->PrepareDC(dc);
398
399 dc.SetLogicalFunction(wxCOPY);
400
401 double xx = x + g_DragOffsetX;
402 double yy = y + g_DragOffsetY;
403
404 canvas->Snap(&xx, &yy);
405
406 double offsetX = xx - g_DragStartX;
407 double offsetY = yy - g_DragStartY;
408
409 wxShape* newShape = GetShape()->CreateNewCopy();
410
411 newShape->SetX(xx);
412 newShape->SetY(yy);
413
1484b5cc 414 csDiagramCommand* cmd = new csDiagramCommand(_T("Move"), (csDiagramDocument*)canvas->GetView()->GetDocument(),
1fc25a89
JS
415 new csCommandState(ID_CS_MOVE, newShape, GetShape()));
416
417 // Move line points
36ca94a2 418 wxObjectList::compatibility_iterator node = GetShape()->GetCanvas()->GetDiagram()->GetShapeList()->GetFirst();
1fc25a89
JS
419 while (node)
420 {
8552e6f0 421 wxShape* shape = (wxShape*) node->GetData();
1fc25a89
JS
422 // Only move the line point(s) if both ends move too
423 if (shape->IsKindOf(CLASSINFO(wxLineShape)) &&
424 ((wxLineShape*)shape)->GetTo()->Selected() && ((wxLineShape*)shape)->GetFrom()->Selected())
425 {
426 wxLineShape* lineShape = (wxLineShape*) shape;
427
8552e6f0 428 if (lineShape->GetLineControlPoints()->GetCount() > 2)
1fc25a89
JS
429 {
430 wxLineShape* newLineShape = (wxLineShape*) lineShape->CreateNewCopy();
431
36ca94a2 432 wxObjectList::compatibility_iterator node1 = newLineShape->GetLineControlPoints()->GetFirst();
1fc25a89
JS
433 while (node1)
434 {
8552e6f0 435 wxRealPoint *point = (wxRealPoint *)node1->GetData();
1fc25a89
JS
436 point->x += offsetX;
437 point->y += offsetY;
8552e6f0 438 node1 = node1->GetNext();
1fc25a89
JS
439 }
440 cmd->AddState(new csCommandState(ID_CS_MOVE_LINE_POINT, newLineShape, lineShape));
441 lineShape->Erase(dc);
442 }
443 }
8552e6f0 444 node = node->GetNext();
1fc25a89
JS
445 }
446
447 // Add other selected node shapes, if any
8552e6f0 448 node = GetShape()->GetCanvas()->GetDiagram()->GetShapeList()->GetFirst();
1fc25a89
JS
449 while (node)
450 {
8552e6f0 451 wxShape* shape = (wxShape*) node->GetData();
1fc25a89
JS
452 if (shape->Selected() && !shape->IsKindOf(CLASSINFO(wxLineShape)) && (shape != GetShape()))
453 {
454 wxShape* newShape2 = shape->CreateNewCopy();
455 newShape2->SetX(shape->GetX() + offsetX);
456 newShape2->SetY(shape->GetY() + offsetY);
457 cmd->AddState(new csCommandState(ID_CS_MOVE, newShape2, shape));
458 }
8552e6f0 459 node = node->GetNext();
1fc25a89
JS
460 }
461
462 canvas->GetView()->GetDocument()->GetCommandProcessor()->Submit(cmd);
463}
464
465void csEvtHandler::OnSizingEndDragLeft(wxControlPoint* pt, double x, double y, int keys, int attachment)
466{
467 wxShape* shape = GetShape();
468 csCanvas *canvas = (csCanvas *)GetShape()->GetCanvas();
469
470 if (shape->IsKindOf(CLASSINFO(wxLineShape)))
471 {
472 // TODO: Do/Undo support for line operations
473 ((wxLineShape*)shape)->wxLineShape::OnSizingEndDragLeft(pt, x, y, keys, attachment);
474#if 0
475 wxLineShape* lineShape = (wxLineShape*) shape;
476
477 wxLineControlPoint* lpt = (wxLineControlPoint*) pt;
478
479 wxClientDC dc(canvas);
480 canvas->PrepareDC(dc);
481
2ba06d5a 482 shape->SetDisableLabel(false);
1fc25a89
JS
483
484 if (lpt->m_type == CONTROL_POINT_LINE)
485 {
486 canvas->Snap(&x, &y);
487
488 dc.SetLogicalFunction(wxCOPY);
489 lpt->SetX(x); lpt->SetY(y);
490 lpt->m_point->x = x; lpt->m_point->y = y;
491
492 this->OnMoveLink(dc);
493 }
494 if (lpt->m_type == CONTROL_POINT_ENDPOINT_FROM)
495 {
496 if (lpt->m_oldCursor)
497 canvas->SetCursor(lpt->m_oldCursor);
498 lineShape->Erase(dc);
499
500 lpt->SetX(x); lpt->SetY(y);
501
502 if (lineShape->GetFrom())
503 {
504 lineShape->GetFrom()->MoveLineToNewAttachment(dc, lineShape, x, y);
505 }
506 }
507 if (lpt->m_type == CONTROL_POINT_ENDPOINT_TO)
508 {
509 if (lpt->m_oldCursor)
510 canvas->SetCursor(lpt->m_oldCursor);
511
512 lpt->SetX(x); lpt->SetY(y);
513
514 if (lineShape->GetTo())
515 {
516 lineShape->GetTo()->MoveLineToNewAttachment(dc, lineShape, x, y);
517 }
518 }
519#endif
520 return;
521 }
522
523 wxClientDC dc(canvas);
524 canvas->PrepareDC(dc);
525
526 canvas->ReleaseMouse();
527 dc.SetLogicalFunction(wxCOPY);
528
529// shape->Erase(dc);
530/*
531 shape->Recompute();
532 shape->ResetControlPoints();
533 if (!pt->m_eraseObject)
2ba06d5a 534 shape->Show(false);
1fc25a89
JS
535*/
536
537 wxShape* newShape = shape->CreateNewCopy();
538
539 if (newShape->IsKindOf(CLASSINFO(wxPolygonShape)))
540 {
541 wxPolygonControlPoint* ppt = (wxPolygonControlPoint*) pt;
542 newShape->SetSize(ppt->GetNewSize().x, ppt->GetNewSize().y);
543
544 ((wxPolygonShape *)newShape)->CalculateBoundingBox();
545 ((wxPolygonShape *)newShape)->CalculatePolygonCentre();
546 newShape->ResetControlPoints();
547 }
548 else
549 {
550 newShape->SetSize(pt->sm_controlPointDragEndWidth, pt->sm_controlPointDragEndHeight);
551 if (shape->GetCentreResize())
552 {
553 // Old position is fine
554 }
555 else
556 {
557 newShape->SetX(pt->sm_controlPointDragPosX);
558 newShape->SetY(pt->sm_controlPointDragPosY);
559 }
560 }
561
1484b5cc 562 csDiagramCommand* cmd = new csDiagramCommand(_T("Size"), (csDiagramDocument*)canvas->GetView()->GetDocument(),
1fc25a89
JS
563 new csCommandState(ID_CS_SIZE, newShape, shape));
564
565 canvas->GetView()->GetDocument()->GetCommandProcessor()->Submit(cmd);
566
567}
568
1484b5cc 569void csEvtHandler::OnEndSize(double WXUNUSED(x), double WXUNUSED(y))
1fc25a89
JS
570{
571 wxClientDC dc(GetShape()->GetCanvas());
572 GetShape()->GetCanvas()->PrepareDC(dc);
573
574 GetShape()->FormatText(dc, m_label);
575}
576
577void csEvtHandler::OnChangeAttachment(int attachment, wxLineShape* line, wxList& ordering)
578{
579 csCanvas *canvas = (csCanvas *)GetShape()->GetCanvas();
580
581 // We actually submit two different states: one to change the ordering, and another
582 // to change the attachment for the line.
583 // Problem. If we refresh after the attachment change, we'll get a flicker.
584 // We really want to do both in a oner.
585
1484b5cc 586 csDiagramCommand* cmd = new csDiagramCommand(_T("Change attachment"), (csDiagramDocument*)canvas->GetView()->GetDocument());
1fc25a89
JS
587
588 wxLineShape* newLine = (wxLineShape*) line->CreateNewCopy();
589 if (line->GetTo() == GetShape())
590 newLine->SetAttachmentTo(attachment);
591 else
592 newLine->SetAttachmentFrom(attachment);
593
594 cmd->AddState(new csCommandState(ID_CS_CHANGE_LINE_ATTACHMENT, newLine, line));
595
596 // Change ordering
597 wxShape* newShape = GetShape()->CreateNewCopy();
598 newShape->ApplyAttachmentOrdering(ordering);
599
600 cmd->AddState(new csCommandState(ID_CS_CHANGE_LINE_ORDERING, newShape, GetShape()));
601
602 canvas->GetView()->GetDocument()->GetCommandProcessor()->Submit(cmd);
603}
604
1484b5cc 605void csEvtHandler::OnLeftDoubleClick(double WXUNUSED(x), double WXUNUSED(y), int WXUNUSED(keys), int WXUNUSED(attachment))
1fc25a89
JS
606{
607 EditProperties();
608}
609
610// Popup up a property dialog
611bool csEvtHandler::EditProperties()
612{
613 wxShape* shape = GetShape();
614
615 // For now, no line property editing
616 if (shape->IsKindOf(CLASSINFO(wxLineShape)))
2ba06d5a 617 return false;
1fc25a89
JS
618
619 csDiagramView* view = ((csCanvas*)shape->GetCanvas())->GetView();
620
621 wxPanel* attributeDialog;
622 wxString attributeDialogName;
623 wxString title;
624
625 if (shape->IsKindOf(CLASSINFO(csThinRectangleShape)))
626 {
627 attributeDialog = new csThinRectangleDialog;
1484b5cc
VS
628 attributeDialogName = _T("thin_rectangle");
629 title = _T("Thin Rectangle Properties");
1fc25a89
JS
630 }
631 else if (shape->IsKindOf(CLASSINFO(csWideRectangleShape)))
632 {
633 attributeDialog = new csWideRectangleDialog;
1484b5cc
VS
634 attributeDialogName = _T("wide_rectangle");
635 title = _T("Wide Rectangle Properties");
1fc25a89
JS
636 }
637 else if (shape->IsKindOf(CLASSINFO(csTriangleShape)))
638 {
639 attributeDialog = new csTriangleDialog;
1484b5cc
VS
640 attributeDialogName = _T("triangle");
641 title = _T("Triangle Properties");
1fc25a89
JS
642 }
643 else if (shape->IsKindOf(CLASSINFO(csSemiCircleShape)))
644 {
645 attributeDialog = new csSemiCircleDialog;
1484b5cc
VS
646 attributeDialogName = _T("semi_circle");
647 title = _T("Semicircle Properties");
1fc25a89
JS
648 }
649 else if (shape->IsKindOf(CLASSINFO(csCircleShape)))
650 {
651 attributeDialog = new csCircleDialog;
1484b5cc
VS
652 attributeDialogName = _T("circle");
653 title = _T("Circle Properties");
1fc25a89
JS
654 }
655 else if (shape->IsKindOf(CLASSINFO(csCircleShadowShape)))
656 {
657 attributeDialog = new csCircleShadowDialog;
1484b5cc
VS
658 attributeDialogName = _T("circle_shadow");
659 title = _T("Circle Shadow Properties");
1fc25a89
JS
660 }
661 else if (shape->IsKindOf(CLASSINFO(csTextBoxShape)))
662 {
663 attributeDialog = new csTextBoxDialog;
1484b5cc
VS
664 attributeDialogName = _T("text_box");
665 title = _T("Text Box Properties");
1fc25a89
JS
666 }
667 else if (shape->IsKindOf(CLASSINFO(csGroupShape)))
668 {
669 attributeDialog = new csGroupDialog;
1484b5cc
VS
670 attributeDialogName = _T("group");
671 title = _T("Group Properties");
1fc25a89
JS
672 }
673 else if (shape->IsKindOf(CLASSINFO(csOctagonShape)))
674 {
675 attributeDialog = new csOctagonDialog;
1484b5cc
VS
676 attributeDialogName = _T("octagon");
677 title = _T("Octagon Properties");
1fc25a89
JS
678 }
679 else
680 {
1484b5cc 681 wxMessageBox(_T("Unrecognised shape."), _T("Studio"), wxICON_EXCLAMATION);
2ba06d5a 682 return false;
1fc25a89
JS
683 }
684
685 csShapePropertiesDialog* dialog = new csShapePropertiesDialog(shape->GetCanvas()->GetParent(), title, attributeDialog, attributeDialogName);
686 dialog->GetGeneralPropertiesDialog()->SetShapeLabel(m_label);
687 if (dialog->ShowModal() == wxID_CANCEL)
688 {
689 dialog->Destroy();
2ba06d5a 690 return false;
1fc25a89
JS
691 }
692
693 wxString newLabel = dialog->GetGeneralPropertiesDialog()->GetShapeLabel();
694 dialog->Destroy();
695
696 wxShape* newShape = shape->CreateNewCopy();
697
698 csEvtHandler* handler2 = (csEvtHandler *)newShape->GetEventHandler();
699 handler2->m_label = newLabel;
700
1484b5cc 701 view->GetDocument()->GetCommandProcessor()->Submit(new csDiagramCommand(_T("Edit properties"), (csDiagramDocument*) view->GetDocument(),
1fc25a89
JS
702 new csCommandState(ID_CS_EDIT_PROPERTIES, newShape, shape)));
703
2ba06d5a 704 return true;
1fc25a89
JS
705}
706
707/*
708 * Diagram
709 */
3454ecd5 710
1fc25a89
JS
711bool csDiagram::OnShapeSave(wxExprDatabase& db, wxShape& shape, wxExpr& expr)
712{
713 wxDiagram::OnShapeSave(db, shape, expr);
714 csEvtHandler *handler = (csEvtHandler *)shape.GetEventHandler();
1484b5cc 715 expr.AddAttributeValueString(_T("label"), handler->m_label);
2ba06d5a 716 return true;
1fc25a89
JS
717}
718
719bool csDiagram::OnShapeLoad(wxExprDatabase& db, wxShape& shape, wxExpr& expr)
720{
721 wxDiagram::OnShapeLoad(db, shape, expr);
1484b5cc
VS
722 wxString label = wxEmptyString;
723 expr.GetAttributeValue(_T("label"), label);
1fc25a89
JS
724 csEvtHandler *handler = new csEvtHandler(&shape, &shape, label);
725 shape.SetEventHandler(handler);
3454ecd5 726
2ba06d5a 727 return true;
1fc25a89
JS
728}
729
730IMPLEMENT_DYNAMIC_CLASS(csThinRectangleShape, wxDrawnShape)
731
732csThinRectangleShape::csThinRectangleShape()
733{
734 SetDrawnPen(wxBLACK_PEN);
735 wxBrush* brush = wxTheBrushList->FindOrCreateBrush(wxColour(220, 220, 220), wxSOLID);
736 SetDrawnBrush(brush);
737
738 double w = csSTANDARD_SHAPE_WIDTH/2;
739 double h = csSTANDARD_SHAPE_WIDTH;
740
8552e6f0 741 DrawRectangle(wxRect((int)(- w/2), (int)(- h/2), (int)(w), (int)(h)));
1fc25a89
JS
742 CalculateSize();
743
744 SetAttachmentMode(ATTACHMENT_MODE_BRANCHING);
745 SetBranchStyle(BRANCHING_ATTACHMENT_NORMAL|BRANCHING_ATTACHMENT_BLOB);
2ba06d5a 746 SetCentreResize(false);
1fc25a89
JS
747}
748
749IMPLEMENT_DYNAMIC_CLASS(csWideRectangleShape, wxDrawnShape)
750
751csWideRectangleShape::csWideRectangleShape()
752{
753 SetDrawnPen(wxBLACK_PEN);
754 wxBrush* brush = wxTheBrushList->FindOrCreateBrush(wxColour(220, 220, 220), wxSOLID);
755 SetDrawnBrush(brush);
756
757 double w = csSTANDARD_SHAPE_WIDTH;
758 double h = w/2.0;
759
8552e6f0 760 DrawRoundedRectangle(wxRect((int)(- w/2), (int)(- h/2), (int)(w), (int)(h)), -0.3);
1fc25a89
JS
761 CalculateSize();
762
763 SetAttachmentMode(ATTACHMENT_MODE_BRANCHING);
764 SetBranchStyle(BRANCHING_ATTACHMENT_NORMAL|BRANCHING_ATTACHMENT_BLOB);
2ba06d5a 765 SetCentreResize(false);
1fc25a89
JS
766}
767
768IMPLEMENT_DYNAMIC_CLASS(csTriangleShape, wxDrawnShape)
769
770csTriangleShape::csTriangleShape()
771{
772 SetDrawnPen(wxBLACK_PEN);
773 wxBrush* brush = wxTheBrushList->FindOrCreateBrush(wxColour(220, 220, 220), wxSOLID);
774 SetDrawnBrush(brush);
775
776 double w = csSTANDARD_SHAPE_WIDTH;
777 double h = (csSTANDARD_SHAPE_WIDTH*2.0)/3.0;
778
779 // Triangle, from top vertex
780 wxPoint* points = new wxPoint[3];
781
782
8552e6f0
MB
783 points[0] = wxPoint( 0 , (int)(- h / 2) );
784 points[1] = wxPoint( (int)(w / 2) , (int)(h / 2) );
785 points[2] = wxPoint( (int)(-w / 2), (int)(h / 2) );
1fc25a89
JS
786
787 DrawPolygon(3, points, oglMETAFLAGS_OUTLINE);
788
789 delete[] points;
790
791 // Add another triangle at the top for the black bit
792 SetDrawnBrush(wxBLACK_BRUSH);
793
794 points = new wxPoint[3];
795
796 // Calculate where the new points will be, using the proportions
797 // of the triangle.
798 double h1 = 8; // Height of little triangle.
799
800 /*
801 Formula: ((w/2) / h) = w1 / h1
802 w1 = ((w/2) / h) * h1;
803 */
804 double ratio = ((w/2.0) / h) ;
805 double w1 = ratio * h1;
806
807 points[0] = wxPoint(0 , (int) (- h / 2 ));
808 points[1] = wxPoint( (int) w1, (int) (- h / 2 + h1));
809 points[2] = wxPoint( (int) -w1, (int) (- h / 2 + h1));
810
811 DrawPolygon(3, points);
812
813 delete[] points;
814
815 CalculateSize();
816
817 SetAttachmentMode(ATTACHMENT_MODE_BRANCHING);
818 SetBranchStyle(BRANCHING_ATTACHMENT_NORMAL|BRANCHING_ATTACHMENT_BLOB);
2ba06d5a 819 SetCentreResize(false);
1fc25a89
JS
820}
821
822IMPLEMENT_DYNAMIC_CLASS(csSemiCircleShape, wxDrawnShape)
823
824csSemiCircleShape::csSemiCircleShape()
825{
826 // Zero degrees
827 DrawAtAngle(oglDRAWN_ANGLE_0);
828
829 double w = csSTANDARD_SHAPE_WIDTH;
830 double h = w/2.0;
831
832 SetDrawnPen(wxTRANSPARENT_PEN);
833 SetDrawnBrush(wxTRANSPARENT_BRUSH);
834
835 // Draw a dummy rectangle that will be used for calculating the
836 // bounding box, since we can't calculate the bounding box for
837 // an arbitrary arc (not implemented)
838
8552e6f0 839 DrawRectangle(wxRect((int)(-w/2.0), (int)(-h/2.0), (int)(w), (int)(h)));
1fc25a89
JS
840
841 SetDrawnPen(wxBLACK_PEN);
842 wxBrush* brush = wxTheBrushList->FindOrCreateBrush(wxColour(220, 220, 220), wxSOLID);
843 SetDrawnBrush(brush);
844
8552e6f0
MB
845 DrawEllipticArc(wxRect((int)(-w/2), (int)(-h/2), (int)(w), (int)(2*h)), 0.0, 180.0);
846 DrawLine(wxPoint((int)(-w/2), (int)(h/2)), wxPoint((int)(w/2), (int)(h/2)));
1fc25a89
JS
847
848 CalculateSize();
849
850 /// 90 degrees
851
852 w = csSTANDARD_SHAPE_WIDTH/2;
853 h = csSTANDARD_SHAPE_WIDTH;
854
855 DrawAtAngle(oglDRAWN_ANGLE_90);
856
857 SetDrawnPen(wxTRANSPARENT_PEN);
858 SetDrawnBrush(wxTRANSPARENT_BRUSH);
859
8552e6f0 860 DrawRectangle(wxRect((int)(-w/2), (int)(-h/2), (int)(w), (int)(h)));
1fc25a89
JS
861
862 SetDrawnPen(wxBLACK_PEN);
863 SetDrawnBrush(brush);
864
8552e6f0
MB
865 DrawEllipticArc(wxRect((int)(-w/2 - w), (int)(-h/2), (int)(2*w), (int)(h)), 270.0, 90.0);
866 DrawLine(wxPoint((int)(-w/2), (int)(-h/2)), wxPoint((int)(-w/2), (int)(h/2)));
1fc25a89
JS
867
868 CalculateSize();
869
870 /// 180 degrees
871
872 DrawAtAngle(oglDRAWN_ANGLE_180);
873
874 w = csSTANDARD_SHAPE_WIDTH;
875 h = csSTANDARD_SHAPE_WIDTH/2;
876
877 SetDrawnPen(wxTRANSPARENT_PEN);
878 SetDrawnBrush(wxTRANSPARENT_BRUSH);
879
8552e6f0 880 DrawRectangle(wxRect((int)(-w/2), (int)(-h/2), (int)(w), (int)(h)));
1fc25a89
JS
881
882 SetDrawnPen(wxBLACK_PEN);
883 SetDrawnBrush(brush);
884
8552e6f0
MB
885 DrawEllipticArc(wxRect((int)(-w/2), (int)(-h/2 - h), (int)(w), (int)(2*h)), 180.0, 0.0);
886 DrawLine(wxPoint((int)(-w/2), (int)(-h/2)), wxPoint((int)(w/2), (int)(-h/2)));
1fc25a89
JS
887
888 CalculateSize();
889
890 /// 270 degrees
891
892 DrawAtAngle(oglDRAWN_ANGLE_270);
893
894 w = csSTANDARD_SHAPE_WIDTH/2;
895 h = csSTANDARD_SHAPE_WIDTH;
896
897 SetDrawnPen(wxTRANSPARENT_PEN);
898 SetDrawnBrush(wxTRANSPARENT_BRUSH);
899
8552e6f0 900 DrawRectangle(wxRect((int)(-w/2), (int)(-h/2), (int)(w), (int)(h)));
1fc25a89
JS
901
902 SetDrawnPen(wxBLACK_PEN);
903 SetDrawnBrush(brush);
904
8552e6f0
MB
905 DrawEllipticArc(wxRect((int)(-w/2), (int)(-h/2), (int)(2*w), (int)(h)), 90.0, 270.0);
906 DrawLine(wxPoint((int)(w/2),(int)(-h/2)), wxPoint((int)(w/2), (int)(h/2)));
1fc25a89
JS
907
908 CalculateSize();
909
910 // Reset to zero
911 DrawAtAngle(oglDRAWN_ANGLE_0);
912 CalculateSize();
913
914 SetAttachmentMode(ATTACHMENT_MODE_BRANCHING);
915 SetBranchStyle(BRANCHING_ATTACHMENT_NORMAL|BRANCHING_ATTACHMENT_BLOB);
2ba06d5a 916 SetCentreResize(false);
1fc25a89
JS
917}
918
919IMPLEMENT_DYNAMIC_CLASS(csCircleShape, wxCircleShape)
920
921csCircleShape::csCircleShape()
922{
923 SetPen(wxBLACK_PEN);
924 wxBrush* brush = wxTheBrushList->FindOrCreateBrush(wxColour(220, 220, 220), wxSOLID);
925 SetBrush(brush);
926
927 SetSize(csSTANDARD_SHAPE_WIDTH*0.6, csSTANDARD_SHAPE_WIDTH*0.6);
928
929 SetAttachmentMode(ATTACHMENT_MODE_BRANCHING);
930 SetBranchStyle(BRANCHING_ATTACHMENT_NORMAL|BRANCHING_ATTACHMENT_BLOB);
2ba06d5a 931 SetCentreResize(false);
1fc25a89
JS
932}
933
934IMPLEMENT_DYNAMIC_CLASS(csCircleShadowShape, wxCircleShape)
935
936csCircleShadowShape::csCircleShadowShape()
937{
938 SetPen(wxBLACK_PEN);
939 wxBrush* brush = wxTheBrushList->FindOrCreateBrush(wxColour(220, 220, 220), wxSOLID);
940 SetBrush(brush);
941
942 SetSize(csSTANDARD_SHAPE_WIDTH*0.6, csSTANDARD_SHAPE_WIDTH*0.6);
943
944 SetAttachmentMode(ATTACHMENT_MODE_BRANCHING);
945 SetBranchStyle(BRANCHING_ATTACHMENT_NORMAL|BRANCHING_ATTACHMENT_BLOB);
2ba06d5a 946 SetCentreResize(false);
1fc25a89
JS
947 SetShadowMode(SHADOW_RIGHT);
948}
949
950IMPLEMENT_DYNAMIC_CLASS(csOctagonShape, wxPolygonShape)
951
952csOctagonShape::csOctagonShape()
953{
954 SetPen(wxBLACK_PEN);
955 SetBrush(wxTheBrushList->FindOrCreateBrush(wxColour(220, 220, 220), wxSOLID));
956
957 double w = csSTANDARD_SHAPE_WIDTH*0.5;
958 double h = csSTANDARD_SHAPE_WIDTH*0.5;
959
960 double prop = h/3.0;
961
962 wxList* points = new wxList;
963 points->Append((wxObject*) new wxRealPoint(-w/2.0 + prop, -h/2.0));
964 points->Append((wxObject*) new wxRealPoint(w/2.0 - prop, -h/2.0));
965 points->Append((wxObject*) new wxRealPoint(w/2.0, -h/2.0 + prop));
966 points->Append((wxObject*) new wxRealPoint(w/2.0, h/2.0 - prop));
967 points->Append((wxObject*) new wxRealPoint(w/2.0 - prop, h/2.0));
968 points->Append((wxObject*) new wxRealPoint(-w/2.0 + prop, h/2.0));
969 points->Append((wxObject*) new wxRealPoint(-w/2.0, h/2.0 - prop));
970 points->Append((wxObject*) new wxRealPoint(-w/2.0, -h/2.0 + prop));
971
972 Create(points);
973
974 SetAttachmentMode(ATTACHMENT_MODE_BRANCHING);
975 SetBranchStyle(BRANCHING_ATTACHMENT_NORMAL|BRANCHING_ATTACHMENT_BLOB);
2ba06d5a 976 SetCentreResize(false);
1fc25a89
JS
977}
978
979// This is a transparent shape for drawing around other shapes.
980IMPLEMENT_DYNAMIC_CLASS(csGroupShape, wxRectangleShape)
981
982csGroupShape::csGroupShape()
983{
1484b5cc 984 SetPen(wxThePenList->FindOrCreatePen(_T("BLACK"), 1, wxDOT));
1fc25a89
JS
985 SetBrush(wxTRANSPARENT_BRUSH);
986
987 SetSize(csSTANDARD_SHAPE_WIDTH, csSTANDARD_SHAPE_WIDTH);
2ba06d5a 988 SetCentreResize(false);
1fc25a89
JS
989}
990
991void csGroupShape::OnDraw(wxDC& dc)
992{
993 wxRectangleShape::OnDraw(dc);
994}
995
996// Must modify the hit-test so it doesn't obscure shapes that are inside.
997bool csGroupShape::HitTest(double x, double y, int* attachment, double* distance)
998{
999 *attachment = 0;
1000 *distance = 0.0;
1001
1002 double width = 0.0, height = 0.0;
1003 GetBoundingBoxMin(&width, &height);
1004
1005 double x1 = GetX() - (width/2.0);
1006 double y1 = GetY() - (height/2.0);
1007 double x2 = GetX() + (width/2.0);
1008 double y2 = GetY() + (height/2.0);
1009
1010 double edgeTolerance = 4.0;
1011
1012 // Test each edge in turn
1013
1014 // Top/bottom edges
1015 if (x >= x1 && x <= x2)
1016 {
1017 if ((y >= y1 - edgeTolerance) && (y <= y1 + edgeTolerance))
2ba06d5a 1018 return true;
1fc25a89 1019 if ((y <= y2 + edgeTolerance) && (y >= y2 - edgeTolerance))
2ba06d5a 1020 return true;
1fc25a89
JS
1021 }
1022 // Left/right edges
1023 if (y >= y1 && y <= y2)
1024 {
1025 if ((x >= x1 - edgeTolerance) && (x <= x1 + edgeTolerance))
2ba06d5a 1026 return true;
1fc25a89 1027 if ((x <= x2 + edgeTolerance) && (x >= x2 - edgeTolerance))
2ba06d5a 1028 return true;
1fc25a89
JS
1029 }
1030
2ba06d5a 1031 return false;
1fc25a89
JS
1032}
1033
1034IMPLEMENT_DYNAMIC_CLASS(csTextBoxShape, wxRectangleShape)
1035
1036csTextBoxShape::csTextBoxShape()
1037{
1038 SetPen(wxTRANSPARENT_PEN);
1039 SetBrush(wxTRANSPARENT_BRUSH);
1040
1041 SetSize(csSTANDARD_SHAPE_WIDTH, csSTANDARD_SHAPE_WIDTH/2.0);
1042
1043 SetAttachmentMode(ATTACHMENT_MODE_NONE);
1044 SetBranchStyle(BRANCHING_ATTACHMENT_NORMAL|BRANCHING_ATTACHMENT_BLOB);
2ba06d5a 1045 SetCentreResize(false);
1fc25a89
JS
1046}
1047
1048IMPLEMENT_DYNAMIC_CLASS(csLineShape, wxLineShape)
1049
1050csLineShape::csLineShape()
1051{
1052}
1053
1484b5cc 1054bool csLineShape::OnMoveMiddleControlPoint(wxDC& WXUNUSED(dc), wxLineControlPoint* lpt, const wxRealPoint& pt)
1fc25a89
JS
1055{
1056 csDiagramView* view = ((csCanvas*)GetCanvas())->GetView();
1057
1058 // Temporarily set the new shape properties so we can copy it
1059 lpt->SetX(pt.x); lpt->SetY(pt.y);
1060 lpt->m_point->x = pt.x; lpt->m_point->y = pt.y;
1061
1062 wxLineShape* newShape = (wxLineShape*) this->CreateNewCopy();
1063
1064 // Now set them back again
1065 lpt->SetX(lpt->m_originalPos.x); lpt->SetY(lpt->m_originalPos.y);
1066 lpt->m_point->x = lpt->m_originalPos.x; lpt->m_point->y = lpt->m_originalPos.y;
1067
1484b5cc 1068 view->GetDocument()->GetCommandProcessor()->Submit(new csDiagramCommand(_T("Move line point"), (csDiagramDocument*) view->GetDocument(),
1fc25a89
JS
1069 new csCommandState(ID_CS_MOVE_LINE_POINT, newShape, this)));
1070
2ba06d5a 1071 return true;
1fc25a89
JS
1072}
1073
1074wxLabelShape* csLineShape::OnCreateLabelShape(wxLineShape *parent, wxShapeRegion *region, double w, double h)
1075{
1076 return new csLabelShape(parent, region, w, h);
1077}
1078
1079#if 0
1080bool csLineShape::OnLabelMovePre(wxDC& dc, wxLabelShape* labelShape, double x, double y, double old_x, double old_y, bool display)
1081{
1082 csDiagramView* view = ((csCanvas*)GetCanvas())->GetView();
1083
1084 wxLineShape* newShape = (wxLineShape*) this->CreateNewCopy();
1085
1086 wxLineShape::OnLabelMovePre(dc, labelShape, x, y, old_x, old_y, display);
1087
1088 view->GetDocument()->GetCommandProcessor()->Submit(new csDiagramCommand("Move label", (csDiagramDocument*) view->GetDocument(),
1089 new csCommandState(ID_CS_MOVE_LABEL, newShape, this)));
2ba06d5a 1090 return true;
1fc25a89
JS
1091}
1092#endif
1093
1094IMPLEMENT_DYNAMIC_CLASS(csLabelShape, wxLabelShape)
1095
1096csLabelShape::csLabelShape(wxLineShape *parent, wxShapeRegion *region, double w, double h):
1097 wxLabelShape(parent, region, w, h)
1098{
1099}
1100
1101// TODO: not sure how intercept normal behaviour (OnMovePre) to make
1102// label movement undo-able.
1103void csLabelShape::OnEndDragLeft(double x, double y, int keys, int attachment)
1104{
1105 wxLabelShape::OnEndDragLeft(x, y, keys, attachment);
1106}
1107
1108
1109// Menu for editing shapes
1110void studioShapeEditProc(wxMenu& menu, wxCommandEvent& event)
1111{
1112 wxShape* shape = (wxShape*) menu.GetClientData();
1113 csDiagramView* view = ((csCanvas*)shape->GetCanvas())->GetView();
1114
1115 switch (event.GetId())
1116 {
1117 case ID_CS_EDIT_PROPERTIES:
1118 {
1119 csEvtHandler* handler1 = (csEvtHandler *)shape->GetEventHandler();
1120 handler1->EditProperties();
1121#if 0
1122 csEvtHandler* handler1 = (csEvtHandler *)shape->GetEventHandler();
1123 csLabelEditingDialog* dialog = new csLabelEditingDialog(shape->GetCanvas()->GetParent());
1124 dialog->SetShapeLabel(handler1->m_label);
1125 if (dialog->ShowModal() == wxID_CANCEL)
1126 {
1127 dialog->Destroy();
1128 return;
1129 }
1130
1131 wxString newLabel = dialog->GetShapeLabel();
1132 dialog->Destroy();
1133
1134 wxShape* newShape = shape->CreateNewCopy();
1135
1136 csEvtHandler* handler2 = (csEvtHandler *)newShape->GetEventHandler();
1137 handler2->m_label = newLabel;
1138
1139 view->GetDocument()->GetCommandProcessor()->Submit(new csDiagramCommand("Edit label", (csDiagramDocument*) view->GetDocument(),
1140 new csCommandState(ID_CS_EDIT_LABEL, newShape, shape)));
1141#endif
1142 break;
1143 }
1144 case wxID_CUT:
1145 {
1146 wxList list;
1147 list.Append(shape);
1148 view->DoCut(list);
1149 break;
1150 }
1151 case ID_CS_ROTATE_CLOCKWISE:
1152 case ID_CS_ROTATE_ANTICLOCKWISE:
1153 {
1154 if (shape->IsKindOf(CLASSINFO(wxLineShape)))
1155 break;
1156
1157 double theta = shape->GetRotation();
3454ecd5 1158 const double myPi = M_PI;
1fc25a89
JS
1159 double ninetyDegrees = myPi/2.0;
1160
1161 wxString opStr;
1162 if (event.GetId() == ID_CS_ROTATE_CLOCKWISE)
1163 {
1164 theta += ninetyDegrees;
1484b5cc 1165 opStr = _T("Rotate clockwise");
1fc25a89
JS
1166 }
1167 else
1168 {
1169 theta -= ninetyDegrees;
1484b5cc 1170 opStr = _T("Rotate anticlockwise");
1fc25a89
JS
1171 }
1172
1173 if (theta >= 2.0*myPi || theta < 0.0)
1174 theta = 0.0;
1175 wxShape* newShape = shape->CreateNewCopy();
1176 newShape->Rotate(0.0, 0.0, theta);
1177 wxList newShapes;
1178 wxList oldShapes;
1179 newShapes.Append(newShape);
1180 oldShapes.Append(shape);
1181 view->DoCmd(newShapes, oldShapes, event.GetId(), opStr);
1182 break;
1183 }
1184 default:
1185 break;
1186 }
1187}
1188
1189BEGIN_EVENT_TABLE(ShapeEditMenu, wxMenu)
1190 EVT_COMMAND_RANGE(1, 65000, wxEVT_COMMAND_MENU_SELECTED, ShapeEditMenu::OnCommand)
1191END_EVENT_TABLE()
1192
1193void ShapeEditMenu::OnCommand(wxCommandEvent& event)
1194{
1195 studioShapeEditProc(*this, event);
1196}
1197