]> Pileus Git - ~andy/gtk/blob - gtk/gtkaccessible.c
entrycompletion: Don't reconnect signals all the time
[~andy/gtk] / gtk / gtkaccessible.c
1 /* GTK - The GIMP Toolkit
2  * Copyright 2001 Sun Microsystems Inc.
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser 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  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library. If not, see <http://www.gnu.org/licenses/>.
16  */
17
18 #include "config.h"
19 #include <string.h>
20
21 #include "gtkwidget.h"
22 #include "gtkintl.h"
23 #include "gtkaccessible.h"
24
25 /**
26  * SECTION:gtkaccessible
27  * @Short_description: Accessibility support for widgets
28  * @Title: GtkAccessible
29  *
30  * The #GtkAccessible class is the base class for accessible
31  * implementations for #GtkWidget subclasses. It is a thin
32  * wrapper around #AtkObject, which adds facilities for associating
33  * a widget with its accessible object.
34  *
35  * An accessible implementation for a third-party widget should
36  * derive from #GtkAccessible and implement the suitable interfaces
37  * from ATK, such as #AtkText or #AtkSelection. To establish
38  * the connection between the widget class and its corresponding
39  * acccessible implementation, override the get_accessible vfunc
40  * in #GtkWidgetClass.
41  */
42
43 struct _GtkAccessiblePrivate
44 {
45   GtkWidget *widget;
46 };
47
48 enum {
49   PROP_0,
50   PROP_WIDGET
51 };
52
53 static void gtk_accessible_real_connect_widget_destroyed (GtkAccessible *accessible);
54
55 G_DEFINE_TYPE (GtkAccessible, gtk_accessible, ATK_TYPE_OBJECT)
56
57 static void
58 gtk_accessible_set_property (GObject      *object,
59                              guint         prop_id,
60                              const GValue *value,
61                              GParamSpec   *pspec)
62 {
63   GtkAccessible *accessible = GTK_ACCESSIBLE (object);
64
65   switch (prop_id)
66     {
67     case PROP_WIDGET:
68       gtk_accessible_set_widget (accessible, g_value_get_object (value));
69       break;
70     default:
71       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
72       break;
73     }
74 }
75
76 static void
77 gtk_accessible_get_property (GObject    *object,
78                              guint       prop_id,
79                              GValue     *value,
80                              GParamSpec *pspec)
81 {
82   GtkAccessible *accessible = GTK_ACCESSIBLE (object);
83   GtkAccessiblePrivate *priv = accessible->priv;
84
85   switch (prop_id)
86     {
87     case PROP_WIDGET:
88       g_value_set_object (value, priv->widget);
89       break;
90     default:
91       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
92       break;
93     }
94 }
95
96 static void
97 gtk_accessible_init (GtkAccessible *accessible)
98 {
99   accessible->priv = G_TYPE_INSTANCE_GET_PRIVATE (accessible,
100                                                   GTK_TYPE_ACCESSIBLE,
101                                                   GtkAccessiblePrivate);
102 }
103
104 static AtkStateSet *
105 gtk_accessible_ref_state_set (AtkObject *object)
106 {
107   GtkAccessible *accessible = GTK_ACCESSIBLE (object);
108   AtkStateSet *state_set;
109
110   state_set = ATK_OBJECT_CLASS (gtk_accessible_parent_class)->ref_state_set (object);
111
112   if (accessible->priv->widget == NULL)
113     atk_state_set_add_state (state_set, ATK_STATE_DEFUNCT);
114
115   return state_set;
116 }
117
118 static void
119 gtk_accessible_real_widget_set (GtkAccessible *accessible)
120 {
121   atk_object_notify_state_change (ATK_OBJECT (accessible), ATK_STATE_DEFUNCT, FALSE);
122 }
123
124 static void
125 gtk_accessible_real_widget_unset (GtkAccessible *accessible)
126 {
127   atk_object_notify_state_change (ATK_OBJECT (accessible), ATK_STATE_DEFUNCT, TRUE);
128 }
129
130 static void
131 gtk_accessible_dispose (GObject *object)
132 {
133   GtkAccessible *accessible = GTK_ACCESSIBLE (object);
134   
135   gtk_accessible_set_widget (accessible, NULL);
136
137   G_OBJECT_CLASS (gtk_accessible_parent_class)->dispose (object);
138 }
139
140 static void
141 gtk_accessible_class_init (GtkAccessibleClass *klass)
142 {
143   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
144   AtkObjectClass *atkobject_class = ATK_OBJECT_CLASS (klass);
145
146   klass->connect_widget_destroyed = gtk_accessible_real_connect_widget_destroyed;
147   klass->widget_set = gtk_accessible_real_widget_set;
148   klass->widget_unset = gtk_accessible_real_widget_unset;
149
150   atkobject_class->ref_state_set = gtk_accessible_ref_state_set;
151   gobject_class->get_property = gtk_accessible_get_property;
152   gobject_class->set_property = gtk_accessible_set_property;
153   gobject_class->dispose = gtk_accessible_dispose;
154
155   g_object_class_install_property (gobject_class,
156                                    PROP_WIDGET,
157                                    g_param_spec_object ("widget",
158                                                         P_("Widget"),
159                                                         P_("The widget referenced by this accessible."),
160                                                         GTK_TYPE_WIDGET,
161                                                         G_PARAM_READWRITE));
162
163   g_type_class_add_private (klass, sizeof (GtkAccessiblePrivate));
164 }
165
166 /**
167  * gtk_accessible_set_widget:
168  * @accessible: a #GtkAccessible
169  * @widget: (allow-none): a #GtkWidget or %NULL to unset
170  *
171  * Sets the #GtkWidget corresponding to the #GtkAccessible.
172  *
173  * <note><para>@accessible will not hold a reference to @widget.
174  * It is the caller's responsibility to ensure that when @widget
175  * is destroyed, the widget is unset by calling this function
176  * again with @widget set to %NULL.</para></note>
177  * Since: 2.22
178  */
179 void
180 gtk_accessible_set_widget (GtkAccessible *accessible,
181                            GtkWidget     *widget)
182 {
183   GtkAccessiblePrivate *priv;
184   GtkAccessibleClass *klass;
185
186   g_return_if_fail (GTK_IS_ACCESSIBLE (accessible));
187
188   priv = accessible->priv;
189   klass = GTK_ACCESSIBLE_GET_CLASS (accessible);
190
191   if (priv->widget == widget)
192     return;
193
194   if (priv->widget)
195     klass->widget_unset (accessible);
196
197   priv->widget = widget;
198
199   if (widget)
200     klass->widget_set (accessible);
201
202   g_object_notify (G_OBJECT (accessible), "widget");
203 }
204
205 /**
206  * gtk_accessible_get_widget:
207  * @accessible: a #GtkAccessible
208  *
209  * Gets the #GtkWidget corresponding to the #GtkAccessible.
210  * The returned widget does not have a reference added, so
211  * you do not need to unref it.
212  *
213  * Returns: (transfer none): pointer to the #GtkWidget
214  *     corresponding to the #GtkAccessible, or %NULL.
215  *
216  * Since: 2.22
217  */
218 GtkWidget*
219 gtk_accessible_get_widget (GtkAccessible *accessible)
220 {
221   g_return_val_if_fail (GTK_IS_ACCESSIBLE (accessible), NULL);
222
223   return accessible->priv->widget;
224 }
225
226 /**
227  * gtk_accessible_connect_widget_destroyed:
228  * @accessible: a #GtkAccessible
229  *
230  * This function specifies the callback function to be called
231  * when the widget corresponding to a GtkAccessible is destroyed.
232  *
233  * Deprecated: 3.4: Use gtk_accessible_set_widget() and its vfuncs.
234  */
235 void
236 gtk_accessible_connect_widget_destroyed (GtkAccessible *accessible)
237 {
238   GtkAccessibleClass *class;
239
240   g_return_if_fail (GTK_IS_ACCESSIBLE (accessible));
241
242   class = GTK_ACCESSIBLE_GET_CLASS (accessible);
243
244   if (class->connect_widget_destroyed)
245     class->connect_widget_destroyed (accessible);
246 }
247
248 static void
249 gtk_accessible_widget_destroyed (GtkWidget     *widget,
250                                  GtkAccessible *accessible)
251 {
252   gtk_accessible_set_widget (accessible, NULL);
253 }
254
255 static void
256 gtk_accessible_real_connect_widget_destroyed (GtkAccessible *accessible)
257 {
258   GtkAccessiblePrivate *priv = accessible->priv;
259
260   if (priv->widget)
261     g_signal_connect (priv->widget, "destroy",
262                       G_CALLBACK (gtk_accessible_widget_destroyed), accessible);
263 }