]> Pileus Git - ~andy/gtk/blob - gtk/gtkprogressbar.c
Initial revision
[~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 Library 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  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the Free
16  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17  */
18 #include "gtkprogressbar.h"
19
20
21 #define MIN_WIDTH   200
22 #define MIN_HEIGHT  20
23
24
25 static void gtk_progress_bar_class_init    (GtkProgressBarClass *klass);
26 static void gtk_progress_bar_init          (GtkProgressBar      *pbar);
27 static void gtk_progress_bar_realize       (GtkWidget           *widget);
28 static void gtk_progress_bar_size_allocate (GtkWidget           *widget,
29                                             GtkAllocation       *allocation);
30 static gint gtk_progress_bar_expose        (GtkWidget           *widget,
31                                             GdkEventExpose      *event);
32 static void gtk_progress_bar_make_pixmap   (GtkProgressBar      *pbar);
33 static void gtk_progress_bar_paint         (GtkProgressBar      *pbar);
34
35
36 guint
37 gtk_progress_bar_get_type ()
38 {
39   static guint progress_bar_type = 0;
40
41   if (!progress_bar_type)
42     {
43       GtkTypeInfo progress_bar_info =
44       {
45         "GtkProgressBar",
46         sizeof (GtkProgressBar),
47         sizeof (GtkProgressBarClass),
48         (GtkClassInitFunc) gtk_progress_bar_class_init,
49         (GtkObjectInitFunc) gtk_progress_bar_init,
50         (GtkArgFunc) NULL,
51       };
52
53       progress_bar_type = gtk_type_unique (gtk_widget_get_type (), &progress_bar_info);
54     }
55
56   return progress_bar_type;
57 }
58
59 static void
60 gtk_progress_bar_class_init (GtkProgressBarClass *class)
61 {
62   GtkWidgetClass *widget_class;
63
64   widget_class = (GtkWidgetClass*) class;
65
66   widget_class->realize = gtk_progress_bar_realize;
67   widget_class->size_allocate = gtk_progress_bar_size_allocate;
68   widget_class->expose_event = gtk_progress_bar_expose;
69 }
70
71 static void
72 gtk_progress_bar_init (GtkProgressBar *pbar)
73 {
74   GTK_WIDGET_SET_FLAGS (pbar, GTK_BASIC);
75
76   GTK_WIDGET (pbar)->requisition.width = MIN_WIDTH;
77   GTK_WIDGET (pbar)->requisition.height = MIN_HEIGHT;
78   pbar->offscreen_pixmap = NULL;
79   pbar->percentage = 0;
80 }
81
82
83 GtkWidget*
84 gtk_progress_bar_new ()
85 {
86   return GTK_WIDGET (gtk_type_new (gtk_progress_bar_get_type ()));
87 }
88
89 void
90 gtk_progress_bar_update (GtkProgressBar *pbar,
91                          gfloat          percentage)
92 {
93   g_return_if_fail (pbar != NULL);
94   g_return_if_fail (GTK_IS_PROGRESS_BAR (pbar));
95
96   if (percentage < 0.0)
97     percentage = 0.0;
98   else if (percentage > 1.0)
99     percentage = 1.0;
100
101   if (pbar->percentage != percentage)
102     {
103       pbar->percentage = percentage;
104       gtk_progress_bar_paint (pbar);
105       gtk_widget_queue_draw (GTK_WIDGET (pbar));
106     }
107 }
108
109 static void
110 gtk_progress_bar_realize (GtkWidget *widget)
111 {
112   GtkProgressBar *pbar;
113   GdkWindowAttr attributes;
114   gint attributes_mask;
115
116   g_return_if_fail (widget != NULL);
117   g_return_if_fail (GTK_IS_PROGRESS_BAR (widget));
118
119   pbar = GTK_PROGRESS_BAR (widget);
120   GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
121
122   attributes.window_type = GDK_WINDOW_CHILD;
123   attributes.x = widget->allocation.x;
124   attributes.y = widget->allocation.y;
125   attributes.width = widget->allocation.width;
126   attributes.height = widget->allocation.height;
127   attributes.wclass = GDK_INPUT_OUTPUT;
128   attributes.visual = gtk_widget_get_visual (widget);
129   attributes.colormap = gtk_widget_get_colormap (widget);
130   attributes.event_mask = gtk_widget_get_events (widget);
131   attributes.event_mask |= GDK_EXPOSURE_MASK;
132
133   attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
134
135   widget->window = gdk_window_new (widget->parent->window, &attributes, attributes_mask);
136   gdk_window_set_user_data (widget->window, pbar);
137
138   widget->style = gtk_style_attach (widget->style, widget->window);
139   gtk_style_set_background (widget->style, widget->window, GTK_STATE_ACTIVE);
140
141   gtk_progress_bar_make_pixmap (pbar);
142 }
143
144 static void
145 gtk_progress_bar_size_allocate (GtkWidget     *widget,
146                                 GtkAllocation *allocation)
147 {
148   g_return_if_fail (widget != NULL);
149   g_return_if_fail (GTK_IS_PROGRESS_BAR (widget));
150   g_return_if_fail (allocation != NULL);
151
152   widget->allocation = *allocation;
153
154   if (GTK_WIDGET_REALIZED (widget))
155     {
156       gdk_window_move_resize (widget->window,
157                               allocation->x, allocation->y,
158                               allocation->width, allocation->height);
159
160       gtk_progress_bar_make_pixmap (GTK_PROGRESS_BAR (widget));
161     }
162 }
163
164 static gint
165 gtk_progress_bar_expose (GtkWidget      *widget,
166                          GdkEventExpose *event)
167 {
168   GtkProgressBar *pbar;
169
170   g_return_val_if_fail (widget != NULL, FALSE);
171   g_return_val_if_fail (GTK_IS_PROGRESS_BAR (widget), FALSE);
172   g_return_val_if_fail (event != NULL, FALSE);
173
174   if (GTK_WIDGET_DRAWABLE (widget))
175     {
176       pbar = GTK_PROGRESS_BAR (widget);
177
178       gdk_draw_pixmap (widget->window,
179                        widget->style->black_gc,
180                        pbar->offscreen_pixmap,
181                        0, 0, 0, 0,
182                        widget->allocation.width,
183                        widget->allocation.height);
184     }
185
186   return FALSE;
187 }
188
189 static void
190 gtk_progress_bar_make_pixmap (GtkProgressBar *pbar)
191 {
192   GtkWidget *widget;
193
194   g_return_if_fail (pbar != NULL);
195   g_return_if_fail (GTK_IS_PROGRESS_BAR (pbar));
196
197   if (GTK_WIDGET_REALIZED (pbar))
198     {
199       widget = GTK_WIDGET (pbar);
200
201       if (pbar->offscreen_pixmap)
202         gdk_pixmap_destroy (pbar->offscreen_pixmap);
203
204       pbar->offscreen_pixmap = gdk_pixmap_new (widget->window,
205                                                widget->allocation.width,
206                                                widget->allocation.height,
207                                                -1);
208
209       gtk_progress_bar_paint (pbar);
210     }
211 }
212
213 static void
214 gtk_progress_bar_paint (GtkProgressBar *pbar)
215 {
216   GtkWidget *widget;
217   int amount;
218
219   g_return_if_fail (pbar != NULL);
220   g_return_if_fail (GTK_IS_PROGRESS_BAR (pbar));
221
222   if (pbar->offscreen_pixmap)
223     {
224       widget = GTK_WIDGET (pbar);
225
226       gtk_draw_shadow (widget->style,
227                        pbar->offscreen_pixmap,
228                        GTK_STATE_NORMAL, GTK_SHADOW_IN, 0, 0,
229                        widget->allocation.width,
230                        widget->allocation.height);
231
232       gdk_draw_rectangle (pbar->offscreen_pixmap,
233                           widget->style->bg_gc[GTK_STATE_ACTIVE], TRUE,
234                           widget->style->klass->xthickness,
235                           widget->style->klass->ythickness,
236                           widget->allocation.width - widget->style->klass->xthickness * 2,
237                           widget->allocation.height - widget->style->klass->ythickness * 2);
238
239
240       amount = pbar->percentage * (widget->allocation.width - widget->style->klass->xthickness * 2);
241       if (amount > 0)
242         {
243           gdk_draw_rectangle (pbar->offscreen_pixmap,
244                               widget->style->bg_gc[GTK_STATE_PRELIGHT], TRUE,
245                               widget->style->klass->xthickness,
246                               widget->style->klass->ythickness,
247                               amount,
248                               widget->allocation.height - widget->style->klass->ythickness * 2);
249
250           gtk_draw_shadow (widget->style,
251                            pbar->offscreen_pixmap,
252                            GTK_STATE_PRELIGHT, GTK_SHADOW_OUT,
253                            widget->style->klass->xthickness,
254                            widget->style->klass->ythickness,
255                            amount,
256                            widget->allocation.height - widget->style->klass->ythickness * 2);
257         }
258     }
259 }