[gtk+/wip/csoriano/pathbar-prototype: 165/166] more size management



commit ae3b1747ade231fb0a907816e9147ecbc558acd8
Author: Carlos Soriano <csoriano gnome org>
Date:   Fri Oct 30 19:59:13 2015 +0100

    more size management

 gtk/gtkpathbar.c                         |  161 +++++++++++++++++++++++-------
 gtk/theme/Adwaita/_common.scss           |    7 +-
 gtk/theme/Adwaita/gtk-contained-dark.css |    7 +-
 gtk/theme/Adwaita/gtk-contained.css      |    7 +-
 gtk/ui/gtkpathbar.ui                     |    4 +-
 tests/testpathbar.c                      |    4 +-
 6 files changed, 140 insertions(+), 50 deletions(-)
---
diff --git a/gtk/gtkpathbar.c b/gtk/gtkpathbar.c
index d44bce0..2ce434c 100644
--- a/gtk/gtkpathbar.c
+++ b/gtk/gtkpathbar.c
@@ -24,6 +24,7 @@
 #include "gtkbutton.h"
 #include "gtktogglebutton.h"
 #include "gtklabel.h"
+#include "gtkpopover.h"
 #include "gtkbuilder.h"
 #include "gtkstylecontext.h"
 
@@ -37,6 +38,8 @@ struct _GtkPathBarPrivate
   GtkWidget *overflow_button;
 
   gchar *path;
+  GList *overflow_path_chunks;
+  GList *path_chunks;
 };
 
 G_DEFINE_TYPE_WITH_PRIVATE (GtkPathBar, gtk_path_bar, GTK_TYPE_BOX)
@@ -55,6 +58,11 @@ enum {
 static GParamSpec *path_bar_properties[LAST_PROP] = { NULL, };
 static guint path_bar_signals[LAST_SIGNAL] = { 0 };
 
+typedef struct {
+  gchar *label;
+  GString *path;
+} PathChunkData;
+
 static void
 on_path_chunk_button_clicked (GtkPathBar *self,
                               GtkButton  *path_chunk_button)
@@ -74,48 +82,98 @@ create_separator ()
   return label;
 }
 
+static void
+free_path_chunk_data (PathChunkData *data)
+{
+  g_free (data->label);
+  g_string_free (data->path, TRUE);
+  g_slice_free (PathChunkData, data);
+}
+
 GtkWidget *
 create_path_chunk (GtkPathBar  *self,
+                   const GString *path,
                    const gchar *label)
 {
   GtkWidget *button;
   GtkStyleContext *style;
+  PathChunkData *path_chunk_data;
 
   button = gtk_toggle_button_new_with_label (label);
+  path_chunk_data = g_slice_new (PathChunkData);
+  path_chunk_data->label = g_strdup (label);
+  path_chunk_data->path = g_string_new (path->str);
+
+  g_object_set_data_full (G_OBJECT (button), "data",
+                          path_chunk_data, (GDestroyNotify) free_path_chunk_data);
   g_signal_connect_swapped (button, "clicked",
                             G_CALLBACK (on_path_chunk_button_clicked), self);
   gtk_widget_show (button);
   style = gtk_widget_get_style_context (button);
-  gtk_style_context_add_class (style, "image-button");
   gtk_style_context_add_class (style, "flat");
-  gtk_style_context_add_class (style, "button-simplic");
 
   return button;
 }
 
+static void
+popup_overflow_menu (GtkPathBar *self)
+{
+  GtkPathBarPrivate *priv = gtk_path_bar_get_instance_private (GTK_PATH_BAR (self));
+  GList *l;
+  PathChunkData *data;
+  GtkWidget *path_chunk;
+  GtkWidget *overflow_box;
+  GtkWidget *popover;
+
+  overflow_box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
+  gtk_widget_show (overflow_box);
+  popover = gtk_popover_new (priv->overflow_button);
+  gtk_container_add (GTK_CONTAINER (popover), overflow_box);
+  for (l = priv->path_chunks; l != NULL; l = l->next)
+    {
+      if (!gtk_widget_get_child_visible (l->data))
+        {
+          data = g_object_get_data (l->data, "data");
+          path_chunk = create_path_chunk (self, (const GString*) data->path, (const gchar*) data->label);
+          gtk_container_add (GTK_CONTAINER (overflow_box), path_chunk);
+        }
+    }
+
+  gtk_widget_show (popover);
+}
+
 void
 gtk_path_bar_set_path (GtkPathBar  *self,
                        const gchar *path)
 {
   GtkPathBarPrivate *priv = gtk_path_bar_get_instance_private (GTK_PATH_BAR (self));
   gchar ** splitted_path;
+  GString *current_path = NULL;
+  GtkWidget *path_chunk;
 
   g_return_if_fail (GTK_IS_PATH_BAR (self));
 
   gtk_container_foreach (GTK_CONTAINER (priv->path_box), (GtkCallback) gtk_widget_destroy, NULL);
+  g_list_free (priv->path_chunks);
+  priv->path_chunks = NULL;
 
   splitted_path = g_strsplit (path, "/", -1);
+  current_path = g_string_new ("/");
   for (guint i = 0; i < g_strv_length (splitted_path); i++)
     {
       if (g_strcmp0 (splitted_path[i], "") == 0)
         continue;
-      gtk_container_add (GTK_CONTAINER (priv->path_box), create_path_chunk (self, splitted_path[i]));
+      g_string_append (current_path, splitted_path[i]);
+      path_chunk = create_path_chunk (self, current_path, splitted_path[i]);
+      priv->path_chunks = g_list_append (priv->path_chunks, path_chunk);
+      gtk_container_add (GTK_CONTAINER (priv->path_box), path_chunk);
       gtk_container_add (GTK_CONTAINER (priv->path_box), create_separator ());
     }
 
   g_object_notify_by_pspec (G_OBJECT (self), path_bar_properties[PROP_PATH]);
 
   g_strfreev (splitted_path);
+  g_string_free (current_path, TRUE);
 }
 
 GtkWidget *
@@ -192,9 +250,6 @@ get_path_preferred_width (GtkWidget *self,
       *min_width += child_min_width;
       *nat_width += child_nat_width;
     }
-
-  g_print ("path nat width %d nat_width %d\n", *nat_width, *min_width);
-
 }
 
 static void
@@ -203,16 +258,18 @@ get_preferred_width (GtkWidget *self,
                      gint      *nat_width)
 {
   GtkPathBarPrivate *priv = gtk_path_bar_get_instance_private (GTK_PATH_BAR (self));
-  gint child_min_width;
+  gint overflow_button_min_width;
+  gint overflow_button_nat_width;
 
   *min_width = 0;
   *nat_width = 0;
 
   get_path_preferred_width (self, min_width, nat_width);
-  gtk_widget_get_preferred_width (priv->overflow_button, &child_min_width, NULL);
+  gtk_widget_get_preferred_width (priv->overflow_button, &overflow_button_min_width, 
&overflow_button_nat_width);
 
-  *min_width = MIN (child_min_width, *min_width);
-  g_print ("nat width %d nat_width %d\n", *nat_width, *min_width);
+  *min_width = MIN (overflow_button_min_width, *min_width);
+  *nat_width = MAX (overflow_button_nat_width, *nat_width);
+  g_print ("PREFERRED WIDTH nat width %d min_width %d\n", *nat_width, *min_width);
 }
 
 static void
@@ -245,9 +302,6 @@ get_path_preferred_height (GtkWidget *self,
       *min_height = MAX (*min_height, child_min_height);
       *nat_height = MAX (*nat_height, child_nat_height);
     }
-
-  g_print ("path nat height %d min_heigh %d\n", *nat_height, *min_height);
-
 }
 
 static void
@@ -309,34 +363,74 @@ allocate_overflow_button (GtkWidget     *self,
 }
 
 static void
+update_visible_children (GtkWidget     *self,
+                         GtkAllocation *container_allocation)
+{
+  GtkPathBarPrivate *priv = gtk_path_bar_get_instance_private (GTK_PATH_BAR (self));
+  GList *children;
+  GList *l;
+  gint child_nat_width;
+  gint child_min_width;
+  gboolean overflow;
+  gint path_min_width;
+  gint path_nat_width;
+  gint min_width;
+  gint nat_width;
+  gboolean allocate_more_children = TRUE;
+
+  children = gtk_container_get_children (GTK_CONTAINER (priv->path_box));
+  children = g_list_reverse (children);
+  min_width = 0;
+  nat_width = 0;
+
+  get_path_preferred_width (self, &path_min_width, &path_nat_width);
+  overflow = container_allocation->width < path_min_width;
+
+  if (overflow)
+    {
+      gint overflow_button_min_width;
+
+      gtk_widget_get_preferred_width (priv->overflow_button, &overflow_button_min_width, NULL);
+      min_width += overflow_button_min_width;
+      nat_width += overflow_button_min_width;
+    }
+
+  for (l = children; l != NULL; l = l->next)
+    {
+      gtk_widget_get_preferred_width (l->data, &child_min_width, &child_nat_width);
+      if (min_width + child_min_width <= container_allocation->width && allocate_more_children)
+        {
+          gtk_widget_set_child_visible (l->data, TRUE);
+          min_width += child_min_width;
+          nat_width += child_nat_width;
+        }
+      else
+        {
+          gtk_widget_set_child_visible (l->data, FALSE);
+          allocate_more_children = FALSE;
+        }
+    }
+}
+
+
+static void
 size_allocate (GtkWidget     *self,
                GtkAllocation *allocation)
 {
   GtkPathBarPrivate *priv = gtk_path_bar_get_instance_private (GTK_PATH_BAR (self));
-  GdkWindow *internal_window;
   gint child_min_width;
   gint child_nat_width;
   gint path_min_width;
   gint path_nat_width;
-  gint overflow_button_min_width;
   gint current_x_pos;
   GtkAllocation child_allocation;
   GtkTextDirection direction;
-  gboolean allocate_more_children = TRUE;
   gboolean overflow;
   GList *children;
   GList *l;
 
   gtk_widget_set_allocation (self, allocation);
 
-  internal_window = gtk_widget_get_window (self);
-  if (internal_window)
-    gdk_window_move_resize (internal_window,
-                            allocation->x, allocation->y,
-                            allocation->width, allocation->height);
-
-  gtk_widget_set_child_visible (priv->overflow_button, FALSE);
-
   children = gtk_container_get_children (GTK_CONTAINER (priv->path_box));
 
   if (g_list_length (children) == 0)
@@ -345,13 +439,15 @@ size_allocate (GtkWidget     *self,
   get_path_preferred_width (self, &path_min_width, &path_nat_width);
   overflow = allocation->width < path_min_width;
   direction = gtk_widget_get_direction (self);
-  g_print ("text dir %d\n", direction);
   current_x_pos = direction == GTK_TEXT_DIR_LTR ? allocation->x : allocation->width;
 
-  gtk_widget_get_preferred_width (priv->overflow_button, &overflow_button_min_width, NULL);
+  if (!overflow)
+    gtk_widget_set_child_visible (priv->overflow_button, FALSE);
+
   if (overflow && direction == GTK_TEXT_DIR_LTR)
     allocate_overflow_button (self, allocation, &current_x_pos);
 
+  update_visible_children (self, allocation);
   for (l = children; l != NULL; l = l->next)
     {
       gtk_widget_get_preferred_width (l->data, &child_min_width, &child_nat_width);
@@ -359,12 +455,9 @@ size_allocate (GtkWidget     *self,
       child_allocation.y = allocation->y;
       child_allocation.height = allocation->height;
       g_print ("current x %d child alloc %d alloc %d\n", current_x_pos, child_allocation.width, 
allocation->width);
-      if (((direction == GTK_TEXT_DIR_LTR && current_x_pos + child_allocation.width < allocation->width) ||
-          (direction == GTK_TEXT_DIR_RTL && current_x_pos - child_allocation.width > allocation->x)) &&
-          allocate_more_children)
+      if (gtk_widget_get_child_visible (l->data))
         {
           child_allocation.x = current_x_pos;
-          gtk_widget_set_child_visible (l->data, TRUE);
           gtk_widget_size_allocate (l->data, &child_allocation);
 
           if (direction == GTK_TEXT_DIR_LTR)
@@ -372,17 +465,11 @@ size_allocate (GtkWidget     *self,
           else
             current_x_pos -= child_allocation.width;
         }
-      else
-        {
-          gtk_widget_set_child_visible (l->data, FALSE);
-          allocate_more_children = FALSE;
-        }
     }
 
   if (overflow && direction == GTK_TEXT_DIR_RTL)
     allocate_overflow_button (self, allocation, &current_x_pos);
 
-  // allocate box
   child_allocation.x = allocation->x;
   child_allocation.width = current_x_pos;
   child_allocation.y = allocation->y;
@@ -467,7 +554,7 @@ gtk_path_bar_class_init (GtkPathBarClass *klass)
   gtk_widget_class_bind_template_child_private (widget_class, GtkPathBar, overflow_button);
   gtk_widget_class_bind_template_child_private (widget_class, GtkPathBar, path_box);
 
-  gtk_widget_class_bind_template_callback (widget_class, on_path_chunk_button_clicked);
+  gtk_widget_class_bind_template_callback (widget_class, popup_overflow_menu);
 
   gtk_widget_class_set_css_name (widget_class, "path-bar");
 }
diff --git a/gtk/theme/Adwaita/_common.scss b/gtk/theme/Adwaita/_common.scss
index 295a4b6..f9f587f 100644
--- a/gtk/theme/Adwaita/_common.scss
+++ b/gtk/theme/Adwaita/_common.scss
@@ -1242,18 +1242,19 @@ headerbar {
 path-bar .button.flat {
     background-image: none;
     border-radius: 0px;
-    border-color: transparent;
+    border-top-color: transparent;
+    border-width: 2px 0px 2px 0px;
     box-shadow: 0px 0px 0px;
     margin: 0px;
     opacity: 0.55;
     padding: 3px 8px 4px;
 
     &:hover {
-      box-shadow: 0px 2px 0px mix($selected_bg_color, $selected_fg_color, 75%);
+      border-bottom-color: mix($selected_bg_color, $selected_fg_color, 75%);
     }
 
     &:checked {
-      box-shadow: 0px 2px 0px $selected_bg_color;
+      border-bottom-color: $selected_bg_color;
     }
 }
 
diff --git a/gtk/theme/Adwaita/gtk-contained-dark.css b/gtk/theme/Adwaita/gtk-contained-dark.css
index 73badab..8fddd67 100644
--- a/gtk/theme/Adwaita/gtk-contained-dark.css
+++ b/gtk/theme/Adwaita/gtk-contained-dark.css
@@ -1841,15 +1841,16 @@ headerbar {
 path-bar .button.flat {
   background-image: none;
   border-radius: 0px;
-  border-color: transparent;
+  border-top-color: transparent;
+  border-width: 2px 0px 2px 0px;
   box-shadow: 0px 0px 0px;
   margin: 0px;
   opacity: 0.55;
   padding: 3px 8px 4px; }
   path-bar .button.flat:hover {
-    box-shadow: 0px 2px 0px #5986b5; }
+    border-bottom-color: #5986b5; }
   path-bar .button.flat:checked {
-    box-shadow: 0px 2px 0px #215d9c; }
+    border-bottom-color: #215d9c; }
 
 /**************
  * Tree Views *
diff --git a/gtk/theme/Adwaita/gtk-contained.css b/gtk/theme/Adwaita/gtk-contained.css
index 113c1ad..6a478b3 100644
--- a/gtk/theme/Adwaita/gtk-contained.css
+++ b/gtk/theme/Adwaita/gtk-contained.css
@@ -1841,15 +1841,16 @@ headerbar {
 path-bar .button.flat {
   background-image: none;
   border-radius: 0px;
-  border-color: transparent;
+  border-top-color: transparent;
+  border-width: 2px 0px 2px 0px;
   box-shadow: 0px 0px 0px;
   margin: 0px;
   opacity: 0.55;
   padding: 3px 8px 4px; }
   path-bar .button.flat:hover {
-    box-shadow: 0px 2px 0px #77ace3; }
+    border-bottom-color: #77ace3; }
   path-bar .button.flat:checked {
-    box-shadow: 0px 2px 0px #4a90d9; }
+    border-bottom-color: #4a90d9; }
 
 /**************
  * Tree Views *
diff --git a/gtk/ui/gtkpathbar.ui b/gtk/ui/gtkpathbar.ui
index ae3fa18..0520809 100644
--- a/gtk/ui/gtkpathbar.ui
+++ b/gtk/ui/gtkpathbar.ui
@@ -4,12 +4,12 @@
     <property name="visible">true</property>
     <property name="orientation">horizontal</property>
     <property name="vexpand">false</property>
-    <property name="hexpand">true</property>
     <property name="valign">GTK_ALIGN_START</property>
     <child>
       <object class="GtkButton" id="overflow_button">
         <property name="visible">true</property>
         <property name="no-show-all">true</property>
+        <signal name="clicked" handler="popup_overflow_menu" object="GtkPathBar" swapped="yes"/>
         <child>
           <object class="GtkImage">
             <property name="visible">true</property>
@@ -18,7 +18,7 @@
           </object>
         </child>
         <style>
-          <class name="image-button"/>
+          <class name="flat"/>
         </style>
       </object>
     </child>
diff --git a/tests/testpathbar.c b/tests/testpathbar.c
index 88d80cf..ac1cadd 100644
--- a/tests/testpathbar.c
+++ b/tests/testpathbar.c
@@ -13,7 +13,7 @@ main (int argc, char *argv[])
                                            "type", GTK_WINDOW_TOPLEVEL,
                                            "title", "Test path bar",
                                            "resizable", TRUE,
-                                           "border_width", 10,
+                                           "default-height", 200,
                                            NULL),
                              "signal::destroy", gtk_main_quit, NULL,
                              NULL);
@@ -21,7 +21,7 @@ main (int argc, char *argv[])
   g_type_ensure (GTK_TYPE_PATH_BAR);
   path_bar = gtk_path_bar_new ();
   gtk_container_add (GTK_CONTAINER (window), path_bar);
-  gtk_path_bar_set_path (path_bar, "/test/test 2/pppppppppp/asda lkasdl/// alskd/");
+  gtk_path_bar_set_path (GTK_PATH_BAR (path_bar), "/test/test 2/pppppppppp/asda lkasdl/// alskd/");
   gtk_widget_show_all (window);
 
   gtk_main ();


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