[ Previous | Next | Contents | Glossary | Home | Search ]
Motif 2.1 Widget Writer's Guide



The CoreClassPart Structure

The top portion of the widget class record, which is the portion containing the 32 fields from Core, is called the CoreClassPart structure. For example, following is the CoreClassPart structure of the ExmSimple widget:

externaldef (exmsimpleclassrec) ExmSimpleClassRec exmSimpleClassRec
= {
 { /* Here is the core class record. */
   /* superclass */                
(WidgetClass)&xmPrimitiveClassRec,
   /* class_name */                 "ExmSimple",
   /* widget_size */                sizeof(ExmSimpleRec),
   /* class_initialize */           ClassInitialize,
   /* class_part_initialize */      ClassPartInitialize,
   /* class_inited */               FALSE,
   /* initialize */                 Initialize,
   /* initialize_hook */            NULL,
   /* realize */                    Realize,
   /* actions */                    NULL,
   /* num_actions */                0,
   /* resources */                  resources,
   /* num_resources */              XtNumber(resources),
   /* xrm_class */                  NULLQUARK,
   /* compress_motion */            TRUE,
   /* compress_exposure */          XtExposeCompressMaximal,
   /* compress_enterleave */        TRUE,
   /* visible_interest */           FALSE,
   /* destroy */                    Destroy,
   /* resize */                     Resize,
   /* expose */                     Redisplay,
   /* set_values */                 SetValues,
   /* set_values_hook */            NULL,
   /* set_values_almost */          XtInheritSetValuesAlmost,
   /* get_values_hook */            NULL,
   /* accept_focus */               NULL,
   /* version */                    XtVersion,
   /* callback_private */           NULL,
   /* tm_table */                   XtInheritTranslations,
   /* query_geometry */             QueryGeometry,
   /* display_accelerator */        NULL,
   /* extension */                  NULL,
 },

These are the same 32 fields that every Intrinsics-based widget defines. A good Intrinsics book can explain what each of these fields means to the Intrinsics. However, we need to go beyond that. You need to explore what Motif widget writers need to know about these fields.

The superclass Field

The first field of the CoreClassPart structure is the superclass field. This field holds the name of the class record of your widget's immediate superclass. If XmPrimitive is the immediate superclass of your widget, then your widget would specify the superclass field as follows:

/* superclass */                
(WidgetClass)&xmPrimitiveClassRec,

The class_name Field

Set the class_name field to a string containing the name of the class; for example:

/* class_name */                 "ExmSimple",

Motif will not make any attempt to interpret the characters in the string. However, it is a good idea to use alphanumeric characters only in the string. The string can be any length.

The string should begin with some prefix that uniquely symbolizes the widget group you are creating. For example, all the sample widgets associated with this group start with the Exm prefix. Do not pick a prefix that is used by other groups. For example, Motif reserves the prefixes xm, Xm, _Xm, Xme, XmQT, and Exm. See Chapter 2 for more information on namespace.

The widget_size Field

The widget_size field of primitive widgets holds the size of the full instance record. For example, the full instance record of the ExmSimple demonstration widget is named ExmSimpleRec; therefore, the Core class record of ExmSimple defines the widget_size field as follows:

/* widget_size */               
sizeof(ExmSimpleRec);

The class_initialize Field

The class_initialize field holds the name of the widget's class initialization method. If your widget does not supply a class initialization method, you should set this field to NULL.

The Intrinsics call the class initialization method only once, at the first instantiation of a widget of this class. Most Motif widgets use the class_initialize method to register representation types. Motif provides a set of functions for registration, the most important of which is XmRepTypeRegister. For example, the class_initialize method of the ExmSimple widget registers the ExmRSimpleShape representation type as follows:

void
ClassInitialize( void)
{
  simpleShapeId = XmRepTypeRegister (ExmRSimpleShape, SimpleShapeNames,
                                     NULL, XtNumber(SimpleShapeNames));
}

See Chapter 6 for more information on representation types.

The class_part_initialize Field (Chained)

You can either set the class_part_initialize field to the name of your class part initialization method or you can set it to NULL. A NULL value indicates the absence of a class part initialization method.

This class_part_initialize method is chained; therefore, the Intrinsics call the class_part_initialize method of the XmPrimitive widget before calling the class_part_initialize method of your own widget. The class_part_initialize method of XmPrimitive contains code that allows its subclasses to inherit the following features of XmPrimitive. This is not to say that all primitive widgets automatically inherit these methods; the code merely makes it possible for any primitive widget that wants to inherit these features to be able to do so.

  1. border_highlight method

  2. border_unhighlight method

  3. arm_and_activate method

  4. translations

    The class_part_initialize method of your own widget should provide the code that allows subclasses to inherit your widget's methods. For example, the ExmSimple widget allows its subclasses to inherit its DrawVisual and DrawShadow methods as follows:

    if (wc->simple_class.draw_visual == ExmInheritDrawVisual)
     wc->simple_class.draw_visual = sc->simple_class.draw_visual;
    if (wc->simple_class.draw_shadow == ExmInheritDrawShadow)
     wc->simple_class.draw_shadow = sc->simple_class.draw_shadow;

    Many Motif widgets use the class_part_initialize method to install traits. For example, the class_part_initialize method of ExmSimple uses the following code to install the XmQTcontainerItem trait:

    XmeTraitSet((XtPointer) wc, XmQTcontainerItem, (XtPointer)
    &simpleCIT);

    XmeTraitSet is a routine that installs traits. (See Chapter 5 for complete details.) If you install a trait in your widget's class_part_initialize method, then this trait is automatically installed in all subclasses of your widget.

    The class_part_initialize method of XmPrimitive installs the XmQTcareParentVisual trait and installs several undocumented traits.

  5. The class_inited Field

    All Motif widgets must set the value of this field to False.

    The initialize Field (Chained)

    The Intrinsics call your widget's initialize method when an application instantiates your widget. You typically specify one of the following for the initialize field:

    1. The name of your widget instance initialize method

    2. NULL, to indicate the absence of an initialize method

      Since the initialize method is chained, the Intrinsics will call the initialize method of the XmPrimitive widget before calling the initialize method in your own widget. ( Core does not provide an initialize method.) Broadly speaking, the initialize method of XmPrimitive does the following:

      1. Merges the keyboard traversal translations (specified in the translations field) with the regular widget translations (specified in the tm_table field). (See Chapter 7 for more details.)

      2. Helps implement the virtual key mechanism of Motif.

      3. Sets the values of the following two primitive flag variables to False: primitive.have_traversal and primitive.highlighted. Both variables are detailed later in this chapter.

      4. Validates the XmNnavigationType and XmNunitType resources.

      5. Initializes keyboard traversal.

      6. Establishes synthetic resources.

      7. Establishes a starting widget width or height if the user or application has not requested one . This is important for ensuring that window creation can happen safely whenever a subclass of XmPrimitive is realized.

      8. Creates the following three GCs: primitive.highlight_GC, primitive.top_shadow_GC, and primitive.bottom_shadow_GC.

        The code in the initialize method of your own widget should check resource values and perform other start-up tasks that are relevant to your widget's creation. If any resources are expecting representation type values, you can validate the representation type values with XmRepTypeValidValue. For example, the ExmSimple widget contains one resource ( ExmNsimpleShape) that expects an ExmRSimpleShape value. Therefore, the initialize method of ExmSimple validates the starting value of ExmNsimpleShape with the following code:

         if (!XmRepTypeValidValue (simpleShapeId,
                                 nw->simple.simple_shape, (Widget)nw))
        /* If the widget has been created without an appropriate starting
          value for XmNsimpleShape, force its starting value to ExmSHAPE_OVAL.
        */
         nw->simple.simple_shape = ExmSHAPE_OVAL;

      9. The initialize_hook Field (Chained)

        The initialize_hook field is obsolete. Motif ignores this value. Set it to NULL.

        The realize Field

        The realize field is responsible for creating the widget's window. You typically specify either

        1. XtInheritRealize, to inherit the realize method of your superclass

        2. The name of a realize method defined by your widget

          The realize method of XmPrimitive calls XtCreateWindow to generate a window. The window class of the created window will be InputOutput. The generated window will not propagate any button, key, or pointer motion events to its parent window(s). In order to inherit this code for your own widget, simply set the value of the realize field to XtInheritRealize. By so doing, your widget's window will behave like other Motif primitive windows.

          The Motif Style Guide does not demand that all windows conform to a certain standard. For that matter, the Motif Style Guide does not even insist that all windows be rectangular. Therefore, you are free to create your own realize method.

        3. The actions Field

          The actions field contains the name of the actions array. The actions array provides a correspondence between action names (as defined in the translations string) and action methods. For example, the ExmCommandButton demonstration widget defines the following actions array:

          /* Declare the actions array. */
          static XtActionsRec actions[] = {
           {"ExmCommandButtonEnter",           ExmCommandButtonEnter},
           {"ExmCommandButtonLeave",           ExmCommandButtonLeave},
           {"ExmCommandButtonArmAndActivate",  ExmCommandButtonArmAndActivate},
           {"ExmCommandButtonArm",             ExmCommandButtonArm},
           {"ExmCommandButtonActivate",        ExmCommandButtonActivate},
           {"ExmCommandButtonDisarm",          ExmCommandButtonDisarm}
          };

          The preceding actions array defines six actions.

          If your widget does not define any action methods, then you should set the actions field to NULL.

          (See Chapter 7 for more details about actions.)

          The num_actions Field

          The num_actions field holds the number of actions defined by the array in the actions field. If your widget does not provide an actions array, then you should specify 0 for the num_actions field. If your widget does provide an actions array, then you should use the XtNumber macro to count these actions. For example, the ExmCommandButton widget does provide an actions array, so its num_actions field looks as follows:

          /* num_actions */               
          XtNumber(actions),

          The resources Field

          If your widget defines new resources, then the resources field must contain the name of the resources array. If your widget does not define any new resources, specify NULL.

          (See Chapter 6 for information and recommendations.)

          The num_resources Field

          The num_resources field holds the number of resources defined by the array in the resources field. If your widget does not provide a resources array, then you should specify 0 for the num_resources field. If your widget does provide a resources array, then your widget should use the XtNumber macro to count these resources. For example, the ExmSimple widget does provide a resources array, so its num_resources field looks as follows:

          /* num_resources */               
          XtNumber(resources),

          The xrm_class Field

          Your widget must always specify NULLQUARK as the value of the xrm_class field.

          The compress_motion Field

          The compress_motion field requires a Boolean value. Setting this value to True eliminates certain redundant pointer motion events from the event queue. Setting this value to False imposes a performance penalty but produces more accurate pointer tracking. (See documentation on the Intrinsics for more complete information.)

          Motif makes no recommendation on the value of the compress_motion field. Within the standard Motif widget set, the value of the compress_motion field is generally True. The XmPrimitive widget sets this field to True.

          The compress_exposure Field

          The compress_exposure field requires a constant value. This value tells the Intrinsics how to respond to multiple exposure events. (See documentation on the Intrinsics for more complete information.)

          Motif makes no recommendation on the value of the compress_exposure field. The XmPrimitive widget sets this field to XtExposeCompressMaximal, with the XtExposeNoRegion modifier enabled.

          The compress_enterleave Field

          The compress_enterleave field requires a Boolean value. Setting this value to True means that the Intrinsics will ignore unimportant enter event/leave event pairs. (See documentation on the Intrinsics for more complete information.)

          Motif makes no recommendation on the value of the compress_enterleave field. However, most standard Motif primitive widgets (including the XmPrimitive widget itself) set this field to True.

          The visible_interest Field

          The visible_interest field requires a Boolean value. This value provides hints to the Intrinsics on the redisplay of partially exposed widgets. Motif does not layer any extra meaning on top of the standard Intrinsics meaning of this field.

          Motif makes no recommendation on the value of this field. However, every standard Motif widget specifies False for this field.

          The destroy Field (Chained)

          The Intrinsics automatically call your widget's destroy method when your widget goes out of scope or is explicitly destroyed. The destroy method is chained up from subclass to superclass; therefore, the destroy method of XmPrimitive will be called after any destroy method that your own widget supplies. The destroy method of XmPrimitive deallocates the following three graphics contexts:

          1. primitive.top_shadow_GC

          2. primitive.bottom_shadow_GC

          3. primitive.highlight_GC

            In addition, the destroy method of XmPrimitive deallocates all the widget traversal information held by this widget.

            If your widget provides a destroy method (as it typically should), make sure it deallocates all strings, fonts, GCs, and so on, that your widget allocates.

            If you do not want your widget to supply a destroy method, set the destroy field to NULL.

          4. The resize Field

            The Intrinsics automatically call the function specified in the resize field in response to a resize action from the parent widget. The XmPrimitive widget does not provide a resize method, so your widget cannot inherit from it.

            The resize method of your widget lays out the widget's visual components. One of the duties of the resize method is to determine what parts of the widget to display when there is not enough space to display everything. Chapter 12 details Motif's recommendations for handling this situation. Sample code that demonstrates these recommendations is available in the ExmSimple and ExmString widgets.

            The expose (Redisplay) Field

            The Intrinsics automatically invoke the expose method upon receiving an exposure event. The interpretation of exposure events can be altered by the values of the compress_exposure and visible_interest fields. (See documentation on the Intrinsics for details.)

            Your widget should set the expose field to one of the following:

            1. XtInheritExpose, to indicate that you are inheriting the expose method of your superclass. The XmPrimitive widget provides an expose method, and your primitive widget can inherit this method.

            2. The name of your widget's expose method. If you do provide an expose method, you should name it Redisplay.

              All standard Motif primitive widgets provide their own expose method. However, you should not feel obligated to write an expose method for your own widget. In fact, most of the primitive widgets in the Exm demonstration widget set inherit the expose method of ExmSimple.

              This Redisplay method of XmPrimitive examines the value of the Boolean field primitive.highlighted. If this field is set to True, Redisplay calls the border_highlight method of XmPrimitive. If this field is False, the expose method calls the border_unhighlight method of XmPrimitive. (The border_highlight and border_unhighlight methods are detailed later in this chapter.) In brief, border_highlight and border_unhighlight of XmPrimitive provide Motif-appropriate border highlighting and unhighlighting.

              Your Redisplay method should do the following:

              1. Call the method responsible for redrawing the visible portions of the widget. For example, the Redisplay method of ExmSimple calls the DrawVisual method. In ExmSimple, the DrawVisual method renders a geometric shape.

              2. Call the method responsible for drawing shadow, if appropriate. The Motif Style Guide should help you determine whether shadows are appropriate for your widget. For example, shadows are appropriate for the ExmSimple widget. Therefore, the expose method of ExmSimple calls its DrawShadow method. The DrawShadow method of ExmSimple calls XmeDrawShadow to draw a Motif-style shadow. See Chapter 17 for syntactic details on the XmeDrawShadow and XmeDrawPolygonShadow routines.

              3. Call the method responsible for handling border highlights, if appropriate. The Motif Style Guide should help you determine whether border highlights are appropriate for your widget. You may write your own method to handle border highlights; however, we recommend that you call the expose method of XmPrimitive instead.

                See Chapter 12 for more details on the expose method.

              4. The set_values Field (Chained)

                The Intrinsics automatically call the set_values method whenever an application calls XtSetValues to change any of the resources in your widget.

                You typically specify one of the following for the set_values field:

                1. The name of your widget's set_values method

                2. NULL, which symbolizes the absence of a set_values method

                  Most of the widgets you write will specify a set_values method.

                  Your widget's set_values method is responsible for validating changes to resource values. Your widget can call XmRepTypeValidValue to validate changes to representation type resources. (See Chapter 6 for details.)

                  The code in a set_values method is usually quite similar to the code in an initialize method.

                  The set_values method returns a Boolean value. The Intrinsics monitor this returned value. If the returned value is True, the Intrinsics automatically invoke the widget's expose (Redisplay) method. There are many reasons why widget redisplay is necessary. For example, one subtle reason is that a widget GC has changed.

                  The set_values method is chained. Therefore, the Intrinsics will call the set_values method of XmPrimitive prior to calling the set_values method of your own widget. The set_values method of XmPrimitive:

                  1. Validates changes to XmNnavigationType and XmNunitType.

                  2. Updates keyboard traversals.

                  3. Examines the primitive.shadow_thickness and primitive.highlight_thickness fields. If either field's value has changed, set_values sets its return value to True.

                  4. Examines the primitive.highlight_color and primitive.highlight_pixmap fields. If either field's value has changed, set_values destroys the existing primitive.highlight_GC and then creates a new one from the updated values. If either field's value has changed, set_values sets its return value to True.

                  5. Examines the primitive.top_shadow_color and primitive.top_shadow_pixmap fields. If either field's value has changed, set_values destroys the existing primitive.top_shadow_GC and then creates a new one from the updated values. If either field's value has changed, set_values sets its return value to True.

                  6. Examines the primitive.bottom_shadow_color and primitive.bottom_shadow_pixmap fields. If either field's value has changed, set_values destroys the existing primitive.bottom_shadow_GC and then creates a new one from the updated values. If either field's value has changed, set_values sets its return value to True.

                  7. Calls the border_unhighlight method when all of the following conditions are True:

                    1. The border highlight is drawn or the widget is insensitive.

                    2. The focus policy is XmImplicit.

                    3. The value of the XmNhighlightOnEnter resource changes from True to False.

                    4. The set_values_hook Field (Chained)

                      This is an obsolete field; Motif ignores its value. Your widget should set it to NULL.

                      The set_values_almost Field

                      The Intrinsics call the method named in the set_values_almost field when certain geometry requests cannot be fulfilled by the parent geometry manager.

                      You should probably set the set_values_almost field to one of the following:

                      1. The name of your widget's set_values_almost field.

                      2. XtInheritSetValuesAlmost, to inherit the set_values_almost method of your superclass.

                        The XmPrimitive widget itself sets the set_values_almost field to XtInheritSetValuesAlmost, meaning that it inherits the set_values_almost method of Core.

                        Motif makes no recommendations for this method. However, all standard Motif primitive widgets except XmLabel and XmFormlset this field to XtInheritSetValuesAlmost.

                      3. The get_values_hook Field (Chained)

                        The get_values_hook field holds the name of a method responsible for doing preprocessing on XtGetValues calls. If your widget has no need to do this, you should set the get_values_hook field to NULL. In fact, most standard Motif primitive widgets do set this field to NULL.

                        The get_values_hook field is chained; therefore, the Intrinsics will call the get_values_hook method of XmPrimitive prior to the get_values_hook method of your widget. The get_values_hook method of XmPrimitive implements synthetic resources for primitive widgets. (See Chapter 6 for details on synthetic resources.)

                        The accept_focus Field

                        Motif ignores the value of the accept_focus field; set it to NULL.

                        The version Field

                        The version field holds an enumerated constant pertaining to the compatibility of the Intrinsics themselves. The version field does not express any information regarding Motif compatibility, nor does Motif interpret the version field in any way.

                        Most widgets set this field to XtVersion. However, if you do not want your widget to check binary compatibility with future releases of the Intrinsics, set this field to XtVersionDontCheck. (See Chapter 15 for details on binary compatibility.)

                        The callback_private Field

                        Motif ignores the value of the callback_private field; you should set this field to NULL.

                        The tm_table Field

                        The tm_table field holds the primary translations string of your widget. Your widget should probably set this field to one of the following:

                        1. The name of your widget's tm_table translations string.

                        2. XtInheritTranslations, to inherit the tm_table translations of your superclass. The XmPrimitive widget does not provide any tm_table translations to inherit.

                          If your widget does not provide any translations, Motif recommends setting the tm_table field to XtInheritTranslations.

                          (See Chapter 7 for more details.)

                        3. The query_geometry Field

                          The Intrinsics call the query_geometry method when another widget (most likely the parent) or an application calls XtQueryGeometry to determine your widget's geometry preferences.

                          Your widget must specify one of the following in the query_geometry field:

                          1. The name of your widget's query_geometry method.

                          2. XtInheritQueryGeometry, to inherit the query_geometry method of your superclass. The XmPrimitive widget does not provide a query_geometry method to inherit.

                          3. NULL, which indicates the absence of a query_geometry method.

                            (See Chapter 12 for details on geometry management.)

                          4. The display_accelerator Field

                            Motif ignores the value of the display_accelerator field; set it to NULL.

                            The Base Class extension Field

                            Motif strongly recommends that you set the value of the extension field to NULL. By so doing, Motif will install the correct extension record for you at runtime.


                            [ Previous | Next | Contents | Glossary | Home | Search ]