[gtk+] entry: Turn progress node into a gadget



commit 429bec54e5b6c276cbdc5abad80ba9c21456ed72
Author: Benjamin Otte <otte redhat com>
Date:   Wed Feb 3 20:44:06 2016 +0100

    entry: Turn progress node into a gadget

 gtk/gtkentry.c |  200 +++++++++++++++++++++++---------------------------------
 1 files changed, 83 insertions(+), 117 deletions(-)
---
diff --git a/gtk/gtkentry.c b/gtk/gtkentry.c
index d304706..2d07e1b 100644
--- a/gtk/gtkentry.c
+++ b/gtk/gtkentry.c
@@ -213,8 +213,8 @@ struct _GtkEntryPrivate
   GtkGesture    *multipress_gesture;
 
   GtkCssGadget  *gadget;
+  GtkCssGadget  *progress_gadget;
   GtkCssNode    *selection_node;
-  GtkCssNode    *progress_node;
   GtkCssNode    *undershoot_node[2];
 
   gfloat        xalign;
@@ -427,8 +427,6 @@ static void  gtk_entry_get_preferred_height_and_baseline_for_width (GtkWidget *w
                                                                     gint      *natural_baseline);
 static void   gtk_entry_size_allocate        (GtkWidget        *widget,
                                              GtkAllocation    *allocation);
-static void   gtk_entry_draw_progress        (GtkWidget        *widget,
-                                              cairo_t          *cr);
 static gint   gtk_entry_draw                 (GtkWidget        *widget,
                                               cairo_t          *cr);
 static gboolean gtk_entry_event              (GtkWidget        *widget,
@@ -2978,6 +2976,7 @@ gtk_entry_finalize (GObject *object)
   if (priv->attrs)
     pango_attr_list_unref (priv->attrs);
 
+  g_clear_object (&priv->progress_gadget);
   g_clear_object (&priv->gadget);
 
   G_OBJECT_CLASS (gtk_entry_parent_class)->finalize (object);
@@ -3192,8 +3191,8 @@ update_node_state (GtkEntry *entry)
 
   state = gtk_widget_get_state_flags (GTK_WIDGET (entry));
 
-  if (priv->progress_node)
-    gtk_css_node_set_state (priv->progress_node, state);
+  if (priv->progress_gadget)
+    gtk_css_gadget_set_state (priv->progress_gadget, state);
   if (priv->selection_node)
     gtk_css_node_set_state (priv->selection_node, state);
 }
@@ -3206,12 +3205,11 @@ update_node_ordering (GtkEntry *entry)
   GtkEntryIconPosition icon_pos;
   GtkCssNode *sibling, *parent;
 
-  if (priv->progress_node)
+  if (priv->progress_gadget)
     {
-      parent = gtk_css_node_get_parent (priv->progress_node);
-      sibling = gtk_css_node_get_last_child (parent);
-      if (priv->progress_node != sibling)
-        gtk_css_node_insert_after (parent, priv->progress_node, sibling);
+      gtk_css_node_insert_before (gtk_css_gadget_get_node (priv->gadget),
+                                  gtk_css_gadget_get_node (priv->progress_gadget),
+                                  NULL);
     }
 
   if (gtk_widget_get_direction (GTK_WIDGET (entry)) == GTK_TEXT_DIR_RTL)
@@ -3575,6 +3573,20 @@ gtk_entry_measure (GtkCssGadget   *gadget,
     }
 
   pango_font_metrics_unref (metrics);
+
+  if (priv->progress_gadget && gtk_css_gadget_get_visible (priv->progress_gadget))
+    {
+      int prog_min, prog_nat;
+
+      gtk_css_gadget_get_preferred_size (priv->progress_gadget,
+                                         orientation,
+                                         for_size,
+                                         &prog_min, &prog_nat,
+                                         NULL, NULL);
+
+      *minimum = MAX (*minimum, prog_min);
+      *natural = MAX (*natural, prog_nat);
+    }
 }
 
 static void
@@ -3777,6 +3789,42 @@ gtk_entry_allocate (GtkCssGadget        *gadget,
       gdk_rectangle_union (out_clip, &clip, out_clip);
     }
 
+  if (priv->progress_gadget && gtk_css_gadget_get_visible (priv->progress_gadget))
+    {
+      int extra_width, req_width;
+      GtkAllocation progress_alloc;
+      GdkRectangle clip;
+
+      gtk_css_gadget_get_preferred_size (priv->progress_gadget,
+                                         GTK_ORIENTATION_HORIZONTAL,
+                                         allocation->height,
+                                         &req_width, NULL,
+                                         NULL, NULL);
+      extra_width = allocation->width - req_width;
+
+      progress_alloc = *allocation;
+
+      if (priv->progress_pulse_mode)
+        {
+          gdouble value = priv->progress_pulse_current;
+
+          progress_alloc.x += (gint) floor (value * extra_width);
+          progress_alloc.width = req_width + (gint) ceil (priv->progress_pulse_fraction * extra_width);
+        }
+      else
+        {
+          gdouble value = priv->progress_fraction;
+
+          progress_alloc.width = req_width + (gint) nearbyint (value * extra_width);
+          if (gtk_widget_get_direction (GTK_WIDGET (entry)) == GTK_TEXT_DIR_RTL)
+            progress_alloc.x += allocation->width - progress_alloc.width;
+        }
+
+      gtk_css_gadget_allocate (priv->progress_gadget, &progress_alloc, baseline, &clip);
+
+      gdk_rectangle_union (out_clip, &clip, out_clip);
+    }
+
   /* Do this here instead of gtk_entry_size_allocate() so it works
    * inside spinbuttons, which don't chain up.
    */
@@ -3812,78 +3860,6 @@ should_prelight (GtkEntry             *entry,
   return TRUE;
 }
 
-static void
-get_progress_area (GtkWidget *widget,
-                   gint       *x,
-                   gint       *y,
-                   gint       *width,
-                   gint       *height)
-{
-  GtkEntry *entry = GTK_ENTRY (widget);
-  GtkEntryPrivate *private = entry->priv;
-  GtkAllocation allocation;
-
-  gtk_css_gadget_get_content_allocation (private->gadget, &allocation, NULL);
-  *x = allocation.x;
-  *y = allocation.y;
-  *width = allocation.width;
-  *height = allocation.height;
-
-  if (private->progress_pulse_mode)
-    {
-      gdouble value = private->progress_pulse_current;
-
-      *x += (gint) floor(value * (*width));
-      *width = (gint) ceil(private->progress_pulse_fraction * (*width));
-    }
-  else if (private->progress_fraction > 0)
-    {
-      gdouble value = private->progress_fraction;
-
-      if (gtk_widget_get_direction (GTK_WIDGET (entry)) == GTK_TEXT_DIR_RTL)
-        {
-          gint bar_width;
-
-          bar_width = floor(value * (*width) + 0.5);
-          *x += *width - bar_width;
-          *width = bar_width;
-        }
-      else
-        {
-          *width = (gint) floor(value * (*width) + 0.5);
-        }
-    }
-  else
-    {
-      *width = 0;
-      *height = 0;
-    }
-}
-
-static void
-gtk_entry_draw_progress (GtkWidget       *widget,
-                         cairo_t         *cr)
-{
-  GtkEntry *entry = GTK_ENTRY (widget);
-  GtkStyleContext *context;
-  GtkAllocation allocation;
-  gint x, y, width, height;
-
-  context = gtk_widget_get_style_context (widget);
-  get_progress_area (widget, &x, &y, &width, &height);
-  gtk_widget_get_allocation (widget, &allocation);
-  x -= allocation.x;
-  y -= allocation.y;
-
-  if ((width <= 0) || (height <= 0))
-    return;
-
-  gtk_style_context_save_to_node (context, entry->priv->progress_node);
-  gtk_render_background (context, cr, x, y, width, height);
-  gtk_render_frame (context, cr, x, y, width, height);
-  gtk_style_context_restore (context);
-}
-
 static gboolean
 gtk_entry_draw (GtkWidget *widget,
                cairo_t   *cr)
@@ -3950,7 +3926,8 @@ gtk_entry_render (GtkCssGadget *gadget,
   priv = entry->priv;
 
   /* Draw progress */
-  gtk_entry_draw_progress (widget, cr);
+  if (priv->progress_gadget && gtk_css_gadget_get_visible (priv->progress_gadget))
+    gtk_css_gadget_draw (priv->progress_gadget, cr);
 
   /* Draw text and cursor */
   cairo_save (cr);
@@ -10458,20 +10435,24 @@ tick_cb (GtkWidget     *widget,
 }
 
 static void
-gtk_entry_ensure_progress_node (GtkEntry *entry)
+gtk_entry_ensure_progress_gadget (GtkEntry *entry)
 {
   GtkEntryPrivate *priv = entry->priv;
-  GtkCssNode *widget_node;
 
-  if (priv->progress_node)
+  if (priv->progress_gadget)
     return;
 
-  widget_node = gtk_css_gadget_get_node (priv->gadget);
-  priv->progress_node = gtk_css_node_new ();
-  gtk_css_node_set_name (priv->progress_node, I_("progress"));
-  gtk_css_node_set_parent (priv->progress_node, widget_node);
-  gtk_css_node_set_state (priv->progress_node, gtk_css_node_get_state (widget_node));
-  g_object_unref (priv->progress_node);
+  priv->progress_gadget = gtk_css_custom_gadget_new ("progress",
+                                                     GTK_WIDGET (entry),
+                                                     priv->gadget,
+                                                     NULL,
+                                                     NULL,
+                                                     NULL,
+                                                     NULL,
+                                                     NULL,
+                                                     NULL);
+  gtk_css_gadget_set_state (priv->progress_gadget,
+      gtk_css_node_get_state (gtk_widget_get_css_node (GTK_WIDGET (entry))));
 
   update_node_ordering (entry);
 }
@@ -10484,9 +10465,9 @@ gtk_entry_start_pulse_mode (GtkEntry *entry)
   if (priv->progress_pulse_mode)
     return;
 
-  gtk_entry_ensure_progress_node (entry);
-  gtk_css_node_set_visible (priv->progress_node, TRUE);
-  gtk_css_node_add_class (priv->progress_node, g_quark_from_static_string (GTK_STYLE_CLASS_PULSE));
+  gtk_entry_ensure_progress_gadget (entry);
+  gtk_css_gadget_set_visible (priv->progress_gadget, TRUE);
+  gtk_css_gadget_add_class (priv->progress_gadget, GTK_STYLE_CLASS_PULSE);
 
   priv->progress_pulse_mode = TRUE;
   priv->tick_id = gtk_widget_add_tick_callback (GTK_WIDGET (entry), tick_cb, NULL, NULL);
@@ -10507,8 +10488,8 @@ gtk_entry_stop_pulse_mode (GtkEntry *entry)
 
   if (priv->progress_pulse_mode)
     {
-      gtk_css_node_set_visible (priv->progress_node, FALSE);
-      gtk_css_node_remove_class (priv->progress_node, g_quark_from_static_string (GTK_STYLE_CLASS_PULSE));
+      gtk_css_gadget_set_visible (priv->progress_gadget, FALSE);
+      gtk_css_gadget_remove_class (priv->progress_gadget, GTK_STYLE_CLASS_PULSE);
 
       priv->progress_pulse_mode = FALSE;
       gtk_widget_remove_tick_callback (GTK_WIDGET (entry), priv->tick_id);
@@ -10543,21 +10524,12 @@ gtk_entry_set_progress_fraction (GtkEntry *entry,
   GtkWidget       *widget;
   GtkEntryPrivate *private;
   gdouble          old_fraction;
-  gint x, y, width, height;
-  gint old_x = 0, old_y = 0, old_width = 0, old_height = 0;
-  gboolean was_pulse;
 
   g_return_if_fail (GTK_IS_ENTRY (entry));
 
   widget = GTK_WIDGET (entry);
   private = entry->priv;
 
-  gtk_entry_ensure_progress_node (entry);
-  gtk_css_node_set_visible (private->progress_node, TRUE);
-  gtk_css_node_remove_class (private->progress_node, g_quark_from_static_string (GTK_STYLE_CLASS_PULSE));
-
-  was_pulse = private->progress_pulse_mode;
-
   if (private->progress_pulse_mode)
     old_fraction = -1;
   else
@@ -10565,24 +10537,18 @@ gtk_entry_set_progress_fraction (GtkEntry *entry,
 
   gtk_entry_stop_pulse_mode (entry);
 
-  if (gtk_widget_is_drawable (widget))
-    get_progress_area (widget, &old_x, &old_y, &old_width, &old_height);
+  gtk_entry_ensure_progress_gadget (entry);
+  gtk_css_gadget_set_visible (private->progress_gadget, TRUE);
 
   fraction = CLAMP (fraction, 0.0, 1.0);
   private->progress_fraction = fraction;
   private->progress_pulse_current = 0.0;
 
-  if (gtk_widget_is_drawable (widget))
+  if (fraction != old_fraction)
     {
-      get_progress_area (widget, &x, &y, &width, &height);
-
-      if (was_pulse ||
-          x != old_x || y != old_y || width != old_width || height != old_height)
-        gtk_widget_queue_draw (widget);
+      g_object_notify_by_pspec (G_OBJECT (entry), entry_props[PROP_PROGRESS_FRACTION]);
+      gtk_widget_queue_allocate (widget);
     }
-
-  if (fraction != old_fraction)
-    g_object_notify_by_pspec (G_OBJECT (entry), entry_props[PROP_PROGRESS_FRACTION]);
 }
 
 /**


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