]> Pileus Git - ~andy/gtk/blob - gtk/gtktoggletoolbutton.c
Add hidden aliases for exported symbols which are used internally in order
[~andy/gtk] / gtk / gtktoggletoolbutton.c
1 /* gtktoggletoolbutton.c
2  *
3  * Copyright (C) 2002 Anders Carlsson <andersca@gnome.org>
4  * Copyright (C) 2002 James Henstridge <james@daa.com.au>
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the
18  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19  * Boston, MA 02111-1307, USA.
20  */
21
22 #include <config.h>
23 #include "gtkalias.h"
24 #include "gtktoggletoolbutton.h"
25 #include "gtkcheckmenuitem.h"
26 #include "gtklabel.h"
27 #include "gtktogglebutton.h"
28 #include "gtkstock.h"
29 #include "gtkintl.h"
30 #include "gtkradiotoolbutton.h"
31
32 #define MENU_ID "gtk-toggle-tool-button-menu-id"
33
34 enum {
35   TOGGLED,
36   LAST_SIGNAL
37 };
38
39 #define GTK_TOGGLE_TOOL_BUTTON_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GTK_TYPE_TOGGLE_TOOL_BUTTON, GtkToggleToolButtonPrivate))
40
41 struct _GtkToggleToolButtonPrivate
42 {
43   guint active : 1;
44 };
45   
46 static void gtk_toggle_tool_button_init       (GtkToggleToolButton      *button);
47 static void gtk_toggle_tool_button_class_init (GtkToggleToolButtonClass *klass);
48
49 static gboolean gtk_toggle_tool_button_create_menu_proxy (GtkToolItem *button);
50
51 static void button_toggled      (GtkWidget           *widget,
52                                  GtkToggleToolButton *button);
53 static void menu_item_activated (GtkWidget           *widget,
54                                  GtkToggleToolButton *button);
55
56 static GObjectClass *parent_class = NULL;
57 static guint         toggle_signals[LAST_SIGNAL] = { 0 };
58
59 GType
60 gtk_toggle_tool_button_get_type (void)
61 {
62   static GType type = 0;
63
64   if (!type)
65     {
66       static const GTypeInfo type_info =
67         {
68           sizeof (GtkToggleToolButtonClass),
69           (GBaseInitFunc) 0,
70           (GBaseFinalizeFunc) 0,
71           (GClassInitFunc) gtk_toggle_tool_button_class_init,
72           (GClassFinalizeFunc) 0,
73           NULL,
74           sizeof (GtkToggleToolButton),
75           0, /* n_preallocs */
76           (GInstanceInitFunc) gtk_toggle_tool_button_init
77         };
78
79       type = g_type_register_static (GTK_TYPE_TOOL_BUTTON,
80                                      "GtkToggleToolButton", &type_info, 0);
81     }
82   return type;
83 }
84
85
86 static void
87 gtk_toggle_tool_button_class_init (GtkToggleToolButtonClass *klass)
88 {
89   GObjectClass *object_class;
90   GtkToolItemClass *toolitem_class;
91   GtkToolButtonClass *toolbutton_class;
92
93   parent_class = g_type_class_peek_parent (klass);
94
95   object_class = (GObjectClass *)klass;
96   toolitem_class = (GtkToolItemClass *)klass;
97   toolbutton_class = (GtkToolButtonClass *)klass;
98
99   toolitem_class->create_menu_proxy = gtk_toggle_tool_button_create_menu_proxy;
100   toolbutton_class->button_type = GTK_TYPE_TOGGLE_BUTTON;
101   
102 /**
103  * GtkToggleToolButton::toggled:
104  * @toggle_tool_button: the object that emitted the signal
105  *
106  * Emitted whenever the toggle tool button changes state.
107  **/
108   toggle_signals[TOGGLED] =
109     g_signal_new ("toggled",
110                   G_OBJECT_CLASS_TYPE (klass),
111                   G_SIGNAL_RUN_FIRST,
112                   G_STRUCT_OFFSET (GtkToggleToolButtonClass, toggled),
113                   NULL, NULL,
114                   g_cclosure_marshal_VOID__VOID,
115                   G_TYPE_NONE, 0);
116
117   g_type_class_add_private (object_class, sizeof (GtkToggleToolButtonPrivate));
118 }
119
120 static void
121 gtk_toggle_tool_button_init (GtkToggleToolButton *button)
122 {
123   GtkToolButton *tool_button = GTK_TOOL_BUTTON (button);
124   GtkToggleButton *toggle_button = GTK_TOGGLE_BUTTON (_gtk_tool_button_get_button (tool_button));
125
126   button->priv = GTK_TOGGLE_TOOL_BUTTON_GET_PRIVATE (button);
127
128   /* If the real button is a radio button, it may have been
129    * active at the time it was created.
130    */
131   button->priv->active = gtk_toggle_button_get_active (toggle_button);
132     
133   g_signal_connect_object (toggle_button,
134                            "toggled", G_CALLBACK (button_toggled), button, 0);
135 }
136
137 static gboolean
138 gtk_toggle_tool_button_create_menu_proxy (GtkToolItem *item)
139 {
140   GtkToolButton *tool_button = GTK_TOOL_BUTTON (item);
141   GtkToggleToolButton *toggle_tool_button = GTK_TOGGLE_TOOL_BUTTON (item);
142   GtkWidget *menu_item = NULL;
143   GtkStockItem stock_item;
144   gboolean use_mnemonic = TRUE;
145   const char *label;
146
147   GtkWidget *label_widget = gtk_tool_button_get_label_widget (tool_button);
148   const gchar *label_text = gtk_tool_button_get_label (tool_button);
149   const gchar *stock_id = gtk_tool_button_get_stock_id (tool_button);
150
151   if (label_widget && GTK_IS_LABEL (label_widget))
152     {
153       label = gtk_label_get_label (GTK_LABEL (label_widget));
154       use_mnemonic = gtk_label_get_use_underline (GTK_LABEL (label_widget));
155     }
156   else if (label_text)
157     {
158       label = label_text;
159       use_mnemonic = gtk_tool_button_get_use_underline (tool_button);
160     }
161   else if (stock_id && gtk_stock_lookup (stock_id, &stock_item))
162     {
163       label = stock_item.label;
164     }
165   else
166     {
167       label = "";
168     }
169   
170   if (use_mnemonic)
171     menu_item = gtk_check_menu_item_new_with_mnemonic (label);
172   else
173     menu_item = gtk_check_menu_item_new_with_label (label);
174
175   gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (menu_item),
176                                   toggle_tool_button->priv->active);
177
178   if (GTK_IS_RADIO_TOOL_BUTTON (toggle_tool_button))
179     {
180       gtk_check_menu_item_set_draw_as_radio (GTK_CHECK_MENU_ITEM (menu_item),
181                                              TRUE);
182     }
183
184   g_signal_connect_closure_by_id (menu_item,
185                                   g_signal_lookup ("activate", G_OBJECT_TYPE (menu_item)), 0,
186                                   g_cclosure_new_object (G_CALLBACK (menu_item_activated),
187                                                          G_OBJECT (toggle_tool_button)),
188                                   FALSE);
189
190   gtk_tool_item_set_proxy_menu_item (item, MENU_ID, menu_item);
191   
192   return TRUE;
193 }
194
195 /* There are two activatable widgets, a toggle button and a menu item.
196  *
197  * If a widget is activated and the state of the tool button is the same as
198  * the new state of the activated widget, then the other widget was the one
199  * that was activated by the user and updated the tool button's state.
200  *
201  * If the state of the tool button is not the same as the new state of the
202  * activated widget, then the activation was activated by the user, and the
203  * widget needs to make sure the tool button is updated before the other
204  * widget is activated. This will make sure the other widget a tool button
205  * in a state that matches its own new state.
206  */
207 static void
208 menu_item_activated (GtkWidget           *menu_item,
209                      GtkToggleToolButton *toggle_tool_button)
210 {
211   GtkToolButton *tool_button = GTK_TOOL_BUTTON (toggle_tool_button);
212   gboolean menu_active = gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (menu_item));
213
214   if (toggle_tool_button->priv->active != menu_active)
215     {
216       toggle_tool_button->priv->active = menu_active;
217
218       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (_gtk_tool_button_get_button (tool_button)),
219                                     toggle_tool_button->priv->active);
220
221       g_signal_emit (G_OBJECT (toggle_tool_button), toggle_signals[TOGGLED], 0);
222     }
223 }
224
225 static void
226 button_toggled (GtkWidget           *widget,
227                 GtkToggleToolButton *toggle_tool_button)
228 {
229   gboolean toggle_active = GTK_TOGGLE_BUTTON (widget)->active;
230
231   if (toggle_tool_button->priv->active != toggle_active)
232     {
233       GtkWidget *menu_item;
234       
235       toggle_tool_button->priv->active = toggle_active;
236        
237       if ((menu_item =
238            gtk_tool_item_get_proxy_menu_item (GTK_TOOL_ITEM (toggle_tool_button), MENU_ID)))
239         {
240           gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (menu_item),
241                                           toggle_tool_button->priv->active);
242         }
243
244       g_signal_emit (G_OBJECT (toggle_tool_button), toggle_signals[TOGGLED], 0);
245     }
246 }
247
248 /**
249  * gtk_toggle_tool_button_new:
250  * 
251  * Returns a new #GtkToggleToolButton
252  * 
253  * Return value: a newly created #GtkToggleToolButton
254  * 
255  * Since: 2.4
256  **/
257 GtkToolItem *
258 gtk_toggle_tool_button_new (void)
259 {
260   GtkToolButton *button;
261
262   button = g_object_new (GTK_TYPE_TOGGLE_TOOL_BUTTON,
263                          NULL);
264   
265   return GTK_TOOL_ITEM (button);
266 }
267
268 /**
269  * gtk_toggle_tool_button_new_from_stock:
270  * @stock_id: the name of the stock item 
271  *
272  * Creates a new #GtkToggleToolButton containing the image and text from a
273  * stock item. Some stock ids have preprocessor macros like #GTK_STOCK_OK
274  * and #GTK_STOCK_APPLY.
275  *
276  * It is an error if @stock_id is not a name of a stock item.
277  * 
278  * Return value: A new #GtkToggleToolButton
279  * 
280  * Since: 2.4
281  **/
282 GtkToolItem *
283 gtk_toggle_tool_button_new_from_stock (const gchar *stock_id)
284 {
285   GtkToolButton *button;
286
287   g_return_val_if_fail (stock_id != NULL, NULL);
288   
289   button = g_object_new (GTK_TYPE_TOGGLE_TOOL_BUTTON,
290                          "stock_id", stock_id,
291                          NULL);
292   
293   return GTK_TOOL_ITEM (button);
294 }
295
296 /**
297  * gtk_toggle_tool_button_set_active:
298  * @button: a #GtkToggleToolButton
299  * @is_active: whether @button should be active
300  * 
301  * Sets the status of the toggle tool button. Set to %TRUE if you
302  * want the GtkToggleButton to be 'pressed in', and %FALSE to raise it.
303  * This action causes the toggled signal to be emitted.
304  * 
305  * Since: 2.4
306  **/
307 void
308 gtk_toggle_tool_button_set_active (GtkToggleToolButton *button,
309                                    gboolean is_active)
310 {
311   g_return_if_fail (GTK_IS_TOGGLE_TOOL_BUTTON (button));
312
313   is_active = is_active != FALSE;
314
315   if (button->priv->active != is_active)
316     gtk_button_clicked (GTK_BUTTON (_gtk_tool_button_get_button (GTK_TOOL_BUTTON (button))));
317 }
318
319 /**
320  * gtk_toggle_tool_button_get_active:
321  * @button: a #GtkToggleToolButton
322  * 
323  * Queries a #GtkToggleToolButton and returns its current state.
324  * Returns %TRUE if the toggle button is pressed in and %FALSE if it is raised.
325  * 
326  * Return value: %TRUE if the toggle tool button is pressed in, %FALSE if not
327  * 
328  * Since: 2.4
329  **/
330 gboolean
331 gtk_toggle_tool_button_get_active (GtkToggleToolButton *button)
332 {
333   g_return_val_if_fail (GTK_IS_TOGGLE_TOOL_BUTTON (button), FALSE);
334
335   return button->priv->active;
336 }