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



The CoreClassPart Structure

Your manager widget must contain a class record. The first portion of the class record is a CoreClassPart structure. For example, following is the CoreClassPart structure of the ExmGrid widget:

externaldef(exmgridclassrec) ExmGridClassRec exmGridClassRec =
{
  {                     /* core_class */
    /* superclass */                 (WidgetClass)
&xmManagerClassRec,
    /* class_name */                 "ExmGrid",
    /* widget_size */                sizeof(ExmGridRec),
    /* class_initialize */           NULL,
    /* class_part_initialize */      ClassPartInitialize,
    /* class_inited */               FALSE,
    /* initialize */                 Initialize,
    /* initialize_hook */            NULL,
    /* realize */                    XtInheritRealize,
    /* 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 */                    NULL,
    /* 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,
  },

The following subsections explain what Motif widget writers need to know about these fields.

The superclass Field

The first field of the CoreClassPart structure is the superclass field. For this field, you must specify the name of the class record of your widget's immediate superclass. For example, if your widget's immediate superclass is XmManager, the superclass field will look as follows:

/* superclass */                 (WidgetClass)
&xmManagerClassRec,

The class_name Field

The class_name field holds a string representing the name of the class; for example:

/* class_name */                 "ExmGrid",

Motif will not make any attempt to interpret the characters in the string. The string can be any length, and can be composed of alphanumeric character, hypens, and underbars.

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 manager widgets holds the size of the full instance record. For example, the full instance record of the ExmGrid demonstration widget is named ExmGridRec; therefore, the Core class record of ExmGrid defines the widget_size field as follows:

/* widget_size */               
sizeof(ExmGridRec);

The class_initialize Field

The Intrinsics call the class_initialize method only once, at the first instantiation of a widget of this class. You can set the class_initialize field to one of the following:

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

  2. NULL, to indicate the absence of a class initialization method. (About half the standard Motif manager widgets set this field to NULL.)

    Motif makes no requirements of the code in class_initialize methods. However, Motif recommends registering any new representation types inside the class_initialize method. (See Chapter 6 for details.)

  3. The class_part_initialize Field (Chained)

    The Intrinsics call the class_part_initialize method at the first instantiation of a widget of this class or of a subclass of this class. You can set the class_part_initialize field to one of the following:

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

    2. NULL, indicating the absence of a class_part_initialize method.

      The class_part_initialize method is chained; therefore, the Intrinsics call the class_part_initialize method of Core, Composite, Constraint, and XmManager before calling the class_part_initialize method of your own widget. (See documentation on the Intrinsics for information on the class_part_initialize methods of Core, Composite, and Constraint.) The class_part_initialize method of XmManager does the following:

      1. If your widget does not specify a Composite class extension record, XmManager creates one for you by copying the Composite class extension record of your widget's superclass.

      2. If your widget does not specify an XmManager class extension record, XmManager creates one for you by copying the XmManager class extension record of your widget's superclass.

      3. Initializes synthetic resource management

      4. Establishes the class translations field, if your widget specifies XtInheritTranslations

        Motif makes no requirements of the code in your widget's class_part_initialize method. However, most Motif widgets use this method to install traits. (See Chapter 5 for details on installing traits.)

      5. The class_inited Field

        Motif widgets must always set the value of the class_inited field to False.

        The initialize Field (Chained)

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

        1. The name of your initialize method

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

          The initialize method is chained; therefore, the Intrinsics call the initialize method of the Core, Composite, Constraint, and XmManager widgets before calling the initialize method of your own widget. (See documentation on the Intrinsics for details on the initialize method of Core, Composite, and Constraint.) The initialize method of XmManager does the following:

          1. Initializes values for certain instance data members of XmManager.

          2. Validates the XmNnavigationType, XmNstringDirection, and XmNunitType resources.

          3. Merges the keyboard traversal translations (specified in the translations field) with the regular widget translations (specified in the tm_table field). The initialize method places the traversal translations at the top of the translations table. Therefore, if a keyboard traversal translation and a regular widget translation both define an action for the same virtual key, then the action of the keyboard traversal translation takes precedence.

          4. Initializes keyboard traversal.

          5. Establishes synthetic resources.

          6. Creates four GCs--manager.highlight_GC, manager.top_shadow_GC, manager.bottom_shadow_GC, and manager.background_GC--by calling GC creation methods stored in XmManager.

          7. Provides a mechanism for automatic inheritance of accelerators.

            The code in your own initialize method should check resource values and perform other start-up tasks relevant to your widget's creation. You can find a sample initialize method for a manager widget inside the Grid.c file.

          8. The initialize_hook Field (Chained)

            The initialize_hook field is obsolete. Motif ignores the stored value of this field; set it to NULL.

            The realize Field

            The realize field holds the name of the method that is responsible for creating the widget's window. If you want a standard Motif manager window, you should inherit the realize method of the XmManager widget by setting the realize field to XtInheritRealize.

            The realize method of XmManager calls XtCreateWindow to create a window. It is impossible for the width or height of the created window to be 0. Therefore, if the widget does not yet have a width or height, the realize method of XmManager forces the width or height to 1 pixel.

            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).

            The default windows for managers and primitives use bit gravity differently. Default manager windows set bit gravity to NorthWest, while default primitive windows take the default bit gravity, ForgetGravity.

            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.

            The actions Field

            Specify the name of the array that holds the actions methods defined by your widget. (See Chapter 7 for details on 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, specify the name of the resources array. If your widget does not define new resources, specify NULL.

            Your widget will automatically inherit the resources of its superclasses. (See Chapter 6 for more details on resources.)

            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 ExmGrid 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 slight performance penalty but produces more accurate pointer tracking. (See documentation on the Intrinsics for more details.)

            Every standard Motif manager widget sets the compress_motion 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 details.)

            Motif makes no recommendations on the value of the compress_exposure field. The XmManager widget sets this field to XtExposeCompressMaximal.

            Managers that may have gadget children should not use the XtExposeNoRegion flag.

            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 details.)

            Motif makes no recommendations on the value of the compress_enterleave field. However, most standard Motif manager widgets, including the XmManager widget, 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 use of this field.

            Motif makes no recommendations on the value of this field. However, every standard Motif widget sets this field to False.

            The destroy Field (Chained)

            The Intrinsics automatically call the destroy method when the widget is explicitly destroyed. You must specify one of the following:

            1. The name of your destroy method

            2. NULL, to indicate the absence of a destroy method

              The destroy field is chained in subclass-to-superclass order; therefore, the destroy method of XmManager will be called after any destroy method that your own widget supplies. The destroy method of XmManager deallocates the following four graphics contexts:

              1. manager.top_shadow_GC

              2. manager.bottom_shadow_GC

              3. manager.highlight_GC

              4. manager.background_GC

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

                If your widget provides a destroy method, make sure it deallocates all strings, fonts, GCs, and so forth, allocated by your widget.

              5. The resize Field

                The Intrinsics automatically call the method specified in the resize field in response to a resize event. The XmManager widget does not provide a resize method, so your widget will not be able to inherit a resize method from XmManager. (See Chapter 12 for more information on geometry management.)

                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 complete 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. However, the XmManager widget does not provide an expose method, so your widget cannot inherit from it.

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

                  All standard Motif manager widgets except XmManager provide their own expose method. Motif requires that your Redisplay method (or the Redisplay method your widget inherits) call XmeRedisplayGadgets in order to pass exposure events down to gadget children. (See Chapter 17 for syntactic details on XmeRedisplayGadgets.)

                3. The set_values Field (Chained)

                  You can either specify the name of your widget's set_values method or you can specify NULL, which symbolizes the absence of a set_values method. Most of the widgets you write will specify a set_values method.

                  When an application calls XtSetValues to change any of the resource values in your widget, the Intrinsics automatically call the 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 could benecessary. 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 XmManager prior to calling the set_values method of your own widget. The set_values method of XmManager does the following:

                  1. Validates changes to XmNinitialFocus, XmNnavigationType, XmNunitType, and XmNstringDirection.

                  2. Updates keyboard traversals.

                  3. Examines the manager.highlight_color and manager.highlight_pixmap fields. If either field's value has changed, set_values destroys the existing manager.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.

                  4. Examines the manager.top_shadow_color and manager.top_shadow_pixmap fields. If either field's value has changed, set_values destroys the existing manager.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.

                  5. Examines the manager.bottom_shadow_color and manager.bottom_shadow_pixmap fields. If either field's value has changed, set_values destroys the existing manager.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.

                  6. Examines the values of the manager.background_pixel or manager.background_pixmap fields. If either field's value has changed, set_values destroys the existing manager.background_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. Checks the values of the GCs of any gadget children of the widget.

                  8. Determines if any visual changes have occurred in your manager widget. If any have, the set_values method calls the redraw trait method of any child widget that has the XmQTcareParentVisual trait installed. If your manager widget needs to be redrawn as a result of this call, set_values sets its return value to True.

                  9. The set_values_hook Field (Chained)

                    The set_values_hook field is obsolete. Motif ignores its value; 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 geometry manager. To inherit the set_values_almost method of your superclass, specify XtInheritSetValuesAlmost. The XmManager widget itself sets the set_values_almost field to XtInheritSetValuesAlmost, so it inherits this field from the Intrinsics widgets.

                    Motif makes no requirements for this method. However, all the standard Motif manager widgets set this field to XtInheritSetValuesAlmost. (See Chapter 12 for details on Motif geometry management.)

                    The get_values_hook Field (Chained)

                    The get_values_hook field holds the name of a method responsible for returning resource values from any subparts of your widget. If your widget has no need to do this, it should set the get_values_hook field to NULL.

                    The get_values_hook field is chained; therefore, the Intrinsics will call the get_values_hook method of XmManager prior to the get_values_hook method of your widget. The get_values_hook method of XmManager implements synthetic resources on manager widgets.

                    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 seek to 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; set it to NULL.

                    The tm_table Field

                    You should specify one of the following three possible values for the tm_table field:

                    1. XtInheritTranslations, to inherit the tm_table string of your widget's immediate superclass.

                    2. The name of your own tm_table string to provide tm_table translations specific to your widget.

                    3. NULL, to indicate the absence of any tm_table string translations.

                      If your tm_table field is set to XtInheritTranslations and your widget's immediate superclass is XmManager, then your widget will inherit the following tm_table translations:

                      <BtnMotion>
                      : ManagerGadgetButtonMotion()\n\
                      c<Btn1Down>
                      : ManagerGadgetTraverseCurrent()\n\
                      ~c<Btn1Down>
                      : ManagerGadgetArm()\n\
                      ~c<Btn1Down>
                      ,~c<Btn1Up>
                      : ManagerGadgetActivate()\n\
                      ~c<Btn1Up>
                      : ManagerGadgetActivate()\n\
                      ~c<Btn1Down>
                      (2+): ManagerGadgetMultiArm()\n\
                      ~c<Btn1Up>
                      (2+): ManagerGadgetMultiActivate()\n\
                      <Btn2Down>
                      : ManagerGadgetDrag()\n\
                      :<Key>
                      osfActivate: ManagerParentActivate()\n\
                      :<Key>
                      osfCancel: ManagerParentCancel()\n\
                      :<Key>
                      osfSelect: ManagerGadgetSelect()\n\
                      :<Key>
                      osfHelp: ManagerGadgetHelp()\n\
                      ~s ~m ~a <Key>
                      Return: ManagerParentActivate()\n\
                      ~s ~m ~a <Key>
                      space: ManagerGadgetSelect()\n\
                      <Key>
                      : ManagerGadgetKeyInput()";

                      Suppose you provide your own tm_table string rather than inherit the tm_table string of XmManager. If you want your manager widget to handle the default button events correctly, then your tm_table string should be a superset of the activation translations of XmManager. That is, your tm_table string should contain the following:

                      :<Key>
                      osfActivate: ManagerParentActivate()\n\
                      :<Key>
                      osfCancel: ManagerParentCancel()\n\
                      ~s ~m ~a <Key>
                      Return: ManagerParentActivate()\n\

                      If you want your manager widget to support gadgets properly, then the tm_table string should specify all of the translations used by XmManager.

                      (See Chapter 7 for more details on translations.)

                    4. The query_geometry Field

                      When your manager is itself a child of another manager widget, the parent manager widget will call your widget's query_geometry method to request your widget's geometry preferences.

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

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

                      2. XtInheritQueryGeometry to inherit the query_geometry method of your widget's immediate superclass.

                        The XmManager widget does not provide a query_geometry method. Therefore, your widget cannot inherit from it.

                      3. NULL, to indicate the absence of a query_geometry method. Motif does not recommend this.

                        (See Chapter 12 for details on Motif geometry management.)

                      4. The display_accelerator Field

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

                        The extension Field

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


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