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



Overview of Implementing UTM

Suppose you want the widget you are writing to support data transfer. To implement data transfer by using UTM, you must do the following:

  1. Decide which data transfer mechanism(s) your widget will support. For example, perhaps your widget will support both the primary and clipboard transfers. Supply translations appropriate for these data transfer mechanisms.

  2. Write action methods for these translations; have these action methods call the appropriate UTM Xme set-up routines.

  3. Install the XmQTtransfer trait on your widget.

  4. Provide a convertProc trait method if your widget is to be a source for data transfer. Source widgets must support the XmNconvertCallback resource.

  5. Provide a destinationProc trait method if your widget is to be a destination for data transfer. Destination widgets must support the XmNdestinationCallback resource.

  6. Provide a transfer procedure if your widget is to be a destination for data transfer.

    This section details each of these steps. Throughout this section and the remainder of the chapter, we will examine how the ExmStringTransfer widget implements UTM. The ExmStringTransfer demonstration widget is a subclass of ExmString. The only feature that ExmStringTransfer layers on top of ExmString is its support of the following three data transfer mechanisms:

    1. Primary

    2. Clipboard

    3. Drag and drop

      ExmStringTransfer gives us an excellent opportunity to isolate the code that implements UTM.

      ExmStringTransfer has two important limitations. First, ExmStringTransfer does not let users transfer portions of the displayed text. In other words, a user may only transfer the entire contents of the ExmStringTransfer widget. By contrast, a more powerful widget such as XmText lets users copy a selected word, line, paragraph, and so forth.

      Second, ExmStringTransfer only knows how to do copy operations; it cannot do a move operation. In fact, when ExmStringTransfer is a destination, the incoming string will overwrite any existing displayed string.

      The sample application stored in directory demos/programs/Exm/app_in_c contains two ExmStringTransfer widgets. You might want to build this application and experiment with it. For example, try to copy data from one ExmStringTransfer widget to another. Then, try to copy text from a widget in another application to one of the ExmStringTransfer widgets.

    4. Supply Appropriate Translations

      You must decide what data transfer mechanisms your widget will support. Ideally, your widget should support as many data transfer mechanisms as possible. Writing a widget that supports multiple data transfer mechanisms is only slightly more time consuming than writing a widget that supports only one data transfer mechanism. Most of the data transfer code is independent of a particular form of data transfer.

      You might be writing a read-only widget. In other words, the user is not allowed to transfer data into the widget. For these widgets, you need only supply the source side of data transfer; you can omit the destination side.

      One way to help you decide what data transfer mechanisms your widget should support is to examine how the widgets in the Motif toolkit support data transfer. (By the way, as of Motif Release 2.0, all the widgets in the Motif toolkit use UTM to implement data transfer.) Table 10-2 summarizes the data transfer methods supported in the standard widget set. When an entry says "Source only" or "Drag only," it means that a user can copy data in this widget but cannot cut data out of it or paste data into it. For example, a user can copy text from an XmLabel to an XmText widget but cannot copy text from an XmText to an XmLabel widget.

      Table 22. Data Transfer in the Standard Widget Set

      Widget Primary Secondary Clipboard Drag and Drop
      XmCascadeButton Yes (Source only) No No Yes (Drag only)
      XmCascadeButtonGadget Yes (Source only) No No Yes (Drag only)
      XmDrawnButton Yes (Source only) No No Yes (Drag only)
      XmContainer Yes No Yes Yes
      XmLabel No No No Yes (Drag only)
      XmLabelGadget No No No Yes (Drag only)
      XmList Yes (Source only) No Yes (source only) Yes (Drag only)
      XmPushButton Yes (Source only) No No Yes (Drag only)
      XmPushButtonGadget Yes (Source only) No No Yes (Drag only)
      XmScale No No No Yes (Drag only)
      XmText Yes Yes Yes Yes
      XmTextField Yes Yes Yes Yes
      XmToggleButton Yes (Source only) No No Yes (Drag only)
      XmToggleButtonGadget Yes (Source only) No No Yes (Drag only)

      Users trigger data transfer by pressing keys or mouse buttons. Your widget must supply data transfer translations compatible with the Motif Style Guide.

      Widgets typically provide two different kinds of translations to support data transfer.

      The first kind of data transfer translation allows the user to select the data to be transferred. For example, the XmText widget provides several translations that allow a user to select different subsets of the displayed text. These subsets range from one character to the entire text. By contrast, XmLabel does not allow a user to select a portion of its displayed text; the user can only select the entire displayed text.

      In addition to providing selection translations, your widget must also supply translations that let the user initiate and complete the data transfer. For example, if a widget is to support drag and drop, the widget must supply a translation that allows the user to mark the start of the drag operation. (Typically, the user starts a drag operation with a Button2 or Button2Press event.) The four different kinds of data transfer each require different translations.

      The easiest way to supply appropriate Motif translations for your widget is to copy the data translations of the standard Motif widget that is most similar to your own. Translations for standard Motif widgets are documented in the Motif Programmer's Reference.

      Write Actions for These Translations

      Your widget must provide actions that respond to the user's data transfer request. These action methods have to call the appropriate UTM Xme set-up routine. The routine your action calls depends on the type of data transfer, and on whether the action method is for the source side of the transfer or the destination side of the transfer.

      If you are writing an action method that represents the source side of a data transfer, the action method must call one of the following routines:

      1. XmePrimarySource

      2. XmeSecondarySource

      3. XmeClipboardSource

      4. XmeDragSource

        For example, suppose a widget is to serve as a source for a clipboard transfer. This widget must respond to a selection translation by calling XmeClipboardSource.

        Broadly speaking, each of the preceding Xme routines makes the following sequence of calls:

        1. It calls the application's XmNconvertCallback procedures, if any.

        2. It calls the widgets's convertProc trait method.

          Actions in destination widgets must call one of the following routines:

          1. XmePrimarySink

          2. XmeSecondarySink

          3. XmeClipboardSink

          4. XmeDragSink

            For example, suppose a widget is to serve as a destination for a clipboard transfer. When the user triggers a clipboard paste, the clipboard paste action must call XmeClipboardSink.

            Broadly speaking, each of the preceding four routines trigger the following sequence of calls:

            1. It calls the widget's destination pre-hook procedure, if any.

            2. It calls the application's XmNdestinationCallback procedures, if any.

            3. It calls the widget's destinationProc trait method.

              The procedures and callbacks are described later in this section.

            4. Install The XmQTtransfer Trait

              Your widget must install the XmQTtransfer trait in order to support UTM data transfers.

              Your widget can install XmQTtransfer as it would install any trait; namely by calling XmeTraitSet. Typically, the call is made from a class_part_initialize method.

              Widgets capable of acting as a source for data transfer must provide a convertProc trait method. Widgets capable of acting as a destination for data transfer must provide at least a destinationProc trait method. Frequently, a widget will be both a source and a destination. In this case, your widget must supply both trait methods. Destination widgets may optionally also provide a destinationPreHookProc trait method.

              For example, the ExmStringTransfer widget installs the XmQTtransfer trait as part of its ClassPartInitialize method. The code that does the installation is as follows:

              ClassPartInitialize(WidgetClass widgetclass)
              {
                XmeTraitSet((XtPointer) widgetclass, XmQTtransfer, (XtPointer)
                            &StringTrT);
              }

              where the StringTrT variable is declared earlier in the StringTrans.c file as follows:

              static XmConstXmTransferTraitRec StringTrT = {
                0,                                           /* version */
                (XmConvertCallbackProc) ConvertProc,         /* convertProc */
                (XmDestinationCallbackProc) DestinationProc, /* destinationProc */
                NULL,                                        /*no
              destinationPreHookProc */
              };

              Supply a convertProc Trait Method

              Source widgets must supply a convertProc (convert procedure) trait method. The convertProc method is one of the trait methods of the XmQTtransfer trait. (See Chapter 18 for complete syntactic details on the XmQTtransfer trait.) UTM automatically calls convertProc whenever an object (typically, a destination widget) requests a conversion from the widget.

              The convertProc has the same prototype as any Intrinsics callback. Therefore, the third argument to convertProc is call_data. UTM will pass an XmConvertCallbackStruct to the call_data argument. The XmConvertCallbackStruct contains all the raw data required for the conversion. For example, the targets member of this structure contains the name of the target atom that the destination procedure wants converted.

              Your convertProc must respond to the following two general kinds of requests:

              1. A request for the list of targets supported by your widget. For example, the requestor may ask your convertProc for TARGETS.

              2. A request to convert the selection to a specific target. For example, the requestor may ask your convertProc to convert the selection to a COMPOUND_TEXT format.

                Later on in this chapter, we will discuss the specific targets your widget should support.

              3. Supply a destinationProc Trait Method

                Your widget must supply a destinationProc (destination procedure) trait method in order to serve as a destination widget in a data transfer. The destinationProc trait method is one of the trait methods of the XmQTtransfer trait. (See Chapter 18 for complete syntactic details on the XmQTtransfer trait.) UTM automatically calls destinationProc whenever a user requests that data be transferred to the destination widget. The destinationProc trait method is responsible for requesting data from the source widget and for pasting this data into the destination widget. However, the destinationProc trait method will ask a transfer procedure to take over some of these responsibilities.

                UTM calls destinationProc after calling any XmNdestinationCallback procedures defined by the application. The toolkit passes destinationProc an XmDestinationCallbackStruct structure. This structure contains all the fields necessary to make requests to the source widget.

                The destinationProc trait method should typically call XmTransferValue to request a conversion from the source widget XmTransferValue automatically calls the source widget's convertProc. When the convertProc finishes, XmTransferValue typically calls the destination widget's transfer procedure. The name of the transfer procedure is identified by the third argument to the XmTransferValue call.

                The destinationProc trait method can terminate a data transfer by calling XmTransferDone.

                XmTransferValue, together with XmTransferDone, form the UTM replacements for the following older calls:

                1. XtGetSelectionValue

                2. XtSetSelectionValue

                3. XmClipboardStartRetrieve

                4. XmClipboardRetrieve

                5. XmClipboardEndRetrieve

                6. XmDropTransferStart

                7. XmDropTransferAdd

                8. Supply a Transfer Procedure

                  If you are writing a destination widget, you will probably have to write one or more transfer procedures. UTM calls a transfer procedure when the convertProc trait method finishes the conversion. UTM passes the transfer procedure a pointer to an XmSelectionCallbackStruct. (See the XmTransferDone(3) reference page of the Motif Programmer's Reference for details on this structure.) The value member of XmSelectionCallbackStruct holds the selection converted to the target that the destination widget has requested. The target procedure will take that converted target and paste it into the destination widget.


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