diff options
Diffstat (limited to 'widgets/misc/e-calendar.c')
-rw-r--r-- | widgets/misc/e-calendar.c | 848 |
1 files changed, 0 insertions, 848 deletions
diff --git a/widgets/misc/e-calendar.c b/widgets/misc/e-calendar.c deleted file mode 100644 index 38336cb618..0000000000 --- a/widgets/misc/e-calendar.c +++ /dev/null @@ -1,848 +0,0 @@ -/* - * This program 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) version 3. - * - * 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see <http://www.gnu.org/licenses/> - * - * - * Authors: - * Damon Chaplin <damon@ximian.com> - * Bolian Yin <bolian.yin@sun.com> - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -/* - * ECalendar - displays a table of monthly calendars, allowing highlighting - * and selection of one or more days. Like GtkCalendar with more features. - * Most of the functionality is in the ECalendarItem canvas item, though - * we also add GnomeCanvasWidget buttons to go to the previous/next month and - * to got to the current day. - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include "e-calendar.h" - -#include <gtk/gtk.h> -#include <libgnomecanvas/gnome-canvas-widget.h> -#include <glib/gi18n.h> - -#define E_CALENDAR_SMALL_FONT_PTSIZE 6 - -#define E_CALENDAR_SMALL_FONT \ - "-adobe-utopia-regular-r-normal-*-*-100-*-*-p-*-iso8859-*" -#define E_CALENDAR_SMALL_FONT_FALLBACK \ - "-adobe-helvetica-medium-r-normal-*-*-80-*-*-p-*-iso8859-*" - -/* The space between the arrow buttons and the edge of the widget. */ -#define E_CALENDAR_ARROW_BUTTON_X_PAD 2 -#define E_CALENDAR_ARROW_BUTTON_Y_PAD 0 - -/* Vertical padding. The padding above the button includes the space for the - * horizontal line. */ -#define E_CALENDAR_YPAD_ABOVE_LOWER_BUTTONS 4 -#define E_CALENDAR_YPAD_BELOW_LOWER_BUTTONS 3 - -/* Horizontal padding inside & between buttons. */ -#define E_CALENDAR_IXPAD_BUTTONS 4 -#define E_CALENDAR_XPAD_BUTTONS 8 - -/* The time between steps when the prev/next buttons is pressed, in 1/1000ths - * of a second, and the number of timeouts we skip before we start - * automatically moving back/forward. */ -#define E_CALENDAR_AUTO_MOVE_TIMEOUT 150 -#define E_CALENDAR_AUTO_MOVE_TIMEOUT_DELAY 2 - -static void e_calendar_dispose (GObject *object); -static void e_calendar_realize (GtkWidget *widget); -static void e_calendar_style_set (GtkWidget *widget, - GtkStyle *previous_style); -static void e_calendar_get_preferred_width (GtkWidget *widget, - gint *minimal_width, - gint *natural_width); -static void e_calendar_get_preferred_height (GtkWidget *widget, - gint *minimal_height, - gint *natural_height); -static void e_calendar_size_allocate (GtkWidget *widget, - GtkAllocation *allocation); -static gint e_calendar_drag_motion (GtkWidget *widget, - GdkDragContext *context, - gint x, - gint y, - guint time); -static void e_calendar_drag_leave (GtkWidget *widget, - GdkDragContext *context, - guint time); -static gboolean e_calendar_button_has_focus (ECalendar *cal); -static gboolean e_calendar_focus (GtkWidget *widget, - GtkDirectionType direction); - -static void e_calendar_on_prev_pressed (ECalendar *cal); -static void e_calendar_on_prev_released (ECalendar *cal); -static void e_calendar_on_prev_clicked (ECalendar *cal); -static void e_calendar_on_next_pressed (ECalendar *cal); -static void e_calendar_on_next_released (ECalendar *cal); -static void e_calendar_on_next_clicked (ECalendar *cal); -static void e_calendar_on_prev_year_pressed (ECalendar *cal); -static void e_calendar_on_prev_year_released (ECalendar *cal); -static void e_calendar_on_prev_year_clicked (ECalendar *cal); -static void e_calendar_on_next_year_pressed (ECalendar *cal); -static void e_calendar_on_next_year_released (ECalendar *cal); -static void e_calendar_on_next_year_clicked (ECalendar *cal); - -static void e_calendar_start_auto_move (ECalendar *cal, - gboolean moving_forward); -static gboolean e_calendar_auto_move_handler (gpointer data); -static void e_calendar_start_auto_move_year (ECalendar *cal, - gboolean moving_forward); -static gboolean e_calendar_auto_move_year_handler (gpointer data); -static void e_calendar_stop_auto_move (ECalendar *cal); - -G_DEFINE_TYPE ( - ECalendar, - e_calendar, - E_TYPE_CANVAS) - -static void -e_calendar_class_init (ECalendarClass *class) -{ - GObjectClass *object_class; - GtkWidgetClass *widget_class; - - object_class = (GObjectClass *) class; - widget_class = (GtkWidgetClass *) class; - - object_class->dispose = e_calendar_dispose; - - widget_class->realize = e_calendar_realize; - widget_class->style_set = e_calendar_style_set; - widget_class->get_preferred_width = e_calendar_get_preferred_width; - widget_class->get_preferred_height = e_calendar_get_preferred_height; - widget_class->size_allocate = e_calendar_size_allocate; - widget_class->drag_motion = e_calendar_drag_motion; - widget_class->drag_leave = e_calendar_drag_leave; - widget_class->focus = e_calendar_focus; -} - -static void -e_calendar_init (ECalendar *cal) -{ - GnomeCanvasGroup *canvas_group; - PangoFontDescription *small_font_desc; - GtkWidget *button, *pixmap; - AtkObject *a11y; - - /* Create the small font. */ - - small_font_desc = pango_font_description_copy ( - gtk_widget_get_style (GTK_WIDGET (cal))->font_desc); - pango_font_description_set_size ( - small_font_desc, - E_CALENDAR_SMALL_FONT_PTSIZE * PANGO_SCALE); - - canvas_group = GNOME_CANVAS_GROUP (GNOME_CANVAS (cal)->root); - - cal->calitem = E_CALENDAR_ITEM ( - gnome_canvas_item_new ( - canvas_group, - e_calendar_item_get_type (), - "week_number_font_desc", small_font_desc, - NULL)); - - pango_font_description_free (small_font_desc); - - /* Create the arrow buttons to move to the previous/next month. */ - button = gtk_button_new (); - gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE); - gtk_widget_show (button); - g_signal_connect_swapped ( - button, "pressed", - G_CALLBACK (e_calendar_on_prev_pressed), cal); - g_signal_connect_swapped ( - button, "released", - G_CALLBACK (e_calendar_on_prev_released), cal); - g_signal_connect_swapped ( - button, "clicked", - G_CALLBACK (e_calendar_on_prev_clicked), cal); - - pixmap = gtk_arrow_new (GTK_ARROW_LEFT, GTK_SHADOW_NONE); - gtk_widget_show (pixmap); - gtk_container_add (GTK_CONTAINER (button), pixmap); - - cal->prev_item = gnome_canvas_item_new ( - canvas_group, - gnome_canvas_widget_get_type (), - "widget", button, - NULL); - a11y = gtk_widget_get_accessible (button); - atk_object_set_name (a11y, _("Previous month")); - - button = gtk_button_new (); - gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE); - gtk_widget_show (button); - g_signal_connect_swapped ( - button, "pressed", - G_CALLBACK (e_calendar_on_next_pressed), cal); - g_signal_connect_swapped ( - button, "released", - G_CALLBACK (e_calendar_on_next_released), cal); - g_signal_connect_swapped ( - button, "clicked", - G_CALLBACK (e_calendar_on_next_clicked), cal); - - pixmap = gtk_arrow_new (GTK_ARROW_RIGHT, GTK_SHADOW_NONE); - gtk_widget_show (pixmap); - gtk_container_add (GTK_CONTAINER (button), pixmap); - - cal->next_item = gnome_canvas_item_new ( - canvas_group, - gnome_canvas_widget_get_type (), - "widget", button, - NULL); - a11y = gtk_widget_get_accessible (button); - atk_object_set_name (a11y, _("Next month")); - - /* Create the arrow buttons to move to the previous/next year. */ - button = gtk_button_new (); - gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE); - gtk_widget_show (button); - g_signal_connect_swapped ( - button, "pressed", - G_CALLBACK (e_calendar_on_prev_year_pressed), cal); - g_signal_connect_swapped ( - button, "released", - G_CALLBACK (e_calendar_on_prev_year_released), cal); - g_signal_connect_swapped ( - button, "clicked", - G_CALLBACK (e_calendar_on_prev_year_clicked), cal); - - pixmap = gtk_arrow_new (GTK_ARROW_LEFT, GTK_SHADOW_NONE); - gtk_widget_show (pixmap); - gtk_container_add (GTK_CONTAINER (button), pixmap); - - cal->prev_item_year = gnome_canvas_item_new ( - canvas_group, - gnome_canvas_widget_get_type (), - "widget", button, - NULL); - a11y = gtk_widget_get_accessible (button); - atk_object_set_name (a11y, _("Previous year")); - - button = gtk_button_new (); - gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE); - gtk_widget_show (button); - g_signal_connect_swapped ( - button, "pressed", - G_CALLBACK (e_calendar_on_next_year_pressed), cal); - g_signal_connect_swapped ( - button, "released", - G_CALLBACK (e_calendar_on_next_year_released), cal); - g_signal_connect_swapped ( - button, "clicked", - G_CALLBACK (e_calendar_on_next_year_clicked), cal); - - pixmap = gtk_arrow_new (GTK_ARROW_RIGHT, GTK_SHADOW_NONE); - gtk_widget_show (pixmap); - gtk_container_add (GTK_CONTAINER (button), pixmap); - - cal->next_item_year = gnome_canvas_item_new ( - canvas_group, - gnome_canvas_widget_get_type (), - "widget", button, - NULL); - a11y = gtk_widget_get_accessible (button); - atk_object_set_name (a11y, _("Next year")); - - cal->min_rows = 1; - cal->min_cols = 1; - cal->max_rows = -1; - cal->max_cols = -1; - - cal->timeout_id = 0; -} - -/** - * e_calendar_new: - * @Returns: a new #ECalendar. - * - * Creates a new #ECalendar. - **/ -GtkWidget * -e_calendar_new (void) -{ - GtkWidget *cal; - AtkObject *a11y; - - cal = g_object_new (e_calendar_get_type (), NULL); - a11y = gtk_widget_get_accessible (cal); - atk_object_set_name (a11y, _("Month Calendar")); - - return cal; -} - -static void -e_calendar_dispose (GObject *object) -{ - ECalendar *cal; - - g_return_if_fail (object != NULL); - g_return_if_fail (E_IS_CALENDAR (object)); - - cal = E_CALENDAR (object); - - if (cal->timeout_id != 0) { - g_source_remove (cal->timeout_id); - cal->timeout_id = 0; - } - - /* Chain up to parent's dispose() method. */ - G_OBJECT_CLASS (e_calendar_parent_class)->dispose (object); -} - -static void -e_calendar_realize (GtkWidget *widget) -{ - GtkStyle *style; - GdkWindow *window; - - (*GTK_WIDGET_CLASS (e_calendar_parent_class)->realize) (widget); - - /* Set the background of the canvas window to the normal color, - * or the arrow buttons are not displayed properly. */ - style = gtk_widget_get_style (widget); - window = gtk_layout_get_bin_window (GTK_LAYOUT (widget)); - gdk_window_set_background (window, &style->bg[GTK_STATE_NORMAL]); -} - -static void -e_calendar_style_set (GtkWidget *widget, - GtkStyle *previous_style) -{ - ECalendar *e_calendar; - - e_calendar = E_CALENDAR (widget); - if (GTK_WIDGET_CLASS (e_calendar_parent_class)->style_set) - (*GTK_WIDGET_CLASS (e_calendar_parent_class)->style_set) (widget, - previous_style); - - /* Set the background of the canvas window to the normal color, - * or the arrow buttons are not displayed properly. */ - if (gtk_widget_get_realized (widget)) { - GtkStyle *style; - GdkWindow *window; - - style = gtk_widget_get_style (widget); - window = gtk_layout_get_bin_window (GTK_LAYOUT (widget)); - gdk_window_set_background (window, &style->bg[GTK_STATE_NORMAL]); - } - e_calendar_item_style_set (widget, e_calendar->calitem); -} - -static void -e_calendar_get_preferred_width (GtkWidget *widget, - gint *minimum, - gint *natural) -{ - ECalendar *cal; - GtkStyle *style; - gint col_width; - - cal = E_CALENDAR (widget); - style = gtk_widget_get_style (GTK_WIDGET (cal)); - - g_object_get ((cal->calitem), "column_width", &col_width, NULL); - - *minimum = *natural = col_width * cal->min_cols + style->xthickness * 2; -} - -static void -e_calendar_get_preferred_height (GtkWidget *widget, - gint *minimum, - gint *natural) -{ - ECalendar *cal; - GtkStyle *style; - gint row_height; - - cal = E_CALENDAR (widget); - style = gtk_widget_get_style (GTK_WIDGET (cal)); - - g_object_get ((cal->calitem), "row_height", &row_height, NULL); - - *minimum = *natural = row_height * cal->min_rows + style->ythickness * 2; -} - -static void -e_calendar_size_allocate (GtkWidget *widget, - GtkAllocation *allocation) -{ - ECalendar *cal; - GtkStyle *style; - GtkAllocation old_allocation; - PangoFontDescription *font_desc; - PangoContext *pango_context; - PangoFontMetrics *font_metrics; - gdouble old_x2, old_y2, new_x2, new_y2; - gdouble xthickness, ythickness, arrow_button_size, current_x, month_width; - gboolean is_rtl; - - cal = E_CALENDAR (widget); - style = gtk_widget_get_style (widget); - xthickness = style->xthickness; - ythickness = style->ythickness; - - (*GTK_WIDGET_CLASS (e_calendar_parent_class)->size_allocate) (widget, allocation); - - /* Set up Pango prerequisites */ - font_desc = gtk_widget_get_style (widget)->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)); - - /* Set the scroll region to its allocated size, if changed. */ - gnome_canvas_get_scroll_region ( - GNOME_CANVAS (cal), - NULL, NULL, &old_x2, &old_y2); - gtk_widget_get_allocation (widget, &old_allocation); - new_x2 = old_allocation.width - 1; - new_y2 = old_allocation.height - 1; - if (old_x2 != new_x2 || old_y2 != new_y2) - gnome_canvas_set_scroll_region ( - GNOME_CANVAS (cal), - 0, 0, new_x2, new_y2); - - /* Take off space for line & buttons if shown. */ - gnome_canvas_item_set ( - GNOME_CANVAS_ITEM (cal->calitem), - "x1", 0.0, - "y1", 0.0, - "x2", new_x2, - "y2", new_y2, - NULL); - - if (cal->calitem->month_width > 0) - month_width = cal->calitem->month_width; - else - month_width = new_x2; - month_width -= E_CALENDAR_ITEM_MIN_CELL_XPAD + E_CALENDAR_ARROW_BUTTON_X_PAD; - - /* Position the arrow buttons. */ - arrow_button_size = - PANGO_PIXELS (pango_font_metrics_get_ascent (font_metrics)) - + PANGO_PIXELS (pango_font_metrics_get_descent (font_metrics)) - + E_CALENDAR_ITEM_YPAD_ABOVE_MONTH_NAME - + E_CALENDAR_ITEM_YPAD_BELOW_MONTH_NAME - - E_CALENDAR_ARROW_BUTTON_Y_PAD * 2 - 2; - - is_rtl = gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL; - current_x = is_rtl ? - (month_width - 2 * xthickness - E_CALENDAR_ARROW_BUTTON_X_PAD - arrow_button_size) : - (xthickness); - - gnome_canvas_item_set ( - cal->prev_item, - "x", current_x, - "y", ythickness + E_CALENDAR_ARROW_BUTTON_Y_PAD, - "width", arrow_button_size, - "height", arrow_button_size, - NULL); - - current_x += (is_rtl ? -1.0 : +1.0) * (cal->calitem->max_month_name_width - xthickness + 2 * arrow_button_size); - - gnome_canvas_item_set ( - cal->next_item, - "x", current_x, - "y", ythickness + E_CALENDAR_ARROW_BUTTON_Y_PAD, - "width", arrow_button_size, - "height", arrow_button_size, - NULL); - - current_x = is_rtl ? - (xthickness) : - (month_width - 2 * xthickness - E_CALENDAR_ARROW_BUTTON_X_PAD - arrow_button_size); - - gnome_canvas_item_set ( - cal->next_item_year, - "x", current_x, - "y", ythickness + E_CALENDAR_ARROW_BUTTON_Y_PAD, - "width", arrow_button_size, - "height", arrow_button_size, - NULL); - - current_x += (is_rtl ? +1.0 : -1.0) * (cal->calitem->max_digit_width * 5 - xthickness + 2 * arrow_button_size); - - gnome_canvas_item_set ( - cal->prev_item_year, - "x", current_x, - "y", ythickness + E_CALENDAR_ARROW_BUTTON_Y_PAD, - "width", arrow_button_size, - "height", arrow_button_size, - NULL); - - pango_font_metrics_unref (font_metrics); -} - -void -e_calendar_set_minimum_size (ECalendar *cal, - gint rows, - gint cols) -{ - g_return_if_fail (E_IS_CALENDAR (cal)); - - cal->min_rows = rows; - cal->min_cols = cols; - - gnome_canvas_item_set ( - GNOME_CANVAS_ITEM (cal->calitem), - "minimum_rows", rows, - "minimum_columns", cols, - NULL); - - gtk_widget_queue_resize (GTK_WIDGET (cal)); -} - -void -e_calendar_set_maximum_size (ECalendar *cal, - gint rows, - gint cols) -{ - g_return_if_fail (E_IS_CALENDAR (cal)); - - cal->max_rows = rows; - cal->max_cols = cols; - - gnome_canvas_item_set ( - GNOME_CANVAS_ITEM (cal->calitem), - "maximum_rows", rows, - "maximum_columns", cols, - NULL); - - gtk_widget_queue_resize (GTK_WIDGET (cal)); -} - -/* Returns the border size on each side of the month displays. */ -void -e_calendar_get_border_size (ECalendar *cal, - gint *top, - gint *bottom, - gint *left, - gint *right) -{ - GtkStyle *style; - - g_return_if_fail (E_IS_CALENDAR (cal)); - - style = gtk_widget_get_style (GTK_WIDGET (cal)); - - if (style) { - *top = style->ythickness; - *bottom = style->ythickness; - *left = style->xthickness; - *right = style->xthickness; - } else { - *top = *bottom = *left = *right = 0; - } -} - -static void -e_calendar_on_prev_pressed (ECalendar *cal) -{ - e_calendar_start_auto_move (cal, FALSE); -} - -static void -e_calendar_on_next_pressed (ECalendar *cal) -{ - e_calendar_start_auto_move (cal, TRUE); -} - -static void -e_calendar_on_prev_year_pressed (ECalendar *cal) -{ - e_calendar_start_auto_move_year (cal, FALSE); -} - -static void -e_calendar_on_next_year_pressed (ECalendar *cal) -{ - e_calendar_start_auto_move_year (cal, TRUE); -} - -static void -e_calendar_start_auto_move (ECalendar *cal, - gboolean moving_forward) -{ - if (cal->timeout_id == 0) { - cal->timeout_id = g_timeout_add ( - E_CALENDAR_AUTO_MOVE_TIMEOUT, - e_calendar_auto_move_handler, - cal); - } - cal->timeout_delay = E_CALENDAR_AUTO_MOVE_TIMEOUT_DELAY; - cal->moving_forward = moving_forward; - -} - -static void -e_calendar_start_auto_move_year (ECalendar *cal, - gboolean moving_forward) -{ - if (cal->timeout_id == 0) { - cal->timeout_id = g_timeout_add ( - E_CALENDAR_AUTO_MOVE_TIMEOUT, - e_calendar_auto_move_year_handler, - cal); - } - cal->timeout_delay = E_CALENDAR_AUTO_MOVE_TIMEOUT_DELAY; - cal->moving_forward = moving_forward; -} - -static gboolean -e_calendar_auto_move_year_handler (gpointer data) -{ - ECalendar *cal; - ECalendarItem *calitem; - gint offset; - - g_return_val_if_fail (E_IS_CALENDAR (data), FALSE); - - cal = E_CALENDAR (data); - calitem = cal->calitem; - - if (cal->timeout_delay > 0) { - cal->timeout_delay--; - } else { - offset = cal->moving_forward ? 12 : -12; - e_calendar_item_set_first_month ( - calitem, calitem->year, - calitem->month + offset); - } - - return TRUE; -} - -static gboolean -e_calendar_auto_move_handler (gpointer data) -{ - ECalendar *cal; - ECalendarItem *calitem; - gint offset; - - g_return_val_if_fail (E_IS_CALENDAR (data), FALSE); - - cal = E_CALENDAR (data); - calitem = cal->calitem; - - if (cal->timeout_delay > 0) { - cal->timeout_delay--; - } else { - offset = cal->moving_forward ? 1 : -1; - e_calendar_item_set_first_month ( - calitem, calitem->year, - calitem->month + offset); - } - - return TRUE; -} - -static void -e_calendar_on_prev_released (ECalendar *cal) -{ - e_calendar_stop_auto_move (cal); -} - -static void -e_calendar_on_next_released (ECalendar *cal) -{ - e_calendar_stop_auto_move (cal); -} - -static void -e_calendar_on_prev_year_released (ECalendar *cal) -{ - e_calendar_stop_auto_move (cal); -} - -static void -e_calendar_on_next_year_released (ECalendar *cal) -{ - e_calendar_stop_auto_move (cal); -} - -static void -e_calendar_stop_auto_move (ECalendar *cal) -{ - if (cal->timeout_id != 0) { - g_source_remove (cal->timeout_id); - cal->timeout_id = 0; - } -} - -static void -e_calendar_on_prev_clicked (ECalendar *cal) -{ - e_calendar_item_set_first_month ( - cal->calitem, cal->calitem->year, - cal->calitem->month - 1); -} - -static void -e_calendar_on_next_clicked (ECalendar *cal) -{ - e_calendar_item_set_first_month ( - cal->calitem, cal->calitem->year, - cal->calitem->month + 1); -} - -static void -e_calendar_on_prev_year_clicked (ECalendar *cal) -{ - e_calendar_item_set_first_month ( - cal->calitem, cal->calitem->year, - cal->calitem->month - 12); -} - -static void -e_calendar_on_next_year_clicked (ECalendar *cal) -{ - e_calendar_item_set_first_month ( - cal->calitem, cal->calitem->year, - cal->calitem->month + 12); -} - -static gint -e_calendar_drag_motion (GtkWidget *widget, - GdkDragContext *context, - gint x, - gint y, - guint time) -{ - return FALSE; -} - -static void -e_calendar_drag_leave (GtkWidget *widget, - GdkDragContext *context, - guint time) -{ -} - -static gboolean -e_calendar_button_has_focus (ECalendar *cal) -{ - GtkWidget *prev_widget, *next_widget; - gboolean ret_val; - - g_return_val_if_fail (E_IS_CALENDAR (cal), FALSE); - - prev_widget = GNOME_CANVAS_WIDGET (cal->prev_item)->widget; - next_widget = GNOME_CANVAS_WIDGET (cal->next_item)->widget; - ret_val = gtk_widget_has_focus (prev_widget) || - gtk_widget_has_focus (next_widget); - return ret_val; -} - -static gboolean -e_calendar_focus (GtkWidget *widget, - GtkDirectionType direction) -{ -#define E_CALENDAR_FOCUS_CHILDREN_NUM 5 - ECalendar *cal; - GnomeCanvas *canvas; - GnomeCanvasItem *children[E_CALENDAR_FOCUS_CHILDREN_NUM]; - gint focused_index = -1; - gint index; - - g_return_val_if_fail (widget != NULL, FALSE); - g_return_val_if_fail (E_IS_CALENDAR (widget), FALSE); - cal = E_CALENDAR (widget); - canvas = GNOME_CANVAS (widget); - - if (!gtk_widget_get_can_focus (widget)) - return FALSE; - - children[0] = GNOME_CANVAS_ITEM (cal->calitem); - children[1] = cal->prev_item; - children[2] = cal->next_item; - children[3] = cal->prev_item_year; - children[4] = cal->next_item_year; - - /* get current focused item, if e-calendar has had focus */ - if (gtk_widget_has_focus (widget) || e_calendar_button_has_focus (cal)) - for (index = 0; index < E_CALENDAR_FOCUS_CHILDREN_NUM; ++index) { - if (canvas->focused_item == NULL) - break; - - if (children[index] == canvas->focused_item) { - focused_index = index; - break; - } - } - - if (focused_index == -1) - if (direction == GTK_DIR_TAB_FORWARD) - focused_index = 0; - else - focused_index = E_CALENDAR_FOCUS_CHILDREN_NUM - 1; - else - if (direction == GTK_DIR_TAB_FORWARD) - ++focused_index; - else - --focused_index; - - if (focused_index < 0 || - focused_index >= E_CALENDAR_FOCUS_CHILDREN_NUM) - /* move out of e-calendar */ - return FALSE; - gnome_canvas_item_grab_focus (children[focused_index]); - if (GNOME_IS_CANVAS_WIDGET (children[focused_index])) { - widget = GNOME_CANVAS_WIDGET (children[focused_index])->widget; - gtk_widget_grab_focus (widget); - } - return TRUE; -} - -void -e_calendar_set_focusable (ECalendar *cal, - gboolean focusable) -{ - GtkWidget *widget; - GtkWidget *prev_widget, *next_widget; - GtkWidget *toplevel; - - g_return_if_fail (E_IS_CALENDAR (cal)); - - widget = GTK_WIDGET (cal); - prev_widget = GNOME_CANVAS_WIDGET (cal->prev_item)->widget; - next_widget = GNOME_CANVAS_WIDGET (cal->next_item)->widget; - - if (focusable) { - gtk_widget_set_can_focus (widget, TRUE); - gtk_widget_set_can_focus (prev_widget, TRUE); - gtk_widget_set_can_focus (next_widget, TRUE); - } - else { - if (gtk_widget_has_focus (GTK_WIDGET (cal)) || - e_calendar_button_has_focus (cal)) { - toplevel = gtk_widget_get_toplevel (widget); - if (toplevel) - gtk_widget_grab_focus (toplevel); - } - gtk_widget_set_can_focus (widget, FALSE); - gtk_widget_set_can_focus (prev_widget, FALSE); - gtk_widget_set_can_focus (next_widget, FALSE); - } -} |