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