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