[gtk+] listbox: Convert to gadgets



commit 29accad89a8fc744123e4327aa907417a20ae9fa
Author: Matthias Clasen <mclasen redhat com>
Date:   Fri Dec 11 23:48:34 2015 -0500

    listbox: Convert to gadgets

 gtk/gtklistbox.c |  374 ++++++++++++++++++++++++++++++++++--------------------
 1 files changed, 238 insertions(+), 136 deletions(-)
---
diff --git a/gtk/gtklistbox.c b/gtk/gtklistbox.c
index ebcb361..76babbc 100644
--- a/gtk/gtklistbox.c
+++ b/gtk/gtklistbox.c
@@ -25,6 +25,7 @@
 #include "gtkprivate.h"
 #include "gtkintl.h"
 #include "gtkwidgetprivate.h"
+#include "gtkcontainerprivate.h"
 #include "gtkcsscustomgadgetprivate.h"
 
 #include <float.h>
@@ -76,6 +77,8 @@ typedef struct
 
   GtkWidget *placeholder;
 
+  GtkCssGadget *gadget;
+
   GtkListBoxSortFunc sort_func;
   gpointer sort_func_target;
   GDestroyNotify sort_func_target_destroy_notify;
@@ -279,6 +282,30 @@ static void                 gtk_list_box_bound_model_changed            (GListMo
                                                                          gpointer             user_data);
 
 static void                 gtk_list_box_check_model_compat             (GtkListBox          *box);
+
+static void     gtk_list_box_measure    (GtkCssGadget        *gadget,
+                                          GtkOrientation       orientation,
+                                          gint                 for_size,
+                                          gint                *minimum_size,
+                                          gint                *natural_size,
+                                          gint                *minimum_baseline,
+                                          gint                *natural_baseline,
+                                          gpointer             data);
+static void     gtk_list_box_allocate    (GtkCssGadget        *gadget,
+                                          const GtkAllocation *allocation,
+                                          int                  baseline,
+                                          GtkAllocation       *out_clip,
+                                          gpointer             data);
+static gboolean gtk_list_box_render      (GtkCssGadget        *gadget,
+                                          cairo_t             *cr,
+                                          int                  x,
+                                          int                  y,
+                                          int                  width,
+                                          int                  height,
+                                          gpointer             data);
+
+
+
 static GParamSpec *properties[LAST_PROPERTY] = { NULL, };
 static guint signals[LAST_SIGNAL] = { 0 };
 static GParamSpec *row_properties[LAST_ROW_PROPERTY] = { NULL, };
@@ -300,33 +327,6 @@ gtk_list_box_new (void)
 }
 
 static void
-gtk_list_box_init (GtkListBox *box)
-{
-  GtkListBoxPrivate *priv = BOX_PRIV (box);
-  GtkWidget *widget = GTK_WIDGET (box);
-
-  gtk_widget_set_has_window (widget, TRUE);
-  gtk_widget_set_redraw_on_allocate (widget, TRUE);
-  priv->selection_mode = GTK_SELECTION_SINGLE;
-  priv->activate_single_click = TRUE;
-
-  priv->children = g_sequence_new (NULL);
-  priv->header_hash = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, NULL);
-
-  priv->multipress_gesture = gtk_gesture_multi_press_new (widget);
-  gtk_event_controller_set_propagation_phase (GTK_EVENT_CONTROLLER (priv->multipress_gesture),
-                                              GTK_PHASE_BUBBLE);
-  gtk_gesture_single_set_touch_only (GTK_GESTURE_SINGLE (priv->multipress_gesture),
-                                     FALSE);
-  gtk_gesture_single_set_button (GTK_GESTURE_SINGLE (priv->multipress_gesture),
-                                 GDK_BUTTON_PRIMARY);
-  g_signal_connect (priv->multipress_gesture, "pressed",
-                    G_CALLBACK (gtk_list_box_multipress_gesture_pressed), box);
-  g_signal_connect (priv->multipress_gesture, "released",
-                    G_CALLBACK (gtk_list_box_multipress_gesture_released), box);
-}
-
-static void
 gtk_list_box_get_property (GObject    *obj,
                            guint       property_id,
                            GValue     *value,
@@ -398,6 +398,8 @@ gtk_list_box_finalize (GObject *obj)
       g_clear_object (&priv->bound_model);
     }
 
+  g_clear_object (&priv->gadget);
+
   G_OBJECT_CLASS (gtk_list_box_parent_class)->finalize (obj);
 }
 
@@ -624,6 +626,44 @@ gtk_list_box_class_init (GtkListBoxClass *klass)
   gtk_widget_class_set_css_name (widget_class, "list");
 }
 
+static void
+gtk_list_box_init (GtkListBox *box)
+{
+  GtkListBoxPrivate *priv = BOX_PRIV (box);
+  GtkWidget *widget = GTK_WIDGET (box);
+  GtkCssNode *widget_node;
+
+  gtk_widget_set_has_window (widget, TRUE);
+  gtk_widget_set_redraw_on_allocate (widget, TRUE);
+  priv->selection_mode = GTK_SELECTION_SINGLE;
+  priv->activate_single_click = TRUE;
+
+  priv->children = g_sequence_new (NULL);
+  priv->header_hash = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, NULL);
+
+  priv->multipress_gesture = gtk_gesture_multi_press_new (widget);
+  gtk_event_controller_set_propagation_phase (GTK_EVENT_CONTROLLER (priv->multipress_gesture),
+                                              GTK_PHASE_BUBBLE);
+  gtk_gesture_single_set_touch_only (GTK_GESTURE_SINGLE (priv->multipress_gesture),
+                                     FALSE);
+  gtk_gesture_single_set_button (GTK_GESTURE_SINGLE (priv->multipress_gesture),
+                                 GDK_BUTTON_PRIMARY);
+  g_signal_connect (priv->multipress_gesture, "pressed",
+                    G_CALLBACK (gtk_list_box_multipress_gesture_pressed), box);
+  g_signal_connect (priv->multipress_gesture, "released",
+                    G_CALLBACK (gtk_list_box_multipress_gesture_released), box);
+
+  widget_node = gtk_widget_get_css_node (GTK_WIDGET (box));
+  priv->gadget = gtk_css_custom_gadget_new_for_node (widget_node,
+                                                     GTK_WIDGET (box),
+                                                     gtk_list_box_measure,
+                                                     gtk_list_box_allocate,
+                                                     gtk_list_box_render,
+                                                     NULL,
+                                                     NULL);
+
+}
+
 /**
  * gtk_list_box_get_selected_row:
  * @box: a #GtkListBox
@@ -2077,16 +2117,25 @@ static gboolean
 gtk_list_box_draw (GtkWidget *widget,
                    cairo_t   *cr)
 {
-  GtkAllocation allocation;
-  GtkStyleContext *context;
+  gtk_css_gadget_draw (BOX_PRIV (widget)->gadget, cr);
 
-  gtk_widget_get_allocation (widget, &allocation);
-  context = gtk_widget_get_style_context (widget);
-  gtk_render_background (context, cr, 0, 0, allocation.width, allocation.height);
+  return FALSE;
+}
+
+static gboolean
+gtk_list_box_render (GtkCssGadget *gadget,
+                     cairo_t      *cr,
+                     int           x,
+                     int           y,
+                     int           width,
+                     int           height,
+                     gpointer      data)
+{
+  GtkWidget *widget = gtk_css_gadget_get_owner (gadget);
 
   GTK_WIDGET_CLASS (gtk_list_box_parent_class)->draw (widget, cr);
 
-  return TRUE;
+  return FALSE;
 }
 
 static void
@@ -2493,138 +2542,157 @@ gtk_list_box_get_request_mode (GtkWidget *widget)
 
 static void
 gtk_list_box_get_preferred_height (GtkWidget *widget,
-                                   gint      *minimum_height,
-                                   gint      *natural_height)
+                                   gint      *minimum,
+                                   gint      *natural)
 {
-  gint min_width, natural_width;
-  gtk_list_box_get_preferred_width (widget, &min_width, &natural_width);
-  gtk_list_box_get_preferred_height_for_width (widget, natural_width,
-                                               minimum_height, natural_height);
+  gtk_css_gadget_get_preferred_size (BOX_PRIV (widget)->gadget,
+                                     GTK_ORIENTATION_VERTICAL,
+                                     -1,
+                                     minimum, natural,
+                                     NULL, NULL);
 }
 
 static void
 gtk_list_box_get_preferred_height_for_width (GtkWidget *widget,
                                              gint       width,
-                                             gint      *minimum_height_out,
-                                             gint      *natural_height_out)
+                                             gint      *minimum,
+                                             gint      *natural)
 {
-  GtkListBoxPrivate *priv = BOX_PRIV (widget);
-  GSequenceIter *iter;
-  gint minimum_height;
-
-  minimum_height = 0;
-
-  if (priv->placeholder != NULL && gtk_widget_get_child_visible (priv->placeholder))
-    gtk_widget_get_preferred_height_for_width (priv->placeholder, width,
-                                               &minimum_height, NULL);
-
-  for (iter = g_sequence_get_begin_iter (priv->children);
-       !g_sequence_iter_is_end (iter);
-       iter = g_sequence_iter_next (iter))
-    {
-      GtkListBoxRow *row;
-      gint row_min = 0;
-
-      row = g_sequence_get (iter);
-      if (!row_is_visible (row))
-        continue;
+  gtk_css_gadget_get_preferred_size (BOX_PRIV (widget)->gadget,
+                                     GTK_ORIENTATION_VERTICAL,
+                                     width,
+                                     minimum, natural,
+                                     NULL, NULL);
+}
 
-      if (ROW_PRIV (row)->header != NULL)
-        {
-          gtk_widget_get_preferred_height_for_width (ROW_PRIV (row)->header, width, &row_min, NULL);
-          minimum_height += row_min;
-        }
-      gtk_widget_get_preferred_height_for_width (GTK_WIDGET (row), width, &row_min, NULL);
-      minimum_height += row_min;
-    }
+static void
+gtk_list_box_get_preferred_width (GtkWidget *widget,
+                                  gint      *minimum,
+                                  gint      *natural)
+{
+  gtk_css_gadget_get_preferred_size (BOX_PRIV (widget)->gadget,
+                                     GTK_ORIENTATION_HORIZONTAL,
+                                     -1,
+                                     minimum, natural,
+                                     NULL, NULL);
+}
 
-  /* We always allocate the minimum height, since handling expanding rows is way too costly,
-   * and unlikely to be used, as lists are generally put inside a scrolling window anyway.
-   */
-  *minimum_height_out = minimum_height;
-  *natural_height_out = minimum_height;
+static void
+gtk_list_box_get_preferred_width_for_height (GtkWidget *widget,
+                                             gint       height,
+                                             gint      *minimum,
+                                             gint      *natural)
+{
+  gtk_css_gadget_get_preferred_size (BOX_PRIV (widget)->gadget,
+                                     GTK_ORIENTATION_HORIZONTAL,
+                                     height,
+                                     minimum, natural,
+                                     NULL, NULL);
 }
 
 static void
-gtk_list_box_get_preferred_width (GtkWidget *widget,
-                                  gint      *minimum_width_out,
-                                  gint      *natural_width_out)
+gtk_list_box_measure (GtkCssGadget   *gadget,
+                      GtkOrientation  orientation,
+                      gint            for_size,
+                      gint           *minimum,
+                      gint           *natural,
+                      gint           *minimum_baseline,
+                      gint           *natural_baseline,
+                      gpointer        unused)
 {
+  GtkWidget *widget = gtk_css_gadget_get_owner (gadget);
   GtkListBoxPrivate *priv = BOX_PRIV (widget);
-  gint minimum_width;
-  gint natural_width;
   GSequenceIter *iter;
-  GtkListBoxRow *row;
-  gint row_min;
-  gint row_nat;
 
-  minimum_width = 0;
-  natural_width = 0;
+  if (orientation == GTK_ORIENTATION_HORIZONTAL)
+    {
+      *minimum = 0;
+      *natural = 0;
 
-  if (priv->placeholder != NULL && gtk_widget_get_child_visible (priv->placeholder))
-    gtk_widget_get_preferred_width (priv->placeholder,
-                                    &minimum_width, &natural_width);
+      if (priv->placeholder && gtk_widget_get_child_visible (priv->placeholder))
+        gtk_widget_get_preferred_width (priv->placeholder, minimum, natural);
 
-  for (iter = g_sequence_get_begin_iter (priv->children);
-       !g_sequence_iter_is_end (iter);
-       iter = g_sequence_iter_next (iter))
-    {
-      row = g_sequence_get (iter);
+      for (iter = g_sequence_get_begin_iter (priv->children);
+           !g_sequence_iter_is_end (iter);
+           iter = g_sequence_iter_next (iter))
+        {
+          GtkListBoxRow *row;
+          gint row_min;
+          gint row_nat;
 
-      /* We *do* take visible but filtered rows into account here so that
-       * the list width doesn't change during filtering
-       */
-      if (!gtk_widget_get_visible (GTK_WIDGET (row)))
-        continue;
+          row = g_sequence_get (iter);
 
-      gtk_widget_get_preferred_width (GTK_WIDGET (row), &row_min, &row_nat);
-      minimum_width = MAX (minimum_width, row_min);
-      natural_width = MAX (natural_width, row_nat);
+          /* We *do* take visible but filtered rows into account here so that
+           * the list width doesn't change during filtering
+           */
+          if (!gtk_widget_get_visible (GTK_WIDGET (row)))
+            continue;
 
-      if (ROW_PRIV (row)->header != NULL)
-        {
-          gtk_widget_get_preferred_width (ROW_PRIV (row)->header, &row_min, &row_nat);
-          minimum_width = MAX (minimum_width, row_min);
-          natural_width = MAX (natural_width, row_nat);
+          gtk_widget_get_preferred_width (GTK_WIDGET (row), &row_min, &row_nat);
+          *minimum = MAX (*minimum, row_min);
+          *natural = MAX (*natural, row_nat);
+
+          if (ROW_PRIV (row)->header != NULL)
+            {
+              gtk_widget_get_preferred_width (ROW_PRIV (row)->header, &row_min, &row_nat);
+              *minimum = MAX (*minimum, row_min);
+              *natural = MAX (*natural, row_nat);
+            }
         }
     }
+  else
+    {
+      if (for_size < 0)
+        gtk_css_gadget_get_preferred_size (priv->gadget,
+                                           GTK_ORIENTATION_HORIZONTAL,
+                                           -1,
+                                           NULL, &for_size,
+                                           NULL, NULL);
 
-  *minimum_width_out = minimum_width;
-  *natural_width_out = natural_width;
-}
+      *minimum = 0;
 
-static void
-gtk_list_box_get_preferred_width_for_height (GtkWidget *widget,
-                                             gint       height,
-                                             gint      *minimum_width,
-                                             gint      *natural_width)
-{
-  gtk_list_box_get_preferred_width (widget, minimum_width, natural_width);
+      if (priv->placeholder && gtk_widget_get_child_visible (priv->placeholder))
+        gtk_widget_get_preferred_height_for_width (priv->placeholder, for_size,
+                                                   minimum, NULL);
+
+      for (iter = g_sequence_get_begin_iter (priv->children);
+           !g_sequence_iter_is_end (iter);
+           iter = g_sequence_iter_next (iter))
+        {
+          GtkListBoxRow *row;
+          gint row_min = 0;
+
+          row = g_sequence_get (iter);
+          if (!row_is_visible (row))
+            continue;
+
+          if (ROW_PRIV (row)->header != NULL)
+            {
+              gtk_widget_get_preferred_height_for_width (ROW_PRIV (row)->header, for_size, &row_min, NULL);
+              *minimum += row_min;
+            }
+          gtk_widget_get_preferred_height_for_width (GTK_WIDGET (row), for_size, &row_min, NULL);
+          *minimum += row_min;
+        }
+
+      /* We always allocate the minimum height, since handling expanding rows
+       * is way too costly, and unlikely to be used, as lists are generally put
+       * inside a scrolling window anyway.
+       */
+      *natural = *minimum;
+    }
 }
 
 static void
 gtk_list_box_size_allocate (GtkWidget     *widget,
                             GtkAllocation *allocation)
 {
-  GtkListBoxPrivate *priv = BOX_PRIV (widget);
-  GtkAllocation child_allocation;
-  GtkAllocation header_allocation;
-  GtkListBoxRow *row;
+  GtkAllocation clip;
   GdkWindow *window;
-  GSequenceIter *iter;
-  int child_min;
-
-  child_allocation.x = 0;
-  child_allocation.y = 0;
-  child_allocation.width = 0;
-  child_allocation.height = 0;
-
-  header_allocation.x = 0;
-  header_allocation.y = 0;
-  header_allocation.width = 0;
-  header_allocation.height = 0;
+  GtkAllocation child_allocation;
 
   gtk_widget_set_allocation (widget, allocation);
+
   window = gtk_widget_get_window (widget);
   if (window != NULL)
     gdk_window_move_resize (window,
@@ -2634,17 +2702,49 @@ gtk_list_box_size_allocate (GtkWidget     *widget,
   child_allocation.x = 0;
   child_allocation.y = 0;
   child_allocation.width = allocation->width;
-  header_allocation.x = 0;
+  child_allocation.height = allocation->height;
+
+  gtk_css_gadget_allocate (BOX_PRIV (widget)->gadget,
+                           &child_allocation,
+                           gtk_widget_get_allocated_baseline (widget),
+                           &clip);
+
+  _gtk_widget_set_simple_clip (widget, &clip);
+}
+
+
+static void
+gtk_list_box_allocate (GtkCssGadget        *gadget,
+                       const GtkAllocation *allocation,
+                       int                  baseline,
+                       GtkAllocation       *out_clip,
+                       gpointer             unused)
+{
+  GtkWidget *widget = gtk_css_gadget_get_owner (gadget);
+  GtkListBoxPrivate *priv = BOX_PRIV (widget);
+  GtkAllocation child_allocation;
+  GtkAllocation header_allocation;
+  GtkListBoxRow *row;
+  GSequenceIter *iter;
+  int child_min;
+
+  child_allocation.x = allocation->x;
+  child_allocation.y = allocation->y;
+  child_allocation.width = allocation->width;
+  child_allocation.height = 0;
+
+  header_allocation.x = allocation->x;
+  header_allocation.y = allocation->y;
   header_allocation.width = allocation->width;
+  header_allocation.height = 0;
 
-  if (priv->placeholder != NULL && gtk_widget_get_child_visible (priv->placeholder))
+  if (priv->placeholder && gtk_widget_get_child_visible (priv->placeholder))
     {
       gtk_widget_get_preferred_height_for_width (priv->placeholder,
                                                  allocation->width, &child_min, NULL);
       header_allocation.height = allocation->height;
       header_allocation.y = child_allocation.y;
-      gtk_widget_size_allocate (priv->placeholder,
-                                &header_allocation);
+      gtk_widget_size_allocate (priv->placeholder, &header_allocation);
       child_allocation.y += child_min;
     }
 
@@ -2680,6 +2780,8 @@ gtk_list_box_size_allocate (GtkWidget     *widget,
       gtk_widget_size_allocate (GTK_WIDGET (row), &child_allocation);
       child_allocation.y += child_min;
     }
+
+  gtk_container_get_children_clip (GTK_CONTAINER (widget), out_clip);
 }
 
 /**


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