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.
24 #undef GTK_DISABLE_DEPRECATED
27 #include "gailclist.h"
28 #include "gailclistcell.h"
29 #include "gailcellparent.h"
31 /* Copied from gtkclist.c */
32 /* this defigns the base grid spacing */
33 #define CELL_SPACING 1
35 /* added the horizontal space at the beginning and end of a row*/
36 #define COLUMN_INSET 3
39 /* gives the top pixel of the given row in context of
40 * the clist's voffset */
41 #define ROW_TOP_YPIXEL(clist, row) (((clist)->row_height * (row)) + \
42 (((row) + 1) * CELL_SPACING) + \
45 /* returns the row index from a y pixel location in the
46 * context of the clist's voffset */
47 #define ROW_FROM_YPIXEL(clist, y) (((y) - (clist)->voffset) / \
48 ((clist)->row_height + CELL_SPACING))
49 /* gives the left pixel of the given column in context of
50 * the clist's hoffset */
51 #define COLUMN_LEFT_XPIXEL(clist, colnum) ((clist)->column[(colnum)].area.x + \
54 /* returns the column index from a x pixel location in the
55 * context of the clist's hoffset */
57 COLUMN_FROM_XPIXEL (GtkCList * clist,
62 for (i = 0; i < clist->columns; i++)
63 if (clist->column[i].visible)
65 cx = clist->column[i].area.x + clist->hoffset;
67 if (x >= (cx - (COLUMN_INSET + CELL_SPACING)) &&
68 x <= (cx + clist->column[i].area.width + COLUMN_INSET))
76 /* returns the top pixel of the given row in the context of
78 #define ROW_TOP(clist, row) (((clist)->row_height + CELL_SPACING) * (row))
80 /* returns the left pixel of the given column in the context of
82 #define COLUMN_LEFT(clist, colnum) ((clist)->column[(colnum)].area.x)
84 /* returns the total height of the list */
85 #define LIST_HEIGHT(clist) (((clist)->row_height * ((clist)->rows)) + \
86 (CELL_SPACING * ((clist)->rows + 1)))
89 LIST_WIDTH (GtkCList * clist)
93 for (last_column = clist->columns - 1;
94 last_column >= 0 && !clist->column[last_column].visible; last_column--);
97 return (clist->column[last_column].area.x +
98 clist->column[last_column].area.width +
99 COLUMN_INSET + CELL_SPACING);
103 /* returns the GList item for the nth row */
104 #define ROW_ELEMENT(clist, row) (((row) == (clist)->rows - 1) ? \
105 (clist)->row_list_end : \
106 g_list_nth ((clist)->row_list, (row)))
108 typedef struct _GailCListRow GailCListRow;
109 typedef struct _GailCListCellData GailCListCellData;
112 static void gail_clist_class_init (GailCListClass *klass);
113 static void gail_clist_init (GailCList *clist);
114 static void gail_clist_real_initialize (AtkObject *obj,
116 static void gail_clist_finalize (GObject *object);
118 static gint gail_clist_get_n_children (AtkObject *obj);
119 static AtkObject* gail_clist_ref_child (AtkObject *obj,
121 static AtkStateSet* gail_clist_ref_state_set (AtkObject *obj);
124 static void atk_selection_interface_init (AtkSelectionIface *iface);
125 static gboolean gail_clist_clear_selection (AtkSelection *selection);
127 static AtkObject* gail_clist_ref_selection (AtkSelection *selection,
129 static gint gail_clist_get_selection_count (AtkSelection *selection);
130 static gboolean gail_clist_is_child_selected (AtkSelection *selection,
132 static gboolean gail_clist_select_all_selection (AtkSelection *selection);
134 static void atk_table_interface_init (AtkTableIface *iface);
135 static gint gail_clist_get_index_at (AtkTable *table,
138 static gint gail_clist_get_column_at_index (AtkTable *table,
140 static gint gail_clist_get_row_at_index (AtkTable *table,
142 static AtkObject* gail_clist_ref_at (AtkTable *table,
145 static AtkObject* gail_clist_ref_at_actual (AtkTable *table,
149 gail_clist_get_caption (AtkTable *table);
151 static gint gail_clist_get_n_columns (AtkTable *table);
152 static gint gail_clist_get_n_actual_columns (GtkCList *clist);
154 static G_CONST_RETURN gchar*
155 gail_clist_get_column_description(AtkTable *table,
157 static AtkObject* gail_clist_get_column_header (AtkTable *table,
159 static gint gail_clist_get_n_rows (AtkTable *table);
160 static G_CONST_RETURN gchar*
161 gail_clist_get_row_description (AtkTable *table,
163 static AtkObject* gail_clist_get_row_header (AtkTable *table,
165 static AtkObject* gail_clist_get_summary (AtkTable *table);
166 static gboolean gail_clist_add_row_selection (AtkTable *table,
168 static gboolean gail_clist_remove_row_selection (AtkTable *table,
170 static gint gail_clist_get_selected_rows (AtkTable *table,
171 gint **rows_selected);
172 static gboolean gail_clist_is_row_selected (AtkTable *table,
174 static gboolean gail_clist_is_selected (AtkTable *table,
177 static void gail_clist_set_caption (AtkTable *table,
179 static void gail_clist_set_column_description(AtkTable *table,
181 const gchar *description);
182 static void gail_clist_set_column_header (AtkTable *table,
185 static void gail_clist_set_row_description (AtkTable *table,
187 const gchar *description);
188 static void gail_clist_set_row_header (AtkTable *table,
191 static void gail_clist_set_summary (AtkTable *table,
192 AtkObject *accessible);
194 /* gailcellparent.h */
196 static void gail_cell_parent_interface_init (GailCellParentIface *iface);
197 static void gail_clist_get_cell_extents (GailCellParent *parent,
203 AtkCoordType coord_type);
205 static void gail_clist_get_cell_area (GailCellParent *parent,
207 GdkRectangle *cell_rect);
209 static void gail_clist_select_row_gtk (GtkCList *clist,
214 static void gail_clist_unselect_row_gtk (GtkCList *clist,
219 static gint gail_clist_get_visible_column (AtkTable *table,
221 static gint gail_clist_get_actual_column (AtkTable *table,
223 static void gail_clist_set_row_data (AtkTable *table,
225 const gchar *description,
229 gail_clist_get_row_data (AtkTable *table,
231 static void gail_clist_get_visible_rect (GtkCList *clist,
232 GdkRectangle *clist_rect);
233 static gboolean gail_clist_is_cell_visible (GdkRectangle *cell_rect,
234 GdkRectangle *visible_rect);
235 static void gail_clist_cell_data_new (GailCList *clist,
239 static void gail_clist_cell_destroyed (gpointer data);
240 static void gail_clist_cell_data_remove (GailCList *clist,
242 static GailCell* gail_clist_find_cell (GailCList *clist,
244 static void gail_clist_adjustment_changed (GtkAdjustment *adjustment,
247 struct _GailCListColumn
255 GtkCListRow *row_data;
261 struct _GailCListCellData
269 G_DEFINE_TYPE_WITH_CODE (GailCList, gail_clist, GAIL_TYPE_CONTAINER,
270 G_IMPLEMENT_INTERFACE (ATK_TYPE_TABLE, atk_table_interface_init)
271 G_IMPLEMENT_INTERFACE (ATK_TYPE_SELECTION, atk_selection_interface_init)
272 G_IMPLEMENT_INTERFACE (GAIL_TYPE_CELL_PARENT, gail_cell_parent_interface_init))
275 gail_clist_class_init (GailCListClass *klass)
277 AtkObjectClass *class = ATK_OBJECT_CLASS (klass);
278 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
280 class->get_n_children = gail_clist_get_n_children;
281 class->ref_child = gail_clist_ref_child;
282 class->ref_state_set = gail_clist_ref_state_set;
283 class->initialize = gail_clist_real_initialize;
285 gobject_class->finalize = gail_clist_finalize;
289 gail_clist_init (GailCList *clist)
294 gail_clist_real_initialize (AtkObject *obj,
301 ATK_OBJECT_CLASS (gail_clist_parent_class)->initialize (obj, data);
303 obj->role = ATK_ROLE_TABLE;
305 clist = GAIL_CLIST (obj);
307 clist->caption = NULL;
308 clist->summary = NULL;
309 clist->row_data = NULL;
310 clist->cell_data = NULL;
311 clist->previous_selected_cell = NULL;
313 gtk_clist = GTK_CLIST (data);
315 clist->n_cols = gtk_clist->columns;
316 clist->columns = g_new (GailCListColumn, gtk_clist->columns);
317 for (i = 0; i < gtk_clist->columns; i++)
319 clist->columns[i].description = NULL;
320 clist->columns[i].header = NULL;
323 * Set up signal handlers for select-row and unselect-row
325 g_signal_connect (gtk_clist,
327 G_CALLBACK (gail_clist_select_row_gtk),
329 g_signal_connect (gtk_clist,
331 G_CALLBACK (gail_clist_unselect_row_gtk),
334 * Adjustment callbacks
336 if (gtk_clist->hadjustment)
338 g_signal_connect (gtk_clist->hadjustment,
340 G_CALLBACK (gail_clist_adjustment_changed),
343 if (gtk_clist->vadjustment)
345 g_signal_connect (gtk_clist->vadjustment,
347 G_CALLBACK (gail_clist_adjustment_changed),
353 gail_clist_finalize (GObject *object)
355 GailCList *clist = GAIL_CLIST (object);
360 g_object_unref (clist->caption);
362 g_object_unref (clist->summary);
364 for (i = 0; i < clist->n_cols; i++)
366 g_free (clist->columns[i].description);
367 if (clist->columns[i].header)
368 g_object_unref (clist->columns[i].header);
370 g_free (clist->columns);
372 array = clist->row_data;
374 if (clist->previous_selected_cell)
375 g_object_unref (clist->previous_selected_cell);
379 for (i = 0; i < array->len; i++)
381 GailCListRow *row_data;
383 row_data = g_array_index (array, GailCListRow*, i);
385 if (row_data->header)
386 g_object_unref (row_data->header);
387 g_free (row_data->description);
391 if (clist->cell_data)
395 for (temp_list = clist->cell_data; temp_list; temp_list = temp_list->next)
397 g_list_free (temp_list->data);
399 g_list_free (clist->cell_data);
402 G_OBJECT_CLASS (gail_clist_parent_class)->finalize (object);
406 gail_clist_get_n_children (AtkObject *obj)
411 g_return_val_if_fail (GAIL_IS_CLIST (obj), 0);
413 widget = GTK_ACCESSIBLE (obj)->widget;
420 row = gail_clist_get_n_rows (ATK_TABLE (obj));
421 col = gail_clist_get_n_actual_columns (GTK_CLIST (widget));
426 gail_clist_ref_child (AtkObject *obj,
433 g_return_val_if_fail (GAIL_IS_CLIST (obj), NULL);
434 g_return_val_if_fail (i >= 0, NULL);
436 widget = GTK_ACCESSIBLE (obj)->widget;
443 n_columns = gail_clist_get_n_actual_columns (GTK_CLIST (widget));
449 return gail_clist_ref_at_actual (ATK_TABLE (obj), row, col);
453 gail_clist_ref_state_set (AtkObject *obj)
455 AtkStateSet *state_set;
458 state_set = ATK_OBJECT_CLASS (gail_clist_parent_class)->ref_state_set (obj);
459 widget = GTK_ACCESSIBLE (obj)->widget;
462 atk_state_set_add_state (state_set, ATK_STATE_MANAGES_DESCENDANTS);
468 atk_selection_interface_init (AtkSelectionIface *iface)
470 iface->clear_selection = gail_clist_clear_selection;
471 iface->ref_selection = gail_clist_ref_selection;
472 iface->get_selection_count = gail_clist_get_selection_count;
473 iface->is_child_selected = gail_clist_is_child_selected;
474 iface->select_all_selection = gail_clist_select_all_selection;
478 gail_clist_clear_selection (AtkSelection *selection)
483 widget = GTK_ACCESSIBLE (selection)->widget;
485 /* State is defunct */
488 clist = GTK_CLIST (widget);
489 gtk_clist_unselect_all(clist);
494 gail_clist_ref_selection (AtkSelection *selection,
497 gint visible_columns;
499 gint selected_column;
502 if ( i < 0 && i >= gail_clist_get_selection_count (selection))
505 visible_columns = gail_clist_get_n_columns (ATK_TABLE (selection));
506 gail_clist_get_selected_rows (ATK_TABLE (selection), &selected_rows);
507 selected_row = selected_rows[i / visible_columns];
508 g_free (selected_rows);
509 selected_column = gail_clist_get_actual_column (ATK_TABLE (selection),
510 i % visible_columns);
512 return gail_clist_ref_at (ATK_TABLE (selection), selected_row,
517 gail_clist_get_selection_count (AtkSelection *selection)
519 gint n_rows_selected;
521 n_rows_selected = gail_clist_get_selected_rows (ATK_TABLE (selection), NULL);
523 if (n_rows_selected > 0)
525 * The number of cells selected is the number of columns
526 * times the number of selected rows
528 return gail_clist_get_n_columns (ATK_TABLE (selection)) * n_rows_selected;
533 gail_clist_is_child_selected (AtkSelection *selection,
538 row = atk_table_get_row_at_index (ATK_TABLE (selection), i);
540 if (row == 0 && i >= gail_clist_get_n_columns (ATK_TABLE (selection)))
542 return gail_clist_is_row_selected (ATK_TABLE (selection), row);
546 gail_clist_select_all_selection (AtkSelection *selection)
552 widget = GTK_ACCESSIBLE (selection)->widget;
554 /* State is defunct */
557 clist = GTK_CLIST (widget);
558 gtk_clist_select_all(clist);
564 atk_table_interface_init (AtkTableIface *iface)
566 iface->ref_at = gail_clist_ref_at;
567 iface->get_index_at = gail_clist_get_index_at;
568 iface->get_column_at_index = gail_clist_get_column_at_index;
569 iface->get_row_at_index = gail_clist_get_row_at_index;
570 iface->get_caption = gail_clist_get_caption;
571 iface->get_n_columns = gail_clist_get_n_columns;
572 iface->get_column_description = gail_clist_get_column_description;
573 iface->get_column_header = gail_clist_get_column_header;
574 iface->get_n_rows = gail_clist_get_n_rows;
575 iface->get_row_description = gail_clist_get_row_description;
576 iface->get_row_header = gail_clist_get_row_header;
577 iface->get_summary = gail_clist_get_summary;
578 iface->add_row_selection = gail_clist_add_row_selection;
579 iface->remove_row_selection = gail_clist_remove_row_selection;
580 iface->get_selected_rows = gail_clist_get_selected_rows;
581 iface->is_row_selected = gail_clist_is_row_selected;
582 iface->is_selected = gail_clist_is_selected;
583 iface->set_caption = gail_clist_set_caption;
584 iface->set_column_description = gail_clist_set_column_description;
585 iface->set_column_header = gail_clist_set_column_header;
586 iface->set_row_description = gail_clist_set_row_description;
587 iface->set_row_header = gail_clist_set_row_header;
588 iface->set_summary = gail_clist_set_summary;
592 gail_clist_ref_at (AtkTable *table,
599 widget = GTK_ACCESSIBLE (table)->widget;
601 /* State is defunct */
604 actual_column = gail_clist_get_actual_column (table, column);
605 return gail_clist_ref_at_actual (table, row, actual_column);
610 gail_clist_ref_at_actual (AtkTable *table,
615 * The column number pased to this function is the actual column number
616 * whereas the column number passed to gail_clist_ref_at is the
617 * visible column number
621 GtkCellType cellType;
622 AtkObject *return_object;
623 gint n_rows, n_columns;
627 g_return_val_if_fail (GTK_IS_ACCESSIBLE (table), NULL);
629 widget = GTK_ACCESSIBLE (table)->widget;
631 /* State is defunct */
634 clist = GTK_CLIST (widget);
635 n_rows = gail_clist_get_n_rows (table);
636 n_columns = gail_clist_get_n_actual_columns (clist);
638 if (row < 0 || row >= n_rows)
640 if (column < 0 || column >= n_columns)
644 * Check whether the child is cached
646 index = column + row * n_columns;
647 cell = gail_clist_find_cell (GAIL_CLIST (table), index);
651 return ATK_OBJECT (cell);
653 cellType = gtk_clist_get_cell_type(clist, row, column);
657 case GTK_CELL_PIXTEXT:
658 return_object = gail_clist_cell_new ();
660 case GTK_CELL_PIXMAP:
661 return_object = NULL;
664 /* Don't handle GTK_CELL_EMPTY or GTK_CELL_WIDGET, return NULL */
665 return_object = NULL;
670 cell = GAIL_CELL (return_object);
672 g_return_val_if_fail (ATK_IS_OBJECT (table), NULL);
674 gail_cell_initialise (cell, widget, ATK_OBJECT (table),
677 * Store the cell in a cache
679 gail_clist_cell_data_new (GAIL_CLIST (table), cell, column, row);
681 * If the column is visible, sets the cell's state
683 if (clist->column[column].visible)
685 GdkRectangle cell_rect, visible_rect;
687 gail_clist_get_cell_area (GAIL_CELL_PARENT (table), cell, &cell_rect);
688 gail_clist_get_visible_rect (clist, &visible_rect);
689 gail_cell_add_state (cell, ATK_STATE_VISIBLE, FALSE);
690 if (gail_clist_is_cell_visible (&cell_rect, &visible_rect))
691 gail_cell_add_state (cell, ATK_STATE_SHOWING, FALSE);
694 * If a row is selected, all cells in the row are selected
696 if (gail_clist_is_row_selected (table, row))
698 gail_cell_add_state (cell, ATK_STATE_SELECTED, FALSE);
699 if (clist->columns == 1)
700 gail_cell_add_state (cell, ATK_STATE_FOCUSED, FALSE);
704 return return_object;
708 gail_clist_get_index_at (AtkTable *table,
714 n_cols = atk_table_get_n_columns (table);
715 n_rows = atk_table_get_n_rows (table);
717 g_return_val_if_fail (row < n_rows, 0);
718 g_return_val_if_fail (column < n_cols, 0);
720 return row * n_cols + column;
724 gail_clist_get_column_at_index (AtkTable *table,
729 n_cols = atk_table_get_n_columns (table);
734 return (gint) (index % n_cols);
738 gail_clist_get_row_at_index (AtkTable *table,
743 n_cols = atk_table_get_n_columns (table);
748 return (gint) (index / n_cols);
752 gail_clist_get_caption (AtkTable *table)
754 GailCList* obj = GAIL_CLIST (table);
760 gail_clist_get_n_columns (AtkTable *table)
765 widget = GTK_ACCESSIBLE (table)->widget;
767 /* State is defunct */
770 clist = GTK_CLIST (widget);
772 return gail_clist_get_visible_column (table,
773 gail_clist_get_n_actual_columns (clist));
777 gail_clist_get_n_actual_columns (GtkCList *clist)
779 return clist->columns;
782 static G_CONST_RETURN gchar*
783 gail_clist_get_column_description (AtkTable *table,
786 GailCList *clist = GAIL_CLIST (table);
790 if (column < 0 || column >= gail_clist_get_n_columns (table))
793 actual_column = gail_clist_get_actual_column (table, column);
794 if (clist->columns[actual_column].description)
795 return (clist->columns[actual_column].description);
797 widget = GTK_ACCESSIBLE (clist)->widget;
801 return gtk_clist_get_column_title (GTK_CLIST (widget), actual_column);
805 gail_clist_get_column_header (AtkTable *table,
808 GailCList *clist = GAIL_CLIST (table);
810 GtkWidget *return_widget;
813 if (column < 0 || column >= gail_clist_get_n_columns (table))
816 actual_column = gail_clist_get_actual_column (table, column);
818 if (clist->columns[actual_column].header)
819 return (clist->columns[actual_column].header);
821 widget = GTK_ACCESSIBLE (clist)->widget;
825 return_widget = gtk_clist_get_column_widget (GTK_CLIST (widget),
827 if (return_widget == NULL)
830 g_return_val_if_fail (GTK_IS_BIN (return_widget), NULL);
831 return_widget = gtk_bin_get_child (GTK_BIN(return_widget));
833 return gtk_widget_get_accessible (return_widget);
837 gail_clist_get_n_rows (AtkTable *table)
842 widget = GTK_ACCESSIBLE (table)->widget;
844 /* State is defunct */
847 clist = GTK_CLIST (widget);
851 static G_CONST_RETURN gchar*
852 gail_clist_get_row_description (AtkTable *table,
855 GailCListRow* row_data;
857 row_data = gail_clist_get_row_data (table, row);
858 if (row_data == NULL)
860 return row_data->description;
864 gail_clist_get_row_header (AtkTable *table,
867 GailCListRow* row_data;
869 row_data = gail_clist_get_row_data (table, row);
870 if (row_data == NULL)
872 return row_data->header;
876 gail_clist_get_summary (AtkTable *table)
878 GailCList* obj = GAIL_CLIST (table);
884 gail_clist_add_row_selection (AtkTable *table,
890 widget = GTK_ACCESSIBLE (table)->widget;
892 /* State is defunct */
895 clist = GTK_CLIST (widget);
896 gtk_clist_select_row (clist, row, -1);
897 if (gail_clist_is_row_selected (table, row))
904 gail_clist_remove_row_selection (AtkTable *table,
910 widget = GTK_ACCESSIBLE (table)->widget;
912 /* State is defunct */
915 clist = GTK_CLIST (widget);
916 if (gail_clist_is_row_selected (table, row))
918 gtk_clist_select_row (clist, row, -1);
925 gail_clist_get_selected_rows (AtkTable *table,
926 gint **rows_selected)
934 widget = GTK_ACCESSIBLE (table)->widget;
936 /* State is defunct */
939 clist = GTK_CLIST (widget);
941 n_selected = g_list_length (clist->selection);
950 selected_rows = (gint*) g_malloc (sizeof (gint) * n_selected);
951 list = clist->selection;
956 selected_rows[i++] = GPOINTER_TO_INT (list->data);
959 *rows_selected = selected_rows;
965 gail_clist_is_row_selected (AtkTable *table,
971 GtkCListRow *clist_row;
973 widget = GTK_ACCESSIBLE (table)->widget;
975 /* State is defunct */
978 clist = GTK_CLIST (widget);
980 if (row < 0 || row >= clist->rows)
983 elem = ROW_ELEMENT (clist, row);
986 clist_row = elem->data;
988 return (clist_row->state == GTK_STATE_SELECTED);
992 gail_clist_is_selected (AtkTable *table,
996 return gail_clist_is_row_selected (table, row);
1000 gail_clist_set_caption (AtkTable *table,
1003 GailCList* obj = GAIL_CLIST (table);
1004 AtkPropertyValues values = { NULL };
1005 AtkObject *old_caption;
1007 old_caption = obj->caption;
1008 obj->caption = caption;
1010 g_object_ref (obj->caption);
1012 g_value_init (&values.old_value, G_TYPE_POINTER);
1013 g_value_set_pointer (&values.old_value, old_caption);
1014 g_value_init (&values.new_value, G_TYPE_POINTER);
1015 g_value_set_pointer (&values.new_value, obj->caption);
1017 values.property_name = "accessible-table-caption";
1018 g_signal_emit_by_name (table,
1019 "property_change::accessible-table-caption",
1022 g_object_unref (old_caption);
1026 gail_clist_set_column_description (AtkTable *table,
1028 const gchar *description)
1030 GailCList *clist = GAIL_CLIST (table);
1031 AtkPropertyValues values = { NULL };
1034 if (column < 0 || column >= gail_clist_get_n_columns (table))
1037 if (description == NULL)
1040 actual_column = gail_clist_get_actual_column (table, column);
1041 g_free (clist->columns[actual_column].description);
1042 clist->columns[actual_column].description = g_strdup (description);
1044 g_value_init (&values.new_value, G_TYPE_INT);
1045 g_value_set_int (&values.new_value, column);
1047 values.property_name = "accessible-table-column-description";
1048 g_signal_emit_by_name (table,
1049 "property_change::accessible-table-column-description",
1055 gail_clist_set_column_header (AtkTable *table,
1059 GailCList *clist = GAIL_CLIST (table);
1060 AtkPropertyValues values = { NULL };
1063 if (column < 0 || column >= gail_clist_get_n_columns (table))
1066 actual_column = gail_clist_get_actual_column (table, column);
1067 if (clist->columns[actual_column].header)
1068 g_object_unref (clist->columns[actual_column].header);
1070 g_object_ref (header);
1071 clist->columns[actual_column].header = header;
1073 g_value_init (&values.new_value, G_TYPE_INT);
1074 g_value_set_int (&values.new_value, column);
1076 values.property_name = "accessible-table-column-header";
1077 g_signal_emit_by_name (table,
1078 "property_change::accessible-table-column-header",
1083 gail_clist_set_row_description (AtkTable *table,
1085 const gchar *description)
1087 gail_clist_set_row_data (table, row, description, NULL, FALSE);
1091 gail_clist_set_row_header (AtkTable *table,
1095 gail_clist_set_row_data (table, row, NULL, header, TRUE);
1099 gail_clist_set_summary (AtkTable *table,
1100 AtkObject *accessible)
1102 GailCList* obj = GAIL_CLIST (table);
1103 AtkPropertyValues values = { 0, };
1104 AtkObject *old_summary;
1106 old_summary = obj->summary;
1107 obj->summary = accessible;
1109 g_object_ref (obj->summary);
1111 g_value_init (&values.old_value, G_TYPE_POINTER);
1112 g_value_set_pointer (&values.old_value, old_summary);
1113 g_value_init (&values.new_value, G_TYPE_POINTER);
1114 g_value_set_pointer (&values.new_value, obj->summary);
1116 values.property_name = "accessible-table-summary";
1117 g_signal_emit_by_name (table,
1118 "property_change::accessible-table-summary",
1121 g_object_unref (old_summary);
1125 static void gail_cell_parent_interface_init (GailCellParentIface *iface)
1127 iface->get_cell_extents = gail_clist_get_cell_extents;
1128 iface->get_cell_area = gail_clist_get_cell_area;
1132 gail_clist_get_cell_extents (GailCellParent *parent,
1138 AtkCoordType coord_type)
1142 gint widget_x, widget_y, widget_width, widget_height;
1143 GdkRectangle cell_rect;
1144 GdkRectangle visible_rect;
1146 widget = GTK_ACCESSIBLE (parent)->widget;
1149 clist = GTK_CLIST (widget);
1151 atk_component_get_extents (ATK_COMPONENT (parent), &widget_x, &widget_y,
1152 &widget_width, &widget_height,
1155 gail_clist_get_cell_area (parent, cell, &cell_rect);
1156 *width = cell_rect.width;
1157 *height = cell_rect.height;
1158 gail_clist_get_visible_rect (clist, &visible_rect);
1159 if (gail_clist_is_cell_visible (&cell_rect, &visible_rect))
1161 *x = cell_rect.x + widget_x;
1162 *y = cell_rect.y + widget_y;
1172 gail_clist_get_cell_area (GailCellParent *parent,
1174 GdkRectangle *cell_rect)
1178 gint column, row, n_columns;
1180 widget = GTK_ACCESSIBLE (parent)->widget;
1183 clist = GTK_CLIST (widget);
1185 n_columns = gail_clist_get_n_actual_columns (clist);
1186 g_return_if_fail (n_columns > 0);
1187 column = cell->index % n_columns;
1188 row = cell->index / n_columns;
1189 cell_rect->x = COLUMN_LEFT (clist, column);
1190 cell_rect->y = ROW_TOP (clist, row);
1191 cell_rect->width = clist->column[column].area.width;
1192 cell_rect->height = clist->row_height;
1196 gail_clist_select_row_gtk (GtkCList *clist,
1202 GailCList *gail_clist;
1204 AtkObject *selected_cell;
1206 gail_clist = GAIL_CLIST (data);
1208 for (temp_list = gail_clist->cell_data; temp_list; temp_list = temp_list->next)
1210 GailCListCellData *cell_data;
1212 cell_data = (GailCListCellData *) (temp_list->data);
1214 if (row == cell_data->row_number)
1219 gail_cell_add_state (cell_data->gail_cell, ATK_STATE_SELECTED, TRUE);
1222 if (clist->columns == 1)
1224 selected_cell = gail_clist_ref_at (ATK_TABLE (data), row, 1);
1227 if (gail_clist->previous_selected_cell)
1228 g_object_unref (gail_clist->previous_selected_cell);
1229 gail_clist->previous_selected_cell = selected_cell;
1230 gail_cell_add_state (GAIL_CELL (selected_cell), ATK_STATE_FOCUSED, FALSE);
1231 g_signal_emit_by_name (gail_clist,
1232 "active-descendant-changed",
1237 g_signal_emit_by_name (gail_clist, "selection_changed");
1241 gail_clist_unselect_row_gtk (GtkCList *clist,
1247 GailCList *gail_clist;
1250 gail_clist = GAIL_CLIST (data);
1252 for (temp_list = gail_clist->cell_data; temp_list; temp_list = temp_list->next)
1254 GailCListCellData *cell_data;
1256 cell_data = (GailCListCellData *) (temp_list->data);
1258 if (row == cell_data->row_number)
1263 gail_cell_add_state (cell_data->gail_cell, ATK_STATE_FOCUSED, FALSE);
1264 gail_cell_remove_state (cell_data->gail_cell, ATK_STATE_SELECTED, TRUE);
1268 g_signal_emit_by_name (gail_clist, "selection_changed");
1272 * This function determines the number of visible columns
1273 * up to and including the specified column
1276 gail_clist_get_visible_column (AtkTable *table,
1284 widget = GTK_ACCESSIBLE (table)->widget;
1286 /* State is defunct */
1289 clist = GTK_CLIST (widget);
1290 for (i = 0, vis_columns = 0; i < column; i++)
1291 if (clist->column[i].visible)
1298 gail_clist_get_actual_column (AtkTable *table,
1306 widget = GTK_ACCESSIBLE (table)->widget;
1308 /* State is defunct */
1311 clist = GTK_CLIST (widget);
1312 for (i = 0, vis_columns = 0; i < clist->columns; i++)
1314 if (clist->column[i].visible)
1316 if (visible_column == vis_columns)
1325 gail_clist_set_row_data (AtkTable *table,
1327 const gchar *description,
1332 GtkCList *gtk_clist;
1333 GailCList *gail_clist;
1335 GailCListRow* row_data;
1337 gboolean found = FALSE;
1338 AtkPropertyValues values = { NULL };
1341 widget = GTK_ACCESSIBLE (table)->widget;
1343 /* State is defunct */
1346 gtk_clist = GTK_CLIST (widget);
1347 if (row < 0 || row >= gtk_clist->rows)
1350 gail_clist = GAIL_CLIST (table);
1352 if (gail_clist->row_data == NULL)
1353 gail_clist->row_data = g_array_sized_new (FALSE, TRUE,
1354 sizeof (GailCListRow *), 0);
1356 array = gail_clist->row_data;
1358 for (i = 0; i < array->len; i++)
1360 row_data = g_array_index (array, GailCListRow*, i);
1362 if (row == row_data->row_number)
1367 if (row_data->header)
1368 g_object_unref (row_data->header);
1369 row_data->header = header;
1370 if (row_data->header)
1371 g_object_ref (row_data->header);
1375 g_free (row_data->description);
1376 row_data->description = g_strdup (row_data->description);
1385 elem = ROW_ELEMENT (gtk_clist, row);
1386 g_return_if_fail (elem != NULL);
1388 row_data = g_new (GailCListRow, 1);
1389 row_data->row_number = row;
1390 row_data->row_data = elem->data;
1393 row_data->header = header;
1394 if (row_data->header)
1395 g_object_ref (row_data->header);
1396 row_data->description = NULL;
1400 row_data->description = g_strdup (row_data->description);
1401 row_data->header = NULL;
1403 g_array_append_val (array, row_data);
1406 g_value_init (&values.new_value, G_TYPE_INT);
1407 g_value_set_int (&values.new_value, row);
1411 values.property_name = "accessible-table-row-header";
1412 signal_name = "property_change::accessible-table-row-header";
1416 values.property_name = "accessible-table-row-description";
1417 signal_name = "property_change::accessible-table-row-description";
1419 g_signal_emit_by_name (table,
1425 static GailCListRow*
1426 gail_clist_get_row_data (AtkTable *table,
1433 GailCListRow* row_data;
1436 widget = GTK_ACCESSIBLE (table)->widget;
1438 /* State is defunct */
1441 clist = GTK_CLIST (widget);
1442 if (row < 0 || row >= clist->rows)
1445 obj = GAIL_CLIST (table);
1447 if (obj->row_data == NULL)
1450 array = obj->row_data;
1452 for (i = 0; i < array->len; i++)
1454 row_data = g_array_index (array, GailCListRow*, i);
1456 if (row == row_data->row_number)
1464 gail_clist_get_visible_rect (GtkCList *clist,
1465 GdkRectangle *clist_rect)
1467 clist_rect->x = - clist->hoffset;
1468 clist_rect->y = - clist->voffset;
1469 clist_rect->width = clist->clist_window_width;
1470 clist_rect->height = clist->clist_window_height;
1474 gail_clist_is_cell_visible (GdkRectangle *cell_rect,
1475 GdkRectangle *visible_rect)
1478 * A cell is reported as visible if any part of the cell is visible
1480 if (((cell_rect->x + cell_rect->width) < visible_rect->x) ||
1481 ((cell_rect->y + cell_rect->height) < visible_rect->y) ||
1482 (cell_rect->x > (visible_rect->x + visible_rect->width)) ||
1483 (cell_rect->y > (visible_rect->y + visible_rect->height)))
1490 gail_clist_cell_data_new (GailCList *clist,
1496 GailCListCellData *cell_data;
1497 GtkCList *gtk_clist;
1498 GtkCListRow *clist_row;
1500 gtk_clist = GTK_CLIST (GTK_ACCESSIBLE (clist)->widget);
1501 elem = g_list_nth (gtk_clist->row_list, row);
1502 g_return_if_fail (elem != NULL);
1503 clist_row = (GtkCListRow *) elem->data;
1504 cell_data = g_new (GailCListCellData, 1);
1505 cell_data->gail_cell = cell;
1506 cell_data->gtk_cell = &(clist_row->cell[column]);
1507 cell_data->column_number = column;
1508 cell_data->row_number = row;
1509 clist->cell_data = g_list_append (clist->cell_data, cell_data);
1511 g_object_weak_ref (G_OBJECT (cell),
1512 (GWeakNotify) gail_clist_cell_destroyed,
1517 gail_clist_cell_destroyed (gpointer data)
1519 GailCell *cell = GAIL_CELL (data);
1522 parent = atk_object_get_parent (ATK_OBJECT (cell));
1524 gail_clist_cell_data_remove (GAIL_CLIST (parent), cell);
1528 gail_clist_cell_data_remove (GailCList *clist,
1533 for (temp_list = clist->cell_data; temp_list; temp_list = temp_list->next)
1535 GailCListCellData *cell_data;
1537 cell_data = (GailCListCellData *) temp_list->data;
1538 if (cell_data->gail_cell == cell)
1540 clist->cell_data = g_list_remove_link (clist->cell_data, temp_list);
1545 g_warning ("No cell removed in gail_clist_cell_data_remove\n");
1549 gail_clist_find_cell (GailCList *clist,
1555 n_cols = clist->n_cols;
1557 for (temp_list = clist->cell_data; temp_list; temp_list = temp_list->next)
1559 GailCListCellData *cell_data;
1562 cell_data = (GailCListCellData *) (temp_list->data);
1564 real_index = cell_data->column_number + n_cols * cell_data->row_number;
1565 if (real_index == index)
1566 return cell_data->gail_cell;
1572 gail_clist_adjustment_changed (GtkAdjustment *adjustment,
1576 GdkRectangle visible_rect;
1577 GdkRectangle cell_rect;
1582 * The scrollbars have changed
1584 atk_obj = gtk_widget_get_accessible (GTK_WIDGET (clist));
1585 obj = GAIL_CLIST (atk_obj);
1587 /* Get the currently visible area */
1588 gail_clist_get_visible_rect (clist, &visible_rect);
1590 /* loop over the cells and report if they are visible or not. */
1591 /* Must loop through them all */
1592 for (temp_list = obj->cell_data; temp_list; temp_list = temp_list->next)
1595 GailCListCellData *cell_data;
1597 cell_data = (GailCListCellData *) (temp_list->data);
1598 cell = cell_data->gail_cell;
1600 gail_clist_get_cell_area (GAIL_CELL_PARENT (atk_obj),
1602 if (gail_clist_is_cell_visible (&cell_rect, &visible_rect))
1603 gail_cell_add_state (cell, ATK_STATE_SHOWING, TRUE);
1605 gail_cell_remove_state (cell, ATK_STATE_SHOWING, TRUE);
1607 g_signal_emit_by_name (atk_obj, "visible_data_changed");