From bbc041eed9120e4a35047c23faf745fcb89ae6fe Mon Sep 17 00:00:00 2001 From: Georges Basile Stavracas Neto Date: Tue, 5 May 2026 21:28:30 -0300 Subject: [PATCH] views/month: Recycle event widgets using the pool Create a new GcalEventWidgetPool shared between all month view rows. The event widgets are distributed to rows as needed. When rows are done with the event widget, the give them back to the pool so that other rows can reuse them. Part-of: --- src/gui/views/gcal-month-view-row.c | 89 +++++++++++++++++++++++------ src/gui/views/gcal-month-view-row.h | 3 +- src/gui/views/gcal-month-view.c | 8 ++- 3 files changed, 82 insertions(+), 18 deletions(-) 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);