[recipes] Initial dnd reordering support
- From: Matthias Clasen <matthiasc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [recipes] Initial dnd reordering support
- Date: Fri, 28 Apr 2017 01:48:04 +0000 (UTC)
commit 76b75ec47a1bb402d27ac6936e91883bff5814a6
Author: Matthias Clasen <mclasen redhat com>
Date: Fri Apr 21 21:01:47 2017 -0400
Initial dnd reordering support
Instead of the up/down arrows, show a drag handle, and
support drag-and-drop reordering. As a little benefit,
we can now support reordering between different lists.
src/gr-ingredients-viewer-row.c | 97 +++++++++++++++++++++++++++++++++----
src/gr-ingredients-viewer-row.ui | 46 ++----------------
src/gr-ingredients-viewer.c | 27 ++++++-----
src/recipes-dark.css | 5 ++
src/recipes-light.css | 5 ++
5 files changed, 117 insertions(+), 63 deletions(-)
---
diff --git a/src/gr-ingredients-viewer-row.c b/src/gr-ingredients-viewer-row.c
index c8dd6a2..a8b0cea 100644
--- a/src/gr-ingredients-viewer-row.c
+++ b/src/gr-ingredients-viewer-row.c
@@ -24,6 +24,7 @@
#include <glib/gi18n.h>
#include "gr-ingredients-viewer-row.h"
+#include "gr-ingredients-viewer.h"
#include "gr-ingredient.h"
@@ -34,6 +35,7 @@ struct _GrIngredientsViewerRow
GtkWidget *unit_label;
GtkWidget *ingredient_label;
GtkWidget *buttons_stack;
+ GtkWidget *ebox;
char *amount;
char *unit;
@@ -228,15 +230,8 @@ emit_delete (GrIngredientsViewerRow *row)
}
static void
-emit_move_up (GrIngredientsViewerRow *row)
+drag_handle_clicked (GrIngredientsViewerRow *row)
{
- g_signal_emit (row, signals[MOVE], 0, -1);
-}
-
-static void
-emit_move_down (GrIngredientsViewerRow *row)
-{
- g_signal_emit (row, signals[MOVE], 0, 1);
}
static void
@@ -294,17 +289,90 @@ gr_ingredients_viewer_row_class_init (GrIngredientsViewerRowClass *klass)
0,
NULL, NULL,
NULL,
- G_TYPE_NONE, 1, G_TYPE_INT);
+ G_TYPE_NONE, 1, GR_TYPE_INGREDIENTS_VIEWER_ROW);
gtk_widget_class_set_template_from_resource (widget_class,
"/org/gnome/Recipes/gr-ingredients-viewer-row.ui");
gtk_widget_class_bind_template_child (widget_class, GrIngredientsViewerRow, unit_label);
gtk_widget_class_bind_template_child (widget_class, GrIngredientsViewerRow, ingredient_label);
gtk_widget_class_bind_template_child (widget_class, GrIngredientsViewerRow, buttons_stack);
+ gtk_widget_class_bind_template_child (widget_class, GrIngredientsViewerRow, ebox);
gtk_widget_class_bind_template_callback (widget_class, emit_delete);
- gtk_widget_class_bind_template_callback (widget_class, emit_move_up);
- gtk_widget_class_bind_template_callback (widget_class, emit_move_down);
+ gtk_widget_class_bind_template_callback (widget_class, drag_handle_clicked);
+}
+
+static GtkTargetEntry entries[] = {
+ { "GTK_LIST_BOX_ROW", GTK_TARGET_SAME_APP, 0 }
+};
+
+static void
+drag_begin (GtkWidget *widget,
+ GdkDragContext *context,
+ gpointer data)
+{
+ GtkAllocation alloc;
+ cairo_surface_t *surface;
+ cairo_t *cr;
+ GtkWidget *row;
+ int x, y;
+
+ row = gtk_widget_get_ancestor (widget, GTK_TYPE_LIST_BOX_ROW);
+
+ gtk_widget_get_allocation (row, &alloc);
+ surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, alloc.width, alloc.height);
+ cr = cairo_create (surface);
+
+ gtk_style_context_add_class (gtk_widget_get_style_context (row), "during-dnd");
+ gtk_widget_draw (row, cr);
+ gtk_style_context_remove_class (gtk_widget_get_style_context (row), "during-dnd");
+
+ gtk_widget_translate_coordinates (widget, row, 0, 0, &x, &y);
+ cairo_surface_set_device_offset (surface, -x, -y);
+ gtk_drag_set_icon_surface (context, surface);
+
+ cairo_destroy (cr);
+ cairo_surface_destroy (surface);
+}
+
+void
+drag_data_get (GtkWidget *widget,
+ GdkDragContext *context,
+ GtkSelectionData *selection_data,
+ guint info,
+ guint time,
+ gpointer data)
+{
+ gtk_selection_data_set (selection_data,
+ gdk_atom_intern_static_string ("GTK_LIST_BOX_ROW"),
+ 32,
+ (const guchar *)&widget,
+ sizeof (gpointer));
+}
+
+static void
+drag_data_received (GtkWidget *widget,
+ GdkDragContext *context,
+ gint x,
+ gint y,
+ GtkSelectionData *selection_data,
+ guint info,
+ guint32 time,
+ gpointer data)
+{
+ GtkWidget *target;
+ GtkWidget *row;
+ GtkWidget *source;
+
+ target = gtk_widget_get_ancestor (widget, GTK_TYPE_LIST_BOX_ROW);
+
+ row = (gpointer)* (gpointer*)gtk_selection_data_get_data (selection_data);
+ source = gtk_widget_get_ancestor (row, GTK_TYPE_LIST_BOX_ROW);
+
+ if (target == source)
+ return;
+
+ g_signal_emit (source, signals[MOVE], 0, target);
}
static void
@@ -312,4 +380,11 @@ gr_ingredients_viewer_row_init (GrIngredientsViewerRow *self)
{
gtk_widget_set_has_window (GTK_WIDGET (self), FALSE);
gtk_widget_init_template (GTK_WIDGET (self));
+
+ gtk_drag_source_set (self->ebox, GDK_BUTTON1_MASK, entries, 1, GDK_ACTION_MOVE);
+ g_signal_connect (self->ebox, "drag-begin", G_CALLBACK (drag_begin), NULL);
+ g_signal_connect (self->ebox, "drag-data-get", G_CALLBACK (drag_data_get), NULL);
+
+ gtk_drag_dest_set (GTK_WIDGET (self), GTK_DEST_DEFAULT_ALL, entries, 1, GDK_ACTION_MOVE);
+ g_signal_connect (self, "drag-data-received", G_CALLBACK (drag_data_received), NULL);
}
diff --git a/src/gr-ingredients-viewer-row.ui b/src/gr-ingredients-viewer-row.ui
index 0608480..ae66467 100644
--- a/src/gr-ingredients-viewer-row.ui
+++ b/src/gr-ingredients-viewer-row.ui
@@ -49,42 +49,7 @@
<object class="GtkButton">
<property name="visible">1</property>
<property name="relief">none</property>
- <signal name="clicked" handler="emit_move_up" swapped="yes"/>
- <style>
- <class name="image-button"/>
- <class name="circular"/>
- </style>
- <child>
- <object class="GtkImage">
- <property name="visible">1</property>
- <property name="icon-name">go-up-symbolic</property>
- <property name="icon-size">1</property>
- </object>
- </child>
- </object>
- </child>
- <child>
- <object class="GtkButton">
- <property name="visible">1</property>
- <property name="relief">none</property>
- <signal name="clicked" handler="emit_move_down" swapped="yes"/>
- <style>
- <class name="image-button"/>
- <class name="circular"/>
- </style>
- <child>
- <object class="GtkImage">
- <property name="visible">1</property>
- <property name="icon-name">go-down-symbolic</property>
- <property name="icon-size">1</property>
- </object>
- </child>
- </object>
- </child>
- <child>
- <object class="GtkButton">
- <property name="visible">1</property>
- <property name="relief">none</property>
+ <signal name="clicked" handler="emit_delete" swapped="yes"/>
<style>
<class name="image-button"/>
<class name="circular"/>
@@ -92,17 +57,17 @@
<child>
<object class="GtkImage">
<property name="visible">1</property>
- <property name="icon-name">document-edit-symbolic</property>
+ <property name="icon-name">user-trash-symbolic</property>
<property name="icon-size">1</property>
</object>
</child>
</object>
</child>
<child>
- <object class="GtkButton">
+ <object class="GtkButton" id="ebox">
<property name="visible">1</property>
<property name="relief">none</property>
- <signal name="clicked" handler="emit_delete" swapped="yes"/>
+ <signal name="clicked" handler="drag_handle_clicked" swapped="yes"/>
<style>
<class name="image-button"/>
<class name="circular"/>
@@ -110,8 +75,9 @@
<child>
<object class="GtkImage">
<property name="visible">1</property>
- <property name="icon-name">user-trash-symbolic</property>
+ <property name="icon-name">open-menu-symbolic</property>
<property name="icon-size">1</property>
+ <property name="margin">4</property>
</object>
</child>
</object>
diff --git a/src/gr-ingredients-viewer.c b/src/gr-ingredients-viewer.c
index a9a6ae8..22945ea 100644
--- a/src/gr-ingredients-viewer.c
+++ b/src/gr-ingredients-viewer.c
@@ -203,23 +203,26 @@ delete_row (GrIngredientsViewerRow *row,
}
static void
-move_row (GrIngredientsViewerRow *row,
- int steps,
- GrIngredientsViewer *viewer)
+move_row (GtkWidget *source,
+ GtkWidget *target,
+ GrIngredientsViewer *viewer)
{
- GtkWidget *list;
+ GtkWidget *source_parent;
+ GtkWidget *target_parent;
int index;
- list = gtk_widget_get_parent (GTK_WIDGET (row));
- index = gtk_list_box_row_get_index (GTK_LIST_BOX_ROW (row));
- gtk_list_box_unselect_row (GTK_LIST_BOX (list), GTK_LIST_BOX_ROW (row));
+ index = gtk_list_box_row_get_index (GTK_LIST_BOX_ROW (target));
+
+ source_parent = gtk_widget_get_parent (source);
+ target_parent = gtk_widget_get_parent (target);
+
+ g_object_ref (source);
+ gtk_container_remove (GTK_CONTAINER (source_parent), source);
+ gtk_list_box_insert (GTK_LIST_BOX (target_parent), source, index);
+ g_object_unref (source);
- g_object_ref (row);
- gtk_container_remove (GTK_CONTAINER (list), GTK_WIDGET (row));
- gtk_list_box_insert (GTK_LIST_BOX (list), GTK_WIDGET (row), index + steps);
- g_object_unref (row);
+ gtk_list_box_select_row (GTK_LIST_BOX (target_parent), GTK_LIST_BOX_ROW (source));
- gtk_list_box_select_row (GTK_LIST_BOX (list), GTK_LIST_BOX_ROW (row));
g_object_notify (G_OBJECT (viewer), "ingredients");
}
diff --git a/src/recipes-dark.css b/src/recipes-dark.css
index 7ee631e..f308e10 100644
--- a/src/recipes-dark.css
+++ b/src/recipes-dark.css
@@ -25,3 +25,8 @@
background: #868d94;
}
+.during-dnd {
+ background: #232729;
+ border: 1px solid alpha(white, 0.3);
+ outline-width: 0;
+}
diff --git a/src/recipes-light.css b/src/recipes-light.css
index 7b287f8..bad8565 100644
--- a/src/recipes-light.css
+++ b/src/recipes-light.css
@@ -23,3 +23,8 @@
background: #cbd6e1;
}
+.during-dnd {
+ background: white;
+ border: 1px solid alpha(black, 0.3);
+ outline-width: 0;
+}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]