git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@45276 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
592 lines
17 KiB
C++
592 lines
17 KiB
C++
///////////////////////////////////////////////////////////////////////////////
|
|
// Name: src/os2/dnd.cpp
|
|
// Purpose: wxDropTarget, wxDropSource, wxDataObject implementation
|
|
// Author: David Webster
|
|
// Modified by:
|
|
// Created: 10/21/99
|
|
// RCS-ID: $Id$
|
|
// Copyright: (c) 1998 AUTHOR
|
|
// Licence: wxWindows licence
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
// For compilers that support precompilation, includes "wx.h".
|
|
#include "wx/wxprec.h"
|
|
|
|
#if wxUSE_DRAG_AND_DROP
|
|
|
|
#include "wx/dnd.h"
|
|
|
|
#ifndef WX_PRECOMP
|
|
#include "wx/app.h"
|
|
#include "wx/window.h"
|
|
#include "wx/gdicmn.h"
|
|
#endif
|
|
|
|
#define INCL_PM
|
|
#define INCL_DOS
|
|
#include <os2.h>
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// global
|
|
// ----------------------------------------------------------------------------
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Private functions
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
#if 0
|
|
static wxDragResult ConvertDragEffectToResult (
|
|
DWORD dwEffect
|
|
)
|
|
{
|
|
switch (dwEffect)
|
|
{
|
|
case DO_COPY:
|
|
return wxDragCopy;
|
|
|
|
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;
|
|
|
|
case wxDragLink:
|
|
return DO_LINK;
|
|
|
|
case wxDragMove:
|
|
return DO_MOVE;
|
|
|
|
default:
|
|
case wxDragNone:
|
|
return DO_DEFAULT;
|
|
}
|
|
} // end of ConvertDragResultToEffect
|
|
#endif
|
|
|
|
class CIDropTarget
|
|
{
|
|
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);
|
|
|
|
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()
|
|
{
|
|
//
|
|
// Remove the UI feedback
|
|
//
|
|
m_pTarget->OnLeave();
|
|
|
|
//
|
|
// Release the held object
|
|
//
|
|
Free();
|
|
return true;
|
|
} // end of CIDropTarget::DragLeave
|
|
|
|
MRESULT CIDropTarget::DragOver ()
|
|
{
|
|
char zBuffer[128];
|
|
ULONG ulBytes;
|
|
USHORT uOp = 0;
|
|
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;
|
|
}
|
|
}
|
|
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 ()
|
|
{
|
|
char zBuffer[128];
|
|
ULONG ulBytes;
|
|
USHORT uOp = 0;
|
|
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 = wxDragNone;
|
|
|
|
//
|
|
// 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
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// wxDropTarget
|
|
// ----------------------------------------------------------------------------
|
|
|
|
wxDropTarget::wxDropTarget (
|
|
wxDataObject* pDataObject
|
|
)
|
|
{
|
|
m_dataObject = pDataObject;
|
|
m_pDropTarget = new CIDropTarget(this);
|
|
} // end of wxDropTarget::wxDropTarget
|
|
|
|
wxDropTarget::~wxDropTarget()
|
|
{
|
|
Release();
|
|
} // end of wxDropTarget::~wxDropTarget
|
|
|
|
bool wxDropTarget::GetData ()
|
|
{
|
|
wxDataFormat vFormat = GetSupportedFormat(m_pDropTarget->GetDataSource());
|
|
|
|
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
|
|
|
|
wxDataFormat wxDropTarget::GetSupportedFormat (
|
|
PDRAGINFO pDataSource
|
|
) const
|
|
{
|
|
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
|
|
);
|
|
|
|
for (n = 0; n < ulFormats; n++)
|
|
{
|
|
switch(pFormats[n].GetType())
|
|
{
|
|
case wxDF_TEXT:
|
|
case wxDF_FILENAME:
|
|
case wxDF_HTML:
|
|
sMechanism = _T("DRM_OS2FILE");
|
|
sFormat = _T("DRF_TEXT");
|
|
break;
|
|
|
|
case wxDF_OEMTEXT:
|
|
sMechanism = _T("DRM_OS2FILE");
|
|
sFormat = _T("DRF_OEMTEXT");
|
|
break;
|
|
|
|
case wxDF_BITMAP:
|
|
sMechanism = _T("DRM_OS2FILE");
|
|
sFormat = _T("DRF_BITMAP");
|
|
break;
|
|
|
|
case wxDF_METAFILE:
|
|
case wxDF_ENHMETAFILE:
|
|
sMechanism = _T("DRM_OS2FILE");
|
|
sFormat = _T("DRF_METAFILE");
|
|
break;
|
|
|
|
case wxDF_TIFF:
|
|
sMechanism = _T("DRM_OS2FILE");
|
|
sFormat = _T("DRF_TIFF");
|
|
break;
|
|
|
|
case wxDF_SYLK:
|
|
sMechanism = _T("DRM_OS2FILE");
|
|
sFormat = _T("DRF_SYLK");
|
|
break;
|
|
|
|
case wxDF_DIF:
|
|
sMechanism = _T("DRM_OS2FILE");
|
|
sFormat = _T("DRF_DIF");
|
|
break;
|
|
|
|
case wxDF_DIB:
|
|
sMechanism = _T("DRM_OS2FILE");
|
|
sFormat = _T("DRF_DIB");
|
|
break;
|
|
|
|
case wxDF_PALETTE:
|
|
case wxDF_PENDATA:
|
|
case wxDF_RIFF:
|
|
case wxDF_WAVE:
|
|
case wxDF_UNICODETEXT:
|
|
case wxDF_LOCALE:
|
|
sMechanism = _T("DRM_OS2FILE");
|
|
sFormat = _T("DRF_UNKNOWN");
|
|
break;
|
|
|
|
case wxDF_PRIVATE:
|
|
sMechanism = _T("DRM_OBJECT");
|
|
sFormat = _T("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 true;
|
|
} // end of wxDropTarget::OnDrop
|
|
|
|
//-------------------------------------------------------------------------
|
|
// wxDropSource
|
|
//-------------------------------------------------------------------------
|
|
|
|
wxDropSource::wxDropSource ( wxWindow* WXUNUSED(pWin) )
|
|
{
|
|
Init();
|
|
} // end of wxDropSource::wxDropSource
|
|
|
|
wxDropSource::wxDropSource ( wxDataObject& rData, wxWindow* WXUNUSED(pWin) )
|
|
{
|
|
Init();
|
|
SetData(rData);
|
|
} // end of wxDropSource::wxDropSource
|
|
|
|
wxDropSource::~wxDropSource ()
|
|
{
|
|
::DrgFreeDraginfo(m_pDragInfo);
|
|
} // end of wxDropSource::~wxDropSource
|
|
|
|
wxDragResult wxDropSource::DoDragDrop (
|
|
int WXUNUSED(flags)
|
|
)
|
|
{
|
|
//
|
|
// 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;
|
|
|
|
case DO_MOVE:
|
|
return wxDragCopy;
|
|
|
|
case DO_LINK:
|
|
return wxDragCopy;
|
|
|
|
default:
|
|
return wxDragNone;
|
|
}
|
|
}
|
|
return wxDragError;
|
|
} // end of wxDropSource::DoDragDrop
|
|
|
|
bool wxDropSource::GiveFeedback (
|
|
wxDragResult eEffect
|
|
)
|
|
{
|
|
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 ()
|
|
{
|
|
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;
|
|
wxChar zFormats[128];
|
|
wxChar zContainer[128];
|
|
USHORT uSize = (USHORT)(GetDataObject()->GetDataSize(GetDataObject()->GetPreferredFormat()) + 1);
|
|
wxChar* pzBuffer = new wxChar[uSize];
|
|
|
|
memset(pzBuffer, '\0', GetDataObject()->GetDataSize(GetDataObject()->GetPreferredFormat()));
|
|
pzBuffer[GetDataObject()->GetDataSize(GetDataObject()->GetPreferredFormat())] = '\0';
|
|
GetDataObject()->GetDataHere( GetDataObject()->GetPreferredFormat()
|
|
,(void*)pzBuffer
|
|
);
|
|
|
|
wxStrcpy(zFormats, _T("<DRM_OS2FILE, DRF_UNKNOWN>"));
|
|
wxStrcpy(zContainer, GetDataObject()->GetPreferredFormat().GetId());
|
|
|
|
hStrRMF = ::DrgAddStrHandle((PSZ)zFormats);
|
|
hStrContainer = ::DrgAddStrHandle((PSZ)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((PSZ)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
|