]> Pileus Git - ~andy/gtk/blob - gtk/gtkprogressbar.c
Mark abstract types as G_TYPE_FLAG_ABSTRACT. (#72383)
[~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 direction 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, 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 (GTK_IS_ADJUSTMENT (adjustment), NULL);
335
336   pbar = gtk_widget_new (GTK_TYPE_PROGRESS_BAR,
337                          "adjustment", adjustment,
338                          NULL);
339
340   return pbar;
341 }
342
343 static void
344 gtk_progress_bar_real_update (GtkProgress *progress)
345 {
346   GtkProgressBar *pbar;
347   GtkWidget *widget;
348
349   g_return_if_fail (GTK_IS_PROGRESS (progress));
350
351   pbar = GTK_PROGRESS_BAR (progress);
352   widget = GTK_WIDGET (progress);
353  
354   if (pbar->bar_style == GTK_PROGRESS_CONTINUOUS ||
355       GTK_PROGRESS (pbar)->activity_mode)
356     {
357       if (GTK_PROGRESS (pbar)->activity_mode)
358         {
359           guint size;
360           
361           /* advance the block */
362
363           if (pbar->orientation == GTK_PROGRESS_LEFT_TO_RIGHT ||
364               pbar->orientation == GTK_PROGRESS_RIGHT_TO_LEFT)
365             {
366               /* Update our activity step. */
367               
368               pbar->activity_step = widget->allocation.width * pbar->pulse_fraction;
369               
370               size = MAX (2, widget->allocation.width / pbar->activity_blocks);
371
372               if (pbar->activity_dir == 0)
373                 {
374                   pbar->activity_pos += pbar->activity_step;
375                   if (pbar->activity_pos + size >=
376                       widget->allocation.width -
377                       widget->style->xthickness)
378                     {
379                       pbar->activity_pos = widget->allocation.width -
380                         widget->style->xthickness - size;
381                       pbar->activity_dir = 1;
382                     }
383                 }
384               else
385                 {
386                   pbar->activity_pos -= pbar->activity_step;
387                   if (pbar->activity_pos <= widget->style->xthickness)
388                     {
389                       pbar->activity_pos = widget->style->xthickness;
390                       pbar->activity_dir = 0;
391                     }
392                 }
393             }
394           else
395             {
396               /* Update our activity step. */
397               
398               pbar->activity_step = widget->allocation.height * pbar->pulse_fraction;
399               
400               size = MAX (2, widget->allocation.height / pbar->activity_blocks);
401
402               if (pbar->activity_dir == 0)
403                 {
404                   pbar->activity_pos += pbar->activity_step;
405                   if (pbar->activity_pos + size >=
406                       widget->allocation.height -
407                       widget->style->ythickness)
408                     {
409                       pbar->activity_pos = widget->allocation.height -
410                         widget->style->ythickness - size;
411                       pbar->activity_dir = 1;
412                     }
413                 }
414               else
415                 {
416                   pbar->activity_pos -= pbar->activity_step;
417                   if (pbar->activity_pos <= widget->style->ythickness)
418                     {
419                       pbar->activity_pos = widget->style->ythickness;
420                       pbar->activity_dir = 0;
421                     }
422                 }
423             }
424         }
425       gtk_progress_bar_paint (progress);
426       gtk_widget_queue_draw (GTK_WIDGET (progress));
427     }
428   else
429     {
430       gint in_block;
431       
432       in_block = -1 + (gint)(gtk_progress_get_current_percentage (progress) *
433                              (gdouble)pbar->blocks);
434       
435       if (pbar->in_block != in_block)
436         {
437           pbar->in_block = in_block;
438           gtk_progress_bar_paint (progress);
439           gtk_widget_queue_draw (GTK_WIDGET (progress));
440         }
441     }
442 }
443
444 static void
445 gtk_progress_bar_size_request (GtkWidget      *widget,
446                                GtkRequisition *requisition)
447 {
448   GtkProgress *progress;
449   GtkProgressBar *pbar;
450   gchar *buf;
451   PangoRectangle logical_rect;
452   PangoLayout *layout;
453
454   g_return_if_fail (GTK_IS_PROGRESS_BAR (widget));
455   g_return_if_fail (requisition != NULL);
456
457   progress = GTK_PROGRESS (widget);
458   pbar = GTK_PROGRESS_BAR (widget);
459
460   if (progress->show_text && pbar->bar_style != GTK_PROGRESS_DISCRETE)
461     {
462       if (!progress->adjustment)
463         gtk_progress_set_adjustment (progress, NULL);
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 (GTK_IS_PROGRESS_BAR (progress));
577
578   pbar = GTK_PROGRESS_BAR (progress);
579   widget = GTK_WIDGET (progress);
580
581   if (pbar->orientation == GTK_PROGRESS_LEFT_TO_RIGHT ||
582       pbar->orientation == GTK_PROGRESS_RIGHT_TO_LEFT)
583     space = widget->allocation.width -
584       2 * widget->style->xthickness;
585   else
586     space = widget->allocation.height -
587       2 * widget->style->ythickness;
588
589   percentage = gtk_progress_get_current_percentage (progress);
590
591   if (progress->offscreen_pixmap)
592     {
593       gtk_paint_box (widget->style,
594                      progress->offscreen_pixmap,
595                      GTK_STATE_NORMAL, GTK_SHADOW_IN, 
596                      NULL, widget, "trough",
597                      0, 0,
598                      widget->allocation.width,
599                      widget->allocation.height);
600       
601       if (progress->activity_mode)
602         {
603           if (pbar->orientation == GTK_PROGRESS_LEFT_TO_RIGHT ||
604               pbar->orientation == GTK_PROGRESS_RIGHT_TO_LEFT)
605             {
606               size = MAX (2, widget->allocation.width / pbar->activity_blocks);
607               
608               gtk_paint_box (widget->style,
609                              progress->offscreen_pixmap,
610                              GTK_STATE_PRELIGHT, GTK_SHADOW_OUT,
611                              NULL, widget, "bar",
612                              pbar->activity_pos,
613                              widget->style->ythickness,
614                              size,
615                              widget->allocation.height - widget->style->ythickness * 2);
616               return;
617             }
618           else
619             {
620               size = MAX (2, widget->allocation.height / pbar->activity_blocks);
621               
622               gtk_paint_box (widget->style,
623                              progress->offscreen_pixmap,
624                              GTK_STATE_PRELIGHT, GTK_SHADOW_OUT,
625                              NULL, widget, "bar",
626                              widget->style->xthickness,
627                              pbar->activity_pos,
628                              widget->allocation.width - widget->style->xthickness * 2,
629                              size);
630               return;
631             }
632         }
633       
634       amount = percentage * space;
635       
636       if (amount > 0)
637         {
638           switch (pbar->orientation)
639             {
640               
641             case GTK_PROGRESS_LEFT_TO_RIGHT:
642               
643               if (pbar->bar_style == GTK_PROGRESS_CONTINUOUS)
644                 {
645                   gtk_paint_box (widget->style,
646                                  progress->offscreen_pixmap,
647                                  GTK_STATE_PRELIGHT, GTK_SHADOW_OUT,
648                                  NULL, widget, "bar",
649                                  widget->style->xthickness,
650                                  widget->style->ythickness,
651                                  amount,
652                                  widget->allocation.height - widget->style->ythickness * 2);
653                 }
654               else
655                 {
656                   x = widget->style->xthickness;
657                   
658                   for (i = 0; i <= pbar->in_block; i++)
659                     {
660                       block_delta = (((i + 1) * space) / pbar->blocks)
661                         - ((i * space) / pbar->blocks);
662                       
663                       gtk_paint_box (widget->style,
664                                      progress->offscreen_pixmap,
665                                      GTK_STATE_PRELIGHT, GTK_SHADOW_OUT,
666                                      NULL, widget, "bar",
667                                      x,
668                                      widget->style->ythickness,
669                                      block_delta,
670                                      widget->allocation.height - widget->style->ythickness * 2);
671                       
672                       x +=  block_delta;
673                     }
674                 }
675               break;
676               
677             case GTK_PROGRESS_RIGHT_TO_LEFT:
678               
679               if (pbar->bar_style == GTK_PROGRESS_CONTINUOUS)
680                 {
681                   gtk_paint_box (widget->style,
682                                  progress->offscreen_pixmap,
683                                  GTK_STATE_PRELIGHT, GTK_SHADOW_OUT,
684                                  NULL, widget, "bar",
685                                  widget->allocation.width - 
686                                  widget->style->xthickness - amount,
687                                  widget->style->ythickness,
688                                  amount,
689                                  widget->allocation.height -
690                                  widget->style->ythickness * 2);
691                 }
692               else
693                 {
694                   x = widget->allocation.width - 
695                     widget->style->xthickness;
696                   
697                   for (i = 0; i <= pbar->in_block; i++)
698                     {
699                       block_delta = (((i + 1) * space) / pbar->blocks) -
700                         ((i * space) / pbar->blocks);
701                       
702                       x -=  block_delta;
703                       
704                       gtk_paint_box (widget->style,
705                                      progress->offscreen_pixmap,
706                                      GTK_STATE_PRELIGHT, GTK_SHADOW_OUT,
707                                      NULL, widget, "bar",
708                                      x,
709                                      widget->style->ythickness,
710                                      block_delta,
711                                      widget->allocation.height -
712                                      widget->style->ythickness * 2);
713                     }
714                 }
715               break;
716
717             case GTK_PROGRESS_BOTTOM_TO_TOP:
718
719               if (pbar->bar_style == GTK_PROGRESS_CONTINUOUS)
720                 {
721                   gtk_paint_box (widget->style,
722                                  progress->offscreen_pixmap,
723                                  GTK_STATE_PRELIGHT, GTK_SHADOW_OUT,
724                                  NULL, widget, "bar",
725                                  widget->style->xthickness,
726                                  widget->allocation.height - 
727                                  widget->style->ythickness - amount,
728                                  widget->allocation.width -
729                                  widget->style->xthickness * 2,
730                                  amount);
731                 }
732               else
733                 {
734                   y = widget->allocation.height - 
735                     widget->style->ythickness;
736                   
737                   for (i = 0; i <= pbar->in_block; i++)
738                     {
739                       block_delta = (((i + 1) * space) / pbar->blocks) -
740                         ((i * space) / pbar->blocks);
741                       
742                       y -= block_delta;
743                       
744                       gtk_paint_box (widget->style,
745                                      progress->offscreen_pixmap,
746                                      GTK_STATE_PRELIGHT, GTK_SHADOW_OUT,
747                                      NULL, widget, "bar",
748                                      widget->style->xthickness,
749                                      y,
750                                      widget->allocation.width - 
751                                      widget->style->xthickness * 2,
752                                      block_delta);
753                     }
754                 }
755               break;
756               
757             case GTK_PROGRESS_TOP_TO_BOTTOM:
758               
759               if (pbar->bar_style == GTK_PROGRESS_CONTINUOUS)
760                 {
761                   gtk_paint_box (widget->style,
762                                  progress->offscreen_pixmap,
763                                  GTK_STATE_PRELIGHT, GTK_SHADOW_OUT,
764                                  NULL, widget, "bar",
765                                  widget->style->xthickness,
766                                  widget->style->ythickness,
767                                  widget->allocation.width -
768                                  widget->style->xthickness * 2,
769                                  amount);
770                 }
771               else
772                 {
773                   y = widget->style->ythickness;
774                   
775                   for (i = 0; i <= pbar->in_block; i++)
776                     {
777                       
778                       block_delta = (((i + 1) * space) / pbar->blocks)
779                         - ((i * space) / pbar->blocks);
780                       
781                       gtk_paint_box (widget->style,
782                                      progress->offscreen_pixmap,
783                                      GTK_STATE_PRELIGHT, GTK_SHADOW_OUT,
784                                      NULL, widget, "bar",
785                                      widget->style->xthickness,
786                                      y,
787                                      widget->allocation.width -
788                                      widget->style->xthickness * 2,
789                                      block_delta);
790                       
791                       y += block_delta;
792                     }
793                 }
794               break;
795               
796             default:
797               break;
798             }
799         }
800       
801       if (progress->show_text && pbar->bar_style != GTK_PROGRESS_DISCRETE)
802         {
803           gint x;
804           gint y;
805           gchar *buf;
806           GdkRectangle rect;
807           PangoLayout *layout;
808           PangoRectangle logical_rect;
809
810           buf = gtk_progress_get_current_text (progress);
811
812           layout = gtk_widget_create_pango_layout (widget, buf);
813           pango_layout_get_pixel_extents (layout, NULL, &logical_rect);
814           
815           x = widget->style->xthickness + 1 + 
816             (widget->allocation.width - 2 * widget->style->xthickness -
817              3 - logical_rect.width)
818             * progress->x_align; 
819
820           y = widget->style->ythickness + 1 +
821             (widget->allocation.height - 2 * widget->style->ythickness -
822              3 - logical_rect.height)
823             * progress->y_align;
824
825           rect.x = widget->style->xthickness + 1;
826           rect.y = widget->style->ythickness + 1;
827           rect.width = widget->allocation.width -
828             2 * widget->style->xthickness - 3;
829           rect.height = widget->allocation.height -
830             2 * widget->style->ythickness - 3;
831       
832           gtk_paint_layout (widget->style,
833                             progress->offscreen_pixmap,
834                             GTK_WIDGET_STATE (widget),
835                             FALSE,
836                             &rect,
837                             widget,
838                             "progressbar",
839                             x, y,
840                             layout);
841
842           g_object_unref (G_OBJECT (layout));
843           g_free (buf);
844         }
845     }
846 }
847
848 /*******************************************************************/
849
850 /**
851  * gtk_progress_bar_set_fraction:
852  * @pbar: a #GtkProgressBar
853  * @fraction: fraction of the task that's been completed
854  * 
855  * Causes the progress bar to "fill in" the given fraction
856  * of the bar. The fraction should be between 0.0 and 1.0,
857  * inclusive.
858  * 
859  **/
860 void
861 gtk_progress_bar_set_fraction (GtkProgressBar *pbar,
862                                gdouble         fraction)
863 {
864   g_return_if_fail (GTK_IS_PROGRESS_BAR (pbar));
865
866   /* If we know the percentage, we don't want activity mode. */
867   gtk_progress_set_activity_mode (GTK_PROGRESS (pbar), FALSE);
868   
869   /* We use the deprecated GtkProgress interface internally.
870    * Once everything's been deprecated for a good long time,
871    * we can clean up all this code.
872    */
873   gtk_progress_set_percentage (GTK_PROGRESS (pbar), fraction);
874
875   g_object_notify (G_OBJECT (pbar), "fraction");
876 }
877
878 /**
879  * gtk_progress_bar_pulse:
880  * @pbar: a #GtkProgressBar
881  * 
882  * Indicates that some progress is made, but you don't know how much.
883  * Causes the progress bar to enter "activity mode," where a block
884  * bounces back and forth. Each call to gtk_progress_bar_pulse()
885  * causes the block to move by a little bit (the amount of movement
886  * per pulse is determined by gtk_progress_bar_set_pulse_step()).
887  **/
888 void
889 gtk_progress_bar_pulse (GtkProgressBar *pbar)
890 {  
891   g_return_if_fail (GTK_IS_PROGRESS_BAR (pbar));
892
893   /* If we don't know the percentage, we must want activity mode. */
894   gtk_progress_set_activity_mode (GTK_PROGRESS (pbar), TRUE);
895
896   /* Sigh. */
897   gtk_progress_bar_real_update (GTK_PROGRESS (pbar));
898 }
899
900 /**
901  * gtk_progress_bar_set_text:
902  * @pbar: a #GtkProgressBar
903  * @text: a UTF-8 string
904  * 
905  * Causes the given @text to appear superimposed on the progress bar.
906  **/
907 void
908 gtk_progress_bar_set_text (GtkProgressBar *pbar,
909                            const gchar    *text)
910 {
911   g_return_if_fail (GTK_IS_PROGRESS_BAR (pbar));
912   
913   if (text && *text)
914     {
915       gtk_progress_set_show_text (GTK_PROGRESS (pbar), TRUE);
916       gtk_progress_set_format_string (GTK_PROGRESS (pbar), text);
917     }
918   else
919     {
920       gtk_progress_set_show_text (GTK_PROGRESS (pbar), FALSE);
921       gtk_progress_set_format_string (GTK_PROGRESS (pbar), "");
922     }
923
924   /* We don't support formats in this interface */
925   GTK_PROGRESS (pbar)->use_text_format = FALSE;
926   
927   g_object_notify (G_OBJECT (pbar), "text");
928 }
929
930 /**
931  * gtk_progress_bar_set_pulse_step:
932  * @pbar: a #GtkProgressBar
933  * @fraction: fraction between 0.0 and 1.0
934  * 
935  * Sets the fraction of total progress bar length to move the
936  * bouncing block for each call to gtk_progress_bar_pulse().
937  **/
938 void
939 gtk_progress_bar_set_pulse_step   (GtkProgressBar *pbar,
940                                    gdouble         fraction)
941 {
942   g_return_if_fail (GTK_IS_PROGRESS_BAR (pbar));
943   
944   pbar->pulse_fraction = fraction;
945
946   g_object_notify (G_OBJECT (pbar), "pulse_step");
947 }
948
949 void
950 gtk_progress_bar_update (GtkProgressBar *pbar,
951                          gdouble         percentage)
952 {
953   g_return_if_fail (GTK_IS_PROGRESS_BAR (pbar));
954
955   /* Use of gtk_progress_bar_update() is deprecated ! 
956    * Use gtk_progress_bar_set_percentage ()
957    */   
958
959   gtk_progress_set_percentage (GTK_PROGRESS (pbar), percentage);
960 }
961
962 /**
963  * gtk_progress_bar_set_orientation:
964  * @pbar: a #GtkProgressBar
965  * @orientation: orientation of the progress bar
966  * 
967  * Causes the progress bar to switch to a different orientation
968  * (left-to-right, right-to-left, top-to-bottom, or bottom-to-top). 
969  **/
970 void
971 gtk_progress_bar_set_orientation (GtkProgressBar           *pbar,
972                                   GtkProgressBarOrientation orientation)
973 {
974   g_return_if_fail (GTK_IS_PROGRESS_BAR (pbar));
975
976   if (pbar->orientation != orientation)
977     {
978       pbar->orientation = orientation;
979
980       if (GTK_WIDGET_DRAWABLE (GTK_WIDGET (pbar)))
981         gtk_widget_queue_resize (GTK_WIDGET (pbar));
982
983       g_object_notify (G_OBJECT (pbar), "orientation");
984     }
985 }
986
987 /**
988  * gtk_progress_bar_get_text:
989  * @pbar: a #GtkProgressBar
990  * 
991  * Retrieves the text displayed superimposed on the progress bar,
992  * if any, otherwise %NULL. The return value is a reference
993  * to the text, not a copy of it, so will become invalid
994  * if you change the text in the progress bar.
995  * 
996  * Return value: text, or %NULL; this string is owned by the widget
997  * and should not be modified or freed.
998  **/
999 G_CONST_RETURN gchar*
1000 gtk_progress_bar_get_text (GtkProgressBar *pbar)
1001 {
1002   g_return_val_if_fail (GTK_IS_PROGRESS_BAR (pbar), NULL);
1003
1004   if (GTK_PROGRESS (pbar)->use_text_format)
1005     return NULL;
1006   else
1007     return GTK_PROGRESS (pbar)->format;
1008 }
1009
1010 /**
1011  * gtk_progress_bar_get_fraction:
1012  * @pbar: a #GtkProgressBar
1013  * 
1014  * Returns the current fraction of the task that's been completed.
1015  * 
1016  * Return value: a fraction from 0.0 to 1.0
1017  **/
1018 gdouble
1019 gtk_progress_bar_get_fraction (GtkProgressBar *pbar)
1020 {
1021   g_return_val_if_fail (GTK_IS_PROGRESS_BAR (pbar), 0);
1022
1023   return gtk_progress_get_current_percentage (GTK_PROGRESS (pbar));
1024 }
1025
1026 /**
1027  * gtk_progress_bar_get_pulse_step:
1028  * @pbar: a #GtkProgressBar
1029  * 
1030  * Retrieves the pulse step set with gtk_progress_bar_set_pulse_step()
1031  * 
1032  * Return value: a fraction from 0.0 to 1.0
1033  **/
1034 gdouble
1035 gtk_progress_bar_get_pulse_step (GtkProgressBar *pbar)
1036 {
1037   g_return_val_if_fail (GTK_IS_PROGRESS_BAR (pbar), 0);
1038
1039   return pbar->pulse_fraction;
1040 }
1041
1042 /**
1043  * gtk_progress_bar_get_orientation:
1044  * @pbar: a #GtkProgressBar
1045  * 
1046  * Retrieves the current progress bar orientation.
1047  * 
1048  * Return value: orientation of the progress bar
1049  **/
1050 GtkProgressBarOrientation
1051 gtk_progress_bar_get_orientation (GtkProgressBar *pbar)
1052 {
1053   g_return_val_if_fail (GTK_IS_PROGRESS_BAR (pbar), 0);
1054
1055   return pbar->orientation;
1056 }
1057
1058 void
1059 gtk_progress_bar_set_bar_style (GtkProgressBar     *pbar,
1060                                 GtkProgressBarStyle bar_style)
1061 {
1062   g_return_if_fail (GTK_IS_PROGRESS_BAR (pbar));
1063
1064   if (pbar->bar_style != bar_style)
1065     {
1066       pbar->bar_style = bar_style;
1067
1068       if (GTK_WIDGET_DRAWABLE (GTK_WIDGET (pbar)))
1069         gtk_widget_queue_resize (GTK_WIDGET (pbar));
1070
1071       g_object_notify (G_OBJECT (pbar), "bar_style");
1072     }
1073 }
1074
1075 void
1076 gtk_progress_bar_set_discrete_blocks (GtkProgressBar *pbar,
1077                                       guint           blocks)
1078 {
1079   g_return_if_fail (GTK_IS_PROGRESS_BAR (pbar));
1080   g_return_if_fail (blocks > 1);
1081
1082   if (pbar->blocks != blocks)
1083     {
1084       pbar->blocks = blocks;
1085
1086       if (GTK_WIDGET_DRAWABLE (GTK_WIDGET (pbar)))
1087         gtk_widget_queue_resize (GTK_WIDGET (pbar));
1088
1089       g_object_notify (G_OBJECT (pbar), "discrete_blocks");
1090     }
1091 }
1092
1093 void
1094 gtk_progress_bar_set_activity_step (GtkProgressBar *pbar,
1095                                     guint           step)
1096 {
1097   g_return_if_fail (GTK_IS_PROGRESS_BAR (pbar));
1098
1099   if (pbar->activity_step != step)
1100     {
1101       pbar->activity_step = step;
1102       g_object_notify (G_OBJECT (pbar), "activity_step");
1103     }
1104 }
1105
1106 void
1107 gtk_progress_bar_set_activity_blocks (GtkProgressBar *pbar,
1108                                       guint           blocks)
1109 {
1110   g_return_if_fail (GTK_IS_PROGRESS_BAR (pbar));
1111   g_return_if_fail (blocks > 1);
1112
1113   if (pbar->activity_blocks != blocks)
1114     {
1115       pbar->activity_blocks = blocks;
1116       g_object_notify (G_OBJECT (pbar), "activity_blocks");
1117     }
1118 }