Working With Drag DataMacApp supplies a number of classes and methods for efficient manipulation of drag data. The following sections provide additional detail on classes and topics introduced earlier in this chapter.
CDragItemIteratorclass provides an iterator that traverses the
TDragItemobjects in a drag operation. A
CDragItemIteratorobject is passed as a parameter to several
TViewmethods during a drag session. For example, the
TView::WillAcceptDropmethod uses a passed iterator to determine whether the view can accept the data in the drag.
How Data Is RepresentedThe Macintosh Drag Manager supports dragging of data in multiple representations, or flavors. This is similar to the concept of putting Clipboard data on the desk scrap in multiple formats, such as PICT and TEXT. A drag source should supply or promise data in as many flavors as it can support, to increase the likelihood that a drop target will be able to accept the dragged data.
MacApp supplies the
TDragItemclass (page 267) to aid your application in supplying data to the Drag Manager, and the
CFlavorFlagsdata structure to provide simplified access to the Drag Manager
When a View Should Accept a DropA view should examine the contents of a drag and determine whether it can accept the dragged item(s). The human interface guidelines for drag and drop suggest that a drop target should accept a drop only if all items can be accepted. This eliminates any ambiguity that might result if a drop target only accepted a subset of items being dragged.
If a view can accept only a single item and the passed
CDragItemIteratorobject represents multiple items, the view should refuse to accept the drop. For example, a
TPictureview accepts a drag if there is exactly one item and it has the PICT flavor.
- Each item in a drag can contain multiple "flavors," or representations, of the item. The drop target doesn't need to accept all flavors offered by each item, but it must accept each of the items in some supplied flavor.
TDragItemA view object uses objects of type
TDragItemto supply data to be dragged. The data can be supplied in multiple representations, or flavors. For example, if a user clicks and drags a picture, the application might supply a single drag item object with flavors of PICT, GIF, JPEG, QuickTime, and any other graphic format it knows how to provide. This enables the drop target to request the item in whatever format it understands best.
TDragItemclass simplifies the multiflavor nature of drag items by implementing the concept of focus. A
TDragItemobject is always "focused" on a specific flavor.
TDragItemmethods for reading and writing data work on whatever flavor is currently focused. Adding a new flavor to a
TDragItemobject has the effect of focusing on the new flavor. An application focuses on a specific flavor by calling the
Promising DataInstead of providing a drag item with actual data, a view can promise to supply data later, using the
TDragItem::PromiseFlavormethod. Promising data requires little overhead and, except for very small data items, is more efficient than supplying all possible flavors up front--consider the memory requirements of supplying data in multiple large graphic formats, which may never even be used!
Fulfilling PromisesWhen a drop target requests data that has been promised, the drag session's
DragSendDataProcmethod calls the
DoFulfillPromisemethod of the drag source (normally a view object), passing a pointer to a
TDragItemobject that is focused on the requested flavor.
The view object can get information about the drag item by calling the
GetItemReferencemethods. The view provides the requested flavor data by calling one or more of the following
TDragItemmethods that write data to the focused flavor of the drag item:
- SetData. The
SetDatamethod sets the flavor data by copying the specified count of bytes from the specified buffer.
- SetDataFromHandle. The
SetDataFromHandlemethod is similar to
SetData, but it sets the flavor data from the specified handle.
- GetDataStream. The
GetDataStreammethod returns a
TDragFlavorStreamobject, which is a descendant of
TStream. A view object can supply flavor data by writing to the stream with standard
- If a view requests a
TDragFlavorStream, the view should free the requested stream before returning from
Drag Copy Versus Drag MoveA user-initiated drag operation can have the effect of either copying or moving the dragged data. The drag-and-drop human interface guidelines specify that data dragged within a single container should be moved. Data dragged between containers should be copied. However, the definition of container depends on the specific application, and the definition of within may vary depending on the user. To avoid confusion, the drag session object evaluates each drag individually and applies criteria established by the views involved to determine whether data should be copied or moved. Specifically, the
DragReceiveHandlermethod of the drag session object calls the
WillDragMovemethod of the source view.
WillDragMovemethod compares the values of the
fDragMoveFamilyfields of the source and target views to determine whether the drag qualifies as a move. Views that will support a drag move should set the
fDragMoveFamilyfield to the same arbitrary value. It's OK if that value is the default,
If, for example, a window contains a number of text views but a move should be generated only when dragging between two specific text views, those two views can assign the same value to
fDragMoveFamily. Consequently, dragging between those two views will generate a move. Dragging between any other text view and one of the two views in the hypothetical family will cause the data to be copied.
Move RelationshipsThe source view of a drag uses its
fDragMoveDeterminerfield to specify a relationship with the target destination that must be met if data is to be moved. MacApp supplies the following values for the
fDragMoveFamilyfield values of the source and destination views match, the
WillDragMovemethod looks at the value of the
fDragMoveDeterminerfield of the source view to determine whether the operation should be treated as a copy or a move. If the views are related in the manner described by the source view's
fDragMoveDeterminerfield, a move is generated. For example, if the source and target of a drag are views within the same window and the
fDragMoveDeterminerfield of the source view is
kMoveWithinApplication, the drag will qualify as a move.
Forcing a CopyMacApp implements a mechanism to circumvent the standard conventions and force a copy. To do so, a user presses the Option key before dropping the data and keeps it down while the data is dropped. The Option keypress is handled in the
SummaryFor MacApp to initiate a drag move operation, the source and destination views must have matching values in their
fDragMoveFamilyfields and the views must have the type of relationship specified by the source view's
- It's still a match if both views have their
fDragMoveFamilyfields set to