gucharmap-chartable-accessible.c 24.5 KB
Newer Older
1
/*
Christian Persch's avatar
Christian Persch committed
2 3
 * Copyright © 2003  Sun Microsystems Inc.
 * Copyright © 2007  Christian Persch
4 5
 *
 * This library is free software; you can redistribute it and/or
Christian Persch's avatar
Christian Persch committed
6
 * modify it under the terms of the GNU General Public
7
 * License as published by the Free Software Foundation; either
Christian Persch's avatar
Christian Persch committed
8
 * version 3 of the License, or (at your option) any later version.
9 10 11 12
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Christian Persch's avatar
Christian Persch committed
13
 * General Public License for more details.
14
 *
Christian Persch's avatar
Christian Persch committed
15
 * You should have received a copy of the GNU General Public
16
 * License along with this library; if not, write to the
17 18
 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
19 20
 */

21
#include <config.h>
22

23
#include <string.h>
24

25 26
#include <glib/gi18n-lib.h>

27
#include <gtk/gtk.h>
28

29
#include "gucharmap.h"
30 31 32
#include "gucharmap-chartable.h"
#include "gucharmap-chartable-accessible.h"
#include "gucharmap-chartable-cell-accessible.h"
33
#include "gucharmap-private.h"
34

35
typedef struct
36
{
37 38 39 40
  GtkAdjustment *vadjustment;
  GPtrArray *cells;
  AtkObject *focus_obj;
} 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
47 48
set_cell_visibility (GucharmapChartable  *chartable,
                     GucharmapChartableCellAccessible  *cell,
49 50
                     gboolean emit_signal)
{
51
  GucharmapChartablePrivate *chartable_priv = chartable->priv;
52
  gucharmap_chartable_cell_accessible_add_state (cell, ATK_STATE_VISIBLE, emit_signal);
53

54 55 56
  if (cell->index >= chartable_priv->page_first_cell &&
      cell->index < chartable_priv->page_first_cell
                    + chartable_priv->rows * chartable_priv->cols)
57
    {
58
      gucharmap_chartable_cell_accessible_add_state (cell, ATK_STATE_SHOWING, emit_signal);
59 60 61
    }
  else 
    {
62
      gucharmap_chartable_cell_accessible_remove_state (cell, ATK_STATE_SHOWING, emit_signal);
63 64 65 66
    }
}

static void
67
cell_destroyed (GucharmapChartableCellAccessible *cell)
68
{
69
  GucharmapChartableAccessiblePrivate *priv;
70
  AtkObject *parent;
71
  GPtrArray *cells;
72 73
  guint n_cells, n;
  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 81 82
  n_cells = cells->len;
  for (n = 0; n < n_cells; ++n)
    {
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 89 90
          return;
        }
    }
91

92
  g_warning ("Cell destroyed but was not in the cells cache?\n");
93 94 95
}

static AtkObject*
96 97
gucharmap_chartable_accessible_ref_child (AtkObject *obj,
                                          int index)
98
{
99 100
  GucharmapChartableAccessible *table;
  GucharmapChartableAccessiblePrivate *priv;
101
  GtkWidget *widget;
102
  GucharmapChartable *chartable;
103 104
  AtkObject *child;
  gchar* name;
105 106
  GPtrArray *cells;
  guint n_cells, n;
107

Christian Persch's avatar
Christian Persch committed
108
  widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (obj));
109 110 111 112
  if (widget == NULL)
    /* State is defunct */
    return NULL;

113
  if (index > UNICHAR_MAX)
114 115
    return NULL;

116
  table = GUCHARMAP_CHARTABLE_ACCESSIBLE (obj);
117
  priv = GET_PRIVATE (table);
118

119
  /* Check whether the child is cached */
120 121 122 123 124 125 126 127 128
  cells = priv->cells;
  n_cells = cells->len;
  for (n = 0; n < n_cells; ++n)
    {
      GucharmapChartableCellAccessible *cell = g_ptr_array_index (cells, n);

      if (index == cell->index)
        return g_object_ref (cell);
    }
129

130
  /* Not cached, create a new cell accessible */
131
  chartable = GUCHARMAP_CHARTABLE (widget);
132

133
  child = gucharmap_chartable_cell_accessible_new ();
134
  gucharmap_chartable_cell_accessible_initialise (GUCHARMAP_CHARTABLE_CELL_ACCESSIBLE (child),
135
                            GTK_WIDGET (chartable), obj, index);
136
  /* Set the name of the cell */
137
  name = g_strdup_printf("U+%4.4X %s", index, gucharmap_get_unicode_name (index));
138 139
  atk_object_set_name (child, name);
  g_free (name);
140
  set_cell_visibility (chartable, GUCHARMAP_CHARTABLE_CELL_ACCESSIBLE (child), FALSE);
141 142

  /* Store the cell in our cache */
143
  g_ptr_array_add (priv->cells, child);
144 145 146
  g_object_weak_ref (G_OBJECT (child),
                     (GWeakNotify) cell_destroyed,
                     child);
147 148 149 150 151

  return child; 
}

static AtkObject* 
152
gucharmap_chartable_accessible_ref_at (AtkTable *table,
153 154 155
                             gint    row,
                             gint    column)
{
156
  GucharmapChartable *chartable;
157
  GucharmapChartablePrivate *chartable_priv;
158
  GtkWidget *widget;
159 160 161
  AtkObject *child;
  gint index;

Christian Persch's avatar
Christian Persch committed
162
  widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (table));
163 164 165 166
  if (widget == NULL)
    /* State is defunct */
    return NULL;

167
  chartable = GUCHARMAP_CHARTABLE (widget);
168
  chartable_priv = chartable->priv;
169

170
  index =  row * chartable_priv->cols + column;
171

172
  child = gucharmap_chartable_accessible_ref_child (ATK_OBJECT (table), index);
173 174 175 176 177

  return child;
}

static AtkObject*
178
gucharmap_chartable_accessible_ref_accessible_at_point (AtkComponent *component,
179 180 181 182 183
                                              gint x, 
                                              gint y,
                                              AtkCoordType coord_type)
{
  GtkWidget *widget;
184
  GucharmapChartable *chartable;
185
  GucharmapChartablePrivate *chartable_priv;
186 187 188
  gint x_pos, y_pos;
  gint row, col;

Christian Persch's avatar
Christian Persch committed
189
  widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (component));
190 191 192 193
  if (widget == NULL)
    /* State is defunct */
    return NULL;

194
  chartable = GUCHARMAP_CHARTABLE (widget);
195
  chartable_priv = chartable->priv;
196

197
  atk_component_get_extents (component, &x_pos, &y_pos,
198 199 200 201 202 203 204
                             NULL, NULL, coord_type);

  /* Find cell at offset x - x_pos, y - y_pos */

  x_pos = x - x_pos;
  y_pos = y - y_pos;

205
  for (col = 0; col < chartable_priv->cols; col++)
206
    {
207
      if (x_pos < _gucharmap_chartable_x_offset (chartable, col))
208 209 210 211 212
        {
          col--;
          break;
        }
    }
213
  if (col == chartable_priv->cols || col < 0)
214 215
    return NULL;

216
  for (row = 0; row < chartable_priv->rows; row++)
217
    {
218
      if (y_pos < _gucharmap_chartable_y_offset (chartable, row))
219 220 221 222 223
        {
          row--;
          break;
        }
    }
224
  if (row == chartable_priv->rows || row < 0)
225 226
    return NULL;

227
  row += chartable_priv->page_first_cell / chartable_priv->cols;
228

229
  return gucharmap_chartable_accessible_ref_at (ATK_TABLE (component), row, col);
230 231 232
}

static void
233
gucharmap_chartable_accessible_component_interface_init (AtkComponentIface *iface)
234 235 236
{
  g_return_if_fail (iface != NULL);

237
  iface->ref_accessible_at_point = gucharmap_chartable_accessible_ref_accessible_at_point;
238 239 240
}

static AtkStateSet*
241
gucharmap_chartable_accessible_ref_state_set (AtkObject *obj)
242 243 244 245
{
  AtkStateSet *state_set;
  GtkWidget *widget;

246
  state_set = ATK_OBJECT_CLASS (gucharmap_chartable_accessible_parent_class)->ref_state_set (obj);
Christian Persch's avatar
Christian Persch committed
247
  widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (obj));
248 249 250 251

  if (widget != NULL)
    atk_state_set_add_state (state_set, ATK_STATE_MANAGES_DESCENDANTS);

Christian Persch's avatar
Christian Persch committed
252
  /* FIXME: reference count ? */
253 254 255
  return state_set;
}

256
/* FIXMEchpe: shouldn't this get the number from the chartable's codepoint list instead?? */
257
static gint
258
gucharmap_chartable_accessible_get_n_children (AtkObject *obj)
259 260 261
{
  GtkWidget *widget;

Christian Persch's avatar
Christian Persch committed
262
  widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (obj));
263 264 265 266 267 268 269
  if (widget == NULL)
    /* State is defunct */
    return 0;

  return UNICHAR_MAX + 1;
}

270 271 272
static void
gucharmap_chartable_accessible_init (GucharmapChartableAccessible *accessible)
{
273 274 275
  GucharmapChartableAccessiblePrivate *priv = GET_PRIVATE (accessible);

  priv->cells = g_ptr_array_sized_new (512);
276 277
}

278
static void
279
gucharmap_chartable_accessible_finalize (GObject *obj)
280
{
281
  GucharmapChartableAccessible *accessible = GUCHARMAP_CHARTABLE_ACCESSIBLE (obj);
282 283
  GucharmapChartableAccessiblePrivate *priv = GET_PRIVATE (accessible);
  GPtrArray *cells;
284 285
  guint n_cells, n;

286 287
  if (priv->focus_obj)
    g_object_unref (priv->focus_obj);
288

289
  /* Remove the weak ref notifications */
290
  cells = priv->cells;
291 292 293 294 295 296 297 298 299 300
  n_cells = cells->len;
  for (n = 0; n < n_cells; ++n)
    {
      GucharmapChartableCellAccessible *cell = g_ptr_array_index (cells, n);

      g_object_weak_unref (G_OBJECT (cell),
                           (GWeakNotify) cell_destroyed,
                           cell);
    }

301
  g_ptr_array_free (priv->cells, TRUE);
302

303
  G_OBJECT_CLASS (gucharmap_chartable_accessible_parent_class)->finalize (obj);
304 305 306
}

static void
307
gucharmap_chartable_accessible_update_all_cells (AtkObject *obj)
308
{
309
  GucharmapChartableAccessible *accessible;
310
  GucharmapChartableAccessiblePrivate *priv;
311
  GtkWidget *widget;
312
  GucharmapChartable *chartable;
313
  GPtrArray *cells;
314
  guint n_cells, n;
315

Christian Persch's avatar
Christian Persch committed
316
  widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (obj));
317 318 319 320
  if (!widget)
    /* Widget is being deleted */
    return;
  
321
  accessible = GUCHARMAP_CHARTABLE_ACCESSIBLE (obj);
322 323
  priv = GET_PRIVATE (accessible);

324
  chartable = GUCHARMAP_CHARTABLE (widget);
325

326
  cells = priv->cells;
327 328
  n_cells = cells->len;
  for (n = 0; n < n_cells; ++n)
329
    {
330
      GucharmapChartableCellAccessible *cell = g_ptr_array_index (cells, n);
331

332
      set_cell_visibility (chartable, GUCHARMAP_CHARTABLE_CELL_ACCESSIBLE (cell), TRUE);
333 334
    }

335 336
  g_signal_emit_by_name (obj, "visible-data-changed");
}
337 338 339 340 341

static void
adjustment_changed (GtkAdjustment *adj,
                    AtkObject     *obj)
{
342
  gucharmap_chartable_accessible_update_all_cells (obj);
343 344 345 346 347 348 349
}

static void
size_allocated (GtkWidget     *widget,
                GtkAllocation *alloc,
                gpointer      data)
{
350
  gucharmap_chartable_accessible_update_all_cells (ATK_OBJECT (data));
351 352
}

353
static AtkObject* /* reference */
354
find_object (GucharmapChartable   *chartable,
355 356 357
             gunichar  uc,
             AtkObject *obj)
{
358
  GucharmapChartablePrivate *chartable_priv = chartable->priv;
359 360
  gint row, column;

361
  row = uc / chartable_priv->cols;
362
  column = _gucharmap_chartable_cell_column (chartable, uc);
363 364 365 366 367

  return atk_table_ref_at (ATK_TABLE (obj), row, column);
}

static void
368 369
sync_active_char (GucharmapChartable  *chartable,
                  GParamSpec *pspec,
370
                  GucharmapChartableAccessible *accessible)
371
{
372
  GucharmapChartableAccessiblePrivate *priv = GET_PRIVATE (accessible);
373 374
  gunichar uc;
  AtkObject *child;
375
  AtkObject *focus_obj;
376

377
  uc = gucharmap_chartable_get_active_character (chartable);
378

379
  child = find_object (chartable, uc, ATK_OBJECT (accessible));
380
  focus_obj = priv->focus_obj;
381 382
  if (focus_obj != child)
    {
383 384 385
      if (focus_obj)
        gucharmap_chartable_cell_accessible_remove_state (GUCHARMAP_CHARTABLE_CELL_ACCESSIBLE (focus_obj), ATK_STATE_FOCUSED, FALSE);

386
      gucharmap_chartable_cell_accessible_add_state (GUCHARMAP_CHARTABLE_CELL_ACCESSIBLE (child), ATK_STATE_FOCUSED, FALSE);
387 388 389 390 391
    }

  if (focus_obj)
    g_object_unref (focus_obj);

392
  priv->focus_obj = child; /* adopts the reference from find_object */
393 394

  g_signal_emit_by_name (accessible, "active-descendant-changed", child);
395 396
}

397 398 399 400 401 402 403
static void
gucharmap_chartable_accessible_set_scroll_adjustments (GucharmapChartable *chartable,
                                                       GtkAdjustment *hadjustment,
                                                       GtkAdjustment *vadjustment,
                                                       AtkObject *obj)
{
  GucharmapChartableAccessible *accessible = GUCHARMAP_CHARTABLE_ACCESSIBLE (obj);
404
  GucharmapChartableAccessiblePrivate *priv = GET_PRIVATE (accessible);
405

406
  if (priv->vadjustment != vadjustment)
407
    {
408 409
      GtkAdjustment **adjustment_ptr = &priv->vadjustment;
      g_object_remove_weak_pointer (G_OBJECT (priv->vadjustment),
410
                                    (gpointer *) adjustment_ptr);
411
      g_signal_handlers_disconnect_by_func (priv->vadjustment,
412 413
                                            G_CALLBACK (adjustment_changed),
                                            obj);
414 415
      priv->vadjustment = vadjustment;
      g_object_add_weak_pointer (G_OBJECT (priv->vadjustment),
416
                                 (gpointer *) adjustment_ptr);
417
      g_signal_connect (vadjustment, "value-changed",
418 419 420
                        G_CALLBACK (adjustment_changed), obj);
    }
}
421

422
static void
423 424 425
sync_adjustment (GucharmapChartable *chartable,
                 GParamSpec         *pspec,
                 AtkObject          *accessible)
426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441
{
  GtkAdjustment *hadjustment, *vadjustment;

  g_object_get (chartable,
                "hadjustment", &hadjustment,
                "vadjustment", &vadjustment,
                NULL);
  /* hadjustment and vadjustment are set to NULL in
     gtk_scrolled_window_remove() */
  if (hadjustment && vadjustment)
    gucharmap_chartable_accessible_set_scroll_adjustments (chartable,
                                                           hadjustment,
                                                           vadjustment,
                                                           accessible);
}

442
static void
443
gucharmap_chartable_accessible_initialize (AtkObject *obj,
444
                                           gpointer  data)
445 446
{
  GtkWidget *widget;
447
  AtkObject *focus_obj, *old_focus_obj;
448
  GucharmapChartableAccessible *accessible;
449
  GucharmapChartableAccessiblePrivate *priv;
450
  GucharmapChartable *chartable;
451
  GucharmapChartablePrivate *chartable_priv;
452

453
  ATK_OBJECT_CLASS (gucharmap_chartable_accessible_parent_class)->initialize (obj, data);
454 455

  widget = GTK_WIDGET (data);
456
  accessible = GUCHARMAP_CHARTABLE_ACCESSIBLE (obj);
457
  priv = GET_PRIVATE (accessible);
458
  chartable = GUCHARMAP_CHARTABLE (widget);
459
  chartable_priv = chartable->priv;
460

461
  if (chartable_priv->vadjustment)
462
    {
463
      GtkAdjustment **adjustment_ptr = &priv->vadjustment;
464

465
      priv->vadjustment = chartable_priv->vadjustment;
466
      g_object_add_weak_pointer (G_OBJECT (priv->vadjustment),
467
                                 (gpointer *) adjustment_ptr);
468
      g_signal_connect (chartable_priv->vadjustment, "value-changed",
469 470 471
                        G_CALLBACK (adjustment_changed), obj);
    }

472 473 474 475
  g_signal_connect_after (chartable, "notify::hadjustment",
                          G_CALLBACK (sync_adjustment), obj);
  g_signal_connect_after (chartable, "notify::vadjustment",
                          G_CALLBACK (sync_adjustment), obj);
476
  g_signal_connect (widget, "size-allocate",
477
                    G_CALLBACK (size_allocated), obj);
478 479
  g_signal_connect (chartable, "notify::active-character",
                    G_CALLBACK (sync_active_char), obj);
480

481
  focus_obj = find_object (chartable, chartable_priv->active_cell, obj);
482 483
  old_focus_obj = priv->focus_obj;
  priv->focus_obj = focus_obj; /* adopts the reference from find_object */
484 485
  if (old_focus_obj)
    g_object_unref (old_focus_obj);
486 487
}

488 489 490 491 492
static void
gucharmap_chartable_accessible_destroyed (GtkWidget *widget,
                                          AtkObject *obj)
{
  GucharmapChartableAccessible *accessible = GUCHARMAP_CHARTABLE_ACCESSIBLE (obj);
493
  GucharmapChartableAccessiblePrivate *priv = GET_PRIVATE (accessible);
494

495
  if (priv->vadjustment)
496
    {
497
      GtkAdjustment **adjustment_ptr = &priv->vadjustment;
498

499
      g_object_remove_weak_pointer (G_OBJECT (priv->vadjustment),
500 501
                                    (gpointer *) adjustment_ptr);
          
502
      g_signal_handlers_disconnect_by_func (priv->vadjustment,
503 504
                                            G_CALLBACK (adjustment_changed),
                                            obj);
505
      priv->vadjustment = NULL;
506 507 508 509 510
    }

  g_signal_handlers_disconnect_by_func (widget,
                                        G_CALLBACK (gucharmap_chartable_accessible_set_scroll_adjustments),
                                        obj);
511 512 513
  g_signal_handlers_disconnect_by_func (widget,
					G_CALLBACK (sync_adjustment),
					obj);
514 515 516 517 518 519 520 521 522 523 524
  g_signal_handlers_disconnect_by_func (widget,
                                        G_CALLBACK (size_allocated),
                                        obj);
  g_signal_handlers_disconnect_by_func (widget,
                                        G_CALLBACK (sync_active_char),
                                        obj);
}

static void
gucharmap_chartable_accessible_connect_widget_destroyed (GtkAccessible *accessible)
{
525 526 527
  if (gtk_accessible_get_widget (accessible))
    {
      g_signal_connect_after (gtk_accessible_get_widget (accessible),
528 529 530 531 532 533 534
                              "destroy",
                              G_CALLBACK (gucharmap_chartable_accessible_destroyed),
                              accessible);
    }

  GTK_ACCESSIBLE_CLASS (gucharmap_chartable_accessible_parent_class)->connect_widget_destroyed (accessible);
}
535 536

static void
537
gucharmap_chartable_accessible_class_init (GucharmapChartableAccessibleClass *klass)
538 539
{
  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
540
  AtkObjectClass *atk_object_class = ATK_OBJECT_CLASS (klass);
541

542 543
  gucharmap_chartable_accessible_parent_class = g_type_class_peek_parent (klass);

544
  gobject_class->finalize = gucharmap_chartable_accessible_finalize;
545

546 547 548 549 550
  /* This is normally true, except during introspection dump */
  if (GTK_IS_ACCESSIBLE_CLASS (klass)) {
    GtkAccessibleClass *accessible_class = GTK_ACCESSIBLE_CLASS (klass);
    accessible_class->connect_widget_destroyed = gucharmap_chartable_accessible_connect_widget_destroyed;
  }
551 552 553 554 555

  atk_object_class->get_n_children = gucharmap_chartable_accessible_get_n_children;
  atk_object_class->ref_child = gucharmap_chartable_accessible_ref_child;
  atk_object_class->ref_state_set = gucharmap_chartable_accessible_ref_state_set;
  atk_object_class->initialize = gucharmap_chartable_accessible_initialize;
556 557

  g_type_class_add_private (gobject_class, sizeof (GucharmapChartableAccessiblePrivate));
558
}
559 560

static gint
561
gucharmap_chartable_accessible_get_n_columns (AtkTable *table)
562 563
{
  GtkWidget *widget;
564
  GucharmapChartable *chartable;
565
  GucharmapChartablePrivate *chartable_priv;
566

Christian Persch's avatar
Christian Persch committed
567
  widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (table));
568 569 570 571
  if (widget == NULL)
    /* State is defunct */
    return 0;

572
  chartable = GUCHARMAP_CHARTABLE (widget);
573
  chartable_priv = chartable->priv;
574

575
  return chartable_priv->cols;
576 577 578 579
}


static gint
580
gucharmap_chartable_accessible_get_column_extent_at (AtkTable       *table,
581 582 583 584 585
                                           gint           row,
                                           gint           column)
{
  GtkWidget *widget;

Christian Persch's avatar
Christian Persch committed
586
  widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (table));
587 588 589 590 591 592 593 594 595
  if (widget == NULL)
    /* State is defunct */
    return 0;

  return 1;
}


static gint
596
gucharmap_chartable_accessible_get_n_rows (AtkTable *table)
597 598
{
  GtkWidget *widget;
599
  GucharmapChartable *chartable;
600
  GucharmapChartablePrivate *chartable_priv;
601 602
  gint n_rows;

Christian Persch's avatar
Christian Persch committed
603
  widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (table));
604 605 606 607
  if (widget == NULL)
    /* State is defunct */
    return 0;

608
  chartable = GUCHARMAP_CHARTABLE (widget);
609
  chartable_priv = chartable->priv;
610

611
  n_rows = UNICHAR_MAX / chartable_priv->cols + 1;
612 613 614 615 616 617

  return n_rows;
}

 
static gint
618
gucharmap_chartable_accessible_get_row_extent_at (AtkTable *table,
619 620 621 622 623
                                        gint    row,
                                        gint    column)
{
  GtkWidget *widget;

Christian Persch's avatar
Christian Persch committed
624
  widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (table));
625 626 627 628 629 630 631 632 633
  if (widget == NULL)
    /* State is defunct */
    return 0;

  return 1;
}

 
static gint
634
gucharmap_chartable_accessible_get_index_at (AtkTable *table,
635 636 637 638
                                   gint     row,
                                   gint     column)
{
  GtkWidget *widget;
639
  GucharmapChartable *chartable;
640
  GucharmapChartablePrivate *chartable_priv;
641

Christian Persch's avatar
Christian Persch committed
642
  widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (table));
643 644 645 646
  if (widget == NULL)
    /* State is defunct */
    return -1;

647
  chartable = GUCHARMAP_CHARTABLE (widget);
648
  chartable_priv = chartable->priv;
649

650
  return row * chartable_priv->cols + column;
651 652 653 654
}


static gint
655
gucharmap_chartable_accessible_get_column_at_index (AtkTable *table,
656 657 658
                                          gint     index)
{
  GtkWidget *widget;
659
  GucharmapChartable *chartable;
660
  GucharmapChartablePrivate *chartable_priv;
661

Christian Persch's avatar
Christian Persch committed
662
  widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (table));
663 664 665 666
  if (widget == NULL)
    /* State is defunct */
    return -1;

667
  chartable = GUCHARMAP_CHARTABLE (widget);
668
  chartable_priv = chartable->priv;
669

670
  return index % chartable_priv->cols;
671 672 673 674
}


static gint
675
gucharmap_chartable_accessible_get_row_at_index (AtkTable *table,
676
                                                 gint     index)
677 678
{
  GtkWidget *widget;
679
  GucharmapChartable *chartable;
680
  GucharmapChartablePrivate *chartable_priv;
681

Christian Persch's avatar
Christian Persch committed
682
  widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (table));
683 684 685 686
  if (widget == NULL)
    /* State is defunct */
    return -1;

687
  chartable = GUCHARMAP_CHARTABLE (widget);
688
  chartable_priv = chartable->priv;
689

690
  return index / chartable_priv->cols;
691 692 693 694
}


static void
695
gucharmap_chartable_accessible_table_interface_init (AtkTableIface *iface)
696
{
697 698 699 700 701 702 703 704
  iface->ref_at = gucharmap_chartable_accessible_ref_at;
  iface->get_n_columns = gucharmap_chartable_accessible_get_n_columns;
  iface->get_column_extent_at = gucharmap_chartable_accessible_get_column_extent_at;
  iface->get_n_rows = gucharmap_chartable_accessible_get_n_rows;
  iface->get_row_extent_at = gucharmap_chartable_accessible_get_row_extent_at;
  iface->get_index_at = gucharmap_chartable_accessible_get_index_at;
  iface->get_column_at_index = gucharmap_chartable_accessible_get_column_at_index;
  iface->get_row_at_index = gucharmap_chartable_accessible_get_row_at_index;
705 706
}

707 708 709 710 711 712 713 714 715 716 717 718 719 720
#if 0
/* See http://bugzilla.gnome.org/show_bug.cgi?id=502840 */
#include <atk/atktype.h>

ATK_DEFINE_TYPE_WITH_CODE (GucharmapChartableAccessible,
                           gucharmap_chartable_accessible,
                           GUCHARMAP_TYPE_CHARTABLE,
                           G_IMPLEMENT_INTERFACE (ATK_TYPE_TABLE,
                                                  gucharmap_chartable_accessible_table_interface_init)
                           G_IMPLEMENT_INTERFACE (ATK_TYPE_COMPONENT,
                                                  gucharmap_chartable_accessible_component_interface_init))

#else

721
GType
722
gucharmap_chartable_accessible_get_type (void)
723
{
724
  static volatile gsize type__volatile = 0;
725

726
  if (g_once_init_enter (&type__volatile))
727
    {
728 729
      GTypeInfo typeinfo =
      {
730
        0 /* filled in by the code below */,
731 732 733 734 735
        (GBaseInitFunc) NULL, /* base init */
        (GBaseFinalizeFunc) NULL, /* base finalize */
        (GClassInitFunc) gucharmap_chartable_accessible_class_init, /* class init */
        (GClassFinalizeFunc) NULL, /* class finalize */
        NULL, /* class data */
736
        0 /* filled in by the code below */,
737
        0, /* nb preallocs */
738
        (GInstanceInitFunc) gucharmap_chartable_accessible_init, /* instance init */
739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778
        NULL /* value table */
      };
      const GInterfaceInfo atk_table_info =
      {
          (GInterfaceInitFunc) gucharmap_chartable_accessible_table_interface_init,
          (GInterfaceFinalizeFunc) NULL,
          NULL
      };
      const GInterfaceInfo atk_component_info =
      {
          (GInterfaceInitFunc) gucharmap_chartable_accessible_component_interface_init,
          (GInterfaceFinalizeFunc) NULL,
          NULL
      };
      AtkObjectFactory *factory;
      GType derived_type;
      GTypeQuery query;
      GType derived_atk_type;
      GType type;

      /* Figure out the size of the class and instance we are deriving from */
      derived_type = g_type_parent (GUCHARMAP_TYPE_CHARTABLE);
      factory = atk_registry_get_factory (atk_get_default_registry (), 
                                          derived_type);
      derived_atk_type = atk_object_factory_get_accessible_type (factory);
      g_type_query (derived_atk_type, &query);
      typeinfo.class_size = query.class_size;
      typeinfo.instance_size = query.instance_size;

      type = g_type_register_static (derived_atk_type,
                                     "GucharmapChartableAccessible",
                                     &typeinfo, 0);

      g_type_add_interface_static (type, ATK_TYPE_TABLE,
                                   &atk_table_info);
      g_type_add_interface_static (type, ATK_TYPE_COMPONENT,
                                   &atk_component_info);

      g_once_init_leave (&type__volatile, type);
    }
779

780
  return type__volatile;
781
}
782
#endif
783

784
/* API */
785 786

AtkObject* 
787
gucharmap_chartable_accessible_new (GucharmapChartable *chartable)
788 789 790 791
{
  GObject *object;
  AtkObject *accessible;

792
  object = g_object_new (gucharmap_chartable_accessible_get_type (), NULL);
793 794
  accessible = ATK_OBJECT (object);

795 796
  /* atk is fucked up... */
  atk_object_initialize (accessible, GTK_WIDGET (chartable));
797
  accessible->role = ATK_ROLE_TABLE;
798
  atk_object_set_name (accessible, _("Character Table"));
799

800 801
  return accessible;
}