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