X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/0e320a79f187558effb04d92020b470372bbe456..1034a6bbff7d4968ab8e273c0b94b49b0a2ae8e2:/src/os2/dnd.cpp diff --git a/src/os2/dnd.cpp b/src/os2/dnd.cpp index 32088eef0f..3a968d3586 100644 --- a/src/os2/dnd.cpp +++ b/src/os2/dnd.cpp @@ -1,133 +1,591 @@ /////////////////////////////////////////////////////////////////////////////// -// Name: dnd.cpp +// Name: src/os2/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 /////////////////////////////////////////////////////////////////////////////// -#ifdef __GNUG__ -#pragma implementation "dnd.h" -#endif +// For compilers that support precompilation, includes "wx.h". +#include "wx/wxprec.h" + +#if wxUSE_DRAG_AND_DROP #include "wx/dnd.h" -#include "wx/window.h" -#include "wx/app.h" -#include "wx/gdicmn.h" + +#ifndef WX_PRECOMP + #include "wx/app.h" + #include "wx/window.h" + #include "wx/gdicmn.h" +#endif + +#define INCL_PM +#define INCL_DOS +#include // ---------------------------------------------------------------------------- // 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; -bool wxTextDropTarget::OnDrop( long x, long y, const void *pData ) + case wxDragMove: + return DO_MOVE; + + 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; } -bool wxTextDropTarget::OnDropText( long x, long y, const char *psz ) + // + // 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() { - 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(); -size_t wxTextDropTarget::GetFormatCount() const + // + // Release the held object + // + Free(); + return true; +} // end of CIDropTarget::DragLeave + +MRESULT CIDropTarget::DragOver () { - return 1; -} + 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)); -wxDataFormat wxTextDropTarget::GetFormat(size_t WXUNUSED(n)) const + 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 () { - return wxDF_TEXT; -} + 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 // ---------------------------------------------------------------------------- -// wxFileDropTarget +// wxDropTarget // ---------------------------------------------------------------------------- -bool wxFileDropTarget::OnDropFiles( long x, long y, size_t nFiles, const char * const WXUNUSED(aszFiles)[] ) +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 { - printf( "Got %d dropped files.\n", (int)nFiles ); - printf( "At x: %d, y: %d.\n", (int)x, (int)y ); - return TRUE; -} + return (GetSupportedFormat(pDataSource) != wxDF_INVALID); +} // end of wxDropTarget::IsAcceptedData -bool wxFileDropTarget::OnDrop(long x, long y, const void *WXUNUSED(pData) ) +void wxDropTarget::Release () { - char *str = "/this/is/a/path.txt"; + m_pDropTarget->Free(); +} // end of wxDropTarget::Release - return OnDropFiles(x, y, 1, &str ); -} -size_t wxFileDropTarget::GetFormatCount() const +wxDragResult wxDropTarget::OnData ( + wxCoord WXUNUSED(vX) +, wxCoord WXUNUSED(y) +, wxDragResult WXUNUSED(vResult) +) { - return 1; -} + return (wxDragResult)0; +} // end of wxDropTarget::OnData -wxDataFormat wxFileDropTarget::GetFormat(size_t WXUNUSED(n)) const +bool wxDropTarget::OnDrop ( + wxCoord WXUNUSED(x) +, wxCoord WXUNUSED(y) +) { - return wxDF_FILENAME; -} + return true; +} // end of wxDropTarget::OnDrop //------------------------------------------------------------------------- // wxDropSource //------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -// drag request +wxDropSource::wxDropSource ( wxWindow* WXUNUSED(pWin) ) +{ + Init(); +} // end of wxDropSource::wxDropSource -wxDropSource::wxDropSource( wxWindow *win ) +wxDropSource::wxDropSource ( wxDataObject& rData, wxWindow* WXUNUSED(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; + 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