The rounded corners look really dumb at this size.
[wxWidgets.git] / src / os2 / dnd.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: src/os2/dnd.cpp
3 // Purpose: wxDropTarget, wxDropSource, wxDataObject implementation
4 // Author: David Webster
5 // Modified by:
6 // Created: 10/21/99
7 // Copyright: (c) 1998 AUTHOR
8 // Licence: wxWindows licence
9 ///////////////////////////////////////////////////////////////////////////////
10
11 // For compilers that support precompilation, includes "wx.h".
12 #include "wx/wxprec.h"
13
14 #if wxUSE_DRAG_AND_DROP
15
16 #include "wx/dnd.h"
17
18 #ifndef WX_PRECOMP
19 #include "wx/app.h"
20 #include "wx/window.h"
21 #include "wx/gdicmn.h"
22 #endif
23
24 #define INCL_PM
25 #define INCL_DOS
26 #include <os2.h>
27
28 // ----------------------------------------------------------------------------
29 // global
30 // ----------------------------------------------------------------------------
31
32 /////////////////////////////////////////////////////////////////////////////
33 // Private functions
34 /////////////////////////////////////////////////////////////////////////////
35
36 #if 0
37 static wxDragResult ConvertDragEffectToResult (
38 DWORD dwEffect
39 )
40 {
41 switch (dwEffect)
42 {
43 case DO_COPY:
44 return wxDragCopy;
45
46 case DO_LINK:
47 return wxDragLink;
48
49 case DO_MOVE:
50 return wxDragMove;
51
52 default:
53 case DO_DEFAULT:
54 return wxDragNone;
55 }
56 } // end of ConvertDragEffectToResult
57
58 static DWORD ConvertDragResultToEffect (
59 wxDragResult eResult
60 )
61 {
62 switch (eResult)
63 {
64 case wxDragCopy:
65 return DO_COPY;
66
67 case wxDragLink:
68 return DO_LINK;
69
70 case wxDragMove:
71 return DO_MOVE;
72
73 default:
74 case wxDragNone:
75 return DO_DEFAULT;
76 }
77 } // end of ConvertDragResultToEffect
78 #endif
79
80 class CIDropTarget
81 {
82 public:
83 CIDropTarget(wxDropTarget* pTarget)
84 {
85 m_pTarget = pTarget;
86 m_pDragItem = NULL;
87 }
88 virtual ~CIDropTarget() { }
89
90 //
91 // Accessors for CDropTarget
92 //
93 void Free(void) { ::DrgFreeDraginfo(m_pDragInfo); }
94 PDRAGINFO GetDataSource(void) { return m_pDragInfo; }
95 void SetDataSource(PDRAGINFO pDragInfo) { m_pDragInfo = pDragInfo; }
96 void SetHWND(HWND hWnd) { m_hWnd = hWnd; }
97
98 //
99 // CIDropTarget methods
100 //
101 bool DragLeave(void);
102 MRESULT DragOver(void);
103 MRESULT Drop(void);
104
105 protected:
106
107 PDRAGINFO m_pDragInfo;
108 PDRAGITEM m_pDragItem; // !NULL between DragEnter and DragLeave/Drop
109 wxDropTarget* m_pTarget; // the real target (we're just a proxy)
110 HWND m_hWnd; // window we're associated with
111 }; // end of CLASS CIDropTarget
112
113 bool CIDropTarget::DragLeave()
114 {
115 //
116 // Remove the UI feedback
117 //
118 m_pTarget->OnLeave();
119
120 //
121 // Release the held object
122 //
123 Free();
124 return true;
125 } // end of CIDropTarget::DragLeave
126
127 MRESULT CIDropTarget::DragOver ()
128 {
129 char zBuffer[128];
130 ULONG ulBytes;
131 USHORT uOp = 0;
132 USHORT uIndicator;
133 ULONG ulItems;
134 ULONG i;
135
136 ::DrgAccessDraginfo(m_pDragInfo);
137 switch(m_pDragInfo->usOperation)
138 {
139 case DO_UNKNOWN:
140 Free();
141 return (MRFROM2SHORT(DOR_NODROPOP, 0));
142
143 case DO_DEFAULT:
144 m_pDragItem = ::DrgQueryDragitemPtr(m_pDragInfo, 0);
145 ulBytes = ::DrgQueryStrName( m_pDragItem->hstrContainerName
146 ,128
147 ,zBuffer
148 );
149 if (!ulBytes)
150 return (MRFROM2SHORT(DOR_NODROPOP, 0));
151 else
152 uOp = DO_MOVE;
153 break;
154
155 case DO_COPY:
156 case DO_MOVE:
157 uOp = m_pDragInfo->usOperation;
158 break;
159 }
160 uIndicator = DOR_DROP;
161 ulItems = (ULONG)::DrgQueryDragitemCount(m_pDragInfo);
162 for (i = 0; i < ulItems; i++)
163 {
164 m_pDragItem = ::DrgQueryDragitemPtr(m_pDragInfo, i);
165 if (((m_pDragItem->fsSupportedOps & DO_COPYABLE) &&
166 (uOp == (USHORT)DO_COPY)) ||
167 ((m_pDragItem->fsSupportedOps & DO_MOVEABLE) &&
168 (uOp == (USHORT)DO_COPY)))
169 {
170 if (::DrgVerifyRMF(m_pDragItem, "DRM_OS2FILE", "DRF_UNKNOWN"))
171 uIndicator = (USHORT)DOR_DROP;
172 else
173 uIndicator = (USHORT)DOR_NEVERDROP;
174 }
175 }
176 Free();
177 return (MRFROM2SHORT(uIndicator, uOp));
178 } // end of CIDropTarget::DragOver
179
180 // #pragma page "CIDropTarget::Drop"
181 /////////////////////////////////////////////////////////////////////////////
182 //
183 // CIDropTarget::Drop
184 //
185 // Instructs the drop target to paste data that was just now dropped on it.
186 //
187 // PARAMETERS
188 // pIDataSource -- the data to paste
189 // dwKeyState -- kbd & mouse state
190 // pt -- mouse coordinates
191 // pdwEffect -- effect flag
192 //
193 // RETURN VALUE
194 // STDMETHODIMP S_OK
195 //
196 /////////////////////////////////////////////////////////////////////////////
197 MRESULT CIDropTarget::Drop ()
198 {
199 char zBuffer[128];
200 ULONG ulBytes;
201 USHORT uOp = 0;
202 USHORT uIndicator;
203 ULONG ulItems;
204 ULONG i;
205
206 ::DrgAccessDraginfo(m_pDragInfo);
207 switch(m_pDragInfo->usOperation)
208 {
209 case DO_UNKNOWN:
210 Free();
211 return (MRFROM2SHORT(DOR_NODROPOP, 0));
212
213 case DO_DEFAULT:
214 m_pDragItem = ::DrgQueryDragitemPtr(m_pDragInfo, 0);
215 ulBytes = ::DrgQueryStrName( m_pDragItem->hstrContainerName
216 ,128
217 ,zBuffer
218 );
219 if (!ulBytes)
220 return (MRFROM2SHORT(DOR_NODROPOP, 0));
221 else
222 uOp = DO_MOVE;
223 break;
224
225 case DO_COPY:
226 case DO_MOVE:
227 uOp = m_pDragInfo->usOperation;
228 break;
229 }
230 uIndicator = DOR_DROP;
231 ulItems = (ULONG)::DrgQueryDragitemCount(m_pDragInfo);
232 for (i = 0; i < ulItems; i++)
233 {
234 m_pDragItem = ::DrgQueryDragitemPtr(m_pDragInfo, i);
235 if (((m_pDragItem->fsSupportedOps & DO_COPYABLE) &&
236 (uOp == (USHORT)DO_COPY)) ||
237 ((m_pDragItem->fsSupportedOps & DO_MOVEABLE) &&
238 (uOp == (USHORT)DO_COPY)))
239 {
240 if (::DrgVerifyRMF(m_pDragItem, "DRM_OS2FILE", "DRF_UNKNOWN"))
241 uIndicator = (USHORT)DOR_DROP;
242 else
243 uIndicator = (USHORT)DOR_NEVERDROP;
244 }
245 }
246
247 //
248 // First ask the drop target if it wants data
249 //
250 if (m_pTarget->OnDrop( m_pDragInfo->xDrop
251 ,m_pDragInfo->yDrop
252 ))
253 {
254 wxDragResult eRc = wxDragNone;
255
256 //
257 // And now it has the data
258 //
259 eRc = m_pTarget->OnData( m_pDragInfo->xDrop
260 ,m_pDragInfo->yDrop
261 ,eRc
262 );
263 }
264 //else: OnDrop() returned false, no need to copy data
265
266 //
267 // Release the held object
268 //
269 Free();
270 return (MRFROM2SHORT(uIndicator, uOp));
271 } // end of CIDropTarget::Drop
272
273 // ----------------------------------------------------------------------------
274 // wxDropTarget
275 // ----------------------------------------------------------------------------
276
277 wxDropTarget::wxDropTarget (
278 wxDataObject* pDataObject
279 )
280 {
281 m_dataObject = pDataObject;
282 m_pDropTarget = new CIDropTarget(this);
283 } // end of wxDropTarget::wxDropTarget
284
285 wxDropTarget::~wxDropTarget()
286 {
287 Release();
288 } // end of wxDropTarget::~wxDropTarget
289
290 bool wxDropTarget::GetData ()
291 {
292 wxDataFormat vFormat = GetSupportedFormat(m_pDropTarget->GetDataSource());
293
294 if (vFormat == wxDF_INVALID)
295 {
296 return false;
297 }
298 //
299 // Under OS/2 we already have the data via the attached DRAGITEM's
300 //
301 return true;
302 } // end of wxDropTarget::GetData
303
304 wxDataFormat wxDropTarget::GetSupportedFormat (
305 PDRAGINFO pDataSource
306 ) const
307 {
308 PDRAGITEM pDragItem;
309 wxDataFormat vFormat;
310 wxDataFormat* pFormats;
311 ULONG ulFormats = m_dataObject->GetFormatCount(wxDataObject::Set);
312 ULONG ulItems = (ULONG)::DrgQueryDragitemCount(pDataSource);
313 ULONG i;
314 ULONG n;
315 wxString sMechanism;
316 wxString sFormat;
317 bool bValid = false;
318
319 pFormats = ulFormats == 1 ? &vFormat : new wxDataFormat[ulFormats];
320 m_dataObject->GetAllFormats( pFormats
321 ,wxDataObject::Set
322 );
323
324 for (n = 0; n < ulFormats; n++)
325 {
326 switch(pFormats[n].GetType())
327 {
328 case wxDF_TEXT:
329 case wxDF_FILENAME:
330 case wxDF_HTML:
331 sMechanism = wxT("DRM_OS2FILE");
332 sFormat = wxT("DRF_TEXT");
333 break;
334
335 case wxDF_OEMTEXT:
336 sMechanism = wxT("DRM_OS2FILE");
337 sFormat = wxT("DRF_OEMTEXT");
338 break;
339
340 case wxDF_BITMAP:
341 sMechanism = wxT("DRM_OS2FILE");
342 sFormat = wxT("DRF_BITMAP");
343 break;
344
345 case wxDF_METAFILE:
346 case wxDF_ENHMETAFILE:
347 sMechanism = wxT("DRM_OS2FILE");
348 sFormat = wxT("DRF_METAFILE");
349 break;
350
351 case wxDF_TIFF:
352 sMechanism = wxT("DRM_OS2FILE");
353 sFormat = wxT("DRF_TIFF");
354 break;
355
356 case wxDF_SYLK:
357 sMechanism = wxT("DRM_OS2FILE");
358 sFormat = wxT("DRF_SYLK");
359 break;
360
361 case wxDF_DIF:
362 sMechanism = wxT("DRM_OS2FILE");
363 sFormat = wxT("DRF_DIF");
364 break;
365
366 case wxDF_DIB:
367 sMechanism = wxT("DRM_OS2FILE");
368 sFormat = wxT("DRF_DIB");
369 break;
370
371 case wxDF_PALETTE:
372 case wxDF_PENDATA:
373 case wxDF_RIFF:
374 case wxDF_WAVE:
375 case wxDF_UNICODETEXT:
376 case wxDF_LOCALE:
377 sMechanism = wxT("DRM_OS2FILE");
378 sFormat = wxT("DRF_UNKNOWN");
379 break;
380
381 case wxDF_PRIVATE:
382 sMechanism = wxT("DRM_OBJECT");
383 sFormat = wxT("DRF_UNKNOWN");
384 break;
385 }
386 for (i = 0; i < ulItems; i++)
387 {
388 pDragItem = ::DrgQueryDragitemPtr(pDataSource, i);
389 if (::DrgVerifyRMF(pDragItem, sMechanism.c_str(), sFormat.c_str()))
390 {
391 bValid = true;
392 break;
393 }
394 }
395 if (bValid)
396 {
397 vFormat = pFormats[n];
398 break;
399 }
400 }
401 if (pFormats != &vFormat)
402 {
403 //
404 // Free memory if we allocated it
405 //
406 delete [] pFormats;
407 }
408 return (n < ulFormats ? vFormat : wxFormatInvalid);
409 } // end of wxDropTarget::GetSupportedFormat
410
411 bool wxDropTarget::IsAcceptedData (
412 PDRAGINFO pDataSource
413 ) const
414 {
415 return (GetSupportedFormat(pDataSource) != wxDF_INVALID);
416 } // end of wxDropTarget::IsAcceptedData
417
418 void wxDropTarget::Release ()
419 {
420 m_pDropTarget->Free();
421 } // end of wxDropTarget::Release
422
423
424 wxDragResult wxDropTarget::OnData (
425 wxCoord WXUNUSED(vX)
426 , wxCoord WXUNUSED(y)
427 , wxDragResult WXUNUSED(vResult)
428 )
429 {
430 return (wxDragResult)0;
431 } // end of wxDropTarget::OnData
432
433 bool wxDropTarget::OnDrop (
434 wxCoord WXUNUSED(x)
435 , wxCoord WXUNUSED(y)
436 )
437 {
438 return true;
439 } // end of wxDropTarget::OnDrop
440
441 //-------------------------------------------------------------------------
442 // wxDropSource
443 //-------------------------------------------------------------------------
444
445 wxDropSource::wxDropSource ( wxWindow* WXUNUSED(pWin) )
446 {
447 Init();
448 } // end of wxDropSource::wxDropSource
449
450 wxDropSource::wxDropSource ( wxDataObject& rData, wxWindow* WXUNUSED(pWin) )
451 {
452 Init();
453 SetData(rData);
454 } // end of wxDropSource::wxDropSource
455
456 wxDropSource::~wxDropSource ()
457 {
458 ::DrgFreeDraginfo(m_pDragInfo);
459 } // end of wxDropSource::~wxDropSource
460
461 wxDragResult wxDropSource::DoDragDrop (
462 int WXUNUSED(flags)
463 )
464 {
465 //
466 // Need to specify drag items in derived classes that know their data types
467 // before calling DoDragDrop
468 //
469 if (::DrgDrag( m_pWindow->GetHWND()
470 ,m_pDragInfo
471 ,&m_vDragImage
472 ,m_ulItems
473 ,VK_BUTTON2
474 ,NULL
475 ) != NULLHANDLE)
476 {
477 switch(m_pDragInfo->usOperation)
478 {
479 case DO_COPY:
480 return wxDragCopy;
481
482 case DO_MOVE:
483 return wxDragCopy;
484
485 case DO_LINK:
486 return wxDragCopy;
487
488 default:
489 return wxDragNone;
490 }
491 }
492 return wxDragError;
493 } // end of wxDropSource::DoDragDrop
494
495 bool wxDropSource::GiveFeedback (
496 wxDragResult eEffect
497 )
498 {
499 const wxCursor& rCursor = GetCursor(eEffect);
500
501 if (rCursor.IsOk())
502 {
503 ::WinSetPointer(HWND_DESKTOP, (HPOINTER)rCursor.GetHCURSOR());
504 m_vDragImage.hImage = (LHANDLE)rCursor.GetHCURSOR();
505 switch(eEffect)
506 {
507 case wxDragCopy:
508 m_pDragInfo->usOperation = DO_COPY;
509 break;
510
511 case wxDragMove:
512 m_pDragInfo->usOperation = DO_MOVE;
513 break;
514
515 case wxDragLink:
516 m_pDragInfo->usOperation = DO_LINK;
517 break;
518
519 case wxDragNone:
520 case wxDragCancel:
521 case wxDragError:
522 break;
523 }
524 return true;
525 }
526 else
527 {
528 return false;
529 }
530 } // end of GuiAdvDnd_CDropSource::GiveFeedback
531
532 void wxDropSource::Init ()
533 {
534 m_pDragInfo = ::DrgAllocDraginfo(m_ulItems);
535
536 //
537 // Set a default drag image struct with what we know so far
538 //
539 m_vDragImage.cb = sizeof(DRAGIMAGE);
540 m_vDragImage.cptl = 0; // non-zero if fl is DRG_POLYGON
541 m_vDragImage.hImage = 0; // Set in GiveFeedback
542 m_vDragImage.sizlStretch.cx = 20L;
543 m_vDragImage.sizlStretch.cy = 20L;
544 m_vDragImage.fl = DRG_ICON | DRG_STRETCH;
545 m_vDragImage.cxOffset = 0;
546 m_vDragImage.cyOffset = 0;
547
548 HSTR hStrType = ::DrgAddStrHandle(DRT_UNKNOWN);
549 HSTR hStrRMF;
550 HSTR hStrContainer;
551 wxChar zFormats[128];
552 wxChar zContainer[128];
553 USHORT uSize = (USHORT)(GetDataObject()->GetDataSize(GetDataObject()->GetPreferredFormat()) + 1);
554 wxChar* pzBuffer = new wxChar[uSize];
555
556 memset(pzBuffer, '\0', GetDataObject()->GetDataSize(GetDataObject()->GetPreferredFormat()));
557 pzBuffer[GetDataObject()->GetDataSize(GetDataObject()->GetPreferredFormat())] = '\0';
558 GetDataObject()->GetDataHere( GetDataObject()->GetPreferredFormat()
559 ,(void*)pzBuffer
560 );
561
562 wxStrcpy(zFormats, wxT("<DRM_OS2FILE, DRF_UNKNOWN>"));
563 wxStrcpy(zContainer, GetDataObject()->GetPreferredFormat().GetId());
564
565 hStrRMF = ::DrgAddStrHandle((PSZ)zFormats);
566 hStrContainer = ::DrgAddStrHandle((PSZ)zContainer);
567
568 m_pDragItem = new DRAGITEM[m_ulItems];
569 for (ULONG i = 0; i < m_ulItems; i++)
570 {
571 m_pDragItem[i].hwndItem = m_pWindow->GetHWND();
572 m_pDragItem[i].hstrType = hStrType;
573 m_pDragItem[i].hstrRMF = hStrRMF;
574 m_pDragItem[i].hstrContainerName = hStrContainer;
575 m_pDragItem[i].fsControl = 0;
576 m_pDragItem[i].fsSupportedOps = DO_COPYABLE | DO_MOVEABLE | DO_LINKABLE;
577 m_pDragItem[i].hstrSourceName = ::DrgAddStrHandle((PSZ)pzBuffer);
578 m_pDragItem[i].hstrTargetName = m_pDragItem[i].hstrSourceName;
579 m_pDragItem[i].ulItemID = i;
580 ::DrgSetDragitem( m_pDragInfo
581 ,&m_pDragItem[i]
582 ,sizeof(DRAGITEM)
583 ,0
584 );
585 }
586 delete [] pzBuffer;
587 delete [] m_pDragItem;
588 } // end of wxDropSource::Init
589
590 #endif //wxUSE_DRAG_AND_DROP