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



Synthetic Resources

Widget writers can mark certain resources as synthetic resources. A synthetic resource can automatically convert a resource value between two formats: external format and internal format.

Users and applications specify resource values in external format. As a widget designer, you should pick an external format that makes it easy for a user or application to convey information. However, an easy format for a widget user or application programmer may be a cumbersome or inefficient format for the widget writer. Therefore, Motif provides a synthetic resources mechanism. This mechanism automatically converts cumbersome external formats to a more efficient internal format. A well-chosen internal format expedites processing of the data or reduces its storage requirements.

Synthetic resources are the domain of the widget writer. An application programmer or user need never know that synthetic resources exist.

Defining Synthetic Resources

Defining a synthetic resource is a four-step process:

  1. Define the synthetic resource inside the regular resources array.

  2. Define the synthetic resource inside the syn_resources array.

  3. Specify the name of the syn_resources array inside the class record.

  4. Provide the routines that convert values between external and internal formats.

  5. Step 1: Define the Synthetic Resource Inside the Regular resources Array

    The first step is to define the resource as you would define any Motif resource, synthetic or not. In other words, you specify a resource record inside the resources array. For example, following is the resource definition of a resource named XmNsomething:

    static XtResource resources[] =
    {
        ...
        {
            XmNsomething,
            XmCSomething,
            XmRHorizontalDimension,
            sizeof (Dimension),
            XtOffsetOf(WidgetRec, widget.something),
            XmRImmediate,
            (XtPointer)42
        },
        ...
    }

    Step 2: Define the Synthetic Resource Inside the syn_resources Array

    The second step is to generate a synthetic resource array. The base data type of the array is XmSyntheticResource. By convention, you should name the array variable syn_resources. Therefore, the framework of the synthetic resources array definition should appear as follows:

    static XmSyntheticResource syn_resources[] =
      {
       /* one or more synthetic resource records */
      }

    Each synthetic resource record contains the following five fields:

    1. The first field holds the resource name.

    2. The second field holds the size of the resource's value.

    3. The third field holds the offset of the resource within the class record.

    4. The fourth field holds the name of a function that converts from the resource's internal format to the resource's external format. The specified function must be declared as an XmExportProc conversion routine. This function is called when an application calls XtGetValues to get the value of the resource.

    5. The fifth field holds the name of a function that converts from the resources's external format to the resource's internal format. The specified function must be declared as an XmImportProc conversion routine. This function is called when the widget is created and when an application calls XtSetValues to modify the value of the resource.

      For example, following is a sample synthetic resource definition:

      static XmSyntheticResource syn_resources[] =
      {
        ...
        {  /* Here is a synthetic resource record. */
         XmNsomething,
         sizeof (ResourceDatatype),
         XtOffsetOf(WidgetRec, widget.something),
         FromInternalToExternalFormat,
         FromExternalToInternalFormat
        }, /* End of synthetic resource record. */
        ...
      };

      You can set either the fourth or fifth field to NULL. Doing so tells Motif that you will not be supplying part of the conversion process. For example, if the fourth field is set to NULL, then this widget is not supplying a function to convert the resource value from internal format to external format. If the fourth field is NULL, a call to XtGetValues returns the resource's value in internal format.

    6. Step 3: Specify the syn_resources Array Inside the Class Record

      You must specify the name of the synthetic resource array in the appropriate portion of the class record. You must also specify the number of synthetic resources. For example:

      /* syn_resources */              syn_resources,
      /* num_syn_resources */         
      XtNumber(syn_resources),

      Step 4: Provide the Conversion Routines

      The final step is to provide the synthetic resource conversion routines themselves. In some cases, you can use one of Motif's existing routines (such as, XmeFromHorizontalPixels). In other cases, you will have to write the synthetic resource conversion routines yourself. There are two kinds of conversion routines you can write:

      1. XmExportProc conversion routines, which convert a resource value from internal format to external format

      2. XmImportProc conversion routines, which convert a resource value from external format to internal format

        An XmExportProc conversion routine has the following prototype:

        void MyExportProcConversionRoutine(
                Widget     wid,
                int           offset,
                   XtArgVal     *value)

        wid
        Specifies the widget which is requesting a synthetic resource conversion.

        offset
        Specifies the offset of a synthetic resource field in the widget record.

        value
        Specifies a pointer to a resource value in internal format and returns a pointer to that resource value converted to external format.

        An XmImportProc conversion routine has the following prototype:

        XmImportOperator MyImportProcConversionRoutine(
           Widget        wid,
                   int      offset,
                   XtArgVal      *value)

        wid
        Specifies the widget which is requesting a synthetic resource conversion.

        offset
        Specifies the offset of a synthetic resource field in the widget record.

        value
        Specifies a pointer to a resource value in external format. If the XmImportProc conversion routine returns XmSYNTHETIC_LOAD, then value must return the input resource value converted to internal format.

        An XmImportProc conversion routine must return an XmImportOperator value, which is an enumerated type having the following possible values:

        1. XmSYNTHETIC_NONE, which means that the caller of the XmImportProc is not responsible for copying the converted value into the resource specified by offset.

        2. XmSYNTHETIC_LOAD, which means that the caller of the XmImportProc is responsible for copying the converted value into the resource specified by offset.

          Motif's synthetic resource mechanism is typically the caller of the XmImportProc. Therefore, if your XmImportProc conversion routine returns XmSYTHETIC_LOAD, Motif synthetic resource mechanism will take care of copying (and casting) value into the resource specified by offset.

        3. Distance Conversions

          The synthetic resource implementation is particularly helpful for converting resource values from real-world units (like millimeters) to pixels and back again.

          The Xlib and Xme drawing routines all expect pixel arguments. Unfortunately, pixels are not always a very handy unit for widget users to work in. One important problem with pixel units is that a pixel's size depends on the resolution of the screen.

          To solve this problem the Motif base classes XmPrimitive and XmManager both provide the XmNunitType resource. This resource holds the kind of units that a given distance or position is measured in. By default, the unit type is pixels. However, the application may specify a unit type of some real-world unit, like millimeters, instead. Any resource whose value symbolizes a size, position, or distance must be able to convert these real-world units to and from pixels.

          The synthetic resource mechanism provides a way to do these conversions. In fact, you do not even have to write conversion routines because Motif provides four unit conversion routines for you:

          1. XmeFromHorizontalPixels and XmeFromVerticalPixels convert values from any unit type named by the XmNunitType resource to pixels.

          2. XmeToHorizontalPixels and XmeToVerticalPixels convert values from pixels to the unit type named by the XmNunitType resource.

            For example, the ExmSimple widget uses all four of these routines in its syn_resources array as follows:

            static XmSyntheticResource syn_resources[] =
            {
                {
                     XmNmarginWidth,
                           sizeof (Dimension),
                           XtOffsetOf( ExmSimpleRec, simple.margin_width),
                           XmeFromHorizontalPixels,
                           XmeToHorizontalPixels
                },
                {
                           XmNmarginHeight,
                           sizeof (Dimension),
                     XtOffsetOf( ExmSimpleRec, simple.margin_height),
                     XmeFromVerticalPixels,
                           XmeToVerticalPixels
                },
            };

          3. How the Synthetic Resource Mechanism Works

            The synthetic resource mechanism is completely transparent to the widget writer. This is because the Motif base classes, XmPrimitive and XmManager, call the appropriate conversion routines at the appropriate times.

            For example, the class_part_initialize method of XmPrimitive and XmManager both contain code that initializes the synthetic resource. In other words, both base classes call the routine that converts all the synthetic resource values from external to internal format Similarly, both base classes contain code in their set_values routines to call the external to internal format conversion routine whenever one of the resource values is changed. Finally, both base classes contain code in their get_values_hook routines to call the internal-to-external format conversion routine whenever an application requests the resource value.

            Since the class_part_initialize, set_values, and get_values_hook methods are all chained, these conversion routines are automatically called for all primitive and manager widgets.


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