month-view: win the fight against the sizing machinery
We can now guarantee that the month cells unconditionally get their desired allocations, but the event widgets are only created when necessary. I won.
This commit is contained in:
+28
-43
@@ -127,7 +127,6 @@ struct _GcalMonthView
|
|||||||
GcalManager *manager;
|
GcalManager *manager;
|
||||||
|
|
||||||
gboolean pending_event_allocation;
|
gboolean pending_event_allocation;
|
||||||
gboolean pending_child_allocation;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#define MIRROR(val,start,end) (start + (val / end) * end + (end - val % end))
|
#define MIRROR(val,start,end) (start + (val / end) * end + (end - val % end))
|
||||||
@@ -437,10 +436,8 @@ static gboolean
|
|||||||
update_month_cells (GcalMonthView *self)
|
update_month_cells (GcalMonthView *self)
|
||||||
{
|
{
|
||||||
g_autoptr (GDateTime) dt;
|
g_autoptr (GDateTime) dt;
|
||||||
gboolean changed;
|
|
||||||
guint row, col;
|
guint row, col;
|
||||||
|
|
||||||
changed = FALSE;
|
|
||||||
dt = g_date_time_new_local (self->date->year, self->date->month, 1, 0, 0, 0);
|
dt = g_date_time_new_local (self->date->year, self->date->month, 1, 0, 0, 0);
|
||||||
|
|
||||||
for (row = 0; row < 6; row++)
|
for (row = 0; row < 6; row++)
|
||||||
@@ -464,26 +461,18 @@ update_month_cells (GcalMonthView *self)
|
|||||||
/* Cell date */
|
/* Cell date */
|
||||||
cell_date = g_date_time_add_days (dt, row * 7 + col - self->days_delay);
|
cell_date = g_date_time_add_days (dt, row * 7 + col - self->days_delay);
|
||||||
|
|
||||||
changed |= datetime_compare_date (gcal_month_cell_get_date (cell), cell_date) != 0;
|
|
||||||
|
|
||||||
gcal_month_cell_set_date (cell, cell_date);
|
gcal_month_cell_set_date (cell, cell_date);
|
||||||
|
|
||||||
/* Different month */
|
/* Different month */
|
||||||
different_month = day < self->days_delay ||
|
different_month = day < self->days_delay ||
|
||||||
day - self->days_delay >= icaltime_days_in_month (self->date->month, self->date->year);
|
day - self->days_delay >= icaltime_days_in_month (self->date->month, self->date->year);
|
||||||
|
|
||||||
changed |= different_month != gcal_month_cell_get_different_month (cell);
|
|
||||||
|
|
||||||
gcal_month_cell_set_different_month (cell, different_month);
|
gcal_month_cell_set_different_month (cell, different_month);
|
||||||
|
|
||||||
if (different_month)
|
if (different_month)
|
||||||
{
|
{
|
||||||
changed |= gcal_month_cell_get_selected (cell) != FALSE;
|
|
||||||
gcal_month_cell_set_selected (cell, FALSE);
|
gcal_month_cell_set_selected (cell, FALSE);
|
||||||
|
|
||||||
changed |= gcal_month_cell_get_overflow (cell) != 0;
|
|
||||||
gcal_month_cell_set_overflow (cell, 0);
|
gcal_month_cell_set_overflow (cell, 0);
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -491,8 +480,6 @@ update_month_cells (GcalMonthView *self)
|
|||||||
if (g_hash_table_contains (self->overflow_cells, GINT_TO_POINTER (day)))
|
if (g_hash_table_contains (self->overflow_cells, GINT_TO_POINTER (day)))
|
||||||
l = g_hash_table_lookup (self->overflow_cells, GINT_TO_POINTER (day));
|
l = g_hash_table_lookup (self->overflow_cells, GINT_TO_POINTER (day));
|
||||||
|
|
||||||
changed |= gcal_month_cell_get_overflow (cell) != g_list_length (l);
|
|
||||||
|
|
||||||
gcal_month_cell_set_overflow (cell, l ? g_list_length (l) : 0);
|
gcal_month_cell_set_overflow (cell, l ? g_list_length (l) : 0);
|
||||||
|
|
||||||
/* Selection */
|
/* Selection */
|
||||||
@@ -516,14 +503,11 @@ update_month_cells (GcalMonthView *self)
|
|||||||
datetime_compare_date (gcal_month_cell_get_date (cell), selection_end) <= 0;
|
datetime_compare_date (gcal_month_cell_get_date (cell), selection_end) <= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
changed |= gcal_month_cell_get_selected (cell) != selected;
|
|
||||||
|
|
||||||
gcal_month_cell_set_selected (cell, selected);
|
gcal_month_cell_set_selected (cell, selected);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self->update_grid_id = 0;
|
self->update_grid_id = 0;
|
||||||
self->pending_child_allocation = changed;
|
|
||||||
|
|
||||||
return G_SOURCE_REMOVE;
|
return G_SOURCE_REMOVE;
|
||||||
}
|
}
|
||||||
@@ -1487,6 +1471,7 @@ gcal_month_view_size_allocate (GtkWidget *widget,
|
|||||||
GHashTableIter iter;
|
GHashTableIter iter;
|
||||||
GtkAllocation child_allocation;
|
GtkAllocation child_allocation;
|
||||||
GtkAllocation cell_alloc;
|
GtkAllocation cell_alloc;
|
||||||
|
GtkAllocation old_alloc;
|
||||||
GcalMonthView *self;
|
GcalMonthView *self;
|
||||||
GtkWidget *child_widget;
|
GtkWidget *child_widget;
|
||||||
GtkWidget *month_cell;
|
GtkWidget *month_cell;
|
||||||
@@ -1506,32 +1491,8 @@ gcal_month_view_size_allocate (GtkWidget *widget,
|
|||||||
|
|
||||||
self = gcal_month_view_get_instance_private (GCAL_MONTH_VIEW (widget));
|
self = gcal_month_view_get_instance_private (GCAL_MONTH_VIEW (widget));
|
||||||
|
|
||||||
/*
|
|
||||||
* If nothing changed, and the month cells didn't request an allocation,
|
|
||||||
* and the size is the same, return early here.
|
|
||||||
*/
|
|
||||||
if (!self->pending_event_allocation &&
|
|
||||||
!self->pending_child_allocation &&
|
|
||||||
allocation->width == gtk_widget_get_allocated_width (widget) &&
|
|
||||||
allocation->height == gtk_widget_get_allocated_height (widget))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Remove every widget' parts, but the master widget */
|
|
||||||
widgets = g_hash_table_get_values (self->children);
|
|
||||||
|
|
||||||
for (aux = widgets; aux != NULL; aux = g_list_next (aux))
|
|
||||||
l = g_list_concat (l, g_list_copy (g_list_next (aux->data)));
|
|
||||||
|
|
||||||
g_list_free (widgets);
|
|
||||||
|
|
||||||
g_list_free_full (l, (GDestroyNotify) gtk_widget_destroy);
|
|
||||||
|
|
||||||
/* Clean overflow information */
|
|
||||||
g_hash_table_remove_all (self->overflow_cells);
|
|
||||||
|
|
||||||
/* Allocate the widget */
|
/* Allocate the widget */
|
||||||
|
gtk_widget_get_allocation (widget, &old_alloc);
|
||||||
gtk_widget_set_allocation (widget, allocation);
|
gtk_widget_set_allocation (widget, allocation);
|
||||||
|
|
||||||
if (gtk_widget_get_realized (widget))
|
if (gtk_widget_get_realized (widget))
|
||||||
@@ -1557,6 +1518,31 @@ gcal_month_view_size_allocate (GtkWidget *widget,
|
|||||||
|
|
||||||
gtk_widget_size_allocate (self->grid, &child_allocation);
|
gtk_widget_size_allocate (self->grid, &child_allocation);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* At this point, the internal widgets are already allocated and happy. Thus, if no new event
|
||||||
|
* was added and the size is the same, we don't need to create and add new event widgets. This
|
||||||
|
* breaks the indirect allocation cycle.
|
||||||
|
*/
|
||||||
|
if (!self->pending_event_allocation &&
|
||||||
|
allocation->width == old_alloc.width &&
|
||||||
|
allocation->height == old_alloc.height)
|
||||||
|
{
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Remove every widget' parts, but the master widget */
|
||||||
|
widgets = g_hash_table_get_values (self->children);
|
||||||
|
|
||||||
|
for (aux = widgets; aux != NULL; aux = g_list_next (aux))
|
||||||
|
l = g_list_concat (l, g_list_copy (g_list_next (aux->data)));
|
||||||
|
|
||||||
|
g_list_free (widgets);
|
||||||
|
|
||||||
|
g_list_free_full (l, (GDestroyNotify) gtk_widget_destroy);
|
||||||
|
|
||||||
|
/* Clean overflow information */
|
||||||
|
g_hash_table_remove_all (self->overflow_cells);
|
||||||
|
|
||||||
/* Event widgets */
|
/* Event widgets */
|
||||||
count_events_per_day (self, events_at_day);
|
count_events_per_day (self, events_at_day);
|
||||||
|
|
||||||
@@ -1888,10 +1874,10 @@ gcal_month_view_size_allocate (GtkWidget *widget,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
queue_update_month_cells (self);
|
queue_update_month_cells (self);
|
||||||
|
|
||||||
self->pending_event_allocation = FALSE;
|
self->pending_event_allocation = FALSE;
|
||||||
self->pending_child_allocation = FALSE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
@@ -2114,7 +2100,6 @@ gcal_month_view_init (GcalMonthView *self)
|
|||||||
self->single_cell_children = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, (GDestroyNotify) g_list_free);
|
self->single_cell_children = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, (GDestroyNotify) g_list_free);
|
||||||
self->overflow_cells = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, (GDestroyNotify) g_list_free);
|
self->overflow_cells = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, (GDestroyNotify) g_list_free);
|
||||||
self->pending_event_allocation = FALSE;
|
self->pending_event_allocation = FALSE;
|
||||||
self->pending_child_allocation = FALSE;
|
|
||||||
|
|
||||||
self->k = gtk_widget_get_direction (GTK_WIDGET (self)) == GTK_TEXT_DIR_RTL;
|
self->k = gtk_widget_get_direction (GTK_WIDGET (self)) == GTK_TEXT_DIR_RTL;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user