From e1635ef07ac4dbbb2511a01ed32ef096399d11fb Mon Sep 17 00:00:00 2001 From: Damon Chaplin Date: Wed, 29 Nov 2000 00:19:44 +0000 Subject: finished 12-hour support and tried to tidy up & comment the drawing code 2000-11-28 Damon Chaplin * gui/e-day-view*.[hc]: * gui/e-week-view*.[hc]: finished 12-hour support and tried to tidy up & comment the drawing code in places. Also fixed a couple of bugs I spotted. All the options on the 'Calendar' page should now work. svn path=/trunk/; revision=6706 --- calendar/ChangeLog | 7 + calendar/gui/e-day-view-time-item.c | 309 +++++++++++++++++++++------------- calendar/gui/e-day-view-top-item.c | 119 ++++++++----- calendar/gui/e-day-view.c | 121 ++++++++----- calendar/gui/e-day-view.h | 14 +- calendar/gui/e-week-view-event-item.c | 260 ++++++++++++++++------------ calendar/gui/e-week-view.c | 189 +++++++++++++++++---- calendar/gui/e-week-view.h | 47 +++++- calendar/gui/gnome-cal.c | 11 +- 9 files changed, 719 insertions(+), 358 deletions(-) diff --git a/calendar/ChangeLog b/calendar/ChangeLog index 325977b6e0..45c4423f70 100644 --- a/calendar/ChangeLog +++ b/calendar/ChangeLog @@ -1,3 +1,10 @@ +2000-11-28 Damon Chaplin + + * gui/e-day-view*.[hc]: + * gui/e-week-view*.[hc]: finished 12-hour support and tried to tidy + up & comment the drawing code in places. Also fixed a couple of bugs I + spotted. All the options on the 'Calendar' page should now work. + 2000-11-28 Jesse Pavel *gui/e-meeting-edit.c: removed some debugging code that I had, diff --git a/calendar/gui/e-day-view-time-item.c b/calendar/gui/e-day-view-time-item.c index e018daa472..18dad8f663 100644 --- a/calendar/gui/e-day-view-time-item.c +++ b/calendar/gui/e-day-view-time-item.c @@ -41,13 +41,18 @@ MIN_X_PAD is the spacing either side of the minute number. The smaller horizontal grid lines match with this. 60_MIN_X_PAD is the space either side of the HH:MM display used when - we are displaying 60 mins per row (inside the main grid lines). */ -#define E_DVTMI_TIME_GRID_X_PAD 4 -#define E_DVTMI_HOUR_L_PAD 4 -#define E_DVTMI_HOUR_R_PAD 2 -#define E_DVTMI_MIN_X_PAD 2 -#define E_DVTMI_60_MIN_X_PAD 4 - + we are displaying 60 mins per row (inside the main grid lines). + LARGE_HOUR_Y_PAD is the offset of the large hour string from the top of the + row. + SMALL_FONT_Y_PAD is the offset of the small time/minute string from the top + of the row. */ +#define E_DVTMI_TIME_GRID_X_PAD 4 +#define E_DVTMI_HOUR_L_PAD 4 +#define E_DVTMI_HOUR_R_PAD 2 +#define E_DVTMI_MIN_X_PAD 2 +#define E_DVTMI_60_MIN_X_PAD 4 +#define E_DVTMI_LARGE_HOUR_Y_PAD 1 +#define E_DVTMI_SMALL_FONT_Y_PAD 1 static void e_day_view_time_item_class_init (EDayViewTimeItemClass *class); static void e_day_view_time_item_init (EDayViewTimeItem *dvtmitem); @@ -68,6 +73,9 @@ static double e_day_view_time_item_point (GnomeCanvasItem *item, GnomeCanvasItem **actual_item); static gint e_day_view_time_item_event (GnomeCanvasItem *item, GdkEvent *event); +static void e_day_view_time_item_increment_time (gint *hour, + gint *minute, + gint mins_per_row); static void e_day_view_time_item_show_popup_menu (EDayViewTimeItem *dvtmitem, GdkEvent *event); static void e_day_view_time_item_on_set_divisions (GtkWidget *item, @@ -189,26 +197,49 @@ gint e_day_view_time_item_get_column_width (EDayViewTimeItem *dvtmitem) { EDayView *day_view; + GtkStyle *style; + GdkFont *small_font, *large_font; + gint digit, large_digit_width, max_large_digit_width; + gint max_suffix_width, max_minute_or_suffix_width; gint column_width_default, column_width_60_min_rows; day_view = dvtmitem->day_view; g_return_val_if_fail (day_view != NULL, 0); + style = GTK_WIDGET (day_view)->style; + g_return_val_if_fail (style != NULL, 0); + small_font = style->font; + g_return_val_if_fail (small_font != NULL, 0); + large_font = day_view->large_font; + g_return_val_if_fail (large_font != NULL, 0); + + for (digit = '0'; digit <= '9'; digit++) { + large_digit_width = gdk_char_width (large_font, digit); + max_large_digit_width = MAX (max_large_digit_width, + large_digit_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; + max_suffix_width = MAX (day_view->am_string_width, + day_view->pm_string_width); + + max_minute_or_suffix_width = MAX (max_suffix_width, + day_view->max_minute_width); + + column_width_default = max_large_digit_width * 2 + + max_minute_or_suffix_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; + + day_view->colon_width + + max_minute_or_suffix_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); @@ -231,13 +262,16 @@ 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, 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[64], *suffix; + gint hour, display_hour, minute, row; + gint row_y, start_y, large_hour_y_offset, small_font_y_offset; + gint long_line_x1, long_line_x2, short_line_x1; + gint large_hour_x2, minute_x2; + gint hour_width, minute_width, suffix_width; + gint max_suffix_width, max_minute_or_suffix_width; dvtmitem = E_DAY_VIEW_TIME_ITEM (canvas_item); day_view = dvtmitem->day_view; @@ -249,119 +283,163 @@ e_day_view_time_item_draw (GnomeCanvasItem *canvas_item, fg_gc = style->fg_gc[GTK_STATE_NORMAL]; dark_gc = style->dark_gc[GTK_STATE_NORMAL]; - time_min_x1 = 0; - hour_r = 0; + /* The start and end of the long horizontal line between hours. */ + long_line_x1 = E_DVTMI_TIME_GRID_X_PAD - x; + long_line_x2 = dvtmitem->column_width - E_DVTMI_TIME_GRID_X_PAD - x; - /* Step through each row, drawing the horizontal grid lines for each - day column and the times. */ - time_hour_x1 = E_DVTMI_TIME_GRID_X_PAD - x; - time_hour_x2 = dvtmitem->column_width - E_DVTMI_TIME_GRID_X_PAD - x; if (day_view->mins_per_row == 60) { - min_r = time_hour_x2 - E_DVTMI_60_MIN_X_PAD; + /* The right edge of the complete time string in 60-min + divisions, e.g. "14:00" or "2 pm". */ + minute_x2 = long_line_x2 - E_DVTMI_60_MIN_X_PAD; + + /* These aren't used for 60-minute divisions, but we initialize + them to keep gcc happy. */ + short_line_x1 = 0; + large_hour_x2 = 0; } else { - time_min_x1 = time_hour_x2 - E_DVTMI_MIN_X_PAD * 2 - - day_view->max_minute_width; - hour_r = time_min_x1 - E_DVTMI_HOUR_R_PAD; - min_r = time_hour_x2 - E_DVTMI_MIN_X_PAD; + max_suffix_width = MAX (day_view->am_string_width, + day_view->pm_string_width); + + max_minute_or_suffix_width = MAX (max_suffix_width, + day_view->max_minute_width); + + /* The start of the short horizontal line between the periods + within each hour. */ + short_line_x1 = long_line_x2 - E_DVTMI_MIN_X_PAD * 2 + - max_minute_or_suffix_width; + + /* The right edge of the large hour string. */ + large_hour_x2 = short_line_x1 - E_DVTMI_HOUR_R_PAD; + + /* The right edge of the minute part of the time. */ + minute_x2 = long_line_x2 - E_DVTMI_MIN_X_PAD; } + /* Start with the first hour & minute shown in the EDayView. */ hour = day_view->first_hour_shown; - hour_y = large_font->ascent + 2; /* FIXME */ minute = day_view->first_minute_shown; - min_y = small_font->ascent + 2; /* FIXME */ - start_y = 0 - MAX (day_view->row_height, hour_y + large_font->descent); + + /* The offset of the large hour string from the top of the row. */ + large_hour_y_offset = large_font->ascent + E_DVTMI_LARGE_HOUR_Y_PAD; + + /* The offset of the small time/minute string from top of row. */ + small_font_y_offset = small_font->ascent + E_DVTMI_SMALL_FONT_Y_PAD; + + /* Calculate the minimum y position of the first row we need to draw. + This is normally one row height above the 0 position, but if we + are using the large font we may have to go back a bit further. */ + start_y = 0 - MAX (day_view->row_height, + large_hour_y_offset + large_font->descent); + + /* Step through each row, drawing the times and the horizontal lines + between them. */ for (row = 0, row_y = 0 - y; row < day_view->rows && row_y < height; row++, row_y += day_view->row_height) { - if (row_y > start_y) { - /* Draw the times down the left if needed. */ - 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 the row is above the first row we want to draw just + increment the time and skip to the next row. */ + if (row_y < start_y) { + e_day_view_time_item_increment_time (&hour, &minute, + day_view->mins_per_row); + continue; + } - if (day_view->mins_per_row == 60) { + /* Calculate the actual hour number to display. For 12-hour + format we convert 0-23 to 12-11am/12-11pm. */ + e_day_view_convert_time_to_display (day_view, hour, + &display_hour, + &suffix, &suffix_width); + + if (day_view->mins_per_row == 60) { + /* 60 minute intervals - draw a long horizontal line + between hours and display as one long string, + e.g. "14:00" or "2 pm". */ + gdk_draw_line (drawable, dark_gc, + long_line_x1, row_y, + long_line_x2, row_y); + + if (day_view->use_24_hour_format) { + g_snprintf (buffer, sizeof (buffer), "%i:%02i", + display_hour, minute); + } else { + g_snprintf (buffer, sizeof (buffer), "%i %s", + display_hour, suffix); + } + minute_width = gdk_string_width (small_font, buffer); + gdk_draw_string (drawable, small_font, fg_gc, + minute_x2 - minute_width, + row_y + small_font_y_offset, + buffer); + } else { + /* 5/10/15/30 minute intervals. */ + + if (minute == 0) { + /* On the hour - draw a long horizontal line + before the hour and display the hour in the + large font. */ gdk_draw_line (drawable, dark_gc, - time_hour_x1, row_y, - time_hour_x2, row_y); - - 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); + long_line_x1, row_y, + long_line_x2, row_y); + + g_snprintf (buffer, sizeof (buffer), "%i", + display_hour); + hour_width = gdk_string_width (large_font, + buffer); + gdk_draw_string (drawable, large_font, fg_gc, + large_hour_x2 - hour_width, + row_y + large_hour_y_offset, + buffer); } else { - if (minute == 0) { - gdk_draw_line (drawable, dark_gc, - time_hour_x1, row_y, - time_hour_x2, row_y); - 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, - row_y + hour_y, - buffer); - } else { - gdk_draw_line (drawable, dark_gc, - time_min_x1, row_y, - time_hour_x2, row_y); - } + /* Within the hour - draw a short line before + the time. */ + gdk_draw_line (drawable, dark_gc, + short_line_x1, row_y, + long_line_x2, row_y); + } - if (day_view->mins_per_row != 30 - || minute != 30) { - 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, - row_y + min_y, - buffer); + /* Normally we display the minute in each + interval, but when using 30-minute intervals + we don't display the '30'. */ + if (day_view->mins_per_row != 30 || minute != 30) { + /* In 12-hour format we display 'am' or 'pm' + instead of '00'. */ + if (minute == 0 + && !day_view->use_24_hour_format) { + strcpy (buffer, suffix); + } else { + g_snprintf (buffer, sizeof (buffer), + "%02i", minute); } + minute_width = gdk_string_width (small_font, + buffer); + gdk_draw_string (drawable, small_font, fg_gc, + minute_x2 - minute_width, + row_y + small_font_y_offset, + buffer); } } - /* 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) { - minute -= 60; - /* Currently we never wrap around to the next day, but - we may do if we display extra timezones. */ - hour = (hour + 1) % 24; - } + e_day_view_time_item_increment_time (&hour, &minute, + day_view->mins_per_row); + } +} + + +/* Increment the time by the 5/10/15/30/60 minute interval. + Note that mins_per_row is never > 60, so we never have to + worry about adding more than 60 minutes. */ +static void +e_day_view_time_item_increment_time (gint *hour, + gint *minute, + gint mins_per_row) +{ + *minute += mins_per_row; + if (*minute >= 60) { + *minute -= 60; + /* Currently we never wrap around to the next day, but + we may do if we display extra timezones. */ + *hour = (*hour + 1) % 24; } } @@ -434,7 +512,8 @@ e_day_view_time_item_show_popup_menu (EDayViewTimeItem *dvtmitem, e_auto_kill_popup_menu_on_hide (GTK_MENU (menu)); for (i = 0; i < num_divisions; i++) { - sprintf (buffer, _("%02i minute divisions"), divisions[i]); + g_snprintf (buffer, sizeof (buffer), + _("%02i minute divisions"), divisions[i]); item = gtk_radio_menu_item_new_with_label (group, buffer); group = gtk_radio_menu_item_group (GTK_RADIO_MENU_ITEM (item)); gtk_widget_show (item); diff --git a/calendar/gui/e-day-view-top-item.c b/calendar/gui/e-day-view-top-item.c index 8a85983592..a9ece2cc50 100644 --- a/calendar/gui/e-day-view-top-item.c +++ b/calendar/gui/e-day-view-top-item.c @@ -340,7 +340,9 @@ e_day_view_top_item_draw_long_event (EDayViewTopItem *dvtitem, gint text_x, icon_x, icon_y, icon_x_inc; CalComponent *comp; gchar buffer[16]; - gint hour, minute, offset, time_width, time_x, min_end_time_x; + gint hour, display_hour, minute, offset, time_width, time_x; + gint min_end_time_x, suffix_width, max_icon_x; + gchar *suffix; gboolean draw_start_triangle, draw_end_triangle; GdkRectangle clip_rect; @@ -435,45 +437,28 @@ e_day_view_top_item_draw_long_event (EDayViewTopItem *dvtitem, to take the scroll offset into account. It will always be 0. */ text_x = event->canvas_item->x1; - /* Draw the icons. */ - icon_x_inc = E_DAY_VIEW_ICON_WIDTH + E_DAY_VIEW_ICON_X_PAD; - icon_x = text_x - icon_x_inc - x; - icon_y = item_y + 1 + E_DAY_VIEW_ICON_Y_PAD - y; - - if (cal_component_has_recurrences (comp)) { - gdk_gc_set_clip_origin (gc, icon_x, icon_y); - gdk_gc_set_clip_mask (gc, day_view->recurrence_mask); - gdk_draw_pixmap (drawable, gc, - day_view->recurrence_icon, - 0, 0, icon_x, icon_y, - E_DAY_VIEW_ICON_WIDTH, - E_DAY_VIEW_ICON_HEIGHT); - icon_x -= icon_x_inc; - } - - if (cal_component_has_alarms (comp)) { - gdk_gc_set_clip_origin (gc, icon_x, icon_y); - gdk_gc_set_clip_mask (gc, day_view->reminder_mask); - gdk_draw_pixmap (drawable, gc, - day_view->reminder_icon, - 0, 0, icon_x, icon_y, - E_DAY_VIEW_ICON_WIDTH, - E_DAY_VIEW_ICON_HEIGHT); - icon_x -= icon_x_inc; - } - gdk_gc_set_clip_mask (gc, NULL); - - /* Draw the start & end times, if necessary. - Note that GtkLabel adds 1 to the ascent so we must do that to be - level with it. */ + /* Draw the start & end times, if necessary. */ min_end_time_x = item_x + E_DAY_VIEW_LONG_EVENT_X_PAD - x; + time_width = e_day_view_get_time_string_width (day_view); + if (event->start > day_view->day_starts[start_day]) { offset = day_view->first_hour_shown * 60 + day_view->first_minute_shown + event->start_minute; hour = offset / 60; minute = offset % 60; - sprintf (buffer, "%02i:%02i", hour, minute); + /* Calculate the actual hour number to display. For 12-hour + format we convert 0-23 to 12-11am/12-11pm. */ + e_day_view_convert_time_to_display (day_view, hour, + &display_hour, + &suffix, &suffix_width); + if (day_view->use_24_hour_format) { + g_snprintf (buffer, sizeof (buffer), "%2i:%02i", + display_hour, minute); + } else { + g_snprintf (buffer, sizeof (buffer), "%2i:%02i%s", + display_hour, minute, suffix); + } clip_rect.x = item_x - x; clip_rect.y = item_y - y; @@ -481,36 +466,90 @@ e_day_view_top_item_draw_long_event (EDayViewTopItem *dvtitem, clip_rect.height = item_h; gdk_gc_set_clip_rectangle (fg_gc, &clip_rect); + time_x = item_x + E_DAY_VIEW_LONG_EVENT_X_PAD - x; + if (hour < 10) + time_x += day_view->digit_width; + gdk_draw_string (drawable, font, fg_gc, - item_x + E_DAY_VIEW_LONG_EVENT_X_PAD - x, - item_y + E_DAY_VIEW_LONG_EVENT_Y_PAD + font->ascent + 1 - y, + time_x, + item_y + E_DAY_VIEW_LONG_EVENT_BORDER_HEIGHT + + E_DAY_VIEW_LONG_EVENT_Y_PAD + + font->ascent - y, buffer); gdk_gc_set_clip_rectangle (fg_gc, NULL); - min_end_time_x += day_view->small_hour_widths[hour] + 2 - + day_view->max_minute_width + day_view->colon_width; + min_end_time_x += time_width + + E_DAY_VIEW_LONG_EVENT_TIME_X_PAD; } + max_icon_x = item_x + item_w - E_DAY_VIEW_LONG_EVENT_X_PAD + - E_DAY_VIEW_ICON_WIDTH; + if (event->end < day_view->day_starts[end_day + 1]) { offset = day_view->first_hour_shown * 60 + day_view->first_minute_shown + event->end_minute; hour = offset / 60; minute = offset % 60; - time_width = day_view->small_hour_widths[hour] - + day_view->max_minute_width + day_view->colon_width; time_x = item_x + item_w - E_DAY_VIEW_LONG_EVENT_X_PAD - time_width - E_DAY_VIEW_LONG_EVENT_TIME_X_PAD - x; if (time_x >= min_end_time_x) { - sprintf (buffer, "%02i:%02i", hour, minute); + /* Calculate the actual hour number to display. */ + e_day_view_convert_time_to_display (day_view, hour, + &display_hour, + &suffix, + &suffix_width); + if (day_view->use_24_hour_format) { + g_snprintf (buffer, sizeof (buffer), + "%2i:%02i", display_hour, minute); + } else { + g_snprintf (buffer, sizeof (buffer), + "%2i:%02i%s", display_hour, minute, + suffix); + } + + if (hour < 10) + time_x += day_view->digit_width; + gdk_draw_string (drawable, font, fg_gc, time_x, item_y + E_DAY_VIEW_LONG_EVENT_Y_PAD + font->ascent + 1 - y, buffer); + + max_icon_x -= time_width + E_DAY_VIEW_LONG_EVENT_TIME_X_PAD; } } + + /* Draw the icons. */ + icon_x_inc = E_DAY_VIEW_ICON_WIDTH + E_DAY_VIEW_ICON_X_PAD; + icon_x = text_x - icon_x_inc - x; + icon_y = item_y + E_DAY_VIEW_LONG_EVENT_BORDER_HEIGHT + + E_DAY_VIEW_ICON_Y_PAD - y; + + if (icon_x <= max_icon_x && cal_component_has_recurrences (comp)) { + gdk_gc_set_clip_origin (gc, icon_x, icon_y); + gdk_gc_set_clip_mask (gc, day_view->recurrence_mask); + gdk_draw_pixmap (drawable, gc, + day_view->recurrence_icon, + 0, 0, icon_x, icon_y, + E_DAY_VIEW_ICON_WIDTH, + E_DAY_VIEW_ICON_HEIGHT); + icon_x -= icon_x_inc; + } + + if (icon_x <= max_icon_x && cal_component_has_alarms (comp)) { + gdk_gc_set_clip_origin (gc, icon_x, icon_y); + gdk_gc_set_clip_mask (gc, day_view->reminder_mask); + gdk_draw_pixmap (drawable, gc, + day_view->reminder_icon, + 0, 0, icon_x, icon_y, + E_DAY_VIEW_ICON_WIDTH, + E_DAY_VIEW_ICON_HEIGHT); + icon_x -= icon_x_inc; + } + gdk_gc_set_clip_mask (gc, NULL); } diff --git a/calendar/gui/e-day-view.c b/calendar/gui/e-day-view.c index 9ea4dae4c4..06e829c39b 100644 --- a/calendar/gui/e-day-view.c +++ b/calendar/gui/e-day-view.c @@ -1066,22 +1066,22 @@ e_day_view_style_set (GtkWidget *widget, day_view->max_small_hour_width = 0; max_large_hour_width = 0; for (hour = 0; hour < 24; hour++) { - sprintf (buffer, "%02i", hour); + g_snprintf (buffer, sizeof (buffer), "%02i", hour); day_view->small_hour_widths[hour] = gdk_string_width (font, buffer); - day_view->large_hour_widths[hour] = gdk_string_width (day_view->large_font, buffer); day_view->max_small_hour_width = MAX (day_view->max_small_hour_width, day_view->small_hour_widths[hour]); - max_large_hour_width = MAX (max_large_hour_width, day_view->large_hour_widths[hour]); } - day_view->max_large_hour_width = max_large_hour_width; max_minute_width = 0; for (minute = 0, i = 0; minute < 60; minute += 5, i++) { - sprintf (buffer, "%02i", minute); - day_view->minute_widths[i] = gdk_string_width (font, buffer); - max_minute_width = MAX (max_minute_width, day_view->minute_widths[i]); + gint minute_width; + + g_snprintf (buffer, sizeof (buffer), "%02i", minute); + minute_width = gdk_string_width (font, buffer); + max_minute_width = MAX (max_minute_width, minute_width); } day_view->max_minute_width = max_minute_width; day_view->colon_width = gdk_string_width (font, ":"); + day_view->digit_width = gdk_string_width (font, "0"); day_view->am_string_width = gdk_string_width (font, day_view->am_string); @@ -1617,7 +1617,9 @@ e_day_view_update_event_label (EDayView *day_view, EDayViewEvent *event; char *text, *start_suffix, *end_suffix; gboolean free_text = FALSE, editing_event = FALSE; - gint offset, start_hour, start_minute, end_hour, end_minute; + gint offset; + gint start_hour, start_display_hour, start_minute, start_suffix_width; + gint end_hour, end_display_hour, end_minute, end_suffix_width; CalComponentText summary; event = &g_array_index (day_view->events[day], EDayViewEvent, @@ -1649,53 +1651,45 @@ e_day_view_update_event_label (EDayView *day_view, end_hour = end_minute / 60; end_minute = end_minute % 60; + e_day_view_convert_time_to_display (day_view, start_hour, + &start_display_hour, + &start_suffix, + &start_suffix_width); + e_day_view_convert_time_to_display (day_view, end_hour, + &end_display_hour, + &end_suffix, + &end_suffix_width); + 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, + start_display_hour, start_minute, + end_display_hour, end_minute, text); } else { /* 24 hour format without end time. */ text = g_strdup_printf ("%02i:%02i %s", - start_hour, start_minute, + start_display_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_display_hour, start_minute, start_suffix, - end_hour, end_minute, + end_display_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_display_hour, start_minute, start_suffix, text); } @@ -1929,8 +1923,6 @@ e_day_view_find_work_week_start (EDayView *day_view, /* 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), @@ -2163,8 +2155,6 @@ e_day_view_recalc_work_week_days_shown (EDayView *day_view) /* 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; @@ -2274,9 +2264,6 @@ e_day_view_set_show_times_cb (EDayView *day_view, 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); } @@ -2303,8 +2290,6 @@ e_day_view_set_week_start_day (EDayView *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; @@ -2324,12 +2309,12 @@ e_day_view_recalc_work_week (EDayView *day_view) if (!day_view->work_week_view) return; + e_day_view_recalc_work_week_days_shown (day_view); + /* 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. */ @@ -3243,8 +3228,10 @@ e_day_view_update_calendar_selection_time (EDayView *day_view) e_day_view_get_selected_time_range (day_view, &start, &end); +#if 0 g_print ("Start: %s", ctime (&start)); g_print ("End : %s", ctime (&end)); +#endif if (day_view->calendar) gnome_calendar_set_selected_time_range (day_view->calendar, @@ -4199,8 +4186,7 @@ e_day_view_reshape_long_event (EDayView *day_view, go off the right edge. */ icons_width = (E_DAY_VIEW_ICON_WIDTH + E_DAY_VIEW_ICON_X_PAD) * num_icons; - time_width = day_view->max_small_hour_width + day_view->colon_width - + day_view->max_minute_width; + time_width = e_day_view_get_time_string_width (day_view); if (use_max_width) { text_x = item_x; @@ -6404,3 +6390,50 @@ e_day_view_on_main_canvas_drag_data_received (GtkWidget *widget, gtk_drag_finish (context, FALSE, FALSE, time); } + + +/* Converts an hour from 0-23 to the preferred time format, and returns the + suffix to add and the width of it in the normal font. */ +void +e_day_view_convert_time_to_display (EDayView *day_view, + gint hour, + gint *display_hour, + gchar **suffix, + gint *suffix_width) +{ + /* Calculate the actual hour number to display. For 12-hour + format we convert 0-23 to 12-11am/12-11pm. */ + *display_hour = hour; + if (day_view->use_24_hour_format) { + *suffix = ""; + *suffix_width = 0; + } else { + if (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 uses 12:00 rather than 0:00. */ + if (*display_hour == 0) + *display_hour = 12; + } +} + + +gint +e_day_view_get_time_string_width (EDayView *day_view) +{ + gint time_width; + + time_width = day_view->digit_width * 4 + day_view->colon_width; + + if (!day_view->use_24_hour_format) + time_width += MAX (day_view->am_string_width, + day_view->pm_string_width); + + return time_width; +} diff --git a/calendar/gui/e-day-view.h b/calendar/gui/e-day-view.h index f0118187e4..a6ecc165d5 100644 --- a/calendar/gui/e-day-view.h +++ b/calendar/gui/e-day-view.h @@ -303,13 +303,11 @@ struct _EDayView guint8 cols_per_row[E_DAY_VIEW_MAX_DAYS][12 * 24]; /* Sizes of the various time strings. */ - gint large_hour_widths[24]; gint small_hour_widths[24]; - gint minute_widths[12]; /* intervals of 5 minutes. */ gint max_small_hour_width; - gint max_large_hour_width; gint max_minute_width; gint colon_width; + gint digit_width; /* Size of '0' character. */ /* This specifies how we are displaying the dates at the top. */ EDayViewDateFormat date_format; @@ -524,7 +522,7 @@ void e_day_view_set_working_day (EDayView *day_view, gint end_hour, gint end_minute); -/* Whether we use 12-hour of 24-hour format. */ +/* Whether we use 12-hour or 24-hour format. */ 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); @@ -582,6 +580,14 @@ void e_day_view_check_auto_scroll (EDayView *day_view, gint event_y); void e_day_view_stop_auto_scroll (EDayView *day_view); +void e_day_view_convert_time_to_display (EDayView *day_view, + gint hour, + gint *display_hour, + gchar **suffix, + gint *suffix_width); +gint e_day_view_get_time_string_width (EDayView *day_view); + + #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/calendar/gui/e-week-view-event-item.c b/calendar/gui/e-week-view-event-item.c index 074aebe486..d50172787b 100644 --- a/calendar/gui/e-week-view-event-item.c +++ b/calendar/gui/e-week-view-event-item.c @@ -48,6 +48,12 @@ static void e_week_view_event_item_draw (GnomeCanvasItem *item, int y, int width, int height); +static void e_week_view_draw_time (EWeekView *week_view, + GdkDrawable *drawable, + gint time_x, + gint time_y, + gint hour, + gint minute); static void e_week_view_event_item_draw_icons (EWeekViewEventItem *wveitem, GdkDrawable *drawable, gint icon_x, @@ -237,13 +243,12 @@ e_week_view_event_item_draw (GnomeCanvasItem *canvas_item, EWeekViewEventSpan *span; GtkStyle *style; GdkGC *fg_gc, *gc; - GdkFont *font; - gint x1, y1, x2, y2, time_x, time_y, time_y_small_min; - gint icon_x, icon_y, time_width, min_end_time_x; + gint x1, y1, x2, y2, time_x, time_y; + gint icon_x, icon_y, time_width, min_end_time_x, max_icon_x; gint rect_x, rect_w, rect_x2; gboolean one_day_event, editing_span = FALSE; - gint start_minute, end_minute; - gchar buffer[128]; + gint start_hour, start_minute, end_hour, end_minute; + gboolean draw_start, draw_end; gboolean draw_start_triangle = FALSE, draw_end_triangle = FALSE; GdkRectangle clip_rect; @@ -265,7 +270,6 @@ e_week_view_event_item_draw (GnomeCanvasItem *canvas_item, event->spans_index + wveitem->span_num); style = GTK_WIDGET (week_view)->style; - font = style->font; fg_gc = style->fg_gc[GTK_STATE_NORMAL]; gc = week_view->main_gc; @@ -277,84 +281,64 @@ e_week_view_event_item_draw (GnomeCanvasItem *canvas_item, if (x1 == x2 || y1 == y2) return; - icon_y = y1 + E_WEEK_VIEW_EVENT_BORDER_HEIGHT + E_WEEK_VIEW_ICON_Y_PAD; - start_minute = event->start_minute; - end_minute = event->end_minute; - time_y_small_min = 0; icon_x = 0; + icon_y = y1 + E_WEEK_VIEW_EVENT_BORDER_HEIGHT + E_WEEK_VIEW_ICON_Y_PAD; - time_y = y1 + E_WEEK_VIEW_EVENT_BORDER_HEIGHT - + E_WEEK_VIEW_EVENT_TEXT_Y_PAD + font->ascent; + /* Get the start & end times in 24-hour format. */ + start_hour = event->start_minute / 60; + start_minute = event->start_minute % 60; + end_hour = event->end_minute / 60; + end_minute = event->end_minute % 60; - if (week_view->small_font) - time_y_small_min = y1 + E_WEEK_VIEW_EVENT_BORDER_HEIGHT - + E_WEEK_VIEW_EVENT_TEXT_Y_PAD - + week_view->small_font->ascent; + time_y = y1 + E_WEEK_VIEW_EVENT_BORDER_HEIGHT + + E_WEEK_VIEW_EVENT_TEXT_Y_PAD; - if (week_view->use_small_font && week_view->small_font) - time_width = week_view->digit_width * 2 - + week_view->small_digit_width * 2; - else - time_width = week_view->digit_width * 4 - + week_view->colon_width; + time_width = e_week_view_get_time_string_width (week_view); one_day_event = e_week_view_is_one_day_event (week_view, wveitem->event_num); if (one_day_event) { time_x = x1 + E_WEEK_VIEW_EVENT_L_PAD; - /* Convert the time into a string. We use different parts of - the string for the different time formats. Notice that the - string is always 11 characters long. */ - sprintf (buffer, "%02i:%02i %02i:%02i", - start_minute / 60, start_minute % 60, - end_minute / 60, end_minute % 60); - /* Draw the start and end times, as required. */ switch (week_view->time_format) { case E_WEEK_VIEW_TIME_BOTH_SMALL_MIN: - gdk_draw_text (drawable, font, fg_gc, - time_x, time_y, buffer, 2); - gdk_draw_text (drawable, week_view->small_font, fg_gc, - time_x + week_view->digit_width * 2, - time_y_small_min, buffer + 3, 2); - gdk_draw_text (drawable, font, fg_gc, - time_x + week_view->digit_width * 4 - 2, - time_y, buffer + 6, 2); - gdk_draw_text (drawable, week_view->small_font, fg_gc, - time_x + week_view->digit_width * 6 - 2, - time_y_small_min, buffer + 9, 2); - - icon_x = x1 + time_width * 2 + week_view->space_width - + E_WEEK_VIEW_EVENT_TEXT_X_PAD; - break; - case E_WEEK_VIEW_TIME_START_SMALL_MIN: - gdk_draw_text (drawable, font, fg_gc, - time_x, time_y, buffer, 2); - gdk_draw_text (drawable, week_view->small_font, fg_gc, - time_x + week_view->digit_width * 2, - time_y_small_min, buffer + 3, 2); - - icon_x = x1 + time_width - + E_WEEK_VIEW_EVENT_TEXT_X_PAD; - break; case E_WEEK_VIEW_TIME_BOTH: - gdk_draw_text (drawable, font, fg_gc, - time_x, time_y, buffer, 11); - icon_x = x1 + time_width * 2 + week_view->space_width - + E_WEEK_VIEW_EVENT_TEXT_X_PAD; + draw_start = TRUE; + draw_end = TRUE; break; + + case E_WEEK_VIEW_TIME_START_SMALL_MIN: case E_WEEK_VIEW_TIME_START: - gdk_draw_text (drawable, font, fg_gc, - time_x, time_y, buffer, 5); - icon_x = x1 + time_width - + E_WEEK_VIEW_EVENT_TEXT_X_PAD; + draw_start = TRUE; + draw_end = FALSE; break; + case E_WEEK_VIEW_TIME_NONE: - icon_x = x1 + E_WEEK_VIEW_EVENT_L_PAD; + draw_start = FALSE; + draw_end = FALSE; break; } + if (draw_start) { + e_week_view_draw_time (week_view, drawable, + time_x, time_y, + start_hour, start_minute); + time_x += time_width; + } + + if (draw_end) { + time_x += E_WEEK_VIEW_EVENT_TIME_SPACING; + e_week_view_draw_time (week_view, drawable, + time_x, time_y, + end_hour, end_minute); + time_x += time_width; + } + + icon_x = time_x; + if (draw_start) + icon_x += E_WEEK_VIEW_EVENT_TIME_X_PAD; + /* Draw the icons. */ e_week_view_event_item_draw_icons (wveitem, drawable, icon_x, icon_y, @@ -365,7 +349,10 @@ e_week_view_event_item_draw (GnomeCanvasItem *canvas_item, rect_w = x2 - x1 - E_WEEK_VIEW_EVENT_L_PAD - E_WEEK_VIEW_EVENT_R_PAD + 1; - /* Draw the triangles at the start & end, if needed. */ + /* Draw the triangles at the start & end, if needed. + They also use the first few pixels at the edge of the + event so we update rect_x & rect_w so we don't draw over + them. */ if (event->start < week_view->day_starts[span->start_day]) { draw_start_triangle = TRUE; rect_x += 2; @@ -402,17 +389,21 @@ e_week_view_event_item_draw (GnomeCanvasItem *canvas_item, if (span->text_item && E_TEXT (span->text_item)->editing) editing_span = TRUE; - /* Draw the start & end times, if necessary. */ + /* Draw the start & end times, if they are not on day + boundaries. The start time would always be shown if it was + needed, though it may be clipped as the window shrinks. + The end time is only displayed if there is enough room. + We calculate the minimum position for the end time, which + depends on whether the start time is displayed. If the end + time doesn't fit, then we don't draw it. */ min_end_time_x = x1 + E_WEEK_VIEW_EVENT_L_PAD + E_WEEK_VIEW_EVENT_BORDER_WIDTH - + E_WEEK_VIEW_EVENT_TEXT_X_PAD; + + E_WEEK_VIEW_EVENT_EDGE_X_PAD; if (!editing_span && event->start > week_view->day_starts[span->start_day]) { - sprintf (buffer, "%02i:%02i", - start_minute / 60, start_minute % 60); time_x = x1 + E_WEEK_VIEW_EVENT_L_PAD + E_WEEK_VIEW_EVENT_BORDER_WIDTH - + E_WEEK_VIEW_EVENT_TEXT_X_PAD; + + E_WEEK_VIEW_EVENT_EDGE_X_PAD; clip_rect.x = x1; clip_rect.y = y1; @@ -421,52 +412,39 @@ e_week_view_event_item_draw (GnomeCanvasItem *canvas_item, clip_rect.height = y2 - y1 + 1; gdk_gc_set_clip_rectangle (fg_gc, &clip_rect); - if (week_view->use_small_font - && week_view->small_font) { - gdk_draw_text (drawable, font, fg_gc, - time_x, time_y, buffer, 2); - gdk_draw_text (drawable, week_view->small_font, - fg_gc, - time_x + week_view->digit_width * 2, - time_y_small_min, - buffer + 3, 2); - } else { - gdk_draw_text (drawable, font, fg_gc, - time_x, time_y, buffer, 5); - } + e_week_view_draw_time (week_view, drawable, + time_x, time_y, + start_hour, start_minute); gdk_gc_set_clip_rectangle (fg_gc, NULL); - min_end_time_x += time_width + 2; + /* We don't want the end time to be drawn over the + start time, so we increase the minimum position. */ + min_end_time_x += time_width + + E_WEEK_VIEW_EVENT_TIME_X_PAD; } + max_icon_x = x2 + 1 - E_WEEK_VIEW_EVENT_R_PAD + - E_WEEK_VIEW_EVENT_BORDER_WIDTH + - E_WEEK_VIEW_EVENT_EDGE_X_PAD; + if (!editing_span && event->end < week_view->day_starts[span->start_day + span->num_days]) { - sprintf (buffer, "%02i:%02i", - end_minute / 60, end_minute % 60); - time_x = x2 - E_WEEK_VIEW_EVENT_R_PAD + /* Calculate where the end time should be displayed. */ + time_x = x2 + 1 - E_WEEK_VIEW_EVENT_R_PAD - E_WEEK_VIEW_EVENT_BORDER_WIDTH - - E_WEEK_VIEW_EVENT_TEXT_X_PAD - 1 + - E_WEEK_VIEW_EVENT_EDGE_X_PAD - time_width; + /* Draw the end time, if the position is greater than + the minimum calculated above. */ if (time_x >= min_end_time_x) { - if (week_view->use_small_font - && week_view->small_font) { - gdk_draw_text (drawable, font, fg_gc, + e_week_view_draw_time (week_view, drawable, time_x, time_y, - buffer, 2); - gdk_draw_text (drawable, - week_view->small_font, - fg_gc, - time_x + week_view->digit_width * 2, - time_y_small_min, - buffer + 3, 2); - } else { - gdk_draw_text (drawable, font, fg_gc, - time_x, time_y, - buffer, 5); - } + end_hour, end_minute); + max_icon_x -= time_width + + E_WEEK_VIEW_EVENT_TIME_X_PAD; } } @@ -475,12 +453,82 @@ e_week_view_event_item_draw (GnomeCanvasItem *canvas_item, icon_x = span->text_item->x1 - x; e_week_view_event_item_draw_icons (wveitem, drawable, icon_x, icon_y, - x2, TRUE); + max_icon_x, TRUE); } } } +static void +e_week_view_draw_time (EWeekView *week_view, + GdkDrawable *drawable, + gint time_x, + gint time_y, + gint hour, + gint minute) +{ + GtkStyle *style; + GdkGC *fg_gc; + GdkFont *font, *small_font; + gint hour_to_display, suffix_width; + gint time_y_normal_font, time_y_small_font; + gchar buffer[128], *suffix; + + style = GTK_WIDGET (week_view)->style; + font = style->font; + small_font = week_view->small_font; + fg_gc = style->fg_gc[GTK_STATE_NORMAL]; + + time_y_normal_font = time_y_small_font = time_y + font->ascent; + if (small_font) + time_y_small_font = time_y + small_font->ascent; + + e_week_view_convert_time_to_display (week_view, hour, &hour_to_display, + &suffix, &suffix_width); + + if (week_view->use_small_font && week_view->small_font) { + g_snprintf (buffer, sizeof (buffer), "%2i:%02i", + hour_to_display, minute); + + /* Draw the hour. */ + if (hour_to_display < 10) + gdk_draw_text (drawable, font, fg_gc, + time_x + week_view->digit_width, + time_y_normal_font, buffer + 1, 1); + else + gdk_draw_text (drawable, font, fg_gc, + time_x, time_y_normal_font, buffer, 2); + + time_x += week_view->digit_width * 2; + + /* Draw the start minute, in the small font. */ + gdk_draw_text (drawable, week_view->small_font, fg_gc, + time_x, time_y_small_font, buffer + 3, 2); + + time_x += week_view->small_digit_width * 2; + + /* Draw the 'am'/'pm' suffix, if 12-hour format. */ + if (!week_view->use_24_hour_format) { + gdk_draw_string (drawable, font, fg_gc, + time_x, time_y_normal_font, suffix); + } + } else { + /* Draw the start time in one go. */ + g_snprintf (buffer, sizeof (buffer), "%2i:%02i%s", + hour_to_display, minute, suffix); + if (hour_to_display < 10) + gdk_draw_string (drawable, font, fg_gc, + time_x + week_view->digit_width, + time_y_normal_font, buffer + 1); + else + gdk_draw_string (drawable, font, fg_gc, + time_x, time_y_normal_font, + buffer); + + } +} + + static void e_week_view_event_item_draw_icons (EWeekViewEventItem *wveitem, GdkDrawable *drawable, @@ -741,12 +789,12 @@ e_week_view_event_item_get_position (EWeekViewEventItem *wveitem, if (!e_week_view_is_one_day_event (week_view, wveitem->event_num)) { if (x < item->x1 + E_WEEK_VIEW_EVENT_L_PAD + E_WEEK_VIEW_EVENT_BORDER_WIDTH - + E_WEEK_VIEW_EVENT_TEXT_X_PAD) + + E_WEEK_VIEW_EVENT_EDGE_X_PAD) return E_WEEK_VIEW_POS_LEFT_EDGE; - if (x >= item->x2 - E_WEEK_VIEW_EVENT_R_PAD + if (x >= item->x2 + 1 - E_WEEK_VIEW_EVENT_R_PAD - E_WEEK_VIEW_EVENT_BORDER_WIDTH - - E_WEEK_VIEW_EVENT_TEXT_X_PAD) + - E_WEEK_VIEW_EVENT_EDGE_X_PAD) return E_WEEK_VIEW_POS_RIGHT_EDGE; } diff --git a/calendar/gui/e-week-view.c b/calendar/gui/e-week-view.c index ca93fd1a14..6968d5ec81 100644 --- a/calendar/gui/e-week-view.c +++ b/calendar/gui/e-week-view.c @@ -283,6 +283,12 @@ e_week_view_init (EWeekView *week_view) if (!week_view->small_font) g_warning ("Couldn't load font"); + /* String to use in 12-hour time format for times in the morning. */ + week_view->am_string = _("am"); + + /* String to use in 12-hour time format for times in the afternoon. */ + week_view->pm_string = _("pm"); + /* * Titles Canvas. Note that we don't show it is only shown in the @@ -561,6 +567,11 @@ e_week_view_style_set (GtkWidget *widget, week_view->max_abbr_day_width = max_abbr_day_width; week_view->max_month_width = max_month_width; week_view->max_abbr_month_width = max_abbr_month_width; + + week_view->am_string_width = gdk_string_width (font, + week_view->am_string); + week_view->pm_string_width = gdk_string_width (font, + week_view->pm_string); } @@ -693,20 +704,18 @@ e_week_view_recalc_cell_sizes (EWeekView *week_view) We only allow the time to take up about half of the width. */ width = week_view->col_widths[0]; + time_width = e_week_view_get_time_string_width (week_view); + week_view->time_format = E_WEEK_VIEW_TIME_NONE; if (week_view->use_small_font && week_view->small_font) { - time_width = week_view->digit_width * 2 - + week_view->small_digit_width * 2; if (week_view->show_event_end_times - && width / 2 > time_width * 2 + week_view->space_width) + && width / 2 > time_width * 2 + E_WEEK_VIEW_EVENT_TIME_SPACING) 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 (week_view->show_event_end_times - && width / 2 > time_width * 2 + week_view->space_width) + && width / 2 > time_width * 2 + E_WEEK_VIEW_EVENT_TIME_SPACING) week_view->time_format = E_WEEK_VIEW_TIME_BOTH; else if (width / 2 > time_width) week_view->time_format = E_WEEK_VIEW_TIME_START; @@ -1297,6 +1306,9 @@ e_week_view_set_weeks_shown (EWeekView *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); + + /* Make sure the events are reloaded. */ + e_week_view_queue_reload_events (week_view); } } @@ -1388,8 +1400,6 @@ e_week_view_set_week_start_day (EWeekView *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; @@ -1404,6 +1414,36 @@ e_week_view_set_week_start_day (EWeekView *week_view, } +/* Whether we use 12-hour or 24-hour format. */ +gboolean +e_week_view_get_24_hour_format (EWeekView *week_view) +{ + g_return_val_if_fail (E_IS_WEEK_VIEW (week_view), FALSE); + + return week_view->use_24_hour_format; +} + + +void +e_week_view_set_24_hour_format (EWeekView *week_view, + gboolean use_24_hour) +{ + g_return_if_fail (E_IS_WEEK_VIEW (week_view)); + + if (week_view->use_24_hour_format == use_24_hour) + return; + + week_view->use_24_hour_format = use_24_hour; + + /* We need to re-layout the events since the time format affects the + sizes. */ + e_week_view_recalc_cell_sizes (week_view); + week_view->events_need_reshape = TRUE; + e_week_view_check_layout (week_view); + gtk_widget_queue_draw (week_view->main_canvas); +} + + static gboolean e_week_view_recalc_display_start_day (EWeekView *week_view) { @@ -1633,7 +1673,11 @@ e_week_view_get_day_position (EWeekView *week_view, /* Returns the bounding box for a span of an event. Usually this can easily be determined by the start & end days and row of the span, which are set in e_week_view_layout_event(). Though we need a special case for the weekends - when they are compressed, since the span may not fit. */ + when they are compressed, since the span may not fit. + The bounding box includes the entire width of the days in the view (but + not the vertical line down the right of the last day), though the displayed + event doesn't normally extend to the edges of the day. + It returns FALSE if the span isn't visible. */ gboolean e_week_view_get_span_position (EWeekView *week_view, gint event_num, @@ -1696,13 +1740,13 @@ e_week_view_get_span_position (EWeekView *week_view, + E_WEEK_VIEW_EVENT_Y_SPACING); if (num_days == 1) { *span_x = start_x; - *span_w = start_w; + *span_w = start_w - 1; } else { e_week_view_get_day_position (week_view, span->start_day + num_days - 1, &end_x, &end_y, &end_w, &end_h); *span_x = start_x; - *span_w = end_x - start_x + end_w; + *span_w = end_x + end_w - start_x - 1; } return TRUE; @@ -2382,12 +2426,15 @@ e_week_view_reshape_event_span (EWeekView *week_view, return; } + /* If we are editing a long event we don't show the icons and the EText + item uses the maximum width available. */ if (!one_day_event && week_view->editing_event_num == event_num && week_view->editing_span_num == span_num) { show_icons = FALSE; use_max_width = TRUE; } + /* Calculate how many icons we need to show. */ num_icons = 0; if (show_icons) { if (cal_component_has_alarms (comp)) @@ -2435,23 +2482,18 @@ e_week_view_reshape_event_span (EWeekView *week_view, /* Calculate the position of the text item. For events < 1 day it starts after the times & icons and ends at the right edge of the span. - For events > 1 day we need to determine whether times are shown at + For events >= 1 day we need to determine whether times are shown at the start and end of the span, then try to center the text item with the icons in the middle, but making sure we don't go over the times. */ /* Calculate the space necessary to display a time, e.g. "13:00". */ - if (week_view->use_small_font && week_view->small_font) - time_width = week_view->digit_width * 2 - + week_view->small_digit_width * 2; - else - time_width = week_view->digit_width * 4 - + week_view->colon_width; + time_width = e_week_view_get_time_string_width (week_view); /* Calculate the space needed for the icons. */ icons_width = (E_WEEK_VIEW_ICON_WIDTH + E_WEEK_VIEW_ICON_X_PAD) - * num_icons; + * num_icons - E_WEEK_VIEW_ICON_X_PAD + E_WEEK_VIEW_ICON_R_PAD; /* The y position and height are the same for both event types. */ text_y = span_y + E_WEEK_VIEW_EVENT_BORDER_HEIGHT @@ -2459,50 +2501,71 @@ e_week_view_reshape_event_span (EWeekView *week_view, text_h = font->ascent + font->descent; if (one_day_event) { - text_x = span_x + E_WEEK_VIEW_EVENT_L_PAD + icons_width; + /* Note that 1-day events don't have a border. Although we + still use the border height to position the events + vertically so they still line up neatly (see above), + we don't use the border width or edge padding at all. */ + text_x = span_x + E_WEEK_VIEW_EVENT_L_PAD; switch (week_view->time_format) { case E_WEEK_VIEW_TIME_BOTH_SMALL_MIN: case E_WEEK_VIEW_TIME_BOTH: - text_x += time_width * 2 + week_view->space_width - + E_WEEK_VIEW_EVENT_TIME_R_PAD; + /* These have 2 time strings with a small space between + them and some space before the EText item. */ + text_x += time_width * 2 + + E_WEEK_VIEW_EVENT_TIME_SPACING + + E_WEEK_VIEW_EVENT_TIME_X_PAD; break; case E_WEEK_VIEW_TIME_START_SMALL_MIN: case E_WEEK_VIEW_TIME_START: - text_x += time_width + E_WEEK_VIEW_EVENT_TIME_R_PAD; + /* These have just 1 time string with some space + before the EText item. */ + text_x += time_width + E_WEEK_VIEW_EVENT_TIME_X_PAD; break; case E_WEEK_VIEW_TIME_NONE: break; } - text_w = span_x + span_w - E_WEEK_VIEW_EVENT_BORDER_WIDTH - - E_WEEK_VIEW_EVENT_R_PAD - text_x; + + /* The icons_width includes space on the right of the icons. */ + text_x += icons_width; + + /* The width of the EText item extends right to the edge of the + event, just inside the border. */ + text_w = span_x + span_w - E_WEEK_VIEW_EVENT_R_PAD - text_x; } else { if (use_max_width) { + /* When we are editing the event we use all the + available width. */ text_x = span_x + E_WEEK_VIEW_EVENT_L_PAD + E_WEEK_VIEW_EVENT_BORDER_WIDTH - + E_WEEK_VIEW_EVENT_TEXT_X_PAD; + + E_WEEK_VIEW_EVENT_EDGE_X_PAD; text_w = span_x + span_w - E_WEEK_VIEW_EVENT_R_PAD - E_WEEK_VIEW_EVENT_BORDER_WIDTH - - E_WEEK_VIEW_EVENT_TEXT_X_PAD - text_x; + - E_WEEK_VIEW_EVENT_EDGE_X_PAD - text_x; } else { - /* Get the requested size of the label. */ + /* Get the width of the text of the event. This is a + bit of a hack. It would be better if EText could + tell us this. */ gtk_object_get (GTK_OBJECT (span->text_item), "text", &text, NULL); text_width = 0; if (text) { + /* It should only have one line of text in it. + I'm not sure we need this any more. */ end_of_line = strchr (text, '\n'); if (end_of_line) line_len = end_of_line - text; else line_len = strlen (text); - text_width = gdk_text_width (font, text, line_len); + text_width = gdk_text_width (font, text, + line_len); g_free (text); } /* Add on the width of the icons and find the default - position. */ + position, which centers the icons + text. */ width = text_width + icons_width; text_x = span_x + (span_w - width) / 2; @@ -2510,11 +2573,15 @@ e_week_view_reshape_event_span (EWeekView *week_view, sure we don't go to the left of that. */ min_text_x = span_x + E_WEEK_VIEW_EVENT_L_PAD + E_WEEK_VIEW_EVENT_BORDER_WIDTH - + E_WEEK_VIEW_EVENT_TEXT_X_PAD; + + E_WEEK_VIEW_EVENT_EDGE_X_PAD; + /* See if we will want to display the start time, and + if so take that into account. */ if (event->start > week_view->day_starts[span->start_day]) min_text_x += time_width - + E_WEEK_VIEW_EVENT_TIME_R_PAD; + + E_WEEK_VIEW_EVENT_TIME_X_PAD; + /* Now make sure we don't go to the left of the minimum + position. */ text_x = MAX (text_x, min_text_x); /* Now calculate the largest valid width, using the @@ -2522,11 +2589,11 @@ e_week_view_reshape_event_span (EWeekView *week_view, exceed that. */ max_text_w = span_x + span_w - E_WEEK_VIEW_EVENT_R_PAD - E_WEEK_VIEW_EVENT_BORDER_WIDTH - - E_WEEK_VIEW_EVENT_TEXT_X_PAD - text_x; + - E_WEEK_VIEW_EVENT_EDGE_X_PAD - text_x; if (event->end < week_view->day_starts[span->start_day + span->num_days]) max_text_w -= time_width - + E_WEEK_VIEW_EVENT_TIME_R_PAD; + + E_WEEK_VIEW_EVENT_TIME_X_PAD; text_w = MIN (width, max_text_w); @@ -2536,7 +2603,9 @@ e_week_view_reshape_event_span (EWeekView *week_view, } } + /* Make sure we don't try to use a negative width. */ text_w = MAX (text_w, 0); + gnome_canvas_item_set (span->text_item, "clip_width", (gdouble) text_w, "clip_height", (gdouble) text_h, @@ -3340,3 +3409,55 @@ e_week_view_on_jump_button_event (GnomeCanvasItem *item, return FALSE; } + + +/* Converts an hour from 0-23 to the preferred time format, and returns the + suffix to add and the width of it in the normal font. */ +void +e_week_view_convert_time_to_display (EWeekView *week_view, + gint hour, + gint *display_hour, + gchar **suffix, + gint *suffix_width) +{ + /* Calculate the actual hour number to display. For 12-hour + format we convert 0-23 to 12-11am/12-11pm. */ + *display_hour = hour; + if (week_view->use_24_hour_format) { + *suffix = ""; + *suffix_width = 0; + } else { + if (hour < 12) { + *suffix = week_view->am_string; + *suffix_width = week_view->am_string_width; + } else { + *display_hour -= 12; + *suffix = week_view->pm_string; + *suffix_width = week_view->pm_string_width; + } + + /* 12-hour uses 12:00 rather than 0:00. */ + if (*display_hour == 0) + *display_hour = 12; + } +} + + +gint +e_week_view_get_time_string_width (EWeekView *week_view) +{ + gint time_width; + + if (week_view->use_small_font && week_view->small_font) + time_width = week_view->digit_width * 2 + + week_view->small_digit_width * 2; + else + time_width = week_view->digit_width * 4 + + week_view->colon_width; + + if (!week_view->use_24_hour_format) + time_width += MAX (week_view->am_string_width, + week_view->pm_string_width); + + return time_width; +} diff --git a/calendar/gui/e-week-view.h b/calendar/gui/e-week-view.h index ccd11bf84a..aa9ba05fb9 100644 --- a/calendar/gui/e-week-view.h +++ b/calendar/gui/e-week-view.h @@ -41,30 +41,38 @@ extern "C" { but we allow 6 for longer selections. */ #define E_WEEK_VIEW_MAX_WEEKS 6 -/* The size of the reminder & recurrence icons, and padding around them. */ +/* The size of the reminder & recurrence icons, and padding around them. + X_PAD is the padding between icons. R_PAD is the padding on the right of + the last icon, before the event text. */ #define E_WEEK_VIEW_ICON_WIDTH 16 #define E_WEEK_VIEW_ICON_HEIGHT 16 #define E_WEEK_VIEW_ICON_X_PAD 0 #define E_WEEK_VIEW_ICON_Y_PAD 0 +#define E_WEEK_VIEW_ICON_R_PAD 2 -/* The space on the left & right of the event. (The triangle to indicate the - event continues is displayed in this space). */ +/* The space on the left & right outside of the event. (The triangle to + indicate the event continues is displayed in this space). */ #define E_WEEK_VIEW_EVENT_L_PAD 2 -#define E_WEEK_VIEW_EVENT_R_PAD 3 +#define E_WEEK_VIEW_EVENT_R_PAD 2 /* The vertical spacing between rows of events. */ #define E_WEEK_VIEW_EVENT_Y_SPACING 1 -/* The size of the border around the event. */ +/* The size of the border around long events. */ #define E_WEEK_VIEW_EVENT_BORDER_WIDTH 1 #define E_WEEK_VIEW_EVENT_BORDER_HEIGHT 1 -/* The padding on each side of the event text. */ -#define E_WEEK_VIEW_EVENT_TEXT_X_PAD 4 +/* The padding on the top and bottom of the event text. */ #define E_WEEK_VIEW_EVENT_TEXT_Y_PAD 1 -/* The space on the right of the time string, if it is shown. */ -#define E_WEEK_VIEW_EVENT_TIME_R_PAD 2 +/* The space between the start and end times. */ +#define E_WEEK_VIEW_EVENT_TIME_SPACING 2 + +/* The space between the time and the event text or icons. */ +#define E_WEEK_VIEW_EVENT_TIME_X_PAD 2 + +/* The space between the borders of long events and any text of icons. */ +#define E_WEEK_VIEW_EVENT_EDGE_X_PAD 2 /* The padding above and on the right of the date string at the top of each cell. */ @@ -213,6 +221,9 @@ struct _EWeekView /* The first day of the week, 0 (Monday) to 6 (Sunday). */ gint week_start_day; + /* Whether we use 12-hour of 24-hour format. */ + gboolean use_24_hour_format; + /* 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. */ @@ -315,6 +326,12 @@ struct _EWeekView /* The last mouse position when dragging, in the entire canvas. */ gint drag_event_x; gint drag_event_y; + + /* "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 _EWeekViewClass @@ -377,6 +394,11 @@ 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); +/* Whether we use 12-hour or 24-hour format. */ +gboolean e_week_view_get_24_hour_format (EWeekView *week_view); +void e_week_view_set_24_hour_format (EWeekView *week_view, + gboolean use_24_hour); + /* @@ -406,6 +428,13 @@ void e_week_view_show_popup_menu (EWeekView *week_view, GdkEventButton *event, gint event_num); +void e_week_view_convert_time_to_display (EWeekView *week_view, + gint hour, + gint *display_hour, + gchar **suffix, + gint *suffix_width); +gint e_week_view_get_time_string_width (EWeekView *week_view); + #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/calendar/gui/gnome-cal.c b/calendar/gui/gnome-cal.c index 802f76341c..b423ffcd41 100644 --- a/calendar/gui/gnome-cal.c +++ b/calendar/gui/gnome-cal.c @@ -1586,7 +1586,6 @@ gnome_calendar_update_config_settings (GnomeCalendar *gcal, /* 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); e_day_view_set_week_start_day (E_DAY_VIEW (priv->work_week_view), @@ -1615,13 +1614,10 @@ gnome_calendar_update_config_settings (GnomeCalendar *gcal, use_24_hour); e_day_view_set_24_hour_format (E_DAY_VIEW (priv->work_week_view), use_24_hour); - /* FIXME: Add support for these. */ -#if 0 e_week_view_set_24_hour_format (E_WEEK_VIEW (priv->week_view), use_24_hour); e_week_view_set_24_hour_format (E_WEEK_VIEW (priv->month_view), use_24_hour); -#endif time_divisions = calendar_config_get_time_divisions (); e_day_view_set_mins_per_row (E_DAY_VIEW (priv->day_view), @@ -1959,8 +1955,11 @@ gnome_calendar_on_date_navigator_selection_changed (ECalendarItem *calitem, new_days_shown = g_date_julian (&new_end_date) - g_date_julian (&new_start_date) + 1; - /* FIXME: This assumes weeks start on Monday for now. */ - if (g_date_weekday (&new_start_date) - 1 == 0) + /* If a complete week is selected we show the Week view. + Note that if weekends are compressed and the week start day is set + to Sunday we don't actually show complete weeks in the Week view, + so this may need tweaking. */ + if ((g_date_weekday (&new_start_date) + 5) % 7 == calendar_config_get_week_start_day ()) starts_on_week_start_day = TRUE; /* Switch views as appropriate, and change the number of days or weeks -- cgit v1.2.3