1 /* GTK+ - accessibility implementations
2  * Copyright 2003 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 
20 #include <glib/gi18n-lib.h>
21 #include <gtk/gtk.h>
22 #include "gtkexpanderaccessible.h"
23 
24 static void atk_action_interface_init (AtkActionIface *iface);
25 
G_DEFINE_TYPE_WITH_CODE(GtkExpanderAccessible,gtk_expander_accessible,GTK_TYPE_CONTAINER_ACCESSIBLE,G_IMPLEMENT_INTERFACE (ATK_TYPE_ACTION,atk_action_interface_init))26 G_DEFINE_TYPE_WITH_CODE (GtkExpanderAccessible, gtk_expander_accessible, GTK_TYPE_CONTAINER_ACCESSIBLE,
27                          G_IMPLEMENT_INTERFACE (ATK_TYPE_ACTION, atk_action_interface_init))
28 
29 static const gchar *
30 gtk_expander_accessible_get_full_text (GtkExpander *widget)
31 {
32   GtkWidget *label_widget;
33 
34   label_widget = gtk_expander_get_label_widget (widget);
35 
36   if (!GTK_IS_LABEL (label_widget))
37     return NULL;
38 
39   return gtk_label_get_text (GTK_LABEL (label_widget));
40 }
41 
42 static const gchar *
gtk_expander_accessible_get_name(AtkObject * obj)43 gtk_expander_accessible_get_name (AtkObject *obj)
44 {
45   GtkWidget *widget;
46   const gchar *name;
47 
48   widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (obj));
49   if (widget == NULL)
50     return NULL;
51 
52   name = ATK_OBJECT_CLASS (gtk_expander_accessible_parent_class)->get_name (obj);
53   if (name != NULL)
54     return name;
55 
56   return gtk_expander_accessible_get_full_text (GTK_EXPANDER (widget));
57 }
58 
59 static gint
gtk_expander_accessible_get_n_children(AtkObject * obj)60 gtk_expander_accessible_get_n_children (AtkObject *obj)
61 {
62   GtkWidget *widget;
63   GList *children;
64   gint count = 0;
65 
66   widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (obj));
67   if (widget == NULL)
68     return 0;
69 
70   children = gtk_container_get_children (GTK_CONTAINER(widget));
71   count = g_list_length (children);
72   g_list_free (children);
73 
74   /* See if there is a label - if there is, reduce our count by 1
75    * since we don't want the label included with the children.
76    */
77   if (gtk_expander_get_label_widget (GTK_EXPANDER (widget)))
78     count -= 1;
79 
80   return count;
81 }
82 
83 static AtkObject *
gtk_expander_accessible_ref_child(AtkObject * obj,gint i)84 gtk_expander_accessible_ref_child (AtkObject *obj,
85                                    gint       i)
86 {
87   GList *children, *tmp_list;
88   AtkObject *accessible;
89   GtkWidget *widget;
90   GtkWidget *label;
91   gint index;
92 
93   widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (obj));
94   if (widget == NULL)
95     return NULL;
96 
97   children = gtk_container_get_children (GTK_CONTAINER (widget));
98 
99   /* See if there is a label - if there is, we need to skip it
100    * since we don't want the label included with the children.
101    */
102   label = gtk_expander_get_label_widget (GTK_EXPANDER (widget));
103   if (label)
104     {
105       for (index = 0; index <= i; index++)
106         {
107           tmp_list = g_list_nth (children, index);
108           if (label == GTK_WIDGET (tmp_list->data))
109             {
110               i += 1;
111               break;
112             }
113         }
114     }
115 
116   tmp_list = g_list_nth (children, i);
117   if (!tmp_list)
118     {
119       g_list_free (children);
120       return NULL;
121     }
122   accessible = gtk_widget_get_accessible (GTK_WIDGET (tmp_list->data));
123 
124   g_list_free (children);
125   g_object_ref (accessible);
126   return accessible;
127 }
128 
129 static void
gtk_expander_accessible_initialize(AtkObject * obj,gpointer data)130 gtk_expander_accessible_initialize (AtkObject *obj,
131                                     gpointer   data)
132 {
133   ATK_OBJECT_CLASS (gtk_expander_accessible_parent_class)->initialize (obj, data);
134 
135   obj->role = ATK_ROLE_TOGGLE_BUTTON;
136 }
137 
138 static void
gtk_expander_accessible_notify_gtk(GObject * obj,GParamSpec * pspec)139 gtk_expander_accessible_notify_gtk (GObject    *obj,
140                                     GParamSpec *pspec)
141 {
142   AtkObject* atk_obj;
143   GtkExpander *expander;
144 
145   expander = GTK_EXPANDER (obj);
146   atk_obj = gtk_widget_get_accessible (GTK_WIDGET (expander));
147 ;
148   if (g_strcmp0 (pspec->name, "label") == 0)
149     {
150       if (atk_obj->name == NULL)
151         g_object_notify (G_OBJECT (atk_obj), "accessible-name");
152       g_signal_emit_by_name (atk_obj, "visible-data-changed");
153     }
154   else if (g_strcmp0 (pspec->name, "expanded") == 0)
155     {
156       atk_object_notify_state_change (atk_obj, ATK_STATE_CHECKED,
157                                       gtk_expander_get_expanded (expander));
158       atk_object_notify_state_change (atk_obj, ATK_STATE_EXPANDED,
159                                       gtk_expander_get_expanded (expander));
160       g_signal_emit_by_name (atk_obj, "visible-data-changed");
161     }
162   else
163     GTK_WIDGET_ACCESSIBLE_CLASS (gtk_expander_accessible_parent_class)->notify_gtk (obj, pspec);
164 }
165 
166 static AtkStateSet *
gtk_expander_accessible_ref_state_set(AtkObject * obj)167 gtk_expander_accessible_ref_state_set (AtkObject *obj)
168 {
169   AtkStateSet *state_set;
170   GtkWidget *widget;
171   GtkExpander *expander;
172 
173   widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (obj));
174   if (widget == NULL)
175     return NULL;
176 
177   state_set = ATK_OBJECT_CLASS (gtk_expander_accessible_parent_class)->ref_state_set (obj);
178 
179   expander = GTK_EXPANDER (widget);
180 
181   atk_state_set_add_state (state_set, ATK_STATE_EXPANDABLE);
182 
183   if (gtk_expander_get_expanded (expander))
184     {
185       atk_state_set_add_state (state_set, ATK_STATE_CHECKED);
186       atk_state_set_add_state (state_set, ATK_STATE_EXPANDED);
187     }
188 
189   return state_set;
190 }
191 
192 static void
gtk_expander_accessible_class_init(GtkExpanderAccessibleClass * klass)193 gtk_expander_accessible_class_init (GtkExpanderAccessibleClass *klass)
194 {
195   AtkObjectClass *class = ATK_OBJECT_CLASS (klass);
196   GtkWidgetAccessibleClass *widget_class = (GtkWidgetAccessibleClass*)klass;
197 
198   widget_class->notify_gtk = gtk_expander_accessible_notify_gtk;
199 
200   class->get_name = gtk_expander_accessible_get_name;
201   class->get_n_children = gtk_expander_accessible_get_n_children;
202   class->ref_child = gtk_expander_accessible_ref_child;
203   class->ref_state_set = gtk_expander_accessible_ref_state_set;
204 
205   class->initialize = gtk_expander_accessible_initialize;
206 }
207 
208 static void
gtk_expander_accessible_init(GtkExpanderAccessible * expander)209 gtk_expander_accessible_init (GtkExpanderAccessible *expander)
210 {
211 }
212 
213 static gboolean
gtk_expander_accessible_do_action(AtkAction * action,gint i)214 gtk_expander_accessible_do_action (AtkAction *action,
215                                    gint       i)
216 {
217   GtkWidget *widget;
218 
219   widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (action));
220   if (widget == NULL)
221     return FALSE;
222 
223   if (!gtk_widget_is_sensitive (widget) || !gtk_widget_get_visible (widget))
224     return FALSE;
225 
226   if (i != 0)
227     return FALSE;
228 
229   gtk_widget_activate (widget);
230   return TRUE;
231 }
232 
233 static gint
gtk_expander_accessible_get_n_actions(AtkAction * action)234 gtk_expander_accessible_get_n_actions (AtkAction *action)
235 {
236   return 1;
237 }
238 
239 static const gchar *
gtk_expander_accessible_get_keybinding(AtkAction * action,gint i)240 gtk_expander_accessible_get_keybinding (AtkAction *action,
241                                         gint       i)
242 {
243   gchar *return_value = NULL;
244   GtkWidget *widget;
245   GtkWidget *label;
246 
247   widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (action));
248   if (widget == NULL)
249     return NULL;
250 
251   if (i != 0)
252     return NULL;
253 
254   label = gtk_expander_get_label_widget (GTK_EXPANDER (widget));
255   if (GTK_IS_LABEL (label))
256     {
257       guint key_val;
258 
259       key_val = gtk_label_get_mnemonic_keyval (GTK_LABEL (label));
260       if (key_val != GDK_KEY_VoidSymbol)
261         return_value = gtk_accelerator_name (key_val, GDK_MOD1_MASK);
262     }
263 
264   return return_value;
265 }
266 
267 static const gchar *
gtk_expander_accessible_action_get_name(AtkAction * action,gint i)268 gtk_expander_accessible_action_get_name (AtkAction *action,
269                                          gint       i)
270 {
271   if (i == 0)
272     return "activate";
273   return NULL;
274 }
275 
276 static const gchar *
gtk_expander_accessible_action_get_localized_name(AtkAction * action,gint i)277 gtk_expander_accessible_action_get_localized_name (AtkAction *action,
278                                                    gint       i)
279 {
280   if (i == 0)
281     return C_("Action name", "Activate");
282   return NULL;
283 }
284 
285 static const gchar *
gtk_expander_accessible_action_get_description(AtkAction * action,gint i)286 gtk_expander_accessible_action_get_description (AtkAction *action,
287                                                 gint       i)
288 {
289   if (i == 0)
290     return C_("Action description", "Activates the expander");
291   return NULL;
292 }
293 
294 static void
atk_action_interface_init(AtkActionIface * iface)295 atk_action_interface_init (AtkActionIface *iface)
296 {
297   iface->do_action = gtk_expander_accessible_do_action;
298   iface->get_n_actions = gtk_expander_accessible_get_n_actions;
299   iface->get_keybinding = gtk_expander_accessible_get_keybinding;
300   iface->get_name = gtk_expander_accessible_action_get_name;
301   iface->get_localized_name = gtk_expander_accessible_action_get_localized_name;
302   iface->get_description = gtk_expander_accessible_action_get_description;
303 }
304