[gnome-calendar] year-view: Remove hardcoded values



commit 97d88595745ae85d94667eb63dd88755af902852
Author: Isaque Galdino <igaldino gmail com>
Date:   Tue Apr 26 21:55:37 2016 -0300

    year-view: Remove hardcoded values
    
    Improve year-view code, removing hardcoded values.
    
    year-view have hardcoded values for grid cell sizes (width and height).
    Those values need to be recalculated every time a change in font or any
    other style are changed.
    
    Sidebar width was also hardcoded instead of getting its value directly
    from the ui file. That would prevent it from drawing the content
    accordingly when ui file is changed.
    
    This patch fixes those two issues by retrieving those values from CSS or
    ui files.
    
    This patch also adds code to resize and redraw the window when
    show-week-numbers property is changed.
    
    Popover mode was also changed and now sidebar will always be shown when
    show-week-numbers is set or when there is space for only 3 or less
    columns.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=753533

 data/theme/gtk-styles.css |    1 +
 data/ui/year-view.ui      |   34 +++++--
 src/gcal-year-view.c      |  215 ++++++++++++++++++++++++++++++++------------
 3 files changed, 181 insertions(+), 69 deletions(-)
---
diff --git a/data/theme/gtk-styles.css b/data/theme/gtk-styles.css
index ae24c04..e1c5182 100644
--- a/data/theme/gtk-styles.css
+++ b/data/theme/gtk-styles.css
@@ -89,6 +89,7 @@ calendar-view.second-view-header {
 }
 
 .year-navigator.days {
+    padding: 5px;
     color: @theme_fg_color;
     font: 9;
 }
diff --git a/data/ui/year-view.ui b/data/ui/year-view.ui
index 25b3ff0..9206279 100644
--- a/data/ui/year-view.ui
+++ b/data/ui/year-view.ui
@@ -6,17 +6,31 @@
       <class name="year-view"/>
     </style>
     <child>
-      <object class="GtkDrawingArea" id="navigator">
+      <object class="GtkScrolledWindow">
         <property name="visible">True</property>
-        <property name="hexpand">True</property>
-        <property 
name="events">GDK_POINTER_MOTION_MASK|GDK_BUTTON_MOTION_MASK|GDK_BUTTON_PRESS_MASK|GDK_BUTTON_RELEASE_MASK|GDK_STRUCTURE_MASK</property>
-        <signal name="draw" handler="draw_navigator" object="GcalYearView" swapped="yes"/>
-        <signal name="button-press-event" handler="navigator_button_press_cb" object="GcalYearView" 
swapped="yes"/>
-        <signal name="button-release-event" handler="navigator_button_release_cb" object="GcalYearView" 
swapped="yes"/>
-        <signal name="motion-notify-event" handler="navigator_motion_notify_cb" object="GcalYearView" 
swapped="yes"/>
-        <style>
-          <class name="year-navigator"/>
-        </style>
+        <property name="shadow_type">none</property>
+        <property name="vexpand">True</property>
+        <child>
+          <object class="GtkViewport">
+            <property name="visible">True</property>
+            <property name="shadow_type">none</property>
+            <property name="vexpand">True</property>
+            <child>
+              <object class="GtkDrawingArea" id="navigator">
+                <property name="visible">True</property>
+                <property name="hexpand">True</property>
+                <property 
name="events">GDK_POINTER_MOTION_MASK|GDK_BUTTON_MOTION_MASK|GDK_BUTTON_PRESS_MASK|GDK_BUTTON_RELEASE_MASK|GDK_STRUCTURE_MASK</property>
+                <signal name="draw" handler="draw_navigator" object="GcalYearView" swapped="yes"/>
+                <signal name="button-press-event" handler="navigator_button_press_cb" object="GcalYearView" 
swapped="yes"/>
+                <signal name="button-release-event" handler="navigator_button_release_cb" 
object="GcalYearView" swapped="yes"/>
+                <signal name="motion-notify-event" handler="navigator_motion_notify_cb" 
object="GcalYearView" swapped="yes"/>
+                <style>
+                  <class name="year-navigator"/>
+                </style>
+              </object>
+            </child>
+          </object>
+        </child>
       </object>
       <packing>
         <property name="position">0</property>
diff --git a/src/gcal-year-view.c b/src/gcal-year-view.c
index 60b061c..147012f 100644
--- a/src/gcal-year-view.c
+++ b/src/gcal-year-view.c
@@ -25,9 +25,7 @@
 #include <math.h>
 #include <string.h>
 
-#define NAVIGATOR_CELL_WIDTH (210 + 15)
-#define NAVIGATOR_CELL_HEIGHT 210
-#define SIDEBAR_PREFERRED_WIDTH 200
+#define NAVIGATOR_MAX_GRID_SIZE 6
 #define VISUAL_CLUES_SIDE 3.0
 #define WEEK_NUMBER_MARGIN 3.0
 
@@ -67,6 +65,12 @@ struct _GcalYearView
 
   /* geometry info */
   GridData     *navigator_grid;
+  guint         number_of_columns;
+  guint         number_of_rows;
+  guint         column_width;
+  guint         row_height;
+  guint         header_height;
+  guint         sidebar_width;
 
   /* state flags */
   gboolean      popover_mode;
@@ -402,6 +406,8 @@ update_sidebar (GcalYearView *year_view)
   for (l = events; l != NULL; l = g_list_next (l))
     add_event_to_day_array (year_view, l->data, days_widgets_array, days_span);
 
+  gtk_widget_queue_draw (year_view->navigator);
+
   for (i = 0; i < days_span; i++)
     {
       GList *current_day = days_widgets_array[i];
@@ -547,7 +553,7 @@ calculate_day_month_for_coord (GcalYearView *year_view,
                                gint         *out_day,
                                gint         *out_month)
 {
-  gint row, column, i, sw, clicked_cell, day, month;
+  gint row, column, i, sw, clicked_cell, day, month, columns_or_rows;
   gdouble box_side;
 
   row = -1;
@@ -555,18 +561,19 @@ calculate_day_month_for_coord (GcalYearView *year_view,
   box_side = year_view->navigator_grid->box_side;
   sw = 1 - 2 * year_view->k;
 
-  /* y selection */
-  for (i = 0; i < 4 && ((row == -1) || (column == -1)); i++)
+  columns_or_rows = year_view->number_of_columns > year_view->number_of_rows ? year_view->number_of_columns 
: year_view->number_of_rows;
+
+  for (i = 0; i < columns_or_rows && ((row == -1) || (column == -1)); i++)
     {
       if (row == -1 &&
-          y > year_view->navigator_grid->coordinates[i * 4].y &&
-          y < year_view->navigator_grid->coordinates[i * 4].y + box_side * 7)
+          y > year_view->navigator_grid->coordinates[i * year_view->number_of_columns].y + box_side &&
+          y < year_view->navigator_grid->coordinates[i * year_view->number_of_columns].y + 
year_view->row_height)
         {
           row = i;
         }
       if (column == -1 &&
-          x > year_view->navigator_grid->coordinates[i].x + box_side * (1 - year_view->k) &&
-          x < year_view->navigator_grid->coordinates[i].x + box_side * (8 - year_view->k))
+          x > year_view->navigator_grid->coordinates[i].x + box_side * year_view->show_week_numbers * (1 - 
year_view->k) &&
+          x < year_view->navigator_grid->coordinates[i].x + year_view->column_width - box_side * 
year_view->show_week_numbers * year_view->k)
         {
           column = i;
         }
@@ -575,9 +582,13 @@ calculate_day_month_for_coord (GcalYearView *year_view,
   if (row == -1 || column == -1)
     return FALSE;
 
-  month = row * 4 + column;
+  month = row * year_view->number_of_columns + column;
+
+  if (month < 0 || month > 11)
+    return FALSE;
+
   row = (y - (year_view->navigator_grid->coordinates[month].y + box_side)) / box_side;
-  column = (x - (year_view->navigator_grid->coordinates[month].x + box_side * (1 - year_view->k))) / 
box_side;
+  column = (x - (year_view->navigator_grid->coordinates[month].x + box_side * year_view->show_week_numbers * 
(1 - year_view->k))) / box_side;
   clicked_cell = row * 7 + column;
   day = 7 * ((clicked_cell + 7 * year_view->k) / 7) + sw * (clicked_cell % 7) + (1 - year_view->k);
   day -= ((time_day_of_week (1, month, year_view->date->year) - year_view->first_weekday + 7) % 7);
@@ -640,11 +651,11 @@ draw_month_grid (GcalYearView *year_view,
   layout = gtk_widget_create_pango_layout (widget, str);
   pango_layout_set_font_description (layout, font_desc);
   pango_layout_get_pixel_size (layout, &layout_width, &layout_height);
-  gtk_render_layout (context, cr, x + (box_side * 8 - layout_width) / 2.0, y + (box_side - layout_height) / 
2.0,
+  gtk_render_layout (context, cr, x + (year_view->column_width - layout_width) / 2.0, y + (box_side - 
layout_height) / 2.0,
                      layout);
 
   gtk_render_background (context, cr,
-                         x + (box_side * 8 - layout_width) / 2.0, y + (box_side - layout_height) / 2.0,
+                         x + (year_view->column_width - layout_width) / 2.0, y + (box_side - layout_height) 
/ 2.0,
                          layout_width, layout_width);
 
   pango_font_description_free (font_desc);
@@ -658,7 +669,8 @@ draw_month_grid (GcalYearView *year_view,
   gtk_style_context_get_color (context, state_flags, &color);
   cairo_set_line_width (cr, 0.2);
   gdk_cairo_set_source_rgba (cr, &color);
-  cairo_move_to (cr, x + box_side * (1 - year_view->k), y + box_side + 0.4);
+
+  cairo_move_to (cr, x + box_side * year_view->show_week_numbers * (1 - year_view->k), y + box_side + 0.4);
   cairo_rel_line_to (cr, 7.0 * box_side, 0);
   cairo_stroke (cr);
 
@@ -674,7 +686,7 @@ draw_month_grid (GcalYearView *year_view,
   days_delay = (time_day_of_week (1, month_nr, year_view->date->year) - year_view->first_weekday + 7) % 7;
   days = days_delay + icaltime_days_in_month (month_nr + 1, year_view->date->year);
   shown_rows = ceil (days / 7.0);
-  sunday_idx = year_view->k * 6 + sw * ((7 - year_view->first_weekday) % 7) + 1;
+  sunday_idx = year_view->k * 7 + sw * ((7 - year_view->first_weekday) % 7) + year_view->show_week_numbers * 
(1 - year_view->k);
 
   start_date.day    = 1;
   start_date.month  = month_nr + 1;
@@ -691,7 +703,7 @@ draw_month_grid (GcalYearView *year_view,
 
   for (i = 0; i < 7 * shown_rows; i++)
     {
-      column = (i % 7) + 1;
+      column = (i % 7) + (year_view->k || year_view->show_week_numbers);
       row = i / 7;
 
       j = 7 * ((i + 7 * year_view->k) / 7) + sw * (i % 7) + (1 - year_view->k);
@@ -883,7 +895,7 @@ draw_navigator (GcalYearView *year_view,
 
   gint header_padding_left, header_padding_top, header_height, layout_width, layout_height;
   gint real_padding_left, real_padding_top, i, sw, weeks_counter;
-  gdouble width, height, box_side;
+  gdouble width, height;
 
   gchar *header_str;
 
@@ -925,23 +937,20 @@ draw_navigator (GcalYearView *year_view,
   header_height = header_padding_top * 2 + layout_height;
   height = gtk_widget_get_allocated_height (widget) - header_height;
 
-  if (((width / 4.0) / 8.0) < ((height / 3.0) / 7.0))
-    box_side = (width / 4.0) / 8.0;
-  else
-    box_side = (height / 3.0) / 7.0;
+  real_padding_left = (width - year_view->column_width * year_view->number_of_columns) / 
(year_view->number_of_columns + 1);
+  real_padding_top = (height - year_view->row_height * year_view->number_of_rows) / 
year_view->number_of_rows;
 
-  real_padding_left = (width - (8 * 4 * box_side)) / 5.0;
-  real_padding_top = (height - (7 * 3 * box_side)) / 4.0;
+  if (real_padding_top < 0)
+    real_padding_top = 0;
 
-  year_view->navigator_grid->box_side = box_side;
   weeks_counter = year_view->first_week_of_year;
   for (i = 0; i < 12; i++)
     {
-      gint row = i / 4;
-      gint column = year_view->k * 3 + sw * (i % 4);
+      gint row = i / year_view->number_of_columns;
+      gint column = year_view->k * (year_view->number_of_columns - 1) + sw * (i % 
year_view->number_of_columns);
 
-      year_view->navigator_grid->coordinates[i].x = (column + 1) * real_padding_left + column * box_side * 8;
-      year_view->navigator_grid->coordinates[i].y = (row + 1) * real_padding_top + row * box_side * 7 + 
header_height;
+      year_view->navigator_grid->coordinates[i].x = (column + 1) * real_padding_left + column * 
year_view->column_width;
+      year_view->navigator_grid->coordinates[i].y = row * real_padding_top + row * year_view->row_height + 
header_height;
       draw_month_grid (year_view, widget, cr, i, &weeks_counter);
     }
 
@@ -1087,6 +1096,86 @@ popover_closed_cb (GcalYearView *year_view,
 }
 
 static void
+calculate_grid_sizes (GcalYearView *self)
+{
+  /* 1 column for week number and 7 for days */
+  if (self->show_week_numbers)
+    self->column_width = self->navigator_grid->box_side * 8;
+  else
+    self->column_width = self->navigator_grid->box_side * 7;
+
+  /* 1 line for month header and 6 lines for weeks */
+  self->row_height = self->navigator_grid->box_side * 7;
+}
+
+static void
+calculate_sizes (GcalYearView *self)
+{
+  GtkStyleContext *context;
+  PangoLayout *layout;
+  PangoFontDescription *font;
+
+  gint padding_left, padding_right, padding_top, padding_bottom;
+  gint width, height, box_width, box_height, natural;
+  gchar *test_str;
+
+  /* get header info from CSS */
+  context = gtk_widget_get_style_context (GTK_WIDGET (self));
+  gtk_style_context_save (context);
+  gtk_style_context_add_class (context, "first-view-header");
+  gtk_style_context_get (context, gtk_style_context_get_state (context),
+                         "padding-top", &padding_top,
+                         "padding-bottom", &padding_bottom,
+                         "font", &font, NULL);
+  gtk_style_context_restore (context);
+
+  /* measure header height */
+  test_str = g_strdup_printf ("8888");
+  layout = gtk_widget_create_pango_layout (self->navigator, test_str);
+  pango_layout_set_font_description (layout, font);
+  pango_layout_get_pixel_size (layout, &width, &height);
+
+  pango_font_description_free (font);
+  g_object_unref (layout);
+  g_free (test_str);
+
+  self->header_height = padding_top + height + padding_bottom;
+
+  /* get day info from CSS */
+  context = gtk_widget_get_style_context (GTK_WIDGET (self->navigator));
+  gtk_style_context_save (context);
+  gtk_style_context_add_class (context, "days");
+  gtk_style_context_get (context, gtk_style_context_get_state (context),
+                         "padding-left", &padding_left,
+                         "padding-right", &padding_right,
+                         "padding-top", &padding_top,
+                         "padding-bottom", &padding_bottom,
+                         "font", &font, NULL);
+  gtk_style_context_restore (context);
+
+  /* measure box size */
+  test_str = g_strdup_printf ("88");
+  layout = gtk_widget_create_pango_layout (self->navigator, test_str);
+  pango_layout_set_font_description (layout, font);
+  pango_layout_get_pixel_size (layout, &width, &height);
+
+  pango_font_description_free (font);
+  g_object_unref (layout);
+  g_free (test_str);
+
+  box_width = padding_left + width + padding_right;
+  box_height = padding_top + height + padding_bottom;
+
+  self->navigator_grid->box_side = (box_width > box_height) ? box_width : box_height;
+
+  /* get sidebar width */
+  gtk_widget_get_preferred_width (self->sidebar, &width, &natural);
+  self->sidebar_width = width;
+
+  calculate_grid_sizes (self);
+}
+
+static void
 gcal_year_view_finalize (GObject *object)
 {
   GcalYearView *year_view = GCAL_YEAR_VIEW (object);
@@ -1145,7 +1234,9 @@ gcal_year_view_set_property (GObject      *object,
       if (self->show_week_numbers != g_value_get_boolean (value))
         {
           self->show_week_numbers = g_value_get_boolean (value);
+          calculate_grid_sizes (self);
           g_object_notify (object, "show-week-numbers");
+          gtk_widget_queue_allocate (GTK_WIDGET (self));
         }
       break;
 
@@ -1161,40 +1252,20 @@ gcal_year_view_get_preferred_width (GtkWidget *widget,
 {
   GcalYearView *year_view = GCAL_YEAR_VIEW (widget);
   GtkStyleContext *context;
-  gint padding_left;
+  gint padding_left, padding_right, hpadding;
 
   context = gtk_widget_get_style_context (year_view->navigator);
 
   gtk_style_context_get (context,
                          gtk_style_context_get_state (context),
-                         "padding-left", &padding_left, NULL);
+                         "padding-left", &padding_left,
+                         "padding-right", &padding_right, NULL);
 
+  hpadding = padding_left + padding_right;
   if (minimum != NULL)
-    *minimum = NAVIGATOR_CELL_WIDTH * 4 + padding_left * 8;
+    *minimum = hpadding + year_view->column_width;
   if (natural != NULL)
-    *natural = NAVIGATOR_CELL_WIDTH * 4 + padding_left * 8 + SIDEBAR_PREFERRED_WIDTH;
-}
-
-static void
-gcal_year_view_get_preferred_height_for_width (GtkWidget *widget,
-                                               gint       width,
-                                               gint      *minimum,
-                                               gint      *natural)
-{
-  GcalYearView *year_view = GCAL_YEAR_VIEW (widget);
-  GtkStyleContext *context;
-  gint padding_top;
-
-  context = gtk_widget_get_style_context (year_view->navigator);
-
-  gtk_style_context_get (context,
-                         gtk_style_context_get_state (context),
-                         "padding-top", &padding_top, NULL);
-
-  if (minimum != NULL)
-    *minimum = NAVIGATOR_CELL_HEIGHT * 3 + padding_top * 6;
-  if (natural != NULL)
-    *natural = NAVIGATOR_CELL_HEIGHT * 3 + padding_top * 6;
+    *natural = hpadding + year_view->column_width + year_view->sidebar_width;
 }
 
 static void
@@ -1203,15 +1274,35 @@ gcal_year_view_size_allocate (GtkWidget     *widget,
 {
   GcalYearView *year_view = GCAL_YEAR_VIEW (widget);
   GtkStyleContext *context;
-  gint padding_left;
+  gint padding_left, padding_right, padding_top, padding_bottom, hpadding, vpadding;
 
   context = gtk_widget_get_style_context (widget);
   gtk_style_context_save (context);
   gtk_style_context_add_class (context, "year-navigator");
-  gtk_style_context_get (context, gtk_style_context_get_state (context), "padding-left", &padding_left, 
NULL);
+  gtk_style_context_get (context,
+                         gtk_style_context_get_state (context),
+                         "padding-left", &padding_left,
+                         "padding-right", &padding_right,
+                         "padding-top", &padding_top,
+                         "padding-bottom", &padding_bottom, NULL);
   gtk_style_context_restore (context);
 
-  year_view->popover_mode = (alloc->width < NAVIGATOR_CELL_WIDTH * 4 + padding_left * 8 + 
SIDEBAR_PREFERRED_WIDTH);
+  hpadding = padding_left + padding_right;
+  vpadding = padding_top + padding_bottom;
+
+  year_view->popover_mode = (alloc->width < (hpadding + year_view->column_width * 2 + 
year_view->sidebar_width));
+
+  year_view->number_of_columns = (alloc->width - hpadding - year_view->sidebar_width * 
!year_view->popover_mode) / year_view->column_width;
+
+  if (year_view->number_of_columns > NAVIGATOR_MAX_GRID_SIZE)
+    year_view->number_of_columns = NAVIGATOR_MAX_GRID_SIZE;
+
+  year_view->number_of_rows = ceil (12.0 / year_view->number_of_columns);
+
+  gtk_widget_set_size_request (year_view->navigator,
+                               hpadding + year_view->column_width * year_view->number_of_columns,
+                               vpadding + year_view->row_height * year_view->number_of_rows + 
year_view->header_height);
+
   if (year_view->popover_mode && !gtk_widget_is_ancestor (year_view->events_sidebar, year_view->popover))
     {
       g_object_ref (year_view->sidebar);
@@ -1343,6 +1434,8 @@ gcal_year_view_component_added (ECalDataModelSubscriber *subscriber,
       g_list_free (current_day);
     }
 
+  gtk_widget_queue_draw (year_view->navigator);
+
 out:
   g_clear_object (&event);
   g_free (days_widgets_array);
@@ -1443,7 +1536,6 @@ gcal_year_view_class_init (GcalYearViewClass *klass)
   object_class->set_property = gcal_year_view_set_property;
 
   widget_class->get_preferred_width = gcal_year_view_get_preferred_width;
-  widget_class->get_preferred_height_for_width = gcal_year_view_get_preferred_height_for_width;
   widget_class->size_allocate = gcal_year_view_size_allocate;
   widget_class->direction_changed = gcal_year_view_direction_changed;
 
@@ -1506,6 +1598,11 @@ gcal_year_view_init (GcalYearView *self)
   g_settings_bind (self->shell_settings, "show-weekdate", self, "show-week-numbers", 
G_SETTINGS_BIND_DEFAULT);
   g_signal_connect_swapped (self->shell_settings, "changed::show-weekdate", G_CALLBACK 
(gtk_widget_queue_draw), self);
 
+  /* layout */
+  self->number_of_columns = 4;
+  self->number_of_rows = 3;
+  calculate_sizes (self);
+
   gtk_list_box_set_header_func (GTK_LIST_BOX (self->events_sidebar), update_sidebar_headers, self, NULL);
   gtk_list_box_set_sort_func (GTK_LIST_BOX (self->events_sidebar), sidebar_sort_func, NULL, NULL);
 }


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]