]> Pileus Git - ~andy/gtk/blob - gtk/a11y/gailscrolledwindow.c
gail: Move from modules/other/gail to gtk/a11y
[~andy/gtk] / gtk / a11y / gailscrolledwindow.c
1 /* GAIL - The GNOME Accessibility Enabling Library
2  * Copyright 2001, 2002, 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, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 #include "config.h"
21
22 #include <string.h>
23 #include <gtk/gtk.h>
24 #include "gailscrolledwindow.h"
25
26
27 static void         gail_scrolled_window_class_init     (GailScrolledWindowClass  *klass); 
28 static void         gail_scrolled_window_init           (GailScrolledWindow       *window);
29 static void         gail_scrolled_window_real_initialize
30                                                         (AtkObject     *obj,
31                                                          gpointer      data);
32
33 static gint         gail_scrolled_window_get_n_children (AtkObject     *object);
34 static AtkObject*   gail_scrolled_window_ref_child      (AtkObject     *obj,
35                                                          gint          child);
36 static void         gail_scrolled_window_scrollbar_visibility_changed 
37                                                         (GObject       *object,
38                                                          GParamSpec    *pspec,
39                                                          gpointer      user_data);
40
41 G_DEFINE_TYPE (GailScrolledWindow, gail_scrolled_window, GAIL_TYPE_CONTAINER)
42
43 static void
44 gail_scrolled_window_class_init (GailScrolledWindowClass *klass)
45 {
46   AtkObjectClass  *class = ATK_OBJECT_CLASS (klass);
47
48   class->get_n_children = gail_scrolled_window_get_n_children;
49   class->ref_child = gail_scrolled_window_ref_child;
50   class->initialize = gail_scrolled_window_real_initialize;
51 }
52
53 static void
54 gail_scrolled_window_init (GailScrolledWindow *window)
55 {
56 }
57
58 static void
59 gail_scrolled_window_real_initialize (AtkObject *obj,
60                                       gpointer  data)
61 {
62   GtkScrolledWindow *window;
63
64   ATK_OBJECT_CLASS (gail_scrolled_window_parent_class)->initialize (obj, data);
65
66   window = GTK_SCROLLED_WINDOW (data);
67
68   g_signal_connect_data (gtk_scrolled_window_get_hscrollbar (window), "notify::visible",
69                          G_CALLBACK (gail_scrolled_window_scrollbar_visibility_changed),
70                          obj, NULL, FALSE);
71   g_signal_connect_data (gtk_scrolled_window_get_vscrollbar (window), "notify::visible",
72                          G_CALLBACK (gail_scrolled_window_scrollbar_visibility_changed),
73                          obj, NULL, FALSE);
74
75   obj->role = ATK_ROLE_SCROLL_PANE;
76 }
77
78 static gint
79 gail_scrolled_window_get_n_children (AtkObject *object)
80 {
81   GtkWidget *widget;
82   GtkScrolledWindow *gtk_window;
83   GList *children;
84   gint n_children;
85  
86   widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (object));
87   if (widget == NULL)
88     /* Object is defunct */
89     return 0;
90
91   gtk_window = GTK_SCROLLED_WINDOW (widget);
92    
93   /* Get the number of children returned by the backing GtkScrolledWindow */
94
95   children = gtk_container_get_children (GTK_CONTAINER(gtk_window));
96   n_children = g_list_length (children);
97   g_list_free (children);
98   
99   /* Add one to the count for each visible scrollbar */
100
101   if (gtk_scrolled_window_get_hscrollbar (gtk_window))
102     n_children++;
103   if (gtk_scrolled_window_get_vscrollbar (gtk_window))
104     n_children++;
105   return n_children;
106 }
107
108 static AtkObject *
109 gail_scrolled_window_ref_child (AtkObject *obj, 
110                                 gint      child)
111 {
112   GtkWidget *widget;
113   GtkScrolledWindow *gtk_window;
114   GtkWidget *hscrollbar, *vscrollbar;
115   GList *children, *tmp_list;
116   gint n_children;
117   AtkObject  *accessible = NULL;
118
119   g_return_val_if_fail (child >= 0, NULL);
120
121   widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (obj));
122   if (widget == NULL)
123     /* Object is defunct */
124     return NULL;
125
126   gtk_window = GTK_SCROLLED_WINDOW (widget);
127   hscrollbar = gtk_scrolled_window_get_hscrollbar (gtk_window);
128   vscrollbar = gtk_scrolled_window_get_vscrollbar (gtk_window);
129
130   children = gtk_container_get_children (GTK_CONTAINER (gtk_window));
131   n_children = g_list_length (children);
132
133   if (child == n_children)
134     {
135       if (gtk_scrolled_window_get_hscrollbar (gtk_window))
136         accessible = gtk_widget_get_accessible (hscrollbar);
137       else if (gtk_scrolled_window_get_vscrollbar (gtk_window))
138         accessible = gtk_widget_get_accessible (vscrollbar);
139     }
140   else if (child == n_children+1 && 
141            gtk_scrolled_window_get_hscrollbar (gtk_window) &&
142            gtk_scrolled_window_get_vscrollbar (gtk_window))
143     accessible = gtk_widget_get_accessible (vscrollbar);
144   else if (child < n_children)
145     {
146       tmp_list = g_list_nth (children, child);
147       if (tmp_list)
148         accessible = gtk_widget_get_accessible (
149                 GTK_WIDGET (tmp_list->data));
150     }
151
152   g_list_free (children);
153   if (accessible)
154     g_object_ref (accessible);
155   return accessible; 
156 }
157
158 static void
159 gail_scrolled_window_scrollbar_visibility_changed (GObject    *object,
160                                                    GParamSpec *pspec,
161                                                    gpointer   user_data)
162 {
163   if (!strcmp (pspec->name, "visible"))
164     {
165       gint index;
166       gint n_children;
167       gboolean child_added = FALSE;
168       GList *children;
169       AtkObject *child;
170       GtkScrolledWindow *gtk_window;
171       GtkWidget *hscrollbar, *vscrollbar;
172       GailScrolledWindow *gail_window = GAIL_SCROLLED_WINDOW (user_data);
173       gchar *signal_name;
174
175       gtk_window = GTK_SCROLLED_WINDOW (gtk_accessible_get_widget (GTK_ACCESSIBLE (user_data)));
176       if (gtk_window == NULL)
177         return;
178       children = gtk_container_get_children (GTK_CONTAINER (gtk_window));
179       index = n_children = g_list_length (children);
180       g_list_free (children);
181
182       hscrollbar = gtk_scrolled_window_get_hscrollbar (gtk_window);
183       vscrollbar = gtk_scrolled_window_get_vscrollbar (gtk_window);
184
185       if ((gpointer) object == (gpointer) (hscrollbar))
186         {
187           if (gtk_scrolled_window_get_hscrollbar (gtk_window))
188             child_added = TRUE;
189
190           child = gtk_widget_get_accessible (hscrollbar);
191         }
192       else if ((gpointer) object == (gpointer) (vscrollbar))
193         {
194           if (gtk_scrolled_window_get_vscrollbar (gtk_window))
195             child_added = TRUE;
196
197           child = gtk_widget_get_accessible (vscrollbar);
198           if (gtk_scrolled_window_get_hscrollbar (gtk_window))
199             index = n_children+1;
200         }
201       else 
202         {
203           g_assert_not_reached ();
204           return;
205         }
206
207       if (child_added)
208         signal_name = "children_changed::add";
209       else
210         signal_name = "children_changed::delete";
211
212       g_signal_emit_by_name (gail_window, signal_name, index, child, NULL);
213     }
214 }