1 /*
2 * Copyright © 2003 Sun Microsystems Inc.
3 * Copyright © 2007 Christian Persch
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public
7 * License as published by the Free Software Foundation; either
8 * version 3 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public
16 * License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
19 */
20
21 #include <config.h>
22
23 #include <string.h>
24
25 #include <glib/gi18n-lib.h>
26
27 #include <gtk/gtk.h>
28
29 #include "gucharmap.h"
30 #include "gucharmap-chartable.h"
31 #include "gucharmap-chartable-accessible.h"
32 #include "gucharmap-chartable-cell-accessible.h"
33 #include "gucharmap-private.h"
34
35 typedef struct
36 {
37 GtkAdjustment *vadjustment;
38 GPtrArray *cells;
39 AtkObject *focus_obj;
40 } GucharmapChartableAccessiblePrivate;
41
42 #define GET_PRIVATE(inst) (G_TYPE_INSTANCE_GET_PRIVATE ((inst), gucharmap_chartable_accessible_get_type (), GucharmapChartableAccessiblePrivate))
43
44 static gpointer gucharmap_chartable_accessible_parent_class;
45
46 static void
set_cell_visibility(GucharmapChartable * chartable,GucharmapChartableCellAccessible * cell,gboolean emit_signal)47 set_cell_visibility (GucharmapChartable *chartable,
48 GucharmapChartableCellAccessible *cell,
49 gboolean emit_signal)
50 {
51 GucharmapChartablePrivate *chartable_priv = chartable->priv;
52 gucharmap_chartable_cell_accessible_add_state (cell, ATK_STATE_VISIBLE, emit_signal);
53
54 if (cell->index >= chartable_priv->page_first_cell &&
55 cell->index < chartable_priv->page_first_cell
56 + chartable_priv->rows * chartable_priv->cols)
57 {
58 gucharmap_chartable_cell_accessible_add_state (cell, ATK_STATE_SHOWING, emit_signal);
59 }
60 else
61 {
62 gucharmap_chartable_cell_accessible_remove_state (cell, ATK_STATE_SHOWING, emit_signal);
63 }
64 }
65
66 static void
cell_destroyed(GucharmapChartableCellAccessible * cell)67 cell_destroyed (GucharmapChartableCellAccessible *cell)
68 {
69 GucharmapChartableAccessiblePrivate *priv;
70 AtkObject *parent;
71 GPtrArray *cells;
72 guint n_cells, n;
73 GucharmapChartableAccessible *accessible;
74
75 parent = atk_object_get_parent (ATK_OBJECT (cell));
76 accessible = GUCHARMAP_CHARTABLE_ACCESSIBLE (parent);
77 priv = GET_PRIVATE (accessible);
78
79 cells = priv->cells;
80 n_cells = cells->len;
81 for (n = 0; n < n_cells; ++n)
82 {
83 GucharmapChartableCellAccessible *another_cell = g_ptr_array_index (cells, n);
84
85 if (another_cell == cell)
86 {
87 g_ptr_array_remove_index_fast (priv->cells, n);
88 return;
89 }
90 }
91
92 g_warning ("Cell destroyed but was not in the cells cache?\n");
93 }
94
95 static AtkObject*
gucharmap_chartable_accessible_ref_child(AtkObject * obj,int index)96 gucharmap_chartable_accessible_ref_child (AtkObject *obj,
97 int index)
98 {
99 GucharmapChartableAccessible *table;
100 GucharmapChartableAccessiblePrivate *priv;
101 GtkWidget *widget;
102 GucharmapChartable *chartable;
103 AtkObject *child;
104 gchar* name;
105 GPtrArray *cells;
106 guint n_cells, n;
107
108 widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (obj));
109 if (widget == NULL)
110 /* State is defunct */
111 return NULL;
112
113 if (index > UNICHAR_MAX)
114 return NULL;
115
116 table = GUCHARMAP_CHARTABLE_ACCESSIBLE (obj);
117 priv = GET_PRIVATE (table);
118
119 /* Check whether the child is cached */
120 cells = priv->cells;
121 n_cells = cells->len;
122 for (n = 0; n < n_cells; ++n)
123 {
124 GucharmapChartableCellAccessible *cell = g_ptr_array_index (cells, n);
125
126 if (index == cell->index)
127 {
128 g_object_ref (cell);
129 return ATK_OBJECT (cell);
130 }
131 }
132
133 /* Not cached, create a new cell accessible */
134 chartable = GUCHARMAP_CHARTABLE (widget);
135
136 child = gucharmap_chartable_cell_accessible_new ();
137 gucharmap_chartable_cell_accessible_initialise (GUCHARMAP_CHARTABLE_CELL_ACCESSIBLE (child),
138 GTK_WIDGET (chartable), obj, index);
139 /* Set the name of the cell */
140 name = g_strdup_printf("U+%4.4X %s", (unsigned int)index, gucharmap_get_unicode_name (index));
141 atk_object_set_name (child, name);
142 g_free (name);
143 set_cell_visibility (chartable, GUCHARMAP_CHARTABLE_CELL_ACCESSIBLE (child), FALSE);
144
145 /* Store the cell in our cache */
146 g_ptr_array_add (priv->cells, child);
147 g_object_weak_ref (G_OBJECT (child),
148 (GWeakNotify) cell_destroyed,
149 child);
150
151 return child;
152 }
153
154 static AtkObject*
gucharmap_chartable_accessible_ref_at(AtkTable * table,gint row,gint column)155 gucharmap_chartable_accessible_ref_at (AtkTable *table,
156 gint row,
157 gint column)
158 {
159 GucharmapChartable *chartable;
160 GucharmapChartablePrivate *chartable_priv;
161 GtkWidget *widget;
162 AtkObject *child;
163 gint index;
164
165 widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (table));
166 if (widget == NULL)
167 /* State is defunct */
168 return NULL;
169
170 chartable = GUCHARMAP_CHARTABLE (widget);
171 chartable_priv = chartable->priv;
172
173 index = row * chartable_priv->cols + column;
174
175 child = gucharmap_chartable_accessible_ref_child (ATK_OBJECT (table), index);
176
177 return child;
178 }
179
180 static AtkObject*
gucharmap_chartable_accessible_ref_accessible_at_point(AtkComponent * component,gint x,gint y,AtkCoordType coord_type)181 gucharmap_chartable_accessible_ref_accessible_at_point (AtkComponent *component,
182 gint x,
183 gint y,
184 AtkCoordType coord_type)
185 {
186 GtkWidget *widget;
187 GucharmapChartable *chartable;
188 GucharmapChartablePrivate *chartable_priv;
189 gint x_pos, y_pos;
190 gint row, col;
191
192 widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (component));
193 if (widget == NULL)
194 /* State is defunct */
195 return NULL;
196
197 chartable = GUCHARMAP_CHARTABLE (widget);
198 chartable_priv = chartable->priv;
199
200 atk_component_get_extents (component, &x_pos, &y_pos,
201 NULL, NULL, coord_type);
202
203 /* Find cell at offset x - x_pos, y - y_pos */
204
205 x_pos = x - x_pos;
206 y_pos = y - y_pos;
207
208 for (col = 0; col < chartable_priv->cols; col++)
209 {
210 if (x_pos < _gucharmap_chartable_x_offset (chartable, col))
211 {
212 col--;
213 break;
214 }
215 }
216 if (col == chartable_priv->cols || col < 0)
217 return NULL;
218
219 for (row = 0; row < chartable_priv->rows; row++)
220 {
221 if (y_pos < _gucharmap_chartable_y_offset (chartable, row))
222 {
223 row--;
224 break;
225 }
226 }
227 if (row == chartable_priv->rows || row < 0)
228 return NULL;
229
230 row += chartable_priv->page_first_cell / chartable_priv->cols;
231
232 return gucharmap_chartable_accessible_ref_at (ATK_TABLE (component), row, col);
233 }
234
235 static void
gucharmap_chartable_accessible_component_interface_init(AtkComponentIface * iface)236 gucharmap_chartable_accessible_component_interface_init (AtkComponentIface *iface)
237 {
238 g_return_if_fail (iface != NULL);
239
240 iface->ref_accessible_at_point = gucharmap_chartable_accessible_ref_accessible_at_point;
241 }
242
243 static AtkStateSet*
gucharmap_chartable_accessible_ref_state_set(AtkObject * obj)244 gucharmap_chartable_accessible_ref_state_set (AtkObject *obj)
245 {
246 AtkStateSet *state_set;
247 GtkWidget *widget;
248
249 state_set = ATK_OBJECT_CLASS (gucharmap_chartable_accessible_parent_class)->ref_state_set (obj);
250 widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (obj));
251
252 if (widget != NULL)
253 atk_state_set_add_state (state_set, ATK_STATE_MANAGES_DESCENDANTS);
254
255 /* FIXME: reference count ? */
256 return state_set;
257 }
258
259 /* FIXMEchpe: shouldn't this get the number from the chartable's codepoint list instead?? */
260 static gint
gucharmap_chartable_accessible_get_n_children(AtkObject * obj)261 gucharmap_chartable_accessible_get_n_children (AtkObject *obj)
262 {
263 GtkWidget *widget;
264
265 widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (obj));
266 if (widget == NULL)
267 /* State is defunct */
268 return 0;
269
270 return UNICHAR_MAX + 1;
271 }
272
273 static void
gucharmap_chartable_accessible_init(GucharmapChartableAccessible * accessible)274 gucharmap_chartable_accessible_init (GucharmapChartableAccessible *accessible)
275 {
276 GucharmapChartableAccessiblePrivate *priv = GET_PRIVATE (accessible);
277
278 priv->cells = g_ptr_array_sized_new (512);
279 }
280
281 static void
gucharmap_chartable_accessible_finalize(GObject * obj)282 gucharmap_chartable_accessible_finalize (GObject *obj)
283 {
284 GucharmapChartableAccessible *accessible = GUCHARMAP_CHARTABLE_ACCESSIBLE (obj);
285 GucharmapChartableAccessiblePrivate *priv = GET_PRIVATE (accessible);
286 GPtrArray *cells;
287 guint n_cells, n;
288
289 if (priv->focus_obj)
290 g_object_unref (priv->focus_obj);
291
292 /* Remove the weak ref notifications */
293 cells = priv->cells;
294 n_cells = cells->len;
295 for (n = 0; n < n_cells; ++n)
296 {
297 GucharmapChartableCellAccessible *cell = g_ptr_array_index (cells, n);
298
299 g_object_weak_unref (G_OBJECT (cell),
300 (GWeakNotify) cell_destroyed,
301 cell);
302 }
303
304 g_ptr_array_free (priv->cells, TRUE);
305
306 G_OBJECT_CLASS (gucharmap_chartable_accessible_parent_class)->finalize (obj);
307 }
308
309 static void
gucharmap_chartable_accessible_update_all_cells(AtkObject * obj)310 gucharmap_chartable_accessible_update_all_cells (AtkObject *obj)
311 {
312 GucharmapChartableAccessible *accessible;
313 GucharmapChartableAccessiblePrivate *priv;
314 GtkWidget *widget;
315 GucharmapChartable *chartable;
316 GPtrArray *cells;
317 guint n_cells, n;
318
319 widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (obj));
320 if (!widget)
321 /* Widget is being deleted */
322 return;
323
324 accessible = GUCHARMAP_CHARTABLE_ACCESSIBLE (obj);
325 priv = GET_PRIVATE (accessible);
326
327 chartable = GUCHARMAP_CHARTABLE (widget);
328
329 cells = priv->cells;
330 n_cells = cells->len;
331 for (n = 0; n < n_cells; ++n)
332 {
333 GucharmapChartableCellAccessible *cell = g_ptr_array_index (cells, n);
334
335 set_cell_visibility (chartable, GUCHARMAP_CHARTABLE_CELL_ACCESSIBLE (cell), TRUE);
336 }
337
338 g_signal_emit_by_name (obj, "visible-data-changed");
339 }
340
341 static void
adjustment_changed(GtkAdjustment * adj,AtkObject * obj)342 adjustment_changed (GtkAdjustment *adj,
343 AtkObject *obj)
344 {
345 gucharmap_chartable_accessible_update_all_cells (obj);
346 }
347
348 static void
size_allocated(GtkWidget * widget,GtkAllocation * alloc,gpointer data)349 size_allocated (GtkWidget *widget,
350 GtkAllocation *alloc,
351 gpointer data)
352 {
353 gucharmap_chartable_accessible_update_all_cells (ATK_OBJECT (data));
354 }
355
356 static AtkObject* /* reference */
find_object(GucharmapChartable * chartable,gunichar uc,AtkObject * obj)357 find_object (GucharmapChartable *chartable,
358 gunichar uc,
359 AtkObject *obj)
360 {
361 GucharmapChartablePrivate *chartable_priv = chartable->priv;
362 gint row, column;
363
364 row = uc / chartable_priv->cols;
365 column = _gucharmap_chartable_cell_column (chartable, uc);
366
367 return atk_table_ref_at (ATK_TABLE (obj), row, column);
368 }
369
370 static void
sync_active_char(GucharmapChartable * chartable,GParamSpec * pspec,GucharmapChartableAccessible * accessible)371 sync_active_char (GucharmapChartable *chartable,
372 GParamSpec *pspec,
373 GucharmapChartableAccessible *accessible)
374 {
375 GucharmapChartableAccessiblePrivate *priv = GET_PRIVATE (accessible);
376 gunichar uc;
377 AtkObject *child;
378 AtkObject *focus_obj;
379
380 uc = gucharmap_chartable_get_active_character (chartable);
381
382 child = find_object (chartable, uc, ATK_OBJECT (accessible));
383 focus_obj = priv->focus_obj;
384 if (focus_obj != child)
385 {
386 if (focus_obj)
387 gucharmap_chartable_cell_accessible_remove_state (GUCHARMAP_CHARTABLE_CELL_ACCESSIBLE (focus_obj), ATK_STATE_FOCUSED, FALSE);
388
389 gucharmap_chartable_cell_accessible_add_state (GUCHARMAP_CHARTABLE_CELL_ACCESSIBLE (child), ATK_STATE_FOCUSED, FALSE);
390 }
391
392 if (focus_obj)
393 g_object_unref (focus_obj);
394
395 priv->focus_obj = child; /* adopts the reference from find_object */
396
397 g_signal_emit_by_name (accessible, "active-descendant-changed", child);
398 }
399
400 static void
gucharmap_chartable_accessible_set_scroll_adjustments(GucharmapChartable * chartable,GtkAdjustment * hadjustment,GtkAdjustment * vadjustment,AtkObject * obj)401 gucharmap_chartable_accessible_set_scroll_adjustments (GucharmapChartable *chartable,
402 GtkAdjustment *hadjustment,
403 GtkAdjustment *vadjustment,
404 AtkObject *obj)
405 {
406 GucharmapChartableAccessible *accessible = GUCHARMAP_CHARTABLE_ACCESSIBLE (obj);
407 GucharmapChartableAccessiblePrivate *priv = GET_PRIVATE (accessible);
408
409 if (priv->vadjustment != vadjustment)
410 {
411 GtkAdjustment **adjustment_ptr = &priv->vadjustment;
412 g_object_remove_weak_pointer (G_OBJECT (priv->vadjustment),
413 (gpointer *) adjustment_ptr);
414 g_signal_handlers_disconnect_by_func (priv->vadjustment,
415 G_CALLBACK (adjustment_changed),
416 obj);
417 priv->vadjustment = vadjustment;
418 g_object_add_weak_pointer (G_OBJECT (priv->vadjustment),
419 (gpointer *) adjustment_ptr);
420 g_signal_connect (vadjustment, "value-changed",
421 G_CALLBACK (adjustment_changed), obj);
422 }
423 }
424
425 static void
sync_adjustment(GucharmapChartable * chartable,GParamSpec * pspec,AtkObject * accessible)426 sync_adjustment (GucharmapChartable *chartable,
427 GParamSpec *pspec,
428 AtkObject *accessible)
429 {
430 GtkAdjustment *hadjustment, *vadjustment;
431
432 g_object_get (chartable,
433 "hadjustment", &hadjustment,
434 "vadjustment", &vadjustment,
435 NULL);
436 /* hadjustment and vadjustment are set to NULL in
437 gtk_scrolled_window_remove() */
438 if (hadjustment && vadjustment)
439 gucharmap_chartable_accessible_set_scroll_adjustments (chartable,
440 hadjustment,
441 vadjustment,
442 accessible);
443 }
444
445 static void
gucharmap_chartable_accessible_initialize(AtkObject * obj,gpointer data)446 gucharmap_chartable_accessible_initialize (AtkObject *obj,
447 gpointer data)
448 {
449 GtkWidget *widget;
450 AtkObject *focus_obj, *old_focus_obj;
451 GucharmapChartableAccessible *accessible;
452 GucharmapChartableAccessiblePrivate *priv;
453 GucharmapChartable *chartable;
454 GucharmapChartablePrivate *chartable_priv;
455
456 ATK_OBJECT_CLASS (gucharmap_chartable_accessible_parent_class)->initialize (obj, data);
457
458 widget = GTK_WIDGET (data);
459 accessible = GUCHARMAP_CHARTABLE_ACCESSIBLE (obj);
460 priv = GET_PRIVATE (accessible);
461 chartable = GUCHARMAP_CHARTABLE (widget);
462 chartable_priv = chartable->priv;
463
464 if (chartable_priv->vadjustment)
465 {
466 GtkAdjustment **adjustment_ptr = &priv->vadjustment;
467
468 priv->vadjustment = chartable_priv->vadjustment;
469 g_object_add_weak_pointer (G_OBJECT (priv->vadjustment),
470 (gpointer *) adjustment_ptr);
471 g_signal_connect (chartable_priv->vadjustment, "value-changed",
472 G_CALLBACK (adjustment_changed), obj);
473 }
474
475 g_signal_connect_after (chartable, "notify::hadjustment",
476 G_CALLBACK (sync_adjustment), obj);
477 g_signal_connect_after (chartable, "notify::vadjustment",
478 G_CALLBACK (sync_adjustment), obj);
479 g_signal_connect (widget, "size-allocate",
480 G_CALLBACK (size_allocated), obj);
481 g_signal_connect (chartable, "notify::active-character",
482 G_CALLBACK (sync_active_char), obj);
483
484 focus_obj = find_object (chartable, chartable_priv->active_cell, obj);
485 old_focus_obj = priv->focus_obj;
486 priv->focus_obj = focus_obj; /* adopts the reference from find_object */
487 if (old_focus_obj)
488 g_object_unref (old_focus_obj);
489 }
490
491 static void
gucharmap_chartable_accessible_destroyed(GtkWidget * widget,AtkObject * obj)492 gucharmap_chartable_accessible_destroyed (GtkWidget *widget,
493 AtkObject *obj)
494 {
495 GucharmapChartableAccessible *accessible = GUCHARMAP_CHARTABLE_ACCESSIBLE (obj);
496 GucharmapChartableAccessiblePrivate *priv = GET_PRIVATE (accessible);
497
498 if (priv->vadjustment)
499 {
500 GtkAdjustment **adjustment_ptr = &priv->vadjustment;
501
502 g_object_remove_weak_pointer (G_OBJECT (priv->vadjustment),
503 (gpointer *) adjustment_ptr);
504
505 g_signal_handlers_disconnect_by_func (priv->vadjustment,
506 G_CALLBACK (adjustment_changed),
507 obj);
508 priv->vadjustment = NULL;
509 }
510
511 g_signal_handlers_disconnect_by_func (widget,
512 G_CALLBACK (gucharmap_chartable_accessible_set_scroll_adjustments),
513 obj);
514 g_signal_handlers_disconnect_by_func (widget,
515 G_CALLBACK (sync_adjustment),
516 obj);
517 g_signal_handlers_disconnect_by_func (widget,
518 G_CALLBACK (size_allocated),
519 obj);
520 g_signal_handlers_disconnect_by_func (widget,
521 G_CALLBACK (sync_active_char),
522 obj);
523 }
524
525 static void
gucharmap_chartable_accessible_connect_widget_destroyed(GtkAccessible * accessible)526 gucharmap_chartable_accessible_connect_widget_destroyed (GtkAccessible *accessible)
527 {
528 if (gtk_accessible_get_widget (accessible))
529 {
530 g_signal_connect_after (gtk_accessible_get_widget (accessible),
531 "destroy",
532 G_CALLBACK (gucharmap_chartable_accessible_destroyed),
533 accessible);
534 }
535
536 GTK_ACCESSIBLE_CLASS (gucharmap_chartable_accessible_parent_class)->connect_widget_destroyed (accessible);
537 }
538
539 static void
gucharmap_chartable_accessible_class_init(GucharmapChartableAccessibleClass * klass)540 gucharmap_chartable_accessible_class_init (GucharmapChartableAccessibleClass *klass)
541 {
542 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
543 AtkObjectClass *atk_object_class = ATK_OBJECT_CLASS (klass);
544
545 gucharmap_chartable_accessible_parent_class = g_type_class_peek_parent (klass);
546
547 gobject_class->finalize = gucharmap_chartable_accessible_finalize;
548
549 /* This is normally true, except during introspection dump */
550 if (GTK_IS_ACCESSIBLE_CLASS (klass)) {
551 GtkAccessibleClass *accessible_class = GTK_ACCESSIBLE_CLASS (klass);
552 accessible_class->connect_widget_destroyed = gucharmap_chartable_accessible_connect_widget_destroyed;
553 }
554
555 atk_object_class->get_n_children = gucharmap_chartable_accessible_get_n_children;
556 atk_object_class->ref_child = gucharmap_chartable_accessible_ref_child;
557 atk_object_class->ref_state_set = gucharmap_chartable_accessible_ref_state_set;
558 atk_object_class->initialize = gucharmap_chartable_accessible_initialize;
559
560 g_type_class_add_private (gobject_class, sizeof (GucharmapChartableAccessiblePrivate));
561 }
562
563 static gint
gucharmap_chartable_accessible_get_n_columns(AtkTable * table)564 gucharmap_chartable_accessible_get_n_columns (AtkTable *table)
565 {
566 GtkWidget *widget;
567 GucharmapChartable *chartable;
568 GucharmapChartablePrivate *chartable_priv;
569
570 widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (table));
571 if (widget == NULL)
572 /* State is defunct */
573 return 0;
574
575 chartable = GUCHARMAP_CHARTABLE (widget);
576 chartable_priv = chartable->priv;
577
578 return chartable_priv->cols;
579 }
580
581
582 static gint
gucharmap_chartable_accessible_get_column_extent_at(AtkTable * table,gint row,gint column)583 gucharmap_chartable_accessible_get_column_extent_at (AtkTable *table,
584 gint row,
585 gint column)
586 {
587 GtkWidget *widget;
588
589 widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (table));
590 if (widget == NULL)
591 /* State is defunct */
592 return 0;
593
594 return 1;
595 }
596
597
598 static gint
gucharmap_chartable_accessible_get_n_rows(AtkTable * table)599 gucharmap_chartable_accessible_get_n_rows (AtkTable *table)
600 {
601 GtkWidget *widget;
602 GucharmapChartable *chartable;
603 GucharmapChartablePrivate *chartable_priv;
604 gint n_rows;
605
606 widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (table));
607 if (widget == NULL)
608 /* State is defunct */
609 return 0;
610
611 chartable = GUCHARMAP_CHARTABLE (widget);
612 chartable_priv = chartable->priv;
613
614 n_rows = UNICHAR_MAX / chartable_priv->cols + 1;
615
616 return n_rows;
617 }
618
619
620 static gint
gucharmap_chartable_accessible_get_row_extent_at(AtkTable * table,gint row,gint column)621 gucharmap_chartable_accessible_get_row_extent_at (AtkTable *table,
622 gint row,
623 gint column)
624 {
625 GtkWidget *widget;
626
627 widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (table));
628 if (widget == NULL)
629 /* State is defunct */
630 return 0;
631
632 return 1;
633 }
634
635
636 static gint
gucharmap_chartable_accessible_get_index_at(AtkTable * table,gint row,gint column)637 gucharmap_chartable_accessible_get_index_at (AtkTable *table,
638 gint row,
639 gint column)
640 {
641 GtkWidget *widget;
642 GucharmapChartable *chartable;
643 GucharmapChartablePrivate *chartable_priv;
644
645 widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (table));
646 if (widget == NULL)
647 /* State is defunct */
648 return -1;
649
650 chartable = GUCHARMAP_CHARTABLE (widget);
651 chartable_priv = chartable->priv;
652
653 return row * chartable_priv->cols + column;
654 }
655
656
657 static gint
gucharmap_chartable_accessible_get_column_at_index(AtkTable * table,gint index)658 gucharmap_chartable_accessible_get_column_at_index (AtkTable *table,
659 gint index)
660 {
661 GtkWidget *widget;
662 GucharmapChartable *chartable;
663 GucharmapChartablePrivate *chartable_priv;
664
665 widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (table));
666 if (widget == NULL)
667 /* State is defunct */
668 return -1;
669
670 chartable = GUCHARMAP_CHARTABLE (widget);
671 chartable_priv = chartable->priv;
672
673 return index % chartable_priv->cols;
674 }
675
676
677 static gint
gucharmap_chartable_accessible_get_row_at_index(AtkTable * table,gint index)678 gucharmap_chartable_accessible_get_row_at_index (AtkTable *table,
679 gint index)
680 {
681 GtkWidget *widget;
682 GucharmapChartable *chartable;
683 GucharmapChartablePrivate *chartable_priv;
684
685 widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (table));
686 if (widget == NULL)
687 /* State is defunct */
688 return -1;
689
690 chartable = GUCHARMAP_CHARTABLE (widget);
691 chartable_priv = chartable->priv;
692
693 return index / chartable_priv->cols;
694 }
695
696
697 static void
gucharmap_chartable_accessible_table_interface_init(AtkTableIface * iface)698 gucharmap_chartable_accessible_table_interface_init (AtkTableIface *iface)
699 {
700 iface->ref_at = gucharmap_chartable_accessible_ref_at;
701 iface->get_n_columns = gucharmap_chartable_accessible_get_n_columns;
702 iface->get_column_extent_at = gucharmap_chartable_accessible_get_column_extent_at;
703 iface->get_n_rows = gucharmap_chartable_accessible_get_n_rows;
704 iface->get_row_extent_at = gucharmap_chartable_accessible_get_row_extent_at;
705 iface->get_index_at = gucharmap_chartable_accessible_get_index_at;
706 iface->get_column_at_index = gucharmap_chartable_accessible_get_column_at_index;
707 iface->get_row_at_index = gucharmap_chartable_accessible_get_row_at_index;
708 }
709
710 #if 0
711 /* See http://bugzilla.gnome.org/show_bug.cgi?id=502840 */
712 #include <atk/atktype.h>
713
714 ATK_DEFINE_TYPE_WITH_CODE (GucharmapChartableAccessible,
715 gucharmap_chartable_accessible,
716 GUCHARMAP_TYPE_CHARTABLE,
717 G_IMPLEMENT_INTERFACE (ATK_TYPE_TABLE,
718 gucharmap_chartable_accessible_table_interface_init)
719 G_IMPLEMENT_INTERFACE (ATK_TYPE_COMPONENT,
720 gucharmap_chartable_accessible_component_interface_init))
721
722 #else
723
724 GType
gucharmap_chartable_accessible_get_type(void)725 gucharmap_chartable_accessible_get_type (void)
726 {
727 static volatile gsize type__volatile = 0;
728
729 if (g_once_init_enter (&type__volatile))
730 {
731 GTypeInfo typeinfo =
732 {
733 0 /* filled in by the code below */,
734 (GBaseInitFunc) NULL, /* base init */
735 (GBaseFinalizeFunc) NULL, /* base finalize */
736 (GClassInitFunc) gucharmap_chartable_accessible_class_init, /* class init */
737 (GClassFinalizeFunc) NULL, /* class finalize */
738 NULL, /* class data */
739 0 /* filled in by the code below */,
740 0, /* nb preallocs */
741 (GInstanceInitFunc) gucharmap_chartable_accessible_init, /* instance init */
742 NULL /* value table */
743 };
744 const GInterfaceInfo atk_table_info =
745 {
746 (GInterfaceInitFunc) gucharmap_chartable_accessible_table_interface_init,
747 (GInterfaceFinalizeFunc) NULL,
748 NULL
749 };
750 const GInterfaceInfo atk_component_info =
751 {
752 (GInterfaceInitFunc) gucharmap_chartable_accessible_component_interface_init,
753 (GInterfaceFinalizeFunc) NULL,
754 NULL
755 };
756 AtkObjectFactory *factory;
757 GType derived_type;
758 GTypeQuery query;
759 GType derived_atk_type;
760 GType type;
761
762 /* Figure out the size of the class and instance we are deriving from */
763 derived_type = g_type_parent (GUCHARMAP_TYPE_CHARTABLE);
764 factory = atk_registry_get_factory (atk_get_default_registry (),
765 derived_type);
766 derived_atk_type = atk_object_factory_get_accessible_type (factory);
767 g_type_query (derived_atk_type, &query);
768 typeinfo.class_size = query.class_size;
769 typeinfo.instance_size = query.instance_size;
770
771 type = g_type_register_static (derived_atk_type,
772 "GucharmapChartableAccessible",
773 &typeinfo, 0);
774
775 g_type_add_interface_static (type, ATK_TYPE_TABLE,
776 &atk_table_info);
777 g_type_add_interface_static (type, ATK_TYPE_COMPONENT,
778 &atk_component_info);
779
780 g_once_init_leave (&type__volatile, type);
781 }
782
783 return type__volatile;
784 }
785 #endif
786
787 /* API */
788
789 AtkObject*
gucharmap_chartable_accessible_new(GucharmapChartable * chartable)790 gucharmap_chartable_accessible_new (GucharmapChartable *chartable)
791 {
792 GObject *object;
793 AtkObject *accessible;
794
795 object = g_object_new (gucharmap_chartable_accessible_get_type (), NULL);
796 accessible = ATK_OBJECT (object);
797
798 /* atk is fucked up... */
799 atk_object_initialize (accessible, GTK_WIDGET (chartable));
800 accessible->role = ATK_ROLE_TABLE;
801 atk_object_set_name (accessible, _("Character Table"));
802
803 return accessible;
804 }
805