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