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