[gnome-control-center/wip/feborges/new-search-panel: 1459/1461] search: Make rows reordable with drag and drop



commit 297e5dafae12297421fa233e60565f2cdb3dcecc
Author: Felipe Borges <felipeborges gnome org>
Date:   Tue Jul 2 16:02:07 2019 +0200

    search: Make rows reordable with drag and drop
    
    Fixes #589

 panels/search/cc-search-panel-row.c  | 100 +++++++++++++++++++++++++++++++++++
 panels/search/cc-search-panel-row.h  |   3 ++
 panels/search/cc-search-panel-row.ui |  10 ++++
 panels/search/cc-search-panel.c      |  19 +++++++
 4 files changed, 132 insertions(+)
---
diff --git a/panels/search/cc-search-panel-row.c b/panels/search/cc-search-panel-row.c
index 352f5ed94..b0f599ed9 100644
--- a/panels/search/cc-search-panel-row.c
+++ b/panels/search/cc-search-panel-row.c
@@ -23,6 +23,84 @@
 
 G_DEFINE_TYPE (CcSearchPanelRow, cc_search_panel_row, GTK_TYPE_LIST_BOX_ROW)
 
+enum
+{
+  SIGNAL_MOVE_ROW,
+  SIGNAL_LAST
+};
+
+static guint signals[SIGNAL_LAST] = { 0, };
+
+static void
+drag_begin_cb (CcSearchPanelRow *self,
+               GdkDragContext   *drag_context)
+{
+  GtkAllocation alloc;
+  gint x = 0, y = 0;
+
+  gtk_widget_get_allocation (GTK_WIDGET (self), &alloc);
+
+  gdk_window_get_device_position (gtk_widget_get_window (GTK_WIDGET (self)),
+                                  gdk_drag_context_get_device (drag_context),
+                                  &x, &y, NULL);
+
+  self->drag_widget = GTK_LIST_BOX (gtk_list_box_new ());
+  gtk_widget_show (GTK_WIDGET (self->drag_widget));
+  gtk_widget_set_size_request (GTK_WIDGET (self->drag_widget), alloc.width, alloc.height);
+  CcSearchPanelRow *drag_row = cc_search_panel_row_new (self->app_info);
+  gtk_widget_show (GTK_WIDGET (drag_row));
+  gtk_container_add (GTK_CONTAINER (self->drag_widget), GTK_WIDGET (drag_row));
+  gtk_list_box_drag_highlight_row (self->drag_widget, GTK_LIST_BOX_ROW (drag_row));
+
+  gtk_drag_set_icon_widget (drag_context, GTK_WIDGET (self->drag_widget), x - alloc.x, y - alloc.y);
+}
+
+static void
+drag_end_cb (CcSearchPanelRow *self)
+{
+  g_clear_pointer ((GtkWidget **) &self->drag_widget, gtk_widget_destroy);
+}
+
+static void
+drag_data_get_cb (CcSearchPanelRow *self,
+                  GdkDragContext   *context,
+                  GtkSelectionData *selection_data,
+                  guint             info,
+                  guint             time_)
+{
+  gtk_selection_data_set (selection_data,
+                          gdk_atom_intern_static_string ("GTK_LIST_BOX_ROW"),
+                          32,
+                          (const guchar *)&self,
+                          sizeof (gpointer));
+}
+
+static void
+drag_data_received_cb (CcSearchPanelRow *self,
+                       GdkDragContext   *context,
+                       gint              x,
+                       gint              y,
+                       GtkSelectionData *selection_data,
+                       guint             info,
+                       guint             time_)
+{
+  CcSearchPanelRow *source;
+
+  source = *((CcSearchPanelRow **) gtk_selection_data_get_data (selection_data));
+  if (source == self)
+    return;
+
+  g_signal_emit (source,
+                 signals[SIGNAL_MOVE_ROW],
+                 0,
+                 self);
+}
+
+static GtkTargetEntry entries[] =
+{
+  { "GTK_LIST_BOX_ROW", GTK_TARGET_SAME_APP, 0 }
+};
+
 CcSearchPanelRow *
 cc_search_panel_row_new (GAppInfo *app_info)
 {
@@ -44,23 +122,45 @@ cc_search_panel_row_new (GAppInfo *app_info)
 
   gtk_label_set_text (self->app_name, g_app_info_get_name (app_info));
 
+  gtk_drag_source_set (GTK_WIDGET (self->drag_handle), GDK_BUTTON1_MASK, entries, 1, GDK_ACTION_MOVE);
+
   return self;
 }
 
 static void
 cc_search_panel_row_class_init (CcSearchPanelRowClass *klass)
 {
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
   GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
 
   gtk_widget_class_set_template_from_resource (widget_class, 
"/org/gnome/control-center/search/cc-search-panel-row.ui");
 
+  gtk_widget_class_bind_template_child (widget_class, CcSearchPanelRow, drag_handle);
   gtk_widget_class_bind_template_child (widget_class, CcSearchPanelRow, icon);
   gtk_widget_class_bind_template_child (widget_class, CcSearchPanelRow, app_name);
   gtk_widget_class_bind_template_child (widget_class, CcSearchPanelRow, switcher);
+
+  gtk_widget_class_bind_template_callback (widget_class, drag_begin_cb);
+  gtk_widget_class_bind_template_callback (widget_class, drag_end_cb);
+  gtk_widget_class_bind_template_callback (widget_class, drag_data_get_cb);
+  gtk_widget_class_bind_template_callback (widget_class, drag_data_received_cb);
+
+  signals[SIGNAL_MOVE_ROW] =
+    g_signal_new ("move-row",
+                  G_TYPE_FROM_CLASS (object_class),
+                  G_SIGNAL_RUN_LAST,
+                  0,
+                  NULL, NULL,
+                  NULL,
+                  G_TYPE_NONE,
+                  1, CC_TYPE_SEARCH_PANEL_ROW);
 }
 
 static void
 cc_search_panel_row_init (CcSearchPanelRow *self)
 {
   gtk_widget_init_template (GTK_WIDGET (self));
+
+  gtk_drag_source_set (GTK_WIDGET (self->drag_handle), GDK_BUTTON1_MASK, entries, 1, GDK_ACTION_MOVE);
+  gtk_drag_dest_set (GTK_WIDGET (self), GTK_DEST_DEFAULT_ALL, entries, 1, GDK_ACTION_MOVE);
 }
diff --git a/panels/search/cc-search-panel-row.h b/panels/search/cc-search-panel-row.h
index 9f14e2d30..6caf42ff5 100644
--- a/panels/search/cc-search-panel-row.h
+++ b/panels/search/cc-search-panel-row.h
@@ -33,9 +33,12 @@ struct _CcSearchPanelRow
 
   GAppInfo      *app_info;
 
+  GtkEventBox   *drag_handle;
   GtkImage      *icon;
   GtkLabel      *app_name;
   GtkSwitch     *switcher;
+
+  GtkListBox    *drag_widget;
 };
 
 
diff --git a/panels/search/cc-search-panel-row.ui b/panels/search/cc-search-panel-row.ui
index 2c82eeffd..571d6507c 100644
--- a/panels/search/cc-search-panel-row.ui
+++ b/panels/search/cc-search-panel-row.ui
@@ -4,14 +4,24 @@
   <template class="CcSearchPanelRow" parent="GtkListBoxRow">
     <property name="visible">True</property>
     <property name="can-focus">True</property>
+    <signal name="drag_data_received" handler="drag_data_received_cb" object="CcSearchPanelRow" 
swapped="yes"/>
     <child>
       <object class="GtkEventBox" id="drag_handle">
         <property name="visible">True</property>
+        <signal name="drag_data_get" handler="drag_data_get_cb" object="CcSearchPanelRow" swapped="yes"/>
+        <signal name="drag-begin" handler="drag_begin_cb" object="CcSearchPanelRow" swapped="yes"/>
+        <signal name="drag_end" handler="drag_end_cb" object="CcSearchPanelRow" swapped="yes"/>
         <child>
           <object class="GtkBox">
             <property name="visible">True</property>
             <property name="spacing">10</property>
             <property name="border-width">10</property>
+            <child>
+              <object class="GtkImage">
+                <property name="visible">True</property>
+                <property name="icon-name">open-menu-symbolic</property>
+              </object>
+            </child>
             <child>
               <object class="GtkImage" id="icon">
                 <property name="visible">True</property>
diff --git a/panels/search/cc-search-panel.c b/panels/search/cc-search-panel.c
index 0e20b9073..d580ce93a 100644
--- a/panels/search/cc-search-panel.c
+++ b/panels/search/cc-search-panel.c
@@ -287,6 +287,22 @@ search_panel_move_selected (CcSearchPanel *self,
   search_panel_propagate_sort_order (self);
 }
 
+static void
+row_moved_cb (CcSearchPanel    *self,
+              CcSearchPanelRow *dest_row,
+              CcSearchPanelRow *row)
+{
+  gint source_idx = gtk_list_box_row_get_index (GTK_LIST_BOX_ROW (row));
+  gint dest_idx = gtk_list_box_row_get_index (GTK_LIST_BOX_ROW (dest_row));
+  gboolean down;
+
+  gtk_list_box_select_row (GTK_LIST_BOX (self->list_box), GTK_LIST_BOX_ROW (row));
+
+  down = (source_idx - dest_idx) < 0;
+  for (int i = 0; i < ABS (source_idx - dest_idx); i++)
+    search_panel_move_selected (self, down);
+}
+
 static void
 down_button_clicked (GtkWidget *widget,
                      CcSearchPanel *self)
@@ -439,6 +455,9 @@ search_panel_add_one_app_info (CcSearchPanel *self,
   gtk_widget_set_valign (self->list_box, GTK_ALIGN_FILL);
 
   row = cc_search_panel_row_new (app_info);
+  g_signal_connect_object (row, "move-row",
+                           G_CALLBACK (row_moved_cb), self,
+                           G_CONNECT_SWAPPED);
   g_object_set_data (G_OBJECT (row), "self", self);
   gtk_container_add (GTK_CONTAINER (self->list_box), GTK_WIDGET (row));
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]