GenClass
provides the basic functionality, via message handlers and instance data, for all objects in the generic object library.
All
generic objects are subclassed off this master class. Therefore, all generic objects will contain common behavior in the instance fields and message handlers of
GenClass
.
GenClass
allows you to create generic trees, manage state data, and attach data such as visual monikers, keyboard accelerators, and even variable-length data to a specific object.
The Gen world, along with the Vis
world, contains a large variety of pre-defined objects ready to install into your applications.
GenClass
itself is not a normally usable object, however. It should not be directly subclassed and used by your application. The functionality within this chapter will normally be accessed within one of
GenClass
' subclasses.
All of these pre-defined objects will contain behavior explained in this chapter. The instance data and message handlers described in this chapter may be implemented differently under different specific UIs, but the basic functionality will remain the same. Therefore, it is important to fully understand the concepts explained in this chapter before using any generic object.
1 GenClass Features
2 GenClass Instance Data
2.1 Instance Fields
2.2 Vardata
3 GenClass Basics
3.1 Visual Monikers
3.2 Composite Links
3.3 Keyboard Accelerators
3.4 Attributes
3.5 States
4 Modifying GenClass Instance Data
4.1 Visual Monikers
4.2 Managing Visual Monikers
4.3 Managing Keyboard Accelerators
5 Generic Trees
5.1 Child/Parent Searches
5.2 Manipulating Children Directly
5.3 Branch Construction/Destruction
6 Vardata
6.1 Optional Attributes (ATTRs)
6.2 Hints to the Specific UI
6.3 Dynamically Managing VarData
7 Special Message Passing
7.1 Parent and Child Message Passing
7.2 Generic Upward Queries
7.3 Object-Specific Queries
8 Visual Refreshing
9 Setting Sizes
10 Activation Messages
11 Focus Modifications
12 Navigation Methods
13 Window Positions and Sizes
GenClass
provides the instance fields and message handlers common to all generic objects. You will need to understand and manipulate
GenClass
operations in almost every generic object you create.
GenClass
is very powerful and diverse, providing a number of wide-ranging functions within your user interface.
GenClass
in specific provides the following:
Most importantly,
GenClass
provides the common functionality that will be accessed by all generic objects from the simplest GenTrigger to the most complex GenView.
Generic objects, along with visual objects, are the main means through which a user can communicate with an application. All generic objects follow an object-oriented class hierarchy with
GenClass
acting as their superclass. Therefore, all
generic objects will share the attributes and behavior of
GenClass
, although many may not make use of the entire utility provided.
GenClass
provides a set of instance fields common to all subclasses. These instance fields are listed in GenClass Instance Data Fields
.
Code Display 2-1 GenClass Instance Data Fields
@instance @link GI_link; @instance @visMoniker GI_visMoniker; @instance @composite GI_comp; @instance @kbdAccelerator GI_kbdAccelerator; @instance GenAttrs GI_attrs = 0; @instance GenStates GI_states = GS_USABLE | GS_ENABLED;
/* GenAttrs store attributes of a generic object. */
typedef ByteFlags GenAttrs; #define GA_SIGNAL_INTERACTION_COMPLETE 0x80 #define GA_INITIATES_BUSY_STATE 0x40 #define GA_INITIATES_INPUT_HOLD_UP 0x20 #define GA_INITIATES_INPUT_IGNORE 0x10 #define GA_READ_ONLY 0x08 #define GA_KBD_SEARCH_PATH 0x04 #define GA_TARGETABLE 0x02 #define GA_NOTIFY_VISIBILITY 0x01
/* GenStates store the usability states of a generic object. */
typedef ByteFlags GenStates; #define GS_USABLE 0x80 #define GS_ENABLED 0x40*
GI_visMoniker
chooses the title for the generic object, usually added in an appropriate location within the object by the specific UI. The moniker can be text, in the form of a null-terminated text string, or as a graphics string, usually set up separately. For more information on visual monikers, see Visual Monikers
.
GI_comp
assigns child objects to the current object (the parent).
GI_comp
takes a list of generic objects separated by commas as arguments in its instance field. It then sets each of those arguments as children of the current object. In the Goc preprocessor, the
GI_comp
arguments will be used to create a generic tree structure, reassigning present links using both the
GI_comp
instance field and an internal instance field,
GI_link
. The
GI_link
instance field is therefore an elemental instance field for every generic object but is rarely, if ever, accessed directly. For more information, see Composite Links
.
GI_kbdAccelerator
sets a given keystroke as a keyboard accelerator for the object. Usually, an object is activated in a manner relating to its specific UI implementation. Pressing the accelerator keystroke will activate the object in the same manner as if its default activation action had occurred. The instance field takes a modifier (
alt
,
shift
,
ctrl
, or combinations of these) and a character (a valid keyboard character) as its arguments. You can further specify the specific keyboard set to use. For more information, see Keyboard Accelerators
.
GI_attrs
defines how actions performed by the generic object will affect user interface input and output. You may set any, all, or none of these attributes within your object declaration. For more information, see Attributes
.
GI_states
defines in what state a generic object will be represented. Default states are GS_USABLE and GS_ENABLED. You may set any, all, or none of these states within your object declaration. For more information, see States
.
GenClass
provides a multitude of pre-defined vardata instance fields. You may add these vardata entries to a generic object directly within its object declaration. Vardata instance fields perform several key roles for a generic object. Specifically, they provide two distinct uses:
Any of these data may be accessed and altered using object system routines. For more information, see the GEOS Programming chapter.
Vardata attributes may contain the same functionality as other instance fields. Variable attributes, however, will only be allocated space within an object declaration if they are actually declared; instance data fields always take up space within an object, whether used or not. Therefore, vardata attributes are ideal for data that should only take up space if actually used. Vardata attributes are prefaced with
ATTR_
. Several ATTRs are included in
GenClass
. See ATTR vardata fields
for a complete list of these vardata attributes.
Code Display 2-2 ATTR vardata fields
@vardata void ATTR_GEN_PROPERTY; @vardata void ATTR_GEN_NOT_PROPERTY;
@vardata DestinationClassArgs ATTR_GEN_DESTINATION_CLASS; @reloc ATTR_GEN_DESTINATION_CLASS, 0, optr;
@vardata char[] ATTR_GEN_INIT_FILE_KEY; @vardata char[] ATTR_GEN_INIT_FILE_CATEGORY; @vardata void ATTR_GEN_INIT_FILE_PROPAGATE_TO_CHILDREN; @vardata void ATTR_GEN_USES_HIERARCHICAL_INIT_FILE_CATEGORY;
@vardata Point ATTR_GEN_POSITION; @vardata sword ATTR_GEN_POSITION_X; @vardata sword ATTR_GEN_POSITION_Y;
@vardata void ATTR_GEN_SEND_APPLY_MSG_ON_APPLY_EVEN_IF_NOT_MODIFIED; @vardata void ATTR_GEN_SEND_APPLY_MSG_ON_APPLY_EVEN_IF_NOT_ENABLED;
@vardata dword ATTR_GEN_VISIBILITY_DATA; @vardata word ATTR_GEN_VISIBILITY_MESSAGE; @vardata optr ATTR_GEN_VISIBILITY_DESTINATION; @reloc ATTR_GEN_VISIBILITY_DESTINATION, 0, optr;
@vardata GenFilePath ATTR_GEN_PATH_DATA;
@vardata ChunkHandle ATTR_GEN_FEATURE_LINK;
@vardata GenDefaultMonikerType ATTR_GEN_DEFAULT_MONIKER;
@vardata optr ATTR_GEN_OUTPUT_TRAVEL_START; @reloc ATTR_GEN_OUTPUT_TRAVEL_START, 0, optr;
/* Generic Help attributes */
@vardata char[] ATTR_GEN_HELP_FILE; @vardata byte ATTR_GEN_HELP_TYPE; @vardata void ATTR_GEN_HELP_FILE_FROM_INIT_FILE; @vardata optr ATTR_GEN_FOCUS_HELP; @vardata optr ATTR_GEN_FOCUS_HELP_LIB; @reloc ATTR_GEN_FOCUS_HELP_LIB, 0, optr; @vardata char[] ATTR_GEN_HELP_CONTEXT;
/* Generic Window attributes */
@vardata MemHandle ATTR_GEN_WINDOW_CUSTOM_LAYER_ID; @reloc ATTR_GEN_WINDOW_CUSTOM_LAYER_ID, 0, optr; @vardata WinPriority ATTR_GEN_WINDOW_CUSTOM_WINDOW_PRIORITY; @vardata LayerPriority ATTR_GEN_WINDOW_CUSTOM_LAYER_PRIORITY; @vardata MemHandle ATTR_GEN_WINDOW_CUSTOM_PARENT; @vardata void ATTR_GEN_CUSTOM_WINDOW; @vardata void ATTR_GEN_WINDOW_ACCEPT_INK_EVEN_IF_NOT_FOCUSED; @vardata KeyboardOverride ATTR_GEN_WINDOW_KBD_OVERRIDE; @vardata Point ATTR_GEN_WINDOW_KDB_POSITION;
ATTR_GEN_PROPERTY
and
ATTR_GEN_NOT_PROPERTY
affect a generic object's ability to behave as a properties group. These attributes override the property group's default behavior. For more information, see Generic Properties
.
ATTR_GEN_DESTINATION_CLASS
specifies an object class that should handle all messages sent out along a destination path. The type
DestinationClassArgs
contains a pointer to a
ClassStruct
. Typically, this attribute is used with a
TravelOption
destination to form a search path. The message for that generic object travels down a path specified in the
TravelOption
until it encounters an object class of type
ATTR_GEN_DESTINATION_CLASS
; at that point, the message will be handled. For more information, see Destination Classes
.
ATTR_GEN_INIT_FILE_KEY
,
ATTR_GEN_INIT_FILE_CATEGORY
,
ATTR_GEN_INIT_FILE_PROPAGATE_TO_CHILDREN
, and ATTR_GEN_USES_HIERARCHICAL_INIT_FILE_CATEGORY allow a generic object to load options from the .INI file upon startup (after receiving a
MSG_META_ATTACH
). Generic objects with these attributes will receive a
MSG_GEN_LOAD_OPTIONS
(with the category and key of the proper entry in the .INI file) and may intercept that message to provide additional behavior. For more information, see Initialization File Management
.
ATTR_GEN_POSITION
,
ATTR_GEN_POSITION_X
, and
ATTR_GEN_POSITION_Y
override default geometry management of an object and set a precise position for the object to appear within the UI, offset from the parent object. ATTR_GEN_POSITION specifies both a horizontal and a vertical position to place the object. ATTR_GEN_POSITION_X and ATTR_GEN_POSITION_Y specify either a horizontal or vertical position to align the object along. You should avoid using these attributes because they override default behavior and may result in different (and potentially unsightly) appearances under different specific UIs. For more information, see Altering Default Geometry Management
.
ATTR_GEN_SEND_APPLY_MSG_ON_APPLY_EVEN_IF_NOT_MODIFIED
and
ATTR_GEN_SEND_APPLY_MSG_ON_APPLY_EVEN_IF_NOT_ENABLED
affect generic objects that contain an apply message--a message that an object sends out when it wishes to apply changes made within that object. By default, an apply message will not be sent out if the object's state has not changed since the last apply or if the object is not enabled; these attributes tell the object to send out its apply message regardless of these conditions. For more information, see Altering Delayed Mode Activity
.
ATTR_GEN_VISIBILITY_DATA
,
ATTR_GEN_VISIBILITY_MESSAGE
, and
ATTR_GEN_VISIBILITY_DESTINATION
set the data, message or destination to use with the visibility notification mechanism in
GenClass
. The visibility mechanism allows an application to know when an object becomes visible and not visible. An object provides this notification if its GA_NOTIFY_VISIBILITY bit is set. For more information, see Notification of Visibility
.
ATTR_GEN_PATH_DATA
stores an object's generic path information in the form of a
GenFilePath
structure. This structure contains disk and path information including path name and file name; generic objects can use this attribute to store current or default paths and files. For more information, see Generic Paths
.
ATTR_GEN_FEATURE_LINK
contains a link to the next feature used by the GenControl mechanism when a controller's features map to multiple objects. It is unlikely you will use this attribute. For more information, see Feature Links
.
ATTR_GEN_DEFAULT_MONIKER specifies a default moniker for a generic object. This is generally used for graphic monikers that occur several places within the system. For more information, see Default Monikers .
ATTR_GEN_OUTPUT_TRAVEL_START
allows you to set a specific object to begin the
TravelOption
. Normally, objects that contain a
TravelOption
in their destination field use their own object as the point of reference for sending messages along travel paths. (I.e sending a message TO_FOCUS would send a message along the focus path, starting at the sending object.) This can be used for optimization purposes, enabling you to skip several layers of hierarchies.
ATTR_GEN_HELP_FILE , ATTR_GEN_HELP_TYPE, ATTR_GEN_HELP_FILE_FROM_INIT_FILE, ATTR_GEN_FOCUS_HELP, ATTR_GEN_FOCUS_HELP_LIB, and ATTR_GEN_HELP_CONTEXT specify the configuration of the help files for a generic object. Focus help starts help notification when the generic object gains the focus. For more information on Help files, see Help Management .
ATTR_GEN_WINDOW_CUSTOM_LAYER_ID , ATTR_GEN_WINDOW_CUSTOM_WINDOW_PRIORITY, ATTR_GEN_WINDOW_CUSTOM_LAYER_PRIORITY, ATTR_GEN_WINDOW_CUSTOM_PARENT, and ATTR_GEN_CUSTOM_WINDOW specify a window's interaction and place within the window system. ATTR_GEN_WINDOW_ACCEPT_INK_EVEN_IF_NOT_FOCUSED, ATTR_GEN_WINDOW_KBD_OVERRIDE, and ATTR_GEN_WINDOW_KBD_POSITION affect how input flows within a generic window. For more information, see Window Management .
Hints to the specific UI suggest added functionality to your application, and are prefaced with
HINT_
(such as
HINT_SEEK_REPLY_BAR
). Hints may also have data structures attached to them. There are a large number of pre-defined hints with
GenClass
. See Hints to the Specific UI
for details on the operation of hints.
Many of the hints provided in
GenClass
manage the geometry of generic objects. For complete information on these hints, see the Managing UI Geometry chapter.
 These hints are listed below and are explained within this chapter. Within
GenClass
, some hints are internal and are not listed in this code display.
Code Display 2-4 Hints Explained Within This Chapter
/* These hints are explained within this chapter (or they are self-explanatory). */
@vardata void HINT_FREQUENTLY_USED; @vardata void HINT_INFREQUENTLY_USED; @vardata void HINT_AN_ADVANCED_FEATURE;
@vardata void HINT_DEFAULT_DEFAULT_ACTION; @vardata void HINT_ENSURE_TEMPORARY_DEFAULT; @vardata void HINT_PREVENT_DEFAULT_OVERRIDES;
@vardata void HINT_SAME_CATEGORY_AS_PARENT;
@vardata void HINT_USE_TEXT_MONIKER; @vardata void HINT_USE_ICONIC_MONIKER;
@vardata void HINT_DEFAULT_FOCUS; @vardata void HINT_DEFAULT_TARGET; @vardata void HINT_DEFAULT_MODEL;
@vardata void HINT_PRESERVE_FOCUS; @vardata void HINT_DO_NOT_PRESERVE_FOCUS;
@vardata void HINT_GENERAL_CONSUMER_MODE;
@vardata void HINT_NEVER_ADOPT_MENUS; @vardata void HINT_ALWAYS_ADOPT_MENUS;
@vardata void HINT_NAVIGATION_ID; @vardata void HINT_NAVIGATION_NEXT_ID
@vardata void HINT_DISMISS_WHEN_DISABLED;
@vardata void HINT_TOOLBOX;
@vardata void HINT_SHOW_SHORTCUT; @vardata void HINT_DONT_SHOW_SHORTCUT; @vardata void HINT_DRAW_SHORTCUT_BELOW;
@vardata void HINT_CAN_CLIP_MONIKER_WIDTH; @vardata void HINT_CAN_CLIP_MONIKER_HEIGHT; @vardata void HINT_SHOW_ENTIRE_MONIKER;
@vardata BackgroundColors HINT_GADGET_BACKGROUND_COLORS; @vardata word HINT_GADGET_TEXT_COLOR;
@vardata SystemAttrs HINT_IF_SYSTEM_ATTRS; @vardata void HINT_ENDIF; @vardata void HINT_ELSE;
HINT_FREQUENTLY_USED, HINT_INFREQUENTLY_USED, and HINT_AN_ADVANCED_FEATURE are descriptive hints that describe the generic object's role within the UI. It is, of course, left up to the specific UI to implement any special behavior based on these hints.
HINT_DEFAULT_DEFAULT_ACTION , HINT_ENSURE_TEMPORARY_DEFAULT, and HINT_PREVENT_DEFAULT_OVERRIDES affect the default activation of objects within the UI. Objects with default activation can be activated indirectly (e.g., pressing the ENTER key within a dialog box activates a default trigger). For more information, see Default Actions .
HINT_SAME_CATEGORY_AS_PARENT indicates to the specific UI that this object should be treated in the same manner as its parent. Currently, this hint only affects GenInteractions. By default, GIV_SUB_GROUP GenInteractions within a GIV_POPUP menu have separator lines drawn around them to set them apart from other children. This hint removes those lines.
HINT_USE_TEXT_MONIKER and HINT_USE_ICONIC_MONIKER indicates that the generic object should choose either a text moniker or an iconic moniker if there exists a choice within the object's moniker list. Currently, these hints are not implemented.
HINT_DEFAULT_FOCUS , HINT_DEFAULT_TARGET, and HINT_DEFAULT_MODEL specify that the generic object is the default focus, target, or model node at this level in the application. HINT_PRESERVE_FOCUS and HINT_DO_NOT_PRESERVE_FOCUS affect how the focus node changes after an object's activation. For a complete discussion of the focus and target hierarchies, see the Input chapter.
HINT_GENERAL_CONSUMER_MODE
instructs the specific UI to show the object in GCM mode. This hint takes an argument of type
GeneralConsumerModeFlags
; this record contains two three-bit flags: GCMF_LEFT_ICON and GCMF_RIGHT_ICON, which specify which icon to use on both the left and right sides of the title bar. Each icon must be of type
GCMIcon
; current types are GCMI_NONE, GCMI_EXIT, and GCMI_HELP.
HINT_NEVER_ADOPT_MENUS and HINT_ALWAYS_ADOPT_MENUS affect the behavior of menus placed within a GenDisplay. Menus can either sit within the GenDisplay or appear in the associated GenPrimary when that GenDisplay is the target. Menus within GenDisplays are discouraged, however, as they are a fairly advanced UI metaphor.
HINT_NAVIGATION_ID and HINT_NAVIGATION_NEXT_ID allow the field navigation path within a windowed object. HINT_NAVIGATION_NEXT_ID sets the object to navigate to from the current object. An object with a matching HINT_NAVIGATION_ID must exist. For more information, see Keyboard Navigation Hints .
HINT_DISMISS_WHEN_DISABLED instructs the specific UI to dismiss the object when it is no longer fully enabled. This is typically useful for independently-displayable windows that should be dismissed in such cases.
HINT_TOOLBOX indicates that the generic object and all objects below it in the visual hierarchy are part of a "toolbox" and should draw themselves appropriately. Objects in toolboxes are typically much smaller than other components. For more information on toolboxes, see the Menus and Dialogs chapter.
HINT_SHOW_SHORTCUT , HINT_DONT_SHOW_SHORTCUT, and HINT_DRAW_SHORTCUT_BELOW affect the display of keyboard accelerators for generic objects. For more information, see Keyboard Accelerators .
HINT_CAN_CLIP_MONIKER_WIDTH and HINT_CAN_CLIP_MONIKER_HEIGHT instruct the specific UI to clip the object's moniker height or width if not enough space is provided for them. Objects with HINT_SHOW_ENTIRE_MONIKER will force the object to leave enough space to show its entire moniker, if possible.
HINT_GADGET_BACKGROUND_COLORS
causes grouping objects in toolboxes to draw custom background colors. The hint takes an argument of type
BackgroundColors
. Two colors can each be chosen for both the unselected state and the selected state; they will be blended together depending on the state of the object. If both colors are set to the same value, a solid color results. HINT_GADGET_TEXT_COLOR
selects the text color of a visual moniker, typically within a toolbox. This hint takes an argument of type
TextColors
.
HINT_IF_SYSTEM_ATTRS
, HINT_ENDIF, and HINT_ELSE may be used together to conditionally add hints to an object based on certain system criteria. If the
SystemAttrs
set in the HINT_IF_SYSTEM_ATTRS field are true for the current system, then the hints that follow (until a HINT_ENDIF is encountered) are included. If no HINT_ENDIF is encountered, then only the next hint is included. If the
SystemAttrs
do not match the current system, the following group of hints is deleted. For more information, see System Attributes
.
Remember that these vardata entries are hints; they can be ignored by the specific UI and their implementation varies from object to object. Some hints, for example, are only relevant for certain object classes. Your mileage may vary.
In most cases, you will set much of your generic object's instance data upon instantiation according to the values you include in your
.goc
file. You may also update and manipulate this instance data during execution with a variety of messages. The following section deals only with directly setting instance fields in your
.goc
file. For information on dynamically altering this instance data, see Modifying GenClass Instance Data
.
A visual moniker is a text or graphics string attached to a generic object. This visual moniker displays the given string in a manner relevant to the specific implementation of an object. For example, a GenTrigger might create a button with text inserted as the object's main visual implementation. The visual moniker in this case might cover the object's total area. A GenPrimary, on the other hand, might only add such text in a title bar of the window. In all cases, the specific user interface has final control over how a visual moniker is displayed to the user.
You may set the visual moniker of an object using the
GI_visMoniker
instance field. This instance field expects an argument of type
@visMoniker
. The visual moniker of an object is not actually stored within this instance field, however. The visual moniker of an object is stored within its own chunk, outside of the object itself. The
GI_visMoniker
instance field contains a chunk handle to this visual moniker chunk. Because a visual moniker can only be referenced by a chunk handle, visual monikers for an object must reside in the same block as the object that points to them. The UI will set up this chunk and chunk handle automatically.
Within the object's definition, set the
GI_visMoniker
field to the desired visual moniker (either a text or graphics string). This can be done either by directly setting the
GI_visMoniker
field to the string or by indirectly setting the field to a visual moniker chunk defined elsewhere within your user interface with the Goc keyword
@visMoniker
. (See Setting Visual Monikers
.)
Code Display 2-5 Setting Visual Monikers
/* A visual moniker can be set directly within the object's definition. */
@object GenTriggerClass MyTrigger = { GI_visMoniker = "Push Me"; }
/* A visual moniker may also be defined indirectly within a .goc file. */
/* The data for MyMoniker is set using the Goc keyword @visMoniker. This moniker * must reside in the same resource block as the object using it. This moniker * should be declared before being used in an object declaration. */
@visMoniker MyMoniker = "Push Me";
@object GenTriggerClass MyTrigger = { GI_visMoniker = @MyMoniker; }
Remember that the
GI_visMoniker
instance field only stores a chunk handle to the actual string. The visual moniker for the object is not contained in the object chunk itself.
Text monikers may also specify a character to act as a mnemonic. Mnemonics are keyboard shortcuts used to activate an object without use of the mouse. Menus, menu items, and buttons frequently have mnemonic characters attached. This allows a user to navigate quickly to other UI objects or to activate them. If the specified character is within the text moniker, that letter will be highlighted in whatever fashion the specific UI decides is relevant. For instance, in OSF/Motif, mnemonic characters are underlined.
Usually the first letter of the text moniker is used for the mnemonic, though any character may be used. The specific UI will underline the first such occurrence of the character within the text moniker. If the character is not within the text itself, the specific UI may place the character within parentheses at the end of the text moniker. Mnemonics are activated according to specifications in the specific UI. In OSF/Motif, pressing the ALT key puts the user interface into its keyboard navigation mode. In this mode, all mnemonics for objects in the focus are activated by pressing the character of the mnemonic without need of an additional keystroke.
Mnemonics are set by enclosing the desired character in single quotes before the text string in your instance data. Mnemonics are case specific when defined. For example, if a visual moniker is the text "File," only an uppercase mnemonic of F would highlight the first character in the text. Mnemonics are not case specific in their activation methods, however. For example, either alt -f or alt -F will activate a keyboard mnemonic of F.
Mnemonics are only valid for an object if that object is visually displayed and currently has the focus (see the Input chapter). Therefore, you may duplicate mnemonics for objects that will not exist at the same focus level. (An example of objects at the same focus level would be objects within the same menu.) Be careful not to duplicate the same mnemonic within the same focus level, as the UI will only associate the mnemonic with the first object that matches it.
The mnemonic may also store one of the following constants:
If you need other functionality that requires keyboard control of some form and mnemonics are not satisfactory, see Keyboard Accelerators .
Code Display 2-6 Setting Mnemonic Characters
/* Mnemonics are case specific. If the following example enclosed f instead of * F within single quotes, then the character f in parentheses would follow the * text "File." Note that this case specificity does not apply to the user's * activation of the object. That is, alt f will activate a mnemonic of F. */
@object MyTrigger GenTriggerClass { GI_visMoniker = `F', "File"; }
/* You can also specify the character to highlight with an actual numerical * position, counting from a zero-based (1st character is 0, 2nd character is 1, * etc.) character position in the text string. The "5" in the following example * will underline the F character (the sixth character in the text string.) */
GI_visMoniker = 5, "Open File";
The GI_
visMoniker
instance field recognizes several keywords. These keywords are listed below and are usually only used in the construction of gstring visual monikers.
VMStyle
in use by this visual moniker.
DisplaySize
that this moniker is intended for. It has nothing to do with the actual size of the moniker, which can be set with the keyword `cachedSize.' Each size corresponds to a display type's resolution level.
DisplayClass
.
Bitmap
operator.Code Display 2-7 Examples of GString Visual Monikers
/* A Graphics string consisting of GString opcodes. */ GI_visMoniker = { size = tiny; color = color4; aspectRatio = normal; cachedSize = 15,15; gstring{ GSSaveTransform(), GSApplyRotation(45), GSFillEllipse(0,0,10,15), GSRestoreTransform(), GSDrawEllipse(0,0,10,15), GSEndString() } }
/* A Graphics string containing a bitmap. */ @visMoniker MyBitmap = { style = icon; size = standard; color = color4; aspectRatio = normal; cachedSize = 64, 40; gstring { GSDrawBitmapAtCP(166), Bitmap (64,40,BMC_PACKBITS, (BMT_MASK|BMF_4BIT)), 251, 0, 233, 221, ..., GSEndString() } }
In some cases, an application may wish to use different visual monikers under specific circumstances. For example, a GenApplication's icon may need separate graphics strings for different display types (VGA, SVGA, etc.) In such cases, the argument for the moniker instance field should be given as a list of separate and distinct visual monikers. (See Simple Lists .)
You may then place each of these monikers within its own separate resource. Because only one moniker will be selected from the list, only one resource will be loaded into the object block, thereby conserving memory. When the application selects its appropriate moniker, the list will be replaced with the specific moniker, copied into the object block. The system performs this function automatically.
/* A list of monikers. */ GI_visMoniker = list { @moniker1, @moniker2, @moniker3 }
/* If several monikers are specified in a list, they must be explicitly defined * somewhere else. If these monikers are complicated (as in the case of graphics * strings) they should each reside within their own resource because they will be * loaded in only once per application run. (Those that will be used together can * be within the same resource.) For example, in GEOS, several monikers * pertaining to different display types would be placed within separate resources. * When the appropriate moniker is selected, the list will be replaced with the * specific moniker. */
@start AppMonikerOneResource, notDetachable;
@visMoniker moniker1 = { size = large; color = color4; aspectRatio = normal; cachedSize = 64, 40; gstring {gstring data} }
@end AppMonikerOneResource;
/* That moniker could then be declared within the object's instance data. */ @object GenPrimaryClass MyObject = { GI_visMoniker = list { @moniker1 } }
/* * The GenApplication object usually contains a moniker list that allows the * specific UI to select a moniker based on the display. */ @object GenApplicationClass MyApplication = { GI_visMoniker = list { @TrigTextMoniker, /* a simple text string */ @TrigLCMoniker, /* Large Color */ @TrigLMMoniker, /* Large Mono */ @TrigSCMoniker, /* Small Color */ @TrigSMMoniker, /* Small Mono */ @TrigLCGAMoniker, /* Large CGA */ @TrigSCGAMoniker /* Small CGA */ } }
@visMoniker TrigTextMoniker = "Push Me";
/* Graphics monikers might then appear within their own resource block. This * enables efficient memory management. */
@start AppMonikerResource, notDetachable;
@visMoniker TrigLCMoniker = { style = icon; size = large; color = color4; aspectRatio = normal; cachedSize = 64, 40; gstring { GSDrawBitmapAtCP(166), Bitmap (64,40,BMC_PACKBITS, (BMT_MASK|BMF_4BIT)), /*** insert Bitmap here ***/ GSEndString() } }
@end AppMonikerResource
The following section explains the inner workings of visual monikers within GEOS. It is not necessary to understand many of these concepts but it is illustrative of the system, and may aid in debugging and custom moniker use.
GI_visMoniker
can take several types and combinations of arguments, all involving either text or graphics strings. Specifically,
GI_visMoniker
may indicate the following:
Each of these arguments can be set up with the
@visMoniker
Goc keyword, but each will store their data in different manners. GEOS automatically sets up the visual moniker in the correct format.
All visual monikers make use of the
VisMoniker
structure. This basic structure indicates whether the moniker is text, a gstring, or a list of several types.
Code Display 2-9 The Basic VisMoniker Structure
/* The Basic VisMoniker structure contains a header which describes the type of * VisMoniker (VisMonikerType) and stores the cached width (width in pixels) of the * VisMoniker. The actual visual moniker data (either text or a gstring) follows * this header. * * If the visual moniker is text, this VisMoniker structure is contained within a * VisMonikerWithText structure. If the visual moniker is a gstring, this * VisMoniker structure is contained within a VisMonikerWithGString structure.*/
typedef struct { byte VM_type; /* VisMonikerType */ word VM_width; /* Cached width of moniker */ } VisMoniker;
/* VisMonikerType specifies the type of moniker contained in the VisMoniker * structure. * * The flag VMT_MONIKER_LIST is actually a dummy flag. (This flag is never set * within a VisMoniker structure.) VisMonikerListEntryType has a matching flag * in the same location (VMLET_MONIKER_LIST). If that flag is set, it tells the * system that this isn't actually a VisMoniker structure but is instead a * VisMonikerListEntry. This is used in moniker lists (see below). * * The flag VMT_GSTRING is set if the visual moniker is in the form of a gstring * instead of a simple text string. If this flag is set, VMT_GS_ASPECT_RATIO and * VMT_GS_COLOR specify the DisplayAspectRatio and DisplayClass used by this * gstring. */
typedef ByteFlags VisMonikerType; #define VMT_MONIKER_LIST 0x80 #define VMT_GSTRING 0x40 #define VMT_GS_ASPECT_RATIO 0x30 /* DisplayAspectRatio */ #define VMT_GS_COLOR 0x0f /* Color */
#define VMT_GS_ASPECT_RATIO_OFFSET 4 #define VMT_GS_COLOR_OFFSET 0
If the visual moniker is a simple text string, the ChunkHandle within GI_
visMoniker
will point to a chunk containing a
VisMonikerWithText
structure. This chunk will contain the basic
VisMoniker
header, along with the moniker's mnemonic character and a null-terminated text-string.
Code Display 2-10 VisMonikers With Text
/* If the VisMoniker contains simple text, the ChunkHandle within GI_visMoniker * points to a VisMonikerWithText structure. This structure contains the * basic VisMoniker header and the character of the mnemonic. (A value of -1 is * stored in VMWT_mnemonicOffset if there is no mnemonic for this visual moniker.) */
typedef struct { VisMoniker VMWT_common; char VMWT_mnemonicOffset; } VisMonikerWithText;
/* The text, in the form of a null-terminated text string, follows this structure. * This text may be accessed with the VMWT_text offset. */
#define VMWT_text (sizeof(VisMonikerWithText)) /* Start of text. */
If the visual moniker is a gstring, the ChunkHandle within GI_
visMoniker
will point to a
VisMonikerWithGString
structure instead. This structure will contain the basic
VisMoniker
header, along with the moniker's cached height and the actual gstring. (The cached width is stored within the
VisMoniker
header.)
Code Display 2-11 VisMonikers With GStrings
/* If the VisMoniker contains a gstring, the ChunkHandle within GI_visMoniker * points to a VisMonikerWithGString structure. This structure contains the * basic VisMoniker header and the cached height of the gstring. (The cached width * is stored within the VisMoniker structure. */
typedef struct { VisMoniker VMWGS_common; word VMWGS_height; } VisMonikerWithGSTring;
/* The gstring follows this structure.This gstring may be accessed (though it is * not recommended) with the VMWGS_gString offset. */
#define VMWGS_gString (sizeof(VisMonikerWithGString)) /* Start of gstring. */
If instead of a single visual moniker, be it a text string or a gstring, GI_
visMoniker
specifies a list of monikers, the case is more complex.
If GI_
visMoniker
contains a list of monikers, that ChunkHandle will point to a group of
VisMonikerListEntry
structures (one for each moniker in the list). Each of these list entries will contain the type of moniker it references and the optr of the moniker it refers to. The actual moniker itself is not stored in that chunk. Also, because the moniker may be referred to by an optr, the actual visual monikers may reside in separate resources.
When the object containing the moniker list is first built, the system will select one of the monikers in the list (based on matching criteria in the VMLE_
type
field) and replace the moniker list with the single selected visual moniker.
Code Display 2-12 VisMoniker Lists
/* If GI_visMoniker contains a list of monikers instead of a single moniker, the * ChunkHandle of that instance field actually points to a collection of * VisMonikerListEntry structures. (The total number can be calculated by dividing * the size of the chunk by sizeof(VisMonikerListEntry) if needed.) * * Each VisMonikerListEntry structure contains a header which describes the type of * VisMoniker stored in that list entry (VisMonikerListEntryType) and the optr of * the stored moniker. The actual moniker may reside in a different resource. */
typedef struct { word VMLE_type; optr VMLE_moniker; } VisMonikerListEntry;
/* VisMonikerListEntryType specifies the type of moniker specified in the * VisMonikerListEntry structure. * * The flag VMLET_MONIKER_LIST must be set within this structure. This flag tells * the system that this isn't actually a VisMoniker structure but is instead a * VisMonikerListEntry. * * The system uses the other flags in this structure to determine the type of * moniker contained as the list entry. The system will use this information to * select the most appropriate moniker that will satisfy the system's needs. This * method is used most often in the selection of a GenPrimary's main application * moniker based on the DisplaySize of the system. * * VMLET_GS_SIZE stores the DisplaySize that this moniker is most appropriate for. * This DisplaySize is set using the "size" entry within the visual moniker * declaration. * * VMLET_STYLE stores the VMStyle that this moniker most closely matches. This * VMStyle is set using the "style" entry within the visual moniker declaration. * * VMLET_GSTRING specifies that this moniker list entry is in the form of a gstring * If this flag is set, VMLET_GS_ASPECT_RATIO and VMLET_GS_COLOR specify the * DisplayAspectRatio and DisplayClass used by this gstring. */
typedef ByteFlags VisMonikerListEntryType; #define VMLET_GS_SIZE 0x0300 /* DisplaySize. */ #define VMLET_STYLE 0x0f00 /* VMStyle */ #define VMLET_MONIKER_LIST 0x0080 #define VMLET_GSTRING 0x0040 #define VMLET_GS_ASPECT_RATIO 0x0030 /* DisplayAspectRatio */ #define VMLET_GS_COLOR 0x000f /* DisplayClass */
#define VMLET_GS_SIZE_OFFSET 12 #define VMLET_STYLE_OFFSET 8 #define VMLET_GS_ASPECT_RATIO_OFFSET 4 #define VMLET_GS_COLOR_OFFSET 0
/* VMStyle specifies the style of the visual moniker. The system may select a * moniker based on the style it wishes to display. */
typedef ByteEnum VMStyle; #define VMS_TEXT 0 /* Simple text */ #define VMS_ABBREV_TEXT 1 /* Abbreviated text */ #define VMS_GRAPHIC_TEXT 2 /* Textual graphics string */ #define VMS_ICON 3 /* Normal gstring */ #define VMS_TOOL 4 /* Tool-sized gstring */
For information on manipulating visual monikers dynamically using
GenClass
messages, see Managing Visual Monikers
.
Composite links form the connections between parent objects and child objects within a generic tree (see the UI Overview). These links are set up using the GI_comp
and
GI_link
instance fields. The
GI_comp
field points to an object's first child. The
GI_link
field points to an object's next sibling or to its parent if no next sibling exists. In Goc, however, this usage is greatly simplified. The developer only needs to set the
GI_comp
field equal to its complete list of children for the parent object. The Goc preprocessor will then create and reassign all necessary links.
Code Display 2-13 Using GI_comp to Add Children
/* The GenInteraction (MyInteraction) acts as the parent object for the three * child GenTriggers. All three GenTrigger children will be placed within the * GenInteraction object. */
@object GenInteractionClass MyInteraction = { GI_visMoniker = "Menu"; /* Text Moniker */ GII_visibility = GIV_POPUP; /* Creates a Menu */ GI_comp = @MyFirstChild, @MySecondChild, @MyThirdChild; /* list of children */ }
@object GenTriggerClass MyFirstChild= { GI_visMoniker = "Child 1"; /* Text Moniker */ }
@object GenTriggerClass MySecondChild = { GI_visMoniker = "Child 2"; /* Text Moniker */ }
@object GenTriggerClass MyThirdChild = { GI_visMoniker = "Child 3"; /* Text Moniker */ }
This simple functionality is all you need to know to add children to your generic objects (and thus to create generic trees). However, it is somewhat helpful in certain cases (as in debugging) to understand what takes place underneath the surface. When an object in GEOS is assigned children, the preprocessor actually only assigns one composite link (
GI_comp
) to the first child. Each additional child acquires a link from its previous sibling using the internal instance field
GI_link
. Therefore, the parent will have a
GI_comp
to its first child, the first child will have a
GI_link
to the next sibling (the parent's second child) and so forth. The last sibling (the parent's last child) will have a
GI_link
back to the parent. This
GI_link
will have the LF_IS_PARENT bit set to indicate that the child points to a parent and not to a sibling. This forms what amounts to a circular linked list rather than a branching tree structure. (See the figure below.)
This structure provides a simple and convenient usage. Any object will always have at most two links to other children or parent objects. Therefore the two instance fields
GI_comp
and
GI_link
provide the entire means of constructing a generic tree.
You can travel anywhere in the generic tree through these two links. For example, for MyInteraction to communicate with MyThirdChild, it follows the path of the
GI_comp
to the first child, MyFirstChild, and then continues through the two
GI_link
s to the third child. Conversely, a child can reach a parent by travelling along the
GI_link
s of siblings until it reaches the last sibling, whose
GI_link
points to its parent object.
GenClass
message handlers provide several means of pointing to the proper parent/child object without needing to explicitly state the proper
GI_comp
and
GI_link
paths. In practice, you will never need to, and in fact should not, manipulate the
GI_link
field at all. This information is provided merely for your use in debugging your applications. In fact, you can usually assume that a conventional branching tree structure exists rather than the linked-list tree structure shown here.
For information on manipulating these links dynamically using
GenClass
messages, see Generic Trees
.
Keyboard accelerators permit the user to activate objects without the use of default activations in the specific UI. (Much of the default activations in most graphical user interfaces use the mouse, for example.) In most cases, these keyboard accelerators require the use of a modifier (the alt , shift or ctrl key) and another key. The keyboard accelerator may also be a function key (F10, etc.). In general, you should avoid using the alt key because of its special role as a keyboard mnemonic within a visual moniker (see Visual Monikers ).
Keyboard accelerators may be activated at any time; they are valid at any point within the application whether the generic object involved is being displayed currently or not. (The only exception to this is during the display of a modal dialog box, which will block input to any other part of the application.) The system will search through the generic tree for the object containing the proper key sequence. In this manner, accelerators differ from mnemonics, which are only valid for an active level. Therefore, only use keyboard accelerators for heavily utilized commands; this prevents a glut of modified keystrokes, which may confuse the user. In general, it is good practice to use the "control" key exclusively for keyboard accelerators to prevent overlapping with GEOS keyboard acclelators and mnemonics.
You can set up keyboard accelerators using the
GI_kbdAccelerator
attribute. A keyboard accelerator must contain a valid modifier such as
alt
,
shift
,
control
, or
ctrl
. You may use any alpha-numeric character as the action key for the modifier to act on. In addition to alpha-numeric characters, the action keys shown above are also available.
The specific UI has final control over how and whether a keyboard accelerator will be implemented. Currently, keyboard accelerators will only work for
GenTriggers and GenItems. In most cases, a keyboard accelerator will be displayed alongside the text for the visual moniker of an object. In OSF/Motif, keyboard accelerators are shown to the right of menu items and to the left of other items). You may add
HINT_DRAW_SHORTCUT_BELOW
on non-menu items to draw the keyboard accelerator below the object's visual moniker.
Code Display 2-14 Using a Keyboard Accelerator
@object GenTriggerClass MyTrigger = { /* Case is ignored for keyboard accelerators. */ GI_kbdAccelerator = ctrl `R'; /* `ctrl' and `control' are both valid. */ }
/ * Other examples: GI_kbdAccelerator = control `A';
Case is ignored for keyboard accelerators (unlike mnemonics). If you need an uppercase `A', use `shift' as a modifier.
GI_kbdAccelerator = control shift `A'; GI_kbdAccelerator = alt `z'; GI_kbdAccelerator = alt shift `Z'; GI_kbdAccelerator = ctrl shift `G';
If you know what specific keyboard set will be implemented, you can add such special characters with the @specificUI keyword, though this is discouraged.
GI_kbdAccelerator = @specificUI alt shift DELETE; GI_kbdAccelerator = @specificUI F6; */
For information on manipulating keyboard accelerators dynamically, see Managing Keyboard Accelerators .
GI_attrs, MSG_GEN_GET_ATTRIBUTES, MSG_GEN_SET_ATTRS
The
GI_attrs
attribute is a record specifying how an object will behave under various circumstances. In some cases, the
GI_attrs
instance field indicates that an object may initiate a busy state within the application. Several attributes only affect how an object will behave during activation. Prior to an object's activation, some of these attributes will not affect the object's behavior.
MSG_GEN_GUP_INTERACTION_COMMAND
to its generic parent with the
InteractionCommand
IC_INTERACTION_COMPLETE. This message is then passed up the generic tree until it reaches an appropriate Interaction. See the Menus and Dialog Boxes chapter for more information.
GA_INITIATES_BUSY_STATE
This flag instructs the UI to mark the application as busy whenever the generic object is activated. You should only set this attribute for objects that may initiate long operations. This attribute requests that the UI visually change the cursor to show that the application is busy. (In OSF/Motif this is represented by an hourglass.) When the application finishes its operation, the cursor will revert to its former state. This attribute causes the object to send
MSG_GEN_APPLICATION_MARK_BUSY
to the object's application object along with
MSG_GEN_APPLICATION_MARK_NOT_BUSY
sent via the process' event queue. This allows the system to process the first message (showing the busy cursor) and only process the second message (removing the busy cursor) after the application finishes its current operation. (If the action is processed quickly, the cursor will often not appear.) The busy state cursor is only reflected in the current application; if the cursor roams outside the application bounds, the default behavior will occur.
MSG_GEN_APPLICATION_HOLD_UP_INPUT
to the application object along with a
MSG_GEN_APPLICATION_RESUME_INPUT
delayed via the process' event queue. This functionality is only reflected in the current application; if the cursor roams outside the application bounds, the default behavior will occur.
MSG_GEN_APPLICATION_IGNORE_INPUT
to the application object along with a
MSG_GEN_APPLICATION_ACCEPT_INPUT
delayed via the application queue. This functionality is only reflected in the current application; if the cursor roams outside the application bounds, the default behavior will occur.
MSG_GEN_APPLICATION_VISIBILITY_NOTIFICATION
Code Display 2-15 Using GI_attrs in a Dialog Box
@object GenInteractionClass MyDialogBox = { GI_comp = @MyButton, @MyOtherButton; GII_visibility = GIV_DIALOG; /* build this Interaction as a dialog box.*/ }
@object GenTriggerClass MyButton = { GTI_actionMsg = MSG_MY_SPECIAL_MESSAGE; GTI_destination = process; /* MyButton, when activated, will send the message above to the * process object. Only when that happens will it activate the * behavior within the GI_attrs instance data below. */ GI_attrs = @default | /* This flag will close the MyDialogBox object */ GA_SIGNAL_INTERACTION_COMPLETE | /* This flag will set the application to ignore all input events while the * message above is processed. */ GA_INITIATES_INPUT_IGNORE; }
byte MSG_GEN_GET_ATTRIBUTES();
This message retrieves the
GI_attrs
instance data for the object the message is sent to. This message returns a byte length bitfield.
Source: Unrestricted.
Destination: Any generic object.
Return: Byte length GI_
attrs
bitfield.
Interception: Generally not intercepted.
void MSG_GEN_SET_ATTRS( byte attrsToSet, byte attrsToClear);
This message sets the recipient's
GI_attrs
field. This message takes two arguments: the attributes to set and the attributes to clear. There is no need to repeat attributes that have been previously set. Note that these attributes will not take effect until the object is activated in the normal manner. (Sending this message does not in itself initiate the activity described).
You should only send this message while an object is not GS_USABLE, because these attributes are only checked when an object is specifically built. Setting the attributes of a GS_USABLE object may cause an error.
Source: Unrestricted.
Destination: Any non-usable generic object.
Parameters:
attrsToSet
GenAttributes
to set in GI_
attrs
.
GenAttributes
to clear in GI_
attrs
.
Interception: Generally not intercepted.
Code Display 2-16 Conditionally Altering the GI_attrs Field
@method MyProcessClass, MSG_DO_CUSTOM_ATTRS { byte MyAttrs;
/* retrieve the GI_attrs field */ MyAttrs = @call @MyObject::MSG_GEN_GET_ATTRIBUTES();
/* If the GA_COMPLETES_INTERACTION bit is set, then set it * GA_INITIATES_BUSY_STATE also. Otherwise set it * GA_INITIATES_INPUT_IGNORE. */
if (MyAttrs & GA_COMPLETES_INTERACTION){ @call @MyObject::MSG_GEN_SET_NOT_USABLE(); @call @MyObject::MSG_GEN_SET_ATTRS(GA_INITIATES_BUSY_STATE, 0);
/* Note that setting an object's GA_INITIATES_BUSY_STATE attribute will * not in itself initiate a busy state. That object will only issue a busy * state when it is activated in the normal fashion. */
@call @MyObject::MSG_GEN_SET_USABLE(); } else { @call @MyObject::MSG_GEN_SET_NOT_USABLE(); @call @MyObject::MSG_GEN_SET_ATTRS(GA_INITITATES_INPUT_IGNORE, 0); @call @MyObject::MSG_GEN_SET_USABLE(); } }
GI_states
The
GI_states
attribute is a record that holds the state of the generic object. These states affect the object's visual representation and its functionality. By default, all objects have both GS_USABLE and GS_ENABLED set when first built. There are two
GI_states
:
These states not only affect the state of the current object but all of its descendants as well. When your user interface is first built (or rebuilt) it conducts a top-down search, building any objects that are declared GS_USABLE. If an object is not GS_USABLE, it will not be visually built. Furthermore, none of its descendants will be searched (or built). Therefore, if any single node is not GS_USABLE, no other object below that node will be fully usable.
In cases where you wish to alter any fundamental behavior of an object, you may have to set the object not usable, change its behavior, and then set the object GS_USABLE again. This ensures that the object is built out correctly (including visually) according to the new criteria.
Code Display 2-17 Setting GI_states
@object GenTriggerClass MyTrigger = { /* The default GI_states are GS_USABLE and GS_ENABLED. * This object will only be GS_USABLE */ GI_states = @default & ~GS_ENABLED; }
MSG_GEN_GET_USABLE, MSG_GEN_SET_USABLE, MSG_GEN_SET_NOT_USABLE, MSG_GEN_CHECK_IF_FULLY_USABLE
Setting an object GS_USABLE will incorporate the object into the generic tree and regard the object as part of the user interface. (It will not by itself enable an object for user input; this requires an object to be set GS_ENABLED also.) If an object is not GS_USABLE, it cannot be used in any manner including any visual implementation by the user interface. The following messages manipulate an object's usable state.
Boolean MSG_GEN_GET_USABLE();
This message checks the GS_USABLE bit of the
GI_states
field.
Source: Unrestricted.
Destination: Any generic object.
Parameters: None.
Return: Will return
true
if the object is GS_USABLE,
false
if it is not usable.
Interception: Generally not intercepted.
void MSG_GEN_SET_USABLE( VisUpdateMode updateMode);
This message sets an object GS_USABLE. (This message has no effect on an object already GS_USABLE.) Objects may be set GS_USABLE only after they have been attached to a generic tree. Setting an object usable forces that object to be specifically built. If the object's associated window is realized, the object will be visually built and updated. Setting an object GS_USABLE that is not attached to the generic tree
will cause an error.
Setting an object usable allows that object to become part of the user interface. Before the object can be used, though, it must be
fully
usable
. An object becomes fully usable only if all of its ancestors are GS_USABLE. If any ancestor is not GS_USABLE, then the entire branch below it will not be fully usable. You can check if an object is fully usable with the message
MSG_GEN_CHECK_IF_FULLY_USABLE
.
Conversely, setting a node GS_USABLE, in which every branch object below it is already GS_USABLE will make that entire branch fully usable. This is useful for bringing up an entire section of a generic tree by setting a single object usable.
Source: Unrestricted.
Destination: Any generic object.
Parameters:
updateMode
VisUpdateMode
to use when updating changes to the screen.
Return: Nothing.
Interception: Generally not intercepted.
void MSG_GEN_SET_NOT_USABLE( VisUpdateMode updateMode);
This message sets an object not usable (clears the GS_USABLE bit). Because an object may be visually unbuilt by this message, the
VisUpdateMode
VUM_MANUAL is not allowed.
Source: Unrestricted.
Destination: Any generic object.
Parameters:
updateMode
VisUpdateMode
to use when updating changes to the screen. May not be VUM_MANUAL.
Return: Nothing.
Interception: Generally not intercepted.
Boolean MSG_GEN_CHECK_IF_FULLY_USABLE();
This message checks whether an object is fully usable. The object and all of its parents must be GS_USABLE for the object to be fully usable.
Source: Unrestricted.
Destination: Any generic object.
Return: Will return
true
if the object is fully usable,
false
if it is not.
Interception: Generally not intercepted.
MSG_GEN_GET_ENABLED, MSG_GEN_SET_ENABLED, MSG_GEN_SET_NOT_ENABLED, MSG_GEN_CHECK_IF_FULLY_ENABLED
An object that is GS_ENABLED is ready for user interaction. As in the case with GS_USABLE, all parents of the object in question must be GS_ENABLED to
fully
enable
the object. An object may be fully enabled without being fully usable, but the object will not be visually represented. You can check if an object is fully enabled with
MSG_GEN_CHECK_IF_FULLY_ENABLED
.
An object that is not enabled but is set usable will be represented in the user interface; it will not, however, allow the user to interact with it. In many cases, the specific UI implements this by "graying out" the object. Setting a disabled object will visually update it.
Boolean MSG_GEN_GET_ENABLED();
This message returns the enabled state of the object the message is sent to.
Source: Unrestricted.
Destination: Any generic object.
Return: Will return
true
if the object is enabled,
false
if it is not.
Interception: Generally not intercepted.
void MSG_GEN_SET_ENABLED( VisUpdateMode updateMode);
This message sets an object GS_ENABLED. (This message has no effect on an object already GS_ENABLED.) You must pass this message a
VisUpdateMode
. Sending this message allows the object to receive user input. Only send this message if your application will be ready to interact with the object after the period specified in the
VisUpdateMode
has passed.
Source: Unrestricted.
Destination: Any generic object.
Parameters:
updateMode
VisUpdateMode
to use when updating changes to the screen.
Interception: Generally not intercepted.
void MSG_GEN_SET_NOT_ENABLED( VisUpdateMode updateMode);
This message sets the object not enabled (clears the object's GS_ENABLED bit.) You must pass the message a
VisUpdateMode
. In most specific UIs a disabled state is implemented by "graying out" the object. The user will be unable to interact with the object according to the
VisUpdateMode
passed.
Source: Unrestricted.
Destination: Any generic object.
Parameters:
updateMode
VisUpdateMode
to use when updating changes to the screen. May not be VUM_MANUAL.
Interception: Generally not intercepted.
Boolean MSG_GEN_CHECK_IF_FULLY_ENABLED();
This message checks whether an object is fully enabled. An object is only fully enabled (ready for user interaction) when both it and all of its ancestors are enabled.
Source: Unrestricted.
Destination: Any generic object.
Return: Will return
true
if fully enabled,
false
if not.
Interception: Generally not intercepted.
Instance data need not be set solely within your
.goc
file. You may also retrieve or alter this data dynamically with messages in
GenClass
. The following section details messages to modify the
GI_visMoniker
,
GI_kbdAccelerator
,
GI_attrs
and
GI_states
instance fields. This section also details ways of using the variable data object routines and messages to modify a generic object's vardata.
Remember that when accessing and modifying instance data, you may need to dereference the pointer to the object's instance data if the location of that instance data may have changed. This pointer (
pself
) is automatically set up correctly inside a method upon receipt of the corresponding message. If you perform actions within that method that may move the object, you can use
ObjDerefGen
() to dereference
pself
again.
If the instance fields you wish to modify are related to generic tree mechanisms (
GI_comp
and
GI_link
), see Special Message Passing
.
Managing Keyboard Accelerators
A visual moniker must reside in a local memory (LMem) chunk. That chunk should be located within the object block of the particular generic object it is associated with. Once monikers are defined, there are several messages in
GenClass
that you can use to change the visual moniker for an object.
The
GI_visMoniker
field contains a ChunkHandle of the
VisMoniker
structure. The
VisMoniker
structure contains three pieces of data: the type of moniker, the width of the moniker chunk, and the moniker data.
MSG_GEN_GET_VIS_MONIKER, MSG_GEN_USE_VIS_MONIKER, MSG_GEN_CREATE_VIS_MONIKER, MSG_GEN_REPLACE_VIS_MONIKER, MSG_GEN_REPLACE_VIS_MONIKER_OPTR, MSG_GEN_REPLACE_VIS_MONIKER_TEXT, MSG_GEN_FIND_MONIKER, MSG_GEN_DRAW_MONIKER, MSG_GEN_GET_MONIKER_POS, MSG_GEN_GET_MONIKER_SIZE, MSG_GEN_RELOC_MONIKER_LIST, MSG_GEN_FIND_OBJECT_WITH_TEXT_MONIKER
Sending
MSG_GEN_GET_VIS_MONIKER
to an object returns the chunk handle of the visual moniker (
GI_visMoniker
) for that object. You can then inspect that visual moniker or use it within other objects (though this is not recommended). You must be careful when sharing monikers with other objects, as freeing one object (and therefore its associated moniker) will interfere with any other objects referencing that moniker.
Sending
MSG_GEN_USE_VIS_MONIKER
to an object sets a visual moniker for that object to use. The message must pass the chunk handle of the moniker desired for the object along with a
VisUpdateMode
. Valid
VisUpdateMode
s are described in the VisClass chapter. The moniker to use must reside in the same block as the object being set. If you need to set an object to use a new moniker from a location outside of its object block, use
MSG_GEN_REPLACE_VIS_MONIKER
to copy the moniker to the new location.
MSG_GEN_REPLACE_VIS_MONIKER
copies a visual moniker from a source location into a destination. This message must pass parameters specifying the type of copy operation. The source for the moniker can be referenced using an optr or a simple text string. Use this message when you wish to copy a moniker from outside of the object's current object block.
MSG_GEN_REPLACE_VIS_MONIKER_OPTR
and
MSG_GEN_REPLACE_VIS_MONIKER_TEXT
are simplified versions of the above message, allowing you to set a visual moniker from an optr or from a pointer to a null-terminated text string without having to pass many other arguments.
MSG_GEN_CREATE_VIS_MONIKER
creates a visual moniker (within the resource block of the object this message is sent to), copying it from a source; it does not, however, attach this moniker to any object.
MSG_GEN_FIND_MONIKER
searches for a specific type of moniker within a moniker list. You may then use the moniker directly. You can also replace the original moniker list with the specified moniker.
MSG_GEN_DRAW_MONIKER, MSG_GEN_GET_MONIKER_POS
, and
MSG_GEN_GET_MONIKER_SIZE
all manipulate a currently existing moniker. These messages are most useful for custom gadgets.
MSG_GEN_DRAW_MONIKER
draws the moniker according to the criteria passed with the message.
MSG_GEN_GET_MONIKER_POS
and
MSG_GEN_GET_MONIKER_SIZE
return
GEOS
coordinates specifying the location and size of the moniker, respectively. You may then inspect and alter these coordinates before sending the moniker a
MSG_GEN_DRAW_MONIKER
to redraw the moniker according to the changed criteria.
The utility message
MSG_GEN_RELOC_MONIKER_LIST
relocates an object's moniker list.
To find an object with a particular visual moniker, send MSG_GEN_FIND_OBJECT_WITH_MONIKER_FLAGS to the object at which to start the top-down search, passing the text to perform the match.
ChunkHandle MSG_GEN_GET_VIS_MONIKER();
This message retrieves the instance data in the object's current
GI_visMoniker
instance field. This message returns the ChunkHandle of the moniker data structure. You can then use that chunk handle to manipulate the visual moniker directly or to copy the moniker for use by other objects.
Source: Unrestricted.
Destination: Any generic object.
Return: The chunk handle of the visual moniker in use by this object.
Interception: Generally not intercepted.
void MSG_GEN_USE_VIS_MONIKER( ChunkHandle moniker, VisUpdateMode updateMode);
This message allows an object to reference a visual moniker; this message does not destroy the chunk of the object's current visual moniker. The moniker must reside in the same block as the object. Use
MSG_GEN_REPLACE_VIS_MONIKER
if you wish to set a moniker from a source outside the object block or if you wish to use a new moniker, overwriting the old one.
You cannot pass a moniker list's chunk handle using this message. See
MSG_GEN_FIND_MONIKER
for information on selecting monikers from within a list.
Source: Unrestricted.
Destination: Any generic object.
Parameters: moniker The chunk handle of the visual moniker to use
VisUpdateMode
to determine when the moniker will be redrawn.Return: Nothing.
Interception: Generally not intercepted.
Code Display 2-18 Getting and Using Visual Monikers
/* This method effectively copies a visual moniker from ObjectOne into ObjectTwo. * Both objects must reside in the same object block. Note that in effect, both * ObjectOne and ObjectTwo will "share" the same moniker. This can be dangerous if * one object is freed, thereby causing the other object to become dereferenced. * For more complex copy operations, use MSG_GEN_REPLACE_VIS_MONIKER instead. */
@method MyProcessClass, MSG_MY_MONIKER_MESSAGE { /* Set up variable to store the chunk handle of the visual moniker. */ ChunkHandle MyVisMonikerCH;
/* Retrieve the visMoniker of ObjectOne and store it in the variable. */
MyVisMonikerCH = @call @ObjectOne::MSG_GEN_GET_VIS_MONIKER();
/* Set the visMoniker of Object Two to MyVisMonikerCH and update * immediately. Use @send if you don't expect a return value. */
@send @ObjectTwo::MSG_GEN_USE_VIS_MONIKER(MyVisMonikerCH, VUM_NOW); }
/* You can also declare visual monikers in your .goc file and set them later */
@visMoniker OnMoniker = "On"; @visMoniker OffMoniker = "Off";
/* Within a method, the following routine will set the moniker to "On". The * OptrToChunk operator casts the object from an optr to a ChunkHandle. */
@call @MyObject::MSG_GEN_SET_MONIKER(OptrToChunk(@OnMoniker), VUM_NOW);
/* Within a method, the following routine will set the moniker to "Off" */
@call @MyObject::MSG_GEN_SET_MONIKER(OptrToChunk(@OffMoniker), VUM_NOW);
ChunkHandle MSG_GEN_REPLACE_VIS_MONIKER(@stack VisUpdateMode updateMode, word height, word width, word length, VisMonikerDataType dataType, VisMonikerSourceType sourceType, dword source);
This message copies a visual moniker from a source to the object sent the message. The message returns the chunk handle of the newly copied moniker. The object's current visual moniker is overwritten by this message; therefore, if more than one object shares the overwritten block, the other object should be updated with
MSG_GEN_USE_VIS_MONIKER
. This message can copy a visual moniker from a variety of sources.
This message is a general, all-purpose, moniker replacement device. If your visual moniker source is a
visMoniker
structure or a null-terminated text string, you may be able to use the simpler messages
MSG_GEN_REPLACE_VIS_MONIKER_OPTR
and
MSG_GEN_REPLACE_VIS_MONIKER_TEXT
.
Source: Unrestricted.
Destination: Any generic object.
Parameters:
updateMode
Specifies the
VisUpdateMode
to use when visually updating the changes to the screen. See the VisClass Chapter for more information on
VisUpdateMode
types.
VisMonikerDataType
types include VMDT_VIS_MONIKER, VMDT_TEXT, VMDT_GSTRING, or VMDT_TOKEN.
VisMonikerSourceType
types are VMST_FPTR, VMST_OPTR, and VMST_HPTR.Return: The chunk handle of the new visual moniker for the object.
Interception: Generally not intercepted.
ChunkHandle MSG_GEN_REPLACE_VIS_MONIKER_OPTR( optr source, VisUpdateMode updateMode);
This message is a simplified version of MSG_GEN_REPLACE_VIS_MONIKER. If your visual moniker source is an existing
visMoniker
structure, you can use this message to replace an object's moniker.
Source: Unrestricted.
Destination: Any generic object.
Parameters: source The optr of the visMoniker structure to use in the replacement operation.
VisUpdateMode
to use when visually updating the changes to the screen.Return: The chunk handle of the new visual moniker for the object.
Interception: Generally not intercepted.
ChunkHandle MSG_GEN_REPLACE_VIS_MONIKER_TEXT( const char *source, VisUpdateMode updateMode);
This message is a simplified version of MSG_GEN_REPLACE_VIS_MONIKER. If your visual moniker source is a pointer to a null-terminated text string, you can use this message to replace an object's moniker without having to pass the arguments of
MSG_GEN_REPLACE_VIS_MONIKER
.
Source: Unrestricted.
Destination: Any generic object.
Parameters: source A pointer to a null-terminated character string to use in the replacement operation.
VisUpdateMode
to use when visually updating the changes to the screen.Return: The chunk handle of the new visual moniker for the object.
Interception: Generally not intercepted.
ChunkHandle MSG_GEN_CREATE_VIS_MONIKER(@stack CreateVisMonikerFlags flags, word height, word width, word length, VisMonikerDataType dataType, VisMonikerSourceType sourceType, dword source);
This message creates a visual moniker chunk within the resource block of the object sent this message. The moniker is copied from the source specified but is not attached to any object in the new object block.
Source: Unrestricted
Destination: Any
GenClass
object
Parameters: flags Flags to use in the creation of the new visual moniker. CVMF_DIRTY marks the new moniker chunk OCF_DIRTY .
VisMonikerDataType
types include VMDT_VIS_MONIKER, VMDT_TEXT, VMDT_GSTRING, or VMDT_TOKEN.
VisMonikerSourceType
types are VMST_FPTR, VMST_OPTR, and VMST_HPTR.Return: The chunk handle of the new visual moniker for the object.
Interception: Generally not intercepted.
optr MSG_GEN_FIND_MONIKER( Boolean useAppMonikerList, word searchFlags, /* VisMonikerSearchFlags */ MemHandle destBlock);
This message scans a list of monikers and selects a specific moniker (or the most appropriate moniker). The moniker selected is determined according to the passed
VisMonikerSearchFlags
. This message is usually used by the specific UI to select an application moniker from a list.
If the first argument (
useAppMonikerList
) is not zero, the message will use the GenApplication's moniker list instead of the recipient's. This is useful for finding the icon used for an iconified application.
Note that this message returns an optr, not a chunk handle, as this message is most often used to find a moniker outside of the current object block. This message returns zero if no moniker is found.
Source: Unrestricted.
Destination: Any generic object.
Parameters:
useAppMonikerList
Non-zero to use the moniker list of the application associated with this object.
VisMonikerSearchFlags
to use for the search criteria. If VMSF_COPY_CHUNK is specified in the
searchFlags
, a block handle must be supplied in
destBlock
. The selected moniker will be copied into that block.Return: The optr of the moniker found according to the search criteria. (This may be outside the current object block.)
Interception: Generally not intercepted.
void MSG_GEN_DRAW_MONIKER(@stack DrawMonikerFlags monikerFlags, word textHeight, GStateHandle gState, word yMaximum, word xMaximum, word yInset, word xInset);
This message draws a moniker for an object according to the parameters passed. The moniker must currently exist. You can use this message to change the way you wish a visual moniker to appear within a generic object without actually changing the visual moniker itself.
Source: Unrestricted.
Destination: Any GS_USABLE generic object.
Parameters:
monikerFlags
Specifies the
DrawMonikerFlags
to use when drawing the moniker. The
DrawMonikerFlags
record specifies the conditions to draw the moniker under.
textHeight
gState
yMaximum, xMaximum
DrawMonikerFlags
) to perform a clipping operation on the moniker. Pass zero if no maximum width is desired.
yInset
xInset
Return: Nothing
Interception: Generally not intercepted. Custom gadgets may handle this if they are supplementing or replacing default functionality.
Structures: The
DrawMonikerFlags
record defines the parameters to use when drawing a currently existing visual moniker. This record is used by
MSG_GEN_DRAW_MONIKER
,
MSG_GEN_GET_MONIKER_POS
and
MSG_GEN_GET_MONIKER_SIZE
. Its flags are shown below:
DMF_UNDERLINE_ACCELERATOR DMF_CLIP_TO_MAX_WIDTH DMF_NONE DMF_Y_JUST_MASK /* of type Justifications */ DMF_X_JUST_MASK /* of type Justifications */
Use DMF_UNDERLINE_ACCELERATOR to underline the keyboard accelerator of a text moniker. Use DMF_CLIP_TO_MAX_WIDTH to clip the visual bounds of the moniker to the width specified in
maxWidth
.
Use DMF_NONE to draw the moniker at the current pen position.
The two justification masks are of type
Justification
, and they specify the vertical and horizontal justifications to use when drawing the moniker. The values you can use in the justification fields are
J_LEFT J_RIGHT J_CENTER J_FULL
XYValueASDWord MSG_GEN_GET_MONIKER_POS(@stack DrawMonikerFlags monikerFlags, word textHeight, GStateHandle gState, word yMaximum, word xMaximum, word yInset, word xInset);
This message returns the x and y coordinates of the moniker for the object as if the moniker were drawn according to the passed parameters (the same as for
MSG_GEN_DRAW_MONIKER
). Use the macros DWORD_X and DWORD_Y to extract the appropriate coordinates from the returned value.
This message, along with
MSG_GEN_DRAW_MONIKER
and
MSG_GEN_GET_MONIKER_SIZE
is most useful in the construction and modification of custom gadgets.
Source: Unrestricted.
Destination: Any generic object.
Parameters: See
MSG_GEN_DRAW_MONIKER
.
Return:
XYValueAsDWord
which can be split up into x and y coordinates of the moniker position with the macros DWORD_X and DWORD_Y.
Interception: Generally not intercepted.
SizeAsDWord MSG_GEN_GET_MONIKER_SIZE( word textHeight, GStateHandle gState);
This message returns the width and height (in points) of the moniker for the object. Use the macros DWORD_WIDTH and DWORD_HEIGHT to extract the appropriate coordinates from the returned value. This message, along with
MSG_GEN_DRAW_MONIKER
and
MSG_GEN_GET_MONIKER_POS
, is most useful in the construction and modification of custom gadgets.
Source: Unrestricted.
Destination: Any generic object.
Parameters:
textHeight
The system text height, if known; otherwise, pass zero.
gstate
Return:
SizeAsDWord
which can be split up into with and height with the macros DWORD_WIDTH and DWORD_HEIGHT.
Interception: Generally not intercepted.
void MSG_GEN_RELOC_MONIKER_LIST( optr monikerList, word relocFlag); /* 0: relocate; 1: unrelocate */
This method (un)relocates a passed moniker list.
Source: Anyone.
Destination: Any GenClass object.
Parameters: monikerList optr of moniker list.
Return: Nothing.
Interception: Generally not intercepted.
optr MSG_GEN_FIND_OBJECT_WITH_TEXT_MONIKER( char *text, word flags);
This message recursively searches through the generic tree (starting at the object sent the message) for an object whose visual moniker matches the passed text. This match does not need to be complete (unless the flag GFTMF_EXACT_MATCH is passed); the message will return the first object whose initial characters match the given text. The message must pass
GenFindObjectWithMonikerFlags
.
typedef WordFlags GenFindObjectWithMonikerFlags; #define GFTMF_EXACT_MATCH 0x8000 #define GFTMF_SKIP_THIS_NODE 0x4000
If GFTMF_EXACT_MATCH is passed, the text and the visual moniker text must match exactly (null-terminated). If GFTMF_SKIP_THIS_NODE is passed, the object which sent the message will not be checked; only its children will be checked.
Source: Unrestricted.
Destination: Any generic object.
Parameters: text Null-terminated text.
GenFindObjectWithMonikerFlags
.Return: optr of the object with the matching moniker, or null if no moniker was found.
Interception: Generally not intercepted.
MSG_GEN_GET_KBD_ACCELERATOR, MSG_GEN_SET_KBD_ACCELERATOR, MSG_GEN_CHANGE_ACCELERATOR
Keyboard Accelerators provide keyboard shortcuts for heavily used application functions. For complete information on valid
GI_kbdAccelerator
instance data and the functionality those data provide, see Keyboard Accelerators
.
MSG_GEN_GET_KBD_ACCELERATOR
returns a word of data specifying the current keyboard accelerator, if any, for the object the message is sent to.
MSG_GEN_SET_KBD_ACCELERATOR
sets the keyboard accelerator of the object the message is sent to. The message must pass the keyboard accelerator to use along with a
VisUpdateMode
. If you wish to remove a keyboard accelerator from an object, pass this message with a keyboard acclerator of zero.
MSG_GEN_CHANGE_ACCELERATOR
changes the keyboard accelerator using a low-level replace operation.
word MSG_GEN_GET_KBD_ACCELERATOR();
This message returns the object's current
GI_kbdAccelerator.
The message returns a word-length data structure (
KeyboardShortcut
). You can then manipulate or use this word of data to set other object's keyboard accelerators. Make sure that you do not have two objects sharing the same keyboard accelerator.
Source: Unrestricted.
Destination: Any generic object.
Return:
KeyboardShortcut
of the generic object (in GI_
kbdAccelerator
).
Interception: Generally not intercepted.
void MSG_GEN_SET_KBD_ACCELERATOR( word accelerator, VisUpdateMode updateMode);
This message sets the
GI_kbdAccelerator
of the object the message is sent to.
Source: Unrestricted.
Destination: Any generic object.
Parameters:
accelerator
KeyboardShortcut
to set GI_
kbdAccelerator
of the generic object to.
VisUpdateMode
to determine when redrawing occurs.Interception: Generally not intercepted.
Code Display 2-19 Using a Keyboard Accelerator
@kbdAccelerator ShortcutOne = ctrl shift `k';
/* @specificUI keyword needed to use DELETE key */ @kbdAccelerator ShortcutTwo = @specificUI ctrl DELETE;
@object GenTriggerClass MyTrigger = { GI_kbdAccelerator = ShortcutOne; /* sets accel to "ctrl shift `k'" */ }
@object GenTriggerClass MyOtherTrigger = { GI_kbdAccelerator = ShortcutCopy; /* Copies "ctrl shift `k'" to * MyOtherTrigger */ }
void MSG_GEN_CHANGE_ACCELERATOR( word bitsToClear, word bitsToSet);
This message changes the keyboard accelerator using constants defined in the input library. In most cases, use
MSG_GEN_SET_KBD_ACCELERATOR
instead.
MSG_GEN_CHANGE_ACCELERATOR
is useful in some cases where you wish to tinker slightly with the keyboard shortcut's usage (as in a case where an accelerator of ctrl z should change to alt z in the duplication of a template object).
Source: Unrestricted.
Destination: Any generic object.
Parameters:
bitsToClear
KeyboardShortcut
and/or
VChar
to clear.
KeyboardShortcut
and/or
VChar
to set.Interception: Generally not intercepted.
Generic trees are constructed in several ways. The most common is to add, remove, and move individual children. These children may be the top of a generic branch and will therefore add, remove, or move the entire branch below them.
GenClass
also provides other means of manipulating entire branches of generic trees. Each manner of generic tree construction and destruction has certain advantages and disadvantages. The various methods are detailed below:
.goc
file, attached to the generic tree. In this case, there is no need to add the child as this is taken care of by the compiler. You can remove the object and any of its children with
MSG_GEN_REMOVE
(or
MSG_GEN_REMOVE_CHILD
). After removal, any single object may be destroyed with
MSG_META_OBJ_FREE
. You may also destroy a tree of generic objects with
MSG_GEN_DESTROY
. You may add the removed object (and its children) to a different location in the generic tree with
MSG_GEN_ADD_CHILD
.
.goc
file but remain unattached to the generic tree. You may attach the object with
MSG_GEN_ADD_CHILD
. You can remove the object, and any children of this object, with
MSG_GEN_REMOVE
(or
MSG_GEN_REMOVE_CHILD
). After removal, destroy any single object with
MSG_META_OBJ_FREE
. You can destroy a tree of generic objects with
MSG_GEN_DESTROY
.
ObjInstantiate(), ObjInstantiateForThread()
These routines create a new instance of a single object. You can then add the object to your generic tree with
MSG_GEN_ADD_CHILD
. After a child is removed using
MSG_GEN_REMOVE
(or
MSG_GEN_REMOVE_CHILD
), it can be destroyed using
MSG_META_OBJ_FREE
. The object destroyed in such a manner must not have any children attached to it at the time of destruction.
ObjDuplicateResource()
This routine duplicates an instance of a previously defined object resource. That object block may contain one or more objects. In your
.gp
file, make sure the resource is marked
discard-only
. Only use this routine if you want to duplicate an instance of a predefined resource block. After a block duplicated in this manner is removed using
MSG_GEN_REMOVE
(or
MSG_GEN_REMOVE_CHILD
), it can be destroyed using
ObjFreeDuplicate()
.
MSG_GEN_COPY_TREE
MSG_GEN_ADD_CHILD
. A generic branch created in this manner can be removed with
MSG_GEN_DESTROY
. These messages are useful because they can duplicate and destroy generic trees across object blocks. (The copied branch will reside in one block, however.)
Objects created in these ways must be added using
MSG_GEN_ADD_CHILD
(except for those created with
MSG_GEN_COPY_TREE
).
MSG_GEN_ADD_CHILD
.goc
file but not attached as a child of any other object. The object may also have been created through
ObjInstantiate()
or
ObjInstantiateForThread()
or with
ObjDuplicateResource()
(see above). Use
MSG_GEN_REMOVE
(or
MSG_GEN_REMOVE_CHILD
) to remove a child added in this manner.Manipulating Children Directly
Branch Construction/Destruction
MSG_GEN_FIND_CHILD, MSG_GEN_FIND_CHILD_AT_POSITION, MSG_GEN_FIND_PARENT, MSG_GEN_COUNT_CHILDREN
The following messages provide means of searching the generic tree. It is necessary (in most cases) to check whether a child exists for an object before attempting to delete or access the child. Note that it is bad practice to retrieve optrs using these messages and then some time later send messages manipulating these optrs directly because the tree might change. Instead, use the generic dispatch messages
MSG_GEN_CALL_PARENT
,
MSG_GEN_SEND_TO_CHILDREN
, etc.
word MSG_GEN_FIND_CHILD( optr child);
This message checks whether the object is a child of the recipient. If so, it returns the child's position. If you wish to find out if a specific child currently exists at a certain position, use
MSG_GEN_FIND_CHILD_AT_POSITION
.
Source: Unrestricted.
Destination: Any generic object.
Parameters: child The optr of child to search for.
Return: The numbered position (zero-based) of the child, or -1 if the specific child is not found.
Interception: Generally not intercepted.
optr MSG_GEN_FIND_CHILD_AT_POSITION( word position);
This message returns the optr of the child at
position
, if any. Pass the message the zero-based (zero indicates the first child) position to check. If no child is found, the message returns zero.
Source: Unrestricted.
Destination: Any generic object.
Parameters: position The position (zero-based) of the child to search for.
Return: The optr of child at position passed, if found. Otherwise returns zero.
Interception: Generally not intercepted.
optr MSG_GEN_FIND_PARENT();
This message returns the parent of the recipient object, if any.
Source: Unrestricted.
Destination: Any generic object.
Return: The optr of the parent object. If no parent is found, this message returns zero.
Interception: Generally not intercepted.
word MSG_GEN_COUNT_CHILDREN();
This message returns the number of children of the recipient.
Source: Unrestricted.
Destination: Any generic object.
Return: The number of children the object has.
Interception: Generally not intercepted.
MSG_GEN_ADD_CHILD, MSG_GEN_REMOVE, MSG_GEN_REMOVE_CHILD, MSG_GEN_MOVE_CHILD, MSG_GEN_ADD_CHILD_UPWARD_LINK_ONLY
The following messages create, move, and remove objects set up directly in your
.goc
file or created with
ObjInstantiate()
,
ObjInstantiateForThread()
or
ObjDuplicateResource()
. These objects may have children, in which case those children will travel with their parent (and be moved and destroyed with the parent).
When adding or removing children, you typically have to use a
CompChildFlags
record. This record has two fields, one of which is a dirty flag; the other is a position number indicating a child's position. The record has the following structure:
typedef WordFlags CompChildFlags; #define CCF_MARK_DIRTY 0x8000 /* high bit */ #define CCF_REFERENCE 0x7FFF /* low 15 bits */
#define CCF_REFERENCE_OFFSET 0
/* The CCF_REFERENCE field may have any integral * number or may be set to one of the following * constants: * CCO_FIRST first child's position * CCO_LAST last child's position */
CCO_FIRST and CCO_LAST specify either the first or last child of the parent, respectively. There is no need to use the CCF_REFERENCE_OFFSET in these cases.
void MSG_GEN_ADD_CHILD( optr child, CompChildFlags flags);
This message adds the passed object as a child of the recipient. The child object must not be GS_USABLE before being added to the generic tree. Make sure not to add a child that is already a child of some other parent. It is also illegal to add an object that is already a child of the parent. If necessary, check first if the specific child currently exists using
MSG_GEN_FIND_CHILD
.
In most cases a routine that adds a new child will follow three phases: checking whether the child exists, adding the child, and setting the child GS_USABLE.
The child object, if already specifically initialized, must be unbuilt before being added to the parent. This ensures that the object will be built out correctly. The internal keyboard search path attribute, GA_KBD_SEARCH_PATH, is also cleared and reset for the child.
Pass this message the optr of the child object to add, along with the
CompChildFlags
to use. If CCF_MARK_DIRTY is specified, the new linkage will be saved to state when the application is detached. You must pass a CCF_REFERENCE in
CompChildFlags
to specify the position to add the child. The special constants CCO_FIRST and CCO_LAST, which are special cases of CCF_REFERENCE, will add the object as the first or last child of the parent, respectively.
Note that the object must currently exist.
MSG_GEN_ADD_CHILD
merely sets up the correct linkage and reconfigures your UI. Note also that successive additions of children using the flag CCO_FIRST will result in a "reverse order" of children (the last added will be the first child, the first added will be the last).
Source: Unrestricted.
Destination: Any generic object.
Parameters: child The optr of the object to add to the current object's children. This child must not be usable.
CompChildFlags
to use when adding the child.Interception: Generally not intercepted. Custom gadgets may intercept to supplement or supersede default functionality.
Code Display 2-20 ObjDuplicateResource() with MSG_GEN_ADD_CHILD
/* This method duplicates a pre-instantiated version of MyMenu. * A duplicated object block may also be added using MSG_GEN_ADD_CHILD.*/
@method MyProcessClass, MSG_DUPLICATE_MY_MENU { MemHandle newBlock; /* The handle of the Duplicate block. */ optr newMenu; /* The optr of the new menu. */ GeodeHandle procHan; /* The geode handle of the process. */
procHan = GeodeGetProcessHandle(); newBlock = ObjDuplicateResource(OptrToHandle(@MyMenu), procHan, -1); /* Pass the handle of MyMenu's resource as well as the * GeodeHandle of the process. Leave the burden thread * the same.*/
/* The new optr is created from the newly created block. */ newMenu = ConstructOptr(newBlock, OptrToChunk(MyMenu));
/* Add the duplicated object tree (MyMenu) as the * first child of MyPrimary. */ @call @MyPrimary::MSG_GEN_ADD_CHILD(newMenu, (CCF_MARK_DIRTY | CCO_FIRST));
/* Then set it usable. Remember, you cannot add a child * that is already GS_USABLE. */ @call @newMenu::MSG_GEN_SET_USABLE(VUM_NOW); }
void MSG_GEN_ADD_CHILD_UPWARD_LINK_ONLY( optr child);
This message sets a parent link to a passed child object without adding a composite link from the parent to the child. This is a "one way" link in that the parent does not have knowledge of its new child. Therefore, it must be used with caution.
Source: Unrestricted.
Destination: Any generic object.
Parameters: child optr of the child to add with an upward link.
Interception: Generally not intercepted.
void MSG_GEN_REMOVE( VisUpdateMode updateMode, CompChildFlags flags)
This message removes the receiving object from the generic tree. The object to be removed need not be set not usable. Note that all objects below this object will also be removed.
Source: Anyone.
Destination: Any generic object.
Parameters: updateMode Visual update mode. VUM_MANUAL is not allowed.
Return: Nothing.
Interception: Generally not intercepted.
void MSG_GEN_REMOVE_CHILD( optr child, CompChildFlags flags);
This message removes the passed object from the recipient. A child must be marked not GS_USABLE in order to be removed. The child must currently exist, so your routine should check this using
MSG_GEN_FIND_CHILD
.
Pass this message the optr of the child object to be removed along with a word of
CompChildFlags
. If CCF_MARK_DIRTY is specified, the updated linkage will be saved to state when the application is detached.
Source: Unrestricted.
Destination: Any generic object.
Parameters: child The optr of child to remove. This child must be non-usable in order to be removed. The child must also exist as a child of the recipient.
CompChildFlags
to use when removing the child.Interception: Generally not intercepted. Custom gadgets may intercept to supplement or supersede default functionality.
Code Display 2-21 MSG_GEN_REMOVE_CHILD
/* This sample method removes the MyChild object from its parent, MyParent. */ @method MyProcessClass, MSG_REMOVE_MY_CHILD { /* If the child currently exists, mark it not usable and remove it. */ if (@call @MyParent::MSG_GEN_FIND_CHILD(@MyChild) != -1) { @call @MyChild::MSG_GEN_SET_NOT_USABLE(VUM_NOW); @call @MyParent::MSG_GEN_REMOVE_CHILD(@MyChild, CCF_MARK_DIRTY); } }
void MSG_GEN_MOVE_CHILD( optr child, CompChildFlags flags);
This message moves the given object from the location it currently occupies among its siblings to another location among its siblings. The object will still remain a child of the same parent.
Pass this message the optr of the child to move along with a word of
CompChildFlags
. If you pass the flag CCF_MARK_DIRTY, the new linkage will be saved to state when the application is detached. You must also pass a CCF_REFERENCE so the object will be moved to the position specified. CCO_FIRST and CCO_LAST will move the object to the first or last position, respectively.
If no flags are specified, the object will be moved to the parent object's first position without marking the linkages dirty. Note that for successive moves of children this will result in a "reverse order" of the children.
Note that this message only moves a child among its siblings. To move an object from one parent of the generic tree to another (different) parent, you must use
MSG_GEN_REMOVE
(or
MSG_GEN_REMOVE_CHILD
) and
MSG_GEN_ADD_CHILD
.
Source: Unrestricted.
Destination: Any generic object.
Parameters: child The optr of the child to move.
CompChildFlags
to use when moving the child.Interception: Generally not intercepted.
MSG_GEN_COPY_TREE, MSG_GEN_DESTROY, MSG_GEN_DESTROY_AND_FREE_BLOCK, MSG_GEN_BRANCH_REPLACE_PARAMS, MSG_GEN_BRANCH_REPLACE_OUTPUT_OPTR_CONSTANT
In addition to instantiating and manipulating generic objects one at a time, you can create, move, and destroy entire branches. One way of doing this is copying a resource using
ObjDuplicateResource()
and sending
MSG_GEN_ADD_CHILD
to the parent object, passing it the optr of the top object in the tree. This method has the advantage of retaining the same chunk offsets to objects within the duplicated block as in the source block.
Code Display 2-22 Using ObjDuplicateResource()
@start ResourceToCopy;
/* For simplicity, the GenItems in this listing contain no monikers or * identifiers. */
@object GenItemGroupClass MyList = { GI_comp = @AirplaneEntry, @TrainEntry, @CarEntry, @BicycleEntry; } @object GenItemClass AirplaneEntry = {} @object GenItemClass TrainEntry = {} @object GenItemClass CarEntry = {} @object GenItemClass BicycleEntry = {}
@end ResourceToCopy;
@method MyProcessClass, MSG_COPY_MY_RESOURCE { MemHandle newBlock;
newBlock = ObjDuplicateResource(OptrToHandle(@MyList), /* Block will be owned by the same geode. */ -1, /* Block will be run by the same thread. */ -1);
@call MyPrimary::MSG_GEN_ADD_CHILD(ConstructOptr(newBlock, OptrToChunk(@MyList)); }
Another way to duplicate groups of objects is with
MSG_GEN_COPY_TREE
. This message greatly simplifies generic tree construction. Those branches of the tree which are roughly similar can be duplicated with one message instead of several.
In many cases, it might be useful to create a UI resource template. This template should contain objects but should not contain object-specific information such as visual monikers, optrs, etc., as this information may be different for different instances of the branch. You can then duplicate these templates with
MSG_GEN_COPY_TREE
. The trees can then be updated to reflect their unique data either object by object or by using
MSG_GEN_BRANCH_REPLACE_PARAMS
, which will replace instance data within an entire branch.
To set up a template, create the generic tree you wish to function as a template, making sure that the top-level object of that tree is not usable (~GS_USABLE). Then use
MSG_GEN_COPY_TREE
to copy the tree to the proper location. You can then set the other instance data within the method. Finally, to make that tree appear on screen, set the top-level object GS_USABLE. You can remove any tree created with
MSG_GEN_COPY_TREE
with
MSG_GEN_DESTROY
. If you use
ObjDuplicateResource()
to copy a resource block, you can use
ObjFreeDuplicate()
to remove it. If the generic branch to be destroyed resides completely within a single block, you may send MSG_GEN_DESTROY_AND_FREE_BLOCK to the top object in that generic branch.
optr MSG_GEN_COPY_TREE( MemHandle destBlock, ChunkHandle parentChunk, word flags);
This message copies an entire branch of a generic object tree, starting at the object first called. Pass this message the handle of the destination object block. The object sent the message must not be GS_USABLE.
You may pass
parentChunk
null if you wish the block to remain unattached to the generic tree. Note that if a generic tree is copied using
MSG_GEN_COPY_TREE
, the objects contained therein not only will have a new resource handle but will also have new chunk handles. Note that this is different from using
ObjDuplicateResource()
, which will keep the same chunk offsets into the object block.
Unlike
ObjDuplicateResource()
, this message will copy the entire branch desired, even if those objects reside in separate resources. This message is therefore more flexible than
ObjDuplicateResource()
, which only copies a given object block.
GenClass
provides the default behavior of broadcasting this message down a generic tree, where each object will make a copy of itself in the destination block. It creates an object chunk the same size as the object chunk being copied, copies over the entire contents of any instance fields and creates an outside chunk for a visual moniker, if any.
If you have a subclass of a generic object which references (and therefore might need to create) a chunk outside the object, you must be sure to intercept this message and allocate, copy over, and update any references to this chunk.
Source: Unrestricted.
Destination: Any generic object.
Parameters: destBlock The block to copy the tree into. This block cannot be the same as the source object block.
parentChunk
. If zero, copy tree into block without linking it to a particular chunk.
CompChildFlags
to use when adding the tree.
Interception: This message is handled by all generic objects. If you wish to intercept this message, you should first call the superclass to copy over the
GenClass
instance data and then copy over any lmem chunks that are referenced by instance data of the intercepting class.
Code Display 2-23 MSG_GEN_COPY_TREE
/* Create a template resource block. For demonstration purposes, this block will * only contain one object, a GenItem. All declared resources must also be * declared in an application's corresponding .gp file. */
@start MyTemplate; @object GenItemClass TemplateItem = { GI_states = @default & ~GS_USABLE; /* Make sure it is NOT usable. */ } @end MyTemplate;
/* Start the Interface resource block */
@start Interface; @object GenItemGroupClass MyList = { } /* Object the template above will be added to. */ @end Interface;
@method MyProcessClass, MSG_COPY_A_LIST_ITEM { optr newListEntry;
/* This call copies TemplateItem to the location at MyList. The macros * OptrToHandle and OptrToChunk are used to cast the optr of MyList into * the proper type for MSG_GEN_COPY_TREE. This new linkage will be marked * dirty, and the child will become the first child of MyList. */ newListEntry = @call TemplateItem::MSG_GEN_COPY_TREE( OptrToHandle(@MyList), OptrToChunk(@MyList), (CCF_MARK_DIRTY | CCO_FIRST));
/* The newListEntry is set usable to bring it up on screen. */ @call newListEntry::MSG_GEN_SET_USABLE(VUM_NOW); }
void MSG_GEN_DESTROY( VisUpdateMode updateMode, word flags);
This message destroys a generic branch starting at the object called. The message sets all required generic objects not usable, removes them from the generic tree, and destroys them, including any chunks associated with the specific object destroyed. This message is the safest way to destroy a generic branch.
The message will leave the block that the objects previously resided in intact (except for objects removed, of course), but any chunks coming from those resources will be marked dirty and will be resized to zero.
It is usually a good idea to destroy generic branches that are not needed to be saved to state when an application detaches or exits. This ensures that when an application is reattached, it will not contain the previous links. This keeps the state file more compact and avoids the possibility of a child not being saved to state while retaining the parent's child pointer.
The only valid flag in
CompChildFlags
is CCF_MARK_DIRTY, which will mark the links as dirty and save them to state.
Source: Unrestricted.
Destination: Any generic object.
Parameters:
updateMode
VisUpdateMode
to determine when the generic tree is to be visually updated. May not be VUM_MANUAL.
CompChildFlags
to use when destroying the branch (either CCF_MARK_DIRTY or zero).
Interception: This message is handled by all generic objects. If you wish to intercept this message, you should first destroy any chunks that are referenced by instance data of the intercepting class and then call the superclass to destroy the object's
GenClass
instance data.
Boolean MSG_GEN_DESTROY_AND_FREE_BLOCK();
This is a utility message used to destroy a generic branch which resides completely within one block. The block will be freed. The object called with this message must be the only top object in the block. This message is called by
UserDestroyDialog()
.
If any object within the block resides on the application active list, or if the object is not a window, a slow, non-optimized approach is taken: the branch is set not usable, removed from the generic tree, and sent
MSG_META_BLOCK_FREE
. If no object of the block can be found on this list, an optimized approach is taken: the window is taken off the screen; FTVMC, mouse, etc. exclusives released; the linkage changed to be one-way upward; and the block sent
MSG_META_BLOCK_FREE
. In other words, the whole unbuild process is carefully avoided.
Source: Unrestricted
Destination: Top object within a block to be freed.
Return: true if the message was handled, false otherwise.
Interception: Generally not intercepted.
void MSG_GEN_BRANCH_REPLACE_PARAMS(@stack BranchReplaceParamType type, dword replaceParam, dword searchParam);
This message travels down a generic branch to all of an object's children; the message replaces all instance data specified in
type
with replacement instance data. A typical way to implement this is to set up a template UI branch with
MSG_GEN_COPY_TREE
. Most often, you will use this message to search and replace optrs set within your template. This is easily done by setting these optrs to certain constant values and then searching for those values in
type
.
If you only wish to replace your destination optrs, use
MSG_GEN_BRANCH_REPLACE_OUTPUT_OPTR_CONSTANT
, which is just a specialized case of this message.
When replacing optrs, the constant BRPT_DUMMY_OPTR_START should be used as the
searchParam
value. If multiple optrs are to be replaced, enumerated values based on that value should be used for other optrs. These values will be constants, and since the
TravelOption
types are also constants, care must be taken to replace these dummy values before anything else is done on the generic branch; otherwise, their output may be interpreted as a
TravelOption
.
This message may not be supported by several subclasses of
GenClass
.
Source: Unrestricted.
Destination: Any generic object.
Parameters:
searchParam
Specifies the search parameter. Typically this search parameter is a pre-set constant used to identify the instance data to replace. The search parameter must be a dword.
replaceParam
searchParam
will be replaced with the data specified in
replaceParam
. The data must be a dword.
type
BranchReplaceParamType
. The only value supported is BRPT_OUTPUT_OPTR, which specifies that all optrs with values matching
searchParam
should be replaced by the value in
replaceParam
.
Interception: This message is handled by most generic objects (although not all). If you wish to intercept this message, you should first call the superclass to search and replace any
GenClass
instance data, if applicable, and then search and replace any instance data in the intercepting class.
void MSG_GEN_BRANCH_OUTPUT_OPTR_CONSTANT( optr replacementOptr, word searchConstant);
This message is a special case of
MSG_GEN_BRANCH_REPLACE_PARAMS
where the
BranchReplaceParamType
is BRPT_OUTPUT_OPTR with a search parameter of a constant value set up beforehand. You must pass this message the optr to replace the search constant found.
Source: Unrestricted.
Destination: Any generic object.
Parameters: replacementOptr The optr to replace all instance fields with destinations matching the searchConstant .
Interception: Generally not intercepted. This message invokes
MSG_GEN_BRANCH_REPLACE_PARAMS
so intercept that instead.
Within
GenClass
, much of your instance data will appear within the basic instance fields allocated with
@instance
. These instance data fields are fixed; each generic object you create will contain each one of these instance fields. You may also make use of special instance data (variable data, also called "vardata") using the object variable data storage mechanism. See the GEOS Programming chapter for complete information on variable data.
Vardata performs many of the same functions that fixed instance data does.
However,
vardata differs significantly from fixed instance data in that it will only occupy memory if it is in fact declared. You may also only access vardata entries through special kernel routines and messages. For generic objects, most vardata is either in the form of attributes (beginning with ATTR_) or hints (beginning with HINT_).
Vardata attribute entries begin with the form ATTR_attributename (as in ATTR_GEN_DESTINATION_CLASS). You can initialize this data within your Goc
object declaration.
ATTR
s within
GenClass
are available for use by any generic object. Several subclasses of
GenClass
also contain their own ATTR vardata entries. In
GenClass
no vardata attributes or hints are set by default.
ATTRs often behave as additional instance data that just happens to be vardata (and therefore optionally added). For generic objects, these should always be considered part of the generic state of an object and therefore may be saved out to the state file. You may, of course, decide not to save any such fields to the state file.
Temporary vardata to be used by an object class can be specified using the format
TEMP
_tempname. Any data set up with
TEMP
in a generic object should not be saved to state and should not be considered part of the API but rather an internal field. In almost all cases, you will not need to access such vardata entries.
For information on manipulating the variable length instance fields dynamically, along with a list of valid hints for
GenClass
, see Dynamically Managing VarData
.
ATTR_GEN_DESTINATION_CLASS
ATTR_GEN_DESTINATION_CLASS
specifies the object class that should handle messages sent out by this object. Typically, an object marked with this ATTR will not have a specific destination optr, but instead a destination path defined by a
TravelOption
. The message for a generic object with a destination class travels down the generic tree along the path specified in the
TravelOption
until it encounters an object class of type
ATTR_GEN_DESTINATION_CLASS
; at that point, the message will be handled.
ATTR_GEN_DESTINATION_CLASS takes an argument of type
DestinationClassArgs
. This type contains a pointer to a
ClassStruct
. You may have to cast the class name into a
ClassStruct
type when setting ATTR_GEN_DESTINATION_CLASS.
typedef struct { ClassStruct * DCA_class; } DestinationClassArgs;
Code Display 2-24 Using ATTR_GEN_DESTINATION_CLASS
/* This object will send MSG_META_CUT to the application object and follow the * target path until it encounters a VisTextClass object. At that point, the * message will be handled. */
@object GenTriggerClass MyTrigger = { GI_visMoniker = "This trigger cuts text from the target object." GTI_actionMsg = MSG_META_CUT; GTI_destination = (TO_APP_TARGET); /* The class pointer points to a ClassStruct structure. */ ATTR_GEN_DESTINATION_CLASS = { (ClassStruct *)&VisTextClass }; }
/* To set up a destination class as any generic object, set * ATTR_GEN_DESTINATION_CLASS to GenClass. This interaction sends * MSG_GEN_SET_NOT_USABLE to the first focus object below the GenInteraction. */
@object GenTriggerClass MyTrigger = { GI_visMoniker = "Remove the Focus object"; GTI_actionMsg = MSG_GEN_SET_NOT_USABLE; GTI_destination = (TO_FOCUS); ATTR_GEN_DESTINATION_CLASS = { (ClassStruct *)&GenClass }; }
typedef enum { /* These values may be used as normal * TravelOptions, and have been set up * so that they will have no value in * common with normal TravelOptions. */ TO_GEN_PARENT=_FIRST_GenClass, TO_FOCUS, TO_TARGET, TO_MODEL, TO_APP_FOCUS, TO_APP_TARGET, TO_APP_MODEL, TO_SYS_FOCUS, TO_SYS_TARGET, TO_SYS_MODEL, } GenTravelOption;
The
TravelOption
types provided with
GenClass
are additional enumerations of the types supplied with
MetaClass
.
MetaClass
provides the types TO_NULL, TO_SELF, TO_OBJ_BLOCK_OUTPUT and TO_PROCESS. Therefore, any generic object can use these types or the further enumerations included here.
These
TravelOption
types typically replace a generic object's destination with a path for a message to be delivered along. Most often, these
TravelOption
s are used in conjunction with the vardata attribute ATTR_GEN_DESTINATION_CLASS. Together, they allow a message to follow a path specified in
TravelOption
until it encounters an object of a class specified in
ATTR_GEN_DESTINATION_CLASS
. This allows an object to generically send a message down an output path without knowing a specific destination.
MSG_GEN_LOAD_OPTIONS, MSG_GEN_SAVE_OPTIONS, ATTR_GEN_INIT_FILE_KEY, ATTR_GEN_INIT_FILE_CATEGORY, ATTR_GEN_INIT_FILE_PROPAGATE_TO_CHILDREN, ATTR_GEN_USES_HIERARCHICAL_INIT_FILE_CATEGORY
Your object may request information from the GEOS.INI file upon startup. Each object on the appropriate GenApplication GCN list may receive a
MSG_GEN_LOAD_OPTIONS
upon receiving
MSG_META_ATTACH
(and a
MSG_GEN_SAVE_OPTIONS
upon
MSG_META_SAVE_OPTIONS
). Various generic objects intercept this message and perform actions according to the information provided.
Your object may also access information in the GEOS.INI file as it is being attached by including ATTR_GEN_INIT_FILE_CATEGORY of the GEOS.INI category you are interested in and the ATTR_GEN_INIT_FILE_KEY of the specific keyword you want the data for. If a file key, but no file category, exists within an object declaration, then the system will query the application object for its ATTR_GEN_INIT_FILE_CATEGORY.
Normally only the GenApplication object and any objects in its GCN list will receive
MSG_GEN_LOAD_OPTIONS
and
MSG_GEN_SAVE_OPTIONS
. If you wish other children below these objects to also receive these messages (and therefore request or save information from the GEOS.INI file) you can add the attribute
ATTR_GEN_INIT_FILE_PROPAGATE_TO_CHILDREN. Any objects with this attribute will send these messages on down the generic tree to their children. Any children may then also contain this attribute and pass the messages on down to their children, etc.
Normally, the object itself and then the GenApplication object is queried for an ATTR_GEN_INIT_FILE_CATEGORY. If instead, the object wants a generic upward query of the object's parents, you can attach ATTR_GEN_USES_HIERARCHICAL_INIT_FILE_CATEGORY to the object. In this case, the object will be queried for its file category, and then query up the generic tree for the first object encountered with an ATTR_GEN_INIT_FILE_CATEGORY. In this manner, one parent may contain a file category and several children may contain different file keys within that category.
Because this method is recursive, it is slow and therefore should be avoided. Most applications should only need one init file category.
void MSG_GEN_LOAD_OPTIONS( GenOptionsParams *params);
This message instructs the generic object to load a value from the GEOS.INI file. It is called automatically by the handler in
GenClass
for
MSG_META_LOAD_OPTIONS
. The message scans the object's vardata for an ATTR_GEN_INIT_FILE_KEY and an ATTR_GEN_INIT_FILE_CATEGORY to scan the .INI file. If no file category is found in the object's vardata, the handler will search up the generic tree for a parent with an ATTR_GEN_INIT_FILE_CATEGORY.
You may send this message, passing it the proper
GenOptionsParams
. The return value must be cast into the proper type of whatever the entry within the file key is. This is a null-terminated text string.
Source: Sent by
GenClass
on
MSG_META_ATTACH
.
GenClass
generates the
GenOptionsParams
structure by looking in the object's vardata (and by querying up the generic tree, if necessary).
Destination: Any generic object.
Parameters:
params
GenOptionsParams
structure (automatically generated by
GenClass
). See
MSG_GEN_SAVE_OPTIONS
.
Return: Return values must be cast into the proper type of whatever the entry of category and file key is.
Interception: Various generic classes intercept this and provide default behavior
void MSG_GEN_SAVE_OPTIONS( GenOptionsParams *params);
This message instructs the generic object to save its options to the initialization file.
Source: Sent by
GenClass
on
MSG_META_SAVE_OPTIONS
.
GenClass
generates the proper
GenOptionsParams
structure by looking in the object's vardata (and querying up the generic tree, if necessary).
Destination: Any generic object.
Parameters:
params
GenOptionsParams
structure (automatically generated by
GenClass
).
Return: Return values must be cast into the proper type of whatever the entry of category and file key is.
Interception: Various generic classes intercept this and provide default behavior
Structures: The
GenOptionsParams
structure is defined as follows:
typedef struct { char GOP_category[INIT_CATEGORY_BUFFER_SIZE]; char GOP_key[INIT_CATEGORY_BUFFER_SIZE]; } GenOptionsParams;
ATTR_GEN_POSITION, ATTR_GEN_POSITION_X, ATTR_GEN_POSITION_Y
You may wish, in rare cases, to hard-wire a generic object's position relative to its parent. You can do this by including one of these attributes with a position offset from the parent. These attributes supersede the geometry manager; because of this, you should exercise extreme caution whenever using these attributes. You should only use these attributes in the rare cases when the geometry manager (and hints) cannot accommodate your geometry concerns.
ATTR_GEN_POSITION
takes a
Point
argument, specifying the x and y offset (in points) from the parent's top left corner. This point will become the object's top left corner.
ATTR_GEN_POSITION_X specifies the horizontal (x) offset (in points) from the left edge of the parent. The vertical (y) offset will be left to the specific UI (or ATTR_GEN_POSITION_Y) to determine.
ATTR_GEN_POSITION_Y specifies the vertical (y) offset (in points) from the top edge of the parent. The horizontal (x) offset will be left to the specific UI (or ATTR_GEN_POSITION_X) to determine.
Several hints also accomplish similar geometry overrides.
HINT_ALIGN_TOP_EDGE_WITH_OBJECT
aligns an object's top edge with the top edge of the object (optr) this hint is set to. Similarly,
HINT_ALIGN_LEFT_EDGE_WITH_OBJECT
,
HINT_ALIGN_RIGHT_EDGE_WITH_OBJECT
, and
HINT_ALIGN_BOTTOM_EDGE_WITH_OBJECT
all line up an object's edge with the same edge of the object these hints are set to. One of these hints can be used in each direction. The same concerns over superceding the default geometry manager in the above attributes are valid here as well. Therefore, avoid using these hints if possible.
ATTR_GEN_SEND_APPLY_MSG_ON_APPLY_EVEN_IF_NOT_MODIFIED, ATTR_GEN_SEND_APPLY_MSG_ON_APPLY_EVEN_IF_NOT_ENABLED
Most generic objects act on changes made by the user. Some generic objects may not immediately react to these changes; instead these objects allow the user to select a variety of settings and then later "apply" these changes. These generic objects operate in delayed mode and each has an "apply message" associated with it. For these objects, the user may alter the state of the object or its children, but the application only sends out the action to perform those changes when the "apply" message is sent out.
For example, a dialog box may contain a list of settings that represent the state of a paragraph in a word processor. If the user ever actually changes those settings, the dialog box is marked as modified, but the changes are not actually made until the object receives notification to apply its changes (send out its apply message).
By default, these generic objects check whether their state has been modified since the last apply message has been sent out. If their state has not been modified and they receive a request to apply changes made, they instead will ignore the request. Likewise, objects set not enabled will ignore the request. ATTR_GEN_SEND_APPLY_MSG_ON_APPLY_EVEN_IF_NOT_MODIFIED
and
ATTR_GEN_SEND_APPLY_MSG_ON_APPLY_EVEN_IF_NOT_ENABLED
override this behavior, telling the generic object to send out its apply message regardless of the modified or enabled state of a generic object.
In the above example, this would mean that whenever the dialog box receives notification to apply its changes it would not check whether its settings have been altered since the last time it applied its changes. Instead it would apply these changes anyway.
ATTR_GEN_VISIBILITY_DATA, ATTR_GEN_VISIBILITY_MESSAGE, ATTR_GEN_VISIBILITY_DESTINATION
If a generic object has its GA_NOTIFY_VISIBILITY bit set, it will notify the GenApplication object when it becomes visible or not visible. The object does this by sending
MSG_GEN_APPLICATION_VISIBILITY_NOTIFICATION
to the GenApplication object, passing the sending object's optr as data.
You can alter this default behavior by including one or more attributes. ATTR_GEN_VISIBILITY_MESSAGE
specifies a different message than
MSG_GEN_APPLICATION_VISIBILITY_NOTIFICATION
; ATTR_GEN_VISIBILITY_DESTINATION
specifies a different destination to send visibility notification to than the GenApplication object; ATTR_GEN_VISIBILITY_DATA
specifies a different word of data to send out than the default data (the optr of the sending object). These attributes will have no effect on objects not marked GA_NOTIFY_VISIBILITY.
ATTR_GEN_PROPERTY, ATTR_GEN_NOT_PROPERTY
Objects that exhibit properties (List Objects, GenValues, GenTexts, etc.) sometimes do not exhibit immediate effects when the user interacts with the object. These objects act in what is known as delayed mode ; they only apply their properties when their object receives a MSG_GEN_APPLY.
Properties objects such as these are usually placed within a GIT_PROPERTIES GenInteraction object. The GIT_PROPERTIES dialog box provides an "Apply" trigger to get the objects to apply their properties. You can, however, change this default behavior, though it is uncommon to need to do so.
ATTR_GEN_PROPERTY, when added to an object that exhibits properties, allows an object to act like it is within a properties dialog box even if it normally operates in immediate mode. That is, it will not apply its changes until explicitly told to do so (using MSG_GEN_APPLY).
ATTR_GEN_NOT_PROPERTY allows an object within a GIT_PROPERTIES dialog box to act like it is not within such a dialog box. That is, any user interaction with the object will result in an immediate application of those changes.
GenClass
supplies several optional attributes that affect the display of windows within the user interface. Windowed objects include GenPrimarys, GenDisplays, and GenInteractions (as dialog boxes).
The optional attributes that follow are divided into two groups. Window layering affects how windowed objects are arranged on the screen; i.e., where they appear and whether they appear above or below other windowed objects. In general, this layering behavior is only determined for windowed objects having the same parent, i.e., windows having the same parent can be custom layered, and their parents will be layered among its siblings.
There also exist optional attributes to alter the manner in which input travels within a window. These optional attributes allow the application to provide floating keyboards for pen input.
ATTR_GEN_WINDOW_CUSTOM_LAYER_ID, ATTR_GEN_WINDOW_CUSTOM_WINDOW_PRIORITY, ATTR_GEN_WINDOW_CUSTOM_LAYER_PRIORITY, ATTR_GEN_WINDOW_CUSTOM_PARENT, ATTR_GEN_WINDOW_CUSTOM_WINDOW
ATTR_GEN_WINDOW_CUSTOM_LAYER_ID sets a unique layer identifier for the windowed object. All objects with a common identifier are considered part of the same window layer. These layers can then be manipulated as a unit. By convention, these IDs are usually set to the handles owned by the application; this avoids collisions with other application window layer IDs.
If a null layer ID is specified, the handle of the block the object lies in will be selected as the layer ID at run-time. This is the common method of assigning layer IDs.
ATTR_GEN_WINDOW_CUSTOM_LAYER_PRIORITY allows a windowed object to set its layer priority to a custom value. The optional attribute expects an argument of type
LayerPriority
. Note that all windowed objects with the same Layer ID
must
have the same layer priority; therefore, this attribute must be used with care. It should only be used if a layer ID declared with ATTR_GEN_WINDOW_CUSTOM_LAYER_ID is also used.
ATTR_GEN_WINDOW_CUSTOM_WINDOW_PRIORITY sets a custom window priority for this specific window among all other windows of the same layer ID. This optional attribute expects an argument of type
WindowPriority
.
ATTR_GEN_WINDOW_CUSTOM_PARENT allows windowed objects to set a custom parent window. Because window layering applies only to the ordering of windows having the same parent, a window with a custom parent will have its layer ID, layer priority, and window priority compared to other windows having the same parent as ATTR_GEN_WINDOW_CUSTOM_PARENT.
If ATTR_GEN_WINDOW_CUSTOM_PARENT is set null, this indicates that the system screen window should be the parent. Because this window is the parent window for all base windows in the system, an object setting the screen window as its custom parent will be able to appear on top of (or below) all other windows in the system (that do not have a matching layer ID). This is very low-level behavior and should be used with caution, however.
ATTR_GEN_WINDOW_ACCEPT_INK_EVEN_IF_NOT_FOCUSED, ATTR_GEN_WINDOW_KBD_OVERRIDE, ATTR_GEN_WINDOW_KBD_POSITION, MSG_GEN_SET_KBD_OVERRIDE, MSG_GEN_SET_KBD_POSITION
ATTR_GEN_WINDOW_ACCEPT_INK_EVEN_IF_NOT_FOCUSED indicates that the object should accept ink even if it doesn't have the focus. In general, presses on non-focused windows will never turn into ink. If this attribute is present, then presses on the window can turn into ink. The normal mechanism for determining if a press should be ink is then followed.
ATTR_GEN_WINDOW_KBD_OVERRIDE indicates the manner in which a floating keyboard is provided for a given window. This optional attribute expects an argument of type of
KeyboardOverride
. This attribute specifies whether a floating keyboard is provided for text input via a pen device.
The following
KeyboardOverride
values are valid:
You can change the
KeyboardOverride
exhibited by a windowed object by sending the object MSG_GEN_SET_KBD_OVERRIDE.
The following rules will ensure that a keyboard will be present whenever the user interacts with a display requiring a keyboard: Set the KO_KEYBOARD_REQUIRED bit for any GenDisplay which should be accompanied by a floating keyboard. If all GenDisplays in your geode require a floating keyboard, then set this bit for each of them. GenDisplays that contain embedded keyboards should have the KO_KEYBOARD_EMBEDDED bit set instead of the KO_KEYBOARD_REQUIRED bit.
If you want a keyboard to appear visible even when no GenDisplays are open, mark the GenPrimary KO_KEYBOARD_REQUIRED and mark each GenDisplay KO_NO_KEYBOARD.
ATTR_GEN_WINDOW_KBD_POSITION specifies the default position for the floating keyboard to appear when the window gains the focus. If the user moves the floating keyboard, this attribute is updated to reflect the new position and the keyboard will appear at that position when brought up in the future.
You can change this keyboard position by sending the object MSG_GEN_SET_KBD_POSITION, passing it the
Point
to position the keyboard at.
void MSG_GEN_SET_KBD_OVERRIDE( KeyboardOverride override);
This message sets an object's ATTR_GEN_WINDOW_KBD_OVERRIDE to the passed
KeyboardOverride
value.
Source: Unrestricted.
Destination: Any windowed generic object.
Parameters:
override
KeyboardOverride
.
Interception: Generally not intercepted.
void MSG_GEN_SET_KBD_POSITION( sword xCoord, sword yCoord);
This message sets an object's ATTR_GEN_WINDOW_KBD_POSITION to the passed
Point
values.
Source: Unrestricted.
Destination: Any windowed generic object.
Parameters: xCoord X coordinate to position the keyboard (relative to the window).
Interception: Generally not intercepted.
The Help system is discussed in full in the Help chapter. You should read that chapter if you wish to include help within your application. The information provided here is mostly an overview of that information.
ATTR_GEN_HELP_FILE, ATTR_GEN_HELP_TYPE, ATTR_GEN_HELP_FILE_FROM_INIT_FILE, ATTR_GEN_HELP_CONTEXT
ATTR_GEN_HELP_FILE stores the help file associated with this object. Help files are generated by the help editor (a modified GeoWrite) from GeoWrite documents and are located in USERDATA\HELP.If the help system queries this object for a help file and this optional attribute does not exist, it will query up the generic tree for the first object with an ATTR_GEN_HELP_FILE.
An object can use
ATTR_GEN_HELP_FILE_FROM_INIT_FILE
to specify that its help file should be taken from the GEOS.INI file. If this attribute is used, the help controller will look in the GEOS.INI file for a category of the same name as the application and a key named "helpfile." Thus, to set the help file to "My Own Help File" for the HelpSamp application, you could add the following to your GEOS.INI file:
[HelpSamp] helpfile = My Own Help File
If, however, no object has
ATTR_GEN_HELP_FILE_FROM_INIT_FILE
, this init file entry will not be noticed by the help controller.
ATTR_GEN_HELP_TYPE stores the
HelpType
associated with this object. If the help system queries this object for a help type and this optional attribute does not exist, it will query up the generic tree for the first object with an ATTR_GEN_HELP_TYPE.
Each help file must have several contexts named within the file. These contexts are set up when the help file is written. When an object brings up help, it should reference the specific context for which the user needs help. This context is stored within the object's ATTR_GEN_HELP_CONTEXT field. Usually this optional attribute is placed on a windowed GenInteraction (dialog box).
If an object needs to set a different help context for itself at run-time, it can use MSG_META_DELETE_VAR_DATA and MSG_META_ADD_VAR_DATA to alter the contents of the object's ATTR_GEN_HELP_CONTEXT.
ATTR_GEN_FOCUS_HELP, ATTR_GEN_FOCUS_HELP_LIB
ATTR_GEN_FOCUS_HELP is currently unsupported. This help mechanism is a simple, scaled down version of the previously mentioned help system. A fixed area at the bottom of the screen on certain displays acts as a help text area. An object with ATTR_GEN_FOCUS_HELP indicates that this text area should display the its help text when this object gains the focus within the application. This field expects an optr pointing to the required text.
ATTR_GEN_FOCUS_HELP_LIB is similar to ATTR_GEN_FOCUS_HELP but only applies to objects exported from a library(e.g., controllers).
ATTR_GEN_DEFAULT_MONIKER, GenDefaultMonikerType
ATTR_GEN_DEFAULT_MONIKER specifies a default moniker for this object. Default monikers are generally used for gstring monikers that occur several places within the system (i.e., they are stored outside of the application). ATTR_GEN_DEFAULT_MONIKER expects an argument of type
GenDefaultMonikerType
.
typedef enum { GDMT_LEVEL_0, GDMT_LEVEL_1, GDMT_LEVEL_2, GDMT_LEVEL_3, GDMT_HELP, GDMT_HELP_PRIMARY } GenDefaultMonikerType;
The GDMT_LEVEL monikers correspond to the gstring monikers used to indicate the current user level. GDMT_HELP corresponds to the default help trigger moniker. GDMT_HELP_PRIMARY corresponds to the special help trigger for a GenPrimary object.
ATTR_GEN_FEATURE_LINK
This optional attribute indicates that a feature within a GenControl object maps to multiple generic trees within the child block. If a feature in a GenControl so marked is turned off, for example, the controller will remove the feature from the first generic tree associated with this feature and then will remove the feature from the link to the next generic tree. Controllers and features are discussed more fully in the Controllers chapter.
ATTR_GEN_PATH_DATA, MSG_GEN_PATH_SET, MSG_GEN_PATH_GET, GenFilePath
GenClass
is able to keep track of file path information.
GenClass
does not use this information itself, but maintains it so that various subclasses (e.g., the file selector and document control) will be able to use the same instance fields and messages.
Because handlers for all these messages are implemented in
GenClass
, it is possible to store a path with any generic object, whether the particular object normally does anything with the file system or not.
The path itself is stored in the object's vardata in the ATTR_GEN_PATH_DATA field. In the absence of such a field,
GenClass
will use SP_TOP as the standard path. Subclasses can change this default by intercepting
MSG_META_INITIALIZE_VAR_DATA
, filling in the
GenFilePath
structure after it has called the superclass (which will actually allocate the attribute).
The ATTR_GEN_PATH_DATA field contains the following structure;
typedef struct { DiskHandle GFP_disk; PathName GFP_path; } GenFilePath;
GFP_
disk
stores the handle of the disk on which the path resides. This value may be initialized to a
StandardPath
constant. GFP_
path
stores the absolute path to the directory; this path may be a relative path if GFP_
disk
is a
StandardPath
directory.
You can retrieve an object's current path with MSG_GEN_PATH_GET. You can alter an object's path with MSG_GEN_PATH_SET.
Boolean MSG_GEN_PATH_SET( char *path, DiskHandle disk);
This message sets the path associated with the object. Normally, a complete path name must be passed. Note that this path string should not include a drive specifier, as this is implied by the passed disk handle. If the passed
DiskHandle
is actually a
StandardPath
value, then the path string will be taken to be relative to this standard path.
Source: Unrestricted.
Destination: Generic object which has an associated path.
Parameters: path Null-terminated pathname; may not be in the same block as the object receiving this message. (If null, default handler will use root directory of disk handle or directory associated with standard path.)
StandardPath
constant.Return: Returns true if error.
Interception: Generally not intercepted. If the object is specifically grown, the message will be forwarded to the specific class after it has been acted on by
GenClass
.
Boolean MSG_GEN_PATH_GET( char *buffer, word bufSize);
This message returns a null-terminated complete path (no drive letter--drive is implied by the disk handle) for the object. Note that if the object is within a standard directory, the disk handle will be a
StandardPath
constant and the path will appear relative.
Source: Unrestricted.
Destination: Generic object which has an associated path.
Parameters: buffer Pointer to character buffer which will be filled with return value.
Return: Returns true if error (if the path won't fit in the passed buffer or is invalid).
Interception: Generally not intercepted.
@alias (MSG_GEN_PATH_GET) MemHandle MSG_GEN_PATH_GET_BLOCK( char *buffer, /* This must be NULL */ word bufSize);
This message returns the handle of a block containing the path.
Source: Unrestricted.
Destination: Generic object which has an associated path.
Parameters: buffer This must be NULL.
Return: Handle of block containing path.
Interception: Generally not intercepted.
DiskHandle MSG_GEN_PATH_GET_DISK_HANDLE();
This message returns the disk handle for the path bound to the object.
Source: Unrestricted.
Destination: Generic object which has an associated path.
Parameters: None.
Return: Disk handle associated with path, or
StandardPath
if object is associated with a standard directory.
Interception: Generally not intercepted.