TweetFollow Us on Twitter

OOP Architectures 1
Volume Number:7
Issue Number:1
Column Tag:OOP Architectures

MacApp and THINK Class Library

By Larry Rosenstein, Apple Computer, Inc.; Joseph S. Terry, Jr., Ajalon Corporation

Part I

Object-oriented Design (OOD) ...

Design is the most difficult and important task of Object Programming (OP) and very few professional software engineers do it well. Everyone claims they know how to do it. Sure, lots of people use C++, Object PASCAL, and THINK C (i.e. C+-). Many software companies have made huge investments in training personnel in MacApp or TCL. Yet, with all the knowledge programmers have about programming in object-oriented languages, little time and effort has been spent on the radical difference in how one should design object-based programs.

Good design requires a through knowledge of the class library architecture that you’re using. If you know the architecture you’re fitting your code into, you can take maximum advantage of the facilities already there. An experienced OP practitioner with a solid knowledge of his or her class library will find as many ways of using existing code as other programmers find reasons to create new code, maybe more. The OP practitioner, obviously, will produce, on average, fewer bugs per hour coding and will produce more tasks accomplished per hour than their clever prodigiously coding colleague.

The following is an introductory article on MacApp and the THINK Class Library, two of the most prominent OP architectures on the Macintosh. The focus of these articles again is NOT how to program in the respective environments, but their functional design or architecture. How do they perform? What happens when you click on a window? What is the path of messages? This architectural knowledge is something that is either gained “in the trenches” or not at all. Many writers on Object-oriented Programming (OOP) do not find this subject nearly as important as “method internal” issues.

When designing any form whether it is a house, or a bridge, or a computer circuit or a program you need guidepost design rules to be used as a starter for a design. These rules would be different for each application type and established “design school” creating a spreadsheet-like shopping list of “object design rules” with application type along the top, above each column and each of the design schools listed on each row.

For OP program design one major division is the world inside of methods/routines vs. the world outside. One of the simplest rules is simply to separate, in your programs and your mind, the states of the hexadecimal, pointer driven, interrupt driven, server or client driven world, inside the message handlers of objects and the world outside which, if relieved of lower-level state maintenance, can become an object machine, in that, assumptions made are based on a very precise, very flexible model of process which is only dependent on input or well defined and flexible object states. Any class library is like a high level program interpreter that processes messages, changes state, and propagates states to other objects. The stack pointer is really just the current object and the program counter is the current message being serviced.

In OP, as in the software engineering of the recent and distant past, the focus has always been on detailed implementation issues and performance, algorithms and data structures, saving a little time here or a little space there. Nothing has changed. The experienced OP crafts-person is as concerned with “efficiency” as the early instruction cycle counting programmers (some still do that!). The efficiency sought is sought in the operation of a logical machine, the class library.

The difference in OOP is that the “space and time” issues are one level of abstraction removed from the “bare semi-metal”. Efficient use of space implies you would use the instance variables of super classes (whenever possible) and not gratuitously create a local or a global. But, when you do create instance variable data structures you can create them at the lowest level of the machine for efficiency. You can be positive that no other object will ever access your primitive data structures (without your consent). Efficient use of time means simply, to rely on another method to handle it. Passing the buck must be the most efficient operation implemented on any computer. The most efficiently written OOP method does nothing, it takes no time and no space,... let the class library handle it.

For some reason, articles that I have read about OP are mostly centered on implementing a particular facility (e.g. pop-up menus) or function in an OP framework. This is great for an experienced “software architect” (yes, you may call yourself that) with a specific problem, but it does nothing to help those that are just hanging onto the discussion with their fingernails.

Some authors seem to think that we would be offended by “another” discussion on architecture...

Larry and I want many more discussions of architecture, design, and other issues which are not directly related to the latest implementation techniques or trap calls. When a newcomer to OP ask’s his or her first questions, it is usually of the type “What do I override to affect this or that behavior?”. These are the kinds of questions that a good knowledge of class library architecture and this article will address.

As a first definition of OOD I offer:

“Object-oriented design is the method which leads to software architectures based on the objects every system or subsystem manipulates (rather than “the” function it is meant to ensure).”3

This is contrary, in a fundamental sense, to the nature of software engineering as it is practiced in the most of the free world (and beyond). In the C language, programmers are taught to call the fundamental algorithmic building blocks of the language “functions”. To explain a “function” in terms other than “what it does”, such as “what it does it to”, might seem most strange yet that is a primary focus of OOD technique. Having said that, functional design is what we are interested in here. How is the function or purpose of these libraries enhanced/retarded by the designs chosen?

Consider this article a proposal for a regular feature in MacTutor that would tackle these issues in a rigorous way and at the same time provide hard facts and cool source code for the working-stiff programmer who must make sense of these issues to produced better, more reliable, more maintainable programs (somebody like me!) -- Tell our favorite editor what you think!.

• How are these two architectures put together to make programming the Macintosh easier?

• What are some of the design decisions that are easily reversed and some that are not so easily reversed?

• What kind of applications are they “best” for?

The structure of each article will be roughly the same. We will attempt to answer the same questions in each so that a comparative picture of the architectures will emerge. We will attempt a comparative architectural analysis in the summary at the end of Part Two. In this first, of a two-part article we will address the first five sections in the following list of sections and subsections.

 1 - BIT O’ HISTORY
 2 - ARCHITECTURAL OVERVIEW
 3 - HOW THINGS WORK TOGETHER: An Example Message Trail
 4 - STORING INFORMATION
 A)APPLICATION->DOCUMENT->FILE RELATIONSHIPS
 B)IN MEMORY DATA STRUCTURES
 5 - DISPLAYING INFORMATION
 A)APPLICATION->WINDOW->VIEW RELATIONSHIPS
 6 - EXECUTING COMMANDS
 A)CONTROLLING THE CHAIN OF COMMAND
 B)TO UNDO OR NOT TO UNDO
 7 - FLOW OF CONTROL
 8 - LOW MEMORY CONDITIONS
 9 - PRINTING
 10 - BACKGROUND TASKS
 11 - ERROR HANDLING
 12 - SUMMARY

MacApp - The E x p a n d a b l e Application

Larry Rosenstein

Apple Computer, Inc.

BIT O’ HISTORY

To understand the MacApp architecture, it helps to understand a bit of its history and how we developed MacApp. MacApp 2.0 is really the 3rd generation of an object-oriented application framework.

The roots of MacApp go back to the early 1980’s and the Lisa project. Larry Tesler and other Lisa software engineers realized that developing interactive, graphical applications was difficult, and well-suited to an object-oriented approach. The result was the Lisa Toolkit. Several developers outside of Apple used the Toolkit to develop Lisa applications, but the Toolkit “died” along with the Lisa operating system. We began the MacApp project soon after, in order to provide the same kind of programming interface on the Macintosh O/S.

We followed the same approach when developing both the Lisa Toolkit and MacApp architectures. First, we examined the source code for existing applications, in order to discover the parts common to all applications. At the same time we looked for useful implementation techniques that individual programmers had learned, so that they could be incorporated once and for all in the application framework.

Second, we identified the basic elements of each application, and created a class that corresponded to each. Some of the obvious elements are the application itself, document, and window. A less-obvious element is the command. The result was the basic classes that make up MacApp: TApplication, TDocument, TWindow, and TCommand.

Of course, the actual design was a bit more complicated than that. We made various refinements to the set of classes as we went along. For example, different menu commands apply to different parts of the application; Quit applies to the application as a whole, while Save applies to the Document. This led us to implement a class (TEvtHandler) responsible for handling menu commands, as well as other kinds of events.

We also made some compromises in the design, for implementation reasons. Menus and menu items are important elements of a Macintosh application, but we did not implement corresponding classes in MacApp (or the Lisa Toolkit). The main reason was to avoid keeping in memory a separate object for each menu item.

We made other compromises in the name of simplification, based on developers’ experiences with the Lisa Toolkit. For example, the Toolkit had separate TSelection and TView classes that represented a selection and an visible representation of some data. In MacApp, however, the role of TSelection was folded into TView, because we found that there was often a 1-to-1 correspondence between TSelection and TView classes.

Most recently, however, the tide is turning in the opposite direction. Developers using MacApp are creating more sophisticated applications, which in turn demand more sophistication in MacApp itself. One example is the view mechanism in MacApp 2.0, which allows you to easily create complicated window layouts. This trend is continuing in MacApp 3.0.

ARCHITECTURAL OVERVIEW

There are 4 classes that make up the core of MacApp: TApplication, TDocument, TView, and TCommand.

• TApplication is responsible for the application’s main event loop, which receives events and distributes them to other parts of the application. It also handles commands that apply to the application as a whole. There is only one application object in existence.

• TDocument contains the data associated with an open document. It is responsible for manipulating that data as well as reading & writing it. An application creates a document object for each opened document; there may be several application-specific subclasses of TDocument, if the application handles more than one kind of document.

• TView is responsible for displaying some data on the screen. Views form a hierarchy, with the window at the root. Each view defines its own drawing space, and clips the drawing of its child views. Since the view is responsible for the visual appearance of the data, it also takes care of interpreting mouse clicks within its boundaries.

Figure: The Class Inheritance Tree for MacApp2.0. Taken from Into to MacApp 2.0, pg. 78

There are many views allocated for each open window. For example, a simple window with 2 scroll bars and a single scrolling area is implemented with 5 separate views.4 MacApp includes a library of view classes that can be put together, using the ViewEdit application, to define the appearance of a window.

You normally creates a subclass of TView to display application-specific data. Most dialogs, however, can be constructed entirely out of views supplied by MacApp. In that case, you only have to worry about what happens when the user clicks in the dialog.

• TCommand represents a command to be executed and/or undone. It also handles mouse tracking.5 You create one subclass of TCommand for each kind of mouse tracking or command. In many cases, the same command subclass can handle more than one user command. For example, cut, copy, and clear are often handled by the same class.

You create an instance of the appropriate command class in response to menu selections, typing, or mouse clicks, and return the command object to MacApp, MacApp then takes care of calling methods of the command object to handle tracking and/or command execution.

HOW THINGS WORK TOGETHER

To see how these classes work together, let’s assume we have an application running, and the user opens a document. Opening a document is an application-level command (since the command is available at all times), and it handled by the TApplication subclass.

TApplication calls a method (that you override) that creates a document object appropriate to the kind of file being opened. MacApp then calls a document method that reads the document from disk. Finally, MacApp calls a method that creates a view hierarchy (including a window) for displaying the document.

There are 2 things to note about this process. First, is that you only write code that creates the document object, reads the document from disk, and creates the view hierarchy. You don’t have to write any code for selecting a menu command or opening/closing the disk file; MacApp takes care of these things for you.

Second, once you’ve written these methods, MacApp can use them in other situations. One example is the case when the user opens a document in the Finder. Another, is when the user chooses the Revert to Saved command. In that case, the Finder will call your document reading method to reread the document from disk.

Now that we have a window on the screen, suppose that the user clicks the mouse. The TApplication class receives the mouseDown event, since it implements the application’s main event loop. TApplication then categorizes the mouse press. If the click is in the menu bar or in the structure part of the window (title bar, close box, etc.) then MacApp takes care of processing the click without any of your code getting involved.

Suppose the click was in the menu bar. In that case, MacApp takes care of pulling down the menu and selecting an item. The (menu id, item number) pair returned by the Menu Manager is mapped to a command number. MacApp uses command numbers to identify menu items because these are easier to handle (they are 2-byte integers) and it allows you to rearrange menu items without recompiling the program.

The command number of the selected item is passed to the “target.” The target is the object in the application that gets the first chance at processing the menu selection. If it chooses not to handle the command, it passes the command number to the next object in a chain of event-handlers. Generally, this chain follows the view hierarchy upward until it reaches the window (the root of the view hierarchy); then it proceeds to the document object and finally the application object.

Unless there’s a program bug, some object in the chain will handle the command.6 In most cases, it does so by creating a command object and returning it to MacApp. MacApp then calls the DoIt method of the command object, in order to perform the command. The command object not only performs the command, but also saves enough information so that the command can be undone. If the user does select the Undo command, MacApp calls the UndoIt method of the same command object.

Instead, suppose the mouse click was within the content of the window. In that case, MacApp locates the view in the hierarchy on which the user clicked by starting at the root of the view hierarchy and following it down. MacApp then calls a method of that view to handle the mouse click. In most cases, the view creates a command object that tracks the mouse while the user presses the mouse button.

MacApp takes care of getting the current mouse position and passing it to the tracker object. It also takes care of automatically scrolling the view if the user moves the mouse outside it. When the user releases the button, the tracker returns a command object (usually itself) that encapsulates the action (e.g., sketching a shape). That command object is handled as described above.

Note the difference between handling a mouse click and menu command. Since a mouse click involves a position in the window, it is handled by searching down the view hierarchy. A menu selection has no positional information; it is handled by starting at the target (the current focus of attention) and working your way upward.

Figure: MacApp View Tree. Taken from Intro to MacApp 2.0, pg. 87

STORING INFORMATION

An important part of every application is its internal data structures. These structures determine the kinds of features the application can support, and how fast the application works. In most applications, the user opens a document in order to work with a certain set of data.

In MacApp, the TDocument class is used to store a document’s data structures. MacApp does not impose any requirements or restrictions on how you implement your internal data structures; you do not even have to use an object-oriented language. This makes it possible to use libraries of code that you might have already implemented.

Normally, you would define methods in your document class to access and modify the internal data structures. Command objects, would call these methods to perform and undo commands. View objects would call these methods to access that data to be displayed.

The application object creates a document object in response to a New or Open command (as well as to opening icons in the Finder). This process involves 2 methods of TApplication. First, is KindOfDocument, which maps information about: (1) the document being opened (its file type, name, etc.) and (2) the command that started the process into a single integer. This number is passed to the second method, TApplication.DoMakeDocument, which creates the appropriate document object based on the number. Once the document object has been created, it is possible to send it a message to either initialize itself to a blank document or read itself from a disk file.

MacApp handles the details of getting the document name (either from a Standard File dialog or from the Finder) and opening the disk file. You simply have to create the appropriate document object, and write code that reads the disk file into memory.

Saving a document is more complicated because of the possible variations. In addition to the normal Save command, MacApp supports Save As..., which saves the document under a new name, and Save A Copy..., which saves a snapshot in a new file, while continuing to edit the original document. Also, in order to prevent the user from losing data, MacApp saves a document into a temporary file; it doesn’t delete the original version until the save is successful.

As in the case of Open, MacApp takes care of the messy details of saving, such as creating and opening the file, renaming it after the save succeeds, etc. You simply write a method that tells MacApp how much disk space the document needs, and a method that writes the document to disk.

DISPLAYING INFORMATION

Once we have the document in memory, we have to display it on the screen. In MacApp, this is done using a view object. The view is responsible for drawing the data on the screen, as well as interpreting mouse clicks within itself.

In MacApp, views form a hierarchy, with the window as the root. In other words, each view has a list of subviews, and a reference to its superview. Each view defines its own coordinate system. When drawing, it doesn’t have to take into account its location within its superview. Also, drawing within a view (including drawing done by its subviews) is clipped to the view’s boundary.

Drawing is done using QuickDraw. Before drawing within a view, therefore, we need to set the current grafPort, clipping, and origin. This is done by the view’s Focus method. In most cases, MacApp focuses on a view before calling that view’s drawing method.

A view hierarchy is created by the document object. When opening a document, MacApp calls the method TDocument.DoMakeViews after the document has been read from disk (or initialized to a blank document). This method is responsible for creating one or more windows, each with the appropriate hierarchy of views. It is possible to have more than one view of a document; for example, you can view a series of numbers as a table or as a graph.

Although you can create each view individually and connect them together in the desired hierarchy, it is more convenient to create the entire hierarchy from a view resource.7 MacApp includes an application called ViewEdit, which allows you to graphically create and arrange views, and which creates the corresponding view resources.8

A view resource contains the class name of each view, as well as the view’s attributes (such as its superview, its size, and its location within its superview). Creating a view hierarchy from a resource relies on MacApp’s mechanism for creating an object given its class name as a string. MacApp reads the view’s class name from the resource, creates the appropriate object, and finally calls the view’s IRes method to initialize the view using the attributes in the resource.

In most applications, you have to define a subclass of TView that will display your application’s data on the screen. MacApp also includes many utility views that you use to construct your window.

For example, there is a view class that represents a standard Macintosh scroll bar. And there is a scroller class, which manages scrolling. To build a simple scrolling window, therefore, you place your custom view within a scroller, and place the scroller along with 2 scroll bars within a window.

MacApp also includes a set of control views (buttons, check boxes, radio clusters, pop-up menus, etc.), a view that interfaces to TextEdit, and a view that implements tables (a List Manager-replacement).

SYMANTEC’s THINK Class Library (TCL)

Joseph S. Terry, Jr.

Ajalon Corporation

BIT O’ HISTORY

The first commercial version of TCL was available in July 1989. At the Boston MacWorld in August 1988, a friend gave Symantec a demonstration of something that Greg H. Dow had done. They obviously liked what they saw and committed to making the THINK Class Library an integral part of their product. The PASCAL version was completed for the introduction of THINK Pascal 3.0 around January 1990.

I asked Greg Dow, “Was TCL based on MacApp?”. There are remarkable similarities and correspondences in the form and function of some classes. Greg said that the TCL was not based on MacApp, but that there are certain design imperatives, on a Macintosh, that clearly can only be addressed in a straight forward manner in a very few ways.

Greg is the editor for a new publication called SPLAsh, Symantec Programming Languages Association.9 This organization is dedicated to providing pertinent and practical information about using the Symantec Languages, C and Pascal, and the class library I discuss in this article which is available for C and Pascal.

ARCHITECTURAL OVERVIEW

To understand TCL requires that certain common words and phrases that are used in precise ways within TCL are defined and explained. All macintosh system events are translated into one of two different kinds of special TCL event, direct commands and visual messages. Objects may send these special TCL events to each other as well as receive them through “normal” channels.

Direct Command

Usually the result of a menu choice, these commands can also be sent from one object to another. This is used to trigger a specific action from an object or it’s ancestors.

Visual Messages

Macintosh events that affect the appearance of the application such as mouse clicks in window contents, activate events, and update events.

Bureaucrat

An abstract class which implements a link in the chain of command. Most objects are descendents of this class.

Supervisor

An object that is a Bureaucrat that is passed a command if the current object cannot respond to the command.

Chain of Command

The path through objects from the first recipient of a direct command (contained in the ‘gGopher’ global variable) to it’s supervisor and so on to the last one in the list, the application itself. Every object in the chain of command is a subclass of Bureaucrat.

Application

An abstract class that is a direct descendent of Bureaucrat. There is only one of these objects per application run and it is always the highest level in the chain of command.

Visual Hierarchy

Includes all of the object classes that can be seen on the screen. All of these objects are subclasses of View.

Director

An abstract class that is a direct descendent of Bureaucrat which manages the communication between an application and a window.

Document

An abstract class that is a direct descendant of Director. The Director contains the reference to the window. The Document contains the reference to the file associated with that window and the “pane” or visual content of the window. Documents are the appropriate place to put the majority of the methods that present and manipulate this “kind” of information. (as in document kind)

View

An abstract class that is a direct descendent of Bureaucrat used to implement all objects which have a visual representation. These include Buttons, Scrollbars and Text items.

Pane

An abstract class that is a direct descendent of View and the basic drawing area on screen. Each pane has its own drawing environment and coordinate system. Window “panes” are the key concept of building screen displays in TCL. Each pane has an enclosure and a supervisor. The enclosure is either a window or another pane. It is the enclosure that determines if a pane will receive mouse clicks. If, for instance, you wanted to disable a large portion of a screen from active mouse clicks in an interactive way, you could simple set the largest enclosing pane’s instance variable ‘wantsClicks’ inherited from the View class to false. You would do this by sending the message SetWantsClicks() with the parameter FALSE. This is true, of course, because all intervening panes must be willing to pass a click on to a subview before the little guys can respond to anything. Visual messages flow as follows:

DeskTop->Window->MainPane->SubPane/SubView->Hit!->DoClick()

Switchboard

An abstract class that is a direct descendent of CObject the “root” object. There is usually only one switchboard object per application. The switchboard processes “ordinary” Macintosh events into “chain of command” events usually passed to the ‘gGopher’ global and “visual messages” usually passed on to the object in the ‘gDesktop’ global, the top object in the visual hierarchy. This object is usually an instance of the Desktop class. The Desktop class is a direct descendent of the View class and therefore is a kind of Bureaucrat which receives and/or passes on commands.

The 7 most important classes that make up the core of TCL are: CBureaucrat, CApplication, CDirector, CDocument, CView, CPane, CSwitchboard.

Figure: The THINK Class Inheritance Tree. Taken from the THINK C Manual, pg. 197

HOW THINGS WORK TOGETHER

Using the same example as used for MacApp. We have an application running, and the user opens a document.

First, we will follow a command to open a document as it percolates through the object hierarchy.

Step 1

We will select the open command from the file menu with the mouse, the Switchboard Object would categorize the mouseDown event, in ProcessEvent(), and send a “DoMouseDown()” message to itself.

Step 2

DoMouseDown in the Switchboard object then sends a “DispatchClick()” message to the object in the ‘gDeskTop’ global variable. After the DispatchClick() returns, DoMouseDown() saves the mouseDown information in a global called ‘gLastMouseDown’ to facilitate the handling of double and triple click sensing.

Step 3

DispatchClick() in the DeskTop object determines the location of the mouseDown. We are now, briefly, in the visual hierarchy. Upon determining that a menu has been chosen the DeskTop object sends the command associated with the menu to the object in the global ‘gGopher’.

Each menu item can have a positive integer associated with it through the resource used to store the menu or through procedures in the Bartender class. (as in ‘Menu Bar’-tender). These command numbers remain constant throughout program development and allow a programmer to rearrange the menus drastically, without affecting how and who responds to the commands from that menu’s items. Whether the items are selected using command key equivalents or the mouse, if they are normal menus, pop-ups, or hierarchicals, the same command number will be generated and used to initiate action.

Step 4

This “OpenDocument()” command/message has just passed over from the “visual hierarchy” to the “chain of command”. The object in ‘gGopher’ is likely to be the main pane in the active window of this application. This object will not ‘understand’ or have a handler/method for the “OpenDocument()” command so it will be passed to the pane’s supervisor which will likely be a document object. You might think that here we will find an “OpenDocument()” method. But, that is not true. Documents don’t open themselves. That would create somewhat of a chicken and egg problem. The document would have to exist before it was opened. No, the document class doesn’t know “OpenDocument()” so it passes the command on to it’s supervisor, usually the Application object.

Step 5

The Application object knows “OpenDocument()” and creates a new document, it then sends that Document an “OpenFile()” command.

Step 6

The Document object’s “OpenFile()” method creates a DataFile object. The DataFile object is stored in an instance variable of the Document object that “owns” this file. The standard implementation of Document only allows for one file, but a subclass of Document could easily be composed of three on-disk files as well as none. A document without a disk file might be a “status” document whose “data” was the state of other documents.

Step 7

After some error checking the Document object sends a “ReadAll()” message to the DataFile object. This reads the entire data fork of the file into memory. Then the “BuildWindow()” message is sent to the Document object with a handle to the information just read in.

Step 8

The “BuildWindow()” method first creates a new window. This new window is the “enclosure” for two(2) panes. A ScrollPane is created because we want to scroll across the data. The ScrollPane implements much of the behavior necessary to accomplish scrolling of graphics or text with little intervention from the programmer. The ScrollPane is “enclosed” by the Window object. Our MainPane, enclosed by the ScrollPane is the pane that implements our unique way of presenting the data, across which we will scroll. There is the Window, it contains a ScrollPane, the ScrollPane contains our MainPane. This is the hierarchical nature of the visual hierarchy. Windows and Panes are subclasses of View so that we have a view, within a view, within a view.

Step 9

The ‘itsMainPane’ instance variable of the Document determines much of the printing control information that is requested of a document before and during printing. The ‘itsMainPane’ variable is used to identify which of potentially many panes is the one that should “encapsulate” the command and control for this particular window/view hierarchy.

You might use your main pane with the data representation code and command code together or you might have a ‘pallet’ pane that controlled the view in the ‘graphic’ pane. In this case you might want to set the ‘pallet’ pane as the one that received ‘questions’ about printing this window/view hierarchy. The ‘itsGopher’ instance variable of the Document, inherited from the Director class, is usually the ‘itsMainPane’ of a document whenever that document becomes the active one. The ‘itsGopher’ instance variable is stored in the ‘gGopher’ variable whenever the Document object becomes the active document. The variables ‘itsMainPane’ and ‘itsGopher’ of a document do not HAVE to be the same thing. They can be set to different panes or, for instance, one object called the “Control” object could be the ‘itsGopher’ for a whole set of open documents.

Step 10

Now that the data has been displayed we set the window’s title and make it the active window by sending a “Select()” message to the ‘itsWindow’ instance variable of the Document object.

Now, that our window is open and ready to respond to the world, the user clicks the mouse.

The Switchboard object determines that a mouseDown has occurred and sends a “DoMouseDown()” message to itself causing a “DispatchClick()” message to be sent to the DeskTop object through the ‘gDeskTop’ global. As with MacApp, if the click is in the menu bar or in the structure part of the window (title bar, close box, grow box, zoom box, etc.) then TCL takes care of the processing with default behavior that is rarely overridden.

If the click is in a pane of a window then a “UpdateWindows()” message is sent to the DeskTop object. Next, a “DispatchClick()” message is sent to the Window enclosing the pane that received the click.

The Window/View object determines if there is a subview that received the click or if there are no subviews. If there is a subview that is under the position of the click that wants to respond to clicks, then the message “DispatchClick()” is sent to that pane/subview, otherwise if the Window/View wants to handle the click, the Window/View sends itself two messages that allow it to do so. This occurs recursively until there are no subviews or none that are willing to handle a click. In that case or in the case that the first Window/View chosen accepts the challenge, the following occurs.

First, a “CountClicks()” message is sent to the Window/View/Subview Object. This message will cause an global variable called ‘gClicks’ to be incremented as long as the clicks are “close” in time and in the same “part” of a pane/subview.

Close in time is defined as less than the value returned by the ToolBox call GetDblTime(). The same “part” is determined by sending a “HitSamePart()” message to the Window/View/Subview object with the current and last click position. This method found in the View class should be overridden to determine when, for instance, in a text view a word is defined as the “same part” or a line or a paragraph. In a graphical view, an “object” as defined by the applications purpose would be defined in this method.

Next, a “DoClick()” message which is implemented as a NULL function in the released TCL is sent to the Window object. This method is an integral part of a text editor or a draw program or a database forms application. DoClick can do things like maintain the position of the cursor, that is which field it is in, when, in a database application the user clicks on a different field. DoClick might initiate a validation function as well to determine if the user can exit the field.

Figure: The THINK Class Library Visual Hierarchy. Taken from the THINK C Manual, pg. 198

STORING INFORMATION

The THINK Class Library provides an a small but well chosen set of file and data structure handling classes. The primary goal it seems was not to attempt an exhaustive toolchest of structures, but to provide a generally powerful strong foundation for the entrepreneurship of third parties. I hope software companies will soon be providing “TCL Books”. TCL Books would be collections of classes that are sold commercially and maintained by one company or entity.

The abstract class called File provides a base for file handling on the Macintosh. As a rule you will use a subclass of File called DataFile to do actual file manipulation. DataFile provides features for reading/writing raw bytes from/to files in a generalized way. Also, all access to files is to the data fork and not to the resource fork. If you wish to access resources in files you will have to write those routines yourself. The good news is that the ToolBox provides a very nice high level set of tools for manipulating and accessing resources in files.

If your file/document has a structure beyond the straight 5, 10, 100 bytes here and 1000 bytes there, then you should subclass DataFile and build specialized access methods.

When a document is opened TCL handles the getting of the file name. First, it creates a window then it tries to open a file to get data to present in that window. This file would then belong to the document and a reference to the file object would be stored in the ‘itsFile’ instance variable of the Document class. From an architectural viewpoint, TCL is very simple and very flexible when it comes to file handling. Very few decisions have been preordained.

Data structures are a very important subject in the world of computers. It is generally recognized that algorithms and data structures equal programs, a book of a similar title “Algorithms + Data Structures = Programs”, by Niklaus Wirth10 is considered a classic on this fundamental viewpoint. In OP the data structure is the central element of the design phase. What are the “objects” my application must manipulate and what are their relationships. TCL includes three classes which are really just a start on a complete “toolkit” of data structures that a working programmer needs. These classes are Collection, Cluster, and List. A Collection is simply a container with a ‘numItems’ instance variable and IsEmpty() and GetNumItems() methods. A Collection is an abstract class that provides an anchor for the data structures that are subclasses.

The Cluster class is an implementation of an unordered Collection. By unordered, we mean that when an object is stored in the Cluster it is stored in “entry order” and that the order is not related to the contents of the object itself. In other words, the objects are not sorted by size, for instance. If you wanted to determine which one was the largest, you would have to examine every single object, to be sure you found the largest object.

To find an object in a Cluster, you write a method that returns a true boolean value when applied to an object that meets the standards your method has set. Then, you would call the send the message FindItem() to the Cluster object, with your method as a parameter. FindItem will examine each object in turn with your method to determine which object to return to you. If none is found that passes your method’s tests then NULL object pointer is returned.

Clusters introduce iteration over a set of objects, which is a very important and powerful facility for all kinds of programming tasks. Iteration allows you to write methods that you want to apply to all of the objects in a Cluster and then send the message DoForEach() to the Cluster object with your method as a parameter.

The power of the iteration concept is that is allows a kind of interrupt driven style of programming. In the world of Expert Systems it is called Forward Chaining. Where some part of the application will wait for a particular kind of object to appear in a Cluster and that will trigger other actions such as more, different types of objects being stored in that Cluster, which in turn spurs other Cluster watchers to action and so on.

List’s are a subclass of Cluster and provide for the ordering of objects based on any criteria you decide. If you want a set of people objects to be ordered by last name then that would be easily accomplished with a List object.

TCL provides all of the standard user interface glue for the programmer. When the ‘dirty’ instance variable of a document has been set to true the default closing method ask’s “Do you want to save changes to “XYZ”?” This behavior can of course be easily and neatly modified.

DISPLAYING INFORMATION

All drawing takes place in objects of class Pane or subclasses of Pane. Windows are Views and contain Panes. Panes are part of the visual hierarchy and can also be part of the chain of command. Panes have an enclosure and a supervisor. Although they can be the same object, it is usually the case that the Pane’s enclosure is the visually enclosing Pane and the Supervisor is the director of the Window that contains the pane.

The root of the view hierarchy for TCL is the DeskTop object. This is the first object to receive mouse clicks anywhere on the screen, even in the menu bar. The DeskTop object allows TCL to implement concepts such as floating tool pallets with a minimum of extra work to manage clicks and window order. This also allows for an application to determine sublayers among its own document windows.

All drawing is done using the standard QuickDraw™11 toolbox routines. Before sending a pane the draw() message, TCL sends the pane a prepare() message. Prepare returns the QuickDraw environment to a known state, currently the default routine sets the port, sets the origin, sets the clipping rectangle so that drawing only takes place within the visible portion of the pane and then sends the message Restore() to the Environment object that every pane contains in its ‘itsEnvironment’ instance variable. The default function of the Restore() message is to execute the QuickDraw command PenNormal().

As it turns out, the normal initialization of a Pane does not create an environment object. Therefore, a Pane will be drawn in the correct port and with correct origins, but with the pen state, font, etc of the previous draw-ing else where on the screen. You may want to override this initialization process or simply, as a subclass of Pane, create and assign different environment objects to your ‘itsEnvironment’ instance variable.

There are a few classes designed as building blocks for your own more complex Views/Panes. There is StaticText, EditText, Picture, Button, RadioButton, CheckBox and Border. All of these classes can be used to create panes of arbitrary complexity.

The RadioButton class has a sister class called RadioGroup that is meant to manage a cluster of RadioButtons. This is a simple example of the Cluster class in use and offers only a glimpse of the potential user interface uses of Clusters of objects.

To create a scolling view, you would first create a Panorama which is a subclass of Pane. A Panorama is a kind of Pane where the frame is the only part of the Panorama that can be seen, as in a normal Pane, but there is more information that can be “scrolled” into view. Next, create a ScrollPane or subclass thereof and then send the message installPanorama() with a your panorama as a parameter. The ScrollPane automatically adjusts settings of the scroll bars to the size of the Panorama and you can determine, when you initialize your ScrollPane, whether you want Horizontal or Vertical Scrollbars or both. Finally, you install the ScrollPane in a window or other pane and you have a scrollable, clickable scrolling pane.

TCL has no ViewEdit as MacApp does. Although many of the Views/Panes that come with the TCL are initialized by default from resources, such as Buttons, there is no MacDraw-like environment for creating these resources. Using ResEdit with TMPL resources is at best, time consuming, at worse error prone and not conducive to creative design.

Third parties arise! OP under TCL needs your products and demands your efforts. TCL has a large natural base because of the popularity of their compilers. I hope that support for TCL will become much better in the coming months and years.

Footnote References

1 trademark of Apple Computer, Inc.

2 Trademark of Symantec Corporation

3 Object-oriented Software Construction, by Bertrand Meyer, published by Prentice Hall

4 One view for the window, one for each scroll bar, one for the image being scrolled, and one for the scroller, which manages scrolling.

5 Another example of simplifying MacApp by combining two functions into one class. Since the result of a mouse action is often an undoable command, it was convenient to represent the tracking and the command in a single class.

6 That’s because MacApp disables all the menu items each time through the main event loop. It then follows the same chain, starting with the target, and gives each object a chance to enable the menu commands it is prepared to handle. Unless some object enables a menu item, it remains disabled.

7 It also turns out that the resource generally takes up less space than the corresponding code.

8 ViewEdit is written with MacApp, of course.

9 SPLAsh can be reached at 1678 Shattuck Ave. #302, Berkeley, CA, 94709/ the yearly membership is $30 USA, $40 Canada and Mexico and $60 international air mail.

10 Algorithms + Data Structures = Programs published by Prentice Hall.

11 QuickDraw™, a trade name of Apple Computer, Inc.

 

Community Search:
MacTech Search:

Software Updates via MacUpdate

Dropbox 193.4.5594 - Cloud backup and sy...
Dropbox is a file hosting service that provides cloud storage, file synchronization, personal cloud, and client software. It is a modern workspace that allows you to get to all of your files, manage... Read more
Google Chrome 122.0.6261.57 - Modern and...
Google Chrome is a Web browser by Google, created to be a modern platform for Web pages and applications. It utilizes very fast loading of Web pages and has a V8 engine, which is a custom built... Read more
Skype 8.113.0.210 - Voice-over-internet...
Skype is a telecommunications app that provides HD video calls, instant messaging, calling to any phone number or landline, and Skype for Business for productive cooperation on the projects. This... Read more
Tor Browser 13.0.10 - Anonymize Web brow...
Using Tor Browser you can protect yourself against tracking, surveillance, and censorship. Tor was originally designed, implemented, and deployed as a third-generation onion-routing project of the U.... Read more
Deeper 3.0.4 - Enable hidden features in...
Deeper is a personalization utility for macOS which allows you to enable and disable the hidden functions of the Finder, Dock, QuickTime, Safari, iTunes, login window, Spotlight, and many of Apple's... Read more
OnyX 4.5.5 - Maintenance and optimizatio...
OnyX is a multifunction utility that you can use to verify the startup disk and the structure of its system files, to run miscellaneous maintenance and cleaning tasks, to configure parameters in the... Read more

Latest Forum Discussions

See All

Zenless Zone Zero opens entries for its...
miHoYo, aka HoYoverse, has become such a big name in mobile gaming that it's hard to believe that arguably their flagship title, Genshin Impact, is only three and a half years old. Now, they continue the road to the next title in their world, with... | Read more »
Live, Playdate, Live! – The TouchArcade...
In this week’s episode of The TouchArcade Show we kick things off by talking about all the games I splurged on during the recent Playdate Catalog one-year anniversary sale, including the new Lucas Pope jam Mars After Midnight. We haven’t played any... | Read more »
TouchArcade Game of the Week: ‘Vroomies’
So here’s a thing: Vroomies from developer Alex Taber aka Unordered Games is the Game of the Week! Except… Vroomies came out an entire month ago. It wasn’t on my radar until this week, which is why I included it in our weekly new games round-up, but... | Read more »
SwitchArcade Round-Up: ‘MLB The Show 24’...
Hello gentle readers, and welcome to the SwitchArcade Round-Up for March 15th, 2024. We’re closing out the week with a bunch of new games, with Sony’s baseball franchise MLB The Show up to bat yet again. There are several other interesting games to... | Read more »
Steam Deck Weekly: WWE 2K24 and Summerho...
Welcome to this week’s edition of the Steam Deck Weekly. The busy season has begun with games we’ve been looking forward to playing including Dragon’s Dogma 2, Horizon Forbidden West Complete Edition, and also console exclusives like Rise of the... | Read more »
Steam Spring Sale 2024 – The 10 Best Ste...
The Steam Spring Sale 2024 began last night, and while it isn’t as big of a deal as say the Steam Winter Sale, you may as well take advantage of it to save money on some games you were planning to buy. I obviously recommend checking out your own... | Read more »
New ‘SaGa Emerald Beyond’ Gameplay Showc...
Last month, Square Enix posted a Let’s Play video featuring SaGa Localization Director Neil Broadley who showcased the worlds, companions, and more from the upcoming and highly-anticipated RPG SaGa Emerald Beyond. | Read more »
Choose Your Side in the Latest ‘Marvel S...
Last month, Marvel Snap (Free) held its very first “imbalance" event in honor of Valentine’s Day. For a limited time, certain well-known couples were given special boosts when conditions were right. It must have gone over well, because we’ve got a... | Read more »
Warframe welcomes the arrival of a new s...
As a Warframe player one of the best things about it launching on iOS, despite it being arguably the best way to play the game if you have a controller, is that I can now be paid to talk about it. To whit, we are gearing up to receive the first... | Read more »
Apple Arcade Weekly Round-Up: Updates an...
Following the new releases earlier in the month and April 2024’s games being revealed by Apple, this week has seen some notable game updates and events go live for Apple Arcade. What The Golf? has an April Fool’s Day celebration event going live “... | Read more »

Price Scanner via MacPrices.net

Apple Education is offering $100 discounts on...
If you’re a student, teacher, or staff member at any educational institution, you can use your .edu email address when ordering at Apple Education to take $100 off the price of a new M3 MacBook Air.... Read more
Apple Watch Ultra 2 with Blood Oxygen feature...
Best Buy is offering Apple Watch Ultra 2 models for $50 off MSRP on their online store this week. Sale prices available for online orders only, in-store prices may vary. Order online, and choose... Read more
New promo at Sams Club: Apple HomePods for $2...
Sams Club has Apple HomePods on sale for $259 through March 31, 2024. Their price is $40 off Apple’s MSRP, and both Space Gray and White colors are available. Sale price is for online orders only, in... Read more
Get Apple’s 2nd generation Apple Pencil for $...
Apple’s Pencil (2nd generation) works with the 12″ iPad Pro (3rd, 4th, 5th, and 6th generation), 11″ iPad Pro (1st, 2nd, 3rd, and 4th generation), iPad Air (4th and 5th generation), and iPad mini (... Read more
10th generation Apple iPads on sale for $100...
Best Buy has Apple’s 10th-generation WiFi iPads back on sale for $100 off MSRP on their online store, starting at only $349. With the discount, Best Buy’s prices are the lowest currently available... Read more
iPad Airs on sale again starting at $449 on B...
Best Buy has 10.9″ M1 WiFi iPad Airs on record-low sale prices again for $150 off Apple’s MSRP, starting at $449. Sale prices for online orders only, in-store price may vary. Order online, and choose... Read more
Best Buy is blowing out clearance 13-inch M1...
Best Buy is blowing out clearance Apple 13″ M1 MacBook Airs this weekend for only $649.99, or $350 off Apple’s original MSRP. Sale prices for online orders only, in-store prices may vary. Order... Read more
Low price alert! You can now get a 13-inch M1...
Walmart has, for the first time, begun offering new Apple MacBooks for sale on their online store, albeit clearance previous-generation models. They now have the 13″ M1 MacBook Air (8GB RAM, 256GB... Read more
Best Apple MacBook deal this weekend: Get the...
Apple has 13″ M2 MacBook Airs available for only $849 today in their Certified Refurbished store. These are the cheapest M2-powered MacBooks for sale at Apple. Apple’s one-year warranty is included,... Read more
New 15-inch M3 MacBook Air (Midnight) on sale...
Amazon has the new 15″ M3 MacBook Air (8GB RAM/256GB SSD/Midnight) in stock and on sale today for $1249.99 including free shipping. Their price is $50 off MSRP, and it’s the lowest price currently... Read more

Jobs Board

Early Preschool Teacher - Glenda Drive/ *Appl...
Early Preschool Teacher - Glenda Drive/ Apple ValleyTeacher Share by Email Share on LinkedIn Share on Twitter Read more
Senior Software Engineer - *Apple* Fundamen...
…center of Microsoft's efforts to empower our users to do more. The Apple Fundamentals team focused on defining and improving the end-to-end developer experience in Read more
Relationship Banker *Apple* Valley Main - W...
…Alcohol Policy to learn more. **Company:** WELLS FARGO BANK **Req Number:** R-350696 **Updated:** Mon Mar 11 00:00:00 UTC 2024 **Location:** APPLE VALLEY,California Read more
Medical Assistant - Surgical Oncology- *Apple...
Medical Assistant - Surgical Oncology- Apple Hill WellSpan Medical Group, York, PA | Nursing | Nursing Support | FTE: 1 | Regular | Tracking Code: 200555 Apply Now Read more
Early Preschool Teacher - Glenda Drive/ *Appl...
Early Preschool Teacher - Glenda Drive/ Apple ValleyTeacher Share by Email Share on LinkedIn Share on Twitter Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.