]> Pileus Git - ~andy/gtk/blob - gtk/gtktogglebutton.c
call the base class init fucntions from all parent types upon class
[~andy/gtk] / gtk / gtktogglebutton.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
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19 #include "gtklabel.h"
20 #include "gtkmain.h"
21 #include "gtksignal.h"
22 #include "gtktogglebutton.h"
23
24
25 #define DEFAULT_LEFT_POS  4
26 #define DEFAULT_TOP_POS   4
27 #define DEFAULT_SPACING   7
28
29 enum {
30   TOGGLED,
31   LAST_SIGNAL
32 };
33
34 enum {
35   ARG_0,
36   ARG_ACTIVE,
37   ARG_DRAW_INDICATOR
38 };
39
40
41 static void gtk_toggle_button_class_init (GtkToggleButtonClass *klass);
42 static void gtk_toggle_button_init       (GtkToggleButton      *toggle_button);
43 static void gtk_toggle_button_draw_focus (GtkWidget            *widget);
44 static void gtk_toggle_button_pressed    (GtkButton            *button);
45 static void gtk_toggle_button_released   (GtkButton            *button);
46 static void gtk_toggle_button_clicked    (GtkButton            *button);
47 static void gtk_toggle_button_enter      (GtkButton            *button);
48 static void gtk_toggle_button_leave      (GtkButton            *button);
49 static void gtk_toggle_button_set_arg    (GtkObject            *object,
50                                           GtkArg               *arg,
51                                           guint                 arg_id);
52 static void gtk_toggle_button_get_arg    (GtkObject            *object,
53                                           GtkArg               *arg,
54                                           guint                 arg_id);
55      
56
57 static guint toggle_button_signals[LAST_SIGNAL] = { 0 };
58
59
60 GtkType
61 gtk_toggle_button_get_type (void)
62 {
63   static GtkType toggle_button_type = 0;
64
65   if (!toggle_button_type)
66     {
67       GtkTypeInfo toggle_button_info =
68       {
69         "GtkToggleButton",
70         sizeof (GtkToggleButton),
71         sizeof (GtkToggleButtonClass),
72         (GtkClassInitFunc) gtk_toggle_button_class_init,
73         (GtkObjectInitFunc) gtk_toggle_button_init,
74         /* reversed_1 */ NULL,
75         /* reversed_2 */ NULL,
76         (GtkClassInitFunc) NULL,
77       };
78
79       toggle_button_type = gtk_type_unique (gtk_button_get_type (), &toggle_button_info);
80     }
81
82   return toggle_button_type;
83 }
84
85 static void
86 gtk_toggle_button_class_init (GtkToggleButtonClass *class)
87 {
88   GtkObjectClass *object_class;
89   GtkWidgetClass *widget_class;
90   GtkContainerClass *container_class;
91   GtkButtonClass *button_class;
92
93   object_class = (GtkObjectClass*) class;
94   widget_class = (GtkWidgetClass*) class;
95   container_class = (GtkContainerClass*) class;
96   button_class = (GtkButtonClass*) class;
97
98   gtk_object_add_arg_type ("GtkToggleButton::active", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_ACTIVE);
99   gtk_object_add_arg_type ("GtkToggleButton::draw_indicator", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_DRAW_INDICATOR);
100
101   toggle_button_signals[TOGGLED] =
102     gtk_signal_new ("toggled",
103                     GTK_RUN_FIRST,
104                     object_class->type,
105                     GTK_SIGNAL_OFFSET (GtkToggleButtonClass, toggled),
106                     gtk_signal_default_marshaller,
107                     GTK_TYPE_NONE, 0);
108
109   gtk_object_class_add_signals (object_class, toggle_button_signals, LAST_SIGNAL);
110
111   object_class->set_arg = gtk_toggle_button_set_arg;
112   object_class->get_arg = gtk_toggle_button_get_arg;
113
114   widget_class->draw_focus = gtk_toggle_button_draw_focus;
115
116   button_class->pressed = gtk_toggle_button_pressed;
117   button_class->released = gtk_toggle_button_released;
118   button_class->clicked = gtk_toggle_button_clicked;
119   button_class->enter = gtk_toggle_button_enter;
120   button_class->leave = gtk_toggle_button_leave;
121
122   class->toggled = NULL;
123 }
124
125 static void
126 gtk_toggle_button_init (GtkToggleButton *toggle_button)
127 {
128   toggle_button->active = FALSE;
129   toggle_button->draw_indicator = FALSE;
130 }
131
132
133 GtkWidget*
134 gtk_toggle_button_new (void)
135 {
136   return GTK_WIDGET (gtk_type_new (gtk_toggle_button_get_type ()));
137 }
138
139 GtkWidget*
140 gtk_toggle_button_new_with_label (const gchar *label)
141 {
142   GtkWidget *toggle_button;
143   GtkWidget *label_widget;
144
145   toggle_button = gtk_toggle_button_new ();
146   label_widget = gtk_label_new (label);
147   gtk_misc_set_alignment (GTK_MISC (label_widget), 0.5, 0.5);
148
149   gtk_container_add (GTK_CONTAINER (toggle_button), label_widget);
150   gtk_widget_show (label_widget);
151
152   return toggle_button;
153 }
154
155 static void
156 gtk_toggle_button_set_arg (GtkObject *object,
157                            GtkArg    *arg,
158                            guint      arg_id)
159 {
160   GtkToggleButton *tb;
161
162   tb = GTK_TOGGLE_BUTTON (object);
163
164   switch (arg_id)
165     {
166     case ARG_ACTIVE:
167       gtk_toggle_button_set_state (tb, GTK_VALUE_BOOL (*arg));
168       break;
169     case ARG_DRAW_INDICATOR:
170       gtk_toggle_button_set_mode (tb, GTK_VALUE_BOOL (*arg));
171       break;
172     default:
173       break;
174     }
175 }
176
177 static void
178 gtk_toggle_button_get_arg (GtkObject *object,
179                            GtkArg    *arg,
180                            guint      arg_id)
181 {
182   GtkToggleButton *tb;
183
184   tb = GTK_TOGGLE_BUTTON (object);
185
186   switch (arg_id)
187     {
188     case ARG_ACTIVE:
189       GTK_VALUE_BOOL (*arg) = tb->active;
190       break;
191     case ARG_DRAW_INDICATOR:
192       GTK_VALUE_BOOL (*arg) = tb->draw_indicator;
193       break;
194     default:
195       arg->type = GTK_TYPE_INVALID;
196       break;
197     }
198 }
199
200 void
201 gtk_toggle_button_set_mode (GtkToggleButton *toggle_button,
202                             gint             draw_indicator)
203 {
204   g_return_if_fail (toggle_button != NULL);
205   g_return_if_fail (GTK_IS_TOGGLE_BUTTON (toggle_button));
206
207   draw_indicator = draw_indicator ? TRUE : FALSE;
208
209   if (toggle_button->draw_indicator != draw_indicator)
210     {
211       toggle_button->draw_indicator = draw_indicator;
212
213       if (GTK_WIDGET_VISIBLE (toggle_button))
214         gtk_widget_queue_resize (GTK_WIDGET (toggle_button));
215     }
216 }
217
218 void
219 gtk_toggle_button_set_state (GtkToggleButton *toggle_button,
220                              gint             state)
221 {
222   g_return_if_fail (toggle_button != NULL);
223   g_return_if_fail (GTK_IS_TOGGLE_BUTTON (toggle_button));
224
225   if (toggle_button->active != (state != FALSE))
226     gtk_button_clicked (GTK_BUTTON (toggle_button));
227 }
228
229 void
230 gtk_toggle_button_toggled (GtkToggleButton *toggle_button)
231 {
232   gtk_signal_emit (GTK_OBJECT (toggle_button), toggle_button_signals[TOGGLED]);
233 }
234
235
236 static void
237 gtk_toggle_button_draw_focus (GtkWidget *widget)
238 {
239   GtkButton *button;
240   GtkToggleButton *toggle_button;
241   GtkShadowType shadow_type;
242   gint width, height;
243   gint x, y;
244
245   g_return_if_fail (widget != NULL);
246   g_return_if_fail (GTK_IS_TOGGLE_BUTTON (widget));
247
248   if (GTK_WIDGET_DRAWABLE (widget))
249     {
250       button = GTK_BUTTON (widget);
251       toggle_button = GTK_TOGGLE_BUTTON (widget);
252
253       x = 0;
254       y = 0;
255       width = widget->allocation.width - GTK_CONTAINER (widget)->border_width * 2;
256       height = widget->allocation.height - GTK_CONTAINER (widget)->border_width * 2;
257
258       if (GTK_WIDGET_CAN_DEFAULT (widget))
259         {
260           x += widget->style->klass->xthickness;
261           y += widget->style->klass->ythickness;
262           width -= 2 * x + DEFAULT_SPACING;
263           height -= 2 * y + DEFAULT_SPACING;
264           x += DEFAULT_LEFT_POS;
265           y += DEFAULT_TOP_POS;
266         }
267
268       if (GTK_WIDGET_HAS_FOCUS (widget))
269         {
270           x += 1;
271           y += 1;
272           width -= 2;
273           height -= 2;
274         }
275       else
276         {
277           if (GTK_WIDGET_STATE (toggle_button) == GTK_STATE_ACTIVE)
278             gdk_draw_rectangle (widget->window,
279                                 widget->style->bg_gc[GTK_WIDGET_STATE (widget)], FALSE,
280                                 x + 1, y + 1, width - 4, height - 4);
281           else
282             gdk_draw_rectangle (widget->window,
283                                 widget->style->bg_gc[GTK_WIDGET_STATE (widget)], FALSE,
284                                 x + 2, y + 2, width - 5, height - 5);
285         }
286
287       if (toggle_button->active)
288         shadow_type = GTK_SHADOW_IN;
289       else
290         shadow_type = GTK_SHADOW_OUT;
291
292       gtk_draw_shadow (widget->style, widget->window,
293                        GTK_WIDGET_STATE (widget), shadow_type,
294                        x, y, width, height);
295
296       if (GTK_WIDGET_HAS_FOCUS (widget))
297         {
298           x -= 1;
299           y -= 1;
300           width += 2;
301           height += 2;
302
303           gdk_draw_rectangle (widget->window,
304                               widget->style->black_gc, FALSE,
305                               x, y, width - 1, height - 1);
306         }
307     }
308 }
309
310 static void
311 gtk_toggle_button_pressed (GtkButton *button)
312 {
313   GtkToggleButton *toggle_button;
314   GtkStateType new_state;
315
316   g_return_if_fail (button != NULL);
317   g_return_if_fail (GTK_IS_TOGGLE_BUTTON (button));
318
319   toggle_button = GTK_TOGGLE_BUTTON (button);
320
321   button->button_down = TRUE;
322
323   if (toggle_button->active)
324     new_state = (button->in_button ? GTK_STATE_NORMAL : GTK_STATE_ACTIVE);
325   else
326     new_state = (button->in_button ? GTK_STATE_ACTIVE : GTK_STATE_NORMAL);
327
328   if (GTK_WIDGET_STATE (button) != new_state)
329     {
330       gtk_widget_set_state (GTK_WIDGET (button), new_state);
331       gtk_widget_queue_draw (GTK_WIDGET (button));
332     }
333 }
334
335 static void
336 gtk_toggle_button_released (GtkButton *button)
337 {
338   GtkToggleButton *toggle_button;
339   GtkStateType new_state;
340
341   g_return_if_fail (button != NULL);
342   g_return_if_fail (GTK_IS_TOGGLE_BUTTON (button));
343
344   if (button->button_down)
345     {
346       toggle_button = GTK_TOGGLE_BUTTON (button);
347
348       button->button_down = FALSE;
349
350       if (button->in_button)
351         {
352           gtk_button_clicked (button);
353         }
354       else
355         {
356           if (toggle_button->active)
357             new_state = (button->in_button ? GTK_STATE_PRELIGHT : GTK_STATE_ACTIVE);
358           else
359             new_state = (button->in_button ? GTK_STATE_PRELIGHT : GTK_STATE_NORMAL);
360
361           if (GTK_WIDGET_STATE (button) != new_state)
362             {
363               gtk_widget_set_state (GTK_WIDGET (button), new_state);
364               gtk_widget_queue_draw (GTK_WIDGET (button));
365             }
366         }
367     }
368 }
369
370 static void
371 gtk_toggle_button_clicked (GtkButton *button)
372 {
373   GtkToggleButton *toggle_button;
374   GtkStateType new_state;
375
376   g_return_if_fail (button != NULL);
377   g_return_if_fail (GTK_IS_TOGGLE_BUTTON (button));
378
379   toggle_button = GTK_TOGGLE_BUTTON (button);
380   toggle_button->active = !toggle_button->active;
381
382   gtk_toggle_button_toggled (toggle_button);
383
384   if (toggle_button->active)
385     new_state = (button->in_button ? GTK_STATE_PRELIGHT : GTK_STATE_ACTIVE);
386   else
387     new_state = (button->in_button ? GTK_STATE_PRELIGHT : GTK_STATE_NORMAL);
388
389   if (GTK_WIDGET_STATE (button) != new_state)
390     gtk_widget_set_state (GTK_WIDGET (button), new_state);
391   gtk_widget_queue_draw (GTK_WIDGET (button));
392 }
393
394 static void
395 gtk_toggle_button_enter (GtkButton *button)
396 {
397   GtkToggleButton *toggle_button;
398   GtkStateType new_state;
399
400   g_return_if_fail (button != NULL);
401   g_return_if_fail (GTK_IS_TOGGLE_BUTTON (button));
402
403   toggle_button = GTK_TOGGLE_BUTTON (button);
404
405   if (toggle_button->active)
406     new_state = (button->button_down ? GTK_STATE_NORMAL : GTK_STATE_PRELIGHT);
407   else
408     new_state = (button->button_down ? GTK_STATE_ACTIVE : GTK_STATE_PRELIGHT);
409
410   if (GTK_WIDGET_STATE (button) != new_state)
411     {
412       gtk_widget_set_state (GTK_WIDGET (button), new_state);
413       gtk_widget_queue_draw (GTK_WIDGET (button));
414     }
415 }
416
417 static void
418 gtk_toggle_button_leave (GtkButton *button)
419 {
420   GtkToggleButton *toggle_button;
421   GtkStateType new_state;
422
423   g_return_if_fail (button != NULL);
424   g_return_if_fail (GTK_IS_TOGGLE_BUTTON (button));
425
426   toggle_button = GTK_TOGGLE_BUTTON (button);
427
428   new_state = (toggle_button->active ? GTK_STATE_ACTIVE : GTK_STATE_NORMAL);
429
430   if (GTK_WIDGET_STATE (button) != new_state)
431     {
432       gtk_widget_set_state (GTK_WIDGET (button), new_state);
433       gtk_widget_queue_draw (GTK_WIDGET (button));
434     }
435 }