Outlining the Art Class Tools Menu
Using the OOPS Flow System (OFS)
By Gerry and David Kenner, Magna, Utah
About the authors
Gerry Kenner is a professional electrical and computer engineering consultant, university researcher and writer who specializes in image analysis systems for investigative scientists. David Kenner is a senior majoring in Electrical Engineering at Brigham Young University.
We can be reached on the following bulletin boards.
Internet at firstname.lastname@example.org.
Apple Link at UUTL. Prodigy at bssx14b.
We are in a new era in programming. Program size has risen by one to two orders of magnitude from the 4k to 16k programs typical of the beginning of the 1980s to 200k or more today. Further, simple command line type interfaces are being replaced by complex graphical interfaces. These changes are largely wrought by the move to object oriented programming which is in process. This results in complex programs whose structure can no longer be visualized. This is a problem in three main areas.
1. Interaction between programmers and their supervisors.
2. Program documentation for maintenance purposes.
3. Effective teaching of object oriented programming.
This article will show how we have solved this problem using a flow charting system which we have developed for THINK C with objects and the TCL library.
Flow charting is only one of several aspects of good program design. Intuitive logic plus a general perusal of program design books indicates that it has approximately four levels. For descriptive reasons we decided to name these as follows.
Flow Diagram Level.
The planning level corresponds to what Neal Goldstein and Jeff Alger call the business level in their book Developing Object-Oriented Software for the Macintosh. This is where everyone who will be involved in the project gets together and works out what kind of program is to be written. Following Goldstein and Alger, the Planning level is broken down into two sublevels, the reference and solution sublevels. The reference component is the description of how things are being done now and who is responsible for what. The solution component encompasses how we want things to work and who will be responsible for what when we are done.
This is where the overall look and feel of the program is developed. Prototyping can be done by writing a textual and pictorial description of how the program is to operate. For instance, a fairly comprehensive description of a program could be achieved by outlining the structure of its Menu Bar and contained items and providing a textual description of what happens when each item is selected. Further information could be gleaned by following the sequence of dialog boxes or windows used. The description could be completed by stating what happens during start-up and/or when high-level events are called.
In the case of the Macintosh there are several programs which can be used to build a prototype showing how the program will ultimately operate. As of this writing, these include AppMaker (Bowers, MA), Marksman (IT Makers, CA), HyperCard (Apple Computer, CA) and Serius Programmer (Serius, UT). The first two are programs which permit the programmer to build menus and windows and link them together to show the execution flow of the final program. In their current versions, C or Pascal source code can be generated with hooks which can be used for writing the final working program. HyperCard is different from the first two in that HyperScript can be used to write the entire program once the basic outline of cards, buttons and text windows has been developed. A skilled programmer can also use the TCL libraries or MacApp to develop a prototype quickly. Finally, Serius Programmer can be used if the programmer is willing to forego the generation of source code. However, it is possible with Serius Programmer to get a finished program with little or no additional coding.
Flow Diagram Level
This is the subject of this article. The idea is to generate a series of easily followed charts which can be used to pinpoint where different things occur. They are to be used to follow the logic of a program in magazine articles and can be used for archiving how the program was written.
This is where the executable source code is written.
OOPS FLOW SYSTEM (OFS)
The OFS has a project structure. The project consists of one or more subprojects. The size of a subproject is determined by how much information can be conveniently put on about half a page of flow chart with one page being maximum size.
The subproject flow chart is broken down into right and left regions, named Objects and Hooks Column and Methods Region respectively. The Objects and Hooks Column is about 1/4 the page width. It contains a column of symbols representing class-object definitions and jump-off points for executing code. The Methods Region is occupied by flow diagrams showing program execution. Special notation is used to facilitate understanding of what is going on.
When a flow chart program such as MacFlow from Mainstay is used, the right hand region has a comment box with explanatory notes about what is going on in the flow chart. This is located on the right-hand side near the top. It is linked to a symbol with invisible borders containing the word comment. It is brought up for reading and writing by executing MacFlows comment accessing command.
Figure 1 - Symbols used by OFS. See text for explanation.
An important feature of OFS is its lack of rigidity. There is a basic system of symbols used in the subproject flow charts. These are shown in Figure 1 while Figure 2 shows how some of them are used. Examples of how the others are used can be found in the second half of the article. Beyond these minimal definitions and usages, the system can be adapted to facilitate clarity in any situation.
The upper three symbols on the left side of Figure 1 are used in the Objects and Hooks Column. The Execution Start Point contains enough information that the programmer can locate where the execution of a program fragment commences. In the example, execution begins when the Start item of the File menu is selected. Whenever a new object is created in the Execution Region of the subproject, it is defined in a hexagonal shaped Object Definition symbol. The symbol is unhilited if the object was created in the subproject being outlined. If it was created in a previous project and being referred to in the current project, then this is indicated by outlining the hex symbol in bold.
The remaining symbols in Figure 1 are all used in the Methods Region of the subproject. The symbols on the right are for referring to executable code. Methods are described by giving the name of the object reference and the method being executed. Functions are identified by using the word function in place of the name of the object reference while the word ToolBox is used in the case of executing toolbox calls.
Whenever a method or function creates a new object, this is indicated by adding a third line with an o: followed by the object reference name. Information such as resource numbers can be added in a similar manner.
Notes are referenced by placing a small circle with an enclosed note number where needed. In MacFlow, this circle is created by taking the square symbol with rounded corners and making it as small as possible. Conditionals are indicated with a diamond shaped symbol while repeated operations use a circle with a line going toward the right on the bottom. Incidentally, in the old days this symbol was used to indicate the programmer was outputting to a tape drive. Arrows are used to indicate the direction of program flow.
Figure 2 - Simple example of how to use OFS. See text for details.
Notes: 1) Cycle until instruction to dismiss the dialog box is given by the EndDialog method.
In Figure 2, the selection of the About Box item of the Apple menu results in the execution of the ShowAboutBox method of the application object where a GNTCLAboutBox object is created. The IGNTCLAboutBox method of the GNTCLAboutBox class is then called. The program idles in the DoModalDialog method until a button in the About Box is clicked upon. When this happens, the event manager determines that the About Box was the active window and calls the DoCommand method of the GNTCLAboutBox object. The dialog box is closed by executing the EndDialog method.
A hexagonal box in the Objects and Hooks column shows that the object reference theAbout points to an object of class GNTCLAboutBox. Similarly, dialog references an object of the class CDLOGDialog and gApplication references an object of class GNApp. The heavy border about the latter object says that it was created in a different subproject.
The small circle with the enclosed 1 references a note which is given in the Figure caption.
The TCL Browser and THINK C Debugger
We have determined that the most effective method of using the OFS charts is to build the project in question and then use the browser and the debugger to follow the program flow as outlined in the charts. It is often useful to set breaks and examine what is happening in the program at various points.
FLOW CHARTING THE ART CLASS TOOLBOX MENU
Now for an example of how to use OFS. In the November/December 1992 issue of MacTutor, Robert J. Sanford, Jr. suggested that Art Class be dissected as an example of how to use the TCL libraries. In particular, we have found the concept of building a customized Tools menu to be one of the most complex things Art Class does.
A fair number or resources are required to build a tools menu. These include a window to display the tool palette, a menu resource, a menu definition, a font resource which stores the icons displayed and a ChGd resource which provides information about the number, orientation and size of the boxes in the palette. Specifically, Art Class.Π.rsrc contains the following resources for implementing the Tools menu.
MENU resource #101. This is named Tools. There are no menu items in the resource.
WIND resource #1003. This is named Palette. It is used by both the Tools and the Patterns menu. It is a small window which is created and moved offscreen.
ChGd resource #101. This provides the number of rows and columns as well as some dimensional information about the Tools menu. This is where the font resource %Art Class Tools is referenced.
Font resource #25728, Font Family: %Art Class Tools. Font resource #25744, %Art Class Tools 16. Fond resource #201, %Art Class Tools. These resources consist of a series of 12 icons and associated data which are drawn in the Tools menu.
MDEF resource #101. This is also named Tools. It contains 10 bytes of which the first two are the Motorola 68000 microprocessor instruction JMP. The Art Class program fills in the other 8 bytes with addresses when the it is executing.
For details of what is in these resources, examine them with ResEdit. It is important to realize that all of these resources must be created by the programmer. The resource number of the MDEF is placed in Menu resource 101 using the Edit Menu and MDEF... item of the MENU selection of ResEdit.
The Art Class Tools menu uses the following classes.
CToolsDir - Project class. Subclass of CDirector through CTearOffMenu. Implements a tearoff window.
CCharGrid - TCL class. Subclass of CPane through CPanorama, CSelector and CGridSelector. Draws grid and places font icons representing tool selections.
CSelectorMDEF - TCL class. Subclass of CMenuDefProc via CPaneMDEF. Handles selections in the menu.
CTextEnvirons - TCL class. Subclass of CEnvironment. Sets up the drawing environment for the pane.
CWindow - TCL class. Manipulates the window.
In addition to the above classes, an interface function named GenericMDEF is used to implement the MDEF.
Figure 3 shows the program flow for initializing the Tools menu. An object of class CToolsDir is created in the SetUpMenus method of CArtClass. The initialization method of this object, IToolsDir creates further objects of classes CCharGrid, CSelectorMDEF and CWindow (ITearOffMenu is called by IToolsDir). Finally, an object of CTextEnvirons is created in the ICharGrid method of the CCharGrid class. The font assigned to the CTextEnvirons object is %Art Class Tools 16.
Figure 3 - Flow diagram for initialization of the Tools menu.
Notes: 1) Gets the character grid dimensions from a ChGd resource. Draws the grid. 2) Put address of GenericMDEF function into the MDEF resource of the Tools menu. This makes the first six bytes of the MDEF a jump instruction to the beginning of GenericMDEF.
TheSelectorMDEF:IMenuDefProc places the address of GenericMDEF in the MDEF resource. The MDEF has the following structure.
/* 1 */
typedef struct GenericMDEFRec
} GenericMDEFRec, *GenericMDEFPtr, **GenericMDEFHand;
This structure is filled by IMenuDefProc as follows. Some code has been deleted for readability.
/* 2 */
void CMenuDefProc::IMenuDefProc(short MDEFid)
theMDEF = (GenericMDEFHand) GetResource('MDEF', MDEFid);
(**theMDEF).defProc = (VoidFunc) GenericMDEF;
(**theMDEF).itsMenuDefProc = this;
This code places the address of GenericMDEF in bytes 3 to 6. The first six bytes of the MDEF now constitute a JMP instruction to execute GenericMDEF. Any subsequent GetResource calls requesting the MDEF will use this copy which is in memory rather than retrieve the original resource from the resource file.
Basically, GenericMDEF consists of a case statement with four choices, mDrawMsg for drawing the menu, mChooseMsg for choosing an item, mSizeMsg for determining menu dimensions and mPopUpMsg for using popup menus.
The first time GenericMDEF is called is during SetUpMenus right after the MDEF has been set up. The mSizeMsg option is executed to find out the menu dimensions.
Once all the required objects have been created and initialized the window is moved offscreen and selected using the MoveOffScreen and Select methods of the CWindow class.
Figure 4 shows what happens when the Tools menu is selected and the cursor is moved about in its window. When the toolbox function MenuSelect is chosen, the code contained in its associated MDEF is executed. First, the mDrawMsg option is executed which draws the menu. This is done by the Draw, DrawGrid and DrawItem methods of the CCharGrid class. When drawn, the default tool will be highlighted by the toolbox function HiliteItem. If the menu is inactive, a call is made to the toolbox function PaintRect to gray it. At this point, GenericMDEF is exited although the mouse is still being held down.
As long as the mouse button is depressed, the toolbox function MenuSelect continues sending calls to GenericMDEF which are processed as shown in Figure 5. As the cursor is moved, the CSelectorMDEF object determines which item is selected and sends a message to the CCharGrid object to find and hilite it. Further, if the user tears off the menu then a message is sent to itsPane::TearOffMenu to handle it.
There are some loose ends which must be tied up before concluding this article. First of all, the desktop object must be a subclass of CFWDesktop. This is because the Tools menu uses a floating window.
Also, when desk accessories are opened and closed while Art Class is running, tear-off menus must be deactivated and activated respectively. This is done to prevent menu selections being made while the application menu bar has been switched out. To do this the SwitchFromDA and SwitchToDA methods of the CApplication class are overridden. In each new method, the ancestral class method is called first followed by gBartender->DisableMenu(MENUtools) or gBartender->EnableMenu(MENUtools) respectively.
Figure 4 - OFS diagram for drawing Tools menu when it is selected from the menu bar.
Notes: 1) Draw the menu. 2) If menu is inactive then BIC with gray. 3) If grid on draw grid lines. 4) Loop until all column and row pictures are drawn. 5) If active, hilite menu selection.
Figure 5 - OFS diagram showing how menu item selection is done.
Notes: 1) Tool menu item chosen. 2) Point is in the menu rectangle. 3) Something was chosen. 4) Tear off menu if option is enabled.
A method of following the execution flow of large object oriented programs has been presented. Experience has shown that such charts and the necessary associated text can be constructed rapidly. Once such diagrams are available, overview of a program becomes a matter of minutes rather than requiring hours of study as is the case when attempting to use annotated source code.