[recipes] Redo ingredients DND
- From: Matthias Clasen <matthiasc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [recipes] Redo ingredients DND
- Date: Fri, 26 May 2017 03:14:48 +0000 (UTC)
commit b477aae102325f9622c8f49a6de4de2d099e3649
Author: Matthias Clasen <mclasen redhat com>
Date: Thu May 25 23:13:05 2017 -0400
Redo ingredients DND
Make the list itself the drop target, and implement
better drag highlighting that hightlights just the gaps.
For implemneting this, we also remove the header separators,
and switch to using CSS borders for that purpose.
src/gr-ingredients-viewer-row.c | 51 ++++------
src/gr-ingredients-viewer.c | 204 ++++++++++++++++++++++++++++++++++++++-
src/gr-ingredients-viewer.h | 4 +-
src/gr-ingredients-viewer.ui | 7 --
src/recipes-dark.css | 2 +-
src/recipes-light.css | 2 +-
src/recipes.css | 32 ++++++
7 files changed, 257 insertions(+), 45 deletions(-)
---
diff --git a/src/gr-ingredients-viewer-row.c b/src/gr-ingredients-viewer-row.c
index fd18523..47c9be1 100644
--- a/src/gr-ingredients-viewer-row.c
+++ b/src/gr-ingredients-viewer-row.c
@@ -576,6 +576,7 @@ drag_begin (GtkWidget *widget,
cairo_t *cr;
GtkWidget *row;
int x, y;
+ GtkWidget *viewer;
row = gtk_widget_get_ancestor (widget, GTK_TYPE_LIST_BOX_ROW);
@@ -583,9 +584,9 @@ drag_begin (GtkWidget *widget,
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_style_context_add_class (gtk_widget_get_style_context (row), "drag-icon");
gtk_widget_draw (row, cr);
- gtk_style_context_remove_class (gtk_widget_get_style_context (row), "during-dnd");
+ gtk_style_context_remove_class (gtk_widget_get_style_context (row), "drag-icon");
gtk_widget_translate_coordinates (widget, row, 0, 0, &x, &y);
cairo_surface_set_device_offset (surface, -x, -y);
@@ -593,6 +594,20 @@ drag_begin (GtkWidget *widget,
cairo_destroy (cr);
cairo_surface_destroy (surface);
+
+ viewer = gtk_widget_get_ancestor (row, GR_TYPE_INGREDIENTS_VIEWER);
+ gr_ingredients_viewer_set_drag_row (GR_INGREDIENTS_VIEWER (viewer), row);
+}
+
+static void
+drag_end (GtkWidget *widget,
+ GdkDragContext *context,
+ gpointer data)
+{
+ GtkWidget *viewer;
+
+ viewer = gtk_widget_get_ancestor (widget, GR_TYPE_INGREDIENTS_VIEWER);
+ gr_ingredients_viewer_set_drag_row (GR_INGREDIENTS_VIEWER (viewer), NULL);
}
void
@@ -610,31 +625,6 @@ drag_data_get (GtkWidget *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 int
sort_func (GtkTreeModel *model,
GtkTreeIter *a,
@@ -780,11 +770,9 @@ setup_editable_row (GrIngredientsViewerRow *self)
gtk_drag_source_set (self->drag_handle, GDK_BUTTON1_MASK, entries, 1, GDK_ACTION_MOVE);
g_signal_connect (self->drag_handle, "drag-begin", G_CALLBACK (drag_begin), NULL);
+ g_signal_connect (self->drag_handle, "drag-end", G_CALLBACK (drag_end), NULL);
g_signal_connect (self->drag_handle, "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);
-
ingredients_model = get_ingredients_model ();
completion = gtk_entry_completion_new ();
gtk_entry_completion_set_model (completion, ingredients_model);
@@ -802,9 +790,6 @@ setup_editable_row (GrIngredientsViewerRow *self)
g_signal_handlers_disconnect_by_func (self->drag_handle, drag_begin, NULL);
g_signal_handlers_disconnect_by_func (self->drag_handle, drag_data_get, NULL);
- gtk_drag_dest_unset (GTK_WIDGET (self));
- g_signal_handlers_disconnect_by_func (self, drag_data_received, NULL);
-
gtk_entry_set_completion (GTK_ENTRY (self->ingredient_entry), NULL);
gtk_entry_set_completion (GTK_ENTRY (self->unit_entry), NULL);
}
diff --git a/src/gr-ingredients-viewer.c b/src/gr-ingredients-viewer.c
index 32cdc92..882f101 100644
--- a/src/gr-ingredients-viewer.c
+++ b/src/gr-ingredients-viewer.c
@@ -49,6 +49,10 @@ struct _GrIngredientsViewer
GtkSizeGroup *group;
GtkWidget *active_row;
+
+ GtkWidget *drag_row;
+ GtkWidget *row_before;
+ GtkWidget *row_after;
};
@@ -341,6 +345,184 @@ gr_ingredients_viewer_set_title (GrIngredientsViewer *viewer,
viewer->title = g_strdup (title);
}
+static GtkTargetEntry entries[] = {
+ { "GTK_LIST_BOX_ROW", GTK_TARGET_SAME_APP, 0 }
+};
+
+void
+gr_ingredients_viewer_set_drag_row (GrIngredientsViewer *viewer,
+ GtkWidget *row)
+{
+ if (viewer->drag_row) {
+ gtk_style_context_remove_class (gtk_widget_get_style_context (viewer->drag_row),
"drag-hover");
+ gtk_style_context_remove_class (gtk_widget_get_style_context (viewer->drag_row), "drag-row");
+ }
+
+ viewer->drag_row = row;
+
+ if (viewer->drag_row)
+ gtk_style_context_add_class (gtk_widget_get_style_context (viewer->drag_row), "drag-row");
+}
+
+static GtkListBoxRow *
+get_last_row (GtkListBox *list)
+{
+ int i;
+ GtkListBoxRow *row = NULL;
+
+ for (i = 0; ; i++) {
+ GtkListBoxRow *tmp = gtk_list_box_get_row_at_index (list, i);
+ if (tmp == NULL)
+ return row;
+ row = tmp;
+ }
+ return row;
+}
+
+static GtkListBoxRow *
+get_row_before (GtkListBox *list,
+ GtkListBoxRow *row)
+{
+ int pos = gtk_list_box_row_get_index (row);
+ return gtk_list_box_get_row_at_index (list, pos - 1);
+}
+
+static GtkListBoxRow *
+get_row_after (GtkListBox *list,
+ GtkListBoxRow *row)
+{
+ int pos = gtk_list_box_row_get_index (row);
+ return gtk_list_box_get_row_at_index (list, pos + 1);
+}
+
+static void
+drag_data_received (GtkWidget *widget,
+ GdkDragContext *context,
+ gint x,
+ gint y,
+ GtkSelectionData *selection_data,
+ guint info,
+ guint32 time,
+ gpointer data)
+{
+ GrIngredientsViewer *viewer = GR_INGREDIENTS_VIEWER (data);
+ GtkWidget *row_before;
+ GtkWidget *row_after;
+ GtkWidget *parent;
+ GtkWidget *row;
+ GtkWidget *source;
+ int pos;
+
+ row_before = viewer->row_before;
+ row_after = viewer->row_after;
+
+ viewer->row_before = NULL;
+ viewer->row_after = NULL;
+
+ if (row_before)
+ gtk_style_context_remove_class (gtk_widget_get_style_context (row_before),
"drag-hover-bottom");
+ if (row_after)
+ gtk_style_context_remove_class (gtk_widget_get_style_context (row_after), "drag-hover-top");
+
+ row = (gpointer)* (gpointer*)gtk_selection_data_get_data (selection_data);
+ source = gtk_widget_get_ancestor (row, GTK_TYPE_LIST_BOX_ROW);
+
+ gtk_style_context_remove_class (gtk_widget_get_style_context (source), "drag-row");
+ gtk_style_context_remove_class (gtk_widget_get_style_context (source), "drag-hover");
+
+ if (source == row_after)
+ return;
+
+ g_object_ref (source);
+ gtk_container_remove (GTK_CONTAINER (gtk_widget_get_parent (source)), source);
+
+ if (row_after) {
+ pos = gtk_list_box_row_get_index (GTK_LIST_BOX_ROW (row_after));
+ parent = gtk_widget_get_parent (row_after);
+ }
+ else {
+ pos = gtk_list_box_row_get_index (GTK_LIST_BOX_ROW (row_before)) + 1;
+ parent = gtk_widget_get_parent (row_before);
+ }
+
+ gtk_list_box_insert (GTK_LIST_BOX (parent), source, pos);
+ g_object_unref (source);
+}
+
+static gboolean
+drag_motion (GtkWidget *widget,
+ GdkDragContext *context,
+ int x,
+ int y,
+ guint time,
+ gpointer data)
+{
+ GrIngredientsViewer *viewer = GR_INGREDIENTS_VIEWER (data);
+ GtkAllocation alloc;
+ GtkWidget *row;
+ int hover_row_y;
+ int hover_row_height;
+
+ row = GTK_WIDGET (gtk_list_box_get_row_at_y (GTK_LIST_BOX (widget), y));
+
+ if (viewer->drag_row)
+ gtk_style_context_remove_class (gtk_widget_get_style_context (viewer->drag_row),
"drag-hover");
+
+ if (viewer->row_before)
+ gtk_style_context_remove_class (gtk_widget_get_style_context (viewer->row_before),
"drag-hover-bottom");
+ if (viewer->row_after)
+ gtk_style_context_remove_class (gtk_widget_get_style_context (viewer->row_after),
"drag-hover-top");
+
+ if (row) {
+ gtk_widget_get_allocation (row, &alloc);
+ hover_row_y = alloc.y;
+ hover_row_height = alloc.height;
+
+ if (y < hover_row_y + hover_row_height/2) {
+ viewer->row_after = row;
+ viewer->row_before = GTK_WIDGET (get_row_before (GTK_LIST_BOX (widget),
GTK_LIST_BOX_ROW (row)));
+ }
+ else {
+ viewer->row_before = row;
+ viewer->row_after = GTK_WIDGET (get_row_after (GTK_LIST_BOX (widget),
GTK_LIST_BOX_ROW (row)));
+ }
+ }
+ else {
+ viewer->row_before = GTK_WIDGET (get_last_row (GTK_LIST_BOX (widget)));
+ viewer->row_after = NULL;
+ }
+
+ if (viewer->drag_row &&
+ (viewer->drag_row == viewer->row_before ||
+ viewer->drag_row == viewer->row_after)) {
+ gtk_style_context_add_class (gtk_widget_get_style_context (viewer->drag_row), "drag-hover");
+ return FALSE;
+ }
+
+ if (viewer->row_before)
+ gtk_style_context_add_class (gtk_widget_get_style_context (viewer->row_before),
"drag-hover-bottom");
+ if (viewer->row_after)
+ gtk_style_context_add_class (gtk_widget_get_style_context (viewer->row_after),
"drag-hover-top");
+
+ return TRUE;
+}
+
+static void
+drag_leave (GtkWidget *widget,
+ GdkDragContext *context,
+ guint time,
+ gpointer data)
+{
+ GrIngredientsViewer *viewer = GR_INGREDIENTS_VIEWER (data);
+
+ if (viewer->drag_row)
+ gtk_style_context_remove_class (gtk_widget_get_style_context (viewer->drag_row),
"drag-hover");
+ if (viewer->row_before)
+ gtk_style_context_remove_class (gtk_widget_get_style_context (viewer->row_before),
"drag-hover-bottom");
+ if (viewer->row_after)
+ gtk_style_context_remove_class (gtk_widget_get_style_context (viewer->row_after),
"drag-hover-top");
+}
+
static void
gr_ingredients_viewer_set_editable (GrIngredientsViewer *viewer,
gboolean editable)
@@ -358,6 +540,26 @@ gr_ingredients_viewer_set_editable (GrIngredientsViewer *viewer,
g_object_set (row, "editable", viewer->editable, NULL);
}
g_list_free (children);
+
+ if (editable) {
+ gtk_style_context_add_class (gtk_widget_get_style_context (viewer->list), "editable");
+ gtk_drag_dest_set (viewer->list,
+ GTK_DEST_DEFAULT_MOTION | GTK_DEST_DEFAULT_DROP,
+ entries, 1, GDK_ACTION_MOVE);
+ g_signal_connect (viewer->list, "drag-data-received",
+ G_CALLBACK (drag_data_received), viewer);
+ g_signal_connect (viewer->list, "drag-motion",
+ G_CALLBACK (drag_motion), viewer);
+ g_signal_connect (viewer->list, "drag-leave",
+ G_CALLBACK (drag_leave), viewer);
+ }
+ else {
+ gtk_style_context_remove_class (gtk_widget_get_style_context (viewer->list), "editable");
+ gtk_drag_dest_unset (viewer->list);
+ g_signal_handlers_disconnect_by_func (viewer->list, drag_data_received, viewer);
+ g_signal_handlers_disconnect_by_func (viewer->list, drag_motion, viewer);
+ g_signal_handlers_disconnect_by_func (viewer->list, drag_leave, viewer);
+ }
}
static void
@@ -414,8 +616,6 @@ gr_ingredients_viewer_init (GrIngredientsViewer *self)
gtk_widget_set_has_window (GTK_WIDGET (self), FALSE);
gtk_widget_init_template (GTK_WIDGET (self));
- gtk_list_box_set_header_func (GTK_LIST_BOX (self->list), all_headers, self, NULL);
-
self->group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
#if defined(ENABLE_GSPELL) && defined(GSPELL_TYPE_ENTRY)
diff --git a/src/gr-ingredients-viewer.h b/src/gr-ingredients-viewer.h
index 5de7a64..0bf8117 100644
--- a/src/gr-ingredients-viewer.h
+++ b/src/gr-ingredients-viewer.h
@@ -31,7 +31,9 @@ G_DECLARE_FINAL_TYPE (GrIngredientsViewer, gr_ingredients_viewer, GR, INGREDIENT
void set_active_row (GrIngredientsViewer *viewer,
GtkWidget *row);
-GtkWidget *gr_ingredients_viewer_has_error (GrIngredientsViewer *viewer);
+GtkWidget *gr_ingredients_viewer_has_error (GrIngredientsViewer *viewer);
+void gr_ingredients_viewer_set_drag_row (GrIngredientsViewer *viewer,
+ GtkWidget *row);
G_END_DECLS
diff --git a/src/gr-ingredients-viewer.ui b/src/gr-ingredients-viewer.ui
index 748d324..e2bf36e 100644
--- a/src/gr-ingredients-viewer.ui
+++ b/src/gr-ingredients-viewer.ui
@@ -68,13 +68,6 @@
</object>
</child>
<child>
- <object class="GtkSeparator">
- <property name="visible">1</property>
- <property name="expand">1</property>
- <property name="valign">center</property>
- </object>
- </child>
- <child>
<object class="GtkEventBox" id="add_row_box">
<property name="can-focus">1</property>
<property name="visible">1</property>
diff --git a/src/recipes-dark.css b/src/recipes-dark.css
index f308e10..3c2e050 100644
--- a/src/recipes-dark.css
+++ b/src/recipes-dark.css
@@ -25,7 +25,7 @@
background: #868d94;
}
-.during-dnd {
+row.drag-icon {
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 bad8565..ea75b6f 100644
--- a/src/recipes-light.css
+++ b/src/recipes-light.css
@@ -23,7 +23,7 @@
background: #cbd6e1;
}
-.during-dnd {
+row.drag-icon {
background: white;
border: 1px solid alpha(black, 0.3);
outline-width: 0;
diff --git a/src/recipes.css b/src/recipes.css
index f8e1d35..793b299 100644
--- a/src/recipes.css
+++ b/src/recipes.css
@@ -449,3 +449,35 @@ dialog.about box.dialog-vbox {
label.error {
text-decoration: underline wavy red;
}
+
+row:not(:first-child) {
+ border-top: 1px solid alpha(gray,0.5);
+ border-bottom: 1px solid transparent;
+}
+
+.editable row:not(.drag-hover-bottom):last-child {
+ border-bottom: 1px solid alpha(gray,0.5);
+}
+
+row.drag-row {
+ color: gray;
+ background: alpha(gray,0.2);
+}
+
+row.drag-row.drag-hover {
+ border-top: 1px solid #4e9a06;
+ border-bottom: 1px solid #4e9a06;
+}
+
+row.drag-hover image,
+row.drag-hover label {
+ color: #4e9a06;
+}
+
+row.drag-hover-top {
+ border-top: 1px solid #4e9a06;
+}
+
+row.drag-hover-bottom {
+ border-bottom: 1px solid #4e9a06;
+}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]