• Keine Ergebnisse gefunden

Filing the Counter Obied

Im Dokument PenPomt GO (Seite 154-160)

STATUS s;

Debugf(ICntrApp:CntrAppFree");

ObjCallRet(rnsgDestroy, pData->counter, Nil(P_ARGS), s);

II Unrnap the file

ObjCallRet(rnsgFSMernoryMapFree, pData->fileHandle, Nil(P_ARGS), s);

II Free the file handle

.ObjCallRet(rnsgDestroy, pData->fileHandle, Nil(P_ARGS), s );

return stsOK;

MsgHandlerPararnetersNoWarning;

1* CntrAppFree *1

Filing the Counter Obied

The only thing that is left to do is to tell the counter object when to save and restore its data. For this, you send the resource messages msgResPutObject and msgResGetObject to the resource file handle created by the Application

Framework. These messages are defined in RESFILE.H. You do not send msgSave and msgRestore directly to the counter object.

The resource file handle is an instance of clsResFile. When you send a message to the resource file handle, you tell it which object you want to put or get. In the case of msgResPutObject, clsResFile writes information about the object to the resource file, then sends msgSave to the object. In the case of msgResGetObject, clsResFile reads information about the object from the file, creates the object, which is essentially empty until clsResFile sends msgRestore to the object. This is how objects receive msgSave and msgRestore.

Saving the Counter Object

When CounterApp receives msgSave, it sends msgResPutObject to the file handle passed in with the msgSave arguments.

MsgHandlerWithTypes(CntrAppSave, P OBJ_SAVE, P_CNTRAPP_INST)

{

STATUS s;

Debugf(ICntrApp:CntrAppSave");

II Save the counter object.

ObjCallRet(rnsgResPutObject, pArgs->file, pData->counter, s);

return stsOK;

MsgHandlerPararnetersNoWarning;

1* CntrAppSave *1

CounterApp doesn't have to save its own data, because the file FORMATFILE is memory mapped to its data.

"..,.. Restoring the Counter Obiect

When CounterApp receives msgRestore, it sends msgResPutObject to the file handle passed in with the msgRestore arguments.

MsgHandlerWithTypes(CntrAppRestore, P_OBJ_RESTORE, P_CNTRAPP_INST).

{

FS NEW fsn;

CNTRAPP_INST inst;

STATUS s;

(Open the memory mapped file.)

II

Restore the counter object.

ObjCallJmp(ms'gResGetObject, pArgs->file, &inst.counter, s, Error);

II

Update instance data.

ObjectWrite(self, ctx, &inst);

return stsOK;

MsgHandlerParametersNoWarning;

Error:

return s;

1* CntrAppRestore *1

". Menu Support

clsCntrApp creates a menu by specifying the contents of the menu statically in a toolkit table. clsTkTable is the ancestor of several VI components which display a set of windows, including choices, option tables, and menus. I,nstead of creating each of the items in a toolkit table by sending msgNew over and over to different classes, you can specify in.a set of toolkit table entries what should be in the table.

When you send msgNew to clsTkTable (or one of its descendants) it creates its child items based on the information you gave it.

When it receives msgAppOpen, clsCntrApp appends its menu to the SAMs (standard application menus) by passing its menu as an argument to

msgAppCreateMenuBar.

MsgHandlerWithTypes(CntrAppOpen, P_ARGS, P_CNTRAPP_INST)

(

APP _METRICS ami .MENU NEW ron;

LABEL NEW In;

STATUS s;

char buf[30)i

II

Get app metrics.

ObjCallJmp(msgAppGetMetrics, self, &am, s, Error);

II

Set the label as the clientWin.

9.4.3.2

9.S

ObjCallJmp(msgFrameSetClientWin, am.mainWin, In.object.uid, s, Error);

II

Create and add menu bar.

CHAPTER 9 / SAVING AND RESTORING DATA (COUNTER APP) 147 .

ObjCallJmp(msgNewDefaults, clsMenu, &mn, s, Error);

mn.tkTable.client = self;

mn.tkTable.pEntries = CntrAppMenuBar;

ObjCallJmp(msgNew, clsMenu~ &mn, s, Error);

ObjCallJmp(msgAppCreateMenuBar, self, &mn.object.uid, s, Error);

ObjCallJmp(msgFrameSetMenuBar, am.mainWin, mn.object.uid, s, Error);

Menu Support

Buttons 9.5.1

The items in the menu are a set of buttons. When you create a button in toolkit table entry, you specify:

• The button's string

• The notification message the button should send when the user activates it

• A value for the button.

There are other fields in a TK_TABLE_ENTRY, but you can rely on their defaults ofO.

The menu bar used in CounterApp is described by the TK_TABLE_ENTRY structure named CntrAppMenuBar in CNTRAPP.C.

typedef enum CNTRAPP_DISPLAY_FORMAT dec, oct, hex

CNTRAPP_DISPLAY_FORMAT,

*P_CNTRAPP_DISPLAY_FORMAT;

typedef struct CNTRAPP_INST {

P CNTRAPP DISPLAY FORMAT pFormat;

OBJECT fileHandle;

OBJECT counter;

CNTRAPP_INST,

*P_CNTRAPP_INST;

static TK_TABLE_ENTRY ~ntrAppMenuBar[] = {

} ;

{"Representation", 0, 0, 0, tkMenuPullDown, clsMenuButton}, {"Dec", msgCntrAppChangeFormat, dec},

{"Oct", msgCntrAppChangeFormat, oct}, {"Hex", msgCntrAppChangeFormat, hex}, {pNull} ,

{pNull}

When the user taps one of the buttons, it sends msgCntrAppChangeFormat to its client, which by default is the application. The message argument is the value of the button (dec, oct, or hex). clsCntrApp's message handler for

msgCntrAppChangeFormat looks at the message argument to determine which button the user tapped.

MsgHandlerWithTypes(CntrAppChangeFormat, P_ARGS, P_CNTRAPP_INST)

{

APP METRICS am;

WIN thelabel;

STATUS s;

char buf[30];

Debugf(ICntrApp:CntrAppChangeFormat");

II II

Update mmap data

II *

(pData->pFormat) = (CNTRAPP_DISPLAY_FORMAT) (U32)pArgs;

II

Build the string for the label.

StsRet(BuildString(buf, pData), s);

II

Get app metrics.

ObjCallRet(msgAppGetMetrics, self, &am, s);

II

Get the clientWin.

ObjCallRet(msgFrameGetClientWin, am.mainWin, &thelabel, s);

II

Set the label string.

ObjCallRet(msgLabelSetString, thelabel, buf, s);

return stsOK;

MsgHandlerParametersNoWarning;

1* CntrAppChangeFormat *1

Chapter 10 / Handling Input (Tic-Tac-Toe)

Tic-Tac-Toe is a large, robust application whjch demonstrates how to "play along" with many of the PenPoint protocols affecting applications:

• SAMs (standard application menus)

• Selections

• Move! copy protocol

• Keyboard input focus

• Stationery

• Help

• Option sheets.

The rest of this chapter details the architecture ofTic-Tac-Toe, its files, classes, objects, etc, and describes some enhanced application features implemented in Tic-T ac-Toe.

,,-'ic-'ac-'oe Obiects

No tutorial of this size can give you a course in object-oriented program design. It is an art, not a science. The books mentioned in Chapter 3 will be helpful. No matter what your experience level, you will find that you redesign your object hierarchy at least once. (Here at GO, we redesigned our class hierarchy countless times in the first two years-now they're quite stable.) But there are some generally-accepted techniques for breaking up an application into manageable components, and this tutorial will lead you through them.

Each section from now on will discuss the various design choices made.

~ Application Components

A typical functional application does something in its application window, then saves data in the document working directory.

Tic-Tac-Toe does this: it displays a tic-tac-toe board in its window, then stores the state of the board. Its application class is clsTttApp. The application creates its own class to display the board, clsTttView. It also creates a separate object just to store the state of the board, clsTttData.

10.1

10.1.1

Figure 10-1

Tic-Tac-Toe Classes and Instances

PenPoint provides:

Objects in a running instance of your application

",. Separate Stateful Data Obiects

The tic-tac-toe data object's set ofXs and Os are the main part of its state, which it must preserve.

The application and view also maintain some state, the application files its version, and the view remembers how thick to ,draw the lines on thetic-tac-toe board.

10.1.2

CHAPTER 10 I HANDLING INPUT (TIC-TAC-TOE) 151 Tic-Tac-Tae Window

F""'~~c'~~c'@~ ~~~Qg~~Qg~~

This table lists the files in Tic-T ac-Toe:

10.2

Message tables for clsTttApp, clsTttView, and clsTttData.

TttDbgHelper support macro and debug flags, TTT3ERSION typedef, function definitions for routines in TTTUTIL.C and debugging routines in TTTDBG.C, and class UID definitions.

Implements the main routine and most of clsTttApp's message handlers.

Implements most of clsTttView, handling repaint and input.

Implements clsTttData.

Utility routines to create scrollwin, create and adjust menu sections, read and write filed data and version numbers, get application components, handle selection. Also

application-specific routines to manipulate Tic-Tac-Toe square values.

Message handlers for the option sheet protocol.

Message handlers for the move/copy selection transfer protocol.

Miscellaneous routines supporting the Debug menu choices (dump, trace, force repaint, etc.).

Defines the TK_TABLE_ENTRYarrays for Tic-Tac-Toe's menu bar.

Defines clsTttApp messages.

Defines clsTttView messages and their message argument structures, and defines tags used in the view's option sheet.

Defines possible square values, various Tic-Tac-Toe data structures, and clsTttView messages and their message argument structures. .

Sets up UID-to-string translation tables which the Class Manager uses to provide more informative debugging output.

".. Tic-Tac-Toe Window

10.3

There is no pre-existing class which draws letters in a rectangular grid. So, some work is needed here. The PenPoint UI Toolkit provides labels which can have borders, along with clsTableLayout which lets you position windows in a regular grid. So, you could create the tic-tac-toe board by creating nine of one-character labels in a table layout window. However, there are some problems with this:

• Labels don't (ordinarily) scale to fit the space available .

• Each label is a window. Windows are relatively "cheap" in PenPoint, but if we were to change to a 16 x 16 board, it would use 256 single-character label windows.

So, to start with, we'll create a single window and draw the squares in this.

Im Dokument PenPomt GO (Seite 154-160)