[gnome-calendar: 16/17] month-view: fix rtl



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]