month-view: improve layout algorithm
Multiday event handling was a mess, and still it. But this commit makes it at least layout things correctly. It's not perfect, though; This commit brought back that terrible allocation cycle issue, since we're showing and hiding events in size-allocate.
This commit is contained in:
+63
-58
@@ -88,11 +88,6 @@ struct _GcalMonthView
|
|||||||
*/
|
*/
|
||||||
GHashTable *overflow_cells;
|
GHashTable *overflow_cells;
|
||||||
|
|
||||||
/*
|
|
||||||
* Set containing the master widgets hidden for delete;
|
|
||||||
*/
|
|
||||||
GHashTable *hidden_as_overflow;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* the cell on which its drawn the first day of the month, in the first row, 0 for the first
|
* the cell on which its drawn the first day of the month, in the first row, 0 for the first
|
||||||
* cell, 1 for the second, and so on, this takes first_weekday into account already.
|
* cell, 1 for the second, and so on, this takes first_weekday into account already.
|
||||||
@@ -305,14 +300,15 @@ get_month_cell_at_position (GcalMonthView *self,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static void
|
||||||
get_widget_parts (gint first_cell,
|
get_widget_parts (gint first_cell,
|
||||||
gint last_cell,
|
gint last_cell,
|
||||||
gint natural_height,
|
gint natural_height,
|
||||||
gdouble *vertical_cell_space,
|
gdouble *vertical_cell_space,
|
||||||
gdouble *size_left,
|
gdouble *size_left,
|
||||||
GArray *cells,
|
GArray *cells,
|
||||||
GArray *lengths)
|
GArray *lengths,
|
||||||
|
GArray *length_visible)
|
||||||
{
|
{
|
||||||
gdouble old_y;
|
gdouble old_y;
|
||||||
gdouble y;
|
gdouble y;
|
||||||
@@ -331,17 +327,22 @@ get_widget_parts (gint first_cell,
|
|||||||
|
|
||||||
for (i = first_cell; i <= last_cell; i++)
|
for (i = first_cell; i <= last_cell; i++)
|
||||||
{
|
{
|
||||||
if (size_left[i] < natural_height)
|
gboolean visible_at_range;
|
||||||
return FALSE;
|
gboolean different_row;
|
||||||
|
|
||||||
|
visible_at_range = size_left[i] >= natural_height;
|
||||||
|
different_row = i / 7 != (i - 1) / 7;
|
||||||
|
|
||||||
y = vertical_cell_space[i] - size_left[i];
|
y = vertical_cell_space[i] - size_left[i];
|
||||||
|
|
||||||
if (old_y == -1.0 || y != old_y)
|
if (old_y == -1.0 || y != old_y || different_row)
|
||||||
{
|
{
|
||||||
current_part_length = 1;
|
current_part_length = 1;
|
||||||
|
old_y = y;
|
||||||
|
|
||||||
g_array_append_val (cells, i);
|
g_array_append_val (cells, i);
|
||||||
g_array_append_val (lengths, current_part_length);
|
g_array_append_val (lengths, current_part_length);
|
||||||
old_y = y;
|
g_array_append_val (length_visible, visible_at_range);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -349,8 +350,6 @@ get_widget_parts (gint first_cell,
|
|||||||
g_array_index (lengths, gint, lengths->len - 1) = current_part_length;
|
g_array_index (lengths, gint, lengths->len - 1) = current_part_length;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -1175,8 +1174,6 @@ gcal_month_view_remove (GtkContainer *container,
|
|||||||
g_hash_table_remove (self->children, uuid);
|
g_hash_table_remove (self->children, uuid);
|
||||||
else
|
else
|
||||||
g_hash_table_replace (self->children, g_strdup (uuid), l);
|
g_hash_table_replace (self->children, g_strdup (uuid), l);
|
||||||
|
|
||||||
g_hash_table_remove (self->hidden_as_overflow, uuid);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
@@ -1295,7 +1292,6 @@ gcal_month_view_finalize (GObject *object)
|
|||||||
g_clear_pointer (&self->children, g_hash_table_destroy);
|
g_clear_pointer (&self->children, g_hash_table_destroy);
|
||||||
g_clear_pointer (&self->single_cell_children, g_hash_table_destroy);
|
g_clear_pointer (&self->single_cell_children, g_hash_table_destroy);
|
||||||
g_clear_pointer (&self->overflow_cells, g_hash_table_destroy);
|
g_clear_pointer (&self->overflow_cells, g_hash_table_destroy);
|
||||||
g_clear_pointer (&self->hidden_as_overflow, g_hash_table_destroy);
|
|
||||||
g_clear_pointer (&self->multi_cell_children, g_list_free);
|
g_clear_pointer (&self->multi_cell_children, g_list_free);
|
||||||
|
|
||||||
g_clear_object (&self->manager);
|
g_clear_object (&self->manager);
|
||||||
@@ -1500,12 +1496,16 @@ gcal_month_view_size_allocate (GtkWidget *widget,
|
|||||||
*/
|
*/
|
||||||
for (l = self->multi_cell_children; l; l = g_list_next (l))
|
for (l = self->multi_cell_children; l; l = g_list_next (l))
|
||||||
{
|
{
|
||||||
|
g_autoptr (GArray) visible_at_length = NULL;
|
||||||
g_autoptr (GArray) lengths = NULL;
|
g_autoptr (GArray) lengths = NULL;
|
||||||
g_autoptr (GArray) cells = NULL;
|
g_autoptr (GArray) cells = NULL;
|
||||||
GDateTime *date;
|
GDateTime *date;
|
||||||
GcalEvent *event;
|
GcalEvent *event;
|
||||||
gboolean visible, all_day;
|
gboolean all_day;
|
||||||
gint first_cell, last_cell, first_row, last_row, start, end;
|
gint first_cell, last_cell;
|
||||||
|
gint first_row, last_row;
|
||||||
|
gint start, end;
|
||||||
|
gint cell;
|
||||||
|
|
||||||
child_widget = (GtkWidget*) l->data;
|
child_widget = (GtkWidget*) l->data;
|
||||||
event = gcal_event_widget_get_event (l->data);
|
event = gcal_event_widget_get_event (l->data);
|
||||||
@@ -1513,9 +1513,6 @@ gcal_month_view_size_allocate (GtkWidget *widget,
|
|||||||
all_day = gcal_event_get_all_day (event);
|
all_day = gcal_event_get_all_day (event);
|
||||||
child_context = gtk_widget_get_style_context (l->data);
|
child_context = gtk_widget_get_style_context (l->data);
|
||||||
|
|
||||||
if (!gtk_widget_is_visible (child_widget) && !g_hash_table_contains (self->hidden_as_overflow, uuid))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
gtk_widget_show (child_widget);
|
gtk_widget_show (child_widget);
|
||||||
gtk_widget_get_preferred_height (child_widget, &minimum_height, NULL);
|
gtk_widget_get_preferred_height (child_widget, &minimum_height, NULL);
|
||||||
|
|
||||||
@@ -1573,11 +1570,11 @@ gcal_month_view_size_allocate (GtkWidget *widget,
|
|||||||
*/
|
*/
|
||||||
first_row = first_cell / 7;
|
first_row = first_cell / 7;
|
||||||
last_row = last_cell / 7;
|
last_row = last_cell / 7;
|
||||||
visible = TRUE;
|
|
||||||
cells = g_array_sized_new (TRUE, TRUE, sizeof (gint), 16);
|
cells = g_array_sized_new (TRUE, TRUE, sizeof (gint), 16);
|
||||||
lengths = g_array_sized_new (TRUE, TRUE, sizeof (gint), 16);
|
lengths = g_array_sized_new (TRUE, TRUE, sizeof (gint), 16);
|
||||||
|
visible_at_length = g_array_sized_new (TRUE, TRUE, sizeof (gboolean), 16);
|
||||||
|
|
||||||
for (row = first_row; row <= last_row && visible; row++)
|
for (row = first_row; row <= last_row; row++)
|
||||||
{
|
{
|
||||||
start = row * 7 + self->k * 6;
|
start = row * 7 + self->k * 6;
|
||||||
end = row * 7 + (1 - self->k) * 6;
|
end = row * 7 + (1 - self->k) * 6;
|
||||||
@@ -1587,51 +1584,42 @@ gcal_month_view_size_allocate (GtkWidget *widget,
|
|||||||
if (row == last_row)
|
if (row == last_row)
|
||||||
end = last_cell;
|
end = last_cell;
|
||||||
|
|
||||||
visible = get_widget_parts (start, end, minimum_height, vertical_cell_space, size_left, cells, lengths);
|
get_widget_parts (start, end,
|
||||||
|
minimum_height,
|
||||||
|
vertical_cell_space,
|
||||||
|
size_left,
|
||||||
|
cells,
|
||||||
|
lengths,
|
||||||
|
visible_at_length);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* No space left, add to the overflow and continue */
|
for (cell = 0; cell < cells->len; cell++)
|
||||||
if (!visible)
|
|
||||||
{
|
|
||||||
gtk_widget_hide (child_widget);
|
|
||||||
g_hash_table_add (self->hidden_as_overflow, g_strdup (uuid));
|
|
||||||
|
|
||||||
for (row = first_cell; row <= last_cell; row++)
|
|
||||||
{
|
|
||||||
aux = g_hash_table_lookup (self->overflow_cells, GINT_TO_POINTER (row));
|
|
||||||
aux = g_list_append (aux, child_widget);
|
|
||||||
|
|
||||||
if (g_list_length (aux) == 1)
|
|
||||||
g_hash_table_insert (self->overflow_cells, GINT_TO_POINTER (row), aux);
|
|
||||||
else
|
|
||||||
g_hash_table_replace (self->overflow_cells, GINT_TO_POINTER (row), g_list_copy (aux));
|
|
||||||
}
|
|
||||||
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (row = 0; row < cells->len; row++)
|
|
||||||
{
|
{
|
||||||
g_autoptr (GDateTime) dt_start = NULL;
|
g_autoptr (GDateTime) dt_start = NULL;
|
||||||
g_autoptr (GDateTime) dt_end = NULL;
|
g_autoptr (GDateTime) dt_end = NULL;
|
||||||
|
gboolean visible;
|
||||||
gdouble width;
|
gdouble width;
|
||||||
gint cell_idx;
|
gint cell_idx;
|
||||||
gint length;
|
gint length;
|
||||||
gint real_row;
|
|
||||||
gint column;
|
gint column;
|
||||||
gint day;
|
gint day;
|
||||||
|
|
||||||
cell_idx = g_array_index (cells, gint, row);
|
visible = g_array_index (visible_at_length, gboolean, cell);
|
||||||
length = g_array_index (lengths, gint, row);
|
cell_idx = g_array_index (cells, gint, cell);
|
||||||
real_row = cell_idx / 7;
|
length = g_array_index (lengths, gint, cell);
|
||||||
|
row = cell_idx / 7;
|
||||||
column = cell_idx % 7;
|
column = cell_idx % 7;
|
||||||
day = cell_idx - self->days_delay + 1;
|
day = cell_idx - self->days_delay + 1;
|
||||||
|
|
||||||
/* Day number is calculated differently on RTL languages */
|
/* Day number is calculated differently on RTL languages */
|
||||||
if (self->k)
|
if (self->k)
|
||||||
day = 7 * real_row + MIRROR (cell_idx % 7, 0, 7) - self->days_delay - length + 1;
|
day = 7 * row + MIRROR (cell_idx % 7, 0, 7) - self->days_delay - length + 1;
|
||||||
|
|
||||||
if (row != 0)
|
/*
|
||||||
|
* Setup a new event widget when the cell index changes. This happens when
|
||||||
|
* the event has a different y position, or when the row changed.
|
||||||
|
*/
|
||||||
|
if (cell != 0)
|
||||||
{
|
{
|
||||||
child_widget = gcal_event_widget_clone (GCAL_EVENT_WIDGET (child_widget));
|
child_widget = gcal_event_widget_clone (GCAL_EVENT_WIDGET (child_widget));
|
||||||
|
|
||||||
@@ -1644,11 +1632,32 @@ gcal_month_view_size_allocate (GtkWidget *widget,
|
|||||||
aux = g_list_append (aux, child_widget);
|
aux = g_list_append (aux, child_widget);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* No space left, add to the overflow and continue */
|
||||||
|
if (!visible)
|
||||||
|
{
|
||||||
|
gint idx;
|
||||||
|
|
||||||
|
gtk_widget_hide (child_widget);
|
||||||
|
|
||||||
|
for (idx = cell_idx; idx < cell_idx + length; idx++)
|
||||||
|
{
|
||||||
|
aux = g_hash_table_lookup (self->overflow_cells, GINT_TO_POINTER (idx));
|
||||||
|
aux = g_list_append (aux, child_widget);
|
||||||
|
|
||||||
|
if (g_list_length (aux) == 1)
|
||||||
|
g_hash_table_insert (self->overflow_cells, GINT_TO_POINTER (idx), aux);
|
||||||
|
else
|
||||||
|
g_hash_table_replace (self->overflow_cells, GINT_TO_POINTER (idx), g_list_copy (aux));
|
||||||
|
}
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
/* Retrieve the cell widget */
|
/* Retrieve the cell widget */
|
||||||
if (self->k)
|
if (self->k)
|
||||||
month_cell = self->month_cell[real_row][6 - column];
|
month_cell = self->month_cell[row][6 - column];
|
||||||
else
|
else
|
||||||
month_cell = self->month_cell[real_row][column];
|
month_cell = self->month_cell[row][column];
|
||||||
|
|
||||||
gtk_widget_get_allocation (month_cell, &cell_alloc);
|
gtk_widget_get_allocation (month_cell, &cell_alloc);
|
||||||
|
|
||||||
@@ -1689,7 +1698,6 @@ gcal_month_view_size_allocate (GtkWidget *widget,
|
|||||||
child_allocation.height = minimum_height;
|
child_allocation.height = minimum_height;
|
||||||
|
|
||||||
gtk_widget_size_allocate (child_widget, &child_allocation);
|
gtk_widget_size_allocate (child_widget, &child_allocation);
|
||||||
g_hash_table_remove (self->hidden_as_overflow, uuid);
|
|
||||||
|
|
||||||
/* update size_left */
|
/* update size_left */
|
||||||
for (j = 0; j < length; j++)
|
for (j = 0; j < length; j++)
|
||||||
@@ -1732,7 +1740,7 @@ gcal_month_view_size_allocate (GtkWidget *widget,
|
|||||||
event = gcal_event_widget_get_event (aux->data);
|
event = gcal_event_widget_get_event (aux->data);
|
||||||
uuid = gcal_event_get_uid (event);
|
uuid = gcal_event_get_uid (event);
|
||||||
|
|
||||||
if (!gtk_widget_is_visible (child_widget) && !g_hash_table_contains (self->hidden_as_overflow, uuid))
|
if (!gtk_widget_is_visible (child_widget))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
gtk_widget_show (child_widget);
|
gtk_widget_show (child_widget);
|
||||||
@@ -1742,7 +1750,6 @@ gcal_month_view_size_allocate (GtkWidget *widget,
|
|||||||
if (size_left[cell] < minimum_height)
|
if (size_left[cell] < minimum_height)
|
||||||
{
|
{
|
||||||
gtk_widget_hide (child_widget);
|
gtk_widget_hide (child_widget);
|
||||||
g_hash_table_add (self->hidden_as_overflow, g_strdup (uuid));
|
|
||||||
|
|
||||||
l = g_hash_table_lookup (self->overflow_cells, GINT_TO_POINTER (cell));
|
l = g_hash_table_lookup (self->overflow_cells, GINT_TO_POINTER (cell));
|
||||||
l = g_list_append (l, child_widget);
|
l = g_list_append (l, child_widget);
|
||||||
@@ -1771,7 +1778,6 @@ gcal_month_view_size_allocate (GtkWidget *widget,
|
|||||||
child_allocation.height = minimum_height;
|
child_allocation.height = minimum_height;
|
||||||
gtk_widget_show (child_widget);
|
gtk_widget_show (child_widget);
|
||||||
gtk_widget_size_allocate (child_widget, &child_allocation);
|
gtk_widget_size_allocate (child_widget, &child_allocation);
|
||||||
g_hash_table_remove (self->hidden_as_overflow, uuid);
|
|
||||||
|
|
||||||
size_left[cell] -= minimum_height + margin.top + margin.bottom;
|
size_left[cell] -= minimum_height + margin.top + margin.bottom;
|
||||||
}
|
}
|
||||||
@@ -2001,7 +2007,6 @@ gcal_month_view_init (GcalMonthView *self)
|
|||||||
self->children = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) g_list_free);
|
self->children = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (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->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->hidden_as_overflow = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
|
|
||||||
|
|
||||||
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