[gtk+/wip/otte/gadget] progress bar: Render text with a gadget too
- From: Matthias Clasen <matthiasc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+/wip/otte/gadget] progress bar: Render text with a gadget too
- Date: Wed, 25 Nov 2015 18:29:36 +0000 (UTC)
commit b844c322f7b91767c3d7a48e2c940d25b7f0ff6d
Author: Matthias Clasen <mclasen redhat com>
Date: Wed Nov 25 13:28:28 2015 -0500
progress bar: Render text with a gadget too
This makes it possible to set padding on the progress bar text,
and give it a different font, etc. At the same time, drop a lot
of complicated code that was drawing text superimposed on the
trough, which we're not doing anymore.
gtk/gtkprogressbar.c | 343 ++++++++++++++++++++++++--------------------------
1 files changed, 163 insertions(+), 180 deletions(-)
---
diff --git a/gtk/gtkprogressbar.c b/gtk/gtkprogressbar.c
index fcb4cf9..7e1d3d1 100644
--- a/gtk/gtkprogressbar.c
+++ b/gtk/gtkprogressbar.c
@@ -72,14 +72,15 @@
* |[<!-- language="plain" -->
* progressbar
* ╰── trough
+ * ├── [text]
* ╰── progress[.pulse]
* ]|
*
- * GtkProgressBar has a main CSS node with name progressbar and subnodes
- * with names trough and progress. The progress subnode has the style class
- * .pulse when in activity mode. It gets the style classes .left, .right,
- * .top or .bottom added when the progress 'touches' the corresponding end
- * of the GtkProgressBar.
+ * GtkProgressBar has a main CSS node with name progressbar and subnodes with
+ * names text, trough and progress. The text subnode is only present if text
+ * is shown. The progress subnode has the style class .pulse when in activity
+ * mode. It gets the style classes .left, .right, .top or .bottom added when
+ * the progress 'touches' the corresponding end of the GtkProgressBar.
*/
#define MIN_HORIZONTAL_BAR_WIDTH 150
@@ -93,6 +94,7 @@ struct _GtkProgressBarPrivate
gchar *text;
GtkCssGadget *gadget;
+ GtkCssGadget *text_gadget;
GtkCssGadget *trough;
GtkCssGadget *progress;
@@ -199,6 +201,21 @@ static gboolean gtk_progress_bar_render_trough (GtkCssGadget *gadget,
gint width,
gint height,
gpointer data);
+static void gtk_progress_bar_get_text_size (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,
+ cairo_t *cr,
+ 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)
@@ -637,6 +654,7 @@ gtk_progress_bar_finalize (GObject *object)
g_free (priv->text);
+ g_clear_object (&priv->text_gadget);
g_clear_object (&priv->progress);
g_clear_object (&priv->trough);
g_clear_object (&priv->gadget);
@@ -668,7 +686,7 @@ gtk_progress_bar_get_content_size (GtkCssGadget *gadget,
GtkWidget *widget;
GtkProgressBar *pbar;
GtkProgressBarPrivate *priv;
- gint text_size;
+ gint text_minimum, text_natural;
gint trough_minimum, trough_natural;
widget = gtk_css_gadget_get_owner (gadget);
@@ -676,46 +694,9 @@ gtk_progress_bar_get_content_size (GtkCssGadget *gadget,
priv = pbar->priv;
if (priv->show_text)
- {
- gchar *buf;
- PangoLayout *layout;
- PangoRectangle logical_rect;
-
- buf = get_current_text (pbar);
- layout = gtk_widget_create_pango_layout (widget, buf);
-
- 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_context_get_font_description (context),
- pango_context_get_language (context));
-
- char_width = pango_font_metrics_get_approximate_char_width (metrics);
- pango_font_metrics_unref (metrics);
-
- text_size = PANGO_PIXELS (char_width) * 3;
- }
- else
- text_size = logical_rect.width;
- }
- else
- text_size = logical_rect.height;
-
- g_object_unref (layout);
- g_free (buf);
- }
+ gtk_css_gadget_get_preferred_size (priv->text_gadget, orientation, -1, &text_minimum, &text_natural,
NULL, NULL);
else
- text_size = 0;
+ text_minimum = text_natural = 0;
gtk_css_gadget_get_preferred_size (priv->trough, orientation, -1, &trough_minimum, &trough_natural, NULL,
NULL);
@@ -723,28 +704,85 @@ gtk_progress_bar_get_content_size (GtkCssGadget *gadget,
{
if (priv->orientation == GTK_ORIENTATION_HORIZONTAL)
{
- *minimum = MAX (text_size, trough_minimum);
- *natural = MAX (text_size, trough_natural);
+ *minimum = MAX (text_minimum, trough_minimum);
+ *natural = MAX (text_natural, trough_natural);
}
else
{
- *minimum = text_size + trough_minimum;
- *natural = text_size + trough_natural;
+ *minimum = text_minimum + trough_minimum;
+ *natural = text_natural + trough_natural;
}
}
else
{
if (priv->orientation == GTK_ORIENTATION_HORIZONTAL)
{
- *minimum = text_size + trough_minimum;
- *natural = text_size + trough_natural;
+ *minimum = text_minimum + trough_minimum;
+ *natural = text_natural + trough_natural;
}
else
{
- *minimum = MAX (text_size, trough_minimum);
- *natural = MAX (text_size, trough_natural);
+ *minimum = MAX (text_minimum, trough_minimum);
+ *natural = MAX (text_natural, trough_natural);
+ }
+ }
+}
+
+static void
+gtk_progress_bar_get_text_size (GtkCssGadget *gadget,
+ GtkOrientation orientation,
+ gint for_size,
+ gint *minimum,
+ gint *natural,
+ gint *minimum_baseline,
+ gint *natural_baseline,
+ gpointer data)
+{
+ GtkWidget *widget;
+ GtkProgressBar *pbar;
+ GtkProgressBarPrivate *priv;
+ gchar *buf;
+ PangoLayout *layout;
+ PangoRectangle logical_rect;
+
+ widget = gtk_css_gadget_get_owner (gadget);
+ pbar = GTK_PROGRESS_BAR (widget);
+ priv = pbar->priv;
+
+ buf = get_current_text (pbar);
+ layout = gtk_widget_create_pango_layout (widget, buf);
+
+ 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_context_get_font_description (context),
+ 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 = logical_rect.width;
}
+ else
+ *minimum = *natural = logical_rect.height;
+
+ g_object_unref (layout);
+ g_free (buf);
}
static void
@@ -814,7 +852,9 @@ gtk_progress_bar_allocate_contents (GtkCssGadget *gadget,
GtkWidget *widget;
GtkProgressBarPrivate *priv;
gint bar_width, bar_height;
+ gint text_width, text_height, text_min, text_nat;
GtkAllocation alloc;
+ GtkAllocation text_clip;
widget = gtk_css_gadget_get_owner (gadget);
priv = GTK_PROGRESS_BAR (widget)->priv;
@@ -836,6 +876,33 @@ gtk_progress_bar_allocate_contents (GtkCssGadget *gadget,
alloc.height = bar_height;
gtk_css_gadget_allocate (priv->trough, &alloc, -1, out_clip);
+
+ 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);
+
+ text_width = CLAMP(text_nat, text_min, allocation->width);
+
+ if (priv->orientation == GTK_ORIENTATION_HORIZONTAL)
+ {
+ alloc.x = allocation->x + (allocation->width - text_width) / 2;
+ alloc.y = allocation->y;
+ alloc.width = text_width;
+ alloc.height = text_height;
+ }
+ else
+ {
+ alloc.x = allocation->x + allocation->width - text_width;
+ alloc.y = allocation->y + (allocation->height - text_height) / 2;
+ alloc.width = text_width;
+ alloc.height = text_height;
+ }
+
+ gtk_css_gadget_allocate (priv->text_gadget, &alloc, -1, &text_clip);
+
+ gdk_rectangle_union (out_clip, &text_clip, out_clip);
}
@@ -1058,135 +1125,43 @@ gtk_progress_bar_act_mode_leave (GtkProgressBar *pbar)
update_node_classes (pbar);
}
-static void
-gtk_progress_bar_paint_text (GtkProgressBar *pbar,
- cairo_t *cr,
- gint offset,
- gint amount,
- GtkOrientation orientation,
- gboolean inverted,
- int width,
- int height)
+static gboolean
+gtk_progress_bar_render_text (GtkCssGadget *gadget,
+ cairo_t *cr,
+ gint x,
+ gint y,
+ gint width,
+ gint height,
+ gpointer data)
{
- GtkProgressBarPrivate *priv = pbar->priv;
+ GtkWidget *widget;
+ GtkProgressBar *pbar;
+ GtkProgressBarPrivate *priv;
GtkStyleContext *context;
- GtkBorder padding;
- GtkWidget *widget = GTK_WIDGET (pbar);
- gint x;
- gint y;
gchar *buf;
- GdkRectangle rect;
PangoLayout *layout;
- PangoRectangle logical_rect;
- GdkRectangle prelight_clip, start_clip, end_clip;
+
+ 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_get_padding (context, gtk_style_context_get_state (context), &padding);
+ gtk_style_context_save_to_node (context, gtk_css_gadget_get_node (gadget));
buf = get_current_text (pbar);
-
layout = gtk_widget_create_pango_layout (widget, buf);
pango_layout_set_ellipsize (layout, priv->ellipsize);
if (priv->ellipsize)
pango_layout_set_width (layout, width * PANGO_SCALE);
- pango_layout_get_pixel_extents (layout, NULL, &logical_rect);
-
- if (orientation == GTK_ORIENTATION_HORIZONTAL)
- {
- x = padding.left + (width - padding.left - padding.right - 2 - logical_rect.width) / 2;
- y = padding.top + 1;
- }
- else
- {
- x = padding.left + 1;
- y = padding.top + 1 + (height - padding.top - padding.bottom - 2 - logical_rect.height) / 2;
- }
-
- rect.x = padding.left;
- rect.y = padding.top;
- rect.width = width - padding.left - padding.right;
- rect.height = height - padding.top - padding.bottom;
-
- prelight_clip = start_clip = end_clip = rect;
-
- if (orientation == GTK_ORIENTATION_HORIZONTAL)
- {
- if (!inverted)
- {
- if (offset != -1)
- prelight_clip.x = offset;
- prelight_clip.width = amount;
- start_clip.width = prelight_clip.x - start_clip.x;
- end_clip.x = start_clip.x + start_clip.width + prelight_clip.width;
- end_clip.width -= prelight_clip.width + start_clip.width;
- }
- else
- {
- if (offset != -1)
- prelight_clip.x = offset;
- else
- prelight_clip.x = rect.x + rect.width - amount;
- prelight_clip.width = amount;
- start_clip.width = prelight_clip.x - start_clip.x;
- end_clip.x = start_clip.x + start_clip.width + prelight_clip.width;
- end_clip.width -= prelight_clip.width + start_clip.width;
- }
- }
- else
- {
- if (!inverted)
- {
- if (offset != -1)
- prelight_clip.y = offset;
- prelight_clip.height = amount;
- start_clip.height = prelight_clip.y - start_clip.y;
- end_clip.y = start_clip.y + start_clip.height + prelight_clip.height;
- end_clip.height -= prelight_clip.height + start_clip.height;
- }
- else
- {
- if (offset != -1)
- prelight_clip.y = offset;
- else
- prelight_clip.y = rect.y + rect.height - amount;
- prelight_clip.height = amount;
- start_clip.height = prelight_clip.y - start_clip.y;
- end_clip.y = start_clip.y + start_clip.height + prelight_clip.height;
- end_clip.height -= prelight_clip.height + start_clip.height;
- }
- }
-
- if (start_clip.width > 0 && start_clip.height > 0)
- {
- cairo_save (cr);
- gdk_cairo_rectangle (cr, &start_clip);
- cairo_clip (cr);
-
- gtk_render_layout (context, cr, x, y, layout);
- cairo_restore (cr);
- }
-
- if (end_clip.width > 0 && end_clip.height > 0)
- {
- cairo_save (cr);
- gdk_cairo_rectangle (cr, &end_clip);
- cairo_clip (cr);
-
- gtk_render_layout (context, cr, x, y, layout);
- cairo_restore (cr);
- }
-
- cairo_save (cr);
- gdk_cairo_rectangle (cr, &prelight_clip);
- cairo_clip (cr);
-
gtk_render_layout (context, cr, x, y, layout);
- cairo_restore (cr);
-
g_object_unref (layout);
g_free (buf);
+
+ gtk_style_context_restore (context);
+
+ return FALSE;
}
static gboolean
@@ -1221,23 +1196,14 @@ gtk_progress_bar_render_contents (GtkCssGadget *gadget,
GtkWidget *widget;
GtkProgressBar *pbar;
GtkProgressBarPrivate *priv;
- gboolean inverted;
widget = gtk_css_gadget_get_owner (gadget);
pbar = GTK_PROGRESS_BAR (widget);
priv = pbar->priv;
gtk_css_gadget_draw (priv->trough, cr);
-
- inverted = priv->inverted;
- if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
- {
- if (priv->orientation == GTK_ORIENTATION_HORIZONTAL)
- inverted = !inverted;
- }
-
if (priv->show_text)
- gtk_progress_bar_paint_text (pbar, cr, -1, 0, priv->orientation, inverted, width, height);
+ gtk_css_gadget_draw (priv->text_gadget, cr);
return FALSE;
}
@@ -1395,14 +1361,31 @@ gtk_progress_bar_set_show_text (GtkProgressBar *pbar,
show_text = !!show_text;
- if (priv->show_text != show_text)
- {
- priv->show_text = show_text;
+ if (priv->show_text == show_text)
+ return;
- gtk_widget_queue_resize (GTK_WIDGET (pbar));
+ priv->show_text = show_text;
- g_object_notify_by_pspec (G_OBJECT (pbar), progress_props[PROP_SHOW_TEXT]);
+ if (show_text)
+ {
+ priv->text_gadget = gtk_css_custom_gadget_new ("text",
+ GTK_WIDGET (pbar),
+ priv->gadget,
+ priv->trough,
+ gtk_progress_bar_get_text_size,
+ NULL,
+ gtk_progress_bar_render_text,
+ NULL,
+ NULL);
}
+ else
+ {
+ g_clear_object (&priv->text_gadget);
+ }
+
+ gtk_widget_queue_resize (GTK_WIDGET (pbar));
+
+ g_object_notify_by_pspec (G_OBJECT (pbar), progress_props[PROP_SHOW_TEXT]);
}
/**
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]