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 #include "gailclist.h"
25 #include "gailclistcell.h"
26 #include "gailcellparent.h"
28 /* Copied from gtkclist.c */
29 /* this defigns the base grid spacing */
30 #define CELL_SPACING 1
32 /* added the horizontal space at the beginning and end of a row*/
33 #define COLUMN_INSET 3
36 /* gives the top pixel of the given row in context of
37 * the clist's voffset */
38 #define ROW_TOP_YPIXEL(clist, row) (((clist)->row_height * (row)) + \
39 (((row) + 1) * CELL_SPACING) + \
42 /* returns the row index from a y pixel location in the
43 * context of the clist's voffset */
44 #define ROW_FROM_YPIXEL(clist, y) (((y) - (clist)->voffset) / \
45 ((clist)->row_height + CELL_SPACING))
46 /* gives the left pixel of the given column in context of
47 * the clist's hoffset */
48 #define COLUMN_LEFT_XPIXEL(clist, colnum) ((clist)->column[(colnum)].area.x + \
51 /* returns the column index from a x pixel location in the
52 * context of the clist's hoffset */
54 COLUMN_FROM_XPIXEL (GtkCList * clist,
59 for (i = 0; i < clist->columns; i++)
60 if (clist->column[i].visible)
62 cx = clist->column[i].area.x + clist->hoffset;
64 if (x >= (cx - (COLUMN_INSET + CELL_SPACING)) &&
65 x <= (cx + clist->column[i].area.width + COLUMN_INSET))
73 /* returns the top pixel of the given row in the context of
75 #define ROW_TOP(clist, row) (((clist)->row_height + CELL_SPACING) * (row))
77 /* returns the left pixel of the given column in the context of
79 #define COLUMN_LEFT(clist, colnum) ((clist)->column[(colnum)].area.x)
81 /* returns the total height of the list */
82 #define LIST_HEIGHT(clist) (((clist)->row_height * ((clist)->rows)) + \
83 (CELL_SPACING * ((clist)->rows + 1)))
86 LIST_WIDTH (GtkCList * clist)
90 for (last_column = clist->columns - 1;
91 last_column >= 0 && !clist->column[last_column].visible; last_column--);
94 return (clist->column[last_column].area.x +
95 clist->column[last_column].area.width +
96 COLUMN_INSET + CELL_SPACING);
100 /* returns the GList item for the nth row */
101 #define ROW_ELEMENT(clist, row) (((row) == (clist)->rows - 1) ? \
102 (clist)->row_list_end : \
103 g_list_nth ((clist)->row_list, (row)))
105 typedef struct _GailCListRow GailCListRow;
106 typedef struct _GailCListCellData GailCListCellData;
109 static void gail_clist_class_init (GailCListClass *klass);
110 static void gail_clist_init (GailCList *clist);
111 static void gail_clist_real_initialize (AtkObject *obj,
113 static void gail_clist_finalize (GObject *object);
115 static gint gail_clist_get_n_children (AtkObject *obj);
116 static AtkObject* gail_clist_ref_child (AtkObject *obj,
118 static AtkStateSet* gail_clist_ref_state_set (AtkObject *obj);
121 static void atk_selection_interface_init (AtkSelectionIface *iface);
122 static gboolean gail_clist_clear_selection (AtkSelection *selection);
124 static AtkObject* gail_clist_ref_selection (AtkSelection *selection,
126 static gint gail_clist_get_selection_count (AtkSelection *selection);
127 static gboolean gail_clist_is_child_selected (AtkSelection *selection,
129 static gboolean gail_clist_select_all_selection (AtkSelection *selection);
131 static void atk_table_interface_init (AtkTableIface *iface);
132 static gint gail_clist_get_index_at (AtkTable *table,
135 static gint gail_clist_get_column_at_index (AtkTable *table,
137 static gint gail_clist_get_row_at_index (AtkTable *table,
139 static AtkObject* gail_clist_ref_at (AtkTable *table,
142 static AtkObject* gail_clist_ref_at_actual (AtkTable *table,
146 gail_clist_get_caption (AtkTable *table);
148 static gint gail_clist_get_n_columns (AtkTable *table);
149 static gint gail_clist_get_n_actual_columns (GtkCList *clist);
151 static G_CONST_RETURN gchar*
152 gail_clist_get_column_description(AtkTable *table,
154 static AtkObject* gail_clist_get_column_header (AtkTable *table,
156 static gint gail_clist_get_n_rows (AtkTable *table);
157 static G_CONST_RETURN gchar*
158 gail_clist_get_row_description (AtkTable *table,
160 static AtkObject* gail_clist_get_row_header (AtkTable *table,
162 static AtkObject* gail_clist_get_summary (AtkTable *table);
163 static gboolean gail_clist_add_row_selection (AtkTable *table,
165 static gboolean gail_clist_remove_row_selection (AtkTable *table,
167 static gint gail_clist_get_selected_rows (AtkTable *table,
168 gint **rows_selected);
169 static gboolean gail_clist_is_row_selected (AtkTable *table,
171 static gboolean gail_clist_is_selected (AtkTable *table,
174 static void gail_clist_set_caption (AtkTable *table,
176 static void gail_clist_set_column_description(AtkTable *table,
178 const gchar *description);
179 static void gail_clist_set_column_header (AtkTable *table,
182 static void gail_clist_set_row_description (AtkTable *table,
184 const gchar *description);
185 static void gail_clist_set_row_header (AtkTable *table,
188 static void gail_clist_set_summary (AtkTable *table,
189 AtkObject *accessible);
191 /* gailcellparent.h */
193 static void gail_cell_parent_interface_init (GailCellParentIface *iface);
194 static void gail_clist_get_cell_extents (GailCellParent *parent,
200 AtkCoordType coord_type);
202 static void gail_clist_get_cell_area (GailCellParent *parent,
204 GdkRectangle *cell_rect);
206 static void gail_clist_select_row_gtk (GtkCList *clist,
211 static void gail_clist_unselect_row_gtk (GtkCList *clist,
216 static gint gail_clist_get_visible_column (AtkTable *table,
218 static gint gail_clist_get_actual_column (AtkTable *table,
220 static void gail_clist_set_row_data (AtkTable *table,
222 const gchar *description,
226 gail_clist_get_row_data (AtkTable *table,
228 static void gail_clist_get_visible_rect (GtkCList *clist,
229 GdkRectangle *clist_rect);
230 static gboolean gail_clist_is_cell_visible (GdkRectangle *cell_rect,
231 GdkRectangle *visible_rect);
232 static void gail_clist_cell_data_new (GailCList *clist,
236 static void gail_clist_cell_destroyed (gpointer data);
237 static void gail_clist_cell_data_remove (GailCList *clist,
239 static GailCell* gail_clist_find_cell (GailCList *clist,
241 static void gail_clist_adjustment_changed (GtkAdjustment *adjustment,
244 struct _GailCListColumn
252 GtkCListRow *row_data;
258 struct _GailCListCellData
266 G_DEFINE_TYPE_WITH_CODE (GailCList, gail_clist, GAIL_TYPE_CONTAINER,
267 G_IMPLEMENT_INTERFACE (ATK_TYPE_TABLE, atk_table_interface_init)
268 G_IMPLEMENT_INTERFACE (ATK_TYPE_SELECTION, atk_selection_interface_init)
269 G_IMPLEMENT_INTERFACE (GAIL_TYPE_CELL_PARENT, gail_cell_parent_interface_init))
272 gail_clist_class_init (GailCListClass *klass)
274 AtkObjectClass *class = ATK_OBJECT_CLASS (klass);
275 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
277 class->get_n_children = gail_clist_get_n_children;
278 class->ref_child = gail_clist_ref_child;
279 class->ref_state_set = gail_clist_ref_state_set;
280 class->initialize = gail_clist_real_initialize;
282 gobject_class->finalize = gail_clist_finalize;
286 gail_clist_init (GailCList *clist)
291 gail_clist_real_initialize (AtkObject *obj,
298 ATK_OBJECT_CLASS (gail_clist_parent_class)->initialize (obj, data);
300 obj->role = ATK_ROLE_TABLE;
302 clist = GAIL_CLIST (obj);
304 clist->caption = NULL;
305 clist->summary = NULL;
306 clist->row_data = NULL;
307 clist->cell_data = NULL;
308 clist->previous_selected_cell = NULL;
310 gtk_clist = GTK_CLIST (data);
312 clist->n_cols = gtk_clist->columns;
313 clist->columns = g_new (GailCListColumn, gtk_clist->columns);
314 for (i = 0; i < gtk_clist->columns; i++)
316 clist->columns[i].description = NULL;
317 clist->columns[i].header = NULL;
320 * Set up signal handlers for select-row and unselect-row
322 g_signal_connect (gtk_clist,
324 G_CALLBACK (gail_clist_select_row_gtk),
326 g_signal_connect (gtk_clist,
328 G_CALLBACK (gail_clist_unselect_row_gtk),
331 * Adjustment callbacks
333 if (gtk_clist->hadjustment)
335 g_signal_connect (gtk_clist->hadjustment,
337 G_CALLBACK (gail_clist_adjustment_changed),
340 if (gtk_clist->vadjustment)
342 g_signal_connect (gtk_clist->vadjustment,
344 G_CALLBACK (gail_clist_adjustment_changed),
350 gail_clist_finalize (GObject *object)
352 GailCList *clist = GAIL_CLIST (object);
357 g_object_unref (clist->caption);
359 g_object_unref (clist->summary);
361 for (i = 0; i < clist->n_cols; i++)
363 g_free (clist->columns[i].description);
364 if (clist->columns[i].header)
365 g_object_unref (clist->columns[i].header);
367 g_free (clist->columns);
369 array = clist->row_data;
371 if (clist->previous_selected_cell)
372 g_object_unref (clist->previous_selected_cell);
376 for (i = 0; i < array->len; i++)
378 GailCListRow *row_data;
380 row_data = g_array_index (array, GailCListRow*, i);
382 if (row_data->header)
383 g_object_unref (row_data->header);
384 g_free (row_data->description);
388 if (clist->cell_data)
392 for (temp_list = clist->cell_data; temp_list; temp_list = temp_list->next)
394 g_list_free (temp_list->data);
396 g_list_free (clist->cell_data);
399 G_OBJECT_CLASS (gail_clist_parent_class)->finalize (object);
403 gail_clist_get_n_children (AtkObject *obj)
408 g_return_val_if_fail (GAIL_IS_CLIST (obj), 0);
410 widget = GTK_ACCESSIBLE (obj)->widget;
417 row = gail_clist_get_n_rows (ATK_TABLE (obj));
418 col = gail_clist_get_n_actual_columns (GTK_CLIST (widget));
423 gail_clist_ref_child (AtkObject *obj,
430 g_return_val_if_fail (GAIL_IS_CLIST (obj), NULL);
431 g_return_val_if_fail (i >= 0, NULL);
433 widget = GTK_ACCESSIBLE (obj)->widget;
440 n_columns = gail_clist_get_n_actual_columns (GTK_CLIST (widget));
446 return gail_clist_ref_at_actual (ATK_TABLE (obj), row, col);
450 gail_clist_ref_state_set (AtkObject *obj)
452 AtkStateSet *state_set;
455 state_set = ATK_OBJECT_CLASS (gail_clist_parent_class)->ref_state_set (obj);
456 widget = GTK_ACCESSIBLE (obj)->widget;
459 atk_state_set_add_state (state_set, ATK_STATE_MANAGES_DESCENDANTS);
465 atk_selection_interface_init (AtkSelectionIface *iface)
467 iface->clear_selection = gail_clist_clear_selection;
468 iface->ref_selection = gail_clist_ref_selection;
469 iface->get_selection_count = gail_clist_get_selection_count;
470 iface->is_child_selected = gail_clist_is_child_selected;
471 iface->select_all_selection = gail_clist_select_all_selection;
475 gail_clist_clear_selection (AtkSelection *selection)
480 widget = GTK_ACCESSIBLE (selection)->widget;
482 /* State is defunct */
485 clist = GTK_CLIST (widget);
486 gtk_clist_unselect_all(clist);
491 gail_clist_ref_selection (AtkSelection *selection,
494 gint visible_columns;
496 gint selected_column;
499 if ( i < 0 && i >= gail_clist_get_selection_count (selection))
502 visible_columns = gail_clist_get_n_columns (ATK_TABLE (selection));
503 gail_clist_get_selected_rows (ATK_TABLE (selection), &selected_rows);
504 selected_row = selected_rows[i / visible_columns];
505 g_free (selected_rows);
506 selected_column = gail_clist_get_actual_column (ATK_TABLE (selection),
507 i % visible_columns);
509 return gail_clist_ref_at (ATK_TABLE (selection), selected_row,
514 gail_clist_get_selection_count (AtkSelection *selection)
516 gint n_rows_selected;
518 n_rows_selected = gail_clist_get_selected_rows (ATK_TABLE (selection), NULL);
520 if (n_rows_selected > 0)
522 * The number of cells selected is the number of columns
523 * times the number of selected rows
525 return gail_clist_get_n_columns (ATK_TABLE (selection)) * n_rows_selected;
530 gail_clist_is_child_selected (AtkSelection *selection,
535 row = atk_table_get_row_at_index (ATK_TABLE (selection), i);
537 if (row == 0 && i >= gail_clist_get_n_columns (ATK_TABLE (selection)))
539 return gail_clist_is_row_selected (ATK_TABLE (selection), row);
543 gail_clist_select_all_selection (AtkSelection *selection)
549 widget = GTK_ACCESSIBLE (selection)->widget;
551 /* State is defunct */
554 clist = GTK_CLIST (widget);
555 gtk_clist_select_all(clist);
561 atk_table_interface_init (AtkTableIface *iface)
563 iface->ref_at = gail_clist_ref_at;
564 iface->get_index_at = gail_clist_get_index_at;
565 iface->get_column_at_index = gail_clist_get_column_at_index;
566 iface->get_row_at_index = gail_clist_get_row_at_index;
567 iface->get_caption = gail_clist_get_caption;
568 iface->get_n_columns = gail_clist_get_n_columns;
569 iface->get_column_description = gail_clist_get_column_description;
570 iface->get_column_header = gail_clist_get_column_header;
571 iface->get_n_rows = gail_clist_get_n_rows;
572 iface->get_row_description = gail_clist_get_row_description;
573 iface->get_row_header = gail_clist_get_row_header;
574 iface->get_summary = gail_clist_get_summary;
575 iface->add_row_selection = gail_clist_add_row_selection;
576 iface->remove_row_selection = gail_clist_remove_row_selection;
577 iface->get_selected_rows = gail_clist_get_selected_rows;
578 iface->is_row_selected = gail_clist_is_row_selected;
579 iface->is_selected = gail_clist_is_selected;
580 iface->set_caption = gail_clist_set_caption;
581 iface->set_column_description = gail_clist_set_column_description;
582 iface->set_column_header = gail_clist_set_column_header;
583 iface->set_row_description = gail_clist_set_row_description;
584 iface->set_row_header = gail_clist_set_row_header;
585 iface->set_summary = gail_clist_set_summary;
589 gail_clist_ref_at (AtkTable *table,
596 widget = GTK_ACCESSIBLE (table)->widget;
598 /* State is defunct */
601 actual_column = gail_clist_get_actual_column (table, column);
602 return gail_clist_ref_at_actual (table, row, actual_column);
607 gail_clist_ref_at_actual (AtkTable *table,
612 * The column number pased to this function is the actual column number
613 * whereas the column number passed to gail_clist_ref_at is the
614 * visible column number
618 GtkCellType cellType;
619 AtkObject *return_object;
620 gint n_rows, n_columns;
624 g_return_val_if_fail (GTK_IS_ACCESSIBLE (table), NULL);
626 widget = GTK_ACCESSIBLE (table)->widget;
628 /* State is defunct */
631 clist = GTK_CLIST (widget);
632 n_rows = gail_clist_get_n_rows (table);
633 n_columns = gail_clist_get_n_actual_columns (clist);
635 if (row < 0 || row >= n_rows)
637 if (column < 0 || column >= n_columns)
641 * Check whether the child is cached
643 index = column + row * n_columns;
644 cell = gail_clist_find_cell (GAIL_CLIST (table), index);
648 return ATK_OBJECT (cell);
650 cellType = gtk_clist_get_cell_type(clist, row, column);
654 case GTK_CELL_PIXTEXT:
655 return_object = gail_clist_cell_new ();
657 case GTK_CELL_PIXMAP:
658 return_object = NULL;
661 /* Don't handle GTK_CELL_EMPTY or GTK_CELL_WIDGET, return NULL */
662 return_object = NULL;
667 cell = GAIL_CELL (return_object);
669 g_return_val_if_fail (ATK_IS_OBJECT (table), NULL);
671 gail_cell_initialise (cell, widget, ATK_OBJECT (table),
674 * Store the cell in a cache
676 gail_clist_cell_data_new (GAIL_CLIST (table), cell, column, row);
678 * If the column is visible, sets the cell's state
680 if (clist->column[column].visible)
682 GdkRectangle cell_rect, visible_rect;
684 gail_clist_get_cell_area (GAIL_CELL_PARENT (table), cell, &cell_rect);
685 gail_clist_get_visible_rect (clist, &visible_rect);
686 gail_cell_add_state (cell, ATK_STATE_VISIBLE, FALSE);
687 if (gail_clist_is_cell_visible (&cell_rect, &visible_rect))
688 gail_cell_add_state (cell, ATK_STATE_SHOWING, FALSE);
691 * If a row is selected, all cells in the row are selected
693 if (gail_clist_is_row_selected (table, row))
695 gail_cell_add_state (cell, ATK_STATE_SELECTED, FALSE);
696 if (clist->columns == 1)
697 gail_cell_add_state (cell, ATK_STATE_FOCUSED, FALSE);
701 return return_object;
705 gail_clist_get_index_at (AtkTable *table,
711 n_cols = atk_table_get_n_columns (table);
712 n_rows = atk_table_get_n_rows (table);
714 g_return_val_if_fail (row < n_rows, 0);
715 g_return_val_if_fail (column < n_cols, 0);
717 return row * n_cols + column;
721 gail_clist_get_column_at_index (AtkTable *table,
726 n_cols = atk_table_get_n_columns (table);
731 return (gint) (index % n_cols);
735 gail_clist_get_row_at_index (AtkTable *table,
740 n_cols = atk_table_get_n_columns (table);
745 return (gint) (index / n_cols);
749 gail_clist_get_caption (AtkTable *table)
751 GailCList* obj = GAIL_CLIST (table);
757 gail_clist_get_n_columns (AtkTable *table)
762 widget = GTK_ACCESSIBLE (table)->widget;
764 /* State is defunct */
767 clist = GTK_CLIST (widget);
769 return gail_clist_get_visible_column (table,
770 gail_clist_get_n_actual_columns (clist));
774 gail_clist_get_n_actual_columns (GtkCList *clist)
776 return clist->columns;
779 static G_CONST_RETURN gchar*
780 gail_clist_get_column_description (AtkTable *table,
783 GailCList *clist = GAIL_CLIST (table);
787 if (column < 0 || column >= gail_clist_get_n_columns (table))
790 actual_column = gail_clist_get_actual_column (table, column);
791 if (clist->columns[actual_column].description)
792 return (clist->columns[actual_column].description);
794 widget = GTK_ACCESSIBLE (clist)->widget;
798 return gtk_clist_get_column_title (GTK_CLIST (widget), actual_column);
802 gail_clist_get_column_header (AtkTable *table,
805 GailCList *clist = GAIL_CLIST (table);
807 GtkWidget *return_widget;
810 if (column < 0 || column >= gail_clist_get_n_columns (table))
813 actual_column = gail_clist_get_actual_column (table, column);
815 if (clist->columns[actual_column].header)
816 return (clist->columns[actual_column].header);
818 widget = GTK_ACCESSIBLE (clist)->widget;
822 return_widget = gtk_clist_get_column_widget (GTK_CLIST (widget),
824 if (return_widget == NULL)
827 g_return_val_if_fail (GTK_IS_BIN (return_widget), NULL);
828 return_widget = gtk_bin_get_child (GTK_BIN(return_widget));
830 return gtk_widget_get_accessible (return_widget);
834 gail_clist_get_n_rows (AtkTable *table)
839 widget = GTK_ACCESSIBLE (table)->widget;
841 /* State is defunct */
844 clist = GTK_CLIST (widget);
848 static G_CONST_RETURN gchar*
849 gail_clist_get_row_description (AtkTable *table,
852 GailCListRow* row_data;
854 row_data = gail_clist_get_row_data (table, row);
855 if (row_data == NULL)
857 return row_data->description;
861 gail_clist_get_row_header (AtkTable *table,
864 GailCListRow* row_data;
866 row_data = gail_clist_get_row_data (table, row);
867 if (row_data == NULL)
869 return row_data->header;
873 gail_clist_get_summary (AtkTable *table)
875 GailCList* obj = GAIL_CLIST (table);
881 gail_clist_add_row_selection (AtkTable *table,
887 widget = GTK_ACCESSIBLE (table)->widget;
889 /* State is defunct */
892 clist = GTK_CLIST (widget);
893 gtk_clist_select_row (clist, row, -1);
894 if (gail_clist_is_row_selected (table, row))
901 gail_clist_remove_row_selection (AtkTable *table,
907 widget = GTK_ACCESSIBLE (table)->widget;
909 /* State is defunct */
912 clist = GTK_CLIST (widget);
913 if (gail_clist_is_row_selected (table, row))
915 gtk_clist_select_row (clist, row, -1);
922 gail_clist_get_selected_rows (AtkTable *table,
923 gint **rows_selected)
931 widget = GTK_ACCESSIBLE (table)->widget;
933 /* State is defunct */
936 clist = GTK_CLIST (widget);
938 n_selected = g_list_length (clist->selection);
947 selected_rows = (gint*) g_malloc (sizeof (gint) * n_selected);
948 list = clist->selection;
953 selected_rows[i++] = GPOINTER_TO_INT (list->data);
956 *rows_selected = selected_rows;
962 gail_clist_is_row_selected (AtkTable *table,
968 GtkCListRow *clist_row;
970 widget = GTK_ACCESSIBLE (table)->widget;
972 /* State is defunct */
975 clist = GTK_CLIST (widget);
977 if (row < 0 || row >= clist->rows)
980 elem = ROW_ELEMENT (clist, row);
983 clist_row = elem->data;
985 return (clist_row->state == GTK_STATE_SELECTED);
989 gail_clist_is_selected (AtkTable *table,
993 return gail_clist_is_row_selected (table, row);
997 gail_clist_set_caption (AtkTable *table,
1000 GailCList* obj = GAIL_CLIST (table);
1001 AtkPropertyValues values = { NULL };
1002 AtkObject *old_caption;
1004 old_caption = obj->caption;
1005 obj->caption = caption;
1007 g_object_ref (obj->caption);
1009 g_value_init (&values.old_value, G_TYPE_POINTER);
1010 g_value_set_pointer (&values.old_value, old_caption);
1011 g_value_init (&values.new_value, G_TYPE_POINTER);
1012 g_value_set_pointer (&values.new_value, obj->caption);
1014 values.property_name = "accessible-table-caption";
1015 g_signal_emit_by_name (table,
1016 "property_change::accessible-table-caption",
1019 g_object_unref (old_caption);
1023 gail_clist_set_column_description (AtkTable *table,
1025 const gchar *description)
1027 GailCList *clist = GAIL_CLIST (table);
1028 AtkPropertyValues values = { NULL };
1031 if (column < 0 || column >= gail_clist_get_n_columns (table))
1034 if (description == NULL)
1037 actual_column = gail_clist_get_actual_column (table, column);
1038 g_free (clist->columns[actual_column].description);
1039 clist->columns[actual_column].description = g_strdup (description);
1041 g_value_init (&values.new_value, G_TYPE_INT);
1042 g_value_set_int (&values.new_value, column);
1044 values.property_name = "accessible-table-column-description";
1045 g_signal_emit_by_name (table,
1046 "property_change::accessible-table-column-description",
1052 gail_clist_set_column_header (AtkTable *table,
1056 GailCList *clist = GAIL_CLIST (table);
1057 AtkPropertyValues values = { NULL };
1060 if (column < 0 || column >= gail_clist_get_n_columns (table))
1063 actual_column = gail_clist_get_actual_column (table, column);
1064 if (clist->columns[actual_column].header)
1065 g_object_unref (clist->columns[actual_column].header);
1067 g_object_ref (header);
1068 clist->columns[actual_column].header = header;
1070 g_value_init (&values.new_value, G_TYPE_INT);
1071 g_value_set_int (&values.new_value, column);
1073 values.property_name = "accessible-table-column-header";
1074 g_signal_emit_by_name (table,
1075 "property_change::accessible-table-column-header",
1080 gail_clist_set_row_description (AtkTable *table,
1082 const gchar *description)
1084 gail_clist_set_row_data (table, row, description, NULL, FALSE);
1088 gail_clist_set_row_header (AtkTable *table,
1092 gail_clist_set_row_data (table, row, NULL, header, TRUE);
1096 gail_clist_set_summary (AtkTable *table,
1097 AtkObject *accessible)
1099 GailCList* obj = GAIL_CLIST (table);
1100 AtkPropertyValues values = { 0, };
1101 AtkObject *old_summary;
1103 old_summary = obj->summary;
1104 obj->summary = accessible;
1106 g_object_ref (obj->summary);
1108 g_value_init (&values.old_value, G_TYPE_POINTER);
1109 g_value_set_pointer (&values.old_value, old_summary);
1110 g_value_init (&values.new_value, G_TYPE_POINTER);
1111 g_value_set_pointer (&values.new_value, obj->summary);
1113 values.property_name = "accessible-table-summary";
1114 g_signal_emit_by_name (table,
1115 "property_change::accessible-table-summary",
1118 g_object_unref (old_summary);
1122 static void gail_cell_parent_interface_init (GailCellParentIface *iface)
1124 iface->get_cell_extents = gail_clist_get_cell_extents;
1125 iface->get_cell_area = gail_clist_get_cell_area;
1129 gail_clist_get_cell_extents (GailCellParent *parent,
1135 AtkCoordType coord_type)
1139 gint widget_x, widget_y, widget_width, widget_height;
1140 GdkRectangle cell_rect;
1141 GdkRectangle visible_rect;
1143 widget = GTK_ACCESSIBLE (parent)->widget;
1146 clist = GTK_CLIST (widget);
1148 atk_component_get_extents (ATK_COMPONENT (parent), &widget_x, &widget_y,
1149 &widget_width, &widget_height,
1152 gail_clist_get_cell_area (parent, cell, &cell_rect);
1153 *width = cell_rect.width;
1154 *height = cell_rect.height;
1155 gail_clist_get_visible_rect (clist, &visible_rect);
1156 if (gail_clist_is_cell_visible (&cell_rect, &visible_rect))
1158 *x = cell_rect.x + widget_x;
1159 *y = cell_rect.y + widget_y;
1169 gail_clist_get_cell_area (GailCellParent *parent,
1171 GdkRectangle *cell_rect)
1175 gint column, row, n_columns;
1177 widget = GTK_ACCESSIBLE (parent)->widget;
1180 clist = GTK_CLIST (widget);
1182 n_columns = gail_clist_get_n_actual_columns (clist);
1183 g_return_if_fail (n_columns > 0);
1184 column = cell->index % n_columns;
1185 row = cell->index / n_columns;
1186 cell_rect->x = COLUMN_LEFT (clist, column);
1187 cell_rect->y = ROW_TOP (clist, row);
1188 cell_rect->width = clist->column[column].area.width;
1189 cell_rect->height = clist->row_height;
1193 gail_clist_select_row_gtk (GtkCList *clist,
1199 GailCList *gail_clist;
1201 AtkObject *selected_cell;
1203 gail_clist = GAIL_CLIST (data);
1205 for (temp_list = gail_clist->cell_data; temp_list; temp_list = temp_list->next)
1207 GailCListCellData *cell_data;
1209 cell_data = (GailCListCellData *) (temp_list->data);
1211 if (row == cell_data->row_number)
1216 gail_cell_add_state (cell_data->gail_cell, ATK_STATE_SELECTED, TRUE);
1219 if (clist->columns == 1)
1221 selected_cell = gail_clist_ref_at (ATK_TABLE (data), row, 1);
1224 if (gail_clist->previous_selected_cell)
1225 g_object_unref (gail_clist->previous_selected_cell);
1226 gail_clist->previous_selected_cell = selected_cell;
1227 gail_cell_add_state (GAIL_CELL (selected_cell), ATK_STATE_FOCUSED, FALSE);
1228 g_signal_emit_by_name (gail_clist,
1229 "active-descendant-changed",
1234 g_signal_emit_by_name (gail_clist, "selection_changed");
1238 gail_clist_unselect_row_gtk (GtkCList *clist,
1244 GailCList *gail_clist;
1247 gail_clist = GAIL_CLIST (data);
1249 for (temp_list = gail_clist->cell_data; temp_list; temp_list = temp_list->next)
1251 GailCListCellData *cell_data;
1253 cell_data = (GailCListCellData *) (temp_list->data);
1255 if (row == cell_data->row_number)
1260 gail_cell_add_state (cell_data->gail_cell, ATK_STATE_FOCUSED, FALSE);
1261 gail_cell_remove_state (cell_data->gail_cell, ATK_STATE_SELECTED, TRUE);
1265 g_signal_emit_by_name (gail_clist, "selection_changed");
1269 * This function determines the number of visible columns
1270 * up to and including the specified column
1273 gail_clist_get_visible_column (AtkTable *table,
1281 widget = GTK_ACCESSIBLE (table)->widget;
1283 /* State is defunct */
1286 clist = GTK_CLIST (widget);
1287 for (i = 0, vis_columns = 0; i < column; i++)
1288 if (clist->column[i].visible)
1295 gail_clist_get_actual_column (AtkTable *table,
1303 widget = GTK_ACCESSIBLE (table)->widget;
1305 /* State is defunct */
1308 clist = GTK_CLIST (widget);
1309 for (i = 0, vis_columns = 0; i < clist->columns; i++)
1311 if (clist->column[i].visible)
1313 if (visible_column == vis_columns)
1322 gail_clist_set_row_data (AtkTable *table,
1324 const gchar *description,
1329 GtkCList *gtk_clist;
1330 GailCList *gail_clist;
1332 GailCListRow* row_data;
1334 gboolean found = FALSE;
1335 AtkPropertyValues values = { NULL };
1338 widget = GTK_ACCESSIBLE (table)->widget;
1340 /* State is defunct */
1343 gtk_clist = GTK_CLIST (widget);
1344 if (row < 0 || row >= gtk_clist->rows)
1347 gail_clist = GAIL_CLIST (table);
1349 if (gail_clist->row_data == NULL)
1350 gail_clist->row_data = g_array_sized_new (FALSE, TRUE,
1351 sizeof (GailCListRow *), 0);
1353 array = gail_clist->row_data;
1355 for (i = 0; i < array->len; i++)
1357 row_data = g_array_index (array, GailCListRow*, i);
1359 if (row == row_data->row_number)
1364 if (row_data->header)
1365 g_object_unref (row_data->header);
1366 row_data->header = header;
1367 if (row_data->header)
1368 g_object_ref (row_data->header);
1372 g_free (row_data->description);
1373 row_data->description = g_strdup (row_data->description);
1382 elem = ROW_ELEMENT (gtk_clist, row);
1383 g_return_if_fail (elem != NULL);
1385 row_data = g_new (GailCListRow, 1);
1386 row_data->row_number = row;
1387 row_data->row_data = elem->data;
1390 row_data->header = header;
1391 if (row_data->header)
1392 g_object_ref (row_data->header);
1393 row_data->description = NULL;
1397 row_data->description = g_strdup (row_data->description);
1398 row_data->header = NULL;
1400 g_array_append_val (array, row_data);
1403 g_value_init (&values.new_value, G_TYPE_INT);
1404 g_value_set_int (&values.new_value, row);
1408 values.property_name = "accessible-table-row-header";
1409 signal_name = "property_change::accessible-table-row-header";
1413 values.property_name = "accessible-table-row-description";
1414 signal_name = "property_change::accessible-table-row-description";
1416 g_signal_emit_by_name (table,
1422 static GailCListRow*
1423 gail_clist_get_row_data (AtkTable *table,
1430 GailCListRow* row_data;
1433 widget = GTK_ACCESSIBLE (table)->widget;
1435 /* State is defunct */
1438 clist = GTK_CLIST (widget);
1439 if (row < 0 || row >= clist->rows)
1442 obj = GAIL_CLIST (table);
1444 if (obj->row_data == NULL)
1447 array = obj->row_data;
1449 for (i = 0; i < array->len; i++)
1451 row_data = g_array_index (array, GailCListRow*, i);
1453 if (row == row_data->row_number)
1461 gail_clist_get_visible_rect (GtkCList *clist,
1462 GdkRectangle *clist_rect)
1464 clist_rect->x = - clist->hoffset;
1465 clist_rect->y = - clist->voffset;
1466 clist_rect->width = clist->clist_window_width;
1467 clist_rect->height = clist->clist_window_height;
1471 gail_clist_is_cell_visible (GdkRectangle *cell_rect,
1472 GdkRectangle *visible_rect)
1475 * A cell is reported as visible if any part of the cell is visible
1477 if (((cell_rect->x + cell_rect->width) < visible_rect->x) ||
1478 ((cell_rect->y + cell_rect->height) < visible_rect->y) ||
1479 (cell_rect->x > (visible_rect->x + visible_rect->width)) ||
1480 (cell_rect->y > (visible_rect->y + visible_rect->height)))
1487 gail_clist_cell_data_new (GailCList *clist,
1493 GailCListCellData *cell_data;
1494 GtkCList *gtk_clist;
1495 GtkCListRow *clist_row;
1497 gtk_clist = GTK_CLIST (GTK_ACCESSIBLE (clist)->widget);
1498 elem = g_list_nth (gtk_clist->row_list, row);
1499 g_return_if_fail (elem != NULL);
1500 clist_row = (GtkCListRow *) elem->data;
1501 cell_data = g_new (GailCListCellData, 1);
1502 cell_data->gail_cell = cell;
1503 cell_data->gtk_cell = &(clist_row->cell[column]);
1504 cell_data->column_number = column;
1505 cell_data->row_number = row;
1506 clist->cell_data = g_list_append (clist->cell_data, cell_data);
1508 g_object_weak_ref (G_OBJECT (cell),
1509 (GWeakNotify) gail_clist_cell_destroyed,
1514 gail_clist_cell_destroyed (gpointer data)
1516 GailCell *cell = GAIL_CELL (data);
1519 parent = atk_object_get_parent (ATK_OBJECT (cell));
1521 gail_clist_cell_data_remove (GAIL_CLIST (parent), cell);
1525 gail_clist_cell_data_remove (GailCList *clist,
1530 for (temp_list = clist->cell_data; temp_list; temp_list = temp_list->next)
1532 GailCListCellData *cell_data;
1534 cell_data = (GailCListCellData *) temp_list->data;
1535 if (cell_data->gail_cell == cell)
1537 clist->cell_data = g_list_remove_link (clist->cell_data, temp_list);
1542 g_warning ("No cell removed in gail_clist_cell_data_remove\n");
1546 gail_clist_find_cell (GailCList *clist,
1552 n_cols = clist->n_cols;
1554 for (temp_list = clist->cell_data; temp_list; temp_list = temp_list->next)
1556 GailCListCellData *cell_data;
1559 cell_data = (GailCListCellData *) (temp_list->data);
1561 real_index = cell_data->column_number + n_cols * cell_data->row_number;
1562 if (real_index == index)
1563 return cell_data->gail_cell;
1569 gail_clist_adjustment_changed (GtkAdjustment *adjustment,
1573 GdkRectangle visible_rect;
1574 GdkRectangle cell_rect;
1579 * The scrollbars have changed
1581 atk_obj = gtk_widget_get_accessible (GTK_WIDGET (clist));
1582 obj = GAIL_CLIST (atk_obj);
1584 /* Get the currently visible area */
1585 gail_clist_get_visible_rect (clist, &visible_rect);
1587 /* loop over the cells and report if they are visible or not. */
1588 /* Must loop through them all */
1589 for (temp_list = obj->cell_data; temp_list; temp_list = temp_list->next)
1592 GailCListCellData *cell_data;
1594 cell_data = (GailCListCellData *) (temp_list->data);
1595 cell = cell_data->gail_cell;
1597 gail_clist_get_cell_area (GAIL_CELL_PARENT (atk_obj),
1599 if (gail_clist_is_cell_visible (&cell_rect, &visible_rect))
1600 gail_cell_add_state (cell, ATK_STATE_SHOWING, TRUE);
1602 gail_cell_remove_state (cell, ATK_STATE_SHOWING, TRUE);
1604 g_signal_emit_by_name (atk_obj, "visible_data_changed");