0fc1a7137c
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@305 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
129 lines
5.3 KiB
TeX
129 lines
5.3 KiB
TeX
\chapter{OGLEdit: a sample OGL application}\label{ogledit}%
|
|
\setheader{{\it CHAPTER \thechapter}}{}{}{}{}{{\it CHAPTER \thechapter}}%
|
|
\setfooter{\thepage}{}{}{}{}{\thepage}
|
|
|
|
OGLEdit is a sample OGL application that allows the user to draw, edit,
|
|
save and load a few shapes. It should clarify aspects of OGL usage, and
|
|
can act as a template for similar applications. OGLEdit can be found in\rtfsp
|
|
{\tt samples/ogledit} in the OGL distribution.
|
|
|
|
$$\image{10cm;0cm}{ogledit.eps}$$\par
|
|
|
|
The wxWindows document/view model has been used in OGL, to reduce the amount of
|
|
housekeeping logic required to get it up and running. OGLEdit also provides
|
|
a demonstration of the Undo/Redo capability supported by the document/view classes,
|
|
and how a typical application might implement this feature.
|
|
|
|
{\it Note:} A bug in the wxWindows document/view implementation before
|
|
version 1.66C may cause Do/Undo to misbehave and get out of sync. If this is the case,
|
|
please replace wxCommandProcessor::Submit with the following in wx\_doc.cpp.
|
|
|
|
{\small
|
|
\begin{verbatim}
|
|
Bool wxCommandProcessor::Submit(wxCommand *command, Bool storeIt)
|
|
{
|
|
Bool success = command->Do();
|
|
if (success && storeIt)
|
|
{
|
|
if (commands.Number() == maxNoCommands)
|
|
{
|
|
wxNode *firstNode = commands.First();
|
|
wxCommand *firstCommand = (wxCommand *)firstNode->Data();
|
|
delete firstCommand;
|
|
delete firstNode;
|
|
}
|
|
|
|
// Correct a bug: we must chop off the current 'branch'
|
|
// so that we're at the end of the command list.
|
|
if (currentCommand)
|
|
{
|
|
wxNode *node = currentCommand->Next();
|
|
while (node)
|
|
{
|
|
wxNode *next = node->Next();
|
|
delete node;
|
|
node = next;
|
|
}
|
|
}
|
|
|
|
commands.Append(command);
|
|
currentCommand = commands.Last();
|
|
SetMenuStrings();
|
|
}
|
|
return success;
|
|
}
|
|
\end{verbatim}
|
|
}
|
|
|
|
\section{OGLEdit files}
|
|
|
|
OGLEdit comprises the following source files.
|
|
|
|
\begin{itemize}\itemsep=0pt
|
|
\item doc.h, doc.cpp: MyDiagram, DiagramDocument, DiagramCommand, MyEvtHandler
|
|
classes related to diagram functionality and documents.
|
|
\item view.h, view.cpp: MyCanvas, DiagramView classes related to visualisation of
|
|
the diagram.
|
|
\item ogledit.h, ogledit.cpp: MyFrame, MyApp classes related to the overall application.
|
|
\item palette.h, palette.cpp: EditorToolPalette implementing the shape palette.
|
|
\end{itemize}
|
|
|
|
\section{How OGLEdit works}
|
|
|
|
OGLEdit defines a DiagramDocument class, each of instance of which holds a MyDiagram
|
|
member which itself contains the shapes.
|
|
|
|
In order to implement specific mouse behaviour for shapes, a class MyEvtHandler is
|
|
defined which is `plugged into' each shape when it is created, instead of overriding each shape class
|
|
individually. This event handler class also holds a label string.
|
|
|
|
The DiagramCommand class is the key to implementing Undo/Redo. Each instance of DiagramCommand
|
|
stores enough information about an operation (create, delete, change colour etc.) to allow
|
|
it to carry out (or undo) its command. In DiagramView::OnMenuCommand, when the user initiates the
|
|
command, a new DiagramCommand instance is created which is then sent to the document's
|
|
command processor (see wxWindows manual for more information about doc/view and command
|
|
processing).
|
|
|
|
Apart from menu commands, another way commands are initiated is by the user left-clicking on
|
|
the canvas or right-dragging on a node. MyCanvas::OnLeftClick in view.cpp shows how
|
|
the appropriate wxClassInfo is passed to a DiagramCommand, to allow DiagramCommand::Do
|
|
to create a new shape given the wxClassInfo.
|
|
|
|
The MyEvtHandler right-drag methods in doc.cpp implement drawing a line between
|
|
two shapes, detecting where the right mouse button was released and looking for a second
|
|
shape. Again, a new DiagramCommand instance is created and passed to the command
|
|
processor to carry out the command.
|
|
|
|
DiagramCommand::Do and DiagramCommand::Undo embody much of the
|
|
interesting interaction with the OGL library. A complication of note
|
|
when implementing undo is the problem of deleting a node shape which has
|
|
one or more arcs attached to it. If you delete the node, the arc(s)
|
|
should be deleted too. But multiple arc deletion represents more information
|
|
that can be incorporated in the existing DiagramCommand scheme. OGLEdit
|
|
copes with this by treating each arc deletion as a separate command, and
|
|
sending Cut commands recursively, providing an undo path. Undoing such a
|
|
Cut will only undo one command at a time - not a one to one
|
|
correspondence with the original command - but it's a reasonable
|
|
compromise and preserves Do/Undo whilst keeping our DiagramCommand class
|
|
simple.
|
|
|
|
\section{Possible enhancements}
|
|
|
|
OGLEdit is very simplistic and does not employ the more advanced features
|
|
of OGL, such as:
|
|
|
|
\begin{itemize}\itemsep=0pt
|
|
\item attachment points (arcs are drawn to particular points on a shape)
|
|
\item metafile and bitmaps shapes
|
|
\item divided rectangles
|
|
\item composite shapes, and constraints
|
|
\item creating labels in shape regions
|
|
\item arc labels (OGL has support for three movable labels per arc)
|
|
\item spline and multiple-segment line arcs
|
|
\item adding annotations to node and arc shapes
|
|
\item line-straightening (supported by OGL) and alignment (not supported directly by OGL)
|
|
\end{itemize}
|
|
|
|
These could be added to OGLEdit, at the risk of making it a less
|
|
useful example for beginners.
|