[gnome-calendar: 16/17] month-view: fix rtl
- From: Georges Basile Stavracas Neto <gbsneto src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-calendar: 16/17] month-view: fix rtl
- Date: Wed, 15 Nov 2017 21:26:22 +0000 (UTC)
commit 54839efbf4f47652f7441232cca4cde561d3aea2
Author: Georges Basile Stavracas Neto <georges stavracas gmail com>
Date: Wed Nov 15 19:02:24 2017 -0200
month-view: fix rtl
This removes much of the subtle complexities of the size allocation
function in month view, and finally delivers a readable and working
implementation of the month view.
This also introduces a small code refactoring, and fixes clicking
on a cell on RTL.
src/views/gcal-month-view.c | 219 ++++++++++++++++++------------------------
1 files changed, 94 insertions(+), 125 deletions(-)
---
diff --git a/src/views/gcal-month-view.c b/src/views/gcal-month-view.c
index 2a55367..b679ca5 100644
--- a/src/views/gcal-month-view.c
+++ b/src/views/gcal-month-view.c
@@ -129,8 +129,6 @@ struct _GcalMonthView
gboolean pending_event_allocation;
};
-#define MIRROR(val,start,end) (start + (val / end) * end + (end - val % end))
-
static void gcal_view_interface_init (GcalViewInterface *iface);
static void gtk_buildable_interface_init (GtkBuildableIface *iface);
@@ -165,16 +163,6 @@ static guint signals[NUM_SIGNALS] = { 0, };
* Auxiliary functions
*/
-static inline gint
-real_cell (gint cell,
- gboolean rtl)
-{
- if (cell < 0)
- return cell;
-
- return rtl ? MIRROR (cell, 0, 7) - 1 : cell;
-}
-
static inline void
cancel_selection (GcalMonthView *self)
{
@@ -302,17 +290,17 @@ get_month_cell_at_position (GcalMonthView *self,
}
static void
-get_widget_parts (GcalMonthView *self,
- gint first_cell,
- gint last_cell,
- gint natural_height,
- gdouble *vertical_cell_space,
- gdouble *size_left,
- GArray *cells,
- GArray *lengths,
- GArray *length_visible,
- gint *events_at_day,
- gint *allocated_events_at_day)
+calculate_multiday_event_blocks (GcalMonthView *self,
+ gint first_cell,
+ gint last_cell,
+ gint natural_height,
+ gdouble *vertical_cell_space,
+ gdouble *size_left,
+ GArray *cells,
+ GArray *lengths,
+ GArray *length_visible,
+ gint *events_at_day,
+ gint *allocated_events_at_day)
{
gboolean was_visible;
gdouble old_y;
@@ -320,6 +308,8 @@ get_widget_parts (GcalMonthView *self,
gint current_part_length;
gint i;
+ GCAL_ENTRY;
+
old_y = -1.0;
current_part_length = 0;
was_visible = FALSE;
@@ -331,6 +321,8 @@ get_widget_parts (GcalMonthView *self,
first_cell = swap;
}
+ GCAL_TRACE_MSG ("Calculating event blocks from cell %d to cell %d", first_cell, last_cell);
+
for (i = first_cell; i <= last_cell; i++)
{
gboolean visible_at_range;
@@ -362,6 +354,8 @@ get_widget_parts (GcalMonthView *self,
if (old_y == -1.0 || y != old_y || different_row || was_visible != visible_at_range)
{
+ GCAL_TRACE_MSG ("Breaking event at cell %d (previous section was %d)", i, current_part_length);
+
current_part_length = 1;
old_y = y;
@@ -377,6 +371,8 @@ get_widget_parts (GcalMonthView *self,
was_visible = visible_at_range;
}
+
+ GCAL_EXIT;
}
static void
@@ -1487,9 +1483,11 @@ gcal_month_view_size_allocate (GtkWidget *widget,
gint minimum_height;
gint header_height;
gint grid_height;
- gint i, j, sw, row;
+ gint i, j;
+
+ GCAL_ENTRY;
- self = gcal_month_view_get_instance_private (GCAL_MONTH_VIEW (widget));
+ self = GCAL_MONTH_VIEW (widget);
/* Allocate the widget */
gtk_widget_get_allocation (widget, &old_alloc);
@@ -1527,7 +1525,8 @@ gcal_month_view_size_allocate (GtkWidget *widget,
allocation->width == old_alloc.width &&
allocation->height == old_alloc.height)
{
- goto out;
+ GCAL_TRACE_MSG ("Events didn't change, stopping here");
+ GCAL_GOTO (out);
}
/* Remove every widget' parts, but the master widget */
@@ -1554,8 +1553,6 @@ gcal_month_view_size_allocate (GtkWidget *widget,
size_left[i] = h;
}
- sw = 1 - 2 * self->k;
-
/*
* Allocate multidays events before single day events, as they have a
* higher priority. Multiday events have a master event, and clones
@@ -1563,15 +1560,16 @@ gcal_month_view_size_allocate (GtkWidget *widget,
*/
for (l = self->multi_cell_children; l; l = g_list_next (l))
{
+ g_autoptr (GDateTime) start_date = NULL;
+ g_autoptr (GDateTime) end_date = NULL;
g_autoptr (GArray) visible_at_length = NULL;
g_autoptr (GArray) lengths = NULL;
- g_autoptr (GArray) cells = NULL;
- GDateTime *date;
+ g_autoptr (GArray) blocks = NULL;
GcalEvent *event;
gboolean all_day;
- gint first_cell, last_cell;
- gint first_row, last_row;
- gint cell;
+ gint event_block;
+ gint first_cell;
+ gint last_cell;
child_widget = (GtkWidget*) l->data;
event = gcal_event_widget_get_event (l->data);
@@ -1584,117 +1582,88 @@ gcal_month_view_size_allocate (GtkWidget *widget,
* we're visualizing, the first cell is the event's day of the
* month. Otherwise, the first cell is the 1st day of the month.
*/
- j = 1;
- date = gcal_event_get_date_start (event);
- date = all_day ? g_date_time_ref (date) : g_date_time_to_local (date);
+ first_cell = 1;
+ start_date = gcal_event_get_date_start (event);
+ start_date = all_day ? g_date_time_ref (start_date) : g_date_time_to_local (start_date);
- if (g_date_time_get_year (date) == self->date->year &&
- g_date_time_get_month (date) == self->date->month)
+ if (g_date_time_get_year (start_date) == self->date->year &&
+ g_date_time_get_month (start_date) == self->date->month)
{
- j = g_date_time_get_day_of_month (date);
+ first_cell = g_date_time_get_day_of_month (start_date);
}
- j += self->days_delay;
-
- g_clear_pointer (&date, g_date_time_unref);
-
- /*
- * Calculate the first cell position according to the locale
- * and the start date.
- */
- first_cell = 7 * ((j - 1) / 7)+ 6 * self->k + sw * ((j - 1) % 7);
+ first_cell += self->days_delay - 1;
/*
* The logic for the end date is the same, except that we have to check
* if the event is all day or not.
*/
- j = icaltime_days_in_month (self->date->month, self->date->year);
- date = gcal_event_get_date_end (event);
- date = all_day ? g_date_time_ref (date) : g_date_time_to_local (date);
+ last_cell = icaltime_days_in_month (self->date->month, self->date->year);
+ end_date = gcal_event_get_date_end (event);
+ end_date = all_day ? g_date_time_ref (end_date) : g_date_time_to_local (end_date);
- if (g_date_time_get_month (date) == self->date->month)
+ if (g_date_time_get_month (end_date) == self->date->month)
{
- j = g_date_time_get_day_of_month (date);
+ last_cell = g_date_time_get_day_of_month (end_date);
/* If the event is all day, we have to subtract 1 to find the the real date */
if (all_day)
- j--;
+ last_cell--;
}
- j += self->days_delay;
-
- g_clear_pointer (&date, g_date_time_unref);
-
- last_cell = 7 * ((j - 1) / 7)+ 6 * self->k + sw * ((j - 1) % 7);
+ last_cell += self->days_delay - 1;
/*
* Now that we found the start & end dates, we have to find out
* whether the event is visible or not.
*/
- first_row = first_cell / 7;
- last_row = last_cell / 7;
- cells = 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; row++)
- {
- gint start, end;
- /* Position and allocate the child widget */
- minimum_height = get_real_event_widget_height (child_widget);
+ GCAL_TRACE_MSG ("Positioning '%s' (multiday) from %d to %d", gcal_event_get_summary (event),
first_cell, last_cell);
- gtk_style_context_get_margin (gtk_widget_get_style_context (child_widget),
- gtk_style_context_get_state (child_context),
- &margin);
-
- start = row * 7 + self->k * 6;
- end = row * 7 + (1 - self->k) * 6;
-
- if (row == first_row)
- start = first_cell;
- if (row == last_row)
- end = last_cell;
-
- get_widget_parts (self,
- start, end,
- minimum_height + margin.top + margin.bottom,
- vertical_cell_space,
- size_left,
- cells,
- lengths,
- visible_at_length,
- events_at_day,
- allocated_events_at_day);
- }
+ blocks = 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 (cell = 0; cell < cells->len; cell++)
+ /* Position and allocate the child widget */
+ minimum_height = get_real_event_widget_height (child_widget);
+
+ gtk_style_context_get_margin (child_context,
+ gtk_style_context_get_state (child_context),
+ &margin);
+
+ calculate_multiday_event_blocks (self,
+ first_cell, last_cell,
+ minimum_height + margin.top + margin.bottom,
+ vertical_cell_space,
+ size_left,
+ blocks,
+ lengths,
+ visible_at_length,
+ events_at_day,
+ allocated_events_at_day);
+
+ for (event_block = 0; event_block < blocks->len; event_block++)
{
g_autoptr (GDateTime) dt_start = NULL;
g_autoptr (GDateTime) dt_end = NULL;
gboolean visible;
gdouble width;
- gint cell_idx;
+ gint last_block_cell;
gint length;
- gint column;
+ gint cell;
gint day;
- visible = g_array_index (visible_at_length, gboolean, cell);
- cell_idx = g_array_index (cells, gint, cell);
- length = g_array_index (lengths, gint, cell);
- row = cell_idx / 7;
- column = cell_idx % 7;
- day = cell_idx - self->days_delay + 1;
-
- /* Day number is calculated differently on RTL languages */
- if (self->k)
- day = 7 * row + MIRROR (cell_idx % 7, 0, 7) - self->days_delay - length + 1;
+ visible = g_array_index (visible_at_length, gboolean, event_block);
+ length = g_array_index (lengths, gint, event_block);
+ cell = g_array_index (blocks, gint, event_block);
+ last_block_cell = cell + length - 1;
+ day = cell - self->days_delay + 1;
/*
* 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)
+ if (event_block != 0)
{
child_widget = gcal_event_widget_clone (GCAL_EVENT_WIDGET (child_widget));
gtk_widget_show (child_widget);
@@ -1714,7 +1683,7 @@ gcal_month_view_size_allocate (GtkWidget *widget,
gtk_widget_set_child_visible (child_widget, FALSE);
- for (idx = cell_idx; idx < cell_idx + length; idx++)
+ for (idx = cell; idx < cell + length; idx++)
{
aux = g_hash_table_lookup (self->overflow_cells, GINT_TO_POINTER (idx));
aux = g_list_append (aux, child_widget);
@@ -1728,11 +1697,15 @@ gcal_month_view_size_allocate (GtkWidget *widget,
continue;
}
- /* Retrieve the cell widget */
+
+ /*
+ * Retrieve the cell widget. On RTL languages, we use the last month cell as the starting
+ * point.
+ */
if (self->k)
- month_cell = self->month_cell[row][6 - column];
+ month_cell = self->month_cell[last_block_cell / 7][last_block_cell % 7];
else
- month_cell = self->month_cell[row][column];
+ month_cell = self->month_cell[cell / 7][cell % 7];
gtk_widget_get_allocation (month_cell, &cell_alloc);
@@ -1774,7 +1747,7 @@ gcal_month_view_size_allocate (GtkWidget *widget,
minimum_height = get_real_event_widget_height (child_widget);
child_allocation.x = pos_x;
- child_allocation.y = pos_y + vertical_cell_space[cell_idx] - size_left[cell_idx];
+ child_allocation.y = pos_y + vertical_cell_space[cell] - size_left[cell];
child_allocation.width = width - (margin.left + margin.right);
child_allocation.height = minimum_height;
@@ -1783,8 +1756,8 @@ gcal_month_view_size_allocate (GtkWidget *widget,
/* update size_left */
for (j = 0; j < length; j++)
{
- size_left[cell_idx + j] -= minimum_height;
- size_left[cell_idx + j] -= margin.top + margin.bottom;
+ size_left[cell + j] -= minimum_height;
+ size_left[cell + j] -= margin.top + margin.bottom;
}
}
}
@@ -1800,15 +1773,11 @@ gcal_month_view_size_allocate (GtkWidget *widget,
{
gboolean will_overflow;
gint cell;
+ gint day;
- j = GPOINTER_TO_INT (key);
- j += self->days_delay;
- cell = 7 * ((j - 1) / 7) + 6 * self->k + sw * ((j - 1) % 7);
-
- if (self->k)
- month_cell = self->month_cell[cell / 7][6 - cell % 7];
- else
- month_cell = self->month_cell[cell / 7][cell % 7];
+ day = GPOINTER_TO_INT (key);
+ cell = day + self->days_delay - 1;
+ month_cell = self->month_cell[cell / 7][cell % 7];
gtk_widget_get_allocation (month_cell, &cell_alloc);
@@ -1834,7 +1803,7 @@ gcal_month_view_size_allocate (GtkWidget *widget,
real_height = size_left[cell];
if (will_overflow)
- real_height -= gcal_month_cell_get_overflow_height (GCAL_MONTH_CELL (self->month_cell[cell /
7][cell % 7]));
+ real_height -= gcal_month_cell_get_overflow_height (GCAL_MONTH_CELL (month_cell));
/* No space left, add to the overflow and continue */
if (real_height < minimum_height)
@@ -1878,6 +1847,8 @@ out:
queue_update_month_cells (self);
self->pending_event_allocation = FALSE;
+
+ GCAL_EXIT;
}
static gboolean
@@ -1899,8 +1870,6 @@ gcal_month_view_button_press (GtkWidget *widget,
get_month_cell_at_position (self, x, y, &clicked_cell);
- clicked_cell = real_cell (clicked_cell, self->k);
-
if (clicked_cell >= self->days_delay && clicked_cell < days)
{
g_clear_pointer (&self->start_mark_cell, g_date_time_unref);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]