]> Pileus Git - ~andy/gtk/blob - gtk/gtkprogressbar.c
s/succesfully/successfully/g
[~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 (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       buf = gtk_progress_get_text_from_value (progress, progress->adjustment->upper);
463
464       layout = gtk_widget_create_pango_layout (widget, buf);
465       pango_layout_get_pixel_extents (layout, NULL, &logical_rect);
466           
467       g_object_unref (G_OBJECT (layout));
468       g_free (buf);
469     }
470   
471   if (pbar->orientation == GTK_PROGRESS_LEFT_TO_RIGHT ||
472       pbar->orientation == GTK_PROGRESS_RIGHT_TO_LEFT)
473     {
474       if (progress->show_text && pbar->bar_style != GTK_PROGRESS_DISCRETE)
475         {
476           requisition->width = MAX (MIN_HORIZONTAL_BAR_WIDTH,
477                                     2 * widget->style->xthickness + 3 +
478                                     logical_rect.width + 2 * TEXT_SPACING);
479
480           requisition->height = MAX (MIN_HORIZONTAL_BAR_HEIGHT,
481                                      2 * widget->style->ythickness + 3 +
482                                      logical_rect.height + 2 * TEXT_SPACING);
483         }
484       else
485         {
486           requisition->width = MIN_HORIZONTAL_BAR_WIDTH;
487           requisition->height = MIN_HORIZONTAL_BAR_HEIGHT;
488         }
489     }
490   else
491     {
492       if (progress->show_text && pbar->bar_style != GTK_PROGRESS_DISCRETE)
493         {         
494           requisition->width = MAX (MIN_VERTICAL_BAR_WIDTH,
495                                     2 * widget->style->xthickness + 3 +
496                                     logical_rect.width + 2 * TEXT_SPACING);
497
498           requisition->height = MAX (MIN_VERTICAL_BAR_HEIGHT,
499                                      2 * widget->style->ythickness + 3 +
500                                      logical_rect.height + 2 * TEXT_SPACING);
501         }
502       else
503         {
504           requisition->width = MIN_VERTICAL_BAR_WIDTH;
505           requisition->height = MIN_VERTICAL_BAR_HEIGHT;
506         }
507     }
508 }
509
510 static void
511 gtk_progress_bar_act_mode_enter (GtkProgress *progress)
512 {
513   GtkProgressBar *pbar;
514   GtkWidget *widget;
515   gint size;
516
517   pbar = GTK_PROGRESS_BAR (progress);
518   widget = GTK_WIDGET (progress);
519
520   /* calculate start pos */
521
522   if (pbar->orientation == GTK_PROGRESS_LEFT_TO_RIGHT ||
523       pbar->orientation == GTK_PROGRESS_RIGHT_TO_LEFT)
524     {
525       size = MAX (2, widget->allocation.width / pbar->activity_blocks);
526
527       if (pbar->orientation == GTK_PROGRESS_LEFT_TO_RIGHT)
528         {
529           pbar->activity_pos = widget->style->xthickness;
530           pbar->activity_dir = 0;
531         }
532       else
533         {
534           pbar->activity_pos = widget->allocation.width - 
535             widget->style->xthickness - (widget->allocation.height - 
536                 widget->style->ythickness * 2);
537           pbar->activity_dir = 1;
538         }
539     }
540   else
541     {
542       size = MAX (2, widget->allocation.height / pbar->activity_blocks);
543
544       if (pbar->orientation == GTK_PROGRESS_TOP_TO_BOTTOM)
545         {
546           pbar->activity_pos = widget->style->ythickness;
547           pbar->activity_dir = 0;
548         }
549       else
550         {
551           pbar->activity_pos = widget->allocation.height -
552             widget->style->ythickness - (widget->allocation.width - 
553                 widget->style->xthickness * 2);
554           pbar->activity_dir = 1;
555         }
556     }
557 }
558
559 static void
560 gtk_progress_bar_paint (GtkProgress *progress)
561 {
562   GtkProgressBar *pbar;
563   GtkWidget *widget;
564   gint amount;
565   gint block_delta = 0;
566   gint space = 0;
567   gint i;
568   gint x;
569   gint y;
570   gdouble percentage;
571   gint size;
572
573   g_return_if_fail (GTK_IS_PROGRESS_BAR (progress));
574
575   pbar = GTK_PROGRESS_BAR (progress);
576   widget = GTK_WIDGET (progress);
577
578   if (pbar->orientation == GTK_PROGRESS_LEFT_TO_RIGHT ||
579       pbar->orientation == GTK_PROGRESS_RIGHT_TO_LEFT)
580     space = widget->allocation.width -
581       2 * widget->style->xthickness;
582   else
583     space = widget->allocation.height -
584       2 * widget->style->ythickness;
585
586   percentage = gtk_progress_get_current_percentage (progress);
587
588   if (progress->offscreen_pixmap)
589     {
590       gtk_paint_box (widget->style,
591                      progress->offscreen_pixmap,
592                      GTK_STATE_NORMAL, GTK_SHADOW_IN, 
593                      NULL, widget, "trough",
594                      0, 0,
595                      widget->allocation.width,
596                      widget->allocation.height);
597       
598       if (progress->activity_mode)
599         {
600           if (pbar->orientation == GTK_PROGRESS_LEFT_TO_RIGHT ||
601               pbar->orientation == GTK_PROGRESS_RIGHT_TO_LEFT)
602             {
603               size = MAX (2, widget->allocation.width / pbar->activity_blocks);
604               
605               gtk_paint_box (widget->style,
606                              progress->offscreen_pixmap,
607                              GTK_STATE_PRELIGHT, GTK_SHADOW_OUT,
608                              NULL, widget, "bar",
609                              pbar->activity_pos,
610                              widget->style->ythickness,
611                              size,
612                              widget->allocation.height - widget->style->ythickness * 2);
613               return;
614             }
615           else
616             {
617               size = MAX (2, widget->allocation.height / pbar->activity_blocks);
618               
619               gtk_paint_box (widget->style,
620                              progress->offscreen_pixmap,
621                              GTK_STATE_PRELIGHT, GTK_SHADOW_OUT,
622                              NULL, widget, "bar",
623                              widget->style->xthickness,
624                              pbar->activity_pos,
625                              widget->allocation.width - widget->style->xthickness * 2,
626                              size);
627               return;
628             }
629         }
630       
631       amount = percentage * space;
632       
633       if (amount > 0)
634         {
635           switch (pbar->orientation)
636             {
637               
638             case GTK_PROGRESS_LEFT_TO_RIGHT:
639               
640               if (pbar->bar_style == GTK_PROGRESS_CONTINUOUS)
641                 {
642                   gtk_paint_box (widget->style,
643                                  progress->offscreen_pixmap,
644                                  GTK_STATE_PRELIGHT, GTK_SHADOW_OUT,
645                                  NULL, widget, "bar",
646                                  widget->style->xthickness,
647                                  widget->style->ythickness,
648                                  amount,
649                                  widget->allocation.height - widget->style->ythickness * 2);
650                 }
651               else
652                 {
653                   x = widget->style->xthickness;
654                   
655                   for (i = 0; i <= pbar->in_block; i++)
656                     {
657                       block_delta = (((i + 1) * space) / pbar->blocks)
658                         - ((i * space) / pbar->blocks);
659                       
660                       gtk_paint_box (widget->style,
661                                      progress->offscreen_pixmap,
662                                      GTK_STATE_PRELIGHT, GTK_SHADOW_OUT,
663                                      NULL, widget, "bar",
664                                      x,
665                                      widget->style->ythickness,
666                                      block_delta,
667                                      widget->allocation.height - widget->style->ythickness * 2);
668                       
669                       x +=  block_delta;
670                     }
671                 }
672               break;
673               
674             case GTK_PROGRESS_RIGHT_TO_LEFT:
675               
676               if (pbar->bar_style == GTK_PROGRESS_CONTINUOUS)
677                 {
678                   gtk_paint_box (widget->style,
679                                  progress->offscreen_pixmap,
680                                  GTK_STATE_PRELIGHT, GTK_SHADOW_OUT,
681                                  NULL, widget, "bar",
682                                  widget->allocation.width - 
683                                  widget->style->xthickness - amount,
684                                  widget->style->ythickness,
685                                  amount,
686                                  widget->allocation.height -
687                                  widget->style->ythickness * 2);
688                 }
689               else
690                 {
691                   x = widget->allocation.width - 
692                     widget->style->xthickness;
693                   
694                   for (i = 0; i <= pbar->in_block; i++)
695                     {
696                       block_delta = (((i + 1) * space) / pbar->blocks) -
697                         ((i * space) / pbar->blocks);
698                       
699                       x -=  block_delta;
700                       
701                       gtk_paint_box (widget->style,
702                                      progress->offscreen_pixmap,
703                                      GTK_STATE_PRELIGHT, GTK_SHADOW_OUT,
704                                      NULL, widget, "bar",
705                                      x,
706                                      widget->style->ythickness,
707                                      block_delta,
708                                      widget->allocation.height -
709                                      widget->style->ythickness * 2);
710                     }
711                 }
712               break;
713
714             case GTK_PROGRESS_BOTTOM_TO_TOP:
715
716               if (pbar->bar_style == GTK_PROGRESS_CONTINUOUS)
717                 {
718                   gtk_paint_box (widget->style,
719                                  progress->offscreen_pixmap,
720                                  GTK_STATE_PRELIGHT, GTK_SHADOW_OUT,
721                                  NULL, widget, "bar",
722                                  widget->style->xthickness,
723                                  widget->allocation.height - 
724                                  widget->style->ythickness - amount,
725                                  widget->allocation.width -
726                                  widget->style->xthickness * 2,
727                                  amount);
728                 }
729               else
730                 {
731                   y = widget->allocation.height - 
732                     widget->style->ythickness;
733                   
734                   for (i = 0; i <= pbar->in_block; i++)
735                     {
736                       block_delta = (((i + 1) * space) / pbar->blocks) -
737                         ((i * space) / pbar->blocks);
738                       
739                       y -= block_delta;
740                       
741                       gtk_paint_box (widget->style,
742                                      progress->offscreen_pixmap,
743                                      GTK_STATE_PRELIGHT, GTK_SHADOW_OUT,
744                                      NULL, widget, "bar",
745                                      widget->style->xthickness,
746                                      y,
747                                      widget->allocation.width - 
748                                      widget->style->xthickness * 2,
749                                      block_delta);
750                     }
751                 }
752               break;
753               
754             case GTK_PROGRESS_TOP_TO_BOTTOM:
755               
756               if (pbar->bar_style == GTK_PROGRESS_CONTINUOUS)
757                 {
758                   gtk_paint_box (widget->style,
759                                  progress->offscreen_pixmap,
760                                  GTK_STATE_PRELIGHT, GTK_SHADOW_OUT,
761                                  NULL, widget, "bar",
762                                  widget->style->xthickness,
763                                  widget->style->ythickness,
764                                  widget->allocation.width -
765                                  widget->style->xthickness * 2,
766                                  amount);
767                 }
768               else
769                 {
770                   y = widget->style->ythickness;
771                   
772                   for (i = 0; i <= pbar->in_block; i++)
773                     {
774                       
775                       block_delta = (((i + 1) * space) / pbar->blocks)
776                         - ((i * space) / pbar->blocks);
777                       
778                       gtk_paint_box (widget->style,
779                                      progress->offscreen_pixmap,
780                                      GTK_STATE_PRELIGHT, GTK_SHADOW_OUT,
781                                      NULL, widget, "bar",
782                                      widget->style->xthickness,
783                                      y,
784                                      widget->allocation.width -
785                                      widget->style->xthickness * 2,
786                                      block_delta);
787                       
788                       y += block_delta;
789                     }
790                 }
791               break;
792               
793             default:
794               break;
795             }
796         }
797       
798       if (progress->show_text && pbar->bar_style != GTK_PROGRESS_DISCRETE)
799         {
800           gint x;
801           gint y;
802           gchar *buf;
803           GdkRectangle rect;
804           PangoLayout *layout;
805           PangoRectangle logical_rect;
806
807           buf = gtk_progress_get_current_text (progress);
808
809           layout = gtk_widget_create_pango_layout (widget, buf);
810           pango_layout_get_pixel_extents (layout, NULL, &logical_rect);
811           
812           x = widget->style->xthickness + 1 + 
813             (widget->allocation.width - 2 * widget->style->xthickness -
814              3 - logical_rect.width)
815             * progress->x_align; 
816
817           y = widget->style->ythickness + 1 +
818             (widget->allocation.height - 2 * widget->style->ythickness -
819              3 - logical_rect.height)
820             * progress->y_align;
821
822           rect.x = widget->style->xthickness + 1;
823           rect.y = widget->style->ythickness + 1;
824           rect.width = widget->allocation.width -
825             2 * widget->style->xthickness - 3;
826           rect.height = widget->allocation.height -
827             2 * widget->style->ythickness - 3;
828       
829           gtk_paint_layout (widget->style,
830                             progress->offscreen_pixmap,
831                             GTK_WIDGET_STATE (widget),
832                             FALSE,
833                             &rect,
834                             widget,
835                             "progressbar",
836                             x, y,
837                             layout);
838
839           g_object_unref (G_OBJECT (layout));
840           g_free (buf);
841         }
842     }
843 }
844
845 /*******************************************************************/
846
847 /**
848  * gtk_progress_bar_set_fraction:
849  * @pbar: a #GtkProgressBar
850  * @fraction: fraction of the task that's been completed
851  * 
852  * Causes the progress bar to "fill in" the given fraction
853  * of the bar. The fraction should be between 0.0 and 1.0,
854  * inclusive.
855  * 
856  **/
857 void
858 gtk_progress_bar_set_fraction (GtkProgressBar *pbar,
859                                gdouble         fraction)
860 {
861   g_return_if_fail (GTK_IS_PROGRESS_BAR (pbar));
862
863   /* If we know the percentage, we don't want activity mode. */
864   gtk_progress_set_activity_mode (GTK_PROGRESS (pbar), FALSE);
865   
866   /* We use the deprecated GtkProgress interface internally.
867    * Once everything's been deprecated for a good long time,
868    * we can clean up all this code.
869    */
870   gtk_progress_set_percentage (GTK_PROGRESS (pbar), fraction);
871
872   g_object_notify (G_OBJECT (pbar), "fraction");
873 }
874
875 /**
876  * gtk_progress_bar_pulse:
877  * @pbar: a #GtkProgressBar
878  * 
879  * Indicates that some progress is made, but you don't know how much.
880  * Causes the progress bar to enter "activity mode," where a block
881  * bounces back and forth. Each call to gtk_progress_bar_pulse()
882  * causes the block to move by a little bit (the amount of movement
883  * per pulse is determined by gtk_progress_bar_set_pulse_step()).
884  **/
885 void
886 gtk_progress_bar_pulse (GtkProgressBar *pbar)
887 {  
888   g_return_if_fail (GTK_IS_PROGRESS_BAR (pbar));
889
890   /* If we don't know the percentage, we must want activity mode. */
891   gtk_progress_set_activity_mode (GTK_PROGRESS (pbar), TRUE);
892
893   /* Sigh. */
894   gtk_progress_bar_real_update (GTK_PROGRESS (pbar));
895 }
896
897 /**
898  * gtk_progress_bar_set_text:
899  * @pbar: a #GtkProgressBar
900  * @text: a UTF-8 string
901  * 
902  * Causes the given @text to appear superimposed on the progress bar.
903  **/
904 void
905 gtk_progress_bar_set_text (GtkProgressBar *pbar,
906                            const gchar    *text)
907 {
908   g_return_if_fail (GTK_IS_PROGRESS_BAR (pbar));
909   
910   if (text && *text)
911     {
912       gtk_progress_set_show_text (GTK_PROGRESS (pbar), TRUE);
913       gtk_progress_set_format_string (GTK_PROGRESS (pbar), text);
914     }
915   else
916     {
917       gtk_progress_set_show_text (GTK_PROGRESS (pbar), FALSE);
918       gtk_progress_set_format_string (GTK_PROGRESS (pbar), "");
919     }
920
921   /* We don't support formats in this interface */
922   GTK_PROGRESS (pbar)->use_text_format = FALSE;
923   
924   g_object_notify (G_OBJECT (pbar), "text");
925 }
926
927 /**
928  * gtk_progress_bar_set_pulse_step:
929  * @pbar: a #GtkProgressBar
930  * @fraction: fraction between 0.0 and 1.0
931  * 
932  * Sets the fraction of total progress bar length to move the
933  * bouncing block for each call to gtk_progress_bar_pulse().
934  **/
935 void
936 gtk_progress_bar_set_pulse_step   (GtkProgressBar *pbar,
937                                    gdouble         fraction)
938 {
939   g_return_if_fail (GTK_IS_PROGRESS_BAR (pbar));
940   
941   pbar->pulse_fraction = fraction;
942
943   g_object_notify (G_OBJECT (pbar), "pulse_step");
944 }
945
946 void
947 gtk_progress_bar_update (GtkProgressBar *pbar,
948                          gdouble         percentage)
949 {
950   g_return_if_fail (GTK_IS_PROGRESS_BAR (pbar));
951
952   /* Use of gtk_progress_bar_update() is deprecated ! 
953    * Use gtk_progress_bar_set_percentage ()
954    */   
955
956   gtk_progress_set_percentage (GTK_PROGRESS (pbar), percentage);
957 }
958
959 /**
960  * gtk_progress_bar_set_orientation:
961  * @pbar: a #GtkProgressBar
962  * @orientation: orientation of the progress bar
963  * 
964  * Causes the progress bar to switch to a different orientation
965  * (left-to-right, right-to-left, top-to-bottom, or bottom-to-top). 
966  **/
967 void
968 gtk_progress_bar_set_orientation (GtkProgressBar           *pbar,
969                                   GtkProgressBarOrientation orientation)
970 {
971   g_return_if_fail (GTK_IS_PROGRESS_BAR (pbar));
972
973   if (pbar->orientation != orientation)
974     {
975       pbar->orientation = orientation;
976
977       if (GTK_WIDGET_DRAWABLE (GTK_WIDGET (pbar)))
978         gtk_widget_queue_resize (GTK_WIDGET (pbar));
979
980       g_object_notify (G_OBJECT (pbar), "orientation");
981     }
982 }
983
984 /**
985  * gtk_progress_bar_get_text:
986  * @pbar: a #GtkProgressBar
987  * 
988  * Retrieves the text displayed superimposed on the progress bar,
989  * if any, otherwise %NULL. The return value is a reference
990  * to the text, not a copy of it, so will become invalid
991  * if you change the text in the progress bar.
992  * 
993  * Return value: text, or %NULL; don't free the string
994  **/
995 G_CONST_RETURN gchar*
996 gtk_progress_bar_get_text (GtkProgressBar *pbar)
997 {
998   g_return_val_if_fail (GTK_IS_PROGRESS_BAR (pbar), NULL);
999
1000   if (GTK_PROGRESS (pbar)->use_text_format)
1001     return NULL;
1002   else
1003     return GTK_PROGRESS (pbar)->format;
1004 }
1005
1006 /**
1007  * gtk_progress_bar_get_fraction:
1008  * @pbar: a #GtkProgressBar
1009  * 
1010  * Returns the current fraction of the task that's been completed.
1011  * 
1012  * Return value: a fraction from 0.0 to 1.0
1013  **/
1014 gdouble
1015 gtk_progress_bar_get_fraction (GtkProgressBar *pbar)
1016 {
1017   g_return_val_if_fail (GTK_IS_PROGRESS_BAR (pbar), 0);
1018
1019   return gtk_progress_get_current_percentage (GTK_PROGRESS (pbar));
1020 }
1021
1022 /**
1023  * gtk_progress_bar_get_pulse_step:
1024  * @pbar: a #GtkProgressBar
1025  * 
1026  * Retrieves the pulse step set with gtk_progress_bar_set_pulse_step()
1027  * 
1028  * Return value: a fraction from 0.0 to 1.0
1029  **/
1030 gdouble
1031 gtk_progress_bar_get_pulse_step (GtkProgressBar *pbar)
1032 {
1033   g_return_val_if_fail (GTK_IS_PROGRESS_BAR (pbar), 0);
1034
1035   return pbar->pulse_fraction;
1036 }
1037
1038 /**
1039  * gtk_progress_bar_get_orientation:
1040  * @pbar: a #GtkProgressBar
1041  * 
1042  * Retrieves the current progress bar orientation.
1043  * 
1044  * Return value: orientation of the progress bar
1045  **/
1046 GtkProgressBarOrientation
1047 gtk_progress_bar_get_orientation (GtkProgressBar *pbar)
1048 {
1049   g_return_val_if_fail (GTK_IS_PROGRESS_BAR (pbar), 0);
1050
1051   return pbar->orientation;
1052 }
1053
1054 void
1055 gtk_progress_bar_set_bar_style (GtkProgressBar     *pbar,
1056                                 GtkProgressBarStyle bar_style)
1057 {
1058   g_return_if_fail (GTK_IS_PROGRESS_BAR (pbar));
1059
1060   if (pbar->bar_style != bar_style)
1061     {
1062       pbar->bar_style = bar_style;
1063
1064       if (GTK_WIDGET_DRAWABLE (GTK_WIDGET (pbar)))
1065         gtk_widget_queue_resize (GTK_WIDGET (pbar));
1066
1067       g_object_notify (G_OBJECT (pbar), "bar_style");
1068     }
1069 }
1070
1071 void
1072 gtk_progress_bar_set_discrete_blocks (GtkProgressBar *pbar,
1073                                       guint           blocks)
1074 {
1075   g_return_if_fail (GTK_IS_PROGRESS_BAR (pbar));
1076   g_return_if_fail (blocks > 1);
1077
1078   if (pbar->blocks != blocks)
1079     {
1080       pbar->blocks = blocks;
1081
1082       if (GTK_WIDGET_DRAWABLE (GTK_WIDGET (pbar)))
1083         gtk_widget_queue_resize (GTK_WIDGET (pbar));
1084
1085       g_object_notify (G_OBJECT (pbar), "discrete_blocks");
1086     }
1087 }
1088
1089 void
1090 gtk_progress_bar_set_activity_step (GtkProgressBar *pbar,
1091                                     guint           step)
1092 {
1093   g_return_if_fail (GTK_IS_PROGRESS_BAR (pbar));
1094
1095   if (pbar->activity_step != step)
1096     {
1097       pbar->activity_step = step;
1098       g_object_notify (G_OBJECT (pbar), "activity_step");
1099     }
1100 }
1101
1102 void
1103 gtk_progress_bar_set_activity_blocks (GtkProgressBar *pbar,
1104                                       guint           blocks)
1105 {
1106   g_return_if_fail (GTK_IS_PROGRESS_BAR (pbar));
1107   g_return_if_fail (blocks > 1);
1108
1109   if (pbar->activity_blocks != blocks)
1110     {
1111       pbar->activity_blocks = blocks;
1112       g_object_notify (G_OBJECT (pbar), "activity_blocks");
1113     }
1114 }