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