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