]> git.saurik.com Git - wxWidgets.git/blame - contrib/samples/ogl/ogledit/doc.cpp
wxMutexGuiEnter/Leave didn't work because this file is compiled with wxUSE_GUI=0
[wxWidgets.git] / contrib / samples / ogl / ogledit / doc.cpp
CommitLineData
1fc25a89
JS
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".
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
1fc25a89
JS
31#include "ogledit.h"
32#include "doc.h"
33#include "view.h"
34
35#if wxUSE_STD_IOSTREAM
dd107c50 36#include <ioswrap.h>
1fc25a89
JS
37#endif
38
39IMPLEMENT_DYNAMIC_CLASS(DiagramDocument, wxDocument)
40
41DiagramDocument::DiagramDocument(void)
42{
43}
44
45DiagramDocument::~DiagramDocument(void)
46{
47}
48
49bool DiagramDocument::OnCloseDocument(void)
50{
51 diagram.DeleteAllShapes();
52 return TRUE;
53}
54
55#if wxUSE_STD_IOSTREAM
dd107c50 56wxSTD ostream& DiagramDocument::SaveObject(wxSTD ostream& stream)
1fc25a89
JS
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
dd107c50 71wxSTD istream& DiagramDocument::LoadObject(wxSTD istream& stream)
1fc25a89
JS
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
88wxOutputStream& DiagramDocument::SaveObject(wxOutputStream& stream)
89{
1dde66dd
JS
90#if wxUSE_PROLOGIO
91
1fc25a89
JS
92 wxDocument::SaveObject(stream);
93 char buf[400];
94 (void) wxGetTempFileName("diag", buf);
95
96 diagram.SaveFile(buf);
97
98 wxTransferFileToStream(buf, stream);
99
100 wxRemoveFile(buf);
1dde66dd
JS
101
102#endif
1fc25a89
JS
103
104 return stream;
105}
106
107wxInputStream& DiagramDocument::LoadObject(wxInputStream& stream)
108{
1dde66dd 109#if wxUSE_PROLOGIO
1fc25a89
JS
110 wxDocument::LoadObject(stream);
111
1fc25a89
JS
112 char buf[400];
113 (void) wxGetTempFileName("diag", buf);
114
115 wxTransferStreamToFile(stream, buf);
116
117 diagram.DeleteAllShapes();
118 diagram.LoadFile(buf);
119 wxRemoveFile(buf);
1dde66dd 120#endif
1fc25a89
JS
121
122 return stream;
123}
124
125#endif
126
127/*
128 * Implementation of drawing command
129 */
130
131DiagramCommand::DiagramCommand(char *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
149DiagramCommand::DiagramCommand(char *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
166DiagramCommand::DiagramCommand(char *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
184DiagramCommand::~DiagramCommand(void)
185{
186 if (shape && deleteShape)
187 {
188 shape->SetCanvas(NULL);
189 delete shape;
190 }
191}
192
193bool 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 = NULL;
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, wxString("")));
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 = NULL;
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, wxString("")));
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, "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
339bool 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.
425void DiagramCommand::RemoveLines(wxShape *shape)
426{
427 wxNode *node = shape->GetLines().First();
428 while (node)
429 {
430 wxLineShape *line = (wxLineShape *)node->Data();
431 doc->GetCommandProcessor()->Submit(new DiagramCommand("Cut", OGLEDIT_CUT, doc, NULL, 0.0, 0.0, line->Selected(), line));
432
433 node = shape->GetLines().First();
434 }
435}
436
437/*
438 * MyEvtHandler: an event handler class for all shapes
439 */
440
441void MyEvtHandler::OnLeftClick(double x, double y, int keys, int 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 wxNode *node = GetShape()->GetCanvas()->GetDiagram()->GetShapeList()->First();
459 while (node)
460 {
461 wxShape *eachShape = (wxShape *)node->Data();
462 if (eachShape->GetParent() == NULL)
463 {
464 if (eachShape->Selected())
465 {
466 eachShape->Select(FALSE, &dc);
467 redraw = TRUE;
468 }
469 }
470 node = node->Next();
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 wxGetApp().frame->SetStatusText(label);
484 }
485}
486
487/*
488 * Implement connection of two shapes by right-dragging between them.
489 */
490
491void MyEvtHandler::OnBeginDragRight(double x, double y, int 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(wxColour(0, 0, 0), 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
509void MyEvtHandler::OnDragRight(bool draw, double x, double y, int 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(wxColour(0, 0, 0), 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
525void MyEvtHandler::OnEndDragRight(double x, double y, int keys, int 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("wxLineShape", OGLEDIT_ADD_LINE, (DiagramDocument *)canvas->view->GetDocument(), CLASSINFO(wxLineShape),
538 0.0, 0.0, FALSE, NULL, GetShape(), otherShape));
539 }
540}
541
542void MyEvtHandler::OnEndSize(double x, double 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 */
1dde66dd
JS
553
554#if wxUSE_PROLOGIO
1fc25a89
JS
555
556bool MyDiagram::OnShapeSave(wxExprDatabase& db, wxShape& shape, wxExpr& expr)
557{
558 wxDiagram::OnShapeSave(db, shape, expr);
559 MyEvtHandler *handler = (MyEvtHandler *)shape.GetEventHandler();
560 expr.AddAttributeValueString("label", handler->label);
561 return TRUE;
562}
563
564bool MyDiagram::OnShapeLoad(wxExprDatabase& db, wxShape& shape, wxExpr& expr)
565{
566 wxDiagram::OnShapeLoad(db, shape, expr);
567 char *label = NULL;
568 expr.AssignAttributeValue("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
1dde66dd
JS
577#endif
578
1fc25a89
JS
579/*
580 * New shapes
581 */
582
583IMPLEMENT_DYNAMIC_CLASS(wxRoundedRectangleShape, wxRectangleShape)
584
585wxRoundedRectangleShape::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
592IMPLEMENT_DYNAMIC_CLASS(wxDiamondShape, wxPolygonShape)
593
594wxDiamondShape::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}