X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/16a12a3d27d3d3e2557bcde15365245ef2675bb4..8e1a5bf979fcdf82238b20cda1209a4f67f394c0:/src/os2/dnd.cpp diff --git a/src/os2/dnd.cpp b/src/os2/dnd.cpp index 452c5a2abc..0f61318b77 100644 --- a/src/os2/dnd.cpp +++ b/src/os2/dnd.cpp @@ -1,5 +1,5 @@ /////////////////////////////////////////////////////////////////////////////// -// Name: dnd.cpp +// Name: src/os2/dnd.cpp // Purpose: wxDropTarget, wxDropSource, wxDataObject implementation // Author: David Webster // Modified by: @@ -9,127 +9,584 @@ // Licence: wxWindows licence /////////////////////////////////////////////////////////////////////////////// -#ifdef __GNUG__ -#pragma implementation "dnd.h" +// 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" #endif +#include "wx/gdicmn.h" + #define INCL_PM +#define INCL_DOS #include -#include "wx/window.h" -#include "wx/app.h" -#include "wx/gdicmn.h" -#include "wx/dnd.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( +wxDropTarget::wxDropTarget ( wxDataObject* pDataObject ) { - // TODO: -}; + m_dataObject = pDataObject; + m_pDropTarget = new CIDropTarget(this); +} // end of wxDropTarget::wxDropTarget wxDropTarget::~wxDropTarget() { -}; + Release(); +} // end of wxDropTarget::~wxDropTarget -void wxDropTarget::Register( - WXHWND hwnd -) +bool wxDropTarget::GetData () { - //TODO: -}; + wxDataFormat vFormat = GetSupportedFormat(m_pDropTarget->GetDataSource()); -void wxDropTarget::Revoke( - WXHWND hwnd -) + 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 { - //TODO: -}; + 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; -wxDragResult wxDropTarget::OnDragOver( - wxCoord x -, wxCoord y -, wxDragResult vDef -) + 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, (PSZ)sMechanism.c_str(), (PSZ)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 { - //TODO: - return vDef; -}; + return (GetSupportedFormat(pDataSource) != wxDF_INVALID); +} // end of wxDropTarget::IsAcceptedData -bool wxDropTarget::OnDrop( - wxCoord x -, wxCoord y -) +void wxDropTarget::Release () { - //TODO: - return FALSE; -}; + m_pDropTarget->Free(); +} // end of wxDropTarget::Release + -wxDragResult wxDropTarget::OnData( - wxCoord x -, wxCoord y -, wxDragResult vResult +wxDragResult wxDropTarget::OnData ( + wxCoord WXUNUSED(vX) +, wxCoord WXUNUSED(y) +, wxDragResult WXUNUSED(vResult) ) { - //TODO: return (wxDragResult)0; -}; +} // end of wxDropTarget::OnData -bool wxDropTarget::GetData() -{ - //TODO: - return FALSE; -}; - -bool wxDropTarget::IsAcceptable( - DRAGINFO* pInfo +bool wxDropTarget::OnDrop ( + wxCoord WXUNUSED(x) +, wxCoord WXUNUSED(y) ) { - //TODO: - return FALSE; -}; + return true; +} // end of wxDropTarget::OnDrop //------------------------------------------------------------------------- // wxDropSource //------------------------------------------------------------------------- -wxDropSource::wxDropSource( - wxWindow* pWin -) +wxDropSource::wxDropSource ( wxWindow* WXUNUSED(pWin) ) { - // TODO -}; + Init(); +} // end of wxDropSource::wxDropSource -wxDropSource::wxDropSource( - wxDataObject& rData -, wxWindow* pWin -) +wxDropSource::wxDropSource ( wxDataObject& rData, wxWindow* WXUNUSED(pWin) ) { - // TODO -}; + Init(); + SetData(rData); +} // end of wxDropSource::wxDropSource -wxDropSource::~wxDropSource() +wxDropSource::~wxDropSource () { - // TODO -}; + ::DrgFreeDraginfo(m_pDragInfo); +} // end of wxDropSource::~wxDropSource -wxDragResult wxDropSource::DoDragDrop( - bool WXUNUSED(bAllowMove) +wxDragResult wxDropSource::DoDragDrop ( + int WXUNUSED(flags) ) { - // TODO + // + // 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); -void wxDropSource::Init() + 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 -}; + 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("")); + 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