GEOS SDK TechDocs
|
|
4.3 Defining Methods
|
4.5 Sending Messages
In GEOS programs, you can instantiate objects in two ways: You can declare them in your source code with the
@object
keyword, or you can instantiate them and fill in their instance data during execution. In most cases, you will probably do the former, especially with generic UI objects.
Additionally, you can create resources and chunks with the
@start, @end
,
@header
, and
@chunk
keywords. GEOS libraries also need an additional set of declarations in their definition (
.goh
) files; these declarations (
@deflib
and
@endlib
) indicate that the code contained between them is part of the specified library.
@deflib, @endlib
If your geode is a library, it will likely have a number of
.goh
files. Each of these files contains some portion of the library's code and is included by applications that use the library. The library code must be delimited by the two keywords
@deflib
and
@endlib
, which have the following formats:
@deflib <libname> @endlib
@deflib ui
/* library code here */
@endlib
Note that these two keywords are only necessary in files that define classes in the library. Files that have just code or data used in the library do not require them (though they are allowed).
@start, @end, @header, @chunk, @gstring, @chunkArray, @elementArray, @extern
There are essentially three types of resources in GEOS: code resources containing routines and methods, object blocks containing object instance chunks (and often data chunks), and data resources containing only data chunks. Code resources are created automatically, and no declaration is required for them (unless you require special segments; then you should use the pragmas appropriate for your C compiler).
Object blocks or other LMem resources are declared with
@start
and
@end
. You can set a special header on a local memory resource with the
@header
keyword. These are described below, and an example of declaring the resource block is given in Declaring Data Resources
. Note that the
@header
keyword must come between the
@start
and
@end
delimiters.
@start <segname> [, <flags>]; @header <type> [= <init>]; @end <segname>
data
is set, the block will be set to a data resource--the default is an object block. If the flag
notDetachable
is set, the resource block will never be saved to a state file.
LMemBlockHeader
(for non object blocks) or
ObjLMemBlockHeader
(for object blocks).
The resource elements (objects or chunks, for example) are also declared
within the
@start
and
@end
delimiters. The
@chunk
keyword declares a data chunk and is shown below. For the
@object
keyword, see the next section.
@chunk <type> <name> [= <init>];
There is a special-case syntax for the declaration of a chunk which contains GString data. A GString is a stored series of graphics commands, discussed in detail in the Graphics Environment chapter. Its syntax may be summarized:
@gstring <name> = { <init> };
@gstring
chunk is set up by means of the
GS...()
macros.
Two other types of resource elements may also be defined, both of which are
array types. The
@chunkArray
keyword declares a chunk array structure,
and the
@elementArray
keyword declares an element array structure. See the Local Memory chapter, for information on the structure and usage of chunk and element arrays. These static arrays must not appear
in a resource marked data; the resource may be marked
notDetachable or may be unmarked. In the .gp file,
the resource should be marked lmem, optionally
read-only.
The formats for the keywords are described below:
@chunkArray <stype> <aname> = {<init>};
@elementArray <stype> <aname> [ = {<init>} ];
@chunk ChunkArrayHeader <aname> = {0,
sizeof(<stype>), 0, sizeof(ChunkArrayHeader) };
Here is an example showing two statically declared chunk arrays:
#define CELL_DATA_LENGTH 15
typedef char CellDataStruct[CELL_DATA_LENGTH];
@chunkArray CellDataStruct headerDataArray = {
"no", "Description", "type", " $/lb"
};
@chunkArray CellDataStruct coffeeDataArray = {
"0", "House Blend", "PEET", "$ 6.95",
"1", "Mocha-Java", "PEET", "$10.75",
"2", "Garuda Blend", "PEET", "$ 9.25",
"3", "Italian Dark", "DARK", "$ 8.75",
"4", "French Roast", "DARK", "$ 8.75",
"5", "Sumatra", "PACF", "$ 8.95",
"6", "Sulawesi-Kal", "PACF", "$11.55",
"7", "Java", "PACF", "$ 8.75",
"8", "Aged Java", "PACF", "$ 9.75",
"9", "Mexican", "AMER", "$ 7.55"
};
One other keyword,
@extern
, allows you to use chunks from a different compilation session. The
@extern
keyword can be used to reference remote (external) chunks, objects, and visual monikers. If the item referenced by
@extern
is not actually defined anywhere, Glue will return an error when it tries to link the item. (Note also that Glue can not link through an external item; only one layer of external linkage is allowed. Thus, one object could not have an
@extern
to a chunk that had an
@extern
to a visMoniker.) Children in object trees may not be defined with
@extern
; Goc will produce an error in this case. The format of this keyword is as follows:
@extern chunk <cname>; @extern object <oname>; @extern visMoniker <vmname>;
Code Display 5-16 Declaring Data Resources
/* This example declares a data block with three different chunks in it and * its own header type. */
typedef struct {
LMemBlockHeader MLMBH_meta; /* basic header structure */
int MLMBH_numEntries; /* the number of entries in the block */
} StudentBlockHeader;
@start StudentBlock, data; /* data flag indicates LMem block */ @header StudentBlockHeader = 1; /* initialize new header fields */
/* The three chunks are defined below. Each represents a single field associated * with a single student; that is why the header's MLMBH_numEntries field contains * one (rather than three). */
@chunk char firstName[] = "John"; @chunk char lastName[] = "Student"; @chunk int grade = 6;
@end StudentBlock /* end of resource block */
@object, @default, @specificUI, gcnList
The
@object
keyword is much like the
@chunk
keyword in its use. It allocates a chunk in a resource segment and fills it with initializer data. However, it also does much more in that it creates an object of a specified class and fills it with default data if no initializer data is specified.
The
@object
keyword, like
@chunk
, must be used between the delimiters
@start
and
@end
(see above). However, it must be used in an object block (it can not be used in a data resource segment). Its format is below, and several examples are shown in Declaring Objects with @object
.
@object <class> <name> = <flags>* {
<fieldName> = <init>;*
<varName> [= <init>];*
};
ignoreDirty
. When set, it will cause the object to ignore when changes have been made to its instance data; this means it will always be restored from a state file in the same way as it is defined in the code file. This flag should
not
be set for any generic objects.
@object
declaration or use the keyword
@default
for the initializer. When declaring variable data, though, be aware that if the extra data is a structure, the initializer must be enclosed in curly braces.GEOS supports special instance data fields as described in Defining Instance Data Fields . These are declared as normal fields and are described below. Also, generic hints are implemented as variable data, so they are added to an object in the same way as other variable data types.
All objects declared in a static tree (e.g., your application's generic tree) should be in the same source file. If they are in different files, then they may be joined into a single tree only by dynamically adding objects from one file as children to objects of the other.
Note that if one file contains a tree of objects, then you may incorporate the whole tree by simply dynamically adding the top object in the file to the main tree. You won't have to add each object individually.
If an object declared in one source file will send a message to an object in another source file, you must include an
@extern
line in the source file containing the sending object:
@extern object ReceivingObjectName;
The message itself should be sent in the following manner (with variations possible if you will be using
@call
, passing arguments, or what have you):
optr ROOptr; ROOptr = GeodeGetOptrNS(@ReceivingObjectName); @send ROOptr::MSG_DO_SOMETHING(0, 0);
GeodeGetOptrNS()
returns the object pointer for the object. In the case of a multiply-launchable program, Goc has no way of knowing which program's @ReceivingObjectName should receive the message--by using
GeodeGetOptrNS()
, you ensure that the object getting the message will be in the same geode as the object calling the routine.
If an object is to be part of an object tree, its class (or one of its superclasses)
must
have at least an
@link
instance data field as does
GenClass
. If the object is to be allowed to have children, it must also have a field of type
@composite
. These allow Goc to automatically and correctly link the tree together.
As described in Defining Instance Data Fields
, the
@composite
field points to the first child of an object, and the
@link
field points either to the object's next sibling or back to the parent if there is no next sibling. However, all child declaration is done completely in the composite field when using
@object
. The format is as follows:
<fname> = <childName> [, <childname>]* ;
@composite
in the class definition.
@object
declaration.There are many examples of this in the sample applications. Some simple examples are shown below.
GI_comp = @TicTacPrimary;
GI_comp = @TicTacView, @TicTacGameMenu;
VCI_comp = @TTX1, @TTX2, @TTX3, @TTX4, @TTX5, @TTO1, @TTO2, @TTO3, @TTO4, @TTO5;
For an object to have a visual moniker, it must have an instance data field of type
@visMoniker
as
GenClass
does (see Defining Instance Data Fields
). If you are in fact working with GenClass' GI_visMoniker field, you might want to consult its description in the GenClass chapter.
Visual monikers may take many forms, and the declaration line changes depending on which form you are using. The form ranges from a simple text field to a complex list of possible monikers based on video resolution. Each of these forms and the declaration line for it is given below.
The following form is used for simple text strings (shown with example):
<fname> = <string>; GI_visMoniker = "One";
The following form is used for text strings that have a keyboard navigation character. A keyboard navigation character can be a character enclosed in single quotation marks, a numerical constant, or a text string representing some constant defined with
#define
. If it's a text string, the string is passed on for the C compiler to parse. The form is shown below with an example.
<fname> = <nav>, <string>; GI_visMoniker = 'V', "View";
The following form is used when a list of monikers is required. Most frequently, this form is used when defining an application's icons; one moniker for each potential screen resolution will be included in the list. The form is shown below, along with an example.
<fname> = list { <nameList> };
GI_visMoniker = list {
@DocDirButtonSCMoniker,
@DocDirButtonSMMoniker,
@DocDirButtonSCGAMoniker
}
@chunk
or
@visMoniker
keyword.
It is possible when declaring a list of visual monikers to have each moniker within a chunk or to declare each moniker with the
@visMoniker
keyword. If used on its own line, this keyword takes the form
@visMoniker <fname> = <init>;
The fields are the name of the moniker (same as that specified in the moniker list) and the moniker data. The visual moniker will be put in its own chunk just as if the moniker had been declared with the
@chunk
keyword, but using
@visMoniker
often is clearer and easier.
Visual monikers and strings presented by a program's UI are often accompanied by localization information. By placing a
@localize
keyword after a
@visMoniker
or
@chunk
construction, you can provide instructions for whoever uses the ResEdit program to localize your program (i.e., to translate its strings into a foreign language). This keyword can use any syntax from the following list:
@localize { <string> <min>-<max> };
@localize { <string> <length> };
@localize { <string> };
@localize <string>;
@localize not;
GEOS employs a "General Change Notification" (GCN) system which allows objects to register for notification of certain types of events. For example, some applications may want to notify for changes in the file system (file deletes, moves, copies, etc.); some objects may require notification each time the selection changes (e.g., a PointSizeControl object needs to know when the user changes a text selection). For further information, see the General Change Notification chapter.
While many objects will add themselves to and remove themselves from GCN lists dynamically, others will need to be placed on certain GCN lists in their definitions. For this, the
gcnList
keyword (the only one not preceded by the marker
@
) is used. Its format is shown below:
gcnList(<manufID>, <ltype>) = <oname>,+;
A keyboard accelerator acts as a "hot key," invoking the object's default action when pressed.
The accelerator character is defined in an instance field declared with
@kbdAccelerator
as shown in Defining Instance Data Fields
. The form of declaration follows.
<fname> = [@specificUI] <mod>* <key>;
@kbdAccelerator
instance data field.
@specificUI
alt
,
control
,
ctrl
, and
shift
.Often an object will be declared with the default values of an instance data field. Other times, especially with generic UI object attributes, an object will have the default values with one or two modifications. In the first case, the instance data field does not need to be addressed at all; the default value will be used if no declaration is made.
In the second case, however, you must use the
@default
keyword to get the default values. If modifications are made and
@default
is not used, all default values will be lost. This is normally used only with bitfield-type attributes, and modifications are made with bitwise operators. The use of
@default
is shown below.
<fname> = @default [<op> [~]<attr>]*;
Code Display 5-17 Declaring Objects with @object
/* This example shows the use of @start, @object, @visMoniker, and @end. * It is taken from the TicTac sample application. */
@start AppResource; /* The AppResource resource block contains the TicTacApp * object and its visual moniker chunk. */
@object GenApplicationClass TicTacApp = {
GI_visMoniker = list { @TicTacTextMoniker };
GI_comp = @TicTacPrimary;
gcnList(MANUFACTURER_ID_GEOWORKS,GAGCNLT_WINDOWS) = @TicTacPrimary;
}
@visMoniker TicTacTextMoniker = "TicTacToe"; @end AppResource
@start Interface;
/* The Interface resource declares TicTac's primary window and other UI
* gadgetry. Only the GenView from this application is shown. */
@object GenViewClass TicTacView = {
GVI_content = @TicTacBoard; /* A relocatable optr field */
GVI_docBounds = {0, 0, BOARD_WIDTH, BOARD_HEIGHT};
/* A Rectangle structure */
GVI_color = { C_BLUE, 0, 0, 0 }; /* A ColorQuad structure */
GVI_horizAttrs = @default | GVDA_NO_LARGER_THAN_CONTENT
| GVDA_NO_SMALLER_THAN_CONTENT
& ~GVDA_SCROLLABLE;
/* The NO_LARGER and NO_SMALLER attributes are set in the
* field, and SCROLLABLE is cleared. The SCROLLABLE attribute
* is not set by default for the GenView; it is shown here
* for illustration. */
GVI_vertAttrs = @default | GVDA_NO_LARGER_THAN_CONTENT
| GVDA_NO_SMALLER_THAN_CONTENT;
}
@end Interface
GEOS SDK TechDocs
|
|
4.3 Defining Methods
|
4.5 Sending Messages