### Direct Manipulation

Direct manipulation is a user interface technique that lets a user start application functions by manipulating objects. The user begins an action by moving the mouse pointer over an object and then pressing and holding down the drag mouse button (mouse button 2 is the default for OS/2) while dragging the selected object to a new location. The user then drops the object onto the new location by releasing the mouse button. For this reason, direct manipulation is also known as drag and drop.

Thus, the user can perform operations directly on objects that appear on the desktop or within an application.

Direct manipulation is not limited to objects in containers, as the object can be a text string in an entry field. Also, users can drag and drop an object onto a new location in the current window, onto another object in a window, or onto a different window.

Direct manipulation is used to move, copy, and link objects. Generally, move is the default operation and is accomplished through the use of the mouse button defined for drag and drop. Other operations can be specified with the additonal use of augmentation keys: the Ctrl key or a combination of the Shift and Ctrl keys.

To initiate a move operation, the user presses and holds the Shift key while moving the drag mouse button. The visual indication of this operation for OS/2 and Motif is the drag image. For Windows, the visual indication for move is the halftoning of the object.

To initiate a copy, the user presses and holds down the Ctrl key while pressing and moving the drag mouse button. The visual indication of this operation for OS/2 and Motif is the halftoning of the drag image. For Windows, the visual indication for copy is the halftoning of the object with the plus sign displayed in the lower-right corner.

Likewise, users can accomplish a link operation by pressing and moving the drag mouse button while pressing the Shift and Ctrl keys. The visual indication of this operation in OS/2 is a line that is drawn that connects the drag image with the object where the drag was initiated. For Windows, the visual indication is the halftoning of the object with the short cut arrow displayed in the lower-right corner.

Users can request help during a direct manipulation operation by pressing the help key F1. This displays help for the object a user is dragging over.

To cancel a direct manipulation operation, press the Esc key.

The Open Class Class Library provides four main classifications of objects to support direct manipulation:

- A drag item (IDMItem)
- A drag item provider (IDMItemProvider)
- A renderer (IDMSourceRenderer or IDMTargetRenderer)
- An event handler (IDMSourceHandler or IDMTargetHandler)

The collaboration of these objects allows the rendering from a source to a target location. Rendering is the process by which data is transferred from the source of a direct manipulation operation to a target. The following is an overview of the process:

1. A user initiates a drag request, which generates an event that is processed by the source handler.

   For Windows, this event needs to be generated. Windows leaves it up to the control to decide when a drag operation is occurring. This decision is usually made on a per control basis because Windows allows using the same mouse button, the left button by default, for selection and drag. IWindow::isDragStarting (Windows only) helps to detect a drag operation and is called for controls that have been enabled for drag through IDMHandler::enableDragFrom or IDMHandler::enableDragDropFor. After a control has been enabled for drag, IWindow::isDragStarting is called for every mouse button down, up, or move that is dispatched to the control. When a drag has been detected, the isDragStarting override should return true. The return value of true causes IDMHandler to send a WM_BEGINDRAG message and initiate the IDM classes to start the drag operation.

   Once the WM_BEGINDRAG message is generated, the IDM classes work the same on both the Windows and OS/2 platforms. OS/2 can generate the WM_BEGINDRAG message for you, because a different mouse button is used for selection and drag operations. Windows also offers you the option of initiating a drag with the right mouse button for non default drag and drops, which allows differentiating the drag and selection operations. IWindow has a default implementation of isDragStarting that tracks the left button state along with mouse move messages. If the left button down message is received and the mouse moves more than 2 pels before a left button up event is received, then a drag operation has occurred. If you need to support drag from a control that requires more elaborate drag conditions, override this member function and supply an implementation. You can use IWindow, IEntryField, IMLE and IContainerControl implementations of isDragStarting for examples.

2. The source handler uses the source window's attached drag item provider to request generation of source drag items.

   Drag items represent the objects that are the focus of the direct manipulation operation and provide access to the object's data. Drag item providers are designed to assist in the generation of drag items and bridge the gap between the drag items and the source and target handlers.

   When you use the IDMItemProviderFor template to instantiate the provider, the static function in the derived drag item class, generateSourceItems, is called. Alternatively, if the provider is instantiated from a derived drag item provider class, then the IDMItemProvider::provideSourceItems override is called.

3. Once the source drag items are generated, appropriate source renderers are selected.
4. When you enter a potential target window, an event is generated that is processed by the target handler.
5. The target handler uses the target window's attached drag item provider to request generation of target drag items.

   When you use the IDMItemProviderFor template to instantiate the provider, the target drag item constructor is called, as follows:

             IDMItem ( const Handle& item );

   Alternatively, if the provider is instantiated from a derived drag item provider class, then the IDMItemProvider::provideTargetItemFor override is called.

6. The target handler also uses the drag item provider to request additional verification support via the virtual function, IDMItemProvider::provideEnterSupport.
7. Once the target drag items are generated and verified, the appropriate target renderer is selected.
8. The drop is processed based upon the rendering mechanism and format, which is stored in the target renderer, and the data is subsequently transferred. The virtual function, IDMItem::targetDrop, is used to process the drop event.

Renderers encapsulate the various mechanisms and formats that are used for rendering and implement the logic that supports the mechanisms and formats (RMFs). Generally, a mechanism defines the method of data transfer, whereas the format identifies the format of the data. The Open Class Class Library's implementation groups the mechanisms and formats under one mechanism.

Target rendering transfers data from the source to the target. Because the source can package all the required transfer information when the drag operation begins, the target can complete the drop operation without further assistance from the source.

A good example of target rendering involves the use of the Open Class Class Library's process RMF. If the source and target are in the same process, the target directly accesses the source's data and subsequently renders the information as required.

On the other hand, source rendering occurs when the target requires additional information from the source in order to complete processing of the drop. The target issues the appropriate events to request the information from the source. A good example of source rendering involves the use of the User Interface Class Library's shared memory RMF. When the source and the target are in separate processes, the target can select this RMF that generates a shared memory buffer that, in turn, transfers the data between the source and target.

### Understanding Drag Items

Drag items are represented by objects of class IDMItem. Drag items encapsulate the logic that serves as the bridge between the context-insensitive handlers and renderers and the application-specific behavior of particular source and target windows. Thus, the drag items provide the application-specific semantics of the direct manipulation operation.

IDMItem is the base class that defines the general behavior of all direct manipulation items. The three derived classes provided by the Open Class Class Library provide specializations of the base class that represent the objects being dragged and dropped on specific controls.

The following classes are derived from IDMItem:

- IDMCnrItem
- IDMMLEItem
- IDMEFItem

### Understanding Drag Item Provider

The IDMItemProvider class is an extension of the IWindow class that provides direct manipulation functions. Objects of the IDMItemProvider class allow generic controls, such as an entry field, to generate context-sensitive drag items. For example, a container that contains customer objects can generate a "customer" item; a bitmap can provide an item that can extract the picture from a .BMP file.

The IDMItemProvider class also provides functions that deal with target entry and exit, as well as help. With IDMItemProvider::provideEnterSupport you can verify objects, using different schemes, when the object is over a potential target.

For example, if you want to restrict drops in an icon view container to the white space area of the container, you can use the provideEnterSupport function to determine if the pointing device is over either white space or an actual container object:

    IBase::Boolean CnrProvider::provideEnterSupport ( IDMTargetEnterEvent &event )
    {
      /***********************************************************************/
      /* Allow default verification to occur                                 */
      /***********************************************************************/
      if (Inherited::provideEnterSupport( event ))
      {
        /*********************************************************************/
        /* Prevent the drop if we're over a container object (icon view)     */
        /*********************************************************************/
        if (event.object())
        {
          event.setDropIndicator( IDM::notOk );
          return(false);
        }
        return(true);
      }
      return(false);
    }

Note: | The return value is not currently used to determine if a drop is allowed. Only the drop indicator is used to set the drop disposition.

Clipboard

Adding Clipboard Support
Using Default Direct Manipulation
Enabling Direct Manipulation
Adding Images to Drag Items

IDM
IDMImage
IDMItemProvider
IDMItemProviderFor
IDMRenderer
IDMSourceRenderer
IDMTargetRenderer
IDMEvent
IDMHandler
IDMItem
IDMOperation
IClipboard