{ if (m_dataObject) delete m_dataObject;
m_dataObject = dataObject; }
- // called when mouse enters/leaves the window: might be used to give
- // some visual feedback to the user
- virtual void OnLeave() { }
+ // these functions are called when data is moved over position (x, y) and
+ // may return either wxDragCopy, wxDragMove or wxDragNone depending on
+ // what would happen if the data were dropped here.
+ //
+ // the last parameter is what would happen by default and is determined by
+ // the platform-specific logic (for example, under Windows it's wxDragCopy
+ // if Ctrl key is pressed and wxDragMove otherwise) except that it will
+ // always be wxDragNone if the carried data is in an unsupported format.
+
+ // called when the mouse enters the window (only once until OnLeave())
+ virtual wxDragResult OnEnter(wxCoord x, wxCoord y, wxDragResult def)
+ { return OnDragOver(x, y, def); }
+
+ // called when the mouse moves in the window - shouldn't take long to
+ // execute or otherwise mouse movement would be too slow
+ virtual wxDragResult OnDragOver(wxCoord WXUNUSED(x), wxCoord WXUNUSED(y),
+ wxDragResult def)
+ { return def; }
- // this function is called when data enters over position (x, y) - if it
- // returns TRUE, the dragging icon can indicate that the window would
- // accept a drop here
- virtual bool OnEnter(wxCoord x, wxCoord y) = 0;
-
- // this function is called when data is move over position (x, y) - if it
- // returns TRUE, the dragging icon can indicate that the window would
- // accept a drop here
- virtual bool OnMove(wxCoord x, wxCoord y) = 0;
+ // called when mouse leaves the window: might be used to remove the
+ // feedback which was given in OnEnter()
+ virtual void OnLeave() { }
// this function is called when data is dropped at position (x, y) - if it
// returns TRUE, OnData() will be called immediately afterwards which will
public:
wxDropTarget(wxDataObject *dataObject = (wxDataObject*) NULL );
- virtual bool OnEnter(wxCoord x, wxCoord y) ;
- virtual bool OnMove(wxCoord x, wxCoord y);
+ virtual wxDragResult OnDragOver(wxCoord x, wxCoord y, wxDragResult def);
virtual bool OnDrop(wxCoord x, wxCoord y);
virtual bool OnData(wxCoord x, wxCoord y);
virtual bool GetData();
public:
wxDropTarget(wxDataObject *dataObject = (wxDataObject*) NULL );
- virtual bool OnEnter(wxCoord x, wxCoord y) ;
- virtual bool OnMove(wxCoord x, wxCoord y);
+ virtual wxDragResult OnDragOver(wxCoord x, wxCoord y, wxDragResult def);
virtual bool OnDrop(wxCoord x, wxCoord y);
virtual bool OnData(wxCoord x, wxCoord y);
virtual bool GetData();
this is only valid for the duration of this call */
drop_target->SetDragContext( context );
- bool ret = FALSE;
+ /* TODO: what should be the default behaviour? Copy or move? */
+ wxDragResult result = wxDragMove;
if (drop_target->m_firstMotion)
{
/* the first "drag_motion" event substitutes a "drag_enter" event */
- ret = drop_target->OnEnter( x, y );
+ result = drop_target->OnEnter( x, y, result );
}
else
{
/* give program a chance to react (i.e. to say no by returning FALSE) */
- ret = drop_target->OnMove( x, y );
+ result = drop_target->OnDragOver( x, y, result );
}
/* we don't yet handle which "actions" (i.e. copy or move)
the target accepts. so far we simply accept the
suggested action. TODO. */
+ bool ret = result != wxDragNone;
if (ret)
gdk_drag_status( context, context->suggested_action, time );
m_dragTime = 0;
}
-bool wxDropTarget::OnEnter( int WXUNUSED(x), int WXUNUSED(y) )
+wxDragResult wxDropTarget::OnDragOver( wxCoord WXUNUSED(x),
+ wxCoord WXUNUSED(y),
+ wxDragResult def )
{
if (!m_dataObject)
return FALSE;
- return (GetMatchingPair() != (GdkAtom) 0);
-}
-
-bool wxDropTarget::OnMove( int WXUNUSED(x), int WXUNUSED(y) )
-{
- if (!m_dataObject)
- return FALSE;
-
- return (GetMatchingPair() != (GdkAtom) 0);
+ return (GetMatchingPair() != (GdkAtom) 0) ? def : wxDragNone;
}
-bool wxDropTarget::OnDrop( int WXUNUSED(x), int WXUNUSED(y) )
+bool wxDropTarget::OnDrop( wxCoord WXUNUSED(x), wxCoord WXUNUSED(y) )
{
if (!m_dataObject)
return FALSE;
return (GetMatchingPair() != (GdkAtom) 0);
}
-bool wxDropTarget::OnData( int WXUNUSED(x), int WXUNUSED(y) )
+bool wxDropTarget::OnData( wxCoord WXUNUSED(x), wxCoord WXUNUSED(y) )
{
if (!m_dataObject)
return FALSE;
this is only valid for the duration of this call */
drop_target->SetDragContext( context );
- bool ret = FALSE;
+ /* TODO: what should be the default behaviour? Copy or move? */
+ wxDragResult result = wxDragMove;
if (drop_target->m_firstMotion)
{
/* the first "drag_motion" event substitutes a "drag_enter" event */
- ret = drop_target->OnEnter( x, y );
+ result = drop_target->OnEnter( x, y, result );
}
else
{
/* give program a chance to react (i.e. to say no by returning FALSE) */
- ret = drop_target->OnMove( x, y );
+ result = drop_target->OnDragOver( x, y, result );
}
/* we don't yet handle which "actions" (i.e. copy or move)
the target accepts. so far we simply accept the
suggested action. TODO. */
+ bool ret = result != wxDragNone;
if (ret)
gdk_drag_status( context, context->suggested_action, time );
m_dragTime = 0;
}
-bool wxDropTarget::OnEnter( int WXUNUSED(x), int WXUNUSED(y) )
+wxDragResult wxDropTarget::OnDragOver( wxCoord WXUNUSED(x),
+ wxCoord WXUNUSED(y),
+ wxDragResult def )
{
if (!m_dataObject)
return FALSE;
- return (GetMatchingPair() != (GdkAtom) 0);
-}
-
-bool wxDropTarget::OnMove( int WXUNUSED(x), int WXUNUSED(y) )
-{
- if (!m_dataObject)
- return FALSE;
-
- return (GetMatchingPair() != (GdkAtom) 0);
+ return (GetMatchingPair() != (GdkAtom) 0) ? def : wxDragNone;
}
-bool wxDropTarget::OnDrop( int WXUNUSED(x), int WXUNUSED(y) )
+bool wxDropTarget::OnDrop( wxCoord WXUNUSED(x), wxCoord WXUNUSED(y) )
{
if (!m_dataObject)
return FALSE;
return (GetMatchingPair() != (GdkAtom) 0);
}
-bool wxDropTarget::OnData( int WXUNUSED(x), int WXUNUSED(y) )
+bool wxDropTarget::OnData( wxCoord WXUNUSED(x), wxCoord WXUNUSED(y) )
{
if (!m_dataObject)
return FALSE;
static inline DWORD GetDropEffect(DWORD flags);
};
+// ----------------------------------------------------------------------------
+// private functions
+// ----------------------------------------------------------------------------
+
+static wxDragResult ConvertDragEffectToResult(DWORD dwEffect);
+static DWORD ConvertDragResultToEffect(wxDragResult result);
+
// ============================================================================
// wxIDropTarget implementation
// ============================================================================
return S_OK;
}
- // TODO should check the point also?
-
- *pdwEffect = GetDropEffect(grfKeyState);
-
// get hold of the data object
m_pIDataObject = pIDataSource;
m_pIDataObject->AddRef();
// give some visual feedback
- m_pTarget->OnEnter();
+ *pdwEffect = ConvertDragResultToEffect(
+ m_pTarget->OnEnter(pt.x, pt.y,
+ ConvertDragEffectToResult(
+ GetDropEffect(grfKeyState)
+ )
+ )
+ );
return S_OK;
}
{
// there are too many of them... wxLogDebug("IDropTarget::DragOver");
- *pdwEffect = m_pIDataObject == NULL ? DROPEFFECT_NONE
- : GetDropEffect(grfKeyState);
+ wxDragResult result;
+ if ( m_pIDataObject ) {
+ result = ConvertDragEffectToResult(GetDropEffect(grfKeyState));
+ }
+ else {
+ // can't accept data anyhow normally
+ result = wxDragNone;
+ }
+
+ *pdwEffect = ConvertDragResultToEffect(
+ m_pTarget->OnDragOver(pt.x, pt.y, result)
+ );
+
return S_OK;
}
((wxFileDataObject *)m_dataObject)->GetFilenames());
}
+// ----------------------------------------------------------------------------
+// private functions
+// ----------------------------------------------------------------------------
+
+static wxDragResult ConvertDragEffectToResult(DWORD dwEffect)
+{
+ switch ( dwEffect ) {
+ case DROPEFFECT_COPY:
+ return wxDragCopy;
+
+ case DROPEFFECT_MOVE:
+ return wxDragMove;
+
+ default:
+ wxFAIL_MSG(wxT("invalid value in ConvertDragEffectToResult"));
+ // fall through
+
+ case DROPEFFECT_NONE:
+ return wxDragNone;
+ }
+}
+
+static DWORD ConvertDragResultToEffect(wxDragResult result)
+{
+ switch ( result ) {
+ case wxDragCopy:
+ return DROPEFFECT_COPY;
+
+ case wxDragMove:
+ return DROPEFFECT_MOVE;
+
+ default:
+ wxFAIL_MSG(wxT("invalid value in ConvertDragResultToEffect"));
+ // fall through
+
+ case wxDragNone:
+ return DROPEFFECT_NONE;
+ }
+}
+
#endif
// wxUSE_DRAG_AND_DROP