// ================================================================================= // CDragItem.cp ©1995 J. Rodden, DD/MF & Associates. All rights reserved // ================================================================================= // Mixin class to be used with anything that supports dragging of it's items. // CDragItem encapsulates the characteristics of a dragable item. // // By using CDragItem and overriding AddFlavors and MakeDragRegion, you can // (a) include as many flavors of an item as you want, (b) define your own outline // to replace the generic rectangle that LDragTask provides, (c) arrange to send // drag data on demand by calling InstallDragSendData when adding flavors (and // installing null data in the drag) and overriding DoSendDragData for the object // being draged, and (d) override the drag manager's default behaviors for DragInput // and DragDrawing by calling InstallDragInput or InstallDragDrawing and overriding // DoDragInput or DoDragDrawing respectively. // ================================================================================= #include "CDragItem.h" // ============================================================================ // € AddFlavors // ============================================================================ // Add flavored items to the DragTask. void CDragItem::AddFlavors(DragReference inDragRef) { } // ============================================================================ // € MakeDragRegion // ============================================================================ // Build the region outlining the items to be dragged void CDragItem::MakeDragRegion( DragReference inDragRef, RgnHandle inDragRegion) { RgnHandle theDragRgn = ::NewRgn(); // Make region containing item ::OpenRgn(); SetLocalFrame(); DrawDragRegion(); // Draw directly into the drag region ::CloseRgn (theDragRgn); OutlineRegion(theDragRgn); // Carve out interior of region RgnHandle extraRgn = ::NewRgn (); if (AddToDragRgn(extraRgn)) { // provide hook to add another region OutlineRegion(extraRgn); ::UnionRgn (extraRgn, theDragRgn, theDragRgn); } ::DisposeRgn (extraRgn); // Accumulate new regions in our total drag region ::UnionRgn (theDragRgn, inDragRegion, inDragRegion); // Tell Drag Manager about this item ::SetDragItemBounds (inDragRef, kItemRef, &(**theDragRgn).rgnBBox); ::DisposeRgn (theDragRgn); } // ============================================================================ // € SetLocalFrame // ============================================================================ // Setup local frame (in global coords) for reference by drawing routines void CDragItem::SetLocalFrame (void) { } // ============================================================================ // € DrawDragRegion // ============================================================================ // Draw into the drag region, default does nothing void CDragItem::DrawDragRegion () { } // ============================================================================ // € AddToDragRgn // ============================================================================ // Add a region to the drag region, default does nothing (automatically outlined) // return true to include changes to inDragRegion to total drag region. Boolean CDragItem::AddToDragRgn (RgnHandle inDragRegion) { return false; } // ============================================================================ // € OutlineRegion // ============================================================================ // Utility for obtaining the outline of a region void CDragItem::OutlineRegion(RgnHandle inRegion) { RgnHandle innerRgn = ::NewRgn(); // Carve out interior of region so ::CopyRgn (inRegion, innerRgn); // that it's just a one-pixel thick ::InsetRgn (innerRgn, 1, 1); // outline of the item ::DiffRgn (inRegion, innerRgn, inRegion); ::DisposeRgn (innerRgn); } // ============================================================================ // € DoDragSendData // ============================================================================ // Send the data associated with a particular drag item // // This function gets called if you installed the optional DragSendDataProc // for this DropArea. In which case you should override this function // to provide the requested data by calling SetDragItemFlavorData. void CDragItem::DoDragSendData( FlavorType inFlavor, ItemReference inItemRef, DragReference inDragRef) { } // ============================================================================ // € DoDragInput // ============================================================================ // Modify the state of the mouse and modifier keys during a drag // // This function gets called if you installed the optional DragInputProc // for this DropArea. void CDragItem::DoDragInput( Point *ioMouse, Int16 *ioModifiers, DragReference inDragRef) { } // ============================================================================ // € DoDragDrawing // ============================================================================ // Draw the items for a drag in progress // // This function gets called if you installed the optional DragDrawingProc // for this DropArea. void CDragItem::DoDragDrawing( DragRegionMessage inMessage, RgnHandle inShowRgn, Point inShowOrigin, RgnHandle inHideRgn, Point inHideOrigin, DragReference inDragRef) { } // ============================================================================ // € Install Callback Functions Install Callback Functions € // ============================================================================ // Install SendData, DragInput, and DragDrawing Handlers for the Drag Manager // // We use a single handler for each of the Drag and Drop operations. // With the Drag Manager, you can register handlers globally or for specific // windows. With PowerPlant, we want to have separate handlers for each // dragable object. // ============================================================================ // € InstallDragSendData // ============================================================================ void CDragItem::InstallDragSendData(DragReference inDragRef) { OSErr err; DragSendDataUPP theDragSendDataUPP = NewDragSendDataProc(HandleDragSendData); err = ::SetDragSendProc( inDragRef, theDragSendDataUPP, this); ThrowIfOSErr_(err); } // ============================================================================ // € InstallDragInput // ============================================================================ void CDragItem::InstallDragInput(DragReference inDragRef) { OSErr err; DragInputUPP theDragInputUPP = NewDragInputProc(HandleDragInput); err = ::SetDragInputProc( inDragRef, theDragInputUPP, this); ThrowIfOSErr_(err); } // ============================================================================ // € InstallDragDrawing // ============================================================================ void CDragItem::InstallDragDrawing(DragReference inDragRef) { OSErr err; DragDrawingUPP theDragDrawingUPP = NewDragDrawingProc(HandleDragDrawing); err = ::SetDragDrawingProc( inDragRef, theDragDrawingUPP, this); ThrowIfOSErr_(err); } // =========================================================================== // € Static Callback Functions Static Callback Functions € // =========================================================================== // ============================================================================ // € HandleDragSendData // ============================================================================ // Drag Manager callback for sending the data for an item that is part // of an accepted drag and drop pascal OSErr CDragItem::HandleDragSendData( FlavorType inFlavor, void *inRefCon, ItemReference inItemRef, DragReference inDragRef) { OSErr err = noErr; Try_ { ((CDragItem*) inRefCon)->DoDragSendData(inFlavor, inItemRef, inDragRef); } Catch_(inErr) { err = inErr; } EndCatch_ return err; } // ============================================================================ // € HandleDragInput // ============================================================================ // Drag Manager callback for manipulating the mouse and modifier keys // during a drag pascal OSErr CDragItem::HandleDragInput( Point *ioMouse, Int16 *ioModifiers, void *inRefCon, DragReference inDragRef) { OSErr err = noErr; Try_ { ((CDragItem*) inRefCon)->DoDragInput(ioMouse, ioModifiers, inDragRef); } Catch_(inErr) { err = inErr; } EndCatch_ return err; } // ============================================================================ // € HandleDragDrawing // ============================================================================ // Drag Manager callback for drawing the items during a drag pascal OSErr CDragItem::HandleDragDrawing( DragRegionMessage inMessage, RgnHandle inShowRgn, Point inShowOrigin, RgnHandle inHideRgn, Point inHideOrigin, void *inRefCon, DragReference inDragRef) { OSErr err = noErr; Try_ { ((CDragItem*) inRefCon)->DoDragDrawing(inMessage, inShowRgn, inShowOrigin, inHideRgn, inHideOrigin, inDragRef); } Catch_(inErr) { err = inErr; } EndCatch_ return err; }