Important: The information in this document is obsolete and should not be used for new development.
Performing a Drop Operation
This section describes how the objects in a MacApp application work together with the Macintosh Drag Manager to perform a drop operation. The discussion refers to the steps of a drop operation--those steps are shown in Figure 9-3.Registering to Receive a Drop
Objects in the application register with other objects and with the Drag Manager to indicate that they can receive dropped data. A droppable view registers with its window object, and the window registers with the global drag session object. The drag session object installs any callback routines needed by the Drag Manager to let the application handle drag tracking and receive dropped data.There is no need for a view to register the fact that it can initiate a drag.
The following routines perform drop registration and install Drag Manager callback routines:
- For a view that adds a
TDragDropBehaviordefinition to its view resource definition to specify that the view accepts drops, the view'sDoPostCreatemethod automatically calls the window object'sRegisterDroppableViewsmethod to register the view.To programmatically register a view with its window, you call the view's
SetDroppablemethod.- A window object's
RegisterDroppableViewsmethod adds the passed view to its list of droppable views, then calls the global drag session object'sRegisterDroppableWindowmethod. That method calls the Drag Manager routinesInstallTrackingHandlerandInstallReceiveHandlerto install callback routines.
Reacting to Drag Manager Callbacks
While a user continues a drag operation, the Drag Manager makes periodic calls toTDragDropSession::DragTrackingHandlerGlue, the application's callback routine for tracking a drag. The Drag Manager passes a message that indicates the state of the drag--that is, whether it's entering or leaving the drag handler or whether it's entering, leaving, or tracking in a drag window.The
DragTrackingHandlerGluemethod passes the message on in a call to theTDragDropSession::DragTrackingHandlermethod, which calls an appropriate method of the drag session object, based on the message.Determining the Target of a Drop
When a user drags over an application window, the Drag Manager calls on the application to determine whether the drag is above a droppable view. The Drag Manager passes the message for tracking in a window, causing theDragTrackingHandlermethod to call the drag session object'sHandleTrackInWindowmethod. That method calls the window to supply from its list of droppable views a target view that can accept the current dragged data.For each of its droppable views, the window's
MouseToDropTargetmethod calls theWillAcceptDropmethod, which iterates over the drag items in the current drag. A view normally accepts a drop only if it can accept at least one flavor for each drag item in the drag data. For efficiency, the window caches information about whether a specific view can accept the current drag, so it doesn't have to be recalculated if the user drags off a view and back over it again. For more information about accepting a drop, see "When a View Should Accept a Drop" and "CDragItemIterator" on page 266.If the window contains a view that can accept the drop, the drag session's tracking handler calls methods of the view to provide visual feedback, as described in the next section.
Providing Visual Feedback for a Drop
Depending on the type of view, visual feedback may include highlighting a region of the view and indicating the current insertion point for the data to be dropped. Step 5 in Figure 9-3 (page 259) shows the highlighted drop-target view and the insertion point for a dragged text selection.When the window returns a target view willing to accept the drag, the drag session object, in response to callbacks from the Drag Manager, calls the following
TViewmethods to provide visual feedback and track the drag operation:
DoDragEnter- Notifies the view that it has been entered by a drag. The view can set up any internal data it uses to track a drag. This may involve initializing variables that track the drop insertion location.
DoMakeDropHiliteRegion- Creates and returns a highlight region to represent the target of the drag. Unlike other drag-and-drop methods that supply regions,
DoMakeDropHiliteRegionreturns the region in global screen coordinates. TheTViewmethodLocalToGlobalRegionis provided to convert a region from local to global coordinates.DoDragWithin- Called repeatedly as the user drags within the view. Allows view to update any visual tracking indicators it provides. This may involve blinking and relocating an insertion point, highlighting a grid cell, or providing other feedback.
DoDragLeave- Called when the drag exits the view, it erases any visual tracking information that has been drawn and frees any memory allocated during tracking. If the user releases the mouse while over a view that is tracking,
DoDragLeaveis not called until after the view has been given a chance to extract data from the drag operation, as described in "Creating Drag-and-Drop Commands" below.Performing a Drop
When the user releases the mouse while dragging over a view that has agreed to accept a drag, the Drag Manager calls the drag session object'sDragReceiveHandlerGluemethod, which in turns calls theDragReceiveHandlermethod. TheDragReceiveHandlermethod determines whether the dragged data should be moved or copied. The logic used to determine whether to treat the drag as a move or copy is described in the section "Drag Copy Versus Drag Move" on page 268.Once the
DragReceiveHandlermethod has determined whether the drag is a copy or move, it calls theTViewmethodDoMakeDragDropCommand, passing a command number ofcDrag,cDrop, orcDragMove:
- If the operation is a drag copy,
DragReceiveHandlercalls theDoMakeDragDropCommandmethod of the destination view, passing the command numbercDrop("drop the data into this view").- If the operation is a drag move between views within the application,
DragReceiveHandlercalls theDoMakeDragDropCommandmethod for the destination view, passing the command numbercDrop, and for the source view, passingcDrag("drag the data out of this view"). The commands are linked and, as a result, performing or undoing the command changes both the source and target view.- If the operation is a drag move to another application (including a drag to the Trash),
DragReceiveHandlercalls theDoMakeDragDropCommandmethod for the source view only, passing the command numbercDrag.- If the source and target are the same view and the operation is a move,
DragReceiveHandlercalls theDoMakeDragDropCommandmethod for the view, passing the command numbercDragMove("move the dragged data within this view").
Creating Drag-and-Drop Commands
The previous section describes how a view'sDoMakeDragDropCommandmethod is asked to create a drag-and-drop command based on the command number passed to it.When a view is asked to create acDragcommand, it creates and returns a command whoseDoItmethod removes the dragged data from the view. The command'sUndoItmethod reinserts the data, and itsRedoItmethod removes the data again.When a view is asked to create a
cDropcommand, it creates and returns a command whoseDoItmethod inserts the dropped data into the view. The command'sUndoItmethod removes the inserted data, and itsRedoItmethod inserts the data again.
When a view is asked to create a
- IMPORTANT
- A view's
DoMakeDragDropCommandmethod must pull all the necessary data out of the current drag before returning, because drag item data becomes invalid as soon as a drag operation is complete.![]()
cDragMovecommand, it creates and returns a command whoseDoItmethod moves the selected data from its current location in the view to the location specified by the drop. TheUndoItmethod reverses the move and theRedoItmethod restores it.Many current MacApp applications already implement commands that perform data insertion or removal. It should be possible to reuse these existing commands, with little modification, to perform the actual work of a drag, drop, or move operation.
Posting the Command
A view is not responsible for posting a command it creates. TheDragReceiveHandlermethod posts commands as necessary.Linked Commands
A drag move operation that causes data to be moved between views has the effect of causing both the source view and the destination view to create a command. TheDragReceiveHandlermethod then links the two commands together. MacApp'sTCommandHandlerclass automatically manages operations on linked commands. Doing, undoing, redoing, or committing either command causes the linked command to be done, undone, redone, or committed as well.When MacApp performs a command, it checks the command's
fValidationFailedfield. If either command of a linked pair of commands fails to complete execution because of a validation error, MacApp ensures that both commands are left undone and that the Clipboard is also left in its
previous state.