diff options
Diffstat (limited to 'calendar/gui')
-rw-r--r-- | calendar/gui/e-day-view-time-item.c | 95 | ||||
-rw-r--r-- | calendar/gui/e-day-view.c | 425 | ||||
-rw-r--r-- | calendar/gui/e-day-view.h | 32 | ||||
-rw-r--r-- | calendar/gui/e-week-view-titles-item.c | 21 | ||||
-rw-r--r-- | calendar/gui/e-week-view.c | 329 | ||||
-rw-r--r-- | calendar/gui/e-week-view.h | 23 | ||||
-rw-r--r-- | calendar/gui/event-editor.c | 89 | ||||
-rw-r--r-- | calendar/gui/gnome-cal.c | 41 | ||||
-rw-r--r-- | calendar/gui/tag-calendar.c | 8 |
9 files changed, 864 insertions, 199 deletions
diff --git a/calendar/gui/e-day-view-time-item.c b/calendar/gui/e-day-view-time-item.c index 19d8d40317..e018daa472 100644 --- a/calendar/gui/e-day-view-time-item.c +++ b/calendar/gui/e-day-view-time-item.c @@ -189,25 +189,29 @@ gint e_day_view_time_item_get_column_width (EDayViewTimeItem *dvtmitem) { EDayView *day_view; + gint column_width_default, column_width_60_min_rows; day_view = dvtmitem->day_view; g_return_val_if_fail (day_view != NULL, 0); - /* Calculate the width of each time column. */ - if (day_view->mins_per_row == 60) { - dvtmitem->column_width = day_view->max_small_hour_width - + day_view->colon_width - + day_view->max_minute_width - + E_DVTMI_60_MIN_X_PAD * 2 - + E_DVTMI_TIME_GRID_X_PAD * 2; - } else { - dvtmitem->column_width = day_view->max_large_hour_width + /* Calculate the width of each time column, using the maximum of the + default format with large hour numbers, and the 60-min divisions + format which uses small text. */ + column_width_default = day_view->max_large_hour_width + day_view->max_minute_width + E_DVTMI_MIN_X_PAD * 2 + E_DVTMI_HOUR_L_PAD + E_DVTMI_HOUR_R_PAD + E_DVTMI_TIME_GRID_X_PAD * 2; - } + + column_width_60_min_rows = day_view->max_small_hour_width + + day_view->colon_width + + day_view->max_minute_width + + E_DVTMI_60_MIN_X_PAD * 2 + + E_DVTMI_TIME_GRID_X_PAD * 2; + + dvtmitem->column_width = MAX (column_width_default, + column_width_60_min_rows); return dvtmitem->column_width; } @@ -228,12 +232,12 @@ e_day_view_time_item_draw (GnomeCanvasItem *canvas_item, EDayView *day_view; EDayViewTimeItem *dvtmitem; gint time_hour_x1, time_hour_x2, time_min_x1; - gint hour, minute, hour_y, min_y, hour_r, min_r, start_y; - gint row, row_y, min_width, hour_width; + gint hour, display_hour, minute, hour_y, min_y, hour_r, min_r, start_y; + gint row, row_y, min_width, hour_width, suffix_width; GtkStyle *style; GdkFont *small_font, *large_font; GdkGC *fg_gc, *dark_gc; - gchar buffer[16]; + gchar buffer[64], *suffix; dvtmitem = E_DAY_VIEW_TIME_ITEM (canvas_item); day_view = dvtmitem->day_view; @@ -262,12 +266,6 @@ e_day_view_time_item_draw (GnomeCanvasItem *canvas_item, } hour = day_view->first_hour_shown; - if (!day_view->use_24_hour_format) { - if (hour == 0 || hour == 12) - hour = 12; - else - hour %= 12; - } hour_y = large_font->ascent + 2; /* FIXME */ minute = day_view->first_minute_shown; min_y = small_font->ascent + 2; /* FIXME */ @@ -280,12 +278,40 @@ e_day_view_time_item_draw (GnomeCanvasItem *canvas_item, if (min_r <= 0) continue; + /* Calculate the actual hour number to display. */ + display_hour = hour; + if (!day_view->use_24_hour_format) { + if (display_hour < 12) { + suffix = day_view->am_string; + suffix_width = day_view->am_string_width; + } else { + display_hour -= 12; + suffix = day_view->pm_string; + suffix_width = day_view->pm_string_width; + } + + /* 12-hour format uses 12:00 rather than 0:00. + */ + if (display_hour == 0) + display_hour = 12; + } + if (day_view->mins_per_row == 60) { gdk_draw_line (drawable, dark_gc, time_hour_x1, row_y, time_hour_x2, row_y); - sprintf (buffer, "%02i:%02i", hour, minute); - min_width = day_view->small_hour_widths[hour] + day_view->minute_widths[minute / 5] + day_view->colon_width; + + if (day_view->use_24_hour_format) { + sprintf (buffer, "%i:%02i", + display_hour, minute); + /*min_width = day_view->small_hour_widths[display_hour] + day_view->minute_widths[minute / 5] + day_view->colon_width;*/ + min_width = gdk_string_width (small_font, buffer); + } else { + sprintf (buffer, "%i %s", + display_hour, suffix); + /*min_width = day_view->small_hour_widths[display_hour] + suffix_width;*/ + min_width = gdk_string_width (small_font, buffer); + } gdk_draw_string (drawable, small_font, fg_gc, min_r - min_width, row_y + min_y, buffer); @@ -294,8 +320,9 @@ e_day_view_time_item_draw (GnomeCanvasItem *canvas_item, gdk_draw_line (drawable, dark_gc, time_hour_x1, row_y, time_hour_x2, row_y); - sprintf (buffer, "%02i", hour); - hour_width = day_view->large_hour_widths[hour]; + sprintf (buffer, "%i", display_hour); + /*hour_width = day_view->large_hour_widths[display_hour];*/ + hour_width = gdk_string_width (large_font, buffer); gdk_draw_string (drawable, large_font, fg_gc, hour_r - hour_width, @@ -309,8 +336,14 @@ e_day_view_time_item_draw (GnomeCanvasItem *canvas_item, if (day_view->mins_per_row != 30 || minute != 30) { - sprintf (buffer, "%02i", minute); - min_width = day_view->minute_widths[minute / 5]; + if (minute == 0 + && !day_view->use_24_hour_format) { + strcpy (buffer, suffix); + min_width = gdk_string_width (small_font, buffer); + } else { + sprintf (buffer, "%02i", minute); + min_width = day_view->minute_widths[minute / 5]; + } gdk_draw_string (drawable, small_font, fg_gc, min_r - min_width, @@ -320,16 +353,14 @@ e_day_view_time_item_draw (GnomeCanvasItem *canvas_item, } } + /* Note that mins_per_row is never > 60, so we never have to + worry about adding more than 60 minutes. */ minute += day_view->mins_per_row; if (minute >= 60) { - hour++; - if (!day_view->use_24_hour_format) { - if (hour == 0 || hour == 12) - hour = 12; - else - hour %= 12; - } minute -= 60; + /* Currently we never wrap around to the next day, but + we may do if we display extra timezones. */ + hour = (hour + 1) % 24; } } } diff --git a/calendar/gui/e-day-view.c b/calendar/gui/e-day-view.c index c1da656ccd..9d7782462c 100644 --- a/calendar/gui/e-day-view.c +++ b/calendar/gui/e-day-view.c @@ -222,6 +222,9 @@ typedef gboolean (* EDayViewForeachEventCallback) (EDayView *day_view, gint event_num, gpointer data); +static void e_day_view_foreach_event (EDayView *day_view, + EDayViewForeachEventCallback callback, + gpointer data); static void e_day_view_foreach_event_with_uid (EDayView *day_view, const gchar *uid, EDayViewForeachEventCallback callback, @@ -380,6 +383,14 @@ static gboolean e_day_view_remove_event_cb (EDayView *day_view, gint event_num, gpointer data); static void e_day_view_normalize_selection (EDayView *day_view); +static gboolean e_day_view_set_show_times_cb (EDayView *day_view, + gint day, + gint event_num, + gpointer data); +static time_t e_day_view_find_work_week_start (EDayView *day_view, + time_t start_time); +static void e_day_view_recalc_work_week (EDayView *day_view); +static void e_day_view_recalc_work_week_days_shown (EDayView *day_view); static GtkTableClass *parent_class; @@ -463,7 +474,6 @@ e_day_view_init (EDayView *day_view) day_view->lower = 0; day_view->upper = 0; - /* FIXME: Initialize day_starts. */ day_view->work_week_view = FALSE; day_view->days_shown = 1; @@ -490,6 +500,8 @@ e_day_view_init (EDayView *day_view) day_view->work_day_start_minute = 0; day_view->work_day_end_hour = 17; day_view->work_day_end_minute = 0; + day_view->show_event_end_times = TRUE; + day_view->week_start_day = 0; day_view->scroll_to_work_day = TRUE; day_view->editing_event_day = -1; @@ -522,6 +534,12 @@ e_day_view_init (EDayView *day_view) if (!day_view->large_font) g_warning ("Couldn't load font"); + /* String to use in 12-hour time format for times in the morning. */ + day_view->am_string = _("am"); + + /* String to use in 12-hour time format for times in the afternoon. */ + day_view->pm_string = _("pm"); + /* * Top Canvas @@ -1065,6 +1083,11 @@ e_day_view_style_set (GtkWidget *widget, day_view->max_minute_width = max_minute_width; day_view->colon_width = gdk_string_width (font, ":"); + day_view->am_string_width = gdk_string_width (font, + day_view->am_string); + day_view->pm_string_width = gdk_string_width (font, + day_view->pm_string); + /* Calculate the width of the time column. */ times_width = e_day_view_time_item_get_column_width (E_DAY_VIEW_TIME_ITEM (day_view->time_canvas_item)); gtk_widget_set_usize (day_view->time_canvas, times_width, -1); @@ -1252,8 +1275,6 @@ e_day_view_set_calendar (EDayView *day_view, g_return_if_fail (E_IS_DAY_VIEW (day_view)); day_view->calendar = calendar; - - /* FIXME: free current events? */ } @@ -1285,6 +1306,9 @@ obj_updated_cb (CalClient *client, const char *uid, gpointer data) day_view = E_DAY_VIEW (data); + /* Sanity check. */ + g_return_if_fail (client == day_view->client); + /* If our time hasn't been set yet, just return. */ if (day_view->lower == 0 && day_view->upper == 0) return; @@ -1459,8 +1483,46 @@ e_day_view_update_event_cb (EDayView *day_view, } +/* This calls a given function for each event instance (in both views). + If the callback returns TRUE the iteration is stopped. + Note that it is safe for the callback to remove the event (since we + step backwards through the arrays). */ +static void +e_day_view_foreach_event (EDayView *day_view, + EDayViewForeachEventCallback callback, + gpointer data) +{ + EDayViewEvent *event; + gint day, event_num; + + for (day = 0; day < day_view->days_shown; day++) { + for (event_num = day_view->events[day]->len - 1; + event_num >= 0; + event_num--) { + event = &g_array_index (day_view->events[day], + EDayViewEvent, event_num); + + if (!(*callback) (day_view, day, event_num, data)) + return; + } + } + + for (event_num = day_view->long_events->len - 1; + event_num >= 0; + event_num--) { + event = &g_array_index (day_view->long_events, + EDayViewEvent, event_num); + + if (!(*callback) (day_view, E_DAY_VIEW_LONG_EVENT, event_num, + data)) + return; + } +} + + /* This calls a given function for each event instance that matches the given - uid. Note that it is safe for the callback to remove the event (since we + uid. If the callback returns TRUE the iteration is stopped. + Note that it is safe for the callback to remove the event (since we step backwards through the arrays). */ static void e_day_view_foreach_event_with_uid (EDayView *day_view, @@ -1553,9 +1615,9 @@ e_day_view_update_event_label (EDayView *day_view, gint event_num) { EDayViewEvent *event; - char *text; + char *text, *start_suffix, *end_suffix; gboolean free_text = FALSE, editing_event = FALSE; - gint offset, start_minute, end_minute; + gint offset, start_hour, start_minute, end_hour, end_minute; CalComponentText summary; event = &g_array_index (day_view->events[day], EDayViewEvent, @@ -1574,17 +1636,70 @@ e_day_view_update_event_label (EDayView *day_view, if (!editing_event && (event->start_minute % day_view->mins_per_row != 0 - || event->end_minute % day_view->mins_per_row != 0)) { + || (day_view->show_event_end_times + && event->end_minute % day_view->mins_per_row != 0))) { offset = day_view->first_hour_shown * 60 + day_view->first_minute_shown; start_minute = offset + event->start_minute; end_minute = offset + event->end_minute; - text = g_strdup_printf ("%02i:%02i-%02i:%02i %s", - start_minute / 60, - start_minute % 60, - end_minute / 60, - end_minute % 60, - text); + + start_hour = start_minute / 60; + start_minute = start_minute % 60; + + end_hour = end_minute / 60; + end_minute = end_minute % 60; + + if (day_view->use_24_hour_format) { + if (day_view->show_event_end_times) { + /* 24 hour format with end time. */ + text = g_strdup_printf + ("%02i:%02i-%02i:%02i %s", + start_hour, start_minute, + end_hour, end_minute, + text); + } else { + /* 24 hour format without end time. */ + text = g_strdup_printf + ("%02i:%02i %s", + start_hour, start_minute, + text); + } + } else { + start_suffix = end_suffix = day_view->am_string; + + if (start_hour >= 12) { + start_hour -= 12; + start_suffix = day_view->pm_string; + } + if (end_hour >= 12) { + end_hour -= 12; + end_suffix = day_view->pm_string; + } + + /* We display 1-12 rather than 0-11 for hours. */ + if (start_hour == 0) + start_hour = 12; + if (end_hour == 0) + end_hour = 12; + + if (day_view->show_event_end_times) { + /* 12 hour format with end time. */ + text = g_strdup_printf + ("%02i:%02i%s-%02i:%02i%s %s", + start_hour, start_minute, + start_suffix, + end_hour, end_minute, + end_suffix, + text); + } else { + /* 12 hour format without end time. */ + text = g_strdup_printf + ("%02i:%02i%s %s", + start_hour % 12, start_minute, + start_suffix, + text); + } + } free_text = TRUE; } @@ -1717,7 +1832,6 @@ e_day_view_set_selected_time_range (EDayView *day_view, time_t start_time, time_t end_time) { - GDate date; time_t lower; gint start_row, start_col, end_row, end_col; gboolean need_redraw = FALSE, start_in_grid, end_in_grid; @@ -1727,16 +1841,11 @@ e_day_view_set_selected_time_range (EDayView *day_view, /* Calculate the first day that should be shown, based on start_time and the days_shown setting. If we are showing 1 day it is just the start of the day given by start_time, otherwise it is the previous - Monday. */ + work-week start day. */ if (!day_view->work_week_view) { lower = time_day_begin (start_time); } else { - g_date_clear (&date, 1); - g_date_set_time (&date, start_time); - g_date_subtract_days (&date, g_date_weekday (&date) - 1); - lower = time_from_day (g_date_year (&date), - g_date_month (&date) - 1, - g_date_day (&date)); + lower = e_day_view_find_work_week_start (day_view, start_time); } /* See if we need to change the days shown. */ @@ -1790,6 +1899,46 @@ e_day_view_set_selected_time_range (EDayView *day_view, } +/* Finds the start of the working week which includes the given time. */ +static time_t +e_day_view_find_work_week_start (EDayView *day_view, + time_t start_time) +{ + GDate date; + gint weekday, day, i, offset; + + g_date_clear (&date, 1); + g_date_set_time (&date, start_time); + + /* The start of the work-week is the first working day after the + week start day. */ + + /* Get the weekday corresponding to start_time, 0 (Sun) to 6 (Sat). */ + weekday = g_date_weekday (&date) % 7; + + /* Calculate the first working day of the week, 0 (Sun) to 6 (Sat). + It will automatically default to the week start day if no days + are set as working days. */ + day = (day_view->week_start_day + 1) % 7; + for (i = 0; i < 7; i++) { + if (day_view->working_days & (1 << day)) + break; + day = (day + 1) % 7; + } + + /* Calculate how many days we need to go back to the first workday. */ + offset = (weekday + 7 - day) % 7; + + g_print ("Weekday: %i Day: %i Offset: %i\n", weekday, day, offset); + + g_date_subtract_days (&date, offset); + + return time_from_day (g_date_year (&date), + g_date_month (&date) - 1, + g_date_day (&date)); +} + + /* Returns the selected time range. */ void e_day_view_get_selected_time_range (EDayView *day_view, @@ -1868,7 +2017,8 @@ e_day_view_set_work_week_view (EDayView *day_view, day_view->work_week_view = work_week_view; - /* FIXME: need to recalc the first day shown if now work-week view. */ + if (day_view->work_week_view) + e_day_view_recalc_work_week (day_view); } @@ -1889,12 +2039,18 @@ e_day_view_set_days_shown (EDayView *day_view, g_return_if_fail (days_shown >= 1); g_return_if_fail (days_shown <= E_DAY_VIEW_MAX_DAYS); - if (day_view->days_shown != days_shown) { - day_view->days_shown = days_shown; - e_day_view_recalc_day_starts (day_view, day_view->lower); - e_day_view_recalc_cell_sizes (day_view); - e_day_view_queue_reload_events (day_view); - } + if (day_view->days_shown = days_shown) + return; + + day_view->days_shown = days_shown; + + /* If the date isn't set, just return. */ + if (day_view->lower == 0 && day_view->upper == 0) + return; + + e_day_view_recalc_day_starts (day_view, day_view->lower); + e_day_view_recalc_cell_sizes (day_view); + e_day_view_queue_reload_events (day_view); } @@ -1934,6 +2090,11 @@ e_day_view_set_mins_per_row (EDayView *day_view, for (day = 0; day < E_DAY_VIEW_MAX_DAYS; day++) day_view->need_layout[day] = TRUE; + /* We need to update all the day event labels since the start & end + times may or may not be on row boundaries any more. */ + e_day_view_foreach_event (day_view, + e_day_view_set_show_times_cb, NULL); + /* We must layout the events before updating the scroll region, since that will result in a redraw which would crash otherwise. */ e_day_view_check_layout (day_view); @@ -1961,10 +2122,55 @@ e_day_view_set_working_days (EDayView *day_view, { g_return_if_fail (E_IS_DAY_VIEW (day_view)); - if (day_view->working_days != days) { - day_view->working_days = days; - gtk_widget_queue_draw (day_view->main_canvas); + if (day_view->working_days == days) + return; + + day_view->working_days = days; + + if (day_view->work_week_view) + e_day_view_recalc_work_week (day_view); + + /* We have to do this, as the new working days may have no effect on + the days shown, but we still want the background color to change. */ + gtk_widget_queue_draw (day_view->main_canvas); +} + + +static void +e_day_view_recalc_work_week_days_shown (EDayView *day_view) +{ + gint first_day, last_day, i, days_shown; + gboolean has_working_days = FALSE; + + /* Find the first working day in the week, 0 (Sun) to 6 (Sat). */ + first_day = (day_view->week_start_day + 1) % 7; + for (i = 0; i < 7; i++) { + if (day_view->working_days & (1 << first_day)) { + has_working_days = TRUE; + break; + } + first_day = (first_day + 1) % 7; + } + + if (has_working_days) { + /* Now find the last working day of the week, backwards. */ + last_day = day_view->week_start_day % 7; + for (i = 0; i < 7; i++) { + if (day_view->working_days & (1 << last_day)) + break; + last_day = (last_day + 6) % 7; + } + /* Now calculate the days we need to show to include all the + working days in the week. Add 1 to make it inclusive. */ + days_shown = (last_day + 7 - first_day) % 7 + 1; + g_print ("First day: %i Last: %i Days: %i\n", + first_day, last_day, days_shown); + } else { + /* If no working days are set, just use 7. */ + days_shown = 7; } + + e_day_view_set_days_shown (day_view, days_shown); } @@ -2020,11 +2226,120 @@ e_day_view_set_24_hour_format (EDayView *day_view, { g_return_if_fail (E_IS_DAY_VIEW (day_view)); - if (day_view->use_24_hour_format != use_24_hour) { - day_view->use_24_hour_format = use_24_hour; + if (day_view->use_24_hour_format == use_24_hour) + return; - /* FIXME: Eventually we need to do a re-layout. */ - gtk_widget_queue_draw (day_view->main_canvas); + day_view->use_24_hour_format = use_24_hour; + + /* We need to update all the text in the events since they may contain + the time in the old format. */ + e_day_view_foreach_event (day_view, e_day_view_set_show_times_cb, + NULL); + + /* FIXME: We need to re-layout the top canvas since the time + format affects the sizes. */ + gtk_widget_queue_draw (day_view->time_canvas); + gtk_widget_queue_draw (day_view->top_canvas); +} + + +/* Whether we display event end times in the main canvas. */ +gboolean +e_day_view_get_show_event_end_times (EDayView *day_view) +{ + g_return_val_if_fail (E_IS_DAY_VIEW (day_view), TRUE); + + return day_view->show_event_end_times; +} + + +void +e_day_view_set_show_event_end_times (EDayView *day_view, + gboolean show) +{ + g_return_if_fail (E_IS_DAY_VIEW (day_view)); + + if (day_view->show_event_end_times != show) { + day_view->show_event_end_times = show; + e_day_view_foreach_event (day_view, + e_day_view_set_show_times_cb, NULL); + } +} + + +/* This is a callback used to update all day event labels. */ +static gboolean +e_day_view_set_show_times_cb (EDayView *day_view, + gint day, + gint event_num, + gpointer data) +{ + g_print ("In e_day_view_set_show_times_cb day:%i event_num:%i\n", + day, event_num); + + if (day != E_DAY_VIEW_LONG_EVENT) { + e_day_view_update_event_label (day_view, day, event_num); + } + + return TRUE; +} + + +/* The first day of the week, 0 (Monday) to 6 (Sunday). */ +gint +e_day_view_get_week_start_day (EDayView *day_view) +{ + g_return_val_if_fail (E_IS_DAY_VIEW (day_view), 0); + + return day_view->week_start_day; +} + + +void +e_day_view_set_week_start_day (EDayView *day_view, + gint week_start_day) +{ + g_return_if_fail (E_IS_DAY_VIEW (day_view)); + g_return_if_fail (week_start_day >= 0); + g_return_if_fail (week_start_day < 7); + + g_print ("In e_day_view_set_week_start_day day: %i\n", week_start_day); + + if (day_view->week_start_day == week_start_day) + return; + + day_view->week_start_day = week_start_day; + + if (day_view->work_week_view) + e_day_view_recalc_work_week (day_view); +} + + +static void +e_day_view_recalc_work_week (EDayView *day_view) +{ + time_t lower; + + /* If we aren't showing the work week, just return. */ + if (!day_view->work_week_view) + return; + + /* If the date isn't set, just return. */ + if (day_view->lower == 0 && day_view->upper == 0) + return; + + e_day_view_recalc_work_week_days_shown (day_view); + + lower = e_day_view_find_work_week_start (day_view, day_view->lower); + if (lower != day_view->lower) { + /* Reset the selection, as it may disappear. */ + day_view->selection_start_day = -1; + + e_day_view_recalc_day_starts (day_view, lower); + e_day_view_queue_reload_events (day_view); + + /* This updates the date navigator. */ + e_day_view_update_calendar_selection_time (day_view); } } @@ -2719,7 +3034,11 @@ e_day_view_on_new_appointment (GtkWidget *widget, gpointer data) cal_component_commit_sequence (comp); - gnome_calendar_edit_object (day_view->calendar, comp); + if (day_view->calendar) + gnome_calendar_edit_object (day_view->calendar, comp); + else + g_warning ("Calendar not set"); + gtk_object_unref (GTK_OBJECT (comp)); } @@ -2736,7 +3055,10 @@ e_day_view_on_edit_appointment (GtkWidget *widget, gpointer data) if (event == NULL) return; - gnome_calendar_edit_object (day_view->calendar, event->comp); + if (day_view->calendar) + gnome_calendar_edit_object (day_view->calendar, event->comp); + else + g_warning ("Calendar not set"); } @@ -2805,6 +3127,9 @@ e_day_view_on_unrecur_appointment (GtkWidget *widget, gpointer data) if (event == NULL) return; + date.value = &itt; + date.tzid = NULL; + /* For the recurring object, we add an exception to get rid of the instance. */ @@ -2917,8 +3242,13 @@ e_day_view_update_calendar_selection_time (EDayView *day_view) time_t start, end; e_day_view_get_selected_time_range (day_view, &start, &end); - gnome_calendar_set_selected_time_range (day_view->calendar, - start, end); + + g_print ("Start: %s", ctime (&start)); + g_print ("End : %s", ctime (&end)); + + if (day_view->calendar) + gnome_calendar_set_selected_time_range (day_view->calendar, + start, end); } @@ -3500,8 +3830,11 @@ e_day_view_reload_events (EDayView *day_view) /* If both lower & upper are 0, then the time range hasn't been set, so we don't try to load any events. */ - if (day_view->calendar - && (day_view->lower != 0 || day_view->upper != 0)) { + if (day_view->lower != 0 || day_view->upper != 0) { +#if 0 + g_print ("EDayView (%s) generating instances\n", + day_view->work_week_view ? "Work Week" : "1 Day View"); +#endif cal_client_generate_instances (day_view->client, CALOBJ_TYPE_EVENT, day_view->lower, @@ -3969,7 +4302,9 @@ e_day_view_layout_day_events (EDayView *day_view, rows. */ guint16 group_starts[12 * 24]; - /* Reset the cols_per_row array, and initialize the connected rows. */ + /* Reset the cols_per_row array, and initialize the connected rows so + that all rows are not connected - each row is the start of a new + group. */ for (row = 0; row < day_view->rows; row++) { day_view->cols_per_row[day][row] = 0; group_starts[row] = row; @@ -4647,7 +4982,8 @@ static void e_day_view_cursor_key_left (EDayView *day_view, GdkEventKey *event) { if (day_view->selection_start_day == 0) { - gnome_calendar_previous (day_view->calendar); + if (day_view->calendar) + gnome_calendar_previous (day_view->calendar); } else { day_view->selection_start_day--; day_view->selection_end_day--; @@ -4665,7 +5001,8 @@ static void e_day_view_cursor_key_right (EDayView *day_view, GdkEventKey *event) { if (day_view->selection_end_day == day_view->days_shown - 1) { - gnome_calendar_next (day_view->calendar); + if (day_view->calendar) + gnome_calendar_next (day_view->calendar); } else { day_view->selection_start_day++; day_view->selection_end_day++; diff --git a/calendar/gui/e-day-view.h b/calendar/gui/e-day-view.h index bf72d47f46..f0118187e4 100644 --- a/calendar/gui/e-day-view.h +++ b/calendar/gui/e-day-view.h @@ -209,7 +209,7 @@ struct _EDayView /* Calendar client object we are monitoring */ CalClient *client; - /* The start and end of the day shown. */ + /* The start and end of the days shown. */ time_t lower; time_t upper; @@ -218,7 +218,7 @@ struct _EDayView /* The number of days we are showing. Usually 1 or 5, but can be up to E_DAY_VIEW_MAX_DAYS, e.g. when the user selects a range of - days in the mini calendar. */ + days in the date navigator. */ gint days_shown; /* The start of each day & an extra element to hold the last time. */ @@ -282,6 +282,12 @@ struct _EDayView /* Whether we use 12-hour of 24-hour format. */ gboolean use_24_hour_format; + /* Whether we use show event end times in the main canvas. */ + gboolean show_event_end_times; + + /* The first day of the week, 0 (Monday) to 6 (Sunday). */ + gint week_start_day; + /* This is set to TRUE when the widget is created, so it scrolls to the start of the working day when first shown. */ gboolean scroll_to_work_day; @@ -291,7 +297,9 @@ struct _EDayView gint day_widths[E_DAY_VIEW_MAX_DAYS]; gint day_offsets[E_DAY_VIEW_MAX_DAYS + 1]; - /* An array holding the number of columns in each row, in each day. */ + /* An array holding the number of columns in each row, in each day. + Note that there are a maximum of 12 * 24 rows (when a row is 5 mins) + but we don't always have that many rows. */ guint8 cols_per_row[E_DAY_VIEW_MAX_DAYS][12 * 24]; /* Sizes of the various time strings. */ @@ -313,7 +321,7 @@ struct _EDayView gint longest_weekday_name; gint longest_abbreviated_weekday_name; - /* The large font use to display the hours. I don't think we need a + /* The large font used to display the hours. I don't think we need a fontset since we only display numbers. */ GdkFont *large_font; @@ -433,6 +441,12 @@ struct _EDayView GnomeCanvasItem *drag_rect_item; GnomeCanvasItem *drag_bar_item; GnomeCanvasItem *drag_item; + + /* "am" and "pm" in the current locale, and their widths. */ + gchar *am_string; + gchar *pm_string; + gint am_string_width; + gint pm_string_width; }; struct _EDayViewClass @@ -515,6 +529,16 @@ gboolean e_day_view_get_24_hour_format (EDayView *day_view); void e_day_view_set_24_hour_format (EDayView *day_view, gboolean use_24_hour); +/* Whether we display event end times in the main canvas. */ +gboolean e_day_view_get_show_event_end_times (EDayView *day_view); +void e_day_view_set_show_event_end_times (EDayView *day_view, + gboolean show); + +/* The first day of the week, 0 (Monday) to 6 (Sunday). */ +gint e_day_view_get_week_start_day (EDayView *day_view); +void e_day_view_set_week_start_day (EDayView *day_view, + gint week_start_day); + /* * Internal functions called by the associated canvas items. */ diff --git a/calendar/gui/e-week-view-titles-item.c b/calendar/gui/e-week-view-titles-item.c index 14f47e4bcf..5a2b9c164a 100644 --- a/calendar/gui/e-week-view-titles-item.c +++ b/calendar/gui/e-week-view-titles-item.c @@ -174,6 +174,7 @@ e_week_view_titles_item_draw (GnomeCanvasItem *canvas_item, GDate date; GdkRectangle clip_rect; gboolean long_format; + gint weekday; #if 0 g_print ("In e_week_view_titles_item_draw %i,%i %ix%i\n", @@ -222,9 +223,12 @@ e_week_view_titles_item_draw (GnomeCanvasItem *canvas_item, /* Draw the date. Set a clipping rectangle so we don't draw over the next day. */ g_date_clear (&date, 1); - g_date_set_dmy (&date, 27, 3, 2000); /* Must be a Monday. */ + /* Note that 20th March 2000 is a Monday. We only care about the + weekday. */ + weekday = week_view->display_start_day; + g_date_set_dmy (&date, 20 + weekday, 3, 2000); for (col = 0; col < week_view->columns; col++) { - if (col == 5 && week_view->compress_weekend) { + if (weekday == 5 && week_view->compress_weekend) { g_date_strftime (buffer, 128, "%a/", &date); g_date_add_days (&date, 1); g_date_strftime (buffer + strlen (buffer), 100, @@ -239,14 +243,14 @@ e_week_view_titles_item_draw (GnomeCanvasItem *canvas_item, clip_rect.height = canvas_height - 2; gdk_gc_set_clip_rectangle (fg_gc, &clip_rect); - if (col == 5 && week_view->compress_weekend) + if (weekday == 5 && week_view->compress_weekend) date_width = week_view->abbr_day_widths[5] + week_view->slash_width + week_view->abbr_day_widths[6]; else if (long_format) - date_width = week_view->day_widths[col]; + date_width = week_view->day_widths[weekday]; else - date_width = week_view->abbr_day_widths[col]; + date_width = week_view->abbr_day_widths[weekday]; date_x = week_view->col_offsets[col] + (week_view->col_widths[col] - date_width) / 2; @@ -280,6 +284,13 @@ e_week_view_titles_item_draw (GnomeCanvasItem *canvas_item, canvas_height - y); } + if (weekday == 5 && week_view->compress_weekend) + weekday += 2; + else + weekday++; + + weekday = weekday % 7; + g_date_add_days (&date, 1); } } diff --git a/calendar/gui/e-week-view.c b/calendar/gui/e-week-view.c index 48c9f147d3..ca93fd1a14 100644 --- a/calendar/gui/e-week-view.c +++ b/calendar/gui/e-week-view.c @@ -175,6 +175,7 @@ static gboolean e_week_view_update_event_cb (EWeekView *week_view, static gboolean e_week_view_remove_event_cb (EWeekView *week_view, gint event_num, gpointer data); +static gboolean e_week_view_recalc_display_start_day (EWeekView *week_view); static GtkTableClass *parent_class; @@ -256,6 +257,9 @@ e_week_view_init (EWeekView *week_view) week_view->rows = 6; week_view->columns = 2; week_view->compress_weekend = TRUE; + week_view->show_event_end_times = TRUE; + week_view->week_start_day = 0; /* Monday. */ + week_view->display_start_day = 0; /* Monday. */ g_date_clear (&week_view->base_date, 1); g_date_clear (&week_view->first_day_shown, 1); @@ -693,14 +697,16 @@ e_week_view_recalc_cell_sizes (EWeekView *week_view) if (week_view->use_small_font && week_view->small_font) { time_width = week_view->digit_width * 2 + week_view->small_digit_width * 2; - if (width / 2 > time_width * 2 + week_view->space_width) + if (week_view->show_event_end_times + && width / 2 > time_width * 2 + week_view->space_width) week_view->time_format = E_WEEK_VIEW_TIME_BOTH_SMALL_MIN; else if (width / 2 > time_width) week_view->time_format = E_WEEK_VIEW_TIME_START_SMALL_MIN; } else { time_width = week_view->digit_width * 4 + week_view->colon_width; - if (width / 2 > time_width * 2 + week_view->space_width) + if (week_view->show_event_end_times + && width / 2 > time_width * 2 + week_view->space_width) week_view->time_format = E_WEEK_VIEW_TIME_BOTH; else if (width / 2 > time_width) week_view->time_format = E_WEEK_VIEW_TIME_START; @@ -812,8 +818,6 @@ e_week_view_set_calendar (EWeekView *week_view, g_return_if_fail (E_IS_WEEK_VIEW (week_view)); week_view->calendar = calendar; - - /* FIXME: free current events? */ } @@ -843,6 +847,9 @@ obj_updated_cb (CalClient *client, const char *uid, gpointer data) week_view = E_WEEK_VIEW (data); + /* Sanity check. */ + g_return_if_fail (client == week_view->client); + /* If we don't have a valid date set yet, just return. */ if (!g_date_valid (&week_view->first_day_shown)) return; @@ -978,7 +985,7 @@ e_week_view_set_selected_time_range (EWeekView *week_view, time_t end_time) { GDate date, base_date, end_date; - gint day_offset, num_days; + gint day_offset, weekday, week_start_offset, num_days; gboolean update_adjustment_value = FALSE; g_return_if_fail (E_IS_WEEK_VIEW (week_view)); @@ -990,13 +997,30 @@ e_week_view_set_selected_time_range (EWeekView *week_view, /* Find the number of days since the start of the month. */ day_offset = g_date_day (&date) - 1; - /* Find the 1st Monday at or before the start of the month. */ + /* Find the 1st week which starts at or before the start of + the month. */ base_date = date; g_date_set_day (&base_date, 1); - day_offset += g_date_weekday (&base_date) - 1; + + /* Calculate the weekday of the 1st of the month, 0 = Mon. */ + weekday = g_date_weekday (&base_date) - 1; + + /* Convert it to an offset from the start of the display. */ + week_start_offset = (weekday + 7 - week_view->display_start_day) % 7; + + /* Add it to the day offset so we go back to the 1st week at + or before the start of the month. */ + day_offset += week_start_offset; } else { - /* Find the 1st Monday at or before the given day. */ - day_offset = g_date_weekday (&date) - 1; + /* Calculate the weekday of the given date, 0 = Mon. */ + weekday = g_date_weekday (&date) - 1; + + /* Convert it to an offset from the start of the display. */ + week_start_offset = (weekday + 7 - week_view->display_start_day) % 7; + + /* Set the day_offset to the result, so we move back to the + start of the week. */ + day_offset = week_start_offset; } /* Calculate the base date, i.e. the first day shown when the @@ -1094,7 +1118,7 @@ e_week_view_set_first_day_shown (EWeekView *week_view, GDate *date) { GDate base_date; - gint day_offset, num_days; + gint weekday, day_offset, num_days; gboolean update_adjustment_value = FALSE; guint32 old_selection_start_julian = 0, old_selection_end_julian = 0; struct tm start_tm; @@ -1112,8 +1136,11 @@ e_week_view_set_first_day_shown (EWeekView *week_view, + week_view->selection_end_day; } - /* Find the 1st Monday at or before the given day. */ - day_offset = g_date_weekday (date) - 1; + /* Calculate the weekday of the given date, 0 = Mon. */ + weekday = g_date_weekday (date) - 1; + + /* Convert it to an offset from the start of the display. */ + day_offset = (weekday + 7 - week_view->display_start_day) % 7; /* Calculate the base date, i.e. the first day shown when the scrollbar adjustment value is 0. */ @@ -1224,11 +1251,11 @@ e_week_view_set_multi_week_view (EWeekView *week_view, adjustment->page_size = page_size; gtk_adjustment_changed (adjustment); - /* FIXME: Need to change start date and adjustment value? */ - - e_week_view_recalc_day_starts (week_view, week_view->day_starts[0]); e_week_view_recalc_cell_sizes (week_view); - e_week_view_queue_reload_events (week_view); + + if (g_date_valid (&week_view->first_day_shown)) + e_week_view_set_first_day_shown (week_view, + &week_view->first_day_shown); } @@ -1266,11 +1293,10 @@ e_week_view_set_weeks_shown (EWeekView *week_view, adjustment->page_size = page_size; gtk_adjustment_changed (adjustment); - /* FIXME: Need to change start date and adjustment value? */ - e_week_view_recalc_day_starts (week_view, - week_view->day_starts[0]); e_week_view_recalc_cell_sizes (week_view); - e_week_view_queue_reload_events (week_view); + + if (g_date_valid (&week_view->first_day_shown)) + e_week_view_set_first_day_shown (week_view, &week_view->first_day_shown); } } @@ -1288,6 +1314,8 @@ void e_week_view_set_compress_weekend (EWeekView *week_view, gboolean compress) { + gboolean need_reload = FALSE; + g_return_if_fail (E_IS_WEEK_VIEW (week_view)); if (week_view->compress_weekend == compress) @@ -1300,8 +1328,102 @@ e_week_view_set_compress_weekend (EWeekView *week_view, return; e_week_view_recalc_cell_sizes (week_view); - week_view->events_need_reshape = TRUE; - e_week_view_check_layout (week_view); + + need_reload = e_week_view_recalc_display_start_day (week_view); + + /* If the display_start_day has changed we need to recalculate the + date range shown and reload all events, otherwise we only need to + do a reshape. */ + if (need_reload) { + /* Recalculate the days shown and reload if necessary. */ + if (g_date_valid (&week_view->first_day_shown)) + e_week_view_set_first_day_shown (week_view, &week_view->first_day_shown); + } else { + week_view->events_need_reshape = TRUE; + e_week_view_check_layout (week_view); + } +} + + +/* Whether we display event end times. */ +gboolean +e_week_view_get_show_event_end_times (EWeekView *week_view) +{ + g_return_val_if_fail (E_IS_WEEK_VIEW (week_view), TRUE); + + return week_view->show_event_end_times; +} + + +void +e_week_view_set_show_event_end_times (EWeekView *week_view, + gboolean show) +{ + g_return_if_fail (E_IS_WEEK_VIEW (week_view)); + + if (week_view->show_event_end_times != show) { + week_view->show_event_end_times = show; + e_week_view_recalc_cell_sizes (week_view); + week_view->events_need_reshape = TRUE; + e_week_view_check_layout (week_view); + } +} + + +/* The first day of the week, 0 (Monday) to 6 (Sunday). */ +gint +e_week_view_get_week_start_day (EWeekView *week_view) +{ + g_return_val_if_fail (E_IS_WEEK_VIEW (week_view), 0); + + return week_view->week_start_day; +} + + +void +e_week_view_set_week_start_day (EWeekView *week_view, + gint week_start_day) +{ + g_return_if_fail (E_IS_WEEK_VIEW (week_view)); + g_return_if_fail (week_start_day >= 0); + g_return_if_fail (week_start_day < 7); + + g_print ("In e_week_view_set_week_start_day day: %i\n", week_start_day); + + if (week_view->week_start_day == week_start_day) + return; + + week_view->week_start_day = week_start_day; + + e_week_view_recalc_display_start_day (week_view); + + /* Recalculate the days shown and reload if necessary. */ + if (g_date_valid (&week_view->first_day_shown)) + e_week_view_set_first_day_shown (week_view, + &week_view->first_day_shown); +} + + +static gboolean +e_week_view_recalc_display_start_day (EWeekView *week_view) +{ + gint display_start_day; + + /* The display start day defaults to week_start_day, but we have + to use Saturday if the weekend is compressed and week_start_day + is Sunday. */ + display_start_day = week_view->week_start_day; + + if (display_start_day == 6 + && (!week_view->multi_week_view || week_view->compress_weekend)) + display_start_day = 5; + + if (week_view->display_start_day != display_start_day) { + week_view->display_start_day = display_start_day; + return TRUE; + } + + return FALSE; } @@ -1426,7 +1548,7 @@ e_week_view_get_day_position (EWeekView *week_view, gint *day_w, gint *day_h) { - gint week, day_of_week, row; + gint week, day_of_week, row, col, weekend_col, box, weekend_box; *day_x = *day_y = *day_w = *day_h = 0; g_return_if_fail (day >= 0); @@ -1435,7 +1557,8 @@ e_week_view_get_day_position (EWeekView *week_view, g_return_if_fail (day < week_view->weeks_shown * 7); week = day / 7; - day_of_week = day % 7; + col = day % 7; + day_of_week = (week_view->display_start_day + day) % 7; if (week_view->compress_weekend && day_of_week >= 5) { /* In the compressed view Saturday is above Sunday and both have just one row as opposed to 2 for all the @@ -1446,23 +1569,41 @@ e_week_view_get_day_position (EWeekView *week_view, } else { *day_y = week_view->row_offsets[week * 2 + 1]; *day_h = week_view->row_heights[week * 2 + 1]; + col--; } - /* Both Saturday and Sunday are in the 6th column. */ - *day_x = week_view->col_offsets[5]; - *day_w = week_view->col_widths[5]; + /* Both Saturday and Sunday are in the same column. */ + *day_x = week_view->col_offsets[col]; + *day_w = week_view->col_widths[col]; } else { + /* If the weekend is compressed and the day is after + the weekend we have to move back a column. */ + if (week_view->compress_weekend) { + /* Calculate where the weekend column is. + Note that 5 is Saturday. */ + weekend_col = (5 + 7 - week_view->display_start_day) % 7; + if (col > weekend_col) + col--; + } + *day_y = week_view->row_offsets[week * 2]; *day_h = week_view->row_heights[week * 2] + week_view->row_heights[week * 2 + 1]; - *day_x = week_view->col_offsets[day_of_week]; - *day_w = week_view->col_widths[day_of_week]; + *day_x = week_view->col_offsets[col]; + *day_w = week_view->col_widths[col]; } } else { g_return_if_fail (day < 7); - /* The week view has Mon, Tue & Wed down the left column and - Thu, Fri & Sat/Sun down the right. */ - if (day < 3) { + /* Calculate which box to place the day in, from 0-5. + Note that in the week view the weekends are always + compressed and share a box. */ + box = day; + day_of_week = (week_view->display_start_day + day) % 7; + weekend_box = (5 + 7 - week_view->display_start_day) % 7; + if (box > weekend_box) + box--; + + if (box < 3) { *day_x = week_view->col_offsets[0]; *day_w = week_view->col_widths[0]; } else { @@ -1470,15 +1611,20 @@ e_week_view_get_day_position (EWeekView *week_view, *day_w = week_view->col_widths[1]; } - if (day < 5) { - row = (day % 3) * 2; + row = (box % 3) * 2; + if (day_of_week < 5) { *day_y = week_view->row_offsets[row]; *day_h = week_view->row_heights[row] + week_view->row_heights[row + 1]; + } else if (day_of_week == 5) { + /* Saturday. */ + *day_y = week_view->row_offsets[row]; + *day_h = week_view->row_heights[row]; + } else { - /* Saturday & Sunday. */ - *day_y = week_view->row_offsets[day - 1]; - *day_h = week_view->row_heights[day - 1]; + /* Sunday. */ + *day_y = week_view->row_offsets[row + 1]; + *day_h = week_view->row_heights[row + 1]; } } } @@ -1515,7 +1661,7 @@ e_week_view_get_span_position (EWeekView *week_view, if (span->row >= week_view->rows_per_cell) return FALSE; - end_day_of_week = (span->start_day + span->num_days - 1) % 7; + end_day_of_week = (week_view->display_start_day + span->start_day + span->num_days - 1) % 7; num_days = span->num_days; /* Check if the row will not be visible in compressed cells. */ if (span->row >= week_view->rows_per_compressed_cell) { @@ -1642,8 +1788,9 @@ e_week_view_on_button_release (GtkWidget *widget, gdk_pointer_ungrab (event->time); start = week_view->day_starts[week_view->selection_start_day]; end = week_view->day_starts[week_view->selection_end_day + 1]; - gnome_calendar_set_selected_time_range (week_view->calendar, - start, end); + + if (week_view->calendar) + gnome_calendar_set_selected_time_range (week_view->calendar, start, end); } return FALSE; @@ -1685,6 +1832,7 @@ e_week_view_convert_position_to_day (EWeekView *week_view, gint y) { gint col, row, grid_x = -1, grid_y = -1, week, day; + gint weekend_col, box, weekend_box; /* First we convert it to a grid position. */ for (col = 0; col <= week_view->columns; col++) { @@ -1708,19 +1856,23 @@ e_week_view_convert_position_to_day (EWeekView *week_view, /* Now convert the grid position to a week and day. */ if (week_view->multi_week_view) { week = grid_y / 2; - if (week_view->compress_weekend && grid_x == 5 - && grid_y % 2 == 1) - day = 6; - else - day = grid_x; + day = grid_x; + + if (week_view->compress_weekend) { + weekend_col = (5 + 7 - week_view->display_start_day) % 7; + if (grid_x > weekend_col + || (grid_x == weekend_col && grid_y % 2 == 1)) + day++; + } } else { week = 0; - if (grid_x == 0) - day = grid_y / 2; - else if (grid_y == 5) - day = 6; - else - day = grid_y / 2 + 3; + + box = grid_x * 3 + grid_y / 2; + weekend_box = (5 + 7 - week_view->display_start_day) % 7; + day = box; + if (box > weekend_box + ||( box == weekend_box && grid_y % 2 == 1)) + day++; } return week * 7 + day; @@ -1814,11 +1966,15 @@ e_week_view_reload_events (EWeekView *week_view) if (!(week_view->client && cal_client_is_loaded (week_view->client))) return; - if (week_view->calendar - && g_date_valid (&week_view->first_day_shown)) { + /* Only load events if the date range has been set. */ + if (g_date_valid (&week_view->first_day_shown)) { num_days = week_view->multi_week_view ? week_view->weeks_shown * 7 : 7; +#if 0 + g_print ("EWeekView (%s) generating instances\n", + week_view->multi_week_view ? "Month View" : "Week View"); +#endif cal_client_generate_instances (week_view->client, CALOBJ_TYPE_EVENT, week_view->day_starts[0], @@ -2157,7 +2313,7 @@ e_week_view_reshape_events (EWeekView *week_view) num_days = week_view->multi_week_view ? week_view->weeks_shown * 7 : 7; for (day = 0; day < num_days; day++) { - is_weekend = (day % 7 >= 5) ? TRUE : FALSE; + is_weekend = ((week_view->display_start_day + day) % 7 >= 5) ? TRUE : FALSE; if (!is_weekend || (week_view->multi_week_view && !week_view->compress_weekend)) max_rows = week_view->rows_per_cell; @@ -2385,8 +2541,7 @@ e_week_view_reshape_event_span (EWeekView *week_view, "clip_width", (gdouble) text_w, "clip_height", (gdouble) text_h, NULL); - e_canvas_item_move_absolute(span->text_item, - text_x, text_y); + e_canvas_item_move_absolute (span->text_item, text_x, text_y); } @@ -2424,26 +2579,36 @@ e_week_view_find_day (EWeekView *week_view, } -/* This returns the last day in the same span as the given day. A span is all - the days which are displayed next to each other from left to right. - In the week view all spans are only 1 day, since Tuesday is below Monday - rather than beside it etc. In the month view, if the weekends are not - compressed then each week is a span, otherwise Monday to Saturday of each - week is a span, and the Sundays are separate spans. */ +/* This returns the last possible day in the same span as the given day. + A span is all the days which are displayed next to each other from left to + right. In the week view all spans are only 1 day, since Tuesday is below + Monday rather than beside it etc. In the month view, if the weekends are not + compressed then each week is a span, otherwise we have to break a span up + on Saturday, use a separate span for Sunday, and start again on Monday. */ static gint e_week_view_find_span_end (EWeekView *week_view, gint day) { - gint week, day_of_week, end_day; + gint week, col, sat_col, end_col; if (week_view->multi_week_view) { week = day / 7; - day_of_week = day % 7; - if (week_view->compress_weekend && day_of_week <= 5) - end_day = 5; - else - end_day = 6; - return week * 7 + end_day; + col = day % 7; + + /* We default to the last column in the row. */ + end_col = 6; + + /* If the weekend is compressed we must end any spans on + Saturday and Sunday. */ + if (week_view->compress_weekend) { + sat_col = (5 + 7 - week_view->display_start_day) % 7; + if (col <= sat_col) + end_col = sat_col; + else if (col == sat_col + 1) + end_col = sat_col + 1; + } + + return week * 7 + end_col; } else { return day; } @@ -2492,8 +2657,8 @@ e_week_view_on_adjustment_changed (GtkAdjustment *adjustment, if (week_view->selection_start_day != -1) { start = week_view->day_starts[week_view->selection_start_day]; end = week_view->day_starts[week_view->selection_end_day + 1]; - gnome_calendar_set_selected_time_range (week_view->calendar, - start, end); + if (week_view->calendar) + gnome_calendar_set_selected_time_range (week_view->calendar, start, end); } gtk_widget_queue_draw (week_view->main_canvas); @@ -2618,7 +2783,7 @@ e_week_view_on_text_item_event (GnomeCanvasItem *item, g_warning ("No GdkEvent"); /* FIXME: Remember the day offset from the start of - the event. */ + the event, for DnD. */ return TRUE; } @@ -3014,7 +3179,11 @@ e_week_view_on_new_appointment (GtkWidget *widget, gpointer data) cal_component_commit_sequence (comp); - gnome_calendar_edit_object (week_view->calendar, comp); + if (week_view->calendar) + gnome_calendar_edit_object (week_view->calendar, comp); + else + g_warning ("Calendar not set"); + gtk_object_unref (GTK_OBJECT (comp)); } @@ -3033,7 +3202,10 @@ e_week_view_on_edit_appointment (GtkWidget *widget, gpointer data) event = &g_array_index (week_view->events, EWeekViewEvent, week_view->popup_event_num); - gnome_calendar_edit_object (week_view->calendar, event->comp); + if (week_view->calendar) + gnome_calendar_edit_object (week_view->calendar, event->comp); + else + g_warning ("Calendar not set"); } @@ -3154,9 +3326,12 @@ e_week_view_on_jump_button_event (GnomeCanvasItem *item, if (event->type == GDK_BUTTON_PRESS) { for (day = 0; day < E_WEEK_VIEW_MAX_WEEKS * 7; day++) { if (item == week_view->jump_buttons[day]) { - gnome_calendar_dayjump - (week_view->calendar, - week_view->day_starts[day]); + if (week_view->calendar) + gnome_calendar_dayjump + (week_view->calendar, + week_view->day_starts[day]); + else + g_warning ("Calendar not set"); return TRUE; } } diff --git a/calendar/gui/e-week-view.h b/calendar/gui/e-week-view.h index e4d5ee72db..ccd11bf84a 100644 --- a/calendar/gui/e-week-view.h +++ b/calendar/gui/e-week-view.h @@ -207,6 +207,17 @@ struct _EWeekView they are always compressed into 1 cell in the week view. */ gboolean compress_weekend; + /* Whether we use show event end times. */ + gboolean show_event_end_times; + + /* The first day of the week, 0 (Monday) to 6 (Sunday). */ + gint week_start_day; + + /* The first day of the week we display, 0 (Monday) to 6 (Sunday). + This will usually be week_start_day, but if the weekend is + compressed, and week_start_day is Sunday we have to use Saturday. */ + gint display_start_day; + /* The vertical offset of the events from the top of the cells. */ gint events_y_offset; @@ -356,6 +367,18 @@ gboolean e_week_view_get_compress_weekend (EWeekView *week_view); void e_week_view_set_compress_weekend (EWeekView *week_view, gboolean compress); +/* Whether we display event end times. */ +gboolean e_week_view_get_show_event_end_times (EWeekView *week_view); +void e_week_view_set_show_event_end_times (EWeekView *week_view, + gboolean show); + +/* The first day of the week, 0 (Monday) to 6 (Sunday). */ +gint e_week_view_get_week_start_day (EWeekView *week_view); +void e_week_view_set_week_start_day (EWeekView *week_view, + gint week_start_day); + + + /* * Internal functions called by the associated canvas items. */ diff --git a/calendar/gui/event-editor.c b/calendar/gui/event-editor.c index 707614e899..6e481c3103 100644 --- a/calendar/gui/event-editor.c +++ b/calendar/gui/event-editor.c @@ -1,3 +1,5 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ + /* Evolution calendar - Event editor dialog * * Copyright (C) 2000 Helix Code, Inc. @@ -31,6 +33,7 @@ #include "calendar-config.h" #include "event-editor.h" #include "e-meeting-edit.h" +#include "calendar-config.h" #include "tag-calendar.h" #include "weekday-picker.h" @@ -1434,7 +1437,6 @@ fill_recurrence_widgets (EventEditor *ee) cal_component_get_rrule_list (priv->comp, &rrule_list); len = g_slist_length (rrule_list); - if (len > 1 || cal_component_has_rdates (priv->comp) || cal_component_has_exrules (priv->comp)) @@ -2099,24 +2101,35 @@ dialog_to_comp_object (EventEditor *ee, CalComponent *comp) cal_component_set_description_list (comp, &l); } + /* FIXME: Do we need to free str?? */ /* Dates */ date.value = g_new (struct icaltimetype, 1); - t = e_date_edit_get_time (E_DATE_EDIT (priv->start_time)); - *date.value = icaltime_from_timet (t, FALSE, FALSE); date.tzid = NULL; - cal_component_set_dtstart (comp, &date); + + t = e_date_edit_get_time (E_DATE_EDIT (priv->start_time)); + if (t != -1) { + *date.value = icaltime_from_timet (t, FALSE, FALSE); + cal_component_set_dtstart (comp, &date); + } else { + /* FIXME: What do we do here? */ + } /* If the all_day toggle is set, the end date is inclusive of the entire day on which it points to. */ all_day_event = e_dialog_toggle_get (priv->all_day_event); t = e_date_edit_get_time (E_DATE_EDIT (priv->end_time)); - if (all_day_event) - t = time_day_end (t); + if (t != -1) { + if (all_day_event) + t = time_day_end (t); + + *date.value = icaltime_from_timet (t, FALSE, FALSE); + cal_component_set_dtend (comp, &date); + } else { + /* FIXME: What do we do here? */ + } - *date.value = icaltime_from_timet (t, FALSE, FALSE); - cal_component_set_dtend (comp, &date); g_free (date.value); #if 0 @@ -2676,8 +2689,20 @@ check_all_day (EventEditor *ee) priv = ee->priv; + /* Currently we just return if the date is not set or not valid. + I'm not entirely sure this is the corrent thing to do. */ ev_start = e_date_edit_get_time (E_DATE_EDIT (priv->start_time)); + g_return_if_fail (ev_start != -1); + ev_end = e_date_edit_get_time (E_DATE_EDIT (priv->end_time)); + g_return_if_fail (ev_end != -1); + +#if 0 + /* all day event checkbox */ + if (time_day_begin (ev_start) == ev_start + && time_day_begin (ev_end) == ev_end) + e_dialog_toggle_set (priv->all_day_event, TRUE); +#endif start_begin_day = time_day_begin (ev_start); end_begin_day = time_day_begin (ev_end); @@ -2685,6 +2710,8 @@ check_all_day (EventEditor *ee) tm_start = *localtime (&start_begin_day); tm_end = *localtime (&end_begin_day); + /* FIXME: This will only set all_day to TRUE if the event lasts 1 day. + But we also want it TRUE for multiple-day events. */ tm_end.tm_mday--; if (mktime (&tm_start) == mktime (&tm_end)) all_day = TRUE; @@ -2711,11 +2738,25 @@ set_all_day (GtkWidget *toggle, EventEditor *ee) priv = ee->priv; - /* If the all_day toggle is set, the end date is inclusive of the - entire day on which it points to. */ + /* When the all_day toggle is on, the start date is rounded down to + the start of the day, and end date is rounded down to the start of + the day on which the event ends. The event is then taken to be + inclusive of the days between the start and end days. + Note that if the event end is at midnight, we do not round it down + to the previous day, since if we do that and the user repeatedly + turns the all_day toggle on and off, the event keeps shrinking. + (We'd also need to make sure we didn't adjust the time when the + radio button is initially set.) + + When the all_day_toggle is off, we set the event start to the start + of the working day, and if the event end is on or before the day + of the event start we set it to one hour after the event start. */ all_day = GTK_TOGGLE_BUTTON (toggle)->active; + /* Start time. */ start_t = e_date_edit_get_time (E_DATE_EDIT (priv->start_time)); + g_return_if_fail (start_t != -1); + start_tm = *localtime (&start_t); start_tm.tm_min = 0; start_tm.tm_sec = 0; @@ -2728,25 +2769,37 @@ set_all_day (GtkWidget *toggle, EventEditor *ee) /* will set recur start too */ e_date_edit_set_time (E_DATE_EDIT (priv->start_time), mktime (&start_tm)); + /* End time. */ end_t = e_date_edit_get_time (E_DATE_EDIT (priv->end_time)); + g_return_if_fail (end_t != -1); + end_tm = *localtime (&end_t); end_tm.tm_min = 0; end_tm.tm_sec = 0; if (all_day) { - /* mktime() will fix this if we go past the end of the month.*/ end_tm.tm_hour = 0; } else { - if (end_tm.tm_year == start_tm.tm_year - && end_tm.tm_mon == start_tm.tm_mon - && end_tm.tm_mday == start_tm.tm_mday - && end_tm.tm_hour <= start_tm.tm_hour) + /* If the event end is now before the event start, make it + end one hour after the start. mktime() will fix any + overflows. */ + if (end_tm.tm_year < start_tm.tm_year + || (end_tm.tm_year == start_tm.tm_year + && end_tm.tm_mon < start_tm.tm_mon) + || (end_tm.tm_year == start_tm.tm_year + && end_tm.tm_mon == start_tm.tm_mon + && end_tm.tm_mday <= start_tm.tm_mday)) { + end_tm.tm_year = start_tm.tm_year; + end_tm.tm_mon = start_tm.tm_mon; + end_tm.tm_mday = start_tm.tm_mday; end_tm.tm_hour = start_tm.tm_hour + 1; + } } + e_date_edit_set_time (E_DATE_EDIT (priv->end_time), mktime (&end_tm)); + e_date_edit_set_show_time (E_DATE_EDIT (priv->start_time), !all_day); e_date_edit_set_show_time (E_DATE_EDIT (priv->end_time), !all_day); - e_date_edit_set_time (E_DATE_EDIT (priv->end_time), mktime (&end_tm)); } /* Callback used when the start or end date widgets change. We check that the @@ -2766,7 +2819,9 @@ date_changed_cb (EDateEdit *dedit, gpointer data) /* Ensure that start < end */ start = e_date_edit_get_time (E_DATE_EDIT (priv->start_time)); + g_return_if_fail (start != -1); end = e_date_edit_get_time (E_DATE_EDIT (priv->end_time)); + g_return_if_fail (end != -1); if (start > end) { tm_start = *localtime (&start); @@ -2943,7 +2998,7 @@ date_edit_new (time_t the_time, int show_time) dedit = e_date_edit_new (); /* FIXME: Set other options. */ e_date_edit_set_show_time (E_DATE_EDIT (dedit), show_time); - e_date_edit_set_time_popup_range (E_DATE_EDIT (dedit), 8, 18); + e_date_edit_set_time_popup_range (E_DATE_EDIT (dedit), calendar_config_get_day_start_hour (), calendar_config_get_day_end_hour ()); return dedit; } diff --git a/calendar/gui/gnome-cal.c b/calendar/gui/gnome-cal.c index f29a27800c..802f76341c 100644 --- a/calendar/gui/gnome-cal.c +++ b/calendar/gui/gnome-cal.c @@ -310,10 +310,10 @@ gnome_calendar_init (GnomeCalendar *gcal) priv->current_view_type = VIEW_NOT_SET; priv->range_selected = FALSE; + setup_widgets (gcal); + priv->selection_start_time = time_day_begin (time (NULL)); priv->selection_end_time = time_add_day (priv->selection_start_time, 1); - - setup_widgets (gcal); } /* Used from g_hash_table_foreach(); frees an object alarms entry */ @@ -1582,19 +1582,21 @@ gnome_calendar_update_config_settings (GnomeCalendar *gcal, /* Note that this is 0 (Sun) to 6 (Sat). */ week_start_day = calendar_config_get_week_start_day (); - /* FIXME: Add support for these. */ -#if 0 + + /* Convert it to 0 (Mon) to 6 (Sun), which is what we use. */ + week_start_day = (week_start_day + 6) % 7; + + g_print ("Setting week start day to %i (0=Sun)\n", week_start_day); e_day_view_set_week_start_day (E_DAY_VIEW (priv->day_view), - week_start_day); + week_start_day); e_day_view_set_week_start_day (E_DAY_VIEW (priv->work_week_view), - week_start_day); + week_start_day); e_week_view_set_week_start_day (E_WEEK_VIEW (priv->week_view), week_start_day); e_week_view_set_week_start_day (E_WEEK_VIEW (priv->month_view), week_start_day); -#endif gnome_canvas_item_set (GNOME_CANVAS_ITEM (E_CALENDAR (priv->date_navigator)->calitem), - "week_start_day", (week_start_day + 6) % 7, + "week_start_day", week_start_day, NULL); start_hour = calendar_config_get_day_start_hour (); @@ -1628,17 +1630,14 @@ gnome_calendar_update_config_settings (GnomeCalendar *gcal, time_divisions); show_event_end = calendar_config_get_show_event_end (); - /* FIXME: Add support for these. */ -#if 0 - e_day_view_set_show_event_end (E_DAY_VIEW (priv->day_view), - show_event_end); - e_day_view_set_show_event_end (E_DAY_VIEW (priv->work_week_view), - show_event_end); - e_week_view_set_show_event_end (E_WEEK_VIEW (priv->week_view), - show_event_end); - e_week_view_set_show_event_end (E_WEEK_VIEW (priv->month_view), - show_event_end); -#endif + e_day_view_set_show_event_end_times (E_DAY_VIEW (priv->day_view), + show_event_end); + e_day_view_set_show_event_end_times (E_DAY_VIEW (priv->work_week_view), + show_event_end); + e_week_view_set_show_event_end_times (E_WEEK_VIEW (priv->week_view), + show_event_end); + e_week_view_set_show_event_end_times (E_WEEK_VIEW (priv->month_view), + show_event_end); compress_weekend = calendar_config_get_compress_weekend (); e_week_view_set_compress_weekend (E_WEEK_VIEW (priv->month_view), @@ -1657,6 +1656,10 @@ gnome_calendar_update_config_settings (GnomeCalendar *gcal, } else { gnome_calendar_update_paned_quanta (gcal); } + + /* The range of days shown may have changed, so we update the date + navigator if needed. */ + gnome_calendar_update_date_navigator (gcal); } diff --git a/calendar/gui/tag-calendar.c b/calendar/gui/tag-calendar.c index be77090f71..658bedc661 100644 --- a/calendar/gui/tag-calendar.c +++ b/calendar/gui/tag-calendar.c @@ -60,7 +60,7 @@ prepare_tag (ECalendar *ecal, struct calendar_tag_closure *c) end_tm.tm_year = end_year - 1900; end_tm.tm_mon = end_month; - end_tm.tm_mday = end_day; + end_tm.tm_mday = end_day + 1; end_tm.tm_hour = 0; end_tm.tm_min = 0; end_tm.tm_sec = 0; @@ -125,6 +125,9 @@ tag_calendar_by_client (ECalendar *ecal, CalClient *client) if (!cal_client_is_loaded (client)) return; +#if 0 + g_print ("DateNavigator generating instances\n"); +#endif cal_client_generate_instances (client, CALOBJ_TYPE_EVENT, c.start_time, c.end_time, tag_calendar_cb, &c); @@ -153,5 +156,8 @@ tag_calendar_by_comp (ECalendar *ecal, CalComponent *comp) return; prepare_tag (ecal, &c); +#if 0 + g_print ("DateNavigator generating instances\n"); +#endif cal_recur_generate_instances (comp, c.start_time, c.end_time, tag_calendar_cb, &c); } |