X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/892b89f3b79a756ba3c278c605b79a6fa377d60f..d1bab566475b6573c1c0c982eec395c6d8eef13a:/src/os2/dnd.cpp diff --git a/src/os2/dnd.cpp b/src/os2/dnd.cpp index f8ed534d5d..6a645291fc 100644 --- a/src/os2/dnd.cpp +++ b/src/os2/dnd.cpp @@ -21,116 +21,566 @@ #include "wx/gdicmn.h" #include "wx/dnd.h" +#if wxUSE_DRAG_AND_DROP + // ---------------------------------------------------------------------------- // global // ---------------------------------------------------------------------------- +///////////////////////////////////////////////////////////////////////////// +// Private functions +///////////////////////////////////////////////////////////////////////////// + +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 + +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; + 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; + 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 + // ---------------------------------------------------------------------------- // 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 = "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 { - //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( +wxDropSource::wxDropSource ( wxWindow* pWin ) { - // TODO -}; + Init(); +} // end of wxDropSource::wxDropSource -wxDropSource::wxDropSource( +wxDropSource::wxDropSource ( wxDataObject& rData , wxWindow* 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 -void wxDropSource::Init() +bool wxDropSource::GiveFeedback ( + wxDragResult eEffect +) { - // TODO -}; + 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; + } + 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; + 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, ""); + 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