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