1 /* GAIL - The GNOME Accessibility Implementation Library
2 * Copyright 2001 Sun Microsystems Inc.
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.
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.
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.
22 #include "gailclist.h"
23 #include "gailclistcell.h"
24 #include "gailcellparent.h"
26 /* Copied from gtkclist.c */
27 /* this defigns the base grid spacing */
28 #define CELL_SPACING 1
30 /* added the horizontal space at the beginning and end of a row*/
31 #define COLUMN_INSET 3
34 /* gives the top pixel of the given row in context of
35 * the clist's voffset */
36 #define ROW_TOP_YPIXEL(clist, row) (((clist)->row_height * (row)) + \
37 (((row) + 1) * CELL_SPACING) + \
40 /* returns the row index from a y pixel location in the
41 * context of the clist's voffset */
42 #define ROW_FROM_YPIXEL(clist, y) (((y) - (clist)->voffset) / \
43 ((clist)->row_height + CELL_SPACING))
44 /* gives the left pixel of the given column in context of
45 * the clist's hoffset */
46 #define COLUMN_LEFT_XPIXEL(clist, colnum) ((clist)->column[(colnum)].area.x + \
49 /* returns the column index from a x pixel location in the
50 * context of the clist's hoffset */
52 COLUMN_FROM_XPIXEL (GtkCList * clist,
57 for (i = 0; i < clist->columns; i++)
58 if (clist->column[i].visible)
60 cx = clist->column[i].area.x + clist->hoffset;
62 if (x >= (cx - (COLUMN_INSET + CELL_SPACING)) &&
63 x <= (cx + clist->column[i].area.width + COLUMN_INSET))
71 /* returns the top pixel of the given row in the context of
73 #define ROW_TOP(clist, row) (((clist)->row_height + CELL_SPACING) * (row))
75 /* returns the left pixel of the given column in the context of
77 #define COLUMN_LEFT(clist, colnum) ((clist)->column[(colnum)].area.x)
79 /* returns the total height of the list */
80 #define LIST_HEIGHT(clist) (((clist)->row_height * ((clist)->rows)) + \
81 (CELL_SPACING * ((clist)->rows + 1)))
84 LIST_WIDTH (GtkCList * clist)
88 for (last_column = clist->columns - 1;
89 last_column >= 0 && !clist->column[last_column].visible; last_column--);
92 return (clist->column[last_column].area.x +
93 clist->column[last_column].area.width +
94 COLUMN_INSET + CELL_SPACING);
98 /* returns the GList item for the nth row */
99 #define ROW_ELEMENT(clist, row) (((row) == (clist)->rows - 1) ? \
100 (clist)->row_list_end : \
101 g_list_nth ((clist)->row_list, (row)))
103 typedef struct _GailCListRow GailCListRow;
104 typedef struct _GailCListCellData GailCListCellData;
107 static void gail_clist_class_init (GailCListClass *klass);
108 static void gail_clist_real_initialize (AtkObject *obj,
110 static void gail_clist_finalize (GObject *object);
112 static gint gail_clist_get_n_children (AtkObject *obj);
113 static AtkObject* gail_clist_ref_child (AtkObject *obj,
115 static AtkStateSet* gail_clist_ref_state_set (AtkObject *obj);
118 static void atk_selection_interface_init (AtkSelectionIface *iface);
119 static gboolean gail_clist_clear_selection (AtkSelection *selection);
121 static AtkObject* gail_clist_ref_selection (AtkSelection *selection,
123 static gint gail_clist_get_selection_count (AtkSelection *selection);
124 static gboolean gail_clist_is_child_selected (AtkSelection *selection,
126 static gboolean gail_clist_select_all_selection (AtkSelection *selection);
128 static void atk_table_interface_init (AtkTableIface *iface);
129 static gint gail_clist_get_index_at (AtkTable *table,
132 static gint gail_clist_get_column_at_index (AtkTable *table,
134 static gint gail_clist_get_row_at_index (AtkTable *table,
136 static AtkObject* gail_clist_ref_at (AtkTable *table,
139 static AtkObject* gail_clist_ref_at_actual (AtkTable *table,
143 gail_clist_get_caption (AtkTable *table);
145 static gint gail_clist_get_n_columns (AtkTable *table);
146 static gint gail_clist_get_n_actual_columns (GtkCList *clist);
148 static G_CONST_RETURN gchar*
149 gail_clist_get_column_description(AtkTable *table,
151 static AtkObject* gail_clist_get_column_header (AtkTable *table,
153 static gint gail_clist_get_n_rows (AtkTable *table);
154 static G_CONST_RETURN gchar*
155 gail_clist_get_row_description (AtkTable *table,
157 static AtkObject* gail_clist_get_row_header (AtkTable *table,
159 static AtkObject* gail_clist_get_summary (AtkTable *table);
160 static gboolean gail_clist_add_row_selection (AtkTable *table,
162 static gboolean gail_clist_remove_row_selection (AtkTable *table,
164 static gint gail_clist_get_selected_rows (AtkTable *table,
165 gint **rows_selected);
166 static gboolean gail_clist_is_row_selected (AtkTable *table,
168 static gboolean gail_clist_is_selected (AtkTable *table,
171 static void gail_clist_set_caption (AtkTable *table,
173 static void gail_clist_set_column_description(AtkTable *table,
175 const gchar *description);
176 static void gail_clist_set_column_header (AtkTable *table,
179 static void gail_clist_set_row_description (AtkTable *table,
181 const gchar *description);
182 static void gail_clist_set_row_header (AtkTable *table,
185 static void gail_clist_set_summary (AtkTable *table,
186 AtkObject *accessible);
188 /* gailcellparent.h */
190 static void gail_cell_parent_interface_init (GailCellParentIface *iface);
191 static void gail_clist_get_cell_extents (GailCellParent *parent,
197 AtkCoordType coord_type);
199 static void gail_clist_get_cell_area (GailCellParent *parent,
201 GdkRectangle *cell_rect);
203 static void gail_clist_select_row_gtk (GtkCList *clist,
208 static void gail_clist_unselect_row_gtk (GtkCList *clist,
213 static gint gail_clist_get_visible_column (AtkTable *table,
215 static gint gail_clist_get_actual_column (AtkTable *table,
217 static void gail_clist_set_row_data (AtkTable *table,
219 const gchar *description,
223 gail_clist_get_row_data (AtkTable *table,
225 static void gail_clist_get_visible_rect (GtkCList *clist,
226 GdkRectangle *clist_rect);
227 static gboolean gail_clist_is_cell_visible (GdkRectangle *cell_rect,
228 GdkRectangle *visible_rect);
229 static void gail_clist_cell_data_new (GailCList *clist,
233 static void gail_clist_cell_destroyed (gpointer data);
234 static void gail_clist_cell_data_remove (GailCList *clist,
236 static GailCell* gail_clist_find_cell (GailCList *clist,
238 static void gail_clist_adjustment_changed (GtkAdjustment *adjustment,
241 struct _GailCListColumn
249 GtkCListRow *row_data;
255 struct _GailCListCellData
263 static gpointer parent_class = NULL;
266 gail_clist_get_type (void)
268 static GType type = 0;
272 static const GTypeInfo tinfo =
274 sizeof (GailCListClass),
275 (GBaseInitFunc) NULL, /* base init */
276 (GBaseFinalizeFunc) NULL, /* base finalize */
277 (GClassInitFunc) gail_clist_class_init, /* class init */
278 (GClassFinalizeFunc) NULL, /* class finalize */
279 NULL, /* class data */
280 sizeof (GailCList), /* instance size */
281 0, /* nb preallocs */
282 (GInstanceInitFunc) NULL, /* instance init */
283 NULL /* value table */
286 static const GInterfaceInfo atk_table_info =
288 (GInterfaceInitFunc) atk_table_interface_init,
289 (GInterfaceFinalizeFunc) NULL,
293 static const GInterfaceInfo atk_selection_info =
295 (GInterfaceInitFunc) atk_selection_interface_init,
296 (GInterfaceFinalizeFunc) NULL,
300 static const GInterfaceInfo gail_cell_parent_info =
302 (GInterfaceInitFunc) gail_cell_parent_interface_init,
303 (GInterfaceFinalizeFunc) NULL,
307 type = g_type_register_static (GAIL_TYPE_CONTAINER,
308 "GailCList", &tinfo, 0);
309 g_type_add_interface_static (type, ATK_TYPE_TABLE,
311 g_type_add_interface_static (type, ATK_TYPE_SELECTION,
312 &atk_selection_info);
313 g_type_add_interface_static (type, GAIL_TYPE_CELL_PARENT,
314 &gail_cell_parent_info);
320 gail_clist_class_init (GailCListClass *klass)
322 AtkObjectClass *class = ATK_OBJECT_CLASS (klass);
323 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
325 parent_class = g_type_class_peek_parent (klass);
327 class->get_n_children = gail_clist_get_n_children;
328 class->ref_child = gail_clist_ref_child;
329 class->ref_state_set = gail_clist_ref_state_set;
330 class->initialize = gail_clist_real_initialize;
332 gobject_class->finalize = gail_clist_finalize;
336 gail_clist_new (GtkWidget *widget)
339 AtkObject *accessible;
341 g_return_val_if_fail (GTK_IS_CLIST (widget), NULL);
343 object = g_object_new (GAIL_TYPE_CLIST, NULL);
345 accessible = ATK_OBJECT (object);
346 atk_object_initialize (accessible, widget);
348 accessible->role = ATK_ROLE_TABLE;
354 gail_clist_real_initialize (AtkObject *obj,
361 ATK_OBJECT_CLASS (parent_class)->initialize (obj, data);
363 clist = GAIL_CLIST (obj);
365 clist->caption = NULL;
366 clist->summary = NULL;
367 clist->row_data = NULL;
368 clist->cell_data = NULL;
369 clist->previous_selected_cell = NULL;
371 gtk_clist = GTK_CLIST (data);
373 clist->n_cols = gtk_clist->columns;
374 clist->columns = g_new (GailCListColumn, gtk_clist->columns);
375 for (i = 0; i < gtk_clist->columns; i++)
377 clist->columns[i].description = NULL;
378 clist->columns[i].header = NULL;
381 * Set up signal handlers for select-row and unselect-row
383 g_signal_connect (gtk_clist,
385 G_CALLBACK (gail_clist_select_row_gtk),
387 g_signal_connect (gtk_clist,
389 G_CALLBACK (gail_clist_unselect_row_gtk),
392 * Adjustment callbacks
394 if (gtk_clist->hadjustment)
396 g_signal_connect (gtk_clist->hadjustment,
398 G_CALLBACK (gail_clist_adjustment_changed),
401 if (gtk_clist->vadjustment)
403 g_signal_connect (gtk_clist->vadjustment,
405 G_CALLBACK (gail_clist_adjustment_changed),
411 gail_clist_finalize (GObject *object)
413 GailCList *clist = GAIL_CLIST (object);
418 g_object_unref (clist->caption);
420 g_object_unref (clist->summary);
422 for (i = 0; i < clist->n_cols; i++)
424 g_free (clist->columns[i].description);
425 if (clist->columns[i].header)
426 g_object_unref (clist->columns[i].header);
428 g_free (clist->columns);
430 array = clist->row_data;
432 if (clist->previous_selected_cell)
433 g_object_unref (clist->previous_selected_cell);
437 for (i = 0; i < array->len; i++)
439 GailCListRow *row_data;
441 row_data = g_array_index (array, GailCListRow*, i);
443 if (row_data->header)
444 g_object_unref (row_data->header);
445 g_free (row_data->description);
449 if (clist->cell_data)
453 for (temp_list = clist->cell_data; temp_list; temp_list = temp_list->next)
455 g_list_free (temp_list->data);
457 g_list_free (clist->cell_data);
460 G_OBJECT_CLASS (parent_class)->finalize (object);
464 gail_clist_get_n_children (AtkObject *obj)
469 g_return_val_if_fail (GAIL_IS_CLIST (obj), 0);
471 widget = GTK_ACCESSIBLE (obj)->widget;
478 row = gail_clist_get_n_rows (ATK_TABLE (obj));
479 col = gail_clist_get_n_actual_columns (GTK_CLIST (widget));
484 gail_clist_ref_child (AtkObject *obj,
491 g_return_val_if_fail (GAIL_IS_CLIST (obj), NULL);
492 g_return_val_if_fail (i >= 0, NULL);
494 widget = GTK_ACCESSIBLE (obj)->widget;
501 n_columns = gail_clist_get_n_actual_columns (GTK_CLIST (widget));
507 return gail_clist_ref_at_actual (ATK_TABLE (obj), row, col);
511 gail_clist_ref_state_set (AtkObject *obj)
513 AtkStateSet *state_set;
516 state_set = ATK_OBJECT_CLASS (parent_class)->ref_state_set (obj);
517 widget = GTK_ACCESSIBLE (obj)->widget;
520 atk_state_set_add_state (state_set, ATK_STATE_MANAGES_DESCENDANTS);
526 atk_selection_interface_init (AtkSelectionIface *iface)
528 g_return_if_fail (iface != NULL);
530 iface->clear_selection = gail_clist_clear_selection;
531 iface->ref_selection = gail_clist_ref_selection;
532 iface->get_selection_count = gail_clist_get_selection_count;
533 iface->is_child_selected = gail_clist_is_child_selected;
534 iface->select_all_selection = gail_clist_select_all_selection;
538 gail_clist_clear_selection (AtkSelection *selection)
543 widget = GTK_ACCESSIBLE (selection)->widget;
545 /* State is defunct */
548 clist = GTK_CLIST (widget);
549 gtk_clist_unselect_all(clist);
554 gail_clist_ref_selection (AtkSelection *selection,
557 gint visible_columns;
559 gint selected_column;
562 if ( i < 0 && i >= gail_clist_get_selection_count (selection))
565 visible_columns = gail_clist_get_n_columns (ATK_TABLE (selection));
566 gail_clist_get_selected_rows (ATK_TABLE (selection), &selected_rows);
567 selected_row = selected_rows[i / visible_columns];
568 g_free (selected_rows);
569 selected_column = gail_clist_get_actual_column (ATK_TABLE (selection),
570 i % visible_columns);
572 return gail_clist_ref_at (ATK_TABLE (selection), selected_row,
577 gail_clist_get_selection_count (AtkSelection *selection)
579 gint n_rows_selected;
581 n_rows_selected = gail_clist_get_selected_rows (ATK_TABLE (selection), NULL);
583 if (n_rows_selected > 0)
585 * The number of cells selected is the number of columns
586 * times the number of selected rows
588 return gail_clist_get_n_columns (ATK_TABLE (selection)) * n_rows_selected;
593 gail_clist_is_child_selected (AtkSelection *selection,
598 row = atk_table_get_row_at_index (ATK_TABLE (selection), i);
600 if (row == 0 && i >= gail_clist_get_n_columns (ATK_TABLE (selection)))
602 return gail_clist_is_row_selected (ATK_TABLE (selection), row);
606 gail_clist_select_all_selection (AtkSelection *selection)
612 widget = GTK_ACCESSIBLE (selection)->widget;
614 /* State is defunct */
617 clist = GTK_CLIST (widget);
618 gtk_clist_select_all(clist);
624 atk_table_interface_init (AtkTableIface *iface)
626 g_return_if_fail (iface != NULL);
627 iface->ref_at = gail_clist_ref_at;
628 iface->get_index_at = gail_clist_get_index_at;
629 iface->get_column_at_index = gail_clist_get_column_at_index;
630 iface->get_row_at_index = gail_clist_get_row_at_index;
631 iface->get_caption = gail_clist_get_caption;
632 iface->get_n_columns = gail_clist_get_n_columns;
633 iface->get_column_description = gail_clist_get_column_description;
634 iface->get_column_header = gail_clist_get_column_header;
635 iface->get_n_rows = gail_clist_get_n_rows;
636 iface->get_row_description = gail_clist_get_row_description;
637 iface->get_row_header = gail_clist_get_row_header;
638 iface->get_summary = gail_clist_get_summary;
639 iface->add_row_selection = gail_clist_add_row_selection;
640 iface->remove_row_selection = gail_clist_remove_row_selection;
641 iface->get_selected_rows = gail_clist_get_selected_rows;
642 iface->is_row_selected = gail_clist_is_row_selected;
643 iface->is_selected = gail_clist_is_selected;
644 iface->set_caption = gail_clist_set_caption;
645 iface->set_column_description = gail_clist_set_column_description;
646 iface->set_column_header = gail_clist_set_column_header;
647 iface->set_row_description = gail_clist_set_row_description;
648 iface->set_row_header = gail_clist_set_row_header;
649 iface->set_summary = gail_clist_set_summary;
653 gail_clist_ref_at (AtkTable *table,
660 widget = GTK_ACCESSIBLE (table)->widget;
662 /* State is defunct */
665 actual_column = gail_clist_get_actual_column (table, column);
666 return gail_clist_ref_at_actual (table, row, actual_column);
671 gail_clist_ref_at_actual (AtkTable *table,
676 * The column number pased to this function is the actual column number
677 * whereas the column number passed to gail_clist_ref_at is the
678 * visible column number
682 GtkCellType cellType;
683 AtkObject *return_object;
684 gint n_rows, n_columns;
688 g_return_val_if_fail (GTK_IS_ACCESSIBLE (table), NULL);
690 widget = GTK_ACCESSIBLE (table)->widget;
692 /* State is defunct */
695 clist = GTK_CLIST (widget);
696 n_rows = gail_clist_get_n_rows (table);
697 n_columns = gail_clist_get_n_actual_columns (clist);
699 if (row < 0 || row >= n_rows)
701 if (column < 0 || column >= n_columns)
705 * Check whether the child is cached
707 index = column + row * n_columns;
708 cell = gail_clist_find_cell (GAIL_CLIST (table), index);
712 return ATK_OBJECT (cell);
714 cellType = gtk_clist_get_cell_type(clist, row, column);
718 case GTK_CELL_PIXTEXT:
719 return_object = gail_clist_cell_new ();
721 case GTK_CELL_PIXMAP:
722 return_object = NULL;
725 /* Don't handle GTK_CELL_EMPTY or GTK_CELL_WIDGET, return NULL */
726 return_object = NULL;
731 cell = GAIL_CELL (return_object);
733 g_return_val_if_fail (ATK_IS_OBJECT (table), NULL);
735 gail_cell_init (cell, widget, ATK_OBJECT (table),
738 * Store the cell in a cache
740 gail_clist_cell_data_new (GAIL_CLIST (table), cell, column, row);
742 * If the column is visible, sets the cell's state
744 if (clist->column[column].visible)
746 GdkRectangle cell_rect, visible_rect;
748 gail_clist_get_cell_area (GAIL_CELL_PARENT (table), cell, &cell_rect);
749 gail_clist_get_visible_rect (clist, &visible_rect);
750 gail_cell_add_state (cell, ATK_STATE_VISIBLE, FALSE);
751 if (gail_clist_is_cell_visible (&cell_rect, &visible_rect))
752 gail_cell_add_state (cell, ATK_STATE_SHOWING, FALSE);
755 * If a row is selected, all cells in the row are selected
757 if (gail_clist_is_row_selected (table, row))
759 gail_cell_add_state (cell, ATK_STATE_SELECTED, FALSE);
760 if (clist->columns == 1)
761 gail_cell_add_state (cell, ATK_STATE_FOCUSED, FALSE);
765 return return_object;
769 gail_clist_get_index_at (AtkTable *table,
775 n_cols = atk_table_get_n_columns (table);
776 n_rows = atk_table_get_n_rows (table);
778 g_return_val_if_fail (row < n_rows, 0);
779 g_return_val_if_fail (column < n_cols, 0);
781 return row * n_cols + column;
785 gail_clist_get_column_at_index (AtkTable *table,
790 n_cols = atk_table_get_n_columns (table);
795 return (gint) (index % n_cols);
799 gail_clist_get_row_at_index (AtkTable *table,
804 n_cols = atk_table_get_n_columns (table);
809 return (gint) (index / n_cols);
813 gail_clist_get_caption (AtkTable *table)
815 GailCList* obj = GAIL_CLIST (table);
821 gail_clist_get_n_columns (AtkTable *table)
826 widget = GTK_ACCESSIBLE (table)->widget;
828 /* State is defunct */
831 clist = GTK_CLIST (widget);
833 return gail_clist_get_visible_column (table,
834 gail_clist_get_n_actual_columns (clist));
838 gail_clist_get_n_actual_columns (GtkCList *clist)
840 return clist->columns;
843 static G_CONST_RETURN gchar*
844 gail_clist_get_column_description (AtkTable *table,
847 GailCList *clist = GAIL_CLIST (table);
851 if (column < 0 || column >= gail_clist_get_n_columns (table))
854 actual_column = gail_clist_get_actual_column (table, column);
855 if (clist->columns[actual_column].description)
856 return (clist->columns[actual_column].description);
858 widget = GTK_ACCESSIBLE (clist)->widget;
862 return gtk_clist_get_column_title (GTK_CLIST (widget), actual_column);
866 gail_clist_get_column_header (AtkTable *table,
869 GailCList *clist = GAIL_CLIST (table);
871 GtkWidget *return_widget;
874 if (column < 0 || column >= gail_clist_get_n_columns (table))
877 actual_column = gail_clist_get_actual_column (table, column);
879 if (clist->columns[actual_column].header)
880 return (clist->columns[actual_column].header);
882 widget = GTK_ACCESSIBLE (clist)->widget;
886 return_widget = gtk_clist_get_column_widget (GTK_CLIST (widget),
888 if (return_widget == NULL)
891 g_return_val_if_fail (GTK_IS_BIN (return_widget), NULL);
892 return_widget = gtk_bin_get_child (GTK_BIN(return_widget));
894 return gtk_widget_get_accessible (return_widget);
898 gail_clist_get_n_rows (AtkTable *table)
903 widget = GTK_ACCESSIBLE (table)->widget;
905 /* State is defunct */
908 clist = GTK_CLIST (widget);
912 static G_CONST_RETURN gchar*
913 gail_clist_get_row_description (AtkTable *table,
916 GailCListRow* row_data;
918 row_data = gail_clist_get_row_data (table, row);
919 if (row_data == NULL)
921 return row_data->description;
925 gail_clist_get_row_header (AtkTable *table,
928 GailCListRow* row_data;
930 row_data = gail_clist_get_row_data (table, row);
931 if (row_data == NULL)
933 return row_data->header;
937 gail_clist_get_summary (AtkTable *table)
939 GailCList* obj = GAIL_CLIST (table);
945 gail_clist_add_row_selection (AtkTable *table,
951 widget = GTK_ACCESSIBLE (table)->widget;
953 /* State is defunct */
956 clist = GTK_CLIST (widget);
957 gtk_clist_select_row (clist, row, -1);
958 if (gail_clist_is_row_selected (table, row))
965 gail_clist_remove_row_selection (AtkTable *table,
971 widget = GTK_ACCESSIBLE (table)->widget;
973 /* State is defunct */
976 clist = GTK_CLIST (widget);
977 if (gail_clist_is_row_selected (table, row))
979 gtk_clist_select_row (clist, row, -1);
986 gail_clist_get_selected_rows (AtkTable *table,
987 gint **rows_selected)
995 widget = GTK_ACCESSIBLE (table)->widget;
997 /* State is defunct */
1000 clist = GTK_CLIST (widget);
1002 n_selected = g_list_length (clist->selection);
1004 if (n_selected == 0)
1009 gint *selected_rows;
1011 selected_rows = (gint*) g_malloc (sizeof (gint) * n_selected);
1012 list = clist->selection;
1017 selected_rows[i++] = GPOINTER_TO_INT (list->data);
1020 *rows_selected = selected_rows;
1026 gail_clist_is_row_selected (AtkTable *table,
1032 GtkCListRow *clist_row;
1034 widget = GTK_ACCESSIBLE (table)->widget;
1036 /* State is defunct */
1039 clist = GTK_CLIST (widget);
1041 if (row < 0 || row >= clist->rows)
1044 elem = ROW_ELEMENT (clist, row);
1047 clist_row = elem->data;
1049 return (clist_row->state == GTK_STATE_SELECTED);
1053 gail_clist_is_selected (AtkTable *table,
1057 return gail_clist_is_row_selected (table, row);
1061 gail_clist_set_caption (AtkTable *table,
1064 GailCList* obj = GAIL_CLIST (table);
1065 AtkPropertyValues values = { NULL };
1066 AtkObject *old_caption;
1068 old_caption = obj->caption;
1069 obj->caption = caption;
1071 g_object_ref (obj->caption);
1073 g_value_init (&values.old_value, G_TYPE_POINTER);
1074 g_value_set_pointer (&values.old_value, old_caption);
1075 g_value_init (&values.new_value, G_TYPE_POINTER);
1076 g_value_set_pointer (&values.new_value, obj->caption);
1078 values.property_name = "accessible-table-caption";
1079 g_signal_emit_by_name (table,
1080 "property_change::accessible-table-caption",
1083 g_object_unref (old_caption);
1087 gail_clist_set_column_description (AtkTable *table,
1089 const gchar *description)
1091 GailCList *clist = GAIL_CLIST (table);
1092 AtkPropertyValues values = { NULL };
1095 if (column < 0 || column >= gail_clist_get_n_columns (table))
1098 if (description == NULL)
1101 actual_column = gail_clist_get_actual_column (table, column);
1102 g_free (clist->columns[actual_column].description);
1103 clist->columns[actual_column].description = g_strdup (description);
1105 g_value_init (&values.new_value, G_TYPE_INT);
1106 g_value_set_int (&values.new_value, column);
1108 values.property_name = "accessible-table-column-description";
1109 g_signal_emit_by_name (table,
1110 "property_change::accessible-table-column-description",
1116 gail_clist_set_column_header (AtkTable *table,
1120 GailCList *clist = GAIL_CLIST (table);
1121 AtkPropertyValues values = { NULL };
1124 if (column < 0 || column >= gail_clist_get_n_columns (table))
1127 actual_column = gail_clist_get_actual_column (table, column);
1128 if (clist->columns[actual_column].header)
1129 g_object_unref (clist->columns[actual_column].header);
1131 g_object_ref (header);
1132 clist->columns[actual_column].header = header;
1134 g_value_init (&values.new_value, G_TYPE_INT);
1135 g_value_set_int (&values.new_value, column);
1137 values.property_name = "accessible-table-column-header";
1138 g_signal_emit_by_name (table,
1139 "property_change::accessible-table-column-header",
1144 gail_clist_set_row_description (AtkTable *table,
1146 const gchar *description)
1148 gail_clist_set_row_data (table, row, description, NULL, FALSE);
1152 gail_clist_set_row_header (AtkTable *table,
1156 gail_clist_set_row_data (table, row, NULL, header, TRUE);
1160 gail_clist_set_summary (AtkTable *table,
1161 AtkObject *accessible)
1163 GailCList* obj = GAIL_CLIST (table);
1164 AtkPropertyValues values = { 0, };
1165 AtkObject *old_summary;
1167 old_summary = obj->summary;
1168 obj->summary = accessible;
1170 g_object_ref (obj->summary);
1172 g_value_init (&values.old_value, G_TYPE_POINTER);
1173 g_value_set_pointer (&values.old_value, old_summary);
1174 g_value_init (&values.new_value, G_TYPE_POINTER);
1175 g_value_set_pointer (&values.new_value, obj->summary);
1177 values.property_name = "accessible-table-summary";
1178 g_signal_emit_by_name (table,
1179 "property_change::accessible-table-summary",
1182 g_object_unref (old_summary);
1186 static void gail_cell_parent_interface_init (GailCellParentIface *iface)
1188 g_return_if_fail (iface);
1190 iface->get_cell_extents = gail_clist_get_cell_extents;
1191 iface->get_cell_area = gail_clist_get_cell_area;
1195 gail_clist_get_cell_extents (GailCellParent *parent,
1201 AtkCoordType coord_type)
1205 gint widget_x, widget_y, widget_width, widget_height;
1206 GdkRectangle cell_rect;
1207 GdkRectangle visible_rect;
1209 widget = GTK_ACCESSIBLE (parent)->widget;
1212 clist = GTK_CLIST (widget);
1214 atk_component_get_extents (ATK_COMPONENT (parent), &widget_x, &widget_y,
1215 &widget_width, &widget_height,
1218 gail_clist_get_cell_area (parent, cell, &cell_rect);
1219 *width = cell_rect.width;
1220 *height = cell_rect.height;
1221 gail_clist_get_visible_rect (clist, &visible_rect);
1222 if (gail_clist_is_cell_visible (&cell_rect, &visible_rect))
1224 *x = cell_rect.x + widget_x;
1225 *y = cell_rect.y + widget_y;
1235 gail_clist_get_cell_area (GailCellParent *parent,
1237 GdkRectangle *cell_rect)
1241 gint column, row, n_columns;
1243 widget = GTK_ACCESSIBLE (parent)->widget;
1246 clist = GTK_CLIST (widget);
1248 n_columns = gail_clist_get_n_actual_columns (clist);
1249 g_return_if_fail (n_columns > 0);
1250 column = cell->index % n_columns;
1251 row = cell->index / n_columns;
1252 cell_rect->x = COLUMN_LEFT (clist, column);
1253 cell_rect->y = ROW_TOP (clist, row);
1254 cell_rect->width = clist->column[column].area.width;
1255 cell_rect->height = clist->row_height;
1259 gail_clist_select_row_gtk (GtkCList *clist,
1265 GailCList *gail_clist;
1267 AtkObject *selected_cell;
1269 gail_clist = GAIL_CLIST (data);
1271 for (temp_list = gail_clist->cell_data; temp_list; temp_list = temp_list->next)
1273 GailCListCellData *cell_data;
1275 cell_data = (GailCListCellData *) (temp_list->data);
1277 if (row == cell_data->row_number)
1282 gail_cell_add_state (cell_data->gail_cell, ATK_STATE_SELECTED, TRUE);
1285 if (clist->columns == 1)
1287 selected_cell = gail_clist_ref_at (ATK_TABLE (data), row, 1);
1290 if (gail_clist->previous_selected_cell)
1291 g_object_unref (gail_clist->previous_selected_cell);
1292 gail_clist->previous_selected_cell = selected_cell;
1293 gail_cell_add_state (GAIL_CELL (selected_cell), ATK_STATE_FOCUSED, FALSE);
1294 g_signal_emit_by_name (gail_clist,
1295 "active-descendant-changed",
1300 g_signal_emit_by_name (gail_clist, "selection_changed");
1304 gail_clist_unselect_row_gtk (GtkCList *clist,
1310 GailCList *gail_clist;
1313 gail_clist = GAIL_CLIST (data);
1315 for (temp_list = gail_clist->cell_data; temp_list; temp_list = temp_list->next)
1317 GailCListCellData *cell_data;
1319 cell_data = (GailCListCellData *) (temp_list->data);
1321 if (row == cell_data->row_number)
1326 gail_cell_add_state (cell_data->gail_cell, ATK_STATE_FOCUSED, FALSE);
1327 gail_cell_remove_state (cell_data->gail_cell, ATK_STATE_SELECTED, TRUE);
1331 g_signal_emit_by_name (gail_clist, "selection_changed");
1335 * This function determines the number of visible columns
1336 * up to and including the specified column
1339 gail_clist_get_visible_column (AtkTable *table,
1347 widget = GTK_ACCESSIBLE (table)->widget;
1349 /* State is defunct */
1352 clist = GTK_CLIST (widget);
1353 for (i = 0, vis_columns = 0; i < column; i++)
1354 if (clist->column[i].visible)
1361 gail_clist_get_actual_column (AtkTable *table,
1369 widget = GTK_ACCESSIBLE (table)->widget;
1371 /* State is defunct */
1374 clist = GTK_CLIST (widget);
1375 for (i = 0, vis_columns = 0; i < clist->columns; i++)
1377 if (clist->column[i].visible)
1379 if (visible_column == vis_columns)
1388 gail_clist_set_row_data (AtkTable *table,
1390 const gchar *description,
1395 GtkCList *gtk_clist;
1396 GailCList *gail_clist;
1398 GailCListRow* row_data;
1400 gboolean found = FALSE;
1401 AtkPropertyValues values = { NULL };
1404 widget = GTK_ACCESSIBLE (table)->widget;
1406 /* State is defunct */
1409 gtk_clist = GTK_CLIST (widget);
1410 if (row < 0 || row >= gtk_clist->rows)
1413 gail_clist = GAIL_CLIST (table);
1415 if (gail_clist->row_data == NULL)
1416 gail_clist->row_data = g_array_sized_new (FALSE, TRUE,
1417 sizeof (GailCListRow *), 0);
1419 array = gail_clist->row_data;
1421 for (i = 0; i < array->len; i++)
1423 row_data = g_array_index (array, GailCListRow*, i);
1425 if (row == row_data->row_number)
1430 if (row_data->header)
1431 g_object_unref (row_data->header);
1432 row_data->header = header;
1433 if (row_data->header)
1434 g_object_ref (row_data->header);
1438 g_free (row_data->description);
1439 row_data->description = g_strdup (row_data->description);
1448 elem = ROW_ELEMENT (gtk_clist, row);
1449 g_return_if_fail (elem != NULL);
1451 row_data = g_new (GailCListRow, 1);
1452 row_data->row_number = row;
1453 row_data->row_data = elem->data;
1456 row_data->header = header;
1457 if (row_data->header)
1458 g_object_ref (row_data->header);
1459 row_data->description = NULL;
1463 row_data->description = g_strdup (row_data->description);
1464 row_data->header = NULL;
1466 g_array_append_val (array, row_data);
1469 g_value_init (&values.new_value, G_TYPE_INT);
1470 g_value_set_int (&values.new_value, row);
1474 values.property_name = "accessible-table-row-header";
1475 signal_name = "property_change::accessible-table-row-header";
1479 values.property_name = "accessible-table-row-description";
1480 signal_name = "property_change::accessible-table-row-description";
1482 g_signal_emit_by_name (table,
1488 static GailCListRow*
1489 gail_clist_get_row_data (AtkTable *table,
1496 GailCListRow* row_data;
1499 widget = GTK_ACCESSIBLE (table)->widget;
1501 /* State is defunct */
1504 clist = GTK_CLIST (widget);
1505 if (row < 0 || row >= clist->rows)
1508 obj = GAIL_CLIST (table);
1510 if (obj->row_data == NULL)
1513 array = obj->row_data;
1515 for (i = 0; i < array->len; i++)
1517 row_data = g_array_index (array, GailCListRow*, i);
1519 if (row == row_data->row_number)
1527 gail_clist_get_visible_rect (GtkCList *clist,
1528 GdkRectangle *clist_rect)
1530 clist_rect->x = - clist->hoffset;
1531 clist_rect->y = - clist->voffset;
1532 clist_rect->width = clist->clist_window_width;
1533 clist_rect->height = clist->clist_window_height;
1537 gail_clist_is_cell_visible (GdkRectangle *cell_rect,
1538 GdkRectangle *visible_rect)
1541 * A cell is reported as visible if any part of the cell is visible
1543 if (((cell_rect->x + cell_rect->width) < visible_rect->x) ||
1544 ((cell_rect->y + cell_rect->height) < visible_rect->y) ||
1545 (cell_rect->x > (visible_rect->x + visible_rect->width)) ||
1546 (cell_rect->y > (visible_rect->y + visible_rect->height)))
1553 gail_clist_cell_data_new (GailCList *clist,
1559 GailCListCellData *cell_data;
1560 GtkCList *gtk_clist;
1561 GtkCListRow *clist_row;
1563 gtk_clist = GTK_CLIST (GTK_ACCESSIBLE (clist)->widget);
1564 elem = g_list_nth (gtk_clist->row_list, row);
1565 g_return_if_fail (elem != NULL);
1566 clist_row = (GtkCListRow *) elem->data;
1567 cell_data = g_new (GailCListCellData, 1);
1568 cell_data->gail_cell = cell;
1569 cell_data->gtk_cell = &(clist_row->cell[column]);
1570 cell_data->column_number = column;
1571 cell_data->row_number = row;
1572 clist->cell_data = g_list_append (clist->cell_data, cell_data);
1574 g_object_weak_ref (G_OBJECT (cell),
1575 (GWeakNotify) gail_clist_cell_destroyed,
1580 gail_clist_cell_destroyed (gpointer data)
1582 GailCell *cell = GAIL_CELL (data);
1585 parent = atk_object_get_parent (ATK_OBJECT (cell));
1587 gail_clist_cell_data_remove (GAIL_CLIST (parent), cell);
1591 gail_clist_cell_data_remove (GailCList *clist,
1596 for (temp_list = clist->cell_data; temp_list; temp_list = temp_list->next)
1598 GailCListCellData *cell_data;
1600 cell_data = (GailCListCellData *) temp_list->data;
1601 if (cell_data->gail_cell == cell)
1603 clist->cell_data = g_list_remove_link (clist->cell_data, temp_list);
1608 g_warning ("No cell removed in gail_clist_cell_data_remove\n");
1612 gail_clist_find_cell (GailCList *clist,
1618 n_cols = clist->n_cols;
1620 for (temp_list = clist->cell_data; temp_list; temp_list = temp_list->next)
1622 GailCListCellData *cell_data;
1625 cell_data = (GailCListCellData *) (temp_list->data);
1627 real_index = cell_data->column_number + n_cols * cell_data->row_number;
1628 if (real_index == index)
1629 return cell_data->gail_cell;
1635 gail_clist_adjustment_changed (GtkAdjustment *adjustment,
1639 GdkRectangle visible_rect;
1640 GdkRectangle cell_rect;
1645 * The scrollbars have changed
1647 atk_obj = gtk_widget_get_accessible (GTK_WIDGET (clist));
1648 obj = GAIL_CLIST (atk_obj);
1650 /* Get the currently visible area */
1651 gail_clist_get_visible_rect (clist, &visible_rect);
1653 /* loop over the cells and report if they are visible or not. */
1654 /* Must loop through them all */
1655 for (temp_list = obj->cell_data; temp_list; temp_list = temp_list->next)
1658 GailCListCellData *cell_data;
1660 cell_data = (GailCListCellData *) (temp_list->data);
1661 cell = cell_data->gail_cell;
1663 gail_clist_get_cell_area (GAIL_CELL_PARENT (atk_obj),
1665 if (gail_clist_is_cell_visible (&cell_rect, &visible_rect))
1666 gail_cell_add_state (cell, ATK_STATE_SHOWING, TRUE);
1668 gail_cell_remove_state (cell, ATK_STATE_SHOWING, TRUE);
1670 g_signal_emit_by_name (atk_obj, "visible_data_changed");