wxDropTarget starts to work
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@2117 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
@@ -113,15 +113,19 @@ public:
|
|||||||
/* may be overridden to react to events */
|
/* may be overridden to react to events */
|
||||||
virtual void OnEnter();
|
virtual void OnEnter();
|
||||||
virtual void OnLeave();
|
virtual void OnLeave();
|
||||||
|
|
||||||
|
/* may be overridden to reject certain formats or drops
|
||||||
|
on certain areas */
|
||||||
virtual bool OnMove( int x, int y );
|
virtual bool OnMove( int x, int y );
|
||||||
|
|
||||||
/* has te be overridden to get data */
|
/* has to be overridden to accept drop. call GetData() to
|
||||||
|
indicate the format you request and get the data. */
|
||||||
virtual bool OnDrop( int x, int y );
|
virtual bool OnDrop( int x, int y );
|
||||||
|
|
||||||
/* called to query formats available */
|
/* called to query what formats are available */
|
||||||
bool IsSupported( wxDataFormat format );
|
bool IsSupported( wxDataFormat format );
|
||||||
|
|
||||||
/* fill data with data on the clipboard (if available) */
|
/* fill data with data from the dragging source */
|
||||||
bool GetData( wxDataObject *data );
|
bool GetData( wxDataObject *data );
|
||||||
|
|
||||||
// implementation
|
// implementation
|
||||||
@@ -130,9 +134,16 @@ public:
|
|||||||
void UnregisterWidget( GtkWidget *widget );
|
void UnregisterWidget( GtkWidget *widget );
|
||||||
|
|
||||||
GdkDragContext *m_dragContext;
|
GdkDragContext *m_dragContext;
|
||||||
|
GtkWidget *m_dragWidget;
|
||||||
|
guint m_dragTime;
|
||||||
|
bool m_firstMotion; /* gdk has no "gdk_drag_enter" event */
|
||||||
|
bool m_waiting; /* asynchronous process */
|
||||||
|
bool m_dataRetrieveSuccess;
|
||||||
|
wxDataObject *m_currentDataObject;
|
||||||
|
|
||||||
void SetDragContext( GdkDragContext *dc ) { m_dragContext = dc; }
|
void SetDragContext( GdkDragContext *dc ) { m_dragContext = dc; }
|
||||||
GdkDragContext *GetDragContext() { return m_dragContext; }
|
void SetDragWidget( GtkWidget *w ) { m_dragWidget = w; }
|
||||||
|
void SetDragTime( guint time ) { m_dragTime = time; }
|
||||||
};
|
};
|
||||||
|
|
||||||
//-------------------------------------------------------------------------
|
//-------------------------------------------------------------------------
|
||||||
@@ -197,6 +208,7 @@ public:
|
|||||||
|
|
||||||
virtual bool OnMove( int x, int y );
|
virtual bool OnMove( int x, int y );
|
||||||
virtual bool OnDrop( int x, int y );
|
virtual bool OnDrop( int x, int y );
|
||||||
|
virtual void OnData( int x, int y );
|
||||||
|
|
||||||
/* you have to override OnDropFiles to get at the file names */
|
/* you have to override OnDropFiles to get at the file names */
|
||||||
virtual bool OnDropFiles( int x, int y, size_t nFiles, const char * const aszFiles[] ) = 0;
|
virtual bool OnDropFiles( int x, int y, size_t nFiles, const char * const aszFiles[] ) = 0;
|
||||||
|
@@ -113,15 +113,19 @@ public:
|
|||||||
/* may be overridden to react to events */
|
/* may be overridden to react to events */
|
||||||
virtual void OnEnter();
|
virtual void OnEnter();
|
||||||
virtual void OnLeave();
|
virtual void OnLeave();
|
||||||
|
|
||||||
|
/* may be overridden to reject certain formats or drops
|
||||||
|
on certain areas */
|
||||||
virtual bool OnMove( int x, int y );
|
virtual bool OnMove( int x, int y );
|
||||||
|
|
||||||
/* has te be overridden to get data */
|
/* has to be overridden to accept drop. call GetData() to
|
||||||
|
indicate the format you request and get the data. */
|
||||||
virtual bool OnDrop( int x, int y );
|
virtual bool OnDrop( int x, int y );
|
||||||
|
|
||||||
/* called to query formats available */
|
/* called to query what formats are available */
|
||||||
bool IsSupported( wxDataFormat format );
|
bool IsSupported( wxDataFormat format );
|
||||||
|
|
||||||
/* fill data with data on the clipboard (if available) */
|
/* fill data with data from the dragging source */
|
||||||
bool GetData( wxDataObject *data );
|
bool GetData( wxDataObject *data );
|
||||||
|
|
||||||
// implementation
|
// implementation
|
||||||
@@ -130,9 +134,16 @@ public:
|
|||||||
void UnregisterWidget( GtkWidget *widget );
|
void UnregisterWidget( GtkWidget *widget );
|
||||||
|
|
||||||
GdkDragContext *m_dragContext;
|
GdkDragContext *m_dragContext;
|
||||||
|
GtkWidget *m_dragWidget;
|
||||||
|
guint m_dragTime;
|
||||||
|
bool m_firstMotion; /* gdk has no "gdk_drag_enter" event */
|
||||||
|
bool m_waiting; /* asynchronous process */
|
||||||
|
bool m_dataRetrieveSuccess;
|
||||||
|
wxDataObject *m_currentDataObject;
|
||||||
|
|
||||||
void SetDragContext( GdkDragContext *dc ) { m_dragContext = dc; }
|
void SetDragContext( GdkDragContext *dc ) { m_dragContext = dc; }
|
||||||
GdkDragContext *GetDragContext() { return m_dragContext; }
|
void SetDragWidget( GtkWidget *w ) { m_dragWidget = w; }
|
||||||
|
void SetDragTime( guint time ) { m_dragTime = time; }
|
||||||
};
|
};
|
||||||
|
|
||||||
//-------------------------------------------------------------------------
|
//-------------------------------------------------------------------------
|
||||||
@@ -197,6 +208,7 @@ public:
|
|||||||
|
|
||||||
virtual bool OnMove( int x, int y );
|
virtual bool OnMove( int x, int y );
|
||||||
virtual bool OnDrop( int x, int y );
|
virtual bool OnDrop( int x, int y );
|
||||||
|
virtual void OnData( int x, int y );
|
||||||
|
|
||||||
/* you have to override OnDropFiles to get at the file names */
|
/* you have to override OnDropFiles to get at the file names */
|
||||||
virtual bool OnDropFiles( int x, int y, size_t nFiles, const char * const aszFiles[] ) = 0;
|
virtual bool OnDropFiles( int x, int y, size_t nFiles, const char * const aszFiles[] ) = 0;
|
||||||
|
@@ -239,7 +239,7 @@ void DnDFrame::OnPaint(wxPaintEvent& /*event*/)
|
|||||||
|
|
||||||
wxPaintDC dc(this);
|
wxPaintDC dc(this);
|
||||||
dc.SetFont( wxFont( 24, wxDECORATIVE, wxNORMAL, wxNORMAL, FALSE, "charter" ) );
|
dc.SetFont( wxFont( 24, wxDECORATIVE, wxNORMAL, wxNORMAL, FALSE, "charter" ) );
|
||||||
dc.DrawText( "Drag text from here!", 20, h-22 );
|
dc.DrawText( "Drag text from here!", 20, h-35 );
|
||||||
}
|
}
|
||||||
|
|
||||||
void DnDFrame::OnDrag(wxCommandEvent& /* event */)
|
void DnDFrame::OnDrag(wxCommandEvent& /* event */)
|
||||||
|
256
src/gtk/dnd.cpp
256
src/gtk/dnd.cpp
@@ -135,11 +135,21 @@ static char * page_xpm[] = {
|
|||||||
static void target_drag_leave( GtkWidget *WXUNUSED(widget),
|
static void target_drag_leave( GtkWidget *WXUNUSED(widget),
|
||||||
GdkDragContext *context,
|
GdkDragContext *context,
|
||||||
guint WXUNUSED(time),
|
guint WXUNUSED(time),
|
||||||
wxDropTarget *dt )
|
wxDropTarget *drop_target )
|
||||||
{
|
{
|
||||||
dt->SetDragContext( context );
|
/* inform the wxDropTarget about the current GdkDragContext.
|
||||||
dt->OnLeave();
|
this is only valid for the duration of this call */
|
||||||
dt->SetDragContext( (GdkDragContext*) NULL );
|
drop_target->SetDragContext( context );
|
||||||
|
|
||||||
|
/* we don't need return values. this event is just for
|
||||||
|
information */
|
||||||
|
drop_target->OnLeave();
|
||||||
|
|
||||||
|
/* this has to be done because GDK has no "drag_enter" event */
|
||||||
|
drop_target->m_firstMotion = TRUE;
|
||||||
|
|
||||||
|
/* after this, invalidate the drop_target's GdkDragContext */
|
||||||
|
drop_target->SetDragContext( (GdkDragContext*) NULL );
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
@@ -151,21 +161,38 @@ static gboolean target_drag_motion( GtkWidget *WXUNUSED(widget),
|
|||||||
gint x,
|
gint x,
|
||||||
gint y,
|
gint y,
|
||||||
guint time,
|
guint time,
|
||||||
wxDropTarget *dt )
|
wxDropTarget *drop_target )
|
||||||
{
|
{
|
||||||
dt->SetDragContext( context );
|
/* Owen Taylor: "if the coordinates not in a drop zone,
|
||||||
|
return FALSE, otherwise call gtk_drag_status() and
|
||||||
|
return TRUE" */
|
||||||
|
|
||||||
if (dt->OnMove( x, y ))
|
/* inform the wxDropTarget about the current GdkDragContext.
|
||||||
|
this is only valid for the duration of this call */
|
||||||
|
drop_target->SetDragContext( context );
|
||||||
|
|
||||||
|
if (drop_target->m_firstMotion)
|
||||||
{
|
{
|
||||||
|
/* the first "drag_motion" event substitutes a "drag_enter" event */
|
||||||
|
drop_target->OnEnter();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* give program a chance to react (i.e. to say no by returning FALSE) */
|
||||||
|
bool ret = drop_target->OnMove( x, y );
|
||||||
|
|
||||||
|
/* we don't yet handle which "actions" (i.e. copy or move)
|
||||||
|
the target accepts. so far we simply accept the
|
||||||
|
suggested action. TODO. */
|
||||||
|
if (ret)
|
||||||
gdk_drag_status( context, context->suggested_action, time );
|
gdk_drag_status( context, context->suggested_action, time );
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
gdk_drag_status( context, (GdkDragAction)0, time );
|
|
||||||
}
|
|
||||||
|
|
||||||
dt->SetDragContext( (GdkDragContext*) NULL );
|
/* after this, invalidate the drop_target's GdkDragContext */
|
||||||
return TRUE;
|
drop_target->SetDragContext( (GdkDragContext*) NULL );
|
||||||
|
|
||||||
|
/* this has to be done because GDK has no "drag_enter" event */
|
||||||
|
drop_target->m_firstMotion = FALSE;
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
@@ -176,18 +203,59 @@ static gboolean target_drag_drop( GtkWidget *widget,
|
|||||||
GdkDragContext *context,
|
GdkDragContext *context,
|
||||||
gint x,
|
gint x,
|
||||||
gint y,
|
gint y,
|
||||||
guint time )
|
guint time,
|
||||||
|
wxDropTarget *drop_target )
|
||||||
{
|
{
|
||||||
printf( "drop at: %d,%d.\n", x, y );
|
/* Owen Taylor: "if the drop is not in a drop zone,
|
||||||
|
return FALSE, otherwise, if you aren't accepting
|
||||||
|
the drop, call gtk_drag_finish() with success == FALSE
|
||||||
|
otherwise call gtk_drag_data_get()" */
|
||||||
|
|
||||||
if (context->targets)
|
/* this seems to make a difference between not accepting
|
||||||
|
due to wrong target area and due to wrong format. let
|
||||||
|
us hope that this is not required.. */
|
||||||
|
|
||||||
|
/* inform the wxDropTarget about the current GdkDragContext.
|
||||||
|
this is only valid for the duration of this call */
|
||||||
|
drop_target->SetDragContext( context );
|
||||||
|
|
||||||
|
/* inform the wxDropTarget about the current drag widget.
|
||||||
|
this is only valid for the duration of this call */
|
||||||
|
drop_target->SetDragWidget( widget );
|
||||||
|
|
||||||
|
/* inform the wxDropTarget about the current drag time.
|
||||||
|
this is only valid for the duration of this call */
|
||||||
|
drop_target->SetDragTime( time );
|
||||||
|
|
||||||
|
bool ret = drop_target->OnDrop( x, y );
|
||||||
|
|
||||||
|
if (ret)
|
||||||
{
|
{
|
||||||
|
/* this should trigger an "drag_data_received" event */
|
||||||
gtk_drag_get_data( widget,
|
gtk_drag_get_data( widget,
|
||||||
context,
|
context,
|
||||||
GPOINTER_TO_INT (context->targets->data),
|
GPOINTER_TO_INT (context->targets->data),
|
||||||
time );
|
time );
|
||||||
}
|
}
|
||||||
return FALSE;
|
else
|
||||||
|
{
|
||||||
|
/* cancel the whole thing */
|
||||||
|
gtk_drag_finish( context,
|
||||||
|
FALSE, /* no success */
|
||||||
|
FALSE, /* don't delete data on dropping side */
|
||||||
|
time );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* after this, invalidate the drop_target's GdkDragContext */
|
||||||
|
drop_target->SetDragContext( (GdkDragContext*) NULL );
|
||||||
|
|
||||||
|
/* after this, invalidate the drop_target's drag widget */
|
||||||
|
drop_target->SetDragWidget( (GtkWidget*) NULL );
|
||||||
|
|
||||||
|
/* this has to be done because GDK has no "drag_enter" event */
|
||||||
|
drop_target->m_firstMotion = TRUE;
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
@@ -200,19 +268,53 @@ static void target_drag_data_received( GtkWidget *WXUNUSED(widget),
|
|||||||
gint y,
|
gint y,
|
||||||
GtkSelectionData *data,
|
GtkSelectionData *data,
|
||||||
guint WXUNUSED(info),
|
guint WXUNUSED(info),
|
||||||
guint time )
|
guint time,
|
||||||
|
wxDropTarget *drop_target )
|
||||||
{
|
{
|
||||||
printf( "data receive at: %d,%d.\n", x, y );
|
/* Owen Taylor: "call gtk_drag_finish() with
|
||||||
|
success == TRUE" */
|
||||||
|
|
||||||
if ((data->length >= 0) && (data->format == 8))
|
/* strangely, we get a "drag_data_received" event even when
|
||||||
|
we don't request them. this checks this. */
|
||||||
|
if (!drop_target->m_currentDataObject) return;
|
||||||
|
|
||||||
|
wxDataObject *data_object = drop_target->m_currentDataObject;
|
||||||
|
|
||||||
|
if ((data->length <= 0) || (data->format != 8))
|
||||||
{
|
{
|
||||||
wxString str = (const char*)data->data;
|
/* negative data length and non 8-bit data format
|
||||||
printf( "Received %s\n.", WXSTRINGCAST str );
|
qualifies for junk */
|
||||||
gtk_drag_finish( context, TRUE, FALSE, time );
|
gtk_drag_finish (context, FALSE, FALSE, time);
|
||||||
return;
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
wxASSERT_MSG( data->target == data_object->GetFormat().GetAtom(), "DnD GetData target mismatch." );
|
||||||
|
|
||||||
|
if (data_object->GetFormat().GetType() == wxDF_TEXT)
|
||||||
|
{
|
||||||
|
wxTextDataObject *text_object = (wxTextDataObject*)data_object;
|
||||||
|
text_object->SetText( (const char*)data->data );
|
||||||
|
} else
|
||||||
|
|
||||||
|
if (data_object->GetFormat().GetType() == wxDF_FILENAME)
|
||||||
|
{
|
||||||
|
} else
|
||||||
|
|
||||||
|
if (data_object->GetFormat().GetType() == wxDF_PRIVATE)
|
||||||
|
{
|
||||||
|
wxPrivateDataObject *priv_object = (wxPrivateDataObject*)data_object;
|
||||||
|
priv_object->SetData( (const char*)data->data, (size_t)data->length );
|
||||||
}
|
}
|
||||||
|
|
||||||
gtk_drag_finish (context, FALSE, FALSE, time);
|
/* tell wxDropTarget that data transfer was successfull */
|
||||||
|
drop_target->m_dataRetrieveSuccess = TRUE;
|
||||||
|
|
||||||
|
/* tell GTK that data transfer was successfull */
|
||||||
|
gtk_drag_finish( context, TRUE, FALSE, time );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* tell wxDropTarget that data has arrived (or not) */
|
||||||
|
drop_target->m_waiting = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
@@ -221,6 +323,12 @@ static void target_drag_data_received( GtkWidget *WXUNUSED(widget),
|
|||||||
|
|
||||||
wxDropTarget::wxDropTarget()
|
wxDropTarget::wxDropTarget()
|
||||||
{
|
{
|
||||||
|
m_firstMotion = TRUE;
|
||||||
|
m_dragContext = (GdkDragContext*) NULL;
|
||||||
|
m_dragWidget = (GtkWidget*) NULL;
|
||||||
|
m_dragTime = 0;
|
||||||
|
m_currentDataObject = (wxDataObject*) NULL;
|
||||||
|
m_dataRetrieveSuccess = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
wxDropTarget::~wxDropTarget()
|
wxDropTarget::~wxDropTarget()
|
||||||
@@ -235,54 +343,63 @@ void wxDropTarget::OnLeave()
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
bool wxDropTarget::OnMove( int x, int y )
|
bool wxDropTarget::OnMove( int WXUNUSED(x), int WXUNUSED(y) )
|
||||||
{
|
{
|
||||||
printf( "generic move %d %d.\n", x, y );
|
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool wxDropTarget::OnDrop( int x, int y )
|
bool wxDropTarget::OnDrop( int WXUNUSED(x), int WXUNUSED(y) )
|
||||||
{
|
{
|
||||||
printf( "generic drop %d %d.\n", x, y );
|
return FALSE;
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool wxDropTarget::IsSupported( wxDataFormat format )
|
bool wxDropTarget::IsSupported( wxDataFormat format )
|
||||||
{
|
{
|
||||||
printf( "generic is supported.\n" );
|
|
||||||
|
|
||||||
if (!m_dragContext) return FALSE;
|
if (!m_dragContext) return FALSE;
|
||||||
|
|
||||||
GList *child = m_dragContext->targets;
|
GList *child = m_dragContext->targets;
|
||||||
while (child)
|
while (child)
|
||||||
{
|
{
|
||||||
GdkAtom formatAtom = (GdkAtom) GPOINTER_TO_INT(child->data);
|
GdkAtom formatAtom = (GdkAtom) GPOINTER_TO_INT(child->data);
|
||||||
char *name = gdk_atom_name( formatAtom );
|
|
||||||
if (name) printf( "Format available: %s.\n", name );
|
|
||||||
|
|
||||||
|
/* char *name = gdk_atom_name( formatAtom );
|
||||||
|
if (name) printf( "Format available: %s.\n", name ); */
|
||||||
|
|
||||||
|
if (formatAtom == format.GetAtom()) return TRUE;
|
||||||
child = child->next;
|
child = child->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
return TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool wxDropTarget::GetData( wxDataObject *data )
|
bool wxDropTarget::GetData( wxDataObject *data )
|
||||||
{
|
{
|
||||||
return FALSE;
|
if (!m_dragContext) return FALSE;
|
||||||
|
if (!m_dragWidget) return FALSE;
|
||||||
|
|
||||||
|
m_currentDataObject = data;
|
||||||
|
m_dataRetrieveSuccess = FALSE;
|
||||||
|
|
||||||
|
/* this should trigger an "drag_data_received" event */
|
||||||
|
gtk_drag_get_data( m_dragWidget,
|
||||||
|
m_dragContext,
|
||||||
|
data->GetFormat().GetAtom(),
|
||||||
|
m_dragTime );
|
||||||
|
|
||||||
|
/* wait for the "drag_data_received" event */
|
||||||
|
m_waiting = TRUE;
|
||||||
|
while (m_waiting) gtk_main_iteration();
|
||||||
|
|
||||||
|
m_currentDataObject = (wxDataObject*) NULL;
|
||||||
|
|
||||||
|
return m_dataRetrieveSuccess;
|
||||||
}
|
}
|
||||||
|
|
||||||
void wxDropTarget::UnregisterWidget( GtkWidget *widget )
|
void wxDropTarget::UnregisterWidget( GtkWidget *widget )
|
||||||
{
|
{
|
||||||
wxCHECK_RET( widget != NULL, "unregister widget is NULL" );
|
wxCHECK_RET( widget != NULL, "unregister widget is NULL" );
|
||||||
|
|
||||||
gtk_drag_dest_set( widget,
|
gtk_drag_dest_unset( widget );
|
||||||
(GtkDestDefaults) 0,
|
|
||||||
(GtkTargetEntry*) NULL,
|
|
||||||
0,
|
|
||||||
(GdkDragAction) 0 );
|
|
||||||
|
|
||||||
gtk_signal_disconnect_by_func( GTK_OBJECT(widget),
|
gtk_signal_disconnect_by_func( GTK_OBJECT(widget),
|
||||||
GTK_SIGNAL_FUNC(target_drag_leave), (gpointer) this );
|
GTK_SIGNAL_FUNC(target_drag_leave), (gpointer) this );
|
||||||
@@ -301,18 +418,21 @@ void wxDropTarget::RegisterWidget( GtkWidget *widget )
|
|||||||
{
|
{
|
||||||
wxCHECK_RET( widget != NULL, "register widget is NULL" );
|
wxCHECK_RET( widget != NULL, "register widget is NULL" );
|
||||||
|
|
||||||
GtkTargetEntry format;
|
/* gtk_drag_dest_set() determines what default behaviour we'd like
|
||||||
format.info = 0;
|
GTK to supply. we don't want to specify out targets (=formats)
|
||||||
format.flags = 0;
|
or actions in advance (i.e. not GTK_DEST_DEFAULT_MOTION and
|
||||||
char buf[100];
|
not GTK_DEST_DEFAULT_DROP). instead we react individually to
|
||||||
strcpy( buf, "text/plain" );
|
"drag_motion" and "drag_drop" events. this makes it possible
|
||||||
format.target = buf;
|
to allow dropping on only a small area. we should set
|
||||||
|
GTK_DEST_DEFAULT_HIGHLIGHT as this will switch on the nice
|
||||||
|
highlighting if dragging over standard controls, but this
|
||||||
|
seems to be broken without the other two. */
|
||||||
|
|
||||||
gtk_drag_dest_set( widget,
|
gtk_drag_dest_set( widget,
|
||||||
GTK_DEST_DEFAULT_ALL,
|
(GtkDestDefaults) 0, /* no default behaviour */
|
||||||
&format,
|
(GtkTargetEntry*) NULL, /* we don't supply any formats here */
|
||||||
1,
|
0, /* number of targets = 0 */
|
||||||
(GdkDragAction)(GDK_ACTION_COPY | GDK_ACTION_MOVE) );
|
(GdkDragAction) 0 ); /* we don't supply any actions here */
|
||||||
|
|
||||||
gtk_signal_connect( GTK_OBJECT(widget), "drag_leave",
|
gtk_signal_connect( GTK_OBJECT(widget), "drag_leave",
|
||||||
GTK_SIGNAL_FUNC(target_drag_leave), (gpointer) this );
|
GTK_SIGNAL_FUNC(target_drag_leave), (gpointer) this );
|
||||||
@@ -333,21 +453,18 @@ void wxDropTarget::RegisterWidget( GtkWidget *widget )
|
|||||||
|
|
||||||
bool wxTextDropTarget::OnMove( int WXUNUSED(x), int WXUNUSED(y) )
|
bool wxTextDropTarget::OnMove( int WXUNUSED(x), int WXUNUSED(y) )
|
||||||
{
|
{
|
||||||
printf( "text move.\n" );
|
return IsSupported( wxDF_TEXT ); // same as "STRING"
|
||||||
|
|
||||||
return IsSupported( wxDF_TEXT ); // same as "TEXT"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool wxTextDropTarget::OnDrop( int x, int y )
|
bool wxTextDropTarget::OnDrop( int x, int y )
|
||||||
{
|
{
|
||||||
printf( "text drop.\n" );
|
|
||||||
|
|
||||||
if (!IsSupported( wxDF_TEXT )) return FALSE;
|
if (!IsSupported( wxDF_TEXT )) return FALSE;
|
||||||
|
|
||||||
wxTextDataObject data;
|
wxTextDataObject data;
|
||||||
if (!GetData( &data )) return FALSE;
|
if (!GetData( &data )) return FALSE;
|
||||||
|
|
||||||
return OnDropText( x, y, data.GetText() );
|
OnDropText( x, y, data.GetText() );
|
||||||
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
//-------------------------------------------------------------------------
|
//-------------------------------------------------------------------------
|
||||||
@@ -376,7 +493,9 @@ bool wxPrivateDropTarget::OnDrop( int x, int y )
|
|||||||
wxPrivateDataObject data;
|
wxPrivateDataObject data;
|
||||||
if (!GetData( &data )) return FALSE;
|
if (!GetData( &data )) return FALSE;
|
||||||
|
|
||||||
return OnDropData( x, y, data.GetData(), data.GetSize() );
|
OnDropData( x, y, data.GetData(), data.GetSize() );
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
@@ -390,10 +509,13 @@ bool wxFileDropTarget::OnMove( int WXUNUSED(x), int WXUNUSED(y) )
|
|||||||
|
|
||||||
bool wxFileDropTarget::OnDrop( int x, int y )
|
bool wxFileDropTarget::OnDrop( int x, int y )
|
||||||
{
|
{
|
||||||
if (!IsSupported( wxDF_FILENAME )) return FALSE;
|
return IsSupported( wxDF_FILENAME ); // same as "file:ALL"
|
||||||
|
}
|
||||||
|
|
||||||
|
void wxFileDropTarget::OnData( int x, int y )
|
||||||
|
{
|
||||||
wxFileDataObject data;
|
wxFileDataObject data;
|
||||||
if (!GetData( &data )) return FALSE;
|
if (!GetData( &data )) return;
|
||||||
|
|
||||||
/* get number of substrings /root/mytext.txt/0/root/myothertext.txt/0/0 */
|
/* get number of substrings /root/mytext.txt/0/root/myothertext.txt/0/0 */
|
||||||
size_t number = 0;
|
size_t number = 0;
|
||||||
@@ -403,7 +525,7 @@ bool wxFileDropTarget::OnDrop( int x, int y )
|
|||||||
for ( i = 0; i < size; i++)
|
for ( i = 0; i < size; i++)
|
||||||
if (text[i] == 0) number++;
|
if (text[i] == 0) number++;
|
||||||
|
|
||||||
if (number == 0) return TRUE;
|
if (number == 0) return;
|
||||||
|
|
||||||
char **files = new char*[number];
|
char **files = new char*[number];
|
||||||
|
|
||||||
@@ -415,11 +537,9 @@ bool wxFileDropTarget::OnDrop( int x, int y )
|
|||||||
text += len+1;
|
text += len+1;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ret = OnDropFiles( x, y, number, files );
|
OnDropFiles( x, y, number, files );
|
||||||
|
|
||||||
free( files );
|
free( files );
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//-------------------------------------------------------------------------
|
//-------------------------------------------------------------------------
|
||||||
|
256
src/gtk1/dnd.cpp
256
src/gtk1/dnd.cpp
@@ -135,11 +135,21 @@ static char * page_xpm[] = {
|
|||||||
static void target_drag_leave( GtkWidget *WXUNUSED(widget),
|
static void target_drag_leave( GtkWidget *WXUNUSED(widget),
|
||||||
GdkDragContext *context,
|
GdkDragContext *context,
|
||||||
guint WXUNUSED(time),
|
guint WXUNUSED(time),
|
||||||
wxDropTarget *dt )
|
wxDropTarget *drop_target )
|
||||||
{
|
{
|
||||||
dt->SetDragContext( context );
|
/* inform the wxDropTarget about the current GdkDragContext.
|
||||||
dt->OnLeave();
|
this is only valid for the duration of this call */
|
||||||
dt->SetDragContext( (GdkDragContext*) NULL );
|
drop_target->SetDragContext( context );
|
||||||
|
|
||||||
|
/* we don't need return values. this event is just for
|
||||||
|
information */
|
||||||
|
drop_target->OnLeave();
|
||||||
|
|
||||||
|
/* this has to be done because GDK has no "drag_enter" event */
|
||||||
|
drop_target->m_firstMotion = TRUE;
|
||||||
|
|
||||||
|
/* after this, invalidate the drop_target's GdkDragContext */
|
||||||
|
drop_target->SetDragContext( (GdkDragContext*) NULL );
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
@@ -151,21 +161,38 @@ static gboolean target_drag_motion( GtkWidget *WXUNUSED(widget),
|
|||||||
gint x,
|
gint x,
|
||||||
gint y,
|
gint y,
|
||||||
guint time,
|
guint time,
|
||||||
wxDropTarget *dt )
|
wxDropTarget *drop_target )
|
||||||
{
|
{
|
||||||
dt->SetDragContext( context );
|
/* Owen Taylor: "if the coordinates not in a drop zone,
|
||||||
|
return FALSE, otherwise call gtk_drag_status() and
|
||||||
|
return TRUE" */
|
||||||
|
|
||||||
if (dt->OnMove( x, y ))
|
/* inform the wxDropTarget about the current GdkDragContext.
|
||||||
|
this is only valid for the duration of this call */
|
||||||
|
drop_target->SetDragContext( context );
|
||||||
|
|
||||||
|
if (drop_target->m_firstMotion)
|
||||||
{
|
{
|
||||||
|
/* the first "drag_motion" event substitutes a "drag_enter" event */
|
||||||
|
drop_target->OnEnter();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* give program a chance to react (i.e. to say no by returning FALSE) */
|
||||||
|
bool ret = drop_target->OnMove( x, y );
|
||||||
|
|
||||||
|
/* we don't yet handle which "actions" (i.e. copy or move)
|
||||||
|
the target accepts. so far we simply accept the
|
||||||
|
suggested action. TODO. */
|
||||||
|
if (ret)
|
||||||
gdk_drag_status( context, context->suggested_action, time );
|
gdk_drag_status( context, context->suggested_action, time );
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
gdk_drag_status( context, (GdkDragAction)0, time );
|
|
||||||
}
|
|
||||||
|
|
||||||
dt->SetDragContext( (GdkDragContext*) NULL );
|
/* after this, invalidate the drop_target's GdkDragContext */
|
||||||
return TRUE;
|
drop_target->SetDragContext( (GdkDragContext*) NULL );
|
||||||
|
|
||||||
|
/* this has to be done because GDK has no "drag_enter" event */
|
||||||
|
drop_target->m_firstMotion = FALSE;
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
@@ -176,18 +203,59 @@ static gboolean target_drag_drop( GtkWidget *widget,
|
|||||||
GdkDragContext *context,
|
GdkDragContext *context,
|
||||||
gint x,
|
gint x,
|
||||||
gint y,
|
gint y,
|
||||||
guint time )
|
guint time,
|
||||||
|
wxDropTarget *drop_target )
|
||||||
{
|
{
|
||||||
printf( "drop at: %d,%d.\n", x, y );
|
/* Owen Taylor: "if the drop is not in a drop zone,
|
||||||
|
return FALSE, otherwise, if you aren't accepting
|
||||||
|
the drop, call gtk_drag_finish() with success == FALSE
|
||||||
|
otherwise call gtk_drag_data_get()" */
|
||||||
|
|
||||||
if (context->targets)
|
/* this seems to make a difference between not accepting
|
||||||
|
due to wrong target area and due to wrong format. let
|
||||||
|
us hope that this is not required.. */
|
||||||
|
|
||||||
|
/* inform the wxDropTarget about the current GdkDragContext.
|
||||||
|
this is only valid for the duration of this call */
|
||||||
|
drop_target->SetDragContext( context );
|
||||||
|
|
||||||
|
/* inform the wxDropTarget about the current drag widget.
|
||||||
|
this is only valid for the duration of this call */
|
||||||
|
drop_target->SetDragWidget( widget );
|
||||||
|
|
||||||
|
/* inform the wxDropTarget about the current drag time.
|
||||||
|
this is only valid for the duration of this call */
|
||||||
|
drop_target->SetDragTime( time );
|
||||||
|
|
||||||
|
bool ret = drop_target->OnDrop( x, y );
|
||||||
|
|
||||||
|
if (ret)
|
||||||
{
|
{
|
||||||
|
/* this should trigger an "drag_data_received" event */
|
||||||
gtk_drag_get_data( widget,
|
gtk_drag_get_data( widget,
|
||||||
context,
|
context,
|
||||||
GPOINTER_TO_INT (context->targets->data),
|
GPOINTER_TO_INT (context->targets->data),
|
||||||
time );
|
time );
|
||||||
}
|
}
|
||||||
return FALSE;
|
else
|
||||||
|
{
|
||||||
|
/* cancel the whole thing */
|
||||||
|
gtk_drag_finish( context,
|
||||||
|
FALSE, /* no success */
|
||||||
|
FALSE, /* don't delete data on dropping side */
|
||||||
|
time );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* after this, invalidate the drop_target's GdkDragContext */
|
||||||
|
drop_target->SetDragContext( (GdkDragContext*) NULL );
|
||||||
|
|
||||||
|
/* after this, invalidate the drop_target's drag widget */
|
||||||
|
drop_target->SetDragWidget( (GtkWidget*) NULL );
|
||||||
|
|
||||||
|
/* this has to be done because GDK has no "drag_enter" event */
|
||||||
|
drop_target->m_firstMotion = TRUE;
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
@@ -200,19 +268,53 @@ static void target_drag_data_received( GtkWidget *WXUNUSED(widget),
|
|||||||
gint y,
|
gint y,
|
||||||
GtkSelectionData *data,
|
GtkSelectionData *data,
|
||||||
guint WXUNUSED(info),
|
guint WXUNUSED(info),
|
||||||
guint time )
|
guint time,
|
||||||
|
wxDropTarget *drop_target )
|
||||||
{
|
{
|
||||||
printf( "data receive at: %d,%d.\n", x, y );
|
/* Owen Taylor: "call gtk_drag_finish() with
|
||||||
|
success == TRUE" */
|
||||||
|
|
||||||
if ((data->length >= 0) && (data->format == 8))
|
/* strangely, we get a "drag_data_received" event even when
|
||||||
|
we don't request them. this checks this. */
|
||||||
|
if (!drop_target->m_currentDataObject) return;
|
||||||
|
|
||||||
|
wxDataObject *data_object = drop_target->m_currentDataObject;
|
||||||
|
|
||||||
|
if ((data->length <= 0) || (data->format != 8))
|
||||||
{
|
{
|
||||||
wxString str = (const char*)data->data;
|
/* negative data length and non 8-bit data format
|
||||||
printf( "Received %s\n.", WXSTRINGCAST str );
|
qualifies for junk */
|
||||||
gtk_drag_finish( context, TRUE, FALSE, time );
|
gtk_drag_finish (context, FALSE, FALSE, time);
|
||||||
return;
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
wxASSERT_MSG( data->target == data_object->GetFormat().GetAtom(), "DnD GetData target mismatch." );
|
||||||
|
|
||||||
|
if (data_object->GetFormat().GetType() == wxDF_TEXT)
|
||||||
|
{
|
||||||
|
wxTextDataObject *text_object = (wxTextDataObject*)data_object;
|
||||||
|
text_object->SetText( (const char*)data->data );
|
||||||
|
} else
|
||||||
|
|
||||||
|
if (data_object->GetFormat().GetType() == wxDF_FILENAME)
|
||||||
|
{
|
||||||
|
} else
|
||||||
|
|
||||||
|
if (data_object->GetFormat().GetType() == wxDF_PRIVATE)
|
||||||
|
{
|
||||||
|
wxPrivateDataObject *priv_object = (wxPrivateDataObject*)data_object;
|
||||||
|
priv_object->SetData( (const char*)data->data, (size_t)data->length );
|
||||||
}
|
}
|
||||||
|
|
||||||
gtk_drag_finish (context, FALSE, FALSE, time);
|
/* tell wxDropTarget that data transfer was successfull */
|
||||||
|
drop_target->m_dataRetrieveSuccess = TRUE;
|
||||||
|
|
||||||
|
/* tell GTK that data transfer was successfull */
|
||||||
|
gtk_drag_finish( context, TRUE, FALSE, time );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* tell wxDropTarget that data has arrived (or not) */
|
||||||
|
drop_target->m_waiting = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
@@ -221,6 +323,12 @@ static void target_drag_data_received( GtkWidget *WXUNUSED(widget),
|
|||||||
|
|
||||||
wxDropTarget::wxDropTarget()
|
wxDropTarget::wxDropTarget()
|
||||||
{
|
{
|
||||||
|
m_firstMotion = TRUE;
|
||||||
|
m_dragContext = (GdkDragContext*) NULL;
|
||||||
|
m_dragWidget = (GtkWidget*) NULL;
|
||||||
|
m_dragTime = 0;
|
||||||
|
m_currentDataObject = (wxDataObject*) NULL;
|
||||||
|
m_dataRetrieveSuccess = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
wxDropTarget::~wxDropTarget()
|
wxDropTarget::~wxDropTarget()
|
||||||
@@ -235,54 +343,63 @@ void wxDropTarget::OnLeave()
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
bool wxDropTarget::OnMove( int x, int y )
|
bool wxDropTarget::OnMove( int WXUNUSED(x), int WXUNUSED(y) )
|
||||||
{
|
{
|
||||||
printf( "generic move %d %d.\n", x, y );
|
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool wxDropTarget::OnDrop( int x, int y )
|
bool wxDropTarget::OnDrop( int WXUNUSED(x), int WXUNUSED(y) )
|
||||||
{
|
{
|
||||||
printf( "generic drop %d %d.\n", x, y );
|
return FALSE;
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool wxDropTarget::IsSupported( wxDataFormat format )
|
bool wxDropTarget::IsSupported( wxDataFormat format )
|
||||||
{
|
{
|
||||||
printf( "generic is supported.\n" );
|
|
||||||
|
|
||||||
if (!m_dragContext) return FALSE;
|
if (!m_dragContext) return FALSE;
|
||||||
|
|
||||||
GList *child = m_dragContext->targets;
|
GList *child = m_dragContext->targets;
|
||||||
while (child)
|
while (child)
|
||||||
{
|
{
|
||||||
GdkAtom formatAtom = (GdkAtom) GPOINTER_TO_INT(child->data);
|
GdkAtom formatAtom = (GdkAtom) GPOINTER_TO_INT(child->data);
|
||||||
char *name = gdk_atom_name( formatAtom );
|
|
||||||
if (name) printf( "Format available: %s.\n", name );
|
|
||||||
|
|
||||||
|
/* char *name = gdk_atom_name( formatAtom );
|
||||||
|
if (name) printf( "Format available: %s.\n", name ); */
|
||||||
|
|
||||||
|
if (formatAtom == format.GetAtom()) return TRUE;
|
||||||
child = child->next;
|
child = child->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
return TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool wxDropTarget::GetData( wxDataObject *data )
|
bool wxDropTarget::GetData( wxDataObject *data )
|
||||||
{
|
{
|
||||||
return FALSE;
|
if (!m_dragContext) return FALSE;
|
||||||
|
if (!m_dragWidget) return FALSE;
|
||||||
|
|
||||||
|
m_currentDataObject = data;
|
||||||
|
m_dataRetrieveSuccess = FALSE;
|
||||||
|
|
||||||
|
/* this should trigger an "drag_data_received" event */
|
||||||
|
gtk_drag_get_data( m_dragWidget,
|
||||||
|
m_dragContext,
|
||||||
|
data->GetFormat().GetAtom(),
|
||||||
|
m_dragTime );
|
||||||
|
|
||||||
|
/* wait for the "drag_data_received" event */
|
||||||
|
m_waiting = TRUE;
|
||||||
|
while (m_waiting) gtk_main_iteration();
|
||||||
|
|
||||||
|
m_currentDataObject = (wxDataObject*) NULL;
|
||||||
|
|
||||||
|
return m_dataRetrieveSuccess;
|
||||||
}
|
}
|
||||||
|
|
||||||
void wxDropTarget::UnregisterWidget( GtkWidget *widget )
|
void wxDropTarget::UnregisterWidget( GtkWidget *widget )
|
||||||
{
|
{
|
||||||
wxCHECK_RET( widget != NULL, "unregister widget is NULL" );
|
wxCHECK_RET( widget != NULL, "unregister widget is NULL" );
|
||||||
|
|
||||||
gtk_drag_dest_set( widget,
|
gtk_drag_dest_unset( widget );
|
||||||
(GtkDestDefaults) 0,
|
|
||||||
(GtkTargetEntry*) NULL,
|
|
||||||
0,
|
|
||||||
(GdkDragAction) 0 );
|
|
||||||
|
|
||||||
gtk_signal_disconnect_by_func( GTK_OBJECT(widget),
|
gtk_signal_disconnect_by_func( GTK_OBJECT(widget),
|
||||||
GTK_SIGNAL_FUNC(target_drag_leave), (gpointer) this );
|
GTK_SIGNAL_FUNC(target_drag_leave), (gpointer) this );
|
||||||
@@ -301,18 +418,21 @@ void wxDropTarget::RegisterWidget( GtkWidget *widget )
|
|||||||
{
|
{
|
||||||
wxCHECK_RET( widget != NULL, "register widget is NULL" );
|
wxCHECK_RET( widget != NULL, "register widget is NULL" );
|
||||||
|
|
||||||
GtkTargetEntry format;
|
/* gtk_drag_dest_set() determines what default behaviour we'd like
|
||||||
format.info = 0;
|
GTK to supply. we don't want to specify out targets (=formats)
|
||||||
format.flags = 0;
|
or actions in advance (i.e. not GTK_DEST_DEFAULT_MOTION and
|
||||||
char buf[100];
|
not GTK_DEST_DEFAULT_DROP). instead we react individually to
|
||||||
strcpy( buf, "text/plain" );
|
"drag_motion" and "drag_drop" events. this makes it possible
|
||||||
format.target = buf;
|
to allow dropping on only a small area. we should set
|
||||||
|
GTK_DEST_DEFAULT_HIGHLIGHT as this will switch on the nice
|
||||||
|
highlighting if dragging over standard controls, but this
|
||||||
|
seems to be broken without the other two. */
|
||||||
|
|
||||||
gtk_drag_dest_set( widget,
|
gtk_drag_dest_set( widget,
|
||||||
GTK_DEST_DEFAULT_ALL,
|
(GtkDestDefaults) 0, /* no default behaviour */
|
||||||
&format,
|
(GtkTargetEntry*) NULL, /* we don't supply any formats here */
|
||||||
1,
|
0, /* number of targets = 0 */
|
||||||
(GdkDragAction)(GDK_ACTION_COPY | GDK_ACTION_MOVE) );
|
(GdkDragAction) 0 ); /* we don't supply any actions here */
|
||||||
|
|
||||||
gtk_signal_connect( GTK_OBJECT(widget), "drag_leave",
|
gtk_signal_connect( GTK_OBJECT(widget), "drag_leave",
|
||||||
GTK_SIGNAL_FUNC(target_drag_leave), (gpointer) this );
|
GTK_SIGNAL_FUNC(target_drag_leave), (gpointer) this );
|
||||||
@@ -333,21 +453,18 @@ void wxDropTarget::RegisterWidget( GtkWidget *widget )
|
|||||||
|
|
||||||
bool wxTextDropTarget::OnMove( int WXUNUSED(x), int WXUNUSED(y) )
|
bool wxTextDropTarget::OnMove( int WXUNUSED(x), int WXUNUSED(y) )
|
||||||
{
|
{
|
||||||
printf( "text move.\n" );
|
return IsSupported( wxDF_TEXT ); // same as "STRING"
|
||||||
|
|
||||||
return IsSupported( wxDF_TEXT ); // same as "TEXT"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool wxTextDropTarget::OnDrop( int x, int y )
|
bool wxTextDropTarget::OnDrop( int x, int y )
|
||||||
{
|
{
|
||||||
printf( "text drop.\n" );
|
|
||||||
|
|
||||||
if (!IsSupported( wxDF_TEXT )) return FALSE;
|
if (!IsSupported( wxDF_TEXT )) return FALSE;
|
||||||
|
|
||||||
wxTextDataObject data;
|
wxTextDataObject data;
|
||||||
if (!GetData( &data )) return FALSE;
|
if (!GetData( &data )) return FALSE;
|
||||||
|
|
||||||
return OnDropText( x, y, data.GetText() );
|
OnDropText( x, y, data.GetText() );
|
||||||
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
//-------------------------------------------------------------------------
|
//-------------------------------------------------------------------------
|
||||||
@@ -376,7 +493,9 @@ bool wxPrivateDropTarget::OnDrop( int x, int y )
|
|||||||
wxPrivateDataObject data;
|
wxPrivateDataObject data;
|
||||||
if (!GetData( &data )) return FALSE;
|
if (!GetData( &data )) return FALSE;
|
||||||
|
|
||||||
return OnDropData( x, y, data.GetData(), data.GetSize() );
|
OnDropData( x, y, data.GetData(), data.GetSize() );
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
@@ -390,10 +509,13 @@ bool wxFileDropTarget::OnMove( int WXUNUSED(x), int WXUNUSED(y) )
|
|||||||
|
|
||||||
bool wxFileDropTarget::OnDrop( int x, int y )
|
bool wxFileDropTarget::OnDrop( int x, int y )
|
||||||
{
|
{
|
||||||
if (!IsSupported( wxDF_FILENAME )) return FALSE;
|
return IsSupported( wxDF_FILENAME ); // same as "file:ALL"
|
||||||
|
}
|
||||||
|
|
||||||
|
void wxFileDropTarget::OnData( int x, int y )
|
||||||
|
{
|
||||||
wxFileDataObject data;
|
wxFileDataObject data;
|
||||||
if (!GetData( &data )) return FALSE;
|
if (!GetData( &data )) return;
|
||||||
|
|
||||||
/* get number of substrings /root/mytext.txt/0/root/myothertext.txt/0/0 */
|
/* get number of substrings /root/mytext.txt/0/root/myothertext.txt/0/0 */
|
||||||
size_t number = 0;
|
size_t number = 0;
|
||||||
@@ -403,7 +525,7 @@ bool wxFileDropTarget::OnDrop( int x, int y )
|
|||||||
for ( i = 0; i < size; i++)
|
for ( i = 0; i < size; i++)
|
||||||
if (text[i] == 0) number++;
|
if (text[i] == 0) number++;
|
||||||
|
|
||||||
if (number == 0) return TRUE;
|
if (number == 0) return;
|
||||||
|
|
||||||
char **files = new char*[number];
|
char **files = new char*[number];
|
||||||
|
|
||||||
@@ -415,11 +537,9 @@ bool wxFileDropTarget::OnDrop( int x, int y )
|
|||||||
text += len+1;
|
text += len+1;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ret = OnDropFiles( x, y, number, files );
|
OnDropFiles( x, y, number, files );
|
||||||
|
|
||||||
free( files );
|
free( files );
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//-------------------------------------------------------------------------
|
//-------------------------------------------------------------------------
|
||||||
|
Reference in New Issue
Block a user