From da073416c7611f821410cd18bdc5751b43b64d91 Mon Sep 17 00:00:00 2001 From: Milan Crha Date: Thu, 15 Jan 2009 11:19:25 +0000 Subject: ** Fix for bug #246313 2009-01-15 Milan Crha ** Fix for bug #246313 * gui/e-day-view.c: (e_day_view_check_if_new_event_fits): Removed. * gui/e-day-view.h: (struct _EDayView): * gui/e-day-view.c: (e_day_view_init), (e_day_view_size_allocate), (e_day_view_recalc_main_canvas_size), (e_day_view_recalc_cell_sizes), (e_day_view_update_scroll_regions), (e_day_view_check_layout): * gui/e-day-view-layout.h: (e_day_view_layout_day_events): * gui/e-day-view-layout.c: (e_day_view_layout_day_events), (e_day_view_layout_day_event), (e_day_view_expand_day_event): Added ability to show all event in one-day view, but show only up to 6 columns in a multi-day view. * gui/print.c: (print_day_details): Always print all events. svn path=/trunk/; revision=37077 --- calendar/gui/e-day-view-layout.c | 62 ++++++++++++++++--------- calendar/gui/e-day-view-layout.h | 5 ++- calendar/gui/e-day-view.c | 97 ++++++++++++++++++---------------------- calendar/gui/e-day-view.h | 12 ++++- calendar/gui/print.c | 2 +- 5 files changed, 99 insertions(+), 79 deletions(-) (limited to 'calendar/gui') diff --git a/calendar/gui/e-day-view-layout.c b/calendar/gui/e-day-view-layout.c index 26459997df..949f4b7ce2 100644 --- a/calendar/gui/e-day-view-layout.c +++ b/calendar/gui/e-day-view-layout.c @@ -29,6 +29,7 @@ #include #include "e-day-view-layout.h" +#include "e-util/e-bit-array.h" static void e_day_view_layout_long_event (EDayViewEvent *event, guint8 *grid, @@ -37,13 +38,14 @@ static void e_day_view_layout_long_event (EDayViewEvent *event, gint *rows_in_top_display); static void e_day_view_layout_day_event (EDayViewEvent *event, - guint8 *grid, + EBitArray **grid, guint16 *group_starts, guint8 *cols_per_row, gint rows, - gint mins_per_row); + gint mins_per_row, + gint max_cols); static void e_day_view_expand_day_event (EDayViewEvent *event, - guint8 *grid, + EBitArray **grid, guint8 *cols_per_row, gint mins_per_row); static void e_day_view_recalc_cols_per_row (gint rows, @@ -127,15 +129,17 @@ e_day_view_layout_long_event (EDayViewEvent *event, } -void +/* returns maximum number of columns among all rows */ +gint e_day_view_layout_day_events (GArray *events, gint rows, gint mins_per_row, - guint8 *cols_per_row) + guint8 *cols_per_row, + gint max_cols) { EDayViewEvent *event; - gint row, event_num; - guint8 *grid; + gint row, event_num, res; + EBitArray **grid; /* This is a temporary array which keeps track of rows which are connected. When an appointment spans multiple rows then the number @@ -145,18 +149,20 @@ e_day_view_layout_day_events (GArray *events, rows. */ guint16 group_starts[12 * 24]; + /* This is a temporary 2-d grid which is used to place events. + Each element is 0 if the position is empty, or 1 if occupied. */ + grid = g_new0 (EBitArray *, 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 < rows; row++) { cols_per_row[row] = 0; group_starts[row] = row; - } - - /* This is a temporary 2-d grid which is used to place events. - Each element is 0 if the position is empty, or 1 if occupied. */ - grid = g_new0 (guint8, rows * E_DAY_VIEW_MAX_COLUMNS); + /* row doesn't contain any event at the moment */ + grid [row] = e_bit_array_new (0); + } /* Iterate over the events, finding which rows they cover, and putting them in the first free column available. Increment the number of @@ -166,7 +172,7 @@ e_day_view_layout_day_events (GArray *events, event = &g_array_index (events, EDayViewEvent, event_num); e_day_view_layout_day_event (event, grid, group_starts, - cols_per_row, rows, mins_per_row); + cols_per_row, rows, mins_per_row, max_cols); } /* Recalculate the number of columns needed in each row. */ @@ -180,8 +186,15 @@ e_day_view_layout_day_events (GArray *events, mins_per_row); } - /* Free the grid. */ + /* Free the grid and compute maximum number of columns used. */ + res = 0; + for (row = 0; row < rows; row++) { + res = MAX (res, e_bit_array_bit_count (grid [row])); + g_object_unref (grid [row]); + } g_free (grid); + + return res; } @@ -190,11 +203,12 @@ e_day_view_layout_day_events (GArray *events, sure they are all in one group. */ static void e_day_view_layout_day_event (EDayViewEvent *event, - guint8 *grid, + EBitArray **grid, guint16 *group_starts, guint8 *cols_per_row, gint rows, - gint mins_per_row) + gint mins_per_row, + gint max_cols) { gint start_row, end_row, free_col, col, row, group_start; @@ -214,10 +228,11 @@ e_day_view_layout_day_event (EDayViewEvent *event, end_row = CLAMP (end_row, 0, rows - 1); /* Try each column until we find a free one. */ - for (col = 0; col < E_DAY_VIEW_MAX_COLUMNS; col++) { + for (col = 0; max_cols <= 0 || col < max_cols; col++) { free_col = col; for (row = start_row; row <= end_row; row++) { - if (grid[row * E_DAY_VIEW_MAX_COLUMNS + col]) { + if (e_bit_array_bit_count (grid [row]) > col && + e_bit_array_value_at (grid [row], col)) { free_col = -1; break; } @@ -243,7 +258,11 @@ e_day_view_layout_day_event (EDayViewEvent *event, all the events have been layed out. Also make sure all the rows that the event covers are in one group. */ for (row = start_row; row <= end_row; row++) { - grid[row * E_DAY_VIEW_MAX_COLUMNS + free_col] = 1; + /* resize the array if necessary */ + if (e_bit_array_bit_count (grid [row]) <= free_col) + e_bit_array_insert (grid [row], e_bit_array_bit_count (grid [row]), free_col - e_bit_array_bit_count (grid [row]) + 1); + + e_bit_array_change_one_row (grid [row], free_col, TRUE); cols_per_row[row]++; group_starts[row] = group_start; } @@ -284,7 +303,7 @@ e_day_view_recalc_cols_per_row (gint rows, /* Expands the event horizontally to fill any free space. */ static void e_day_view_expand_day_event (EDayViewEvent *event, - guint8 *grid, + EBitArray **grid, guint8 *cols_per_row, gint mins_per_row) { @@ -300,7 +319,8 @@ e_day_view_expand_day_event (EDayViewEvent *event, clashed = FALSE; for (col = event->start_row_or_col + 1; col < cols_per_row[start_row]; col++) { for (row = start_row; row <= end_row; row++) { - if (grid[row * E_DAY_VIEW_MAX_COLUMNS + col]) { + if (e_bit_array_bit_count (grid [row]) > col && + e_bit_array_value_at (grid [row], col)) { clashed = TRUE; break; } diff --git a/calendar/gui/e-day-view-layout.h b/calendar/gui/e-day-view-layout.h index 19ee6ee036..4ad1de64bd 100644 --- a/calendar/gui/e-day-view-layout.h +++ b/calendar/gui/e-day-view-layout.h @@ -39,10 +39,11 @@ void e_day_view_layout_long_events (GArray *events, gint *rows_in_top_display); -void e_day_view_layout_day_events (GArray *events, +gint e_day_view_layout_day_events (GArray *events, gint rows, gint mins_per_row, - guint8 *cols_per_row); + guint8 *cols_per_row, + gint max_cols); gboolean e_day_view_find_long_event_days (EDayViewEvent *event, gint days_shown, diff --git a/calendar/gui/e-day-view.c b/calendar/gui/e-day-view.c index 05f4d1ca64..141d4d33c0 100644 --- a/calendar/gui/e-day-view.c +++ b/calendar/gui/e-day-view.c @@ -182,8 +182,6 @@ static void e_day_view_top_scroll (EDayView *day_view, static void e_day_view_update_top_scroll (EDayView *day_view, gboolean scroll_to_top); -static gboolean e_day_view_check_if_new_event_fits (EDayView *day_view); - static void e_day_view_on_canvas_realized (GtkWidget *widget, EDayView *day_view); @@ -987,6 +985,10 @@ e_day_view_init (EDayView *day_view) /* * Scrollbar. */ + day_view->mc_hscrollbar = gtk_hscrollbar_new (GTK_LAYOUT (day_view->main_canvas)->hadjustment); + gtk_table_attach (GTK_TABLE (day_view), day_view->mc_hscrollbar, 1, 2, 2, 3, GTK_FILL, 0, 0, 0); + gtk_widget_show (day_view->mc_hscrollbar); + day_view->tc_vscrollbar = gtk_vscrollbar_new (GTK_LAYOUT (day_view->top_canvas)->vadjustment); gtk_table_attach (GTK_TABLE (day_view), day_view->tc_vscrollbar, 2, 3, 0, 1, 0, GTK_FILL, 0, 0); @@ -1461,28 +1463,19 @@ e_day_view_style_set (GtkWidget *widget, pango_font_metrics_unref (font_metrics); } -/* This recalculates the sizes of each column. */ static void -e_day_view_size_allocate (GtkWidget *widget, GtkAllocation *allocation) +e_day_view_recalc_main_canvas_size (EDayView *day_view) { - EDayView *day_view; gint day, scroll_y; gboolean need_reshape; -#if 0 - g_print ("In e_day_view_size_allocate\n"); -#endif - day_view = E_DAY_VIEW (widget); - - (*GTK_WIDGET_CLASS (e_day_view_parent_class)->size_allocate) (widget, allocation); - - e_day_view_recalc_cell_sizes (day_view); - /* Set the scroll region of the top canvas */ e_day_view_update_top_scroll (day_view, TRUE); need_reshape = e_day_view_update_scroll_regions (day_view); + e_day_view_recalc_cell_sizes (day_view); + /* Scroll to the start of the working day, if this is the initial allocation. */ if (day_view->scroll_to_work_day) { @@ -1503,6 +1496,17 @@ e_day_view_size_allocate (GtkWidget *widget, GtkAllocation *allocation) } } +/* This recalculates the sizes of each column. */ +static void +e_day_view_size_allocate (GtkWidget *widget, GtkAllocation *allocation) +{ +#if 0 + g_print ("In e_day_view_size_allocate\n"); +#endif + (*GTK_WIDGET_CLASS (e_day_view_parent_class)->size_allocate) (widget, allocation); + + e_day_view_recalc_main_canvas_size (E_DAY_VIEW (widget)); +} static void e_day_view_recalc_cell_sizes (EDayView *day_view) @@ -1529,6 +1533,8 @@ e_day_view_recalc_cell_sizes (EDayView *day_view) get divided evenly. Note that we use one more element than the number of columns, to make it easy to get the column widths. */ width = day_view->main_canvas->allocation.width; + if (day_view->days_shown == 1) + width = MAX (width, day_view->max_cols * (E_DAY_VIEW_MIN_DAY_COL_WIDTH + E_DAY_VIEW_GAP_WIDTH) - E_DAY_VIEW_MIN_DAY_COL_WIDTH - 1); width /= day_view->days_shown; offset = 0; for (day = 0; day <= day_view->days_shown; day++) { @@ -2673,12 +2679,21 @@ e_day_view_update_scroll_regions (EDayView *day_view) gnome_canvas_get_scroll_region (GNOME_CANVAS (day_view->main_canvas), NULL, NULL, &old_x2, &old_y2); new_x2 = day_view->main_canvas->allocation.width - 1; + + if (day_view->days_shown == 1) + new_x2 = MAX (new_x2, day_view->max_cols * (E_DAY_VIEW_MIN_DAY_COL_WIDTH + E_DAY_VIEW_GAP_WIDTH) - E_DAY_VIEW_MIN_DAY_COL_WIDTH - 1); + if (old_x2 != new_x2 || old_y2 != new_y2) { need_reshape = TRUE; gnome_canvas_set_scroll_region (GNOME_CANVAS (day_view->main_canvas), 0, 0, new_x2, new_y2); } + if (new_x2 <= day_view->main_canvas->allocation.width - 1) + gtk_widget_hide (day_view->mc_hscrollbar); + else + gtk_widget_show (day_view->mc_hscrollbar); + return need_reshape; } @@ -4262,13 +4277,13 @@ e_day_view_add_event (ECalComponent *comp, return TRUE; } - /* This lays out the short (less than 1 day) events in the columns. Any long events are simply skipped. */ void e_day_view_check_layout (EDayView *day_view) { gint day, rows_in_top_display; + gint max_cols = -1; /* Don't bother if we aren't visible. */ if (!E_CALENDAR_VIEW (day_view)->in_focus) @@ -4278,11 +4293,17 @@ e_day_view_check_layout (EDayView *day_view) e_day_view_ensure_events_sorted (day_view); for (day = 0; day < day_view->days_shown; day++) { - if (day_view->need_layout[day]) - e_day_view_layout_day_events (day_view->events[day], + if (day_view->need_layout[day]) { + gint cols; + + cols = e_day_view_layout_day_events (day_view->events[day], day_view->rows, day_view->mins_per_row, - day_view->cols_per_row[day]); + day_view->cols_per_row[day], + day_view->days_shown == 1 ? -1 : E_DAY_VIEW_MULTI_DAY_MAX_COLUMNS); + + max_cols = MAX (cols, max_cols); + } if (day_view->need_layout[day] || day_view->need_reshape[day]) { @@ -4308,13 +4329,17 @@ e_day_view_check_layout (EDayView *day_view) } } - if (day_view->long_events_need_layout || day_view->long_events_need_reshape) e_day_view_reshape_long_events (day_view); day_view->long_events_need_layout = FALSE; day_view->long_events_need_reshape = FALSE; + + if (max_cols != -1 && max_cols != day_view->max_cols) { + day_view->max_cols = max_cols; + e_day_view_recalc_main_canvas_size (day_view); + } } @@ -4927,13 +4952,6 @@ e_day_view_do_key_press (GtkWidget *widget, GdkEventKey *event) if (day_view->selection_start_day == -1) return FALSE; - /* Check if there is room for a new event to be typed in. If there - isn't we don't want to add an event as we will then add a new - event for every key press. */ - if (!e_day_view_check_if_new_event_fits (day_view)) { - return FALSE; - } - /* We only want to start an edit with a return key or a simple character. */ if ((keyval != GDK_Return) && @@ -5581,33 +5599,6 @@ e_day_view_top_scroll (EDayView *day_view, gtk_adjustment_set_value (adj, new_value); } -static gboolean -e_day_view_check_if_new_event_fits (EDayView *day_view) -{ - gint day, start_row, end_row, row; - - day = day_view->selection_start_day; - start_row = day_view->selection_start_row; - end_row = day_view->selection_end_row; - - /* Long events always fit, since we keep adding rows to the top - canvas. */ - if (day != day_view->selection_end_day) - return TRUE; - if (start_row == 0 && end_row == day_view->rows) - return TRUE; - - /* If any of the rows already have E_DAY_VIEW_MAX_COLUMNS columns, - return FALSE. */ - for (row = start_row; row <= end_row; row++) { - if (day_view->cols_per_row[day][row] >= E_DAY_VIEW_MAX_COLUMNS) - return FALSE; - } - - return TRUE; -} - - void e_day_view_ensure_rows_visible (EDayView *day_view, gint start_row, diff --git a/calendar/gui/e-day-view.h b/calendar/gui/e-day-view.h index 6f4c0d7da1..3a357e332d 100644 --- a/calendar/gui/e-day-view.h +++ b/calendar/gui/e-day-view.h @@ -45,8 +45,11 @@ G_BEGIN_DECLS of a normal event. */ #define E_DAY_VIEW_LONG_EVENT E_DAY_VIEW_MAX_DAYS -/* The maximum number of columns of appointments within a day. */ -#define E_DAY_VIEW_MAX_COLUMNS 6 +/* The maximum number of columns of appointments within a day in multi-day view. */ +#define E_DAY_VIEW_MULTI_DAY_MAX_COLUMNS 6 + +/* minimum width of the event in one-day view in pixels */ +#define E_DAY_VIEW_MIN_DAY_COL_WIDTH 60 /* The width of the gap between appointments. This should be at least E_DAY_VIEW_BAR_WIDTH, since in the top canvas we use this space to draw @@ -204,6 +207,9 @@ struct _EDayView /* scrollbar for top_canvas */ GtkWidget *tc_vscrollbar; + /* horizontal scrollbar for main_canvas */ + GtkWidget *mc_hscrollbar; + /* The main canvas where the rest of the appointments are shown. */ GtkWidget *main_canvas; GnomeCanvasItem *main_canvas_item; @@ -310,6 +316,8 @@ struct _EDayView 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]; + /* The maximum number of columns from all rows in cols_per_row */ + gint max_cols; /* Sizes of the various time strings. */ gint small_hour_widths[24]; diff --git a/calendar/gui/print.c b/calendar/gui/print.c index 33c45ab6c4..a60d1e93d8 100644 --- a/calendar/gui/print.c +++ b/calendar/gui/print.c @@ -1335,7 +1335,7 @@ print_day_details (GtkPrintContext *context, GnomeCalendar *gcal, time_t whence, /* lay out the short events, within the day. */ e_day_view_layout_day_events (pdi.events[0], DAY_VIEW_ROWS, - DAY_VIEW_MINS_PER_ROW, pdi.cols_per_row); + DAY_VIEW_MINS_PER_ROW, pdi.cols_per_row, -1); /* print the short events. */ if (top > bottom ) -- cgit v1.2.3