X-Git-Url: http://pileus.org/git/?a=blobdiff_plain;f=gtk%2Fgtkprogressbar.c;h=932980a33e5deb8599becbdabf73bb98e0968d8d;hb=5d011386a69aa59d6eda1e3ef32005efd831c179;hp=500f2d1aac86b384d496e11b595f3aeaf464789f;hpb=0a07e9733bb259598a09515a3e4cdbcda5feef57;p=~andy%2Fgtk diff --git a/gtk/gtkprogressbar.c b/gtk/gtkprogressbar.c index 500f2d1aa..932980a33 100644 --- a/gtk/gtkprogressbar.c +++ b/gtk/gtkprogressbar.c @@ -12,9 +12,7 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. + * License along with this library. If not, see . */ /* @@ -29,59 +27,102 @@ #include #include "gtkprogressbar.h" +#include "gtkorientableprivate.h" #include "gtkprivate.h" #include "gtkintl.h" +#include "a11y/gtkprogressbaraccessible.h" + +/** + * SECTION:gtkprogressbar + * @Short_description: A widget which indicates progress visually + * @Title: GtkProgressBar + * + * The #GtkProgressBar is typically used to display the progress of a long + * running operation. It provides a visual clue that processing + * is underway. The #GtkProgressBar can be used in two different + * modes: percentage mode and activity mode. + * + * When an application can determine how much work needs to take place + * (e.g. read a fixed number of bytes from a file) and can monitor its + * progress, it can use the #GtkProgressBar in percentage mode and the user + * sees a growing bar indicating the percentage of the work that has + * been completed. In this mode, the application is required to call + * gtk_progress_bar_set_fraction() periodically to update the progress bar. + * + * When an application has no accurate way of knowing the amount of work + * to do, it can use the #GtkProgressBar in activity mode, which shows + * activity by a block moving back and forth within the progress area. In + * this mode, the application is required to call gtk_progress_bar_pulse() + * periodically to update the progress bar. + * + * There is quite a bit of flexibility provided to control the appearance + * of the #GtkProgressBar. Functions are provided to control the + * orientation of the bar, optional text can be displayed along with + * the bar, and the step size used in activity mode can be set. + */ #define MIN_HORIZONTAL_BAR_WIDTH 150 #define MIN_HORIZONTAL_BAR_HEIGHT 20 #define MIN_VERTICAL_BAR_WIDTH 22 #define MIN_VERTICAL_BAR_HEIGHT 80 + +struct _GtkProgressBarPrivate +{ + gchar *text; + + gdouble fraction; + gdouble pulse_fraction; + + double activity_pos; + guint activity_blocks; + + GtkOrientation orientation; + + guint activity_dir : 1; + guint activity_mode : 1; + guint ellipsize : 3; + guint show_text : 1; + guint inverted : 1; +}; + enum { PROP_0, PROP_FRACTION, PROP_PULSE_STEP, PROP_ORIENTATION, + PROP_INVERTED, PROP_TEXT, PROP_SHOW_TEXT, PROP_ELLIPSIZE }; -static void gtk_progress_bar_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec); -static void gtk_progress_bar_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec); -static gboolean gtk_progress_bar_expose (GtkWidget *widget, - GdkEventExpose *event); -static void gtk_progress_bar_size_request (GtkWidget *widget, - GtkRequisition *requisition); -static void gtk_progress_bar_size_allocate (GtkWidget *widget, - GtkAllocation *allocation); -static void gtk_progress_bar_style_set (GtkWidget *widget, - GtkStyle *previous); -static void gtk_progress_bar_real_update (GtkProgressBar *progress); -static void gtk_progress_bar_paint (GtkProgressBar *progress); -static void gtk_progress_bar_act_mode_enter (GtkProgressBar *progress); -static void gtk_progress_bar_realize (GtkWidget *widget); -static void gtk_progress_bar_finalize (GObject *object); -static void gtk_progress_bar_create_pixmap (GtkProgressBar *pbar); - - -typedef struct -{ - gchar* text; - gdouble fraction; -} GtkProgressBarPrivate; - -#define GTK_PROGRESS_BAR_GET_PRIVATE(o) \ - (G_TYPE_INSTANCE_GET_PRIVATE ((o), GTK_TYPE_PROGRESS_BAR, GtkProgressBarPrivate)) - -G_DEFINE_TYPE (GtkProgressBar, gtk_progress_bar, GTK_TYPE_WIDGET) +static void gtk_progress_bar_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec); +static void gtk_progress_bar_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec); +static void gtk_progress_bar_get_preferred_width (GtkWidget *widget, + gint *minimum, + gint *natural); +static void gtk_progress_bar_get_preferred_height (GtkWidget *widget, + gint *minimum, + gint *natural); + +static void gtk_progress_bar_real_update (GtkProgressBar *progress); +static gboolean gtk_progress_bar_draw (GtkWidget *widget, + cairo_t *cr); +static void gtk_progress_bar_act_mode_enter (GtkProgressBar *progress); +static void gtk_progress_bar_finalize (GObject *object); +static void gtk_progress_bar_set_orientation (GtkProgressBar *progress, + GtkOrientation orientation); + +G_DEFINE_TYPE_WITH_CODE (GtkProgressBar, gtk_progress_bar, GTK_TYPE_WIDGET, + G_IMPLEMENT_INTERFACE (GTK_TYPE_ORIENTABLE, NULL)) static void gtk_progress_bar_class_init (GtkProgressBarClass *class) @@ -96,24 +137,19 @@ gtk_progress_bar_class_init (GtkProgressBarClass *class) gobject_class->get_property = gtk_progress_bar_get_property; gobject_class->finalize = gtk_progress_bar_finalize; - widget_class->realize = gtk_progress_bar_realize; - widget_class->expose_event = gtk_progress_bar_expose; - widget_class->size_request = gtk_progress_bar_size_request; - widget_class->size_allocate = gtk_progress_bar_size_allocate; - widget_class->style_set = gtk_progress_bar_style_set; + widget_class->draw = gtk_progress_bar_draw; + widget_class->get_preferred_width = gtk_progress_bar_get_preferred_width; + widget_class->get_preferred_height = gtk_progress_bar_get_preferred_height; - class->paint = gtk_progress_bar_paint; - class->update = gtk_progress_bar_real_update; - class->act_mode_enter = gtk_progress_bar_act_mode_enter; + g_object_class_override_property (gobject_class, PROP_ORIENTATION, "orientation"); g_object_class_install_property (gobject_class, - PROP_ORIENTATION, - g_param_spec_enum ("orientation", - P_("Orientation"), - P_("Orientation and growth direction of the progress bar"), - GTK_TYPE_PROGRESS_BAR_ORIENTATION, - GTK_PROGRESS_LEFT_TO_RIGHT, - GTK_PARAM_READWRITE)); + PROP_INVERTED, + g_param_spec_boolean ("inverted", + P_("Inverted"), + P_("Invert the direction in which the progress bar grows"), + FALSE, + GTK_PARAM_READWRITE)); g_object_class_install_property (gobject_class, PROP_FRACTION, @@ -139,6 +175,20 @@ gtk_progress_bar_class_init (GtkProgressBarClass *class) NULL, GTK_PARAM_READWRITE)); + /** + * GtkProgressBar:show-text: + * + * Sets whether the progress bar will show text superimposed + * over the bar. The shown text is either the value of + * the #GtkProgressBar:text property or, if that is %NULL, + * the #GtkProgressBar:fraction value, as a percentage. + * + * To make a progress bar that is styled and sized suitably for containing + * text (even if the actual text is blank), set #GtkProgressBar:show-text to + * %TRUE and #GtkProgressBar:text to the empty string (not %NULL). + * + * Since: 3.0 + */ g_object_class_install_property (gobject_class, PROP_SHOW_TEXT, g_param_spec_boolean ("show-text", @@ -150,14 +200,14 @@ gtk_progress_bar_class_init (GtkProgressBarClass *class) /** * GtkProgressBar:ellipsize: * - * The preferred place to ellipsize the string, if the progressbar does + * The preferred place to ellipsize the string, if the progress bar does * not have enough room to display the entire string, specified as a - * #PangoEllisizeMode. + * #PangoEllipsizeMode. * * Note that setting this property to a value other than - * %PANGO_ELLIPSIZE_NONE has the side-effect that the progressbar requests - * only enough space to display the ellipsis "...". Another means to set a - * progressbar's width is gtk_widget_set_size_request(). + * %PANGO_ELLIPSIZE_NONE has the side-effect that the progress bar requests + * only enough space to display the ellipsis ("..."). Another means to set a + * progress bar's width is gtk_widget_set_size_request(). * * Since: 2.6 */ @@ -172,13 +222,13 @@ gtk_progress_bar_class_init (GtkProgressBarClass *class) GTK_PARAM_READWRITE)); gtk_widget_class_install_style_property (widget_class, g_param_spec_int ("xspacing", - P_("XSpacing"), + P_("X spacing"), P_("Extra spacing applied to the width of a progress bar."), 0, G_MAXINT, 7, G_PARAM_READWRITE)); gtk_widget_class_install_style_property (widget_class, g_param_spec_int ("yspacing", - P_("YSpacing"), + P_("Y spacing"), P_("Extra spacing applied to the height of a progress bar."), 0, G_MAXINT, 7, G_PARAM_READWRITE)); @@ -192,7 +242,7 @@ gtk_progress_bar_class_init (GtkProgressBarClass *class) */ gtk_widget_class_install_style_property (widget_class, g_param_spec_int ("min-horizontal-bar-width", - P_("Min horizontal bar width"), + P_("Minimum horizontal bar width"), P_("The minimum horizontal width of the progress bar"), 1, G_MAXINT, MIN_HORIZONTAL_BAR_WIDTH, G_PARAM_READWRITE)); @@ -205,7 +255,7 @@ gtk_progress_bar_class_init (GtkProgressBarClass *class) */ gtk_widget_class_install_style_property (widget_class, g_param_spec_int ("min-horizontal-bar-height", - P_("Min horizontal bar height"), + P_("Minimum horizontal bar height"), P_("Minimum horizontal height of the progress bar"), 1, G_MAXINT, MIN_HORIZONTAL_BAR_HEIGHT, G_PARAM_READWRITE)); @@ -218,7 +268,7 @@ gtk_progress_bar_class_init (GtkProgressBarClass *class) */ gtk_widget_class_install_style_property (widget_class, g_param_spec_int ("min-vertical-bar-width", - P_("Min vertical bar width"), + P_("Minimum vertical bar width"), P_("The minimum vertical width of the progress bar"), 1, G_MAXINT, MIN_VERTICAL_BAR_WIDTH, G_PARAM_READWRITE)); @@ -231,64 +281,39 @@ gtk_progress_bar_class_init (GtkProgressBarClass *class) */ gtk_widget_class_install_style_property (widget_class, g_param_spec_int ("min-vertical-bar-height", - P_("Min vertical bar height"), + P_("Minimum vertical bar height"), P_("The minimum vertical height of the progress bar"), 1, G_MAXINT, MIN_VERTICAL_BAR_HEIGHT, G_PARAM_READWRITE)); g_type_class_add_private (class, sizeof (GtkProgressBarPrivate)); + + gtk_widget_class_set_accessible_type (widget_class, GTK_TYPE_PROGRESS_BAR_ACCESSIBLE); } static void gtk_progress_bar_init (GtkProgressBar *pbar) { - GtkProgressBarPrivate* priv; + GtkProgressBarPrivate *priv; + + pbar->priv = G_TYPE_INSTANCE_GET_PRIVATE (pbar, + GTK_TYPE_PROGRESS_BAR, + GtkProgressBarPrivate); + priv = pbar->priv; + + priv->orientation = GTK_ORIENTATION_HORIZONTAL; + priv->inverted = FALSE; + priv->pulse_fraction = 0.1; + priv->activity_pos = 0; + priv->activity_dir = 1; + priv->activity_blocks = 5; + priv->ellipsize = PANGO_ELLIPSIZE_NONE; + priv->show_text = FALSE; - pbar->blocks = 10; - pbar->in_block = -1; - pbar->orientation = GTK_PROGRESS_LEFT_TO_RIGHT; - pbar->pulse_fraction = 0.1; - pbar->activity_pos = 0; - pbar->activity_dir = 1; - pbar->activity_step = 3; - pbar->activity_blocks = 5; - pbar->ellipsize = PANGO_ELLIPSIZE_NONE; - pbar->show_text = FALSE; - - /* FIXME: Put priv in the structure once we break ABI */ - priv = GTK_PROGRESS_BAR_GET_PRIVATE (pbar); priv->text = NULL; priv->fraction = 0.0; -} -static void -gtk_progress_bar_realize (GtkWidget *widget) -{ - GdkWindowAttr attributes; - gint attributes_mask; - - gtk_widget_set_realized (widget, TRUE); - - attributes.window_type = GDK_WINDOW_CHILD; - attributes.x = widget->allocation.x; - attributes.y = widget->allocation.y; - attributes.width = widget->allocation.width; - attributes.height = widget->allocation.height; - attributes.wclass = GDK_INPUT_OUTPUT; - attributes.visual = gtk_widget_get_visual (widget); - attributes.colormap = gtk_widget_get_colormap (widget); - attributes.event_mask = gtk_widget_get_events (widget); - attributes.event_mask |= GDK_EXPOSURE_MASK; - - attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP; - widget->window = gdk_window_new (gtk_widget_get_parent_window (widget), - &attributes, attributes_mask); - gdk_window_set_user_data (widget->window, widget); - - widget->style = gtk_style_attach (widget->style, widget->window); - gtk_style_set_background (widget->style, widget->window, GTK_STATE_ACTIVE); - - gtk_progress_bar_create_pixmap (GTK_PROGRESS_BAR (widget)); + gtk_widget_set_has_window (GTK_WIDGET (pbar), FALSE); } static void @@ -306,6 +331,9 @@ gtk_progress_bar_set_property (GObject *object, case PROP_ORIENTATION: gtk_progress_bar_set_orientation (pbar, g_value_get_enum (value)); break; + case PROP_INVERTED: + gtk_progress_bar_set_inverted (pbar, g_value_get_boolean (value)); + break; case PROP_FRACTION: gtk_progress_bar_set_fraction (pbar, g_value_get_double (value)); break; @@ -333,31 +361,31 @@ gtk_progress_bar_get_property (GObject *object, GValue *value, GParamSpec *pspec) { - GtkProgressBar *pbar; - GtkProgressBarPrivate* priv; - - pbar = GTK_PROGRESS_BAR (object); - priv = GTK_PROGRESS_BAR_GET_PRIVATE (pbar); + GtkProgressBar *pbar = GTK_PROGRESS_BAR (object); + GtkProgressBarPrivate* priv = pbar->priv; switch (prop_id) { case PROP_ORIENTATION: - g_value_set_enum (value, pbar->orientation); + g_value_set_enum (value, priv->orientation); + break; + case PROP_INVERTED: + g_value_set_boolean (value, priv->inverted); break; case PROP_FRACTION: g_value_set_double (value, priv->fraction); break; case PROP_PULSE_STEP: - g_value_set_double (value, pbar->pulse_fraction); + g_value_set_double (value, priv->pulse_fraction); break; case PROP_TEXT: g_value_set_string (value, priv->text); break; case PROP_SHOW_TEXT: - g_value_set_boolean (value, pbar->show_text); + g_value_set_boolean (value, priv->show_text); break; case PROP_ELLIPSIZE: - g_value_set_enum (value, pbar->ellipsize); + g_value_set_enum (value, priv->ellipsize); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); @@ -365,6 +393,13 @@ gtk_progress_bar_get_property (GObject *object, } } +/** + * gtk_progress_bar_new: + * + * Creates a new #GtkProgressBar. + * + * Returns: a #GtkProgressBar. + */ GtkWidget* gtk_progress_bar_new (void) { @@ -378,74 +413,36 @@ gtk_progress_bar_new (void) static void gtk_progress_bar_real_update (GtkProgressBar *pbar) { + GtkProgressBarPrivate *priv; GtkWidget *widget; g_return_if_fail (GTK_IS_PROGRESS_BAR (pbar)); + priv = pbar->priv; widget = GTK_WIDGET (pbar); - if (pbar->activity_mode) + if (priv->activity_mode) { - guint size; - /* advance the block */ - if (pbar->orientation == GTK_PROGRESS_LEFT_TO_RIGHT || - pbar->orientation == GTK_PROGRESS_RIGHT_TO_LEFT) + if (priv->activity_dir == 0) { - /* Update our activity step. */ - pbar->activity_step = widget->allocation.width * pbar->pulse_fraction; - - size = MAX (2, widget->allocation.width / pbar->activity_blocks); - - if (pbar->activity_dir == 0) + priv->activity_pos += priv->pulse_fraction; + if (priv->activity_pos > 1.0) { - pbar->activity_pos += pbar->activity_step; - if (pbar->activity_pos + size >= widget->allocation.width - widget->style->xthickness) - { - pbar->activity_pos = widget->allocation.width - - widget->style->xthickness - size; - pbar->activity_dir = 1; - } - } - else - { - pbar->activity_pos -= pbar->activity_step; - if (pbar->activity_pos <= widget->style->xthickness) - { - pbar->activity_pos = widget->style->xthickness; - pbar->activity_dir = 0; - } + priv->activity_pos = 1.0; + priv->activity_dir = 1; } } else { - /* Update our activity step. */ - pbar->activity_step = widget->allocation.height * pbar->pulse_fraction; - - size = MAX (2, widget->allocation.height / pbar->activity_blocks); - - if (pbar->activity_dir == 0) + priv->activity_pos -= priv->pulse_fraction; + if (priv->activity_pos <= 0) { - pbar->activity_pos += pbar->activity_step; - if (pbar->activity_pos + size >= widget->allocation.height - widget->style->ythickness) - { - pbar->activity_pos = widget->allocation.height - - widget->style->ythickness - size; - pbar->activity_dir = 1; - } - } - else - { - pbar->activity_pos -= pbar->activity_step; - if (pbar->activity_pos <= widget->style->ythickness) - { - pbar->activity_pos = widget->style->ythickness; - pbar->activity_dir = 0; - } + priv->activity_pos = 0; + priv->activity_dir = 0; } } } - pbar->dirty = TRUE; gtk_widget_queue_draw (widget); } @@ -453,45 +450,17 @@ static void gtk_progress_bar_finalize (GObject *object) { GtkProgressBar *pbar = GTK_PROGRESS_BAR (object); - GtkProgressBarPrivate *priv = GTK_PROGRESS_BAR_GET_PRIVATE (pbar); - - if (pbar->offscreen_pixmap) - g_object_unref (pbar->offscreen_pixmap); + GtkProgressBarPrivate *priv = pbar->priv; g_free (priv->text); G_OBJECT_CLASS (gtk_progress_bar_parent_class)->finalize (object); } -static gboolean -gtk_progress_bar_expose (GtkWidget *widget, - GdkEventExpose *event) -{ - GtkProgressBar *pbar = GTK_PROGRESS_BAR (widget); - - if (gtk_widget_is_drawable (widget)) - { - if (pbar->dirty) - gtk_progress_bar_paint (pbar); - - gdk_draw_drawable (widget->window, - widget->style->black_gc, - pbar->offscreen_pixmap, - event->area.x, event->area.y, - event->area.x, event->area.y, - event->area.width, - event->area.height); - } - - return FALSE; -} - static gchar * get_current_text (GtkProgressBar *pbar) { - GtkProgressBarPrivate *priv; - - priv = GTK_PROGRESS_BAR_GET_PRIVATE (pbar); + GtkProgressBarPrivate *priv = pbar->priv; if (priv->text) return g_strdup (priv->text); @@ -500,40 +469,45 @@ get_current_text (GtkProgressBar *pbar) } static void -gtk_progress_bar_size_request (GtkWidget *widget, - GtkRequisition *requisition) +gtk_progress_bar_get_preferred_width (GtkWidget *widget, + gint *minimum, + gint *natural) { GtkProgressBar *pbar; GtkProgressBarPrivate *priv; + GtkStyleContext *style_context; + GtkStateFlags state; + GtkBorder padding; gchar *buf; PangoRectangle logical_rect; PangoLayout *layout; - gint width, height; - gint xspacing, yspacing; - gint min_width, min_height; + gint width; + gint xspacing; + gint min_width; g_return_if_fail (GTK_IS_PROGRESS_BAR (widget)); - g_return_if_fail (requisition != NULL); + + style_context = gtk_widget_get_style_context (widget); + state = gtk_widget_get_state_flags (widget); + gtk_style_context_get_padding (style_context, state, &padding); gtk_widget_style_get (widget, "xspacing", &xspacing, - "yspacing", &yspacing, NULL); pbar = GTK_PROGRESS_BAR (widget); - priv = GTK_PROGRESS_BAR_GET_PRIVATE (pbar); + priv = pbar->priv; - width = 2 * widget->style->xthickness + xspacing; - height = 2 * widget->style->ythickness + yspacing; + width = padding.left + padding.right + xspacing; - if (pbar->show_text) + if (priv->show_text) { buf = get_current_text (pbar); layout = gtk_widget_create_pango_layout (widget, buf); pango_layout_get_pixel_extents (layout, NULL, &logical_rect); - if (pbar->ellipsize) + if (priv->ellipsize) { PangoContext *context; PangoFontMetrics *metrics; @@ -541,7 +515,9 @@ gtk_progress_bar_size_request (GtkWidget *widget, /* The minimum size for ellipsized text is ~ 3 chars */ context = pango_layout_get_context (layout); - metrics = pango_context_get_metrics (context, widget->style->font_desc, pango_context_get_language (context)); + 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); @@ -551,247 +527,267 @@ gtk_progress_bar_size_request (GtkWidget *widget, else width += logical_rect.width; - height += logical_rect.height; - g_object_unref (layout); g_free (buf); } - if (pbar->orientation == GTK_PROGRESS_LEFT_TO_RIGHT || - pbar->orientation == GTK_PROGRESS_RIGHT_TO_LEFT) + if (priv->orientation == GTK_ORIENTATION_HORIZONTAL) gtk_widget_style_get (widget, "min-horizontal-bar-width", &min_width, - "min-horizontal-bar-height", &min_height, NULL); else gtk_widget_style_get (widget, "min-vertical-bar-width", &min_width, - "min-vertical-bar-height", &min_height, NULL); - requisition->width = MAX (min_width, width); - requisition->height = MAX (min_height, height); + *minimum = *natural = MAX (min_width, width); } static void -gtk_progress_bar_size_allocate (GtkWidget *widget, - GtkAllocation *allocation) +gtk_progress_bar_get_preferred_height (GtkWidget *widget, + gint *minimum, + gint *natural) { - widget->allocation = *allocation; + GtkProgressBar *pbar; + GtkProgressBarPrivate *priv; + GtkStyleContext *context; + GtkStateFlags state; + GtkBorder padding; + gchar *buf; + PangoRectangle logical_rect; + PangoLayout *layout; + gint height; + gint yspacing; + gint min_height; - if (gtk_widget_get_realized (widget)) - { - gdk_window_move_resize (widget->window, - allocation->x, allocation->y, - allocation->width, allocation->height); + g_return_if_fail (GTK_IS_PROGRESS_BAR (widget)); - gtk_progress_bar_create_pixmap (GTK_PROGRESS_BAR (widget)); - } -} + context = gtk_widget_get_style_context (widget); + state = gtk_widget_get_state_flags (widget); + gtk_style_context_get_padding (context, state, &padding); -static void -gtk_progress_bar_create_pixmap (GtkProgressBar *pbar) -{ - GtkWidget *widget; + gtk_widget_style_get (widget, + "yspacing", &yspacing, + NULL); - widget = GTK_WIDGET (pbar); + pbar = GTK_PROGRESS_BAR (widget); + priv = pbar->priv; - if (gtk_widget_get_realized (widget)) + height = padding.top + padding.bottom + yspacing; + + if (priv->show_text) { - if (pbar->offscreen_pixmap) - g_object_unref (pbar->offscreen_pixmap); - - pbar->offscreen_pixmap = gdk_pixmap_new (widget->window, - widget->allocation.width, - widget->allocation.height, - -1); - - /* clear the pixmap for transparent themes */ - gtk_paint_flat_box (widget->style, - pbar->offscreen_pixmap, - GTK_STATE_NORMAL, - GTK_SHADOW_NONE, - NULL, widget, "trough", 0, 0, -1, -1); - - GTK_PROGRESS_BAR_GET_CLASS (pbar)->paint (pbar); - } -} + buf = get_current_text (pbar); + layout = gtk_widget_create_pango_layout (widget, buf); -static void -gtk_progress_bar_style_set (GtkWidget *widget, - GtkStyle *previous) -{ - GtkProgressBar *pbar = GTK_PROGRESS_BAR (widget); + pango_layout_get_pixel_extents (layout, NULL, &logical_rect); - pbar->dirty = TRUE; + height += logical_rect.height; - GTK_WIDGET_CLASS (gtk_progress_bar_parent_class)->style_set (widget, previous); + g_object_unref (layout); + g_free (buf); + } + + if (priv->orientation == GTK_ORIENTATION_HORIZONTAL) + gtk_widget_style_get (widget, + "min-horizontal-bar-height", &min_height, + NULL); + else + gtk_widget_style_get (widget, + "min-vertical-bar-height", &min_height, + NULL); + + *minimum = *natural = MAX (min_height, height); } static void gtk_progress_bar_act_mode_enter (GtkProgressBar *pbar) { - GtkWidget *widget; - GtkProgressBarOrientation orientation; + GtkProgressBarPrivate *priv = pbar->priv; + GtkStyleContext *context; + GtkStateFlags state; + GtkBorder padding; + GtkWidget *widget = GTK_WIDGET (pbar); + GtkOrientation orientation; + gboolean inverted; - widget = GTK_WIDGET (pbar); + context = gtk_widget_get_style_context (widget); + state = gtk_widget_get_state_flags (widget); + gtk_style_context_get_padding (context, state, &padding); - orientation = pbar->orientation; + orientation = priv->orientation; + inverted = priv->inverted; if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL) { - if (pbar->orientation == GTK_PROGRESS_LEFT_TO_RIGHT) - orientation = GTK_PROGRESS_RIGHT_TO_LEFT; - else if (pbar->orientation == GTK_PROGRESS_RIGHT_TO_LEFT) - orientation = GTK_PROGRESS_LEFT_TO_RIGHT; + if (priv->orientation == GTK_ORIENTATION_HORIZONTAL) + inverted = !inverted; } /* calculate start pos */ - if (orientation == GTK_PROGRESS_LEFT_TO_RIGHT || - orientation == GTK_PROGRESS_RIGHT_TO_LEFT) + if (orientation == GTK_ORIENTATION_HORIZONTAL) { - if (orientation == GTK_PROGRESS_LEFT_TO_RIGHT) + if (!inverted) { - pbar->activity_pos = widget->style->xthickness; - pbar->activity_dir = 0; + priv->activity_pos = 0.0; + priv->activity_dir = 0; } else { - pbar->activity_pos = widget->allocation.width - - widget->style->xthickness - (widget->allocation.height - - widget->style->ythickness * 2); - pbar->activity_dir = 1; + priv->activity_pos = 1.0; + priv->activity_dir = 1; } } else { - if (orientation == GTK_PROGRESS_TOP_TO_BOTTOM) + if (!inverted) { - pbar->activity_pos = widget->style->ythickness; - pbar->activity_dir = 0; + priv->activity_pos = 0.0; + priv->activity_dir = 0; } else { - pbar->activity_pos = widget->allocation.height - - widget->style->ythickness - (widget->allocation.width - - widget->style->xthickness * 2); - pbar->activity_dir = 1; + priv->activity_pos = 1.0; + priv->activity_dir = 1; } } } static void -gtk_progress_bar_get_activity (GtkProgressBar *pbar, - GtkProgressBarOrientation orientation, - gint *offset, - gint *amount) +gtk_progress_bar_get_activity (GtkProgressBar *pbar, + GtkOrientation orientation, + gint *offset, + gint *amount) { + GtkProgressBarPrivate *priv = pbar->priv; GtkWidget *widget = GTK_WIDGET (pbar); + GtkStyleContext *context; + GtkAllocation allocation; + GtkStateFlags state; + GtkBorder padding; + int size; + + context = gtk_widget_get_style_context (widget); + state = gtk_style_context_get_state (context); + gtk_widget_get_allocation (widget, &allocation); + gtk_style_context_get_padding (context, state, &padding); + + if (orientation == GTK_ORIENTATION_HORIZONTAL) + size = allocation.width - padding.left - padding.top; + else + size = allocation.height - padding.left - padding.top; - *offset = pbar->activity_pos; - - switch (orientation) - { - case GTK_PROGRESS_LEFT_TO_RIGHT: - case GTK_PROGRESS_RIGHT_TO_LEFT: - *amount = MAX (2, widget->allocation.width / pbar->activity_blocks); - break; - - case GTK_PROGRESS_TOP_TO_BOTTOM: - case GTK_PROGRESS_BOTTOM_TO_TOP: - *amount = MAX (2, widget->allocation.height / pbar->activity_blocks); - break; - } + *amount = MAX (2, size / priv->activity_blocks); + *offset = priv->activity_pos * (size - *amount); } static void -gtk_progress_bar_paint_activity (GtkProgressBar *pbar, - GtkProgressBarOrientation orientation) +gtk_progress_bar_paint_activity (GtkProgressBar *pbar, + cairo_t *cr, + GtkOrientation orientation, + gboolean inverted, + int width, + int height) { + GtkStyleContext *context; + GtkStateFlags state; + GtkBorder padding; GtkWidget *widget = GTK_WIDGET (pbar); GdkRectangle area; - switch (orientation) + context = gtk_widget_get_style_context (widget); + state = gtk_widget_get_state_flags (widget); + gtk_style_context_get_padding (context, state, &padding); + + if (orientation == GTK_ORIENTATION_HORIZONTAL) { - case GTK_PROGRESS_LEFT_TO_RIGHT: - case GTK_PROGRESS_RIGHT_TO_LEFT: gtk_progress_bar_get_activity (pbar, orientation, &area.x, &area.width); - area.y = widget->style->ythickness; - area.height = widget->allocation.height - 2 * widget->style->ythickness; - break; - - case GTK_PROGRESS_TOP_TO_BOTTOM: - case GTK_PROGRESS_BOTTOM_TO_TOP: + area.y = padding.top; + area.height = height - padding.top - padding.bottom; + } + else + { gtk_progress_bar_get_activity (pbar, orientation, &area.y, &area.height); - area.x = widget->style->xthickness; - area.width = widget->allocation.width - 2 * widget->style->xthickness; - break; - - default: - return; - break; + area.x = padding.left; + area.width = width - padding.left - padding.right; } - gtk_paint_box (widget->style, - pbar->offscreen_pixmap, - GTK_STATE_PRELIGHT, GTK_SHADOW_OUT, - &area, widget, "bar", - area.x, area.y, area.width, area.height); + gtk_style_context_save (context); + gtk_style_context_add_class (context, GTK_STYLE_CLASS_PROGRESSBAR); + gtk_style_context_add_class (context, GTK_STYLE_CLASS_PULSE); + + gtk_render_activity (context, cr, area.x, area.y, area.width, area.height); + + gtk_style_context_restore (context); } static void -gtk_progress_bar_paint_continuous (GtkProgressBar *pbar, - gint amount, - GtkProgressBarOrientation orientation) +gtk_progress_bar_paint_continuous (GtkProgressBar *pbar, + cairo_t *cr, + gint amount, + GtkOrientation orientation, + gboolean inverted, + int width, + int height) { - GdkRectangle area; + GtkStyleContext *context; + GtkStateFlags state; + GtkBorder padding; GtkWidget *widget = GTK_WIDGET (pbar); + GdkRectangle area; if (amount <= 0) return; - switch (orientation) + context = gtk_widget_get_style_context (widget); + state = gtk_widget_get_state_flags (widget); + gtk_style_context_get_padding (context, state, &padding); + + if (orientation == GTK_ORIENTATION_HORIZONTAL) { - case GTK_PROGRESS_LEFT_TO_RIGHT: - case GTK_PROGRESS_RIGHT_TO_LEFT: area.width = amount; - area.height = widget->allocation.height - widget->style->ythickness * 2; - area.y = widget->style->ythickness; + area.height = height - padding.top - padding.bottom; + area.y = padding.top; - area.x = widget->style->xthickness; - if (orientation == GTK_PROGRESS_RIGHT_TO_LEFT) - area.x = widget->allocation.width - amount - area.x; - break; - - case GTK_PROGRESS_TOP_TO_BOTTOM: - case GTK_PROGRESS_BOTTOM_TO_TOP: - area.width = widget->allocation.width - widget->style->xthickness * 2; + if (!inverted) + area.x = padding.left; + else + area.x = width - amount - padding.right; + } + else + { + area.width = width - padding.left - padding.right; area.height = amount; - area.x = widget->style->xthickness; - - area.y = widget->style->ythickness; - if (orientation == GTK_PROGRESS_BOTTOM_TO_TOP) - area.y = widget->allocation.height - amount - area.y; - break; + area.x = padding.left; - default: - return; - break; + if (!inverted) + area.y = padding.top; + else + area.y = height - amount - padding.bottom; } - gtk_paint_box (widget->style, - pbar->offscreen_pixmap, - GTK_STATE_PRELIGHT, GTK_SHADOW_OUT, - &area, widget, "bar", - area.x, area.y, area.width, area.height); + gtk_style_context_save (context); + gtk_style_context_add_class (context, GTK_STYLE_CLASS_PROGRESSBAR); + + gtk_render_activity (context, cr, area.x, area.y, area.width, area.height); + + gtk_style_context_restore (context); } static void -gtk_progress_bar_paint_text (GtkProgressBar *pbar, - gint offset, - gint amount, - GtkProgressBarOrientation orientation) +gtk_progress_bar_paint_text (GtkProgressBar *pbar, + cairo_t *cr, + gint offset, + gint amount, + GtkOrientation orientation, + gboolean inverted, + int width, + int height) { + GtkProgressBarPrivate *priv = pbar->priv; + GtkStyleContext *context; + GtkStateFlags state; + GtkBorder padding; GtkWidget *widget = GTK_WIDGET (pbar); gint x; gint y; @@ -803,192 +799,210 @@ gtk_progress_bar_paint_text (GtkProgressBar *pbar, gfloat text_xalign = 0.5; gfloat text_yalign = 0.5; + context = gtk_widget_get_style_context (widget); + state = gtk_widget_get_state_flags (widget); + gtk_style_context_get_padding (context, state, &padding); + if (gtk_widget_get_direction (widget) != GTK_TEXT_DIR_LTR) text_xalign = 1.0 - text_xalign; buf = get_current_text (pbar); layout = gtk_widget_create_pango_layout (widget, buf); - pango_layout_set_ellipsize (layout, pbar->ellipsize); - if (pbar->ellipsize) - pango_layout_set_width (layout, widget->allocation.width * PANGO_SCALE); + 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); - x = widget->style->xthickness + 1 + text_xalign * - (widget->allocation.width - 2 * widget->style->xthickness - - 2 - logical_rect.width); - - y = widget->style->ythickness + 1 + text_yalign * - (widget->allocation.height - 2 * widget->style->ythickness - - 2 - logical_rect.height); + x = padding.left + 1 + text_xalign * (width - padding.left - padding.right - 2 - logical_rect.width); + y = padding.top + 1 + text_yalign * (height - padding.top - padding.bottom - 2 - logical_rect.height); - rect.x = widget->style->xthickness; - rect.y = widget->style->ythickness; - rect.width = widget->allocation.width - 2 * widget->style->xthickness; - rect.height = widget->allocation.height - 2 * widget->style->ythickness; + 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; - switch (orientation) + if (orientation == GTK_ORIENTATION_HORIZONTAL) { - case GTK_PROGRESS_LEFT_TO_RIGHT: - 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; - break; - - case GTK_PROGRESS_RIGHT_TO_LEFT: - if (offset != -1) - prelight_clip.x = offset; + 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 - 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; - break; - - case GTK_PROGRESS_TOP_TO_BOTTOM: - 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; - break; - - case GTK_PROGRESS_BOTTOM_TO_TOP: - if (offset != -1) - prelight_clip.y = offset; + { + 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 - 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; - break; + { + 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; + } } + gtk_style_context_save (context); + gtk_style_context_add_class (context, GTK_STYLE_CLASS_TROUGH); + if (start_clip.width > 0 && start_clip.height > 0) - gtk_paint_layout (widget->style, - pbar->offscreen_pixmap, - GTK_STATE_NORMAL, - FALSE, - &start_clip, - widget, - "progressbar", - x, y, - layout); + { + 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) - gtk_paint_layout (widget->style, - pbar->offscreen_pixmap, - GTK_STATE_NORMAL, - FALSE, - &end_clip, - widget, - "progressbar", - x, y, - layout); - - gtk_paint_layout (widget->style, - pbar->offscreen_pixmap, - GTK_STATE_PRELIGHT, - FALSE, - &prelight_clip, - widget, - "progressbar", - x, y, - layout); + { + cairo_save (cr); + gdk_cairo_rectangle (cr, &end_clip); + cairo_clip (cr); + + gtk_render_layout (context, cr, x, y, layout); + cairo_restore (cr); + } + + gtk_style_context_restore (context); + + cairo_save (cr); + gdk_cairo_rectangle (cr, &prelight_clip); + cairo_clip (cr); + + gtk_style_context_save (context); + gtk_style_context_add_class (context, GTK_STYLE_CLASS_PROGRESSBAR); + + gtk_render_layout (context, cr, x, y, layout); + + gtk_style_context_restore (context); + cairo_restore (cr); g_object_unref (layout); g_free (buf); } -static void -gtk_progress_bar_paint (GtkProgressBar *pbar) +static gboolean +gtk_progress_bar_draw (GtkWidget *widget, + cairo_t *cr) { - GtkProgressBarPrivate *priv; - GtkWidget *widget; - GtkProgressBarOrientation orientation; - - priv = GTK_PROGRESS_BAR_GET_PRIVATE (pbar); - widget = GTK_WIDGET (pbar); - - orientation = pbar->orientation; + GtkProgressBar *pbar = GTK_PROGRESS_BAR (widget); + GtkProgressBarPrivate *priv = pbar->priv; + GtkOrientation orientation; + gboolean inverted; + GtkStyleContext *context; + GtkStateFlags state; + GtkBorder padding; + int width, height; + + context = gtk_widget_get_style_context (widget); + state = gtk_widget_get_state_flags (widget); + gtk_style_context_get_padding (context, state, &padding); + + orientation = priv->orientation; + inverted = priv->inverted; if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL) { - if (pbar->orientation == GTK_PROGRESS_LEFT_TO_RIGHT) - orientation = GTK_PROGRESS_RIGHT_TO_LEFT; - else if (pbar->orientation == GTK_PROGRESS_RIGHT_TO_LEFT) - orientation = GTK_PROGRESS_LEFT_TO_RIGHT; + if (priv->orientation == GTK_ORIENTATION_HORIZONTAL) + inverted = !inverted; } + width = gtk_widget_get_allocated_width (widget); + height = gtk_widget_get_allocated_height (widget); - if (pbar->offscreen_pixmap) - { - gtk_paint_box (widget->style, - pbar->offscreen_pixmap, - GTK_STATE_NORMAL, GTK_SHADOW_IN, - NULL, widget, "trough", - 0, 0, - widget->allocation.width, - widget->allocation.height); - - if (pbar->activity_mode) - { - gtk_progress_bar_paint_activity (pbar, orientation); + gtk_style_context_save (context); + gtk_style_context_add_class (context, GTK_STYLE_CLASS_TROUGH); - if (pbar->show_text) - { - gint offset; - gint amount; + gtk_render_background (context, cr, 0, 0, width, height); + gtk_render_frame (context, cr, 0, 0, width, height); - gtk_progress_bar_get_activity (pbar, orientation, &offset, &amount); - gtk_progress_bar_paint_text (pbar, offset, amount, orientation); - } - } - else + gtk_style_context_restore (context); + + if (priv->activity_mode) + { + gtk_progress_bar_paint_activity (pbar, cr, + orientation, inverted, + width, height); + + if (priv->show_text) { + gint offset; gint amount; - gint space; - if (orientation == GTK_PROGRESS_LEFT_TO_RIGHT || - orientation == GTK_PROGRESS_RIGHT_TO_LEFT) - space = widget->allocation.width - 2 * widget->style->xthickness; - else - space = widget->allocation.height - 2 * widget->style->ythickness; + gtk_progress_bar_get_activity (pbar, orientation, &offset, &amount); + gtk_progress_bar_paint_text (pbar, cr, + offset, amount, + orientation, inverted, + width, height); + } + } + else + { + gint amount; + gint space; - amount = space * gtk_progress_bar_get_fraction (pbar); + if (orientation == GTK_ORIENTATION_HORIZONTAL) + space = width - padding.left - padding.right; + else + space = height - padding.top - padding.bottom; - gtk_progress_bar_paint_continuous (pbar, amount, orientation); + amount = space * gtk_progress_bar_get_fraction (pbar); - if (pbar->show_text) - gtk_progress_bar_paint_text (pbar, -1, amount, orientation); - } + gtk_progress_bar_paint_continuous (pbar, cr, amount, orientation, inverted, width, height); - pbar->dirty = FALSE; + if (priv->show_text) + gtk_progress_bar_paint_text (pbar, cr, -1, amount, orientation, inverted, width, height); } + + return FALSE; } static void gtk_progress_bar_set_activity_mode (GtkProgressBar *pbar, gboolean activity_mode) { + GtkProgressBarPrivate *priv = pbar->priv; + activity_mode = !!activity_mode; - if (pbar->activity_mode != activity_mode) + if (priv->activity_mode != activity_mode) { - pbar->activity_mode = activity_mode; + priv->activity_mode = activity_mode; - if (pbar->activity_mode) - GTK_PROGRESS_BAR_GET_CLASS (pbar)->act_mode_enter (pbar); + if (priv->activity_mode) + gtk_progress_bar_act_mode_enter (pbar); - if (gtk_widget_is_drawable (GTK_WIDGET (pbar))) - gtk_widget_queue_resize (GTK_WIDGET (pbar)); + gtk_widget_queue_resize (GTK_WIDGET (pbar)); } } @@ -1000,8 +1014,7 @@ gtk_progress_bar_set_activity_mode (GtkProgressBar *pbar, * Causes the progress bar to "fill in" the given fraction * of the bar. The fraction should be between 0.0 and 1.0, * inclusive. - * - **/ + */ void gtk_progress_bar_set_fraction (GtkProgressBar *pbar, gdouble fraction) @@ -1010,8 +1023,9 @@ gtk_progress_bar_set_fraction (GtkProgressBar *pbar, g_return_if_fail (GTK_IS_PROGRESS_BAR (pbar)); - priv = GTK_PROGRESS_BAR_GET_PRIVATE (pbar); - priv->fraction = fraction; + priv = pbar->priv; + + priv->fraction = CLAMP(fraction, 0.0, 1.0); gtk_progress_bar_set_activity_mode (pbar, FALSE); gtk_progress_bar_real_update (pbar); @@ -1022,12 +1036,12 @@ gtk_progress_bar_set_fraction (GtkProgressBar *pbar, * gtk_progress_bar_pulse: * @pbar: a #GtkProgressBar * - * Indicates that some progress is made, but you don't know how much. + * Indicates that some progress has been made, but you don't know how much. * Causes the progress bar to enter "activity mode," where a block * bounces back and forth. Each call to gtk_progress_bar_pulse() * causes the block to move by a little bit (the amount of movement * per pulse is determined by gtk_progress_bar_set_pulse_step()). - **/ + */ void gtk_progress_bar_pulse (GtkProgressBar *pbar) { @@ -1043,7 +1057,15 @@ gtk_progress_bar_pulse (GtkProgressBar *pbar) * @text: (allow-none): a UTF-8 string, or %NULL * * Causes the given @text to appear superimposed on the progress bar. - **/ + * + * If @text is %NULL and #GtkProgressBar:show-text is %TRUE, the current + * value of #GtkProgressBar:fraction will be displayed as a percentage. + * + * If @text is non-%NULL and #GtkProgressBar:show-text is %TRUE, the text will + * be displayed. In this case, it will not display the progress percentage. + * If @text is the empty string, the progress bar will still be styled and sized + * suitably for containing text, as long as #GtkProgressBar:show-text is %TRUE. + */ void gtk_progress_bar_set_text (GtkProgressBar *pbar, const gchar *text) @@ -1052,12 +1074,16 @@ gtk_progress_bar_set_text (GtkProgressBar *pbar, g_return_if_fail (GTK_IS_PROGRESS_BAR (pbar)); - priv = GTK_PROGRESS_BAR_GET_PRIVATE (pbar); + priv = pbar->priv; + + /* Don't notify again if nothing's changed. */ + if (g_strcmp0 (priv->text, text) == 0) + return; + g_free (priv->text); - priv->text = text && *text ? g_strdup (text) : NULL; + priv->text = g_strdup (text); - if (gtk_widget_is_drawable (GTK_WIDGET (pbar))) - gtk_widget_queue_resize (GTK_WIDGET (pbar)); + gtk_widget_queue_resize (GTK_WIDGET (pbar)); g_object_notify (G_OBJECT (pbar), "text"); } @@ -1067,10 +1093,14 @@ gtk_progress_bar_set_text (GtkProgressBar *pbar, * @pbar: a #GtkProgressBar * @show_text: whether to show superimposed text * - * Sets whether the progressbar will show text superimposed + * Sets whether the progress bar will show text superimposed * over the bar. The shown text is either the value of - * the #GtkProgressBar::text property or, if that is %NULL, - * the #GtkProgressBar::fraction value, as a percentage. + * the #GtkProgressBar:text property or, if that is %NULL, + * the #GtkProgressBar:fraction value, as a percentage. + * + * To make a progress bar that is styled and sized suitably for containing + * text (even if the actual text is blank), set #GtkProgressBar:show-text to + * %TRUE and #GtkProgressBar:text to the empty string (not %NULL). * * Since: 3.0 */ @@ -1078,16 +1108,19 @@ void gtk_progress_bar_set_show_text (GtkProgressBar *pbar, gboolean show_text) { + GtkProgressBarPrivate *priv; + g_return_if_fail (GTK_IS_PROGRESS_BAR (pbar)); + priv = pbar->priv; + show_text = !!show_text; - if (pbar->show_text != show_text) + if (priv->show_text != show_text) { - pbar->show_text = show_text; + priv->show_text = show_text; - if (gtk_widget_is_drawable (GTK_WIDGET (pbar))) - gtk_widget_queue_resize (GTK_WIDGET (pbar)); + gtk_widget_queue_resize (GTK_WIDGET (pbar)); g_object_notify (G_OBJECT (pbar), "show-text"); } @@ -1097,7 +1130,7 @@ gtk_progress_bar_set_show_text (GtkProgressBar *pbar, * gtk_progress_bar_get_show_text: * @pbar: a #GtkProgressBar * - * Gets the value of the #GtkProgressBar::show-text property. + * Gets the value of the #GtkProgressBar:show-text property. * See gtk_progress_bar_set_show_text(). * * Returns: %TRUE if text is shown in the progress bar @@ -1109,7 +1142,7 @@ gtk_progress_bar_get_show_text (GtkProgressBar *pbar) { g_return_val_if_fail (GTK_IS_PROGRESS_BAR (pbar), FALSE); - return pbar->show_text; + return pbar->priv->show_text; } /** @@ -1119,40 +1152,62 @@ gtk_progress_bar_get_show_text (GtkProgressBar *pbar) * * Sets the fraction of total progress bar length to move the * bouncing block for each call to gtk_progress_bar_pulse(). - **/ + */ void gtk_progress_bar_set_pulse_step (GtkProgressBar *pbar, gdouble fraction) { + GtkProgressBarPrivate *priv; + g_return_if_fail (GTK_IS_PROGRESS_BAR (pbar)); - pbar->pulse_fraction = fraction; + priv = pbar->priv; + + priv->pulse_fraction = fraction; g_object_notify (G_OBJECT (pbar), "pulse-step"); } +static void +gtk_progress_bar_set_orientation (GtkProgressBar *pbar, + GtkOrientation orientation) +{ + GtkProgressBarPrivate *priv = pbar->priv; + + if (priv->orientation != orientation) + { + priv->orientation = orientation; + _gtk_orientable_set_style_classes (GTK_ORIENTABLE (pbar)); + + gtk_widget_queue_resize (GTK_WIDGET (pbar)); + } +} + /** - * gtk_progress_bar_set_orientation: + * gtk_progress_bar_set_inverted: * @pbar: a #GtkProgressBar - * @orientation: orientation of the progress bar + * @inverted: %TRUE to invert the progress bar * - * Causes the progress bar to switch to a different orientation - * (left-to-right, right-to-left, top-to-bottom, or bottom-to-top). - **/ + * Progress bars normally grow from top to bottom or left to right. + * Inverted progress bars grow in the opposite direction. + */ void -gtk_progress_bar_set_orientation (GtkProgressBar *pbar, - GtkProgressBarOrientation orientation) +gtk_progress_bar_set_inverted (GtkProgressBar *pbar, + gboolean inverted) { + GtkProgressBarPrivate *priv; + g_return_if_fail (GTK_IS_PROGRESS_BAR (pbar)); - if (pbar->orientation != orientation) + priv = pbar->priv; + + if (priv->inverted != inverted) { - pbar->orientation = orientation; + priv->inverted = inverted; - if (gtk_widget_is_drawable (GTK_WIDGET (pbar))) - gtk_widget_queue_resize (GTK_WIDGET (pbar)); + gtk_widget_queue_resize (GTK_WIDGET (pbar)); - g_object_notify (G_OBJECT (pbar), "orientation"); + g_object_notify (G_OBJECT (pbar), "inverted"); } } @@ -1167,16 +1222,13 @@ gtk_progress_bar_set_orientation (GtkProgressBar *pbar, * * Return value: text, or %NULL; this string is owned by the widget * and should not be modified or freed. - **/ -G_CONST_RETURN gchar* + */ +const gchar* gtk_progress_bar_get_text (GtkProgressBar *pbar) { - GtkProgressBarPrivate* priv; - g_return_val_if_fail (GTK_IS_PROGRESS_BAR (pbar), NULL); - priv = GTK_PROGRESS_BAR_GET_PRIVATE (pbar); - return priv->text; + return pbar->priv->text; } /** @@ -1186,48 +1238,45 @@ gtk_progress_bar_get_text (GtkProgressBar *pbar) * Returns the current fraction of the task that's been completed. * * Return value: a fraction from 0.0 to 1.0 - **/ + */ gdouble gtk_progress_bar_get_fraction (GtkProgressBar *pbar) { - GtkProgressBarPrivate* priv; - g_return_val_if_fail (GTK_IS_PROGRESS_BAR (pbar), 0); - priv = GTK_PROGRESS_BAR_GET_PRIVATE (pbar); - return priv->fraction; + return pbar->priv->fraction; } /** * gtk_progress_bar_get_pulse_step: * @pbar: a #GtkProgressBar * - * Retrieves the pulse step set with gtk_progress_bar_set_pulse_step() + * Retrieves the pulse step set with gtk_progress_bar_set_pulse_step(). * * Return value: a fraction from 0.0 to 1.0 - **/ + */ gdouble gtk_progress_bar_get_pulse_step (GtkProgressBar *pbar) { g_return_val_if_fail (GTK_IS_PROGRESS_BAR (pbar), 0); - return pbar->pulse_fraction; + return pbar->priv->pulse_fraction; } /** - * gtk_progress_bar_get_orientation: + * gtk_progress_bar_get_inverted: * @pbar: a #GtkProgressBar * - * Retrieves the current progress bar orientation. + * Gets the value set by gtk_progress_bar_set_inverted(). * - * Return value: orientation of the progress bar - **/ -GtkProgressBarOrientation -gtk_progress_bar_get_orientation (GtkProgressBar *pbar) + * Return value: %TRUE if the progress bar is inverted + */ +gboolean +gtk_progress_bar_get_inverted (GtkProgressBar *pbar) { - g_return_val_if_fail (GTK_IS_PROGRESS_BAR (pbar), 0); + g_return_val_if_fail (GTK_IS_PROGRESS_BAR (pbar), FALSE); - return pbar->orientation; + return pbar->priv->inverted; } /** @@ -1239,18 +1288,22 @@ gtk_progress_bar_get_orientation (GtkProgressBar *pbar) * if there is not enough space to render the entire string. * * Since: 2.6 - **/ + */ void gtk_progress_bar_set_ellipsize (GtkProgressBar *pbar, PangoEllipsizeMode mode) { + GtkProgressBarPrivate *priv; + g_return_if_fail (GTK_IS_PROGRESS_BAR (pbar)); g_return_if_fail (mode >= PANGO_ELLIPSIZE_NONE && mode <= PANGO_ELLIPSIZE_END); - if ((PangoEllipsizeMode)pbar->ellipsize != mode) + priv = pbar->priv; + + if ((PangoEllipsizeMode)priv->ellipsize != mode) { - pbar->ellipsize = mode; + priv->ellipsize = mode; g_object_notify (G_OBJECT (pbar), "ellipsize"); gtk_widget_queue_resize (GTK_WIDGET (pbar)); @@ -1261,17 +1314,17 @@ gtk_progress_bar_set_ellipsize (GtkProgressBar *pbar, * gtk_progress_bar_get_ellipsize: * @pbar: a #GtkProgressBar * - * Returns the ellipsizing position of the progressbar. + * Returns the ellipsizing position of the progress bar. * See gtk_progress_bar_set_ellipsize(). * * Return value: #PangoEllipsizeMode * * Since: 2.6 - **/ + */ PangoEllipsizeMode gtk_progress_bar_get_ellipsize (GtkProgressBar *pbar) { g_return_val_if_fail (GTK_IS_PROGRESS_BAR (pbar), PANGO_ELLIPSIZE_NONE); - return pbar->ellipsize; + return pbar->priv->ellipsize; }