[evolution-patches] patch for bug # 50538: atk table and atk selection impl. for e-calendar.



Hi,

another a11y patch for e-calendar:  atk table and atk selection impl. for e-calendar.
bug 50538: http://bugzilla.ximian.com/show_bug.cgi?id=50538

Most of changes are in evolution/a11y/widgets


Thanks,
Bolian Yin

Index: widgets/misc/ChangeLog
===================================================================
RCS file: /cvs/gnome/evolution/widgets/misc/ChangeLog,v
retrieving revision 1.238
diff -u -r1.238 ChangeLog
--- widgets/misc/ChangeLog	28 Oct 2003 18:56:34 -0000	1.238
+++ widgets/misc/ChangeLog	4 Nov 2003 10:08:57 -0000
@@ -1,3 +1,9 @@
+2003-11-04  Bolian Yin <bolian yin sun com>
+
+	* e-calendar-item: make e_calendar_item_normalize_date public func.
+	   add "selection_preview_changed" signal.
+	   move some definition of constants to .h
+
 2003-10-28  Rodrigo Moya <rodrigo ximian com>
 
 	* e-source-selector.c (class_init): fill_popup_menu signal has
Index: widgets/misc/e-calendar-item.c
===================================================================
RCS file: /cvs/gnome/evolution/widgets/misc/e-calendar-item.c,v
retrieving revision 1.36
diff -u -r1.36 e-calendar-item.c
--- widgets/misc/e-calendar-item.c	22 Sep 2003 03:19:00 -0000	1.36
+++ widgets/misc/e-calendar-item.c	4 Nov 2003 10:09:00 -0000
@@ -46,36 +46,6 @@
 #include <libgnome/gnome-i18n.h>
 #include <gal/util/e-util.h>
 
-/*
- * These are the padding sizes between various pieces of the calendar.
- */
-
-/* The minimum padding around the numbers in each cell/day. */
-#define	E_CALENDAR_ITEM_MIN_CELL_XPAD	4
-#define	E_CALENDAR_ITEM_MIN_CELL_YPAD	0
-
-/* Vertical padding. */
-#define	E_CALENDAR_ITEM_YPAD_ABOVE_DAY_LETTERS		1
-#define	E_CALENDAR_ITEM_YPAD_BELOW_DAY_LETTERS		0
-#define	E_CALENDAR_ITEM_YPAD_ABOVE_CELLS		1
-#define	E_CALENDAR_ITEM_YPAD_BELOW_CELLS		2
-
-/* Horizontal padding in the heading bars. */
-#define	E_CALENDAR_ITEM_XPAD_BEFORE_MONTH_NAME_WITH_BUTTON	16
-#define	E_CALENDAR_ITEM_XPAD_BEFORE_MONTH_NAME			3
-#define	E_CALENDAR_ITEM_XPAD_AFTER_MONTH_NAME			3
-#define	E_CALENDAR_ITEM_XPAD_AFTER_MONTH_NAME_WITH_BUTTON	16
-
-/* Horizontal padding in the month displays. */
-#define	E_CALENDAR_ITEM_XPAD_BEFORE_WEEK_NUMBERS	4
-#define	E_CALENDAR_ITEM_XPAD_AFTER_WEEK_NUMBERS		2
-#define	E_CALENDAR_ITEM_XPAD_BEFORE_CELLS		1
-#define	E_CALENDAR_ITEM_XPAD_AFTER_CELLS		4
-
-/* The number of rows & columns of days in each month. */
-#define E_CALENDAR_ROWS_PER_MONTH	6
-#define E_CALENDAR_COLS_PER_MONTH	7
-
 static const int e_calendar_item_days_in_month[12] = {
 	31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
 };
@@ -168,11 +138,6 @@
 						 gint		*days_in_prev_month);
 static void e_calendar_item_recalc_sizes(ECalendarItem *calitem);
 
-static gint e_calendar_item_get_week_number	(ECalendarItem *calitem,
-						 gint		day,
-						 gint		month,
-						 gint		year);
-
 static void e_calendar_item_get_day_style	(ECalendarItem	*calitem,
 						 gint		 year,
 						 gint		 month,
@@ -197,9 +162,6 @@
 						  gint		*start_day,
 						  gint		 end_month,
 						  gint		 end_day);
-static void e_calendar_item_normalize_date	(ECalendarItem	*calitem,
-						 gint		*year,
-						 gint		*month);
 static void e_calendar_item_add_days_to_selection(ECalendarItem	*calitem,
 						  gint		 days);
 static void e_calendar_item_round_up_selection	(ECalendarItem	*calitem,
@@ -272,6 +234,7 @@
 enum {
   DATE_RANGE_CHANGED,
   SELECTION_CHANGED,
+  SELECTION_PREVIEW_CHANGED,
   LAST_SIGNAL
 };
 
@@ -376,6 +339,14 @@
 				G_STRUCT_OFFSET (ECalendarItemClass, selection_changed),
 				gtk_marshal_NONE__NONE,
 				GTK_TYPE_NONE, 0);
+	e_calendar_item_signals[SELECTION_PREVIEW_CHANGED] =
+		g_signal_new ("selection_preview_changed",
+			      G_TYPE_FROM_CLASS (object_class),
+			      G_SIGNAL_RUN_LAST,
+			      G_STRUCT_OFFSET (ECalendarItemClass, selection_preview_changed),
+			      NULL, NULL,
+			      g_cclosure_marshal_VOID__VOID,
+			      G_TYPE_NONE, 0);
 
 	object_class->destroy = e_calendar_item_destroy;
 	object_class->get_arg = e_calendar_item_get_arg;
@@ -394,6 +365,7 @@
 
 	class->date_range_changed	= NULL;
 	class->selection_changed	= NULL;
+	class->selection_preview_changed	= NULL;
 
 	e_calendar_item_a11y_init ();
 }
@@ -1576,7 +1548,7 @@
 }
 
 
-static gint
+gint
 e_calendar_item_get_week_number	(ECalendarItem *calitem,
 				 gint		day,
 				 gint		month,
@@ -1715,6 +1687,8 @@
 	e_calendar_item_set_selection_if_emission (calitem,
 						   &gdate_start, &gdate_end,
 						   FALSE);
+	g_signal_emit_by_name (G_OBJECT (calitem),
+			       "selection_preview_changed");
 }
 
 static gint
@@ -2531,7 +2505,7 @@
 
 /* This will make sure that the given year & month are valid, i.e. if month
    is < 0 or > 11 the year and month will be updated accordingly. */
-static void
+void
 e_calendar_item_normalize_date	(ECalendarItem	*calitem,
 				 gint		*year,
 				 gint		*month)
Index: widgets/misc/e-calendar-item.h
===================================================================
RCS file: /cvs/gnome/evolution/widgets/misc/e-calendar-item.h,v
retrieving revision 1.16
diff -u -r1.16 e-calendar-item.h
--- widgets/misc/e-calendar-item.h	22 Sep 2003 03:19:00 -0000	1.16
+++ widgets/misc/e-calendar-item.h	4 Nov 2003 10:09:00 -0000
@@ -36,9 +36,39 @@
 #define	E_CALENDAR_ITEM_YPAD_ABOVE_MONTH_NAME	1
 #define	E_CALENDAR_ITEM_YPAD_BELOW_MONTH_NAME	1
 
+/* The number of rows & columns of days in each month. */
+#define E_CALENDAR_ROWS_PER_MONTH	6
+#define E_CALENDAR_COLS_PER_MONTH	7
+
 /* Used to mark days as bold in e_calendar_item_mark_day(). */
 #define E_CALENDAR_ITEM_MARK_BOLD	1
 
+/*
+ * These are the padding sizes between various pieces of the calendar.
+ */
+
+/* The minimum padding around the numbers in each cell/day. */
+#define	E_CALENDAR_ITEM_MIN_CELL_XPAD	4
+#define	E_CALENDAR_ITEM_MIN_CELL_YPAD	0
+
+/* Vertical padding. */
+#define	E_CALENDAR_ITEM_YPAD_ABOVE_DAY_LETTERS		1
+#define	E_CALENDAR_ITEM_YPAD_BELOW_DAY_LETTERS		0
+#define	E_CALENDAR_ITEM_YPAD_ABOVE_CELLS		1
+#define	E_CALENDAR_ITEM_YPAD_BELOW_CELLS		2
+
+/* Horizontal padding in the heading bars. */
+#define	E_CALENDAR_ITEM_XPAD_BEFORE_MONTH_NAME_WITH_BUTTON	16
+#define	E_CALENDAR_ITEM_XPAD_BEFORE_MONTH_NAME			3
+#define	E_CALENDAR_ITEM_XPAD_AFTER_MONTH_NAME			3
+#define	E_CALENDAR_ITEM_XPAD_AFTER_MONTH_NAME_WITH_BUTTON	16
+
+/* Horizontal padding in the month displays. */
+#define	E_CALENDAR_ITEM_XPAD_BEFORE_WEEK_NUMBERS	4
+#define	E_CALENDAR_ITEM_XPAD_AFTER_WEEK_NUMBERS		2
+#define	E_CALENDAR_ITEM_XPAD_BEFORE_CELLS		1
+#define	E_CALENDAR_ITEM_XPAD_AFTER_CELLS		4
+
 
 /* These index our colors array. */
 typedef enum
@@ -231,6 +261,7 @@
 
 	void (* date_range_changed)	(ECalendarItem *calitem);
 	void (* selection_changed)	(ECalendarItem *calitem);
+	void (* selection_preview_changed)	(ECalendarItem *calitem);
 };
 
 
@@ -332,6 +363,14 @@
 						 ECalendarItemGetTimeCallback cb,
 						 gpointer	 data,
 						 GtkDestroyNotify destroy);
+void e_calendar_item_normalize_date	(ECalendarItem	*calitem,
+					 gint		*year,
+					 gint		*month);
+gint e_calendar_item_get_week_number	(ECalendarItem *calitem,
+					 gint		day,
+					 gint		month,
+					 gint		year);
+
 
 #ifdef __cplusplus
 }
Index: a11y/ChangeLog
===================================================================
RCS file: /cvs/gnome/evolution/a11y/ChangeLog,v
retrieving revision 1.6
diff -u -r1.6 ChangeLog
--- a11y/ChangeLog	4 Nov 2003 08:15:56 -0000	1.6
+++ a11y/ChangeLog	4 Nov 2003 10:09:03 -0000
@@ -1,5 +1,15 @@
 2003-11-04  Bolian Yin <bolian yin sun com>
 
+	Fixes #50538
+
+	* new files:
+		widgets/ea-calendar-cell.[hc]
+
+	* widgets/ea-calendar-item: impl. atk selection and atk table interface.
+	* widgets/Makefile.am : use shared object library (.so)
+
+2003-11-04  Bolian Yin <bolian yin sun com>
+
 	Fixes # 48509
 
 	* new files:
Index: a11y/widgets/Makefile.am
===================================================================
RCS file: /cvs/gnome/evolution/a11y/widgets/Makefile.am,v
retrieving revision 1.1
diff -u -r1.1 Makefile.am
--- a11y/widgets/Makefile.am	27 Aug 2003 03:36:42 -0000	1.1
+++ a11y/widgets/Makefile.am	4 Nov 2003 10:09:03 -0000
@@ -1,5 +1,8 @@
 
-noinst_LTLIBRARIES = libevolution-widgets-a11y.la
+# for debug
+#A11Y_CFLAGS += -pedantic -ansi -DACC_DEBUG -Werror
+
+privlib_LTLIBRARIES = libevolution-widgets-a11y.la
 
 INCLUDES =						\
 	-DG_LOG_DOMAIN=\"evolution-a11y\"		\
@@ -19,5 +22,11 @@
 libevolution_widgets_a11y_la_SOURCES =		\
 	ea-calendar-item.c			\
 	ea-calendar-item.h			\
+	ea-calendar-cell.c			\
+	ea-calendar-cell.h			\
 	ea-widgets.c				\
 	ea-widgets.h
+
+libevolution_widgets_a11y_la_LIBADD =   \
+        $(top_builddir)/a11y/libevolution-a11y.la
+                                                                                
Index: a11y/widgets/ea-calendar-cell.c
===================================================================
RCS file: a11y/widgets/ea-calendar-cell.c
diff -N a11y/widgets/ea-calendar-cell.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ a11y/widgets/ea-calendar-cell.c	4 Nov 2003 10:09:03 -0000
@@ -0,0 +1,305 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/* vim:expandtab:shiftwidth=8:tabstop=8:
+ */
+/* Evolution Accessibility: ea-calendar-cell.c
+ *
+ * Copyright (C) 2003 Ximian, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program 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
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Bolian Yin <bolian yin sun com> Sun Microsystem Inc., 2003
+ *
+ */
+
+#include "ea-calendar-cell.h"
+#include "ea-calendar-item.h"
+#include "ea-factory.h"
+
+/* ECalendarCell */
+
+static void e_calendar_cell_class_init (ECalendarCellClass *class);
+
+EA_FACTORY_GOBJECT (EA_TYPE_CALENDAR_CELL, ea_calendar_cell, ea_calendar_cell_new)
+
+GType
+e_calendar_cell_get_type (void)
+{
+	static GType type = 0;
+
+	if (!type) {
+		static GTypeInfo tinfo = {
+			sizeof (ECalendarCellClass),
+			(GBaseInitFunc) NULL, /* base init */
+			(GBaseFinalizeFunc) NULL, /* base finalize */
+			(GClassInitFunc) e_calendar_cell_class_init, /* class init */
+			(GClassFinalizeFunc) NULL, /* class finalize */
+			NULL, /* class data */
+			sizeof (ECalendarCell), /* instance size */
+			0, /* nb preallocs */
+			(GInstanceInitFunc) NULL, /* instance init */
+			NULL /* value table */
+		};
+
+		type = g_type_register_static (G_TYPE_OBJECT,
+					       "ECalendarCell", &tinfo, 0);
+	}
+
+	return type;
+}
+
+static void
+e_calendar_cell_class_init (ECalendarCellClass *class)
+{
+    EA_SET_FACTORY (e_calendar_cell_get_type (), ea_calendar_cell);
+}
+
+ECalendarCell *
+e_calendar_cell_new (ECalendarItem *calitem, gint row, gint column)
+{
+	GObject *object;
+	ECalendarCell *cell;
+
+	g_return_val_if_fail (E_IS_CALENDAR_ITEM (calitem), NULL);
+
+	object = g_object_new (E_TYPE_CALENDAR_CELL, NULL);
+	cell = E_CALENDAR_CELL (object);
+	cell->calitem = calitem;
+	cell->row = row;
+	cell->column = column;
+
+#ifdef ACC_DEBUG
+	g_print ("EvoAcc: e_calendar_cell created %p\n", (void *)cell);
+#endif
+
+	return cell;
+}
+
+/* EaCalendarCell */
+
+static void ea_calendar_cell_class_init (EaCalendarCellClass *klass);
+
+static G_CONST_RETURN gchar* ea_calendar_cell_get_name (AtkObject *accessible);
+static G_CONST_RETURN gchar* ea_calendar_cell_get_description (AtkObject *accessible);
+static AtkObject * ea_calendar_cell_get_parent (AtkObject *accessible);
+
+/* component interface */
+static void atk_component_interface_init (AtkComponentIface *iface);
+static void component_interface_get_extents (AtkComponent *component,
+					     gint *x, gint *y,
+					     gint *width, gint *height,
+					     AtkCoordType coord_type);
+
+static gpointer parent_class = NULL;
+
+#ifdef ACC_DEBUG
+static gint n_ea_calendar_cell_created = 0, n_ea_calendar_cell_destroyed = 0;
+static void ea_calendar_cell_finalize (GObject *object);
+#endif
+
+GType
+ea_calendar_cell_get_type (void)
+{
+	static GType type = 0;
+
+	if (!type) {
+		static GTypeInfo tinfo = {
+			sizeof (EaCalendarCellClass),
+			(GBaseInitFunc) NULL, /* base init */
+			(GBaseFinalizeFunc) NULL, /* base finalize */
+			(GClassInitFunc) ea_calendar_cell_class_init, /* class init */
+			(GClassFinalizeFunc) NULL, /* class finalize */
+			NULL, /* class data */
+			sizeof (EaCalendarCell), /* instance size */
+			0, /* nb preallocs */
+			(GInstanceInitFunc) NULL, /* instance init */
+			NULL /* value table */
+		};
+
+		static const GInterfaceInfo atk_component_info = {
+			(GInterfaceInitFunc) atk_component_interface_init,
+			(GInterfaceFinalizeFunc) NULL,
+			NULL
+		};
+
+		type = g_type_register_static (ATK_TYPE_GOBJECT_ACCESSIBLE,
+					       "EaCalendarCell", &tinfo, 0);
+		g_type_add_interface_static (type, ATK_TYPE_COMPONENT,
+					     &atk_component_info);
+	}
+
+	return type;
+}
+
+static void
+ea_calendar_cell_class_init (EaCalendarCellClass *klass)
+{
+	AtkObjectClass *class = ATK_OBJECT_CLASS (klass);
+
+#ifdef ACC_DEBUG
+	GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+	gobject_class->finalize = ea_calendar_cell_finalize;
+#endif
+
+	parent_class = g_type_class_peek_parent (klass);
+
+	class->get_name = ea_calendar_cell_get_name;
+	class->get_description = ea_calendar_cell_get_description;
+
+	class->get_parent = ea_calendar_cell_get_parent;
+}
+
+AtkObject* 
+ea_calendar_cell_new (GObject *obj)
+{
+	gpointer object;
+	AtkObject *atk_object;
+
+	g_return_val_if_fail (E_IS_CALENDAR_CELL (obj), NULL);
+	object = g_object_new (EA_TYPE_CALENDAR_CELL, NULL);
+	atk_object = ATK_OBJECT (object);
+	atk_object_initialize (atk_object, obj);
+	atk_object->role = ATK_ROLE_TABLE_CELL;
+
+#ifdef ACC_DEBUG
+	++n_ea_calendar_cell_created;
+	g_print ("ACC_DEBUG: n_ea_calendar_cell_created = %d\n",
+		n_ea_calendar_cell_created);
+#endif
+	return atk_object;
+}
+
+#ifdef ACC_DEBUG
+static void ea_calendar_cell_finalize (GObject *object)
+{
+	++n_ea_calendar_cell_destroyed;
+	g_print ("ACC_DEBUG: n_ea_calendar_cell_destroyed = %d\n",
+		n_ea_calendar_cell_destroyed);
+}
+#endif
+
+static G_CONST_RETURN gchar*
+ea_calendar_cell_get_name (AtkObject *accessible)
+{
+	GObject *g_obj;
+
+	g_return_val_if_fail (EA_IS_CALENDAR_CELL (accessible), NULL);
+
+	g_obj = atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE(accessible));
+	if (!g_obj)
+		/* defunct object*/
+		return NULL;
+
+	if (!accessible->name) {
+		AtkObject *atk_obj;
+		EaCalendarItem *ea_calitem;
+		ECalendarCell *cell;
+		gint day_index;
+		gint year, month, day;
+		gchar buffer[128];
+
+		cell = E_CALENDAR_CELL (g_obj);
+		atk_obj = ea_calendar_cell_get_parent (accessible);
+		ea_calitem = EA_CALENDAR_ITEM (atk_obj);
+		day_index = atk_table_get_index_at (ATK_TABLE (ea_calitem),
+						    cell->row, cell->column);
+		e_calendar_item_get_date_for_offset (cell->calitem, day_index,
+						     &year, &month, &day);
+
+		g_snprintf (buffer, 128, "%d-%d-%d", year, month + 1, day);
+		ATK_OBJECT_CLASS (parent_class)->set_name (accessible, buffer);
+	}
+	return accessible->name;
+}
+
+static G_CONST_RETURN gchar*
+ea_calendar_cell_get_description (AtkObject *accessible)
+{
+	return ea_calendar_cell_get_name (accessible);
+}
+
+static AtkObject *
+ea_calendar_cell_get_parent (AtkObject *accessible)
+{
+	GObject *g_obj;
+	ECalendarCell *cell;
+	ECalendarItem *calitem;
+
+	g_return_val_if_fail (EA_IS_CALENDAR_CELL (accessible), NULL);
+
+	g_obj = atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE(accessible));
+	if (!g_obj)
+		/* defunct object*/
+		return NULL;
+
+	cell = E_CALENDAR_CELL (g_obj);
+	calitem = cell->calitem;
+	return atk_gobject_accessible_for_object (G_OBJECT (calitem));
+}
+
+/* Atk Component Interface */
+
+static void 
+atk_component_interface_init (AtkComponentIface *iface)
+{
+	g_return_if_fail (iface != NULL);
+
+	iface->get_extents = component_interface_get_extents;
+}
+
+static void 
+component_interface_get_extents (AtkComponent *component,
+				 gint *x, gint *y, gint *width, gint *height,
+				 AtkCoordType coord_type)
+{
+	GObject *g_obj;
+	AtkObject *atk_obj, *atk_canvas;
+	ECalendarCell *cell;
+	ECalendarItem *calitem;
+	EaCalendarItem *ea_calitem;
+	gint day_index;
+	gint year, month, day;
+	gint canvas_x, canvas_y, canvas_width, canvas_height;
+
+	*x = *y = *width = *height = 0;
+
+	g_return_if_fail (EA_IS_CALENDAR_CELL (component));
+
+
+	g_obj = atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE(component));
+	if (!g_obj)
+		/* defunct object*/
+		return;
+
+	cell = E_CALENDAR_CELL (g_obj);
+	calitem = cell->calitem;
+	atk_obj = atk_gobject_accessible_for_object (G_OBJECT (calitem));
+	ea_calitem = EA_CALENDAR_ITEM (atk_obj);
+	day_index = atk_table_get_index_at (ATK_TABLE (ea_calitem),
+					    cell->row, cell->column);
+	e_calendar_item_get_date_for_offset (calitem, day_index,
+					     &year, &month, &day);
+
+	if (!e_calendar_item_get_day_extents (calitem,
+					      year, month, day,
+					      x, y, width, height))
+	    return;
+	atk_canvas = atk_object_get_parent (ATK_OBJECT (ea_calitem));
+	atk_component_get_extents (ATK_COMPONENT (atk_canvas),
+					     &canvas_x, &canvas_y,
+					     &canvas_width, &canvas_height,
+					     coord_type);
+	*x += canvas_x;
+	*y += canvas_y;
+}
Index: a11y/widgets/ea-calendar-cell.h
===================================================================
RCS file: a11y/widgets/ea-calendar-cell.h
diff -N a11y/widgets/ea-calendar-cell.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ a11y/widgets/ea-calendar-cell.h	4 Nov 2003 10:09:03 -0000
@@ -0,0 +1,92 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/* vim:expandtab:shiftwidth=8:tabstop=8:
+ */
+/* Evolution Accessibility: ea-calendar-cell.h
+ *
+ * Copyright (C) 2003 Ximian, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program 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
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Bolian Yin <bolian yin sun com> Sun Microsystem Inc., 2003
+ *
+ */
+
+#ifndef __EA_CALENDAR_CELL_H__
+#define __EA_CALENDAR_CELL_H__
+
+#include <atk/atkgobjectaccessible.h>
+#include "misc/e-calendar-item.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#define E_TYPE_CALENDAR_CELL                     (e_calendar_cell_get_type ())
+#define E_CALENDAR_CELL(obj)                     (G_TYPE_CHECK_INSTANCE_CAST ((obj), E_TYPE_CALENDAR_CELL, ECalendarCell))
+#define E_CALENDAR_CELL_CLASS(klass)             (G_TYPE_CHECK_CLASS_CAST ((klass), E_TYPE_CALENDAR_CELL, ECalendarCellClass))
+#define E_IS_CALENDAR_CELL(obj)                  (G_TYPE_CHECK_INSTANCE_TYPE ((obj), E_TYPE_CALENDAR_CELL))
+#define E_IS_CALENDAR_CELL_CLASS(klass)          (G_TYPE_CHECK_CLASS_TYPE ((klass), E_TYPE_CALENDAR_CELL))
+#define E_CALENDAR_CELL_GET_CLASS(obj)           (G_TYPE_INSTANCE_GET_CLASS ((obj), E_TYPE_CALENDAR_CELL, ECalendarCellClass))
+
+typedef struct _ECalendarCell                   ECalendarCell;
+typedef struct _ECalendarCellClass              ECalendarCellClass;
+
+struct _ECalendarCell
+{
+	GObject parent;
+	ECalendarItem *calitem;
+	gint row;
+	gint column;
+};
+
+GType e_calendar_cell_get_type (void);
+
+struct _ECalendarCellClass
+{
+	GObjectClass parent_class;
+};
+
+ECalendarCell * e_calendar_cell_new (ECalendarItem *calitem,
+				     gint row, gint column);
+
+#define EA_TYPE_CALENDAR_CELL                     (ea_calendar_cell_get_type ())
+#define EA_CALENDAR_CELL(obj)                     (G_TYPE_CHECK_INSTANCE_CAST ((obj), EA_TYPE_CALENDAR_CELL, EaCalendarCell))
+#define EA_CALENDAR_CELL_CLASS(klass)             (G_TYPE_CHECK_CLASS_CAST ((klass), EA_TYPE_CALENDAR_CELL, EaCalendarCellClass))
+#define EA_IS_CALENDAR_CELL(obj)                  (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EA_TYPE_CALENDAR_CELL))
+#define EA_IS_CALENDAR_CELL_CLASS(klass)          (G_TYPE_CHECK_CLASS_TYPE ((klass), EA_TYPE_CALENDAR_CELL))
+#define EA_CALENDAR_CELL_GET_CLASS(obj)           (G_TYPE_INSTANCE_GET_CLASS ((obj), EA_TYPE_CALENDAR_CELL, EaCalendarCellClass))
+
+typedef struct _EaCalendarCell                   EaCalendarCell;
+typedef struct _EaCalendarCellClass              EaCalendarCellClass;
+
+struct _EaCalendarCell
+{
+	AtkGObjectAccessible parent;
+};
+
+GType ea_calendar_cell_get_type (void);
+
+struct _EaCalendarCellClass
+{
+	AtkGObjectAccessibleClass parent_class;
+};
+
+AtkObject*     ea_calendar_cell_new         (GObject *gobj);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __EA_CALENDAR_CELL_H__ */
Index: a11y/widgets/ea-calendar-item.c
===================================================================
RCS file: /cvs/gnome/evolution/a11y/widgets/ea-calendar-item.c,v
retrieving revision 1.1
diff -u -r1.1 ea-calendar-item.c
--- a11y/widgets/ea-calendar-item.c	27 Aug 2003 03:36:42 -0000	1.1
+++ a11y/widgets/ea-calendar-item.c	4 Nov 2003 10:09:05 -0000
@@ -24,15 +24,109 @@
  */
 
 #include <stdio.h>
+#include <time.h>
 #include <string.h>
 #include <libgnomecanvas/gnome-canvas.h>
 #include <glib/gdate.h>
 #include "ea-calendar-item.h"
+#include "ea-calendar-cell.h"
+#include "ea-cell-table.h"
 
+#define EA_CALENDAR_COLUMN_NUM E_CALENDAR_COLS_PER_MONTH
+
+/* EaCalendarItem */
 static void ea_calendar_item_class_init (EaCalendarItemClass *klass);
+static void ea_calendar_item_finalize (GObject *object);
 
 static G_CONST_RETURN gchar* ea_calendar_item_get_name (AtkObject *accessible);
 static G_CONST_RETURN gchar* ea_calendar_item_get_description (AtkObject *accessible);
+static gint ea_calendar_item_get_n_children (AtkObject *accessible);
+static AtkObject *ea_calendar_item_ref_child (AtkObject *accessible, gint index);
+
+/* atk table interface */
+static void atk_table_interface_init (AtkTableIface *iface);
+static gint table_interface_get_index_at (AtkTable *table,
+					  gint     row,
+					  gint     column);
+static gint table_interface_get_column_at_index (AtkTable *table,
+						 gint     index);
+static gint table_interface_get_row_at_index (AtkTable *table,
+					      gint     index);
+static AtkObject* table_interface_ref_at (AtkTable *table,
+					  gint     row, 
+					  gint     column);
+static gint table_interface_get_n_rows (AtkTable *table);
+static gint table_interface_get_n_columns (AtkTable *table);
+static gint table_interface_get_column_extent_at (AtkTable      *table,
+						  gint          row,
+						  gint          column);
+static gint table_interface_get_row_extent_at (AtkTable      *table,
+					       gint          row,
+					       gint          column);
+
+static gboolean table_interface_is_row_selected (AtkTable *table,
+						 gint     row);
+static gboolean table_interface_is_column_selected (AtkTable *table,
+						    gint     row);
+static gboolean table_interface_is_selected (AtkTable *table,
+					     gint     row,
+					     gint     column);
+static gint table_interface_get_selected_rows (AtkTable *table,
+					       gint **rows_selected);
+static gint table_interface_get_selected_columns (AtkTable *table,
+						  gint     **columns_selected);
+static gboolean table_interface_add_row_selection (AtkTable *table, gint row);
+static gboolean table_interface_remove_row_selection (AtkTable *table,
+						      gint row);
+static gboolean table_interface_add_column_selection (AtkTable *table,
+						      gint column);
+static gboolean table_interface_remove_column_selection (AtkTable *table,
+							 gint column);
+static AtkObject* table_interface_get_row_header (AtkTable *table, gint row);
+static AtkObject* table_interface_get_column_header (AtkTable *table,
+						     gint in_col);
+static AtkObject* table_interface_get_caption (AtkTable *table);
+
+static G_CONST_RETURN gchar*
+table_interface_get_column_description (AtkTable *table, gint in_col);
+
+static G_CONST_RETURN gchar*
+table_interface_get_row_description (AtkTable *table, gint row);
+
+static AtkObject* table_interface_get_summary (AtkTable *table);
+
+/* atk selection interface */
+static void atk_selection_interface_init (AtkSelectionIface *iface);
+static gboolean selection_interface_add_selection (AtkSelection *selection,
+						   gint i);
+static gboolean selection_interface_clear_selection (AtkSelection *selection);
+static AtkObject* selection_interface_ref_selection (AtkSelection *selection,
+						     gint i);
+static gint selection_interface_get_selection_count (AtkSelection *selection);
+static gboolean selection_interface_is_child_selected (AtkSelection *selection,
+						       gint i);
+
+/* callbacks */
+static void selection_preview_change_cb (ECalendarItem *calitem);
+static void date_range_changed_cb (ECalendarItem *calitem);
+static void selection_changed_cb (ECalendarItem *calitem);
+
+/* helpers */
+static EaCellTable *ea_calendar_item_get_cell_data (EaCalendarItem *ea_calitem);
+static void ea_calendar_item_destory_cell_data (EaCalendarItem *ea_calitem);
+static gboolean ea_calendar_item_get_column_label (EaCalendarItem *ea_calitem,
+						   gint column,
+						   gchar *buffer,
+						   gint buffer_size);
+static gboolean ea_calendar_item_get_row_label (EaCalendarItem *ea_calitem,
+						gint row,
+						gchar *buffer,
+						gint buffer_size);
+
+#ifdef ACC_DEBUG
+static gint n_ea_calendar_item_created = 0;
+static gint n_ea_calendar_item_destroyed = 0;
+#endif
 
 static gpointer parent_class = NULL;
 
@@ -44,7 +138,6 @@
 	GTypeQuery query;
 	GType derived_atk_type;
 
-
 	if (!type) {
 		static GTypeInfo tinfo = {
 			sizeof (EaCalendarItemClass),
@@ -59,6 +152,17 @@
 			NULL /* value table */
 		};
 
+		static const GInterfaceInfo atk_table_info = {
+			(GInterfaceInitFunc) atk_table_interface_init,
+			(GInterfaceFinalizeFunc) NULL,
+			NULL
+		};
+		static const GInterfaceInfo atk_selection_info = {
+			(GInterfaceInitFunc) atk_selection_interface_init,
+			(GInterfaceFinalizeFunc) NULL,
+			NULL
+		};
+
 		/*
 		 * Figure out the size of the class and instance
 		 * we are run-time deriving from (GailCanvasItem, in this case)
@@ -74,6 +178,10 @@
 
 		type = g_type_register_static (derived_atk_type,
 					       "EaCalendarItem", &tinfo, 0);
+		g_type_add_interface_static (type, ATK_TYPE_TABLE,
+					     &atk_table_info);
+		g_type_add_interface_static (type, ATK_TYPE_SELECTION,
+					     &atk_selection_info);
 	}
 
 	return type;
@@ -82,12 +190,17 @@
 static void
 ea_calendar_item_class_init (EaCalendarItemClass *klass)
 {
+	GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
 	AtkObjectClass *class = ATK_OBJECT_CLASS (klass);
 
+	gobject_class->finalize = ea_calendar_item_finalize;
 	parent_class = g_type_class_peek_parent (klass);
 
 	class->get_name = ea_calendar_item_get_name;
 	class->get_description = ea_calendar_item_get_description;
+
+	class->get_n_children = ea_calendar_item_get_n_children;
+	class->ref_child = ea_calendar_item_ref_child;
 }
 
 AtkObject* 
@@ -100,13 +213,46 @@
 	object = g_object_new (EA_TYPE_CALENDAR_ITEM, NULL);
 	atk_object = ATK_OBJECT (object);
 	atk_object_initialize (atk_object, obj);
-	atk_object->role = ATK_ROLE_CALENDAR;
+	atk_object->role = ATK_ROLE_TABLE;
 #ifdef ACC_DEBUG
-	g_print ("ea_calendar_item created %p\n", atk_object);
+	++n_ea_calendar_item_created;
+	g_print ("ACC_DEBUG: n_ea_calendar_item_created = %d\n",
+		n_ea_calendar_item_created);
 #endif
+	/* connect signal handlers */
+	g_signal_connect (obj, "selection_preview_changed",
+			  G_CALLBACK (selection_preview_change_cb),
+			  atk_object);
+	g_signal_connect (obj, "date_range_changed",
+			  G_CALLBACK (date_range_changed_cb),
+			  atk_object);
+	g_signal_connect (obj, "selection_preview_changed",
+			  G_CALLBACK (selection_changed_cb),
+			  atk_object);
+
 	return atk_object;
 }
 
+static void
+ea_calendar_item_finalize (GObject *object)
+{
+	EaCalendarItem *ea_calitem;
+
+	g_return_if_fail (EA_IS_CALENDAR_ITEM (object));
+
+	ea_calitem = EA_CALENDAR_ITEM (object);
+
+	/* Free the allocated cell data */
+	ea_calendar_item_destory_cell_data (ea_calitem);
+
+	G_OBJECT_CLASS (parent_class)->finalize (object);
+#ifdef ACC_DEBUG
+	++n_ea_calendar_item_destroyed;
+	printf ("ACC_DEBUG: n_ea_calendar_item_destroyed = %d\n",
+		n_ea_calendar_item_destroyed);
+#endif
+}
+
 static G_CONST_RETURN gchar*
 ea_calendar_item_get_name (AtkObject *accessible)
 {
@@ -114,7 +260,6 @@
 	ECalendarItem *calitem;
 	gint start_year, start_month, start_day;
 	gint end_year, end_month, end_day;
-	GDate select_start, select_end;
 	static gchar new_name[256] = "";
 
 	g_return_val_if_fail (EA_IS_CALENDAR_ITEM (accessible), NULL);
@@ -131,11 +276,14 @@
 					    &end_year, &end_month, &end_day)) {
 		++start_month;
 		++end_month;
-		sprintf (new_name, "calendar date range: from %d-%d-%d to %d-%d-%d.",
+		sprintf (new_name, "calendar (from %d-%d-%d to %d-%d-%d)",
 			 start_year, start_month, start_day,
 			 end_year, end_month, end_day);
 	}
+
+#if 0
 	if (e_calendar_item_get_selection (calitem, &select_start, &select_end)) {
+		GDate select_start, select_end;
 		gint year1, year2, month1, month2, day1, day2;
 
 		year1 = g_date_get_year (&select_start);
@@ -147,10 +295,11 @@
 		day2 = g_date_get_day (&select_end);
 
 		sprintf (new_name + strlen (new_name),
-			 "current selection: from %d-%d-%d to %d-%d-%d.",
+			 " : current selection: from %d-%d-%d to %d-%d-%d.",
 			 year1, month1, day1,
 			 year2, month2, day2);
 	}
+#endif
 
 	return new_name;
 }
@@ -161,5 +310,921 @@
 	if (accessible->description)
 		return accessible->description;
 
-	return "evolution calendar widget";
+	return "evolution calendar item";
+}
+
+static gint
+ea_calendar_item_get_n_children (AtkObject *accessible)
+{
+	AtkGObjectAccessible *atk_gobj;
+	GObject *g_obj;
+	ECalendarItem *calitem;
+	gint n_children = 0;
+	gint start_year, start_month, start_day;
+	gint end_year, end_month, end_day;
+	GDate *start_date, *end_date;
+
+	g_return_val_if_fail (EA_IS_CALENDAR_ITEM (accessible), -1);
+
+	atk_gobj = ATK_GOBJECT_ACCESSIBLE (accessible);
+	g_obj = atk_gobject_accessible_get_object (atk_gobj);
+	if (!g_obj)
+		return -1;
+
+	calitem = E_CALENDAR_ITEM (g_obj);
+	if (!e_calendar_item_get_date_range (calitem, &start_year,
+					     &start_month, &start_day,
+					     &end_year, &end_month,
+					     &end_day))
+		return 0;
+
+	start_date = g_date_new_dmy (start_day, start_month + 1, start_year);
+	end_date = g_date_new_dmy (end_day, end_month + 1, end_year);
+
+	n_children = g_date_days_between (start_date, end_date) + 1;
+	g_free (start_date);
+	g_free (end_date);
+	return n_children;
+}
+
+static AtkObject *
+ea_calendar_item_ref_child (AtkObject *accessible, gint index)
+{
+	AtkGObjectAccessible *atk_gobj;
+	GObject *g_obj;
+	ECalendarItem *calitem;
+	gint n_children;
+	ECalendarCell *cell;
+	EaCellTable *cell_data;
+	EaCalendarItem *ea_calitem;
+
+	g_return_val_if_fail (EA_IS_CALENDAR_ITEM (accessible), NULL);
+
+	atk_gobj = ATK_GOBJECT_ACCESSIBLE (accessible);
+	g_obj = atk_gobject_accessible_get_object (atk_gobj);
+	if (!g_obj)
+		return NULL;
+
+	calitem = E_CALENDAR_ITEM (g_obj);
+
+	n_children = ea_calendar_item_get_n_children (accessible);
+	if (index < 0 || index >= n_children)
+		return NULL;
+
+	ea_calitem = EA_CALENDAR_ITEM (accessible);
+	cell_data = ea_calendar_item_get_cell_data (ea_calitem);
+	if (!cell_data)
+		return NULL;
+
+	cell = ea_cell_table_get_cell_at_index (cell_data, index);
+	if (!cell) {
+		cell = e_calendar_cell_new (calitem,
+					    index / EA_CALENDAR_COLUMN_NUM,
+					    index % EA_CALENDAR_COLUMN_NUM);
+		ea_cell_table_set_cell_at_index (cell_data, index, cell);
+		g_object_unref (cell);
+	}
+
+#ifdef ACC_DEBUG
+	g_print ("AccDebug: ea_calendar_item children[%d]=%p\n", index,
+		 (gpointer)cell);
+#endif
+	return g_object_ref (atk_gobject_accessible_for_object (G_OBJECT(cell)));
+}
+
+/* atk table interface */
+
+static void 
+atk_table_interface_init (AtkTableIface *iface)
+{
+	g_return_if_fail (iface != NULL);
+
+	iface->ref_at = table_interface_ref_at;
+
+	iface->get_n_rows = table_interface_get_n_rows;
+	iface->get_n_columns = table_interface_get_n_columns;
+	iface->get_index_at = table_interface_get_index_at;
+	iface->get_column_at_index = table_interface_get_column_at_index;
+	iface->get_row_at_index = table_interface_get_row_at_index;
+	iface->get_column_extent_at = table_interface_get_column_extent_at;
+	iface->get_row_extent_at = table_interface_get_row_extent_at;
+
+	iface->is_selected = table_interface_is_selected;
+	iface->get_selected_rows = table_interface_get_selected_rows;
+	iface->get_selected_columns = table_interface_get_selected_columns;
+	iface->is_row_selected = table_interface_is_row_selected;
+	iface->is_column_selected = table_interface_is_column_selected;
+	iface->add_row_selection = table_interface_add_row_selection;
+	iface->remove_row_selection = table_interface_remove_row_selection;
+	iface->add_column_selection = table_interface_add_column_selection;
+	iface->remove_column_selection = table_interface_remove_column_selection;
+
+	iface->get_row_header = table_interface_get_row_header;
+	iface->get_column_header = table_interface_get_column_header;
+	iface->get_caption = table_interface_get_caption;
+	iface->get_summary = table_interface_get_summary;
+	iface->get_row_description = table_interface_get_row_description;
+	iface->get_column_description = table_interface_get_column_description;
+}
+
+static AtkObject* 
+table_interface_ref_at (AtkTable *table,
+			gint     row, 
+			gint     column)
+{
+	gint index;
+
+	EaCalendarItem* ea_calitem = EA_CALENDAR_ITEM (table);
+	index = EA_CALENDAR_COLUMN_NUM * row + column;
+	return ea_calendar_item_ref_child (ATK_OBJECT (ea_calitem), index);
+}
+
+static gint 
+table_interface_get_n_rows (AtkTable *table)
+{
+	AtkGObjectAccessible *atk_gobj;
+	GObject *g_obj;
+	EaCalendarItem* ea_calitem = EA_CALENDAR_ITEM (table);
+	gint n_children;
+
+	atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_calitem);
+	g_obj = atk_gobject_accessible_get_object (atk_gobj);
+	if (!g_obj)
+		return -1;
+
+	n_children = ea_calendar_item_get_n_children (ATK_OBJECT (ea_calitem));
+	return (n_children - 1) / EA_CALENDAR_COLUMN_NUM + 1;
+}
+
+static gint 
+table_interface_get_n_columns (AtkTable *table)
+{
+	AtkGObjectAccessible *atk_gobj;
+	GObject *g_obj;
+	EaCalendarItem* ea_calitem = EA_CALENDAR_ITEM (table);
+
+	atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_calitem);
+	g_obj = atk_gobject_accessible_get_object (atk_gobj);
+	if (!g_obj)
+		return -1;
+
+	return EA_CALENDAR_COLUMN_NUM;
+}
+
+static gint
+table_interface_get_index_at (AtkTable *table,
+			      gint     row,
+			      gint     column)
+{
+	AtkGObjectAccessible *atk_gobj;
+	GObject *g_obj;
+	EaCalendarItem* ea_calitem = EA_CALENDAR_ITEM (table);
+
+	atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_calitem);
+	g_obj = atk_gobject_accessible_get_object (atk_gobj);
+	if (!g_obj)
+		return -1;
+
+	return row * EA_CALENDAR_COLUMN_NUM + column;
+}
+
+static gint
+table_interface_get_column_at_index (AtkTable *table,
+				     gint index)
+{
+	AtkGObjectAccessible *atk_gobj;
+	GObject *g_obj;
+	EaCalendarItem* ea_calitem = EA_CALENDAR_ITEM (table);
+	gint n_children;
+
+	atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_calitem);
+	g_obj = atk_gobject_accessible_get_object (atk_gobj);
+	if (!g_obj)
+		return -1;
+
+	n_children = ea_calendar_item_get_n_children (ATK_OBJECT (ea_calitem));
+	if (index >= 0 && index < n_children)
+		return index % EA_CALENDAR_COLUMN_NUM;
+	return -1;
+}
+
+static gint
+table_interface_get_row_at_index (AtkTable *table,
+				  gint     index)
+{
+	AtkGObjectAccessible *atk_gobj;
+	GObject *g_obj;
+	EaCalendarItem* ea_calitem = EA_CALENDAR_ITEM (table);
+	gint n_children;
+
+	atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_calitem);
+	g_obj = atk_gobject_accessible_get_object (atk_gobj);
+	if (!g_obj)
+		return -1;
+
+	n_children = ea_calendar_item_get_n_children (ATK_OBJECT (ea_calitem));
+	if (index >= 0 && index < n_children)
+		return index / EA_CALENDAR_COLUMN_NUM;
+	return -1;
+}
+
+static gint
+table_interface_get_column_extent_at (AtkTable      *table,
+				      gint          row,
+				      gint          column)
+{
+	AtkGObjectAccessible *atk_gobj;
+	GObject *g_obj;
+	ECalendarItem *calitem;
+	EaCalendarItem* ea_calitem = EA_CALENDAR_ITEM (table);
+
+	atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_calitem);
+	g_obj = atk_gobject_accessible_get_object (atk_gobj);
+	if (!g_obj)
+		return FALSE;
+
+	calitem = E_CALENDAR_ITEM (g_obj);
+	return calitem->cell_width;
+}
+
+static gint 
+table_interface_get_row_extent_at (AtkTable *table,
+				   gint row, gint column)
+{
+	AtkGObjectAccessible *atk_gobj;
+	GObject *g_obj;
+	ECalendarItem *calitem;
+	EaCalendarItem* ea_calitem = EA_CALENDAR_ITEM (table);
+
+	atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_calitem);
+	g_obj = atk_gobject_accessible_get_object (atk_gobj);
+	if (!g_obj)
+		return FALSE;
+
+	calitem = E_CALENDAR_ITEM (g_obj);
+	return calitem->cell_height;
+}
+
+/* any day in the row is selected, the row is selected */
+static gboolean 
+table_interface_is_row_selected (AtkTable *table,
+				 gint row)
+{
+	AtkGObjectAccessible *atk_gobj;
+	GObject *g_obj;
+	gint n_rows;
+	ECalendarItem *calitem;
+	gint row_index_start, row_index_end;
+	gint sel_index_start, sel_index_end;
+
+	GDate start_date, end_date;
+
+	g_return_val_if_fail (EA_IS_CALENDAR_ITEM (table), FALSE);
+
+	atk_gobj = ATK_GOBJECT_ACCESSIBLE (table);
+	g_obj = atk_gobject_accessible_get_object (atk_gobj);
+	if (!g_obj)
+		return FALSE;
+
+	n_rows = table_interface_get_n_rows (table);
+	if (row < 0 || row >= n_rows)
+		return FALSE;
+
+	row_index_start = row * EA_CALENDAR_COLUMN_NUM;
+	row_index_end = row_index_start + EA_CALENDAR_COLUMN_NUM - 1;
+
+	calitem = E_CALENDAR_ITEM (g_obj);
+	e_calendar_item_get_selection (calitem, &start_date, &end_date);
+
+	sel_index_start =
+		e_calendar_item_get_offset_for_date (calitem,
+						     g_date_get_year (&start_date),
+						     g_date_get_month (&start_date),
+						     g_date_get_day (&start_date));
+	sel_index_end =
+		e_calendar_item_get_offset_for_date (calitem,
+						     g_date_get_year (&end_date),
+						     g_date_get_month (&end_date),
+						     g_date_get_day (&end_date));
+
+	if ((sel_index_start < row_index_start &&
+	     sel_index_end >= row_index_start) ||
+	    (sel_index_start >= row_index_start &&
+	     sel_index_start <= row_index_end))
+	    return TRUE;
+	return FALSE;
+}
+
+static gboolean 
+table_interface_is_selected (AtkTable *table, 
+			     gint     row, 
+			     gint     column)
+{
+	AtkGObjectAccessible *atk_gobj;
+	GObject *g_obj;
+	gint n_rows, n_columns;
+	ECalendarItem *calitem;
+	gint index;
+	gint sel_index_start, sel_index_end;
+
+	GDate start_date, end_date;
+
+	g_return_val_if_fail (EA_IS_CALENDAR_ITEM (table), FALSE);
+
+	atk_gobj = ATK_GOBJECT_ACCESSIBLE (table);
+	g_obj = atk_gobject_accessible_get_object (atk_gobj);
+	if (!g_obj)
+		return FALSE;
+
+	n_rows = table_interface_get_n_rows (table);
+	if (row < 0 || row >= n_rows)
+		return FALSE;
+	n_columns = table_interface_get_n_columns (table);
+	if (column < 0 || column >= n_columns)
+		return FALSE;
+
+	index = table_interface_get_index_at (table, row, column);
+
+	calitem = E_CALENDAR_ITEM (g_obj);
+	e_calendar_item_get_selection (calitem, &start_date, &end_date);
+
+	sel_index_start =
+		e_calendar_item_get_offset_for_date (calitem,
+						     g_date_get_year (&start_date),
+						     g_date_get_month (&start_date),
+						     g_date_get_day (&start_date));
+	sel_index_end =
+		e_calendar_item_get_offset_for_date (calitem,
+						     g_date_get_year (&end_date),
+						     g_date_get_month (&end_date),
+						     g_date_get_day (&end_date));
+
+	if (sel_index_start <= index && sel_index_end >= index)
+	    return TRUE;
+	return FALSE;
+}
+
+static gboolean 
+table_interface_is_column_selected (AtkTable *table,
+				    gint column)
+{
+	return FALSE;
+}
+
+static gint 
+table_interface_get_selected_rows (AtkTable *table,
+				   gint **rows_selected)
+{
+	*rows_selected = NULL;
+	return -1;
+}
+
+static gint 
+table_interface_get_selected_columns (AtkTable *table,
+				      gint **columns_selected)
+{
+	columns_selected = NULL;
+	return -1;
+}
+
+static gboolean 
+table_interface_add_row_selection (AtkTable *table, 
+				   gint row)
+{
+	return FALSE;
+}
+
+static gboolean 
+table_interface_remove_row_selection (AtkTable *table, 
+				      gint row)
+{
+	return FALSE;
+}
+
+static gboolean 
+table_interface_add_column_selection (AtkTable *table, 
+				      gint column)
+{
+	return FALSE;
+}
+
+static gboolean 
+table_interface_remove_column_selection (AtkTable *table, 
+					 gint     column)
+{
+	/* FIXME: NOT IMPLEMENTED */
+	return FALSE;
+}
+
+static AtkObject* 
+table_interface_get_row_header (AtkTable *table, 
+				gint     row)
+{
+	/* FIXME: NOT IMPLEMENTED */
+	return NULL;
+}
+
+static AtkObject* 
+table_interface_get_column_header (AtkTable *table, 
+				   gint     in_col)
+{
+	/* FIXME: NOT IMPLEMENTED */
+	return NULL;
+}
+
+static AtkObject*
+table_interface_get_caption (AtkTable	*table)
+{
+	/* FIXME: NOT IMPLEMENTED */
+	return NULL;
+}
+
+static G_CONST_RETURN gchar*
+table_interface_get_column_description (AtkTable *table, gint in_col)
+{
+	AtkGObjectAccessible *atk_gobj;
+	GObject *g_obj;
+	ECalendarItem *calitem;
+	EaCalendarItem* ea_calitem = EA_CALENDAR_ITEM (table);
+	const gchar *description = NULL;
+	EaCellTable *cell_data;
+	gint n_columns;
+
+	atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_calitem);
+	g_obj = atk_gobject_accessible_get_object (atk_gobj);
+	if (!g_obj)
+		return NULL;
+
+	calitem = E_CALENDAR_ITEM (g_obj);
+	n_columns = table_interface_get_n_columns (table);
+	if (in_col < 0 || in_col >= n_columns)
+		return NULL;
+	cell_data = ea_calendar_item_get_cell_data (ea_calitem);
+	if (!cell_data)
+		return NULL;
+
+	description = ea_cell_table_get_column_label (cell_data, in_col);
+	if (!description) {
+		gchar buffer[128] = "column description";
+		ea_calendar_item_get_column_label (ea_calitem, in_col,
+						   buffer, sizeof (buffer));
+		ea_cell_table_set_column_label (cell_data, in_col, buffer);
+		description = ea_cell_table_get_column_label (cell_data,
+							      in_col);
+	}
+	return description;
+}
+
+static G_CONST_RETURN gchar*
+table_interface_get_row_description (AtkTable *table, gint row)
+{
+	AtkGObjectAccessible *atk_gobj;
+	GObject *g_obj;
+	ECalendarItem *calitem;
+	EaCalendarItem* ea_calitem = EA_CALENDAR_ITEM (table);
+	const gchar *description = NULL;
+	EaCellTable *cell_data;
+	gint n_rows;
+
+	atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_calitem);
+	g_obj = atk_gobject_accessible_get_object (atk_gobj);
+	if (!g_obj)
+		return NULL;
+
+	calitem = E_CALENDAR_ITEM (g_obj);
+	n_rows = table_interface_get_n_rows (table);
+	if (row < 0 || row >= n_rows)
+		return NULL;
+	cell_data = ea_calendar_item_get_cell_data (ea_calitem);
+	if (!cell_data)
+		return NULL;
+
+	description = ea_cell_table_get_row_label (cell_data, row);
+	if (!description) {
+		gchar buffer[128] = "row description";
+		ea_calendar_item_get_row_label (ea_calitem, row,
+						buffer, sizeof (buffer));
+		ea_cell_table_set_row_label (cell_data, row, buffer);
+		description = ea_cell_table_get_row_label (cell_data,
+							   row);
+	}
+	return description;
+}
+
+static AtkObject*
+table_interface_get_summary (AtkTable	*table)
+{
+	/* FIXME: NOT IMPLEMENTED */
+	return NULL;
+}
+
+/* atkselection interface */
+
+static void
+atk_selection_interface_init (AtkSelectionIface *iface)
+{
+	g_return_if_fail (iface != NULL);
+
+	iface->add_selection = selection_interface_add_selection;
+	iface->clear_selection = selection_interface_clear_selection;
+	iface->ref_selection = selection_interface_ref_selection;
+	iface->get_selection_count = selection_interface_get_selection_count;
+	iface->is_child_selected = selection_interface_is_child_selected;
+}
+
+static gboolean
+selection_interface_add_selection (AtkSelection *selection, gint index)
+{
+	AtkGObjectAccessible *atk_gobj;
+	GObject *g_obj;
+	ECalendarItem *calitem;
+	EaCalendarItem* ea_calitem = EA_CALENDAR_ITEM (selection);
+	gint year, month, day;
+	GDate start_date, end_date;
+
+	atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_calitem);
+	g_obj = atk_gobject_accessible_get_object (atk_gobj);
+	if (!g_obj)
+		return FALSE;
+
+	calitem = E_CALENDAR_ITEM (g_obj);
+	if (!e_calendar_item_get_date_for_offset (calitem, index,
+						  &year, &month, &day))
+		return FALSE;
+
+	/* FIXME: not support mulit-selection */
+	g_date_set_dmy (&start_date, day, month + 1, year);
+	end_date = start_date;
+	e_calendar_item_set_selection (calitem, &start_date, &end_date);
+	return TRUE;
+}
+
+static gboolean
+selection_interface_clear_selection (AtkSelection *selection)
+{
+	AtkGObjectAccessible *atk_gobj;
+	GObject *g_obj;
+	ECalendarItem *calitem;
+	EaCalendarItem* ea_calitem = EA_CALENDAR_ITEM (selection);
+
+	atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_calitem);
+	g_obj = atk_gobject_accessible_get_object (atk_gobj);
+	if (!g_obj)
+		return FALSE;
+
+	calitem = E_CALENDAR_ITEM (g_obj);
+	e_calendar_item_set_selection (calitem, NULL, NULL);
+
+	return TRUE;
+}
+
+static AtkObject*  
+selection_interface_ref_selection (AtkSelection *selection, gint i)
+{
+	if (selection_interface_is_child_selected (selection, i))
+		return ea_calendar_item_ref_child (ATK_OBJECT (selection), i);
+	return NULL;
+}
+
+static gint
+selection_interface_get_selection_count (AtkSelection *selection)
+{
+	AtkGObjectAccessible *atk_gobj;
+	GObject *g_obj;
+	ECalendarItem *calitem;
+	EaCalendarItem* ea_calitem = EA_CALENDAR_ITEM (selection);
+	GDate start_date, end_date;
+
+	atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_calitem);
+	g_obj = atk_gobject_accessible_get_object (atk_gobj);
+	if (!g_obj)
+		return 0;
+
+	calitem = E_CALENDAR_ITEM (g_obj);
+	e_calendar_item_get_selection (calitem, &start_date, &end_date);
+
+	return g_date_days_between (&start_date, &end_date) + 1;
+}
+
+static gboolean
+selection_interface_is_child_selected (AtkSelection *selection, gint index)
+{
+	AtkGObjectAccessible *atk_gobj;
+	GObject *g_obj;
+	ECalendarItem *calitem;
+	EaCalendarItem* ea_calitem = EA_CALENDAR_ITEM (selection);
+	gint row, column, n_children;
+
+	atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_calitem);
+	g_obj = atk_gobject_accessible_get_object (atk_gobj);
+	if (!g_obj)
+		return FALSE;
+
+	calitem = E_CALENDAR_ITEM (g_obj);
+	n_children = atk_object_get_n_accessible_children (ATK_OBJECT (selection));
+	if (index < 0 || index >= n_children)
+		return FALSE;
+
+	row = index / EA_CALENDAR_COLUMN_NUM;
+	column = index % EA_CALENDAR_COLUMN_NUM;
+
+	return table_interface_is_selected (ATK_TABLE (selection), row, column);
+}
+
+/* callbacks */
+
+static void
+selection_preview_change_cb (ECalendarItem *calitem)
+{
+	AtkObject *atk_obj;
+
+	g_return_if_fail (E_IS_CALENDAR_ITEM (calitem));
+	atk_obj = atk_gobject_accessible_for_object (G_OBJECT (calitem));
+
+	g_signal_emit_by_name (atk_obj, "selection_changed");
+}
+
+static void
+date_range_changed_cb (ECalendarItem *calitem)
+{
+	AtkObject *atk_obj;
+
+	g_return_if_fail (E_IS_CALENDAR_ITEM (calitem));
+	atk_obj = atk_gobject_accessible_for_object (G_OBJECT (calitem));
+	ea_calendar_item_destory_cell_data (EA_CALENDAR_ITEM (atk_obj));
+
+	g_signal_emit_by_name (atk_obj, "model_changed");
+}
+
+static void
+selection_changed_cb (ECalendarItem *calitem)
+{
+	selection_preview_change_cb (calitem);
+}
+
+/* helpers */
+
+static EaCellTable *
+ea_calendar_item_get_cell_data (EaCalendarItem *ea_calitem)
+{
+	AtkGObjectAccessible *atk_gobj;
+	GObject *g_obj;
+	ECalendarItem *calitem;
+	EaCellTable *cell_data;
+
+	g_return_val_if_fail (ea_calitem, NULL);
+
+	atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_calitem);
+	g_obj = atk_gobject_accessible_get_object (atk_gobj);
+	if (!g_obj)
+		return NULL;
+
+	calitem = E_CALENDAR_ITEM (g_obj);
+
+	cell_data = g_object_get_data (G_OBJECT(ea_calitem),
+				       "ea-calendar-cell-table");
+
+	if (!cell_data) {
+		gint n_cells = ea_calendar_item_get_n_children (ATK_OBJECT(ea_calitem));
+		cell_data = ea_cell_table_create (n_cells/EA_CALENDAR_COLUMN_NUM,
+						  EA_CALENDAR_COLUMN_NUM,
+						  FALSE);
+		g_object_set_data (G_OBJECT(ea_calitem),
+				   "ea-calendar-cell-table", cell_data);
+	}
+	return cell_data;
+}
+
+static void
+ea_calendar_item_destory_cell_data (EaCalendarItem *ea_calitem)
+{
+	EaCellTable *cell_data;
+
+	g_return_if_fail (ea_calitem);
+
+	cell_data = g_object_get_data (G_OBJECT(ea_calitem),
+				       "ea-calendar-cell-table");
+	if (cell_data) {
+		ea_cell_table_destroy (cell_data);
+		g_object_set_data (G_OBJECT(ea_calitem),
+				   "ea-calendar-cell-table", NULL);
+	}
+}
+
+static gboolean
+ea_calendar_item_get_row_label (EaCalendarItem *ea_calitem, gint row,
+				gchar *buffer, gint buffer_size)
+{
+	AtkGObjectAccessible *atk_gobj;
+	GObject *g_obj;
+	ECalendarItem *calitem;
+	gint index, week_num;
+	gint year, month, day;
+
+	g_return_val_if_fail (ea_calitem, FALSE);
+
+	atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_calitem);
+	g_obj = atk_gobject_accessible_get_object (atk_gobj);
+	if (!g_obj)
+		return FALSE;
+
+	calitem = E_CALENDAR_ITEM (g_obj);
+
+	index = atk_table_get_index_at (ATK_TABLE (ea_calitem), row, 0);
+	if (!e_calendar_item_get_date_for_offset (calitem, index,
+						  &year, &month, &day))
+		return FALSE;
+
+	week_num = e_calendar_item_get_week_number (calitem,
+						    day, month, year);
+
+	g_snprintf (buffer, buffer_size, "week number : %d", week_num);
+	return TRUE;
+}
+
+static gboolean
+ea_calendar_item_get_column_label (EaCalendarItem *ea_calitem, gint column,
+				   gchar *buffer, gint buffer_size)
+{
+	AtkGObjectAccessible *atk_gobj;
+	GObject *g_obj;
+	ECalendarItem *calitem;
+	gchar *week_char;
+	gint char_size;
+
+	g_return_val_if_fail (ea_calitem, FALSE);
+
+	atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_calitem);
+	g_obj = atk_gobject_accessible_get_object (atk_gobj);
+	if (!g_obj)
+		return FALSE;
+
+	calitem = E_CALENDAR_ITEM (g_obj);
+	week_char = g_utf8_offset_to_pointer (calitem->days, column);
+	char_size = strlen (calitem->days) -
+		strlen (g_utf8_find_next_char (calitem->days, NULL));
+
+	if (week_char && char_size < buffer_size) {
+		memcpy (buffer, week_char, char_size);
+		buffer[char_size] = '\0';
+		return TRUE;
+	}
+	return FALSE;
+}
+
+/* the coordinate the e-calendar canvas coord */
+gboolean
+e_calendar_item_get_day_extents (ECalendarItem *calitem,
+				 gint year, gint month, gint date,
+				 gint *x, gint *y,
+				 gint *width, gint *height)
+{
+	GnomeCanvasItem *item;
+	GtkWidget *widget;
+	GtkStyle *style;
+	PangoFontDescription *font_desc;
+	PangoContext *pango_context;
+	PangoFontMetrics *font_metrics;
+	gint char_height, xthickness, ythickness, text_y;
+	gint new_year, new_month, num_months, months_offset;
+	gint month_x, month_y, month_cell_x, month_cell_y;
+	gint month_row, month_col;
+	gint day_row, day_col;
+	gint days_from_week_start;
+
+	g_return_val_if_fail (E_IS_CALENDAR_ITEM (calitem), FALSE);
+
+	item = GNOME_CANVAS_ITEM (calitem);
+	widget = GTK_WIDGET (item->canvas);
+	style = widget->style;
+
+	/* Set up Pango prerequisites */
+	font_desc = calitem->font_desc;
+	if (!font_desc)
+		font_desc = style->font_desc;
+	pango_context = gtk_widget_get_pango_context (widget);
+	font_metrics = pango_context_get_metrics (pango_context, font_desc,
+						  pango_context_get_language (pango_context));
+
+	char_height =
+		PANGO_PIXELS (pango_font_metrics_get_ascent (font_metrics)) +
+		PANGO_PIXELS (pango_font_metrics_get_descent (font_metrics));
+
+	xthickness = style->xthickness;
+	ythickness = style->ythickness;
+
+	new_year = year;
+	new_month = month;
+	e_calendar_item_normalize_date	(calitem, &new_year, &new_month);
+	num_months = calitem->rows * calitem->cols;
+	months_offset = (new_year - calitem->year) * 12
+		+ new_month - calitem->month;
+
+	if (months_offset > num_months || months_offset < 0)
+		return FALSE;
+
+	month_row = months_offset / calitem->cols;
+	month_col = months_offset % calitem->cols;
+
+	month_x = item->x1 + xthickness + calitem->x_offset
+		+ month_col * calitem->month_width;
+	month_y = item->y1 + ythickness + month_row * calitem->month_height;
+
+	month_cell_x = month_x + E_CALENDAR_ITEM_XPAD_BEFORE_WEEK_NUMBERS
+ 		+ calitem->month_lpad + E_CALENDAR_ITEM_XPAD_BEFORE_CELLS;
+	text_y = month_y + ythickness * 2
+		+ E_CALENDAR_ITEM_YPAD_ABOVE_MONTH_NAME
+		+ char_height + E_CALENDAR_ITEM_YPAD_BELOW_MONTH_NAME
+		+ E_CALENDAR_ITEM_YPAD_ABOVE_DAY_LETTERS + calitem->month_tpad;
+
+	month_cell_y = text_y + char_height
+		+ E_CALENDAR_ITEM_YPAD_BELOW_DAY_LETTERS + 1
+		+ E_CALENDAR_ITEM_YPAD_ABOVE_CELLS;
+
+	days_from_week_start =
+		e_calendar_item_get_n_days_from_week_start (calitem, new_year,
+							    new_month);
+	day_row = (date + days_from_week_start - 1) / EA_CALENDAR_COLUMN_NUM;
+	day_col = (date + days_from_week_start - 1) % EA_CALENDAR_COLUMN_NUM;
+
+	*x = month_cell_x + day_col * calitem->cell_width;
+	*y = month_cell_y + day_row * calitem->cell_height;
+	*width = calitem->cell_width;
+	*height = calitem->cell_height;
+
+	return TRUE;
+}
+
+/* month is from 0 to 11 */
+gboolean
+e_calendar_item_get_date_for_offset (ECalendarItem *calitem, gint day_offset,
+				     gint *year, gint *month, gint *day)
+{
+	gint start_year, start_month, start_day;
+	gint end_year, end_month, end_day;
+	GDate *start_date;
+
+	g_return_val_if_fail (E_IS_CALENDAR_ITEM (calitem), FALSE);
+
+	if (!e_calendar_item_get_date_range (calitem, &start_year,
+					     &start_month, &start_day,
+					     &end_year, &end_month,
+					     &end_day))
+		return FALSE;
+
+	start_date = g_date_new_dmy (start_day, start_month + 1, start_year);
+
+	g_date_add_days (start_date, day_offset);
+
+	*year = g_date_get_year (start_date);
+	*month = g_date_get_month (start_date) - 1;
+	*day = g_date_get_day (start_date);
+
+	return TRUE;
+}
+
+/* month is from 0 to 11 */
+gint
+e_calendar_item_get_offset_for_date (ECalendarItem *calitem,
+				     gint year, gint month, gint day)
+{
+	gint start_year, start_month, start_day;
+	gint end_year, end_month, end_day;
+	GDate *start_date, *end_date;
+	gint n_days;
+
+	g_return_val_if_fail (E_IS_CALENDAR_ITEM (calitem), FALSE);
+
+	if (!e_calendar_item_get_date_range (calitem, &start_year,
+					     &start_month, &start_day,
+					     &end_year, &end_month,
+					     &end_day))
+		return FALSE;
+
+	start_date = g_date_new_dmy (start_day, start_month + 1, start_year);
+	end_date = g_date_new_dmy (day, month + 1, year);
+
+	n_days = g_date_days_between (start_date, end_date);
+	g_free (start_date);
+	g_free (end_date);
+	return n_days;
+}
+
+gint
+e_calendar_item_get_n_days_from_week_start (ECalendarItem *calitem,
+					    gint year, gint month)
+{
+	struct tm tmp_tm;
+	gint start_weekday, days_from_week_start;
+
+	memset (&tmp_tm, 0, sizeof (tmp_tm));
+	tmp_tm.tm_year = year - 1900;
+	tmp_tm.tm_mon = month;
+	tmp_tm.tm_mday = 1;
+	tmp_tm.tm_isdst = -1;
+	mktime (&tmp_tm);
+	start_weekday = (tmp_tm.tm_wday + 6) % 7;   /* 0 to 6 */
+	days_from_week_start = (start_weekday + 7 - calitem->week_start_day)
+		% 7;
+	return days_from_week_start;
 }
Index: a11y/widgets/ea-calendar-item.h
===================================================================
RCS file: /cvs/gnome/evolution/a11y/widgets/ea-calendar-item.h,v
retrieving revision 1.1
diff -u -r1.1 ea-calendar-item.h
--- a11y/widgets/ea-calendar-item.h	27 Aug 2003 03:36:42 -0000	1.1
+++ a11y/widgets/ea-calendar-item.h	4 Nov 2003 10:09:05 -0000
@@ -56,6 +56,18 @@
 };
 
 AtkObject *ea_calendar_item_new (GObject *obj);
+gboolean e_calendar_item_get_day_extents (ECalendarItem *calitem,
+					  gint year, gint month, gint date,
+					  gint *x, gint *y,
+					  gint *width, gint *height);
+gboolean e_calendar_item_get_date_for_offset (ECalendarItem *calitem,
+					      gint day_offset,
+					      gint *year, gint *month,
+					      gint *day);
+gint e_calendar_item_get_offset_for_date (ECalendarItem *calitem,
+					  gint year, gint month, gint day);
+gint e_calendar_item_get_n_days_from_week_start (ECalendarItem *calitem,
+						 gint year, gint month);
 
 #ifdef __cplusplus
 }
Index: a11y/widgets/ea-widgets.c
===================================================================
RCS file: /cvs/gnome/evolution/a11y/widgets/ea-widgets.c,v
retrieving revision 1.1
diff -u -r1.1 ea-widgets.c
--- a11y/widgets/ea-widgets.c	27 Aug 2003 03:36:42 -0000	1.1
+++ a11y/widgets/ea-widgets.c	4 Nov 2003 10:09:05 -0000
@@ -27,7 +27,7 @@
 #include "widgets/ea-calendar-item.h"
 #include "ea-widgets.h"
 
-EA_FACTORY_GOBJECT (EA_TYPE_CALENDAR_ITEM, ea_calendar_item, ea_calendar_item_new);
+EA_FACTORY_GOBJECT (EA_TYPE_CALENDAR_ITEM, ea_calendar_item, ea_calendar_item_new)
 
 void e_calendar_item_a11y_init (void)
 {


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]