From 57479a86be71dfac361633838c8129267a278233 Mon Sep 17 00:00:00 2001 From: Owen Taylor Date: Tue, 6 Nov 2001 19:10:03 +0000 Subject: [PATCH] Add row_draggable() vfunc, and wrapper function. Mon Nov 5 22:34:29 2001 Owen Taylor * gtk/gtktreednd.[ch] (struct _GtkTreeDragSourceIface): Add row_draggable() vfunc, and wrapper function. * gtk/gtktreednd.[ch] (struct _GtkTreeDragDestIface): Make row_drop_possible take a GtkSelectionData, rather than model/row pair. * gtk/gtktreestore.c gtk/gtkliststore.c: Update for new DND interfaces. * gtk/gtktreeview.[ch]: Remove the row_draggable_func location_dropable_func from gtk_tree_view_set_rows_drag_source/dest. and rename them to enable_model_drag_source/dest. * gtk/treeviewcolumn.c: Add DND of columns between rows. Still can't drop _to_ the left tree, but other places work. * gtk/gtktreeview.c (unset_reorderable): Unset the reorderable property if unset/enable_model_drag_source/dest are called manually. * gtk/gtktreestore.c (gtk_tree_store_row_drop_possible): Correct for change in depth count handling. * gtk/gtktreeview.c (gtk_tree_view_create_row_drag_icon): Pass in a expose area to gtk_tree_view_column_cell_render() --- ChangeLog | 30 ++++ ChangeLog.pre-2-0 | 30 ++++ ChangeLog.pre-2-10 | 30 ++++ ChangeLog.pre-2-2 | 30 ++++ ChangeLog.pre-2-4 | 30 ++++ ChangeLog.pre-2-6 | 30 ++++ ChangeLog.pre-2-8 | 30 ++++ gtk/gtkliststore.c | 33 +++-- gtk/gtktreednd.c | 42 ++++-- gtk/gtktreednd.h | 17 ++- gtk/gtktreestore.c | 61 ++++---- gtk/gtktreeview.c | 147 +++++++++---------- gtk/gtktreeview.h | 21 +-- tests/testtreecolumns.c | 306 ++++++++++++++++++++++++++++++++-------- tests/testtreeview.c | 22 ++- 15 files changed, 641 insertions(+), 218 deletions(-) diff --git a/ChangeLog b/ChangeLog index cb8c8eaa4..3133db0ad 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,33 @@ +Mon Nov 5 22:34:29 2001 Owen Taylor + + * gtk/gtktreednd.[ch] (struct _GtkTreeDragSourceIface): + Add row_draggable() vfunc, and wrapper function. + + * gtk/gtktreednd.[ch] (struct _GtkTreeDragDestIface): Make + row_drop_possible take a GtkSelectionData, rather than + model/row pair. + + * gtk/gtktreestore.c gtk/gtkliststore.c: Update for + new DND interfaces. + + * gtk/gtktreeview.[ch]: Remove the row_draggable_func + location_dropable_func from gtk_tree_view_set_rows_drag_source/dest. + and rename them to enable_model_drag_source/dest. + + * gtk/treeviewcolumn.c: Add DND of columns between rows. + Still can't drop _to_ the left tree, but other places + work. + + * gtk/gtktreeview.c (unset_reorderable): Unset the + reorderable property if unset/enable_model_drag_source/dest + are called manually. + + * gtk/gtktreestore.c (gtk_tree_store_row_drop_possible): + Correct for change in depth count handling. + + * gtk/gtktreeview.c (gtk_tree_view_create_row_drag_icon): + Pass in a expose area to gtk_tree_view_column_cell_render() + 2001-11-06 Havoc Pennington * demos/gtk-demo/textview.c (easter_egg_callback): wacky easter egg diff --git a/ChangeLog.pre-2-0 b/ChangeLog.pre-2-0 index cb8c8eaa4..3133db0ad 100644 --- a/ChangeLog.pre-2-0 +++ b/ChangeLog.pre-2-0 @@ -1,3 +1,33 @@ +Mon Nov 5 22:34:29 2001 Owen Taylor + + * gtk/gtktreednd.[ch] (struct _GtkTreeDragSourceIface): + Add row_draggable() vfunc, and wrapper function. + + * gtk/gtktreednd.[ch] (struct _GtkTreeDragDestIface): Make + row_drop_possible take a GtkSelectionData, rather than + model/row pair. + + * gtk/gtktreestore.c gtk/gtkliststore.c: Update for + new DND interfaces. + + * gtk/gtktreeview.[ch]: Remove the row_draggable_func + location_dropable_func from gtk_tree_view_set_rows_drag_source/dest. + and rename them to enable_model_drag_source/dest. + + * gtk/treeviewcolumn.c: Add DND of columns between rows. + Still can't drop _to_ the left tree, but other places + work. + + * gtk/gtktreeview.c (unset_reorderable): Unset the + reorderable property if unset/enable_model_drag_source/dest + are called manually. + + * gtk/gtktreestore.c (gtk_tree_store_row_drop_possible): + Correct for change in depth count handling. + + * gtk/gtktreeview.c (gtk_tree_view_create_row_drag_icon): + Pass in a expose area to gtk_tree_view_column_cell_render() + 2001-11-06 Havoc Pennington * demos/gtk-demo/textview.c (easter_egg_callback): wacky easter egg diff --git a/ChangeLog.pre-2-10 b/ChangeLog.pre-2-10 index cb8c8eaa4..3133db0ad 100644 --- a/ChangeLog.pre-2-10 +++ b/ChangeLog.pre-2-10 @@ -1,3 +1,33 @@ +Mon Nov 5 22:34:29 2001 Owen Taylor + + * gtk/gtktreednd.[ch] (struct _GtkTreeDragSourceIface): + Add row_draggable() vfunc, and wrapper function. + + * gtk/gtktreednd.[ch] (struct _GtkTreeDragDestIface): Make + row_drop_possible take a GtkSelectionData, rather than + model/row pair. + + * gtk/gtktreestore.c gtk/gtkliststore.c: Update for + new DND interfaces. + + * gtk/gtktreeview.[ch]: Remove the row_draggable_func + location_dropable_func from gtk_tree_view_set_rows_drag_source/dest. + and rename them to enable_model_drag_source/dest. + + * gtk/treeviewcolumn.c: Add DND of columns between rows. + Still can't drop _to_ the left tree, but other places + work. + + * gtk/gtktreeview.c (unset_reorderable): Unset the + reorderable property if unset/enable_model_drag_source/dest + are called manually. + + * gtk/gtktreestore.c (gtk_tree_store_row_drop_possible): + Correct for change in depth count handling. + + * gtk/gtktreeview.c (gtk_tree_view_create_row_drag_icon): + Pass in a expose area to gtk_tree_view_column_cell_render() + 2001-11-06 Havoc Pennington * demos/gtk-demo/textview.c (easter_egg_callback): wacky easter egg diff --git a/ChangeLog.pre-2-2 b/ChangeLog.pre-2-2 index cb8c8eaa4..3133db0ad 100644 --- a/ChangeLog.pre-2-2 +++ b/ChangeLog.pre-2-2 @@ -1,3 +1,33 @@ +Mon Nov 5 22:34:29 2001 Owen Taylor + + * gtk/gtktreednd.[ch] (struct _GtkTreeDragSourceIface): + Add row_draggable() vfunc, and wrapper function. + + * gtk/gtktreednd.[ch] (struct _GtkTreeDragDestIface): Make + row_drop_possible take a GtkSelectionData, rather than + model/row pair. + + * gtk/gtktreestore.c gtk/gtkliststore.c: Update for + new DND interfaces. + + * gtk/gtktreeview.[ch]: Remove the row_draggable_func + location_dropable_func from gtk_tree_view_set_rows_drag_source/dest. + and rename them to enable_model_drag_source/dest. + + * gtk/treeviewcolumn.c: Add DND of columns between rows. + Still can't drop _to_ the left tree, but other places + work. + + * gtk/gtktreeview.c (unset_reorderable): Unset the + reorderable property if unset/enable_model_drag_source/dest + are called manually. + + * gtk/gtktreestore.c (gtk_tree_store_row_drop_possible): + Correct for change in depth count handling. + + * gtk/gtktreeview.c (gtk_tree_view_create_row_drag_icon): + Pass in a expose area to gtk_tree_view_column_cell_render() + 2001-11-06 Havoc Pennington * demos/gtk-demo/textview.c (easter_egg_callback): wacky easter egg diff --git a/ChangeLog.pre-2-4 b/ChangeLog.pre-2-4 index cb8c8eaa4..3133db0ad 100644 --- a/ChangeLog.pre-2-4 +++ b/ChangeLog.pre-2-4 @@ -1,3 +1,33 @@ +Mon Nov 5 22:34:29 2001 Owen Taylor + + * gtk/gtktreednd.[ch] (struct _GtkTreeDragSourceIface): + Add row_draggable() vfunc, and wrapper function. + + * gtk/gtktreednd.[ch] (struct _GtkTreeDragDestIface): Make + row_drop_possible take a GtkSelectionData, rather than + model/row pair. + + * gtk/gtktreestore.c gtk/gtkliststore.c: Update for + new DND interfaces. + + * gtk/gtktreeview.[ch]: Remove the row_draggable_func + location_dropable_func from gtk_tree_view_set_rows_drag_source/dest. + and rename them to enable_model_drag_source/dest. + + * gtk/treeviewcolumn.c: Add DND of columns between rows. + Still can't drop _to_ the left tree, but other places + work. + + * gtk/gtktreeview.c (unset_reorderable): Unset the + reorderable property if unset/enable_model_drag_source/dest + are called manually. + + * gtk/gtktreestore.c (gtk_tree_store_row_drop_possible): + Correct for change in depth count handling. + + * gtk/gtktreeview.c (gtk_tree_view_create_row_drag_icon): + Pass in a expose area to gtk_tree_view_column_cell_render() + 2001-11-06 Havoc Pennington * demos/gtk-demo/textview.c (easter_egg_callback): wacky easter egg diff --git a/ChangeLog.pre-2-6 b/ChangeLog.pre-2-6 index cb8c8eaa4..3133db0ad 100644 --- a/ChangeLog.pre-2-6 +++ b/ChangeLog.pre-2-6 @@ -1,3 +1,33 @@ +Mon Nov 5 22:34:29 2001 Owen Taylor + + * gtk/gtktreednd.[ch] (struct _GtkTreeDragSourceIface): + Add row_draggable() vfunc, and wrapper function. + + * gtk/gtktreednd.[ch] (struct _GtkTreeDragDestIface): Make + row_drop_possible take a GtkSelectionData, rather than + model/row pair. + + * gtk/gtktreestore.c gtk/gtkliststore.c: Update for + new DND interfaces. + + * gtk/gtktreeview.[ch]: Remove the row_draggable_func + location_dropable_func from gtk_tree_view_set_rows_drag_source/dest. + and rename them to enable_model_drag_source/dest. + + * gtk/treeviewcolumn.c: Add DND of columns between rows. + Still can't drop _to_ the left tree, but other places + work. + + * gtk/gtktreeview.c (unset_reorderable): Unset the + reorderable property if unset/enable_model_drag_source/dest + are called manually. + + * gtk/gtktreestore.c (gtk_tree_store_row_drop_possible): + Correct for change in depth count handling. + + * gtk/gtktreeview.c (gtk_tree_view_create_row_drag_icon): + Pass in a expose area to gtk_tree_view_column_cell_render() + 2001-11-06 Havoc Pennington * demos/gtk-demo/textview.c (easter_egg_callback): wacky easter egg diff --git a/ChangeLog.pre-2-8 b/ChangeLog.pre-2-8 index cb8c8eaa4..3133db0ad 100644 --- a/ChangeLog.pre-2-8 +++ b/ChangeLog.pre-2-8 @@ -1,3 +1,33 @@ +Mon Nov 5 22:34:29 2001 Owen Taylor + + * gtk/gtktreednd.[ch] (struct _GtkTreeDragSourceIface): + Add row_draggable() vfunc, and wrapper function. + + * gtk/gtktreednd.[ch] (struct _GtkTreeDragDestIface): Make + row_drop_possible take a GtkSelectionData, rather than + model/row pair. + + * gtk/gtktreestore.c gtk/gtkliststore.c: Update for + new DND interfaces. + + * gtk/gtktreeview.[ch]: Remove the row_draggable_func + location_dropable_func from gtk_tree_view_set_rows_drag_source/dest. + and rename them to enable_model_drag_source/dest. + + * gtk/treeviewcolumn.c: Add DND of columns between rows. + Still can't drop _to_ the left tree, but other places + work. + + * gtk/gtktreeview.c (unset_reorderable): Unset the + reorderable property if unset/enable_model_drag_source/dest + are called manually. + + * gtk/gtktreestore.c (gtk_tree_store_row_drop_possible): + Correct for change in depth count handling. + + * gtk/gtktreeview.c (gtk_tree_view_create_row_drag_icon): + Pass in a expose area to gtk_tree_view_column_cell_render() + 2001-11-06 Havoc Pennington * demos/gtk-demo/textview.c (easter_egg_callback): wacky easter egg diff --git a/gtk/gtkliststore.c b/gtk/gtkliststore.c index ebb6fd2a3..5f8bfc335 100644 --- a/gtk/gtkliststore.c +++ b/gtk/gtkliststore.c @@ -84,9 +84,8 @@ static gboolean gtk_list_store_drag_data_received (GtkTreeDragDest *drag_dest, GtkTreePath *dest, GtkSelectionData *selection_data); static gboolean gtk_list_store_row_drop_possible (GtkTreeDragDest *drag_dest, - GtkTreeModel *src_model, - GtkTreePath *src_path, - GtkTreePath *dest_path); + GtkTreePath *dest_path, + GtkSelectionData *selection_data); /* sortable */ @@ -1407,29 +1406,39 @@ gtk_list_store_drag_data_received (GtkTreeDragDest *drag_dest, } static gboolean -gtk_list_store_row_drop_possible (GtkTreeDragDest *drag_dest, - GtkTreeModel *src_model, - GtkTreePath *src_path, - GtkTreePath *dest_path) +gtk_list_store_row_drop_possible (GtkTreeDragDest *drag_dest, + GtkTreePath *dest_path, + GtkSelectionData *selection_data) { gint *indices; + GtkTreeModel *src_model = NULL; + GtkTreePath *src_path = NULL; + gboolean retval = FALSE; g_return_val_if_fail (GTK_IS_LIST_STORE (drag_dest), FALSE); + if (!gtk_tree_get_row_drag_data (selection_data, + &src_model, + &src_path)) + goto out; + if (src_model != GTK_TREE_MODEL (drag_dest)) - return FALSE; + goto out; if (gtk_tree_path_get_depth (dest_path) != 1) - return FALSE; + goto out; /* can drop before any existing node, or before one past any existing. */ indices = gtk_tree_path_get_indices (dest_path); if (indices[0] <= GTK_LIST_STORE (drag_dest)->length) - return TRUE; - else - return FALSE; + retval = TRUE; + + out: + gtk_tree_path_free (src_path); + + return retval; } diff --git a/gtk/gtktreednd.c b/gtk/gtktreednd.c index 8f1cd7b3a..22873b126 100644 --- a/gtk/gtktreednd.c +++ b/gtk/gtktreednd.c @@ -73,6 +73,31 @@ gtk_tree_drag_dest_get_type (void) return our_type; } +/** + * gtk_tree_drag_source_row_draggable: + * @drag_source: a #GtkTreeDragSource + * @path: row on which user is initiating a drag + * + * Asks the #GtkTreeDragSource whether a particular row can be used as + * the source of a DND operation. If the source doesn't implement + * this interface, the row is assumed draggable. + * + * Return value: %TRUE if the row can be dragged + **/ +gboolean +gtk_tree_drag_source_row_draggable (GtkTreeDragSource *drag_source, + GtkTreePath *path) +{ + GtkTreeDragSourceIface *iface = GTK_TREE_DRAG_SOURCE_GET_IFACE (drag_source); + + g_return_val_if_fail (path != NULL, FALSE); + + if (iface->row_draggable) + return (* iface->row_draggable) (drag_source, path); + else + return TRUE; +} + /** * gtk_tree_drag_source_drag_data_delete: @@ -159,13 +184,12 @@ gtk_tree_drag_dest_drag_data_received (GtkTreeDragDest *drag_dest, /** * gtk_tree_drag_dest_drop_possible: * @drag_dest: a #GtkTreeDragDest - * @src_model: #GtkTreeModel being dragged from - * @src_path: row being dragged * @dest_path: destination row + * @selection_data: the data being dragged * * Determines whether a drop is possible before the given @dest_path, - * at the same depth as @dest_path. i.e., can we drop @src_model such - * that it now resides at @dest_path. @dest_path does not have to + * at the same depth as @dest_path. i.e., can we drop the data in + * @selection_data at that location. @dest_path does not have to * exist; the return value will almost certainly be %FALSE if the * parent of @dest_path doesn't exist, though. * @@ -173,18 +197,16 @@ gtk_tree_drag_dest_drag_data_received (GtkTreeDragDest *drag_dest, **/ gboolean gtk_tree_drag_dest_row_drop_possible (GtkTreeDragDest *drag_dest, - GtkTreeModel *src_model, - GtkTreePath *src_path, - GtkTreePath *dest_path) + GtkTreePath *dest_path, + GtkSelectionData *selection_data) { GtkTreeDragDestIface *iface = GTK_TREE_DRAG_DEST_GET_IFACE (drag_dest); g_return_val_if_fail (iface->row_drop_possible != NULL, FALSE); - g_return_val_if_fail (GTK_IS_TREE_MODEL (src_model), FALSE); - g_return_val_if_fail (src_path != NULL, FALSE); + g_return_val_if_fail (selection_data != NULL, FALSE); g_return_val_if_fail (dest_path != NULL, FALSE); - return (* iface->row_drop_possible) (drag_dest, src_model, src_path, dest_path); + return (* iface->row_drop_possible) (drag_dest, dest_path, selection_data); } typedef struct _TreeRowData TreeRowData; diff --git a/gtk/gtktreednd.h b/gtk/gtktreednd.h index fe1373ebf..74a796755 100644 --- a/gtk/gtktreednd.h +++ b/gtk/gtktreednd.h @@ -41,6 +41,9 @@ struct _GtkTreeDragSourceIface /* VTable - not signals */ + gboolean (* row_draggable) (GtkTreeDragSource *drag_source, + GtkTreePath *path); + gboolean (* drag_data_get) (GtkTreeDragSource *drag_source, GtkTreePath *path, GtkSelectionData *selection_data); @@ -51,6 +54,10 @@ struct _GtkTreeDragSourceIface GType gtk_tree_drag_source_get_type (void) G_GNUC_CONST; +/* Returns whether the given row can be dragged */ +gboolean gtk_tree_drag_source_row_draggable (GtkTreeDragSource *drag_source, + GtkTreePath *path); + /* Deletes the given row, or returns FALSE if it can't */ gboolean gtk_tree_drag_source_drag_data_delete (GtkTreeDragSource *drag_source, GtkTreePath *path); @@ -81,9 +88,8 @@ struct _GtkTreeDragDestIface GtkSelectionData *selection_data); gboolean (* row_drop_possible) (GtkTreeDragDest *drag_dest, - GtkTreeModel *src_model, - GtkTreePath *src_path, - GtkTreePath *dest_path); + GtkTreePath *dest_path, + GtkSelectionData *selection_data); }; GType gtk_tree_drag_dest_get_type (void) G_GNUC_CONST; @@ -98,9 +104,8 @@ gboolean gtk_tree_drag_dest_drag_data_received (GtkTreeDragDest *drag_dest, /* Returns TRUE if we can drop before path; path may not exist. */ gboolean gtk_tree_drag_dest_row_drop_possible (GtkTreeDragDest *drag_dest, - GtkTreeModel *src_model, - GtkTreePath *src_path, - GtkTreePath *dest_path); + GtkTreePath *dest_path, + GtkSelectionData *selection_data); /* The selection data would normally have target type GTK_TREE_MODEL_ROW in this diff --git a/gtk/gtktreestore.c b/gtk/gtktreestore.c index 85049b1fe..cec22d8cf 100644 --- a/gtk/gtktreestore.c +++ b/gtk/gtktreestore.c @@ -83,9 +83,8 @@ static gboolean gtk_tree_store_drag_data_received (GtkTreeDragDest *drag_dest, GtkTreePath *dest, GtkSelectionData *selection_data); static gboolean gtk_tree_store_row_drop_possible (GtkTreeDragDest *drag_dest, - GtkTreeModel *src_model, - GtkTreePath *src_path, - GtkTreePath *dest_path); + GtkTreePath *dest_path, + GtkSelectionData *selection_data); /* Sortable Interfaces */ @@ -1587,45 +1586,55 @@ gtk_tree_store_drag_data_received (GtkTreeDragDest *drag_dest, } static gboolean -gtk_tree_store_row_drop_possible (GtkTreeDragDest *drag_dest, - GtkTreeModel *src_model, - GtkTreePath *src_path, - GtkTreePath *dest_path) +gtk_tree_store_row_drop_possible (GtkTreeDragDest *drag_dest, + GtkTreePath *dest_path, + GtkSelectionData *selection_data) { + GtkTreeModel *src_model = NULL; + GtkTreePath *src_path = NULL; + GtkTreePath *tmp = NULL; + gboolean retval = FALSE; + + if (!gtk_tree_get_row_drag_data (selection_data, + &src_model, + &src_path)) + goto out; + /* can only drag to ourselves */ if (src_model != GTK_TREE_MODEL (drag_dest)) - return FALSE; + goto out; /* Can't drop into ourself. */ if (gtk_tree_path_is_ancestor (src_path, dest_path)) - return FALSE; + goto out; /* Can't drop if dest_path's parent doesn't exist */ { GtkTreeIter iter; - GtkTreePath *tmp = gtk_tree_path_copy (dest_path); - /* if we can't go up, we know the parent exists, the root - * always exists. - */ - if (gtk_tree_path_up (tmp)) + if (gtk_tree_path_get_depth (dest_path) > 1) { - if (!gtk_tree_model_get_iter (GTK_TREE_MODEL (drag_dest), - &iter, tmp)) - { - if (tmp) - gtk_tree_path_free (tmp); - return FALSE; - } + tmp = gtk_tree_path_copy (dest_path); + gtk_tree_path_up (tmp); + + if (!gtk_tree_model_get_iter (GTK_TREE_MODEL (drag_dest), + &iter, tmp)) + goto out; } - - if (tmp) - gtk_tree_path_free (tmp); } - + /* Can otherwise drop anywhere. */ - return TRUE; + retval = TRUE; + + out: + + if (src_path) + gtk_tree_path_free (src_path); + if (tmp) + gtk_tree_path_free (tmp); + + return retval; } /* Sorting */ diff --git a/gtk/gtktreeview.c b/gtk/gtktreeview.c index 0673330bd..ff65f9c44 100644 --- a/gtk/gtktreeview.c +++ b/gtk/gtktreeview.c @@ -77,10 +77,8 @@ struct _TreeViewDragInfo GdkModifierType start_button_mask; GtkTargetList *source_target_list; GdkDragAction source_actions; - GClosure *row_draggable_closure; GtkTargetList *dest_target_list; - GClosure *location_droppable_closure; guint source_set : 1; guint dest_set : 1; @@ -2463,6 +2461,9 @@ gtk_tree_view_motion (GtkWidget *widget, /* Warning: Very scary function. * Modify at your own risk + * + * KEEP IN SYNC WITH gtk_tree_view_create_row_drag_icon()! + * FIXME: It's not... */ static gboolean gtk_tree_view_bin_expose (GtkWidget *widget, @@ -3127,23 +3128,15 @@ clear_source_info (TreeViewDragInfo *di) if (di->source_target_list) gtk_target_list_unref (di->source_target_list); - if (di->row_draggable_closure) - g_closure_unref (di->row_draggable_closure); - di->source_target_list = NULL; - di->row_draggable_closure = NULL; } static void clear_dest_info (TreeViewDragInfo *di) { - if (di->location_droppable_closure) - g_closure_unref (di->location_droppable_closure); - if (di->dest_target_list) gtk_target_list_unref (di->dest_target_list); - di->location_droppable_closure = NULL; di->dest_target_list = NULL; } @@ -3464,25 +3457,26 @@ gtk_tree_view_maybe_begin_dragging_row (GtkTreeView *tree_view, gint button; gint cell_x, cell_y; GtkTreeModel *model; + gboolean retval = FALSE; di = get_info (tree_view); if (di == NULL) - return FALSE; + goto out; if (tree_view->priv->pressed_button < 0) - return FALSE; + goto out; if (!gtk_drag_check_threshold (GTK_WIDGET (tree_view), tree_view->priv->press_start_x, tree_view->priv->press_start_y, event->x, event->y)) - return FALSE; + goto out; model = gtk_tree_view_get_model (tree_view); if (model == NULL) - return FALSE; + goto out; button = tree_view->priv->pressed_button; tree_view->priv->pressed_button = -1; @@ -3497,16 +3491,21 @@ gtk_tree_view_maybe_begin_dragging_row (GtkTreeView *tree_view, &cell_y); if (path == NULL) - return FALSE; + goto out; - /* FIXME if the path doesn't match the row_draggable predicate, - * return FALSE and free path - */ + if (!GTK_IS_TREE_DRAG_SOURCE (model) || + !gtk_tree_drag_source_row_draggable (GTK_TREE_DRAG_SOURCE (model), + path)) + goto out; /* FIXME Check whether we're a start button, if not return FALSE and * free path */ + /* Now we can begin the drag */ + + retval = TRUE; + context = gtk_drag_begin (GTK_WIDGET (tree_view), di->source_target_list, di->source_actions, @@ -3533,9 +3532,12 @@ gtk_tree_view_maybe_begin_dragging_row (GtkTreeView *tree_view, } set_source_row (context, model, path); - gtk_tree_path_free (path); - return TRUE; + out: + if (path) + gtk_tree_path_free (path); + + return retval; } @@ -3822,24 +3824,10 @@ gtk_tree_view_drag_data_received (GtkWidget *widget, if (suggested_action) { - GtkTreeModel *src_model = NULL; - GtkTreePath *src_path = NULL; - - if (!gtk_tree_get_row_drag_data (selection_data, - &src_model, - &src_path)) - suggested_action = 0; - - if (suggested_action) - { - if (!gtk_tree_drag_dest_row_drop_possible (GTK_TREE_DRAG_DEST (model), - src_model, - src_path, - path)) - suggested_action = 0; - - gtk_tree_path_free (src_path); - } + if (!gtk_tree_drag_dest_row_drop_possible (GTK_TREE_DRAG_DEST (model), + path, + selection_data)) + suggested_action = 0; } gdk_drag_status (context, suggested_action, time); @@ -7996,17 +7984,15 @@ gtk_tree_view_set_reorderable (GtkTreeView *tree_view, if (reorderable) { - gtk_tree_view_set_rows_drag_source (tree_view, - GDK_BUTTON1_MASK, - row_targets, - G_N_ELEMENTS (row_targets), - GDK_ACTION_MOVE, - NULL, NULL); - gtk_tree_view_set_rows_drag_dest (tree_view, - row_targets, - G_N_ELEMENTS (row_targets), - GDK_ACTION_MOVE, - NULL, NULL); + gtk_tree_view_enable_model_drag_source (tree_view, + GDK_BUTTON1_MASK, + row_targets, + G_N_ELEMENTS (row_targets), + GDK_ACTION_MOVE); + gtk_tree_view_enable_model_drag_dest (tree_view, + row_targets, + G_N_ELEMENTS (row_targets), + GDK_ACTION_MOVE); } else { @@ -8475,15 +8461,22 @@ gtk_tree_view_tree_to_widget_coords (GtkTreeView *tree_view, *wy = ty - tree_view->priv->vadjustment->value; } +static void +unset_reorderable (GtkTreeView *tree_view) +{ + if (tree_view->priv->reorderable) + { + tree_view->priv->reorderable = FALSE; + g_object_notify (G_OBJECT (tree_view), "reorderable"); + } +} void -gtk_tree_view_set_rows_drag_source (GtkTreeView *tree_view, - GdkModifierType start_button_mask, - const GtkTargetEntry *targets, - gint n_targets, - GdkDragAction actions, - GtkTreeViewDraggableFunc row_draggable_func, - gpointer user_data) +gtk_tree_view_enable_model_drag_source (GtkTreeView *tree_view, + GdkModifierType start_button_mask, + const GtkTargetEntry *targets, + gint n_targets, + GdkDragAction actions) { TreeViewDragInfo *di; @@ -8496,24 +8489,16 @@ gtk_tree_view_set_rows_drag_source (GtkTreeView *tree_view, di->source_target_list = gtk_target_list_new (targets, n_targets); di->source_actions = actions; - if (row_draggable_func) - { - di->row_draggable_closure = g_cclosure_new ((GCallback) row_draggable_func, - user_data, NULL); - g_closure_ref (di->row_draggable_closure); - g_closure_sink (di->row_draggable_closure); - } - di->source_set = TRUE; + + unset_reorderable (tree_view); } void -gtk_tree_view_set_rows_drag_dest (GtkTreeView *tree_view, - const GtkTargetEntry *targets, - gint n_targets, - GdkDragAction actions, - GtkTreeViewDroppableFunc location_droppable_func, - gpointer user_data) +gtk_tree_view_enable_model_drag_dest (GtkTreeView *tree_view, + const GtkTargetEntry *targets, + gint n_targets, + GdkDragAction actions) { TreeViewDragInfo *di; @@ -8531,15 +8516,9 @@ gtk_tree_view_set_rows_drag_dest (GtkTreeView *tree_view, if (targets) di->dest_target_list = gtk_target_list_new (targets, n_targets); - if (location_droppable_func) - { - di->location_droppable_closure = g_cclosure_new ((GCallback) location_droppable_func, - user_data, NULL); - g_closure_ref (di->location_droppable_closure); - g_closure_sink (di->location_droppable_closure); - } - di->dest_set = TRUE; + + unset_reorderable (tree_view); } void @@ -8562,6 +8541,8 @@ gtk_tree_view_unset_rows_drag_source (GtkTreeView *tree_view) if (!di->dest_set && !di->source_set) remove_info (tree_view); } + + unset_reorderable (tree_view); } void @@ -8585,6 +8566,8 @@ gtk_tree_view_unset_rows_drag_dest (GtkTreeView *tree_view) if (!di->dest_set && !di->source_set) remove_info (tree_view); } + + unset_reorderable (tree_view); } void @@ -8754,6 +8737,7 @@ gtk_tree_view_create_row_drag_icon (GtkTreeView *tree_view, gint cell_offset; GList *list; GdkRectangle background_area; + GdkRectangle expose_area; GtkWidget *widget; gint depth; /* start drawing inside the black outline */ @@ -8791,6 +8775,11 @@ gtk_tree_view_create_row_drag_icon (GtkTreeView *tree_view, background_area.height + 2, -1); + expose_area.x = 0; + expose_area.y = 0; + expose_area.width = bin_window_width + 2; + expose_area.height = background_area.height + 2; + gdk_draw_rectangle (drawable, widget->style->base_gc [GTK_WIDGET_STATE (widget)], TRUE, @@ -8839,7 +8828,7 @@ gtk_tree_view_create_row_drag_icon (GtkTreeView *tree_view, drawable, &background_area, &cell_area, - NULL, + &expose_area, 0); cell_offset += column->width; diff --git a/gtk/gtktreeview.h b/gtk/gtktreeview.h index 8fbd7efd7..d6c56bd94 100644 --- a/gtk/gtktreeview.h +++ b/gtk/gtktreeview.h @@ -108,18 +108,9 @@ typedef gboolean (* GtkTreeViewColumnDropFunc) (GtkTreeView *tree_vi GtkTreeViewColumn *prev_column, GtkTreeViewColumn *next_column, gpointer data); -typedef gboolean (* GtkTreeViewDraggableFunc) (GtkTreeView *tree_view, - GdkDragContext *context, - GtkTreePath *path, - gpointer user_data); typedef void (* GtkTreeViewMappingFunc) (GtkTreeView *tree_view, GtkTreePath *path, gpointer user_data); -typedef gboolean (* GtkTreeViewDroppableFunc) (GtkTreeView *tree_view, - GdkDragContext *context, - GtkTreePath *path, - GtkTreeViewDropPosition *pos, - gpointer user_data); typedef gboolean (*GtkTreeViewSearchEqualFunc) (GtkTreeModel *model, gint column, const gchar *key, @@ -255,19 +246,15 @@ void gtk_tree_view_tree_to_widget_coords (GtkTreeView gint *wy); /* Drag-and-Drop support */ -void gtk_tree_view_set_rows_drag_source (GtkTreeView *tree_view, +void gtk_tree_view_enable_model_drag_source (GtkTreeView *tree_view, GdkModifierType start_button_mask, const GtkTargetEntry *targets, gint n_targets, - GdkDragAction actions, - GtkTreeViewDraggableFunc row_draggable_func, - gpointer user_data); -void gtk_tree_view_set_rows_drag_dest (GtkTreeView *tree_view, + GdkDragAction actions); +void gtk_tree_view_enable_model_drag_dest (GtkTreeView *tree_view, const GtkTargetEntry *targets, gint n_targets, - GdkDragAction actions, - GtkTreeViewDroppableFunc location_droppable_func, - gpointer user_data); + GdkDragAction actions); void gtk_tree_view_unset_rows_drag_source (GtkTreeView *tree_view); void gtk_tree_view_unset_rows_drag_dest (GtkTreeView *tree_view); diff --git a/tests/testtreecolumns.c b/tests/testtreecolumns.c index c57eb0755..dda575104 100644 --- a/tests/testtreecolumns.c +++ b/tests/testtreecolumns.c @@ -33,7 +33,10 @@ GtkWidget *sample_tree_view_bottom; #define column_data "my_column_data" - +static void move_row (GtkTreeModel *src, + GtkTreeIter *src_iter, + GtkTreeModel *dest, + GtkTreeIter *dest_iter); /* Kids, don't try this at home. */ @@ -246,6 +249,102 @@ view_column_model_tree_model_init (GtkTreeModelIface *iface) iface->iter_parent = view_column_model_iter_parent; } +static gboolean +view_column_model_drag_data_get (GtkTreeDragSource *drag_source, + GtkTreePath *path, + GtkSelectionData *selection_data) +{ + if (gtk_tree_set_row_drag_data (selection_data, + GTK_TREE_MODEL (drag_source), + path)) + return TRUE; + else + return FALSE; +} + +static gboolean +view_column_model_drag_data_delete (GtkTreeDragSource *drag_source, + GtkTreePath *path) +{ + /* Nothing -- we handle moves on the dest side */ + + return TRUE; +} + +static gboolean +view_column_model_row_drop_possible (GtkTreeDragDest *drag_dest, + GtkTreePath *dest_path, + GtkSelectionData *selection_data) +{ + GtkTreeModel *src_model; + + if (gtk_tree_get_row_drag_data (selection_data, + &src_model, + NULL)) + { + if (src_model == left_tree_model || + src_model == top_right_tree_model || + src_model == bottom_right_tree_model) + return TRUE; + } + + return FALSE; +} + +static gboolean +view_column_model_drag_data_received (GtkTreeDragDest *drag_dest, + GtkTreePath *dest, + GtkSelectionData *selection_data) +{ + GtkTreeModel *src_model; + GtkTreePath *src_path = NULL; + gboolean retval = FALSE; + + if (gtk_tree_get_row_drag_data (selection_data, + &src_model, + &src_path)) + { + GtkTreeIter src_iter; + GtkTreeIter dest_iter; + gboolean have_dest; + + /* We are a little lazy here, and assume if we can't convert dest + * to an iter, we need to append. See gtkliststore.c for a more + * careful handling of this. + */ + have_dest = gtk_tree_model_get_iter (GTK_TREE_MODEL (drag_dest), &dest_iter, dest); + + if (gtk_tree_model_get_iter (src_model, &src_iter, src_path)) + { + if (src_model == left_tree_model || + src_model == top_right_tree_model || + src_model == bottom_right_tree_model) + { + move_row (src_model, &src_iter, GTK_TREE_MODEL (drag_dest), + have_dest ? &dest_iter : NULL); + retval = TRUE; + } + } + + gtk_tree_path_free (src_path); + } + + return retval; +} + +static void +view_column_model_drag_source_init (GtkTreeDragSourceIface *iface) +{ + iface->drag_data_get = view_column_model_drag_data_get; + iface->drag_data_delete = view_column_model_drag_data_delete; +} + +static void +view_column_model_drag_dest_init (GtkTreeDragDestIface *iface) +{ + iface->drag_data_received = view_column_model_drag_data_received; + iface->row_drop_possible = view_column_model_row_drop_possible; +} GType view_column_model_get_type (void) @@ -274,10 +373,30 @@ view_column_model_get_type (void) NULL }; + static const GInterfaceInfo drag_source_info = + { + (GInterfaceInitFunc) view_column_model_drag_source_init, + NULL, + NULL + }; + + static const GInterfaceInfo drag_dest_info = + { + (GInterfaceInitFunc) view_column_model_drag_dest_init, + NULL, + NULL + }; + view_column_model_type = g_type_register_static (G_TYPE_OBJECT, "ViewModelColumn", &view_column_model_info, 0); g_type_add_interface_static (view_column_model_type, GTK_TYPE_TREE_MODEL, &tree_model_info); + g_type_add_interface_static (view_column_model_type, + GTK_TYPE_TREE_DRAG_SOURCE, + &drag_source_info); + g_type_add_interface_static (view_column_model_type, + GTK_TYPE_TREE_DRAG_DEST, + &drag_dest_info); } return view_column_model_type; @@ -470,20 +589,18 @@ set_visible (GtkCellRendererToggle *cell, } static void -add_left_clicked (GtkWidget *button, - gpointer data) +move_to_left (GtkTreeModel *src, + GtkTreeIter *src_iter, + GtkTreeIter *dest_iter) { GtkTreeIter iter; - gchar *label; GtkTreeViewColumn *column; + GtkTreeSelection *selection; + gchar *label; - GtkTreeSelection *selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (data)); - - gtk_tree_selection_get_selected (selection, NULL, &iter); - gtk_tree_model_get (gtk_tree_view_get_model (GTK_TREE_VIEW (data)), - &iter, 0, &label, 1, &column, -1); + gtk_tree_model_get (src, src_iter, 0, &label, 1, &column, -1); - if (GTK_WIDGET (data) == top_right_tree_view) + if (src == top_right_tree_model) gtk_tree_view_remove_column (GTK_TREE_VIEW (sample_tree_view_top), column); else gtk_tree_view_remove_column (GTK_TREE_VIEW (sample_tree_view_bottom), column); @@ -491,33 +608,116 @@ add_left_clicked (GtkWidget *button, /* gtk_list_store_remove (GTK_LIST_STORE (gtk_tree_view_get_model (GTK_TREE_VIEW (data))), &iter);*/ /* Put it back on the left */ - gtk_list_store_append (GTK_LIST_STORE (left_tree_model), &iter); + if (dest_iter) + gtk_list_store_insert_before (GTK_LIST_STORE (left_tree_model), + &iter, dest_iter); + else + gtk_list_store_append (GTK_LIST_STORE (left_tree_model), &iter); + gtk_list_store_set (GTK_LIST_STORE (left_tree_model), &iter, 0, label, 1, column, -1); selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (left_tree_view)); gtk_tree_selection_select_iter (selection, &iter); + + g_free (label); +} + +static void +move_to_right (GtkTreeIter *src_iter, + GtkTreeModel *dest, + GtkTreeIter *dest_iter) +{ + gchar *label; + GtkTreeViewColumn *column; + gint before = -1; + + gtk_tree_model_get (GTK_TREE_MODEL (left_tree_model), + src_iter, 0, &label, 1, &column, -1); + gtk_list_store_remove (GTK_LIST_STORE (left_tree_model), src_iter); + + if (dest_iter) + { + GtkTreePath *path = gtk_tree_model_get_path (dest, dest_iter); + before = (gtk_tree_path_get_indices (path))[0]; + gtk_tree_path_free (path); + } + + if (dest == top_right_tree_model) + gtk_tree_view_insert_column (GTK_TREE_VIEW (sample_tree_view_top), column, before); + else + gtk_tree_view_insert_column (GTK_TREE_VIEW (sample_tree_view_bottom), column, before); + + g_free (label); +} + +static void +move_up_or_down (GtkTreeModel *src, + GtkTreeIter *src_iter, + GtkTreeModel *dest, + GtkTreeIter *dest_iter) +{ + GtkTreeViewColumn *column; + gchar *label; + gint before = -1; + + gtk_tree_model_get (src, src_iter, 0, &label, 1, &column, -1); + + if (dest_iter) + { + GtkTreePath *path = gtk_tree_model_get_path (dest, dest_iter); + before = (gtk_tree_path_get_indices (path))[0]; + gtk_tree_path_free (path); + } + + if (src == top_right_tree_model) + gtk_tree_view_remove_column (GTK_TREE_VIEW (sample_tree_view_top), column); + else + gtk_tree_view_remove_column (GTK_TREE_VIEW (sample_tree_view_bottom), column); + + if (dest == top_right_tree_model) + gtk_tree_view_insert_column (GTK_TREE_VIEW (sample_tree_view_top), column, before); + else + gtk_tree_view_insert_column (GTK_TREE_VIEW (sample_tree_view_bottom), column, before); + g_free (label); } +static void +move_row (GtkTreeModel *src, + GtkTreeIter *src_iter, + GtkTreeModel *dest, + GtkTreeIter *dest_iter) +{ + if (src == left_tree_model) + move_to_right (src_iter, dest, dest_iter); + else if (dest == left_tree_model) + move_to_left (src, src_iter, dest_iter); + else + move_up_or_down (src, src_iter, dest, dest_iter); +} + +static void +add_left_clicked (GtkWidget *button, + gpointer data) +{ + GtkTreeIter iter; + + GtkTreeSelection *selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (data)); + + gtk_tree_selection_get_selected (selection, NULL, &iter); + + move_to_left (gtk_tree_view_get_model (GTK_TREE_VIEW (data)), &iter, NULL); +} static void add_right_clicked (GtkWidget *button, gpointer data) { GtkTreeIter iter; - gchar *label; - GtkTreeViewColumn *column; GtkTreeSelection *selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (left_tree_view)); gtk_tree_selection_get_selected (selection, NULL, &iter); - gtk_tree_model_get (GTK_TREE_MODEL (left_tree_model), - &iter, 0, &label, 1, &column, -1); - gtk_list_store_remove (GTK_LIST_STORE (left_tree_model), &iter); - if (GTK_WIDGET (data) == top_right_tree_view) - gtk_tree_view_append_column (GTK_TREE_VIEW (sample_tree_view_top), column); - else - gtk_tree_view_append_column (GTK_TREE_VIEW (sample_tree_view_bottom), column); - g_free (label); + move_to_right (&iter, gtk_tree_view_get_model (GTK_TREE_VIEW (data)), NULL); } static void @@ -689,41 +889,35 @@ main (int argc, char *argv[]) /* Drag and Drop */ - gtk_tree_view_set_rows_drag_source (GTK_TREE_VIEW (left_tree_view), - GDK_BUTTON1_MASK, - row_targets, - G_N_ELEMENTS (row_targets), - GDK_ACTION_MOVE, - NULL, NULL); - gtk_tree_view_set_rows_drag_dest (GTK_TREE_VIEW (left_tree_view), - row_targets, - G_N_ELEMENTS (row_targets), - GDK_ACTION_MOVE, - NULL, NULL); - - gtk_tree_view_set_rows_drag_source (GTK_TREE_VIEW (top_right_tree_view), - GDK_BUTTON1_MASK, - row_targets, - G_N_ELEMENTS (row_targets), - GDK_ACTION_MOVE, - NULL, NULL); - gtk_tree_view_set_rows_drag_dest (GTK_TREE_VIEW (top_right_tree_view), - row_targets, - G_N_ELEMENTS (row_targets), - GDK_ACTION_MOVE, - NULL, NULL); - - gtk_tree_view_set_rows_drag_source (GTK_TREE_VIEW (bottom_right_tree_view), - GDK_BUTTON1_MASK, - row_targets, - G_N_ELEMENTS (row_targets), - GDK_ACTION_MOVE, - NULL, NULL); - gtk_tree_view_set_rows_drag_dest (GTK_TREE_VIEW (bottom_right_tree_view), - row_targets, - G_N_ELEMENTS (row_targets), - GDK_ACTION_MOVE, - NULL, NULL); + gtk_tree_view_enable_model_drag_source (GTK_TREE_VIEW (left_tree_view), + GDK_BUTTON1_MASK, + row_targets, + G_N_ELEMENTS (row_targets), + GDK_ACTION_MOVE); + gtk_tree_view_enable_model_drag_dest (GTK_TREE_VIEW (left_tree_view), + row_targets, + G_N_ELEMENTS (row_targets), + GDK_ACTION_MOVE); + + gtk_tree_view_enable_model_drag_source (GTK_TREE_VIEW (top_right_tree_view), + GDK_BUTTON1_MASK, + row_targets, + G_N_ELEMENTS (row_targets), + GDK_ACTION_MOVE); + gtk_tree_view_enable_model_drag_dest (GTK_TREE_VIEW (top_right_tree_view), + row_targets, + G_N_ELEMENTS (row_targets), + GDK_ACTION_MOVE); + + gtk_tree_view_enable_model_drag_source (GTK_TREE_VIEW (bottom_right_tree_view), + GDK_BUTTON1_MASK, + row_targets, + G_N_ELEMENTS (row_targets), + GDK_ACTION_MOVE); + gtk_tree_view_enable_model_drag_dest (GTK_TREE_VIEW (bottom_right_tree_view), + row_targets, + G_N_ELEMENTS (row_targets), + GDK_ACTION_MOVE); gtk_box_pack_start (GTK_BOX (vbox), gtk_hseparator_new (), FALSE, FALSE, 0); diff --git a/tests/testtreeview.c b/tests/testtreeview.c index 6367a5f32..43bedfcfb 100644 --- a/tests/testtreeview.c +++ b/tests/testtreeview.c @@ -656,18 +656,16 @@ main (int argc, tv = gtk_tree_view_new_with_model (models[0]); - gtk_tree_view_set_rows_drag_source (GTK_TREE_VIEW (tv), - GDK_BUTTON1_MASK, - row_targets, - G_N_ELEMENTS (row_targets), - GDK_ACTION_MOVE | GDK_ACTION_COPY, - NULL, NULL); - - gtk_tree_view_set_rows_drag_dest (GTK_TREE_VIEW (tv), - row_targets, - G_N_ELEMENTS (row_targets), - GDK_ACTION_MOVE | GDK_ACTION_COPY, - NULL, NULL); + gtk_tree_view_enable_model_drag_source (GTK_TREE_VIEW (tv), + GDK_BUTTON1_MASK, + row_targets, + G_N_ELEMENTS (row_targets), + GDK_ACTION_MOVE | GDK_ACTION_COPY); + + gtk_tree_view_enable_model_drag_dest (GTK_TREE_VIEW (tv), + row_targets, + G_N_ELEMENTS (row_targets), + GDK_ACTION_MOVE | GDK_ACTION_COPY); /* Model menu */ -- 2.43.2