TweetFollow Us on Twitter

What a Drag Volume Number: 16 (2000)
Issue Number: 12
Column Tag: Mac OS X

What a Drag!

By Andrew C. Stone

Creating drag wells in Cocoa

The richness of the user interface in Macintosh OS X is due, in part, to the abundance of elements that allow dragging and dropping of data within and between applications. For example, Cocoa uses drag and drop for applying color swatches to text selections and objects. Stone Design's flagship application, Create[TM], makes heavy use of the drag and drop metaphor. A library of resources allows users to drag in components, pages, effects, blends, images, and patterns. The user can quickly save a selection of graphics to one of many image formats with Create's "Image Well". This article will cover the basics of creating a custom control which allows a user to drag in a file, and then allows the user to drag out the file.

Create's image well lets you drag out data in various image formats.

First, a bit of article administrivia. Mac OS X has been a fast moving target with the various developer releases, Public Beta, and soon OS X GM (for Golden Master which always reminds me of that Eddy Murphy movie about G)! Because of the changes introduced with each release and the several month lag time between penning articles and when MacTech hits the stands, there are times when what I've written doesn't jive with the current reality. To address this, I've added a section to the Stone Design website for MacTech article updates and errata. So if you get confused, check out to see if there are updates, and if not, email me so I can post fixes.

It's actually quite simple to create new types of user interface controls using Cocoa because of the well designed hierarchy of classes that comprise the Application framework. Your first job is to find an existing class that your control can inherit from, which will reduce the amount of code that you have to write. I keep /Developer/Documentation/Cocoa/cocoa.html open so I can quickly navigate to the AppKit or Foundation API's. But an even easier way to look at the object hierarchy is to use InterfaceBuilder. First launch ProjectBuilder and create a new Cocoa Application project named ImageWellTester. Click on the "Resources" triangle in the Files and Groups outline view, and double-click the MainMenu.nib. This will launch InterfaceBuilder.

Click on the "Classes" tab of the document window, and then explore the NSObject outline view:

Interface Builder lets you explore the hierarchy of objects offered by Cocoa.

Our drag well is definitely a subclass of NSView, but we can gain further functionality by subclassing NSControl, which gives us the target/action support. Select NSControl in the Classes pane. If you hold down the CONTROL key while clicking on NSControl, a context-sensitive menu appears. Do this and select "Subclass". A new class which inherits from NSControl is created and named, by default, MyControl. Rename the class to DragWell.

Why write code if you can have it written for you? You can use InterfaceBuilder to produce stub files where all you have to do is fill in the functionality in the stubbed out methods. Click on the "outlet" icon to add instance variables to the class, and the "+" icon to add actions to the class. For now, we don't have any to add. Be sure DragWell is selected, and choose select "Create Files..." from the Classes menu (or again using the context menu via CONTROL key). They will be named DragWell.m and DragWell.h - leave the "Insert into Project Builder" selected and click OK.

Drag out a "Custom View" from the IB palette window, second tab, onto to the main window. Choose Tools->Inspector->Custom Class popup button, and click on "DragWell". The custom view should now say "DragWell". Save the file.

Go back to ProjectBuilder, select the newly added DragWell.h and DragWell.m and you'll see the stub:

#import <Cocoa/Cocoa.h>

@interface DragWell : NSControl

#import "DragWell.h"

@implementation DragWell


Every custom view must define its own drawing method, drawRect:, where the actual drawing of the view takes place. We'll want a simple, depressed bezeled look, with an icon to drag in the center. And our control will adhere to two protocols - NSDraggingDestination and NSDraggingSource, to allow both dragging out of info and accepting dragged in info. A complete list of the methods required by the protocols are found in:


Here's the 'well' commented code for the DragWell - type it in (or download it from You can copy and paste it as a template for use in other objects, modifying where needed to copy other data types to the drag pasteboard as needed.

+++++++++++ DragWell.h ++++++++++++++++

#import <Cocoa/Cocoa.h>

@interface DragWell : NSControl
    NSImage *image;      // the image displayed and dragged by the user
    NSString *file;      // the file path that the user will drag out
    unsigned int last;   // for optimizing the draggingUpdated: method

// if you want to programmatically set a file in the well:
- (void)setFile:(NSString *)newFile;


+++++++++++ DragWell.m ++++++++++++++++

#import "DragWell.h"

/* Example source by Andrew Stone for MacTech */

@implementation DragWell

// when our DragWell is reconstituted from the nib file, awakeFromNib gets called

- (void) awakeFromNib
     // this is where you register for various types of drag pasteboards:
     [self registerForDraggedTypes:[NSArray arrayWithObject:NSFilenamesPboardType]];

// Never add an ivar which allocates memory without releasing it in dealloc:
// Don't Litter!

- (void)dealloc {
    [file release];
    [image release];
    [super dealloc];

// Every custom view must implement drawRect:
// We'll draw our depressed bezeled rect
// and if there is a file, we'll draw an image for dragging out

- (void)drawRect:(NSRect)rects
    // one simple call draws the depressed bezel:
    NSDrawGrayBezel([self bounds] , [self bounds]);

    // if you like the pinstripes, then include these two lines:
    [[NSColor windowBackgroundColor] set];
    NSRectFill(NSInsetRect([self bounds],3.0,3.0));

    // find the center of the view and draw the image over:
    if (image != nil) {
        NSPoint p;
        NSSize sz = [image size];
        p.x = ([self bounds].size.width - sz.width)/2.;
        p.y = ([self bounds].size.height - sz.height)/2.;
        [image compositeToPoint:p operation:NSCompositeSourceOver];

// When we set the file, we also set the image which we get from the NSWorkspace:

- (void)setFile:(NSString *)newFile {

    // it's good practice to not do any work if nothing would change:
    if (![newFile isEqualToString:file]) {
        // live clean and let your works be seen:
        [file release];
        [image release];
        // copy the newFile into our instance variable file:
        file = [newFile copyWithZone:[self zone]];
        // check if the file is nil or empty string:
        if (!file || [file isEqualToString:@""]) {
            image = nil;
        } else {
            // we have a file, now let's find the image for that file:
            image = [[[NSWorkspace sharedWorkspace] iconForFile:file]retain];
        // we'll need to redraw next event 
        // this is the approved Cocoa way of setting ourselves "dirty"
        [self setNeedsDisplayInRect:[self bounds]];

// here we copy the filename to the pasteboard
// I like to factor this out because it may vary from object to object:

- (BOOL)copyDataTo:pboard
    if (file != nil && ![file isEqualToString:@""]) {
        [pboard declareTypes:[NSArray arrayWithObject:NSFilenamesPboardType] owner:self];
        [pboard setPropertyList:[NSArray arrayWithObject:file] forType:NSFilenamesPboardType];
        return YES;
    } else return NO;

// To add drag away functionality to a control, implement these:

// draggingSourceOperationMaskForLocal lets you control the behavior of what should
// happen with the data on the pasteboard: copy, link or any
// the isLocal flag tells you whether the object querying is from within your app
// or from another application running on the system

- (unsigned int)draggingSourceOperationMaskForLocal:(BOOL)isLocal
        if (isLocal) return NSDragOperationCopy;
        return NSDragOperationCopy|NSDragOperationGeneric|NSDragOperationLink;

// The simple dragImage:at:offset:event:pasteboard:source:slideback: method
// is all we do to initiate and run the actual drag sequence
// But we only do this if we have an image and we successfully write our data
// to the pasteboard in copyDataTo: method

- (void)mouseDown:(NSEvent *)e
        NSPoint location;
        NSSize size;
        NSPasteboard *pb = [NSPasteboard pasteboardWithName:(NSString *) NSDragPboard];

        if (image && [self copyDataTo:pb]) {
                size = [image size];
    location.x = ([self bounds].size.width - size.width)/2;
    location.y = ([self bounds].size.height - size.height)/2;

                [self dragImage:image at:location offset:NSZeroSize event:(NSEvent *)e
pasteboard:pb source:self slideBack:YES];

// To add drag acceptance functionality to a control, implement these methods:

// this is called when the drag enters our view
// by returning NSDragOperationCopy
- (unsigned int) draggingEntered:sender
    NSPasteboard   *pboard;

     last      = NSDragOperationNone;
     pboard    = [sender draggingPasteboard];

// we don't acept drags if we are the provider!!
     if ([sender draggingSource] == self) return NSDragOperationNone;

     if ([[pboard types] containsObject:NSFilenamesPboardType]) {
         if (image == nil) {
            image = [[[NSWorkspace sharedWorkspace] iconForFile:[[pboard
             [self setNeedsDisplayInRect:[self bounds]];
   // we'll copy or link depending on the intent of the dragging source:
   last = [sender draggingSourceOperationMask]; 
     return last;

// instead of constantly rechecking the pasteboard as the mouse moves inside the view
// we'll simply return the cached value that we set in 'last' in draggingEntered:

- (unsigned int) draggingUpdated:sender
     return last;

// Because we're providing feedback by setting the file right when the user enters
// we'll need to undo that work if the user does not let go of the drag inside and exits instead:

- (void) draggingExited:sender
    // the user has exited -> clean up:     
    if ([sender draggingSource] != self)  {
        if (file == nil) {
            // then unset the file image we set in mouseEntered as feedback...
            [image release];
            image = nil;
            [self setNeedsDisplayInRect:[self bounds]];
        last = NSDragOperationNone;

// any dragging clean up might be done here
// don't forget to return YES!

- (BOOL) prepareForDragOperation:sender
     return YES;

// Actually do the work in this method if it's not too time consuming
// Otherwise, you may consider returning YES, and doing the work
// in concludeDragOperation to prevent the drag from sliding back
// because it "timed out"

- (BOOL) performDragOperation:(id <NSDraggingInfo>)sender
    NSPasteboard   *pboard;
    pboard    = [sender draggingPasteboard];
    [self setFile:[[pboard propertyListForType:NSFilenamesPboardType]objectAtIndex:0]];
    return YES;

- (void)concludeDragOperation:(id <NSDraggingInfo>)sender
    // we already did the work in draggingEntered
    // You might notify some other object that the file is here

// this is good if you want to be able to drag out data even if the window is not
// front most, the first click will do more than just bring the window to front -
// It will also allow the drag to begin on that first mouse down

- (BOOL)acceptsFirstMouse:(NSEvent *)theEvent {
    return YES;



Adding drag and drop support to controls and views is very easy in Cocoa. Because ease of use and intuitive behavior is the keystone of Mac OS X, be sure to make your applications conform to this model.

Andrew Stone <> washes windows at Stone Design Corp <> and divides his time between writing applications for Mac OS X and raising farm animals, including children.


Community Search:
MacTech Search:

Software Updates via MacUpdate

Printopia 3.0.8 - Share Mac printers wit...
Run Printopia on your Mac to share its printers to any capable iPhone, iPad, or iPod Touch. Printopia will also add virtual printers, allowing you to save print-outs to your Mac and send to apps.... Read more
BetterTouchTool 2.417 - Customize multi-...
BetterTouchTool adds many new, fully customizable gestures to the Magic Mouse, Multi-Touch MacBook trackpad, and Magic Trackpad. These gestures are customizable: Magic Mouse: Pinch in / out (zoom... Read more
Mellel 4.1.0 - The word processor for sc...
Mellel is the leading word processor for OS X and has been widely considered the industry standard for long form documents since its inception. Mellel focuses on writers and scholars for technical... Read more
ScreenFlow 7.3 - Create screen recording...
ScreenFlow is powerful, easy-to-use screencasting software for the Mac. With ScreenFlow you can record the contents of your entire monitor while also capturing your video camera, microphone and your... Read more
Dashlane 5.9.0 - Password manager and se...
Dashlane is an award-winning service that revolutionizes the online experience by replacing the drudgery of everyday transactional processes with convenient, automated simplicity - in other words,... Read more
ForkLift 3.2 - Powerful file manager: FT...
ForkLift is a powerful file manager and ferociously fast FTP client clothed in a clean and versatile UI that offers the combination of absolute simplicity and raw power expected from a well-executed... Read more
Cocktail 11.5 - General maintenance and...
Cocktail is a general purpose utility for macOS that lets you clean, repair and optimize your Mac. It is a powerful digital toolset that helps hundreds of thousands of Mac users around the world get... Read more
Hazel 4.2.4 - Create rules for organizin...
Hazel is your personal housekeeper, organizing and cleaning folders based on rules you define. Hazel can also manage your trash and uninstall your applications. Organize your files using a familiar... Read more
Skype - Voice-over-internet pho...
Skype allows you to talk to friends, family, and co-workers across the Internet without the inconvenience of long distance telephone charges. Using peer-to-peer data transmission technology, Skype... Read more
Backup and Sync 3.40.8921.5350 - File ba...
Backup and Sync (was Google Drive) is a place where you can create, share, collaborate, and keep all of your stuff. Whether you're working with a friend on a joint research project, planning a... Read more

Latest Forum Discussions

See All

Destiny meets its mobile match - Everyth...
Shadowgun Legends is the latest game in the Shadowgun series, and it's taking the franchise in some interesting new directions. Which is good news. The even better news is that it's coming out tomorrow, so if you didn't make it into the beta you... | Read more »
How PUBG, Fortnite, and the battle royal...
The history of the battle royale genre isn't a long one. While the nascent parts of the experience have existed ever since players first started killing one another online, it's really only in the past six years that the genre has coalesced into... | Read more »
Around the Empire: What have you missed...
Oh hi nice reader, and thanks for popping in to check out our weekly round-up of all the stuff that you might have missed across the Steel Media network. Yeah, that's right, it's a big ol' network. Obviously 148Apps is the best, but there are some... | Read more »
All the best games on sale for iPhone an...
It might not have been the greatest week for new releases on the App Store, but don't let that get you down, because there are some truly incredible games on sale for iPhone and iPad right now. Seriously, you could buy anything on this list and I... | Read more »
Everything You Need to Know About The Fo...
In just over a week, Epic Games has made a flurry of announcements. First, they revealed that Fortnite—their ultra-popular PUBG competitor—is coming to mobile. This was followed by brief sign-up period for interested beta testers before sending out... | Read more »
The best games that came out for iPhone...
It's not been the best week for games on the App Store. There are a few decent ones here and there, but nothing that's really going to make you throw down what you're doing and run to the nearest WiFi hotspot in order to download it. That's not to... | Read more »
Death Coming (Games)
Death Coming Device: iOS Universal Category: Games Price: $1.99, Version: (iTunes) Description: --- Background Story ---You Died. Pure and simple, but death was not the end. You have become an agent of Death: a... | Read more »
Hints, tips, and tricks for Empires and...
Empires and Puzzles is a slick match-stuff RPG that mixes in a bunch of city-building aspects to keep things fresh. And it's currently the Game of the Day over on the App Store. So, if you're picking it up for the first time today, we thought it'd... | Read more »
What You Need to Know About Sam Barlow’s...
Sam Barlow’s follow up to Her Story is #WarGames, an interactive video series that reimagines the 1983 film WarGames in a more present day context. It’s not exactly a game, but it’s definitely still interesting. Here are the top things you should... | Read more »
Pixel Plex Guide - How to Build Better T...
Pixel Plex is the latest city builder that has come to the App Store, and it takes a pretty different tact than the ones that came before it. Instead of being in charge of your own city by yourself, you have to work together with other players to... | Read more »

Price Scanner via

Back in stock! Apple’s full line of Certified...
Save $300-$300 on the purchase of a 2017 13″ MacBook Pro today with Certified Refurbished models at Apple. Apple’s refurbished prices are the lowest available for each model from any reseller. A... Read more
Back in stock: 13-inch 2.5GHz MacBook Pro (Ce...
Apple has Certified Refurbished 13″ 2.5GHz MacBook Pros (MD101LL/A) available for $829, or $270 off original MSRP. Apple’s one-year warranty is standard, and shipping is free: – 13″ 2.5GHz MacBook... Read more
Apple restocks Certified Refurbished 2017 13″...
Apple has Certified Refurbished 2017 13″ MacBook Airs available starting at $849. An Apple one-year warranty is included with each MacBook, and shipping is free: – 13″ 1.8GHz/8GB/128GB MacBook Air (... Read more
8-Core iMac Pro on sale for $4699, save $300
Amazon has the 8-core iMac Pro on sale for $4699 including free shipping. Their price is $300 off MSRP, and it’s the currently lowest price available for an iMac Pro. For the latest up-to-date prices... Read more
10″ 512GB WiFi iPad Pros on sale for $849, sa...
B&H Photo has Space Gray and Rose Gold 10.5″ 512GB WiFi iPad Pros on sale for $849. Their price is $150 off MSRP, and it’s the lowest price available for these models, new, from any Apple... Read more
MacBook Pro sale! B&H drops prices on new...
B&H Photo has dropped prices on new 2017 13″ MacBook Pros, with models now on sale for up to $200 off MSRP. Shipping is free, and B&H charges sales tax for NY & NJ residents only. Their... Read more
13″ MacBook Airs on sale for $100-$150 off MS...
B&H Photo has 13″ MacBook Airs on sale for $100-$150 off MSRP. Shipping is free, and B&H charges sales tax for NY & NJ residents only: – 13″ 1.8GHz/128GB MacBook Air (MQD32LL/A): $899, $... Read more
Huge iMac sale! Apple reseller now offering 2...
B&H Photo has new 2017 21″ & 27″ iMacs on sale today for up to $300 off MSRP. Shipping is free, and B&H charges sales tax for NY & NJ residents only: – 27″ 3.8GHz iMac (MNED2LL/A): $... Read more
Sale! 1.4GHz Mac mini for $399, $100 off MSRP
B&H Photo has the 1.4GHz Mac mini on sale for $399 for a limited time. Their price is $100 off MSRP, and it’s the lowest price available for a mini from any Apple reseller: – 1.4GHz Mac mini (... Read more
Sale of the year continues as Apple resellers...
Adorama has new 2017 15″ MacBook Pros on sale for $250-$300 off MSRP. Shipping is free, and Adorama charges sales tax in NJ and NY only: – 15″ 2.8GHz Touch Bar MacBook Pro Space Gray (MPTR2LL/A): $... Read more

Jobs Board

*Apple* Retail - Multiple Positions - Apple,...
Sales Specialist - Retail Customer Service and Sales Transform Apple Store visitors into loyal Apple customers. When customers enter the store, you're also the Read more
Data Scientist, *Apple* Ecosystem (AMP Anal...
# Data Scientist, Apple Ecosystem (AMP Analytics) Job Number: 113428728 Santa Clara Valley, California, United States Posted: 24-Jan-2018 Weekly Hours: 40.00 **Job Read more
*Apple* Professional Learning Specialist - A...
# Apple Professional Learning Specialist Job Number: 113456892 Englewood, NJ, New Jersey, United States Posted: 02-Feb-2018 Weekly Hours: 40.00 **Job Summary** The Read more
*Apple* Retail Online, Senior Financial Anal...
# Apple Retail Online, Senior Financial Analyst Job Number: 57228835 Santa Clara Valley, California, United States Posted: 12-Feb-2018 Weekly Hours: 40.00 **Job Read more
Site Reliability Engineer, *Apple* Pay - Ap...
# Site Reliability Engineer, Apple Pay Job Number: 113356036 Santa Clara Valley, California, United States Posted: 12-Jan-2018 Weekly Hours: 40.00 **Job Summary** Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.