The fourth part of the class record is the ManagerClassPart structure. For example, following is the ManagerClassPart structure of the ExmGrid widget:
{ /* manager class */ /* translations */ XtInheritTranslations, /* syn_resources */ syn_resources, /* num_syn_resources */ XtNumber(syn_resources), /* syn_constraint_resources */ syn_constraints, /* num_syn_constraint_resources */ XtNumber(syn_constraints), /* parent_process */ XmInheritParentProcess, /* extension */ NULL, },
The following subsections explain what a Motif widget writer should know about these fields.
The translations field defines the keyboard traversal translations for your manager widget. For this field, you must specify one of the following:
The keyboard traversal translations for the XmManager widget are as follows:
<EnterWindow>: ManagerEnter() <LeaveWindow>: ManagerLeave() <FocusOut>: ManagerFocusOut() <FocusIn>: ManagerFocusIn() :<Key>osfBeginLine: ManagerGadgetTraverseHome() :<Key>osfUp: ManagerGadgetTraverseUp() :<Key>osfDown: ManagerGadgetTraverseDown() :<Key>osfLeft: ManagerGadgetTraverseLeft() :<Key>osfRight: ManagerGadgetTraverseRight() s ~m ~a <Key>Tab: ManagerGadgetPrevTabGroup() ~m ~a <Key>Tab: ManagerGadgetNextTabGroup()
If you provide your own keyboard traversal translations string, Motif strongly recommends that the string contain all the keyboard traversal translations of XmManager.
The syn_resources field holds the name of the array that defines the widget's synthetic resources. Synthetic resources provide a mechanism for translating widget resource values between different formats. (See Chapter 6 for information on synthetic resources.)
If you do not wish to define synthetic resources for your widget, set the value of this field to NULL.
The num_syn_resources field holds the number of synthetic resources defined by the array in the syn_resources field. If your widget does not provide a syn_resources array, then you should specify 0 for the num_syn_resources field. If your widget does provide a syn_resources array, then your widget should use the XtNumber macro to count these resources.
Synthetic constraints are to constraints what synthetic resources are to resources. In short, synthetic constraints provide a mechanism for automatic conversion of constraints between an external format and an internal format. (See Chapter 6 for details on synthetic resources.)
You must specify one of the following for the syn_constraint_resources field:
For example, the ExmGrid widget defines two synthetic constraints in its synthetic constraint resources array as follows:
static XmSyntheticResource syn_constraints[] = { { ExmNgridMarginWidthWithinCell, /* resource name */ sizeof (Dimension), /* data type of resource */ XtOffsetOf( ExmGridConstraintRec, grid.grid_margin_width_within_cell), /* offset */ XmeFromHorizontalPixels, /* conversion routine */ XmeToHorizontalPixels /* conversion routine */ }, { ExmNgridMarginHeightWithinCell, sizeof (Dimension), XtOffsetOf( ExmGridConstraintRec, grid.grid_margin_height_within_cell), XmeFromVerticalPixels, XmeToVerticalPixels }, };
XmeFromHorizontalPixels and XmeToHorizontalPixels are functions that convert a constraint resource value between pixels and real-world dimensions assuming a horizontal resolution. (See Chapter 6 for details.)
The num_syn_constraint_resources field holds the number of synthetic constraints defined by the array in the syn_constraint_resources field. If your widget does not provide a syn_constraint_resources array, then you should specify 0 for the num_syn_constraint_resources field. If your widget does provide a syn_constraint_resources array, then your widget should use the XtNumber macro to count these constraints.
The parent_process method provides a mechanism for a child to pass an event up to its parent. Motif widgets use this mechanism to pass an osfActivate or an osfCancel event up to the first manager in the hierarchy that can process it. The osfActivate and osfCancel of all Motif primitive actions end up calling their parent's parent_process method.
Your manager widget must set the parent_process field to one of the following:
The parent_process method of XmManager passes the received event up to the parent of the manager that received it. If that manager widget also inherits the parent_process method of XmManager, then the event will be passed to its parent, and so on. This trail of passed events ends when either of the following happens:
For example, consider the hierarchy shown in Figure 4-2. Assume that ManagerA inherits the parent_process method of XmManager, but ManagerB provides its own parent_process method. Suppose that PrimitiveA receives an osfActivate event. Since ManagerA is the parent of PrimitiveA, the osfActivate event is passed up to ManagerA. ManagerA cannot process the event, so ManagerA passes the event up to its parent, ManagerB. ManagerB processes the osfActivate event.
Figure 4. A Hierarchy for Exploring the parent_process Method.
View figure. |
On the other hand, if ManagerB had been a Shell rather than a manager, then the osfActivate event would have been ignored.
Many manager widgets have no need to track the osfActivate and osfCancel events of their children. For such widgets, inheriting the parent_process method of XmManager is appropriate. However, DialogBox widgets do need to know when a child has received an osfActivate or osfCancel event in order to activate the default button or the cancel button.
If you write your own parent_process method, it must have the following prototype:
Boolean ParentProcess( Widget w, XmParentProcessData data)
The second argument to the method must be a XmParentProcessData structure. This structure has the following definition:
typedef struct XmParentProcessData { int process_type; XEvent *event; int action; String *params; Cardinal *num_params; };
Your parent_process method must return a Boolean value. Return True if the parent of your widget is a manager with a parent_process field set to something other than NULL. Otherwise, return False.
Your widget's parent_process method must do one of the following tasks:
The following code illustrates how to do the latter task:
XmManagerWidgetClass manClass; manClass = (XmManagerWidgetClass) widget->core.widget_class; if (XmIsManager(widget) && manClass->manager_class.parent_process) return( (*manClass->manager_class.parent_process)( widget, data)); return( FALSE) ;
The XmManager widget provides an extension record. Motif recommends that you specify the extension field as NULL. If you do, Motif will automatically supply an appropriate extension field for your widget. If you do not specify the extension field as NULL, you must specify the name of the manager class extension record.