[gnome-calendar/search-improvements] year-view: initial GtkWidget::size_allocate impl



commit c1f6f7ac4742102ae75c614f1e056cdec17b0428
Author: Erick PĂ©rez Castellanos <erick red gmail com>
Date:   Mon Dec 29 16:35:41 2014 -0500

    year-view: initial GtkWidget::size_allocate impl
    
    This impl uses internals structures from GcalSubscriber

 src/gcal-year-view.c |  278 +++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 273 insertions(+), 5 deletions(-)
---
diff --git a/src/gcal-year-view.c b/src/gcal-year-view.c
index 802b9f7..e2ae043 100644
--- a/src/gcal-year-view.c
+++ b/src/gcal-year-view.c
@@ -28,6 +28,8 @@
 
 typedef struct
 {
+  /* overflow buttons */
+  GHashTable     *internal_children;
 
   GdkWindow      *event_window;
 
@@ -54,6 +56,14 @@ enum
 static void           event_opened                                (GcalEventWidget *event_widget,
                                                                    gpointer         user_data);
 
+static gboolean       get_widget_parts                            (gint             first_cell,
+                                                                   gint             last_cell,
+                                                                   gint             natural_height,
+                                                                   gdouble          vertical_cell_space,
+                                                                   gdouble         *size_left,
+                                                                   GArray          *cells,
+                                                                   GArray          *lengths);
+
 static void           gcal_view_interface_init                    (GcalViewIface  *iface);
 
 static void           gcal_year_view_set_property                 (GObject        *object,
@@ -130,6 +140,53 @@ event_opened (GcalEventWidget *event_widget,
                          event_widget);
 }
 
+static gboolean
+get_widget_parts (gint     first_cell,
+                  gint     last_cell,
+                  gint     natural_height,
+                  gdouble  vertical_cell_space,
+                  gdouble *size_left,
+                  GArray  *cells,
+                  GArray  *lengths)
+{
+  gint i;
+  gint current_part_length;
+  gdouble y, old_y = - 1.0;
+
+  if (last_cell < first_cell)
+    {
+      gint swap = last_cell;
+      last_cell = first_cell;
+      first_cell = swap;
+    }
+
+  for (i = first_cell; i <= last_cell; i++)
+    {
+      if (size_left[i] < natural_height)
+        {
+          return FALSE;
+        }
+      else
+        {
+          y = vertical_cell_space - size_left[i];
+          if (y != old_y)
+            {
+              current_part_length = 1;
+              g_array_append_val (cells, i);
+              g_array_append_val (lengths, current_part_length);
+              old_y = y;
+            }
+          else
+            {
+              current_part_length++;
+              g_array_index (lengths, gint, lengths->len - 1) = current_part_length;
+            }
+        }
+    }
+
+  return TRUE;
+}
+
 static void
 gcal_year_view_class_init (GcalYearViewClass *klass)
 {
@@ -370,18 +427,229 @@ gcal_year_view_size_allocate (GtkWidget     *widget,
                               GtkAllocation *allocation)
 {
   GcalYearViewPrivate *priv;
+  GcalSubscriberPrivate *ppriv;
+  gint i, j, sw;
+
+  gint padding_bottom;
+  PangoLayout *layout;
+  PangoFontDescription *font_desc;
+  gint font_height;
+
+  gdouble cell_width, cell_height, vertical_cell_space;
+  gdouble pos_x, pos_y;
+  gdouble size_left [12];
+
+  const gchar *uuid;
+  GtkWidget *child_widget;
+  GtkAllocation child_allocation;
+  gint natural_height;
+
+  GList *widgets, *l, *aux, *l2 = NULL;
+  GHashTableIter iter;
+  gpointer key, value;
 
   priv = gcal_year_view_get_instance_private (GCAL_YEAR_VIEW (widget));
+  ppriv = GCAL_SUBSCRIBER (widget)->priv;
+
+  /* remove every widget' parts, but the master widget */
+  widgets = g_hash_table_get_values (ppriv->children);
+  for (aux = widgets; aux != NULL; aux = g_list_next (aux))
+    {
+      l = g_list_next ((GList*) aux->data);
+      for (; l != NULL; l = g_list_next (l))
+        l2 = g_list_append (l2, l->data);
+    }
+  g_list_free (widgets);
+
+  for (aux = l2; aux != NULL; aux = g_list_next (aux))
+    gtk_widget_destroy ((GtkWidget*) aux->data);
+  g_list_free (l2);
+
+  /* clean overflow information */
+  g_hash_table_remove_all (ppriv->overflow_cells);
 
   gtk_widget_set_allocation (widget, allocation);
   if (gtk_widget_get_realized (widget))
+    gdk_window_move_resize (priv->event_window, allocation->x, allocation->y, allocation->width, 
allocation->height);
+
+  gtk_style_context_get (gtk_widget_get_style_context (widget), gtk_widget_get_state_flags (widget),
+                         "font", &font_desc, "padding-bottom", &padding_bottom, NULL);
+
+  layout = gtk_widget_create_pango_layout (widget, _("Other events"));
+  pango_layout_set_font_description (layout, font_desc);
+  pango_layout_get_pixel_size (layout, NULL, &font_height);
+  pango_font_description_free (font_desc);
+  g_object_unref (layout);
+
+  cell_width = allocation->width / 6.0;
+  cell_height = allocation->height / 2.0;
+  vertical_cell_space = cell_height - (padding_bottom + font_height);
+
+  for (i = 0; i < 12; i++)
+    size_left[i] = vertical_cell_space;
+
+  sw = 1 - 2 * priv->k;
+
+  /* allocate multimonth events */
+  for (l = ppriv->multi_cell_children; l != NULL; l = g_list_next (l))
+    {
+      gint first_cell, last_cell, first_row, last_row, start, end;
+      gboolean visible;
+
+      const icaltimetype *date;
+      GArray *cells, *lengths;
+
+      child_widget = (GtkWidget*) l->data;
+      uuid = gcal_event_widget_peek_uuid (GCAL_EVENT_WIDGET (child_widget));
+      if (!gtk_widget_is_visible (child_widget) && !g_hash_table_contains (ppriv->hidden_as_overflow, uuid))
+        continue;
+
+      gtk_widget_show (child_widget);
+      gtk_widget_get_preferred_height (child_widget, NULL, &natural_height);
+
+      j = 1;
+      date = gcal_event_widget_peek_start_date (GCAL_EVENT_WIDGET (child_widget));
+      if (date->year == priv->date->year)
+        j = date->month;
+      first_cell = 6 * ((j - 1) / 6) + 6 * priv->k + sw * ((j - 1) % 6) - (1 * priv->k);
+
+      j = 12;
+      date = gcal_event_widget_peek_end_date (GCAL_EVENT_WIDGET (child_widget));
+      if (date->year == priv->date->year)
+        j = date->month;
+      last_cell = 6 * ((j - 1) / 6) + 6 * priv->k + sw * ((j - 1) % 6) - (1 * priv->k);
+
+      /* FIXME missing mark widgets with continuos tags */
+
+      first_row = first_cell / 6;
+      last_row = last_cell / 6;
+      visible = TRUE;
+      cells = g_array_sized_new (TRUE, TRUE, sizeof (gint), 16);
+      lengths = g_array_sized_new (TRUE, TRUE, sizeof (gint), 16);
+      for (i = first_row; i <= last_row && visible; i++)
+        {
+          start = i * 6 + priv->k * 5;
+          end = i * 6 + (1 - priv->k) * 5;
+
+          if (i == first_row)
+            {
+              start = first_cell;
+            }
+          if (i == last_row)
+            {
+              end = last_cell;
+            }
+
+          visible = get_widget_parts (start, end, natural_height, vertical_cell_space, size_left, cells, 
lengths);
+        }
+
+      if (visible)
+        {
+          for (i = 0; i < cells->len; i++)
+            {
+              gint cell_idx = g_array_index (cells, gint, i);
+              gint row = cell_idx / 6;
+              gint column = cell_idx % 6;
+              pos_x = cell_width * column;
+              pos_y = cell_height * row;
+
+              child_allocation.x = pos_x;
+              child_allocation.y = pos_y + vertical_cell_space - size_left[cell_idx];
+              child_allocation.width = cell_width * g_array_index (lengths, gint, i);
+              child_allocation.height = natural_height;
+
+              if (i != 0)
+                {
+                  child_widget = gcal_event_widget_clone (GCAL_EVENT_WIDGET (child_widget));
+
+                  //setup_child (child_widget, widget);
+                  gtk_widget_set_parent (child_widget, widget); /* FIXME */
+                  gtk_widget_show (child_widget);
+
+                  aux = g_hash_table_lookup (ppriv->children, uuid);
+                  aux = g_list_append (aux, child_widget);
+                }
+              gtk_widget_size_allocate (child_widget, &child_allocation);
+              g_hash_table_remove (ppriv->hidden_as_overflow, uuid);
+
+              /* update size_left */
+              for (j = 0; j < g_array_index (lengths, gint, i); j++)
+                size_left[cell_idx + j] -= natural_height;
+            }
+        }
+      else
+        {
+          gtk_widget_hide (child_widget);
+          g_hash_table_add (ppriv->hidden_as_overflow, g_strdup (uuid));
+
+          for (i = first_cell; i <= last_cell; i++)
+            {
+              aux = g_hash_table_lookup (ppriv->overflow_cells, GINT_TO_POINTER (i));
+              aux = g_list_append (aux, child_widget);
+
+              if (g_list_length (aux) == 1)
+                g_hash_table_insert (ppriv->overflow_cells, GINT_TO_POINTER (i), aux);
+              else
+                g_hash_table_replace (ppriv->overflow_cells, GINT_TO_POINTER (i), g_list_copy (aux));
+            }
+        }
+
+      g_array_free (cells, TRUE);
+      g_array_free (lengths, TRUE);
+    }
+
+  g_hash_table_iter_init (&iter, ppriv->single_cell_children);
+  while (g_hash_table_iter_next (&iter, &key, &value))
     {
-      gdk_window_move_resize (priv->event_window,
-                              allocation->x,
-                              allocation->y,
-                              allocation->width,
-                              allocation->height);
+      j = GPOINTER_TO_INT (key);
+      i = 6 * ((j - 1) / 6) + 6 * priv->k + sw * ((j - 1) % 6) - (1 * priv->k);
+
+      l = (GList*) value;
+      for (aux = l; aux != NULL; aux = g_list_next (aux))
+        {
+          child_widget = (GtkWidget*) aux->data;
+
+          uuid = gcal_event_widget_peek_uuid (GCAL_EVENT_WIDGET (child_widget));
+          if (!gtk_widget_is_visible (child_widget) && !g_hash_table_contains (ppriv->hidden_as_overflow, 
uuid))
+            continue;
+
+          gtk_widget_show (child_widget);
+          gtk_widget_get_preferred_height (child_widget, NULL, &natural_height);
+
+          if (size_left[i] > natural_height)
+            {
+              pos_x = cell_width * (i % 6);
+              pos_y = cell_height * (i / 6);
+
+              child_allocation.x = pos_x;
+              child_allocation.y = pos_y + vertical_cell_space - size_left[i];
+              child_allocation.width = cell_width;
+              child_allocation.height = natural_height;
+              gtk_widget_show (child_widget);
+              gtk_widget_size_allocate (child_widget, &child_allocation);
+              g_hash_table_remove (ppriv->hidden_as_overflow, uuid);
+
+              size_left[i] -= natural_height;
+            }
+          else
+            {
+              gtk_widget_hide (child_widget);
+              g_hash_table_add (ppriv->hidden_as_overflow, g_strdup (uuid));
+
+              l = g_hash_table_lookup (ppriv->overflow_cells, GINT_TO_POINTER (i));
+              l = g_list_append (l, child_widget);
+
+              if (g_list_length (l) == 1)
+                g_hash_table_insert (ppriv->overflow_cells, GINT_TO_POINTER (i), l);
+              else
+                g_hash_table_replace (ppriv->overflow_cells, GINT_TO_POINTER (i), g_list_copy (l));
+            }
+        }
     }
+
+  /* FIXME: remove on Gtk+ 3.15.4 release */
+  if (g_hash_table_size (ppriv->overflow_cells) != 0)
+    gtk_widget_queue_draw_area (widget, allocation->x, allocation->y, allocation->width, allocation->height);
 }
 
 static gboolean


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