diff options
Diffstat (limited to 'calendar/gui/e-day-view.c')
-rw-r--r-- | calendar/gui/e-day-view.c | 369 |
1 files changed, 38 insertions, 331 deletions
diff --git a/calendar/gui/e-day-view.c b/calendar/gui/e-day-view.c index eac99a18aa..b08ed848d8 100644 --- a/calendar/gui/e-day-view.c +++ b/calendar/gui/e-day-view.c @@ -53,6 +53,7 @@ #include "e-meeting-edit.h" #include "e-day-view-time-item.h" #include "e-day-view-top-item.h" +#include "e-day-view-layout.h" #include "e-day-view-main-item.h" /* Images */ @@ -266,27 +267,9 @@ static void e_day_view_update_event_label (EDayView *day_view, static void e_day_view_update_long_event_label (EDayView *day_view, gint event_num); -static void e_day_view_layout_long_events (EDayView *day_view); -static void e_day_view_layout_long_event (EDayView *day_view, - EDayViewEvent *event, - guint8 *grid); static void e_day_view_reshape_long_events (EDayView *day_view); static void e_day_view_reshape_long_event (EDayView *day_view, gint event_num); -static void e_day_view_layout_day_events (EDayView *day_view, - gint day); -static void e_day_view_layout_day_event (EDayView *day_view, - gint day, - EDayViewEvent *event, - guint8 *grid, - guint16 *group_starts); -static void e_day_view_expand_day_event (EDayView *day_view, - gint day, - EDayViewEvent *event, - guint8 *grid); -static void e_day_view_recalc_cols_per_row (EDayView *day_view, - gint day, - guint16 *group_starts); static void e_day_view_reshape_day_events (EDayView *day_view, gint day); static void e_day_view_reshape_day_event (EDayView *day_view, @@ -297,8 +280,6 @@ static void e_day_view_reshape_resize_long_event_rect_item (EDayView *day_view); static void e_day_view_reshape_resize_rect_item (EDayView *day_view); static void e_day_view_ensure_events_sorted (EDayView *day_view); -static gint e_day_view_event_sort_func (const void *arg1, - const void *arg2); static void e_day_view_start_editing_event (EDayView *day_view, gint day, @@ -2909,7 +2890,9 @@ e_day_view_on_long_event_click (EDayView *day_view, if (!(cal_component_has_recurrences (event->comp)) && (pos == E_DAY_VIEW_POS_LEFT_EDGE || pos == E_DAY_VIEW_POS_RIGHT_EDGE)) { - if (!e_day_view_find_long_event_days (day_view, event, + if (!e_day_view_find_long_event_days (event, + day_view->days_shown, + day_view->day_starts, &start_day, &end_day)) return; @@ -4163,7 +4146,7 @@ e_day_view_add_event (CalComponent *comp, void e_day_view_check_layout (EDayView *day_view) { - gint day; + gint day, rows_in_top_display, top_canvas_height, top_rows; /* Don't bother if we aren't visible. */ if (!GTK_WIDGET_VISIBLE (day_view)) @@ -4174,7 +4157,10 @@ e_day_view_check_layout (EDayView *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, day); + e_day_view_layout_day_events (day_view->events[day], + day_view->rows, + day_view->mins_per_row, + day_view->cols_per_row[day]); if (day_view->need_layout[day] || day_view->need_reshape[day]) { @@ -4188,8 +4174,25 @@ e_day_view_check_layout (EDayView *day_view) day_view->need_reshape[day] = FALSE; } - if (day_view->long_events_need_layout) - e_day_view_layout_long_events (day_view); + if (day_view->long_events_need_layout) { + e_day_view_layout_long_events (day_view->long_events, + day_view->days_shown, + day_view->day_starts, + &rows_in_top_display); + + /* Set the height of the top canvas based on the row height + and the number of rows needed (min 1 + 1 for the dates + 1 + space for DnD).*/ + if (day_view->rows_in_top_display != rows_in_top_display) { + day_view->rows_in_top_display = rows_in_top_display; + top_rows = MAX (1, rows_in_top_display); + top_canvas_height = (top_rows + 2) + * day_view->top_row_height; + gtk_widget_set_usize (day_view->top_canvas, -1, + top_canvas_height); + } + } + if (day_view->long_events_need_layout || day_view->long_events_need_reshape) @@ -4201,88 +4204,6 @@ e_day_view_check_layout (EDayView *day_view) static void -e_day_view_layout_long_events (EDayView *day_view) -{ - EDayViewEvent *event; - gint event_num, old_rows_in_top_display, top_canvas_height, top_rows; - guint8 *grid; - - /* 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. - We allocate the maximum size possible here, assuming that each - event will need its own row. */ - grid = g_new0 (guint8, - day_view->long_events->len * E_DAY_VIEW_MAX_DAYS); - - /* Reset the number of rows in the top display to 0. It will be - updated as events are layed out below. */ - old_rows_in_top_display = day_view->rows_in_top_display; - day_view->rows_in_top_display = 0; - - /* Iterate over the events, finding which days they cover, and putting - them in the first free row available. */ - for (event_num = 0; event_num < day_view->long_events->len; - event_num++) { - event = &g_array_index (day_view->long_events, - EDayViewEvent, event_num); - e_day_view_layout_long_event (day_view, event, grid); - } - - /* Free the grid. */ - g_free (grid); - - /* Set the height of the top canvas based on the row height and the - number of rows needed (min 1 + 1 for the dates + 1 space for DnD).*/ - if (day_view->rows_in_top_display != old_rows_in_top_display) { - top_rows = MAX (1, day_view->rows_in_top_display); - top_canvas_height = (top_rows + 2) * day_view->top_row_height; - gtk_widget_set_usize (day_view->top_canvas, -1, - top_canvas_height); - } -} - - -static void -e_day_view_layout_long_event (EDayView *day_view, - EDayViewEvent *event, - guint8 *grid) -{ - gint start_day, end_day, free_row, day, row; - - event->num_columns = 0; - - if (!e_day_view_find_long_event_days (day_view, event, - &start_day, &end_day)) - return; - - /* Try each row until we find a free one. */ - row = 0; - do { - free_row = row; - for (day = start_day; day <= end_day; day++) { - if (grid[row * E_DAY_VIEW_MAX_DAYS + day]) { - free_row = -1; - break; - } - } - row++; - } while (free_row == -1); - - event->start_row_or_col = free_row; - event->num_columns = 1; - - /* Mark the cells as full. */ - for (day = start_day; day <= end_day; day++) { - grid[free_row * E_DAY_VIEW_MAX_DAYS + day] = 1; - } - - /* Update the number of rows in the top canvas if necessary. */ - day_view->rows_in_top_display = MAX (day_view->rows_in_top_display, - free_row + 1); -} - - -static void e_day_view_reshape_long_events (EDayView *day_view) { EDayViewEvent *event; @@ -4438,225 +4359,6 @@ e_day_view_reshape_long_event (EDayView *day_view, } -/* Find the start and end days for the event. */ -gboolean -e_day_view_find_long_event_days (EDayView *day_view, - EDayViewEvent *event, - gint *start_day_return, - gint *end_day_return) -{ - gint day, start_day, end_day; - - start_day = -1; - end_day = -1; - - for (day = 0; day < day_view->days_shown; day++) { - if (start_day == -1 - && event->start < day_view->day_starts[day + 1]) - start_day = day; - if (event->end > day_view->day_starts[day]) - end_day = day; - } - - /* Sanity check. */ - if (start_day < 0 || start_day >= day_view->days_shown - || end_day < 0 || end_day >= day_view->days_shown - || end_day < start_day) { - g_warning ("Invalid date range for event"); - return FALSE; - } - - *start_day_return = start_day; - *end_day_return = end_day; - - return TRUE; -} - - -static void -e_day_view_layout_day_events (EDayView *day_view, - gint day) -{ - EDayViewEvent *event; - gint row, event_num; - guint8 *grid; - - /* This is a temporary array which keeps track of rows which are - connected. When an appointment spans multiple rows then the number - of columns in each of these rows must be the same (i.e. the maximum - of all of them). Each element in the array corresponds to one row - and contains the index of the first row in the group of connected - rows. */ - guint16 group_starts[12 * 24]; - - /* 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; - } - - /* 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, day_view->rows * E_DAY_VIEW_MAX_COLUMNS); - - - /* Iterate over the events, finding which rows they cover, and putting - them in the first free column available. Increment the number of - events in each of the rows it covers, and make sure they are all - in one group. */ - for (event_num = 0; event_num < day_view->events[day]->len; - event_num++) { - event = &g_array_index (day_view->events[day], EDayViewEvent, - event_num); - - e_day_view_layout_day_event (day_view, day, event, - grid, group_starts); - } - - /* Recalculate the number of columns needed in each row. */ - e_day_view_recalc_cols_per_row (day_view, day, group_starts); - - /* Iterate over the events again, trying to expand events horizontally - if there is enough space. */ - for (event_num = 0; event_num < day_view->events[day]->len; - event_num++) { - event = &g_array_index (day_view->events[day], EDayViewEvent, - event_num); - e_day_view_expand_day_event (day_view, day, event, grid); - } - - /* Free the grid. */ - g_free (grid); -} - - -/* Finds the first free position to place the event in. - Increments the number of events in each of the rows it covers, and makes - sure they are all in one group. */ -static void -e_day_view_layout_day_event (EDayView *day_view, - gint day, - EDayViewEvent *event, - guint8 *grid, - guint16 *group_starts) -{ - gint start_row, end_row, free_col, col, row, group_start; - - start_row = event->start_minute / day_view->mins_per_row; - end_row = (event->end_minute - 1) / day_view->mins_per_row; - - event->num_columns = 0; - - /* If the event can't currently be seen, just return. */ - if (start_row >= day_view->rows || end_row < 0) - return; - - /* Make sure we don't go outside the visible times. */ - start_row = CLAMP (start_row, 0, day_view->rows - 1); - end_row = CLAMP (end_row, 0, day_view->rows - 1); - - /* Try each column until we find a free one. */ - for (col = 0; col < E_DAY_VIEW_MAX_COLUMNS; col++) { - free_col = col; - for (row = start_row; row <= end_row; row++) { - if (grid[row * E_DAY_VIEW_MAX_COLUMNS + col]) { - free_col = -1; - break; - } - } - - if (free_col != -1) - break; - } - - /* If we can't find space for the event, just return. */ - if (free_col == -1) - return; - - /* The event is assigned 1 col initially, but may be expanded later. */ - event->start_row_or_col = free_col; - event->num_columns = 1; - - /* Determine the start index of the group. */ - group_start = group_starts[start_row]; - - /* Increment number of events in each of the rows the event covers. - We use the cols_per_row array for this. It will be sorted out after - 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; - day_view->cols_per_row[day][row]++; - group_starts[row] = group_start; - } - - /* If any following rows should be in the same group, add them. */ - for (row = end_row + 1; row < day_view->rows; row++) { - if (group_starts[row] > end_row) - break; - group_starts[row] = group_start; - } -} - - -/* For each group of rows, find the max number of events in all the - rows, and set the number of cols in each of the rows to that. */ -static void -e_day_view_recalc_cols_per_row (EDayView *day_view, - gint day, - guint16 *group_starts) -{ - gint start_row = 0, row, next_start_row, max_events; - - while (start_row < day_view->rows) { - - max_events = 0; - for (row = start_row; row < day_view->rows && group_starts[row] == start_row; row++) - max_events = MAX (max_events, day_view->cols_per_row[day][row]); - - next_start_row = row; - - for (row = start_row; row < next_start_row; row++) - day_view->cols_per_row[day][row] = max_events; - - start_row = next_start_row; - } -} - - -/* Expands the event horizontally to fill any free space. */ -static void -e_day_view_expand_day_event (EDayView *day_view, - gint day, - EDayViewEvent *event, - guint8 *grid) -{ - gint start_row, end_row, col, row; - gboolean clashed; - - start_row = event->start_minute / day_view->mins_per_row; - end_row = (event->end_minute - 1) / day_view->mins_per_row; - - /* Try each column until we find a free one. */ - clashed = FALSE; - for (col = event->start_row_or_col + 1; col < day_view->cols_per_row[day][start_row]; col++) { - for (row = start_row; row <= end_row; row++) { - if (grid[row * E_DAY_VIEW_MAX_COLUMNS + col]) { - clashed = TRUE; - break; - } - } - - if (clashed) - break; - - event->num_columns++; - } -} - - /* This creates or updates the sizes of the canvas items for one day of the main canvas. */ static void @@ -4837,7 +4539,7 @@ e_day_view_ensure_events_sorted (EDayView *day_view) } -static gint +gint e_day_view_event_sort_func (const void *arg1, const void *arg2) { @@ -5774,7 +5476,9 @@ e_day_view_get_long_event_position (EDayView *day_view, if (event->num_columns == 0) return FALSE; - if (!e_day_view_find_long_event_days (day_view, event, + if (!e_day_view_find_long_event_days (event, + day_view->days_shown, + day_view->day_starts, start_day, end_day)) return FALSE; @@ -6037,7 +5741,9 @@ e_day_view_update_top_canvas_drag (EDayView *day_view, day_view->drag_event_num); row = event->start_row_or_col + 1; - if (!e_day_view_find_long_event_days (day_view, event, + if (!e_day_view_find_long_event_days (event, + day_view->days_shown, + day_view->day_starts, &start_day, &end_day)) return; @@ -6450,8 +6156,9 @@ e_day_view_on_top_canvas_drag_data_received (GtkWidget *widget, day -= day_view->drag_event_offset; day = MAX (day, 0); - e_day_view_find_long_event_days (day_view, - event, + e_day_view_find_long_event_days (event, + day_view->days_shown, + day_view->day_starts, &start_day, &end_day); num_days = end_day - start_day + 1; |