--- /dev/null
+%
+% %%%%%%% %%%%% %%%%%% %%%%% % %
+% % % % % % % % % %
+% % % % % % % % % %
+% %%%%%%% %%%%% %%%%%% % % %
+% % % % % % % % %
+% % % % % % % % %
+% % %%%%%% %%%%%% %%%%% % %
+%
+% By Jean Orloff
+% Comments & suggestions by e-mail: ORLOFF@surya11.cern.ch
+% No modification of this file allowed if not e-sent to me.
+%
+% A simple way to measure the size of encapsulated postscript figures
+% from inside TeX, and to use it for automatically formatting texts
+% with inserted figures. Works both under Plain TeX-based macros
+% (Phyzzx, Harvmac, Psizzl, ...) and LaTeX environment.
+% Provides exactly the same result on any PostScript printer provided
+% the single instruction \psfor... is changed to fit the needs of the
+% particular dvi->ps translator used.
+% History:
+% 1.31: adds \psforDVIALW(?)
+% 1.30: adds \splitfile & \joinfiles for multi-file management
+% 1.24: fix error handling & add \psonlyboxes
+% 1.23: adds \putsp@ce for OzTeX fix
+% 1.22: makes \drawingBox \global for use in Phyzzx
+% 1.21: accepts %%BoundingBox: (atend)
+% 1.20: tries to add \psfordvitps for the TeXPS package.
+% 1.10: adds \psforoztex, error handling...
+%2345678 1 2345678 2 2345678 3 2345678 4 2345678 5 2345678 6 2345678 7 23456789
+%
+\def\temp{1.31}
+\let\tempp=\relax
+\expandafter\ifx\csname psboxversion\endcsname\relax
+ \message{version: \temp}
+\else
+ \ifdim\temp cm>\psboxversion cm
+ \message{version: \temp}
+ \else
+ \message{psbox(\psboxversion) is already loaded: I won't load
+ psbox(\temp)!}
+ \let\temp=\psboxversion
+ \let\tempp=\endinput
+ \fi
+\fi
+\tempp
+\let\psboxversion=\temp
+\catcode`\@=11
+% Every macro likes a little privacy...
+%
+% Some common defs
+%
+\def\execute#1{#1}% NOT stupid: cs in #1 are then identified BEFORE execution
+\def\psm@keother#1{\catcode`#112\relax}% borrowed from latex
+\def\executeinspecs#1{%
+\execute{\begingroup\let\do\psm@keother\dospecials\catcode`\^^M=9#1\endgroup}}
+%
+%Trying to tame the variety of \special commands for Postscript: the
+% universal internal command \PSspeci@l##1##2 takes ##1 to be the
+% filename and ##2 to be the integer scale factor*1000 (as for usual
+% TeX \scale commands)
+%
+\def\psfortextures{% For TeXtures on the Macintosh
+%-----------------
+\def\PSspeci@l##1##2{%
+\special{illustration ##1\space scaled ##2}%
+}}
+%
+\def\psfordvitops{% For the DVItoPS converter on IBM mainframes
+%----------------
+\def\PSspeci@l##1##2{%
+\special{dvitops: import ##1\space \the\drawingwd \the\drawinght}%
+}}
+%
+\def\psfordvips{% For DVIPS converter on VAX, UNIX and PC's
+%--------------
+\def\PSspeci@l##1##2{%
+% \special{/@scaleunit 1000 def}% never read dox without trying!
+\d@my=0.1bp \d@mx=\drawingwd \divide\d@mx by\d@my%
+\special{PSfile=##1\space llx=\psllx\space lly=\pslly\space%
+urx=\psurx\space ury=\psury\space rwi=\number\d@mx}%
+}}
+%
+\def\psforoztex{% For the OzTeX shareware on the Macintosh
+%--------------
+\def\PSspeci@l##1##2{%
+\special{##1 \space
+ ##2 1000 div dup scale
+ \putsp@ce{\number-\psllx} \putsp@ce{\number-\pslly} translate
+}%
+}}
+\def\putsp@ce#1{#1 }
+%
+\def\psfordvitps{% From the UNIX TeXPS package, vers.>3.12
+%---------------
+% Convert a dimension into the number \psn@sp (in scaled points)
+\def\psdimt@n@sp##1{\d@mx=##1\relax\edef\psn@sp{\number\d@mx}}
+\def\PSspeci@l##1##2{%
+% psfig.psr contains the def of "startTexFig": if you can locate it
+% and include the correct pathname, it should work
+\special{dvitps: Include0 "psfig.psr"}% contains def of "startTexFig"
+\psdimt@n@sp{\drawingwd}
+\special{dvitps: Literal "\psn@sp\space"}
+\psdimt@n@sp{\drawinght}
+\special{dvitps: Literal "\psn@sp\space"}
+\psdimt@n@sp{\psllx bp}
+\special{dvitps: Literal "\psn@sp\space"}
+\psdimt@n@sp{\pslly bp}
+\special{dvitps: Literal "\psn@sp\space"}
+\psdimt@n@sp{\psurx bp}
+\special{dvitps: Literal "\psn@sp\space"}
+\psdimt@n@sp{\psury bp}
+\special{dvitps: Literal "\psn@sp\space startTexFig\space"}
+\special{dvitps: Include1 "##1"}
+\special{dvitps: Literal "endTexFig\space"}
+}}
+\def\psforDVIALW{% Try for dvialw, a UNIX public domain
+%---------------
+\def\PSspeci@l##1##2{
+\special{language "PS"
+literal "##2 1000 div dup scale"
+include "##1"}}}
+\def\psonlyboxes{% Draft-like behaviour if none of the others works
+%---------------
+\def\PSspeci@l##1##2{%
+\at(0cm;0cm){\boxit{\vbox to\drawinght
+ {\vss
+ \hbox to\drawingwd{\at(0cm;0cm){\hbox{(##1)}}\hss}
+ }}}
+}%
+}
+%
+\def\psloc@lerr#1{%
+\let\savedPSspeci@l=\PSspeci@l%
+\def\PSspeci@l##1##2{%
+\at(0cm;0cm){\boxit{\vbox to\drawinght
+ {\vss
+ \hbox to\drawingwd{\at(0cm;0cm){\hbox{(##1) #1}}\hss}
+ }}}
+\let\PSspeci@l=\savedPSspeci@l% restore normal output for other figs!
+}%
+}
+%
+%\def\psfor... add your own!
+%
+% \ReadPSize{PSfilename} reads the dimensions of a PostScript drawing
+% and stores it in \drawinght(wd)
+\newread\pst@mpin
+\newdimen\drawinght\newdimen\drawingwd
+\newdimen\psxoffset\newdimen\psyoffset
+\newbox\drawingBox
+\newif\ifNotB@undingBox
+\newhelp\PShelp{Proceed: you'll have a 5cm square blank box instead of
+your graphics (Jean Orloff).}
+\def\@mpty{}
+\def\s@tsize#1 #2 #3 #4\@ndsize{
+ \def\psllx{#1}\def\pslly{#2}%
+ \def\psurx{#3}\def\psury{#4}% needed by a crazyness of dvips!
+ \ifx\psurx\@mpty\NotB@undingBoxtrue% this is not a valid one!
+ \else
+ \drawinght=#4bp\advance\drawinght by-#2bp
+ \drawingwd=#3bp\advance\drawingwd by-#1bp
+% !Units related by crazy factors as bp/pt=72.27/72 should be BANNED!
+ \fi
+ }
+\def\sc@nline#1:#2\@ndline{\edef\p@rameter{#1}\edef\v@lue{#2}}
+\def\g@bblefirstblank#1#2:{\ifx#1 \else#1\fi#2}
+\def\psm@keother#1{\catcode`#112\relax}% borrowed from latex
+\def\execute#1{#1}% Seems stupid, but cs are identified BEFORE execution
+{\catcode`\%=12
+\xdef\B@undingBox{%%BoundingBox}
+} %% is not a true comment in PostScript, even if % is!
+\def\ReadPSize#1{
+ \edef\PSfilename{#1}
+ \openin\pst@mpin=#1\relax
+ \ifeof\pst@mpin \errhelp=\PShelp
+ \errmessage{I haven't found your postscript file (\PSfilename)}
+ \psloc@lerr{was not found}
+ \s@tsize 0 0 142 142\@ndsize
+ \closein\pst@mpin
+ \else
+ \immediate\write\psbj@inaux{#1,}
+ \loop
+ \executeinspecs{\catcode`\ =10\global\read\pst@mpin to\n@xtline}
+ \ifeof\pst@mpin
+ \errhelp=\PShelp
+ \errmessage{(\PSfilename) is not an Encapsulated PostScript File:
+ I could not find any \B@undingBox: line.}
+ \edef\v@lue{0 0 142 142:}
+ \psloc@lerr{is not an EPSFile}
+ \NotB@undingBoxfalse
+ \else
+ \expandafter\sc@nline\n@xtline:\@ndline
+ \ifx\p@rameter\B@undingBox\NotB@undingBoxfalse
+ \edef\t@mp{%
+ \expandafter\g@bblefirstblank\v@lue\space\space\space}
+ \expandafter\s@tsize\t@mp\@ndsize
+ \else\NotB@undingBoxtrue
+ \fi
+ \fi
+ \ifNotB@undingBox\repeat
+ \closein\pst@mpin
+ \fi
+\message{#1}
+}
+%
+% \psboxto(xdim;ydim){psfilename}: you specify the dimensions and
+% TeX uniformly scales to fit the largest one. If xdim=0pt, the
+% scale is fully determined by ydim and vice versa.
+% Notice: psboxes are a real vboxes; couldn't take hbox otherwise all
+% indentation and all cr's would be interpreted as spaces (hugh!).
+%
+\newcount\xscale \newcount\yscale \newdimen\pscm\pscm=1cm
+\newdimen\d@mx \newdimen\d@my
+\let\ps@nnotation=\relax
+\def\psboxto(#1;#2)#3{\vbox{
+ \ReadPSize{#3}
+ \divide\drawingwd by 1000
+ \divide\drawinght by 1000
+ \d@mx=#1
+ \ifdim\d@mx=0pt\xscale=1000
+ \else \xscale=\d@mx \divide \xscale by \drawingwd\fi
+ \d@my=#2
+ \ifdim\d@my=0pt\yscale=1000
+ \else \yscale=\d@my \divide \yscale by \drawinght\fi
+ \ifnum\yscale=1000
+ \else\ifnum\xscale=1000\xscale=\yscale
+ \else\ifnum\yscale<\xscale\xscale=\yscale\fi
+ \fi
+ \fi
+ \divide \psxoffset by 1000\multiply\psxoffset by \xscale
+ \divide \psyoffset by 1000\multiply\psyoffset by \xscale
+ \global\divide\pscm by 1000
+ \global\multiply\pscm by\xscale
+ \multiply\drawingwd by\xscale \multiply\drawinght by\xscale
+ \ifdim\d@mx=0pt\d@mx=\drawingwd\fi
+ \ifdim\d@my=0pt\d@my=\drawinght\fi
+ \message{scaled \the\xscale}
+ \hbox to\d@mx{\hss\vbox to\d@my{\vss
+ \global\setbox\drawingBox=\hbox to 0pt{\kern\psxoffset\vbox to 0pt{
+ \kern-\psyoffset
+ \PSspeci@l{\PSfilename}{\the\xscale}
+ \vss}\hss\ps@nnotation}
+ \global\ht\drawingBox=\the\drawinght
+ \global\wd\drawingBox=\the\drawingwd
+ \baselineskip=0pt
+ \copy\drawingBox
+ \vss}\hss}
+ \global\psxoffset=0pt
+ \global\psyoffset=0pt% These are local to one figure
+ \global\pscm=1cm
+ \global\drawingwd=\drawingwd
+ \global\drawinght=\drawinght
+}}
+%
+% \psboxscaled{scalefactor*1000}{PSfilename} allows to bypass the
+% rounding errors of TeX integer divisions for situations where the
+% TeX box should fit the original BoundingBox with a precision better
+% than 1/1000.
+%
+\def\psboxscaled#1#2{\vbox{
+ \ReadPSize{#2}
+ \xscale=#1
+ \message{scaled \the\xscale}
+ \divide\drawingwd by 1000\multiply\drawingwd by\xscale
+ \divide\drawinght by 1000\multiply\drawinght by\xscale
+ \divide \psxoffset by 1000\multiply\psxoffset by \xscale
+ \divide \psyoffset by 1000\multiply\psyoffset by \xscale
+ \global\divide\pscm by 1000
+ \global\multiply\pscm by\xscale
+ \global\setbox\drawingBox=\hbox to 0pt{\kern\psxoffset\vbox to 0pt{
+ \kern-\psyoffset
+ \PSspeci@l{\PSfilename}{\the\xscale}
+ \vss}\hss\ps@nnotation}
+ \global\ht\drawingBox=\the\drawinght
+ \global\wd\drawingBox=\the\drawingwd
+ \baselineskip=0pt
+ \copy\drawingBox
+ \global\psxoffset=0pt
+ \global\psyoffset=0pt% These are local to one figure
+ \global\pscm=1cm
+ \global\drawingwd=\drawingwd
+ \global\drawinght=\drawinght
+}}
+%
+% \psbox{PSfilename} makes a TeX box having the minimal size to
+% enclose the picture
+\def\psbox#1{\psboxscaled{1000}{#1}}
+%
+%
+% \joinfiles file1, file2, ...n \into joinedfilename .
+% makes one file out of many
+% \splitfile joinedfilename
+% the opposite
+%
+%\def\execute#1{#1}% NOT stupid: cs in #1 are then identified BEFORE execution
+%\def\psm@keother#1{\catcode`#112\relax}% borrowed from latex
+%\def\executeinspecs#1{%
+%\execute{\begingroup\let\do\psm@keother\dospecials\catcode`\^^M=9#1\endgroup}}
+%\newread\pst@mpin
+\newif\ifn@teof\n@teoftrue
+\newif\ifc@ntrolline
+\newif\ifmatch
+\newread\j@insplitin
+\newwrite\j@insplitout
+\newwrite\psbj@inaux
+\immediate\openout\psbj@inaux=psbjoin.aux
+\immediate\write\psbj@inaux{\string\joinfiles}
+\immediate\write\psbj@inaux{\jobname,}
+%
+% We redefine input to keep track of the various files inputted
+%
+\immediate\let\oldinput=\input
+\def\input#1 {
+ \immediate\write\psbj@inaux{#1,}
+ \oldinput #1 }
+\def\empty{}
+\def\setmatchif#1\contains#2{
+ \def\match##1#2##2\endmatch{
+ \def\tmp{##2}
+ \ifx\empty\tmp
+ \matchfalse
+ \else
+ \matchtrue
+ \fi}
+ \match#1#2\endmatch}
+\def\warnopenout#1#2{
+ \setmatchif{TrashMe,psbjoin.aux,psbjoin.all}\contains{#2}
+ \ifmatch
+ \else
+ \immediate\openin\pst@mpin=#2
+ \ifeof\pst@mpin
+ \else
+ \errhelp{If the content of this file is so precious to you, abort (ie
+press x or e) and rename it before retrying.}
+ \errmessage{I'm just about to replace your file named #2}
+ \fi
+ \immediate\closein\pst@mpin
+ \fi
+ \message{#2}
+ \immediate\openout#1=#2}
+% No comments allowed below: % will have an unusual catcode
+{
+\catcode`\%=12
+\gdef\splitfile#1 {
+ \immediate\openin\j@insplitin=#1
+ \message{Splitting file #1 into:}
+ \warnopenout\j@insplitout{TrashMe}
+ \loop
+ \ifeof
+ \j@insplitin\immediate\closein\j@insplitin\n@teoffalse
+ \else
+ \n@teoftrue
+ \executeinspecs{\global\read\j@insplitin to\spl@tinline\expandafter
+ \ch@ckbeginnewfile\spl@tinline%Beginning-Of-File-Named:%\endcheck}
+ \ifc@ntrolline
+ \else
+ \toks0=\expandafter{\spl@tinline}
+ \immediate\write\j@insplitout{\the\toks0}
+ \fi
+ \fi
+ \ifn@teof\repeat
+ \immediate\closeout\j@insplitout}
+\gdef\ch@ckbeginnewfile#1%Beginning-Of-File-Named:#2%#3\endcheck{
+ \def\t@mp{#1}
+ \ifx\empty\t@mp
+ \def\t@mp{#3}
+ \ifx\empty\t@mp
+ \global\c@ntrollinefalse
+ \else
+ \immediate\closeout\j@insplitout
+ \warnopenout\j@insplitout{#2}
+ \global\c@ntrollinetrue
+ \fi
+ \else
+ \global\c@ntrollinefalse
+ \fi}
+\gdef\joinfiles#1\into#2 {
+ \message{Joining following files into}
+ \warnopenout\j@insplitout{#2}
+ \message{:}
+ {
+ \edef\w@##1{\immediate\write\j@insplitout{##1}}
+ \w@{% This text was produced with psbox's \string\joinfiles.}
+ \w@{% To decompose and tex it:}
+ \w@{%-save this with a filename CONTAINING ONLY LETTERS, and no extensions}
+ \w@{% (say, JOINTFIL), in some uncrowded directory;}
+ \w@{%-make sure you can \string\input\space psbox.tex (version>=1.3);}
+ \w@{%-tex JOINTFIL using Plain, or LaTeX, or whatever is needed by}
+ \w@{% the first part in the joining (after splitting JOINTFIL into}
+ \w@{% it's constituents, TeX will try to process it as it stands).}
+ \w@{\string\input\space psbox.tex}
+ \w@{\string\splitfile{\string\jobname}}
+ }
+ \tre@tfilelist#1, \endtre@t
+ \immediate\closeout\j@insplitout}
+\gdef\tre@tfilelist#1, #2\endtre@t{
+ \def\t@mp{#1}
+ \ifx\empty\t@mp
+ \else
+ \llj@in{#1}
+ \tre@tfilelist#2, \endtre@t
+ \fi}
+\gdef\llj@in#1{
+ \immediate\openin\j@insplitin=#1
+ \ifeof\j@insplitin
+ \errmessage{I couldn't find file #1.}
+ \else
+ \message{#1}
+ \toks0={%Beginning-Of-File-Named:#1}
+ \immediate\write\j@insplitout{\the\toks0}
+ \executeinspecs{\global\read\j@insplitin to\oldj@ininline}
+ \loop
+ \ifeof\j@insplitin\immediate\closein\j@insplitin\n@teoffalse
+ \else\n@teoftrue
+ \executeinspecs{\global\read\j@insplitin to\j@ininline}
+ \toks0=\expandafter{\oldj@ininline}
+ \let\oldj@ininline=\j@ininline
+ \immediate\write\j@insplitout{\the\toks0}
+ \fi
+ \ifn@teof
+ \repeat
+ \immediate\closein\j@insplitin
+ \fi}
+}
+% To be put at the end of a file, for making an tar-like file containing
+% everything it used.
+\def\autojoin{
+ \immediate\write\psbj@inaux{\string\into\space psbjoin.all}
+ \immediate\closeout\psbj@inaux
+ \input psbjoin.aux
+}
+%
+% Annotations & Captions etc...
+%
+%
+% \centinsert{anybox} is just a centered \midinsert, but is included as
+% people barely use the original inserts from TeX.
+%
+\def\centinsert#1{\midinsert\line{\hss#1\hss}\endinsert}
+\def\psannotate#1#2{\def\ps@nnotation{#2\global\let\ps@nnotation=\relax}#1}
+\def\pscaption#1#2{\vbox{
+ \setbox\drawingBox=#1
+ \copy\drawingBox
+ \vskip\baselineskip
+ \vbox{\hsize=\wd\drawingBox\setbox0=\hbox{#2}
+ \ifdim\wd0>\hsize
+ \noindent\unhbox0\tolerance=5000
+ \else\centerline{\box0}
+ \fi
+}}}
+% for compatibility with older versions
+\def\psfig#1#2#3{\pscaption{\psannotate{#1}{#2}}{#3}}
+\def\psfigurebox#1#2#3{\pscaption{\psannotate{\psbox{#1}}{#2}}{#3}}
+%
+% \at(#1;#2)#3 puts #3 at #1-higher and #2-right of the current
+% position without moving it (to be used in annotations).
+\def\at(#1;#2)#3{\setbox0=\hbox{#3}\ht0=0pt\dp0=0pt
+ \rlap{\kern#1\vbox to0pt{\kern-#2\box0\vss}}}
+%
+% \gridfill(ht;wd) makes a 1cm*1cm grid of ht by wd whose lower-left
+% corner is the current point
+\newdimen\gridht \newdimen\gridwd
+\def\gridfill(#1;#2){
+ \setbox0=\hbox to 1\pscm
+ {\vrule height1\pscm width.4pt\leaders\hrule\hfill}
+ \gridht=#1
+ \divide\gridht by \ht0
+ \multiply\gridht by \ht0
+ \gridwd=#2
+ \divide\gridwd by \wd0
+ \multiply\gridwd by \wd0
+ \advance \gridwd by \wd0
+ \vbox to \gridht{\leaders\hbox to\gridwd{\leaders\box0\hfill}\vfill}}
+%
+% Useful to measure where to put annotations
+\def\fillinggrid{\at(0cm;0cm){\vbox{
+ \gridfill(\drawinght;\drawingwd)}}}
+%
+% \textleftof\anybox: Sample text\endtext
+% inserts "Sample text" on the left of \anybox ie \vbox, \psbox.
+% \textrightof is the symmetric (not documented, too uggly)
+% Welcome any suggestion about clean wraparound macros from
+% TeXhackers reading this
+%
+\def\textleftof#1:{
+ \setbox1=#1
+ \setbox0=\vbox\bgroup
+ \advance\hsize by -\wd1 \advance\hsize by -2em}
+\def\textrightof#1:{
+ \setbox0=#1
+ \setbox1=\vbox\bgroup
+ \advance\hsize by -\wd0 \advance\hsize by -2em}
+\def\endtext{
+ \egroup
+ \hbox to \hsize{\valign{\vfil##\vfil\cr%
+\box0\cr%
+\noalign{\hss}\box1\cr}}}
+%
+% \frameit{\thick}{\skip}{\anybox}
+% draws with thickness \thick a box around \anybox, leaving \skip of
+% blank around it. eg \frameit{0.5pt}{1pt}{\hbox{hello}}
+% \boxit{\anybox} is a shortcut.
+\def\frameit#1#2#3{\hbox{\vrule width#1\vbox{
+ \hrule height#1\vskip#2\hbox{\hskip#2\vbox{#3}\hskip#2}%
+ \vskip#2\hrule height#1}\vrule width#1}}
+\def\boxit#1{\frameit{0.4pt}{0pt}{#1}}
+%
+%
+\catcode`\@=12 % cs containing @ are unreachable
+%
+% CUSTOMIZE YOUR DEFAULT DRIVER:
+% Uncomment the line corresponding to your TeX system:
+%\psfortextures% For TeXtures on the Macintosh
+%\psforoztex % For OzTeX shareware on the Macintosh
+%\psfordvitops % For the DVItoPS converter for TeX on IBM mainframes
+ \psfordvips % For DVIPS converter on VAX and UNIX
+%\psfordvitps % For dvitps from TeXPS package under UNIX
+%\psforDVIALW % For DVIALW, UNIX public domain
+%\psonlyboxes % Blank Boxes (when all else fails).
\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.
-
-\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.
The following sections describe particular topics.
-\section{OGL overview}\label{ogloverview}
-
-\helpref{wxShapeCanvas}{wxshapecanvas}, derived from {\bf wxCanvas}, is the drawing area
-for a number of \helpref{wxShape}{wxshape} instances. Everything drawn on a
-wxShapeCanvas is derived from wxShape, which provides virtual
-member functions for redrawing, creating and destroying
-resize/selection `handles', movement and erasing behaviour, mouse
-click behaviour, calculating the bounding box of the shape, linking
-nodes with arcs, and so on.
-
-The way a client application copes with `damage' to the canvas is to
-erase (white out) anything should no longer be displayed, redraw the shape,
-and then redraw everything on the canvas to repair any damage. If quick edit
-mode is on for the canvas, the complete should be omitted by OGL and the
-application.
-
-Selection handles (called control points in the code) are implemented as
-wxRectangleShapes.
-
-Events are passed to shapes by the canvas in a high-level form, for example {\bf OnLeftClick},
-{\bf OnBeginDragLeft}, {\bf OnDragLeft}, {\bf OnEndDragLeft}. The canvas decides
-what is a click and what is a drag, whether it is on a shape or the canvas itself,
-and (by interrogating the shape) which attachment point the click is associated with.
-
-In order to provide event-handling flexibility, each shapes has an `event handler' associated with it,
-which by default is the shape itself (all shapes derive from wxShapeEvtHandler).
-An application can modify the event-handling behaviour simply by plugging a new
-event handler into the shape. This can avoid the need for multiple inheritance when
-new properties and behaviour are required for a number of different shape classes: instead
-of overriding each class, one new event handler class can be defined and used for all
-existing shape classes.
-
-A range of shapes have been predefined in the library, including rectangles, ellipses,
-polygons. A client application can derive from these shapes and/or derive entirely
-new shapes from wxShape.
-
-Instances of a class called \helpref{wxDiagram}{wxdiagram} organise collections of
-shapes, providing default file input and output behaviour.
-
-\section{wxDividedShape overview}\label{dividedshapeoverview}
-
-Classes: \helpref{wxDividedShape}{wxdividedshape}
-
-A wxDividedShape is a rectangle with a number of vertical divisions. Each
-division may have its text formatted with independent characteristics, and
-the size of each division relative to the whole image may be specified.
-
-Once a wxDividedShape has been created, the user may move the divisions with the
-mouse. By pressing Ctrl while right-clicking, the region attributes can be edited.
-
-Here are examples of creating wxDividedShape objects:
-
-{\small
-\begin{verbatim}
- /*
- * Divided rectangle with 3 regions
- *
- */
-
- wxDividedShape *dividedRect = new wxDividedShape(50, 60);
-
- wxShapeRegion *region = new wxShapeRegion;
- region->SetProportions(0.0, 0.25);
- dividedRect->AddRegion(region);
-
- region = new wxShapeRegion;
- region->SetProportions(0.0, 0.5);
- dividedRect->AddRegion(region);
-
- region = new wxShapeRegion;
- region->SetProportions(0.0, 0.25);
- dividedRect->AddRegion(region);
-
- dividedRect->SetSize(50, 60); // Allow it to calculate region sizes
- dividedRect->SetPen(wxBLACK_PEN);
- dividedRect->SetBrush(wxWHITE_BRUSH);
- dividedRect->Show(TRUE);
- dividedRect->NameRegions();
-
- /*
- * Divided rectangle with 3 regions, rounded
- *
- */
-
- wxDividedShape *dividedRect3 = new wxDividedShape(50, 60);
- dividedRect3->SetCornerRadius(-0.4);
-
- region = new wxShapeRegion;
- region->SetProportions(0.0, 0.25);
- dividedRect3->AddRegion(region);
-
- region = new wxShapeRegion;
- region->SetProportions(0.0, 0.5);
- dividedRect3->AddRegion(region);
-
- region = new wxShapeRegion;
- region->SetProportions(0.0, 0.25);
- dividedRect3->AddRegion(region);
-
- dividedRect3->SetSize(50, 60); // Allow it to calculate region sizes
- dividedRect3->SetPen(wxBLACK_PEN);
- dividedRect3->SetBrush(wxWHITE_BRUSH);
- dividedRect3->Show(TRUE);
- dividedRect3->NameRegions();
-\end{verbatim}
-}
-
-\section{wxCompositeShape overview}\label{compositeshapeoverview}
-
-Classes: \helpref{wxCompositeShape}{wxcompositeshape}, \helpref{wxOGLConstraint}{wxoglconstraint}
-
-The wxCompositeShape allows fairly complex shapes to be created, and maintains
-a set of constraints which specify the layout and proportions of child shapes.
-
-Add child shapes to a wxCompositeShape using \helpref{AddChild}{wxcompositeshapeaddchild}, and
-add constraints using \helpref{AddConstraint}{wxcompositeshapeaddconstraint}.
-
-After children and shapes have been added, call \helpref{Recompute}{wxcompositeshaperecompute} which
-will return TRUE is the constraints could be satisfied, FALSE otherwise. If
-constraints have been correctly and consistently specified, this call will succeed.
-
-If there is more than one child, constraints must be specified: OGL cannot calculate
-the size and position of children otherwise. Don't assume that children will simply
-move relative to the parent without the use of constraints.
-
-To specify a constraint, you need three things:
-
-\begin{enumerate}\itemsep=0pt
-\item a constraint type, such as gyCONSTRAINT\_CENTRED\_VERTICALLY;
-\item a reference shape, with respect to which other shapes are going to be positioned - the\rtfsp
-{\it constraining} shape;
-\item a list of one or more shapes to be constrained: the {\it constrained} shapes.
-\end{enumerate}
-
-The constraining shape can be either the parent of the constrained shapes, or a sibling. The
-constrained shapes must all be siblings of each other.
-
-For an exhaustive list and description of the available constraint types, see the \helpref{wxOGLConstraint constructor}{wxoglconstraintconstr}.
-Note that most constraints operate in one dimension only (vertically or horizontally), so you will
-usually need to specify constraints in pairs.
-
-You can set the spacing between constraining and constrained shapes by
-calling \helpref{wxOGLConstraint::SetSpacing}{wxoglconstraintsetspacing}.
-
-Finally, a wxCompositeShape can have {\it divisions}, which are special child shapes of class
-wxDivisionShape (not to be confused with wxDividedShape). The purpose of this is to allow
-the composite to be divided into user-adjustable regions (divisions) into which other shapes
-can be dropped dynamically, given suitable application code. Divisons allow the child
-shapes to have an identity of their own - they can be manipulated independently of their container -
-but to behave as if they are contained with the division, moving with the parent shape.
-Divisions boundaries can themselves be moved using the mouse.
-
-To create an initial division, call \helpref{wxCompositeShape::MakeContainer}{wxcompositeshapemakecontainer}.
-Make further divisions by calling \helpref{wxDivisionShape::Divide}{wxdivisionshapedivide}.
+\section{MMedia extension overview}\label{mmedoverview}