diff --git a/src/gui/views/gcal-month-view-row.c b/src/gui/views/gcal-month-view-row.c index 74f7ca82..50a486de 100644 --- a/src/gui/views/gcal-month-view-row.c +++ b/src/gui/views/gcal-month-view-row.c @@ -53,6 +53,8 @@ struct _GcalMonthViewRow GListModel *events; + GcalEventWidgetPool *event_widget_pool; + GHashTable *layout_blocks; gboolean layout_blocks_valid; }; @@ -684,6 +686,37 @@ extract_current_event_widgets (GcalMonthViewRow *self) return g_steal_pointer (&event_widgets); } +static void +return_remaining_event_widgets_to_pool (GcalMonthViewRow *self, + GHashTable *event_widgets) +{ + GHashTableIter iter; + GPtrArray *widgets; + + g_assert (GCAL_IS_MONTH_VIEW_ROW (self)); + g_assert (event_widgets != NULL); + + g_hash_table_iter_init (&iter, event_widgets); + while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &widgets)) + { + g_assert (widgets != NULL); + + while (widgets->len > 0) + { + GtkWidget *widget = g_ptr_array_steal_index_fast (widgets, 0); + + g_signal_handlers_disconnect_by_func (widget, on_event_widget_activated_cb, self); + gtk_widget_unparent (widget); + + gcal_event_widget_pool_reclaim (self->event_widget_pool, g_steal_pointer (&widget)); + } + + g_hash_table_iter_remove (&iter); + } + + g_assert (g_hash_table_size (event_widgets) == 0); +} + static GtkWidget * pick_existing_event_widget (GHashTable *event_widgets, GcalEvent *event) @@ -700,6 +733,26 @@ pick_existing_event_widget (GHashTable *event_widgets, return g_ptr_array_steal_index_fast (widgets, 0); } +static GtkWidget * +pick_or_create_event_widget_for_event (GcalMonthViewRow *self, + GHashTable *event_widgets, + GcalEvent *event) +{ + GtkWidget *event_widget; + + event_widget = pick_existing_event_widget (event_widgets, event); + if (!event_widget) + { + event_widget = gcal_event_widget_pool_take_or_create (self->event_widget_pool, event); + + g_assert (GCAL_IS_EVENT_WIDGET (event_widget)); + + setup_child_widget (self, event_widget); + } + + return g_steal_pointer (&event_widget); +} + static void recalculate_layout_blocks (GcalMonthViewRow *self) { @@ -745,14 +798,10 @@ recalculate_layout_blocks (GcalMonthViewRow *self) { GtkWidget *event_widget; - event_widget = pick_existing_event_widget (event_widgets, event); - if (!event_widget) - { - event_widget = gcal_event_widget_new (event); - if (!gcal_event_get_all_day (event) && !gcal_event_is_multiday (event)) - gcal_event_widget_set_timestamp_policy (GCAL_EVENT_WIDGET (event_widget), GCAL_TIMESTAMP_POLICY_START); - setup_child_widget (self, event_widget); - } + event_widget = pick_or_create_event_widget_for_event (self, event_widgets, event); + + if (!gcal_event_get_all_day (event) && !gcal_event_is_multiday (event)) + gcal_event_widget_set_timestamp_policy (GCAL_EVENT_WIDGET (event_widget), GCAL_TIMESTAMP_POLICY_START); block = g_new (GcalEventBlock, 1); block->event_widget = g_steal_pointer (&event_widget); @@ -765,12 +814,10 @@ recalculate_layout_blocks (GcalMonthViewRow *self) { GtkWidget *new_event_widget; - new_event_widget = pick_existing_event_widget (event_widgets, event); - if (!new_event_widget) - { - new_event_widget = gcal_event_widget_clone (GCAL_EVENT_WIDGET (block->event_widget)); - setup_child_widget (self, new_event_widget); - } + new_event_widget = pick_or_create_event_widget_for_event (self, event_widgets, event); + + if (!gcal_event_get_all_day (event) && !gcal_event_is_multiday (event)) + gcal_event_widget_set_timestamp_policy (GCAL_EVENT_WIDGET (new_event_widget), GCAL_TIMESTAMP_POLICY_START); block = g_new (GcalEventBlock, 1); block->event_widget = g_steal_pointer (&new_event_widget); @@ -814,6 +861,8 @@ recalculate_layout_blocks (GcalMonthViewRow *self) g_hash_table_insert (self->layout_blocks, event, g_steal_pointer (&blocks)); } + return_remaining_event_widgets_to_pool (self, event_widgets); + self->layout_blocks_valid = TRUE; GCAL_EXIT; @@ -1172,6 +1221,7 @@ gcal_month_view_row_finalize (GObject *object) { GcalMonthViewRow *self = (GcalMonthViewRow *)object; + g_clear_object (&self->event_widget_pool); g_clear_pointer (&self->range, gcal_range_unref); G_OBJECT_CLASS (gcal_month_view_row_parent_class)->finalize (object); @@ -1304,9 +1354,16 @@ gcal_month_view_row_init (GcalMonthViewRow *self) } GtkWidget * -gcal_month_view_row_new (void) +gcal_month_view_row_new (GcalEventWidgetPool *event_widget_pool) { - return g_object_new (GCAL_TYPE_MONTH_VIEW_ROW, NULL); + g_autoptr (GcalMonthViewRow) self = NULL; + + g_assert (GCAL_IS_EVENT_WIDGET_POOL (event_widget_pool)); + + self = g_object_new (GCAL_TYPE_MONTH_VIEW_ROW, NULL); + self->event_widget_pool = g_object_ref (event_widget_pool); + + return GTK_WIDGET (g_steal_pointer (&self)); } GcalRange * diff --git a/src/gui/views/gcal-month-view-row.h b/src/gui/views/gcal-month-view-row.h index bedff686..ea1cf8d9 100644 --- a/src/gui/views/gcal-month-view-row.h +++ b/src/gui/views/gcal-month-view-row.h @@ -25,6 +25,7 @@ #include "gcal-context.h" #include "gcal-event.h" +#include "gcal-event-widget-pool.h" #include "gcal-range.h" G_BEGIN_DECLS @@ -32,7 +33,7 @@ G_BEGIN_DECLS #define GCAL_TYPE_MONTH_VIEW_ROW (gcal_month_view_row_get_type()) G_DECLARE_FINAL_TYPE (GcalMonthViewRow, gcal_month_view_row, GCAL, MONTH_VIEW_ROW, GtkWidget) -GtkWidget * gcal_month_view_row_new (void); +GtkWidget * gcal_month_view_row_new (GcalEventWidgetPool *event_widget_pool); GcalRange * gcal_month_view_row_get_range (GcalMonthViewRow *self); diff --git a/src/gui/views/gcal-month-view.c b/src/gui/views/gcal-month-view.c index c7312fd1..b6f98cbb 100644 --- a/src/gui/views/gcal-month-view.c +++ b/src/gui/views/gcal-month-view.c @@ -23,6 +23,7 @@ #include "config.h" #include "gcal-debug.h" +#include "gcal-event-widget-pool.h" #include "gcal-month-cell.h" #include "gcal-month-popover.h" #include "gcal-month-view.h" @@ -56,6 +57,8 @@ struct _GcalMonthView GPtrArray *week_rows; + GcalEventWidgetPool *event_widget_pool; + struct { GtkWidget *popover; GcalMonthViewRow *row; @@ -1737,6 +1740,7 @@ gcal_month_view_finalize (GObject *object) { GcalMonthView *self = (GcalMonthView *)object; + g_clear_object (&self->event_widget_pool); gcal_clear_date_time (&self->selection.start); gcal_clear_date_time (&self->selection.end); gcal_clear_date_time (&self->date); @@ -1836,6 +1840,8 @@ gcal_month_view_init (GcalMonthView *self) { g_autoptr (GDateTime) now = NULL; + self->event_widget_pool = gcal_event_widget_pool_new (); + gtk_widget_init_template (GTK_WIDGET (self)); update_weekday_labels (self); @@ -1847,7 +1853,7 @@ gcal_month_view_init (GcalMonthView *self) self->week_rows = g_ptr_array_new_full (N_TOTAL_ROWS, (GDestroyNotify) gtk_widget_unparent); for (gint i = 0; i < N_TOTAL_ROWS; i++) { - GtkWidget *row = gcal_month_view_row_new (); + GtkWidget *row = gcal_month_view_row_new (self->event_widget_pool); g_signal_connect (row, "event-activated", G_CALLBACK (on_event_widget_activated_cb), self); g_signal_connect (row, "cell-activated", G_CALLBACK (on_month_row_cell_activated_cb), self); g_signal_connect (row, "show-overflow", G_CALLBACK (on_month_row_show_overflow_cb), self);