|
|
Sample Programs from NeXSTEP 3.3
{\rtf0\ansi{\fonttbl\f1\fnil Times-Roman;\f2\fmodern Ohlfs;}
\paperw9840
\paperh7740
\margl120
\margr120
{\colortbl;\red0\green0\blue0;}
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\f1\b0\i0\ulnone\qc\fs36\fc0\cf0 The Graph Example\
\b\ql\fs28 \
Overview\
\b0 \
\b\fi560 Graph
\b0 plots 2D line graphs of functions of the form y = f(x) and 3D surfaces given by the set of equations x = f(u,v); y = f(u,v); z = f(u,v). Important things that Graph demonstrates are being a source of Object Links, use of the 3D Kit and general NeXTSTEP programming of a small, multi-document application.\
\
The heart of the application is the
\b Expression
\b0 class. Objects of this class parse the text of mathematical expressions, and can then evaluate the expressions given a set of values for the variables found in the expression. The Expression class gives Graph a great flexibility in that it can graph novel expressions, intead of being limited to a pre-compiled set.\
\
The Expression class is built using the Unix tools
\b yacc
\b0 and
\b lex
\b0 . The parsing code will probably be confusing for anyone not familiar with these tools. However, the Expression class is designed to have a sufficiently complete interface that it can be used without understanding these internals. Hopefully, between the documentation in the header file and the example usage in this program will allow others to incorporate this object in other applications. The ability to dynamically interpret new expressions should greatly enrich applications which make modest use of formulas.\
\
The rest of the application is fairly standard NeXTSTEP programming, using the Expression class' abilities to create the data points for 2D and 3D graphs. A Display PostScript userpath is used to draw the line graph, and RenderMan is used to image the 3D surfaces. Both types of documents function as Object Link sources.\
\
\
\b\fi0 Road Map\
\b0 \
\b\fi560 Expression.m
\b0 implement the expression class. They are supported by the files
\b expr.ym
\b0 (a yacc source file),
\b token.lm
\b0 (a lex source file) and
\b exprDefs.h
\b0 (some common declarations shared between these files). The files
\b expr.m
\b0 ,
\b token.m
\b0 ,
\b y.tab.h
\b0 are by-products of the yacc and lex phases of the build.\
\
\b GraphDoc.m
\b0 and
\b GraphDoc.nib
\b0 implement a 2D Graph document. For each 2D Graph document, a GraphDoc object is created and a instance of the Graph document user interface is loaded from GraphDoc.nib. The GraphDoc object coordinates the user actions performed on the various controls, and uses an Expression object and a LineGraph view to create the graphs requested. Object Link support is implemented in GraphDoc.m.\
\
\b\fc1\cf1 LineGraph
\fc0\cf0 .m
\b0\fc1\cf1 implement a view which knows how to draw an xy line plot. It uses Display PostScript userpaths for top performance.\
\
\b\fc0\cf0 Graph3DDoc.m
\b0 and
\b Graph3DDoc.nib
\b0 implement a 3D Graph document. For each 3D Graph document, a GraphDoc object is created and a instance of the 3DGraph document user interface is loaded from Graph3DDoc.nib. The Graph3DDoc object uses three Expression objects to evaluate the user's equations, a PointMesh surface to render the data and a RotatorCamera to view it. Object Link support is implemented here also.\
\
\b PointMesh
\fc1\cf1 .m
\b0 is a subclass of N3DShape, which uses a RenderMan bilinear patch mesh to render a two dimensional mesh of points in 3-space (the sort of surfaces Graph plots).\
\
\b\fc0\cf0 RotatorCamera
\fc1\cf1 .m
\b0 is a small subclass of N3DCamera. Its only purpose is to implement the mouse tracking needed to use a N3DRotator to rotate the graph. \
\
\b\fc0\cf0 ThreeDPanel.m
\b0\fc1\cf1 and
\b\fc0\cf0 ThreeDPanel.nib
\b0\fc1\cf1 implement a very simple accessory panel to allow the user to change a few attributes of the 3D graphs.\
\fc0\cf0 \
\b\fc1\cf1 GraphApp.m
\b0 and
\b GraphApp.h
\b0 implement the delegate of NXApp. There is one instance of this class in the entire application. This class mostly responds to non-document specific commands, such as putting up the Help or Info panels. It also receives messages from the Workspace Manager to open documents. Finally it is the keeper of the application's NXStringTable, which holds the strings used by Graph, translated to a particular language.\
\
\b GraphApp.nib
\b0 holds the global user interface for the program, such as the menus. It also holds the application's small NXStringTable. These strings are loaded from the file
\b\fi0 Graph.strings
\b0 .
\b Help.nib
\b0 and
\b Info.nib
\b0 hold the user interface for the Help and Info panels.\
\
\b\fi560 AppIcon.tiff
\b0 ,
\b DocIcon.tiff
\b0 and
\b DocIcon3D.tiff
\b0 hold the images for the application and document icons.
\fi0
\b\fi560 Graph.h
\b0 is used to make the precompiled header file,
\b Graph.p
\b0 .
\b\fi0 Makefile
\b0 ,
\b Graph_main.m
\b0\fi560 ,
\b PB.project
\b0 ,
\b PB.gdbinit
\b0 and
\b\fi0 Graph.iconheader
\b0 are the usual files that
\fi560 Project
\fi0 Builder manages.
\b Makefile.postamble
\b0 and
\b Makefile.preamble
\b0 contain a few additions to the build process.
\b vers.c
\b0 is a derived file created by the
\b vers_string
\b0 command as part of the build process. It contains some useful version information about the program.
\fi560 \
\
\
\b\fi0 Highlights\
\b0 \
\fi560 GraphDoc and Graph3DDoc have the minimal amount of code needed to make a simple document be an Object Link source.\
\
The PointMesh class shows how to turn a set of data points in 3-space into a surface RenderMan can display.\
\
The RotatorCamera shows the minimal glue needed to use the N3DRotator class to manipulate an Object. However, there should be more user feedback during the rotation, such as a lightly overlaid virtual sphere to give the user some idea of the rotation axes he is working with.\
\
GraphDoc's and Graph3DDoc's
\b -copyGraph:
\b0 methods are a good example of how simple it is to implement copying a view's PostScript or RenderMan into the Pasteboard. Normally this wouldn't be a separate command in the user interface, but this was done because there is no notion of selection in the view where the graph is drawn.\
\
The GraphApp class is a good example of the minimal amount of glue you need to respond to Workspace messages to open documents (see
\b -appOpenFile:type:
\b0 and
\b -appAcceptsAnotherFile:
\b0 ). The
\b -appDidInit:
\b0 method shows how to open a new document when launched if the user didn't double click on a document.\
\
GraphDoc has a good use of TypedStreams for reading and writing its documents.\
\
The save methods in GraphDoc might be helpful in dealing with the various cases of saving.\
\
LineGraph has a nice example of userpaths. It stores its data in a form that can be directly passed to
\b DPSDoUserPath()
\b0 .\
\
In LineGraph.m,
\b drawSelf::
\b0 and
\b drawAxes()
\b0 have a PostScript trick of maintaining a consistent line width regardless of how the view has been zoomed.\
\
Graph takes a fairly minimal approach to localization. Since it has so few strings, the strategy of putting them in one global NXStringTable works fine. Any real application will want to break up their strings into tables along functional boundaries.\
\pard\tx960\tx1920\tx2880\tx3840\tx4800\tx5760\tx6720\tx7680\tx8640\tx9600\fc1\cf1 \
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\fi560\fc1\cf1 \
\b\fi0 Less exemplary parts (exercises for the reader?)\
\pard\tx960\tx1920\tx2880\tx3840\tx4800\tx5760\tx6720\tx7680\tx8640\tx9600\fc1\cf1 \
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\b0\fi560\fc1\cf1 GraphDoc and Graph3DDoc share a lot of code. Some common functionality could certainly be factored out into an abstract super-class, eliminating the current code duplication.\
\b \
\b0 Graph needs some good icons for itself and its documents!\
\b \
\b0 A SplitView couple be used to enlarge the viewing area of the graphs. I think it would be best to slide the lower half of the window down instead of covering it from top to bottom, since the parameter sliders are more useful than those controlling the domain.\
}
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.