[gtk+/wip/csoriano/pathbar-prototype: 35/42] gtkhidingbox: add property to choose side to handle overflow



commit 3e546debfde1a8e5cdd122fdb4d1679ccbe3004b
Author: Carlos Soriano <csoriano gnome org>
Date:   Fri Nov 6 14:17:28 2015 +0100

    gtkhidingbox: add property to choose side to handle overflow
    
    i.e. The case of Nautilus and FileChooser GtkPathBar is that we always
    want to show the end part of the path. However that might not be the
    case for other uses, like gnome-software and its titles.

 gtk/gtkhidingbox.c        |  100 +++++++++++++++++++++++++++++++++++++++-----
 gtk/gtkhidingboxprivate.h |   16 +++++--
 2 files changed, 99 insertions(+), 17 deletions(-)
---
diff --git a/gtk/gtkhidingbox.c b/gtk/gtkhidingbox.c
index bdf07fb..e91a346 100644
--- a/gtk/gtkhidingbox.c
+++ b/gtk/gtkhidingbox.c
@@ -29,6 +29,7 @@ struct _GtkHidingBoxPrivate
 {
   GList *children;
   gint16 spacing;
+  GtkDirectionType hide_direction;
 };
 
 static void
@@ -56,6 +57,7 @@ G_DEFINE_TYPE_WITH_CODE (GtkHidingBox, gtk_hiding_box, GTK_TYPE_CONTAINER,
 enum {
   PROP_0,
   PROP_SPACING,
+  PROP_HIDE_DIRECTION,
   LAST_PROP
 };
 
@@ -74,6 +76,9 @@ gtk_hiding_box_set_property (GObject      *object,
     case PROP_SPACING:
       gtk_hiding_box_set_spacing (box, g_value_get_int (value));
       break;
+    case PROP_HIDE_DIRECTION:
+      gtk_hiding_box_set_hide_direction (box, g_value_get_int (value));
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -94,6 +99,9 @@ gtk_hiding_box_get_property (GObject    *object,
     case PROP_SPACING:
       g_value_set_int (value, priv->spacing);
       break;
+    case PROP_HIDE_DIRECTION:
+      g_value_set_int (value, priv->hide_direction);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -167,15 +175,21 @@ update_children_visibility (GtkHidingBox     *box,
   GtkHidingBoxPrivate *priv = gtk_hiding_box_get_instance_private (box);
   GtkWidget *child_widget;
   GList *child;
+  GtkRequestedSize *sizes_temp;
   gint i;
   gint children_size = -priv->spacing;
+  GList *children;
   gboolean allocate_more_children = TRUE;
 
   *n_visible_children = 0;
   *n_visible_children_expanding = 0;
+  children = g_list_copy (priv->children);
+  sizes_temp = g_newa (GtkRequestedSize, g_list_length (priv->children));
+  if (priv->hide_direction == GTK_DIR_LEFT)
+    children = g_list_reverse (children);
 
   /* Retrieve desired size for visible children. */
-  for (i = 0, child = priv->children; child != NULL; i++, child = child->next)
+  for (i = 0, child = children; child != NULL; i++, child = child->next)
     {
       child_widget = GTK_WIDGET (child->data);
       if (!gtk_widget_get_visible (child_widget) || !allocate_more_children)
@@ -186,22 +200,22 @@ update_children_visibility (GtkHidingBox     *box,
 
       gtk_widget_get_preferred_width_for_height (child_widget,
                                                  allocation->height,
-                                                 &sizes[i].minimum_size,
-                                                 &sizes[i].natural_size);
+                                                 &sizes_temp[i].minimum_size,
+                                                 &sizes_temp[i].natural_size);
       /* Assert the api is working properly */
-      if (sizes[i].minimum_size < 0)
+      if (sizes_temp[i].minimum_size < 0)
         g_error ("GtkHidingBox child %s minimum width: %d < 0 for height %d",
                  gtk_widget_get_name (child_widget),
-                 sizes[i].minimum_size, allocation->height);
+                 sizes_temp[i].minimum_size, allocation->height);
 
-      if (sizes[i].natural_size < sizes[i].minimum_size)
+      if (sizes_temp[i].natural_size < sizes_temp[i].minimum_size)
         g_error ("GtkHidingBox child %s natural width: %d < minimum %d for height %d",
                  gtk_widget_get_name (child_widget),
-                 sizes[i].natural_size, sizes[i].minimum_size,
+                 sizes_temp[i].natural_size, sizes_temp[i].minimum_size,
                  allocation->height);
 
-      children_size += sizes[i].minimum_size + priv->spacing;
-      sizes[i].data = child_widget;
+      children_size += sizes_temp[i].minimum_size + priv->spacing;
+      sizes_temp[i].data = child_widget;
 
       if (children_size > allocation->width)
         {
@@ -215,6 +229,22 @@ update_children_visibility (GtkHidingBox     *box,
       (*n_visible_children)++;
       gtk_widget_set_child_visible (child_widget, TRUE);
     }
+
+  for (i = 0; i < *n_visible_children; i++)
+    {
+      if (priv->hide_direction == GTK_DIR_RIGHT)
+        {
+          sizes[i].minimum_size = sizes_temp[i].minimum_size;
+          sizes[i].natural_size = sizes_temp[i].natural_size;
+        }
+      else
+        {
+          sizes[*n_visible_children - i - 1].minimum_size = sizes_temp[i].minimum_size;
+          sizes[*n_visible_children - i - 1].natural_size = sizes_temp[i].natural_size;
+        }
+    }
+
+  g_list_free (children);
 }
 
 static void
@@ -329,12 +359,17 @@ gtk_hiding_box_get_preferred_width (GtkWidget *widget,
   GList *child;
   gint n_visible_children;
   gboolean have_min = FALSE;
+  GList *children;
 
   *minimum_width = 0;
   *natural_width = 0;
 
+  children = g_list_copy (priv->children);
+  if (priv->hide_direction == GTK_DIR_LEFT)
+    children = g_list_reverse (children);
+
   n_visible_children = 0;
-  for (child = priv->children; child != NULL; child = child->next)
+  for (child = children; child != NULL; child = child->next)
     {
       if (!gtk_widget_is_visible (child->data))
         continue;
@@ -354,6 +389,8 @@ gtk_hiding_box_get_preferred_width (GtkWidget *widget,
   /* Natural must also include the spacing */
   if (priv->spacing && n_visible_children > 1)
     *natural_width += priv->spacing * (n_visible_children - 1);
+
+  g_list_free (children);
 }
 
 static void
@@ -386,9 +423,8 @@ gtk_hiding_box_init (GtkHidingBox *box)
   GtkHidingBoxPrivate *priv = gtk_hiding_box_get_instance_private (box);
 
   gtk_widget_set_has_window (GTK_WIDGET (box), FALSE);
-  gtk_widget_set_redraw_on_allocate (GTK_WIDGET (box), FALSE);
-
   priv->spacing = 0;
+  priv->hide_direction = GTK_DIR_RIGHT;
 }
 
 static void
@@ -416,6 +452,13 @@ gtk_hiding_box_class_init (GtkHidingBoxClass *class)
                              0, G_MAXINT, 0,
                              G_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
 
+  hiding_box_properties[PROP_HIDE_DIRECTION] =
+           g_param_spec_int ("hide-direction",
+                             _("Hide direction"),
+                             _("From where the container will start hiding widgets when there is not enough 
space"),
+                             0, G_MAXINT, 0,
+                             G_PARAM_READWRITE);
+
   g_object_class_install_properties (object_class, LAST_PROP, hiding_box_properties);
 }
 
@@ -480,3 +523,36 @@ gtk_hiding_box_get_spacing (GtkHidingBox *box)
   return priv->spacing;
 }
 
+
+void
+gtk_hiding_box_set_hide_direction (GtkHidingBox     *box,
+                                   GtkDirectionType  hide_direction)
+{
+  GtkHidingBoxPrivate *priv ;
+
+  g_return_if_fail (GTK_IS_HIDING_BOX (box));
+  g_return_if_fail (hide_direction == GTK_DIR_LEFT || hide_direction == GTK_DIR_RIGHT);
+
+  priv = gtk_hiding_box_get_instance_private (box);
+
+  if (priv->hide_direction != hide_direction)
+    {
+      priv->hide_direction = hide_direction;
+
+      g_object_notify (G_OBJECT (box), "hide-direction");
+
+      gtk_widget_queue_resize (GTK_WIDGET (box));
+    }
+}
+
+GtkDirectionType
+gtk_hiding_box_get_hide_direction (GtkHidingBox *box)
+{
+  GtkHidingBoxPrivate *priv ;
+
+  g_return_val_if_fail (GTK_IS_HIDING_BOX (box), 0);
+
+  priv = gtk_hiding_box_get_instance_private (box);
+
+  return priv->hide_direction;
+}
diff --git a/gtk/gtkhidingboxprivate.h b/gtk/gtkhidingboxprivate.h
index 89f360b..b894237 100644
--- a/gtk/gtkhidingboxprivate.h
+++ b/gtk/gtkhidingboxprivate.h
@@ -54,15 +54,21 @@ struct _GtkHidingBox
 };
 
 GDK_AVAILABLE_IN_3_20
-GType             gtk_hiding_box_get_type         (void) G_GNUC_CONST;
+GType             gtk_hiding_box_get_type                (void) G_GNUC_CONST;
 
 GDK_AVAILABLE_IN_3_20
-GtkWidget        *gtk_hiding_box_new              (void);
+GtkWidget        *gtk_hiding_box_new                     (void);
 GDK_AVAILABLE_IN_3_20
-void              gtk_hiding_box_set_spacing      (GtkHidingBox      *box,
-                                                   gint               spacing);
+void              gtk_hiding_box_set_spacing             (GtkHidingBox      *box,
+                                                          gint               spacing);
 GDK_AVAILABLE_IN_3_20
-gint              gtk_hiding_box_get_spacing      (GtkHidingBox      *box);
+gint              gtk_hiding_box_get_spacing             (GtkHidingBox      *box);
+
+GDK_AVAILABLE_IN_3_20
+void              gtk_hiding_box_set_hide_direction      (GtkHidingBox      *box,
+                                                          GtkDirectionType   hide_direction);
+GDK_AVAILABLE_IN_3_20
+GtkDirectionType  gtk_hiding_box_get_hide_direction      (GtkHidingBox      *box);
 
 G_END_DECLS
 


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