/* ATK -  Accessibility Toolkit
 * 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 "atktable.h"
#include "atkmarshal.h"

/**
 * SECTION:atktable
 * @Short_description: The ATK interface implemented for UI components
 *  which contain tabular or row/column information.
 * @Title:AtkTable
 *
 * #AtkTable should be implemented by components which present
 * elements ordered via rows and columns.  It may also be used to
 * present tree-structured information if the nodes of the trees can
 * be said to contain multiple "columns".  Individual elements of an
 * #AtkTable are typically referred to as "cells". Those cells should
 * implement the interface #AtkTableCell, but #Atk doesn't require
 * them to be direct children of the current #AtkTable. They can be
 * grand-children, grand-grand-children etc. #AtkTable provides the
 * API needed to get a individual cell based on the row and column
 * numbers.
 *
 * Children of #AtkTable are frequently "lightweight" objects, that
 * is, they may not have backing widgets in the host UI toolkit.  They
 * are therefore often transient.
 *
 * Since tables are often very complex, #AtkTable includes provision
 * for offering simplified summary information, as well as row and
 * column headers and captions.  Headers and captions are #AtkObjects
 * which may implement other interfaces (#AtkText, #AtkImage, etc.) as
 * appropriate.  #AtkTable summaries may themselves be (simplified)
 * #AtkTables, etc.
 *
 * Note for implementors: in the past, #AtkTable required that all the
 * cells should be direct children of #AtkTable, and provided some
 * index based methods to request the cells. The practice showed that
 * that forcing made #AtkTable implementation complex, and hard to
 * expose other kind of children, like rows or captions. Right now,
 * index-based methods are deprecated.
 */

enum {
  ROW_INSERTED,
  ROW_DELETED,
  COLUMN_INSERTED,
  COLUMN_DELETED,
  ROW_REORDERED,
  COLUMN_REORDERED,
  MODEL_CHANGED,
  LAST_SIGNAL
};

static void  atk_table_base_init (gpointer *g_class);

static guint atk_table_signals[LAST_SIGNAL] = { 0 };

GType
atk_table_get_type (void)
{
  static GType type = 0;
  
  if (!type) {
    GTypeInfo tinfo =
    {
      sizeof (AtkTableIface),
      (GBaseInitFunc) atk_table_base_init,
      (GBaseFinalizeFunc) NULL,
      
    };
    
    type = g_type_register_static (G_TYPE_INTERFACE, "AtkTable", &tinfo, 0);
  }
  
  return type;
}


static void
atk_table_base_init (gpointer *g_class)
{
  static gboolean initialized = FALSE;
  
  if (!initialized)
    {
      /**
       * AtkTable::row-inserted:
       * @atktable: the object which received the signal.
       * @arg1: The index of the first row inserted.
       * @arg2: The number of rows inserted.
       *
       * The "row-inserted" signal is emitted by an object which
       * implements the AtkTable interface when a row is inserted.
       */
      atk_table_signals[ROW_INSERTED] =
	g_signal_new ("row_inserted",
		      ATK_TYPE_TABLE,
		      G_SIGNAL_RUN_LAST,
		      G_STRUCT_OFFSET (AtkTableIface, row_inserted),
		      (GSignalAccumulator) NULL, NULL,
		      atk_marshal_VOID__INT_INT,
		      G_TYPE_NONE,
		      2, G_TYPE_INT, G_TYPE_INT);
      /**
       * AtkTable::column-inserted:
       * @atktable: the object which received the signal.
       * @arg1: The index of the column inserted.
       * @arg2: The number of colums inserted.
       *
       * The "column-inserted" signal is emitted by an object which
       * implements the AtkTable interface when a column is inserted.
       */
      atk_table_signals[COLUMN_INSERTED] =
	g_signal_new ("column_inserted",
		      ATK_TYPE_TABLE,
		      G_SIGNAL_RUN_LAST,
		      G_STRUCT_OFFSET (AtkTableIface, column_inserted),
		      (GSignalAccumulator) NULL, NULL,
		      atk_marshal_VOID__INT_INT,
		      G_TYPE_NONE,
		      2, G_TYPE_INT, G_TYPE_INT);
      /**
       * AtkTable::row-deleted:
       * @atktable: the object which received the signal.
       * @arg1: The index of the first row deleted.
       * @arg2: The number of rows deleted.
       *
       * The "row-deleted" signal is emitted by an object which
       * implements the AtkTable interface when a row is deleted.
       */
      atk_table_signals[ROW_DELETED] =
	g_signal_new ("row_deleted",
		      ATK_TYPE_TABLE,
		      G_SIGNAL_RUN_LAST,
		      G_STRUCT_OFFSET (AtkTableIface, row_deleted),
		      (GSignalAccumulator) NULL, NULL,
		      atk_marshal_VOID__INT_INT,
		      G_TYPE_NONE,
		      2, G_TYPE_INT, G_TYPE_INT);
      /**
       * AtkTable::column-deleted:
       * @atktable: the object which received the signal.
       * @arg1: The index of the first column deleted.
       * @arg2: The number of columns deleted.
       *
       * The "column-deleted" signal is emitted by an object which
       * implements the AtkTable interface when a column is deleted.
       */
      atk_table_signals[COLUMN_DELETED] =
	g_signal_new ("column_deleted",
		      ATK_TYPE_TABLE,
		      G_SIGNAL_RUN_LAST,
		      G_STRUCT_OFFSET (AtkTableIface, column_deleted),
		      (GSignalAccumulator) NULL, NULL,
		      atk_marshal_VOID__INT_INT,
		      G_TYPE_NONE,
		      2, G_TYPE_INT, G_TYPE_INT);
      /**
       * AtkTable::row-reordered:
       * @atktable: the object which received the signal.
       *
       * The "row-reordered" signal is emitted by an object which
       * implements the AtkTable interface when the rows are
       * reordered.
       */
      atk_table_signals[ROW_REORDERED] =
	g_signal_new ("row_reordered",
		      ATK_TYPE_TABLE,
		      G_SIGNAL_RUN_LAST,
		      G_STRUCT_OFFSET (AtkTableIface, row_reordered),
		      (GSignalAccumulator) NULL, NULL,
		      g_cclosure_marshal_VOID__VOID,
		      G_TYPE_NONE,
		      0);
      /**
       * AtkTable::column-reordered:
       * @atktable: the object which received the signal.
       *
       * The "column-reordered" signal is emitted by an object which
       * implements the AtkTable interface when the columns are
       * reordered.
       */
      atk_table_signals[COLUMN_REORDERED] =
	g_signal_new ("column_reordered",
		      ATK_TYPE_TABLE,
		      G_SIGNAL_RUN_LAST,
		      G_STRUCT_OFFSET (AtkTableIface, column_reordered),
		      (GSignalAccumulator) NULL, NULL,
		      g_cclosure_marshal_VOID__VOID,
		      G_TYPE_NONE,
		      0);

      /**
       * AtkTable::model-changed:
       * @atktable: the object which received the signal.
       *
       * The "model-changed" signal is emitted by an object which
       * implements the AtkTable interface when the model displayed by
       * the table changes.
       */
      atk_table_signals[MODEL_CHANGED] =
        g_signal_new ("model_changed",
                      ATK_TYPE_TABLE,
                      G_SIGNAL_RUN_LAST,
                      G_STRUCT_OFFSET (AtkTableIface, model_changed),
                      (GSignalAccumulator) NULL, NULL,
                      g_cclosure_marshal_VOID__VOID,
                      G_TYPE_NONE, 0);

      initialized = TRUE;
    }
}

/**
 * atk_table_ref_at:
 * @table: a GObject instance that implements AtkTableIface
 * @row: a #gint representing a row in @table
 * @column: a #gint representing a column in @table
 *
 * Get a reference to the table cell at @row, @column. This cell
 * should implement the interface #AtkTableCell
 *
 * Returns: (transfer full): an #AtkObject representing the referred
 * to accessible
 **/
AtkObject*
atk_table_ref_at (AtkTable *table,
                  gint     row,
                  gint     column)
{
  AtkTableIface *iface;

  g_return_val_if_fail (ATK_IS_TABLE (table), NULL);
  g_return_val_if_fail (row >= 0, NULL);
  g_return_val_if_fail (column >= 0, NULL);

  iface = ATK_TABLE_GET_IFACE (table);

  if (iface->ref_at)
    return (iface->ref_at) (table, row, column);
  else
    return NULL;
}

/**
 * atk_table_get_index_at:
 * @table: a GObject instance that implements AtkTableIface
 * @row: a #gint representing a row in @table
 * @column: a #gint representing a column in @table
 *
 * Gets a #gint representing the index at the specified @row and
 * @column.
 *
 * Deprecated: Since 2.12. Use atk_table_ref_at() in order to get the
 * accessible that represents the cell at (@row, @column)
 *
 * Returns: a #gint representing the index at specified position.
 * The value -1 is returned if the object at row,column is not a child
 * of table or table does not implement this interface.
 **/
gint
atk_table_get_index_at (AtkTable *table,
                        gint     row,
                        gint     column)
{
  AtkTableIface *iface;

  g_return_val_if_fail (ATK_IS_TABLE (table), -1);
  g_return_val_if_fail (row >= 0, -1);
  g_return_val_if_fail (column >= 0, -1);

  iface = ATK_TABLE_GET_IFACE (table);

  if (iface->get_index_at)
    return (iface->get_index_at) (table, row, column);
  else
    return -1;
}

/**
 * atk_table_get_row_at_index:
 * @table: a GObject instance that implements AtkTableInterface
 * @index_: a #gint representing an index in @table
 *
 * Gets a #gint representing the row at the specified @index_.
 *
 * Deprecated: since 2.12.
 *
 * Returns: a gint representing the row at the specified index,
 * or -1 if the table does not implement this method.
 **/
gint
atk_table_get_row_at_index (AtkTable *table,
                            gint     index)
{
  AtkTableIface *iface;

  g_return_val_if_fail (ATK_IS_TABLE (table), -1);

  iface = ATK_TABLE_GET_IFACE (table);

  if (iface->get_row_at_index)
    return (iface->get_row_at_index) (table, index);
  else
    return -1;
}

/**
 * atk_table_get_column_at_index:
 * @table: a GObject instance that implements AtkTableInterface
 * @index_: a #gint representing an index in @table
 *
 * Gets a #gint representing the column at the specified @index_.
 *
 * Deprecated: Since 2.12.
 *
 * Returns: a gint representing the column at the specified index,
 * or -1 if the table does not implement this method.
 **/
gint
atk_table_get_column_at_index (AtkTable *table,
                               gint     index)
{
  AtkTableIface *iface;

  g_return_val_if_fail (ATK_IS_TABLE (table), 0);

  iface = ATK_TABLE_GET_IFACE (table);

  if (iface->get_column_at_index)
    return (iface->get_column_at_index) (table, index);
  else
    return -1;
}

/**
 * atk_table_get_caption:
 * @table: a GObject instance that implements AtkTableInterface
 *
 * Gets the caption for the @table.
 *
 * Returns: (nullable) (transfer none): a AtkObject* representing the
 * table caption, or %NULL if value does not implement this interface.
 **/
AtkObject*
atk_table_get_caption (AtkTable *table)
{
  AtkTableIface *iface;

  g_return_val_if_fail (ATK_IS_TABLE (table), NULL);

  iface = ATK_TABLE_GET_IFACE (table);

  if (iface->get_caption)
    return (iface->get_caption) (table);
  else
    return NULL;
}

/**
 * atk_table_get_n_columns:
 * @table: a GObject instance that implements AtkTableIface
 *
 * Gets the number of columns in the table.
 *
 * Returns: a gint representing the number of columns, or 0
 * if value does not implement this interface.
 **/
gint
atk_table_get_n_columns (AtkTable *table)
{
  AtkTableIface *iface;

  g_return_val_if_fail (ATK_IS_TABLE (table), 0);

  iface = ATK_TABLE_GET_IFACE (table);

  if (iface->get_n_columns)
    return (iface->get_n_columns) (table);
  else
    return 0;
}

/**
 * atk_table_get_column_description:
 * @table: a GObject instance that implements AtkTableIface
 * @column: a #gint representing a column in @table
 *
 * Gets the description text of the specified @column in the table
 *
 * Returns: a gchar* representing the column description, or %NULL
 * if value does not implement this interface.
 **/
const gchar*
atk_table_get_column_description (AtkTable *table,
                                  gint     column)
{
  AtkTableIface *iface;

  g_return_val_if_fail (ATK_IS_TABLE (table), NULL);

  iface = ATK_TABLE_GET_IFACE (table);

  if (iface->get_column_description)
    return (iface->get_column_description) (table, column);
  else
    return NULL;
}

/**
 * atk_table_get_column_extent_at:
 * @table: a GObject instance that implements AtkTableIface
 * @row: a #gint representing a row in @table
 * @column: a #gint representing a column in @table
 *
 * Gets the number of columns occupied by the accessible object
 * at the specified @row and @column in the @table.
 *
 * Returns: a gint representing the column extent at specified position, or 0
 * if value does not implement this interface.
 **/
gint
atk_table_get_column_extent_at (AtkTable *table,
                                gint     row,
                                gint     column)
{
  AtkTableIface *iface;

  g_return_val_if_fail (ATK_IS_TABLE (table), 0);

  iface = ATK_TABLE_GET_IFACE (table);

  if (iface->get_column_extent_at)
    return (iface->get_column_extent_at) (table, row, column);
  else
    return 0;
}

/**
 * atk_table_get_column_header:
 * @table: a GObject instance that implements AtkTableIface
 * @column: a #gint representing a column in the table
 *
 * Gets the column header of a specified column in an accessible table.
 *
 * Returns: (nullable) (transfer none): a AtkObject* representing the
 * specified column header, or %NULL if value does not implement this
 * interface.
 **/
AtkObject*
atk_table_get_column_header (AtkTable *table, gint column)
{
  AtkTableIface *iface;

  g_return_val_if_fail (ATK_IS_TABLE (table), NULL);

  iface = ATK_TABLE_GET_IFACE (table);

  if (iface->get_column_header)
    return (iface->get_column_header) (table, column);
  else
    return NULL;
}

/**
 * atk_table_get_n_rows:
 * @table: a GObject instance that implements AtkTableIface
 *
 * Gets the number of rows in the table.
 *
 * Returns: a gint representing the number of rows, or 0
 * if value does not implement this interface.
 **/
gint
atk_table_get_n_rows (AtkTable *table)
{
  AtkTableIface *iface;

  g_return_val_if_fail (ATK_IS_TABLE (table), 0);

  iface = ATK_TABLE_GET_IFACE (table);

  if (iface->get_n_rows)
    return (iface->get_n_rows) (table);
  else
    return 0;
}

/**
 * atk_table_get_row_description:
 * @table: a GObject instance that implements AtkTableIface
 * @row: a #gint representing a row in @table
 *
 * Gets the description text of the specified row in the table
 *
 * Returns: (nullable): a gchar* representing the row description, or
 * %NULL if value does not implement this interface.
 **/
const gchar*
atk_table_get_row_description (AtkTable *table,
                               gint      row)
{
  AtkTableIface *iface;

  g_return_val_if_fail (ATK_IS_TABLE (table), NULL);

  iface = ATK_TABLE_GET_IFACE (table);

  if (iface->get_row_description)
    return (iface->get_row_description) (table, row);
  else
    return NULL;
}

/**
 * atk_table_get_row_extent_at:
 * @table: a GObject instance that implements AtkTableIface
 * @row: a #gint representing a row in @table
 * @column: a #gint representing a column in @table
 *
 * Gets the number of rows occupied by the accessible object
 * at a specified @row and @column in the @table.
 *
 * Returns: a gint representing the row extent at specified position, or 0
 * if value does not implement this interface.
 **/
gint
atk_table_get_row_extent_at (AtkTable *table,
                             gint     row,
                             gint     column)
{
  AtkTableIface *iface;

  g_return_val_if_fail (ATK_IS_TABLE (table), 0);

  iface = ATK_TABLE_GET_IFACE (table);

  if (iface->get_row_extent_at)
    return (iface->get_row_extent_at) (table, row, column);
  else
    return 0;
}

/**
 * atk_table_get_row_header:
 * @table: a GObject instance that implements AtkTableIface
 * @row: a #gint representing a row in the table
 *
 * Gets the row header of a specified row in an accessible table.
 *
 * Returns: (nullable) (transfer none): a AtkObject* representing the
 * specified row header, or %NULL if value does not implement this
 * interface.
 **/
AtkObject*
atk_table_get_row_header (AtkTable *table, gint row)
{
  AtkTableIface *iface;

  g_return_val_if_fail (ATK_IS_TABLE (table), NULL);

  iface = ATK_TABLE_GET_IFACE (table);

  if (iface->get_row_header)
    return (iface->get_row_header) (table, row);
  else
    return NULL;
}

/**
 * atk_table_get_summary:
 * @table: a GObject instance that implements AtkTableIface
 *
 * Gets the summary description of the table.
 *
 * Returns: (transfer full): a AtkObject* representing a summary description
 * of the table, or zero if value does not implement this interface.
 **/
AtkObject*
atk_table_get_summary (AtkTable *table)
{
  AtkTableIface *iface;

  g_return_val_if_fail (ATK_IS_TABLE (table), NULL);

  iface = ATK_TABLE_GET_IFACE (table);

  if (iface->get_summary)
    return (iface->get_summary) (table);
  else
    return NULL;
}

/**
 * atk_table_get_selected_rows:
 * @table: a GObject instance that implements AtkTableIface
 * @selected: a #gint** that is to contain the selected row numbers
 *
 * Gets the selected rows of the table by initializing **selected with 
 * the selected row numbers. This array should be freed by the caller.
 *
 * Returns: a gint representing the number of selected rows,
 * or zero if value does not implement this interface.
 **/
gint
atk_table_get_selected_rows (AtkTable *table, gint **selected)
{
  AtkTableIface *iface;

  g_return_val_if_fail (ATK_IS_TABLE (table), 0);

  iface = ATK_TABLE_GET_IFACE (table);

  if (iface->get_selected_rows)
    return (iface->get_selected_rows) (table, selected);
  else
    return 0;
}

/**
 * atk_table_get_selected_columns:
 * @table: a GObject instance that implements AtkTableIface
 * @selected: a #gint** that is to contain the selected columns numbers
 *
 * Gets the selected columns of the table by initializing **selected with 
 * the selected column numbers. This array should be freed by the caller.
 *
 * Returns: a gint representing the number of selected columns,
 * or %0 if value does not implement this interface.
 **/
gint 
atk_table_get_selected_columns (AtkTable *table, gint **selected)
{
  AtkTableIface *iface;

  g_return_val_if_fail (ATK_IS_TABLE (table), 0);

  iface = ATK_TABLE_GET_IFACE (table);

  if (iface->get_selected_columns)
    return (iface->get_selected_columns) (table, selected);
  else
    return 0;
}

/**
 * atk_table_is_column_selected:
 * @table: a GObject instance that implements AtkTableIface
 * @column: a #gint representing a column in @table
 *
 * Gets a boolean value indicating whether the specified @column
 * is selected
 *
 * Returns: a gboolean representing if the column is selected, or 0
 * if value does not implement this interface.
 **/
gboolean
atk_table_is_column_selected (AtkTable *table,
                              gint     column)
{
  AtkTableIface *iface;

  g_return_val_if_fail (ATK_IS_TABLE (table), FALSE);

  iface = ATK_TABLE_GET_IFACE (table);

  if (iface->is_column_selected)
    return (iface->is_column_selected) (table, column);
  else
    return FALSE;
}

/**
 * atk_table_is_row_selected:
 * @table: a GObject instance that implements AtkTableIface
 * @row: a #gint representing a row in @table
 *
 * Gets a boolean value indicating whether the specified @row
 * is selected
 *
 * Returns: a gboolean representing if the row is selected, or 0
 * if value does not implement this interface.
 **/
gboolean
atk_table_is_row_selected (AtkTable *table,
                           gint     row)
{
  AtkTableIface *iface;

  g_return_val_if_fail (ATK_IS_TABLE (table), FALSE);

  iface = ATK_TABLE_GET_IFACE (table);

  if (iface->is_row_selected)
    return (iface->is_row_selected) (table, row);
  else
    return FALSE;
}

/**
 * atk_table_is_selected:
 * @table: a GObject instance that implements AtkTableIface
 * @row: a #gint representing a row in @table
 * @column: a #gint representing a column in @table
 *
 * Gets a boolean value indicating whether the accessible object
 * at the specified @row and @column is selected
 *
 * Returns: a gboolean representing if the cell is selected, or 0
 * if value does not implement this interface.
 **/
gboolean
atk_table_is_selected (AtkTable *table,
                       gint     row,
                       gint     column)
{
  AtkTableIface *iface;

  g_return_val_if_fail (ATK_IS_TABLE (table), FALSE);

  iface = ATK_TABLE_GET_IFACE (table);

  if (iface->is_selected)
    return (iface->is_selected) (table, row, column);
  else
    return FALSE;
}

/**
 * atk_table_add_row_selection:
 * @table: a GObject instance that implements AtkTableIface
 * @row: a #gint representing a row in @table
 *
 * Adds the specified @row to the selection. 
 *
 * Returns: a gboolean representing if row was successfully added to selection,
 * or 0 if value does not implement this interface.
 **/
gboolean
atk_table_add_row_selection (AtkTable *table,
                       		 gint     row)
{
  AtkTableIface *iface;

  g_return_val_if_fail (ATK_IS_TABLE (table), FALSE);

  iface = ATK_TABLE_GET_IFACE (table);

  if (iface->add_row_selection)
    return (iface->add_row_selection) (table, row);
  else
    return FALSE;
}
/**
 * atk_table_remove_row_selection:
 * @table: a GObject instance that implements AtkTableIface
 * @row: a #gint representing a row in @table
 *
 * Removes the specified @row from the selection. 
 *
 * Returns: a gboolean representing if the row was successfully removed from
 * the selection, or 0 if value does not implement this interface.
 **/
gboolean
atk_table_remove_row_selection (AtkTable *table,
                       		    gint     row)
{
  AtkTableIface *iface;

  g_return_val_if_fail (ATK_IS_TABLE (table), FALSE);

  iface = ATK_TABLE_GET_IFACE (table);

  if (iface->remove_row_selection)
    return (iface->remove_row_selection) (table, row);
  else
    return FALSE;
}
/**
 * atk_table_add_column_selection:
 * @table: a GObject instance that implements AtkTableIface
 * @column: a #gint representing a column in @table
 *
 * Adds the specified @column to the selection. 
 *
 * Returns: a gboolean representing if the column was successfully added to 
 * the selection, or 0 if value does not implement this interface.
 **/
gboolean
atk_table_add_column_selection (AtkTable *table,
                       		    gint     column)
{
  AtkTableIface *iface;

  g_return_val_if_fail (ATK_IS_TABLE (table), FALSE);

  iface = ATK_TABLE_GET_IFACE (table);

  if (iface->add_column_selection)
    return (iface->add_column_selection) (table, column);
  else
    return FALSE;
}
/**
 * atk_table_remove_column_selection:
 * @table: a GObject instance that implements AtkTableIface
 * @column: a #gint representing a column in @table
 *
 * Adds the specified @column to the selection. 
 *
 * Returns: a gboolean representing if the column was successfully removed from
 * the selection, or 0 if value does not implement this interface.
 **/
gboolean
atk_table_remove_column_selection (AtkTable *table,
                       			   gint     column)
{
  AtkTableIface *iface;

  g_return_val_if_fail (ATK_IS_TABLE (table), FALSE);

  iface = ATK_TABLE_GET_IFACE (table);

  if (iface->remove_column_selection)
    return (iface->remove_column_selection) (table, column);
  else
    return FALSE;
}

/**
 * atk_table_set_caption:
 * @table: a GObject instance that implements AtkTableIface
 * @caption: a #AtkObject representing the caption to set for @table
 *
 * Sets the caption for the table.
 **/
void
atk_table_set_caption (AtkTable       *table,
                       AtkObject      *caption)
{
  AtkTableIface *iface;

  g_return_if_fail (ATK_IS_TABLE (table));

  iface = ATK_TABLE_GET_IFACE (table);

  if (iface->set_caption)
    (iface->set_caption) (table, caption);
}

/**
 * atk_table_set_column_description:
 * @table: a GObject instance that implements AtkTableIface
 * @column: a #gint representing a column in @table
 * @description: a #gchar representing the description text
 * to set for the specified @column of the @table
 *
 * Sets the description text for the specified @column of the @table.
 **/
void
atk_table_set_column_description (AtkTable       *table,
                                  gint           column,
                                  const gchar    *description)
{
  AtkTableIface *iface;

  g_return_if_fail (ATK_IS_TABLE (table));

  iface = ATK_TABLE_GET_IFACE (table);

  if (iface->set_column_description)
    (iface->set_column_description) (table, column, description);
}

/**
 * atk_table_set_column_header:
 * @table: a GObject instance that implements AtkTableIface
 * @column: a #gint representing a column in @table
 * @header: an #AtkTable
 *
 * Sets the specified column header to @header.
 **/
void
atk_table_set_column_header (AtkTable  *table,
                             gint      column,
                             AtkObject *header)
{
  AtkTableIface *iface;

  g_return_if_fail (ATK_IS_TABLE (table));

  iface = ATK_TABLE_GET_IFACE (table);

  if (iface->set_column_header)
    (iface->set_column_header) (table, column, header);
}

/**
 * atk_table_set_row_description:
 * @table: a GObject instance that implements AtkTableIface
 * @row: a #gint representing a row in @table
 * @description: a #gchar representing the description text
 * to set for the specified @row of @table
 *
 * Sets the description text for the specified @row of @table.
 **/
void
atk_table_set_row_description (AtkTable       *table,
                               gint           row,
                               const gchar    *description)
{
  AtkTableIface *iface;

  g_return_if_fail (ATK_IS_TABLE (table));

  iface = ATK_TABLE_GET_IFACE (table);

  if (iface->set_row_description)
    (iface->set_row_description) (table, row, description);
}

/**
 * atk_table_set_row_header:
 * @table: a GObject instance that implements AtkTableIface
 * @row: a #gint representing a row in @table
 * @header: an #AtkTable 
 *
 * Sets the specified row header to @header.
 **/
void
atk_table_set_row_header (AtkTable  *table,
                          gint      row,
                          AtkObject *header)
{
  AtkTableIface *iface;

  g_return_if_fail (ATK_IS_TABLE (table));

  iface = ATK_TABLE_GET_IFACE (table);

  if (iface->set_row_header)
    (iface->set_row_header) (table, row, header);
}

/**
 * atk_table_set_summary:
 * @table: a GObject instance that implements AtkTableIface
 * @accessible: an #AtkObject representing the summary description
 * to set for @table
 *
 * Sets the summary description of the table.
 **/
void
atk_table_set_summary (AtkTable       *table,
                       AtkObject      *accessible)
{
  AtkTableIface *iface;

  g_return_if_fail (ATK_IS_TABLE (table));

  iface = ATK_TABLE_GET_IFACE (table);

  if (iface->set_summary)
    (iface->set_summary) (table, accessible);
}
