]> Pileus Git - ~andy/gtk/blob - gtk/gtkradiomenuitem.c
Make this compile without framebuffer enabled
[~andy/gtk] / gtk / gtkradiomenuitem.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
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 "gtkaccellabel.h"
28 #include "gtkradiomenuitem.h"
29
30
31 static void gtk_radio_menu_item_class_init     (GtkRadioMenuItemClass *klass);
32 static void gtk_radio_menu_item_init           (GtkRadioMenuItem      *radio_menu_item);
33 static void gtk_radio_menu_item_destroy        (GtkObject             *object);
34 static void gtk_radio_menu_item_activate       (GtkMenuItem           *menu_item);
35 static void gtk_radio_menu_item_draw_indicator (GtkCheckMenuItem      *check_menu_item,
36                                                 GdkRectangle          *area);
37
38 static GtkCheckMenuItemClass *parent_class = NULL;
39
40 GtkType
41 gtk_radio_menu_item_get_type (void)
42 {
43   static GtkType radio_menu_item_type = 0;
44
45   if (!radio_menu_item_type)
46     {
47       static const GtkTypeInfo radio_menu_item_info =
48       {
49         "GtkRadioMenuItem",
50         sizeof (GtkRadioMenuItem),
51         sizeof (GtkRadioMenuItemClass),
52         (GtkClassInitFunc) gtk_radio_menu_item_class_init,
53         (GtkObjectInitFunc) gtk_radio_menu_item_init,
54         /* reserved_1 */ NULL,
55         /* reserved_2 */ NULL,
56         (GtkClassInitFunc) NULL,
57       };
58
59       radio_menu_item_type = gtk_type_unique (gtk_check_menu_item_get_type (), &radio_menu_item_info);
60     }
61
62   return radio_menu_item_type;
63 }
64
65 GtkWidget*
66 gtk_radio_menu_item_new (GSList *group)
67 {
68   GtkRadioMenuItem *radio_menu_item;
69
70   radio_menu_item = gtk_type_new (gtk_radio_menu_item_get_type ());
71
72   gtk_radio_menu_item_set_group (radio_menu_item, group);
73
74   return GTK_WIDGET (radio_menu_item);
75 }
76
77 void
78 gtk_radio_menu_item_set_group (GtkRadioMenuItem *radio_menu_item,
79                                GSList           *group)
80 {
81   g_return_if_fail (radio_menu_item != NULL);
82   g_return_if_fail (GTK_IS_RADIO_MENU_ITEM (radio_menu_item));
83   g_return_if_fail (!g_slist_find (group, radio_menu_item));
84   
85   if (radio_menu_item->group)
86     {
87       GSList *slist;
88       
89       radio_menu_item->group = g_slist_remove (radio_menu_item->group, radio_menu_item);
90       
91       for (slist = radio_menu_item->group; slist; slist = slist->next)
92         {
93           GtkRadioMenuItem *tmp_item;
94           
95           tmp_item = slist->data;
96           
97           tmp_item->group = radio_menu_item->group;
98         }
99     }
100   
101   radio_menu_item->group = g_slist_prepend (group, radio_menu_item);
102   
103   if (group)
104     {
105       GSList *slist;
106       
107       for (slist = group; slist; slist = slist->next)
108         {
109           GtkRadioMenuItem *tmp_item;
110           
111           tmp_item = slist->data;
112           
113           tmp_item->group = radio_menu_item->group;
114         }
115     }
116   else
117     {
118       GTK_CHECK_MENU_ITEM (radio_menu_item)->active = TRUE;
119       /* gtk_widget_set_state (GTK_WIDGET (radio_menu_item), GTK_STATE_ACTIVE);
120        */
121     }
122 }
123
124 GtkWidget*
125 gtk_radio_menu_item_new_with_label (GSList *group,
126                                     const gchar *label)
127 {
128   GtkWidget *radio_menu_item;
129   GtkWidget *accel_label;
130
131   radio_menu_item = gtk_radio_menu_item_new (group);
132   accel_label = gtk_accel_label_new (label);
133   gtk_misc_set_alignment (GTK_MISC (accel_label), 0.0, 0.5);
134   gtk_container_add (GTK_CONTAINER (radio_menu_item), accel_label);
135   gtk_accel_label_set_accel_widget (GTK_ACCEL_LABEL (accel_label), radio_menu_item);
136   gtk_widget_show (accel_label);
137
138   return radio_menu_item;
139 }
140
141 GSList*
142 gtk_radio_menu_item_group (GtkRadioMenuItem *radio_menu_item)
143 {
144   g_return_val_if_fail (radio_menu_item != NULL, NULL);
145   g_return_val_if_fail (GTK_IS_RADIO_MENU_ITEM (radio_menu_item), NULL);
146
147   return radio_menu_item->group;
148 }
149
150
151 static void
152 gtk_radio_menu_item_class_init (GtkRadioMenuItemClass *klass)
153 {
154   GtkObjectClass *object_class;
155   GtkMenuItemClass *menu_item_class;
156   GtkCheckMenuItemClass *check_menu_item_class;
157
158   object_class = (GtkObjectClass*) klass;
159   menu_item_class = (GtkMenuItemClass*) klass;
160   check_menu_item_class = (GtkCheckMenuItemClass*) klass;
161
162   parent_class = gtk_type_class (gtk_check_menu_item_get_type ());
163
164   object_class->destroy = gtk_radio_menu_item_destroy;
165
166   menu_item_class->activate = gtk_radio_menu_item_activate;
167
168   check_menu_item_class->draw_indicator = gtk_radio_menu_item_draw_indicator;
169 }
170
171 static void
172 gtk_radio_menu_item_init (GtkRadioMenuItem *radio_menu_item)
173 {
174   radio_menu_item->group = g_slist_prepend (NULL, radio_menu_item);
175 }
176
177 static void
178 gtk_radio_menu_item_destroy (GtkObject *object)
179 {
180   GtkRadioMenuItem *radio_menu_item;
181   GtkRadioMenuItem *tmp_menu_item;
182   GSList *tmp_list;
183
184   g_return_if_fail (object != NULL);
185   g_return_if_fail (GTK_IS_RADIO_MENU_ITEM (object));
186
187   radio_menu_item = GTK_RADIO_MENU_ITEM (object);
188
189   radio_menu_item->group = g_slist_remove (radio_menu_item->group,
190                                            radio_menu_item);
191   tmp_list = radio_menu_item->group;
192
193   while (tmp_list)
194     {
195       tmp_menu_item = tmp_list->data;
196       tmp_list = tmp_list->next;
197
198       tmp_menu_item->group = radio_menu_item->group;
199     }
200
201   if (GTK_OBJECT_CLASS (parent_class)->destroy)
202     (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
203 }
204
205 static void
206 gtk_radio_menu_item_activate (GtkMenuItem *menu_item)
207 {
208   GtkRadioMenuItem *radio_menu_item;
209   GtkCheckMenuItem *check_menu_item;
210   GtkCheckMenuItem *tmp_menu_item;
211   GSList *tmp_list;
212   gint toggled;
213
214   g_return_if_fail (menu_item != NULL);
215   g_return_if_fail (GTK_IS_RADIO_MENU_ITEM (menu_item));
216
217   radio_menu_item = GTK_RADIO_MENU_ITEM (menu_item);
218   check_menu_item = GTK_CHECK_MENU_ITEM (menu_item);
219   toggled = FALSE;
220
221   if (check_menu_item->active)
222     {
223       tmp_menu_item = NULL;
224       tmp_list = radio_menu_item->group;
225
226       while (tmp_list)
227         {
228           tmp_menu_item = tmp_list->data;
229           tmp_list = tmp_list->next;
230
231           if (tmp_menu_item->active && (tmp_menu_item != check_menu_item))
232             break;
233
234           tmp_menu_item = NULL;
235         }
236
237       if (tmp_menu_item)
238         {
239           toggled = TRUE;
240           check_menu_item->active = !check_menu_item->active;
241         }
242     }
243   else
244     {
245       toggled = TRUE;
246       check_menu_item->active = !check_menu_item->active;
247
248       tmp_list = radio_menu_item->group;
249       while (tmp_list)
250         {
251           tmp_menu_item = tmp_list->data;
252           tmp_list = tmp_list->next;
253
254           if (tmp_menu_item->active && (tmp_menu_item != check_menu_item))
255             {
256               gtk_menu_item_activate (GTK_MENU_ITEM (tmp_menu_item));
257               break;
258             }
259         }
260     }
261
262   if (toggled)
263     gtk_check_menu_item_toggled (check_menu_item);
264   gtk_widget_queue_draw (GTK_WIDGET (radio_menu_item));
265 }
266
267 static void
268 gtk_radio_menu_item_draw_indicator (GtkCheckMenuItem *check_menu_item,
269                                     GdkRectangle     *area)
270 {
271   GtkWidget *widget;
272   GtkStateType state_type;
273   GtkShadowType shadow_type;
274   gint width, height;
275   gint x, y;
276
277   g_return_if_fail (check_menu_item != NULL);
278   g_return_if_fail (GTK_IS_RADIO_MENU_ITEM (check_menu_item));
279
280   if (GTK_WIDGET_DRAWABLE (check_menu_item))
281     {
282       widget = GTK_WIDGET (check_menu_item);
283
284       width = 8;
285       height = 8;
286       x = (GTK_CONTAINER (check_menu_item)->border_width +
287            widget->style->xthickness + 2);
288       y = (widget->allocation.height - height) / 2;
289
290       if (check_menu_item->active ||
291           check_menu_item->always_show_toggle ||
292           (GTK_WIDGET_STATE (check_menu_item) == GTK_STATE_PRELIGHT))
293         {
294           state_type = GTK_WIDGET_STATE (widget);
295           if (check_menu_item->active ||
296               !check_menu_item->always_show_toggle)
297             shadow_type = GTK_SHADOW_IN;
298           else
299             shadow_type = GTK_SHADOW_OUT;
300
301           gtk_paint_option (widget->style, widget->window,
302                             state_type, shadow_type,
303                             area, widget, "option",
304                             x, y, width, height);
305         }
306     }
307 }
308