source: trunk/third/gtk/gtk/gtkradiobutton.c @ 17071

Revision 17071, 11.0 KB checked in by ghudson, 23 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r17070, which included commits to RCS files with non-trunk default branches.
Line 
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
20/*
21 * Modified by the GTK+ Team and others 1997-1999.  See the AUTHORS
22 * file for a list of people on the GTK+ Team.  See the ChangeLog
23 * files for a list of changes.  These files are distributed with
24 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
25 */
26
27#include "gtklabel.h"
28#include "gtkradiobutton.h"
29#include "gtksignal.h"
30
31
32enum {
33  ARG_0,
34  ARG_GROUP
35};
36
37#define CHECK_BUTTON_CLASS(w)  GTK_CHECK_BUTTON_CLASS (GTK_OBJECT (w)->klass)
38
39
40static void gtk_radio_button_class_init     (GtkRadioButtonClass  *klass);
41static void gtk_radio_button_init           (GtkRadioButton       *radio_button);
42static void gtk_radio_button_destroy        (GtkObject            *object);
43static void gtk_radio_button_clicked        (GtkButton            *button);
44static void gtk_radio_button_draw_indicator (GtkCheckButton       *check_button,
45                                             GdkRectangle         *area);
46static void gtk_radio_button_set_arg        (GtkObject            *object,
47                                             GtkArg               *arg,
48                                             guint                 arg_id);
49static void gtk_radio_button_get_arg        (GtkObject            *object,
50                                             GtkArg               *arg,
51                                             guint                 arg_id);
52
53
54static GtkCheckButtonClass *parent_class = NULL;
55
56
57GtkType
58gtk_radio_button_get_type (void)
59{
60  static GtkType radio_button_type = 0;
61
62  if (!radio_button_type)
63    {
64      static const GtkTypeInfo radio_button_info =
65      {
66        "GtkRadioButton",
67        sizeof (GtkRadioButton),
68        sizeof (GtkRadioButtonClass),
69        (GtkClassInitFunc) gtk_radio_button_class_init,
70        (GtkObjectInitFunc) gtk_radio_button_init,
71        /* reserved_1 */ NULL,
72        /* reserved_2 */ NULL,
73        (GtkClassInitFunc) NULL,
74      };
75
76      radio_button_type = gtk_type_unique (gtk_check_button_get_type (), &radio_button_info);
77    }
78
79  return radio_button_type;
80}
81
82static void
83gtk_radio_button_class_init (GtkRadioButtonClass *class)
84{
85  GtkObjectClass *object_class;
86  GtkButtonClass *button_class;
87  GtkCheckButtonClass *check_button_class;
88
89  object_class = (GtkObjectClass*) class;
90  button_class = (GtkButtonClass*) class;
91  check_button_class = (GtkCheckButtonClass*) class;
92
93  parent_class = gtk_type_class (gtk_check_button_get_type ());
94
95  gtk_object_add_arg_type ("GtkRadioButton::group", GTK_TYPE_RADIO_BUTTON, GTK_ARG_WRITABLE, ARG_GROUP);
96
97  object_class->set_arg = gtk_radio_button_set_arg;
98  object_class->get_arg = gtk_radio_button_get_arg;
99  object_class->destroy = gtk_radio_button_destroy;
100
101  button_class->clicked = gtk_radio_button_clicked;
102
103  check_button_class->draw_indicator = gtk_radio_button_draw_indicator;
104}
105
106static void
107gtk_radio_button_init (GtkRadioButton *radio_button)
108{
109  GTK_WIDGET_SET_FLAGS (radio_button, GTK_NO_WINDOW);
110  GTK_WIDGET_UNSET_FLAGS (radio_button, GTK_RECEIVES_DEFAULT);
111
112  GTK_TOGGLE_BUTTON (radio_button)->active = TRUE;
113
114  radio_button->group = g_slist_prepend (NULL, radio_button);
115
116  gtk_widget_set_state (GTK_WIDGET (radio_button), GTK_STATE_ACTIVE);
117}
118
119static void
120gtk_radio_button_set_arg (GtkObject      *object,
121                          GtkArg         *arg,
122                          guint           arg_id)
123{
124  GtkRadioButton *radio_button;
125
126  radio_button = GTK_RADIO_BUTTON (object);
127
128  switch (arg_id)
129    {
130      GSList *slist;
131
132    case ARG_GROUP:
133      if (GTK_VALUE_OBJECT (*arg))
134        slist = gtk_radio_button_group ((GtkRadioButton*) GTK_VALUE_OBJECT (*arg));
135      else
136        slist = NULL;
137      gtk_radio_button_set_group (radio_button, slist);
138      break;
139    default:
140      break;
141    }
142}
143
144static void
145gtk_radio_button_get_arg (GtkObject      *object,
146                          GtkArg         *arg,
147                          guint           arg_id)
148{
149  GtkRadioButton *radio_button;
150
151  radio_button = GTK_RADIO_BUTTON (object);
152
153  switch (arg_id)
154    {
155    default:
156      arg->type = GTK_TYPE_INVALID;
157      break;
158    }
159}
160
161void
162gtk_radio_button_set_group (GtkRadioButton *radio_button,
163                            GSList         *group)
164{
165  g_return_if_fail (radio_button != NULL);
166  g_return_if_fail (GTK_IS_RADIO_BUTTON (radio_button));
167  g_return_if_fail (!g_slist_find (group, radio_button));
168
169  if (radio_button->group)
170    {
171      GSList *slist;
172     
173      radio_button->group = g_slist_remove (radio_button->group, radio_button);
174     
175      for (slist = radio_button->group; slist; slist = slist->next)
176        {
177          GtkRadioButton *tmp_button;
178         
179          tmp_button = slist->data;
180         
181          tmp_button->group = radio_button->group;
182        }
183    }
184 
185  radio_button->group = g_slist_prepend (group, radio_button);
186 
187  if (group)
188    {
189      GSList *slist;
190     
191      for (slist = group; slist; slist = slist->next)
192        {
193          GtkRadioButton *tmp_button;
194         
195          tmp_button = slist->data;
196         
197          tmp_button->group = radio_button->group;
198        }
199    }
200
201  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (radio_button), group == NULL);
202}
203
204GtkWidget*
205gtk_radio_button_new (GSList *group)
206{
207  GtkRadioButton *radio_button;
208
209  radio_button = gtk_type_new (gtk_radio_button_get_type ());
210
211  if (group)
212    gtk_radio_button_set_group (radio_button, group);
213
214  return GTK_WIDGET (radio_button);
215}
216
217GtkWidget*
218gtk_radio_button_new_with_label (GSList      *group,
219                                 const gchar *label)
220{
221  GtkWidget *radio_button;
222  GtkWidget *label_widget;
223
224  radio_button = gtk_radio_button_new (group);
225  label_widget = gtk_label_new (label);
226  gtk_misc_set_alignment (GTK_MISC (label_widget), 0.0, 0.5);
227
228  gtk_container_add (GTK_CONTAINER (radio_button), label_widget);
229  gtk_widget_show (label_widget);
230
231  return radio_button;
232}
233
234GtkWidget*
235gtk_radio_button_new_from_widget (GtkRadioButton *group)
236{
237  GSList *l = NULL;
238  if (group)
239    l = gtk_radio_button_group (group);
240  return gtk_radio_button_new (l);
241}
242
243
244GtkWidget*
245gtk_radio_button_new_with_label_from_widget (GtkRadioButton *group,
246                                             const gchar    *label)
247{
248  GSList *l = NULL;
249  if (group)
250    l = gtk_radio_button_group (group);
251  return gtk_radio_button_new_with_label (l, label);
252}
253
254GSList*
255gtk_radio_button_group (GtkRadioButton *radio_button)
256{
257  g_return_val_if_fail (radio_button != NULL, NULL);
258  g_return_val_if_fail (GTK_IS_RADIO_BUTTON (radio_button), NULL);
259
260  return radio_button->group;
261}
262
263
264static void
265gtk_radio_button_destroy (GtkObject *object)
266{
267  GtkRadioButton *radio_button;
268  GtkRadioButton *tmp_button;
269  GSList *tmp_list;
270
271  g_return_if_fail (object != NULL);
272  g_return_if_fail (GTK_IS_RADIO_BUTTON (object));
273
274  radio_button = GTK_RADIO_BUTTON (object);
275
276  radio_button->group = g_slist_remove (radio_button->group, radio_button);
277  tmp_list = radio_button->group;
278
279  while (tmp_list)
280    {
281      tmp_button = tmp_list->data;
282      tmp_list = tmp_list->next;
283
284      tmp_button->group = radio_button->group;
285    }
286
287  if (GTK_OBJECT_CLASS (parent_class)->destroy)
288    (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
289}
290
291static void
292gtk_radio_button_clicked (GtkButton *button)
293{
294  GtkToggleButton *toggle_button;
295  GtkRadioButton *radio_button;
296  GtkToggleButton *tmp_button;
297  GtkStateType new_state;
298  GSList *tmp_list;
299  gint toggled;
300
301  g_return_if_fail (button != NULL);
302  g_return_if_fail (GTK_IS_RADIO_BUTTON (button));
303
304  radio_button = GTK_RADIO_BUTTON (button);
305  toggle_button = GTK_TOGGLE_BUTTON (button);
306  toggled = FALSE;
307
308  gtk_widget_ref (GTK_WIDGET (button));
309
310  if (toggle_button->active)
311    {
312      tmp_button = NULL;
313      tmp_list = radio_button->group;
314
315      while (tmp_list)
316        {
317          tmp_button = tmp_list->data;
318          tmp_list = tmp_list->next;
319
320          if (tmp_button->active && tmp_button != toggle_button)
321            break;
322
323          tmp_button = NULL;
324        }
325
326      if (!tmp_button)
327        {
328          new_state = (button->in_button ? GTK_STATE_PRELIGHT : GTK_STATE_ACTIVE);
329        }
330      else
331        {
332          toggled = TRUE;
333          toggle_button->active = !toggle_button->active;
334          new_state = (button->in_button ? GTK_STATE_PRELIGHT : GTK_STATE_NORMAL);
335        }
336    }
337  else
338    {
339      toggled = TRUE;
340      toggle_button->active = !toggle_button->active;
341
342      tmp_list = radio_button->group;
343      while (tmp_list)
344        {
345          tmp_button = tmp_list->data;
346          tmp_list = tmp_list->next;
347
348          if (tmp_button->active && (tmp_button != toggle_button))
349            {
350              gtk_button_clicked (GTK_BUTTON (tmp_button));
351              break;
352            }
353        }
354
355      new_state = (button->in_button ? GTK_STATE_PRELIGHT : GTK_STATE_ACTIVE);
356    }
357
358  if (GTK_WIDGET_STATE (button) != new_state)
359    gtk_widget_set_state (GTK_WIDGET (button), new_state);
360
361  if (toggled)
362    gtk_toggle_button_toggled (toggle_button);
363
364  gtk_widget_queue_draw (GTK_WIDGET (button));
365
366  gtk_widget_unref (GTK_WIDGET (button));
367}
368
369static void
370gtk_radio_button_draw_indicator (GtkCheckButton *check_button,
371                                 GdkRectangle   *area)
372{
373  GtkWidget *widget;
374  GtkButton *button;
375  GtkToggleButton *toggle_button;
376  GtkStateType state_type;
377  GtkShadowType shadow_type;
378  GdkRectangle restrict_area;
379  GdkRectangle new_area;
380  gint x, y;
381  gint indicator_size, indicator_spacing;
382
383  g_return_if_fail (check_button != NULL);
384  g_return_if_fail (GTK_IS_RADIO_BUTTON (check_button));
385
386  if (GTK_WIDGET_VISIBLE (check_button) && GTK_WIDGET_MAPPED (check_button))
387    {
388      widget = GTK_WIDGET (check_button);
389      button = GTK_BUTTON (check_button);
390      toggle_button = GTK_TOGGLE_BUTTON (check_button);
391
392      state_type = GTK_WIDGET_STATE (widget);
393      if ((state_type != GTK_STATE_NORMAL) &&
394          (state_type != GTK_STATE_PRELIGHT))
395        state_type = GTK_STATE_NORMAL;
396
397      _gtk_check_button_get_props (check_button, &indicator_size, &indicator_spacing);
398
399      restrict_area.x = widget->allocation.x + GTK_CONTAINER (widget)->border_width;
400      restrict_area.y = widget->allocation.y + GTK_CONTAINER (widget)->border_width;
401      restrict_area.width = widget->allocation.width - ( 2 * GTK_CONTAINER (widget)->border_width);
402      restrict_area.height = widget->allocation.height - ( 2 * GTK_CONTAINER (widget)->border_width);
403
404      if (gdk_rectangle_intersect (area, &restrict_area, &new_area))
405        {
406           if (state_type != GTK_STATE_NORMAL)
407             gtk_paint_flat_box(widget->style, widget->window, state_type,
408                                GTK_SHADOW_ETCHED_OUT,
409                                area, widget, "radiobutton",
410                                new_area.x, new_area.y,
411                                new_area.width, new_area.height);
412        }
413     
414      x = widget->allocation.x + indicator_spacing + GTK_CONTAINER (widget)->border_width;
415      y = widget->allocation.y + ((gint)widget->allocation.height - indicator_size) / 2;
416      if (GTK_TOGGLE_BUTTON (widget)->active)
417        shadow_type = GTK_SHADOW_IN;
418      else
419        shadow_type = GTK_SHADOW_OUT;
420     
421      gtk_paint_option (widget->style, widget->window,
422                        GTK_WIDGET_STATE (widget), shadow_type,
423                        area, widget, "radiobutton",
424                        x, y, indicator_size, indicator_size);
425    }
426}
Note: See TracBrowser for help on using the repository browser.