1 ///////////////////////////////////////////////////////////////////////////////
 
   2 // Name:        src/osx/cocoa/dnd.mm
 
   3 // Purpose:     wxDropTarget, wxDropSource implementations
 
   4 // Author:      Stefan Csomor
 
   7 // Copyright:   (c) 1998 Stefan Csomor
 
   8 // Licence:     wxWindows licence
 
   9 ///////////////////////////////////////////////////////////////////////////////
 
  11 #include "wx/wxprec.h"
 
  14 #include "wx/object.h"
 
  17 #if wxUSE_DRAG_AND_DROP
 
  23     #include "wx/toplevel.h"
 
  24     #include "wx/gdicmn.h"
 
  28 #include "wx/evtloop.h"
 
  30 #include "wx/osx/private.h"
 
  32 wxDropSource* gCurrentSource = NULL;
 
  34 wxDragResult NSDragOperationToWxDragResult(NSDragOperation code)
 
  38         case NSDragOperationGeneric:
 
  40         case NSDragOperationCopy:
 
  42         case NSDragOperationMove:
 
  44         case NSDragOperationLink:
 
  46         case NSDragOperationNone:
 
  49             wxFAIL_MSG("Unexpected result code");
 
  54 @interface DropSourceDelegate : NSObject
 
  61 - (void)setImplementation: (wxDropSource *)dropSource;
 
  63 - (NSDragOperation)code;
 
  64 - (void)draggedImage:(NSImage *)anImage movedTo:(NSPoint)aPoint;
 
  65 - (void)draggedImage:(NSImage *)anImage endedAt:(NSPoint)aPoint operation:(NSDragOperation)operation;
 
  68 @implementation DropSourceDelegate
 
  74     resultCode = NSDragOperationNone;
 
  79 - (void)setImplementation: (wxDropSource *)dropSource
 
  89 - (NSDragOperation)code
 
  94 - (void)draggedImage:(NSImage *)anImage movedTo:(NSPoint)aPoint
 
  96     wxUnusedVar( anImage );
 
  97     wxUnusedVar( aPoint );
 
  99     bool optionDown = GetCurrentKeyModifiers() & optionKey;
 
 100     wxDragResult result = optionDown ? wxDragCopy : wxDragMove;
 
 102     if (wxDropSource* source = impl)
 
 104         if (!source->GiveFeedback(result))
 
 106             wxStockCursor cursorID = wxCURSOR_NONE;
 
 111                     cursorID = wxCURSOR_COPY_ARROW;
 
 115                     cursorID = wxCURSOR_ARROW;
 
 119                     cursorID = wxCURSOR_NO_ENTRY;
 
 126                     // put these here to make gcc happy
 
 130             if (cursorID != wxCURSOR_NONE)
 
 132                 // TODO under 10.6 the os itself deals with the cursor, remove if things
 
 133                 // work properly everywhere
 
 135                 wxCursor cursor( cursorID );
 
 143 - (void)draggedImage:(NSImage *)anImage endedAt:(NSPoint)aPoint operation:(NSDragOperation)operation
 
 145     wxUnusedVar( anImage );
 
 146     wxUnusedVar( aPoint );
 
 148     resultCode = operation;
 
 154 wxDropTarget::wxDropTarget( wxDataObject *data )
 
 155             : wxDropTargetBase( data )
 
 160 //-------------------------------------------------------------------------
 
 162 //-------------------------------------------------------------------------
 
 164 wxDropSource::wxDropSource(wxWindow *win,
 
 165                            const wxCursor &cursorCopy,
 
 166                            const wxCursor &cursorMove,
 
 167                            const wxCursor &cursorStop)
 
 168             : wxDropSourceBase(cursorCopy, cursorMove, cursorStop)
 
 173 wxDropSource::wxDropSource(wxDataObject& data,
 
 175                            const wxCursor &cursorCopy,
 
 176                            const wxCursor &cursorMove,
 
 177                            const wxCursor &cursorStop)
 
 178             : wxDropSourceBase(cursorCopy, cursorMove, cursorStop)
 
 184 wxDropSource* wxDropSource::GetCurrentDropSource()
 
 186     return gCurrentSource;
 
 189 wxDragResult wxDropSource::DoDragDrop(int WXUNUSED(flags))
 
 191     wxASSERT_MSG( m_data, wxT("Drop source: no data") );
 
 193     wxDragResult result = wxDragNone;
 
 194     if ((m_data == NULL) || (m_data->GetFormatCount() == 0))
 
 197     NSView* view = m_window->GetPeer()->GetWXWidget();
 
 200         NSPasteboard *pboard;
 
 202         pboard = [NSPasteboard pasteboardWithName:NSDragPboard];
 
 204         OSStatus err = noErr;
 
 205         PasteboardRef pboardRef;
 
 206         PasteboardCreate((CFStringRef)[pboard name], &pboardRef);
 
 208         err = PasteboardClear( pboardRef );
 
 211             CFRelease( pboardRef );
 
 214         PasteboardSynchronize( pboardRef );
 
 216         m_data->AddToPasteboard( pboardRef, 1 );
 
 218         NSEvent* theEvent = (NSEvent*)wxTheApp->MacGetCurrentEvent();
 
 219         wxASSERT_MSG(theEvent, "DoDragDrop must be called in response to a mouse down or drag event.");
 
 221         NSPoint down = [theEvent locationInWindow];
 
 222         NSPoint p = [view convertPoint:down fromView:nil];
 
 224         gCurrentSource = this;
 
 226         // add a dummy square as dragged image for the moment, 
 
 227         // TODO: proper drag image for data
 
 228         NSSize sz = NSMakeSize(16,16);
 
 229         NSRect fillRect = NSMakeRect(0, 0, 16, 16);
 
 230         NSImage* image = [[NSImage alloc] initWithSize: sz];
 
 234         [[[NSColor whiteColor] colorWithAlphaComponent:0.8] set];
 
 235         NSRectFill(fillRect);
 
 236         [[NSColor blackColor] set];
 
 237         NSFrameRectWithWidthUsingOperation(fillRect,1.0f,NSCompositeDestinationOver);
 
 242         DropSourceDelegate* delegate = [[DropSourceDelegate alloc] init];
 
 243         [delegate setImplementation: this];
 
 244         [view dragImage:image at:p offset:NSMakeSize(0.0,0.0) 
 
 245             event: theEvent pasteboard: pboard source:delegate slideBack: NO];
 
 247         wxEventLoopBase * const loop = wxEventLoop::GetActive();
 
 248         while ( ![delegate finished] )
 
 251         result = NSDragOperationToWxDragResult([delegate code]);
 
 255         wxWindow* mouseUpTarget = wxWindow::GetCapture();
 
 257         if ( mouseUpTarget == NULL )
 
 259             mouseUpTarget = m_window;
 
 262         if ( mouseUpTarget != NULL )
 
 264             wxMouseEvent wxevent(wxEVT_LEFT_DOWN);
 
 265             ((wxWidgetCocoaImpl*)mouseUpTarget->GetPeer())->SetupMouseEvent(wxevent , theEvent) ;
 
 266             wxevent.SetEventType(wxEVT_LEFT_UP);
 
 268             mouseUpTarget->HandleWindowEvent(wxevent);
 
 271         gCurrentSource = NULL;
 
 278 #endif // wxUSE_DRAG_AND_DROP