]>
Commit | Line | Data |
---|---|---|
0fc1a713 JS |
1 | \chapter{OGLEdit: a sample OGL application}\label{ogledit}% |
2 | \setheader{{\it CHAPTER \thechapter}}{}{}{}{}{{\it CHAPTER \thechapter}}% | |
3 | \setfooter{\thepage}{}{}{}{}{\thepage} | |
4 | ||
5 | OGLEdit is a sample OGL application that allows the user to draw, edit, | |
6 | save and load a few shapes. It should clarify aspects of OGL usage, and | |
7 | can act as a template for similar applications. OGLEdit can be found in\rtfsp | |
8 | {\tt samples/ogledit} in the OGL distribution. | |
9 | ||
10 | $$\image{10cm;0cm}{ogledit.eps}$$\par | |
11 | ||
12 | The wxWindows document/view model has been used in OGL, to reduce the amount of | |
13 | housekeeping logic required to get it up and running. OGLEdit also provides | |
14 | a demonstration of the Undo/Redo capability supported by the document/view classes, | |
15 | and how a typical application might implement this feature. | |
16 | ||
17 | {\it Note:} A bug in the wxWindows document/view implementation before | |
18 | version 1.66C may cause Do/Undo to misbehave and get out of sync. If this is the case, | |
19 | please replace wxCommandProcessor::Submit with the following in wx\_doc.cpp. | |
20 | ||
21 | {\small | |
22 | \begin{verbatim} | |
23 | Bool wxCommandProcessor::Submit(wxCommand *command, Bool storeIt) | |
24 | { | |
25 | Bool success = command->Do(); | |
26 | if (success && storeIt) | |
27 | { | |
28 | if (commands.Number() == maxNoCommands) | |
29 | { | |
30 | wxNode *firstNode = commands.First(); | |
31 | wxCommand *firstCommand = (wxCommand *)firstNode->Data(); | |
32 | delete firstCommand; | |
33 | delete firstNode; | |
34 | } | |
35 | ||
36 | // Correct a bug: we must chop off the current 'branch' | |
37 | // so that we're at the end of the command list. | |
38 | if (currentCommand) | |
39 | { | |
40 | wxNode *node = currentCommand->Next(); | |
41 | while (node) | |
42 | { | |
43 | wxNode *next = node->Next(); | |
44 | delete node; | |
45 | node = next; | |
46 | } | |
47 | } | |
48 | ||
49 | commands.Append(command); | |
50 | currentCommand = commands.Last(); | |
51 | SetMenuStrings(); | |
52 | } | |
53 | return success; | |
54 | } | |
55 | \end{verbatim} | |
56 | } | |
57 | ||
58 | \section{OGLEdit files} | |
59 | ||
60 | OGLEdit comprises the following source files. | |
61 | ||
62 | \begin{itemize}\itemsep=0pt | |
63 | \item doc.h, doc.cpp: MyDiagram, DiagramDocument, DiagramCommand, MyEvtHandler | |
64 | classes related to diagram functionality and documents. | |
65 | \item view.h, view.cpp: MyCanvas, DiagramView classes related to visualisation of | |
66 | the diagram. | |
67 | \item ogledit.h, ogledit.cpp: MyFrame, MyApp classes related to the overall application. | |
68 | \item palette.h, palette.cpp: EditorToolPalette implementing the shape palette. | |
69 | \end{itemize} | |
70 | ||
71 | \section{How OGLEdit works} | |
72 | ||
73 | OGLEdit defines a DiagramDocument class, each of instance of which holds a MyDiagram | |
74 | member which itself contains the shapes. | |
75 | ||
76 | In order to implement specific mouse behaviour for shapes, a class MyEvtHandler is | |
77 | defined which is `plugged into' each shape when it is created, instead of overriding each shape class | |
78 | individually. This event handler class also holds a label string. | |
79 | ||
80 | The DiagramCommand class is the key to implementing Undo/Redo. Each instance of DiagramCommand | |
81 | stores enough information about an operation (create, delete, change colour etc.) to allow | |
82 | it to carry out (or undo) its command. In DiagramView::OnMenuCommand, when the user initiates the | |
83 | command, a new DiagramCommand instance is created which is then sent to the document's | |
84 | command processor (see wxWindows manual for more information about doc/view and command | |
85 | processing). | |
86 | ||
87 | Apart from menu commands, another way commands are initiated is by the user left-clicking on | |
88 | the canvas or right-dragging on a node. MyCanvas::OnLeftClick in view.cpp shows how | |
89 | the appropriate wxClassInfo is passed to a DiagramCommand, to allow DiagramCommand::Do | |
90 | to create a new shape given the wxClassInfo. | |
91 | ||
92 | The MyEvtHandler right-drag methods in doc.cpp implement drawing a line between | |
93 | two shapes, detecting where the right mouse button was released and looking for a second | |
94 | shape. Again, a new DiagramCommand instance is created and passed to the command | |
95 | processor to carry out the command. | |
96 | ||
97 | DiagramCommand::Do and DiagramCommand::Undo embody much of the | |
98 | interesting interaction with the OGL library. A complication of note | |
99 | when implementing undo is the problem of deleting a node shape which has | |
100 | one or more arcs attached to it. If you delete the node, the arc(s) | |
101 | should be deleted too. But multiple arc deletion represents more information | |
102 | that can be incorporated in the existing DiagramCommand scheme. OGLEdit | |
103 | copes with this by treating each arc deletion as a separate command, and | |
104 | sending Cut commands recursively, providing an undo path. Undoing such a | |
105 | Cut will only undo one command at a time - not a one to one | |
106 | correspondence with the original command - but it's a reasonable | |
107 | compromise and preserves Do/Undo whilst keeping our DiagramCommand class | |
108 | simple. | |
109 | ||
110 | \section{Possible enhancements} | |
111 | ||
112 | OGLEdit is very simplistic and does not employ the more advanced features | |
113 | of OGL, such as: | |
114 | ||
115 | \begin{itemize}\itemsep=0pt | |
116 | \item attachment points (arcs are drawn to particular points on a shape) | |
117 | \item metafile and bitmaps shapes | |
118 | \item divided rectangles | |
119 | \item composite shapes, and constraints | |
120 | \item creating labels in shape regions | |
121 | \item arc labels (OGL has support for three movable labels per arc) | |
122 | \item spline and multiple-segment line arcs | |
123 | \item adding annotations to node and arc shapes | |
124 | \item line-straightening (supported by OGL) and alignment (not supported directly by OGL) | |
125 | \end{itemize} | |
126 | ||
127 | These could be added to OGLEdit, at the risk of making it a less | |
128 | useful example for beginners. |