Important: The information in this document is obsolete and should not be used for new development.
Working With Drag Data
MacApp 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.CDragItemIterator
TheCDragItemIterator
class provides an iterator that traverses theTDragItem
objects in a drag operation. ACDragItemIterator
object is passed as a parameter to severalTView
methods during a drag session. For example, theTView::WillAcceptDrop
method uses a passed iterator to determine whether the view can accept the data in the drag.How Data Is Represented
The 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
TDragItem
class (page 267) to aid your application in supplying data to the Drag Manager, and theCFlavorFlags
data structure to provide simplified access to the Drag ManagerFlavorFlags
data type.When a View Should Accept a Drop
A 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
CDragItemIterator
object represents multiple items, the view should refuse to accept the drop. For example, aTPicture
view accepts a drag if there is exactly one item and it has the PICT flavor.
- Note
- 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.
TDragItem
A view object uses objects of typeTDragItem
to 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.The
TDragItem
class simplifies the multiflavor nature of drag items by implementing the concept of focus. ATDragItem
object is always "focused" on a specific flavor.TDragItem
methods for reading and writing data work on whatever flavor is currently focused. Adding a new flavor to aTDragItem
object has the effect of focusing on the new flavor. An application focuses on a specific flavor by calling theFocusOnFlavor
method.Promising Data
Instead of providing a drag item with actual data, a view can promise to supply data later, using theTDragItem::PromiseFlavor
method. 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 Promises
When a drop target requests data that has been promised, the drag session'sDragSendDataProc
method calls theDoFulfillPromise
method of the drag source (normally a view object), passing a pointer to aTDragItem
object that is focused on the requested flavor.The view object can get information about the drag item by calling the
GetFlavorType
andGetItemReference
methods. The view provides the requested flavor data by calling one or more of the followingTDragItem
methods that write data to the focused flavor of the drag item:
- SetData. The
SetData
method sets the flavor data by copying the specified count of bytes from the specified buffer.- SetDataFromHandle. The
SetDataFromHandle
method is similar toSetData
, but it sets the flavor data from the specified handle.- GetDataStream. The
GetDataStream
method returns aTDragFlavorStream
object, which is a descendant ofTStream
. A view object can supply flavor data by writing to the stream with standardTStream
methods.
- Note
- If a view requests a
TDragFlavorStream
, the view should free the requested stream before returning fromDoFulfillPromise
.Drag Copy Versus Drag Move
A 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, theDragReceiveHandler
method of the drag session object calls theWillDragMove
method of the source view.Move Families
TheWillDragMove
method compares the values of thefDragMoveFamily
fields of the source and target views to determine whether the drag qualifies as a move. Views that will support a drag move should set thefDragMoveFamily
field to the same arbitrary value. It's OK if that value is the default,kNoIdentifier
.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 Relationships
The source view of a drag uses itsfDragMoveDeterminer
field to specify a relationship with the target destination that must be met if data is to be moved. MacApp supplies the following values for thefDragMoveDeterminer
field:kNeverMove
,kMoveWithinWindow
,kMoveWithinContext
,kMoveWithinView
, andkMoveWithinApplication
.If the
fDragMoveFamily
field values of the source and destination views match, theWillDragMove
method looks at the value of thefDragMoveDeterminer
field 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'sfDragMoveDeterminer
field, a move is generated. For example, if the source and target of a drag are views within the same window and thefDragMoveDeterminer
field of the source view iskMoveWithinWindow
,kMoveWithinContext
, orkMoveWithinApplication
, the drag will qualify as a move.Forcing a Copy
MacApp 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 theTDragDropSession::DragReceiveHandler
method.Summary
For MacApp to initiate a drag move operation, the source and destination views must have matching values in theirfDragMoveFamily
fields and the views must have the type of relationship specified by the source view'sfDragMoveDeterminer
field.
- Note
- It's still a match if both views have their
fDragMoveFamily
fields set tokNoIdentifier
.