[gtk/wip/otte/bitset: 21/22] listbase: Only compute the modifiers when releasing the rubberband



commit 30488e60e292dfdb98fffc083083097ab793602e
Author: Benjamin Otte <otte redhat com>
Date:   Fri Jun 26 03:26:11 2020 +0200

    listbase: Only compute the modifiers when releasing the rubberband
    
    ... and do the right things:
    
    nothing:    selection = rubberband
    ctrl:       selection = selection OR rubberband
    shift:      selection = selection AND (NOT rubberband)
    ctrl+shift: selection = selection XOR rubberband
                (not sure this one makes sense, but toggling is fun)

 gtk/gtklistbase.c | 62 +++++++++++++++++++++++++++++++++++--------------------
 1 file changed, 40 insertions(+), 22 deletions(-)
---
diff --git a/gtk/gtklistbase.c b/gtk/gtklistbase.c
index 19bb54b2d2..edd68833df 100644
--- a/gtk/gtklistbase.c
+++ b/gtk/gtklistbase.c
@@ -48,8 +48,6 @@ struct _RubberbandData
   double              start_align_along;        /* alignment in vertical direction */
 
   double pointer_x, pointer_y;                  /* mouse coordinates in widget space */
-  gboolean modify;
-  gboolean extend;
 };
 
 typedef struct _GtkListBasePrivate GtkListBasePrivate;
@@ -1506,9 +1504,7 @@ gtk_list_base_allocate_rubberband (GtkListBase *self)
 static void
 gtk_list_base_start_rubberband (GtkListBase *self,
                                 double       x,
-                                double       y,
-                                gboolean     modify,
-                                gboolean     extend)
+                                double       y)
 {
   GtkListBasePrivate *priv = gtk_list_base_get_instance_private (self);
   cairo_rectangle_int_t item_area;
@@ -1535,16 +1531,15 @@ gtk_list_base_start_rubberband (GtkListBase *self,
   priv->rubberband->pointer_x = x;
   priv->rubberband->pointer_y = y;
 
-  priv->rubberband->modify = modify;
-  priv->rubberband->extend = extend;
-
   priv->rubberband->widget = gtk_gizmo_new ("rubberband",
                                             NULL, NULL, NULL, NULL, NULL, NULL);
   gtk_widget_set_parent (priv->rubberband->widget, GTK_WIDGET (self));
 }
 
 static void
-gtk_list_base_stop_rubberband (GtkListBase *self)
+gtk_list_base_stop_rubberband (GtkListBase *self,
+                               gboolean     modify,
+                               gboolean     extend)
 {
   GtkListBasePrivate *priv = gtk_list_base_get_instance_private (self);
   GtkListItemManagerItem *item;
@@ -1572,22 +1567,46 @@ gtk_list_base_stop_rubberband (GtkListBase *self)
         return;
 
       rubberband_selection = gtk_list_base_get_items_in_rect (self, &rect);
+      if (gtk_bitset_is_empty (rubberband_selection))
+        {
+          gtk_bitset_unref (rubberband_selection);
+          return;
+        }
 
-      if (priv->rubberband->extend)
+      if (modify && extend) /* Ctrl + Shift */
         {
+          GtkBitset *current;
+          guint min = gtk_bitset_get_minimum (rubberband_selection);
+          guint max = gtk_bitset_get_maximum (rubberband_selection);
+          /* toggle the rubberband, keep the rest */
+          current = gtk_selection_model_get_selection_in_range (model, min, max - min + 1);
+          selected = gtk_bitset_copy (current);
+          gtk_bitset_unref (current);
+          gtk_bitset_intersect (selected, rubberband_selection);
+          gtk_bitset_difference (selected, rubberband_selection);
+                                                              
           mask = gtk_bitset_ref (rubberband_selection);
         }
-      else
+      else if (modify) /* Ctrl */
         {
+          /* select the rubberband, keep the rest */
+          selected = gtk_bitset_ref (rubberband_selection);
+          mask = gtk_bitset_ref (rubberband_selection);
+        }
+      else if (extend) /* Shift */
+        {
+          /* unselect the rubberband, keep the rest */
+          selected = gtk_bitset_new_empty ();
+          mask = gtk_bitset_ref (rubberband_selection);
+        }
+      else /* no modifer */
+        {
+          /* select the rubberband, clear the rest */
+          selected = gtk_bitset_ref (rubberband_selection);
           mask = gtk_bitset_new_empty ();
           gtk_bitset_add_range (mask, 0, g_list_model_get_n_items (G_LIST_MODEL (model)));
         }
 
-      if (priv->rubberband->modify)
-        selected = gtk_bitset_new_empty ();
-      else
-        selected = gtk_bitset_ref (rubberband_selection);
-
       gtk_selection_model_set_selection (model, selected, mask);
 
       gtk_bitset_unref (selected);
@@ -1683,11 +1702,7 @@ gtk_list_base_drag_begin (GtkGestureDrag *gesture,
                           double          start_y,
                           GtkListBase    *self)
 {
-  gboolean modify;
-  gboolean extend;
-
-  get_selection_modifiers (GTK_GESTURE (gesture), &modify, &extend);
-  gtk_list_base_start_rubberband (self, start_x, start_y, modify, extend);
+  gtk_list_base_start_rubberband (self, start_x, start_y);
 }
 
 static void
@@ -1707,8 +1722,11 @@ gtk_list_base_drag_end (GtkGestureDrag *gesture,
                         double          offset_y,
                         GtkListBase    *self)
 {
+  gboolean modify, extend;
+
   gtk_list_base_drag_update (gesture, offset_x, offset_y, self);
-  gtk_list_base_stop_rubberband (self);
+  get_selection_modifiers (GTK_GESTURE (gesture), &modify, &extend);
+  gtk_list_base_stop_rubberband (self, modify, extend);
 }
 
 void


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