]> Pileus Git - ~andy/gtk/blob - gtk/gtkprogressbar.c
applied patch from Andreas Persenius <ndap@swipnet.se> that updates the
[~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
40
41 #define MIN_HORIZONTAL_BAR_WIDTH   150
42 #define MIN_HORIZONTAL_BAR_HEIGHT  20
43 #define MIN_VERTICAL_BAR_WIDTH     22
44 #define MIN_VERTICAL_BAR_HEIGHT    80
45 #define MAX_TEXT_LENGTH            80
46 #define TEXT_SPACING               2
47
48 enum {
49   ARG_0,
50   ARG_ADJUSTMENT,
51   ARG_ORIENTATION,
52   ARG_BAR_STYLE,
53   ARG_ACTIVITY_STEP,
54   ARG_ACTIVITY_BLOCKS,
55   ARG_DISCRETE_BLOCKS,
56   ARG_FRACTION,
57   ARG_PULSE_STEP
58 };
59
60 static void gtk_progress_bar_class_init    (GtkProgressBarClass *klass);
61 static void gtk_progress_bar_init          (GtkProgressBar      *pbar);
62 static void gtk_progress_bar_set_arg       (GtkObject           *object,
63                                             GtkArg              *arg,
64                                             guint                arg_id);
65 static void gtk_progress_bar_get_arg       (GtkObject           *object,
66                                             GtkArg              *arg,
67                                             guint                arg_id);
68 static void gtk_progress_bar_size_request  (GtkWidget           *widget,
69                                             GtkRequisition      *requisition);
70 static void gtk_progress_bar_real_update   (GtkProgress         *progress);
71 static void gtk_progress_bar_paint         (GtkProgress         *progress);
72 static void gtk_progress_bar_act_mode_enter (GtkProgress        *progress);
73
74
75 GtkType
76 gtk_progress_bar_get_type (void)
77 {
78   static GtkType progress_bar_type = 0;
79
80   if (!progress_bar_type)
81     {
82       static const GtkTypeInfo progress_bar_info =
83       {
84         "GtkProgressBar",
85         sizeof (GtkProgressBar),
86         sizeof (GtkProgressBarClass),
87         (GtkClassInitFunc) gtk_progress_bar_class_init,
88         (GtkObjectInitFunc) gtk_progress_bar_init,
89         /* reserved_1 */ NULL,
90         /* reserved_2 */ NULL,
91         (GtkClassInitFunc) NULL
92       };
93
94       progress_bar_type = gtk_type_unique (GTK_TYPE_PROGRESS, &progress_bar_info);
95     }
96
97   return progress_bar_type;
98 }
99
100 static void
101 gtk_progress_bar_class_init (GtkProgressBarClass *class)
102 {
103   GtkObjectClass *object_class;
104   GtkWidgetClass *widget_class;
105   GtkProgressClass *progress_class;
106   
107   object_class = (GtkObjectClass *) class;
108   widget_class = (GtkWidgetClass *) class;
109   progress_class = (GtkProgressClass *) class;
110   
111   gtk_object_add_arg_type ("GtkProgressBar::adjustment",
112                            GTK_TYPE_ADJUSTMENT,
113                            GTK_ARG_READWRITE,
114                            ARG_ADJUSTMENT);
115   gtk_object_add_arg_type ("GtkProgressBar::orientation",
116                            GTK_TYPE_PROGRESS_BAR_ORIENTATION,
117                            GTK_ARG_READWRITE,
118                            ARG_ORIENTATION);
119   gtk_object_add_arg_type ("GtkProgressBar::bar_style",
120                            GTK_TYPE_PROGRESS_BAR_STYLE,
121                            GTK_ARG_READWRITE,
122                            ARG_BAR_STYLE);
123   gtk_object_add_arg_type ("GtkProgressBar::activity_step",
124                            GTK_TYPE_UINT,
125                            GTK_ARG_READWRITE,
126                            ARG_ACTIVITY_STEP);
127   gtk_object_add_arg_type ("GtkProgressBar::activity_blocks",
128                            GTK_TYPE_UINT,
129                            GTK_ARG_READWRITE,
130                            ARG_ACTIVITY_BLOCKS);
131   gtk_object_add_arg_type ("GtkProgressBar::discrete_blocks",
132                            GTK_TYPE_UINT,
133                            GTK_ARG_READWRITE,
134                            ARG_DISCRETE_BLOCKS);
135   gtk_object_add_arg_type ("GtkProgressBar::fraction",
136                            GTK_TYPE_FLOAT,
137                            GTK_ARG_READWRITE,
138                            ARG_FRACTION);
139   gtk_object_add_arg_type ("GtkProgressBar::pulse_step",
140                            GTK_TYPE_FLOAT,
141                            GTK_ARG_READWRITE,
142                            ARG_FRACTION);
143   
144   object_class->set_arg = gtk_progress_bar_set_arg;
145   object_class->get_arg = gtk_progress_bar_get_arg;
146
147   widget_class->size_request = gtk_progress_bar_size_request;
148
149   progress_class->paint = gtk_progress_bar_paint;
150   progress_class->update = gtk_progress_bar_real_update;
151   progress_class->act_mode_enter = gtk_progress_bar_act_mode_enter;
152 }
153
154 static void
155 gtk_progress_bar_init (GtkProgressBar *pbar)
156 {
157   pbar->bar_style = GTK_PROGRESS_CONTINUOUS;
158   pbar->blocks = 10;
159   pbar->in_block = -1;
160   pbar->orientation = GTK_PROGRESS_LEFT_TO_RIGHT;
161   pbar->pulse_fraction = 0.1;
162   pbar->activity_pos = 0;
163   pbar->activity_dir = 1;
164   pbar->activity_step = 3;
165   pbar->activity_blocks = 5;
166 }
167
168 static void
169 gtk_progress_bar_set_arg (GtkObject           *object,
170                           GtkArg              *arg,
171                           guint                arg_id)
172 {
173   GtkProgressBar *pbar;
174
175   pbar = GTK_PROGRESS_BAR (object);
176
177   switch (arg_id)
178     {
179     case ARG_ADJUSTMENT:
180       gtk_progress_set_adjustment (GTK_PROGRESS (pbar), GTK_VALUE_POINTER (*arg));
181       break;
182     case ARG_ORIENTATION:
183       gtk_progress_bar_set_orientation (pbar, GTK_VALUE_ENUM (*arg));
184       break;
185     case ARG_BAR_STYLE:
186       gtk_progress_bar_set_bar_style (pbar, GTK_VALUE_ENUM (*arg));
187       break;
188     case ARG_ACTIVITY_STEP:
189       gtk_progress_bar_set_activity_step (pbar, GTK_VALUE_UINT (*arg));
190       break;
191     case ARG_ACTIVITY_BLOCKS:
192       gtk_progress_bar_set_activity_blocks (pbar, GTK_VALUE_UINT (*arg));
193       break;
194     case ARG_DISCRETE_BLOCKS:
195       gtk_progress_bar_set_discrete_blocks (pbar, GTK_VALUE_UINT (*arg));
196       break;
197     case ARG_FRACTION:
198       gtk_progress_bar_set_fraction (pbar, GTK_VALUE_FLOAT (*arg));
199       break;
200     case ARG_PULSE_STEP:
201       gtk_progress_bar_set_pulse_step (pbar, GTK_VALUE_FLOAT (*arg));
202       break;
203     default:
204       break;
205     }
206 }
207
208 static void
209 gtk_progress_bar_get_arg (GtkObject           *object,
210                           GtkArg              *arg,
211                           guint                arg_id)
212 {
213   GtkProgressBar *pbar;
214
215   pbar = GTK_PROGRESS_BAR (object);
216
217   switch (arg_id)
218     {
219     case ARG_ADJUSTMENT:
220       GTK_VALUE_POINTER (*arg) = GTK_PROGRESS (pbar)->adjustment;
221       break;
222     case ARG_ORIENTATION:
223       GTK_VALUE_ENUM (*arg) = pbar->orientation;
224       break;
225     case ARG_BAR_STYLE:
226       GTK_VALUE_ENUM (*arg) = pbar->bar_style;
227       break;
228     case ARG_ACTIVITY_STEP:
229       GTK_VALUE_UINT (*arg) = pbar->activity_step;
230       break;
231     case ARG_ACTIVITY_BLOCKS:
232       GTK_VALUE_UINT (*arg) = pbar->activity_blocks;
233       break;
234     case ARG_DISCRETE_BLOCKS:
235       GTK_VALUE_UINT (*arg) = pbar->blocks;
236       break;
237     case ARG_FRACTION:
238       GTK_VALUE_FLOAT (*arg) = gtk_progress_get_current_percentage (GTK_PROGRESS (pbar));
239       break;
240     case ARG_PULSE_STEP:
241       GTK_VALUE_FLOAT (*arg) = pbar->pulse_fraction;
242       break;
243     default:
244       arg->type = GTK_TYPE_INVALID;
245       break;
246     }
247 }
248
249 GtkWidget*
250 gtk_progress_bar_new (void)
251 {
252   GtkWidget *pbar;
253
254   pbar = gtk_widget_new (GTK_TYPE_PROGRESS_BAR, NULL);
255
256   return pbar;
257 }
258
259 GtkWidget*
260 gtk_progress_bar_new_with_adjustment (GtkAdjustment *adjustment)
261 {
262   GtkWidget *pbar;
263
264   g_return_val_if_fail (adjustment != NULL, NULL);
265   g_return_val_if_fail (GTK_IS_ADJUSTMENT (adjustment), NULL);
266
267   pbar = gtk_widget_new (GTK_TYPE_PROGRESS_BAR,
268                          "adjustment", adjustment,
269                          NULL);
270
271   return pbar;
272 }
273
274 static void
275 gtk_progress_bar_real_update (GtkProgress *progress)
276 {
277   GtkProgressBar *pbar;
278   GtkWidget *widget;
279
280   g_return_if_fail (progress != NULL);
281   g_return_if_fail (GTK_IS_PROGRESS (progress));
282
283   pbar = GTK_PROGRESS_BAR (progress);
284   widget = GTK_WIDGET (progress);
285  
286   if (pbar->bar_style == GTK_PROGRESS_CONTINUOUS ||
287       GTK_PROGRESS (pbar)->activity_mode)
288     {
289       if (GTK_PROGRESS (pbar)->activity_mode)
290         {
291           guint size;
292           
293           /* advance the block */
294
295           if (pbar->orientation == GTK_PROGRESS_LEFT_TO_RIGHT ||
296               pbar->orientation == GTK_PROGRESS_RIGHT_TO_LEFT)
297             {
298               /* Update our activity step. */
299               
300               pbar->activity_step = widget->allocation.width * pbar->pulse_fraction;
301               
302               size = MAX (2, widget->allocation.width / pbar->activity_blocks);
303
304               if (pbar->activity_dir == 0)
305                 {
306                   pbar->activity_pos += pbar->activity_step;
307                   if (pbar->activity_pos + size >=
308                       widget->allocation.width -
309                       widget->style->xthickness)
310                     {
311                       pbar->activity_pos = widget->allocation.width -
312                         widget->style->xthickness - size;
313                       pbar->activity_dir = 1;
314                     }
315                 }
316               else
317                 {
318                   pbar->activity_pos -= pbar->activity_step;
319                   if (pbar->activity_pos <= widget->style->xthickness)
320                     {
321                       pbar->activity_pos = widget->style->xthickness;
322                       pbar->activity_dir = 0;
323                     }
324                 }
325             }
326           else
327             {
328               /* Update our activity step. */
329               
330               pbar->activity_step = widget->allocation.height * pbar->pulse_fraction;
331               
332               size = MAX (2, widget->allocation.height / pbar->activity_blocks);
333
334               if (pbar->activity_dir == 0)
335                 {
336                   pbar->activity_pos += pbar->activity_step;
337                   if (pbar->activity_pos + size >=
338                       widget->allocation.height -
339                       widget->style->ythickness)
340                     {
341                       pbar->activity_pos = widget->allocation.height -
342                         widget->style->ythickness - size;
343                       pbar->activity_dir = 1;
344                     }
345                 }
346               else
347                 {
348                   pbar->activity_pos -= pbar->activity_step;
349                   if (pbar->activity_pos <= widget->style->ythickness)
350                     {
351                       pbar->activity_pos = widget->style->ythickness;
352                       pbar->activity_dir = 0;
353                     }
354                 }
355             }
356         }
357       gtk_progress_bar_paint (progress);
358       gtk_widget_queue_draw (GTK_WIDGET (progress));
359     }
360   else
361     {
362       gint in_block;
363       
364       in_block = -1 + (gint)(gtk_progress_get_current_percentage (progress) *
365                              (gfloat)pbar->blocks);
366       
367       if (pbar->in_block != in_block)
368         {
369           pbar->in_block = in_block;
370           gtk_progress_bar_paint (progress);
371           gtk_widget_queue_draw (GTK_WIDGET (progress));
372         }
373     }
374 }
375
376 static void
377 gtk_progress_bar_size_request (GtkWidget      *widget,
378                                GtkRequisition *requisition)
379 {
380   GtkProgress *progress;
381   GtkProgressBar *pbar;
382   gchar *buf;
383   PangoRectangle logical_rect;
384   PangoLayout *layout;
385
386   g_return_if_fail (widget != NULL);
387   g_return_if_fail (GTK_IS_PROGRESS_BAR (widget));
388   g_return_if_fail (requisition != NULL);
389
390   progress = GTK_PROGRESS (widget);
391   pbar = GTK_PROGRESS_BAR (widget);
392
393   if (progress->show_text && pbar->bar_style != GTK_PROGRESS_DISCRETE)
394     {
395       buf = gtk_progress_get_text_from_value (progress, progress->adjustment->upper);
396
397       layout = gtk_widget_create_pango_layout (widget, buf);
398       pango_layout_get_pixel_extents (layout, NULL, &logical_rect);
399           
400       g_object_unref (G_OBJECT (layout));
401       g_free (buf);
402     }
403   
404   if (pbar->orientation == GTK_PROGRESS_LEFT_TO_RIGHT ||
405       pbar->orientation == GTK_PROGRESS_RIGHT_TO_LEFT)
406     {
407       if (progress->show_text && pbar->bar_style != GTK_PROGRESS_DISCRETE)
408         {
409           requisition->width = MAX (MIN_HORIZONTAL_BAR_WIDTH,
410                                     2 * widget->style->xthickness + 3 +
411                                     logical_rect.width + 2 * TEXT_SPACING);
412
413           requisition->height = MAX (MIN_HORIZONTAL_BAR_HEIGHT,
414                                      2 * widget->style->ythickness + 3 +
415                                      logical_rect.height + 2 * TEXT_SPACING);
416         }
417       else
418         {
419           requisition->width = MIN_HORIZONTAL_BAR_WIDTH;
420           requisition->height = MIN_HORIZONTAL_BAR_HEIGHT;
421         }
422     }
423   else
424     {
425       if (progress->show_text && pbar->bar_style != GTK_PROGRESS_DISCRETE)
426         {         
427           requisition->width = MAX (MIN_VERTICAL_BAR_WIDTH,
428                                     2 * widget->style->xthickness + 3 +
429                                     logical_rect.width + 2 * TEXT_SPACING);
430
431           requisition->height = MAX (MIN_VERTICAL_BAR_HEIGHT,
432                                      2 * widget->style->ythickness + 3 +
433                                      logical_rect.height + 2 * TEXT_SPACING);
434         }
435       else
436         {
437           requisition->width = MIN_VERTICAL_BAR_WIDTH;
438           requisition->height = MIN_VERTICAL_BAR_HEIGHT;
439         }
440     }
441 }
442
443 static void
444 gtk_progress_bar_act_mode_enter (GtkProgress *progress)
445 {
446   GtkProgressBar *pbar;
447   GtkWidget *widget;
448   gint size;
449
450   pbar = GTK_PROGRESS_BAR (progress);
451   widget = GTK_WIDGET (progress);
452
453   /* calculate start pos */
454
455   if (pbar->orientation == GTK_PROGRESS_LEFT_TO_RIGHT ||
456       pbar->orientation == GTK_PROGRESS_RIGHT_TO_LEFT)
457     {
458       size = MAX (2, widget->allocation.width / pbar->activity_blocks);
459
460       if (pbar->orientation == GTK_PROGRESS_LEFT_TO_RIGHT)
461         {
462           pbar->activity_pos = widget->style->xthickness;
463           pbar->activity_dir = 0;
464         }
465       else
466         {
467           pbar->activity_pos = widget->allocation.width - 
468             widget->style->xthickness - (widget->allocation.height - 
469                 widget->style->ythickness * 2);
470           pbar->activity_dir = 1;
471         }
472     }
473   else
474     {
475       size = MAX (2, widget->allocation.height / pbar->activity_blocks);
476
477       if (pbar->orientation == GTK_PROGRESS_TOP_TO_BOTTOM)
478         {
479           pbar->activity_pos = widget->style->ythickness;
480           pbar->activity_dir = 0;
481         }
482       else
483         {
484           pbar->activity_pos = widget->allocation.height -
485             widget->style->ythickness - (widget->allocation.width - 
486                 widget->style->xthickness * 2);
487           pbar->activity_dir = 1;
488         }
489     }
490 }
491
492 static void
493 gtk_progress_bar_paint (GtkProgress *progress)
494 {
495   GtkProgressBar *pbar;
496   GtkWidget *widget;
497   gint amount;
498   gint block_delta = 0;
499   gint space = 0;
500   gint i;
501   gint x;
502   gint y;
503   gfloat percentage;
504   gint size;
505
506   g_return_if_fail (progress != NULL);
507   g_return_if_fail (GTK_IS_PROGRESS_BAR (progress));
508
509   pbar = GTK_PROGRESS_BAR (progress);
510   widget = GTK_WIDGET (progress);
511
512   if (pbar->orientation == GTK_PROGRESS_LEFT_TO_RIGHT ||
513       pbar->orientation == GTK_PROGRESS_RIGHT_TO_LEFT)
514     space = widget->allocation.width -
515       2 * widget->style->xthickness;
516   else
517     space = widget->allocation.height -
518       2 * widget->style->ythickness;
519
520   percentage = gtk_progress_get_current_percentage (progress);
521
522   if (progress->offscreen_pixmap)
523     {
524       gtk_paint_box (widget->style,
525                      progress->offscreen_pixmap,
526                      GTK_STATE_NORMAL, GTK_SHADOW_IN, 
527                      NULL, widget, "trough",
528                      0, 0,
529                      widget->allocation.width,
530                      widget->allocation.height);
531       
532       if (progress->activity_mode)
533         {
534           if (pbar->orientation == GTK_PROGRESS_LEFT_TO_RIGHT ||
535               pbar->orientation == GTK_PROGRESS_RIGHT_TO_LEFT)
536             {
537               size = MAX (2, widget->allocation.width / pbar->activity_blocks);
538               
539               gtk_paint_box (widget->style,
540                              progress->offscreen_pixmap,
541                              GTK_STATE_PRELIGHT, GTK_SHADOW_OUT,
542                              NULL, widget, "bar",
543                              pbar->activity_pos,
544                              widget->style->ythickness,
545                              size,
546                              widget->allocation.height - widget->style->ythickness * 2);
547               return;
548             }
549           else
550             {
551               size = MAX (2, widget->allocation.height / pbar->activity_blocks);
552               
553               gtk_paint_box (widget->style,
554                              progress->offscreen_pixmap,
555                              GTK_STATE_PRELIGHT, GTK_SHADOW_OUT,
556                              NULL, widget, "bar",
557                              widget->style->xthickness,
558                              pbar->activity_pos,
559                              widget->allocation.width - widget->style->xthickness * 2,
560                              size);
561               return;
562             }
563         }
564       
565       amount = percentage * space;
566       
567       if (amount > 0)
568         {
569           switch (pbar->orientation)
570             {
571               
572             case GTK_PROGRESS_LEFT_TO_RIGHT:
573               
574               if (pbar->bar_style == GTK_PROGRESS_CONTINUOUS)
575                 {
576                   gtk_paint_box (widget->style,
577                                  progress->offscreen_pixmap,
578                                  GTK_STATE_PRELIGHT, GTK_SHADOW_OUT,
579                                  NULL, widget, "bar",
580                                  widget->style->xthickness,
581                                  widget->style->ythickness,
582                                  amount,
583                                  widget->allocation.height - widget->style->ythickness * 2);
584                 }
585               else
586                 {
587                   x = widget->style->xthickness;
588                   
589                   for (i = 0; i <= pbar->in_block; i++)
590                     {
591                       block_delta = (((i + 1) * space) / pbar->blocks)
592                         - ((i * space) / pbar->blocks);
593                       
594                       gtk_paint_box (widget->style,
595                                      progress->offscreen_pixmap,
596                                      GTK_STATE_PRELIGHT, GTK_SHADOW_OUT,
597                                      NULL, widget, "bar",
598                                      x,
599                                      widget->style->ythickness,
600                                      block_delta,
601                                      widget->allocation.height - widget->style->ythickness * 2);
602                       
603                       x +=  block_delta;
604                     }
605                 }
606               break;
607               
608             case GTK_PROGRESS_RIGHT_TO_LEFT:
609               
610               if (pbar->bar_style == GTK_PROGRESS_CONTINUOUS)
611                 {
612                   gtk_paint_box (widget->style,
613                                  progress->offscreen_pixmap,
614                                  GTK_STATE_PRELIGHT, GTK_SHADOW_OUT,
615                                  NULL, widget, "bar",
616                                  widget->allocation.width - 
617                                  widget->style->xthickness - amount,
618                                  widget->style->ythickness,
619                                  amount,
620                                  widget->allocation.height -
621                                  widget->style->ythickness * 2);
622                 }
623               else
624                 {
625                   x = widget->allocation.width - 
626                     widget->style->xthickness;
627                   
628                   for (i = 0; i <= pbar->in_block; i++)
629                     {
630                       block_delta = (((i + 1) * space) / pbar->blocks) -
631                         ((i * space) / pbar->blocks);
632                       
633                       x -=  block_delta;
634                       
635                       gtk_paint_box (widget->style,
636                                      progress->offscreen_pixmap,
637                                      GTK_STATE_PRELIGHT, GTK_SHADOW_OUT,
638                                      NULL, widget, "bar",
639                                      x,
640                                      widget->style->ythickness,
641                                      block_delta,
642                                      widget->allocation.height -
643                                      widget->style->ythickness * 2);
644                     }
645                 }
646               break;
647
648             case GTK_PROGRESS_BOTTOM_TO_TOP:
649
650               if (pbar->bar_style == GTK_PROGRESS_CONTINUOUS)
651                 {
652                   gtk_paint_box (widget->style,
653                                  progress->offscreen_pixmap,
654                                  GTK_STATE_PRELIGHT, GTK_SHADOW_OUT,
655                                  NULL, widget, "bar",
656                                  widget->style->xthickness,
657                                  widget->allocation.height - 
658                                  widget->style->ythickness - amount,
659                                  widget->allocation.width -
660                                  widget->style->xthickness * 2,
661                                  amount);
662                 }
663               else
664                 {
665                   y = widget->allocation.height - 
666                     widget->style->ythickness;
667                   
668                   for (i = 0; i <= pbar->in_block; i++)
669                     {
670                       block_delta = (((i + 1) * space) / pbar->blocks) -
671                         ((i * space) / pbar->blocks);
672                       
673                       y -= block_delta;
674                       
675                       gtk_paint_box (widget->style,
676                                      progress->offscreen_pixmap,
677                                      GTK_STATE_PRELIGHT, GTK_SHADOW_OUT,
678                                      NULL, widget, "bar",
679                                      widget->style->xthickness,
680                                      y,
681                                      widget->allocation.width - 
682                                      widget->style->xthickness * 2,
683                                      block_delta);
684                     }
685                 }
686               break;
687               
688             case GTK_PROGRESS_TOP_TO_BOTTOM:
689               
690               if (pbar->bar_style == GTK_PROGRESS_CONTINUOUS)
691                 {
692                   gtk_paint_box (widget->style,
693                                  progress->offscreen_pixmap,
694                                  GTK_STATE_PRELIGHT, GTK_SHADOW_OUT,
695                                  NULL, widget, "bar",
696                                  widget->style->xthickness,
697                                  widget->style->ythickness,
698                                  widget->allocation.width -
699                                  widget->style->xthickness * 2,
700                                  amount);
701                 }
702               else
703                 {
704                   y = widget->style->ythickness;
705                   
706                   for (i = 0; i <= pbar->in_block; i++)
707                     {
708                       
709                       block_delta = (((i + 1) * space) / pbar->blocks)
710                         - ((i * space) / pbar->blocks);
711                       
712                       gtk_paint_box (widget->style,
713                                      progress->offscreen_pixmap,
714                                      GTK_STATE_PRELIGHT, GTK_SHADOW_OUT,
715                                      NULL, widget, "bar",
716                                      widget->style->xthickness,
717                                      y,
718                                      widget->allocation.width -
719                                      widget->style->xthickness * 2,
720                                      block_delta);
721                       
722                       y += block_delta;
723                     }
724                 }
725               break;
726               
727             default:
728               break;
729             }
730         }
731       
732       if (progress->show_text && pbar->bar_style != GTK_PROGRESS_DISCRETE)
733         {
734           gint x;
735           gint y;
736           gchar *buf;
737           GdkRectangle rect;
738           PangoLayout *layout;
739           PangoRectangle logical_rect;
740
741           buf = gtk_progress_get_current_text (progress);
742
743           layout = gtk_widget_create_pango_layout (widget, buf);
744           pango_layout_get_pixel_extents (layout, NULL, &logical_rect);
745           
746           x = widget->style->xthickness + 1 + 
747             (widget->allocation.width - 2 * widget->style->xthickness -
748              3 - logical_rect.width)
749             * progress->x_align; 
750
751           y = widget->style->ythickness + 1 +
752             (widget->allocation.height - 2 * widget->style->ythickness -
753              3 - logical_rect.height)
754             * progress->y_align;
755
756           rect.x = widget->style->xthickness + 1;
757           rect.y = widget->style->ythickness + 1;
758           rect.width = widget->allocation.width -
759             2 * widget->style->xthickness - 3;
760           rect.height = widget->allocation.height -
761             2 * widget->style->ythickness - 3;
762
763           gdk_gc_set_clip_rectangle (widget->style->fg_gc[widget->state],
764                                      &rect);
765
766           gdk_draw_layout (progress->offscreen_pixmap, 
767                            widget->style->fg_gc[widget->state],
768                            x, y, layout);
769
770           gdk_gc_set_clip_rectangle (widget->style->fg_gc[widget->state],
771                                      NULL);
772           g_object_unref (G_OBJECT (layout));
773           g_free (buf);
774         }
775     }
776 }
777
778 /*******************************************************************/
779
780 void
781 gtk_progress_bar_set_fraction (GtkProgressBar *pbar,
782                                gfloat          fraction)
783 {
784   g_return_if_fail (pbar != NULL);
785   g_return_if_fail (GTK_IS_PROGRESS_BAR (pbar));
786
787   /* If we know the percentage, we don't want activity mode. */
788   gtk_progress_set_activity_mode (GTK_PROGRESS (pbar), FALSE);
789   
790   /* We use the deprecated GtkProgress interface internally.
791    * Once everything's been deprecated for a good long time,
792    * we can clean up all this code.
793    */
794   gtk_progress_set_percentage (GTK_PROGRESS (pbar), fraction);
795 }
796
797 void
798 gtk_progress_bar_pulse (GtkProgressBar *pbar)
799 {  
800   g_return_if_fail (pbar != NULL);
801   g_return_if_fail (GTK_IS_PROGRESS_BAR (pbar));
802
803   /* If we don't know the percentage, we must want activity mode. */
804   gtk_progress_set_activity_mode (GTK_PROGRESS (pbar), TRUE);
805
806   /* Sigh. */
807   gtk_progress_bar_real_update (GTK_PROGRESS (pbar));
808 }
809
810 void
811 gtk_progress_bar_set_text (GtkProgressBar *pbar,
812                            const gchar *text)
813 {
814   g_return_if_fail (pbar != NULL);
815   g_return_if_fail (GTK_IS_PROGRESS_BAR (pbar));
816   
817   /* We don't support formats in this interface */
818   GTK_PROGRESS (pbar)->use_text_format = FALSE;
819   
820   if (text && *text)
821     {
822       gtk_progress_set_show_text (GTK_PROGRESS (pbar), TRUE);
823       gtk_progress_set_format_string (GTK_PROGRESS (pbar), text);
824     }
825   else
826     {
827       gtk_progress_set_show_text (GTK_PROGRESS (pbar), FALSE);
828       gtk_progress_set_format_string (GTK_PROGRESS (pbar), "");
829     }
830 }
831
832 void
833 gtk_progress_bar_set_pulse_step   (GtkProgressBar *pbar,
834                                    gfloat          fraction)
835 {
836   g_return_if_fail (pbar != NULL);
837   g_return_if_fail (GTK_IS_PROGRESS_BAR (pbar));
838   
839   pbar->pulse_fraction = fraction;
840 }
841
842 void
843 gtk_progress_bar_update (GtkProgressBar *pbar,
844                          gfloat          percentage)
845 {
846   g_return_if_fail (pbar != NULL);
847   g_return_if_fail (GTK_IS_PROGRESS_BAR (pbar));
848
849   /* Use of gtk_progress_bar_update() is deprecated ! 
850    * Use gtk_progress_bar_set_percentage ()
851    */   
852
853   gtk_progress_set_percentage (GTK_PROGRESS (pbar), percentage);
854 }
855
856 void
857 gtk_progress_bar_set_orientation (GtkProgressBar           *pbar,
858                                   GtkProgressBarOrientation orientation)
859 {
860   g_return_if_fail (pbar != NULL);
861   g_return_if_fail (GTK_IS_PROGRESS_BAR (pbar));
862
863   if (pbar->orientation != orientation)
864     {
865       pbar->orientation = orientation;
866
867       if (GTK_WIDGET_DRAWABLE (GTK_WIDGET (pbar)))
868         gtk_widget_queue_resize (GTK_WIDGET (pbar));
869     }
870 }
871
872 void
873 gtk_progress_bar_set_bar_style (GtkProgressBar     *pbar,
874                                 GtkProgressBarStyle bar_style)
875 {
876   g_return_if_fail (pbar != NULL);
877   g_return_if_fail (GTK_IS_PROGRESS_BAR (pbar));
878
879   if (pbar->bar_style != bar_style)
880     {
881       pbar->bar_style = bar_style;
882
883       if (GTK_WIDGET_DRAWABLE (GTK_WIDGET (pbar)))
884         gtk_widget_queue_resize (GTK_WIDGET (pbar));
885     }
886 }
887
888 void
889 gtk_progress_bar_set_discrete_blocks (GtkProgressBar *pbar,
890                                       guint           blocks)
891 {
892   g_return_if_fail (pbar != NULL);
893   g_return_if_fail (GTK_IS_PROGRESS_BAR (pbar));
894   g_return_if_fail (blocks > 1);
895
896   if (pbar->blocks != blocks)
897     {
898       pbar->blocks = blocks;
899
900       if (GTK_WIDGET_DRAWABLE (GTK_WIDGET (pbar)))
901         gtk_widget_queue_resize (GTK_WIDGET (pbar));
902     }
903 }
904
905 void
906 gtk_progress_bar_set_activity_step (GtkProgressBar *pbar,
907                                     guint           step)
908 {
909   g_return_if_fail (pbar != NULL);
910   g_return_if_fail (GTK_IS_PROGRESS_BAR (pbar));
911
912   if (pbar->activity_step != step)
913     pbar->activity_step = step;
914 }
915
916 void
917 gtk_progress_bar_set_activity_blocks (GtkProgressBar *pbar,
918                                       guint           blocks)
919 {
920   g_return_if_fail (pbar != NULL);
921   g_return_if_fail (GTK_IS_PROGRESS_BAR (pbar));
922   g_return_if_fail (blocks > 1);
923
924   if (pbar->activity_blocks != blocks)
925     pbar->activity_blocks = blocks;
926 }