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
TDragDropBehavior
definition to its view resource definition to specify that the view accepts drops, the view'sDoPostCreate
method automatically calls the window object'sRegisterDroppableViews
method to register the view.To programmatically register a view with its window, you call the view's
SetDroppable
method.- A window object's
RegisterDroppableViews
method adds the passed view to its list of droppable views, then calls the global drag session object'sRegisterDroppableWindow
method. That method calls the Drag Manager routinesInstallTrackingHandler
andInstallReceiveHandler
to 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
DragTrackingHandlerGlue
method passes the message on in a call to theTDragDropSession::DragTrackingHandler
method, 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 theDragTrackingHandler
method to call the drag session object'sHandleTrackInWindow
method. 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
MouseToDropTarget
method calls theWillAcceptDrop
method, 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
TView
methods 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,
DoMakeDropHiliteRegion
returns the region in global screen coordinates. TheTView
methodLocalToGlobalRegion
is 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,
DoDragLeave
is 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'sDragReceiveHandlerGlue
method, which in turns calls theDragReceiveHandler
method. TheDragReceiveHandler
method 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
DragReceiveHandler
method has determined whether the drag is a copy or move, it calls theTView
methodDoMakeDragDropCommand
, passing a command number ofcDrag
,cDrop
, orcDragMove
:
- If the operation is a drag copy,
DragReceiveHandler
calls theDoMakeDragDropCommand
method 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,
DragReceiveHandler
calls theDoMakeDragDropCommand
method 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),
DragReceiveHandler
calls theDoMakeDragDropCommand
method for the source view only, passing the command numbercDrag
.- If the source and target are the same view and the operation is a move,
DragReceiveHandler
calls theDoMakeDragDropCommand
method 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'sDoMakeDragDropCommand
method is asked to create a drag-and-drop command based on the command number passed to it.When a view is asked to create a
cDrag
command, it creates and returns a command whoseDoIt
method removes the dragged data from the view. The command'sUndoIt
method reinserts the data, and itsRedoIt
method removes the data again.When a view is asked to create a
cDrop
command, it creates and returns a command whoseDoIt
method inserts the dropped data into the view. The command'sUndoIt
method removes the inserted data, and itsRedoIt
method inserts the data again.
When a view is asked to create a
- IMPORTANT
- A view's
DoMakeDragDropCommand
method 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.cDragMove
command, it creates and returns a command whoseDoIt
method moves the selected data from its current location in the view to the location specified by the drop. TheUndoIt
method reverses the move and theRedoIt
method 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. TheDragReceiveHandler
method 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. TheDragReceiveHandler
method then links the two commands together. MacApp'sTCommandHandler
class 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
fValidationFailed
field. 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.