From e67721cbd7d3549c07701913b1de32fac8807063 Mon Sep 17 00:00:00 2001 From: Damon Chaplin Date: Sat, 17 Jun 2000 04:13:42 +0000 Subject: updated to use EText items rather than GtkEntry widgets and added support 2000-06-17 Damon Chaplin * widgets/meeting-time-sel/*: updated to use EText items rather than GtkEntry widgets and added support for adding new rows. svn path=/trunk/; revision=3604 --- widgets/meeting-time-sel/Makefile.am | 7 +- widgets/meeting-time-sel/e-meeting-time-sel-item.c | 76 ++++- widgets/meeting-time-sel/e-meeting-time-sel-item.h | 1 + .../e-meeting-time-sel-list-item.c | 99 ++++++- .../e-meeting-time-sel-list-item.h | 3 +- widgets/meeting-time-sel/e-meeting-time-sel.c | 307 +++++++++++++++++---- widgets/meeting-time-sel/e-meeting-time-sel.h | 22 ++ widgets/meeting-time-sel/test-meeting-time-sel.c | 6 + 8 files changed, 450 insertions(+), 71 deletions(-) (limited to 'widgets/meeting-time-sel') diff --git a/widgets/meeting-time-sel/Makefile.am b/widgets/meeting-time-sel/Makefile.am index fcf735c9bc..013006aaed 100644 --- a/widgets/meeting-time-sel/Makefile.am +++ b/widgets/meeting-time-sel/Makefile.am @@ -20,8 +20,11 @@ noinst_PROGRAMS = \ test_meeting_time_selector_SOURCES = \ test-meeting-time-sel.c -test_meeting_time_selector_LDADD = \ - libevolutionmtsel.a $(GNOMEUI_LIBS) +test_meeting_time_selector_LDADD = \ + libevolutionmtsel.a \ + $(top_builddir)/widgets/e-text/libetext.a \ + $(top_builddir)/e-util/libeutil.la \ + $(GNOMEUI_LIBS) test_meeting_time_selector_LDFLAGS = $(GNOME_LIBDIR) diff --git a/widgets/meeting-time-sel/e-meeting-time-sel-item.c b/widgets/meeting-time-sel/e-meeting-time-sel-item.c index cb716d6f08..54cde8d319 100644 --- a/widgets/meeting-time-sel/e-meeting-time-sel-item.c +++ b/widgets/meeting-time-sel/e-meeting-time-sel-item.c @@ -84,6 +84,12 @@ static gint e_meeting_time_selector_item_find_first_busy_period (EMeetingTimeSel 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; @@ -154,6 +160,7 @@ e_meeting_time_selector_item_init (EMeetingTimeSelectorItem *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_TOP_LEFT_ARROW); @@ -215,6 +222,7 @@ e_meeting_time_selector_item_realize (GnomeCanvasItem *item) window = GTK_WIDGET (canvas)->window; mts_item->main_gc = gdk_gc_new (window); + mts_item->stipple_gc = gdk_gc_new (window); } @@ -227,6 +235,8 @@ e_meeting_time_selector_item_unrealize (GnomeCanvasItem *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); @@ -258,15 +268,16 @@ e_meeting_time_selector_item_draw (GnomeCanvasItem *item, GdkDrawable *drawable, EMeetingTimeSelectorItem *mts_item; EMeetingTimeSelectorAttendee *attendee; gint day_x, meeting_start_x, meeting_end_x, bar_y, bar_height; - gint row, row_y; + gint row, row_y, start_x, end_x; GDate date, last_date, current_date; gboolean is_display_top, show_meeting_time; - GdkGC *gc; + 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; @@ -299,7 +310,7 @@ e_meeting_time_selector_item_draw (GnomeCanvasItem *item, GdkDrawable *drawable, 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, height); + meeting_end_x - meeting_start_x - 2, mts->row_height); else gdk_draw_rectangle (drawable, gc, TRUE, meeting_start_x + 1 - x, 0, @@ -310,17 +321,33 @@ e_meeting_time_selector_item_draw (GnomeCanvasItem *item, GdkDrawable *drawable, that have no calendar information. */ if (!is_display_top) { gdk_gc_set_foreground (gc, &mts->grid_color); - gdk_gc_set_background (gc, &mts->stipple_bg_color); - gdk_gc_set_stipple (gc, mts->stipple); - gnome_canvas_set_stipple_origin (item->canvas, gc); - gdk_gc_set_fill (gc, GDK_OPAQUE_STIPPLED); + 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) { - gdk_draw_rectangle (drawable, gc, TRUE, + 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); } @@ -419,7 +446,7 @@ e_meeting_time_selector_item_paint_day_top (EMeetingTimeSelectorItem *mts_item, 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, + x + grid_x, mts->row_height * 2 - 4 - scroll_y, x + grid_x, height); } grid_x = mts->day_width - 2; @@ -525,7 +552,7 @@ e_meeting_time_selector_item_paint_day (EMeetingTimeSelectorItem *mts_item, grid_y < height; grid_y += mts->row_height) { - if (attendee_index < mts->attendees->len) { + 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); @@ -922,3 +949,30 @@ e_meeting_time_selector_item_get_drag_position (EMeetingTimeSelectorItem *mts_it 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 index c2bd2872ce..d9fe6c6a9b 100644 --- a/widgets/meeting-time-sel/e-meeting-time-sel-item.h +++ b/widgets/meeting-time-sel/e-meeting-time-sel-item.h @@ -57,6 +57,7 @@ struct _EMeetingTimeSelectorItem /* 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; 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 index ac4b7b9009..f9a05a29a7 100644 --- a/widgets/meeting-time-sel/e-meeting-time-sel-list-item.c +++ b/widgets/meeting-time-sel/e-meeting-time-sel-list-item.c @@ -25,12 +25,12 @@ /* * EMeetingTimeSelectorListItem - A GnomeCanvasItem covering the entire attendee * list. It just draws the grid lines between the rows and after the icon - * column. It probably won't be needed when we switch to Miguel's new editable - * GtkList-like widget. + * column. */ #include #include +#include "../../e-util/e-canvas.h" #include "e-meeting-time-sel-list-item.h" #include "e-meeting-time-sel.h" @@ -60,6 +60,10 @@ 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; @@ -119,9 +123,7 @@ e_meeting_time_selector_list_item_class_init (EMeetingTimeSelectorListItemClass 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; -#if 0 item_class->event = e_meeting_time_selector_list_item_event; -#endif } @@ -237,6 +239,7 @@ e_meeting_time_selector_list_item_draw (GnomeCanvasItem *item, GdkDrawable *draw EMeetingTimeSelector *mts; EMeetingTimeSelectorAttendee *attendee; GdkGC *gc; + GdkFont *font; gint row, row_y, icon_x, icon_y; GdkPixmap *pixmap; GdkBitmap *mask; @@ -286,6 +289,18 @@ e_meeting_time_selector_list_item_draw (GnomeCanvasItem *item, GdkDrawable *draw 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"); } @@ -301,3 +316,79 @@ e_meeting_time_selector_list_item_point (GnomeCanvasItem *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; + GtkAdjustment *adjustment; + + 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); + 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 index 9ef295ebb2..07df052c08 100644 --- a/widgets/meeting-time-sel/e-meeting-time-sel-list-item.h +++ b/widgets/meeting-time-sel/e-meeting-time-sel-list-item.h @@ -25,8 +25,7 @@ /* * MeetingTimeSelectorListItem - A GnomeCanvasItem covering the entire attendee * list. It just draws the grid lines between the rows and after the icon - * column. It probably won't be needed when we switch to Miguel's new editable - * GtkList-like widget. + * column. */ #ifndef _E_MEETING_TIME_SELECTOR_LIST_ITEM_H_ diff --git a/widgets/meeting-time-sel/e-meeting-time-sel.c b/widgets/meeting-time-sel/e-meeting-time-sel.c index 86f81cc80e..0b6fd5c294 100644 --- a/widgets/meeting-time-sel/e-meeting-time-sel.c +++ b/widgets/meeting-time-sel/e-meeting-time-sel.c @@ -45,6 +45,7 @@ #include #include +#include "../../e-util/e-canvas.h" #include "e-meeting-time-sel.h" #include "e-meeting-time-sel-item.h" #include "e-meeting-time-sel-list-item.h" @@ -59,8 +60,6 @@ const gchar *EMeetingTimeSelectorHours[24] = { /* The number of days shown in the entire canvas. */ #define E_MEETING_TIME_SELECTOR_DAYS_SHOWN 365 -#define E_MEETING_TIME_SELECTOR_ENTRY_INNER_BORDER 2 - /* 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 @@ -94,6 +93,9 @@ 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, @@ -185,8 +187,13 @@ static void e_meeting_time_selector_ensure_meeting_time_shown (EMeetingTimeSelec 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 *e_meeting_time_selector_parent_class; +static GtkTableClass *parent_class; GtkType @@ -220,7 +227,7 @@ e_meeting_time_selector_class_init (EMeetingTimeSelectorClass * klass) GtkObjectClass *object_class; GtkWidgetClass *widget_class; - e_meeting_time_selector_parent_class = gtk_type_class (gtk_table_get_type()); + parent_class = gtk_type_class (gtk_table_get_type()); object_class = (GtkObjectClass *) klass; widget_class = (GtkWidgetClass *) klass; @@ -231,6 +238,7 @@ e_meeting_time_selector_class_init (EMeetingTimeSelectorClass * klass) 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; } @@ -250,6 +258,9 @@ e_meeting_time_selector_init (EMeetingTimeSelector * mts) 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, @@ -302,7 +313,7 @@ e_meeting_time_selector_init (EMeetingTimeSelector * mts) "expose_event", GTK_SIGNAL_FUNC (e_meeting_time_selector_expose_title_bar), mts); - mts->attendees_list = gnome_canvas_new (); + 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, @@ -659,6 +670,7 @@ e_meeting_time_selector_init (EMeetingTimeSelector * mts) 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); @@ -848,8 +860,8 @@ e_meeting_time_selector_destroy (GtkObject *object) g_array_free (mts->attendees, TRUE); - if (GTK_OBJECT_CLASS (e_meeting_time_selector_parent_class)->destroy) - (*GTK_OBJECT_CLASS (e_meeting_time_selector_parent_class)->destroy)(object); + if (GTK_OBJECT_CLASS (parent_class)->destroy) + (*GTK_OBJECT_CLASS (parent_class)->destroy)(object); } @@ -858,8 +870,8 @@ e_meeting_time_selector_realize (GtkWidget *widget) { EMeetingTimeSelector *mts; - if (GTK_WIDGET_CLASS (e_meeting_time_selector_parent_class)->realize) - (*GTK_WIDGET_CLASS (e_meeting_time_selector_parent_class)->realize)(widget); + if (GTK_WIDGET_CLASS (parent_class)->realize) + (*GTK_WIDGET_CLASS (parent_class)->realize)(widget); mts = E_MEETING_TIME_SELECTOR (widget); @@ -877,8 +889,8 @@ e_meeting_time_selector_unrealize (GtkWidget *widget) gdk_gc_unref (mts->color_key_gc); mts->color_key_gc = NULL; - if (GTK_WIDGET_CLASS (e_meeting_time_selector_parent_class)->unrealize) - (*GTK_WIDGET_CLASS (e_meeting_time_selector_parent_class)->unrealize)(widget); + if (GTK_WIDGET_CLASS (parent_class)->unrealize) + (*GTK_WIDGET_CLASS (parent_class)->unrealize)(widget); } @@ -891,8 +903,8 @@ e_meeting_time_selector_style_set (GtkWidget *widget, GdkFont *font; gint hour, max_hour_width; - if (GTK_WIDGET_CLASS (e_meeting_time_selector_parent_class)->style_set) - (*GTK_WIDGET_CLASS (e_meeting_time_selector_parent_class)->style_set)(widget, previous_style); + 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; @@ -904,15 +916,8 @@ e_meeting_time_selector_style_set (GtkWidget *widget, max_hour_width = MAX (max_hour_width, mts->hour_widths[hour]); } - /* The row height really depends on the requested height of the - GtkEntry widgets in the list on the left, so we really need to - call size_request on them, AFTER their style has been set. */ - /* FIXME: This uses the default style ythickness of 2, though it won't - be needed when we switch to Miguel's new editable GtkCList widget - so I won't worry about it. */ mts->row_height = font->ascent + font->descent - + E_MEETING_TIME_SELECTOR_ENTRY_INNER_BORDER * 2 - + 2 * 2; + + 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); @@ -933,17 +938,49 @@ e_meeting_time_selector_expose_event (GtkWidget *widget, GdkEventExpose *event) { EMeetingTimeSelector *mts; - gint x, y, w, h; 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); + 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; @@ -951,12 +988,8 @@ e_meeting_time_selector_expose_event (GtkWidget *widget, 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); - - if (GTK_WIDGET_CLASS (e_meeting_time_selector_parent_class)->expose_event) - (*GTK_WIDGET_CLASS (e_meeting_time_selector_parent_class)->expose_event)(widget, event); - - return FALSE; + gtk_draw_shadow (widget->style, widget->window, GTK_STATE_NORMAL, + GTK_SHADOW_IN, x, y, w, h); } @@ -970,7 +1003,7 @@ e_meeting_time_selector_hadjustment_changed (GtkAdjustment *adjustment, adj = GTK_LAYOUT (mts->display_top)->hadjustment; if (adj->value != adjustment->value) { adj->value = adjustment->value; - gtk_signal_emit_by_name (GTK_OBJECT (adj), "value_changed"); + gtk_adjustment_value_changed (adj); } } @@ -984,7 +1017,7 @@ e_meeting_time_selector_vadjustment_changed (GtkAdjustment *adjustment, adj = GTK_LAYOUT (mts->attendees_list)->vadjustment; if (adj->value != adjustment->value) { adj->value = adjustment->value; - gtk_signal_emit_by_name (GTK_OBJECT (adj), "value_changed"); + gtk_adjustment_value_changed (adj); } } @@ -1185,8 +1218,8 @@ e_meeting_time_selector_attendee_add (EMeetingTimeSelector *mts, gpointer data) { EMeetingTimeSelectorAttendee attendee; - GtkWidget *entry; 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); @@ -1195,6 +1228,12 @@ e_meeting_time_selector_attendee_add (EMeetingTimeSelector *mts, 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; @@ -1202,21 +1241,32 @@ e_meeting_time_selector_attendee_add (EMeetingTimeSelector *mts, attendee.data = data; /* Add to the list on the left. */ - entry = gtk_entry_new (); - gtk_entry_set_text (GTK_ENTRY (entry), attendee_name); - gtk_widget_show (entry); list_width = GTK_WIDGET (mts->attendees_list)->allocation.width; - item_width = MAX (1, list_width - E_MEETING_TIME_SELECTOR_ICON_COLUMN_WIDTH); - attendee.text_item = gnome_canvas_item_new (GNOME_CANVAS_GROUP (GNOME_CANVAS (mts->attendees_list)->root), - gnome_canvas_widget_get_type (), - "GnomeCanvasWidget::widget", entry, - "GnomeCanvasWidget::size_pixels", TRUE, - "GnomeCanvasWidget::x", (gdouble) E_MEETING_TIME_SELECTOR_ICON_COLUMN_WIDTH, - "GnomeCanvasWidget::y", (gdouble) (mts->attendees->len * mts->row_height), - "GnomeCanvasWidget::width", (gdouble) item_width, - "GnomeCanvasWidget::height", (gdouble) mts->row_height, - NULL); + 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 : "", + "x", (gdouble) E_MEETING_TIME_SELECTOR_ICON_COLUMN_WIDTH + + E_MEETING_TIME_SELECTOR_TEXT_X_PAD, + "y", (gdouble) (mts->attendees->len * mts->row_height + 1 + + E_MEETING_TIME_SELECTOR_TEXT_Y_PAD), + "clip_width", (gdouble) item_width, + "clip_height", (gdouble) font->ascent + font->descent, + NULL); +#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); @@ -1361,6 +1411,58 @@ e_meeting_time_selector_attendee_set_send_meeting_to (EMeetingTimeSelector *mts, } +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, @@ -2542,7 +2644,7 @@ e_meeting_time_selector_update_main_canvas_scroll_region (EMeetingTimeSelector * { gint height, canvas_height, list_width; - height = mts->row_height * mts->attendees->len; + 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; @@ -2935,18 +3037,24 @@ e_meeting_time_selector_update_attendees_list_positions (EMeetingTimeSelector *m 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); + 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, - "GnomeCanvasWidget::y", (gdouble) (row * mts->row_height), - "GnomeCanvasWidget::width", (gdouble) item_width, - "GnomeCanvasWidget::height", (gdouble) (mts->row_height), - NULL); + gnome_canvas_item_set + (attendee->text_item, + "font_gdk", font, + "y", (gdouble) (row * mts->row_height + 1 + + E_MEETING_TIME_SELECTOR_TEXT_Y_PAD), + "clip_width", (gdouble) item_width, + "clip_height", (gdouble) (font->ascent + + font->descent), + NULL); gnome_canvas_item_show (attendee->text_item); } @@ -3063,3 +3171,98 @@ e_meeting_time_selector_calculate_time_position (EMeetingTimeSelector *mts, } +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); + + /* 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 index 6df15fe54c..a2ad4b9cd5 100644 --- a/widgets/meeting-time-sel/e-meeting-time-sel.h +++ b/widgets/meeting-time-sel/e-meeting-time-sel.h @@ -26,6 +26,7 @@ #include #include +#include "../e-text/e-text.h" #ifdef __cplusplus extern "C" { @@ -43,6 +44,8 @@ extern "C" { /* 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 @@ -146,6 +149,11 @@ struct _EMeetingTimeSelectorAttendee /* 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: @@ -423,6 +431,20 @@ void e_meeting_time_selector_attendee_set_send_meeting_to (EMeetingTimeSelector 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); diff --git a/widgets/meeting-time-sel/test-meeting-time-sel.c b/widgets/meeting-time-sel/test-meeting-time-sel.c index debe4e8f40..33c15ff19b 100644 --- a/widgets/meeting-time-sel/test-meeting-time-sel.c +++ b/widgets/meeting-time-sel/test-meeting-time-sel.c @@ -60,6 +60,12 @@ main (int argc, char *argv[]) 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)); -- cgit v1.2.3