1 /* GTK - The GIMP Toolkit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
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.
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.
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.
20 #include "gtkradiobutton.h"
21 #include "gtksignal.h"
29 #define CHECK_BUTTON_CLASS(w) GTK_CHECK_BUTTON_CLASS (GTK_OBJECT (w)->klass)
32 static void gtk_radio_button_class_init (GtkRadioButtonClass *klass);
33 static void gtk_radio_button_init (GtkRadioButton *radio_button);
34 static void gtk_radio_button_destroy (GtkObject *object);
35 static void gtk_radio_button_clicked (GtkButton *button);
36 static void gtk_radio_button_draw_indicator (GtkCheckButton *check_button,
38 static void gtk_radio_button_set_arg (GtkRadioButton *radio_button,
41 static void gtk_radio_button_get_arg (GtkRadioButton *radio_button,
46 static GtkCheckButtonClass *parent_class = NULL;
50 gtk_radio_button_get_type (void)
52 static GtkType radio_button_type = 0;
54 if (!radio_button_type)
56 GtkTypeInfo radio_button_info =
59 sizeof (GtkRadioButton),
60 sizeof (GtkRadioButtonClass),
61 (GtkClassInitFunc) gtk_radio_button_class_init,
62 (GtkObjectInitFunc) gtk_radio_button_init,
63 (GtkArgSetFunc) gtk_radio_button_set_arg,
64 (GtkArgGetFunc) gtk_radio_button_get_arg,
67 radio_button_type = gtk_type_unique (gtk_check_button_get_type (), &radio_button_info);
70 return radio_button_type;
74 gtk_radio_button_class_init (GtkRadioButtonClass *class)
76 GtkObjectClass *object_class;
77 GtkButtonClass *button_class;
78 GtkCheckButtonClass *check_button_class;
80 object_class = (GtkObjectClass*) class;
81 button_class = (GtkButtonClass*) class;
82 check_button_class = (GtkCheckButtonClass*) class;
84 parent_class = gtk_type_class (gtk_check_button_get_type ());
86 gtk_object_add_arg_type ("GtkRadioButton::group", GTK_TYPE_RADIO_BUTTON, GTK_ARG_WRITABLE, ARG_GROUP);
88 object_class->destroy = gtk_radio_button_destroy;
90 button_class->clicked = gtk_radio_button_clicked;
92 check_button_class->draw_indicator = gtk_radio_button_draw_indicator;
96 gtk_radio_button_init (GtkRadioButton *radio_button)
98 radio_button->group = g_slist_prepend (NULL, radio_button);
102 gtk_radio_button_set_arg (GtkRadioButton *radio_button,
111 if (GTK_VALUE_OBJECT (*arg))
112 slist = gtk_radio_button_group ((GtkRadioButton*) GTK_VALUE_OBJECT (*arg));
115 gtk_radio_button_set_group (radio_button, slist);
123 gtk_radio_button_get_arg (GtkRadioButton *radio_button,
130 arg->type = GTK_TYPE_INVALID;
136 gtk_radio_button_set_group (GtkRadioButton *radio_button,
139 g_return_if_fail (radio_button != NULL);
140 g_return_if_fail (GTK_IS_RADIO_BUTTON (radio_button));
141 g_return_if_fail (!g_slist_find (group, radio_button));
143 if (radio_button->group)
147 radio_button->group = g_slist_remove (radio_button->group, radio_button);
149 for (slist = radio_button->group; slist; slist = slist->next)
151 GtkRadioButton *tmp_button;
153 tmp_button = slist->data;
155 tmp_button->group = radio_button->group;
159 radio_button->group = g_slist_prepend (group, radio_button);
165 for (slist = group; slist; slist = slist->next)
167 GtkRadioButton *tmp_button;
169 tmp_button = slist->data;
171 tmp_button->group = radio_button->group;
176 GTK_TOGGLE_BUTTON (radio_button)->active = TRUE;
177 gtk_widget_set_state (GTK_WIDGET (radio_button), GTK_STATE_ACTIVE);
182 gtk_radio_button_new (GSList *group)
184 GtkRadioButton *radio_button;
186 radio_button = gtk_type_new (gtk_radio_button_get_type ());
188 gtk_radio_button_set_group (radio_button, group);
190 return GTK_WIDGET (radio_button);
194 gtk_radio_button_new_with_label (GSList *group,
197 GtkWidget *radio_button;
198 GtkWidget *label_widget;
200 radio_button = gtk_radio_button_new (group);
201 label_widget = gtk_label_new (label);
202 gtk_misc_set_alignment (GTK_MISC (label_widget), 0.0, 0.5);
204 gtk_container_add (GTK_CONTAINER (radio_button), label_widget);
205 gtk_widget_show (label_widget);
211 gtk_radio_button_new_from_widget (GtkRadioButton *group)
215 l = gtk_radio_button_group (group);
216 return gtk_radio_button_new (l);
221 gtk_radio_button_new_with_label_from_widget (GtkRadioButton *group,
226 l = gtk_radio_button_group (group);
227 return gtk_radio_button_new_with_label (l, label);
231 gtk_radio_button_group (GtkRadioButton *radio_button)
233 g_return_val_if_fail (radio_button != NULL, NULL);
234 g_return_val_if_fail (GTK_IS_RADIO_BUTTON (radio_button), NULL);
236 return radio_button->group;
241 gtk_radio_button_destroy (GtkObject *object)
243 GtkRadioButton *radio_button;
244 GtkRadioButton *tmp_button;
247 g_return_if_fail (object != NULL);
248 g_return_if_fail (GTK_IS_RADIO_BUTTON (object));
250 radio_button = GTK_RADIO_BUTTON (object);
252 radio_button->group = g_slist_remove (radio_button->group, radio_button);
253 tmp_list = radio_button->group;
257 tmp_button = tmp_list->data;
258 tmp_list = tmp_list->next;
260 tmp_button->group = radio_button->group;
263 if (GTK_OBJECT_CLASS (parent_class)->destroy)
264 (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
268 gtk_radio_button_clicked (GtkButton *button)
270 GtkToggleButton *toggle_button;
271 GtkRadioButton *radio_button;
272 GtkToggleButton *tmp_button;
273 GtkStateType new_state;
277 g_return_if_fail (button != NULL);
278 g_return_if_fail (GTK_IS_RADIO_BUTTON (button));
280 radio_button = GTK_RADIO_BUTTON (button);
281 toggle_button = GTK_TOGGLE_BUTTON (button);
284 if (toggle_button->active)
287 tmp_list = radio_button->group;
291 tmp_button = tmp_list->data;
292 tmp_list = tmp_list->next;
294 if (tmp_button->active && (tmp_button != toggle_button))
302 new_state = (button->in_button ? GTK_STATE_PRELIGHT : GTK_STATE_ACTIVE);
307 toggle_button->active = !toggle_button->active;
308 new_state = (button->in_button ? GTK_STATE_PRELIGHT : GTK_STATE_NORMAL);
314 toggle_button->active = !toggle_button->active;
316 tmp_list = radio_button->group;
319 tmp_button = tmp_list->data;
320 tmp_list = tmp_list->next;
322 if (tmp_button->active && (tmp_button != toggle_button))
324 gtk_button_clicked (GTK_BUTTON (tmp_button));
329 new_state = (button->in_button ? GTK_STATE_PRELIGHT : GTK_STATE_ACTIVE);
332 if (GTK_WIDGET_STATE (button) != new_state)
333 gtk_widget_set_state (GTK_WIDGET (button), new_state);
335 gtk_toggle_button_toggled (toggle_button);
336 gtk_widget_queue_draw (GTK_WIDGET (button));
340 gtk_radio_button_draw_indicator (GtkCheckButton *check_button,
345 GtkToggleButton *toggle_button;
346 GtkStateType state_type;
347 GtkShadowType shadow_type;
348 GdkRectangle restrict_area;
349 GdkRectangle new_area;
354 g_return_if_fail (check_button != NULL);
355 g_return_if_fail (GTK_IS_RADIO_BUTTON (check_button));
357 if (GTK_WIDGET_VISIBLE (check_button) && GTK_WIDGET_MAPPED (check_button))
359 widget = GTK_WIDGET (check_button);
360 button = GTK_BUTTON (check_button);
361 toggle_button = GTK_TOGGLE_BUTTON (check_button);
363 state_type = GTK_WIDGET_STATE (widget);
364 if ((state_type != GTK_STATE_NORMAL) &&
365 (state_type != GTK_STATE_PRELIGHT))
366 state_type = GTK_STATE_NORMAL;
368 restrict_area.x = GTK_CONTAINER (widget)->border_width;
369 restrict_area.y = restrict_area.x;
370 restrict_area.width = widget->allocation.width - restrict_area.x * 2;
371 restrict_area.height = widget->allocation.height - restrict_area.x * 2;
373 if (gdk_rectangle_intersect (area, &restrict_area, &new_area))
375 gtk_style_set_background (widget->style, widget->window, state_type);
376 gdk_window_clear_area (widget->window, new_area.x, new_area.y,
377 new_area.width, new_area.height);
380 x = CHECK_BUTTON_CLASS (widget)->indicator_spacing + GTK_CONTAINER (widget)->border_width;
381 y = (widget->allocation.height - CHECK_BUTTON_CLASS (widget)->indicator_size) / 2;
382 width = CHECK_BUTTON_CLASS (widget)->indicator_size;
383 height = CHECK_BUTTON_CLASS (widget)->indicator_size;
385 if (GTK_TOGGLE_BUTTON (widget)->active)
386 shadow_type = GTK_SHADOW_IN;
388 shadow_type = GTK_SHADOW_OUT;
390 pts[0].x = x + width / 2;
392 pts[1].x = x + width;
393 pts[1].y = y + height / 2;
395 pts[2].y = y + height;
399 gdk_draw_polygon (widget->window,
400 widget->style->bg_gc[GTK_WIDGET_STATE (widget)],
402 gtk_draw_diamond (widget->style, widget->window,
403 GTK_WIDGET_STATE (widget), shadow_type,
404 x, y, width, height);