]> git.saurik.com Git - wxWidgets.git/blob - contrib/samples/ogl/ogledit/doc.cpp
wxUSE_STL fixes.
[wxWidgets.git] / contrib / samples / ogl / ogledit / doc.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: doc.cpp
3 // Purpose: Implements document functionality in OGLEdit
4 // Author: Julian Smart
5 // Modified by:
6 // Created: 12/07/98
7 // RCS-ID: $Id$
8 // Copyright: (c) Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 #ifdef __GNUG__
13 // #pragma implementation
14 #endif
15
16 // For compilers that support precompilation, includes "wx.h".
17 #include "wx/wxprec.h"
18
19 #ifdef __BORLANDC__
20 #pragma hdrstop
21 #endif
22
23 #ifndef WX_PRECOMP
24 #include <wx/wx.h>
25 #endif
26
27 #if !wxUSE_DOC_VIEW_ARCHITECTURE
28 #error You must set wxUSE_DOC_VIEW_ARCHITECTURE to 1 in wx_setup.h!
29 #endif
30
31 #include "ogledit.h"
32 #include "doc.h"
33 #include "view.h"
34
35 #if wxUSE_STD_IOSTREAM
36 #include <ioswrap.h>
37 #endif
38
39 IMPLEMENT_DYNAMIC_CLASS(DiagramDocument, wxDocument)
40
41 DiagramDocument::DiagramDocument(void)
42 {
43 }
44
45 DiagramDocument::~DiagramDocument(void)
46 {
47 }
48
49 bool DiagramDocument::OnCloseDocument(void)
50 {
51 diagram.DeleteAllShapes();
52 return true;
53 }
54
55 #if wxUSE_STD_IOSTREAM
56 wxSTD ostream& DiagramDocument::SaveObject(wxSTD ostream& stream)
57 {
58 wxDocument::SaveObject(stream);
59
60 char buf[400];
61 (void) wxGetTempFileName("diag", buf);
62
63 diagram.SaveFile(buf);
64 wxTransferFileToStream(buf, stream);
65
66 wxRemoveFile(buf);
67
68 return stream;
69 }
70
71 wxSTD istream& DiagramDocument::LoadObject(wxSTD istream& stream)
72 {
73 wxDocument::LoadObject(stream);
74
75 char buf[400];
76 (void) wxGetTempFileName("diag", buf);
77
78 wxTransferStreamToFile(stream, buf);
79
80 diagram.DeleteAllShapes();
81 diagram.LoadFile(buf);
82 wxRemoveFile(buf);
83
84 return stream;
85 }
86 #else
87
88 wxOutputStream& DiagramDocument::SaveObject(wxOutputStream& stream)
89 {
90 #if wxUSE_PROLOGIO
91
92 wxDocument::SaveObject(stream);
93 wxChar buf[400];
94 (void) wxGetTempFileName(_T("diag"), buf);
95
96 diagram.SaveFile(buf);
97
98 wxTransferFileToStream(buf, stream);
99
100 wxRemoveFile(buf);
101
102 #endif
103
104 return stream;
105 }
106
107 wxInputStream& DiagramDocument::LoadObject(wxInputStream& stream)
108 {
109 #if wxUSE_PROLOGIO
110 wxDocument::LoadObject(stream);
111
112 wxChar buf[400];
113 (void) wxGetTempFileName(_T("diag"), buf);
114
115 wxTransferStreamToFile(stream, buf);
116
117 diagram.DeleteAllShapes();
118 diagram.LoadFile(buf);
119 wxRemoveFile(buf);
120 #endif
121
122 return stream;
123 }
124
125 #endif
126
127 /*
128 * Implementation of drawing command
129 */
130
131 DiagramCommand::DiagramCommand(const wxString& name, int command, DiagramDocument *ddoc, wxClassInfo *info, double xx, double yy,
132 bool sel, wxShape *theShape, wxShape *fs, wxShape *ts):
133 wxCommand(true, name)
134 {
135 doc = ddoc;
136 cmd = command;
137 shape = theShape;
138 fromShape = fs;
139 toShape = ts;
140 shapeInfo = info;
141 shapeBrush = NULL;
142 shapePen = NULL;
143 x = xx;
144 y = yy;
145 selected = sel;
146 deleteShape = false;
147 }
148
149 DiagramCommand::DiagramCommand(const wxString& name, int command, DiagramDocument *ddoc, wxBrush *backgroundColour, wxShape *theShape):
150 wxCommand(true, name)
151 {
152 doc = ddoc;
153 cmd = command;
154 shape = theShape;
155 fromShape = NULL;
156 toShape = NULL;
157 shapeInfo = NULL;
158 x = 0.0;
159 y = 0.0;
160 selected = false;
161 deleteShape = false;
162 shapeBrush = backgroundColour;
163 shapePen = NULL;
164 }
165
166 DiagramCommand::DiagramCommand(const wxString& name, int command, DiagramDocument *ddoc, const wxString& lab, wxShape *theShape):
167 wxCommand(true, name)
168 {
169 doc = ddoc;
170 cmd = command;
171 shape = theShape;
172 fromShape = NULL;
173 toShape = NULL;
174 shapeInfo = NULL;
175 x = 0.0;
176 y = 0.0;
177 selected = false;
178 deleteShape = false;
179 shapeBrush = NULL;
180 shapePen = NULL;
181 shapeLabel = lab;
182 }
183
184 DiagramCommand::~DiagramCommand(void)
185 {
186 if (shape && deleteShape)
187 {
188 shape->SetCanvas(NULL);
189 delete shape;
190 }
191 }
192
193 bool DiagramCommand::Do(void)
194 {
195 switch (cmd)
196 {
197 case OGLEDIT_CUT:
198 {
199 if (shape)
200 {
201 deleteShape = true;
202
203 shape->Select(false);
204
205 // Generate commands to explicitly remove each connected line.
206 RemoveLines(shape);
207
208 doc->GetDiagram()->RemoveShape(shape);
209 if (shape->IsKindOf(CLASSINFO(wxLineShape)))
210 {
211 wxLineShape *lineShape = (wxLineShape *)shape;
212 fromShape = lineShape->GetFrom();
213 toShape = lineShape->GetTo();
214 }
215 shape->Unlink();
216
217 doc->Modify(true);
218 doc->UpdateAllViews();
219 }
220
221 break;
222 }
223 case OGLEDIT_ADD_SHAPE:
224 {
225 wxShape *theShape;
226 if (shape)
227 theShape = shape; // Saved from undoing the shape
228 else
229 {
230 theShape = (wxShape *)shapeInfo->CreateObject();
231 theShape->AssignNewIds();
232 theShape->SetEventHandler(new MyEvtHandler(theShape, theShape, wxEmptyString));
233 theShape->SetCentreResize(false);
234 theShape->SetPen(wxBLACK_PEN);
235 theShape->SetBrush(wxCYAN_BRUSH);
236
237 theShape->SetSize(60, 60);
238 }
239 doc->GetDiagram()->AddShape(theShape);
240 theShape->Show(true);
241
242 wxClientDC dc(theShape->GetCanvas());
243 theShape->GetCanvas()->PrepareDC(dc);
244
245 theShape->Move(dc, x, y);
246
247 shape = theShape;
248 deleteShape = false;
249
250 doc->Modify(true);
251 doc->UpdateAllViews();
252 break;
253 }
254 case OGLEDIT_ADD_LINE:
255 {
256 wxShape *theShape;
257 if (shape)
258 theShape = shape; // Saved from undoing the line
259 else
260 {
261 theShape = (wxShape *)shapeInfo->CreateObject();
262 theShape->AssignNewIds();
263 theShape->SetEventHandler(new MyEvtHandler(theShape, theShape, wxEmptyString));
264 theShape->SetPen(wxBLACK_PEN);
265 theShape->SetBrush(wxRED_BRUSH);
266
267 wxLineShape *lineShape = (wxLineShape *)theShape;
268
269 // Yes, you can have more than 2 control points, in which case
270 // it becomes a multi-segment line.
271 lineShape->MakeLineControlPoints(2);
272 lineShape->AddArrow(ARROW_ARROW, ARROW_POSITION_END, 10.0, 0.0, _T("Normal arrowhead"));
273 }
274
275 doc->GetDiagram()->AddShape(theShape);
276
277 fromShape->AddLine((wxLineShape *)theShape, toShape);
278
279 theShape->Show(true);
280
281 wxClientDC dc(theShape->GetCanvas());
282 theShape->GetCanvas()->PrepareDC(dc);
283
284 // It won't get drawn properly unless you move both
285 // connected images
286 fromShape->Move(dc, fromShape->GetX(), fromShape->GetY());
287 toShape->Move(dc, toShape->GetX(), toShape->GetY());
288
289 shape = theShape;
290 deleteShape = false;
291
292 doc->Modify(true);
293 doc->UpdateAllViews();
294 break;
295 }
296 case OGLEDIT_CHANGE_BACKGROUND_COLOUR:
297 {
298 if (shape)
299 {
300 wxClientDC dc(shape->GetCanvas());
301 shape->GetCanvas()->PrepareDC(dc);
302
303 wxBrush *oldBrush = shape->GetBrush();
304 shape->SetBrush(shapeBrush);
305 shapeBrush = oldBrush;
306 shape->Draw(dc);
307
308 doc->Modify(true);
309 doc->UpdateAllViews();
310 }
311
312 break;
313 }
314 case OGLEDIT_EDIT_LABEL:
315 {
316 if (shape)
317 {
318 MyEvtHandler *myHandler = (MyEvtHandler *)shape->GetEventHandler();
319 wxString oldLabel(myHandler->label);
320 myHandler->label = shapeLabel;
321 shapeLabel = oldLabel;
322
323 wxClientDC dc(shape->GetCanvas());
324 shape->GetCanvas()->PrepareDC(dc);
325
326 shape->FormatText(dc, /* (char*) (const char*) */ myHandler->label);
327 shape->Draw(dc);
328
329 doc->Modify(true);
330 doc->UpdateAllViews();
331 }
332
333 break;
334 }
335 }
336 return true;
337 }
338
339 bool DiagramCommand::Undo(void)
340 {
341 switch (cmd)
342 {
343 case OGLEDIT_CUT:
344 {
345 if (shape)
346 {
347 doc->GetDiagram()->AddShape(shape);
348 shape->Show(true);
349
350 if (shape->IsKindOf(CLASSINFO(wxLineShape)))
351 {
352 wxLineShape *lineShape = (wxLineShape *)shape;
353
354 fromShape->AddLine(lineShape, toShape);
355 }
356 if (selected)
357 shape->Select(true);
358
359 deleteShape = false;
360 }
361 doc->Modify(true);
362 doc->UpdateAllViews();
363 break;
364 }
365 case OGLEDIT_ADD_SHAPE:
366 case OGLEDIT_ADD_LINE:
367 {
368 if (shape)
369 {
370 wxClientDC dc(shape->GetCanvas());
371 shape->GetCanvas()->PrepareDC(dc);
372
373 shape->Select(false, &dc);
374 doc->GetDiagram()->RemoveShape(shape);
375 shape->Unlink();
376 deleteShape = true;
377 }
378 doc->Modify(true);
379 doc->UpdateAllViews();
380 break;
381 }
382 case OGLEDIT_CHANGE_BACKGROUND_COLOUR:
383 {
384 if (shape)
385 {
386 wxClientDC dc(shape->GetCanvas());
387 shape->GetCanvas()->PrepareDC(dc);
388
389 wxBrush *oldBrush = shape->GetBrush();
390 shape->SetBrush(shapeBrush);
391 shapeBrush = oldBrush;
392 shape->Draw(dc);
393
394 doc->Modify(true);
395 doc->UpdateAllViews();
396 }
397 break;
398 }
399 case OGLEDIT_EDIT_LABEL:
400 {
401 if (shape)
402 {
403 MyEvtHandler *myHandler = (MyEvtHandler *)shape->GetEventHandler();
404 wxString oldLabel(myHandler->label);
405 myHandler->label = shapeLabel;
406 shapeLabel = oldLabel;
407
408 wxClientDC dc(shape->GetCanvas());
409 shape->GetCanvas()->PrepareDC(dc);
410
411 shape->FormatText(dc, /* (char*) (const char*) */ myHandler->label);
412 shape->Draw(dc);
413
414 doc->Modify(true);
415 doc->UpdateAllViews();
416 }
417
418 break;
419 }
420 }
421 return true;
422 }
423
424 // Remove each individual line connected to a shape by sending a command.
425 void DiagramCommand::RemoveLines(wxShape *shape)
426 {
427 wxObjectList::compatibility_iterator node = shape->GetLines().GetFirst();
428 while (node)
429 {
430 wxLineShape *line = (wxLineShape *)node->GetData();
431 doc->GetCommandProcessor()->Submit(new DiagramCommand(_T("Cut"), OGLEDIT_CUT, doc, NULL, 0.0, 0.0, line->Selected(), line));
432
433 node = shape->GetLines().GetFirst();
434 }
435 }
436
437 /*
438 * MyEvtHandler: an event handler class for all shapes
439 */
440
441 void MyEvtHandler::OnLeftClick(double WXUNUSED(x), double WXUNUSED(y), int keys, int WXUNUSED(attachment))
442 {
443 wxClientDC dc(GetShape()->GetCanvas());
444 GetShape()->GetCanvas()->PrepareDC(dc);
445
446 if (keys == 0)
447 {
448 // Selection is a concept the library knows about
449 if (GetShape()->Selected())
450 {
451 GetShape()->Select(false, &dc);
452 GetShape()->GetCanvas()->Redraw(dc); // Redraw because bits of objects will be are missing
453 }
454 else
455 {
456 // Ensure no other shape is selected, to simplify Undo/Redo code
457 bool redraw = false;
458 wxObjectList::compatibility_iterator node = GetShape()->GetCanvas()->GetDiagram()->GetShapeList()->GetFirst();
459 while (node)
460 {
461 wxShape *eachShape = (wxShape *)node->GetData();
462 if (eachShape->GetParent() == NULL)
463 {
464 if (eachShape->Selected())
465 {
466 eachShape->Select(false, &dc);
467 redraw = true;
468 }
469 }
470 node = node->GetNext();
471 }
472 GetShape()->Select(true, &dc);
473 if (redraw)
474 GetShape()->GetCanvas()->Redraw(dc);
475 }
476 }
477 else if (keys & KEY_CTRL)
478 {
479 // Do something for CONTROL
480 }
481 else
482 {
483 #if wxUSE_STATUSBAR
484 wxGetApp().frame->SetStatusText(label);
485 #endif // wxUSE_STATUSBAR
486 }
487 }
488
489 /*
490 * Implement connection of two shapes by right-dragging between them.
491 */
492
493 void MyEvtHandler::OnBeginDragRight(double x, double y, int WXUNUSED(keys), int attachment)
494 {
495 // Force attachment to be zero for now. Eventually we can deal with
496 // the actual attachment point, e.g. a rectangle side if attachment mode is on.
497 attachment = 0;
498
499 wxClientDC dc(GetShape()->GetCanvas());
500 GetShape()->GetCanvas()->PrepareDC(dc);
501
502 wxPen dottedPen(wxColour(0, 0, 0), 1, wxDOT);
503 dc.SetLogicalFunction(OGLRBLF);
504 dc.SetPen(dottedPen);
505 double xp, yp;
506 GetShape()->GetAttachmentPosition(attachment, &xp, &yp);
507 dc.DrawLine((long) xp, (long) yp, (long) x, (long) y);
508 GetShape()->GetCanvas()->CaptureMouse();
509 }
510
511 void MyEvtHandler::OnDragRight(bool WXUNUSED(draw), double x, double y, int WXUNUSED(keys), int attachment)
512 {
513 // Force attachment to be zero for now
514 attachment = 0;
515
516 wxClientDC dc(GetShape()->GetCanvas());
517 GetShape()->GetCanvas()->PrepareDC(dc);
518
519 wxPen dottedPen(wxColour(0, 0, 0), 1, wxDOT);
520 dc.SetLogicalFunction(OGLRBLF);
521 dc.SetPen(dottedPen);
522 double xp, yp;
523 GetShape()->GetAttachmentPosition(attachment, &xp, &yp);
524 dc.DrawLine((long) xp, (long) yp, (long) x, (long) y);
525 }
526
527 void MyEvtHandler::OnEndDragRight(double x, double y, int WXUNUSED(keys), int WXUNUSED(attachment))
528 {
529 GetShape()->GetCanvas()->ReleaseMouse();
530 MyCanvas *canvas = (MyCanvas *)GetShape()->GetCanvas();
531
532 // Check if we're on an object
533 int new_attachment;
534 wxShape *otherShape = canvas->FindFirstSensitiveShape(x, y, &new_attachment, OP_DRAG_RIGHT);
535
536 if (otherShape && !otherShape->IsKindOf(CLASSINFO(wxLineShape)))
537 {
538 canvas->view->GetDocument()->GetCommandProcessor()->Submit(
539 new DiagramCommand(_T("wxLineShape"), OGLEDIT_ADD_LINE, (DiagramDocument *)canvas->view->GetDocument(), CLASSINFO(wxLineShape),
540 0.0, 0.0, false, NULL, GetShape(), otherShape));
541 }
542 }
543
544 void MyEvtHandler::OnEndSize(double WXUNUSED(x), double WXUNUSED(y))
545 {
546 wxClientDC dc(GetShape()->GetCanvas());
547 GetShape()->GetCanvas()->PrepareDC(dc);
548
549 GetShape()->FormatText(dc, /* (char*) (const char*) */ label);
550 }
551
552 /*
553 * Diagram
554 */
555
556 #if wxUSE_PROLOGIO
557
558 bool MyDiagram::OnShapeSave(wxExprDatabase& db, wxShape& shape, wxExpr& expr)
559 {
560 wxDiagram::OnShapeSave(db, shape, expr);
561 MyEvtHandler *handler = (MyEvtHandler *)shape.GetEventHandler();
562 expr.AddAttributeValueString(_T("label"), handler->label);
563 return true;
564 }
565
566 bool MyDiagram::OnShapeLoad(wxExprDatabase& db, wxShape& shape, wxExpr& expr)
567 {
568 wxDiagram::OnShapeLoad(db, shape, expr);
569 wxChar *label = NULL;
570 expr.AssignAttributeValue(_T("label"), &label);
571 MyEvtHandler *handler = new MyEvtHandler(&shape, &shape, wxString(label));
572 shape.SetEventHandler(handler);
573
574 if (label)
575 delete[] label;
576 return true;
577 }
578
579 #endif
580
581 /*
582 * New shapes
583 */
584
585 IMPLEMENT_DYNAMIC_CLASS(wxRoundedRectangleShape, wxRectangleShape)
586
587 wxRoundedRectangleShape::wxRoundedRectangleShape(double w, double h):
588 wxRectangleShape(w, h)
589 {
590 // 0.3 of the smaller rectangle dimension
591 SetCornerRadius((double) -0.3);
592 }
593
594 IMPLEMENT_DYNAMIC_CLASS(wxDiamondShape, wxPolygonShape)
595
596 wxDiamondShape::wxDiamondShape(double w, double h):
597 wxPolygonShape()
598 {
599 // wxPolygonShape::SetSize relies on the shape having non-zero
600 // size initially.
601 if (w == 0.0)
602 w = 60.0;
603 if (h == 0.0)
604 h = 60.0;
605
606 wxList *thePoints = new wxList;
607 wxRealPoint *point = new wxRealPoint(0.0, (-h/2.0));
608 thePoints->Append((wxObject*) point);
609
610 point = new wxRealPoint((w/2.0), 0.0);
611 thePoints->Append((wxObject*) point);
612
613 point = new wxRealPoint(0.0, (h/2.0));
614 thePoints->Append((wxObject*) point);
615
616 point = new wxRealPoint((-w/2.0), 0.0);
617 thePoints->Append((wxObject*) point);
618
619 Create(thePoints);
620 }