TweetFollow Us on Twitter

August 91 - Speedcode

Speedcode

Huan Keh, Walter Wittel, and Ted Lewis

Speedcode is of interest to MacApp programmers because it's currently being ported to platforms other than the Macintosh, because it is part of a system that makes use of code generation technology, and because it claims to be smaller and simpler than MacApp. The initial release of Oregon Software Universe 3-the development system that contains the Speedcode framework-is expected in September. A book is underway as well.

Walter Wittel is a software engineer for Microsoft, and Huan Keh is a PhD candidate at Oregon State University. Speedcode is part of Keh's PhD dissertation and Wittel's MS thesis under the direction of Ted Lewis, who is a Professor of Computer Science at Oregon State University. Their work was partially supported by Apple Computer.

This article concentrates on the framework portion, Speedcode, of OSU 3. Look for additional articles that cover other aspects of the OSU 3 system in future issues of FrameWorks.

In Search of the Holy Grail

Programmers are always attempting to reduce the time and effort to produce the next great application. In GUI programming on machines like the Macintosh, there is a high cost of learning the toolbox routines and the intricacies of event-driven programming. The holy grail of Mac programming has become the search for automatic tools like program generators and application development frameworks.

In 1985, we formed a team of students and faculty to study ways in which programmer productivity on the Mac could be increased. Our first attempt was Oregon Speedcode Universe (OSU), which looked a lot like Prototyper or AppMaker.

Funding from Dupont corporation allowed us to improve OSU, and in 1989, we released OSU 2 to the world. Version 2 was able to connect to VideoWorks II movies, and in general made GUI programming as simple as MacDraw. But OSU 2 had severe limitations-one of which was that it generated Pascal, meaning that it couldn't take advantage of design or code reuse.

Since late 1989, we've been working long hours to produce a C++-based application framework that is somewhat portable across different GUI platforms and much more capable than OSU 2. We're now on the verge of releasing OSU 3 to the world in the form of a book and free source code. The expected first release date of the source code and minimal documentation is September 1991.

The search for the holy grail is not over, but we feel that OSU 3 is a step in the right direction. It incorporates the following tools:

  • Application Framework, including extensive class library; see Figure 1.
  • PetriNet Editor, used to sequence applications code; this is how application specific functions are added to the basic framework.
  • Browser-yet another class hierarchy browser.
  • Code Generator, which synthesizes C++ code from the framework, PetriNet, and programmer supplied routines.
  • RezDez-yet another resource editor.

We don't have enough space in this article to describe the entire OSU 3 system, so for the moment, we'll focus on the framework portion only. For brevity, we call the OSU Application Framework Speedcode.

Intimations of Leverage

Before we dive into the details of Speedcode, let me emphasize that this approach is still in its infancy, and we don't yet know what it is capable of doing to the development process. However, we are encouraged by early results that suggest a 10-to-1 reduction in lines of code for small applications-and we are hoping for a 2 or 3-to-1 reduction in the size of code that must be manually written for large applications. The following table is not meant to be a commercial break, but only to suggest early results of using Speedcode to produce some of its own tools:
Application    Mac toolbox & C++   Speedcode & C++ Ratio
___________________________________________________________
MVC Demo        3000    300     10:1
MiniDraw Demo   7000    300     23:1
ExampleDraw     8000    300     27:1
PetrNed Editor  6000    2500    2.4:1
Browser         4700    2000    2.4:1
____________________________________________________________

These lines-of-code estimates were obtained by comparison between the application written in C++ using the Mac Toolbox, and the same application written in C++ using Speedcode. The numbers are probably only representative of small applications.

Note that the Speedcode framework contains 16K lines of C++ itself. So the lines of code quoted in the "Speedcode with C++" column are the number of lines of code that the programmer had to add to the 16K lines of reusable code that always exists in the framework.

A FrameWork, or a Toolkit?

Most of you may already familiar with frameworks such as MacApp, ET++, and InterViews. But like pornography, everyone knows what a framework is, but we often have trouble defining it. Besides, what is the difference between a framework and a toolkit? Before going further, perhaps we can define what a framework is.

When function A calls function B, we say A is the caller and B is the callee. In a toolkit approach such as provided by the Mac OS, application programs are callers and toolbox routines are callees. In fact, many C++ class hierarchies have been described as frameworks, but in reality they are only toolkits. Why?

One of the most important features of a framework is that application code written by the programmer is composed of callee functions-the caller functions are all part of the framework. So, the next time you see an advertisement for a C++ framework, ask yourself, "who is the caller, and who is the callee?"

A true framework should also incorporate some paradigm or pattern of design that is used consistently throughout. A design paradigm is simply a pattern of function calls, data structures, and general program organization that obeys some rules of behavior. This is where MacApp and many other frameworks are weak; it's one of the reasons we decided to build a replacement for MacApp.

Speedcode-Overview

Speedcode uses an object-oriented paradigm. This means that all applications are constructed by repeated application of a pattern of specialization. Specifically, all applications are special instances of the framework. In Speedcode, programmers form special cases by instantiating an existing class from the built-in library, subclassing, overriding methods, or extending the class library through the addition of new classes.

Second-and this is a major feature-Speedcode incorporates an advanced version of the Model-View-Controller (MVC) paradigm put forth by the inventors of SmallTalk. For the programmer, this means that multiple views of the same data are automatically updated whenever any change occurs to the data. So, if spreadsheet data is viewed both as a spreadsheet and a bar chart, and the user changes the data in the spreadsheet view, it is automatically changed in the bar chart view. The separation of applications into Model=Data, View=Display, and Controller=Interaction with the user, alters the paradigm of the program. Recombining the Model, View, and Controller parts of an application into a framework makes the framework much more useful than a simple class library.

Speedcode implements automatic change propagation in a variant of the MVC paradigm. This also means that Speedcode removes this detail from concern by the programmer. Thus, the Speedcode framework must be more "intelligent," and the class hierarchy must do most of the work of storing data in RAM and on disk. Note that the data storage hierarchy in the class library of Speedcode is very extensive as a consequence of this decision-but I am ahead of our story.

Now, we are ready for a formal definition of framework: An object-oriented application framework is a mixture of abstract and concrete classes along with a model of interaction and control flow among the classes. The framework has "hooks" to allow an application programmer to plug in objects that represent the functionality unique to the application. Generic features, such as handling windows, undo and redo of commands, saving and opening files, and printing-which are always found in a GUI application-are provided by the framework as reusable code.

SpeedCODE-Technical details

With that breathtaking introduction, we're now ready to get technical. Once again, it's impossible to give all the details in this survey. I'll concentrate mainly on the class hierarchy here, but remember that this is only a small part of the application development system. Contact the authors for complete details on OSU 3, and for information on how to obtain your own copy.

The OSU Application Framework is written in MPW C++ and built on top of the Macintosh Toolbox. It is divided into three parts: the data structure class library, the shape class library, and the application framework classes. Figure 2 shows the class hierarchy of the OSU Application Framework.

The data structure class library is rooted at the Collection class, the shape class library is rooted at the Shape class, and others are application framework classes. The data structure class library defines general useful data structures, such as arrays, lists, and sets. The shape library supports various kinds of shapes and defines the user interface for creating and manipulating these shapes. The application framework classes define much of a Macintosh application's standard user interface, generic behavior, and operating environment. In order to show the differences between our framework, MacApp, and ET++, the simplified class hierarchies of MacApp and ET++ are also given in Figure 3 and Figure 4, respectively.  The Application class is much smaller than MacApp's TApplication. The Application object manages a list of all the windows used by the program, runs the main event loop, and dispatches events to the appropriate objects to handle them. The programmer will always subclass Application and each program will have one, and only one, instance of that subclass.

The Document class encapsulates the data structure or model of an application and knows how to fill the model with data. Document is not a subclass of Controller as in MacApp and ET++.

The abstract class Command not only supports Undo and Redo operations but also helps structure complex applications. The Command objects are normally pushed onto the Undo stack by Menu, Palette, or Window objects and pushed onto the Redo stack and popped off the Redo and Undo stacks by Window objects only.

Each Pane object has its own coordinate system and clips the drawing of a view to a rectangular area (the pane's frame). It also handles scrolling the view displayed inside it. Panes can be installed within other panes. This results in an hierarchical subpane/superpane relationship. The Window object can contain subpanes, and is always the topmost pane in the subpane/superpane hierarchy.

The relationship among documents, views, and windows is important. In general, a user's program follows a three-step process in creating a new domain-specific view to display the data in the model filled by a document.

First, the menu or the application object creates and initializes the window that will hold the view objects. Then, the window creates and initializes its document. Finally, the document creates and initializes the view objects.

Figure 5 shows the message flow diagram in our modified MVC paradigm. The standard interaction cycle in modified MVC can be described as follows. The Application controller is used as the top level event handler or dispatcher. When the user takes some input action, the Application controller either handles this event or dispatches it to the Menu, Palette, or the Window/Pane controller depending upon the type of the event. The Menu, Palette, or Window/Pane controller then dispatches the event to the appropriate view.

After handling the event, the view notifies the model to change itself and the model in turn broadcasts change messages to its dependent views. Views can then query the model about its new state, and update their display if necessary.

Data Structure Class Library

The data structure class library is a portable collection of classes similar to those of Smalltalk collection classes (see Figure 6). It includes generally useful abstract data types such as OrderedCollection, Set (hash table), ObjList (linked list), and Dictionary. We have used these data structure classes extensively for the implementation of the OSU Application Framework itself and the set of high level tools in OSU 3.0. The data structure class library is rooted at the Collection class shown in Figure 2.

The Shape Class Library

It's quite an understatement to say that graphics are an important part of most GUI applications. Unfortunately, there isn't any standard code in either the Macintosh Toolbox or MacApp to implement structured graphics. The result is that there are subtle differences between applications in how the user manipulate shapes.

Our solution to this problem is to implement a standard shape library that can be used in any application that manipulates shapes (see Figure 7). The class hierarchy of the shape library is rooted at the Shape class shown in Figure 2. Our shape library handles various kinds of shapes, so that it is usable in a variety of applications. It also allows the programmer to customize and extend the way shapes are manipulated through subclassing.

The Application Framework Classes

The Object Class

The OSU Application Framework is single-rooted, and all other classes shown in Figure 2 are subclasses of the abstract class Object. Object defines a base method, Clone(), and three abstract methods: ReadFrom(), WriteTo(), and Equal(). Clone() copies the object and its instance variables exactly and can be directly inherited by subclasses. ReadFrom() and WriteTo() are overridden in subclasses to read and write an object to and from disk. The Equal() method is overridden in subclass to compare objects.

The Controller Class

Controller is an abstract class, forming a root for any classes that handle input from the mouse or keyboard. It is roughly equivalent to the TEvtHandler class in MacApp. Controller defines abstract event handling methods, such as DoKeyDown() and DoMouseCommand(), for subclasses like Application, Window, and View. All methods defined in the Controller class are expected to be overridden in subclasses.

The Model Class/

Model is an abstract class that supports the MVC paradigm by maintaining a list of views dependent on its data. Model defines the methods Changed() and Notify() for implementing change propagation. In the Speedcode framework, data structure classes such as lists and arrays are subclassed from the Model class. For this reason, it is usually unnecessary to subclass the Model class directly, unless you need a model of unusual data. The data structures are provided with methods to allow modification of the object's data. When these methods are invoked, they call the model's Changed() function which in turn calls Notify(). Notify() sends the ModelUpdated() message to each dependent view.

The View Class

The View abstract class is responsible for rendering model data within panes. Views draw inside a pane, and panes are inside windows. Each view object draws relative to an origin of (0, 0) positioned at the upper left hand corner of the enclosing pane. The pane class takes care of offsetting the origin of the view to account for its position within a pane and window, and also clipping the view so that it doesn't draw outside of its enclosing pane.

When a model sends the ModelUpdated() message to a view, the view sends a ViewUpdate() message to all the panes in its superPaneList. The pane in turn "focuses" the view and calls its DrawContents() method. If the view is visible, its Draw() method is called and drawing takes place on the screen within the bounds of the clip region.

MouseDown events are converted by the template method DoMouseCommand() to single, double, triple clicks, or drags and dispatched to the appropriate abstract view methods which are expected to be overridden in subclasses such as domain-specific views or user-written subclasses of View. These methods include DoSingleClick(), DODoubleClick(), DoTripleClick(), and DoDrag(). Note that the template method DoMouseCommand() may be overridden if the programmer wants to handle any unusual mouse actions. KeyDown events are handled in a similar manner. The Application Class The Application class manages a list of all the windows used by the program, runs the main event loop, and dispatches events to the appropriate objects to handle them. The programmer will always subclass Application; and each program will have one, and only one, instance of that subclass. At a minimum, the abstract method CreateMenus() must be overwritten in the subclass to create a MenuBar object and install the application's menu objects into it.

When the application class is instantiated (the first action in the GUI application's C++ function "main"), its constructor initializes the Macintosh Toolbox routines. The abstract method Initialize() is usually overridden in the subclass of Application to perform domain-specific initialization. As the application program starts, the template method Run() of the Application class invokes the Initialize() and CreateMenus() methods and then starts the main event loop.

The Document and FileDocument Classes

Document encapsulates the data structure or model of an application and knows how to fill the model with data. Our Document class, unlike MacApp and ET++, is not an event handler. The data that fills a model does not necessarily come from a file; it may come from RAM-based data structures. We have separated the FileDocument class from the Document class so that a document does not have to be disk based. The abstract method CreateViews() must be overridden in subclasses to create all necessary views for the model. The FileDocument class knows how to open and close files and provides the means for reading and writing data to and from files on disk.

The FileDocument class manages the logic of putting up dialogs to get file names to open (load from disk) and save. It also puts up a dialog that asks the user if a modified file document (really the model's data) should be saved before closing. FileDocument defines the abstract methods DoRead() and DoWrite() which are usually overridden in subclasses. A file document is usually created by the CreateDocument() method of the Window class.

The UIObject Class

The UIObject class provides two instance variables (fID and fName) for the storage of the object's ID and name, and base methods to get and set the variables. These variables are used to obtain the references to the desired user interface objects. The method GetWindowByName() defined in the Application class, for example, uses fName to obtain the reference to the desired window object.

The StdUIObject Class

The StdUIObject class provides an instance variable for the storage of the object's resource ID, and base methods to get and set the variable.

The Pane Class

The Pane class positions, scrolls, and clips views within a window, as well as directing MouseDown and KeyDown events received by a window to the proper view. Pane Objects can have a single base view or one or more subpanes, allowing for a hierarchical display of panes within panes in a window. The root of the hierarchy is the pane from which windows are subclassed, and the leaf nodes contain the views.

Panes are initialized with a location and size which positions them within the enclosing window, and if the pane is a leaf, the number of scroll bars and a pointer to the view. Each pane has a pane rectangle that encloses the entire pane and is framed by a one pixel line. Inset one pixel within this pane rectangle is a view rectangle that defines the clipping region when drawing the view. If the pane has a vertical or horizontal scroll bar, then the appropriate edges of the view rectangle are inset further.

When a MouseDown is received by a window, it is passed along to the root pane. If the pane has scroll bars, and the MouseDown was enclosed in one of their rectangles, the DoMouseDown message is passed along to the scroll bar object. Otherwise, the MouseDown is passed to the view, or to the appropriate subpane, whichever is enclosed in the pane. If the user scrolls a view, the framework calculates a new offset for the view, scrolls the bits within the view rectangle on the screen, and updates (redraws using the new origin) the area filled with the background color after the screen bits are scrolled.

Another function provided by the Pane class is bringing panes and views into "focus." FocusPane() is invoked before a pane is adorned (framed with a one pixel line and the scroll bars redrawn). The FocusPane() method sets the graphics port to the correct (enclosing) window, sets the clip rectangle to the pane's rectangle, and draws the frame and scroll bars. In a similar manner, FocusView() sets the port, but also takes into account both the local location of the pane and the amount it is currently scrolled to calculate the clip rectangle.

Calculating new values for the pane rectangle, view rectangle, and scroll bars is done automatically when a window is resized or zoomed if the pane it encloses is initialized to "sizeVariable." Usually panes within panes are initialized to "SizeFixed."

All this takes place without the need for the user to write any code or subclass the Pane class. Every pane is simply an instance of the framework's Pane class. The user may, at times, wish to override the Adorn(), MouseInPane(), and DoSetupMenus() methods to customize the panes behavior.

The BasicWindow Class

The BasicWindow class is an abstract superclass common to windows, dialogs, and palettes. It holds the window's WindowPtr and its constructor automatically inserts a pointer to itself into the window list maintained by the application object. It also contains methods to drag a window.

The Command Class

The abstract class Command supports undo and redo of multiple commands. Command objects are temporary objects that carry out user requests while storing information about the previous state so the user can undo the operation if required. Due to the fact that command objects consume a great deal of memory space, the current implementation supports only five levels of undo/redo operations. However, this is sufficient for most applications.

You generally use many different subclasses of Command-one for each type of user action that you want to be undoable, such as typing characters, mouse operations like drawing and dragging, and menu or palette items like Delete and Rotate. Command objects should be used when the user action will change data in the model of the application.

Command objects are created by several methods in a View object in response to an event. These methods include DoMouseCommand(), DoKeyCommand(), and several other menu/palette item related methods such as DoCut(). Command objects are stored in the Redo and Undo stacks defined in the Window class.

Newly created Command objects are executed and managed by Window, MenuBar or Palette objects. Typing and mouse command objects are managed and executed by the Window class; menu command objects are managed and executed by the MenuBar class; palette command objects are managed and executed by the Palette class.

Command objects which have been undone or redone are managed by Window objects only. Three abstract methods-DoIt(), UndoIt(), and RedoIt()-are often overridden in subclasses to implement undoable commands.

Application programs never perform commands directly, but simply instantiate commands objects and pass them to the framework. A menu command, for example, is automatically invoked by the template method HandleMenuCommand() defined in the MenuBar class.

The abstract class Command is a very good example of the reuse of an abstract design. It not only eases the implementation process substantially but also helps the programmer to modularize complex applications into small and more manageable pieces.

The Window Class

The Window class implements standard window manipulation functions such as resizing and zooming. It also implements many event handling methods defined in the Controller class such as DoMouseDown(), DoKeyDown(), DoActivateEvt(), and DoUpdateEvt(). It supports menu commands such as DoNew(), DoOpen(), DoClose(), DoSave(), Undo(), and Redo(). Our framework implements multiple levels of undo and redo operations, and the Undo and Redo stacks are contained in the Window class.

The template method Undo() undoes the command on the top of the Undo stack. After a command is undone, it is popped off the Undo stack and then pushed onto the Redo Stack. The template method Redo() redoes the command on the top of the Redo stack. After a command is redone, it is popped off the Redo stack and then pushed onto the Undo Stack.

The Window object is also responsible for creating the document object and subpanes. The abstract methods CreateDocument() and CreateSubpanes() must be overridden in subclasses to create the document and subpanes in the Window object. The Menu Class The abstract class Menu implements standard menu operations such as enabling and checking menu items, and provides default behavior for handling menu commands. The abstract method DoMenuCommand() must be overridden in subclasses to dispatch menu commands to the appropriate View methods. DoMenuCommand() will be invoked by the template method HandleMenuCommand() of the MenuBar class. The abstract method DoSetupMenus() is often overridden in subclasses to enable or check menu items.

The MenuBar Classes

The MenuBar class contains and handles menu objects. It provides methods for the user to install and remove menu objects. It also dispatches menu commands to the responsible menu object.

The template method HandleMenuCommand() executes the menu command by invoking the abstract method DoIt() which is overridden in the subclass of Command. If it is an undoable command, it is pushed onto the undo stack of the frontmost window object. When there is a MouseDown event in the menu region, HandleMenuCommand() is invoked by another template method, DoMouseDownEvt(), defined in the Application class. In most cases, the programmer is not required to subclass MenuBar.

The Palette Class

The abstract class Palette is similar to the combination of the Menu and MenuBar classes. It supports multi-dimensional palettes and implements standard palette operations such as turning on or off the highlighting of palette items. It also handles undoable palette commands in a similar way to the MenuBar class which handles undoable menu commands.

The template method DoMouseDown() executes the palette command by invoking the abstract method DoIt(), which is overridden in the subclass of Command, and pushes it onto the undo stack of the frontmost window object if it is an undoable command. The abstract method DoMouseCommand() must be overridden in subclasses to dispatch palette commands to the appropriate View methods.

The GraphicsView Class

The domain-specific class GraphicsView is a subclass of the abstract superclass View. It uses the underlying shape library to implement standard shape manipulation operations, such as Cut, Rotate, and SelectAll, found in most conventional drawing programs. It also provides hooks to allow the MenuBar and Palette objects to be connected with the GraphicsView object. The palette object, for example, can send the message SetPaletteState() to the GraphicsView object so that the GraphicsView object knows what kind of shape should be drawn next.

The GraphicsView class overrides the abstract methods DoSingleClick(), DoDoubleClick(), DoTripleClick(), and DoDrag() defined in its abstract superclass View to support standard mouse actions. To create simple drawing programs, the programmer can directly instantiate GraphicsView objects. Also, the programmer can subclass GraphicsView to implement application-specific operations such as checking the consistency of a graph diagram.

The GraphicsFileDocument Class

The domain-specific GraphicsFileDocument class comes with the domain-specific View class GraphicsView. It overrides the abstract methods DoRead() and DoWrite() defined in its abstract superclass FileDocument. DoRead() reads shape data from a disk file into a linked list (shapeList) of shapes, while DoWrite() writes shape data from a linked list to a disk file.

Standard document operations, such as opening and closing files and putting up dialogs to get file names or to ask the user if a modified file should be saved before closing, are inherited from the abstract superclass FileDocument.

Other Classes

Other classes such as Clipboard, Alert, Dialog, Control, and their subclasses simply provide an easy-to-use, object-oriented interface to the underlying Macintosh Toolbox routines.

Size of the Framework

The table on the following page summarizes size statistics for the framework. It is incredibly small and yet offers more power than other frameworks.

The source for a minimal sample application, MiniDraw, appears in the following listing. Look for additional articles that cover other aspects of OSU 3, and provide more extensive source code examples, in future issues of FrameWorks. n

A Minimal SAMPLE Application: MINIDRAW

//  Test by Chih Lai, 06/29/91

#ifndef CLAPPLICATION_H
#include "clapplication.h"
#endif
#ifndef CLMENU_H
#include "clmenu.h"
#endif
#ifndef CLMODEL_H
#include "clmodel.h"
#endif
#ifndef CLWINDOW_H
#include "clwindow.h"
#endif
#ifndef CLVIEW_H
#include "clview.h"
#endif
#ifndef CLPALETTE_H
#include "clpalette.h"
#endif
#ifndef __DESK__
#include <Desk.h>
#endif
#ifndef __QUICKDRAW__
#include <Quickdraw.h>
#endif
#ifndef CLCollection_First
#include "CLCollection.h"
#endif
#include "cldialog.h"
#include <textedit.h>
#include <dialogs.h>
#include <traps.h>
#ifndef CLDOCUMENT_H
#include "cldocument.h"
#endif
#ifndef CLGraphicsView_H
#include "a_clGraphicsView.h"
#endif

#define MAX_MENU_OBJ    4
#define BASE_MENU_ID    256
#define WIND_ID         256

CLGraphicsView *myView1;
CLGraphicsView *myView2;

//
//  MyWindow
//

class MyWindow : public CLWindow {
public:
    MyWindow():(WIND_ID) {};
    class CLDocument * CreateDocument();
    void CreateSubPanes();
};

CLDocument * MyWindow::CreateDocument() {
    return new CLGraphicsDocument(this,'TEXT','MINI');
}

    void MyWindow::CreateSubPanes() {
    CLPane  *myPane1;
    CLView  *aView;
    Point   thePaneSize, theLocation;

    SetPt(&thePaneSize, fWindPtr->
    portRect.right, fWindPtr->portRect.bottom);
    SetPt(&theLocation, 0, 0);
    myPane1 = new CLPane(this, this, false, true);
    aView = GetViewByName("MyView1");
    myView1 = (CLGraphicsView*)aView ;
    myPane1->ICLPane(&thePaneSize, &theLocation, 3, aView);
    AddSubPane(myPane1);

}

//
//  MyFileMenu
//

class MyFileMenu : public CLMenu {
public:
    class CLCommand * DoMenuCommand(short pItemNumber) ;
    MyFileMenu():(BASE_MENU_ID + 1) {}
};

class CLCommand * MyFileMenu::DoMenuCommand(short pItemNumber)
{
    class MyWindow * aWindowObj ;
    
    CheckOnlyItem(pItemNumber);
    switch (pItemNumber) {
    case 1 : 
        MyWindow * myWind = new MyWindow;
        myWind->Initialize();
        myWind->Draw();
        break ;
    case 2 :
        aWindowObj =
            (MyWindow *)
            (gApplication->GetWindowObject(FrontWindow()));
        if (aWindowObj) 
            aWindowObj -> DoOpen();
        break ;
    case 5 :
        aWindowObj =
            (MyWindow *)
            (gApplication->GetWindowObject(FrontWindow()));
        if (aWindowObj) 
            aWindowObj -> DoSave();
        break ;
    case 12 :
        gApplication->Terminate();
        break ;
}
return 0 ;
}
//
//  MyEditMenu
//

class MyEditMenu : public CLMenu {
public:
class CLCommand * DoMenuCommand(short pItemNumber) ;
MyEditMenu():(BASE_MENU_ID + 2) {}
};

class CLCommand * MyEditMenu::DoMenuCommand(short pItemNumber)
{
switch (pItemNumber) {
    case 1 : 
        // not a command object, user can't undo
        myView1->Undo() ;    
        break ;
    case 3 :
        return myView1->Cut() ;
    case 5 :
        return myView1->Paste() ;
    case 8 :
        // not a command object, user can't undo
        myView1->SelectAll() ;   
}
return 0 ;
}

//
//  MyPatternMenu
//

class MyPatternMenu : public CLMenu {
public:
    class CLCommand * DoMenuCommand(short pItemNumber) ;
    MyPatternMenu():(BASE_MENU_ID + 3) {}
};

class CLCommand * MyPatternMenu::DoMenuCommand(short pItemNumber)
{
switch (pItemNumber) {
    case 1 : // Black
        return myView1->SetPattern(qd.black) ;
    case 2 : // White
        return myView1->SetPattern(qd.white) ;
    case 3 : // Gray
        return myView1->SetPattern(qd.gray) ;
    case 4 : // LightGray
        return myView1->SetPattern(qd.ltGray) ;
}
}

//
//  MyAppleMenu
//

class MyAppleMenu : public CLMenu {
private:
    Str255      name;
    short       temp;
    CLUserAlert *aboutMini;
public:
class CLCommand * DoMenuCommand(short pItemNumber)
    {
        if (pItemNumber == 1) {
            aboutMini = new CLUserAlert(128);
            aboutMini->Draw();
            delete aboutMini;
        }
        else {
            GetItem(fMenuHandle,pItemNumber,name);
            temp = OpenDeskAcc(name);
        }
        return 0;
    };
    
public:
    MyAppleMenu():(BASE_MENU_ID) {}
};

//
// MyPalette
//

class MyPalette : public CLPalette {
public :
    MyPalette(short pPaletteId):(pPaletteId) { };
    class CLCommand * DoMouseCommand(short pItemHit);
};

CLCommand * MyPalette::DoMouseCommand(short pItemHit){
short   ShapeTool ;

switch (pItemHit) {
    case 1 :
        ShapeTool = selectionTool ; 
        break ;
    case 2 :
        ShapeTool = Rectangle ; 
        break ;
    case 3 :
        ShapeTool = RoundRect ; 
        break ;
    case 4 :
        ShapeTool = Oval ;  
        break ;
    case 5 :
        ShapeTool = Line ;  
        break ;
    case 6 :
        ShapeTool = ArrowLine ; 
        break ;
    case 7 :
        ShapeTool = Diamond ;   
        break ;
    case 8 :
        ShapeTool = Label ; 
        break ;
} 
myView1->CLSetCurrentShapeTool(ShapeTool) ;  
return CLPalette::DoMouseCommand(pItemHit);
};

//
//  MyApplication
//

class MyApplication : public CLApplication {
public :
    CLMenuBar * CreateMenus();
    void Initialize();
};

CLMenuBar * MyApplication::CreateMenus(){
CLMenu * aMenuObj;
CLMenuBar * aMenuBarObj = new CLMenuBar;
aMenuObj = new MyAppleMenu();
aMenuObj->AddRsrc();
aMenuBarObj->AddMenu(aMenuObj);
aMenuObj = new MyFileMenu;
aMenuBarObj->AddMenu(aMenuObj);
aMenuObj = new MyEditMenu;
aMenuBarObj->AddMenu(aMenuObj);
aMenuObj = new MyPatternMenu;
aMenuBarObj->AddMenu(aMenuObj);
aMenuBarObj->CheckMenuItem(257, 2);
return aMenuBarObj;
};

void MyApplication::Initialize() {

MyPalette * myPalette1 = new MyPalette(128);    
myPalette1->Draw();
MyWindow * myWind = new MyWindow;
myWind->Initialize();
myWind->Draw();
}

main(){

MyApplication * myApp = new MyApplication;
myApp->Run();
return 0;
}
End of listing.
 

Community Search:
MacTech Search:

Software Updates via MacUpdate

LibreOffice 4.4.5.2 - Free, open-source...
LibreOffice is an office suite (word processor, spreadsheet, presentations, drawing tool) compatible with other major office suites. The Document Foundation is coordinating development and... Read more
Adobe Lightroom 6.1.1 - Import, develop,...
Adobe Lightroom is available as part of Adobe Creative Cloud for as little as $9.99/month bundled with Photoshop CC as part of the photography package. Lightroom 6 is also available for purchase as a... Read more
File Juicer 4.41 - Extract images, video...
File Juicer is a drag-and-drop can opener and data archaeologist. Its specialty is to find and extract images, video, audio, or text from files which are hard to open in other ways. It finds and... Read more
A Better Finder Rename 9.52 - File, phot...
A Better Finder Rename is the most complete renaming solution available on the market today. That's why, since 1996, tens of thousands of hobbyists, professionals and businesses depend on A Better... Read more
OmniFocus 2.2.3 - GTD task manager with...
OmniFocus helps you manage your tasks the way that you want, freeing you to focus your attention on the things that matter to you most. Capturing tasks and ideas is always a keyboard shortcut away in... Read more
TinkerTool 5.4 - Expanded preference set...
TinkerTool is an application that gives you access to additional preference settings Apple has built into Mac OS X. This allows to activate hidden features in the operating system and in some of the... Read more
Tinderbox 6.3.1 - Store and organize you...
Tinderbox is a personal content management assistant. It stores your notes, ideas, and plans. It can help you organize and understand them. And Tinderbox helps you share ideas through Web journals... Read more
Parallels Desktop 10.2.2 - Run Windows a...
Parallels Desktop is simply the world's bestselling, top-rated, and most trusted solution for running Windows applications on your Mac. With Parallels Desktop for Mac, you can seamlessly run both... Read more
Adobe Premiere Pro CC 2015 9.0.1 - Digit...
Premiere Pro CC 2015 is available as part of Adobe Creative Cloud for as little as $19.99/month (or $9.99/month if you're a previous Premiere Pro customer). Premiere Pro CS6 is still available for... Read more
Adobe After Effects CC 2015 13.5.1 - Cre...
After Effects CC 2015 is available as part of Adobe Creative Cloud for as little as $19.99/month (or $9.99/month if you're a previous After Effects customer). After Effects CS6 is still available... Read more

Domino Drop (Games)
Domino Drop 1.0 Device: iOS Universal Category: Games Price: $1.99, Version: 1.0 (iTunes) Description: Domino Drop is a delightful new puzzle game with dominos and gravity!Learn how to play it in a minute, master it day by day.Your... | Read more »
OPERATION DRACULA (Games)
OPERATION DRACULA 1.0.1 Device: iOS Universal Category: Games Price: $5.99, Version: 1.0.1 (iTunes) Description: 25% off launch sale!!! 'Could prove to be one of the most accurate representations of the Japanese bullet hell shmup... | Read more »
Race The Sun (Games)
Race The Sun 1.01 Device: iOS iPhone Category: Games Price: $4.99, Version: 1.01 (iTunes) Description: You are a solar craft. The sun is your death timer. Hurtle towards the sunset at breakneck speed in a futile race against time.... | Read more »
Tap Delay (Music)
Tap Delay 1.0.0 Device: iOS Universal Category: Music Price: $4.99, Version: 1.0.0 (iTunes) Description: Back in the “old days”, producers and engineers created delay and echo effects using tape machines. Tap Delay combines the warm... | Read more »
This Week at 148Apps: July 20-24, 2015
July is Heating Up With 148Apps How do you know what apps are worth your time and money? Just look to the review team at 148Apps. We sort through the chaos and find the apps you're looking for. The ones we love become Editor’s Choice, standing out... | Read more »
Red Game Without A Great Name (Games)
Red Game Without A Great Name 1.0.3 Device: iOS Universal Category: Games Price: $2.99, Version: 1.0.3 (iTunes) Description: The mechanical bird is flying through an unfriendly, Steampunk world. Help it avoid obstacles and deadly... | Read more »
Warhammer: Arcane Magic (Games)
Warhammer: Arcane Magic 1.0.2 Device: iOS Universal Category: Games Price: $9.99, Version: 1.0.2 (iTunes) Description: Engage in epic battles and tactical gameplay that challenge both novice and veteran in Warhammer: Arcane Magic, a... | Read more »
Mazes of Karradash (Games)
Mazes of Karradash 1.0 Device: iOS Universal Category: Games Price: $1.99, Version: 1.0 (iTunes) Description: The city of Karradash is under attack: the monsters of the Shadow Realms are emerging from the depths.No adventurer is... | Read more »
Battle Golf is the Newest Game from the...
Wrassling was a pretty weird - and equally great - little wressling game. Now the developers, Folmer Kelly and Colin Lane, have turned their attention to a different sport: golfing. This is gonna be weird. [Read more] | Read more »
Qbert Rebooted has the App Store Going...
The weird little orange... whatever... is back, mostly thanks to that movie which shall remain nameless (you know the one). But anyway it's been "rebooted" and now you can play the fancy-looking Qbert Rebooted on iOS devices. [Read more] | Read more »

Price Scanner via MacPrices.net

Apple’s Education discount saves up to $300 o...
Purchase a new Mac or iPad at The Apple Store for Education and take up to $300 off MSRP. All teachers, students, and staff of any educational institution qualify for the discount. Shipping is free,... Read more
12-inch MacBooks in stock for $20 off, save o...
Adorama has 12″ Retina MacBooks in stock for $20 off MSRP including free shipping plus NY & NJ sales tax only. For a limited time, Adorama will include a free Apple USB-C to USB Adapter, free 4-... Read more
College Student Deals: Additional $100 off Ma...
Take an additional $100 off all MacBooks and iMacs at Best Buy Online with their College Students Deals Savings, valid through August 8, 2015. Anyone with a valid .EDU email address can take... Read more
2015 13-inch 2.7GHz Retina MacBook Pro on sal...
B&H Photo has the new 2015 13″ 2.7GHz/128GB Retina MacBook Pro on sale today for $1199 including free shipping plus NY sales tax only. Their price is $100 off MSRP. Read more
2.8GHz Mac mini available for $988, includes...
Adorama has the 2.8GHz Mac mini available for $988, $11 off MSRP, including a free copy of Apple’s 3-Year AppleCare Protection Plan. Shipping is free, and Adorama charges sales tax in NY & NJ... Read more
Updated Mac Price Trackers
We’ve updated our Mac Price Trackers with the latest information on prices, bundles, and availability on systems from Apple’s authorized internet/catalog resellers: - 15″ MacBook Pros - 13″ MacBook... Read more
High-Precision Battery Fuel Gauge IC Extends...
Renesas Electronics Corporation has announced its new lithium-ion (Li-ion) battery fuel gauge IC, the RAJ240500, designed to extend battery life for connected mobile devices such as tablets, notebook... Read more
27-inch 3.3GHz 5K iMac on sale for $1799, $20...
B&H Photo has the 27″ 3.3GHz 5K iMac on sale for $1799 including free shipping plus NY tax only. Their price is $200 off MSRP, and it’s the lowest price available for this model from any Apple... Read more
Twelve South Free Dual Screen Backgrounds Co...
Twelve South has posted a second collection of travel Desktop photos, noting: For the Twelve South team, a vacation is never just a vacation. It’s a time to try out new prototypes on the road, visit... Read more
Apple Refurbished iMacs available for up to $...
The Apple Store has Apple Certified Refurbished iMacs available for up to $380 off the cost of new models. Apple’s one-year warranty is standard, and shipping is free: - 27″ 3.5GHz 5K iMac – $1949 $... Read more

Jobs Board

*Apple* Retail - Multiple Positions (US) - A...
Job Description: Sales. Specialist - Retail Customer Service and Sales. Transform Apple Store visitors into loyal Apple customers. When customers enter the store, Read more
*Apple* Retail - Multiple Positions (US) - A...
Job Description: Sales Specialist - Retail Customer Service and Sales Transform Apple Store visitors into loyal Apple customers. When customers enter the store, Read more
*Apple* Retail - Multiple Positions (US) - A...
Job Description: Sales. Specialist - Retail Customer Service and Sales. Transform Apple Store visitors into loyal Apple customers. When customers enter the store, Read more
*Apple* Customer Experience (ACE) Leader - A...
…management to deliver on business objectives Training partner store staff on Apple products, services, and merchandising guidelines Coaching partner store staff on Read more
Project Manager - *Apple* Pay Security - Ap...
**Job Summary** The Apple Pay Security team is seeking a highly organized, results-driven Project Manager to drive the development of Apple Pay Security. If you are Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.