]> git.saurik.com Git - wxWidgets.git/blame - contrib/samples/ogl/studio/doc.cpp
Add missing files to release tarballs
[wxWidgets.git] / contrib / samples / ogl / studio / doc.cpp
CommitLineData
1fc25a89
JS
1/////////////////////////////////////////////////////////////////////////////
2// Name: doc.cpp
3// Purpose: Implements document functionality
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
1fc25a89 12// For compilers that support precompilation, includes "wx.h".
92a19c2e 13#include "wx/wxprec.h"
1fc25a89
JS
14
15#ifdef __BORLANDC__
16#pragma hdrstop
17#endif
18
19#ifndef WX_PRECOMP
20#include <wx/wx.h>
21#endif
22
1fc25a89
JS
23#include "studio.h"
24#include "doc.h"
25#include "view.h"
26#include <wx/ogl/basicp.h>
27
28IMPLEMENT_DYNAMIC_CLASS(csDiagramDocument, wxDocument)
29
2b5dcd17 30#ifdef __VISUALC__
1fc25a89
JS
31#pragma warning(disable:4355)
32#endif
33
34csDiagramDocument::csDiagramDocument():m_diagram(this)
35{
36}
37
2b5dcd17 38#ifdef __VISUALC__
1fc25a89
JS
39#pragma warning(default:4355)
40#endif
41
42csDiagramDocument::~csDiagramDocument()
43{
44}
45
46bool csDiagramDocument::OnCloseDocument()
47{
48 m_diagram.DeleteAllShapes();
2ba06d5a 49 return true;
1fc25a89
JS
50}
51
cecdcad1 52#if wxUSE_PROLOGIO
1fc25a89
JS
53bool csDiagramDocument::OnSaveDocument(const wxString& file)
54{
1484b5cc 55 if (file == wxEmptyString)
2ba06d5a 56 return false;
1fc25a89
JS
57
58 if (!m_diagram.SaveFile(file))
59 {
60 wxString msgTitle;
1484b5cc 61 if (wxTheApp->GetAppName() != wxEmptyString)
1fc25a89
JS
62 msgTitle = wxTheApp->GetAppName();
63 else
1484b5cc 64 msgTitle = wxString(_T("File error"));
1fc25a89 65
1484b5cc 66 (void)wxMessageBox(_T("Sorry, could not open this file for saving."), msgTitle, wxOK | wxICON_EXCLAMATION,
1fc25a89 67 GetDocumentWindow());
2ba06d5a 68 return false;
1fc25a89
JS
69 }
70
2ba06d5a 71 Modify(false);
1fc25a89 72 SetFilename(file);
2ba06d5a 73 return true;
1fc25a89 74}
2ba06d5a 75
1fc25a89
JS
76bool csDiagramDocument::OnOpenDocument(const wxString& file)
77{
78 if (!OnSaveModified())
2ba06d5a 79 return false;
1fc25a89
JS
80
81 wxString msgTitle;
1484b5cc 82 if (wxTheApp->GetAppName() != wxEmptyString)
1fc25a89
JS
83 msgTitle = wxTheApp->GetAppName();
84 else
1484b5cc 85 msgTitle = wxString(_T("File error"));
1fc25a89
JS
86
87 m_diagram.DeleteAllShapes();
88 if (!m_diagram.LoadFile(file))
89 {
1484b5cc 90 (void)wxMessageBox(_T("Sorry, could not open this file."), msgTitle, wxOK|wxICON_EXCLAMATION,
1fc25a89 91 GetDocumentWindow());
2ba06d5a 92 return false;
1fc25a89 93 }
2ba06d5a
WS
94 SetFilename(file, true);
95 Modify(false);
1fc25a89 96 UpdateAllViews();
cecdcad1 97
2ba06d5a 98 return true;
1fc25a89 99}
cecdcad1 100#endif // wxUSE_PROLOGIO
2ba06d5a 101
1fc25a89
JS
102
103/*
104 * Implementation of drawing command
105 */
106
107csDiagramCommand::csDiagramCommand(const wxString& name, csDiagramDocument *doc,
108 csCommandState* onlyState):
2ba06d5a 109 wxCommand(true, name)
1fc25a89
JS
110{
111 m_doc = doc;
112
113 if (onlyState)
114 {
115 AddState(onlyState);
116 }
117}
118
119csDiagramCommand::~csDiagramCommand()
120{
36ca94a2 121 wxObjectList::compatibility_iterator node = m_states.GetFirst();
1fc25a89
JS
122 while (node)
123 {
8552e6f0 124 csCommandState* state = (csCommandState*) node->GetData();
1fc25a89 125 delete state;
8552e6f0 126 node = node->GetNext();
1fc25a89
JS
127 }
128}
129
130void csDiagramCommand::AddState(csCommandState* state)
131{
132 state->m_doc = m_doc;
133// state->m_cmd = m_cmd;
134 m_states.Append(state);
135}
136
137// Insert a state at the beginning of the list
138void csDiagramCommand::InsertState(csCommandState* state)
139{
140 state->m_doc = m_doc;
141// state->m_cmd = m_cmd;
142 m_states.Insert(state);
143}
144
145// Schedule all lines connected to the states to be cut.
146void csDiagramCommand::RemoveLines()
147{
36ca94a2 148 wxObjectList::compatibility_iterator node = m_states.GetFirst();
1fc25a89
JS
149 while (node)
150 {
8552e6f0 151 csCommandState* state = (csCommandState*) node->GetData();
1fc25a89
JS
152 wxShape* shape = state->GetShapeOnCanvas();
153 wxASSERT( (shape != NULL) );
154
36ca94a2 155 wxObjectList::compatibility_iterator node1 = shape->GetLines().GetFirst();
1fc25a89
JS
156 while (node1)
157 {
8552e6f0 158 wxLineShape *line = (wxLineShape *)node1->GetData();
1fc25a89
JS
159 if (!FindStateByShape(line))
160 {
161 csCommandState* newState = new csCommandState(ID_CS_CUT, NULL, line);
162 InsertState(newState);
163 }
164
8552e6f0 165 node1 = node1->GetNext();
1fc25a89 166 }
8552e6f0 167 node = node->GetNext();
1fc25a89
JS
168 }
169}
170
171csCommandState* csDiagramCommand::FindStateByShape(wxShape* shape)
172{
36ca94a2 173 wxObjectList::compatibility_iterator node = m_states.GetFirst();
1fc25a89
JS
174 while (node)
175 {
8552e6f0 176 csCommandState* state = (csCommandState*) node->GetData();
1fc25a89
JS
177 if (shape == state->GetShapeOnCanvas() || shape == state->GetSavedState())
178 return state;
8552e6f0 179 node = node->GetNext();
1fc25a89
JS
180 }
181 return NULL;
182}
183
184bool csDiagramCommand::Do()
185{
36ca94a2 186 wxObjectList::compatibility_iterator node = m_states.GetFirst();
1fc25a89
JS
187 while (node)
188 {
8552e6f0 189 csCommandState* state = (csCommandState*) node->GetData();
1fc25a89 190 if (!state->Do())
2ba06d5a 191 return false;
8552e6f0 192 node = node->GetNext();
1fc25a89 193 }
2ba06d5a 194 return true;
1fc25a89
JS
195}
196
197bool csDiagramCommand::Undo()
198{
199 // Undo in reverse order, so e.g. shapes get added
200 // back before the lines do.
36ca94a2 201 wxObjectList::compatibility_iterator node = m_states.GetLast();
1fc25a89
JS
202 while (node)
203 {
8552e6f0 204 csCommandState* state = (csCommandState*) node->GetData();
1fc25a89 205 if (!state->Undo())
2ba06d5a 206 return false;
8552e6f0 207 node = node->GetPrevious();
1fc25a89 208 }
2ba06d5a 209 return true;
1fc25a89
JS
210}
211
212csCommandState::csCommandState(int cmd, wxShape* savedState, wxShape* shapeOnCanvas)
213{
214 m_cmd = cmd;
215 m_doc = NULL;
216 m_savedState = savedState;
217 m_shapeOnCanvas = shapeOnCanvas;
218 m_linePositionFrom = 0;
219 m_linePositionTo = 0;
220}
221
222csCommandState::~csCommandState()
223{
224 if (m_savedState)
225 {
226 m_savedState->SetCanvas(NULL);
227 delete m_savedState;
228 }
229}
230
231bool csCommandState::Do()
232{
233 switch (m_cmd)
234 {
235 case ID_CS_CUT:
236 {
237 // New state is 'nothing' - maybe pass shape ID to state so we know what
238 // we're talking about.
239 // Then save old shape in m_savedState (actually swap pointers)
240
241 wxASSERT( (m_shapeOnCanvas != NULL) );
242 wxASSERT( (m_savedState == NULL) ); // new state will be 'nothing'
243 wxASSERT( (m_doc != NULL) );
244
245 wxShapeCanvas* canvas = m_shapeOnCanvas->GetCanvas();
246
247 // In case this is a line
248 wxShape* lineFrom = NULL;
249 wxShape* lineTo = NULL;
250 int attachmentFrom = 0, attachmentTo = 0;
251
252 if (m_shapeOnCanvas->IsKindOf(CLASSINFO(wxLineShape)))
253 {
254 // Store the from/to info to save in the line shape
255 wxLineShape* lineShape = (wxLineShape*) m_shapeOnCanvas;
256 lineFrom = lineShape->GetFrom();
257 lineTo = lineShape->GetTo();
258 attachmentFrom = lineShape->GetAttachmentFrom();
259 attachmentTo = lineShape->GetAttachmentTo();
260
261 m_linePositionFrom = lineFrom->GetLinePosition(lineShape);
262 m_linePositionTo = lineTo->GetLinePosition(lineShape);
263 }
264
2ba06d5a
WS
265 m_shapeOnCanvas->Select(false);
266 ((csDiagramView*) m_doc->GetFirstView())->SelectShape(m_shapeOnCanvas, false);
1fc25a89
JS
267
268 m_shapeOnCanvas->Unlink();
cecdcad1 269
1fc25a89
JS
270 m_doc->GetDiagram()->RemoveShape(m_shapeOnCanvas);
271
272 m_savedState = m_shapeOnCanvas;
273
274 if (m_savedState->IsKindOf(CLASSINFO(wxLineShape)))
275 {
276 // Restore the from/to info for future reference
277 wxLineShape* lineShape = (wxLineShape*) m_savedState;
278 lineShape->SetFrom(lineFrom);
279 lineShape->SetTo(lineTo);
280 lineShape->SetAttachments(attachmentFrom, attachmentTo);
281
282 wxClientDC dc(canvas);
283 canvas->PrepareDC(dc);
284
285 lineFrom->MoveLinks(dc);
286 lineTo->MoveLinks(dc);
287 }
288
2ba06d5a 289 m_doc->Modify(true);
1fc25a89
JS
290 m_doc->UpdateAllViews();
291 break;
292 }
293 case ID_CS_ADD_SHAPE:
294 case ID_CS_ADD_SHAPE_SELECT:
295 {
296 // The app has given the command state a new m_savedState
297 // shape, which is the new shape to add to the canvas (but
298 // not actually added until this point).
299 // The new 'saved state' is therefore 'nothing' since there
300 // was nothing there before.
301
302 wxASSERT( (m_shapeOnCanvas == NULL) );
303 wxASSERT( (m_savedState != NULL) );
304 wxASSERT( (m_doc != NULL) );
305
306 m_shapeOnCanvas = m_savedState;
307 m_savedState = NULL;
308
309 m_doc->GetDiagram()->AddShape(m_shapeOnCanvas);
2ba06d5a 310 m_shapeOnCanvas->Show(true);
1fc25a89
JS
311
312 wxClientDC dc(m_shapeOnCanvas->GetCanvas());
313 m_shapeOnCanvas->GetCanvas()->PrepareDC(dc);
314
315 csEvtHandler *handler = (csEvtHandler *)m_shapeOnCanvas->GetEventHandler();
316 m_shapeOnCanvas->FormatText(dc, handler->m_label);
317
318 m_shapeOnCanvas->Move(dc, m_shapeOnCanvas->GetX(), m_shapeOnCanvas->GetY());
319
320 if (m_cmd == ID_CS_ADD_SHAPE_SELECT)
321 {
2ba06d5a
WS
322 m_shapeOnCanvas->Select(true, &dc);
323 ((csDiagramView*) m_doc->GetFirstView())->SelectShape(m_shapeOnCanvas, true);
1fc25a89
JS
324 }
325
2ba06d5a 326 m_doc->Modify(true);
1fc25a89
JS
327 m_doc->UpdateAllViews();
328 break;
329 }
330 case ID_CS_ADD_LINE:
331 case ID_CS_ADD_LINE_SELECT:
332 {
333 wxASSERT( (m_shapeOnCanvas == NULL) );
334 wxASSERT( (m_savedState != NULL) );
335 wxASSERT( (m_doc != NULL) );
336
337 wxLineShape *lineShape = (wxLineShape *)m_savedState;
338 wxASSERT( (lineShape->GetFrom() != NULL) );
339 wxASSERT( (lineShape->GetTo() != NULL) );
340
341 m_shapeOnCanvas = m_savedState;
342 m_savedState = NULL;
343
344 m_doc->GetDiagram()->AddShape(lineShape);
345
346 lineShape->GetFrom()->AddLine(lineShape, lineShape->GetTo(),
347 lineShape->GetAttachmentFrom(), lineShape->GetAttachmentTo());
cecdcad1 348
2ba06d5a 349 lineShape->Show(true);
1fc25a89
JS
350
351 wxClientDC dc(lineShape->GetCanvas());
352 lineShape->GetCanvas()->PrepareDC(dc);
353
354 // It won't get drawn properly unless you move both
355 // connected images
356 lineShape->GetFrom()->Move(dc, lineShape->GetFrom()->GetX(), lineShape->GetFrom()->GetY());
357 lineShape->GetTo()->Move(dc, lineShape->GetTo()->GetX(), lineShape->GetTo()->GetY());
358
359 if (m_cmd == ID_CS_ADD_LINE_SELECT)
360 {
2ba06d5a
WS
361 lineShape->Select(true, &dc);
362 ((csDiagramView*) m_doc->GetFirstView())->SelectShape(m_shapeOnCanvas, true);
1fc25a89
JS
363 }
364
2ba06d5a 365 m_doc->Modify(true);
1fc25a89
JS
366 m_doc->UpdateAllViews();
367 break;
368 }
369 case ID_CS_CHANGE_BACKGROUND_COLOUR:
370 case ID_CS_MOVE:
371 case ID_CS_SIZE:
372 case ID_CS_EDIT_PROPERTIES:
373 case ID_CS_FONT_CHANGE:
374 case ID_CS_ARROW_CHANGE:
375 case ID_CS_ROTATE_CLOCKWISE:
376 case ID_CS_ROTATE_ANTICLOCKWISE:
377 case ID_CS_CHANGE_LINE_ORDERING:
378 case ID_CS_CHANGE_LINE_ATTACHMENT:
379 case ID_CS_ALIGN:
380 case ID_CS_NEW_POINT:
381 case ID_CS_CUT_POINT:
382 case ID_CS_MOVE_LINE_POINT:
383 case ID_CS_STRAIGHTEN:
384 case ID_CS_MOVE_LABEL:
385 {
386 // At this point we have been given a new shape
387 // just like the old one but with a changed colour.
388 // It's now time to apply that change to the
389 // shape on the canvas, saving the old state.
390 // NOTE: this is general enough to work with MOST attribute
391 // changes!
392
393 wxASSERT( (m_shapeOnCanvas != NULL) );
394 wxASSERT( (m_savedState != NULL) ); // This is the new shape with changed colour
395 wxASSERT( (m_doc != NULL) );
396
397 wxClientDC dc(m_shapeOnCanvas->GetCanvas());
398 m_shapeOnCanvas->GetCanvas()->PrepareDC(dc);
399
400 bool isSelected = m_shapeOnCanvas->Selected();
401 if (isSelected)
2ba06d5a 402 m_shapeOnCanvas->Select(false, & dc);
1fc25a89
JS
403
404 if (m_cmd == ID_CS_SIZE || m_cmd == ID_CS_ROTATE_CLOCKWISE || m_cmd == ID_CS_ROTATE_ANTICLOCKWISE ||
405 m_cmd == ID_CS_CHANGE_LINE_ORDERING || m_cmd == ID_CS_CHANGE_LINE_ATTACHMENT)
406 {
407 m_shapeOnCanvas->Erase(dc);
408 }
409
410 // TODO: make sure the ID is the same. Or, when applying the new state,
411 // don't change the original ID.
412 wxShape* tempShape = m_shapeOnCanvas->CreateNewCopy();
413
414 // Apply the saved state to the shape on the canvas, by copying.
415 m_savedState->CopyWithHandler(*m_shapeOnCanvas);
416
417 // Delete this state now it's been used (m_shapeOnCanvas currently holds this state)
418 delete m_savedState;
419
420 // Remember the previous state
421 m_savedState = tempShape;
422
423 // Redraw the shape
424
425 if (m_cmd == ID_CS_MOVE || m_cmd == ID_CS_ROTATE_CLOCKWISE || m_cmd == ID_CS_ROTATE_ANTICLOCKWISE ||
426 m_cmd == ID_CS_ALIGN)
427 {
428 m_shapeOnCanvas->Move(dc, m_shapeOnCanvas->GetX(), m_shapeOnCanvas->GetY());
429
430 csEvtHandler *handler = (csEvtHandler *)m_shapeOnCanvas->GetEventHandler();
431 m_shapeOnCanvas->FormatText(dc, handler->m_label);
432 m_shapeOnCanvas->Draw(dc);
433 }
434 else if (m_cmd == ID_CS_CHANGE_LINE_ORDERING)
435 {
436 m_shapeOnCanvas->MoveLinks(dc);
437 }
438 else if (m_cmd == ID_CS_CHANGE_LINE_ATTACHMENT)
439 {
440 wxLineShape *lineShape = (wxLineShape *)m_shapeOnCanvas;
441
442 // Have to move both sets of links since we don't know which links
443 // have been affected (unless we compared before and after states).
444 lineShape->GetFrom()->MoveLinks(dc);
445 lineShape->GetTo()->MoveLinks(dc);
446 }
447 else if (m_cmd == ID_CS_SIZE)
448 {
449 double width, height;
450 m_shapeOnCanvas->GetBoundingBoxMax(&width, &height);
451
452 m_shapeOnCanvas->SetSize(width, height);
453 m_shapeOnCanvas->Move(dc, m_shapeOnCanvas->GetX(), m_shapeOnCanvas->GetY());
454
2ba06d5a 455 m_shapeOnCanvas->Show(true);
1fc25a89
JS
456
457 // Recursively redraw links if we have a composite.
8552e6f0 458 if (m_shapeOnCanvas->GetChildren().GetCount() > 0)
2ba06d5a 459 m_shapeOnCanvas->DrawLinks(dc, -1, true);
1fc25a89
JS
460
461 m_shapeOnCanvas->GetEventHandler()->OnEndSize(width, height);
462 }
463 else if (m_cmd == ID_CS_EDIT_PROPERTIES || m_cmd == ID_CS_FONT_CHANGE)
464 {
465 csEvtHandler *handler = (csEvtHandler *)m_shapeOnCanvas->GetEventHandler();
466 m_shapeOnCanvas->FormatText(dc, handler->m_label);
467 m_shapeOnCanvas->Draw(dc);
468 }
469 else
470 {
471 m_shapeOnCanvas->Draw(dc);
472 }
473
474 if (isSelected)
2ba06d5a 475 m_shapeOnCanvas->Select(true, & dc);
cecdcad1 476
2ba06d5a 477 m_doc->Modify(true);
1fc25a89
JS
478 m_doc->UpdateAllViews();
479
480 break;
481 }
482 }
2ba06d5a 483 return true;
1fc25a89
JS
484}
485
486bool csCommandState::Undo()
487{
488 switch (m_cmd)
489 {
490 case ID_CS_CUT:
491 {
492 wxASSERT( (m_savedState != NULL) );
493 wxASSERT( (m_doc != NULL) );
494
495 m_doc->GetDiagram()->AddShape(m_savedState);
496 m_shapeOnCanvas = m_savedState;
497 m_savedState = NULL;
498
499 if (m_shapeOnCanvas->IsKindOf(CLASSINFO(wxLineShape)))
500 {
501 wxLineShape* lineShape = (wxLineShape*) m_shapeOnCanvas;
502 lineShape->GetFrom()->AddLine(lineShape, lineShape->GetTo(),
503 lineShape->GetAttachmentFrom(), lineShape->GetAttachmentTo(),
504 m_linePositionFrom, m_linePositionTo);
505
506 wxShapeCanvas* canvas = lineShape->GetFrom()->GetCanvas();
507
508 wxClientDC dc(canvas);
509 canvas->PrepareDC(dc);
510
511 lineShape->GetFrom()->MoveLinks(dc);
512 lineShape->GetTo()->MoveLinks(dc);
513
514 }
2ba06d5a 515 m_shapeOnCanvas->Show(true);
1fc25a89 516
2ba06d5a 517 m_doc->Modify(true);
1fc25a89
JS
518 m_doc->UpdateAllViews();
519 break;
520 }
521 case ID_CS_ADD_SHAPE:
522 case ID_CS_ADD_LINE:
523 case ID_CS_ADD_SHAPE_SELECT:
524 case ID_CS_ADD_LINE_SELECT:
525 {
526 wxASSERT( (m_shapeOnCanvas != NULL) );
527 wxASSERT( (m_savedState == NULL) );
528 wxASSERT( (m_doc != NULL) );
529
530 // In case this is a line
531 wxShape* lineFrom = NULL;
532 wxShape* lineTo = NULL;
533 int attachmentFrom = 0, attachmentTo = 0;
534
535 if (m_shapeOnCanvas->IsKindOf(CLASSINFO(wxLineShape)))
536 {
537 // Store the from/to info to save in the line shape
538 wxLineShape* lineShape = (wxLineShape*) m_shapeOnCanvas;
539 lineFrom = lineShape->GetFrom();
540 lineTo = lineShape->GetTo();
541 attachmentFrom = lineShape->GetAttachmentFrom();
542 attachmentTo = lineShape->GetAttachmentTo();
543 }
544
545 wxClientDC dc(m_shapeOnCanvas->GetCanvas());
546 m_shapeOnCanvas->GetCanvas()->PrepareDC(dc);
547
2ba06d5a
WS
548 m_shapeOnCanvas->Select(false, &dc);
549 ((csDiagramView*) m_doc->GetFirstView())->SelectShape(m_shapeOnCanvas, false);
1fc25a89
JS
550 m_doc->GetDiagram()->RemoveShape(m_shapeOnCanvas);
551 m_shapeOnCanvas->Unlink(); // Unlinks the line, if it is a line
552
553 if (m_shapeOnCanvas->IsKindOf(CLASSINFO(wxLineShape)))
554 {
555 // Restore the from/to info for future reference
556 wxLineShape* lineShape = (wxLineShape*) m_shapeOnCanvas;
557 lineShape->SetFrom(lineFrom);
558 lineShape->SetTo(lineTo);
559 lineShape->SetAttachments(attachmentFrom, attachmentTo);
560 }
561
562 m_savedState = m_shapeOnCanvas;
563 m_shapeOnCanvas = NULL;
564
2ba06d5a 565 m_doc->Modify(true);
1fc25a89
JS
566 m_doc->UpdateAllViews();
567 break;
568 }
569 case ID_CS_CHANGE_BACKGROUND_COLOUR:
570 case ID_CS_MOVE:
571 case ID_CS_SIZE:
572 case ID_CS_EDIT_PROPERTIES:
573 case ID_CS_FONT_CHANGE:
574 case ID_CS_ARROW_CHANGE:
575 case ID_CS_ROTATE_CLOCKWISE:
576 case ID_CS_ROTATE_ANTICLOCKWISE:
577 case ID_CS_CHANGE_LINE_ORDERING:
578 case ID_CS_CHANGE_LINE_ATTACHMENT:
579 case ID_CS_ALIGN:
580 case ID_CS_NEW_POINT:
581 case ID_CS_CUT_POINT:
582 case ID_CS_MOVE_LINE_POINT:
583 case ID_CS_STRAIGHTEN:
584 case ID_CS_MOVE_LABEL:
585 {
586 // Exactly like the Do case; we're just swapping states.
587 Do();
588 break;
589 }
590 }
591
2ba06d5a 592 return true;
1fc25a89
JS
593}
594