forked from AuroraMiddleware/gtk
c5edf5e513
2008-12-09 Michael Natterer <mitch@imendio.com> * Makefile.am * tests/Makefile.am: add GTK_DISABLE_DEPRECATED to CFLAGS. * gail.c * gailclist.c * gailclistcell.c * gailcombo.c * gaillist.c * gailmenu.c * gailoptionmenu.c * gailpixmap.c * gailprogressbar.c * gailtoplevel.c * gailwidget.c * gailwindow.c * tests/ferret.c * tests/testcombo.c * tests/testlib.h * tests/testoptionmenu.c: #undef it where we need to access deprecated cruft. svn path=/trunk/; revision=21859
1610 lines
47 KiB
C
1610 lines
47 KiB
C
/* GAIL - The GNOME Accessibility Implementation Library
|
|
* Copyright 2001 Sun Microsystems Inc.
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the
|
|
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
|
* Boston, MA 02111-1307, USA.
|
|
*/
|
|
|
|
#include "config.h"
|
|
|
|
#include <stdio.h>
|
|
|
|
#undef GTK_DISABLE_DEPRECATED
|
|
|
|
#include <gtk/gtk.h>
|
|
#include "gailclist.h"
|
|
#include "gailclistcell.h"
|
|
#include "gailcellparent.h"
|
|
|
|
/* Copied from gtkclist.c */
|
|
/* this defigns the base grid spacing */
|
|
#define CELL_SPACING 1
|
|
|
|
/* added the horizontal space at the beginning and end of a row*/
|
|
#define COLUMN_INSET 3
|
|
|
|
|
|
/* gives the top pixel of the given row in context of
|
|
* the clist's voffset */
|
|
#define ROW_TOP_YPIXEL(clist, row) (((clist)->row_height * (row)) + \
|
|
(((row) + 1) * CELL_SPACING) + \
|
|
(clist)->voffset)
|
|
|
|
/* returns the row index from a y pixel location in the
|
|
* context of the clist's voffset */
|
|
#define ROW_FROM_YPIXEL(clist, y) (((y) - (clist)->voffset) / \
|
|
((clist)->row_height + CELL_SPACING))
|
|
/* gives the left pixel of the given column in context of
|
|
* the clist's hoffset */
|
|
#define COLUMN_LEFT_XPIXEL(clist, colnum) ((clist)->column[(colnum)].area.x + \
|
|
(clist)->hoffset)
|
|
|
|
/* returns the column index from a x pixel location in the
|
|
* context of the clist's hoffset */
|
|
static inline gint
|
|
COLUMN_FROM_XPIXEL (GtkCList * clist,
|
|
gint x)
|
|
{
|
|
gint i, cx;
|
|
|
|
for (i = 0; i < clist->columns; i++)
|
|
if (clist->column[i].visible)
|
|
{
|
|
cx = clist->column[i].area.x + clist->hoffset;
|
|
|
|
if (x >= (cx - (COLUMN_INSET + CELL_SPACING)) &&
|
|
x <= (cx + clist->column[i].area.width + COLUMN_INSET))
|
|
return i;
|
|
}
|
|
|
|
/* no match */
|
|
return -1;
|
|
}
|
|
|
|
/* returns the top pixel of the given row in the context of
|
|
* the list height */
|
|
#define ROW_TOP(clist, row) (((clist)->row_height + CELL_SPACING) * (row))
|
|
|
|
/* returns the left pixel of the given column in the context of
|
|
* the list width */
|
|
#define COLUMN_LEFT(clist, colnum) ((clist)->column[(colnum)].area.x)
|
|
|
|
/* returns the total height of the list */
|
|
#define LIST_HEIGHT(clist) (((clist)->row_height * ((clist)->rows)) + \
|
|
(CELL_SPACING * ((clist)->rows + 1)))
|
|
|
|
static inline gint
|
|
LIST_WIDTH (GtkCList * clist)
|
|
{
|
|
gint last_column;
|
|
|
|
for (last_column = clist->columns - 1;
|
|
last_column >= 0 && !clist->column[last_column].visible; last_column--);
|
|
|
|
if (last_column >= 0)
|
|
return (clist->column[last_column].area.x +
|
|
clist->column[last_column].area.width +
|
|
COLUMN_INSET + CELL_SPACING);
|
|
return 0;
|
|
}
|
|
|
|
/* returns the GList item for the nth row */
|
|
#define ROW_ELEMENT(clist, row) (((row) == (clist)->rows - 1) ? \
|
|
(clist)->row_list_end : \
|
|
g_list_nth ((clist)->row_list, (row)))
|
|
|
|
typedef struct _GailCListRow GailCListRow;
|
|
typedef struct _GailCListCellData GailCListCellData;
|
|
|
|
|
|
static void gail_clist_class_init (GailCListClass *klass);
|
|
static void gail_clist_init (GailCList *clist);
|
|
static void gail_clist_real_initialize (AtkObject *obj,
|
|
gpointer data);
|
|
static void gail_clist_finalize (GObject *object);
|
|
|
|
static gint gail_clist_get_n_children (AtkObject *obj);
|
|
static AtkObject* gail_clist_ref_child (AtkObject *obj,
|
|
gint i);
|
|
static AtkStateSet* gail_clist_ref_state_set (AtkObject *obj);
|
|
|
|
|
|
static void atk_selection_interface_init (AtkSelectionIface *iface);
|
|
static gboolean gail_clist_clear_selection (AtkSelection *selection);
|
|
|
|
static AtkObject* gail_clist_ref_selection (AtkSelection *selection,
|
|
gint i);
|
|
static gint gail_clist_get_selection_count (AtkSelection *selection);
|
|
static gboolean gail_clist_is_child_selected (AtkSelection *selection,
|
|
gint i);
|
|
static gboolean gail_clist_select_all_selection (AtkSelection *selection);
|
|
|
|
static void atk_table_interface_init (AtkTableIface *iface);
|
|
static gint gail_clist_get_index_at (AtkTable *table,
|
|
gint row,
|
|
gint column);
|
|
static gint gail_clist_get_column_at_index (AtkTable *table,
|
|
gint index);
|
|
static gint gail_clist_get_row_at_index (AtkTable *table,
|
|
gint index);
|
|
static AtkObject* gail_clist_ref_at (AtkTable *table,
|
|
gint row,
|
|
gint column);
|
|
static AtkObject* gail_clist_ref_at_actual (AtkTable *table,
|
|
gint row,
|
|
gint column);
|
|
static AtkObject*
|
|
gail_clist_get_caption (AtkTable *table);
|
|
|
|
static gint gail_clist_get_n_columns (AtkTable *table);
|
|
static gint gail_clist_get_n_actual_columns (GtkCList *clist);
|
|
|
|
static G_CONST_RETURN gchar*
|
|
gail_clist_get_column_description(AtkTable *table,
|
|
gint column);
|
|
static AtkObject* gail_clist_get_column_header (AtkTable *table,
|
|
gint column);
|
|
static gint gail_clist_get_n_rows (AtkTable *table);
|
|
static G_CONST_RETURN gchar*
|
|
gail_clist_get_row_description (AtkTable *table,
|
|
gint row);
|
|
static AtkObject* gail_clist_get_row_header (AtkTable *table,
|
|
gint row);
|
|
static AtkObject* gail_clist_get_summary (AtkTable *table);
|
|
static gboolean gail_clist_add_row_selection (AtkTable *table,
|
|
gint row);
|
|
static gboolean gail_clist_remove_row_selection (AtkTable *table,
|
|
gint row);
|
|
static gint gail_clist_get_selected_rows (AtkTable *table,
|
|
gint **rows_selected);
|
|
static gboolean gail_clist_is_row_selected (AtkTable *table,
|
|
gint row);
|
|
static gboolean gail_clist_is_selected (AtkTable *table,
|
|
gint row,
|
|
gint column);
|
|
static void gail_clist_set_caption (AtkTable *table,
|
|
AtkObject *caption);
|
|
static void gail_clist_set_column_description(AtkTable *table,
|
|
gint column,
|
|
const gchar *description);
|
|
static void gail_clist_set_column_header (AtkTable *table,
|
|
gint column,
|
|
AtkObject *header);
|
|
static void gail_clist_set_row_description (AtkTable *table,
|
|
gint row,
|
|
const gchar *description);
|
|
static void gail_clist_set_row_header (AtkTable *table,
|
|
gint row,
|
|
AtkObject *header);
|
|
static void gail_clist_set_summary (AtkTable *table,
|
|
AtkObject *accessible);
|
|
|
|
/* gailcellparent.h */
|
|
|
|
static void gail_cell_parent_interface_init (GailCellParentIface *iface);
|
|
static void gail_clist_get_cell_extents (GailCellParent *parent,
|
|
GailCell *cell,
|
|
gint *x,
|
|
gint *y,
|
|
gint *width,
|
|
gint *height,
|
|
AtkCoordType coord_type);
|
|
|
|
static void gail_clist_get_cell_area (GailCellParent *parent,
|
|
GailCell *cell,
|
|
GdkRectangle *cell_rect);
|
|
|
|
static void gail_clist_select_row_gtk (GtkCList *clist,
|
|
int row,
|
|
int column,
|
|
GdkEvent *event,
|
|
gpointer data);
|
|
static void gail_clist_unselect_row_gtk (GtkCList *clist,
|
|
int row,
|
|
int column,
|
|
GdkEvent *event,
|
|
gpointer data);
|
|
static gint gail_clist_get_visible_column (AtkTable *table,
|
|
int column);
|
|
static gint gail_clist_get_actual_column (AtkTable *table,
|
|
int visible_column);
|
|
static void gail_clist_set_row_data (AtkTable *table,
|
|
gint row,
|
|
const gchar *description,
|
|
AtkObject *header,
|
|
gboolean is_header);
|
|
static GailCListRow*
|
|
gail_clist_get_row_data (AtkTable *table,
|
|
gint row);
|
|
static void gail_clist_get_visible_rect (GtkCList *clist,
|
|
GdkRectangle *clist_rect);
|
|
static gboolean gail_clist_is_cell_visible (GdkRectangle *cell_rect,
|
|
GdkRectangle *visible_rect);
|
|
static void gail_clist_cell_data_new (GailCList *clist,
|
|
GailCell *cell,
|
|
gint column,
|
|
gint row);
|
|
static void gail_clist_cell_destroyed (gpointer data);
|
|
static void gail_clist_cell_data_remove (GailCList *clist,
|
|
GailCell *cell);
|
|
static GailCell* gail_clist_find_cell (GailCList *clist,
|
|
gint index);
|
|
static void gail_clist_adjustment_changed (GtkAdjustment *adjustment,
|
|
GtkCList *clist);
|
|
|
|
struct _GailCListColumn
|
|
{
|
|
gchar *description;
|
|
AtkObject *header;
|
|
};
|
|
|
|
struct _GailCListRow
|
|
{
|
|
GtkCListRow *row_data;
|
|
int row_number;
|
|
gchar *description;
|
|
AtkObject *header;
|
|
};
|
|
|
|
struct _GailCListCellData
|
|
{
|
|
GtkCell *gtk_cell;
|
|
GailCell *gail_cell;
|
|
int row_number;
|
|
int column_number;
|
|
};
|
|
|
|
G_DEFINE_TYPE_WITH_CODE (GailCList, gail_clist, GAIL_TYPE_CONTAINER,
|
|
G_IMPLEMENT_INTERFACE (ATK_TYPE_TABLE, atk_table_interface_init)
|
|
G_IMPLEMENT_INTERFACE (ATK_TYPE_SELECTION, atk_selection_interface_init)
|
|
G_IMPLEMENT_INTERFACE (GAIL_TYPE_CELL_PARENT, gail_cell_parent_interface_init))
|
|
|
|
static void
|
|
gail_clist_class_init (GailCListClass *klass)
|
|
{
|
|
AtkObjectClass *class = ATK_OBJECT_CLASS (klass);
|
|
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
|
|
|
class->get_n_children = gail_clist_get_n_children;
|
|
class->ref_child = gail_clist_ref_child;
|
|
class->ref_state_set = gail_clist_ref_state_set;
|
|
class->initialize = gail_clist_real_initialize;
|
|
|
|
gobject_class->finalize = gail_clist_finalize;
|
|
}
|
|
|
|
static void
|
|
gail_clist_init (GailCList *clist)
|
|
{
|
|
}
|
|
|
|
static void
|
|
gail_clist_real_initialize (AtkObject *obj,
|
|
gpointer data)
|
|
{
|
|
GailCList *clist;
|
|
GtkCList *gtk_clist;
|
|
gint i;
|
|
|
|
ATK_OBJECT_CLASS (gail_clist_parent_class)->initialize (obj, data);
|
|
|
|
obj->role = ATK_ROLE_TABLE;
|
|
|
|
clist = GAIL_CLIST (obj);
|
|
|
|
clist->caption = NULL;
|
|
clist->summary = NULL;
|
|
clist->row_data = NULL;
|
|
clist->cell_data = NULL;
|
|
clist->previous_selected_cell = NULL;
|
|
|
|
gtk_clist = GTK_CLIST (data);
|
|
|
|
clist->n_cols = gtk_clist->columns;
|
|
clist->columns = g_new (GailCListColumn, gtk_clist->columns);
|
|
for (i = 0; i < gtk_clist->columns; i++)
|
|
{
|
|
clist->columns[i].description = NULL;
|
|
clist->columns[i].header = NULL;
|
|
}
|
|
/*
|
|
* Set up signal handlers for select-row and unselect-row
|
|
*/
|
|
g_signal_connect (gtk_clist,
|
|
"select-row",
|
|
G_CALLBACK (gail_clist_select_row_gtk),
|
|
obj);
|
|
g_signal_connect (gtk_clist,
|
|
"unselect-row",
|
|
G_CALLBACK (gail_clist_unselect_row_gtk),
|
|
obj);
|
|
/*
|
|
* Adjustment callbacks
|
|
*/
|
|
if (gtk_clist->hadjustment)
|
|
{
|
|
g_signal_connect (gtk_clist->hadjustment,
|
|
"value_changed",
|
|
G_CALLBACK (gail_clist_adjustment_changed),
|
|
gtk_clist);
|
|
}
|
|
if (gtk_clist->vadjustment)
|
|
{
|
|
g_signal_connect (gtk_clist->vadjustment,
|
|
"value_changed",
|
|
G_CALLBACK (gail_clist_adjustment_changed),
|
|
gtk_clist);
|
|
}
|
|
}
|
|
|
|
static void
|
|
gail_clist_finalize (GObject *object)
|
|
{
|
|
GailCList *clist = GAIL_CLIST (object);
|
|
gint i;
|
|
GArray *array;
|
|
|
|
if (clist->caption)
|
|
g_object_unref (clist->caption);
|
|
if (clist->summary)
|
|
g_object_unref (clist->summary);
|
|
|
|
for (i = 0; i < clist->n_cols; i++)
|
|
{
|
|
g_free (clist->columns[i].description);
|
|
if (clist->columns[i].header)
|
|
g_object_unref (clist->columns[i].header);
|
|
}
|
|
g_free (clist->columns);
|
|
|
|
array = clist->row_data;
|
|
|
|
if (clist->previous_selected_cell)
|
|
g_object_unref (clist->previous_selected_cell);
|
|
|
|
if (array)
|
|
{
|
|
for (i = 0; i < array->len; i++)
|
|
{
|
|
GailCListRow *row_data;
|
|
|
|
row_data = g_array_index (array, GailCListRow*, i);
|
|
|
|
if (row_data->header)
|
|
g_object_unref (row_data->header);
|
|
g_free (row_data->description);
|
|
}
|
|
}
|
|
|
|
if (clist->cell_data)
|
|
{
|
|
GList *temp_list;
|
|
|
|
for (temp_list = clist->cell_data; temp_list; temp_list = temp_list->next)
|
|
{
|
|
g_list_free (temp_list->data);
|
|
}
|
|
g_list_free (clist->cell_data);
|
|
}
|
|
|
|
G_OBJECT_CLASS (gail_clist_parent_class)->finalize (object);
|
|
}
|
|
|
|
static gint
|
|
gail_clist_get_n_children (AtkObject *obj)
|
|
{
|
|
GtkWidget *widget;
|
|
gint row, col;
|
|
|
|
g_return_val_if_fail (GAIL_IS_CLIST (obj), 0);
|
|
|
|
widget = GTK_ACCESSIBLE (obj)->widget;
|
|
if (widget == NULL)
|
|
/*
|
|
* State is defunct
|
|
*/
|
|
return 0;
|
|
|
|
row = gail_clist_get_n_rows (ATK_TABLE (obj));
|
|
col = gail_clist_get_n_actual_columns (GTK_CLIST (widget));
|
|
return (row * col);
|
|
}
|
|
|
|
static AtkObject*
|
|
gail_clist_ref_child (AtkObject *obj,
|
|
gint i)
|
|
{
|
|
GtkWidget *widget;
|
|
gint row, col;
|
|
gint n_columns;
|
|
|
|
g_return_val_if_fail (GAIL_IS_CLIST (obj), NULL);
|
|
g_return_val_if_fail (i >= 0, NULL);
|
|
|
|
widget = GTK_ACCESSIBLE (obj)->widget;
|
|
if (widget == NULL)
|
|
/*
|
|
* State is defunct
|
|
*/
|
|
return NULL;
|
|
|
|
n_columns = gail_clist_get_n_actual_columns (GTK_CLIST (widget));
|
|
if (!n_columns)
|
|
return NULL;
|
|
|
|
row = i / n_columns;
|
|
col = i % n_columns;
|
|
return gail_clist_ref_at_actual (ATK_TABLE (obj), row, col);
|
|
}
|
|
|
|
static AtkStateSet*
|
|
gail_clist_ref_state_set (AtkObject *obj)
|
|
{
|
|
AtkStateSet *state_set;
|
|
GtkWidget *widget;
|
|
|
|
state_set = ATK_OBJECT_CLASS (gail_clist_parent_class)->ref_state_set (obj);
|
|
widget = GTK_ACCESSIBLE (obj)->widget;
|
|
|
|
if (widget != NULL)
|
|
atk_state_set_add_state (state_set, ATK_STATE_MANAGES_DESCENDANTS);
|
|
|
|
return state_set;
|
|
}
|
|
|
|
static void
|
|
atk_selection_interface_init (AtkSelectionIface *iface)
|
|
{
|
|
iface->clear_selection = gail_clist_clear_selection;
|
|
iface->ref_selection = gail_clist_ref_selection;
|
|
iface->get_selection_count = gail_clist_get_selection_count;
|
|
iface->is_child_selected = gail_clist_is_child_selected;
|
|
iface->select_all_selection = gail_clist_select_all_selection;
|
|
}
|
|
|
|
static gboolean
|
|
gail_clist_clear_selection (AtkSelection *selection)
|
|
{
|
|
GtkCList *clist;
|
|
GtkWidget *widget;
|
|
|
|
widget = GTK_ACCESSIBLE (selection)->widget;
|
|
if (widget == NULL)
|
|
/* State is defunct */
|
|
return FALSE;
|
|
|
|
clist = GTK_CLIST (widget);
|
|
gtk_clist_unselect_all(clist);
|
|
return TRUE;
|
|
}
|
|
|
|
static AtkObject*
|
|
gail_clist_ref_selection (AtkSelection *selection,
|
|
gint i)
|
|
{
|
|
gint visible_columns;
|
|
gint selected_row;
|
|
gint selected_column;
|
|
gint *selected_rows;
|
|
|
|
if ( i < 0 && i >= gail_clist_get_selection_count (selection))
|
|
return NULL;
|
|
|
|
visible_columns = gail_clist_get_n_columns (ATK_TABLE (selection));
|
|
gail_clist_get_selected_rows (ATK_TABLE (selection), &selected_rows);
|
|
selected_row = selected_rows[i / visible_columns];
|
|
g_free (selected_rows);
|
|
selected_column = gail_clist_get_actual_column (ATK_TABLE (selection),
|
|
i % visible_columns);
|
|
|
|
return gail_clist_ref_at (ATK_TABLE (selection), selected_row,
|
|
selected_column);
|
|
}
|
|
|
|
static gint
|
|
gail_clist_get_selection_count (AtkSelection *selection)
|
|
{
|
|
gint n_rows_selected;
|
|
|
|
n_rows_selected = gail_clist_get_selected_rows (ATK_TABLE (selection), NULL);
|
|
|
|
if (n_rows_selected > 0)
|
|
/*
|
|
* The number of cells selected is the number of columns
|
|
* times the number of selected rows
|
|
*/
|
|
return gail_clist_get_n_columns (ATK_TABLE (selection)) * n_rows_selected;
|
|
return 0;
|
|
}
|
|
|
|
static gboolean
|
|
gail_clist_is_child_selected (AtkSelection *selection,
|
|
gint i)
|
|
{
|
|
gint row;
|
|
|
|
row = atk_table_get_row_at_index (ATK_TABLE (selection), i);
|
|
|
|
if (row == 0 && i >= gail_clist_get_n_columns (ATK_TABLE (selection)))
|
|
return FALSE;
|
|
return gail_clist_is_row_selected (ATK_TABLE (selection), row);
|
|
}
|
|
|
|
static gboolean
|
|
gail_clist_select_all_selection (AtkSelection *selection)
|
|
{
|
|
GtkCList *clist;
|
|
GtkWidget *widget;
|
|
/* GtkArg arg; */
|
|
|
|
widget = GTK_ACCESSIBLE (selection)->widget;
|
|
if (widget == NULL)
|
|
/* State is defunct */
|
|
return FALSE;
|
|
|
|
clist = GTK_CLIST (widget);
|
|
gtk_clist_select_all(clist);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static void
|
|
atk_table_interface_init (AtkTableIface *iface)
|
|
{
|
|
iface->ref_at = gail_clist_ref_at;
|
|
iface->get_index_at = gail_clist_get_index_at;
|
|
iface->get_column_at_index = gail_clist_get_column_at_index;
|
|
iface->get_row_at_index = gail_clist_get_row_at_index;
|
|
iface->get_caption = gail_clist_get_caption;
|
|
iface->get_n_columns = gail_clist_get_n_columns;
|
|
iface->get_column_description = gail_clist_get_column_description;
|
|
iface->get_column_header = gail_clist_get_column_header;
|
|
iface->get_n_rows = gail_clist_get_n_rows;
|
|
iface->get_row_description = gail_clist_get_row_description;
|
|
iface->get_row_header = gail_clist_get_row_header;
|
|
iface->get_summary = gail_clist_get_summary;
|
|
iface->add_row_selection = gail_clist_add_row_selection;
|
|
iface->remove_row_selection = gail_clist_remove_row_selection;
|
|
iface->get_selected_rows = gail_clist_get_selected_rows;
|
|
iface->is_row_selected = gail_clist_is_row_selected;
|
|
iface->is_selected = gail_clist_is_selected;
|
|
iface->set_caption = gail_clist_set_caption;
|
|
iface->set_column_description = gail_clist_set_column_description;
|
|
iface->set_column_header = gail_clist_set_column_header;
|
|
iface->set_row_description = gail_clist_set_row_description;
|
|
iface->set_row_header = gail_clist_set_row_header;
|
|
iface->set_summary = gail_clist_set_summary;
|
|
}
|
|
|
|
static AtkObject*
|
|
gail_clist_ref_at (AtkTable *table,
|
|
gint row,
|
|
gint column)
|
|
{
|
|
GtkWidget *widget;
|
|
gint actual_column;
|
|
|
|
widget = GTK_ACCESSIBLE (table)->widget;
|
|
if (widget == NULL)
|
|
/* State is defunct */
|
|
return NULL;
|
|
|
|
actual_column = gail_clist_get_actual_column (table, column);
|
|
return gail_clist_ref_at_actual (table, row, actual_column);
|
|
}
|
|
|
|
|
|
static AtkObject*
|
|
gail_clist_ref_at_actual (AtkTable *table,
|
|
gint row,
|
|
gint column)
|
|
{
|
|
/*
|
|
* The column number pased to this function is the actual column number
|
|
* whereas the column number passed to gail_clist_ref_at is the
|
|
* visible column number
|
|
*/
|
|
GtkCList *clist;
|
|
GtkWidget *widget;
|
|
GtkCellType cellType;
|
|
AtkObject *return_object;
|
|
gint n_rows, n_columns;
|
|
gint index;
|
|
GailCell *cell;
|
|
|
|
g_return_val_if_fail (GTK_IS_ACCESSIBLE (table), NULL);
|
|
|
|
widget = GTK_ACCESSIBLE (table)->widget;
|
|
if (widget == NULL)
|
|
/* State is defunct */
|
|
return NULL;
|
|
|
|
clist = GTK_CLIST (widget);
|
|
n_rows = gail_clist_get_n_rows (table);
|
|
n_columns = gail_clist_get_n_actual_columns (clist);
|
|
|
|
if (row < 0 || row >= n_rows)
|
|
return NULL;
|
|
if (column < 0 || column >= n_columns)
|
|
return NULL;
|
|
|
|
/*
|
|
* Check whether the child is cached
|
|
*/
|
|
index = column + row * n_columns;
|
|
cell = gail_clist_find_cell (GAIL_CLIST (table), index);
|
|
if (cell)
|
|
{
|
|
g_object_ref (cell);
|
|
return ATK_OBJECT (cell);
|
|
}
|
|
cellType = gtk_clist_get_cell_type(clist, row, column);
|
|
switch (cellType)
|
|
{
|
|
case GTK_CELL_TEXT:
|
|
case GTK_CELL_PIXTEXT:
|
|
return_object = gail_clist_cell_new ();
|
|
break;
|
|
case GTK_CELL_PIXMAP:
|
|
return_object = NULL;
|
|
break;
|
|
default:
|
|
/* Don't handle GTK_CELL_EMPTY or GTK_CELL_WIDGET, return NULL */
|
|
return_object = NULL;
|
|
break;
|
|
}
|
|
if (return_object)
|
|
{
|
|
cell = GAIL_CELL (return_object);
|
|
|
|
g_return_val_if_fail (ATK_IS_OBJECT (table), NULL);
|
|
|
|
gail_cell_initialise (cell, widget, ATK_OBJECT (table),
|
|
index);
|
|
/*
|
|
* Store the cell in a cache
|
|
*/
|
|
gail_clist_cell_data_new (GAIL_CLIST (table), cell, column, row);
|
|
/*
|
|
* If the column is visible, sets the cell's state
|
|
*/
|
|
if (clist->column[column].visible)
|
|
{
|
|
GdkRectangle cell_rect, visible_rect;
|
|
|
|
gail_clist_get_cell_area (GAIL_CELL_PARENT (table), cell, &cell_rect);
|
|
gail_clist_get_visible_rect (clist, &visible_rect);
|
|
gail_cell_add_state (cell, ATK_STATE_VISIBLE, FALSE);
|
|
if (gail_clist_is_cell_visible (&cell_rect, &visible_rect))
|
|
gail_cell_add_state (cell, ATK_STATE_SHOWING, FALSE);
|
|
}
|
|
/*
|
|
* If a row is selected, all cells in the row are selected
|
|
*/
|
|
if (gail_clist_is_row_selected (table, row))
|
|
{
|
|
gail_cell_add_state (cell, ATK_STATE_SELECTED, FALSE);
|
|
if (clist->columns == 1)
|
|
gail_cell_add_state (cell, ATK_STATE_FOCUSED, FALSE);
|
|
}
|
|
}
|
|
|
|
return return_object;
|
|
}
|
|
|
|
static gint
|
|
gail_clist_get_index_at (AtkTable *table,
|
|
gint row,
|
|
gint column)
|
|
{
|
|
gint n_cols, n_rows;
|
|
|
|
n_cols = atk_table_get_n_columns (table);
|
|
n_rows = atk_table_get_n_rows (table);
|
|
|
|
g_return_val_if_fail (row < n_rows, 0);
|
|
g_return_val_if_fail (column < n_cols, 0);
|
|
|
|
return row * n_cols + column;
|
|
}
|
|
|
|
static gint
|
|
gail_clist_get_column_at_index (AtkTable *table,
|
|
gint index)
|
|
{
|
|
gint n_cols;
|
|
|
|
n_cols = atk_table_get_n_columns (table);
|
|
|
|
if (n_cols == 0)
|
|
return 0;
|
|
else
|
|
return (gint) (index % n_cols);
|
|
}
|
|
|
|
static gint
|
|
gail_clist_get_row_at_index (AtkTable *table,
|
|
gint index)
|
|
{
|
|
gint n_cols;
|
|
|
|
n_cols = atk_table_get_n_columns (table);
|
|
|
|
if (n_cols == 0)
|
|
return 0;
|
|
else
|
|
return (gint) (index / n_cols);
|
|
}
|
|
|
|
static AtkObject*
|
|
gail_clist_get_caption (AtkTable *table)
|
|
{
|
|
GailCList* obj = GAIL_CLIST (table);
|
|
|
|
return obj->caption;
|
|
}
|
|
|
|
static gint
|
|
gail_clist_get_n_columns (AtkTable *table)
|
|
{
|
|
GtkWidget *widget;
|
|
GtkCList *clist;
|
|
|
|
widget = GTK_ACCESSIBLE (table)->widget;
|
|
if (widget == NULL)
|
|
/* State is defunct */
|
|
return 0;
|
|
|
|
clist = GTK_CLIST (widget);
|
|
|
|
return gail_clist_get_visible_column (table,
|
|
gail_clist_get_n_actual_columns (clist));
|
|
}
|
|
|
|
static gint
|
|
gail_clist_get_n_actual_columns (GtkCList *clist)
|
|
{
|
|
return clist->columns;
|
|
}
|
|
|
|
static G_CONST_RETURN gchar*
|
|
gail_clist_get_column_description (AtkTable *table,
|
|
gint column)
|
|
{
|
|
GailCList *clist = GAIL_CLIST (table);
|
|
GtkWidget *widget;
|
|
gint actual_column;
|
|
|
|
if (column < 0 || column >= gail_clist_get_n_columns (table))
|
|
return NULL;
|
|
|
|
actual_column = gail_clist_get_actual_column (table, column);
|
|
if (clist->columns[actual_column].description)
|
|
return (clist->columns[actual_column].description);
|
|
|
|
widget = GTK_ACCESSIBLE (clist)->widget;
|
|
if (widget == NULL)
|
|
return NULL;
|
|
|
|
return gtk_clist_get_column_title (GTK_CLIST (widget), actual_column);
|
|
}
|
|
|
|
static AtkObject*
|
|
gail_clist_get_column_header (AtkTable *table,
|
|
gint column)
|
|
{
|
|
GailCList *clist = GAIL_CLIST (table);
|
|
GtkWidget *widget;
|
|
GtkWidget *return_widget;
|
|
gint actual_column;
|
|
|
|
if (column < 0 || column >= gail_clist_get_n_columns (table))
|
|
return NULL;
|
|
|
|
actual_column = gail_clist_get_actual_column (table, column);
|
|
|
|
if (clist->columns[actual_column].header)
|
|
return (clist->columns[actual_column].header);
|
|
|
|
widget = GTK_ACCESSIBLE (clist)->widget;
|
|
if (widget == NULL)
|
|
return NULL;
|
|
|
|
return_widget = gtk_clist_get_column_widget (GTK_CLIST (widget),
|
|
actual_column);
|
|
if (return_widget == NULL)
|
|
return NULL;
|
|
|
|
g_return_val_if_fail (GTK_IS_BIN (return_widget), NULL);
|
|
return_widget = gtk_bin_get_child (GTK_BIN(return_widget));
|
|
|
|
return gtk_widget_get_accessible (return_widget);
|
|
}
|
|
|
|
static gint
|
|
gail_clist_get_n_rows (AtkTable *table)
|
|
{
|
|
GtkWidget *widget;
|
|
GtkCList *clist;
|
|
|
|
widget = GTK_ACCESSIBLE (table)->widget;
|
|
if (widget == NULL)
|
|
/* State is defunct */
|
|
return 0;
|
|
|
|
clist = GTK_CLIST (widget);
|
|
return clist->rows;
|
|
}
|
|
|
|
static G_CONST_RETURN gchar*
|
|
gail_clist_get_row_description (AtkTable *table,
|
|
gint row)
|
|
{
|
|
GailCListRow* row_data;
|
|
|
|
row_data = gail_clist_get_row_data (table, row);
|
|
if (row_data == NULL)
|
|
return NULL;
|
|
return row_data->description;
|
|
}
|
|
|
|
static AtkObject*
|
|
gail_clist_get_row_header (AtkTable *table,
|
|
gint row)
|
|
{
|
|
GailCListRow* row_data;
|
|
|
|
row_data = gail_clist_get_row_data (table, row);
|
|
if (row_data == NULL)
|
|
return NULL;
|
|
return row_data->header;
|
|
}
|
|
|
|
static AtkObject*
|
|
gail_clist_get_summary (AtkTable *table)
|
|
{
|
|
GailCList* obj = GAIL_CLIST (table);
|
|
|
|
return obj->summary;
|
|
}
|
|
|
|
static gboolean
|
|
gail_clist_add_row_selection (AtkTable *table,
|
|
gint row)
|
|
{
|
|
GtkWidget *widget;
|
|
GtkCList *clist;
|
|
|
|
widget = GTK_ACCESSIBLE (table)->widget;
|
|
if (widget == NULL)
|
|
/* State is defunct */
|
|
return 0;
|
|
|
|
clist = GTK_CLIST (widget);
|
|
gtk_clist_select_row (clist, row, -1);
|
|
if (gail_clist_is_row_selected (table, row))
|
|
return TRUE;
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
static gboolean
|
|
gail_clist_remove_row_selection (AtkTable *table,
|
|
gint row)
|
|
{
|
|
GtkWidget *widget;
|
|
GtkCList *clist;
|
|
|
|
widget = GTK_ACCESSIBLE (table)->widget;
|
|
if (widget == NULL)
|
|
/* State is defunct */
|
|
return 0;
|
|
|
|
clist = GTK_CLIST (widget);
|
|
if (gail_clist_is_row_selected (table, row))
|
|
{
|
|
gtk_clist_select_row (clist, row, -1);
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
static gint
|
|
gail_clist_get_selected_rows (AtkTable *table,
|
|
gint **rows_selected)
|
|
{
|
|
GtkWidget *widget;
|
|
GtkCList *clist;
|
|
GList *list;
|
|
gint n_selected;
|
|
gint i;
|
|
|
|
widget = GTK_ACCESSIBLE (table)->widget;
|
|
if (widget == NULL)
|
|
/* State is defunct */
|
|
return 0;
|
|
|
|
clist = GTK_CLIST (widget);
|
|
|
|
n_selected = g_list_length (clist->selection);
|
|
|
|
if (n_selected == 0)
|
|
return 0;
|
|
|
|
if (rows_selected)
|
|
{
|
|
gint *selected_rows;
|
|
|
|
selected_rows = (gint*) g_malloc (sizeof (gint) * n_selected);
|
|
list = clist->selection;
|
|
|
|
i = 0;
|
|
while (list)
|
|
{
|
|
selected_rows[i++] = GPOINTER_TO_INT (list->data);
|
|
list = list->next;
|
|
}
|
|
*rows_selected = selected_rows;
|
|
}
|
|
return n_selected;
|
|
}
|
|
|
|
static gboolean
|
|
gail_clist_is_row_selected (AtkTable *table,
|
|
gint row)
|
|
{
|
|
GList *elem;
|
|
GtkWidget *widget;
|
|
GtkCList *clist;
|
|
GtkCListRow *clist_row;
|
|
|
|
widget = GTK_ACCESSIBLE (table)->widget;
|
|
if (widget == NULL)
|
|
/* State is defunct */
|
|
return FALSE;
|
|
|
|
clist = GTK_CLIST (widget);
|
|
|
|
if (row < 0 || row >= clist->rows)
|
|
return FALSE;
|
|
|
|
elem = ROW_ELEMENT (clist, row);
|
|
if (!elem)
|
|
return FALSE;
|
|
clist_row = elem->data;
|
|
|
|
return (clist_row->state == GTK_STATE_SELECTED);
|
|
}
|
|
|
|
static gboolean
|
|
gail_clist_is_selected (AtkTable *table,
|
|
gint row,
|
|
gint column)
|
|
{
|
|
return gail_clist_is_row_selected (table, row);
|
|
}
|
|
|
|
static void
|
|
gail_clist_set_caption (AtkTable *table,
|
|
AtkObject *caption)
|
|
{
|
|
GailCList* obj = GAIL_CLIST (table);
|
|
AtkPropertyValues values = { NULL };
|
|
AtkObject *old_caption;
|
|
|
|
old_caption = obj->caption;
|
|
obj->caption = caption;
|
|
if (obj->caption)
|
|
g_object_ref (obj->caption);
|
|
|
|
g_value_init (&values.old_value, G_TYPE_POINTER);
|
|
g_value_set_pointer (&values.old_value, old_caption);
|
|
g_value_init (&values.new_value, G_TYPE_POINTER);
|
|
g_value_set_pointer (&values.new_value, obj->caption);
|
|
|
|
values.property_name = "accessible-table-caption";
|
|
g_signal_emit_by_name (table,
|
|
"property_change::accessible-table-caption",
|
|
&values, NULL);
|
|
if (old_caption)
|
|
g_object_unref (old_caption);
|
|
}
|
|
|
|
static void
|
|
gail_clist_set_column_description (AtkTable *table,
|
|
gint column,
|
|
const gchar *description)
|
|
{
|
|
GailCList *clist = GAIL_CLIST (table);
|
|
AtkPropertyValues values = { NULL };
|
|
gint actual_column;
|
|
|
|
if (column < 0 || column >= gail_clist_get_n_columns (table))
|
|
return;
|
|
|
|
if (description == NULL)
|
|
return;
|
|
|
|
actual_column = gail_clist_get_actual_column (table, column);
|
|
g_free (clist->columns[actual_column].description);
|
|
clist->columns[actual_column].description = g_strdup (description);
|
|
|
|
g_value_init (&values.new_value, G_TYPE_INT);
|
|
g_value_set_int (&values.new_value, column);
|
|
|
|
values.property_name = "accessible-table-column-description";
|
|
g_signal_emit_by_name (table,
|
|
"property_change::accessible-table-column-description",
|
|
&values, NULL);
|
|
|
|
}
|
|
|
|
static void
|
|
gail_clist_set_column_header (AtkTable *table,
|
|
gint column,
|
|
AtkObject *header)
|
|
{
|
|
GailCList *clist = GAIL_CLIST (table);
|
|
AtkPropertyValues values = { NULL };
|
|
gint actual_column;
|
|
|
|
if (column < 0 || column >= gail_clist_get_n_columns (table))
|
|
return;
|
|
|
|
actual_column = gail_clist_get_actual_column (table, column);
|
|
if (clist->columns[actual_column].header)
|
|
g_object_unref (clist->columns[actual_column].header);
|
|
if (header)
|
|
g_object_ref (header);
|
|
clist->columns[actual_column].header = header;
|
|
|
|
g_value_init (&values.new_value, G_TYPE_INT);
|
|
g_value_set_int (&values.new_value, column);
|
|
|
|
values.property_name = "accessible-table-column-header";
|
|
g_signal_emit_by_name (table,
|
|
"property_change::accessible-table-column-header",
|
|
&values, NULL);
|
|
}
|
|
|
|
static void
|
|
gail_clist_set_row_description (AtkTable *table,
|
|
gint row,
|
|
const gchar *description)
|
|
{
|
|
gail_clist_set_row_data (table, row, description, NULL, FALSE);
|
|
}
|
|
|
|
static void
|
|
gail_clist_set_row_header (AtkTable *table,
|
|
gint row,
|
|
AtkObject *header)
|
|
{
|
|
gail_clist_set_row_data (table, row, NULL, header, TRUE);
|
|
}
|
|
|
|
static void
|
|
gail_clist_set_summary (AtkTable *table,
|
|
AtkObject *accessible)
|
|
{
|
|
GailCList* obj = GAIL_CLIST (table);
|
|
AtkPropertyValues values = { 0, };
|
|
AtkObject *old_summary;
|
|
|
|
old_summary = obj->summary;
|
|
obj->summary = accessible;
|
|
if (obj->summary)
|
|
g_object_ref (obj->summary);
|
|
|
|
g_value_init (&values.old_value, G_TYPE_POINTER);
|
|
g_value_set_pointer (&values.old_value, old_summary);
|
|
g_value_init (&values.new_value, G_TYPE_POINTER);
|
|
g_value_set_pointer (&values.new_value, obj->summary);
|
|
|
|
values.property_name = "accessible-table-summary";
|
|
g_signal_emit_by_name (table,
|
|
"property_change::accessible-table-summary",
|
|
&values, NULL);
|
|
if (old_summary)
|
|
g_object_unref (old_summary);
|
|
}
|
|
|
|
|
|
static void gail_cell_parent_interface_init (GailCellParentIface *iface)
|
|
{
|
|
iface->get_cell_extents = gail_clist_get_cell_extents;
|
|
iface->get_cell_area = gail_clist_get_cell_area;
|
|
}
|
|
|
|
static void
|
|
gail_clist_get_cell_extents (GailCellParent *parent,
|
|
GailCell *cell,
|
|
gint *x,
|
|
gint *y,
|
|
gint *width,
|
|
gint *height,
|
|
AtkCoordType coord_type)
|
|
{
|
|
GtkWidget* widget;
|
|
GtkCList *clist;
|
|
gint widget_x, widget_y, widget_width, widget_height;
|
|
GdkRectangle cell_rect;
|
|
GdkRectangle visible_rect;
|
|
|
|
widget = GTK_ACCESSIBLE (parent)->widget;
|
|
if (widget == NULL)
|
|
return;
|
|
clist = GTK_CLIST (widget);
|
|
|
|
atk_component_get_extents (ATK_COMPONENT (parent), &widget_x, &widget_y,
|
|
&widget_width, &widget_height,
|
|
coord_type);
|
|
|
|
gail_clist_get_cell_area (parent, cell, &cell_rect);
|
|
*width = cell_rect.width;
|
|
*height = cell_rect.height;
|
|
gail_clist_get_visible_rect (clist, &visible_rect);
|
|
if (gail_clist_is_cell_visible (&cell_rect, &visible_rect))
|
|
{
|
|
*x = cell_rect.x + widget_x;
|
|
*y = cell_rect.y + widget_y;
|
|
}
|
|
else
|
|
{
|
|
*x = G_MININT;
|
|
*y = G_MININT;
|
|
}
|
|
}
|
|
|
|
static void
|
|
gail_clist_get_cell_area (GailCellParent *parent,
|
|
GailCell *cell,
|
|
GdkRectangle *cell_rect)
|
|
{
|
|
GtkWidget* widget;
|
|
GtkCList *clist;
|
|
gint column, row, n_columns;
|
|
|
|
widget = GTK_ACCESSIBLE (parent)->widget;
|
|
if (widget == NULL)
|
|
return;
|
|
clist = GTK_CLIST (widget);
|
|
|
|
n_columns = gail_clist_get_n_actual_columns (clist);
|
|
g_return_if_fail (n_columns > 0);
|
|
column = cell->index % n_columns;
|
|
row = cell->index / n_columns;
|
|
cell_rect->x = COLUMN_LEFT (clist, column);
|
|
cell_rect->y = ROW_TOP (clist, row);
|
|
cell_rect->width = clist->column[column].area.width;
|
|
cell_rect->height = clist->row_height;
|
|
}
|
|
|
|
static void
|
|
gail_clist_select_row_gtk (GtkCList *clist,
|
|
gint row,
|
|
gint column,
|
|
GdkEvent *event,
|
|
gpointer data)
|
|
{
|
|
GailCList *gail_clist;
|
|
GList *temp_list;
|
|
AtkObject *selected_cell;
|
|
|
|
gail_clist = GAIL_CLIST (data);
|
|
|
|
for (temp_list = gail_clist->cell_data; temp_list; temp_list = temp_list->next)
|
|
{
|
|
GailCListCellData *cell_data;
|
|
|
|
cell_data = (GailCListCellData *) (temp_list->data);
|
|
|
|
if (row == cell_data->row_number)
|
|
{
|
|
/*
|
|
* Row is selected
|
|
*/
|
|
gail_cell_add_state (cell_data->gail_cell, ATK_STATE_SELECTED, TRUE);
|
|
}
|
|
}
|
|
if (clist->columns == 1)
|
|
{
|
|
selected_cell = gail_clist_ref_at (ATK_TABLE (data), row, 1);
|
|
if (selected_cell)
|
|
{
|
|
if (gail_clist->previous_selected_cell)
|
|
g_object_unref (gail_clist->previous_selected_cell);
|
|
gail_clist->previous_selected_cell = selected_cell;
|
|
gail_cell_add_state (GAIL_CELL (selected_cell), ATK_STATE_FOCUSED, FALSE);
|
|
g_signal_emit_by_name (gail_clist,
|
|
"active-descendant-changed",
|
|
selected_cell);
|
|
}
|
|
}
|
|
|
|
g_signal_emit_by_name (gail_clist, "selection_changed");
|
|
}
|
|
|
|
static void
|
|
gail_clist_unselect_row_gtk (GtkCList *clist,
|
|
gint row,
|
|
gint column,
|
|
GdkEvent *event,
|
|
gpointer data)
|
|
{
|
|
GailCList *gail_clist;
|
|
GList *temp_list;
|
|
|
|
gail_clist = GAIL_CLIST (data);
|
|
|
|
for (temp_list = gail_clist->cell_data; temp_list; temp_list = temp_list->next)
|
|
{
|
|
GailCListCellData *cell_data;
|
|
|
|
cell_data = (GailCListCellData *) (temp_list->data);
|
|
|
|
if (row == cell_data->row_number)
|
|
{
|
|
/*
|
|
* Row is unselected
|
|
*/
|
|
gail_cell_add_state (cell_data->gail_cell, ATK_STATE_FOCUSED, FALSE);
|
|
gail_cell_remove_state (cell_data->gail_cell, ATK_STATE_SELECTED, TRUE);
|
|
}
|
|
}
|
|
|
|
g_signal_emit_by_name (gail_clist, "selection_changed");
|
|
}
|
|
|
|
/*
|
|
* This function determines the number of visible columns
|
|
* up to and including the specified column
|
|
*/
|
|
static gint
|
|
gail_clist_get_visible_column (AtkTable *table,
|
|
int column)
|
|
{
|
|
GtkWidget *widget;
|
|
GtkCList *clist;
|
|
gint i;
|
|
gint vis_columns;
|
|
|
|
widget = GTK_ACCESSIBLE (table)->widget;
|
|
if (widget == NULL)
|
|
/* State is defunct */
|
|
return 0;
|
|
|
|
clist = GTK_CLIST (widget);
|
|
for (i = 0, vis_columns = 0; i < column; i++)
|
|
if (clist->column[i].visible)
|
|
vis_columns++;
|
|
|
|
return vis_columns;
|
|
}
|
|
|
|
static gint
|
|
gail_clist_get_actual_column (AtkTable *table,
|
|
int visible_column)
|
|
{
|
|
GtkWidget *widget;
|
|
GtkCList *clist;
|
|
gint i;
|
|
gint vis_columns;
|
|
|
|
widget = GTK_ACCESSIBLE (table)->widget;
|
|
if (widget == NULL)
|
|
/* State is defunct */
|
|
return 0;
|
|
|
|
clist = GTK_CLIST (widget);
|
|
for (i = 0, vis_columns = 0; i < clist->columns; i++)
|
|
{
|
|
if (clist->column[i].visible)
|
|
{
|
|
if (visible_column == vis_columns)
|
|
return i;
|
|
vis_columns++;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static void
|
|
gail_clist_set_row_data (AtkTable *table,
|
|
gint row,
|
|
const gchar *description,
|
|
AtkObject *header,
|
|
gboolean is_header)
|
|
{
|
|
GtkWidget *widget;
|
|
GtkCList *gtk_clist;
|
|
GailCList *gail_clist;
|
|
GArray *array;
|
|
GailCListRow* row_data;
|
|
gint i;
|
|
gboolean found = FALSE;
|
|
AtkPropertyValues values = { NULL };
|
|
gchar *signal_name;
|
|
|
|
widget = GTK_ACCESSIBLE (table)->widget;
|
|
if (widget == NULL)
|
|
/* State is defunct */
|
|
return;
|
|
|
|
gtk_clist = GTK_CLIST (widget);
|
|
if (row < 0 || row >= gtk_clist->rows)
|
|
return;
|
|
|
|
gail_clist = GAIL_CLIST (table);
|
|
|
|
if (gail_clist->row_data == NULL)
|
|
gail_clist->row_data = g_array_sized_new (FALSE, TRUE,
|
|
sizeof (GailCListRow *), 0);
|
|
|
|
array = gail_clist->row_data;
|
|
|
|
for (i = 0; i < array->len; i++)
|
|
{
|
|
row_data = g_array_index (array, GailCListRow*, i);
|
|
|
|
if (row == row_data->row_number)
|
|
{
|
|
found = TRUE;
|
|
if (is_header)
|
|
{
|
|
if (row_data->header)
|
|
g_object_unref (row_data->header);
|
|
row_data->header = header;
|
|
if (row_data->header)
|
|
g_object_ref (row_data->header);
|
|
}
|
|
else
|
|
{
|
|
g_free (row_data->description);
|
|
row_data->description = g_strdup (row_data->description);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
if (!found)
|
|
{
|
|
GList *elem;
|
|
|
|
elem = ROW_ELEMENT (gtk_clist, row);
|
|
g_return_if_fail (elem != NULL);
|
|
|
|
row_data = g_new (GailCListRow, 1);
|
|
row_data->row_number = row;
|
|
row_data->row_data = elem->data;
|
|
if (is_header)
|
|
{
|
|
row_data->header = header;
|
|
if (row_data->header)
|
|
g_object_ref (row_data->header);
|
|
row_data->description = NULL;
|
|
}
|
|
else
|
|
{
|
|
row_data->description = g_strdup (row_data->description);
|
|
row_data->header = NULL;
|
|
}
|
|
g_array_append_val (array, row_data);
|
|
}
|
|
|
|
g_value_init (&values.new_value, G_TYPE_INT);
|
|
g_value_set_int (&values.new_value, row);
|
|
|
|
if (is_header)
|
|
{
|
|
values.property_name = "accessible-table-row-header";
|
|
signal_name = "property_change::accessible-table-row-header";
|
|
}
|
|
else
|
|
{
|
|
values.property_name = "accessible-table-row-description";
|
|
signal_name = "property_change::accessible-table-row-description";
|
|
}
|
|
g_signal_emit_by_name (table,
|
|
signal_name,
|
|
&values, NULL);
|
|
|
|
}
|
|
|
|
static GailCListRow*
|
|
gail_clist_get_row_data (AtkTable *table,
|
|
gint row)
|
|
{
|
|
GtkWidget *widget;
|
|
GtkCList *clist;
|
|
GailCList *obj;
|
|
GArray *array;
|
|
GailCListRow* row_data;
|
|
gint i;
|
|
|
|
widget = GTK_ACCESSIBLE (table)->widget;
|
|
if (widget == NULL)
|
|
/* State is defunct */
|
|
return NULL;
|
|
|
|
clist = GTK_CLIST (widget);
|
|
if (row < 0 || row >= clist->rows)
|
|
return NULL;
|
|
|
|
obj = GAIL_CLIST (table);
|
|
|
|
if (obj->row_data == NULL)
|
|
return NULL;
|
|
|
|
array = obj->row_data;
|
|
|
|
for (i = 0; i < array->len; i++)
|
|
{
|
|
row_data = g_array_index (array, GailCListRow*, i);
|
|
|
|
if (row == row_data->row_number)
|
|
return row_data;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
static void
|
|
gail_clist_get_visible_rect (GtkCList *clist,
|
|
GdkRectangle *clist_rect)
|
|
{
|
|
clist_rect->x = - clist->hoffset;
|
|
clist_rect->y = - clist->voffset;
|
|
clist_rect->width = clist->clist_window_width;
|
|
clist_rect->height = clist->clist_window_height;
|
|
}
|
|
|
|
static gboolean
|
|
gail_clist_is_cell_visible (GdkRectangle *cell_rect,
|
|
GdkRectangle *visible_rect)
|
|
{
|
|
/*
|
|
* A cell is reported as visible if any part of the cell is visible
|
|
*/
|
|
if (((cell_rect->x + cell_rect->width) < visible_rect->x) ||
|
|
((cell_rect->y + cell_rect->height) < visible_rect->y) ||
|
|
(cell_rect->x > (visible_rect->x + visible_rect->width)) ||
|
|
(cell_rect->y > (visible_rect->y + visible_rect->height)))
|
|
return FALSE;
|
|
else
|
|
return TRUE;
|
|
}
|
|
|
|
static void
|
|
gail_clist_cell_data_new (GailCList *clist,
|
|
GailCell *cell,
|
|
gint column,
|
|
gint row)
|
|
{
|
|
GList *elem;
|
|
GailCListCellData *cell_data;
|
|
GtkCList *gtk_clist;
|
|
GtkCListRow *clist_row;
|
|
|
|
gtk_clist = GTK_CLIST (GTK_ACCESSIBLE (clist)->widget);
|
|
elem = g_list_nth (gtk_clist->row_list, row);
|
|
g_return_if_fail (elem != NULL);
|
|
clist_row = (GtkCListRow *) elem->data;
|
|
cell_data = g_new (GailCListCellData, 1);
|
|
cell_data->gail_cell = cell;
|
|
cell_data->gtk_cell = &(clist_row->cell[column]);
|
|
cell_data->column_number = column;
|
|
cell_data->row_number = row;
|
|
clist->cell_data = g_list_append (clist->cell_data, cell_data);
|
|
|
|
g_object_weak_ref (G_OBJECT (cell),
|
|
(GWeakNotify) gail_clist_cell_destroyed,
|
|
cell);
|
|
}
|
|
|
|
static void
|
|
gail_clist_cell_destroyed (gpointer data)
|
|
{
|
|
GailCell *cell = GAIL_CELL (data);
|
|
AtkObject* parent;
|
|
|
|
parent = atk_object_get_parent (ATK_OBJECT (cell));
|
|
|
|
gail_clist_cell_data_remove (GAIL_CLIST (parent), cell);
|
|
}
|
|
|
|
static void
|
|
gail_clist_cell_data_remove (GailCList *clist,
|
|
GailCell *cell)
|
|
{
|
|
GList *temp_list;
|
|
|
|
for (temp_list = clist->cell_data; temp_list; temp_list = temp_list->next)
|
|
{
|
|
GailCListCellData *cell_data;
|
|
|
|
cell_data = (GailCListCellData *) temp_list->data;
|
|
if (cell_data->gail_cell == cell)
|
|
{
|
|
clist->cell_data = g_list_remove_link (clist->cell_data, temp_list);
|
|
g_free (cell_data);
|
|
return;
|
|
}
|
|
}
|
|
g_warning ("No cell removed in gail_clist_cell_data_remove\n");
|
|
}
|
|
|
|
static GailCell*
|
|
gail_clist_find_cell (GailCList *clist,
|
|
gint index)
|
|
{
|
|
GList *temp_list;
|
|
gint n_cols;
|
|
|
|
n_cols = clist->n_cols;
|
|
|
|
for (temp_list = clist->cell_data; temp_list; temp_list = temp_list->next)
|
|
{
|
|
GailCListCellData *cell_data;
|
|
gint real_index;
|
|
|
|
cell_data = (GailCListCellData *) (temp_list->data);
|
|
|
|
real_index = cell_data->column_number + n_cols * cell_data->row_number;
|
|
if (real_index == index)
|
|
return cell_data->gail_cell;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
static void
|
|
gail_clist_adjustment_changed (GtkAdjustment *adjustment,
|
|
GtkCList *clist)
|
|
{
|
|
AtkObject *atk_obj;
|
|
GdkRectangle visible_rect;
|
|
GdkRectangle cell_rect;
|
|
GailCList* obj;
|
|
GList *temp_list;
|
|
|
|
/*
|
|
* The scrollbars have changed
|
|
*/
|
|
atk_obj = gtk_widget_get_accessible (GTK_WIDGET (clist));
|
|
obj = GAIL_CLIST (atk_obj);
|
|
|
|
/* Get the currently visible area */
|
|
gail_clist_get_visible_rect (clist, &visible_rect);
|
|
|
|
/* loop over the cells and report if they are visible or not. */
|
|
/* Must loop through them all */
|
|
for (temp_list = obj->cell_data; temp_list; temp_list = temp_list->next)
|
|
{
|
|
GailCell *cell;
|
|
GailCListCellData *cell_data;
|
|
|
|
cell_data = (GailCListCellData *) (temp_list->data);
|
|
cell = cell_data->gail_cell;
|
|
|
|
gail_clist_get_cell_area (GAIL_CELL_PARENT (atk_obj),
|
|
cell, &cell_rect);
|
|
if (gail_clist_is_cell_visible (&cell_rect, &visible_rect))
|
|
gail_cell_add_state (cell, ATK_STATE_SHOWING, TRUE);
|
|
else
|
|
gail_cell_remove_state (cell, ATK_STATE_SHOWING, TRUE);
|
|
}
|
|
g_signal_emit_by_name (atk_obj, "visible_data_changed");
|
|
}
|
|
|