Update OpenVMS makefile
[wxWidgets.git] / src / osx / cocoa / dnd.mm
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name:        src/osx/cocoa/dnd.mm
3 // Purpose:     wxDropTarget, wxDropSource implementations
4 // Author:      Stefan Csomor
5 // Modified by:
6 // Created:     1998-01-01
7 // Copyright:   (c) 1998 Stefan Csomor
8 // Licence:     wxWindows licence
9 ///////////////////////////////////////////////////////////////////////////////
10
11 #include "wx/wxprec.h"
12
13 #ifndef WX_PRECOMP
14 #include "wx/object.h"
15 #endif
16
17 #if wxUSE_DRAG_AND_DROP
18
19 #include "wx/dnd.h"
20
21 #ifndef WX_PRECOMP
22     #include "wx/app.h"
23     #include "wx/toplevel.h"
24     #include "wx/gdicmn.h"
25     #include "wx/wx.h"
26 #endif // WX_PRECOMP
27
28 #include "wx/evtloop.h"
29
30 #include "wx/osx/private.h"
31
32 wxDropSource* gCurrentSource = NULL;
33
34 wxDragResult NSDragOperationToWxDragResult(NSDragOperation code)
35 {
36     switch (code)
37     {
38         case NSDragOperationGeneric:
39             return wxDragCopy;
40         case NSDragOperationCopy:
41             return wxDragCopy;
42         case NSDragOperationMove:
43             return wxDragMove;
44         case NSDragOperationLink:
45             return wxDragLink;
46         case NSDragOperationNone:
47             return wxDragNone;
48         default:
49             wxFAIL_MSG("Unexpected result code");
50     }
51     return wxDragNone;
52 }
53
54 @interface DropSourceDelegate : NSObject
55 {
56     BOOL dragFinished;
57     int resultCode;
58     wxDropSource* impl;
59 }
60
61 - (void)setImplementation: (wxDropSource *)dropSource;
62 - (BOOL)finished;
63 - (NSDragOperation)code;
64 - (void)draggedImage:(NSImage *)anImage movedTo:(NSPoint)aPoint;
65 - (void)draggedImage:(NSImage *)anImage endedAt:(NSPoint)aPoint operation:(NSDragOperation)operation;
66 @end
67
68 @implementation DropSourceDelegate
69
70 - (id)init
71 {
72     self = [super init];
73     dragFinished = NO;
74     resultCode = NSDragOperationNone;
75     impl = 0;
76     return self;
77 }
78
79 - (void)setImplementation: (wxDropSource *)dropSource
80 {
81     impl = dropSource;
82 }
83
84 - (BOOL)finished
85 {
86     return dragFinished;
87 }
88
89 - (NSDragOperation)code
90 {
91     return resultCode;
92 }
93
94 - (void)draggedImage:(NSImage *)anImage movedTo:(NSPoint)aPoint
95 {
96     wxUnusedVar( anImage );
97     wxUnusedVar( aPoint );
98     
99     bool optionDown = GetCurrentKeyModifiers() & optionKey;
100     wxDragResult result = optionDown ? wxDragCopy : wxDragMove;
101     
102     if (wxDropSource* source = impl)
103     {
104         if (!source->GiveFeedback(result))
105         {
106             wxStockCursor cursorID = wxCURSOR_NONE;
107
108             switch (result)
109             {
110                 case wxDragCopy:
111                     cursorID = wxCURSOR_COPY_ARROW;
112                     break;
113
114                 case wxDragMove:
115                     cursorID = wxCURSOR_ARROW;
116                     break;
117
118                 case wxDragNone:
119                     cursorID = wxCURSOR_NO_ENTRY;
120                     break;
121
122                 case wxDragError:
123                 case wxDragLink:
124                 case wxDragCancel:
125                 default:
126                     // put these here to make gcc happy
127                     ;
128             }
129
130             if (cursorID != wxCURSOR_NONE)
131             {
132                 // TODO under 10.6 the os itself deals with the cursor, remove if things
133                 // work properly everywhere
134 #if 0
135                 wxCursor cursor( cursorID );
136                 cursor.MacInstall();
137 #endif
138             }
139         }
140     }
141 }
142
143 - (void)draggedImage:(NSImage *)anImage endedAt:(NSPoint)aPoint operation:(NSDragOperation)operation
144 {
145     wxUnusedVar( anImage );
146     wxUnusedVar( aPoint );
147     
148     resultCode = operation;
149     dragFinished = YES;
150 }
151
152 @end
153
154 wxDropTarget::wxDropTarget( wxDataObject *data )
155             : wxDropTargetBase( data )
156 {
157
158 }
159
160 //-------------------------------------------------------------------------
161 // wxDropSource
162 //-------------------------------------------------------------------------
163
164 wxDropSource::wxDropSource(wxWindow *win,
165                            const wxCursor &cursorCopy,
166                            const wxCursor &cursorMove,
167                            const wxCursor &cursorStop)
168             : wxDropSourceBase(cursorCopy, cursorMove, cursorStop)
169 {
170     m_window = win;
171 }
172
173 wxDropSource::wxDropSource(wxDataObject& data,
174                            wxWindow *win,
175                            const wxCursor &cursorCopy,
176                            const wxCursor &cursorMove,
177                            const wxCursor &cursorStop)
178             : wxDropSourceBase(cursorCopy, cursorMove, cursorStop)
179 {
180     SetData( data );
181     m_window = win;
182 }
183
184 wxDropSource* wxDropSource::GetCurrentDropSource()
185 {
186     return gCurrentSource;
187 }
188
189 wxDragResult wxDropSource::DoDragDrop(int WXUNUSED(flags))
190 {
191     wxASSERT_MSG( m_data, wxT("Drop source: no data") );
192
193     wxDragResult result = wxDragNone;
194     if ((m_data == NULL) || (m_data->GetFormatCount() == 0))
195         return result;
196
197     NSView* view = m_window->GetPeer()->GetWXWidget();
198     if (view)
199     {
200         NSPasteboard *pboard;
201  
202         pboard = [NSPasteboard pasteboardWithName:NSDragPboard];
203     
204         OSStatus err = noErr;
205         PasteboardRef pboardRef;
206         PasteboardCreate((CFStringRef)[pboard name], &pboardRef);
207         
208         err = PasteboardClear( pboardRef );
209         if ( err != noErr )
210         {
211             CFRelease( pboardRef );
212             return wxDragNone;
213         }
214         PasteboardSynchronize( pboardRef );
215         
216         m_data->AddToPasteboard( pboardRef, 1 );
217         
218         NSEvent* theEvent = (NSEvent*)wxTheApp->MacGetCurrentEvent();
219         wxASSERT_MSG(theEvent, "DoDragDrop must be called in response to a mouse down or drag event.");
220
221         NSPoint down = [theEvent locationInWindow];
222         NSPoint p = [view convertPoint:down fromView:nil];
223                 
224         gCurrentSource = this;
225         
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];
231  
232         [image lockFocus];
233         
234         [[[NSColor whiteColor] colorWithAlphaComponent:0.8] set];
235         NSRectFill(fillRect);
236         [[NSColor blackColor] set];
237         NSFrameRectWithWidthUsingOperation(fillRect,1.0f,NSCompositeDestinationOver);
238         
239         [image unlockFocus];        
240         
241         
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];
246         
247         wxEventLoopBase * const loop = wxEventLoop::GetActive();
248         while ( ![delegate finished] )
249             loop->Dispatch();
250         
251         result = NSDragOperationToWxDragResult([delegate code]);
252         [delegate release];
253         [image release];
254         
255         wxWindow* mouseUpTarget = wxWindow::GetCapture();
256
257         if ( mouseUpTarget == NULL )
258         {
259             mouseUpTarget = m_window;
260         }
261         
262         if ( mouseUpTarget != NULL )
263         {
264             wxMouseEvent wxevent(wxEVT_LEFT_DOWN);
265             ((wxWidgetCocoaImpl*)mouseUpTarget->GetPeer())->SetupMouseEvent(wxevent , theEvent) ;
266             wxevent.SetEventType(wxEVT_LEFT_UP);
267         
268             mouseUpTarget->HandleWindowEvent(wxevent);
269         }
270         
271         gCurrentSource = NULL;
272     }
273
274
275     return result;
276 }
277
278 #endif // wxUSE_DRAG_AND_DROP
279