December 93 - DRAG AND DROP FROM THE FINDER
DRAG AND DROP FROM THE FINDER
DAVE EVANS AND GREG ROBBINS
Some users navigate Standard File dialogs with no problem, but many others find them
tedious or even confusing. Users want to find and organize their files without having to
learn the intricacies of the hierarchical file system and Standard File dialogs. With
applications that use the Drag Manager, users will be able to work with files the way
they expect: by dragging files from the Finder into an application window. This article
and the accompanying sample program show how easily your application can provide
this valuable feature.
The Drag Manager is so new you won't find it in Inside Macintosh yet, but if your
application works with files, you'll want to learn more about what it can do for you.
This new Macintosh Toolbox manager lets users drag and drop data (such as text and
pictures) between windows in an application and between different applications. It also
allows users to drag document icons to and from the Finder.
Rather than describing the Drag Manager in depth, this article and its sample
application focus on using the Drag Manager to drag picture files (files of type 'PICT')
from the Finder into an application. The techniques used by the sample application can
easily be generalized to cover other cases.
The Drag Manager is currently packaged as a system software extension that you can
license to include with your products. It requires System 7, and to take advantage of
the Finder dragging described in this article you need Finder version 7.1.1 or later.
You can order the full Macintosh Drag and Drop Developer's Kit from APDA. The Drag
Manager will also be included in future system software releases.
Along with the sample application, called SimpleDrag, this issue's CD contains the
programmer's guide for the Drag Manager as well as theDrag and Drop Human
Interface Guidelines. After you've read this article and looked at the SimpleDrag code,
you should read these two documents to get a deeper understanding of the Drag Manager.
SimpleDrag not only allows picture files to be dragged from the Finder but also lets
PICT data be dragged from one application window into another; for the full story on
this, look at the code and documentation on the CD.
THE INTERFACE: IT'S NOT SUCH A DRAG
Dragging is a skill that every Macintosh user has mastered. It provides a quick, simple
alternative to commands as a way of performing common operations such as moving or
deleting files. This use of dragging gives users a sense of control because they can
manipulate objects directly with excellent visual feedback. And it's faster and more
intuitive than commands because it's not hidden in a menu.
Since all Macintosh users use dragging to arrange and manipulate files in the Finder, it
only makes sense that they should be able to drag files from the Finder into an
application window. But until now, the only way to select and specify files within an
application has been with Standard File dialogs. Now you can use the Drag Manager to
provide an alternate, more intuitive way to work with files: the user can open a file in
your application simply by dragging the file's icon into an application window.
FIRST, A FEW TERMS
Before we look at the sample code, we need to clarify a few terms that the Drag
manager introduces: drag items, drag flavors, drag handlers, senders, and receivers.
The objects that a user drags are called drag items. For example, a user who selects
and drags three files is dragging three different drag items.
Drag flavorsdescribe the kind of data that a drag item contains. When a user drags an
item to an application window, the receiving application must determine whether it
can accept the data in the drag item. Each item can have more than one flavor, because
data can usually be described in more than one format or data type. For example, you
can describe text data as ASCII data, styled text data, or RTF interchange format; if a
program can't accept the more elaborate RTF format, it may be able to use the plain
ASCII text. The Drag Manager uses a four-character ResType to identify a flavor. In
our sample application, we use only two drag flavors: one that identifies files dragged
from the Finder, and another that identifies PICT data dragged from an application
window.
The Drag Manager uses an application'sdrag handlersto provide dragging feedback and
to complete a drag. There are two types of drag handlers:tracking handlersand receive
handlers. A tracking handler is called while an item is being dragged over an
application's windows; a receive handler is called when the user releases the mouse
button to drop the item in a window. Each window has a tracking handler and receive
handler installed for it, though several windows may use the same handler. When you
initialize your application or open a new window, you call the Drag Manager to install
your drag handler callback routines.
Because the Drag Manager provides interapplication drag and drop services, it's
important to know where the drag starts and where it ends. The application in which
the drag starts is called thesender. Any application that the item is dragged over is a
potentialreceiverof the drag; the application it's dropped into is the actual receiver.
The sender and receiver might be the same application -- but with interapplication
dragging, another application could be the receiver of the drag.
NOW, ON TO THE CODE
With the lingo out of the way, let's look at our SimpleDrag application. This
application displays pictures in its windows. One way the user specifies a picture file
to be displayed is by choosing the application's Open command and then selecting a file
from the Standard File dialog. But since the application uses the Drag Manager, the
user can also drag a picture file from the Finder into a SimpleDrag window. PICT data
displayed in a SimpleDrag window can even be dragged into another SimpleDrag
window.
Before you call any Drag Manager routines, make sure that the Drag Manager is
available by calling Gestalt with the selector gestaltDragMgrAttr and checking the
gestaltDragMgrPresent bit of the response. *
First let's consider the code for the Open command case. When the user chooses the
Open command, SimpleDrag calls the Standard File Package to present a dialog that
lists the picture files. Once the user has selected a file, SimpleDrag calls its
SetWindowPictureFromFile routine to read the file and display it.
To support dragging files from the Finder into the application, SimpleDrag installs two
drag handlers for each new window. While the user drags a PICT drag item over a
SimpleDrag window, the tracking handler provides visual feedback. If the user drops
the item in a SimpleDrag window, the Drag Manager calls the receive handler to read
and display the PICT information, which may be not only a picture file but also PICT
data dragged from another window; the receive handler calls
itsSetWindowPictureFromFile routine if the drag item is a picture file (just as when
the user chooses Open from the File menu).
The following routine installs the tracking and receive handlers:
OSErr InstallDragHandlers(WindowPtr theWindow)
{
OSErr retCode;
retCode = InstallTrackingHandler(MyTrackingHandler, theWindow,
nil);
if (retCode == noErr) {
retCode = InstallReceiveHandler(MyReceiveHandler, theWindow,
nil);
if (retCode != noErr)
(void) RemoveTrackingHandler(MyTrackingHandler,
theWindow);
}
return retCode;
}
That's all you need to do to set up tracking and receive handlers for the given window.
You can also install a default handler, to be used for any window that you don't
explicitly install a handler for, by passing nil as the window pointer to the install
routine.
TRACKING THE DRAG
Now let's see what happens while the user drags an item around. Our main objective is
to indicate, with visual feedback, where it's OK to drop the item. SimpleDrag provides
the standard feedback highlighting for its type of windows and data -- a thin frame
highlight within the content region of the window. This highlight signals the user that
the item can be dropped there.
While the user drags an item (or items) over one of the application's windows, the
mouse movement determines what messages the tracking handler receives, as follows:
• The tracking handler receives an EnterHandler message the first time it's
called (that is, the first time the drag enters a window that uses that handler).
You can allocate memory or, as in our application, check whether you can
receive the drag.
• The handler receives an EnterWindow message when the drag enters a
window. This message is distinct from EnterHandler because you may be
using the same handler for more than one window, in which case there might
be many EnterWindow messages between an EnterHandler/LeaveHandler pair.
• While the user drags within a window, the handler receives multiple
InWindow messages.
• When the drag leaves the window, the handler receives a LeaveWindow
message.
• When the user drags to a window that uses a different tracking handler,
the handler receives a LeaveHandler message.
The tracking handler for SimpleDrag is as follows:
pascal OSErr MyTrackingHandler(DragTrackingMessage theMessage,
WindowPtr theWindow, void *handlerRefCon, DragReference theDrag)
{
#pragma unused (handlerRefCon)
RgnHandle tempRgn;
Boolean mouseInContentFlag;
OSErr retCode;

retCode = noErr;
switch (theMessage) {
case dragTrackingEnterHandler:
// Determine whether the drag item is acceptable and