]> Pileus Git - ~andy/gtk/blob - gtk/gtkprogressbar.c
c02a9814d5ecb6c77d98c706c1a063c59190566f
[~andy/gtk] / gtk / gtkprogressbar.c
1 /* GTK - The GIMP Toolkit
2  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 /*
21  * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
22  * file for a list of people on the GTK+ Team.  See the ChangeLog
23  * files for a list of changes.  These files are distributed with
24  * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
25  */
26
27 #if HAVE_CONFIG_H
28 #  include <config.h>
29 #  if STDC_HEADERS
30 #    include <string.h>
31 #    include <stdio.h>
32 #  endif
33 #else
34 #  include <stdio.h>
35 #endif
36
37 #include "gtkprogressbar.h"
38 #include "gtksignal.h"
39 #include "gtkintl.h"
40
41
42 #define MIN_HORIZONTAL_BAR_WIDTH   150
43 #define MIN_HORIZONTAL_BAR_HEIGHT  20
44 #define MIN_VERTICAL_BAR_WIDTH     22
45 #define MIN_VERTICAL_BAR_HEIGHT    80
46 #define MAX_TEXT_LENGTH            80
47 #define TEXT_SPACING               2
48
49 enum {
50   PROP_0,
51
52   /* Supported args */
53   PROP_FRACTION,
54   PROP_PULSE_STEP,
55   PROP_ORIENTATION,
56   PROP_TEXT,
57   
58   /* Deprecated args */
59   PROP_ADJUSTMENT,
60   PROP_BAR_STYLE,
61   PROP_ACTIVITY_STEP,
62   PROP_ACTIVITY_BLOCKS,
63   PROP_DISCRETE_BLOCKS
64 };
65
66 static void gtk_progress_bar_class_init    (GtkProgressBarClass *klass);
67 static void gtk_progress_bar_init          (GtkProgressBar      *pbar);
68 static void gtk_progress_bar_set_property  (GObject             *object,
69                                             guint                prop_id,
70                                             const GValue        *value,
71                                             GParamSpec          *pspec);
72 static void gtk_progress_bar_get_property  (GObject             *object,
73                                             guint                prop_id,
74                                             GValue              *value,
75                                             GParamSpec          *pspec);
76 static void gtk_progress_bar_size_request  (GtkWidget           *widget,
77                                             GtkRequisition      *requisition);
78 static void gtk_progress_bar_real_update   (GtkProgress         *progress);
79 static void gtk_progress_bar_paint         (GtkProgress         *progress);
80 static void gtk_progress_bar_act_mode_enter (GtkProgress        *progress);
81
82
83 GtkType
84 gtk_progress_bar_get_type (void)
85 {
86   static GtkType progress_bar_type = 0;
87
88   if (!progress_bar_type)
89     {
90       static const GtkTypeInfo progress_bar_info =
91       {
92         "GtkProgressBar",
93         sizeof (GtkProgressBar),
94         sizeof (GtkProgressBarClass),
95         (GtkClassInitFunc) gtk_progress_bar_class_init,
96         (GtkObjectInitFunc) gtk_progress_bar_init,
97         /* reserved_1 */ NULL,
98         /* reserved_2 */ NULL,
99         (GtkClassInitFunc) NULL
100       };
101
102       progress_bar_type = gtk_type_unique (GTK_TYPE_PROGRESS, &progress_bar_info);
103     }
104
105   return progress_bar_type;
106 }
107
108 static void
109 gtk_progress_bar_class_init (GtkProgressBarClass *class)
110 {
111   GObjectClass *gobject_class;
112   GtkWidgetClass *widget_class;
113   GtkProgressClass *progress_class;
114   
115   gobject_class = G_OBJECT_CLASS (class);
116   widget_class = (GtkWidgetClass *) class;
117   progress_class = (GtkProgressClass *) class;
118
119   gobject_class->set_property = gtk_progress_bar_set_property;
120   gobject_class->get_property = gtk_progress_bar_get_property;
121   
122   widget_class->size_request = gtk_progress_bar_size_request;
123
124   progress_class->paint = gtk_progress_bar_paint;
125   progress_class->update = gtk_progress_bar_real_update;
126   progress_class->act_mode_enter = gtk_progress_bar_act_mode_enter;
127
128   g_object_class_install_property (gobject_class,
129                                    PROP_ADJUSTMENT,
130                                    g_param_spec_object ("adjustment",
131                                                         _("Adjustment"),
132                                                         _("The GtkAdjustment connected to the progress bar (Deprecated)"),
133                                                         GTK_TYPE_ADJUSTMENT,
134                                                         G_PARAM_READWRITE));
135
136   g_object_class_install_property (gobject_class,
137                                    PROP_ORIENTATION,
138                                    g_param_spec_enum ("orientation",
139                                                       _("Orientation"),
140                                                       _("Orientation and growth of the progress bar"),
141                                                       GTK_TYPE_PROGRESS_BAR_ORIENTATION,
142                                                       GTK_PROGRESS_LEFT_TO_RIGHT,
143                                                       G_PARAM_READWRITE));
144
145   g_object_class_install_property (gobject_class,
146                                    PROP_BAR_STYLE,
147                                    g_param_spec_enum ("bar_style",
148                                                       _("Bar style"),
149                                                       _("Specifies the visual style of the bar in percentage mode (Deprecated)"),
150                                                       GTK_TYPE_PROGRESS_BAR_STYLE,
151                                                       GTK_PROGRESS_CONTINUOUS,
152                                                       G_PARAM_READWRITE));
153
154   g_object_class_install_property (gobject_class,
155                                    PROP_ACTIVITY_STEP,
156                                    g_param_spec_uint ("activity_step",
157                                                       _("Activity Step"),
158                                                       _("The increment used for each iteration in activity mode (Deprecated)"),
159                                                       -G_MAXUINT,
160                                                       G_MAXUINT,
161                                                       3,
162                                                       G_PARAM_READWRITE));
163
164   g_object_class_install_property (gobject_class,
165                                    PROP_ACTIVITY_BLOCKS,
166                                    g_param_spec_uint ("activity_blocks",
167                                                       _("Activity Blocks"),
168                                                       _("The number of blocks which can fit in the progress bar area in activity mode (Deprecated)"),
169                                                       2,
170                                                       G_MAXUINT,
171                                                       5,
172                                                       G_PARAM_READWRITE));
173
174   g_object_class_install_property (gobject_class,
175                                    PROP_DISCRETE_BLOCKS,
176                                    g_param_spec_uint ("discrete_blocks",
177                                                       _("Discrete Blocks"),
178                                                       _("The number of discrete blocks in a progress bar (when shown in the discrete style"),
179                                                       2,
180                                                       G_MAXUINT,
181                                                       10,
182                                                       G_PARAM_READWRITE));
183   
184   g_object_class_install_property (gobject_class,
185                                    PROP_FRACTION,
186                                    g_param_spec_double ("fraction",
187                                                         _("Fraction"),
188                                                         _("The fraction of total work that has been completed"),
189                                                         0.0,
190                                                         1.0,
191                                                         0.0,
192                                                         G_PARAM_READWRITE));  
193   
194   g_object_class_install_property (gobject_class,
195                                    PROP_PULSE_STEP,
196                                    g_param_spec_double ("pulse_step",
197                                                         _("Pulse Step"),
198                                                         _("The fraction of total progress to move the bouncing block when pulsed"),
199                                                         0.0,
200                                                         1.0,
201                                                         0.1,
202                                                         G_PARAM_READWRITE));  
203   
204   g_object_class_install_property (gobject_class,
205                                    PROP_TEXT,
206                                    g_param_spec_string ("text",
207                                                         _("Text"),
208                                                         _("Text to be displayed in the progress bar"),
209                                                         "%P %%",
210                                                         G_PARAM_READWRITE));
211
212 }
213
214 static void
215 gtk_progress_bar_init (GtkProgressBar *pbar)
216 {
217   pbar->bar_style = GTK_PROGRESS_CONTINUOUS;
218   pbar->blocks = 10;
219   pbar->in_block = -1;
220   pbar->orientation = GTK_PROGRESS_LEFT_TO_RIGHT;
221   pbar->pulse_fraction = 0.1;
222   pbar->activity_pos = 0;
223   pbar->activity_dir = 1;
224   pbar->activity_step = 3;
225   pbar->activity_blocks = 5;
226 }
227
228 static void
229 gtk_progress_bar_set_property (GObject      *object,
230                                guint         prop_id,
231                                const GValue *value,
232                                GParamSpec   *pspec)
233 {
234   GtkProgressBar *pbar;
235
236   pbar = GTK_PROGRESS_BAR (object);
237
238   switch (prop_id)
239     {
240     case PROP_ADJUSTMENT:
241       gtk_progress_set_adjustment (GTK_PROGRESS (pbar),
242                                    GTK_ADJUSTMENT (g_value_get_object (value)));
243       break;
244     case PROP_ORIENTATION:
245       gtk_progress_bar_set_orientation (pbar, g_value_get_enum (value));
246       break;
247     case PROP_BAR_STYLE:
248       gtk_progress_bar_set_bar_style (pbar, g_value_get_enum (value));
249       break;
250     case PROP_ACTIVITY_STEP:
251       gtk_progress_bar_set_activity_step (pbar, g_value_get_uint (value));
252       break;
253     case PROP_ACTIVITY_BLOCKS:
254       gtk_progress_bar_set_activity_blocks (pbar, g_value_get_uint (value));
255       break;
256     case PROP_DISCRETE_BLOCKS:
257       gtk_progress_bar_set_discrete_blocks (pbar, g_value_get_uint (value));
258       break;
259     case PROP_FRACTION:
260       gtk_progress_bar_set_fraction (pbar, g_value_get_double (value));
261       break;
262     case PROP_PULSE_STEP:
263       gtk_progress_bar_set_pulse_step (pbar, g_value_get_double (value));
264       break;
265     case PROP_TEXT:
266       gtk_progress_bar_set_text (pbar, g_value_get_string (value));
267       break;
268     default:
269       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
270       break;
271     }
272 }
273
274 static void
275 gtk_progress_bar_get_property (GObject      *object,
276                                guint         prop_id,
277                                GValue       *value,
278                                GParamSpec   *pspec)
279 {
280   GtkProgressBar *pbar;
281
282   pbar = GTK_PROGRESS_BAR (object);
283
284   switch (prop_id)
285     {
286     case PROP_ADJUSTMENT:
287       g_value_set_object (value, G_OBJECT (GTK_PROGRESS (pbar)->adjustment));
288       break;
289     case PROP_ORIENTATION:
290       g_value_set_enum (value, pbar->orientation);
291       break;
292     case PROP_BAR_STYLE:
293       g_value_set_enum (value, pbar->bar_style);
294       break;
295     case PROP_ACTIVITY_STEP:
296       g_value_set_uint (value, pbar->activity_step);
297       break;
298     case PROP_ACTIVITY_BLOCKS:
299       g_value_set_uint (value, pbar->activity_blocks);
300       break;
301     case PROP_DISCRETE_BLOCKS:
302       g_value_set_uint (value, pbar->blocks);
303       break;
304     case PROP_FRACTION:
305       g_value_set_double (value, gtk_progress_get_current_percentage (GTK_PROGRESS (pbar)));
306       break;
307     case PROP_PULSE_STEP:
308       g_value_set_double (value, pbar->pulse_fraction);
309       break;
310     case PROP_TEXT:
311       g_value_set_string (value, gtk_progress_bar_get_text (pbar));
312       break;
313     default:
314       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
315       break;
316     }
317 }
318
319 GtkWidget*
320 gtk_progress_bar_new (void)
321 {
322   GtkWidget *pbar;
323
324   pbar = gtk_widget_new (GTK_TYPE_PROGRESS_BAR, NULL);
325
326   return pbar;
327 }
328
329 GtkWidget*
330 gtk_progress_bar_new_with_adjustment (GtkAdjustment *adjustment)
331 {
332   GtkWidget *pbar;
333
334   g_return_val_if_fail (adjustment != NULL, NULL);
335   g_return_val_if_fail (GTK_IS_ADJUSTMENT (adjustment), NULL);
336
337   pbar = gtk_widget_new (GTK_TYPE_PROGRESS_BAR,
338                          "adjustment", adjustment,
339                          NULL);
340
341   return pbar;
342 }
343
344 static void
345 gtk_progress_bar_real_update (GtkProgress *progress)
346 {
347   GtkProgressBar *pbar;
348   GtkWidget *widget;
349
350   g_return_if_fail (progress != NULL);
351   g_return_if_fail (GTK_IS_PROGRESS (progress));
352
353   pbar = GTK_PROGRESS_BAR (progress);
354   widget = GTK_WIDGET (progress);
355  
356   if (pbar->bar_style == GTK_PROGRESS_CONTINUOUS ||
357       GTK_PROGRESS (pbar)->activity_mode)
358     {
359       if (GTK_PROGRESS (pbar)->activity_mode)
360         {
361           guint size;
362           
363           /* advance the block */
364
365           if (pbar->orientation == GTK_PROGRESS_LEFT_TO_RIGHT ||
366               pbar->orientation == GTK_PROGRESS_RIGHT_TO_LEFT)
367             {
368               /* Update our activity step. */
369               
370               pbar->activity_step = widget->allocation.width * pbar->pulse_fraction;
371               
372               size = MAX (2, widget->allocation.width / pbar->activity_blocks);
373
374               if (pbar->activity_dir == 0)
375                 {
376                   pbar->activity_pos += pbar->activity_step;
377                   if (pbar->activity_pos + size >=
378                       widget->allocation.width -
379                       widget->style->xthickness)
380                     {
381                       pbar->activity_pos = widget->allocation.width -
382                         widget->style->xthickness - size;
383                       pbar->activity_dir = 1;
384                     }
385                 }
386               else
387                 {
388                   pbar->activity_pos -= pbar->activity_step;
389                   if (pbar->activity_pos <= widget->style->xthickness)
390                     {
391                       pbar->activity_pos = widget->style->xthickness;
392                       pbar->activity_dir = 0;
393                     }
394                 }
395             }
396           else
397             {
398               /* Update our activity step. */
399               
400               pbar->activity_step = widget->allocation.height * pbar->pulse_fraction;
401               
402               size = MAX (2, widget->allocation.height / pbar->activity_blocks);
403
404               if (pbar->activity_dir == 0)
405                 {
406                   pbar->activity_pos += pbar->activity_step;
407                   if (pbar->activity_pos + size >=
408                       widget->allocation.height -
409                       widget->style->ythickness)
410                     {
411                       pbar->activity_pos = widget->allocation.height -
412                         widget->style->ythickness - size;
413                       pbar->activity_dir = 1;
414                     }
415                 }
416               else
417                 {
418                   pbar->activity_pos -= pbar->activity_step;
419                   if (pbar->activity_pos <= widget->style->ythickness)
420                     {
421                       pbar->activity_pos = widget->style->ythickness;
422                       pbar->activity_dir = 0;
423                     }
424                 }
425             }
426         }
427       gtk_progress_bar_paint (progress);
428       gtk_widget_queue_draw (GTK_WIDGET (progress));
429     }
430   else
431     {
432       gint in_block;
433       
434       in_block = -1 + (gint)(gtk_progress_get_current_percentage (progress) *
435                              (gdouble)pbar->blocks);
436       
437       if (pbar->in_block != in_block)
438         {
439           pbar->in_block = in_block;
440           gtk_progress_bar_paint (progress);
441           gtk_widget_queue_draw (GTK_WIDGET (progress));
442         }
443     }
444 }
445
446 static void
447 gtk_progress_bar_size_request (GtkWidget      *widget,
448                                GtkRequisition *requisition)
449 {
450   GtkProgress *progress;
451   GtkProgressBar *pbar;
452   gchar *buf;
453   PangoRectangle logical_rect;
454   PangoLayout *layout;
455
456   g_return_if_fail (widget != NULL);
457   g_return_if_fail (GTK_IS_PROGRESS_BAR (widget));
458   g_return_if_fail (requisition != NULL);
459
460   progress = GTK_PROGRESS (widget);
461   pbar = GTK_PROGRESS_BAR (widget);
462
463   if (progress->show_text && pbar->bar_style != GTK_PROGRESS_DISCRETE)
464     {
465       buf = gtk_progress_get_text_from_value (progress, progress->adjustment->upper);
466
467       layout = gtk_widget_create_pango_layout (widget, buf);
468       pango_layout_get_pixel_extents (layout, NULL, &logical_rect);
469           
470       g_object_unref (G_OBJECT (layout));
471       g_free (buf);
472     }
473   
474   if (pbar->orientation == GTK_PROGRESS_LEFT_TO_RIGHT ||
475       pbar->orientation == GTK_PROGRESS_RIGHT_TO_LEFT)
476     {
477       if (progress->show_text && pbar->bar_style != GTK_PROGRESS_DISCRETE)
478         {
479           requisition->width = MAX (MIN_HORIZONTAL_BAR_WIDTH,
480                                     2 * widget->style->xthickness + 3 +
481                                     logical_rect.width + 2 * TEXT_SPACING);
482
483           requisition->height = MAX (MIN_HORIZONTAL_BAR_HEIGHT,
484                                      2 * widget->style->ythickness + 3 +
485                                      logical_rect.height + 2 * TEXT_SPACING);
486         }
487       else
488         {
489           requisition->width = MIN_HORIZONTAL_BAR_WIDTH;
490           requisition->height = MIN_HORIZONTAL_BAR_HEIGHT;
491         }
492     }
493   else
494     {
495       if (progress->show_text && pbar->bar_style != GTK_PROGRESS_DISCRETE)
496         {         
497           requisition->width = MAX (MIN_VERTICAL_BAR_WIDTH,
498                                     2 * widget->style->xthickness + 3 +
499                                     logical_rect.width + 2 * TEXT_SPACING);
500
501           requisition->height = MAX (MIN_VERTICAL_BAR_HEIGHT,
502                                      2 * widget->style->ythickness + 3 +
503                                      logical_rect.height + 2 * TEXT_SPACING);
504         }
505       else
506         {
507           requisition->width = MIN_VERTICAL_BAR_WIDTH;
508           requisition->height = MIN_VERTICAL_BAR_HEIGHT;
509         }
510     }
511 }
512
513 static void
514 gtk_progress_bar_act_mode_enter (GtkProgress *progress)
515 {
516   GtkProgressBar *pbar;
517   GtkWidget *widget;
518   gint size;
519
520   pbar = GTK_PROGRESS_BAR (progress);
521   widget = GTK_WIDGET (progress);
522
523   /* calculate start pos */
524
525   if (pbar->orientation == GTK_PROGRESS_LEFT_TO_RIGHT ||
526       pbar->orientation == GTK_PROGRESS_RIGHT_TO_LEFT)
527     {
528       size = MAX (2, widget->allocation.width / pbar->activity_blocks);
529
530       if (pbar->orientation == GTK_PROGRESS_LEFT_TO_RIGHT)
531         {
532           pbar->activity_pos = widget->style->xthickness;
533           pbar->activity_dir = 0;
534         }
535       else
536         {
537           pbar->activity_pos = widget->allocation.width - 
538             widget->style->xthickness - (widget->allocation.height - 
539                 widget->style->ythickness * 2);
540           pbar->activity_dir = 1;
541         }
542     }
543   else
544     {
545       size = MAX (2, widget->allocation.height / pbar->activity_blocks);
546
547       if (pbar->orientation == GTK_PROGRESS_TOP_TO_BOTTOM)
548         {
549           pbar->activity_pos = widget->style->ythickness;
550           pbar->activity_dir = 0;
551         }
552       else
553         {
554           pbar->activity_pos = widget->allocation.height -
555             widget->style->ythickness - (widget->allocation.width - 
556                 widget->style->xthickness * 2);
557           pbar->activity_dir = 1;
558         }
559     }
560 }
561
562 static void
563 gtk_progress_bar_paint (GtkProgress *progress)
564 {
565   GtkProgressBar *pbar;
566   GtkWidget *widget;
567   gint amount;
568   gint block_delta = 0;
569   gint space = 0;
570   gint i;
571   gint x;
572   gint y;
573   gdouble percentage;
574   gint size;
575
576   g_return_if_fail (progress != NULL);
577   g_return_if_fail (GTK_IS_PROGRESS_BAR (progress));
578
579   pbar = GTK_PROGRESS_BAR (progress);
580   widget = GTK_WIDGET (progress);
581
582   if (pbar->orientation == GTK_PROGRESS_LEFT_TO_RIGHT ||
583       pbar->orientation == GTK_PROGRESS_RIGHT_TO_LEFT)
584     space = widget->allocation.width -
585       2 * widget->style->xthickness;
586   else
587     space = widget->allocation.height -
588       2 * widget->style->ythickness;
589
590   percentage = gtk_progress_get_current_percentage (progress);
591
592   if (progress->offscreen_pixmap)
593     {
594       gtk_paint_box (widget->style,
595                      progress->offscreen_pixmap,
596                      GTK_STATE_NORMAL, GTK_SHADOW_IN, 
597                      NULL, widget, "trough",
598                      0, 0,
599                      widget->allocation.width,
600                      widget->allocation.height);
601       
602       if (progress->activity_mode)
603         {
604           if (pbar->orientation == GTK_PROGRESS_LEFT_TO_RIGHT ||
605               pbar->orientation == GTK_PROGRESS_RIGHT_TO_LEFT)
606             {
607               size = MAX (2, widget->allocation.width / pbar->activity_blocks);
608               
609               gtk_paint_box (widget->style,
610                              progress->offscreen_pixmap,
611                              GTK_STATE_PRELIGHT, GTK_SHADOW_OUT,
612                              NULL, widget, "bar",
613                              pbar->activity_pos,
614                              widget->style->ythickness,
615                              size,
616                              widget->allocation.height - widget->style->ythickness * 2);
617               return;
618             }
619           else
620             {
621               size = MAX (2, widget->allocation.height / pbar->activity_blocks);
622               
623               gtk_paint_box (widget->style,
624                              progress->offscreen_pixmap,
625                              GTK_STATE_PRELIGHT, GTK_SHADOW_OUT,
626                              NULL, widget, "bar",
627                              widget->style->xthickness,
628                              pbar->activity_pos,
629                              widget->allocation.width - widget->style->xthickness * 2,
630                              size);
631               return;
632             }
633         }
634       
635       amount = percentage * space;
636       
637       if (amount > 0)
638         {
639           switch (pbar->orientation)
640             {
641               
642             case GTK_PROGRESS_LEFT_TO_RIGHT:
643               
644               if (pbar->bar_style == GTK_PROGRESS_CONTINUOUS)
645                 {
646                   gtk_paint_box (widget->style,
647                                  progress->offscreen_pixmap,
648                                  GTK_STATE_PRELIGHT, GTK_SHADOW_OUT,
649                                  NULL, widget, "bar",
650                                  widget->style->xthickness,
651                                  widget->style->ythickness,
652                                  amount,
653                                  widget->allocation.height - widget->style->ythickness * 2);
654                 }
655               else
656                 {
657                   x = widget->style->xthickness;
658                   
659                   for (i = 0; i <= pbar->in_block; i++)
660                     {
661                       block_delta = (((i + 1) * space) / pbar->blocks)
662                         - ((i * space) / pbar->blocks);
663                       
664                       gtk_paint_box (widget->style,
665                                      progress->offscreen_pixmap,
666                                      GTK_STATE_PRELIGHT, GTK_SHADOW_OUT,
667                                      NULL, widget, "bar",
668                                      x,
669                                      widget->style->ythickness,
670                                      block_delta,
671                                      widget->allocation.height - widget->style->ythickness * 2);
672                       
673                       x +=  block_delta;
674                     }
675                 }
676               break;
677               
678             case GTK_PROGRESS_RIGHT_TO_LEFT:
679               
680               if (pbar->bar_style == GTK_PROGRESS_CONTINUOUS)
681                 {
682                   gtk_paint_box (widget->style,
683                                  progress->offscreen_pixmap,
684                                  GTK_STATE_PRELIGHT, GTK_SHADOW_OUT,
685                                  NULL, widget, "bar",
686                                  widget->allocation.width - 
687                                  widget->style->xthickness - amount,
688                                  widget->style->ythickness,
689                                  amount,
690                                  widget->allocation.height -
691                                  widget->style->ythickness * 2);
692                 }
693               else
694                 {
695                   x = widget->allocation.width - 
696                     widget->style->xthickness;
697                   
698                   for (i = 0; i <= pbar->in_block; i++)
699                     {
700                       block_delta = (((i + 1) * space) / pbar->blocks) -
701                         ((i * space) / pbar->blocks);
702                       
703                       x -=  block_delta;
704                       
705                       gtk_paint_box (widget->style,
706                                      progress->offscreen_pixmap,
707                                      GTK_STATE_PRELIGHT, GTK_SHADOW_OUT,
708                                      NULL, widget, "bar",
709                                      x,
710                                      widget->style->ythickness,
711                                      block_delta,
712                                      widget->allocation.height -
713                                      widget->style->ythickness * 2);
714                     }
715                 }
716               break;
717
718             case GTK_PROGRESS_BOTTOM_TO_TOP:
719
720               if (pbar->bar_style == GTK_PROGRESS_CONTINUOUS)
721                 {
722                   gtk_paint_box (widget->style,
723                                  progress->offscreen_pixmap,
724                                  GTK_STATE_PRELIGHT, GTK_SHADOW_OUT,
725                                  NULL, widget, "bar",
726                                  widget->style->xthickness,
727                                  widget->allocation.height - 
728                                  widget->style->ythickness - amount,
729                                  widget->allocation.width -
730                                  widget->style->xthickness * 2,
731                                  amount);
732                 }
733               else
734                 {
735                   y = widget->allocation.height - 
736                     widget->style->ythickness;
737                   
738                   for (i = 0; i <= pbar->in_block; i++)
739                     {
740                       block_delta = (((i + 1) * space) / pbar->blocks) -
741                         ((i * space) / pbar->blocks);
742                       
743                       y -= block_delta;
744                       
745                       gtk_paint_box (widget->style,
746                                      progress->offscreen_pixmap,
747                                      GTK_STATE_PRELIGHT, GTK_SHADOW_OUT,
748                                      NULL, widget, "bar",
749                                      widget->style->xthickness,
750                                      y,
751                                      widget->allocation.width - 
752                                      widget->style->xthickness * 2,
753                                      block_delta);
754                     }
755                 }
756               break;
757               
758             case GTK_PROGRESS_TOP_TO_BOTTOM:
759               
760               if (pbar->bar_style == GTK_PROGRESS_CONTINUOUS)
761                 {
762                   gtk_paint_box (widget->style,
763                                  progress->offscreen_pixmap,
764                                  GTK_STATE_PRELIGHT, GTK_SHADOW_OUT,
765                                  NULL, widget, "bar",
766                                  widget->style->xthickness,
767                                  widget->style->ythickness,
768                                  widget->allocation.width -
769                                  widget->style->xthickness * 2,
770                                  amount);
771                 }
772               else
773                 {
774                   y = widget->style->ythickness;
775                   
776                   for (i = 0; i <= pbar->in_block; i++)
777                     {
778                       
779                       block_delta = (((i + 1) * space) / pbar->blocks)
780                         - ((i * space) / pbar->blocks);
781                       
782                       gtk_paint_box (widget->style,
783                                      progress->offscreen_pixmap,
784                                      GTK_STATE_PRELIGHT, GTK_SHADOW_OUT,
785                                      NULL, widget, "bar",
786                                      widget->style->xthickness,
787                                      y,
788                                      widget->allocation.width -
789                                      widget->style->xthickness * 2,
790                                      block_delta);
791                       
792                       y += block_delta;
793                     }
794                 }
795               break;
796               
797             default:
798               break;
799             }
800         }
801       
802       if (progress->show_text && pbar->bar_style != GTK_PROGRESS_DISCRETE)
803         {
804           gint x;
805           gint y;
806           gchar *buf;
807           GdkRectangle rect;
808           PangoLayout *layout;
809           PangoRectangle logical_rect;
810
811           buf = gtk_progress_get_current_text (progress);
812
813           layout = gtk_widget_create_pango_layout (widget, buf);
814           pango_layout_get_pixel_extents (layout, NULL, &logical_rect);
815           
816           x = widget->style->xthickness + 1 + 
817             (widget->allocation.width - 2 * widget->style->xthickness -
818              3 - logical_rect.width)
819             * progress->x_align; 
820
821           y = widget->style->ythickness + 1 +
822             (widget->allocation.height - 2 * widget->style->ythickness -
823              3 - logical_rect.height)
824             * progress->y_align;
825
826           rect.x = widget->style->xthickness + 1;
827           rect.y = widget->style->ythickness + 1;
828           rect.width = widget->allocation.width -
829             2 * widget->style->xthickness - 3;
830           rect.height = widget->allocation.height -
831             2 * widget->style->ythickness - 3;
832       
833           gtk_paint_layout (widget->style,
834                             progress->offscreen_pixmap,
835                             GTK_WIDGET_STATE (widget),
836                             FALSE,
837                             &rect,
838                             widget,
839                             "progressbar",
840                             x, y,
841                             layout);
842
843           g_object_unref (G_OBJECT (layout));
844           g_free (buf);
845         }
846     }
847 }
848
849 /*******************************************************************/
850
851 /**
852  * gtk_progress_bar_set_fraction:
853  * @pbar: a #GtkProgressBar
854  * @fraction: fraction of the task that's been completed
855  * 
856  * Causes the progress bar to "fill in" the given fraction
857  * of the bar. The fraction should be between 0.0 and 1.0,
858  * inclusive.
859  * 
860  **/
861 void
862 gtk_progress_bar_set_fraction (GtkProgressBar *pbar,
863                                gdouble         fraction)
864 {
865   g_return_if_fail (pbar != NULL);
866   g_return_if_fail (GTK_IS_PROGRESS_BAR (pbar));
867
868   /* If we know the percentage, we don't want activity mode. */
869   gtk_progress_set_activity_mode (GTK_PROGRESS (pbar), FALSE);
870   
871   /* We use the deprecated GtkProgress interface internally.
872    * Once everything's been deprecated for a good long time,
873    * we can clean up all this code.
874    */
875   gtk_progress_set_percentage (GTK_PROGRESS (pbar), fraction);
876
877   g_object_notify (G_OBJECT (pbar), "fraction");
878 }
879
880 /**
881  * gtk_progress_bar_pulse:
882  * @pbar: a #GtkProgressBar
883  * 
884  * Indicates that some progress is made, but you don't know how much.
885  * Causes the progress bar to enter "activity mode," where a block
886  * bounces back and forth. Each call to gtk_progress_bar_pulse()
887  * causes the block to move by a little bit (the amount of movement
888  * per pulse is determined by gtk_progress_bar_set_pulse_step()).
889  **/
890 void
891 gtk_progress_bar_pulse (GtkProgressBar *pbar)
892 {  
893   g_return_if_fail (pbar != NULL);
894   g_return_if_fail (GTK_IS_PROGRESS_BAR (pbar));
895
896   /* If we don't know the percentage, we must want activity mode. */
897   gtk_progress_set_activity_mode (GTK_PROGRESS (pbar), TRUE);
898
899   /* Sigh. */
900   gtk_progress_bar_real_update (GTK_PROGRESS (pbar));
901 }
902
903 /**
904  * gtk_progress_bar_set_text:
905  * @pbar: a #GtkProgressBar
906  * @text: a UTF-8 string
907  * 
908  * Causes the given @text to appear superimposed on the progress bar.
909  **/
910 void
911 gtk_progress_bar_set_text (GtkProgressBar *pbar,
912                            const gchar    *text)
913 {
914   g_return_if_fail (pbar != NULL);
915   g_return_if_fail (GTK_IS_PROGRESS_BAR (pbar));
916   
917   /* We don't support formats in this interface */
918   GTK_PROGRESS (pbar)->use_text_format = FALSE;
919   
920   if (text && *text)
921     {
922       gtk_progress_set_show_text (GTK_PROGRESS (pbar), TRUE);
923       gtk_progress_set_format_string (GTK_PROGRESS (pbar), text);
924     }
925   else
926     {
927       gtk_progress_set_show_text (GTK_PROGRESS (pbar), FALSE);
928       gtk_progress_set_format_string (GTK_PROGRESS (pbar), "");
929     }
930
931   g_object_notify (G_OBJECT (pbar), "text");
932 }
933
934 /**
935  * gtk_progress_bar_set_pulse_step:
936  * @pbar: a #GtkProgressBar
937  * @fraction: fraction between 0.0 and 1.0
938  * 
939  * Sets the fraction of total progress bar length to move the
940  * bouncing block for each call to gtk_progress_bar_pulse().
941  **/
942 void
943 gtk_progress_bar_set_pulse_step   (GtkProgressBar *pbar,
944                                    gdouble         fraction)
945 {
946   g_return_if_fail (pbar != NULL);
947   g_return_if_fail (GTK_IS_PROGRESS_BAR (pbar));
948   
949   pbar->pulse_fraction = fraction;
950
951   g_object_notify (G_OBJECT (pbar), "pulse_step");
952 }
953
954 void
955 gtk_progress_bar_update (GtkProgressBar *pbar,
956                          gdouble         percentage)
957 {
958   g_return_if_fail (pbar != NULL);
959   g_return_if_fail (GTK_IS_PROGRESS_BAR (pbar));
960
961   /* Use of gtk_progress_bar_update() is deprecated ! 
962    * Use gtk_progress_bar_set_percentage ()
963    */   
964
965   gtk_progress_set_percentage (GTK_PROGRESS (pbar), percentage);
966 }
967
968 /**
969  * gtk_progress_bar_set_orientation:
970  * @pbar: a #GtkProgressBar
971  * @orientation: orientation of the progress bar
972  * 
973  * Causes the progress bar to switch to a different orientation
974  * (left-to-right, right-to-left, top-to-bottom, or bottom-to-top). 
975  **/
976 void
977 gtk_progress_bar_set_orientation (GtkProgressBar           *pbar,
978                                   GtkProgressBarOrientation orientation)
979 {
980   g_return_if_fail (pbar != NULL);
981   g_return_if_fail (GTK_IS_PROGRESS_BAR (pbar));
982
983   if (pbar->orientation != orientation)
984     {
985       pbar->orientation = orientation;
986
987       if (GTK_WIDGET_DRAWABLE (GTK_WIDGET (pbar)))
988         gtk_widget_queue_resize (GTK_WIDGET (pbar));
989
990       g_object_notify (G_OBJECT (pbar), "orientation");
991     }
992 }
993
994 /**
995  * gtk_progress_bar_get_text:
996  * @pbar: a #GtkProgressBar
997  * 
998  * Retrieves the text displayed superimposed on the progress bar,
999  * if any, otherwise %NULL. The return value is a reference
1000  * to the text, not a copy of it, so will become invalid
1001  * if you change the text in the progress bar.
1002  * 
1003  * Return value: text, or %NULL; don't free the string
1004  **/
1005 G_CONST_RETURN gchar*
1006 gtk_progress_bar_get_text (GtkProgressBar *pbar)
1007 {
1008   g_return_val_if_fail (GTK_IS_PROGRESS_BAR (pbar), NULL);
1009
1010   if (GTK_PROGRESS (pbar)->use_text_format)
1011     return NULL;
1012   else
1013     return GTK_PROGRESS (pbar)->format;
1014 }
1015
1016 /**
1017  * gtk_progress_bar_get_fraction:
1018  * @pbar: a #GtkProgressBar
1019  * 
1020  * Returns the current fraction of the task that's been completed.
1021  * 
1022  * Return value: a fraction from 0.0 to 1.0
1023  **/
1024 gdouble
1025 gtk_progress_bar_get_fraction (GtkProgressBar *pbar)
1026 {
1027   g_return_val_if_fail (GTK_IS_PROGRESS_BAR (pbar), 0);
1028
1029   return gtk_progress_get_current_percentage (GTK_PROGRESS (pbar));
1030 }
1031
1032 /**
1033  * gtk_progress_bar_get_pulse_step:
1034  * @pbar: a #GtkProgressBar
1035  * 
1036  * Retrieves the pulse step set with gtk_progress_bar_set_pulse_step()
1037  * 
1038  * Return value: a fraction from 0.0 to 1.0
1039  **/
1040 gdouble
1041 gtk_progress_bar_get_pulse_step (GtkProgressBar *pbar)
1042 {
1043   g_return_val_if_fail (GTK_IS_PROGRESS_BAR (pbar), 0);
1044
1045   return pbar->pulse_fraction;
1046 }
1047
1048 /**
1049  * gtk_progress_bar_get_orientation:
1050  * @pbar: a #GtkProgressBar
1051  * 
1052  * Retrieves the current progress bar orientation.
1053  * 
1054  * Return value: orientation of the progress bar
1055  **/
1056 GtkProgressBarOrientation
1057 gtk_progress_bar_get_orientation (GtkProgressBar *pbar)
1058 {
1059   g_return_val_if_fail (GTK_IS_PROGRESS_BAR (pbar), 0);
1060
1061   return pbar->orientation;
1062 }
1063
1064 void
1065 gtk_progress_bar_set_bar_style (GtkProgressBar     *pbar,
1066                                 GtkProgressBarStyle bar_style)
1067 {
1068   g_return_if_fail (pbar != NULL);
1069   g_return_if_fail (GTK_IS_PROGRESS_BAR (pbar));
1070
1071   if (pbar->bar_style != bar_style)
1072     {
1073       pbar->bar_style = bar_style;
1074
1075       if (GTK_WIDGET_DRAWABLE (GTK_WIDGET (pbar)))
1076         gtk_widget_queue_resize (GTK_WIDGET (pbar));
1077
1078       g_object_notify (G_OBJECT (pbar), "bar_style");
1079     }
1080 }
1081
1082 void
1083 gtk_progress_bar_set_discrete_blocks (GtkProgressBar *pbar,
1084                                       guint           blocks)
1085 {
1086   g_return_if_fail (pbar != NULL);
1087   g_return_if_fail (GTK_IS_PROGRESS_BAR (pbar));
1088   g_return_if_fail (blocks > 1);
1089
1090   if (pbar->blocks != blocks)
1091     {
1092       pbar->blocks = blocks;
1093
1094       if (GTK_WIDGET_DRAWABLE (GTK_WIDGET (pbar)))
1095         gtk_widget_queue_resize (GTK_WIDGET (pbar));
1096
1097       g_object_notify (G_OBJECT (pbar), "discrete_blocks");
1098     }
1099 }
1100
1101 void
1102 gtk_progress_bar_set_activity_step (GtkProgressBar *pbar,
1103                                     guint           step)
1104 {
1105   g_return_if_fail (pbar != NULL);
1106   g_return_if_fail (GTK_IS_PROGRESS_BAR (pbar));
1107
1108   if (pbar->activity_step != step)
1109     {
1110       pbar->activity_step = step;
1111       g_object_notify (G_OBJECT (pbar), "activity_step");
1112     }
1113 }
1114
1115 void
1116 gtk_progress_bar_set_activity_blocks (GtkProgressBar *pbar,
1117                                       guint           blocks)
1118 {
1119   g_return_if_fail (pbar != NULL);
1120   g_return_if_fail (GTK_IS_PROGRESS_BAR (pbar));
1121   g_return_if_fail (blocks > 1);
1122
1123   if (pbar->activity_blocks != blocks)
1124     {
1125       pbar->activity_blocks = blocks;
1126       g_object_notify (G_OBJECT (pbar), "activity_blocks");
1127     }
1128 }