• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-R7000-V1.0.7.12_1.2.5/ap/gpl/amule/wxWidgets-2.8.12/contrib/samples/ogl/studio/
1/////////////////////////////////////////////////////////////////////////////
2// Name:        contrib/samples/ogl/studio/doc.cpp
3// Purpose:     Implements document functionality
4// Author:      Julian Smart
5// Modified by:
6// Created:     12/07/98
7// RCS-ID:      $Id: doc.cpp 37440 2006-02-10 11:59:52Z ABX $
8// Copyright:   (c) Julian Smart
9// Licence:     wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
12// For compilers that support precompilation, includes "wx.h".
13#include "wx/wxprec.h"
14
15#ifdef __BORLANDC__
16#pragma hdrstop
17#endif
18
19#ifndef WX_PRECOMP
20#include "wx/wx.h"
21#endif
22
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
30#ifdef __VISUALC__
31#pragma warning(disable:4355)
32#endif
33
34csDiagramDocument::csDiagramDocument():m_diagram(this)
35{
36}
37
38#ifdef __VISUALC__
39#pragma warning(default:4355)
40#endif
41
42csDiagramDocument::~csDiagramDocument()
43{
44}
45
46bool csDiagramDocument::OnCloseDocument()
47{
48  m_diagram.DeleteAllShapes();
49  return true;
50}
51
52#if wxUSE_PROLOGIO
53bool csDiagramDocument::OnSaveDocument(const wxString& file)
54{
55  if (file == wxEmptyString)
56    return false;
57
58  if (!m_diagram.SaveFile(file))
59  {
60    wxString msgTitle;
61    if (wxTheApp->GetAppName() != wxEmptyString)
62        msgTitle = wxTheApp->GetAppName();
63    else
64        msgTitle = wxString(_T("File error"));
65
66    (void)wxMessageBox(_T("Sorry, could not open this file for saving."), msgTitle, wxOK | wxICON_EXCLAMATION,
67      GetDocumentWindow());
68    return false;
69  }
70
71  Modify(false);
72  SetFilename(file);
73  return true;
74}
75
76bool csDiagramDocument::OnOpenDocument(const wxString& file)
77{
78  if (!OnSaveModified())
79    return false;
80
81  wxString msgTitle;
82  if (wxTheApp->GetAppName() != wxEmptyString)
83    msgTitle = wxTheApp->GetAppName();
84  else
85    msgTitle = wxString(_T("File error"));
86
87  m_diagram.DeleteAllShapes();
88  if (!m_diagram.LoadFile(file))
89  {
90    (void)wxMessageBox(_T("Sorry, could not open this file."), msgTitle, wxOK|wxICON_EXCLAMATION,
91     GetDocumentWindow());
92    return false;
93  }
94  SetFilename(file, true);
95  Modify(false);
96  UpdateAllViews();
97
98  return true;
99}
100#endif // wxUSE_PROLOGIO
101
102
103/*
104 * Implementation of drawing command
105 */
106
107csDiagramCommand::csDiagramCommand(const wxString& name, csDiagramDocument *doc,
108    csCommandState* onlyState):
109  wxCommand(true, name)
110{
111  m_doc = doc;
112
113  if (onlyState)
114  {
115    AddState(onlyState);
116  }
117}
118
119csDiagramCommand::~csDiagramCommand()
120{
121    wxObjectList::compatibility_iterator node = m_states.GetFirst();
122    while (node)
123    {
124        csCommandState* state = (csCommandState*) node->GetData();
125        delete state;
126        node = node->GetNext();
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{
148    wxObjectList::compatibility_iterator node = m_states.GetFirst();
149    while (node)
150    {
151        csCommandState* state = (csCommandState*) node->GetData();
152        wxShape* shape = state->GetShapeOnCanvas();
153        wxASSERT( (shape != NULL) );
154
155        wxObjectList::compatibility_iterator node1 = shape->GetLines().GetFirst();
156        while (node1)
157        {
158            wxLineShape *line = (wxLineShape *)node1->GetData();
159            if (!FindStateByShape(line))
160            {
161                csCommandState* newState = new csCommandState(ID_CS_CUT, NULL, line);
162                InsertState(newState);
163            }
164
165            node1 = node1->GetNext();
166        }
167        node = node->GetNext();
168    }
169}
170
171csCommandState* csDiagramCommand::FindStateByShape(wxShape* shape)
172{
173    wxObjectList::compatibility_iterator node = m_states.GetFirst();
174    while (node)
175    {
176        csCommandState* state = (csCommandState*) node->GetData();
177        if (shape == state->GetShapeOnCanvas() || shape == state->GetSavedState())
178            return state;
179        node = node->GetNext();
180    }
181    return NULL;
182}
183
184bool csDiagramCommand::Do()
185{
186    wxObjectList::compatibility_iterator node = m_states.GetFirst();
187    while (node)
188    {
189        csCommandState* state = (csCommandState*) node->GetData();
190        if (!state->Do())
191            return false;
192        node = node->GetNext();
193    }
194    return true;
195}
196
197bool csDiagramCommand::Undo()
198{
199    // Undo in reverse order, so e.g. shapes get added
200    // back before the lines do.
201    wxObjectList::compatibility_iterator node = m_states.GetLast();
202    while (node)
203    {
204        csCommandState* state = (csCommandState*) node->GetData();
205        if (!state->Undo())
206            return false;
207        node = node->GetPrevious();
208    }
209    return true;
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
265        m_shapeOnCanvas->Select(false);
266        ((csDiagramView*) m_doc->GetFirstView())->SelectShape(m_shapeOnCanvas, false);
267
268        m_shapeOnCanvas->Unlink();
269
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
289        m_doc->Modify(true);
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);
310        m_shapeOnCanvas->Show(true);
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        {
322            m_shapeOnCanvas->Select(true, &dc);
323            ((csDiagramView*) m_doc->GetFirstView())->SelectShape(m_shapeOnCanvas, true);
324        }
325
326        m_doc->Modify(true);
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());
348
349        lineShape->Show(true);
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        {
361            lineShape->Select(true, &dc);
362            ((csDiagramView*) m_doc->GetFirstView())->SelectShape(m_shapeOnCanvas, true);
363        }
364
365        m_doc->Modify(true);
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)
402            m_shapeOnCanvas->Select(false, & dc);
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
455            m_shapeOnCanvas->Show(true);
456
457            // Recursively redraw links if we have a composite.
458            if (m_shapeOnCanvas->GetChildren().GetCount() > 0)
459                m_shapeOnCanvas->DrawLinks(dc, -1, true);
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)
475            m_shapeOnCanvas->Select(true, & dc);
476
477        m_doc->Modify(true);
478        m_doc->UpdateAllViews();
479
480        break;
481    }
482  }
483  return true;
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        }
515        m_shapeOnCanvas->Show(true);
516
517        m_doc->Modify(true);
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
548        m_shapeOnCanvas->Select(false, &dc);
549        ((csDiagramView*) m_doc->GetFirstView())->SelectShape(m_shapeOnCanvas, false);
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
565        m_doc->Modify(true);
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
592    return true;
593}
594