From 554bd2d0ff796e7fafe9b4ef5e7977352b0a0a83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= Date: Sun, 26 Mar 2017 11:12:57 +0200 Subject: [PATCH] progressbar: Use GtkLabel for the text --- gtk/gtkprogressbar.c | 270 ++++++++++--------------------------------- 1 file changed, 58 insertions(+), 212 deletions(-) diff --git a/gtk/gtkprogressbar.c b/gtk/gtkprogressbar.c index 69114ab2ec..deb8e80c2b 100644 --- a/gtk/gtkprogressbar.c +++ b/gtk/gtkprogressbar.c @@ -91,10 +91,9 @@ struct _GtkProgressBarPrivate { - gchar *text; + GtkWidget *label; GtkCssGadget *gadget; - GtkCssGadget *text_gadget; GtkCssGadget *trough_gadget; GtkCssGadget *progress_gadget; @@ -114,9 +113,9 @@ struct _GtkProgressBarPrivate guint activity_dir : 1; guint activity_mode : 1; - guint ellipsize : 3; guint show_text : 1; guint inverted : 1; + guint text_set : 1; }; enum { @@ -195,21 +194,6 @@ static gboolean gtk_progress_bar_render_trough (GtkCssGadget *gadget, gint width, gint height, gpointer data); -static void gtk_progress_bar_measure_text (GtkCssGadget *gadget, - GtkOrientation orientation, - gint for_size, - gint *minimum, - gint *natural, - gint *minimum_baseline, - gint *natural_baseline, - gpointer data); -static gboolean gtk_progress_bar_render_text (GtkCssGadget *gadget, - GtkSnapshot *snapshot, - gint x, - gint y, - gint width, - gint height, - gpointer data); G_DEFINE_TYPE_WITH_CODE (GtkProgressBar, gtk_progress_bar, GTK_TYPE_WIDGET, G_ADD_PRIVATE (GtkProgressBar) @@ -429,8 +413,6 @@ update_node_state (GtkProgressBar *pbar) gtk_css_gadget_set_state (priv->gadget, state); gtk_css_gadget_set_state (priv->trough_gadget, state); gtk_css_gadget_set_state (priv->progress_gadget, state); - if (priv->text_gadget) - gtk_css_gadget_set_state (priv->text_gadget, state); } static void @@ -448,10 +430,9 @@ gtk_progress_bar_init (GtkProgressBar *pbar) priv->activity_pos = 0; priv->activity_dir = 1; priv->activity_blocks = 5; - priv->ellipsize = PANGO_ELLIPSIZE_NONE; priv->show_text = FALSE; + priv->text_set = FALSE; - priv->text = NULL; priv->fraction = 0.0; gtk_widget_set_has_window (GTK_WIDGET (pbar), FALSE); @@ -554,13 +535,13 @@ gtk_progress_bar_get_property (GObject *object, g_value_set_double (value, priv->pulse_fraction); break; case PROP_TEXT: - g_value_set_string (value, priv->text); + g_value_set_string (value, gtk_progress_bar_get_text (pbar)); break; case PROP_SHOW_TEXT: g_value_set_boolean (value, priv->show_text); break; case PROP_ELLIPSIZE: - g_value_set_enum (value, priv->ellipsize); + g_value_set_enum (value, gtk_progress_bar_get_ellipsize (pbar)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); @@ -594,9 +575,9 @@ gtk_progress_bar_finalize (GObject *object) if (priv->activity_mode) gtk_progress_bar_act_mode_leave (pbar); - g_free (priv->text); + if (priv->label) + gtk_widget_unparent (priv->label); - g_clear_object (&priv->text_gadget); g_clear_object (&priv->progress_gadget); g_clear_object (&priv->trough_gadget); g_clear_object (&priv->gadget); @@ -604,17 +585,6 @@ gtk_progress_bar_finalize (GObject *object) G_OBJECT_CLASS (gtk_progress_bar_parent_class)->finalize (object); } -static gchar * -get_current_text (GtkProgressBar *pbar) -{ - GtkProgressBarPrivate *priv = pbar->priv; - - if (priv->text) - return g_strdup (priv->text); - else - return g_strdup_printf (C_("progress bar label", "%.0f %%"), priv->fraction * 100.0); -} - static void gtk_progress_bar_measure (GtkCssGadget *gadget, GtkOrientation orientation, @@ -636,11 +606,8 @@ gtk_progress_bar_measure (GtkCssGadget *gadget, priv = pbar->priv; if (priv->show_text) - gtk_css_gadget_get_preferred_size (priv->text_gadget, - orientation, - -1, - &text_minimum, &text_natural, - NULL, NULL); + gtk_widget_measure (priv->label, orientation, -1, + &text_minimum, &text_natural, NULL, NULL); else text_minimum = text_natural = 0; @@ -678,89 +645,6 @@ gtk_progress_bar_measure (GtkCssGadget *gadget, } } -static PangoLayout * -gtk_progress_bar_get_layout (GtkProgressBar *pbar) -{ - PangoLayout *layout; - gchar *buf; - GtkCssStyle *style; - PangoAttrList *attrs; - PangoFontDescription *desc; - - buf = get_current_text (pbar); - layout = gtk_widget_create_pango_layout (GTK_WIDGET (pbar), buf); - - style = gtk_css_node_get_style (gtk_css_gadget_get_node (pbar->priv->text_gadget)); - - attrs = gtk_css_style_get_pango_attributes (style); - desc = gtk_css_style_get_pango_font (style); - - pango_layout_set_attributes (layout, attrs); - pango_layout_set_font_description (layout, desc); - - if (attrs) - pango_attr_list_unref (attrs); - pango_font_description_free (desc); - - g_free (buf); - - return layout; -} - -static void -gtk_progress_bar_measure_text (GtkCssGadget *gadget, - GtkOrientation orientation, - int for_size, - int *minimum, - int *natural, - int *minimum_baseline, - int *natural_baseline, - gpointer data) -{ - GtkWidget *widget; - GtkProgressBar *pbar; - GtkProgressBarPrivate *priv; - PangoLayout *layout; - PangoRectangle logical_rect; - - widget = gtk_css_gadget_get_owner (gadget); - pbar = GTK_PROGRESS_BAR (widget); - priv = pbar->priv; - - layout = gtk_progress_bar_get_layout (pbar); - - pango_layout_get_pixel_extents (layout, NULL, &logical_rect); - - if (orientation == GTK_ORIENTATION_HORIZONTAL) - { - if (priv->ellipsize) - { - PangoContext *context; - PangoFontMetrics *metrics; - gint char_width; - - /* The minimum size for ellipsized text is ~ 3 chars */ - context = pango_layout_get_context (layout); - metrics = pango_context_get_metrics (context, - pango_layout_get_font_description (layout), - pango_context_get_language (context)); - - char_width = pango_font_metrics_get_approximate_char_width (metrics); - pango_font_metrics_unref (metrics); - - *minimum = PANGO_PIXELS (char_width) * 3; - } - else - *minimum = logical_rect.width; - - *natural = MAX (*minimum, logical_rect.width); - } - else - *minimum = *natural = logical_rect.height; - - g_object_unref (layout); -} - static void gtk_progress_bar_size_allocate (GtkWidget *widget, GtkAllocation *allocation) @@ -823,16 +707,11 @@ gtk_progress_bar_allocate (GtkCssGadget *gadget, if (!priv->show_text) return; - gtk_css_gadget_get_preferred_size (priv->text_gadget, - GTK_ORIENTATION_HORIZONTAL, - -1, - &text_min, &text_nat, - NULL, NULL); - gtk_css_gadget_get_preferred_size (priv->text_gadget, - GTK_ORIENTATION_VERTICAL, - -1, - &text_height, NULL, - NULL, NULL); + gtk_widget_measure (priv->label, GTK_ORIENTATION_HORIZONTAL, -1, + &text_min, &text_nat, NULL, NULL); + + gtk_widget_measure (priv->label, GTK_ORIENTATION_VERTICAL, -1, + &text_height, NULL, NULL, NULL); text_width = CLAMP (text_nat, text_min, allocation->width); @@ -851,7 +730,8 @@ gtk_progress_bar_allocate (GtkCssGadget *gadget, alloc.height = text_height; } - gtk_css_gadget_allocate (priv->text_gadget, &alloc, -1, &text_clip); + gtk_widget_size_allocate (priv->label, &alloc); + gtk_widget_get_clip (priv->label, &text_clip); gdk_rectangle_union (out_clip, &text_clip, out_clip); } @@ -1065,42 +945,6 @@ gtk_progress_bar_act_mode_leave (GtkProgressBar *pbar) update_node_classes (pbar); } -static gboolean -gtk_progress_bar_render_text (GtkCssGadget *gadget, - GtkSnapshot *snapshot, - int x, - int y, - int width, - int height, - gpointer data) -{ - GtkWidget *widget; - GtkProgressBar *pbar; - GtkProgressBarPrivate *priv; - GtkStyleContext *context; - PangoLayout *layout; - - widget = gtk_css_gadget_get_owner (gadget); - pbar = GTK_PROGRESS_BAR (widget); - priv = pbar->priv; - - context = gtk_widget_get_style_context (widget); - gtk_style_context_save_to_node (context, gtk_css_gadget_get_node (gadget)); - - layout = gtk_progress_bar_get_layout (pbar); - pango_layout_set_ellipsize (layout, priv->ellipsize); - if (priv->ellipsize) - pango_layout_set_width (layout, width * PANGO_SCALE); - - gtk_snapshot_render_layout (snapshot, context, x, y, layout); - - g_object_unref (layout); - - gtk_style_context_restore (context); - - return FALSE; -} - static gboolean gtk_progress_bar_render_trough (GtkCssGadget *gadget, GtkSnapshot *snapshot, @@ -1137,8 +981,8 @@ gtk_progress_bar_render (GtkCssGadget *gadget, priv = GTK_PROGRESS_BAR (widget)->priv; gtk_css_gadget_snapshot (priv->trough_gadget, snapshot); - if (priv->show_text) - gtk_css_gadget_snapshot (priv->text_gadget, snapshot); + if (priv->label) + gtk_widget_snapshot_child (widget, priv->label, snapshot); return FALSE; } @@ -1198,6 +1042,15 @@ gtk_progress_bar_set_fraction (GtkProgressBar *pbar, gtk_widget_queue_allocate (GTK_WIDGET (pbar)); update_fraction_classes (pbar); + if (!priv->text_set && priv->label != NULL) + { + char *text = g_strdup_printf (C_("progress bar label", "%.0f %%"), priv->fraction * 100.0); + + gtk_label_set_label (GTK_LABEL (priv->label), text); + + g_free (text); + } + g_object_notify_by_pspec (G_OBJECT (pbar), progress_props[PROP_FRACTION]); } @@ -1254,36 +1107,25 @@ gtk_progress_bar_set_text (GtkProgressBar *pbar, const gchar *text) { GtkProgressBarPrivate *priv; + const char *current_text = NULL; g_return_if_fail (GTK_IS_PROGRESS_BAR (pbar)); priv = pbar->priv; + if (priv->label) + current_text = gtk_label_get_label (GTK_LABEL (priv->label)); + /* Don't notify again if nothing's changed. */ - if (g_strcmp0 (priv->text, text) == 0) + if (g_strcmp0 (current_text, text) == 0) return; - g_free (priv->text); - priv->text = g_strdup (text); - - gtk_widget_queue_resize (GTK_WIDGET (pbar)); + priv->text_set = TRUE; + gtk_label_set_label (GTK_LABEL (priv->label), text); g_object_notify_by_pspec (G_OBJECT (pbar), progress_props[PROP_TEXT]); } -static void -gtk_progress_bar_text_style_changed (GtkCssNode *node, - GtkCssStyleChange *change, - GtkProgressBar *pbar) -{ - if (change == NULL || - gtk_css_style_change_affects (change, GTK_CSS_AFFECTS_TEXT_ATTRS) || - gtk_css_style_change_affects (change, GTK_CSS_AFFECTS_FONT)) - { - gtk_widget_queue_resize (GTK_WIDGET (pbar)); - } -} - /** * gtk_progress_bar_set_show_text: * @pbar: a #GtkProgressBar @@ -1319,25 +1161,24 @@ gtk_progress_bar_set_show_text (GtkProgressBar *pbar, if (show_text) { - priv->text_gadget = gtk_css_custom_gadget_new ("text", - GTK_WIDGET (pbar), - priv->gadget, - priv->trough_gadget, - gtk_progress_bar_measure_text, - NULL, - gtk_progress_bar_render_text, - NULL, - NULL); - g_signal_connect (gtk_css_gadget_get_node (priv->text_gadget), "style-changed", - G_CALLBACK (gtk_progress_bar_text_style_changed), pbar); + priv->label = g_object_new (GTK_TYPE_LABEL, + "css-name", "text", + NULL); + gtk_widget_set_parent (priv->label, GTK_WIDGET (pbar)); - update_node_state (pbar); + if (!priv->text_set) + { + char *text = g_strdup_printf (C_("progress bar label", "%.0f %%"), priv->fraction * 100.0); + + gtk_label_set_label (GTK_LABEL (priv->label), text); + + g_free (text); + } } else { - if (priv->text_gadget) - gtk_css_node_set_parent (gtk_css_gadget_get_node (priv->text_gadget), NULL); - g_clear_object (&priv->text_gadget); + gtk_widget_unparent (priv->label); + g_clear_object (&priv->label); } gtk_widget_queue_resize (GTK_WIDGET (pbar)); @@ -1474,7 +1315,7 @@ gtk_progress_bar_get_text (GtkProgressBar *pbar) { g_return_val_if_fail (GTK_IS_PROGRESS_BAR (pbar), NULL); - return pbar->priv->text; + return pbar->priv->label ? gtk_label_get_label (GTK_LABEL (pbar->priv->label)) : NULL; } /** @@ -1547,12 +1388,14 @@ gtk_progress_bar_set_ellipsize (GtkProgressBar *pbar, priv = pbar->priv; - if ((PangoEllipsizeMode)priv->ellipsize != mode) + if (priv->label == NULL) + return; + + if (gtk_label_get_ellipsize (GTK_LABEL (priv->label)) != mode) { - priv->ellipsize = mode; + gtk_label_set_ellipsize (GTK_LABEL (priv->label), mode); g_object_notify_by_pspec (G_OBJECT (pbar), progress_props[PROP_ELLIPSIZE]); - gtk_widget_queue_resize (GTK_WIDGET (pbar)); } } @@ -1572,5 +1415,8 @@ gtk_progress_bar_get_ellipsize (GtkProgressBar *pbar) { g_return_val_if_fail (GTK_IS_PROGRESS_BAR (pbar), PANGO_ELLIPSIZE_NONE); - return pbar->priv->ellipsize; + if (pbar->priv->label == NULL) + return PANGO_ELLIPSIZE_NONE; + + return gtk_label_get_ellipsize (GTK_LABEL (pbar->priv->label)); }