///////////////////////////////////////////////////////////////////////////////
// Name: dnd.cpp
// Purpose: wxDropTarget, wxDropSource, wxDataObject implementation
-// Author: AUTHOR
+// Author: David Webster
// Modified by:
-// Created: ??/??/98
+// Created: 10/21/99
// RCS-ID: $Id$
// Copyright: (c) 1998 AUTHOR
// Licence: wxWindows licence
#pragma implementation "dnd.h"
#endif
-#include "wx/dnd.h"
#include "wx/window.h"
#include "wx/app.h"
#include "wx/gdicmn.h"
+#include "wx/dnd.h"
+
+#define INCL_PM
+#define INCL_DOS
+#include <os2.h>
+
+#if wxUSE_DRAG_AND_DROP
// ----------------------------------------------------------------------------
// global
// ----------------------------------------------------------------------------
-// ----------------------------------------------------------------------------
-// wxDropTarget
-// ----------------------------------------------------------------------------
+/////////////////////////////////////////////////////////////////////////////
+// Private functions
+/////////////////////////////////////////////////////////////////////////////
-wxDropTarget::wxDropTarget()
+#if 0
+static wxDragResult ConvertDragEffectToResult (
+ DWORD dwEffect
+)
{
-};
+ switch (dwEffect)
+ {
+ case DO_COPY:
+ return wxDragCopy;
-wxDropTarget::~wxDropTarget()
+ case DO_LINK:
+ return wxDragLink;
+
+ case DO_MOVE:
+ return wxDragMove;
+
+ default:
+ case DO_DEFAULT:
+ return wxDragNone;
+ }
+} // end of ConvertDragEffectToResult
+
+static DWORD ConvertDragResultToEffect (
+ wxDragResult eResult
+)
{
-};
+ switch (eResult)
+ {
+ case wxDragCopy:
+ return DO_COPY;
-// ----------------------------------------------------------------------------
-// wxTextDropTarget
-// ----------------------------------------------------------------------------
+ case wxDragLink:
+ return DO_LINK;
+
+ case wxDragMove:
+ return DO_MOVE;
-bool wxTextDropTarget::OnDrop( long x, long y, const void *pData )
+ default:
+ case wxDragNone:
+ return DO_DEFAULT;
+ }
+} // end of ConvertDragResultToEffect
+#endif
+
+class CIDropTarget
{
- OnDropText( x, y, (const char*)pData );
- return TRUE;
-};
+public:
+ CIDropTarget(wxDropTarget* pTarget)
+ {
+ m_pTarget = pTarget;
+ m_pDragItem = NULL;
+ }
+ virtual ~CIDropTarget() { }
+
+ //
+ // Accessors for CDropTarget
+ //
+ void Free(void) { ::DrgFreeDraginfo(m_pDragInfo); }
+ PDRAGINFO GetDataSource(void) { return m_pDragInfo; }
+ void SetDataSource(PDRAGINFO pDragInfo) { m_pDragInfo = pDragInfo; }
+ void SetHWND(HWND hWnd) { m_hWnd = hWnd; }
+
+ //
+ // CIDropTarget methods
+ //
+ bool DragLeave(void);
+ MRESULT DragOver(void);
+ MRESULT Drop(void);
-bool wxTextDropTarget::OnDropText( long x, long y, const char *psz )
+protected:
+
+ PDRAGINFO m_pDragInfo;
+ PDRAGITEM m_pDragItem; // !NULL between DragEnter and DragLeave/Drop
+ wxDropTarget* m_pTarget; // the real target (we're just a proxy)
+ HWND m_hWnd; // window we're associated with
+}; // end of CLASS CIDropTarget
+
+bool CIDropTarget::DragLeave()
{
- printf( "Got dropped text: %s.\n", psz );
- printf( "At x: %d, y: %d.\n", (int)x, (int)y );
- return TRUE;
-};
+ //
+ // Remove the UI feedback
+ //
+ m_pTarget->OnLeave();
+
+ //
+ // Release the held object
+ //
+ Free();
+ return TRUE;
+} // end of CIDropTarget::DragLeave
-size_t wxTextDropTarget::GetFormatCount() const
+MRESULT CIDropTarget::DragOver ()
{
- return 1;
-}
+ char zBuffer[128];
+ ULONG ulBytes;
+ USHORT uOp;
+ USHORT uIndicator;
+ ULONG ulItems;
+ ULONG i;
+
+ ::DrgAccessDraginfo(m_pDragInfo);
+ switch(m_pDragInfo->usOperation)
+ {
+ case DO_UNKNOWN:
+ Free();
+ return (MRFROM2SHORT(DOR_NODROPOP, 0));
+
+ case DO_DEFAULT:
+ m_pDragItem = ::DrgQueryDragitemPtr(m_pDragInfo, 0);
+ ulBytes = ::DrgQueryStrName( m_pDragItem->hstrContainerName
+ ,128
+ ,zBuffer
+ );
+ if (!ulBytes)
+ return (MRFROM2SHORT(DOR_NODROPOP, 0));
+ else
+ uOp = DO_MOVE;
+ break;
-wxDataFormat wxTextDropTarget::GetFormat(size_t WXUNUSED(n)) const
+ case DO_COPY:
+ case DO_MOVE:
+ uOp = m_pDragInfo->usOperation;
+ break;
+ }
+ uIndicator = DOR_DROP;
+ ulItems = (ULONG)::DrgQueryDragitemCount(m_pDragInfo);
+ for (i = 0; i < ulItems; i++)
+ {
+ m_pDragItem = ::DrgQueryDragitemPtr(m_pDragInfo, i);
+ if (((m_pDragItem->fsSupportedOps & DO_COPYABLE) &&
+ (uOp == (USHORT)DO_COPY)) ||
+ ((m_pDragItem->fsSupportedOps & DO_MOVEABLE) &&
+ (uOp == (USHORT)DO_COPY)))
+ {
+ if (::DrgVerifyRMF(m_pDragItem, "DRM_OS2FILE", "DRF_UNKNOWN"))
+ uIndicator = (USHORT)DOR_DROP;
+ else
+ uIndicator = (USHORT)DOR_NEVERDROP;
+ }
+ }
+ Free();
+ return (MRFROM2SHORT(uIndicator, uOp));
+} // end of CIDropTarget::DragOver
+
+// #pragma page "CIDropTarget::Drop"
+/////////////////////////////////////////////////////////////////////////////
+//
+// CIDropTarget::Drop
+//
+// Instructs the drop target to paste data that was just now dropped on it.
+//
+// PARAMETERS
+// pIDataSource -- the data to paste
+// dwKeyState -- kbd & mouse state
+// pt -- mouse coordinates
+// pdwEffect -- effect flag
+//
+// RETURN VALUE
+// STDMETHODIMP S_OK
+//
+/////////////////////////////////////////////////////////////////////////////
+MRESULT CIDropTarget::Drop ()
{
- return wxDF_TEXT;
-}
+ char zBuffer[128];
+ ULONG ulBytes;
+ USHORT uOp;
+ USHORT uIndicator;
+ ULONG ulItems;
+ ULONG i;
+
+ ::DrgAccessDraginfo(m_pDragInfo);
+ switch(m_pDragInfo->usOperation)
+ {
+ case DO_UNKNOWN:
+ Free();
+ return (MRFROM2SHORT(DOR_NODROPOP, 0));
+
+ case DO_DEFAULT:
+ m_pDragItem = ::DrgQueryDragitemPtr(m_pDragInfo, 0);
+ ulBytes = ::DrgQueryStrName( m_pDragItem->hstrContainerName
+ ,128
+ ,zBuffer
+ );
+ if (!ulBytes)
+ return (MRFROM2SHORT(DOR_NODROPOP, 0));
+ else
+ uOp = DO_MOVE;
+ break;
+
+ case DO_COPY:
+ case DO_MOVE:
+ uOp = m_pDragInfo->usOperation;
+ break;
+ }
+ uIndicator = DOR_DROP;
+ ulItems = (ULONG)::DrgQueryDragitemCount(m_pDragInfo);
+ for (i = 0; i < ulItems; i++)
+ {
+ m_pDragItem = ::DrgQueryDragitemPtr(m_pDragInfo, i);
+ if (((m_pDragItem->fsSupportedOps & DO_COPYABLE) &&
+ (uOp == (USHORT)DO_COPY)) ||
+ ((m_pDragItem->fsSupportedOps & DO_MOVEABLE) &&
+ (uOp == (USHORT)DO_COPY)))
+ {
+ if (::DrgVerifyRMF(m_pDragItem, "DRM_OS2FILE", "DRF_UNKNOWN"))
+ uIndicator = (USHORT)DOR_DROP;
+ else
+ uIndicator = (USHORT)DOR_NEVERDROP;
+ }
+ }
+
+ //
+ // First ask the drop target if it wants data
+ //
+ if (m_pTarget->OnDrop( m_pDragInfo->xDrop
+ ,m_pDragInfo->yDrop
+ ))
+ {
+ wxDragResult eRc;
+
+ //
+ // And now it has the data
+ //
+ eRc = m_pTarget->OnData( m_pDragInfo->xDrop
+ ,m_pDragInfo->yDrop
+ ,eRc
+ );
+ }
+ //else: OnDrop() returned FALSE, no need to copy data
+
+ //
+ // Release the held object
+ //
+ Free();
+ return (MRFROM2SHORT(uIndicator, uOp));
+} // end of CIDropTarget::Drop
// ----------------------------------------------------------------------------
-// wxFileDropTarget
+// wxDropTarget
// ----------------------------------------------------------------------------
-bool wxFileDropTarget::OnDropFiles( long x, long y, size_t nFiles, const char * const WXUNUSED(aszFiles)[] )
+wxDropTarget::wxDropTarget (
+ wxDataObject* pDataObject
+)
{
- printf( "Got %d dropped files.\n", (int)nFiles );
- printf( "At x: %d, y: %d.\n", (int)x, (int)y );
- return TRUE;
-}
+ m_dataObject = pDataObject;
+ m_pDropTarget = new CIDropTarget(this);
+} // end of wxDropTarget::wxDropTarget
-bool wxFileDropTarget::OnDrop(long x, long y, const void *WXUNUSED(pData) )
+wxDropTarget::~wxDropTarget()
+{
+ Release();
+} // end of wxDropTarget::~wxDropTarget
+
+bool wxDropTarget::GetData ()
{
- char *str = "/this/is/a/path.txt";
+ wxDataFormat vFormat = GetSupportedFormat(m_pDropTarget->GetDataSource());
- return OnDropFiles(x, y, 1, &str );
-}
+ if (vFormat == wxDF_INVALID)
+ {
+ return FALSE;
+ }
+ //
+ // Under OS/2 we already have the data via the attached DRAGITEM's
+ //
+ return TRUE;
+} // end of wxDropTarget::GetData
-size_t wxFileDropTarget::GetFormatCount() const
+wxDataFormat wxDropTarget::GetSupportedFormat (
+ PDRAGINFO pDataSource
+) const
{
- return 1;
-}
+ PDRAGITEM pDragItem;
+ wxDataFormat vFormat;
+ wxDataFormat* pFormats;
+ ULONG ulFormats = m_dataObject->GetFormatCount(wxDataObject::Set);
+ ULONG ulItems = (ULONG)::DrgQueryDragitemCount(pDataSource);
+ ULONG i;
+ ULONG n;
+ wxString sMechanism;
+ wxString sFormat;
+ bool bValid = FALSE;
+
+ pFormats = ulFormats == 1 ? &vFormat : new wxDataFormat[ulFormats];
+ m_dataObject->GetAllFormats( pFormats
+ ,wxDataObject::Set
+ );
-wxDataFormat wxFileDropTarget::GetFormat(size_t WXUNUSED(n)) const
+ for (n = 0; n < ulFormats; n++)
+ {
+ switch(pFormats[n].GetType())
+ {
+ case wxDF_TEXT:
+ case wxDF_FILENAME:
+ case wxDF_HTML:
+ sMechanism = "DRM_OS2FILE";
+ sFormat = "DRF_TEXT";
+ break;
+
+ case wxDF_OEMTEXT:
+ sMechanism = "DRM_OS2FILE";
+ sFormat = "DRF_OEMTEXT";
+ break;
+
+ case wxDF_BITMAP:
+ sMechanism = "DRM_OS2FILE";
+ sFormat = "DRF_BITMAP";
+ break;
+
+ case wxDF_METAFILE:
+ case wxDF_ENHMETAFILE:
+ sMechanism = "DRM_OS2FILE";
+ sFormat = "DRF_METAFILE";
+ break;
+
+ case wxDF_TIFF:
+ sMechanism = "DRM_OS2FILE";
+ sFormat = "DRF_TIFF";
+ break;
+
+ case wxDF_SYLK:
+ sMechanism = "DRM_OS2FILE";
+ sFormat = "DRF_SYLK";
+ break;
+
+ case wxDF_DIF:
+ sMechanism = "DRM_OS2FILE";
+ sFormat = "DRF_DIF";
+ break;
+
+ case wxDF_DIB:
+ sMechanism = "DRM_OS2FILE";
+ sFormat = "DRF_DIB";
+ break;
+
+ case wxDF_PALETTE:
+ case wxDF_PENDATA:
+ case wxDF_RIFF:
+ case wxDF_WAVE:
+ case wxDF_UNICODETEXT:
+ case wxDF_LOCALE:
+ sMechanism = "DRM_OS2FILE";
+ sFormat = "DRF_UNKNOWN";
+ break;
+
+ case wxDF_PRIVATE:
+ sMechanism = "DRM_OBJECT";
+ sFormat = "DRF_UNKNOWN";
+ break;
+ }
+ for (i = 0; i < ulItems; i++)
+ {
+ pDragItem = ::DrgQueryDragitemPtr(pDataSource, i);
+ if (::DrgVerifyRMF(pDragItem, sMechanism.c_str(), sFormat.c_str()))
+ {
+ bValid = TRUE;
+ break;
+ }
+ }
+ if (bValid)
+ {
+ vFormat = pFormats[n];
+ break;
+ }
+ }
+ if (pFormats != &vFormat)
+ {
+ //
+ // Free memory if we allocated it
+ //
+ delete [] pFormats;
+ }
+ return (n < ulFormats ? vFormat : wxFormatInvalid);
+} // end of wxDropTarget::GetSupportedFormat
+
+bool wxDropTarget::IsAcceptedData (
+ PDRAGINFO pDataSource
+) const
+{
+ return (GetSupportedFormat(pDataSource) != wxDF_INVALID);
+} // end of wxDropTarget::IsAcceptedData
+
+void wxDropTarget::Release ()
+{
+ m_pDropTarget->Free();
+} // end of wxDropTarget::Release
+
+
+wxDragResult wxDropTarget::OnData (
+ wxCoord WXUNUSED(vX)
+, wxCoord WXUNUSED(y)
+, wxDragResult WXUNUSED(vResult)
+)
+{
+ return (wxDragResult)0;
+} // end of wxDropTarget::OnData
+
+bool wxDropTarget::OnDrop (
+ wxCoord WXUNUSED(x)
+, wxCoord WXUNUSED(y)
+)
{
- return wxDF_FILENAME;
-}
+ return TRUE;
+} // end of wxDropTarget::OnDrop
//-------------------------------------------------------------------------
// wxDropSource
//-------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-// drag request
+wxDropSource::wxDropSource (
+ wxWindow* pWin
+)
+{
+ Init();
+} // end of wxDropSource::wxDropSource
-wxDropSource::wxDropSource( wxWindow *win )
+wxDropSource::wxDropSource (
+ wxDataObject& rData
+, wxWindow* pWin
+)
{
- // TODO
- // m_window = win;
- m_data = NULL;
+ Init();
+ SetData(rData);
+} // end of wxDropSource::wxDropSource
- // m_defaultCursor = wxCursor( wxCURSOR_NO_ENTRY );
- // m_goaheadCursor = wxCursor( wxCURSOR_HAND );
-};
+wxDropSource::~wxDropSource ()
+{
+ ::DrgFreeDraginfo(m_pDragInfo);
+} // end of wxDropSource::~wxDropSource
-wxDropSource::wxDropSource( wxDataObject &data, wxWindow *win )
+wxDragResult wxDropSource::DoDragDrop (
+ int WXUNUSED(flags)
+)
{
- // TODO
- // m_window = win;
- m_data = &data;
+ //
+ // Need to specify drag items in derived classes that know their data types
+ // before calling DoDragDrop
+ //
+ if (::DrgDrag( m_pWindow->GetHWND()
+ ,m_pDragInfo
+ ,&m_vDragImage
+ ,m_ulItems
+ ,VK_BUTTON2
+ ,NULL
+ ) != NULLHANDLE)
+ {
+ switch(m_pDragInfo->usOperation)
+ {
+ case DO_COPY:
+ return wxDragCopy;
- // m_defaultCursor = wxCursor( wxCURSOR_NO_ENTRY );
- // m_goaheadCursor = wxCursor( wxCURSOR_HAND );
-};
+ case DO_MOVE:
+ return wxDragCopy;
-void wxDropSource::SetData( wxDataObject &data )
-{
- m_data = &data;
-};
+ case DO_LINK:
+ return wxDragCopy;
+
+ default:
+ return wxDragNone;
+ }
+ }
+ return wxDragError;
+} // end of wxDropSource::DoDragDrop
-wxDropSource::~wxDropSource(void)
+bool wxDropSource::GiveFeedback (
+ wxDragResult eEffect
+)
{
-};
-
-wxDragResult wxDropSource::DoDragDrop( bool WXUNUSED(bAllowMove) )
+ const wxCursor& rCursor = GetCursor(eEffect);
+
+ if (rCursor.Ok())
+ {
+ ::WinSetPointer(HWND_DESKTOP, (HPOINTER)rCursor.GetHCURSOR());
+ m_vDragImage.hImage = (LHANDLE)rCursor.GetHCURSOR();
+ switch(eEffect)
+ {
+ case wxDragCopy:
+ m_pDragInfo->usOperation = DO_COPY;
+ break;
+
+ case wxDragMove:
+ m_pDragInfo->usOperation = DO_MOVE;
+ break;
+
+ case wxDragLink:
+ m_pDragInfo->usOperation = DO_LINK;
+ break;
+
+ case wxDragNone:
+ case wxDragCancel:
+ case wxDragError:
+ break;
+ }
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
+} // end of GuiAdvDnd_CDropSource::GiveFeedback
+
+void wxDropSource::Init ()
{
- // TODO
- return wxDragError;
-};
+ m_pDragInfo = ::DrgAllocDraginfo(m_ulItems);
+
+ //
+ // Set a default drag image struct with what we know so far
+ //
+ m_vDragImage.cb = sizeof(DRAGIMAGE);
+ m_vDragImage.cptl = 0; // non-zero if fl is DRG_POLYGON
+ m_vDragImage.hImage = 0; // Set in GiveFeedback
+ m_vDragImage.sizlStretch.cx = 20L;
+ m_vDragImage.sizlStretch.cy = 20L;
+ m_vDragImage.fl = DRG_ICON | DRG_STRETCH;
+ m_vDragImage.cxOffset = 0;
+ m_vDragImage.cyOffset = 0;
+
+ HSTR hStrType = ::DrgAddStrHandle(DRT_UNKNOWN);
+ HSTR hStrRMF;
+ HSTR hStrContainer;
+ char zFormats[128];
+ char zContainer[128];
+ USHORT uSize = GetDataObject()->GetDataSize(GetDataObject()->GetPreferredFormat()) + 1;
+ char* pzBuffer = new char[uSize];
+
+ memset(pzBuffer, '\0', GetDataObject()->GetDataSize(GetDataObject()->GetPreferredFormat()));
+ pzBuffer[GetDataObject()->GetDataSize(GetDataObject()->GetPreferredFormat())] = '\0';
+ GetDataObject()->GetDataHere( GetDataObject()->GetPreferredFormat()
+ ,(void*)pzBuffer
+ );
+
+ strcpy(zFormats, "<DRM_OS2FILE, DRF_UNKNOWN>");
+ strcpy(zContainer, GetDataObject()->GetPreferredFormat().GetId().c_str());
+
+ hStrRMF = ::DrgAddStrHandle(zFormats);
+ hStrContainer = ::DrgAddStrHandle(zContainer);
+
+ m_pDragItem = new DRAGITEM[m_ulItems];
+ for (ULONG i = 0; i < m_ulItems; i++)
+ {
+ m_pDragItem[i].hwndItem = m_pWindow->GetHWND();
+ m_pDragItem[i].hstrType = hStrType;
+ m_pDragItem[i].hstrRMF = hStrRMF;
+ m_pDragItem[i].hstrContainerName = hStrContainer;
+ m_pDragItem[i].fsControl = 0;
+ m_pDragItem[i].fsSupportedOps = DO_COPYABLE | DO_MOVEABLE | DO_LINKABLE;
+ m_pDragItem[i].hstrSourceName = ::DrgAddStrHandle(pzBuffer);
+ m_pDragItem[i].hstrTargetName = m_pDragItem[i].hstrSourceName;
+ m_pDragItem[i].ulItemID = i;
+ ::DrgSetDragitem( m_pDragInfo
+ ,&m_pDragItem[i]
+ ,sizeof(DRAGITEM)
+ ,0
+ );
+ }
+ delete [] pzBuffer;
+ delete [] m_pDragItem;
+} // end of wxDropSource::Init
+#endif //wxUSE_DRAG_AND_DROP