[gnome-control-center/wip/feborges/new-search-panel: 16/18] search: Make the list_box the DnD target
- From: Felipe Borges <felipeborges src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-control-center/wip/feborges/new-search-panel: 16/18] search: Make the list_box the DnD target
- Date: Mon, 25 Sep 2017 10:35:52 +0000 (UTC)
commit 2836c4e10a6c55f48e13f61ed0c68636e0ada15f
Author: Felipe Borges <felipeborges gnome org>
Date: Thu Jun 29 13:02:16 2017 +0200
search: Make the list_box the DnD target
By making the list_box itself the Drag and Drop target, we are
able to use CSS to create a gap between the rows while on hover.
https://bugzilla.gnome.org/show_bug.cgi?id=775958
panels/search/cc-search-panel.c | 228 +++++++++++++++++++++++++++++++++++++--
1 files changed, 219 insertions(+), 9 deletions(-)
---
diff --git a/panels/search/cc-search-panel.c b/panels/search/cc-search-panel.c
index 73627ea..1c111f5 100644
--- a/panels/search/cc-search-panel.c
+++ b/panels/search/cc-search-panel.c
@@ -334,6 +334,22 @@ drag_begin (GtkWidget *widget,
cairo_destroy (cr);
cairo_surface_destroy (surface);
+
+ g_object_set_data (G_OBJECT (gtk_widget_get_parent (row)), "drag-row", row);
+ gtk_style_context_add_class (gtk_widget_get_style_context (row), "draw-row");
+}
+
+static void
+drag_end (GtkWidget *widget,
+ GdkDragContext *context,
+ gpointer data)
+{
+ GtkWidget *row;
+
+ row = gtk_widget_get_ancestor (widget, GTK_TYPE_LIST_BOX_ROW);
+ g_object_set_data (G_OBJECT (gtk_widget_get_parent (row)), "drag-row", NULL);
+ gtk_style_context_remove_class (gtk_widget_get_style_context (row), "drag-row");
+ gtk_style_context_remove_class (gtk_widget_get_style_context (row), "drag-hover");
}
static void
@@ -351,6 +367,44 @@ drag_data_get (GtkWidget *widget,
sizeof (gpointer));
}
+static GtkListBoxRow *
+get_last_row (GtkListBox *list)
+{
+ GtkListBoxRow *row;
+ int i;
+
+ row = NULL;
+ for (i = 0; ; i++)
+ {
+ GtkListBoxRow *tmp;
+ 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,
@@ -362,23 +416,39 @@ drag_data_received (GtkWidget *widget,
gpointer data)
{
CcSearchPanel *self = CC_SEARCH_PANEL (data);
- GtkWidget *target;
+ GtkWidget *row_before;
+ GtkWidget *row_after;
GtkWidget *row;
GtkWidget *source;
- int idx;
+ int pos;
+
+ row_before = GTK_WIDGET (g_object_get_data (G_OBJECT (widget), "row-before"));
+ row_after = GTK_WIDGET (g_object_get_data (G_OBJECT (widget), "row-after"));
- target = widget;
+ g_object_set_data (G_OBJECT (widget), "row-before", NULL);
+ g_object_set_data (G_OBJECT (widget), "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);
- idx = gtk_list_box_row_get_index (GTK_LIST_BOX_ROW (target));
- if (source == target)
+ if (source == row_after)
return;
g_object_ref (source);
gtk_container_remove (GTK_CONTAINER (gtk_widget_get_parent (source)), source);
- gtk_list_box_insert (GTK_LIST_BOX (gtk_widget_get_parent (target)), source, idx);
+
+ if (row_after)
+ pos = gtk_list_box_row_get_index (GTK_LIST_BOX_ROW (row_after));
+ else
+ pos = gtk_list_box_row_get_index (GTK_LIST_BOX_ROW (row_before)) + 1;
+
+
+ gtk_list_box_insert (GTK_LIST_BOX (widget), source, pos);
g_object_unref (source);
gtk_container_foreach (GTK_CONTAINER (self->priv->list_box), update_row_position, self);
@@ -386,6 +456,93 @@ drag_data_received (GtkWidget *widget,
search_panel_propagate_sort_order (self);
}
+static gboolean
+drag_motion (GtkWidget *widget,
+ GdkDragContext *context,
+ int x,
+ int y,
+ guint time)
+{
+ GtkAllocation alloc;
+ GtkWidget *row;
+ int hover_row_y;
+ int hover_row_height;
+ GtkWidget *drag_row;
+ GtkWidget *row_before;
+ GtkWidget *row_after;
+
+ row = GTK_WIDGET (gtk_list_box_get_row_at_y (GTK_LIST_BOX (widget), y));
+
+ drag_row = GTK_WIDGET (g_object_get_data (G_OBJECT (widget), "drag-row"));
+ row_before = GTK_WIDGET (g_object_get_data (G_OBJECT (widget), "row-before"));
+ row_after = GTK_WIDGET (g_object_get_data (G_OBJECT (widget), "row-after"));
+
+ gtk_style_context_remove_class (gtk_widget_get_style_context (drag_row), "drag-hover");
+ 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");
+
+ 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)
+ {
+ row_after = row;
+ row_before = GTK_WIDGET (get_row_before (GTK_LIST_BOX (widget), GTK_LIST_BOX_ROW (row)));
+ }
+ else
+ {
+ row_before = row;
+ row_after = GTK_WIDGET (get_row_after (GTK_LIST_BOX (widget), GTK_LIST_BOX_ROW (row)));
+ }
+ }
+ else
+ {
+ row_before = GTK_WIDGET (get_last_row (GTK_LIST_BOX (widget)));
+ row_after = NULL;
+ }
+
+ g_object_set_data (G_OBJECT (widget), "row-before", row_before);
+ g_object_set_data (G_OBJECT (widget), "row-after", row_after);
+
+ if (drag_row == row_before || drag_row == row_after)
+ {
+ gtk_style_context_add_class (gtk_widget_get_style_context (drag_row), "drag-hover");
+ return FALSE;
+ }
+
+ if (row_before)
+ gtk_style_context_add_class (gtk_widget_get_style_context (row_before), "drag-hover-bottom");
+ if (row_after)
+ gtk_style_context_add_class (gtk_widget_get_style_context (row_after), "drag-hover-top");
+
+ return TRUE;
+}
+
+static void
+drag_leave (GtkWidget *widget,
+ GdkDragContext *context,
+ guint time)
+{
+ GtkWidget *drag_row;
+ GtkWidget *row_before;
+ GtkWidget *row_after;
+
+ drag_row = GTK_WIDGET (g_object_get_data (G_OBJECT (widget), "drag-row"));
+ row_before = GTK_WIDGET (g_object_get_data (G_OBJECT (widget), "row-before"));
+ row_after = GTK_WIDGET (g_object_get_data (G_OBJECT (widget), "row-after"));
+
+ gtk_style_context_remove_class (gtk_widget_get_style_context (drag_row), "drag-hover");
+ 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");
+}
+
static void
search_panel_add_one_app_info (CcSearchPanel *self,
GAppInfo *app_info,
@@ -419,13 +576,12 @@ search_panel_add_one_app_info (CcSearchPanel *self,
gtk_container_add (GTK_CONTAINER (handle), gtk_image_new_from_icon_name ("open-menu-symbolic", 1));
gtk_container_add (GTK_CONTAINER (box), handle);
+ gtk_style_context_add_class (gtk_widget_get_style_context (row), "row");
gtk_drag_source_set (handle, GDK_BUTTON1_MASK, entries, 1, GDK_ACTION_MOVE);
g_signal_connect (handle, "drag-begin", G_CALLBACK (drag_begin), self->priv->list_box);
+ g_signal_connect (handle, "drag-end", G_CALLBACK (drag_end), NULL);
g_signal_connect (handle, "drag-data-get", G_CALLBACK (drag_data_get), NULL);
- gtk_drag_dest_set (row, GTK_DEST_DEFAULT_ALL, entries, 1, GDK_ACTION_MOVE);
- g_signal_connect (row, "drag-data-received", G_CALLBACK (drag_data_received), self);
-
icon = g_app_info_get_icon (app_info);
if (icon == NULL)
icon = g_themed_icon_new ("application-x-executable");
@@ -716,9 +872,43 @@ cc_search_panel_constructed (GObject *object)
cc_shell_embed_widget_in_header (cc_panel_get_shell (CC_PANEL (self)), box);
}
+static const char *css =
+ ".row:not(:first-child) { "
+ " border-top: 1px solid alpha(gray,0.5); "
+ " border-bottom: 1px solid transparent; "
+ "}"
+ ".row:first-child { "
+ " border-top: 1px solid transparent; "
+ " border-bottom: 1px solid transparent; "
+ "}"
+ ".row:last-child { "
+ " border-top: 1px solid alpha(gray,0.5); "
+ " border-bottom: 1px solid alpha(gray,0.5); "
+ "}"
+ ".row.drag-icon { "
+ " background: @theme_base_color; "
+ " border: 1px solid @borders; "
+ "}"
+ ".row.drag-row { "
+ " color: gray; "
+ " background: alpha(gray,0.2); "
+ "}"
+ ".row.drag-hover image, "
+ ".row.drag-hover label { "
+ " color: @theme_text_color; "
+ "}"
+ ".row.drag-hover-top {"
+ " border-top: 48px solid @theme_bg_color; "
+ "}"
+ ".row.drag-hover-bottom {"
+ " border-bottom: 1px solid @theme_bg_color; "
+ "}"
+;
+
static void
cc_search_panel_init (CcSearchPanel *self)
{
+ GtkCssProvider *provider;
GError *error;
GtkWidget *widget;
GtkWidget *frame;
@@ -751,6 +941,26 @@ cc_search_panel_init (CcSearchPanel *self)
self->priv->list_box = widget;
gtk_widget_show (widget);
+ /* Drag and Drop */
+ gtk_drag_dest_set (self->priv->list_box,
+ GTK_DEST_DEFAULT_MOTION | GTK_DEST_DEFAULT_DROP,
+ entries, 1,
+ GDK_ACTION_MOVE);
+ g_signal_connect (self->priv->list_box,
+ "drag-data-received",
+ G_CALLBACK (drag_data_received), self);
+ g_signal_connect (self->priv->list_box,
+ "drag-motion",
+ G_CALLBACK (drag_motion), NULL);
+ g_signal_connect (self->priv->list_box,
+ "drag-leave",
+ G_CALLBACK (drag_leave), NULL);
+
+ provider = gtk_css_provider_new ();
+ gtk_css_provider_load_from_data (provider, css, -1, NULL);
+ gtk_style_context_add_provider_for_screen (gdk_screen_get_default (),
+ GTK_STYLE_PROVIDER (provider), 800);
+
widget = WID ("settings_button");
g_signal_connect (widget, "clicked",
G_CALLBACK (settings_button_clicked), self);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]