week-header: implement merging of consecultive events

When an event is placed in the same row consecultively, we must
guarantee that it's only one widget.
This commit is contained in:
Georges Basile Stavracas Neto
2016-12-01 23:48:54 -02:00
parent bb0e927fc2
commit 92ba507b9e
+249 -19
View File
@@ -185,6 +185,205 @@ add_event_to_weekday (GcalWeekHeader *self,
self->events[weekday] = l;
}
static gint
merge_events (GcalWeekHeader *self,
GtkWidget *event,
GtkWidget *to_be_removed)
{
gint deleted_width, current_width;
/* Retrieve the current sizes */
gtk_container_child_get (GTK_CONTAINER (self->grid),
to_be_removed,
"width", &deleted_width,
NULL);
if (event == to_be_removed)
goto out;
gtk_container_child_get (GTK_CONTAINER (self->grid),
event,
"width", &current_width,
NULL);
gtk_widget_destroy (to_be_removed);
/* Update the event's size */
gtk_container_child_set (GTK_CONTAINER (self->grid),
event,
"width", current_width + deleted_width,
NULL);
out:
return deleted_width;
}
static void
check_mergeable_events (GcalWeekHeader *self)
{
gint weekday;
/* We don't need to check the last column */
for (weekday = 0; weekday < 6; weekday++)
{
GList *events_at_weekday, *l;
gint index;
index = 0;
events_at_weekday = self->events[weekday];
for (l = events_at_weekday; l != NULL; l = l->next)
{
GcalEvent *current_event;
gint events_to_merge, i;
current_event = l->data;
events_to_merge = 0;
/* No need to continue if we're hiding the events */
if (!self->expanded && index > 3)
break;
/*
* Horizontally check if the next cells have the same event
* than the current cell.
*/
for (i = 1; i < 7 - weekday; i++)
{
GcalEvent *next_event;
next_event = g_list_nth_data (self->events[weekday + 1], index);
if (next_event != current_event)
break;
events_to_merge++;
}
/* We found events to merge. Lets merge them */
i = 0;
while (events_to_merge > 0)
{
GtkWidget *current_widget, *to_be_removed;
gint removed_cells;
current_widget = gtk_grid_get_child_at (GTK_GRID (self->grid), weekday + i, index);
to_be_removed = gtk_grid_get_child_at (GTK_GRID (self->grid), weekday + i + 1, index);
/* First, remove the events from the cells */
removed_cells = merge_events (self, current_widget, to_be_removed);
events_to_merge -= removed_cells;
i += removed_cells;
}
index++;
}
}
}
static void
split_event_widget_at_column (GcalWeekHeader *self,
GtkWidget *widget,
gint column)
{
GDateTime *week_start, *column_date, *end_column_date;
GcalEvent *event;
gboolean create_before;
gboolean create_after;
gint left_attach;
gint top_attach;
gint new_width;
gint old_width;
week_start = get_start_of_week (self->active_date);
column_date = g_date_time_add_days (week_start, column);
end_column_date = g_date_time_add_days (column_date, 1);
event = gcal_event_widget_get_event (GCAL_EVENT_WIDGET (widget));
create_before = column > 0 && g_date_time_compare (gcal_event_get_date_start (event), column_date) < 0;
create_after = column < 6 && g_date_time_compare (gcal_event_get_date_end (event), end_column_date) >= 0;
gtk_container_child_get (GTK_CONTAINER (self->grid),
widget,
"top_attach", &top_attach,
"left_attach", &left_attach,
"width", &old_width,
NULL);
g_message (" - - - breaking event '%s'", gcal_event_get_summary (event));
if (create_before)
{
GtkWidget *widget_before;
g_message (" - - - - creating new widget before");
widget_before = gcal_event_widget_clone (GCAL_EVENT_WIDGET (widget));
gtk_grid_attach (GTK_GRID (self->grid),
widget_before,
left_attach,
top_attach,
column - left_attach,
1);
new_width = old_width - column + left_attach;
old_width = new_width;
left_attach = column;
/* Update the current event position and size */
gtk_container_child_set (GTK_CONTAINER (self->grid),
widget,
"left_attach", left_attach,
"width", new_width,
NULL);
gtk_widget_show (widget_before);
}
/* Create a new widget after the current widget */
if (create_after)
{
GtkWidget *widget_after;
g_message (" - - - - creating new widget after");
widget_after = gcal_event_widget_clone (GCAL_EVENT_WIDGET (widget));
gcal_event_widget_set_date_start (GCAL_EVENT_WIDGET (widget_after), end_column_date);
gcal_event_widget_set_date_end (GCAL_EVENT_WIDGET (widget_after),
gcal_event_widget_get_date_end (GCAL_EVENT_WIDGET (widget)));
gtk_grid_attach (GTK_GRID (self->grid),
widget_after,
column + 1,
top_attach,
old_width - 1,
1);
new_width = old_width - (column - left_attach + 1);
g_message (" - - - - placing new widget at (x: %d, y: %d, w: %d)",
column + 1,
top_attach,
new_width);
/* Only update the current widget's width */
gtk_container_child_set (GTK_CONTAINER (self->grid),
widget,
"width", new_width,
NULL);
gtk_widget_show (widget_after);
}
g_clear_pointer (&end_column_date, g_date_time_unref);
g_clear_pointer (&column_date, g_date_time_unref);
g_clear_pointer (&week_start, g_date_time_unref);
}
static void
move_events_at_column (GcalWeekHeader *self,
gint column,
@@ -234,16 +433,22 @@ move_events_at_column (GcalWeekHeader *self,
*/
for (l = found_widgets; l != NULL; l = l->next)
{
gint top_attach;
gint top_attach, left_attach, width;
/* Get the widget's current position... */
gtk_container_child_get (GTK_CONTAINER (self->grid),
l->data,
"top_attach", &top_attach,
"left_attach", &left_attach,
"width", &width,
NULL);
g_message (" - - - setting top_attach to %d", top_attach + 1);
/* If this is a multiday event, break it */
if (width > 1)
split_event_widget_at_column (self, l->data, column);
/* And move it to position + 1 */
gtk_container_child_set (GTK_CONTAINER (self->grid),
l->data,
@@ -251,6 +456,9 @@ move_events_at_column (GcalWeekHeader *self,
NULL);
}
/* Check if we eventually can merge events */
check_mergeable_events (self);
g_clear_pointer (&found_widgets, g_list_free);
}
@@ -260,7 +468,7 @@ add_event_to_grid (GcalWeekHeader *self,
gint start,
gint end)
{
GDateTime *widget_start_dt, *widget_end_dt;
GDateTime *week_start, *week_end, *widget_end_dt;
GtkWidget *widget;
gint events_at_weekday;
gint position;
@@ -307,15 +515,15 @@ add_event_to_grid (GcalWeekHeader *self,
if (!gcal_event_is_multiday (event))
return;
week_start = get_start_of_week (self->active_date);
week_end = get_end_of_week (self->active_date);
/* Setup the event's start date */
widget_start_dt = get_start_of_week (self->active_date);
widget_end_dt = g_date_time_add_days (widget_start_dt, 1);
widget_end_dt = g_date_time_add_days (week_start, 1);
gcal_event_widget_set_date_start (GCAL_EVENT_WIDGET (widget), widget_start_dt);
gcal_event_widget_set_date_start (GCAL_EVENT_WIDGET (widget), week_start);
gcal_event_widget_set_date_end (GCAL_EVENT_WIDGET (widget), widget_end_dt);
g_clear_pointer (&widget_start_dt, g_date_time_unref);
/*
* In addition to moving the current column's events below, multiday
* events must also move the events from ~all~ the columns it spans
@@ -323,9 +531,11 @@ add_event_to_grid (GcalWeekHeader *self,
*/
for (i = start + 1; i <= end; i++)
{
GDateTime *new_widget_end_dt;
gint new_position;
events_at_weekday = g_list_length (self->events[i]);
new_widget_end_dt = g_date_time_add_days (widget_end_dt, 1);
/* Add the event to that day */
add_event_to_weekday (self, event, i);
@@ -333,7 +543,6 @@ add_event_to_grid (GcalWeekHeader *self,
g_message (" - - adding event to column %d", i);
g_message (" - - - there are %d events in this column", events_at_weekday);
/* Check the event position at this weekday */
new_position = g_list_index (self->events[i], event) + 1;
@@ -344,28 +553,49 @@ add_event_to_grid (GcalWeekHeader *self,
/* Add the event to the grid */
if (new_position == position)
{
GDateTime *new_widget_end_dt;
new_widget_end_dt = g_date_time_add_days (widget_end_dt, 1);
/* Update the widget's end date */
gcal_event_widget_set_date_end (GCAL_EVENT_WIDGET (widget), new_widget_end_dt);
gtk_container_child_set (GTK_CONTAINER (self->grid),
widget,
"width", i - start + 1,
NULL);
g_clear_pointer (&widget_end_dt, g_date_time_unref);
widget_end_dt = new_widget_end_dt;
}
else
{
/* TODO: clone the widget */
GDateTime *cloned_widget_start_dt;
GtkWidget *cloned_widget;
cloned_widget_start_dt = g_date_time_add_days (week_start, i);
cloned_widget = gcal_event_widget_clone (GCAL_EVENT_WIDGET (widget));
g_message (" - - - - cloning event");
gtk_grid_attach (GTK_GRID (self->grid),
cloned_widget,
i,
new_position,
1,
1);
gcal_event_widget_set_date_start (GCAL_EVENT_WIDGET (cloned_widget), cloned_widget_start_dt);
/* From now on, let's modify this widget */
widget = cloned_widget;
g_clear_pointer (&cloned_widget_start_dt, g_date_time_unref);
}
/* Update the widget's end date */
gcal_event_widget_set_date_end (GCAL_EVENT_WIDGET (widget), new_widget_end_dt);
g_clear_pointer (&widget_end_dt, g_date_time_unref);
widget_end_dt = new_widget_end_dt;
}
gtk_widget_show (widget);
g_clear_pointer (&widget_end_dt, g_date_time_unref);
g_clear_pointer (&week_start, g_date_time_unref);
g_clear_pointer (&week_end, g_date_time_unref);
}
static void