]> Pileus Git - ~andy/gtk/blob - gtk/gtktogglebutton.c
fc5e1f8e96223c2634cff25df2c8f5ec59871319
[~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
35 static void gtk_toggle_button_class_init (GtkToggleButtonClass *klass);
36 static void gtk_toggle_button_init       (GtkToggleButton      *toggle_button);
37 static void gtk_toggle_button_draw_focus (GtkWidget            *widget);
38 static void gtk_toggle_button_pressed    (GtkButton            *button);
39 static void gtk_toggle_button_released   (GtkButton            *button);
40 static void gtk_toggle_button_clicked    (GtkButton            *button);
41 static void gtk_toggle_button_enter      (GtkButton            *button);
42 static void gtk_toggle_button_leave      (GtkButton            *button);
43
44
45 static guint toggle_button_signals[LAST_SIGNAL] = { 0 };
46
47
48 guint
49 gtk_toggle_button_get_type (void)
50 {
51   static guint toggle_button_type = 0;
52
53   if (!toggle_button_type)
54     {
55       GtkTypeInfo toggle_button_info =
56       {
57         "GtkToggleButton",
58         sizeof (GtkToggleButton),
59         sizeof (GtkToggleButtonClass),
60         (GtkClassInitFunc) gtk_toggle_button_class_init,
61         (GtkObjectInitFunc) gtk_toggle_button_init,
62         (GtkArgSetFunc) NULL,
63         (GtkArgGetFunc) NULL,
64       };
65
66       toggle_button_type = gtk_type_unique (gtk_button_get_type (), &toggle_button_info);
67     }
68
69   return toggle_button_type;
70 }
71
72 static void
73 gtk_toggle_button_class_init (GtkToggleButtonClass *class)
74 {
75   GtkObjectClass *object_class;
76   GtkWidgetClass *widget_class;
77   GtkContainerClass *container_class;
78   GtkButtonClass *button_class;
79
80   object_class = (GtkObjectClass*) class;
81   widget_class = (GtkWidgetClass*) class;
82   container_class = (GtkContainerClass*) class;
83   button_class = (GtkButtonClass*) class;
84
85   toggle_button_signals[TOGGLED] =
86     gtk_signal_new ("toggled",
87                     GTK_RUN_FIRST,
88                     object_class->type,
89                     GTK_SIGNAL_OFFSET (GtkToggleButtonClass, toggled),
90                     gtk_signal_default_marshaller,
91                     GTK_TYPE_NONE, 0);
92
93   gtk_object_class_add_signals (object_class, toggle_button_signals, LAST_SIGNAL);
94
95   widget_class->draw_focus = gtk_toggle_button_draw_focus;
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 (void)
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 != FALSE))
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_DRAWABLE (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 - GTK_CONTAINER (widget)->border_width * 2;
192       height = widget->allocation.height - GTK_CONTAINER (widget)->border_width * 2;
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 (toggle_button) == 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 (toggle_button->active)
224         shadow_type = GTK_SHADOW_IN;
225       else
226         shadow_type = GTK_SHADOW_OUT;
227
228       gtk_draw_shadow (widget->style, widget->window,
229                        GTK_WIDGET_STATE (widget), shadow_type,
230                        x, y, width, height);
231
232       if (GTK_WIDGET_HAS_FOCUS (widget))
233         {
234           x -= 1;
235           y -= 1;
236           width += 2;
237           height += 2;
238
239           gdk_draw_rectangle (widget->window,
240                               widget->style->black_gc, FALSE,
241                               x, y, width - 1, height - 1);
242         }
243     }
244 }
245
246 static void
247 gtk_toggle_button_pressed (GtkButton *button)
248 {
249   GtkToggleButton *toggle_button;
250   GtkStateType new_state;
251
252   g_return_if_fail (button != NULL);
253   g_return_if_fail (GTK_IS_TOGGLE_BUTTON (button));
254
255   toggle_button = GTK_TOGGLE_BUTTON (button);
256
257   button->button_down = TRUE;
258
259   if (toggle_button->active)
260     new_state = (button->in_button ? GTK_STATE_NORMAL : GTK_STATE_ACTIVE);
261   else
262     new_state = (button->in_button ? GTK_STATE_ACTIVE : GTK_STATE_NORMAL);
263
264   if (GTK_WIDGET_STATE (button) != new_state)
265     {
266       gtk_widget_set_state (GTK_WIDGET (button), new_state);
267       gtk_widget_queue_draw (GTK_WIDGET (button));
268     }
269 }
270
271 static void
272 gtk_toggle_button_released (GtkButton *button)
273 {
274   GtkToggleButton *toggle_button;
275   GtkStateType new_state;
276
277   g_return_if_fail (button != NULL);
278   g_return_if_fail (GTK_IS_TOGGLE_BUTTON (button));
279
280   if (button->button_down)
281     {
282       toggle_button = GTK_TOGGLE_BUTTON (button);
283
284       button->button_down = FALSE;
285
286       if (button->in_button)
287         {
288           gtk_button_clicked (button);
289         }
290       else
291         {
292           if (toggle_button->active)
293             new_state = (button->in_button ? GTK_STATE_PRELIGHT : GTK_STATE_ACTIVE);
294           else
295             new_state = (button->in_button ? GTK_STATE_PRELIGHT : GTK_STATE_NORMAL);
296
297           if (GTK_WIDGET_STATE (button) != new_state)
298             {
299               gtk_widget_set_state (GTK_WIDGET (button), new_state);
300               gtk_widget_queue_draw (GTK_WIDGET (button));
301             }
302         }
303     }
304 }
305
306 static void
307 gtk_toggle_button_clicked (GtkButton *button)
308 {
309   GtkToggleButton *toggle_button;
310   GtkStateType new_state;
311
312   g_return_if_fail (button != NULL);
313   g_return_if_fail (GTK_IS_TOGGLE_BUTTON (button));
314
315   toggle_button = GTK_TOGGLE_BUTTON (button);
316   toggle_button->active = !toggle_button->active;
317
318   gtk_toggle_button_toggled (toggle_button);
319
320   if (toggle_button->active)
321     new_state = (button->in_button ? GTK_STATE_PRELIGHT : GTK_STATE_ACTIVE);
322   else
323     new_state = (button->in_button ? GTK_STATE_PRELIGHT : GTK_STATE_NORMAL);
324
325   if (GTK_WIDGET_STATE (button) != new_state)
326     gtk_widget_set_state (GTK_WIDGET (button), new_state);
327   gtk_widget_queue_draw (GTK_WIDGET (button));
328 }
329
330 static void
331 gtk_toggle_button_enter (GtkButton *button)
332 {
333   GtkToggleButton *toggle_button;
334   GtkStateType new_state;
335
336   g_return_if_fail (button != NULL);
337   g_return_if_fail (GTK_IS_TOGGLE_BUTTON (button));
338
339   toggle_button = GTK_TOGGLE_BUTTON (button);
340
341   if (toggle_button->active)
342     new_state = (button->button_down ? GTK_STATE_NORMAL : GTK_STATE_PRELIGHT);
343   else
344     new_state = (button->button_down ? GTK_STATE_ACTIVE : GTK_STATE_PRELIGHT);
345
346   if (GTK_WIDGET_STATE (button) != new_state)
347     {
348       gtk_widget_set_state (GTK_WIDGET (button), new_state);
349       gtk_widget_queue_draw (GTK_WIDGET (button));
350     }
351 }
352
353 static void
354 gtk_toggle_button_leave (GtkButton *button)
355 {
356   GtkToggleButton *toggle_button;
357   GtkStateType new_state;
358
359   g_return_if_fail (button != NULL);
360   g_return_if_fail (GTK_IS_TOGGLE_BUTTON (button));
361
362   toggle_button = GTK_TOGGLE_BUTTON (button);
363
364   new_state = (toggle_button->active ? GTK_STATE_ACTIVE : GTK_STATE_NORMAL);
365
366   if (GTK_WIDGET_STATE (button) != new_state)
367     {
368       gtk_widget_set_state (GTK_WIDGET (button), new_state);
369       gtk_widget_queue_draw (GTK_WIDGET (button));
370     }
371 }