diff options
This commit was manufactured by cvs2svn to create tagMERGE_TO_HEAD_1
'MERGE_TO_HEAD_1'.
svn path=/tags/MERGE_TO_HEAD_1/; revision=12887
Diffstat (limited to 'widgets/meeting-time-sel')
-rw-r--r-- | widgets/meeting-time-sel/.cvsignore | 8 | ||||
-rw-r--r-- | widgets/meeting-time-sel/ChangeLog | 82 | ||||
-rw-r--r-- | widgets/meeting-time-sel/LICENSE | 1 | ||||
-rw-r--r-- | widgets/meeting-time-sel/Makefile.am | 35 | ||||
-rw-r--r-- | widgets/meeting-time-sel/e-meeting-time-sel-item.c | 993 | ||||
-rw-r--r-- | widgets/meeting-time-sel/e-meeting-time-sel-item.h | 79 | ||||
-rw-r--r-- | widgets/meeting-time-sel/e-meeting-time-sel-list-item.c | 397 | ||||
-rw-r--r-- | widgets/meeting-time-sel/e-meeting-time-sel-list-item.h | 73 | ||||
-rw-r--r-- | widgets/meeting-time-sel/e-meeting-time-sel-mail.xpm | 135 | ||||
-rw-r--r-- | widgets/meeting-time-sel/e-meeting-time-sel-no-mail.xpm | 123 | ||||
-rw-r--r-- | widgets/meeting-time-sel/e-meeting-time-sel.c | 3308 | ||||
-rw-r--r-- | widgets/meeting-time-sel/e-meeting-time-sel.h | 521 | ||||
-rw-r--r-- | widgets/meeting-time-sel/test-meeting-time-sel.c | 252 |
13 files changed, 0 insertions, 6007 deletions
diff --git a/widgets/meeting-time-sel/.cvsignore b/widgets/meeting-time-sel/.cvsignore deleted file mode 100644 index 50530fdf4e..0000000000 --- a/widgets/meeting-time-sel/.cvsignore +++ /dev/null @@ -1,8 +0,0 @@ -.deps -.libs -.pure -Makefile -Makefile.in -*.lo -*.la -test-meeting-time-selector diff --git a/widgets/meeting-time-sel/ChangeLog b/widgets/meeting-time-sel/ChangeLog deleted file mode 100644 index f2598d9fa2..0000000000 --- a/widgets/meeting-time-sel/ChangeLog +++ /dev/null @@ -1,82 +0,0 @@ -2001-05-04 JP Rosevear <jpr@ximian.com> - - * e-meeting-time-sel-list-item.c - (e_meeting_time_selector_list_item_destroy): correct type where - same pixmap mask was unreffed twice - -2001-04-24 Kjartan Maraas <kmaraas@gnome.org> - - * e-meeting-time-sel.c, test-meeting-time-sel.c: Added #include - <glib.h>. - -2001-04-08 Federico Mena Quintero <federico@ximian.com> - - * e-meeting-time-sel-item.c (e_meeting_time_selector_item_init): - Use a pretty arrow instead of GDK_TOP_LEFT_ARROW. - -2001-04-04 Kjartan Maraas <kmaraas@gnome.org> - - * e-meeting-time-sel-item.c: Fix headers. - * e-meeting-time-sel-list-item.c: Same here. - * e-meeting-time-sel.[ch]: Same here. - * test-meeting-time-sel.c: Same here. - -2001-03-29 Larry Ewing <lewing@ximian.com> - - * e-meeting-time-sel-list-item.c: s/#include/#ifdef/ to fix - Kjartan's commit. - -2001-03-29 Kjartan Maraas <kmaraas@gnome.org> - - * e-meeting-time-sel-item.c: #ifdef HAVE_CONFIG_H - * e-meeting-time-sel-list-item.c: Same here. - * e-meeting-time-sel.c: Same here. - * test-meeting-time-sel.c: And here. - -2001-03-15 Dan Winship <danw@ximian.com> - - * e-meeting-time-sel.c - (e_meeting_time_selector_on_text_item_event): - * e-meeting-time-sel-list-item.c - (e_meeting_time_selector_list_item_button_press): Update arguments - to e_canvas_item_grab_focus. - -2000-12-25 Miguel de Icaza <miguel@helixcode.com> - - * e-meeting-time-sel.c (e_meeting_time_selector_attendee_add): Set - draw_background to FALSE. - -2000-12-06 Christopher James Lahey <clahey@helixcode.com> - - * e-meeting-time-sel.c: Fixed a bunch of warnings. - -2000-09-25 Damon Chaplin <damon@helixcode.com> - - * e-meeting-time-sel-item.c: - * e-meeting-time-sel.c: fixed use of date strings to support i18n - better. - (e_meeting_time_selector_update_attendees_list_positions): updated to - use e_canvas_item_move_absolute() to position the EText items. - -2000-09-18 Christopher James Lahey <clahey@helixcode.com> - - * Makefile.am: Added $(EXTRA_GNOME_CFLAGS) and - $(EXTRA_GNOME_LIBS). Removed unneeded libraries. - - * e-meeting-time-sel-list-item.c, e-meeting-time-sel.c, - e-meeting-time-sel.h: Fixed the #include lines to deal properly - with gal. - -2000-09-06 Ettore Perazzoli <ettore@helixcode.com> - - * Makefile.am (INCLUDES): Add `$(EXTRA_GNOME_CFLAGS)'. - -2000-06-26 Christopher James Lahey <clahey@helixcode.com> - - * Makefile.am: Added the include path to top_srcdir. - -2000-06-25 Ettore Perazzoli <ettore@helixcode.com> - - * e-meeting-time-sel.c: Specify the #include path for - `e-canvas-utils.h' so that we build with builddir != srcdir. - diff --git a/widgets/meeting-time-sel/LICENSE b/widgets/meeting-time-sel/LICENSE deleted file mode 100644 index 9babf4395f..0000000000 --- a/widgets/meeting-time-sel/LICENSE +++ /dev/null @@ -1 +0,0 @@ -This code is licensed under the terms of the GNU GPL diff --git a/widgets/meeting-time-sel/Makefile.am b/widgets/meeting-time-sel/Makefile.am deleted file mode 100644 index 767de5cd86..0000000000 --- a/widgets/meeting-time-sel/Makefile.am +++ /dev/null @@ -1,35 +0,0 @@ - -INCLUDES = \ - $(EXTRA_GNOME_CFLAGS) \ - $(GNOME_INCLUDEDIR) \ - -I $(top_srcdir) \ - -DG_LOG_DOMAIN=\"meeting-time-sel\" - -noinst_LIBRARIES = \ - libevolutionmtsel.a - -libevolutionmtsel_a_SOURCES = \ - e-meeting-time-sel.c \ - e-meeting-time-sel.h \ - e-meeting-time-sel-item.c \ - e-meeting-time-sel-item.h \ - e-meeting-time-sel-list-item.c \ - e-meeting-time-sel-list-item.h - -noinst_PROGRAMS = \ - test-meeting-time-selector - -test_meeting_time_selector_SOURCES = \ - test-meeting-time-sel.c - -test_meeting_time_selector_LDADD = \ - libevolutionmtsel.a \ - $(EXTRA_GNOME_LIBS) \ - $(GNOMEUI_LIBS) - -test_meeting_time_selector_LDFLAGS = $(GNOME_LIBDIR) - -EXTRA_DIST = \ - e-meeting-time-sel-mail.xpm \ - e-meeting-time-sel-no-mail.xpm - diff --git a/widgets/meeting-time-sel/e-meeting-time-sel-item.c b/widgets/meeting-time-sel/e-meeting-time-sel-item.c deleted file mode 100644 index e11c3a6a16..0000000000 --- a/widgets/meeting-time-sel/e-meeting-time-sel-item.c +++ /dev/null @@ -1,993 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ - -/* - * Author : - * Damon Chaplin <damon@gtk.org> - * - * Copyright 1999, Ximian, Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * 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 - */ - -/* - * EMeetingTimeSelectorItem - A GnomeCanvasItem which is used for both the main - * display canvas and the top display (with the dates, times & All Attendees). - * I didn't make these separate GnomeCanvasItems since they share a lot of - * code. - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <time.h> -#include <glib.h> -#include <libgnome/gnome-defs.h> -#include <libgnome/gnome-i18n.h> -#include "e-meeting-time-sel-item.h" -#include "e-meeting-time-sel.h" - -/* Initially the grid lines were drawn at the bottom of cells, but this didn't - line up well with the GtkEntry widgets, which in the default theme draw a - black shadow line across the top. So I've switched our code to draw the - lines across the top of cells. */ -#define E_MEETING_TIME_SELECTOR_DRAW_GRID_LINES_AT_BOTTOM 0 - -static void e_meeting_time_selector_item_class_init (EMeetingTimeSelectorItemClass *mts_item_class); -static void e_meeting_time_selector_item_init (EMeetingTimeSelectorItem *mts_item); -static void e_meeting_time_selector_item_destroy (GtkObject *object); - -static void e_meeting_time_selector_item_set_arg (GtkObject *o, GtkArg *arg, - guint arg_id); -static void e_meeting_time_selector_item_realize (GnomeCanvasItem *item); -static void e_meeting_time_selector_item_unrealize (GnomeCanvasItem *item); -static void e_meeting_time_selector_item_update (GnomeCanvasItem *item, - double *affine, - ArtSVP *clip_path, int flags); -static void e_meeting_time_selector_item_draw (GnomeCanvasItem *item, - GdkDrawable *drawable, - int x, int y, - int width, int height); -static double e_meeting_time_selector_item_point (GnomeCanvasItem *item, - double x, double y, - int cx, int cy, - GnomeCanvasItem **actual_item); -static gint e_meeting_time_selector_item_event (GnomeCanvasItem *item, - GdkEvent *event); -static gint e_meeting_time_selector_item_button_press (EMeetingTimeSelectorItem *mts_item, - GdkEvent *event); -static gint e_meeting_time_selector_item_button_release (EMeetingTimeSelectorItem *mts_item, - GdkEvent *event); -static gint e_meeting_time_selector_item_motion_notify (EMeetingTimeSelectorItem *mts_item, - GdkEvent *event); - -static void e_meeting_time_selector_item_paint_day_top (EMeetingTimeSelectorItem *mts_item, - GdkDrawable *drawable, - GDate *date, - int x, int scroll_y, - int width, int height); -static void e_meeting_time_selector_item_paint_all_attendees_busy_periods (EMeetingTimeSelectorItem *mts_item, GdkDrawable *drawable, GDate *date, int x, int y, int width, int height); -static void e_meeting_time_selector_item_paint_day (EMeetingTimeSelectorItem *mts_item, - GdkDrawable *drawable, - GDate *date, - int x, int scroll_y, - int width, int height); -static void e_meeting_time_selector_item_paint_busy_periods (EMeetingTimeSelectorItem *mts_item, GdkDrawable *drawable, GDate *date, int x, int scroll_y, int width, int height); -static gint e_meeting_time_selector_item_find_first_busy_period (EMeetingTimeSelectorItem *mts_item, GDate *date, gint row); -static void e_meeting_time_selector_item_paint_attendee_busy_periods (EMeetingTimeSelectorItem *mts_item, GdkDrawable *drawable, int row, int x, int y, int width, int first_period, EMeetingTimeSelectorBusyType busy_type); - -static EMeetingTimeSelectorPosition e_meeting_time_selector_item_get_drag_position (EMeetingTimeSelectorItem *mts_item, gint x, gint y); -static gboolean e_meeting_time_selector_item_calculate_busy_range (EMeetingTimeSelector *mts, - gint row, - gint x, - gint width, - gint *start_x, - gint *end_x); - -static GnomeCanvasItemClass *parent_class; - -/* The arguments we take */ -enum { - ARG_0, - ARG_MEETING_TIME_SELECTOR -}; - - -GtkType -e_meeting_time_selector_item_get_type (void) -{ - static GtkType e_meeting_time_selector_item_type = 0; - - if (!e_meeting_time_selector_item_type) { - GtkTypeInfo e_meeting_time_selector_item_info = { - "EMeetingTimeSelectorItem", - sizeof (EMeetingTimeSelectorItem), - sizeof (EMeetingTimeSelectorItemClass), - (GtkClassInitFunc) e_meeting_time_selector_item_class_init, - (GtkObjectInitFunc) e_meeting_time_selector_item_init, - NULL, /* reserved_1 */ - NULL, /* reserved_2 */ - (GtkClassInitFunc) NULL - }; - - e_meeting_time_selector_item_type = gtk_type_unique (gnome_canvas_item_get_type (), &e_meeting_time_selector_item_info); - } - - return e_meeting_time_selector_item_type; -} - - -static void -e_meeting_time_selector_item_class_init (EMeetingTimeSelectorItemClass *mts_item_class) -{ - GtkObjectClass *object_class; - GnomeCanvasItemClass *item_class; - - parent_class = gtk_type_class (gnome_canvas_item_get_type()); - - object_class = (GtkObjectClass *) mts_item_class; - item_class = (GnomeCanvasItemClass *) mts_item_class; - - gtk_object_add_arg_type ("EMeetingTimeSelectorItem::meeting_time_selector", - GTK_TYPE_POINTER, GTK_ARG_WRITABLE, - ARG_MEETING_TIME_SELECTOR); - - object_class->destroy = e_meeting_time_selector_item_destroy; - object_class->set_arg = e_meeting_time_selector_item_set_arg; - - /* GnomeCanvasItem method overrides */ - item_class->realize = e_meeting_time_selector_item_realize; - item_class->unrealize = e_meeting_time_selector_item_unrealize; - item_class->update = e_meeting_time_selector_item_update; - item_class->draw = e_meeting_time_selector_item_draw; - item_class->point = e_meeting_time_selector_item_point; - item_class->event = e_meeting_time_selector_item_event; -} - - -static void -e_meeting_time_selector_item_init (EMeetingTimeSelectorItem *mts_item) -{ - GnomeCanvasItem *item = GNOME_CANVAS_ITEM (mts_item); - - mts_item->mts = NULL; - - mts_item->main_gc = NULL; - mts_item->stipple_gc = NULL; - - /* Create the cursors. */ - mts_item->normal_cursor = gdk_cursor_new (GDK_LEFT_PTR); - mts_item->resize_cursor = gdk_cursor_new (GDK_SB_H_DOUBLE_ARROW); - mts_item->last_cursor_set = NULL; - - item->x1 = 0; - item->y1 = 0; - item->x2 = 0; - item->y2 = 0; -} - - -static void -e_meeting_time_selector_item_destroy (GtkObject *object) -{ - EMeetingTimeSelectorItem *mts_item; - - mts_item = E_MEETING_TIME_SELECTOR_ITEM (object); - - gdk_cursor_destroy (mts_item->normal_cursor); - gdk_cursor_destroy (mts_item->resize_cursor); - - if (GTK_OBJECT_CLASS (parent_class)->destroy) - (*GTK_OBJECT_CLASS (parent_class)->destroy)(object); -} - - -static void -e_meeting_time_selector_item_set_arg (GtkObject *o, GtkArg *arg, guint arg_id) -{ - GnomeCanvasItem *item; - EMeetingTimeSelectorItem *mts_item; - - item = GNOME_CANVAS_ITEM (o); - mts_item = E_MEETING_TIME_SELECTOR_ITEM (o); - - switch (arg_id){ - case ARG_MEETING_TIME_SELECTOR: - mts_item->mts = GTK_VALUE_POINTER (*arg); - break; - } -} - - -static void -e_meeting_time_selector_item_realize (GnomeCanvasItem *item) -{ - GnomeCanvas *canvas; - GdkWindow *window; - EMeetingTimeSelectorItem *mts_item; - - if (GNOME_CANVAS_ITEM_CLASS (parent_class)->realize) - (*GNOME_CANVAS_ITEM_CLASS (parent_class)->realize)(item); - - mts_item = E_MEETING_TIME_SELECTOR_ITEM (item); - - canvas = item->canvas; - window = GTK_WIDGET (canvas)->window; - - mts_item->main_gc = gdk_gc_new (window); - mts_item->stipple_gc = gdk_gc_new (window); -} - - -static void -e_meeting_time_selector_item_unrealize (GnomeCanvasItem *item) -{ - EMeetingTimeSelectorItem *mts_item; - - mts_item = E_MEETING_TIME_SELECTOR_ITEM (item); - - gdk_gc_unref (mts_item->main_gc); - mts_item->main_gc = NULL; - gdk_gc_unref (mts_item->stipple_gc); - mts_item->stipple_gc = NULL; - - if (GNOME_CANVAS_ITEM_CLASS (parent_class)->unrealize) - (*GNOME_CANVAS_ITEM_CLASS (parent_class)->unrealize)(item); -} - - -static void -e_meeting_time_selector_item_update (GnomeCanvasItem *item, double *affine, ArtSVP *clip_path, int flags) -{ - if (GNOME_CANVAS_ITEM_CLASS (parent_class)->update) - (* GNOME_CANVAS_ITEM_CLASS (parent_class)->update) (item, affine, clip_path, flags); - - /* The grid covers the entire canvas area. */ - item->x1 = 0; - item->y1 = 0; - item->x2 = INT_MAX; - item->y2 = INT_MAX; -} - - -/* - * DRAWING ROUTINES - functions to paint the canvas item. - */ - -static void -e_meeting_time_selector_item_draw (GnomeCanvasItem *item, GdkDrawable *drawable, int x, int y, int width, int height) -{ - EMeetingTimeSelector *mts; - EMeetingTimeSelectorItem *mts_item; - EMeetingTimeSelectorAttendee *attendee; - gint day_x, meeting_start_x, meeting_end_x, bar_y, bar_height; - gint row, row_y, start_x, end_x; - GDate date, last_date, current_date; - gboolean is_display_top, show_meeting_time; - GdkGC *gc, *stipple_gc; - - mts_item = E_MEETING_TIME_SELECTOR_ITEM (item); - mts = mts_item->mts; - g_return_if_fail (mts != NULL); - gc = mts_item->main_gc; - stipple_gc = mts_item->stipple_gc; - - is_display_top = (GTK_WIDGET (item->canvas) == mts->display_top) - ? TRUE : FALSE; - - /* Calculate the first and last visible days and positions. */ - e_meeting_time_selector_calculate_day_and_position (mts, x, - &date, &day_x); - e_meeting_time_selector_calculate_day_and_position (mts, x + width, - &last_date, NULL); - - /* For the top display draw the 'All Attendees' row background. */ - if (is_display_top) { - gdk_gc_set_foreground (gc, &mts->all_attendees_bg_color); - gdk_draw_rectangle (drawable, gc, TRUE, - 0, mts->row_height * 2 - y, - width, mts->row_height); - } else { - gdk_gc_set_foreground (gc, &mts->bg_color); - gdk_draw_rectangle (drawable, gc, TRUE, 0, 0, width, height); - } - - /* Calculate the x coordinates of the meeting time. */ - show_meeting_time = e_meeting_time_selector_get_meeting_time_positions (mts, &meeting_start_x, &meeting_end_x); - - /* Draw the meeting time background. */ - if (show_meeting_time - && (meeting_end_x - 1 >= x) && (meeting_start_x + 1 < x + width) - && (meeting_end_x - meeting_start_x > 2)) { - gdk_gc_set_foreground (gc, &mts->meeting_time_bg_color); - if (is_display_top) - gdk_draw_rectangle (drawable, gc, TRUE, - meeting_start_x + 1 - x, mts->row_height * 2 - y, - meeting_end_x - meeting_start_x - 2, mts->row_height); - else - gdk_draw_rectangle (drawable, gc, TRUE, - meeting_start_x + 1 - x, 0, - meeting_end_x - meeting_start_x - 2, height); - } - - /* For the main display draw the stipple background for attendee's - that have no calendar information. */ - if (!is_display_top) { - gdk_gc_set_foreground (gc, &mts->grid_color); - gdk_gc_set_foreground (stipple_gc, &mts->grid_color); - gdk_gc_set_background (stipple_gc, &mts->stipple_bg_color); - gdk_gc_set_stipple (stipple_gc, mts->stipple); - gnome_canvas_set_stipple_origin (item->canvas, stipple_gc); - gdk_gc_set_fill (stipple_gc, GDK_OPAQUE_STIPPLED); - row = y / mts->row_height; - row_y = row * mts->row_height - y; - while (row < mts->attendees->len && row_y < height) { - attendee = &g_array_index (mts->attendees, - EMeetingTimeSelectorAttendee, row); - if (attendee->has_calendar_info) { - if (e_meeting_time_selector_item_calculate_busy_range (mts, row, x, width, &start_x, &end_x)) { - if (start_x >= width || end_x <= 0) { - gdk_draw_rectangle (drawable, stipple_gc, TRUE, 0, row_y, width, mts->row_height); - } else { - if (start_x >= 0) { - gdk_draw_rectangle (drawable, stipple_gc, TRUE, 0, row_y, start_x, mts->row_height); - gdk_draw_line (drawable, gc, start_x, row_y, start_x, row_y + mts->row_height); - } - if (end_x <= width) { - gdk_draw_rectangle (drawable, stipple_gc, TRUE, end_x, row_y, width - end_x, mts->row_height); - gdk_draw_line (drawable, gc, end_x, row_y, end_x, row_y + mts->row_height); - } - } - } - } else { - gdk_draw_rectangle (drawable, stipple_gc, TRUE, - 0, row_y, - width, mts->row_height); - } - row++; - row_y += mts->row_height; - } - gdk_gc_set_fill (gc, GDK_SOLID); - } - - /* Now paint the visible days one by one. */ - current_date = date; - for (;;) { - /* Currently we use the same GnomeCanvasItem class for the - top display and the main display. We may use separate - classes in future if necessary. */ - if (is_display_top) - e_meeting_time_selector_item_paint_day_top (mts_item, drawable, ¤t_date, day_x, y, width, height); - else - e_meeting_time_selector_item_paint_day (mts_item, drawable, ¤t_date, day_x, y, width, height); - - day_x += mts_item->mts->day_width; - if (g_date_compare (¤t_date, &last_date) == 0) - break; - g_date_add_days (¤t_date, 1); - } - - /* Draw the busy periods. */ - if (is_display_top) - e_meeting_time_selector_item_paint_all_attendees_busy_periods (mts_item, drawable, &date, x, y, width, height); - else - e_meeting_time_selector_item_paint_busy_periods (mts_item, drawable, &date, x, y, width, height); - - - /* Draw the currently-selected meeting time vertical bars. */ - if (show_meeting_time) { - if (is_display_top) { - bar_y = mts->row_height * 2 - y; - bar_height = mts->row_height; - } else { - bar_y = 0; - bar_height = height; - } - - gdk_gc_set_foreground (gc, &mts->grid_color); - - if ((meeting_start_x + 2 >= x) - && (meeting_start_x - 2 < x + width)) { - gdk_draw_rectangle (drawable, gc, TRUE, - meeting_start_x - 2 - x, bar_y, - 5, bar_height); - } - - if ((meeting_end_x + 2 >= x) - && (meeting_end_x - 2 < x + width)) { - gdk_draw_rectangle (drawable, gc, TRUE, - meeting_end_x - 2 - x, bar_y, - 5, bar_height); - } - } -} - - -static void -e_meeting_time_selector_item_paint_day_top (EMeetingTimeSelectorItem *mts_item, - GdkDrawable *drawable, GDate *date, - int x, int scroll_y, - int width, int height) -{ - EMeetingTimeSelector *mts; - GdkGC *gc; - GdkFont *font; - gint y, grid_x; - gchar buffer[128], *format; - gint hour, hour_x, hour_y; - GdkRectangle clip_rect; - - mts = mts_item->mts; - gc = mts_item->main_gc; - - gdk_gc_set_foreground (gc, &mts->grid_color); - - /* Draw the horizontal lines. */ - y = mts->row_height - 1 - scroll_y; - gdk_draw_line (drawable, gc, x, y, x + mts->day_width - 1, y); - gdk_gc_set_foreground (gc, &mts->grid_shadow_color); - gdk_draw_line (drawable, gc, x, y + 1, x + mts->day_width - 1, y + 1); - gdk_gc_set_foreground (gc, &mts->grid_color); - y += mts->row_height; - gdk_draw_line (drawable, gc, x, y, x + mts->day_width - 1, y); - y += mts->row_height; - gdk_draw_line (drawable, gc, x, y, x + mts->day_width - 1, y); - - - /* Draw the vertical grid lines. */ - for (grid_x = mts->col_width - 1; - grid_x < mts->day_width - mts->col_width; - grid_x += mts->col_width) { - gdk_draw_line (drawable, gc, - x + grid_x, mts->row_height * 2 - 4 - scroll_y, - x + grid_x, height); - } - grid_x = mts->day_width - 2; - gdk_draw_line (drawable, gc, x + grid_x, 0, x + grid_x, height); - grid_x++; - gdk_draw_line (drawable, gc, x + grid_x, 0, x + grid_x, height); - - /* Draw the date. Set a clipping rectangle so we don't draw over the - next day. */ - font = GTK_WIDGET (mts)->style->font; - if (mts->date_format == E_MEETING_TIME_SELECTOR_DATE_FULL) - /* This is a strftime() format string %A = full weekday name, - %B = full month name, %d = month day, %Y = full year. */ - format = _("%A, %B %d, %Y"); - else if (mts->date_format == E_MEETING_TIME_SELECTOR_DATE_ABBREVIATED_DAY) - /* This is a strftime() format string %a = abbreviated weekday - name, %m = month number, %d = month day, %Y = full year. */ - format = _("%a %m/%d/%Y"); - else - /* This is a strftime() format string %m = month number, - %d = month day, %Y = full year. */ - format = _("%m/%d/%Y"); - - g_date_strftime (buffer, sizeof (buffer), format, date); - - clip_rect.x = x; - clip_rect.y = -scroll_y; - clip_rect.width = mts->day_width - 2; - clip_rect.height = mts->row_height - 2; - gdk_gc_set_clip_rectangle (gc, &clip_rect); - gdk_draw_string (drawable, font, gc, - x + 4, 4 + font->ascent - scroll_y, buffer); - gdk_gc_set_clip_rectangle (gc, NULL); - - /* Draw the hours. */ - hour = mts->first_hour_shown + (mts->zoomed_out ? 3 : 1); - hour_x = x + mts->col_width; - hour_y = mts->row_height + 4 + font->ascent - scroll_y; - while (hour < mts->last_hour_shown) { - gdk_draw_string (drawable, font, gc, - hour_x - (mts->hour_widths[hour] / 2), - hour_y, EMeetingTimeSelectorHours[hour]); - - hour += mts->zoomed_out ? 3 : 1; - hour_x += mts->col_width; - } -} - - -/* This paints the colored bars representing busy periods for the combined - list of attendees. For now we just paint the bars for each attendee of - each other. If we want to speed it up we could optimise it later. */ -static void -e_meeting_time_selector_item_paint_all_attendees_busy_periods (EMeetingTimeSelectorItem *mts_item, GdkDrawable *drawable, GDate *date, int x, int scroll_y, int width, int height) -{ - EMeetingTimeSelector *mts; - EMeetingTimeSelectorBusyType busy_type; - gint row, y; - GdkGC *gc; - gint *first_periods; - - mts = mts_item->mts; - gc = mts_item->main_gc; - - /* Calculate the y coordinate to paint the row at in the drawable. */ - y = 2 * mts->row_height - scroll_y - 1; - - /* Get the first visible busy periods for all the attendees. */ - first_periods = g_new (gint, mts->attendees->len); - for (row = 0; row < mts->attendees->len; row++) { - first_periods[row] = e_meeting_time_selector_item_find_first_busy_period (mts_item, date, row); - } - - for (busy_type = 0; - busy_type < E_MEETING_TIME_SELECTOR_BUSY_LAST; - busy_type++) { - gdk_gc_set_foreground (gc, &mts->busy_colors[busy_type]); - for (row = 0; row < mts->attendees->len; row++) { - if (first_periods[row] == -1) - continue; - e_meeting_time_selector_item_paint_attendee_busy_periods (mts_item, drawable, x, y, width, row, first_periods[row], busy_type); - } - } - - g_free (first_periods); -} - - -static void -e_meeting_time_selector_item_paint_day (EMeetingTimeSelectorItem *mts_item, - GdkDrawable *drawable, GDate *date, - int x, int scroll_y, - int width, int height) -{ - EMeetingTimeSelector *mts; - GdkGC *gc; - gint grid_x, grid_y, attendee_index, unused_y; - - mts = mts_item->mts; - gc = mts_item->main_gc; - - /* Draw the grid lines. The grid lines around unused rows are drawn in - a different color. */ - - /* Draw the horizontal grid lines. */ - attendee_index = scroll_y / mts->row_height; -#if E_MEETING_TIME_SELECTOR_DRAW_GRID_LINES_AT_BOTTOM - for (grid_y = mts->row_height - 1 - (scroll_y % mts->row_height); -#else - for (grid_y = - (scroll_y % mts->row_height); -#endif - grid_y < height; - grid_y += mts->row_height) - { - if (attendee_index <= mts->attendees->len) { - gdk_gc_set_foreground (gc, &mts->grid_color); - gdk_draw_line (drawable, gc, 0, grid_y, - width, grid_y); - } else { - gdk_gc_set_foreground (gc, &mts->grid_unused_color); - gdk_draw_line (drawable, gc, 0, grid_y, - width, grid_y); - } - attendee_index++; - } - - /* Draw the vertical grid lines. */ - unused_y = (mts->attendees->len * mts->row_height) - scroll_y; - if (unused_y >= 0) { - gdk_gc_set_foreground (gc, &mts->grid_color); - for (grid_x = mts->col_width - 1; - grid_x < mts->day_width - mts->col_width; - grid_x += mts->col_width) - { - gdk_draw_line (drawable, gc, - x + grid_x, 0, - x + grid_x, unused_y - 1); - } - gdk_draw_rectangle (drawable, gc, TRUE, - x + mts->day_width - 2, 0, - 2, unused_y); - } - - if (unused_y < height) { - gdk_gc_set_foreground (gc, &mts->grid_unused_color); - for (grid_x = mts->col_width - 1; - grid_x < mts->day_width - mts->col_width; - grid_x += mts->col_width) - { - gdk_draw_line (drawable, gc, - x + grid_x, unused_y, - x + grid_x, height); - } - gdk_draw_rectangle (drawable, gc, TRUE, - x + mts->day_width - 2, unused_y, - 2, height - unused_y); - } - - -} - - -/* This paints the colored bars representing busy periods for the individual - attendees. */ -static void -e_meeting_time_selector_item_paint_busy_periods (EMeetingTimeSelectorItem *mts_item, GdkDrawable *drawable, GDate *date, int x, int scroll_y, int width, int height) -{ - EMeetingTimeSelector *mts; - EMeetingTimeSelectorBusyType busy_type; - gint row, y, first_period; - GdkGC *gc; - - mts = mts_item->mts; - gc = mts_item->main_gc; - - /* Calculate the first visible attendee row. */ - row = scroll_y / mts->row_height; - - /* Calculate the y coordinate to paint the row at in the drawable. */ - y = row * mts->row_height - scroll_y; - - /* Step through the attendees painting the busy periods. */ - while (y < height && row < mts->attendees->len) { - - /* Find the first visible busy period. */ - first_period = e_meeting_time_selector_item_find_first_busy_period (mts_item, date, row); - if (first_period != -1) { - /* Paint the different types of busy periods, in - reverse order of precedence, so the highest - precedences are displayed. */ - for (busy_type = 0; - busy_type < E_MEETING_TIME_SELECTOR_BUSY_LAST; - busy_type++) { - gdk_gc_set_foreground (gc, &mts->busy_colors[busy_type]); - e_meeting_time_selector_item_paint_attendee_busy_periods (mts_item, drawable, x, y, width, row, first_period, busy_type); - } - } - y += mts->row_height; - row++; - } -} - - -/* This subtracts the attendees longest_period_in_days from the given date, - and does a binary search of the attendee's busy periods array to find the - first one which could possible end on the given day or later. - If none are found it returns -1. */ -static gint -e_meeting_time_selector_item_find_first_busy_period (EMeetingTimeSelectorItem *mts_item, GDate *date, gint row) -{ - EMeetingTimeSelector *mts; - EMeetingTimeSelectorAttendee *attendee; - EMeetingTimeSelectorPeriod *period; - gint period_num; - - mts = mts_item->mts; - - attendee = &g_array_index (mts->attendees, - EMeetingTimeSelectorAttendee, row); - - period_num = e_meeting_time_selector_find_first_busy_period (mts, attendee, date); - if (period_num == -1) - return -1; - - /* Check if the period starts after the end of the current canvas - scroll area. */ - period = &g_array_index (attendee->busy_periods, - EMeetingTimeSelectorPeriod, period_num); - if (g_date_compare (&mts->last_date_shown, &period->start.date) < 0) - return -1; - - return period_num; -} - - -/* This paints the visible busy periods for one attendee which are of a certain - busy type, e.g out of office. It is passed the index of the first visible - busy period of the attendee and continues until it runs off the screen. */ -static void -e_meeting_time_selector_item_paint_attendee_busy_periods (EMeetingTimeSelectorItem *mts_item, GdkDrawable *drawable, int x, int y, int width, int row, int first_period, EMeetingTimeSelectorBusyType busy_type) -{ - EMeetingTimeSelector *mts; - EMeetingTimeSelectorAttendee *attendee; - EMeetingTimeSelectorPeriod *period; - GdkGC *gc; - gint period_num, x1, x2, x2_within_day, x2_within_col; - - mts = mts_item->mts; - gc = mts_item->main_gc; - - attendee = &g_array_index (mts->attendees, - EMeetingTimeSelectorAttendee, row); - - for (period_num = first_period; - period_num < attendee->busy_periods->len; - period_num++) { - period = &g_array_index (attendee->busy_periods, - EMeetingTimeSelectorPeriod, period_num); - - if (period->busy_type != busy_type) - continue; - - /* Convert the period start and end times to x coordinates. */ - x1 = e_meeting_time_selector_calculate_time_position (mts, &period->start); - /* If the period is off the right of the area being drawn, we - are finished. */ - if (x1 >= x + width) - return; - - x2 = e_meeting_time_selector_calculate_time_position (mts, &period->end); - /* If the period is off the left edge of the area skip it. */ - if (x2 <= x) - continue; - - /* We paint from x1 to x2 - 1, so that for example a time - from 5:00-6:00 is distinct from 6:00-7:00. - We never finish on a grid line separating days, and we only - ever paint on a normal vertical grid line if the period is - only 1 pixel wide. */ - x2_within_day = x2 % mts->day_width; - if (x2_within_day == 0) { - x2 -= 2; - } else if (x2_within_day == mts->day_width - 1) { - x2 -= 1; - } else { - x2_within_col = x2_within_day % mts->col_width; - if (x2_within_col == 0 && x2 > x1 + 1) - x2 -= 1; - } - - /* Paint the rectangle. We leave a gap of 2 pixels at the - top and bottom, remembering that the grid is painted along - the top/bottom line of each row. */ - if (x2 - x1 > 0) { -#if E_MEETING_TIME_SELECTOR_DRAW_GRID_LINES_AT_BOTTOM - gdk_draw_rectangle (drawable, gc, TRUE, - x1 - x, y + 2, - x2 - x1, mts->row_height - 5); -#else - gdk_draw_rectangle (drawable, gc, TRUE, - x1 - x, y + 3, - x2 - x1, mts->row_height - 5); -#endif - } - } -} - - -/* - * CANVAS ITEM ROUTINES - functions to be a GnomeCanvasItem. - */ - -/* This is supposed to return the nearest item the the point and the distance. - Since we are the only item we just return ourself and 0 for the distance. - This is needed so that we get button/motion events. */ -static double -e_meeting_time_selector_item_point (GnomeCanvasItem *item, double x, double y, - int cx, int cy, - GnomeCanvasItem **actual_item) -{ - *actual_item = item; - return 0.0; -} - - -static gint -e_meeting_time_selector_item_event (GnomeCanvasItem *item, GdkEvent *event) -{ - EMeetingTimeSelectorItem *mts_item; - - mts_item = E_MEETING_TIME_SELECTOR_ITEM (item); - - switch (event->type) { - case GDK_BUTTON_PRESS: - return e_meeting_time_selector_item_button_press (mts_item, - event); - case GDK_BUTTON_RELEASE: - return e_meeting_time_selector_item_button_release (mts_item, - event); - case GDK_MOTION_NOTIFY: - return e_meeting_time_selector_item_motion_notify (mts_item, - event); - default: - break; - } - - return FALSE; -} - - -/* This handles all button press events for the item. If the cursor is over - one of the meeting time vertical bars we start a drag. If not we set the - meeting time to the nearest half-hour interval. - Note that GnomeCanvas converts the event coords to world coords, - i.e. relative to the entire canvas scroll area. */ -static gint -e_meeting_time_selector_item_button_press (EMeetingTimeSelectorItem *mts_item, - GdkEvent *event) -{ - EMeetingTimeSelector *mts; - EMeetingTimeSelectorTime start_time, end_time; - EMeetingTimeSelectorPosition position; - GDate *start_date, *end_date; - gint x, y; - - mts = mts_item->mts; - x = (gint) event->button.x; - y = (gint) event->button.y; - - /* Check if we are starting a drag of the vertical meeting time bars.*/ - position = e_meeting_time_selector_item_get_drag_position (mts_item, - x, y); - if (position != E_MEETING_TIME_SELECTOR_POS_NONE) { - if (gnome_canvas_item_grab (GNOME_CANVAS_ITEM (mts_item), - GDK_POINTER_MOTION_MASK - | GDK_BUTTON_RELEASE_MASK, - mts_item->resize_cursor, - event->button.time) == 0 /*Success*/) { - mts->dragging_position = position; - return TRUE; - } - } - - /* Convert the x coordinate into a EMeetingTimeSelectorTime. */ - e_meeting_time_selector_calculate_time (mts, x, &start_time); - start_date = &start_time.date; - end_date = &end_time.date; - - /* Find the nearest half-hour or hour interval, depending on whether - zoomed_out is set. */ - if (mts->zoomed_out) { - start_time.minute = 0; - end_time = start_time; - end_time.hour += 1; - } else { - start_time.minute -= start_time.minute % 30; - end_time = start_time; - end_time.minute += 30; - } - - /* Fix any overflows. */ - e_meeting_time_selector_fix_time_overflows (&end_time); - - /* Set the new meeting time. */ - e_meeting_time_selector_set_meeting_time (mts_item->mts, - g_date_year (start_date), - g_date_month (start_date), - g_date_day (start_date), - start_time.hour, - start_time.minute, - g_date_year (end_date), - g_date_month (end_date), - g_date_day (end_date), - end_time.hour, - end_time.minute); - - - return FALSE; -} - - -/* This handles all button release events for the item. If we were dragging, - we finish the drag. */ -static gint -e_meeting_time_selector_item_button_release (EMeetingTimeSelectorItem *mts_item, - GdkEvent *event) -{ - EMeetingTimeSelector *mts; - - mts = mts_item->mts; - - /* Reset any drag. */ - if (mts->dragging_position != E_MEETING_TIME_SELECTOR_POS_NONE) { - mts->dragging_position = E_MEETING_TIME_SELECTOR_POS_NONE; - e_meeting_time_selector_remove_timeout (mts); - gnome_canvas_item_ungrab (GNOME_CANVAS_ITEM (mts_item), - event->button.time); - } - - return FALSE; -} - - -/* This handles all motion notify events for the item. If button1 is pressed - we check if a drag is in progress. If not, we set the cursor if we are over - the meeting time vertical bars. Note that GnomeCanvas doesn't use motion - hints, which may affect performance. */ -static gint -e_meeting_time_selector_item_motion_notify (EMeetingTimeSelectorItem *mts_item, - GdkEvent *event) -{ - EMeetingTimeSelector *mts; - EMeetingTimeSelectorPosition position; - GdkCursor *cursor; - gint x, y; - - mts = mts_item->mts; - x = (gint) event->motion.x; - y = (gint) event->motion.y; - - if (mts->dragging_position != E_MEETING_TIME_SELECTOR_POS_NONE) { - e_meeting_time_selector_drag_meeting_time (mts, x); - return TRUE; - } - - position = e_meeting_time_selector_item_get_drag_position (mts_item, - x, y); - - /* Determine which cursor should be used. */ - if (position == E_MEETING_TIME_SELECTOR_POS_NONE) - cursor = mts_item->normal_cursor; - else - cursor = mts_item->resize_cursor; - - /* Only set the cursor if it is different to the last one we set. */ - if (mts_item->last_cursor_set != cursor) { - mts_item->last_cursor_set = cursor; - gdk_window_set_cursor (GTK_WIDGET (GNOME_CANVAS_ITEM (mts_item)->canvas)->window, cursor); - } - - return FALSE; -} - - -static EMeetingTimeSelectorPosition -e_meeting_time_selector_item_get_drag_position (EMeetingTimeSelectorItem *mts_item, - gint x, gint y) -{ - EMeetingTimeSelector *mts; - gboolean is_display_top; - gint meeting_start_x, meeting_end_x; - - mts = mts_item->mts; - - is_display_top = (GTK_WIDGET (GNOME_CANVAS_ITEM (mts_item)->canvas) == mts->display_top) ? TRUE : FALSE; - - if (is_display_top && y < mts->row_height * 2) - return E_MEETING_TIME_SELECTOR_POS_NONE; - - if (!e_meeting_time_selector_get_meeting_time_positions (mts, &meeting_start_x, &meeting_end_x)) - return E_MEETING_TIME_SELECTOR_POS_NONE; - - if (x >= meeting_end_x - 2 && x <= meeting_end_x + 2) - return E_MEETING_TIME_SELECTOR_POS_END; - - if (x >= meeting_start_x - 2 && x <= meeting_start_x + 2) - return E_MEETING_TIME_SELECTOR_POS_START; - - return E_MEETING_TIME_SELECTOR_POS_NONE; -} - - -static gboolean -e_meeting_time_selector_item_calculate_busy_range (EMeetingTimeSelector *mts, - gint row, - gint x, - gint width, - gint *start_x, - gint *end_x) -{ - EMeetingTimeSelectorAttendee *attendee; - - attendee = &g_array_index (mts->attendees, - EMeetingTimeSelectorAttendee, row); - - *start_x = -1; - *end_x = -1; - - if (!g_date_valid (&attendee->busy_periods_start.date) - || !g_date_valid (&attendee->busy_periods_end.date)) - return FALSE; - - *start_x = e_meeting_time_selector_calculate_time_position (mts, &attendee->busy_periods_start) - x - 1; - - *end_x = e_meeting_time_selector_calculate_time_position (mts, &attendee->busy_periods_end) - x; - - return TRUE; -} diff --git a/widgets/meeting-time-sel/e-meeting-time-sel-item.h b/widgets/meeting-time-sel/e-meeting-time-sel-item.h deleted file mode 100644 index 7ad1f232b2..0000000000 --- a/widgets/meeting-time-sel/e-meeting-time-sel-item.h +++ /dev/null @@ -1,79 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ - -/* - * Author : - * Damon Chaplin <damon@gtk.org> - * - * Copyright 1999, Ximian, Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * 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 - */ - -/* - * MeetingTimeSelectorItem - A GnomeCanvasItem which is used for both the main - * display canvas and the top display (with the dates, times & All Attendees). - * I didn't make these separate GnomeCanvasItems since they share a lot of - * code. - */ - -#ifndef _E_MEETING_TIME_SELECTOR_ITEM_H_ -#define _E_MEETING_TIME_SELECTOR_ITEM_H_ - -#include "e-meeting-time-sel.h" - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - - -#define E_MEETING_TIME_SELECTOR_ITEM(obj) (GTK_CHECK_CAST((obj), e_meeting_time_selector_item_get_type (), EMeetingTimeSelectorItem)) -#define E_MEETING_TIME_SELECTOR_ITEM_CLASS(k) (GTK_CHECK_CLASS_CAST ((k), e_meeting_time_selector_item_get_type (), EMeetingTimeSelectorItemClass)) -#define IS_E_MEETING_TIME_SELECTOR_ITEM(o) (GTK_CHECK_TYPE((o), e_meeting_time_selector_item_get_type ())) - - -typedef struct _EMeetingTimeSelectorItem EMeetingTimeSelectorItem; -typedef struct _EMeetingTimeSelectorItemClass EMeetingTimeSelectorItemClass; - -struct _EMeetingTimeSelectorItem -{ - GnomeCanvasItem canvas_item; - - /* The parent EMeetingTimeSelector widget. */ - EMeetingTimeSelector *mts; - - /* This GC is used for most of the drawing. The fg/bg colors are - changed for each bit. */ - GdkGC *main_gc; - GdkGC *stipple_gc; - - /* The normal & resize cursors. */ - GdkCursor *normal_cursor; - GdkCursor *resize_cursor; - - /* This remembers the last cursor set on the window. */ - GdkCursor *last_cursor_set; -}; - - -struct _EMeetingTimeSelectorItemClass -{ - GnomeCanvasItemClass parent_class; -}; - -GtkType e_meeting_time_selector_item_get_type (void); - - -#endif /* _E_MEETING_TIME_SELECTOR_ITEM_H_ */ diff --git a/widgets/meeting-time-sel/e-meeting-time-sel-list-item.c b/widgets/meeting-time-sel/e-meeting-time-sel-list-item.c deleted file mode 100644 index 1a6ddf3e62..0000000000 --- a/widgets/meeting-time-sel/e-meeting-time-sel-list-item.c +++ /dev/null @@ -1,397 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ - -/* - * Author : - * Damon Chaplin <damon@gtk.org> - * - * Copyright 1999, Ximian, Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * 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 - */ - -/* - * EMeetingTimeSelectorListItem - A GnomeCanvasItem covering the entire attendee - * list. It just draws the grid lines between the rows and after the icon - * column. - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <time.h> -#include <gtk/gtksignal.h> -#include <gal/widgets/e-canvas.h> -#include "e-meeting-time-sel-list-item.h" -#include "e-meeting-time-sel.h" - -/* This is the size of our icons. */ -#define E_MEETING_TIME_SELECTOR_ICON_WIDTH 19 -#define E_MEETING_TIME_SELECTOR_ICON_HEIGHT 16 - -#include "e-meeting-time-sel-mail.xpm" -#include "e-meeting-time-sel-no-mail.xpm" - -static void e_meeting_time_selector_list_item_class_init (EMeetingTimeSelectorListItemClass *mtsl_item_class); -static void e_meeting_time_selector_list_item_init (EMeetingTimeSelectorListItem *mtsl_item); -static void e_meeting_time_selector_list_item_destroy (GtkObject *object); - -static void e_meeting_time_selector_list_item_set_arg (GtkObject *o, GtkArg *arg, - guint arg_id); -static void e_meeting_time_selector_list_item_realize (GnomeCanvasItem *item); -static void e_meeting_time_selector_list_item_unrealize (GnomeCanvasItem *item); -static void e_meeting_time_selector_list_item_update (GnomeCanvasItem *item, - double *affine, - ArtSVP *clip_path, int flags); -static void e_meeting_time_selector_list_item_draw (GnomeCanvasItem *item, - GdkDrawable *drawable, - int x, int y, - int width, int height); -static double e_meeting_time_selector_list_item_point (GnomeCanvasItem *item, - double x, double y, - int cx, int cy, - GnomeCanvasItem **actual_item); -static gint e_meeting_time_selector_list_item_event (GnomeCanvasItem *item, - GdkEvent *event); -static gboolean e_meeting_time_selector_list_item_button_press (EMeetingTimeSelectorListItem *mtsl_item, - GdkEvent *event); - - -static GnomeCanvasItemClass *e_meeting_time_selector_list_item_parent_class; - -/* The arguments we take */ -enum { - ARG_0, - ARG_MEETING_TIME_SELECTOR -}; - - -GtkType -e_meeting_time_selector_list_item_get_type (void) -{ - static GtkType e_meeting_time_selector_list_item_type = 0; - - if (!e_meeting_time_selector_list_item_type) { - GtkTypeInfo e_meeting_time_selector_list_item_info = { - "EMeetingTimeSelectorListItem", - sizeof (EMeetingTimeSelectorListItem), - sizeof (EMeetingTimeSelectorListItemClass), - (GtkClassInitFunc) e_meeting_time_selector_list_item_class_init, - (GtkObjectInitFunc) e_meeting_time_selector_list_item_init, - NULL, /* reserved_1 */ - NULL, /* reserved_2 */ - (GtkClassInitFunc) NULL - }; - - e_meeting_time_selector_list_item_type = gtk_type_unique (gnome_canvas_item_get_type (), &e_meeting_time_selector_list_item_info); - } - - return e_meeting_time_selector_list_item_type; -} - - -static void -e_meeting_time_selector_list_item_class_init (EMeetingTimeSelectorListItemClass *mtsl_item_class) -{ - GtkObjectClass *object_class; - GnomeCanvasItemClass *item_class; - - e_meeting_time_selector_list_item_parent_class = gtk_type_class (gnome_canvas_item_get_type()); - - object_class = (GtkObjectClass *) mtsl_item_class; - item_class = (GnomeCanvasItemClass *) mtsl_item_class; - - gtk_object_add_arg_type ("EMeetingTimeSelectorListItem::meeting_time_selector", - GTK_TYPE_POINTER, GTK_ARG_WRITABLE, - ARG_MEETING_TIME_SELECTOR); - - object_class->destroy = e_meeting_time_selector_list_item_destroy; - object_class->set_arg = e_meeting_time_selector_list_item_set_arg; - - /* GnomeCanvasItem method overrides */ - item_class->realize = e_meeting_time_selector_list_item_realize; - item_class->unrealize = e_meeting_time_selector_list_item_unrealize; - item_class->update = e_meeting_time_selector_list_item_update; - item_class->draw = e_meeting_time_selector_list_item_draw; - item_class->point = e_meeting_time_selector_list_item_point; - item_class->event = e_meeting_time_selector_list_item_event; -} - - -static void -e_meeting_time_selector_list_item_init (EMeetingTimeSelectorListItem *mtsl_item) -{ - GnomeCanvasItem *item = GNOME_CANVAS_ITEM (mtsl_item); - GdkColormap *colormap; - - mtsl_item->mts = NULL; - - colormap = gtk_widget_get_default_colormap (); - mtsl_item->mail_icon = gdk_pixmap_colormap_create_from_xpm_d (NULL, colormap, &mtsl_item->mail_icon_mask, NULL, e_meeting_time_sel_mail_xpm); - mtsl_item->no_mail_icon = gdk_pixmap_colormap_create_from_xpm_d (NULL, colormap, &mtsl_item->no_mail_icon_mask, NULL, e_meeting_time_sel_no_mail_xpm); - - item->x1 = 0; - item->y1 = 0; - item->x2 = 0; - item->y2 = 0; -} - - -static void -e_meeting_time_selector_list_item_destroy (GtkObject *object) -{ - EMeetingTimeSelectorListItem *mtsl_item; - - mtsl_item = E_MEETING_TIME_SELECTOR_LIST_ITEM (object); - - gdk_pixmap_unref (mtsl_item->mail_icon); - gdk_pixmap_unref (mtsl_item->no_mail_icon); - gdk_bitmap_unref (mtsl_item->mail_icon_mask); - gdk_bitmap_unref (mtsl_item->no_mail_icon_mask); - - if (GTK_OBJECT_CLASS (e_meeting_time_selector_list_item_parent_class)->destroy) - (*GTK_OBJECT_CLASS (e_meeting_time_selector_list_item_parent_class)->destroy)(object); -} - - -static void -e_meeting_time_selector_list_item_set_arg (GtkObject *o, GtkArg *arg, guint arg_id) -{ - GnomeCanvasItem *item; - EMeetingTimeSelectorListItem *mtsl_item; - - item = GNOME_CANVAS_ITEM (o); - mtsl_item = E_MEETING_TIME_SELECTOR_LIST_ITEM (o); - - switch (arg_id){ - case ARG_MEETING_TIME_SELECTOR: - mtsl_item->mts = GTK_VALUE_POINTER (*arg); - break; - } -} - - -static void -e_meeting_time_selector_list_item_realize (GnomeCanvasItem *item) -{ - GnomeCanvas *canvas; - GdkWindow *window; - EMeetingTimeSelectorListItem *mtsl_item; - - if (GNOME_CANVAS_ITEM_CLASS (e_meeting_time_selector_list_item_parent_class)->realize) - (*GNOME_CANVAS_ITEM_CLASS (e_meeting_time_selector_list_item_parent_class)->realize)(item); - - mtsl_item = E_MEETING_TIME_SELECTOR_LIST_ITEM (item); - - canvas = item->canvas; - window = GTK_WIDGET (canvas)->window; - - mtsl_item->main_gc = gdk_gc_new (window); -} - - -static void -e_meeting_time_selector_list_item_unrealize (GnomeCanvasItem *item) -{ - EMeetingTimeSelectorListItem *mtsl_item; - - mtsl_item = E_MEETING_TIME_SELECTOR_LIST_ITEM (item); - - gdk_gc_unref (mtsl_item->main_gc); - mtsl_item->main_gc = NULL; - - if (GNOME_CANVAS_ITEM_CLASS (e_meeting_time_selector_list_item_parent_class)->unrealize) - (*GNOME_CANVAS_ITEM_CLASS (e_meeting_time_selector_list_item_parent_class)->unrealize)(item); -} - - -static void -e_meeting_time_selector_list_item_update (GnomeCanvasItem *item, double *affine, ArtSVP *clip_path, int flags) -{ - if (GNOME_CANVAS_ITEM_CLASS (e_meeting_time_selector_list_item_parent_class)->update) - (* GNOME_CANVAS_ITEM_CLASS (e_meeting_time_selector_list_item_parent_class)->update) (item, affine, clip_path, flags); - - /* The item covers the entire canvas area. */ - item->x1 = 0; - item->y1 = 0; - item->x2 = INT_MAX; - item->y2 = INT_MAX; -} - - -/* - * DRAWING ROUTINES - functions to paint the canvas item. - */ - -static void -e_meeting_time_selector_list_item_draw (GnomeCanvasItem *item, GdkDrawable *drawable, int x, int y, int width, int height) -{ - EMeetingTimeSelectorListItem *mtsl_item; - EMeetingTimeSelector *mts; - EMeetingTimeSelectorAttendee *attendee; - GdkGC *gc; - GdkFont *font; - gint row, row_y, icon_x, icon_y; - GdkPixmap *pixmap; - GdkBitmap *mask; - - mtsl_item = E_MEETING_TIME_SELECTOR_LIST_ITEM (item); - mts = mtsl_item->mts; - gc = mtsl_item->main_gc; - - gdk_gc_set_foreground (gc, &mts->attendee_list_bg_color); - gdk_draw_rectangle (drawable, gc, TRUE, 0, 0, width, height); - - gdk_gc_set_foreground (gc, &mts->grid_unused_color); - gdk_draw_line (drawable, gc, 24 - x, 0, 24 - x, height); - - /* Draw the grid line across the top of the row. */ - row = y / mts->row_height; - row_y = row * mts->row_height - y; - while (row_y < height) { - gdk_draw_line (drawable, gc, 0, row_y, width, row_y); - row_y += mts->row_height; - } - - row = y / mts->row_height; - row_y = row * mts->row_height - y; - icon_x = (E_MEETING_TIME_SELECTOR_ICON_COLUMN_WIDTH - E_MEETING_TIME_SELECTOR_ICON_WIDTH + 1) / 2 - x; - icon_y = row_y + (mts->row_height - E_MEETING_TIME_SELECTOR_ICON_HEIGHT + 1) / 2; - while (row < mts->attendees->len && row_y < height) { - attendee = &g_array_index (mts->attendees, - EMeetingTimeSelectorAttendee, row); - - gdk_gc_set_clip_origin (gc, icon_x, icon_y); - - if (attendee->send_meeting_to) { - pixmap = mtsl_item->mail_icon; - mask = mtsl_item->mail_icon_mask; - } else { - pixmap = mtsl_item->no_mail_icon; - mask = mtsl_item->no_mail_icon_mask; - } - - gdk_gc_set_clip_mask (gc, mask); - gdk_draw_pixmap (drawable, gc, pixmap, 0, 0, - icon_x, icon_y, 24, 24); - - row++; - row_y += mts->row_height; - icon_y += mts->row_height; - } - gdk_gc_set_clip_mask (gc, NULL); - - /* Draw 'Click here to add attendee' on the last dummy row. */ - row_y = mts->attendees->len * mts->row_height; - - font = GTK_WIDGET (mts)->style->font; - gdk_gc_set_foreground (gc, &mts->grid_unused_color); - gdk_draw_string (drawable, font, gc, - E_MEETING_TIME_SELECTOR_ICON_COLUMN_WIDTH - + E_MEETING_TIME_SELECTOR_TEXT_X_PAD - x, - row_y + E_MEETING_TIME_SELECTOR_TEXT_Y_PAD - + font->ascent + 1 - y, - "Click here to add attendee"); -} - - -/* This is supposed to return the nearest item the the point and the distance. - Since we cover the entire canvas we just return ourself and 0 for the - distance. This is needed so that we get button/motion events. */ -static double -e_meeting_time_selector_list_item_point (GnomeCanvasItem *item, - double x, double y, - int cx, int cy, - GnomeCanvasItem **actual_item) -{ - *actual_item = item; - return 0.0; -} - - -static gint -e_meeting_time_selector_list_item_event (GnomeCanvasItem *item, - GdkEvent *event) -{ - EMeetingTimeSelectorListItem *mtsl_item; - - mtsl_item = E_MEETING_TIME_SELECTOR_LIST_ITEM (item); - - switch (event->type) { - case GDK_BUTTON_PRESS: - return e_meeting_time_selector_list_item_button_press (mtsl_item, event); - case GDK_BUTTON_RELEASE: - break; - case GDK_MOTION_NOTIFY: - break; - default: - break; - } - - return FALSE; -} - - -static gboolean -e_meeting_time_selector_list_item_button_press (EMeetingTimeSelectorListItem *mtsl_item, - GdkEvent *event) -{ - EMeetingTimeSelector *mts; - EMeetingTimeSelectorAttendee *attendee; - gint row; - gboolean return_val; - - mts = mtsl_item->mts; - row = event->button.y / mts->row_height; - - g_print ("In e_meeting_time_selector_list_item_button_press: %g,%g row:%i\n", - event->button.x, event->button.y, row); - - if (event->button.x >= E_MEETING_TIME_SELECTOR_ICON_COLUMN_WIDTH) { - if (row < mts->attendees->len) { - attendee = &g_array_index (mts->attendees, EMeetingTimeSelectorAttendee, row); - gtk_signal_emit_by_name (GTK_OBJECT (attendee->text_item), - "event", event, &return_val); - return return_val; - } else { - row = e_meeting_time_selector_attendee_add (mts, "", - NULL); - - /* Scroll down to show the last line.?? */ -#if 0 - adjustment = GTK_LAYOUT (mts->display_main)->vadjustment; - adjustment->value = adjustment->upper - adjustment->page_size; - gtk_adjustment_value_changed (adjustment); -#endif - - attendee = &g_array_index (mts->attendees, EMeetingTimeSelectorAttendee, row); - e_canvas_item_grab_focus (attendee->text_item, TRUE); - return TRUE; - } - } else { - attendee = &g_array_index (mts->attendees, - EMeetingTimeSelectorAttendee, row); - - attendee->send_meeting_to = !attendee->send_meeting_to; - - gnome_canvas_request_redraw (GNOME_CANVAS_ITEM (mtsl_item)->canvas, - 0, row * mts->row_height, - E_MEETING_TIME_SELECTOR_ICON_COLUMN_WIDTH, - (row + 1) * mts->row_height); - return TRUE; - } -} - diff --git a/widgets/meeting-time-sel/e-meeting-time-sel-list-item.h b/widgets/meeting-time-sel/e-meeting-time-sel-list-item.h deleted file mode 100644 index b71474b0e9..0000000000 --- a/widgets/meeting-time-sel/e-meeting-time-sel-list-item.h +++ /dev/null @@ -1,73 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ - -/* - * Author : - * Damon Chaplin <damon@gtk.org> - * - * Copyright 1999, Ximian, Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * 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 - */ - -/* - * MeetingTimeSelectorListItem - A GnomeCanvasItem covering the entire attendee - * list. It just draws the grid lines between the rows and after the icon - * column. - */ - -#ifndef _E_MEETING_TIME_SELECTOR_LIST_ITEM_H_ -#define _E_MEETING_TIME_SELECTOR_LIST_ITEM_H_ - -#include "e-meeting-time-sel.h" - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - - -#define E_MEETING_TIME_SELECTOR_LIST_ITEM(obj) (GTK_CHECK_CAST((obj), e_meeting_time_selector_list_item_get_type (), EMeetingTimeSelectorListItem)) -#define E_MEETING_TIME_SELECTOR_LIST_ITEM_CLASS(k) (GTK_CHECK_CLASS_CAST ((k), e_meeting_time_selector_list_item_get_type (), EMeetingTimeSelectorListItemClass)) -#define IS_E_MEETING_TIME_SELECTOR_LIST_ITEM(o) (GTK_CHECK_TYPE((o), e_meeting_time_selector_list_item_get_type ())) - - -typedef struct _EMeetingTimeSelectorListItem EMeetingTimeSelectorListItem; -typedef struct _EMeetingTimeSelectorListItemClass EMeetingTimeSelectorListItemClass; - -struct _EMeetingTimeSelectorListItem -{ - GnomeCanvasItem canvas_item; - - /* The parent EMeetingTimeSelector widget. */ - EMeetingTimeSelector *mts; - - /* This GC is used for most of the drawing. The fg/bg colors are - changed for each bit. */ - GdkGC *main_gc; - - GdkPixmap *mail_icon, *no_mail_icon; - GdkBitmap *mail_icon_mask, *no_mail_icon_mask; -}; - - -struct _EMeetingTimeSelectorListItemClass -{ - GnomeCanvasItemClass parent_class; -}; - -GtkType e_meeting_time_selector_list_item_get_type (void); - - -#endif /* _E_MEETING_TIME_SELECTOR_LIST_ITEM_H_ */ diff --git a/widgets/meeting-time-sel/e-meeting-time-sel-mail.xpm b/widgets/meeting-time-sel/e-meeting-time-sel-mail.xpm deleted file mode 100644 index 5a03c7ea8a..0000000000 --- a/widgets/meeting-time-sel/e-meeting-time-sel-mail.xpm +++ /dev/null @@ -1,135 +0,0 @@ -/* XPM */ -static char * e_meeting_time_sel_mail_xpm[] = { -"19 16 116 2", -" c None", -". c #000000", -"+ c #7B7B78", -"@ c #C7C7C3", -"# c #F1F0EB", -"$ c #BFBFBC", -"% c #5F5E5E", -"& c #E3E3DF", -"* c #F3F3EF", -"= c #F2F2EE", -"- c #F1F1EC", -"; c #F0EFEB", -"> c #D2D2CD", -", c #969592", -"' c #616060", -") c #B5B5B4", -"! c #F8F8F6", -"~ c #F7F7F5", -"{ c #F6F6F3", -"] c #F5F5F2", -"^ c #F4F4F0", -"/ c #F2F1ED", -"( c #F1F0EC", -"_ c #F0EFEA", -": c #EFEEE9", -"< c #4F4F4D", -"[ c #BDBCB8", -"} c #A7A6A3", -"| c #C6C6C4", -"1 c #7C7C7B", -"2 c #525251", -"3 c #DBDBD9", -"4 c #F5F4F1", -"5 c #F4F3F0", -"6 c #F3F2EE", -"7 c #999894", -"8 c #62625F", -"9 c #BCBCB6", -"0 c #EBE9E3", -"a c #838381", -"b c #D7D6D4", -"c c #A8A8A6", -"d c #515150", -"e c #7E7D7C", -"f c #DAD9D5", -"g c #EFEEE8", -"h c #EEEDE7", -"i c #4F4E4C", -"j c #BCBBB6", -"k c #EBE9E2", -"l c #EAE8E1", -"m c #F6F5F2", -"n c #F4F3EF", -"o c #B5B4B1", -"p c #9B9A97", -"q c #646361", -"r c #92918E", -"s c #EEEDE8", -"t c #EDECE6", -"u c #4E4E4C", -"v c #797976", -"w c #797874", -"x c #E9E8E1", -"y c #E8E7DF", -"z c #B4B3AF", -"A c #D0D0CD", -"B c #F2F2ED", -"C c #BFBEBA", -"D c #BEBDB9", -"E c #7A7A77", -"F c #979691", -"G c #EAE9E2", -"H c #959590", -"I c #787773", -"J c #B8B7B0", -"K c #E6E4DC", -"L c #A9A9A6", -"M c #626260", -"N c #ECEBE4", -"O c #EBEAE3", -"P c #E9E7E0", -"Q c #E8E6DF", -"R c #E7E5DD", -"S c #777671", -"T c #93918C", -"U c #BEBDB8", -"V c #989793", -"W c #ECEAE4", -"X c #E8E6DE", -"Y c #E6E4DB", -"Z c #E4E3DA", -"` c #75746F", -" . c #91908A", -".. c #EEECE7", -"+. c #62615F", -"@. c #EBEAE4", -"#. c #E7E6DE", -"$. c #E6E5DC", -"%. c #E5E4DB", -"&. c #E4E2DA", -"*. c #CCCBC4", -"=. c #A3A29D", -"-. c #B6B5B2", -";. c #BCBCB7", -">. c #CDCCC6", -",. c #959490", -"'. c #ECEBE5", -"). c #61615E", -"!. c #E9E8E0", -"~. c #CECDC7", -"{. c #797875", -"]. c #969590", -"^. c #CFCEC8", -"/. c #AEADA8", -"(. c #585754", -"_. c #7B7A76", -" . . . . ", -" . . . . . + @ # $ . ", -" . . . . . % $ & * = - ; > , . ", -". ' ) ! ~ { ] ^ * / ( _ : < [ } . ", -". | 1 2 3 4 5 6 / # _ : 7 8 9 0 . ", -". a b c d e f / # _ g h i j k l . ", -" . m 4 n o p q r s t u v w x y z . ", -" . A * B ( ; C D E u F G H I J K . ", -" . L / ( _ : M t N O l P Q R S T . ", -" . # _ g U V W 0 l P X R Y Z ` .. ", -" . ; g ..+.@.G x y #.$.%.&.*.=.. . ", -" . -.t ;.F G x y #.K >.,.. . . ", -" . '.).G !.Q ~.H . . . ", -" . {.].^./.. . . ", -" . (._.. . ", -" . . "}; diff --git a/widgets/meeting-time-sel/e-meeting-time-sel-no-mail.xpm b/widgets/meeting-time-sel/e-meeting-time-sel-no-mail.xpm deleted file mode 100644 index 747202b3e2..0000000000 --- a/widgets/meeting-time-sel/e-meeting-time-sel-no-mail.xpm +++ /dev/null @@ -1,123 +0,0 @@ -/* XPM */ -static char * e_meeting_time_sel_no_mail_xpm[] = { -"19 16 104 2", -" c None", -". c #000000", -"+ c #7B7B78", -"@ c #C7C7C3", -"# c #F1F0EB", -"$ c #BFBFBC", -"% c #5F5E5E", -"& c #E3E3DF", -"* c #F3F3EF", -"= c #F2F2EE", -"- c #F1F1EC", -"; c #F0EFEB", -"> c #D2D2CD", -", c #969592", -"' c #616060", -") c #B5B5B4", -"! c #F8F8F6", -"~ c #F7F7F5", -"{ c #F6F6F3", -"] c #F5F5F2", -"^ c #F4F4F0", -"/ c #F2F1ED", -"( c #F1F0EC", -"_ c #F0EFEA", -": c #EFEEE9", -"< c #4F4F4D", -"[ c #BDBCB8", -"} c #A7A6A3", -"| c #C6C6C4", -"1 c #7C7C7B", -"2 c #525251", -"3 c #DBDBD9", -"4 c #F5F4F1", -"5 c #F4F3F0", -"6 c #F3F2EE", -"7 c #999894", -"8 c #62625F", -"9 c #BCBCB6", -"0 c #EBE9E3", -"a c #838381", -"b c #D7D6D4", -"c c #A8A8A6", -"d c #515150", -"e c #7E7D7C", -"f c #DAD9D5", -"g c #D16069", -"h c #EEEDE7", -"i c #4F4E4C", -"j c #BCBBB6", -"k c #F6F5F2", -"l c #F4F3EF", -"m c #B5B4B1", -"n c #9B9A97", -"o c #646361", -"p c #92918E", -"q c #9F3C44", -"r c #797976", -"s c #B5444E", -"t c #B4B3AF", -"u c #D0D0CD", -"v c #F2F2ED", -"w c #BFBEBA", -"x c #BEBDB9", -"y c #BB565F", -"z c #812F36", -"A c #E6E4DC", -"B c #A9A9A6", -"C c #626260", -"D c #EDECE6", -"E c #ECEBE4", -"F c #BB555D", -"G c #90353D", -"H c #777671", -"I c #93918C", -"J c #EFEEE8", -"K c #BEBDB8", -"L c #989793", -"M c #ECEAE4", -"N c #E6E4DB", -"O c #E4E3DA", -"P c #75746F", -"Q c #91908A", -"R c #EEECE7", -"S c #62615F", -"T c #EBEAE4", -"U c #EAE9E2", -"V c #BD5A62", -"W c #E4E2DA", -"X c #CCCBC4", -"Y c #A3A29D", -"Z c #B6B5B2", -"` c #BCBCB7", -" . c #979691", -".. c #BC5760", -"+. c #A13C45", -"@. c #ECEBE5", -"#. c #61615E", -"$. c #C0636B", -"%. c #A83F48", -"&. c #797875", -"*. c #969590", -"=. c #CFCEC8", -"-. c #585754", -";. c #7B7A76", -" . . . . ", -" . . . . . + @ # $ . ", -" . . . . . % $ & * = - ; > , . ", -". ' ) ! ~ { ] ^ * / ( _ : < [ } . ", -". | 1 2 3 4 5 6 / # _ : 7 8 9 0 . ", -". a b c d e f / # g g h i j g g . ", -" . k 4 l m n o p g q g r g s g t . ", -" . u * v ( ; w x g s g g y z g A . ", -" . B / ( _ : C D E g s F G g H I . ", -" . # _ J K L M 0 g s s g N O P Q . ", -" . ; J R S T U g V s s g W X Y . . ", -" . Z D ` .U g ..G g g +.g . . ", -" . @.#.U g $.G g . g %.g ", -" . &.*.=.g g g . g g ", -" . -.;.. . ", -" . . "}; diff --git a/widgets/meeting-time-sel/e-meeting-time-sel.c b/widgets/meeting-time-sel/e-meeting-time-sel.c deleted file mode 100644 index c00bed73b1..0000000000 --- a/widgets/meeting-time-sel/e-meeting-time-sel.c +++ /dev/null @@ -1,3308 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ - -/* - * Author : - * Damon Chaplin <damon@gtk.org> - * - * Copyright 1999, Ximian, Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * 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 - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include "e-meeting-time-sel.h" - -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <time.h> -#include <glib.h> -#include <gdk/gdkkeysyms.h> -#include <gtk/gtkalignment.h> -#include <gtk/gtkarrow.h> -#include <gtk/gtkbutton.h> -#include <gtk/gtkdrawingarea.h> -#include <gtk/gtkentry.h> -#include <gtk/gtkhbox.h> -#include <gtk/gtkhscrollbar.h> -#include <gtk/gtkhseparator.h> -#include <gtk/gtklabel.h> -#include <gtk/gtkmenu.h> -#include <gtk/gtkradiomenuitem.h> -#include <gtk/gtksignal.h> -#include <gtk/gtkvbox.h> -#include <gtk/gtkvscrollbar.h> -#include <libgnomeui/gnome-dateedit.h> -#include <libgnome/gnome-i18n.h> -#include <libgnomeui/gnome-canvas-widget.h> - -#include <gal/widgets/e-canvas.h> -#include <gal/widgets/e-canvas-utils.h> -#include "e-meeting-time-sel-item.h" -#include "e-meeting-time-sel-list-item.h" - -/* An array of hour strings, "0:00" .. "23:00". */ -const gchar *EMeetingTimeSelectorHours[24] = { - "0:00", "1:00", "2:00", "3:00", "4:00", "5:00", "6:00", "7:00", - "8:00", "9:00", "10:00", "11:00", "12:00", "13:00", "14:00", "15:00", - "16:00", "17:00", "18:00", "19:00", "20:00", "21:00", "22:00", "23:00" -}; - -/* The number of days shown in the entire canvas. */ -#define E_MEETING_TIME_SELECTOR_DAYS_SHOWN 365 - -/* This is the number of pixels between the mouse has to move before the - scroll speed is incremented. */ -#define E_MEETING_TIME_SELECTOR_SCROLL_INCREMENT_WIDTH 10 - -/* This is the maximum scrolling speed. */ -#define E_MEETING_TIME_SELECTOR_MAX_SCROLL_SPEED 4 - - -static void e_meeting_time_selector_class_init (EMeetingTimeSelectorClass * klass); -static void e_meeting_time_selector_init (EMeetingTimeSelector * mts); -static void e_meeting_time_selector_destroy (GtkObject *object); -static void e_meeting_time_selector_alloc_named_color (EMeetingTimeSelector * mts, - const char *name, GdkColor *c); -static void e_meeting_time_selector_add_key_color (EMeetingTimeSelector * mts, - GtkWidget *hbox, - gchar *label_text, - GdkColor *color); -static gint e_meeting_time_selector_expose_key_color (GtkWidget *darea, - GdkEventExpose *event, - GdkColor *color); -static gint e_meeting_time_selector_expose_title_bar (GtkWidget *darea, - GdkEventExpose *event, - gpointer data); -static void e_meeting_time_selector_options_menu_detacher (GtkWidget *widget, - GtkMenu *menu); -static void e_meeting_time_selector_autopick_menu_detacher (GtkWidget *widget, - GtkMenu *menu); -static void e_meeting_time_selector_realize (GtkWidget *widget); -static void e_meeting_time_selector_unrealize (GtkWidget *widget); -static void e_meeting_time_selector_style_set (GtkWidget *widget, - GtkStyle *previous_style); -static gint e_meeting_time_selector_expose_event (GtkWidget *widget, - GdkEventExpose *event); -static void e_meeting_time_selector_draw (GtkWidget *widget, - GdkRectangle *area); -static void e_meeting_time_selector_draw_shadow (EMeetingTimeSelector *mts); -static void e_meeting_time_selector_hadjustment_changed (GtkAdjustment *adjustment, - EMeetingTimeSelector *mts); -static void e_meeting_time_selector_vadjustment_changed (GtkAdjustment *adjustment, - EMeetingTimeSelector *mts); - -static void e_meeting_time_selector_on_canvas_realized (GtkWidget *widget, - EMeetingTimeSelector *mts); - -static gint e_meeting_time_selector_compare_period_starts (const void *arg1, - const void *arg2); -#if 0 -static gint e_meeting_time_selector_compare_periods (const void *arg1, - const void *arg2); -#endif -static gint e_meeting_time_selector_compare_times (EMeetingTimeSelectorTime *time1, - EMeetingTimeSelectorTime *time2); -static void e_meeting_time_selector_on_options_button_clicked (GtkWidget *button, - EMeetingTimeSelector *mts); -static void e_meeting_time_selector_options_menu_position_callback (GtkMenu *menu, - gint *x, - gint *y, - gpointer user_data); -static void e_meeting_time_selector_on_zoomed_out_toggled (GtkWidget *button, - EMeetingTimeSelector *mts); -static void e_meeting_time_selector_on_working_hours_toggled (GtkWidget *button, - EMeetingTimeSelector *mts); -static void e_meeting_time_selector_on_invite_others_button_clicked (GtkWidget *button, - EMeetingTimeSelector *mts); -static void e_meeting_time_selector_on_update_free_busy (GtkWidget *button, - EMeetingTimeSelector *mts); -static void e_meeting_time_selector_on_autopick_button_clicked (GtkWidget *button, - EMeetingTimeSelector *mts); -static void e_meeting_time_selector_autopick_menu_position_callback (GtkMenu *menu, - gint *x, - gint *y, - gpointer user_data); -static void e_meeting_time_selector_on_autopick_option_toggled (GtkWidget *button, - EMeetingTimeSelector *mts); -static void e_meeting_time_selector_on_prev_button_clicked (GtkWidget *button, - EMeetingTimeSelector *mts); -static void e_meeting_time_selector_on_next_button_clicked (GtkWidget *button, - EMeetingTimeSelector *mts); -static void e_meeting_time_selector_autopick (EMeetingTimeSelector *mts, - gboolean forward); -static void e_meeting_time_selector_calculate_time_difference (EMeetingTimeSelectorTime *start, - EMeetingTimeSelectorTime *end, - gint *days, - gint *hours, - gint *minutes); -static void e_meeting_time_selector_find_nearest_interval (EMeetingTimeSelector *mts, - EMeetingTimeSelectorTime *start_time, - EMeetingTimeSelectorTime *end_time, - gint days, gint hours, gint mins); -static void e_meeting_time_selector_find_nearest_interval_backward (EMeetingTimeSelector *mts, - EMeetingTimeSelectorTime *start_time, - EMeetingTimeSelectorTime *end_time, - gint days, gint hours, gint mins); -static void e_meeting_time_selector_adjust_time (EMeetingTimeSelectorTime *mtstime, - gint days, gint hours, gint minutes); -static EMeetingTimeSelectorPeriod* e_meeting_time_selector_find_time_clash (EMeetingTimeSelector *mts, - EMeetingTimeSelectorAttendee *attendee, - EMeetingTimeSelectorTime *start_time, - EMeetingTimeSelectorTime *end_time); - - -static void e_meeting_time_selector_recalc_grid (EMeetingTimeSelector *mts); -static void e_meeting_time_selector_recalc_date_format (EMeetingTimeSelector *mts); -static void e_meeting_time_selector_save_position (EMeetingTimeSelector *mts, - EMeetingTimeSelectorTime *mtstime); -static void e_meeting_time_selector_restore_position (EMeetingTimeSelector *mts, - EMeetingTimeSelectorTime *mtstime); -static void e_meeting_time_selector_on_start_time_changed (GtkWidget *widget, - EMeetingTimeSelector *mts); -static void e_meeting_time_selector_on_end_time_changed (GtkWidget *widget, - EMeetingTimeSelector *mts); -static void e_meeting_time_selector_update_date_popup_menus (EMeetingTimeSelector *mts); -static void e_meeting_time_selector_on_attendees_list_size_allocate (GtkWidget *widget, - GtkAllocation *allocation, - EMeetingTimeSelector *mts); -static void e_meeting_time_selector_on_canvas_size_allocate (GtkWidget *widget, - GtkAllocation *allocation, - EMeetingTimeSelector *mts); -static void e_meeting_time_selector_update_main_canvas_scroll_region (EMeetingTimeSelector *mts); -static void e_meeting_time_selector_update_attendees_list_scroll_region (EMeetingTimeSelector *mts); -static gboolean e_meeting_time_selector_timeout_handler (gpointer data); -static void e_meeting_time_selector_update_start_date_edit (EMeetingTimeSelector *mts); -static void e_meeting_time_selector_update_end_date_edit (EMeetingTimeSelector *mts); -static void e_meeting_time_selector_ensure_meeting_time_shown (EMeetingTimeSelector *mts); -static void e_meeting_time_selector_update_dates_shown (EMeetingTimeSelector *mts); - -static void e_meeting_time_selector_update_attendees_list_positions (EMeetingTimeSelector *mts); -static gboolean e_meeting_time_selector_on_text_item_event (GnomeCanvasItem *item, - GdkEvent *event, - EMeetingTimeSelector *mts); -static gint e_meeting_time_selector_find_row_from_text_item (EMeetingTimeSelector *mts, - GnomeCanvasItem *item); - -static GtkTableClass *parent_class; - - -GtkType -e_meeting_time_selector_get_type (void) -{ - static guint e_meeting_time_selector_type = 0; - - if (!e_meeting_time_selector_type) { - GtkTypeInfo e_meeting_time_selector_info = - { - "EMeetingTimeSelector", - sizeof (EMeetingTimeSelector), - sizeof (EMeetingTimeSelectorClass), - (GtkClassInitFunc) e_meeting_time_selector_class_init, - (GtkObjectInitFunc) e_meeting_time_selector_init, - /* reserved_1 */ NULL, - /* reserved_2 */ NULL, - (GtkClassInitFunc) NULL, - }; - - e_meeting_time_selector_type = gtk_type_unique (GTK_TYPE_TABLE, - &e_meeting_time_selector_info); - } - return e_meeting_time_selector_type; -} - - -static void -e_meeting_time_selector_class_init (EMeetingTimeSelectorClass * klass) -{ - GtkObjectClass *object_class; - GtkWidgetClass *widget_class; - - parent_class = gtk_type_class (gtk_table_get_type()); - - object_class = (GtkObjectClass *) klass; - widget_class = (GtkWidgetClass *) klass; - - object_class->destroy = e_meeting_time_selector_destroy; - - widget_class->realize = e_meeting_time_selector_realize; - widget_class->unrealize = e_meeting_time_selector_unrealize; - widget_class->style_set = e_meeting_time_selector_style_set; - widget_class->expose_event = e_meeting_time_selector_expose_event; - widget_class->draw = e_meeting_time_selector_draw; -} - - -static void -e_meeting_time_selector_init (EMeetingTimeSelector * mts) -{ - GtkWidget *hbox, *separator, *button, *label, *table; - GtkWidget *alignment, *child_hbox, *arrow, *menuitem; - GSList *group; - GdkVisual *visual; - GdkColormap *colormap; - guint accel_key; - GtkAccelGroup *menu_accel_group; - time_t meeting_start_time; - struct tm *meeting_start_tm; - guchar stipple_bits[] = { - 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, - }; - - /* The shadow is drawn in the border so it must be >= 2 pixels. */ - gtk_container_set_border_width (GTK_CONTAINER (mts), 2); - - mts->accel_group = gtk_accel_group_new (); - - mts->attendees = g_array_new (FALSE, FALSE, - sizeof (EMeetingTimeSelectorAttendee)); - - mts->working_hours_only = TRUE; - mts->day_start_hour = 9; - mts->day_start_minute = 0; - mts->day_end_hour = 18; - mts->day_end_minute = 0; - mts->zoomed_out = FALSE; - mts->dragging_position = E_MEETING_TIME_SELECTOR_POS_NONE; - - /* The default meeting time is the nearest half-hour interval in the - future, in working hours. */ - meeting_start_time = time (NULL); - g_date_clear (&mts->meeting_start_time.date, 1); - g_date_set_time (&mts->meeting_start_time.date, meeting_start_time); - meeting_start_tm = localtime (&meeting_start_time); - mts->meeting_start_time.hour = meeting_start_tm->tm_hour; - mts->meeting_start_time.minute = meeting_start_tm->tm_min; - - e_meeting_time_selector_find_nearest_interval (mts, &mts->meeting_start_time, - &mts->meeting_end_time, - 0, 0, 30); - - e_meeting_time_selector_update_dates_shown (mts); - - mts->meeting_positions_valid = FALSE; - - mts->row_height = 30; - mts->col_width = 50; - mts->day_width = 50 * 24 + 1; - - mts->auto_scroll_timeout_id = 0; - - - mts->attendees_title_bar_vbox = gtk_vbox_new (FALSE, 2); - /* Add some horizontal padding for the shadow around the display. */ - gtk_table_attach (GTK_TABLE (mts), - mts->attendees_title_bar_vbox, - 0, 1, 0, 1, GTK_EXPAND | GTK_FILL, GTK_FILL, 2, 0); - gtk_widget_show (mts->attendees_title_bar_vbox); - - mts->attendees_title_bar = gtk_drawing_area_new (); - gtk_box_pack_end (GTK_BOX (mts->attendees_title_bar_vbox), - mts->attendees_title_bar, FALSE, FALSE, 0); - gtk_widget_show (mts->attendees_title_bar); - gtk_signal_connect (GTK_OBJECT (mts->attendees_title_bar), - "expose_event", - GTK_SIGNAL_FUNC (e_meeting_time_selector_expose_title_bar), mts); - - mts->attendees_list = e_canvas_new (); - /* Add some horizontal padding for the shadow around the display. */ - gtk_table_attach (GTK_TABLE (mts), mts->attendees_list, - 0, 1, 1, 2, - GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 2, 0); - gtk_widget_show (mts->attendees_list); - gtk_signal_connect (GTK_OBJECT (mts->attendees_list), "realize", - GTK_SIGNAL_FUNC (e_meeting_time_selector_on_canvas_realized), mts); - gtk_signal_connect (GTK_OBJECT (mts->attendees_list), "size_allocate", - GTK_SIGNAL_FUNC (e_meeting_time_selector_on_attendees_list_size_allocate), mts); - - /* Create the item in the list canvas. */ - gnome_canvas_item_new (GNOME_CANVAS_GROUP (GNOME_CANVAS (mts->attendees_list)->root), - e_meeting_time_selector_list_item_get_type (), - "EMeetingTimeSelectorListItem::meeting_time_selector", mts, - NULL); - - mts->display_top = gnome_canvas_new (); - gnome_canvas_set_scroll_region (GNOME_CANVAS (mts->display_top), - 0, 0, - mts->day_width * E_MEETING_TIME_SELECTOR_DAYS_SHOWN, - mts->row_height * 3); - /* Add some horizontal padding for the shadow around the display. */ - gtk_table_attach (GTK_TABLE (mts), mts->display_top, - 1, 4, 0, 1, GTK_EXPAND | GTK_FILL, 0, 2, 0); - gtk_widget_show (mts->display_top); - gtk_signal_connect (GTK_OBJECT (mts->display_top), "realize", - GTK_SIGNAL_FUNC (e_meeting_time_selector_on_canvas_realized), mts); - - mts->display_main = gnome_canvas_new (); - e_meeting_time_selector_update_main_canvas_scroll_region (mts); - /* Add some horizontal padding for the shadow around the display. */ - gtk_table_attach (GTK_TABLE (mts), mts->display_main, - 1, 4, 1, 2, - GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 2, 0); - gtk_widget_show (mts->display_main); - gtk_signal_connect (GTK_OBJECT (mts->display_main), "realize", - GTK_SIGNAL_FUNC (e_meeting_time_selector_on_canvas_realized), mts); - gtk_signal_connect (GTK_OBJECT (mts->display_main), "size_allocate", - GTK_SIGNAL_FUNC (e_meeting_time_selector_on_canvas_size_allocate), mts); - - mts->hscrollbar = gtk_hscrollbar_new (GTK_LAYOUT (mts->display_main)->hadjustment); - gtk_table_attach (GTK_TABLE (mts), mts->hscrollbar, - 1, 4, 2, 3, GTK_EXPAND | GTK_FILL, 0, 0, 0); - gtk_widget_show (mts->hscrollbar); - - mts->vscrollbar = gtk_vscrollbar_new (GTK_LAYOUT (mts->display_main)->vadjustment); - gtk_table_attach (GTK_TABLE (mts), mts->vscrollbar, - 4, 5, 1, 2, 0, GTK_EXPAND | GTK_FILL, 0, 0); - gtk_widget_show (mts->vscrollbar); - - /* Create the item in the top canvas. */ - gnome_canvas_item_new (GNOME_CANVAS_GROUP (GNOME_CANVAS (mts->display_top)->root), - e_meeting_time_selector_item_get_type (), - "EMeetingTimeSelectorItem::meeting_time_selector", mts, - NULL); - - /* Create the item in the main canvas. */ - gnome_canvas_item_new (GNOME_CANVAS_GROUP (GNOME_CANVAS (mts->display_main)->root), - e_meeting_time_selector_item_get_type (), - "EMeetingTimeSelectorItem::meeting_time_selector", mts, - NULL); - - /* Create the hbox containing the color key. */ - hbox = gtk_hbox_new (FALSE, 2); - gtk_table_attach (GTK_TABLE (mts), hbox, - 1, 4, 3, 4, GTK_FILL, 0, 0, 8); - gtk_widget_show (hbox); - - e_meeting_time_selector_add_key_color (mts, hbox, _("Tentative"), &mts->busy_colors[E_MEETING_TIME_SELECTOR_BUSY_TENTATIVE]); - e_meeting_time_selector_add_key_color (mts, hbox, _("Busy"), &mts->busy_colors[E_MEETING_TIME_SELECTOR_BUSY_BUSY]); - e_meeting_time_selector_add_key_color (mts, hbox, _("Out of Office"), &mts->busy_colors[E_MEETING_TIME_SELECTOR_BUSY_OUT_OF_OFFICE]); - e_meeting_time_selector_add_key_color (mts, hbox, _("No Information"), - NULL); - - separator = gtk_hseparator_new (); - gtk_table_attach (GTK_TABLE (mts), separator, - 0, 5, 4, 5, GTK_FILL, 0, 0, 0); - gtk_widget_show (separator); - - /* Create the Invite Others & Options buttons on the left. */ - hbox = gtk_hbox_new (FALSE, 4); - gtk_table_attach (GTK_TABLE (mts), hbox, - 0, 1, 3, 4, GTK_FILL, 0, 0, 0); - gtk_widget_show (hbox); - - button = gtk_button_new_with_label (""); - accel_key = gtk_label_parse_uline (GTK_LABEL (GTK_BIN (button)->child), - _("_Invite Others...")); - gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0); - gtk_widget_show (button); - gtk_widget_add_accelerator (button, "clicked", mts->accel_group, - accel_key, GDK_MOD1_MASK, 0); - gtk_signal_connect (GTK_OBJECT (button), "clicked", - GTK_SIGNAL_FUNC (e_meeting_time_selector_on_invite_others_button_clicked), mts); - - mts->options_button = gtk_button_new (); - gtk_box_pack_start (GTK_BOX (hbox), mts->options_button, TRUE, TRUE, 0); - gtk_widget_show (mts->options_button); - - gtk_signal_connect (GTK_OBJECT (mts->options_button), "clicked", - GTK_SIGNAL_FUNC (e_meeting_time_selector_on_options_button_clicked), mts); - - child_hbox = gtk_hbox_new (FALSE, 2); - gtk_container_add (GTK_CONTAINER (mts->options_button), child_hbox); - gtk_widget_show (child_hbox); - - label = gtk_label_new (""); - accel_key = gtk_label_parse_uline (GTK_LABEL (label), _("_Options")); - gtk_box_pack_start (GTK_BOX (child_hbox), label, TRUE, TRUE, 0); - gtk_widget_show (label); - gtk_widget_add_accelerator (mts->options_button, "clicked", mts->accel_group, - accel_key, GDK_MOD1_MASK, 0); - - arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_OUT); - gtk_box_pack_start (GTK_BOX (child_hbox), arrow, FALSE, FALSE, 2); - gtk_widget_show (arrow); - - /* Create the Options menu. */ - mts->options_menu = gtk_menu_new (); - gtk_menu_attach_to_widget (GTK_MENU (mts->options_menu), mts->options_button, - e_meeting_time_selector_options_menu_detacher); - menu_accel_group = gtk_menu_ensure_uline_accel_group (GTK_MENU (mts->options_menu)); - - menuitem = gtk_check_menu_item_new_with_label (""); - accel_key = gtk_label_parse_uline (GTK_LABEL (GTK_BIN (menuitem)->child), _("Show _Only Working Hours")); - gtk_menu_append (GTK_MENU (mts->options_menu), menuitem); - gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (menuitem), - mts->working_hours_only); - gtk_widget_add_accelerator (menuitem, "activate", menu_accel_group, - accel_key, 0, 0); - gtk_widget_add_accelerator (menuitem, "activate", menu_accel_group, - accel_key, GDK_MOD1_MASK, 0); - gtk_signal_connect (GTK_OBJECT (menuitem), "toggled", - GTK_SIGNAL_FUNC (e_meeting_time_selector_on_working_hours_toggled), mts); - gtk_widget_show (menuitem); - - menuitem = gtk_check_menu_item_new_with_label (""); - accel_key = gtk_label_parse_uline (GTK_LABEL (GTK_BIN (menuitem)->child), _("Show _Zoomed Out")); - gtk_menu_append (GTK_MENU (mts->options_menu), menuitem); - gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (menuitem), - mts->zoomed_out); - gtk_widget_add_accelerator (menuitem, "activate", menu_accel_group, - accel_key, 0, 0); - gtk_widget_add_accelerator (menuitem, "activate", menu_accel_group, - accel_key, GDK_MOD1_MASK, 0); - gtk_signal_connect (GTK_OBJECT (menuitem), "toggled", - GTK_SIGNAL_FUNC (e_meeting_time_selector_on_zoomed_out_toggled), mts); - gtk_widget_show (menuitem); - - menuitem = gtk_menu_item_new (); - gtk_menu_append (GTK_MENU (mts->options_menu), menuitem); - gtk_widget_set_sensitive (menuitem, FALSE); - gtk_widget_show (menuitem); - - menuitem = gtk_menu_item_new_with_label (""); - accel_key = gtk_label_parse_uline (GTK_LABEL (GTK_BIN (menuitem)->child), _("_Update Free/Busy")); - gtk_menu_append (GTK_MENU (mts->options_menu), menuitem); - gtk_widget_add_accelerator (menuitem, "activate", menu_accel_group, - accel_key, 0, 0); - gtk_widget_add_accelerator (menuitem, "activate", menu_accel_group, - accel_key, GDK_MOD1_MASK, 0); - gtk_signal_connect (GTK_OBJECT (menuitem), "activate", - GTK_SIGNAL_FUNC (e_meeting_time_selector_on_update_free_busy), mts); - gtk_widget_show (menuitem); - - /* Create the 3 AutoPick buttons on the left. */ - hbox = gtk_hbox_new (FALSE, 0); - gtk_table_attach (GTK_TABLE (mts), hbox, - 0, 1, 5, 6, GTK_FILL, 0, 0, 0); - gtk_widget_show (hbox); - - button = gtk_button_new_with_label (""); - accel_key = gtk_label_parse_uline (GTK_LABEL (GTK_BIN (button)->child), - _("_<<")); - gtk_widget_add_accelerator (button, "clicked", mts->accel_group, - accel_key, GDK_MOD1_MASK | GDK_SHIFT_MASK, 0); - gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0); - gtk_widget_show (button); - gtk_signal_connect (GTK_OBJECT (button), "clicked", - GTK_SIGNAL_FUNC (e_meeting_time_selector_on_prev_button_clicked), mts); - - mts->autopick_button = gtk_button_new (); - gtk_box_pack_start (GTK_BOX (hbox), mts->autopick_button, TRUE, TRUE, 0); - gtk_widget_show (mts->autopick_button); - - child_hbox = gtk_hbox_new (FALSE, 2); - gtk_container_add (GTK_CONTAINER (mts->autopick_button), child_hbox); - gtk_widget_show (child_hbox); - - label = gtk_label_new (""); - accel_key = gtk_label_parse_uline (GTK_LABEL (label), _("_Autopick")); - gtk_box_pack_start (GTK_BOX (child_hbox), label, TRUE, TRUE, 0); - gtk_widget_show (label); - gtk_widget_add_accelerator (mts->autopick_button, "clicked", mts->accel_group, - accel_key, GDK_MOD1_MASK, 0); - gtk_signal_connect (GTK_OBJECT (mts->autopick_button), "clicked", - GTK_SIGNAL_FUNC (e_meeting_time_selector_on_autopick_button_clicked), mts); - - arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_OUT); - gtk_box_pack_start (GTK_BOX (child_hbox), arrow, FALSE, FALSE, 2); - gtk_widget_show (arrow); - - button = gtk_button_new_with_label (""); - accel_key = gtk_label_parse_uline (GTK_LABEL (GTK_BIN (button)->child), - _(">_>")); - gtk_widget_add_accelerator (button, "clicked", mts->accel_group, - accel_key, GDK_MOD1_MASK | GDK_SHIFT_MASK, 0); - gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0); - gtk_widget_show (button); - gtk_signal_connect (GTK_OBJECT (button), "clicked", - GTK_SIGNAL_FUNC (e_meeting_time_selector_on_next_button_clicked), mts); - - /* Create the Autopick menu. */ - mts->autopick_menu = gtk_menu_new (); - gtk_menu_attach_to_widget (GTK_MENU (mts->autopick_menu), mts->autopick_button, - e_meeting_time_selector_autopick_menu_detacher); - menu_accel_group = gtk_menu_ensure_uline_accel_group (GTK_MENU (mts->autopick_menu)); - - menuitem = gtk_radio_menu_item_new_with_label (NULL, ""); - mts->autopick_all_item = menuitem; - group = gtk_radio_menu_item_group (GTK_RADIO_MENU_ITEM (menuitem)); - accel_key = gtk_label_parse_uline (GTK_LABEL (GTK_BIN (menuitem)->child), _("_All People and Resources")); - gtk_menu_append (GTK_MENU (mts->autopick_menu), menuitem); - gtk_widget_add_accelerator (menuitem, "activate", menu_accel_group, - accel_key, 0, 0); - gtk_widget_add_accelerator (menuitem, "activate", menu_accel_group, - accel_key, GDK_MOD1_MASK, 0); - gtk_signal_connect (GTK_OBJECT (menuitem), "toggled", - GTK_SIGNAL_FUNC (e_meeting_time_selector_on_autopick_option_toggled), mts); - gtk_widget_show (menuitem); - - menuitem = gtk_radio_menu_item_new_with_label (group, ""); - mts->autopick_all_people_one_resource_item = menuitem; - group = gtk_radio_menu_item_group (GTK_RADIO_MENU_ITEM (menuitem)); - accel_key = gtk_label_parse_uline (GTK_LABEL (GTK_BIN (menuitem)->child), _("All _People and One Resource")); - gtk_menu_append (GTK_MENU (mts->autopick_menu), menuitem); - gtk_widget_add_accelerator (menuitem, "activate", menu_accel_group, - accel_key, 0, 0); - gtk_widget_add_accelerator (menuitem, "activate", menu_accel_group, - accel_key, GDK_MOD1_MASK, 0); - gtk_signal_connect (GTK_OBJECT (menuitem), "toggled", - GTK_SIGNAL_FUNC (e_meeting_time_selector_on_autopick_option_toggled), mts); - gtk_widget_show (menuitem); - - menuitem = gtk_radio_menu_item_new_with_label (group, ""); - mts->autopick_required_people_item = menuitem; - group = gtk_radio_menu_item_group (GTK_RADIO_MENU_ITEM (menuitem)); - accel_key = gtk_label_parse_uline (GTK_LABEL (GTK_BIN (menuitem)->child), _("_Required People")); - gtk_menu_append (GTK_MENU (mts->autopick_menu), menuitem); - gtk_widget_add_accelerator (menuitem, "activate", menu_accel_group, - accel_key, 0, 0); - gtk_widget_add_accelerator (menuitem, "activate", menu_accel_group, - accel_key, GDK_MOD1_MASK, 0); - gtk_signal_connect (GTK_OBJECT (menuitem), "activate", - GTK_SIGNAL_FUNC (e_meeting_time_selector_on_autopick_option_toggled), mts); - gtk_widget_show (menuitem); - - menuitem = gtk_radio_menu_item_new_with_label (group, ""); - mts->autopick_required_people_one_resource_item = menuitem; - group = gtk_radio_menu_item_group (GTK_RADIO_MENU_ITEM (menuitem)); - accel_key = gtk_label_parse_uline (GTK_LABEL (GTK_BIN (menuitem)->child), _("Required People and _One Resource")); - gtk_menu_append (GTK_MENU (mts->autopick_menu), menuitem); - gtk_widget_add_accelerator (menuitem, "activate", menu_accel_group, - accel_key, 0, 0); - gtk_widget_add_accelerator (menuitem, "activate", menu_accel_group, - accel_key, GDK_MOD1_MASK, 0); - gtk_signal_connect (GTK_OBJECT (menuitem), "activate", - GTK_SIGNAL_FUNC (e_meeting_time_selector_on_autopick_option_toggled), mts); - gtk_widget_show (menuitem); - - /* Create the date entry fields on the right. */ - alignment = gtk_alignment_new (0.5, 0.5, 0, 0); - gtk_table_attach (GTK_TABLE (mts), alignment, - 1, 4, 5, 6, GTK_FILL, 0, 0, 0); - gtk_widget_show (alignment); - - table = gtk_table_new (2, 2, FALSE); - gtk_table_set_row_spacings (GTK_TABLE (table), 4); - gtk_container_add (GTK_CONTAINER (alignment), table); - gtk_widget_show (table); - - label = gtk_label_new (""); - accel_key = gtk_label_parse_uline (GTK_LABEL (label), - _("Meeting _start time:")); - gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5); - gtk_table_attach (GTK_TABLE (table), label, - 0, 1, 0, 1, GTK_FILL, 0, 4, 0); - gtk_widget_show (label); - - mts->start_date_edit = gnome_date_edit_new (0, TRUE, TRUE); - /* I don't like the 'Calendar' label. */ - gtk_widget_hide (GNOME_DATE_EDIT (mts->start_date_edit)->cal_label); - gtk_table_attach (GTK_TABLE (table), mts->start_date_edit, - 1, 2, 0, 1, GTK_FILL, 0, 0, 0); - gtk_widget_show (mts->start_date_edit); - gtk_signal_connect (GTK_OBJECT (mts->start_date_edit), "date_changed", - GTK_SIGNAL_FUNC (e_meeting_time_selector_on_start_time_changed), mts); - gtk_signal_connect (GTK_OBJECT (mts->start_date_edit), "time_changed", - GTK_SIGNAL_FUNC (e_meeting_time_selector_on_start_time_changed), mts); - gtk_signal_connect (GTK_OBJECT (GNOME_DATE_EDIT (mts->start_date_edit)->date_entry), "activate", GTK_SIGNAL_FUNC (e_meeting_time_selector_on_start_time_changed), mts); - gtk_signal_connect (GTK_OBJECT (GNOME_DATE_EDIT (mts->start_date_edit)->time_entry), "activate", GTK_SIGNAL_FUNC (e_meeting_time_selector_on_start_time_changed), mts); - gtk_widget_add_accelerator (GNOME_DATE_EDIT (mts->start_date_edit)->date_entry, - "grab_focus", mts->accel_group, - accel_key, GDK_MOD1_MASK, 0); - - label = gtk_label_new (""); - accel_key = gtk_label_parse_uline (GTK_LABEL (label), - _("Meeting _end time:")); - gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5); - gtk_table_attach (GTK_TABLE (table), label, - 0, 1, 1, 2, GTK_FILL, 0, 4, 0); - gtk_widget_show (label); - - mts->end_date_edit = gnome_date_edit_new (0, TRUE, TRUE); - gtk_widget_hide (GNOME_DATE_EDIT (mts->end_date_edit)->cal_label); - gtk_table_attach (GTK_TABLE (table), mts->end_date_edit, - 1, 2, 1, 2, GTK_FILL, 0, 0, 0); - gtk_widget_show (mts->end_date_edit); - gtk_signal_connect (GTK_OBJECT (mts->end_date_edit), "date_changed", - GTK_SIGNAL_FUNC (e_meeting_time_selector_on_end_time_changed), mts); - gtk_signal_connect (GTK_OBJECT (mts->end_date_edit), "time_changed", - GTK_SIGNAL_FUNC (e_meeting_time_selector_on_end_time_changed), mts); - gtk_signal_connect (GTK_OBJECT (GNOME_DATE_EDIT (mts->end_date_edit)->date_entry), "activate", GTK_SIGNAL_FUNC (e_meeting_time_selector_on_end_time_changed), mts); - gtk_signal_connect (GTK_OBJECT (GNOME_DATE_EDIT (mts->end_date_edit)->time_entry), "activate", GTK_SIGNAL_FUNC (e_meeting_time_selector_on_end_time_changed), mts); - gtk_widget_add_accelerator (GNOME_DATE_EDIT (mts->end_date_edit)->date_entry, - "grab_focus", mts->accel_group, - accel_key, GDK_MOD1_MASK, 0); - - gtk_table_set_col_spacing (GTK_TABLE (mts), 0, 4); - gtk_table_set_row_spacing (GTK_TABLE (mts), 4, 12); - - /* Allocate the colors. */ - visual = gtk_widget_get_visual (GTK_WIDGET (mts)); - colormap = gtk_widget_get_colormap (GTK_WIDGET (mts)); - mts->color_context = gdk_color_context_new (visual, colormap); - e_meeting_time_selector_alloc_named_color (mts, "gray75", &mts->bg_color); - e_meeting_time_selector_alloc_named_color (mts, "gray50", &mts->all_attendees_bg_color); - gdk_color_black (colormap, &mts->grid_color); - gdk_color_white (colormap, &mts->grid_shadow_color); - e_meeting_time_selector_alloc_named_color (mts, "gray50", &mts->grid_unused_color); - gdk_color_white (colormap, &mts->meeting_time_bg_color); - gdk_color_white (colormap, &mts->stipple_bg_color); - gdk_color_white (colormap, &mts->attendee_list_bg_color); - - e_meeting_time_selector_alloc_named_color (mts, "LightSkyBlue2", &mts->busy_colors[E_MEETING_TIME_SELECTOR_BUSY_TENTATIVE]); - e_meeting_time_selector_alloc_named_color (mts, "blue", &mts->busy_colors[E_MEETING_TIME_SELECTOR_BUSY_BUSY]); - e_meeting_time_selector_alloc_named_color (mts, "HotPink3", &mts->busy_colors[E_MEETING_TIME_SELECTOR_BUSY_OUT_OF_OFFICE]); - - /* Create the stipple, for attendees with no data. */ - mts->stipple = gdk_bitmap_create_from_data (NULL, (gchar*)stipple_bits, - 8, 8); - - /* Connect handlers to the adjustments in the main canvas, so we can - scroll the other 2 canvases. */ - gtk_signal_connect (GTK_OBJECT (GTK_LAYOUT (mts->display_main)->hadjustment), "value_changed", GTK_SIGNAL_FUNC (e_meeting_time_selector_hadjustment_changed), mts); - gtk_signal_connect (GTK_OBJECT (GTK_LAYOUT (mts->display_main)->vadjustment), "value_changed", GTK_SIGNAL_FUNC (e_meeting_time_selector_vadjustment_changed), mts); - gtk_signal_connect (GTK_OBJECT (GTK_LAYOUT (mts->display_main)->vadjustment), "changed", GTK_SIGNAL_FUNC (e_meeting_time_selector_vadjustment_changed), mts); - - e_meeting_time_selector_recalc_grid (mts); - e_meeting_time_selector_ensure_meeting_time_shown (mts); - e_meeting_time_selector_update_start_date_edit (mts); - e_meeting_time_selector_update_end_date_edit (mts); - e_meeting_time_selector_update_date_popup_menus (mts); -} - - -/* This adds a color to the color key beneath the main display. If color is - NULL, it displays the No Info stipple instead. */ -static void -e_meeting_time_selector_add_key_color (EMeetingTimeSelector * mts, - GtkWidget *hbox, - gchar *label_text, GdkColor *color) -{ - GtkWidget *child_hbox, *darea, *label; - - child_hbox = gtk_hbox_new (FALSE, 4); - gtk_box_pack_start (GTK_BOX (hbox), child_hbox, TRUE, TRUE, 0); - gtk_widget_show (child_hbox); - - darea = gtk_drawing_area_new (); - gtk_box_pack_start (GTK_BOX (child_hbox), darea, FALSE, FALSE, 0); - gtk_object_set_user_data (GTK_OBJECT (darea), mts); - gtk_widget_set_usize (darea, 14, 14); - gtk_widget_show (darea); - - label = gtk_label_new (label_text); - gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5); - gtk_box_pack_start (GTK_BOX (child_hbox), label, TRUE, TRUE, 0); - gtk_widget_show (label); - - gtk_signal_connect (GTK_OBJECT (darea), "expose_event", - GTK_SIGNAL_FUNC (e_meeting_time_selector_expose_key_color), - color); -} - - -static gint -e_meeting_time_selector_expose_title_bar (GtkWidget *widget, - GdkEventExpose *event, - gpointer data) -{ - EMeetingTimeSelector * mts; - GdkFont *font; - - mts = E_MEETING_TIME_SELECTOR (data); - - gtk_draw_shadow (widget->style, widget->window, GTK_STATE_NORMAL, - GTK_SHADOW_OUT, 0, 0, - E_MEETING_TIME_SELECTOR_ICON_COLUMN_WIDTH + 1, - widget->allocation.height); - gtk_draw_shadow (widget->style, widget->window, GTK_STATE_NORMAL, - GTK_SHADOW_OUT, - E_MEETING_TIME_SELECTOR_ICON_COLUMN_WIDTH + 1, 0, - widget->allocation.width - E_MEETING_TIME_SELECTOR_ICON_COLUMN_WIDTH - 1, - widget->allocation.height); - - font = widget->style->font; - gdk_draw_string (widget->window, font, - widget->style->fg_gc[GTK_STATE_NORMAL], - E_MEETING_TIME_SELECTOR_ICON_COLUMN_WIDTH + 4, - 4 + font->ascent, _("All Attendees")); - - return FALSE; -} - - -static gint -e_meeting_time_selector_expose_key_color (GtkWidget *darea, - GdkEventExpose *event, - GdkColor *color) -{ - EMeetingTimeSelector * mts; - GdkGC *gc; - gint width, height; - - mts = gtk_object_get_user_data (GTK_OBJECT (darea)); - gc = mts->color_key_gc; - width = darea->allocation.width; - height = darea->allocation.height; - - gtk_draw_shadow (darea->style, darea->window, GTK_STATE_NORMAL, - GTK_SHADOW_IN, 0, 0, width, height); - - if (color) { - gdk_gc_set_foreground (gc, color); - gdk_draw_rectangle (darea->window, gc, TRUE, 1, 1, - width - 2, height - 2); - } else { - gdk_gc_set_foreground (gc, &mts->grid_color); - gdk_gc_set_background (gc, &mts->stipple_bg_color); - gdk_gc_set_stipple (gc, mts->stipple); - gdk_gc_set_fill (gc, GDK_OPAQUE_STIPPLED); - gdk_draw_rectangle (darea->window, gc, TRUE, 1, 1, - width - 2, height - 2); - gdk_gc_set_fill (gc, GDK_SOLID); - } - - return TRUE; -} - - -static void -e_meeting_time_selector_alloc_named_color (EMeetingTimeSelector * mts, - const char *name, GdkColor *c) -{ - int failed; - - g_return_if_fail (name != NULL); - g_return_if_fail (c != NULL); - - gdk_color_parse (name, c); - c->pixel = 0; - c->pixel = gdk_color_context_get_pixel (mts->color_context, - c->red, c->green, c->blue, - &failed); - if (failed) - g_warning ("Failed to allocate color: %s\n", name); -} - - -static void -e_meeting_time_selector_options_menu_detacher (GtkWidget *widget, - GtkMenu *menu) -{ - EMeetingTimeSelector *mts; - - g_return_if_fail (widget != NULL); - g_return_if_fail (IS_E_MEETING_TIME_SELECTOR (widget)); - - mts = E_MEETING_TIME_SELECTOR (widget); - g_return_if_fail (mts->options_menu == (GtkWidget*) menu); - - mts->options_menu = NULL; -} - - -static void -e_meeting_time_selector_autopick_menu_detacher (GtkWidget *widget, - GtkMenu *menu) -{ - EMeetingTimeSelector *mts; - - g_return_if_fail (widget != NULL); - g_return_if_fail (IS_E_MEETING_TIME_SELECTOR (widget)); - - mts = E_MEETING_TIME_SELECTOR (widget); - g_return_if_fail (mts->autopick_menu == (GtkWidget*) menu); - - mts->autopick_menu = NULL; -} - - -GtkWidget * -e_meeting_time_selector_new (void) -{ - GtkWidget *mts; - - mts = GTK_WIDGET (gtk_type_new (e_meeting_time_selector_get_type ())); - - return mts; -} - - -static void -e_meeting_time_selector_destroy (GtkObject *object) -{ - EMeetingTimeSelector *mts; - EMeetingTimeSelectorAttendee *attendee; - gint row; - - mts = E_MEETING_TIME_SELECTOR (object); - - e_meeting_time_selector_remove_timeout (mts); - - gdk_color_context_free (mts->color_context); - gdk_bitmap_unref (mts->stipple); - - for (row = 0; row < mts->attendees->len; row++) { - attendee = &g_array_index (mts->attendees, - EMeetingTimeSelectorAttendee, row); - g_free (attendee->name); - g_array_free (attendee->busy_periods, TRUE); - } - - g_array_free (mts->attendees, TRUE); - - if (GTK_OBJECT_CLASS (parent_class)->destroy) - (*GTK_OBJECT_CLASS (parent_class)->destroy)(object); -} - - -static void -e_meeting_time_selector_realize (GtkWidget *widget) -{ - EMeetingTimeSelector *mts; - - if (GTK_WIDGET_CLASS (parent_class)->realize) - (*GTK_WIDGET_CLASS (parent_class)->realize)(widget); - - mts = E_MEETING_TIME_SELECTOR (widget); - - mts->color_key_gc = gdk_gc_new (widget->window); -} - - -static void -e_meeting_time_selector_unrealize (GtkWidget *widget) -{ - EMeetingTimeSelector *mts; - - mts = E_MEETING_TIME_SELECTOR (widget); - - gdk_gc_unref (mts->color_key_gc); - mts->color_key_gc = NULL; - - if (GTK_WIDGET_CLASS (parent_class)->unrealize) - (*GTK_WIDGET_CLASS (parent_class)->unrealize)(widget); -} - - -static void -e_meeting_time_selector_style_set (GtkWidget *widget, - GtkStyle *previous_style) -{ - EMeetingTimeSelector *mts; - EMeetingTimeSelectorTime saved_time; - GdkFont *font; - gint hour, max_hour_width; - - if (GTK_WIDGET_CLASS (parent_class)->style_set) - (*GTK_WIDGET_CLASS (parent_class)->style_set)(widget, previous_style); - - mts = E_MEETING_TIME_SELECTOR (widget); - font = widget->style->font; - - /* Calculate the widths of the hour strings in the style's font. */ - max_hour_width = 0; - for (hour = 0; hour < 24; hour++) { - mts->hour_widths[hour] = gdk_string_width (font, EMeetingTimeSelectorHours[hour]); - max_hour_width = MAX (max_hour_width, mts->hour_widths[hour]); - } - - mts->row_height = font->ascent + font->descent - + E_MEETING_TIME_SELECTOR_TEXT_Y_PAD * 2 + 1; - mts->col_width = max_hour_width + 4; - - e_meeting_time_selector_save_position (mts, &saved_time); - e_meeting_time_selector_recalc_grid (mts); - e_meeting_time_selector_restore_position (mts, &saved_time); - - gtk_widget_set_usize (mts->display_top, -1, mts->row_height * 3); - gtk_widget_set_usize (mts->attendees_title_bar, -1, mts->row_height); - - GTK_LAYOUT (mts->display_main)->hadjustment->step_increment = mts->col_width; - GTK_LAYOUT (mts->display_main)->vadjustment->step_increment = mts->row_height; -} - - -/* This draws a shadow around the top display and main display. */ -static gint -e_meeting_time_selector_expose_event (GtkWidget *widget, - GdkEventExpose *event) -{ - EMeetingTimeSelector *mts; - - mts = E_MEETING_TIME_SELECTOR (widget); - - e_meeting_time_selector_draw_shadow (mts); - - if (GTK_WIDGET_CLASS (parent_class)->expose_event) - (*GTK_WIDGET_CLASS (parent_class)->expose_event)(widget, event); - - return FALSE; -} - - -static void -e_meeting_time_selector_draw (GtkWidget *widget, - GdkRectangle *area) -{ - EMeetingTimeSelector *mts; - - mts = E_MEETING_TIME_SELECTOR (widget); - - e_meeting_time_selector_draw_shadow (mts); - - if (GTK_WIDGET_CLASS (parent_class)->draw) - (*GTK_WIDGET_CLASS (parent_class)->draw)(widget, area); -} - - -static void -e_meeting_time_selector_draw_shadow (EMeetingTimeSelector *mts) -{ - GtkWidget *widget; - gint x, y, w, h; - - widget = GTK_WIDGET (mts); - - /* Draw the shadow around the attendees title bar and list. */ - x = mts->attendees_title_bar->allocation.x - 2; - y = mts->attendees_title_bar->allocation.y - 2; - w = mts->attendees_title_bar->allocation.width + 4; - h = mts->attendees_title_bar->allocation.height + mts->attendees_list->allocation.height + 4; - - gtk_draw_shadow (widget->style, widget->window, GTK_STATE_NORMAL, - GTK_SHADOW_IN, x, y, w, h); - - /* Draw the shadow around the graphical displays. */ - x = mts->display_top->allocation.x - 2; - y = mts->display_top->allocation.y - 2; - w = mts->display_top->allocation.width + 4; - h = mts->display_top->allocation.height + mts->display_main->allocation.height + 4; - - gtk_draw_shadow (widget->style, widget->window, GTK_STATE_NORMAL, - GTK_SHADOW_IN, x, y, w, h); -} - - -/* When the main canvas scrolls, we scroll the other canvases. */ -static void -e_meeting_time_selector_hadjustment_changed (GtkAdjustment *adjustment, - EMeetingTimeSelector *mts) -{ - GtkAdjustment *adj; - - adj = GTK_LAYOUT (mts->display_top)->hadjustment; - if (adj->value != adjustment->value) { - adj->value = adjustment->value; - gtk_adjustment_value_changed (adj); - } -} - - -static void -e_meeting_time_selector_vadjustment_changed (GtkAdjustment *adjustment, - EMeetingTimeSelector *mts) -{ - GtkAdjustment *adj; - - adj = GTK_LAYOUT (mts->attendees_list)->vadjustment; - if (adj->value != adjustment->value) { - adj->value = adjustment->value; - gtk_adjustment_value_changed (adj); - } -} - - -void -e_meeting_time_selector_get_meeting_time (EMeetingTimeSelector *mts, - gint *start_year, - gint *start_month, - gint *start_day, - gint *start_hour, - gint *start_minute, - gint *end_year, - gint *end_month, - gint *end_day, - gint *end_hour, - gint *end_minute) -{ - *start_year = g_date_year (&mts->meeting_start_time.date); - *start_month = g_date_month (&mts->meeting_start_time.date); - *start_day = g_date_day (&mts->meeting_start_time.date); - *start_hour = mts->meeting_start_time.hour; - *start_minute = mts->meeting_start_time.minute; - - *end_year = g_date_year (&mts->meeting_end_time.date); - *end_month = g_date_month (&mts->meeting_end_time.date); - *end_day = g_date_day (&mts->meeting_end_time.date); - *end_hour = mts->meeting_end_time.hour; - *end_minute = mts->meeting_end_time.minute; -} - - -gboolean -e_meeting_time_selector_set_meeting_time (EMeetingTimeSelector *mts, - gint start_year, - gint start_month, - gint start_day, - gint start_hour, - gint start_minute, - gint end_year, - gint end_month, - gint end_day, - gint end_hour, - gint end_minute) -{ - g_return_val_if_fail (IS_E_MEETING_TIME_SELECTOR (mts), FALSE); - - /* Check the dates are valid. */ - if (!g_date_valid_dmy (start_day, start_month, start_year) - || !g_date_valid_dmy (end_day, end_month, end_year) - || start_hour < 0 || start_hour > 23 - || end_hour < 0 || end_hour > 23 - || start_minute < 0 || start_minute > 59 - || end_minute < 0 || end_minute > 59) - return FALSE; - - g_date_set_dmy (&mts->meeting_start_time.date, start_day, start_month, - start_year); - mts->meeting_start_time.hour = start_hour; - mts->meeting_start_time.minute = start_minute; - g_date_set_dmy (&mts->meeting_end_time.date, end_day, end_month, - end_year); - mts->meeting_end_time.hour = end_hour; - mts->meeting_end_time.minute = end_minute; - - mts->meeting_positions_valid = FALSE; - - gtk_widget_queue_draw (mts->display_top); - gtk_widget_queue_draw (mts->display_main); - - /* Set the times in the GnomeDateEdit widgets. */ - e_meeting_time_selector_update_start_date_edit (mts); - e_meeting_time_selector_update_end_date_edit (mts); - - return TRUE; -} - - -void -e_meeting_time_selector_set_working_hours_only (EMeetingTimeSelector *mts, - gboolean working_hours_only) -{ - EMeetingTimeSelectorTime saved_time; - - g_return_if_fail (IS_E_MEETING_TIME_SELECTOR (mts)); - - if (mts->working_hours_only == working_hours_only) - return; - - mts->working_hours_only = working_hours_only; - - e_meeting_time_selector_save_position (mts, &saved_time); - e_meeting_time_selector_recalc_grid (mts); - e_meeting_time_selector_restore_position (mts, &saved_time); - - gtk_widget_queue_draw (mts->display_top); - gtk_widget_queue_draw (mts->display_main); - e_meeting_time_selector_update_date_popup_menus (mts); -} - - -void -e_meeting_time_selector_set_working_hours (EMeetingTimeSelector *mts, - gint day_start_hour, - gint day_start_minute, - gint day_end_hour, - gint day_end_minute) -{ - EMeetingTimeSelectorTime saved_time; - - g_return_if_fail (IS_E_MEETING_TIME_SELECTOR (mts)); - - if (mts->day_start_hour == day_start_hour - && mts->day_start_minute == day_start_minute - && mts->day_end_hour == day_end_hour - && mts->day_end_minute == day_end_minute) - return; - - mts->day_start_hour = day_start_hour; - mts->day_start_minute = day_start_minute; - mts->day_end_hour = day_end_hour; - mts->day_end_minute = day_end_minute; - - e_meeting_time_selector_save_position (mts, &saved_time); - e_meeting_time_selector_recalc_grid (mts); - e_meeting_time_selector_restore_position (mts, &saved_time); - - gtk_widget_queue_draw (mts->display_top); - gtk_widget_queue_draw (mts->display_main); - e_meeting_time_selector_update_date_popup_menus (mts); -} - - -void -e_meeting_time_selector_set_zoomed_out (EMeetingTimeSelector *mts, - gboolean zoomed_out) -{ - EMeetingTimeSelectorTime saved_time; - - g_return_if_fail (IS_E_MEETING_TIME_SELECTOR (mts)); - - if (mts->zoomed_out == zoomed_out) - return; - - mts->zoomed_out = zoomed_out; - - e_meeting_time_selector_save_position (mts, &saved_time); - e_meeting_time_selector_recalc_grid (mts); - e_meeting_time_selector_restore_position (mts, &saved_time); - - gtk_widget_queue_draw (mts->display_top); - gtk_widget_queue_draw (mts->display_main); -} - - -EMeetingTimeSelectorAutopickOption -e_meeting_time_selector_get_autopick_option (EMeetingTimeSelector *mts) -{ - if (GTK_CHECK_MENU_ITEM (mts->autopick_all_item)->active) - return E_MEETING_TIME_SELECTOR_ALL_PEOPLE_AND_RESOURCES; - if (GTK_CHECK_MENU_ITEM (mts->autopick_all_people_one_resource_item)->active) - return E_MEETING_TIME_SELECTOR_ALL_PEOPLE_AND_ONE_RESOURCE; - if (GTK_CHECK_MENU_ITEM (mts->autopick_required_people_item)->active) - return E_MEETING_TIME_SELECTOR_REQUIRED_PEOPLE; - return E_MEETING_TIME_SELECTOR_REQUIRED_PEOPLE_AND_ONE_RESOURCE; -} - - -void -e_meeting_time_selector_set_autopick_option (EMeetingTimeSelector *mts, - EMeetingTimeSelectorAutopickOption autopick_option) -{ - g_return_if_fail (IS_E_MEETING_TIME_SELECTOR (mts)); - - switch (autopick_option) { - case E_MEETING_TIME_SELECTOR_ALL_PEOPLE_AND_RESOURCES: - gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (mts->autopick_all_item), TRUE); - break; - case E_MEETING_TIME_SELECTOR_ALL_PEOPLE_AND_ONE_RESOURCE: - gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (mts->autopick_all_people_one_resource_item), TRUE); - break; - case E_MEETING_TIME_SELECTOR_REQUIRED_PEOPLE: - gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (mts->autopick_required_people_item), TRUE); - break; - case E_MEETING_TIME_SELECTOR_REQUIRED_PEOPLE_AND_ONE_RESOURCE: - gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (mts->autopick_required_people_one_resource_item), TRUE); - break; - } -} - - -/* Adds an attendee to the list, returning the row. The data is meant for - something like an address book id, though if the user edits the name this - will become invalid. We'll probably have to handle address book lookup - ourself. */ -gint -e_meeting_time_selector_attendee_add (EMeetingTimeSelector *mts, - gchar *attendee_name, - gpointer data) -{ - EMeetingTimeSelectorAttendee attendee; - gint list_width, item_width; - GdkFont *font; - - g_return_val_if_fail (IS_E_MEETING_TIME_SELECTOR (mts), -1); - g_return_val_if_fail (attendee_name != NULL, -1); - - attendee.name = g_strdup (attendee_name); - attendee.type = E_MEETING_TIME_SELECTOR_REQUIRED_PERSON; - attendee.has_calendar_info = FALSE; - attendee.send_meeting_to = TRUE; - g_date_clear (&attendee.busy_periods_start.date, 1); - attendee.busy_periods_start.hour = 0; - attendee.busy_periods_start.minute = 0; - g_date_clear (&attendee.busy_periods_end.date, 1); - attendee.busy_periods_end.hour = 0; - attendee.busy_periods_end.minute = 0; - attendee.busy_periods = g_array_new (FALSE, FALSE, - sizeof (EMeetingTimeSelectorPeriod)); - attendee.busy_periods_sorted = TRUE; - attendee.longest_period_in_days = 0; - attendee.data = data; - - /* Add to the list on the left. */ - list_width = GTK_WIDGET (mts->attendees_list)->allocation.width; - item_width = MAX (1, list_width - E_MEETING_TIME_SELECTOR_ICON_COLUMN_WIDTH - E_MEETING_TIME_SELECTOR_TEXT_X_PAD * 2); - font = GTK_WIDGET (mts)->style->font; - attendee.text_item = gnome_canvas_item_new - (GNOME_CANVAS_GROUP (GNOME_CANVAS (mts->attendees_list)->root), - e_text_get_type (), - "font_gdk", font, - "anchor", GTK_ANCHOR_NW, - "clip", TRUE, - "max_lines", 1, - "editable", TRUE, - "text", attendee_name ? attendee_name : "", - "clip_width", (gdouble) item_width, - "clip_height", (gdouble) font->ascent + font->descent, - "draw_background", FALSE, - NULL); - - e_canvas_item_move_absolute(attendee.text_item, - E_MEETING_TIME_SELECTOR_ICON_COLUMN_WIDTH - + E_MEETING_TIME_SELECTOR_TEXT_X_PAD, - mts->attendees->len * mts->row_height + 1 - + E_MEETING_TIME_SELECTOR_TEXT_Y_PAD); -#if 0 - gnome_canvas_item_hide (attendee.text_item); -#endif - - gtk_signal_connect (GTK_OBJECT (attendee.text_item), "event", - GTK_SIGNAL_FUNC (e_meeting_time_selector_on_text_item_event), - mts); - - g_array_append_val (mts->attendees, attendee); - - /* Update the scroll region. */ - e_meeting_time_selector_update_attendees_list_scroll_region (mts); - e_meeting_time_selector_update_main_canvas_scroll_region (mts); - - /* Redraw the canvases. */ - gtk_widget_queue_draw (mts->display_top); - gtk_widget_queue_draw (mts->display_main); - - - return mts->attendees->len - 1; -} - - -gint -e_meeting_time_selector_attendee_find_by_name (EMeetingTimeSelector *mts, - gchar *attendee_name, - gint start_row) -{ - EMeetingTimeSelectorAttendee *attendee; - gint row; - - g_return_val_if_fail (IS_E_MEETING_TIME_SELECTOR (mts), -1); - g_return_val_if_fail (start_row >= 0, -1); - g_return_val_if_fail (start_row < mts->attendees->len, -1); - - for (row = start_row; row < mts->attendees->len; row++) { - attendee = &g_array_index (mts->attendees, - EMeetingTimeSelectorAttendee, row); - if (!strcmp (attendee->name, attendee_name)) - return row; - } - - return -1; -} - - -gint -e_meeting_time_selector_attendee_find_by_data (EMeetingTimeSelector *mts, - gpointer data, - gint start_row) -{ - EMeetingTimeSelectorAttendee *attendee; - gint row; - - g_return_val_if_fail (IS_E_MEETING_TIME_SELECTOR (mts), -1); - g_return_val_if_fail (start_row >= 0, -1); - g_return_val_if_fail (start_row < mts->attendees->len, -1); - - for (row = start_row; row < mts->attendees->len; row++) { - attendee = &g_array_index (mts->attendees, - EMeetingTimeSelectorAttendee, row); - if (attendee->data == data) - return row; - } - - return -1; -} - - -void -e_meeting_time_selector_attendee_remove (EMeetingTimeSelector *mts, - gint row) -{ - EMeetingTimeSelectorAttendee *attendee; - - g_return_if_fail (IS_E_MEETING_TIME_SELECTOR (mts)); - g_return_if_fail (row >= 0); - g_return_if_fail (row < mts->attendees->len); - - attendee = &g_array_index (mts->attendees, - EMeetingTimeSelectorAttendee, row); - - g_free (attendee->name); - g_array_free (attendee->busy_periods, TRUE); - - /* Destroy the GtkEntry in the list. */ - gtk_object_destroy (GTK_OBJECT (attendee->text_item)); - - g_array_remove_index (mts->attendees, row); - - /* Update the positions of all the other GtkEntry widgets. */ - e_meeting_time_selector_update_attendees_list_positions (mts); - - e_meeting_time_selector_update_attendees_list_scroll_region (mts); - e_meeting_time_selector_update_main_canvas_scroll_region (mts); - gtk_widget_queue_draw (mts->display_top); - gtk_widget_queue_draw (mts->display_main); -} - - -void -e_meeting_time_selector_attendee_set_type (EMeetingTimeSelector *mts, - gint row, - EMeetingTimeSelectorAttendeeType type) -{ - EMeetingTimeSelectorAttendee *attendee; - - g_return_if_fail (IS_E_MEETING_TIME_SELECTOR (mts)); - g_return_if_fail (row >= 0); - g_return_if_fail (row < mts->attendees->len); - - attendee = &g_array_index (mts->attendees, - EMeetingTimeSelectorAttendee, row); - attendee->type = type; -} - - -void -e_meeting_time_selector_attendee_set_has_calendar_info (EMeetingTimeSelector *mts, - gint row, - gboolean has_calendar_info) -{ - EMeetingTimeSelectorAttendee *attendee; - - g_return_if_fail (IS_E_MEETING_TIME_SELECTOR (mts)); - g_return_if_fail (row >= 0); - g_return_if_fail (row < mts->attendees->len); - - attendee = &g_array_index (mts->attendees, - EMeetingTimeSelectorAttendee, row); - attendee->has_calendar_info = has_calendar_info; -} - - -void -e_meeting_time_selector_attendee_set_send_meeting_to (EMeetingTimeSelector *mts, - gint row, - gboolean send_meeting_to) -{ - EMeetingTimeSelectorAttendee *attendee; - - g_return_if_fail (IS_E_MEETING_TIME_SELECTOR (mts)); - g_return_if_fail (row >= 0); - g_return_if_fail (row < mts->attendees->len); - - attendee = &g_array_index (mts->attendees, - EMeetingTimeSelectorAttendee, row); - attendee->send_meeting_to = send_meeting_to; -} - - -gboolean -e_meeting_time_selector_attendee_set_busy_range (EMeetingTimeSelector *mts, - gint row, - gint start_year, - gint start_month, - gint start_day, - gint start_hour, - gint start_minute, - gint end_year, - gint end_month, - gint end_day, - gint end_hour, - gint end_minute) -{ - EMeetingTimeSelectorAttendee *attendee; - - g_return_val_if_fail (IS_E_MEETING_TIME_SELECTOR (mts), FALSE); - g_return_val_if_fail (row >= 0, FALSE); - g_return_val_if_fail (row < mts->attendees->len, FALSE); - - /* Check the dates are valid. */ - if (!g_date_valid_dmy (start_day, start_month, start_year)) - return FALSE; - if (!g_date_valid_dmy (end_day, end_month, end_year)) - return FALSE; - if (start_hour < 0 || start_hour > 23) - return FALSE; - if (end_hour < 0 || end_hour > 23) - return FALSE; - if (start_minute < 0 || start_minute > 59) - return FALSE; - if (end_minute < 0 || end_minute > 59) - return FALSE; - - attendee = &g_array_index (mts->attendees, - EMeetingTimeSelectorAttendee, row); - - g_date_clear (&attendee->busy_periods_start.date, 1); - g_date_clear (&attendee->busy_periods_end.date, 1); - g_date_set_dmy (&attendee->busy_periods_start.date, - start_day, start_month, start_year); - g_date_set_dmy (&attendee->busy_periods_end.date, - end_day, end_month, end_year); - attendee->busy_periods_start.hour = start_hour; - attendee->busy_periods_start.minute = start_minute; - attendee->busy_periods_end.hour = end_hour; - attendee->busy_periods_end.minute = end_minute; - - return TRUE; -} - - -/* Clears all busy times for the given attendee. */ -void -e_meeting_time_selector_attendee_clear_busy_periods (EMeetingTimeSelector *mts, - gint row) -{ - EMeetingTimeSelectorAttendee *attendee; - - g_return_if_fail (IS_E_MEETING_TIME_SELECTOR (mts)); - g_return_if_fail (row >= 0); - g_return_if_fail (row < mts->attendees->len); - - attendee = &g_array_index (mts->attendees, - EMeetingTimeSelectorAttendee, row); - - g_array_set_size (attendee->busy_periods, 0); - attendee->busy_periods_sorted = TRUE; - attendee->longest_period_in_days = 0; -} - - -/* Adds one busy time for the given attendee. It returns FALSE if the date - or time is invalid. Months and days count from 1. */ -gboolean -e_meeting_time_selector_attendee_add_busy_period (EMeetingTimeSelector *mts, - gint row, - gint start_year, - gint start_month, - gint start_day, - gint start_hour, - gint start_minute, - gint end_year, - gint end_month, - gint end_day, - gint end_hour, - gint end_minute, - EMeetingTimeSelectorBusyType busy_type) -{ - EMeetingTimeSelectorAttendee *attendee; - EMeetingTimeSelectorPeriod period; - gint period_in_days; - - g_return_val_if_fail (IS_E_MEETING_TIME_SELECTOR (mts), FALSE); - g_return_val_if_fail (row >= 0, FALSE); - g_return_val_if_fail (row < mts->attendees->len, FALSE); - g_return_val_if_fail (busy_type >= 0, FALSE); - g_return_val_if_fail (busy_type < E_MEETING_TIME_SELECTOR_BUSY_LAST, FALSE); - - /* Check the dates are valid. */ - if (!g_date_valid_dmy (start_day, start_month, start_year)) - return FALSE; - if (!g_date_valid_dmy (end_day, end_month, end_year)) - return FALSE; - if (start_hour < 0 || start_hour > 23) - return FALSE; - if (end_hour < 0 || end_hour > 23) - return FALSE; - if (start_minute < 0 || start_minute > 59) - return FALSE; - if (end_minute < 0 || end_minute > 59) - return FALSE; - - g_date_clear (&period.start.date, 1); - g_date_clear (&period.end.date, 1); - g_date_set_dmy (&period.start.date, start_day, start_month, start_year); - g_date_set_dmy (&period.end.date, end_day, end_month, end_year); - period.start.hour = start_hour; - period.start.minute = start_minute; - period.end.hour = end_hour; - period.end.minute = end_minute; - period.busy_type = busy_type; - - /* Check that the start time is before or equal to the end time. */ - if (e_meeting_time_selector_compare_times (&period.start, &period.end) > 0) - return FALSE; - - attendee = &g_array_index (mts->attendees, - EMeetingTimeSelectorAttendee, row); - g_array_append_val (attendee->busy_periods, period); - attendee->has_calendar_info = TRUE; - attendee->busy_periods_sorted = FALSE; - - period_in_days = g_date_julian (&period.end.date) - g_date_julian (&period.start.date) + 1; - attendee->longest_period_in_days = MAX (attendee->longest_period_in_days, period_in_days); - - return TRUE; -} - - -void -e_meeting_time_selector_attendee_ensure_periods_sorted (EMeetingTimeSelector *mts, - EMeetingTimeSelectorAttendee *attendee) -{ - if (attendee->busy_periods_sorted) - return; - - qsort (attendee->busy_periods->data, attendee->busy_periods->len, - sizeof (EMeetingTimeSelectorPeriod), - e_meeting_time_selector_compare_period_starts); - attendee->busy_periods_sorted = TRUE; -} - - -/* This compares two time periods, using their end times. */ -static gint -e_meeting_time_selector_compare_period_starts (const void *arg1, - const void *arg2) -{ - EMeetingTimeSelectorPeriod *period1, *period2; - - period1 = (EMeetingTimeSelectorPeriod *) arg1; - period2 = (EMeetingTimeSelectorPeriod *) arg2; - - return e_meeting_time_selector_compare_times (&period1->start, - &period2->start); -} - - -/* This compares two time periods, using start and end times, mainly to see if - they overlap at all. If they overlap it returns 0. Or -1 if arg1 < arg2. - Or 1 if arg1 > arg2. */ -/* Currently unused. */ -#if 0 -static gint -e_meeting_time_selector_compare_periods (const void *arg1, - const void *arg2) -{ - EMeetingTimeSelectorPeriod *period1, *period2; - - period1 = (EMeetingTimeSelectorPeriod *) arg1; - period2 = (EMeetingTimeSelectorPeriod *) arg2; - - /* If period 2 starts after period 1 ends, return 1. */ - if (e_meeting_time_selector_compare_times (&period2->start, &period1->end) >= 0) - return 1; - - /* If period 1 starts after period 2 ends, return -1. */ - if (e_meeting_time_selector_compare_times (&period1->start, &period2->end) >= 0) - return -1; - - /* They must overlap so return 0. */ - return 0; -} -#endif - - -static gint -e_meeting_time_selector_compare_times (EMeetingTimeSelectorTime *time1, - EMeetingTimeSelectorTime *time2) -{ - gint day_comparison; - - day_comparison = g_date_compare (&time1->date, - &time2->date); - if (day_comparison != 0) - return day_comparison; - - if (time1->hour < time2->hour) - return -1; - if (time1->hour > time2->hour) - return 1; - - if (time1->minute < time2->minute) - return -1; - if (time1->minute > time2->minute) - return 1; - - /* The start times are exactly the same. */ - return 0; -} - - -/* - * DEBUGGING ROUTINES - functions to output various bits of data. - */ - -#ifdef E_MEETING_TIME_SELECTOR_DEBUG - -/* Debugging function to dump information on all attendees. */ -void -e_meeting_time_selector_dump (EMeetingTimeSelector *mts) -{ - EMeetingTimeSelectorAttendee *attendee; - EMeetingTimeSelectorPeriod *period; - gint row, period_num; - gchar buffer[128]; - - g_return_if_fail (IS_E_MEETING_TIME_SELECTOR (mts)); - - g_print ("\n\nAttendee Information:\n"); - - for (row = 0; row < mts->attendees->len; row++) { - attendee = &g_array_index (mts->attendees, - EMeetingTimeSelectorAttendee, row); - g_print ("Attendee: %s\n", attendee->name); - g_print (" Longest Busy Period: %i days\n", - attendee->longest_period_in_days); - - e_meeting_time_selector_attendee_ensure_periods_sorted (mts, attendee); -#if 1 - for (period_num = 0; - period_num < attendee->busy_periods->len; - period_num++) { - period = &g_array_index (attendee->busy_periods, - EMeetingTimeSelectorPeriod, - period_num); - - /* These are just for debugging so don't need i18n. */ - g_date_strftime (buffer, sizeof (buffer), - "%A, %B %d, %Y", &period->start.date); - g_print (" Start: %s %i:%02i\n", buffer, - period->start.hour, period->start.minute); - - g_date_strftime (buffer, sizeof (buffer), - "%A, %B %d, %Y", &period->end.date); - g_print (" End : %s %i:%02i\n", buffer, - period->end.hour, period->end.minute); - } -#endif - } - -} - - -/* This formats a EMeetingTimeSelectorTime in a string and returns it. - Note that it uses a static buffer. */ -gchar* -e_meeting_time_selector_dump_time (EMeetingTimeSelectorTime *mtstime) -{ - static gchar buffer[128]; - - gchar buffer2[128]; - - /* This is just for debugging so doesn't need i18n. */ - g_date_strftime (buffer, sizeof (buffer), "%A, %B %d, %Y", - &mtstime->date); - sprintf (buffer2, " at %i:%02i", (gint) mtstime->hour, - (gint) mtstime->minute); - strcat (buffer, buffer2); - - return buffer; -} - - -/* This formats a GDate in a string and returns it. - Note that it uses a static buffer. */ -gchar* -e_meeting_time_selector_dump_date (GDate *date) -{ - static gchar buffer[128]; - - /* This is just for debugging so doesn't need i18n. */ - g_date_strftime (buffer, sizeof (buffer), "%A, %B %d, %Y", date); - return buffer; -} - -#endif /* E_MEETING_TIME_SELECTOR_DEBUG */ - - -static void -e_meeting_time_selector_on_invite_others_button_clicked (GtkWidget *button, - EMeetingTimeSelector *mts) -{ - - -} - - -static void -e_meeting_time_selector_on_options_button_clicked (GtkWidget *button, - EMeetingTimeSelector *mts) -{ - gtk_menu_popup (GTK_MENU (mts->options_menu), NULL, NULL, - e_meeting_time_selector_options_menu_position_callback, - mts, 1, GDK_CURRENT_TIME); -} - - -static void -e_meeting_time_selector_options_menu_position_callback (GtkMenu *menu, - gint *x, - gint *y, - gpointer user_data) -{ - EMeetingTimeSelector *mts; - GtkRequisition menu_requisition; - gint max_x, max_y; - - mts = E_MEETING_TIME_SELECTOR (user_data); - - /* Calculate our preferred position. */ - gdk_window_get_origin (mts->options_button->window, x, y); - *y += mts->options_button->allocation.height; - - /* Now make sure we are on the screen. */ - gtk_widget_size_request (mts->options_menu, &menu_requisition); - max_x = MAX (0, gdk_screen_width () - menu_requisition.width); - max_y = MAX (0, gdk_screen_height () - menu_requisition.height); - *x = CLAMP (*x, 0, max_x); - *y = CLAMP (*y, 0, max_y); -} - - -static void -e_meeting_time_selector_on_update_free_busy (GtkWidget *button, - EMeetingTimeSelector *mts) -{ - - /* Make sure the menu pops down, which doesn't happen by default if - keyboard accelerators are used. */ - if (GTK_WIDGET_VISIBLE (mts->options_menu)) - gtk_menu_popdown (GTK_MENU (mts->options_menu)); -} - - -static void -e_meeting_time_selector_on_autopick_button_clicked (GtkWidget *button, - EMeetingTimeSelector *mts) -{ - gtk_menu_popup (GTK_MENU (mts->autopick_menu), NULL, NULL, - e_meeting_time_selector_autopick_menu_position_callback, - mts, 1, GDK_CURRENT_TIME); -} - - -static void -e_meeting_time_selector_autopick_menu_position_callback (GtkMenu *menu, - gint *x, - gint *y, - gpointer user_data) -{ - EMeetingTimeSelector *mts; - GtkRequisition menu_requisition; - gint max_x, max_y; - - mts = E_MEETING_TIME_SELECTOR (user_data); - - /* Calculate our preferred position. */ - gdk_window_get_origin (mts->autopick_button->window, x, y); - *y += mts->autopick_button->allocation.height; - - /* Now make sure we are on the screen. */ - gtk_widget_size_request (mts->autopick_menu, &menu_requisition); - max_x = MAX (0, gdk_screen_width () - menu_requisition.width); - max_y = MAX (0, gdk_screen_height () - menu_requisition.height); - *x = CLAMP (*x, 0, max_x); - *y = CLAMP (*y, 0, max_y); -} - - -static void -e_meeting_time_selector_on_autopick_option_toggled (GtkWidget *button, - EMeetingTimeSelector *mts) -{ - /* Make sure the menu pops down, which doesn't happen by default if - keyboard accelerators are used. */ - if (GTK_WIDGET_VISIBLE (mts->autopick_menu)) - gtk_menu_popdown (GTK_MENU (mts->autopick_menu)); -} - - -static void -e_meeting_time_selector_on_prev_button_clicked (GtkWidget *button, - EMeetingTimeSelector *mts) -{ - e_meeting_time_selector_autopick (mts, FALSE); -} - - -static void -e_meeting_time_selector_on_next_button_clicked (GtkWidget *button, - EMeetingTimeSelector *mts) -{ - e_meeting_time_selector_autopick (mts, TRUE); -} - - -/* This tries to find the previous or next meeting time for which all - attendees will be available. */ -static void -e_meeting_time_selector_autopick (EMeetingTimeSelector *mts, - gboolean forward) -{ - EMeetingTimeSelectorTime start_time, end_time, *resource_free; - EMeetingTimeSelectorAttendee *attendee; - EMeetingTimeSelectorPeriod *period; - EMeetingTimeSelectorAutopickOption autopick_option; - gint duration_days, duration_hours, duration_minutes, row; - gboolean meeting_time_ok, skip_optional = FALSE; - gboolean need_one_resource = FALSE, found_resource; - - /* Get the current meeting duration in days + hours + minutes. */ - e_meeting_time_selector_calculate_time_difference (&mts->meeting_start_time, &mts->meeting_end_time, &duration_days, &duration_hours, &duration_minutes); - - /* Find the first appropriate start time. */ - start_time = mts->meeting_start_time; - if (forward) - e_meeting_time_selector_find_nearest_interval (mts, &start_time, &end_time, duration_days, duration_hours, duration_minutes); - else - e_meeting_time_selector_find_nearest_interval_backward (mts, &start_time, &end_time, duration_days, duration_hours, duration_minutes); - - /* Determine if we can skip optional people and if we only need one - resource based on the autopick option. */ - autopick_option = e_meeting_time_selector_get_autopick_option (mts); - if (autopick_option == E_MEETING_TIME_SELECTOR_REQUIRED_PEOPLE - || autopick_option == E_MEETING_TIME_SELECTOR_REQUIRED_PEOPLE_AND_ONE_RESOURCE) - skip_optional = TRUE; - if (autopick_option == E_MEETING_TIME_SELECTOR_ALL_PEOPLE_AND_ONE_RESOURCE - || autopick_option == E_MEETING_TIME_SELECTOR_REQUIRED_PEOPLE_AND_ONE_RESOURCE) - need_one_resource = TRUE; - - /* Keep moving forward or backward until we find a possible meeting - time. */ - for (;;) { - meeting_time_ok = TRUE; - found_resource = FALSE; - resource_free = NULL; - - /* Step through each attendee, checking if the meeting time - intersects one of the attendees busy periods. */ - for (row = 0; row < mts->attendees->len; row++) { - attendee = &g_array_index (mts->attendees, - EMeetingTimeSelectorAttendee, - row); - - /* Skip optional people if they don't matter. */ - if (skip_optional && attendee->type == E_MEETING_TIME_SELECTOR_OPTIONAL_PERSON) - continue; - - period = e_meeting_time_selector_find_time_clash (mts, attendee, &start_time, &end_time); - - if (need_one_resource && attendee->type == E_MEETING_TIME_SELECTOR_RESOURCE) { - if (period) { - /* We want to remember the closest - prev/next time that one resource is - available, in case we don't find any - free resources. */ - if (forward) { - if (!resource_free || e_meeting_time_selector_compare_times (resource_free, &period->end) > 0) - resource_free = &period->end; - } else { - if (!resource_free || e_meeting_time_selector_compare_times (resource_free, &period->start) < 0) - resource_free = &period->start; - } - - } else { - found_resource = TRUE; - } - } else if (period) { - /* Skip the period which clashed. */ - if (forward) { - start_time = period->end; - } else { - start_time = period->start; - e_meeting_time_selector_adjust_time (&start_time, -duration_days, -duration_hours, -duration_minutes); - } - meeting_time_ok = FALSE; - break; - } - } - - /* Check that we found one resource if necessary. If not, skip - to the closest time that a resource is free. Note that if - there are no resources, resource_free will never get set, - so we assume the meeting time is OK. */ - if (meeting_time_ok && need_one_resource && !found_resource - && resource_free) { - if (forward) { - start_time = *resource_free; - } else { - start_time = *resource_free; - e_meeting_time_selector_adjust_time (&start_time, -duration_days, -duration_hours, -duration_minutes); - } - meeting_time_ok = FALSE; - } - - if (meeting_time_ok) { - mts->meeting_start_time = start_time; - mts->meeting_end_time = end_time; - mts->meeting_positions_valid = FALSE; - gtk_widget_queue_draw (mts->display_top); - gtk_widget_queue_draw (mts->display_main); - - /* Make sure the time is shown. */ - e_meeting_time_selector_ensure_meeting_time_shown (mts); - - /* Set the times in the GnomeDateEdit widgets. */ - e_meeting_time_selector_update_start_date_edit (mts); - e_meeting_time_selector_update_end_date_edit (mts); - return; - } - - /* Move forward to the next possible interval. */ - if (forward) - e_meeting_time_selector_find_nearest_interval (mts, &start_time, &end_time, duration_days, duration_hours, duration_minutes); - else - e_meeting_time_selector_find_nearest_interval_backward (mts, &start_time, &end_time, duration_days, duration_hours, duration_minutes); - } -} - - -static void -e_meeting_time_selector_calculate_time_difference (EMeetingTimeSelectorTime *start, - EMeetingTimeSelectorTime *end, - gint *days, - gint *hours, - gint *minutes) -{ - *days = g_date_julian (&end->date) - g_date_julian (&start->date); - *hours = end->hour - start->hour; - *minutes = end->minute - start->minute; - if (*minutes < 0) { - *minutes += 60; - *hours = *hours - 1; - } - if (*hours < 0) { - *hours += 24; - *days = *days - 1; - } -} - - -/* This moves the given time forward to the next suitable start of a meeting. - If zoomed_out is set, this means every hour. If not every half-hour. */ -static void -e_meeting_time_selector_find_nearest_interval (EMeetingTimeSelector *mts, - EMeetingTimeSelectorTime *start_time, - EMeetingTimeSelectorTime *end_time, - gint days, gint hours, gint mins) -{ - gint minutes_shown; - gboolean set_to_start_of_working_day = FALSE; - - if (mts->zoomed_out) { - start_time->hour++; - start_time->minute = 0; - } else { - start_time->minute += 30; - start_time->minute -= start_time->minute % 30; - } - e_meeting_time_selector_fix_time_overflows (start_time); - - *end_time = *start_time; - e_meeting_time_selector_adjust_time (end_time, days, hours, mins); - - /* Check if the interval is less than a day as seen in the display. - If it isn't we don't worry about the working day. */ - if (!mts->working_hours_only || days > 0) - return; - minutes_shown = (mts->day_end_hour - mts->day_start_hour) * 60; - minutes_shown += mts->day_end_minute - mts->day_start_minute; - if (hours * 60 + mins > minutes_shown) - return; - - /* If the meeting time finishes past the end of the working day, move - onto the start of the next working day. If the meeting time starts - before the working day, move it on as well. */ - if (start_time->hour > mts->day_end_hour - || (start_time->hour == mts->day_end_hour - && start_time->minute > mts->day_end_minute) - || end_time->hour > mts->day_end_hour - || (end_time->hour == mts->day_end_hour - && end_time->minute > mts->day_end_minute)) { - g_date_add_days (&start_time->date, 1); - set_to_start_of_working_day = TRUE; - } else if (start_time->hour < mts->day_start_hour - || (start_time->hour == mts->day_start_hour - && start_time->minute < mts->day_start_minute)) { - set_to_start_of_working_day = TRUE; - } - - if (set_to_start_of_working_day) { - start_time->hour = mts->day_start_hour; - start_time->minute = mts->day_start_minute; - - if (mts->zoomed_out) { - if (start_time->minute > 0) { - start_time->hour++; - start_time->minute = 0; - } - } else { - start_time->minute += 29; - start_time->minute -= start_time->minute % 30; - } - e_meeting_time_selector_fix_time_overflows (start_time); - - *end_time = *start_time; - e_meeting_time_selector_adjust_time (end_time, days, hours, mins); - } -} - - -/* This moves the given time backward to the next suitable start of a meeting. - If zoomed_out is set, this means every hour. If not every half-hour. */ -static void -e_meeting_time_selector_find_nearest_interval_backward (EMeetingTimeSelector *mts, - EMeetingTimeSelectorTime *start_time, - EMeetingTimeSelectorTime *end_time, - gint days, gint hours, gint mins) -{ - gint new_hour, minutes_shown; - gboolean set_to_end_of_working_day = FALSE; - - new_hour = start_time->hour; - if (mts->zoomed_out) { - if (start_time->minute == 0) - new_hour--; - start_time->minute = 0; - } else { - if (start_time->minute == 0) { - start_time->minute = 30; - new_hour--; - } else if (start_time->minute <= 30) - start_time->minute = 0; - else - start_time->minute = 30; - } - if (new_hour < 0) { - new_hour += 24; - g_date_subtract_days (&start_time->date, 1); - } - start_time->hour = new_hour; - - *end_time = *start_time; - e_meeting_time_selector_adjust_time (end_time, days, hours, mins); - - /* Check if the interval is less than a day as seen in the display. - If it isn't we don't worry about the working day. */ - if (!mts->working_hours_only || days > 0) - return; - minutes_shown = (mts->day_end_hour - mts->day_start_hour) * 60; - minutes_shown += mts->day_end_minute - mts->day_start_minute; - if (hours * 60 + mins > minutes_shown) - return; - - /* If the meeting time finishes past the end of the working day, move - back to the end of the working day. If the meeting time starts - before the working day, move it back to the end of the previous - working day. */ - if (start_time->hour > mts->day_end_hour - || (start_time->hour == mts->day_end_hour - && start_time->minute > mts->day_end_minute) - || end_time->hour > mts->day_end_hour - || (end_time->hour == mts->day_end_hour - && end_time->minute > mts->day_end_minute)) { - set_to_end_of_working_day = TRUE; - } else if (start_time->hour < mts->day_start_hour - || (start_time->hour == mts->day_start_hour - && start_time->minute < mts->day_start_minute)) { - g_date_subtract_days (&end_time->date, 1); - set_to_end_of_working_day = TRUE; - } - - if (set_to_end_of_working_day) { - end_time->hour = mts->day_end_hour; - end_time->minute = mts->day_end_minute; - *start_time = *end_time; - e_meeting_time_selector_adjust_time (start_time, -days, -hours, -mins); - - if (mts->zoomed_out) { - start_time->minute = 0; - } else { - start_time->minute -= start_time->minute % 30; - } - - *end_time = *start_time; - e_meeting_time_selector_adjust_time (end_time, days, hours, mins); - } -} - - -/* This adds on the given days, hours & minutes to a EMeetingTimeSelectorTime. - It is used to calculate the end of a period given a start & duration. - Days, hours & minutes can be negative, to move backwards, but they should - be within normal ranges, e.g. hours should be between -23 and 23. */ -static void -e_meeting_time_selector_adjust_time (EMeetingTimeSelectorTime *mtstime, - gint days, gint hours, gint minutes) -{ - gint new_hours, new_minutes; - - /* We have to handle negative values for hous and minutes here, since - EMeetingTimeSelectorTime uses guint8s to store them. */ - new_minutes = mtstime->minute + minutes; - if (new_minutes < 0) { - new_minutes += 60; - hours -= 1; - } - - new_hours = mtstime->hour + hours; - if (new_hours < 0) { - new_hours += 24; - days -= 1; - } - - g_date_add_days (&mtstime->date, days); - mtstime->hour = new_hours; - mtstime->minute = new_minutes; - - e_meeting_time_selector_fix_time_overflows (mtstime); -} - - -/* This looks for any busy period of the given attendee which clashes with - the start and end time. It uses a binary search. */ -static EMeetingTimeSelectorPeriod* -e_meeting_time_selector_find_time_clash (EMeetingTimeSelector *mts, - EMeetingTimeSelectorAttendee *attendee, - EMeetingTimeSelectorTime *start_time, - EMeetingTimeSelectorTime *end_time) -{ - EMeetingTimeSelectorPeriod *period; - gint period_num; - - period_num = e_meeting_time_selector_find_first_busy_period (mts, attendee, &start_time->date); - - if (period_num == -1) - return NULL; - - /* Step forward through the busy periods until we find a clash or we - go past the end_time. */ - while (period_num < attendee->busy_periods->len) { - period = &g_array_index (attendee->busy_periods, - EMeetingTimeSelectorPeriod, - period_num); - - /* If the period starts at or after the end time, there is no - clash and we are finished. The busy periods are sorted by - their start times, so all the rest will be later. */ - if (e_meeting_time_selector_compare_times (&period->start, - end_time) >= 0) - return NULL; - - /* If the period ends after the start time, we have found a - clash. From the above test we already know the busy period - isn't completely after the meeting time. */ - if (e_meeting_time_selector_compare_times (&period->end, - start_time) > 0) { - return period; - } - - period_num++; - } - - return NULL; -} - - -/* This subtracts the attendees longest_period_in_days from the given date, - and does a binary search of the attendee's busy periods array to find the - first one which could possible end on the given day or later. - If none are found it returns -1. */ -gint -e_meeting_time_selector_find_first_busy_period (EMeetingTimeSelector *mts, - EMeetingTimeSelectorAttendee *attendee, - GDate *date) -{ - EMeetingTimeSelectorPeriod *period; - gint lower, upper, middle = 0, cmp = 0; - GDate tmp_date; - - /* Make sure the busy periods have been sorted. */ - e_meeting_time_selector_attendee_ensure_periods_sorted (mts, attendee); - - /* Calculate the first day which could have a busy period which - continues onto our given date. */ - tmp_date = *date; - g_date_subtract_days (&tmp_date, attendee->longest_period_in_days); - - /* We want the first busy period which starts on tmp_date. */ - lower = 0; - upper = attendee->busy_periods->len; - - if (upper == 0) - return -1; - - while (lower < upper) { - middle = (lower + upper) >> 1; - - period = &g_array_index (attendee->busy_periods, - EMeetingTimeSelectorPeriod, middle); - - cmp = g_date_compare (&tmp_date, &period->start.date); - - if (cmp == 0) - break; - else if (cmp < 0) - upper = middle; - else - lower = middle + 1; - } - - /* There may be several busy periods on the same day so we step - backwards to the first one. */ - if (cmp == 0) { - while (middle > 0) { - period = &g_array_index (attendee->busy_periods, - EMeetingTimeSelectorPeriod, middle - 1); - if (g_date_compare (&tmp_date, &period->start.date) != 0) - break; - middle--; - } - } else if (cmp > 0) { - /* This means we couldn't find a period on the given day, and - the last one we looked at was before it, so if there are - any more periods after this one we return it. */ - middle++; - if (attendee->busy_periods->len <= middle) - return -1; - } - - return middle; -} - - -static void -e_meeting_time_selector_on_zoomed_out_toggled (GtkWidget *menuitem, - EMeetingTimeSelector *mts) -{ - /* Make sure the menu pops down, which doesn't happen by default if - keyboard accelerators are used. */ - if (GTK_WIDGET_VISIBLE (mts->options_menu)) - gtk_menu_popdown (GTK_MENU (mts->options_menu)); - - e_meeting_time_selector_set_zoomed_out (mts, GTK_CHECK_MENU_ITEM (menuitem)->active); -} - - -static void -e_meeting_time_selector_on_working_hours_toggled (GtkWidget *menuitem, - EMeetingTimeSelector *mts) -{ - /* Make sure the menu pops down, which doesn't happen by default if - keyboard accelerators are used. */ - if (GTK_WIDGET_VISIBLE (mts->options_menu)) - gtk_menu_popdown (GTK_MENU (mts->options_menu)); - - e_meeting_time_selector_set_working_hours_only (mts, GTK_CHECK_MENU_ITEM (menuitem)->active); -} - - -/* This recalculates day_width, first_hour_shown and last_hour_shown. */ -static void -e_meeting_time_selector_recalc_grid (EMeetingTimeSelector *mts) -{ - if (mts->working_hours_only) { - mts->first_hour_shown = mts->day_start_hour; - mts->last_hour_shown = mts->day_end_hour; - if (mts->day_end_minute != 0) - mts->last_hour_shown += 1; - } else { - mts->first_hour_shown = 0; - mts->last_hour_shown = 24; - } - - /* In the brief view we use the nearest hours divisible by 3. */ - if (mts->zoomed_out) { - mts->first_hour_shown -= mts->first_hour_shown % 3; - mts->last_hour_shown += 2; - mts->last_hour_shown -= mts->last_hour_shown % 3; - } - - mts->day_width = mts->col_width * (mts->last_hour_shown - mts->first_hour_shown); - if (mts->zoomed_out) - mts->day_width /= 3; - - /* Add one pixel for the extra vertical grid line. */ - mts->day_width++; - - gnome_canvas_set_scroll_region (GNOME_CANVAS (mts->display_top), - 0, 0, - mts->day_width * E_MEETING_TIME_SELECTOR_DAYS_SHOWN, - mts->row_height * 3); - e_meeting_time_selector_update_main_canvas_scroll_region (mts); - - e_meeting_time_selector_recalc_date_format (mts); - mts->meeting_positions_valid = FALSE; -} - - -/* This saves the first visible time in the given EMeetingTimeSelectorTime. */ -static void -e_meeting_time_selector_save_position (EMeetingTimeSelector *mts, - EMeetingTimeSelectorTime *mtstime) -{ - gint scroll_x, scroll_y; - - gnome_canvas_get_scroll_offsets (GNOME_CANVAS (mts->display_main), - &scroll_x, &scroll_y); - e_meeting_time_selector_calculate_time (mts, scroll_x, mtstime); -} - - -/* This restores a saved position. */ -static void -e_meeting_time_selector_restore_position (EMeetingTimeSelector *mts, - EMeetingTimeSelectorTime *mtstime) -{ - gint scroll_x, scroll_y, new_scroll_x; - - new_scroll_x = e_meeting_time_selector_calculate_time_position (mts, - mtstime); - gnome_canvas_get_scroll_offsets (GNOME_CANVAS (mts->display_main), - &scroll_x, &scroll_y); - gnome_canvas_scroll_to (GNOME_CANVAS (mts->display_main), - new_scroll_x, scroll_y); -} - - -/* This returns the x pixel coords of the meeting time in the entire scroll - region. It recalculates them if they have been marked as invalid. - If it returns FALSE then no meeting time is set or the meeting time is - not visible in the current scroll area. */ -gboolean -e_meeting_time_selector_get_meeting_time_positions (EMeetingTimeSelector *mts, - gint *start_x, - gint *end_x) -{ - if (mts->meeting_positions_valid) { - if (mts->meeting_positions_in_scroll_area) { - *start_x = mts->meeting_start_x; - *end_x = mts->meeting_end_x; - return TRUE; - } else { - return FALSE; - } - } - - mts->meeting_positions_valid = TRUE; - - /* Check if the days aren't in our current range. */ - if (g_date_compare (&mts->meeting_start_time.date, &mts->last_date_shown) > 0 - || g_date_compare (&mts->meeting_end_time.date, &mts->first_date_shown) < 0) { - mts->meeting_positions_in_scroll_area = FALSE; - return FALSE; - } - - mts->meeting_positions_in_scroll_area = TRUE; - *start_x = mts->meeting_start_x = e_meeting_time_selector_calculate_time_position (mts, &mts->meeting_start_time); - *end_x = mts->meeting_end_x = e_meeting_time_selector_calculate_time_position (mts, &mts->meeting_end_time); - - return TRUE; -} - - -/* This recalculates the date format to used, by computing the width of the - longest date strings in the widget's font and seeing if they fit. */ -static void -e_meeting_time_selector_recalc_date_format (EMeetingTimeSelector *mts) -{ - /* An array of dates, one for each month in the year 2000. They must - all be Sundays. */ - static const int days[12] = { 23, 20, 19, 23, 21, 18, - 23, 20, 17, 22, 19, 24 }; - GDate date; - gint max_date_width, longest_weekday_width, longest_month_width, width; - gint day, longest_weekday, month, longest_month; - gchar buffer[128]; - GdkFont *font; - - font = GTK_WIDGET (mts)->style->font; - - /* Calculate the maximum date width we can fit into the display. */ - max_date_width = mts->day_width - 2; - - /* Find the biggest full weekday name. We start on a particular - Monday and go through seven days. */ - g_date_clear (&date, 1); - g_date_set_dmy (&date, 3, 1, 2000); /* Monday 3rd Jan 2000. */ - longest_weekday_width = 0; - longest_weekday = G_DATE_MONDAY; - for (day = G_DATE_MONDAY; day <= G_DATE_SUNDAY; day++) { - g_date_strftime (buffer, sizeof (buffer), "%A", &date); - width = gdk_string_width (font, buffer); - if (width > longest_weekday_width) { - longest_weekday = day; - longest_weekday_width = width; - } - g_date_add_days (&date, 1); - } - - /* Now find the biggest month name. */ - longest_month_width = 0; - longest_month = G_DATE_JANUARY; - for (month = G_DATE_JANUARY; month <= G_DATE_DECEMBER; month++) { - g_date_set_month (&date, month); - g_date_strftime (buffer, sizeof (buffer), "%B", &date); - width = gdk_string_width (font, buffer); - if (width > longest_month_width) { - longest_month = month; - longest_month_width = width; - } - } - - /* See if we can use the full date. We want to use a date with a - month day > 20 and also the longest weekday. We use a - pre-calculated array of days for each month and add on the - weekday (which is 1 (Mon) to 7 (Sun). */ - g_date_set_dmy (&date, days[longest_month - 1] + longest_weekday, - longest_month, 2000); - /* This is a strftime() format string %A = full weekday name, - %B = full month name, %d = month day, %Y = full year. */ - g_date_strftime (buffer, sizeof (buffer), _("%A, %B %d, %Y"), &date); - - g_print ("longest_month: %i longest_weekday: %i date: %s\n", - longest_month, longest_weekday, buffer); - - if (gdk_string_width (font, buffer) < max_date_width) { - mts->date_format = E_MEETING_TIME_SELECTOR_DATE_FULL; - return; - } - - /* Now try it with abbreviated weekday names. */ - longest_weekday_width = 0; - longest_weekday = G_DATE_MONDAY; - g_date_set_dmy (&date, 3, 1, 2000); /* Monday 3rd Jan 2000. */ - for (day = G_DATE_MONDAY; day <= G_DATE_SUNDAY; day++) { - g_date_strftime (buffer, sizeof (buffer), "%a", &date); - width = gdk_string_width (font, buffer); - if (width > longest_weekday_width) { - longest_weekday = day; - longest_weekday_width = width; - } - g_date_add_days (&date, 1); - } - - g_date_set_dmy (&date, days[longest_month - 1] + longest_weekday, - longest_month, 2000); - /* This is a strftime() format string %a = abbreviated weekday name, - %m = month number, %d = month day, %Y = full year. */ - g_date_strftime (buffer, sizeof (buffer), _("%a %m/%d/%Y"), &date); - - g_print ("longest_month: %i longest_weekday: %i date: %s\n", - longest_month, longest_weekday, buffer); - - if (gdk_string_width (font, buffer) < max_date_width) - mts->date_format = E_MEETING_TIME_SELECTOR_DATE_ABBREVIATED_DAY; - else - mts->date_format = E_MEETING_TIME_SELECTOR_DATE_SHORT; -} - - -/* Turn off the background of the canvas windows. This reduces flicker - considerably when scrolling. (Why isn't it in GnomeCanvas?). */ -static void -e_meeting_time_selector_on_canvas_realized (GtkWidget *widget, - EMeetingTimeSelector *mts) -{ - gdk_window_set_back_pixmap (GTK_LAYOUT (widget)->bin_window, - NULL, FALSE); -} - - -/* This is called when the meeting start time GnomeDateEdit is changed, - either via the "date_changed". "time_changed" or "activate" signals on one - of the GtkEntry widgets. So don't use the widget parameter since it may be - one of the child GtkEntry widgets. */ -static void -e_meeting_time_selector_on_start_time_changed (GtkWidget *widget, - EMeetingTimeSelector *mts) -{ - gint duration_days, duration_hours, duration_minutes; - EMeetingTimeSelectorTime mtstime; - time_t newtime; - struct tm *newtime_tm; - - newtime = gnome_date_edit_get_date (GNOME_DATE_EDIT (mts->start_date_edit)); - newtime_tm = localtime (&newtime); - g_date_clear (&mtstime.date, 1); - g_date_set_time (&mtstime.date, newtime); - mtstime.hour = newtime_tm->tm_hour; - mtstime.minute = newtime_tm->tm_min; - - /* If the time hasn't changed, just return. */ - if (e_meeting_time_selector_compare_times (&mtstime, &mts->meeting_start_time) == 0) - return; - - /* Calculate the current meeting duration. */ - e_meeting_time_selector_calculate_time_difference (&mts->meeting_start_time, &mts->meeting_end_time, &duration_days, &duration_hours, &duration_minutes); - - /* Set the new start time. */ - mts->meeting_start_time = mtstime; - - /* Update the end time so the meeting duration stays the same. */ - mts->meeting_end_time = mts->meeting_start_time; - e_meeting_time_selector_adjust_time (&mts->meeting_end_time, duration_days, duration_hours, duration_minutes); - e_meeting_time_selector_update_end_date_edit (mts); - - mts->meeting_positions_valid = FALSE; - e_meeting_time_selector_ensure_meeting_time_shown (mts); - gtk_widget_queue_draw (mts->display_top); - gtk_widget_queue_draw (mts->display_main); -} - - -/* This is called when the meeting end time GnomeDateEdit is changed, - either via the "date_changed", "time_changed" or "activate" signals on one - of the GtkEntry widgets. So don't use the widget parameter since it may be - one of the child GtkEntry widgets. */ -static void -e_meeting_time_selector_on_end_time_changed (GtkWidget *widget, - EMeetingTimeSelector *mts) -{ - EMeetingTimeSelectorTime mtstime; - time_t newtime; - struct tm *newtime_tm; - - newtime = gnome_date_edit_get_date (GNOME_DATE_EDIT (mts->end_date_edit)); - newtime_tm = localtime (&newtime); - g_date_clear (&mtstime.date, 1); - g_date_set_time (&mtstime.date, newtime); - mtstime.hour = newtime_tm->tm_hour; - mtstime.minute = newtime_tm->tm_min; - - /* If the time hasn't changed, just return. */ - if (e_meeting_time_selector_compare_times (&mtstime, &mts->meeting_end_time) == 0) - return; - - /* Set the new end time. */ - mts->meeting_end_time = mtstime; - - /* If the start time is after the end time, set it to the same time. */ - if (e_meeting_time_selector_compare_times (&mtstime, &mts->meeting_start_time) < 0) { - /* We set it first, before updating the widget, so the signal - handler will just return. */ - mts->meeting_start_time = mtstime; - e_meeting_time_selector_update_start_date_edit (mts); - } - - mts->meeting_positions_valid = FALSE; - e_meeting_time_selector_ensure_meeting_time_shown (mts); - gtk_widget_queue_draw (mts->display_top); - gtk_widget_queue_draw (mts->display_main); -} - - -/* This updates the ranges shown in the GnomeDateEdit popup menus, according - to working_hours_only etc. */ -static void -e_meeting_time_selector_update_date_popup_menus (EMeetingTimeSelector *mts) -{ - GnomeDateEdit *start_edit, *end_edit; - gint low_hour, high_hour; - - start_edit = GNOME_DATE_EDIT (mts->start_date_edit); - end_edit = GNOME_DATE_EDIT (mts->end_date_edit); - - if (mts->working_hours_only) { - low_hour = mts->day_start_hour; - high_hour = mts->day_end_hour; - } else { - low_hour = 0; - high_hour = 23; - } - - gnome_date_edit_set_popup_range (start_edit, low_hour, high_hour); - gnome_date_edit_set_popup_range (end_edit, low_hour, high_hour); -} - - -static void -e_meeting_time_selector_on_canvas_size_allocate (GtkWidget *widget, - GtkAllocation *allocation, - EMeetingTimeSelector *mts) -{ - e_meeting_time_selector_update_main_canvas_scroll_region (mts); - - e_meeting_time_selector_ensure_meeting_time_shown (mts); -} - - -static void -e_meeting_time_selector_on_attendees_list_size_allocate (GtkWidget *widget, - GtkAllocation *allocation, - EMeetingTimeSelector *mts) -{ - e_meeting_time_selector_update_attendees_list_scroll_region (mts); - e_meeting_time_selector_update_attendees_list_positions (mts); -} - - -/* This updates the list canvas scroll region according to the number of - attendees. If the total height needed is less than the height of the canvas, - we must use the height of the canvas, or it causes problems. */ -static void -e_meeting_time_selector_update_attendees_list_scroll_region (EMeetingTimeSelector *mts) -{ - gint height, canvas_width, canvas_height; - - height = mts->row_height * mts->attendees->len; - canvas_width = GTK_WIDGET (mts->attendees_list)->allocation.width; - canvas_height = GTK_WIDGET (mts->attendees_list)->allocation.height; - - height = MAX (height, canvas_height); - - gnome_canvas_set_scroll_region (GNOME_CANVAS (mts->attendees_list), - 0, 0, - canvas_width, - height); -} - - -/* This updates the canvas scroll regions according to the number of attendees. - If the total height needed is less than the height of the canvas, we must - use the height of the canvas, or it causes problems. */ -static void -e_meeting_time_selector_update_main_canvas_scroll_region (EMeetingTimeSelector *mts) -{ - gint height, canvas_height, list_width; - - height = mts->row_height * (mts->attendees->len + 1); - canvas_height = GTK_WIDGET (mts->display_main)->allocation.height; - list_width = GTK_WIDGET (mts->attendees_list)->allocation.width; - - height = MAX (height, canvas_height); - - gnome_canvas_set_scroll_region (GNOME_CANVAS (mts->attendees_list), - 0, 0, - list_width, - height); - gnome_canvas_set_scroll_region (GNOME_CANVAS (mts->display_main), - 0, 0, - mts->day_width * E_MEETING_TIME_SELECTOR_DAYS_SHOWN, - height); -} - - -/* This changes the meeting time based on the given x coordinate and whether - we are dragging the start or end bar. It returns the new position, which - will be swapped if the start bar is dragged past the end bar or vice versa. - It make sure the meeting time is never dragged outside the visible canvas - area. */ -void -e_meeting_time_selector_drag_meeting_time (EMeetingTimeSelector *mts, - gint x) -{ - EMeetingTimeSelectorTime first_time, last_time, drag_time, *time_to_set; - gint scroll_x, scroll_y, canvas_width; - gboolean set_both_times = FALSE; - - /* Get the x coords of visible part of the canvas. */ - gnome_canvas_get_scroll_offsets (GNOME_CANVAS (mts->display_main), - &scroll_x, &scroll_y); - canvas_width = mts->display_main->allocation.width; - - /* Save the x coordinate for the timeout handler. */ - mts->last_drag_x = (x < scroll_x) ? x - scroll_x - : x - scroll_x - canvas_width + 1; - - /* Check if the mouse is off the edge of the canvas. */ - if (x < scroll_x || x > scroll_x + canvas_width) { - /* If we haven't added a timeout function, add one. */ - if (mts->auto_scroll_timeout_id == 0) { - mts->auto_scroll_timeout_id = g_timeout_add (60, e_meeting_time_selector_timeout_handler, mts); - mts->scroll_count = 0; - - /* Call the handler to start scrolling now. */ - e_meeting_time_selector_timeout_handler (mts); - return; - } - } else { - e_meeting_time_selector_remove_timeout (mts); - } - - /* Calculate the minimum & maximum times we can use, based on the - scroll offsets and whether zoomed_out is set. */ - e_meeting_time_selector_calculate_time (mts, scroll_x, &first_time); - e_meeting_time_selector_calculate_time (mts, scroll_x + canvas_width - 1, - &last_time); - if (mts->zoomed_out) { - if (first_time.minute > 30) - first_time.hour++; - first_time.minute = 0; - last_time.minute = 0; - } else { - first_time.minute += 15; - first_time.minute -= first_time.minute % 30; - last_time.minute -= last_time.minute % 30; - } - e_meeting_time_selector_fix_time_overflows (&first_time); - e_meeting_time_selector_fix_time_overflows (&last_time); - - /* Calculate the time from x coordinate. */ - e_meeting_time_selector_calculate_time (mts, x, &drag_time); - - /* Calculate the nearest half-hour or hour, depending on whether - zoomed_out is set. */ - if (mts->zoomed_out) { - if (drag_time.minute > 30) - drag_time.hour++; - drag_time.minute = 0; - } else { - drag_time.minute += 15; - drag_time.minute -= drag_time.minute % 30; - } - e_meeting_time_selector_fix_time_overflows (&drag_time); - - /* Now make sure we are between first_time & last_time. */ - if (e_meeting_time_selector_compare_times (&drag_time, &first_time) < 0) - drag_time = first_time; - if (e_meeting_time_selector_compare_times (&drag_time, &last_time) > 0) - drag_time = last_time; - - /* Set the meeting start or end time to drag_time. */ - if (mts->dragging_position == E_MEETING_TIME_SELECTOR_POS_START) - time_to_set = &mts->meeting_start_time; - else - time_to_set = &mts->meeting_end_time; - - /* If the time is unchanged, just return. */ - if (e_meeting_time_selector_compare_times (time_to_set, &drag_time) == 0) - return; - - *time_to_set = drag_time; - - /* Check if the start time and end time need to be switched. */ - if (e_meeting_time_selector_compare_times (&mts->meeting_start_time, - &mts->meeting_end_time) > 0) { - drag_time = mts->meeting_start_time; - mts->meeting_start_time = mts->meeting_end_time; - mts->meeting_end_time = drag_time; - - if (mts->dragging_position == E_MEETING_TIME_SELECTOR_POS_START) - mts->dragging_position = E_MEETING_TIME_SELECTOR_POS_END; - else - mts->dragging_position = E_MEETING_TIME_SELECTOR_POS_START; - - set_both_times = TRUE; - } - - /* Mark the calculated positions as invalid. */ - mts->meeting_positions_valid = FALSE; - - /* Redraw the canvases. */ - gtk_widget_queue_draw (mts->display_top); - gtk_widget_queue_draw (mts->display_main); - - /* Set the times in the GnomeDateEdit widgets. */ - if (set_both_times - || mts->dragging_position == E_MEETING_TIME_SELECTOR_POS_START) - e_meeting_time_selector_update_start_date_edit (mts); - - if (set_both_times - || mts->dragging_position == E_MEETING_TIME_SELECTOR_POS_END) - e_meeting_time_selector_update_end_date_edit (mts); -} - - -/* This is the timeout function which handles auto-scrolling when the user is - dragging one of the meeting time vertical bars outside the left or right - edge of the canvas. */ -static gboolean -e_meeting_time_selector_timeout_handler (gpointer data) -{ - EMeetingTimeSelector *mts; - EMeetingTimeSelectorTime drag_time, *time_to_set; - gint scroll_x, max_scroll_x, scroll_y, canvas_width; - gint scroll_speed, scroll_offset; - gboolean set_both_times = FALSE; - - mts = E_MEETING_TIME_SELECTOR (data); - - GDK_THREADS_ENTER (); - - /* Return if we don't need to scroll yet. */ - if (mts->scroll_count-- > 0) { - GDK_THREADS_LEAVE (); - return TRUE; - } - - /* Get the x coords of visible part of the canvas. */ - gnome_canvas_get_scroll_offsets (GNOME_CANVAS (mts->display_main), - &scroll_x, &scroll_y); - canvas_width = mts->display_main->allocation.width; - - /* Calculate the scroll delay, between 0 and MAX_SCROLL_SPEED. */ - scroll_speed = abs (mts->last_drag_x / E_MEETING_TIME_SELECTOR_SCROLL_INCREMENT_WIDTH); - scroll_speed = MIN (scroll_speed, - E_MEETING_TIME_SELECTOR_MAX_SCROLL_SPEED); - - /* Reset the scroll count. */ - mts->scroll_count = E_MEETING_TIME_SELECTOR_MAX_SCROLL_SPEED - scroll_speed; - - /* Calculate how much we need to scroll. */ - if (mts->last_drag_x >= 0) - scroll_offset = mts->col_width; - else - scroll_offset = -mts->col_width; - - scroll_x += scroll_offset; - max_scroll_x = (mts->day_width * E_MEETING_TIME_SELECTOR_DAYS_SHOWN) - - canvas_width; - scroll_x = CLAMP (scroll_x, 0, max_scroll_x); - - /* Calculate the minimum or maximum visible time in the canvas, which - we will now set the dragged time to. */ - if (scroll_offset > 0) { - e_meeting_time_selector_calculate_time (mts, - scroll_x + canvas_width - 1, - &drag_time); - if (mts->zoomed_out) { - drag_time.minute = 0; - } else { - drag_time.minute -= drag_time.minute % 30; - } - } else { - e_meeting_time_selector_calculate_time (mts, scroll_x, - &drag_time); - if (mts->zoomed_out) { - if (drag_time.minute > 30) - drag_time.hour++; - drag_time.minute = 0; - } else { - drag_time.minute += 15; - drag_time.minute -= drag_time.minute % 30; - } - } - e_meeting_time_selector_fix_time_overflows (&drag_time); - - /* Set the meeting start or end time to drag_time. */ - if (mts->dragging_position == E_MEETING_TIME_SELECTOR_POS_START) - time_to_set = &mts->meeting_start_time; - else - time_to_set = &mts->meeting_end_time; - - /* If the time is unchanged, just return. */ - if (e_meeting_time_selector_compare_times (time_to_set, &drag_time) == 0) { - GDK_THREADS_LEAVE (); - return TRUE; - } - - *time_to_set = drag_time; - - /* Check if the start time and end time need to be switched. */ - if (e_meeting_time_selector_compare_times (&mts->meeting_start_time, &mts->meeting_end_time) > 0) { - drag_time = mts->meeting_start_time; - mts->meeting_start_time = mts->meeting_end_time; - mts->meeting_end_time = drag_time; - - if (mts->dragging_position == E_MEETING_TIME_SELECTOR_POS_START) - mts->dragging_position = E_MEETING_TIME_SELECTOR_POS_END; - else - mts->dragging_position = E_MEETING_TIME_SELECTOR_POS_START; - - set_both_times = TRUE; - } - - /* Mark the calculated positions as invalid. */ - mts->meeting_positions_valid = FALSE; - - /* Set the times in the GnomeDateEdit widgets. */ - if (set_both_times - || mts->dragging_position == E_MEETING_TIME_SELECTOR_POS_START) - e_meeting_time_selector_update_start_date_edit (mts); - - if (set_both_times - || mts->dragging_position == E_MEETING_TIME_SELECTOR_POS_END) - e_meeting_time_selector_update_end_date_edit (mts); - - /* Redraw the canvases. We freeze and thaw the layouts so that they - get redrawn completely. Otherwise the pixels get scrolled left or - right which is not good for us (since our vertical bars have been - moved) and causes flicker. */ - gtk_layout_freeze (GTK_LAYOUT (mts->display_main)); - gtk_layout_freeze (GTK_LAYOUT (mts->display_top)); - gnome_canvas_scroll_to (GNOME_CANVAS (mts->display_main), - scroll_x, scroll_y); - gnome_canvas_scroll_to (GNOME_CANVAS (mts->display_top), - scroll_x, scroll_y); - gtk_layout_thaw (GTK_LAYOUT (mts->display_main)); - gtk_layout_thaw (GTK_LAYOUT (mts->display_top)); - - GDK_THREADS_LEAVE (); - return TRUE; -} - - -/* This removes our auto-scroll timeout function, if we have one installed. */ -void -e_meeting_time_selector_remove_timeout (EMeetingTimeSelector *mts) -{ - if (mts->auto_scroll_timeout_id) { - g_source_remove (mts->auto_scroll_timeout_id); - mts->auto_scroll_timeout_id = 0; - } -} - - -/* This updates the GnomeDateEdit widget displaying the meeting start time. */ -static void -e_meeting_time_selector_update_start_date_edit (EMeetingTimeSelector *mts) -{ - struct tm start_tm; - time_t start_time_t; - - g_date_to_struct_tm (&mts->meeting_start_time.date, &start_tm); - start_tm.tm_hour = mts->meeting_start_time.hour; - start_tm.tm_min = mts->meeting_start_time.minute; - start_time_t = mktime (&start_tm); - gnome_date_edit_set_time (GNOME_DATE_EDIT (mts->start_date_edit), - start_time_t); -} - - -/* This updates the GnomeDateEdit widget displaying the meeting end time. */ -static void -e_meeting_time_selector_update_end_date_edit (EMeetingTimeSelector *mts) -{ - struct tm end_tm; - time_t end_time_t; - - g_date_to_struct_tm (&mts->meeting_end_time.date, &end_tm); - end_tm.tm_hour = mts->meeting_end_time.hour; - end_tm.tm_min = mts->meeting_end_time.minute; - end_time_t = mktime (&end_tm); - gnome_date_edit_set_time (GNOME_DATE_EDIT (mts->end_date_edit), - end_time_t); -} - - -/* This ensures that the meeting time is shown on screen, by scrolling the - canvas and possibly by changing the range of dates shown in the canvas. */ -static void -e_meeting_time_selector_ensure_meeting_time_shown (EMeetingTimeSelector *mts) -{ - gint start_x, end_x, scroll_x, scroll_y, canvas_width; - gint new_scroll_x; - gboolean fits_in_canvas; - - /* Check if we need to change the range of dates shown. */ - if (g_date_compare (&mts->meeting_start_time.date, - &mts->first_date_shown) < 0 - || g_date_compare (&mts->meeting_end_time.date, - &mts->last_date_shown) > 0) { - e_meeting_time_selector_update_dates_shown (mts); - gtk_widget_queue_draw (mts->display_top); - gtk_widget_queue_draw (mts->display_main); - } - - /* If all of the meeting time is visible, just return. */ - e_meeting_time_selector_get_meeting_time_positions (mts, &start_x, - &end_x); - gnome_canvas_get_scroll_offsets (GNOME_CANVAS (mts->display_main), - &scroll_x, &scroll_y); - canvas_width = mts->display_main->allocation.width; - if (start_x > scroll_x && end_x <= scroll_x + canvas_width) - return; - - fits_in_canvas = end_x - start_x < canvas_width ? TRUE : FALSE; - - /* If the meeting is not entirely visible, either center it if it is - smaller than the canvas, or show the start of it if it is big. */ - if (fits_in_canvas) { - new_scroll_x = (start_x + end_x - canvas_width) / 2; - } else { - new_scroll_x = start_x; - } - gnome_canvas_scroll_to (GNOME_CANVAS (mts->display_main), - new_scroll_x, scroll_y); -} - - -/* This updates the range of dates shown in the canvas, to make sure that the - currently selected meeting time is in the range. */ -static void -e_meeting_time_selector_update_dates_shown (EMeetingTimeSelector *mts) -{ - mts->first_date_shown = mts->meeting_start_time.date; - g_date_subtract_days (&mts->first_date_shown, 60); - - mts->last_date_shown = mts->first_date_shown; - g_date_add_days (&mts->last_date_shown, E_MEETING_TIME_SELECTOR_DAYS_SHOWN - 1); -} - - -/* This checks if the time's hour is over 24 or its minute is over 60 and if - so it updates the day/hour appropriately. Note that hours and minutes are - stored in guint8's so they can't overflow by much. */ -void -e_meeting_time_selector_fix_time_overflows (EMeetingTimeSelectorTime *mtstime) -{ - gint hours_to_add, days_to_add; - - hours_to_add = mtstime->minute / 60; - if (hours_to_add > 0) { - mtstime->minute -= hours_to_add * 60; - mtstime->hour += hours_to_add; - } - - days_to_add = mtstime->hour / 24; - if (days_to_add > 0) { - mtstime->hour -= days_to_add * 24; - g_date_add_days (&mtstime->date, days_to_add); - } -} - - -static void -e_meeting_time_selector_update_attendees_list_positions (EMeetingTimeSelector *mts) -{ - EMeetingTimeSelectorAttendee *attendee; - gint list_width, item_width; - gint row; - GdkFont *font; - - list_width = GTK_WIDGET (mts->attendees_list)->allocation.width; - item_width = MAX (1, list_width - E_MEETING_TIME_SELECTOR_ICON_COLUMN_WIDTH - E_MEETING_TIME_SELECTOR_TEXT_X_PAD * 2); - font = GTK_WIDGET (mts)->style->font; - for (row = 0; row < mts->attendees->len; row++) { - attendee = &g_array_index (mts->attendees, - EMeetingTimeSelectorAttendee, row); - - gnome_canvas_item_set - (attendee->text_item, - "font_gdk", font, - "clip_width", (gdouble) item_width, - "clip_height", (gdouble) (font->ascent - + font->descent), - NULL); - - e_canvas_item_move_absolute (attendee->text_item, - E_MEETING_TIME_SELECTOR_ICON_COLUMN_WIDTH - + E_MEETING_TIME_SELECTOR_TEXT_X_PAD, - row * mts->row_height + 1 + E_MEETING_TIME_SELECTOR_TEXT_Y_PAD); - - gnome_canvas_item_show (attendee->text_item); - } -} - - -/* - * CONVERSION ROUTINES - functions to convert between different coordinate - * spaces and dates. - */ - -/* This takes an x pixel coordinate within the entire canvas scroll region and - returns the date in which it falls. If day_position is not NULL it also - returns the x coordinate within the date, relative to the visible part of - the canvas. It is used when painting the days in the item_draw function. - Note that it must handle negative x coordinates in case we are dragging off - the edge of the canvas. */ -void -e_meeting_time_selector_calculate_day_and_position (EMeetingTimeSelector *mts, - gint x, - GDate *date, - gint *day_position) -{ - gint days_from_first_shown; - - *date = mts->first_date_shown; - - if (x >= 0) { - days_from_first_shown = x / mts->day_width; - g_date_add_days (date, days_from_first_shown); - if (day_position) - *day_position = - x % mts->day_width; - } else { - days_from_first_shown = -x / mts->day_width + 1; - g_date_subtract_days (date, days_from_first_shown); - if (day_position) - *day_position = -mts->day_width - x % mts->day_width; - } -} - - -/* This takes an x pixel coordinate within a day, and converts it to hours - and minutes, depending on working_hours_only and zoomed_out. */ -void -e_meeting_time_selector_convert_day_position_to_hours_and_mins (EMeetingTimeSelector *mts, gint day_position, guint8 *hours, guint8 *minutes) -{ - if (mts->zoomed_out) - day_position *= 3; - - /* Calculate the hours & minutes from the first displayed. */ - *hours = day_position / mts->col_width; - *minutes = (day_position % mts->col_width) * 60 / mts->col_width; - - /* Now add on the first hour shown. */ - *hours += mts->first_hour_shown; -} - - -/* This takes an x pixel coordinate within the entire canvas scroll region and - returns the time in which it falls. Note that it won't be extremely - accurate since hours may only be a few pixels wide in the display. - With zoomed_out set each pixel may represent 5 minutes or more, depending - on how small the font is. */ -void -e_meeting_time_selector_calculate_time (EMeetingTimeSelector *mts, - gint x, - EMeetingTimeSelectorTime *time) -{ - gint day_position; - - /* First get the day and the x position within the day. */ - e_meeting_time_selector_calculate_day_and_position (mts, x, &time->date, - NULL); - - /* Now convert the day_position into an hour and minute. */ - if (x >= 0) - day_position = x % mts->day_width; - else - day_position = mts->day_width + x % mts->day_width; - - e_meeting_time_selector_convert_day_position_to_hours_and_mins (mts, day_position, &time->hour, &time->minute); -} - - -/* This takes a EMeetingTimeSelectorTime and calculates the x pixel coordinate - within the entire canvas scroll region. It is used to draw the selected - meeting time and all the busy periods. */ -gint -e_meeting_time_selector_calculate_time_position (EMeetingTimeSelector *mts, - EMeetingTimeSelectorTime *mtstime) -{ - gint x, date_offset, day_offset; - - /* Calculate the number of days since the first date shown in the - entire canvas scroll region. */ - date_offset = g_date_julian (&mtstime->date) - g_date_julian (&mts->first_date_shown); - - /* Calculate the x pixel coordinate of the start of the day. */ - x = date_offset * mts->day_width; - - /* Add on the hours and minutes, depending on whether zoomed_out and - working_hours_only are set. */ - day_offset = (mtstime->hour - mts->first_hour_shown) * 60 - + mtstime->minute; - /* The day width includes an extra vertical grid line so subtract 1. */ - day_offset *= (mts->day_width - 1); - day_offset /= (mts->last_hour_shown - mts->first_hour_shown) * 60; - - /* Clamp the day_offset in case the time isn't actually visible. */ - x += CLAMP (day_offset, 0, mts->day_width); - - return x; -} - - -static gboolean -e_meeting_time_selector_on_text_item_event (GnomeCanvasItem *item, - GdkEvent *event, - EMeetingTimeSelector *mts) -{ - EMeetingTimeSelectorAttendee *attendee; - gint row, min; - ETextEventProcessor *event_processor = NULL; - ETextEventProcessorCommand command; - GtkAdjustment *adj; - gchar *text; - gboolean empty = FALSE; - - switch (event->type) { - case GDK_KEY_PRESS: - if (event && event->key.keyval == GDK_Return) { - row = e_meeting_time_selector_find_row_from_text_item (mts, item); - g_return_val_if_fail (row != -1, FALSE); - - if (row == mts->attendees->len - 1) - row = e_meeting_time_selector_attendee_add (mts, "", NULL); - else - row++; - - /* Make sure the item is visible. */ - adj = GTK_LAYOUT (mts->display_main)->vadjustment; - min = ((row + 1) * mts->row_height) - adj->page_size; - if (adj->value < min) { - adj->value = min; - gtk_adjustment_value_changed (adj); - } - - attendee = &g_array_index (mts->attendees, EMeetingTimeSelectorAttendee, row); - e_canvas_item_grab_focus (attendee->text_item, TRUE); - - /* Try to move the cursor to the end of the text. */ - gtk_object_get (GTK_OBJECT (attendee->text_item), - "event_processor", &event_processor, - NULL); - if (event_processor) { - command.action = E_TEP_MOVE; - command.position = E_TEP_END_OF_BUFFER; - gtk_signal_emit_by_name (GTK_OBJECT (event_processor), - "command", &command); - } - - /* Stop the signal last or we will also stop any - other events getting to the EText item. */ - gtk_signal_emit_stop_by_name (GTK_OBJECT (item), - "event"); - return TRUE; - } - break; - case GDK_FOCUS_CHANGE: - if (!event->focus_change.in) { - gtk_object_get (GTK_OBJECT (item), - "text", &text, - NULL); - if (!text || !text[0]) - empty = TRUE; - g_free (text); - - if (empty) { - row = e_meeting_time_selector_find_row_from_text_item (mts, item); - g_return_val_if_fail (row != -1, FALSE); - e_meeting_time_selector_attendee_remove (mts, - row); - } - } - break; - default: - break; - } - - return FALSE; -} - - -static gint -e_meeting_time_selector_find_row_from_text_item (EMeetingTimeSelector *mts, - GnomeCanvasItem *item) -{ - EMeetingTimeSelectorAttendee *attendee; - gint row; - - for (row = 0; row < mts->attendees->len; row++) { - attendee = &g_array_index (mts->attendees, - EMeetingTimeSelectorAttendee, row); - if (attendee->text_item == item) - return row; - } - - return -1; -} - diff --git a/widgets/meeting-time-sel/e-meeting-time-sel.h b/widgets/meeting-time-sel/e-meeting-time-sel.h deleted file mode 100644 index a92cea9d7d..0000000000 --- a/widgets/meeting-time-sel/e-meeting-time-sel.h +++ /dev/null @@ -1,521 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ - -/* - * Author : - * Damon Chaplin <damon@gtk.org> - * - * Copyright 1999, Ximian, Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * 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 - */ -#ifndef _E_MEETING_TIME_SELECTOR_H_ -#define _E_MEETING_TIME_SELECTOR_H_ - -#include <glib.h> -#include <gtk/gtkaccelgroup.h> -#include <gtk/gtktable.h> -#include <gtk/gtkwidget.h> -#include <libgnomeui/gnome-canvas.h> -#include <gal/e-text/e-text.h> - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -/* - * EMeetingTimeSelector displays a list of attendees for a meeting and a - * graphical summary of the times which they are free and busy, allowing the - * user to select an appropriate time for a meeting. - */ - -/* Define this to include the debugging functions. */ -#undef E_MEETING_TIME_SELECTOR_DEBUG - -/* This is the width of the icon column in the attendees list. */ -#define E_MEETING_TIME_SELECTOR_ICON_COLUMN_WIDTH 24 - -#define E_MEETING_TIME_SELECTOR_TEXT_Y_PAD 3 -#define E_MEETING_TIME_SELECTOR_TEXT_X_PAD 2 - -/* These specify the type of attendee. Either a person or a resource (e.g. a - meeting room). These are used for the Autopick options, where the user can - ask for a time when, for example, all people and one resource are free. - The default is E_MEETING_TIME_SELECTOR_REQUIRED_PERSON. */ -typedef enum -{ - E_MEETING_TIME_SELECTOR_REQUIRED_PERSON, - E_MEETING_TIME_SELECTOR_OPTIONAL_PERSON, - E_MEETING_TIME_SELECTOR_RESOURCE -} EMeetingTimeSelectorAttendeeType; - - -/* These are used to specify whether an attendee is free or busy at a - particular time. We'll probably replace this with a global calendar type. - These should be ordered in increasing order of preference. Higher precedence - busy periods will be painted over lower precedence ones. These are also - used as for loop counters, so they should start at 0 and be ordered. */ -typedef enum -{ - E_MEETING_TIME_SELECTOR_BUSY_TENTATIVE = 0, - E_MEETING_TIME_SELECTOR_BUSY_OUT_OF_OFFICE = 1, - E_MEETING_TIME_SELECTOR_BUSY_BUSY = 2, - - E_MEETING_TIME_SELECTOR_BUSY_LAST = 3 -} EMeetingTimeSelectorBusyType; - - -/* This is used to specify the format used when displaying the dates. - The full format is like 'Sunday, September 12, 1999'. The abbreviated format - is like 'Sun 12/9/99'. The short format is like '12/9/99'. The actual - format used is determined in e_meeting_time_selector_style_set(), once we - know the font being used. */ -typedef enum -{ - E_MEETING_TIME_SELECTOR_DATE_FULL, - E_MEETING_TIME_SELECTOR_DATE_ABBREVIATED_DAY, - E_MEETING_TIME_SELECTOR_DATE_SHORT -} EMeetingTimeSelectorDateFormat; - - -/* This is used to specify a position regarding the vertical bars around the - current meeting time, so we know which one is being dragged. */ -typedef enum -{ - E_MEETING_TIME_SELECTOR_POS_NONE, - E_MEETING_TIME_SELECTOR_POS_START, - E_MEETING_TIME_SELECTOR_POS_END -} EMeetingTimeSelectorPosition; - - -/* This is used to specify the autopick option, which determines how we choose - the previous/next appropriate meeting time. */ -typedef enum -{ - E_MEETING_TIME_SELECTOR_ALL_PEOPLE_AND_RESOURCES, - E_MEETING_TIME_SELECTOR_ALL_PEOPLE_AND_ONE_RESOURCE, - E_MEETING_TIME_SELECTOR_REQUIRED_PEOPLE, - E_MEETING_TIME_SELECTOR_REQUIRED_PEOPLE_AND_ONE_RESOURCE -} EMeetingTimeSelectorAutopickOption; - - -/* This is our representation of a time. We use a GDate to store the day, - and guint8s for the hours and minutes. */ -typedef struct _EMeetingTimeSelectorTime EMeetingTimeSelectorTime; -struct _EMeetingTimeSelectorTime -{ - GDate date; - guint8 hour; - guint8 minute; -}; - - -/* This represents a busy period. */ -typedef struct _EMeetingTimeSelectorPeriod EMeetingTimeSelectorPeriod; -struct _EMeetingTimeSelectorPeriod -{ - EMeetingTimeSelectorTime start; - EMeetingTimeSelectorTime end; - EMeetingTimeSelectorBusyType busy_type; -}; - - -/* This contains information on one attendee. */ -typedef struct _EMeetingTimeSelectorAttendee EMeetingTimeSelectorAttendee; -struct _EMeetingTimeSelectorAttendee -{ - gchar *name; - - /* The type of attendee, e.g. a person or a resource. */ - EMeetingTimeSelectorAttendeeType type; - - /* This is TRUE if the attendee has calendar information available. - It is set to TRUE when a busy period is added, but can also be set - to TRUE explicitly to indicate that the attendee has calendar - information available, but no current busy periods. If it is FALSE - then a diagonal stipple pattern is used to fill the entire row in - the main graphical display. */ - gboolean has_calendar_info; - - /* This is TRUE if the meeting request is sent to this attendee. */ - gboolean send_meeting_to; - - /* This is the period for which free/busy data for the attendee is - available. */ - EMeetingTimeSelectorTime busy_periods_start; - EMeetingTimeSelectorTime busy_periods_end; - - /* This is an array of EMeetingTimeSelectorPeriod elements. When it is - updated busy_periods_sorted is set to FALSE, and if a function - needs them sorted, it should call this to re-sort them if needed: - e_meeting_time_selector_attendee_ensure_periods_sorted(). Note that - they are sorted by the start times. */ - GArray *busy_periods; - gboolean busy_periods_sorted; - - /* This holds the length of the longest busy period in days, rounded - up. It is used to determine where to start looking in the - busy_periods array. If we didn't use this we'd have to go through - most of the busy_periods array every time we wanted to paint part - of the display. */ - gint longest_period_in_days; - - /* This is the canvas text item where the name is edited. */ - GnomeCanvasItem *text_item; - - /* This is supposed to be something like an address book id. */ - gpointer data; -}; - -/* An array of hour strings, "0:00" .. "23:00". */ -extern const gchar *EMeetingTimeSelectorHours[24]; - - -#define E_MEETING_TIME_SELECTOR(obj) GTK_CHECK_CAST (obj, e_meeting_time_selector_get_type (), EMeetingTimeSelector) -#define E_MEETING_TIME_SELECTOR_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, e_meeting_time_selector_get_type (), EMeetingTimeSelectorClass) -#define IS_E_MEETING_TIME_SELECTOR(obj) GTK_CHECK_TYPE (obj, e_meeting_time_selector_get_type ()) - - -typedef struct _EMeetingTimeSelector EMeetingTimeSelector; -typedef struct _EMeetingTimeSelectorClass EMeetingTimeSelectorClass; - -struct _EMeetingTimeSelector -{ - /* We subclass a GtkTable which makes it easy to add extra widgets - if neccesary. */ - GtkTable table; - - /* - * User Interface stuff - widgets, colors etc. - */ - - /* This contains our keyboard accelerators, which need to be added to - the toplevel window. */ - GtkAccelGroup *accel_group; - - /* The vbox in the top-left corner, containing the 'All Attendees' - title bar packed at the end. Extra widgets can be added here - with PACK_START if necessary. */ - GtkWidget *attendees_title_bar_vbox; - - /* The 'All Attendees' title bar above the list of attendees. */ - GtkWidget *attendees_title_bar; - - /* The list of attendees. */ - GtkWidget *attendees_list; - - /* The canvas displaying the dates, times, and the summary - 'All Attendees' free/busy display. */ - GtkWidget *display_top; - - /* The canvas containing the free/busy displays of individual - attendees. This is separate from display_top since it also scrolls - vertically. */ - GtkWidget *display_main; - - /* This is the 'Options' button & menu. */ - GtkWidget *options_button; - GtkWidget *options_menu; - - /* This is the 'Autopick' button, menu & radio menu items. */ - GtkWidget *autopick_button; - GtkWidget *autopick_menu; - GtkWidget *autopick_all_item; - GtkWidget *autopick_all_people_one_resource_item; - GtkWidget *autopick_required_people_item; - GtkWidget *autopick_required_people_one_resource_item; - - /* The horizontal scrollbar which scrolls display_top & display_main.*/ - GtkWidget *hscrollbar; - - /* The vertical scrollbar which scrolls attendees & display_main. */ - GtkWidget *vscrollbar; - - /* The 2 GnomeDateEdit widgets for the meeting start & end times. */ - GtkWidget *start_date_edit; - GtkWidget *end_date_edit; - - /* Colors. */ - GdkColorContext *color_context; - GdkColor bg_color; - GdkColor all_attendees_bg_color; - GdkColor meeting_time_bg_color; - GdkColor stipple_bg_color; - GdkColor attendee_list_bg_color; - GdkColor grid_color; - GdkColor grid_shadow_color; - GdkColor grid_unused_color; - GdkColor busy_colors[E_MEETING_TIME_SELECTOR_BUSY_LAST]; - - /* The stipple used for attendees with no data. */ - GdkPixmap *stipple; - - /* GC for drawing the color key. */ - GdkGC *color_key_gc; - - /* Width of the hours strings (e.g. "1:00") in the current font. */ - gint hour_widths[24]; - - /* Whether we are using the full, abbreviated or short date format. */ - EMeetingTimeSelectorDateFormat date_format; - - - /* - * Attendee Data. - */ - - /* This is an array of EMeetingTimeSelectorAttendee elements. */ - GArray *attendees; - - - /* - * Option Settings. - */ - - /* If this is TRUE we only show hours between day_start_hour and - day_end_hour, defaults to TRUE (9am-6pm). */ - gboolean working_hours_only; - gint day_start_hour; - gint day_start_minute; - gint day_end_hour; - gint day_end_minute; - - /* If TRUE, view is compressed, with one cell for every 3 hours rather - than every hour. Defaults to FALSE. */ - gboolean zoomed_out; - - - /* - * Internal Data. - */ - - /* These are the first & last dates shown in the current scroll area. - We show E_MEETING_TIME_SELECTOR_DAYS_SHOWN days at a time. */ - GDate first_date_shown; - GDate last_date_shown; - - /* This is the current selection of the meeting time. */ - EMeetingTimeSelectorTime meeting_start_time; - EMeetingTimeSelectorTime meeting_end_time; - - /* These are the x pixel coordinates in the entire scroll region of - the start and end times. Set to meeting_positions_valid to FALSE to - invalidate. They will then be recomputed when needed. Always access - with e_meeting_time_selector_get_meeting_time_positions(). */ - gint meeting_positions_valid; - gint meeting_positions_in_scroll_area; - gint meeting_start_x; - gint meeting_end_x; - - /* These are the width and height of the cells, including the grid - lines which are displayed on the right and top or bottom of cells.*/ - gint row_height; - gint col_width; - - /* This is the width of a day in the display, which depends on - col_width, working_hours_only and zoomed_out. */ - gint day_width; - - /* These are the first and last hour of each day we display, depending - on working_hours_only and zoomed_out. */ - gint first_hour_shown; - gint last_hour_shown; - - /* The id of the source function for auto-scroll timeouts. */ - guint auto_scroll_timeout_id; - - /* This specifies if we are dragging one of the vertical bars around - the meeting time. */ - EMeetingTimeSelectorPosition dragging_position; - - /* The last x coordinate of the mouse, relative to either the left or - right edge of the canvas. Used in the auto_scroll_timeout function - to determine which way to scroll and how fast. */ - gint last_drag_x; - - /* This is used to determine the delay between scrolls. */ - gint scroll_count; -}; - - -struct _EMeetingTimeSelectorClass -{ - GtkTableClass parent_class; -}; - - -/* - * PUBLIC INTERFACE - note that this interface will probably change, when I - * know where the data is coming from. This is mainly just for testing for now. - */ - -GtkType e_meeting_time_selector_get_type (void); -GtkWidget* e_meeting_time_selector_new (void); - -/* This returns the currently selected meeting time. - Note that months are 1-12 and days are 1-31. The start time is guaranteed to - be before or equal to the end time. You may want to check if they are equal - if that if it is a problem. */ -void e_meeting_time_selector_get_meeting_time (EMeetingTimeSelector *mts, - gint *start_year, - gint *start_month, - gint *start_day, - gint *start_hour, - gint *start_minute, - gint *end_year, - gint *end_month, - gint *end_day, - gint *end_hour, - gint *end_minute); - -/* This sets the meeting time, returning TRUE if it is valid. */ -gboolean e_meeting_time_selector_set_meeting_time (EMeetingTimeSelector *mts, - gint start_year, - gint start_month, - gint start_day, - gint start_hour, - gint start_minute, - gint end_year, - gint end_month, - gint end_day, - gint end_hour, - gint end_minute); - -void e_meeting_time_selector_set_working_hours_only (EMeetingTimeSelector *mts, - gboolean working_hours_only); -void e_meeting_time_selector_set_working_hours (EMeetingTimeSelector *mts, - gint day_start_hour, - gint day_start_minute, - gint day_end_hour, - gint day_end_minute); - -void e_meeting_time_selector_set_zoomed_out (EMeetingTimeSelector *mts, - gboolean zoomed_out); - -EMeetingTimeSelectorAutopickOption e_meeting_time_selector_get_autopick_option (EMeetingTimeSelector *mts); -void e_meeting_time_selector_set_autopick_option (EMeetingTimeSelector *mts, - EMeetingTimeSelectorAutopickOption autopick_option); - -/* Adds an attendee to the list, returning the row. The data is meant for - something like an address book id, though if the user edits the name this - will become invalid. We'll probably have to handle address book lookup - ourself. */ -gint e_meeting_time_selector_attendee_add (EMeetingTimeSelector *mts, - gchar *attendee_name, - gpointer data); -gint e_meeting_time_selector_attendee_find_by_name (EMeetingTimeSelector *mts, - gchar *attendee_name, - gint start_row); -gint e_meeting_time_selector_attendee_find_by_data (EMeetingTimeSelector *mts, - gpointer data, - gint start_row); -void e_meeting_time_selector_attendee_remove (EMeetingTimeSelector *mts, - gint row); - -void e_meeting_time_selector_attendee_set_type (EMeetingTimeSelector *mts, - gint row, - EMeetingTimeSelectorAttendeeType type); -void e_meeting_time_selector_attendee_set_has_calendar_info (EMeetingTimeSelector *mts, - gint row, - gboolean has_calendar_info); -void e_meeting_time_selector_attendee_set_send_meeting_to (EMeetingTimeSelector *mts, - gint row, - gboolean send_meeting_to); - -gboolean e_meeting_time_selector_attendee_set_busy_range (EMeetingTimeSelector *mts, - gint row, - gint start_year, - gint start_month, - gint start_day, - gint start_hour, - gint start_minute, - gint end_year, - gint end_month, - gint end_day, - gint end_hour, - gint end_minute); - - -/* Clears all busy times for the given attendee. */ -void e_meeting_time_selector_attendee_clear_busy_periods (EMeetingTimeSelector *mts, - gint row); -/* Adds one busy time for the given attendee. */ -gboolean e_meeting_time_selector_attendee_add_busy_period (EMeetingTimeSelector *mts, - gint row, - gint start_year, - gint start_month, - gint start_day, - gint start_hour, - gint start_minute, - gint end_year, - gint end_month, - gint end_day, - gint end_hour, - gint end_minute, - EMeetingTimeSelectorBusyType busy_type); - - - -/* - * INTERNAL ROUTINES - functions to communicate with the canvas items within - * the EMeetingTimeSelector. - */ - -/* This returns the x pixel coordinates of the meeting start and end times, - in the entire canvas scroll area. If it returns FALSE, then the meeting - time isn't in the current scroll area (which shouldn't really happen). */ -gboolean e_meeting_time_selector_get_meeting_time_positions (EMeetingTimeSelector *mts, - gint *start_x, - gint *end_x); - -void e_meeting_time_selector_drag_meeting_time (EMeetingTimeSelector *mts, - gint x); - -void e_meeting_time_selector_remove_timeout (EMeetingTimeSelector *mts); - -void e_meeting_time_selector_fix_time_overflows (EMeetingTimeSelectorTime *mtstime); - -gint e_meeting_time_selector_find_first_busy_period (EMeetingTimeSelector *mts, - EMeetingTimeSelectorAttendee *attendee, - GDate *date); - -/* Makes sure the busy periods are sorted, so we can do binary searches. */ -void e_meeting_time_selector_attendee_ensure_periods_sorted (EMeetingTimeSelector *mts, - EMeetingTimeSelectorAttendee *attendee); - -void e_meeting_time_selector_calculate_day_and_position (EMeetingTimeSelector *mts, - gint x, - GDate *date, - gint *day_position); -void e_meeting_time_selector_convert_day_position_to_hours_and_mins (EMeetingTimeSelector *mts, gint day_position, guint8 *hours, guint8 *minutes); -void e_meeting_time_selector_calculate_time (EMeetingTimeSelector *mts, - gint x, - EMeetingTimeSelectorTime *time); -gint e_meeting_time_selector_calculate_time_position (EMeetingTimeSelector *mts, - EMeetingTimeSelectorTime *mtstime); - -/* Debugging function to dump information on all attendees. */ -#ifdef E_MEETING_TIME_SELECTOR_DEBUG -void e_meeting_time_selector_dump (EMeetingTimeSelector *mts); -gchar* e_meeting_time_selector_dump_time (EMeetingTimeSelectorTime *mtstime); -gchar* e_meeting_time_selector_dump_date (GDate *date); -#endif /* E_MEETING_TIME_SELECTOR_DEBUG */ - - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* _E_MEETING_TIME_SELECTOR_H_ */ diff --git a/widgets/meeting-time-sel/test-meeting-time-sel.c b/widgets/meeting-time-sel/test-meeting-time-sel.c deleted file mode 100644 index 98d22ce7b8..0000000000 --- a/widgets/meeting-time-sel/test-meeting-time-sel.c +++ /dev/null @@ -1,252 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ - -/* - * Author : - * Damon Chaplin <damon@gtk.org> - * - * Copyright 1999, Ximian, Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * 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 - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <time.h> -#include <glib.h> -#include <gtk/gtkmain.h> -#include <gdk_imlib.h> -#include <libgnome/gnome-defs.h> -#include <libgnomeui/gnome-dialog.h> -#include <libgnomeui/gnome-init.h> -#include <libgnomeui/gnome-stock.h> -#include "e-meeting-time-sel.h" - -void add_random_attendee_test_data (EMeetingTimeSelector *mts); -void add_simple_attendee_test_data (EMeetingTimeSelector *mts); -gint get_random_int (gint max); - -int -main (int argc, char *argv[]) -{ - GtkWidget *window, *mts; - gint i; - - gnome_init ("test-meeting-time-selector", "0.1", argc, argv); - - gtk_widget_push_visual (gdk_imlib_get_visual ()); - gtk_widget_push_colormap (gdk_imlib_get_colormap ()); - - window = gnome_dialog_new ("Plan a Meeting", "Make Meeting", - GNOME_STOCK_BUTTON_CLOSE, NULL); - gtk_window_set_default_size (GTK_WINDOW (window), 600, 400); - gtk_window_set_policy (GTK_WINDOW (window), FALSE, TRUE, FALSE); - - mts = e_meeting_time_selector_new (); - gtk_container_add (GTK_CONTAINER (GNOME_DIALOG (window)->vbox), mts); - gtk_window_add_accel_group (GTK_WINDOW (window), - E_MEETING_TIME_SELECTOR (mts)->accel_group); - gtk_widget_show (mts); - - gtk_widget_pop_visual (); - gtk_widget_pop_colormap (); - - i = 0; -#if 1 - for (i = 0; i < 20; i++) { - add_random_attendee_test_data (E_MEETING_TIME_SELECTOR (mts)); - } - - if (!e_meeting_time_selector_attendee_set_busy_range (E_MEETING_TIME_SELECTOR (mts), 3, - 2000, 5, 1, 14, 0, - 2000, 11, 1, 11, 30)) - g_print ("Error setting busy range\n"); - -#else - for (i = 0; i < 1; i++) { - add_simple_attendee_test_data (E_MEETING_TIME_SELECTOR (mts)); - } -#endif - -#if 0 - e_meeting_time_selector_dump (E_MEETING_TIME_SELECTOR (mts)); -#endif - - gnome_dialog_run (GNOME_DIALOG (window)); - - gtk_main (); - return 0; -} - - -/* Adds an attendee and a lot of random busy periods. The periods start 60 - days before the current date and extend over 365 days, to match the range - that EMeetingTimeSelector currently displays. We generate a time_t and an - interval and then convert them into a struct tm which provides everything - we need. */ -void -add_random_attendee_test_data (EMeetingTimeSelector *mts) -{ - gchar buffer[128], *name; - gint row, num_periods, busy_period, random_num, duration; - EMeetingTimeSelectorAttendeeType type; - EMeetingTimeSelectorBusyType busy_type; - time_t range_start; - time_t period_start; - time_t period_end; - struct tm *tmp_tm; - struct tm tm1; - struct tm tm2; - - /* Determine the type of attendee. */ - random_num = get_random_int (10); - if (random_num < 4) { - type = E_MEETING_TIME_SELECTOR_REQUIRED_PERSON; - name = "Req. Attendee"; - } else if (random_num < 7) { - type = E_MEETING_TIME_SELECTOR_OPTIONAL_PERSON; - name = "Opt. Attendee"; - } else { - type = E_MEETING_TIME_SELECTOR_RESOURCE; - name = "Resource"; - } - - sprintf (buffer, "%s %i", name, mts->attendees->len + 1); - row = e_meeting_time_selector_attendee_add (mts, buffer, NULL); - e_meeting_time_selector_attendee_set_type (mts, row, type); - - /* Don't send the meeting request to some attendees. */ - if (get_random_int (10) <= 2) - e_meeting_time_selector_attendee_set_send_meeting_to (mts, row, - FALSE); - - /* Some attendees have no calendar information. */ - if (get_random_int (10) == 2) - return; - - range_start = time (NULL) - 61 * 24 * 60 * 60; - num_periods = get_random_int (1000); -#if 0 - g_print ("num_periods: %i\n", num_periods); -#endif - for (busy_period = 0; busy_period < num_periods; busy_period++) { - - period_start = range_start + get_random_int (365 * 24 * 60 * 60); - - /* Make busy periods mainly 30 mins to a few hours, with a - couple of week/fortnight periods as well. */ - random_num = get_random_int (10000); - if (random_num < 2000) - duration = 30; - else if (random_num < 5000) - duration = 60; - else if (random_num < 7500) - duration = 90; - else if (random_num < 9995) - duration = 120; - else if (random_num < 9998) - duration = 60 * 24 * 7; - else - duration = 60 * 24 * 14; -#if 0 - g_print ("random_num: %i, duration: %i\n", - random_num, duration); -#endif - period_end = period_start + duration * 60; - - tmp_tm = localtime (&period_start); - tm1 = *tmp_tm; - tmp_tm = localtime (&period_end); - tm2 = *tmp_tm; - - /* A hack to avoid daylight-saving time problems. */ - if (tm2.tm_hour == tm1.tm_hour && tm2.tm_min < tm1.tm_min) - tm2.tm_hour++; - - busy_type = get_random_int (E_MEETING_TIME_SELECTOR_BUSY_LAST); - - if (!e_meeting_time_selector_attendee_add_busy_period (mts, row, tm1.tm_year + 1900, tm1.tm_mon + 1, tm1.tm_mday, tm1.tm_hour, tm1.tm_min, tm2.tm_year + 1900, tm2.tm_mon + 1, tm2.tm_mday, tm2.tm_hour, tm2.tm_min, busy_type)) - { - g_print ("Invalid busy period %i/%i/%i %i:%i to %i/%i/%i %i:%i\n", tm1.tm_year + 1900, tm1.tm_mon + 1, tm1.tm_mday, tm1.tm_hour, tm1.tm_min, tm2.tm_year + 1900, tm2.tm_mon + 1, tm2.tm_mday, tm2.tm_hour, tm2.tm_min); - g_print ("random_num: %i, duration: %i\n", - random_num, duration); - } - } -} - - -/* Returns a random integer between 0 and max - 1. */ -gint -get_random_int (gint max) -{ - gint random_num; - - random_num = (int) (max * (rand () / (RAND_MAX + 1.0))); -#if 0 - g_print ("Random num (%i): %i\n", max, random_num); -#endif - return random_num; -} - - -void -add_simple_attendee_test_data (EMeetingTimeSelector *mts) -{ - gint row; - - row = e_meeting_time_selector_attendee_add (mts, "John Smith", NULL); - if (!e_meeting_time_selector_attendee_add_busy_period (mts, row, - 1999, 11, 7, 14, 30, - 1999, 11, 7, 16, 30, - E_MEETING_TIME_SELECTOR_BUSY_BUSY)) - g_warning ("Invalid busy period"); - - e_meeting_time_selector_attendee_add_busy_period (mts, row, - 1999, 11, 7, 10, 30, - 1999, 11, 7, 11, 30, - E_MEETING_TIME_SELECTOR_BUSY_OUT_OF_OFFICE); - e_meeting_time_selector_attendee_add_busy_period (mts, row, - 1999, 11, 4, 10, 30, - 1999, 11, 7, 11, 30, - E_MEETING_TIME_SELECTOR_BUSY_BUSY); - row = e_meeting_time_selector_attendee_add (mts, "Dave Jones", NULL); - e_meeting_time_selector_attendee_add_busy_period (mts, row, - 1999, 11, 7, 15, 30, - 1999, 11, 7, 18, 30, - E_MEETING_TIME_SELECTOR_BUSY_TENTATIVE); - e_meeting_time_selector_attendee_add_busy_period (mts, row, - 1999, 11, 7, 11, 00, - 1999, 11, 7, 12, 00, - E_MEETING_TIME_SELECTOR_BUSY_BUSY); - - row = e_meeting_time_selector_attendee_add (mts, "Andrew Carlisle", NULL); - e_meeting_time_selector_attendee_set_send_meeting_to (mts, row, FALSE); - - row = e_meeting_time_selector_attendee_add (mts, "Michael Cain", NULL); - e_meeting_time_selector_attendee_add_busy_period (mts, row, - 1999, 11, 7, 15, 30, - 1999, 11, 7, 18, 30, - E_MEETING_TIME_SELECTOR_BUSY_TENTATIVE); - e_meeting_time_selector_attendee_add_busy_period (mts, row, - 1999, 11, 7, 12, 30, - 1999, 11, 7, 13, 30, - E_MEETING_TIME_SELECTOR_BUSY_OUT_OF_OFFICE); - e_meeting_time_selector_attendee_add_busy_period (mts, row, - 1999, 11, 7, 11, 00, - 1999, 11, 7, 12, 00, - E_MEETING_TIME_SELECTOR_BUSY_TENTATIVE); -} |