[gtk+/wip/csoriano/pathbar-prototype: 166/166] base funcionality implemented



commit a80b9e163c46a69bb7ef7ccc1469b997726f9c48
Author: Carlos Soriano <csoriano gnome org>
Date:   Tue Nov 3 00:19:45 2015 +0100

    base funcionality implemented
    
    TODO for tomorrow, move the internal gtk_box in a separate
    class to override size_allocate to take into account non-mapped
    children, so we don't trick all the allocation in the main
    gtkpathbar size_allocate.

 gtk/Makefile.am                          |    2 +-
 gtk/glade/gtk-private-widgets.xml        |    2 -
 gtk/gtk.h                                |    1 -
 gtk/gtkpathbar.c                         |  283 +++++++++++++++++++++++++-----
 gtk/gtkpathbar.h                         |    7 +-
 gtk/makefile.msc.in                      |    1 +
 gtk/theme/Adwaita/_common.scss           |    2 +-
 gtk/theme/Adwaita/gtk-contained-dark.css |   12 +-
 gtk/theme/Adwaita/gtk-contained.css      |   12 +-
 gtk/ui/gtkpathbar.ui                     |    2 +-
 tests/testpathbar.c                      |   87 +++++++++-
 11 files changed, 353 insertions(+), 58 deletions(-)
---
diff --git a/gtk/Makefile.am b/gtk/Makefile.am
index 02a3092..bfefd76 100644
--- a/gtk/Makefile.am
+++ b/gtk/Makefile.am
@@ -236,6 +236,7 @@ gtk_public_h_sources =              \
        gtkpagesetup.h          \
        gtkpaned.h              \
        gtkpapersize.h          \
+       gtkpathbar.h            \
        gtkplacessidebar.h      \
        gtkplug.h               \
        gtkpopover.h            \
@@ -483,7 +484,6 @@ gtk_private_h_sources =             \
        gtkmountoperationprivate.h \
        gtkorientableprivate.h  \
        gtkpango.h              \
-       gtkpathbar.h            \
        gtkplacessidebarprivate.h       \
        gtkplacesviewprivate.h  \
        gtkplacesviewrowprivate.h       \
diff --git a/gtk/glade/gtk-private-widgets.xml b/gtk/glade/gtk-private-widgets.xml
index d15a568..91758e4 100644
--- a/gtk/glade/gtk-private-widgets.xml
+++ b/gtk/glade/gtk-private-widgets.xml
@@ -6,7 +6,6 @@
 
   <glade-widget-classes>
     <!-- base GTK+ private widgets -->
-    <glade-widget-class name="GtkPathBar" generic-name="pathbar" title="Path Bar" 
icon-name="widget-gtk-toolbar"/>
     <glade-widget-class name="GtkColorEditor" generic-name="coloreditor" title="Color Editor" 
icon-name="widget-gtk-colorselection"/>
     <glade-widget-class name="GtkColorSwatch" generic-name="colorswatch" title="Color Swatch" 
icon-name="widget-gtk-colorselection"/>
     <glade-widget-class name="GtkColorPlane" generic-name="colorplane" title="Color Plane" 
icon-name="widget-gtk-colorselection"/>
@@ -23,7 +22,6 @@
   </glade-widget-classes>
   
   <glade-widget-group name="gtk-private" title="Private GTK+ Classes">
-    <glade-widget-class-ref name="GtkPathBar"/>
     <glade-widget-class-ref name="GtkColorEditor"/>
     <glade-widget-class-ref name="GtkColorSwatch"/>
     <glade-widget-class-ref name="GtkColorPlane"/>
diff --git a/gtk/gtk.h b/gtk/gtk.h
index 9829e9a..1b4feaf 100644
--- a/gtk/gtk.h
+++ b/gtk/gtk.h
@@ -151,7 +151,6 @@
 #include <gtk/gtkpagesetup.h>
 #include <gtk/gtkpapersize.h>
 #include <gtk/gtkpathbar.h>
-#include <gtk/gtkpapersize.h>
 #include <gtk/gtkpaned.h>
 #include <gtk/gtkplacessidebar.h>
 #include <gtk/gtkpopover.h>
diff --git a/gtk/gtkpathbar.c b/gtk/gtkpathbar.c
index 2ce434c..5285236 100644
--- a/gtk/gtkpathbar.c
+++ b/gtk/gtkpathbar.c
@@ -20,6 +20,7 @@
 
 #include "config.h"
 
+#include "gtkmain.h"
 #include "gtkpathbar.h"
 #include "gtkbutton.h"
 #include "gtktogglebutton.h"
@@ -36,16 +37,18 @@ struct _GtkPathBarPrivate
 {
   GtkWidget *path_box;
   GtkWidget *overflow_button;
+  GtkWidget *path_chunk_popover_container;
 
   gchar *path;
-  GList *overflow_path_chunks;
-  GList *path_chunks;
+
+  gboolean selecting_path;
 };
 
 G_DEFINE_TYPE_WITH_PRIVATE (GtkPathBar, gtk_path_bar, GTK_TYPE_BOX)
 
 enum {
   POPULATE_POPUP,
+  PATH_SELECTED,
   LAST_SIGNAL
 };
 
@@ -59,27 +62,106 @@ static GParamSpec *path_bar_properties[LAST_PROP] = { NULL, };
 static guint path_bar_signals[LAST_SIGNAL] = { 0 };
 
 typedef struct {
+  GtkWidget *button;
   gchar *label;
   GString *path;
+  GtkPathBar *path_bar;
 } PathChunkData;
 
 static void
-on_path_chunk_button_clicked (GtkPathBar *self,
-                              GtkButton  *path_chunk_button)
+emit_path_selected (GtkPathBar  *self,
+                    const gchar *path)
 {
-  g_print ("cliked %s\n", gtk_button_get_label (GTK_BUTTON (path_chunk_button)));
+  g_signal_emit (self, path_bar_signals[PATH_SELECTED], 0, path);
+
 }
 
-GtkWidget *
-create_separator ()
+static void
+emit_populate_popup (GtkPathBar  *self,
+                     const gchar *path)
+{
+  GtkPathBarPrivate *priv = gtk_path_bar_get_instance_private (GTK_PATH_BAR (self));
+
+  g_signal_emit (self, path_bar_signals[POPULATE_POPUP], 0,
+                 priv->path_chunk_popover_container, path);
+}
+
+static void
+on_path_chunk_popover_destroyed (GtkPathBar *self)
+{
+  GtkPathBarPrivate *priv;
+
+  if (self == NULL)
+    return;
+
+  priv = gtk_path_bar_get_instance_private (GTK_PATH_BAR (self));
+  priv->path_chunk_popover_container = NULL;
+}
+
+static void
+show_path_chunk_popover (GtkPathBar *self,
+                         GtkWidget  *path_chunk)
 {
-  GtkWidget *label;
+  GtkPathBarPrivate *priv = gtk_path_bar_get_instance_private (GTK_PATH_BAR (self));
+  GtkWidget *popover;
+
+  if (priv->path_chunk_popover_container != NULL)
+    {
+      popover = gtk_widget_get_ancestor (priv->path_chunk_popover_container,
+                                         GTK_TYPE_POPOVER);
+      gtk_widget_destroy (popover);
+    }
+
+  popover = gtk_popover_new (path_chunk);
+  priv->path_chunk_popover_container = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
+  gtk_container_add (GTK_CONTAINER (popover), priv->path_chunk_popover_container);
+  /* Clean private pointer when its destroyed, most of the times due to its
+   * relative_to associated widget being destroyed */
+  g_signal_connect_swapped (popover, "destroy",
+                            G_CALLBACK (on_path_chunk_popover_destroyed), self);
+
+  gtk_widget_show (popover);
+}
+
+static gboolean
+on_path_chunk_button_release_event (GtkWidget      *path_chunk,
+                                    GdkEventButton *event)
+{
+  PathChunkData *data;
+  GtkPathBarPrivate *priv;
 
-  label = gtk_label_new ("/");
-  gtk_widget_set_sensitive (label, FALSE);
-  gtk_widget_show (label);
+  data = g_object_get_data (G_OBJECT (path_chunk), "data");
+  g_assert (data != NULL);
 
-  return label;
+  priv = gtk_path_bar_get_instance_private (GTK_PATH_BAR (data->path_bar));
+
+  if (event->type == GDK_BUTTON_RELEASE)
+    {
+      switch (event->button)
+        {
+        case GDK_BUTTON_PRIMARY:
+          if (priv->selecting_path)
+            return TRUE;
+
+          priv->selecting_path = TRUE;
+          gtk_path_bar_select_path (data->path_bar, (const gchar*) data->path->str);
+          priv->selecting_path = FALSE;
+          emit_path_selected (data->path_bar, data->path->str);
+
+          return TRUE;
+
+        case GDK_BUTTON_SECONDARY:
+          show_path_chunk_popover (data->path_bar, path_chunk);
+          emit_populate_popup (data->path_bar, data->path->str);
+
+          return TRUE;
+
+        default:
+          break;
+        }
+    }
+
+  return FALSE;
 }
 
 static void
@@ -90,35 +172,65 @@ free_path_chunk_data (PathChunkData *data)
   g_slice_free (PathChunkData, data);
 }
 
-GtkWidget *
-create_path_chunk (GtkPathBar  *self,
+static GtkWidget *
+create_path_chunk (GtkPathBar    *self,
                    const GString *path,
-                   const gchar *label)
+                   const gchar   *label,
+                   gboolean       add_separator)
 {
   GtkWidget *button;
+  GtkWidget *separator;
+  GtkWidget *path_chunk;
   GtkStyleContext *style;
   PathChunkData *path_chunk_data;
+  GtkTextDirection direction;
+
+  direction = gtk_widget_get_direction (GTK_WIDGET (self));
+
+  path_chunk = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
 
   button = gtk_toggle_button_new_with_label (label);
+
+  g_signal_connect_swapped (button, "button-release-event",
+                            G_CALLBACK (on_path_chunk_button_release_event), path_chunk);
+  style = gtk_widget_get_style_context (button);
+  gtk_style_context_add_class (style, "flat");
+
+  if (add_separator)
+    {
+      separator = gtk_label_new ("/");
+      gtk_widget_set_sensitive (separator, FALSE);
+    }
+
+  if (direction == GTK_TEXT_DIR_LTR)
+    {
+      gtk_container_add (GTK_CONTAINER (path_chunk), button);
+      if (add_separator)
+        gtk_container_add (GTK_CONTAINER (path_chunk), separator);
+    } else {
+      if (add_separator)
+        gtk_container_add (GTK_CONTAINER (path_chunk), separator);
+      gtk_container_add (GTK_CONTAINER (path_chunk), button);
+    }
+
   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->path_bar = self;
+  path_chunk_data->button = button;
+  g_object_set_data_full (G_OBJECT (path_chunk), "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, "flat");
 
-  return button;
+  gtk_widget_show_all (path_chunk);
+
+  return path_chunk;
 }
 
 static void
 popup_overflow_menu (GtkPathBar *self)
 {
   GtkPathBarPrivate *priv = gtk_path_bar_get_instance_private (GTK_PATH_BAR (self));
+  GList *children;
   GList *l;
   PathChunkData *data;
   GtkWidget *path_chunk;
@@ -126,54 +238,110 @@ popup_overflow_menu (GtkPathBar *self)
   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)
+
+  children = gtk_container_get_children (GTK_CONTAINER (priv->path_box));
+  for (l = children; 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);
+          path_chunk = create_path_chunk (self, (const GString*) data->path,
+                                          (const gchar*) data->label, FALSE);
           gtk_container_add (GTK_CONTAINER (overflow_box), path_chunk);
         }
     }
 
-  gtk_widget_show (popover);
+  gtk_widget_show_all (popover);
+
+  g_list_free (children);
 }
 
 void
 gtk_path_bar_set_path (GtkPathBar  *self,
                        const gchar *path)
 {
-  GtkPathBarPrivate *priv = gtk_path_bar_get_instance_private (GTK_PATH_BAR (self));
+  GtkPathBarPrivate *priv;
   gchar ** splitted_path;
   GString *current_path = NULL;
   GtkWidget *path_chunk;
+  PathChunkData *data;
+  GList *children;
 
   g_return_if_fail (GTK_IS_PATH_BAR (self));
 
+  priv = gtk_path_bar_get_instance_private (GTK_PATH_BAR (self));
+
+  if (g_strcmp0 (priv->path, path) == 0)
+    return;
+
   gtk_container_foreach (GTK_CONTAINER (priv->path_box), (GtkCallback) gtk_widget_destroy, NULL);
-  g_list_free (priv->path_chunks);
-  priv->path_chunks = NULL;
+
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->overflow_button), FALSE);
+
+  if (priv->path)
+    {
+      g_free (priv->path);
+      priv->path = NULL;
+    }
 
   splitted_path = g_strsplit (path, "/", -1);
-  current_path = g_string_new ("/");
+  current_path = g_string_new ("");
   for (guint i = 0; i < g_strv_length (splitted_path); i++)
     {
       if (g_strcmp0 (splitted_path[i], "") == 0)
         continue;
+
+      g_string_append (current_path, "/");
       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);
+      path_chunk = create_path_chunk (self, current_path, splitted_path[i], TRUE);
       gtk_container_add (GTK_CONTAINER (priv->path_box), path_chunk);
-      gtk_container_add (GTK_CONTAINER (priv->path_box), create_separator ());
+      data = g_object_get_data (G_OBJECT (path_chunk), "data");
+    }
+
+  children = gtk_container_get_children (GTK_CONTAINER (priv->path_box));
+  if (children != NULL)
+    {
+      path_chunk = GTK_WIDGET (g_list_last (children)->data);
+      data = g_object_get_data (G_OBJECT (path_chunk), "data");
+      priv->selecting_path = TRUE;
+      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (data->button), TRUE);
+      priv->selecting_path = FALSE;
+      priv->path = g_strdup (data->path->str);
     }
 
   g_object_notify_by_pspec (G_OBJECT (self), path_bar_properties[PROP_PATH]);
 
   g_strfreev (splitted_path);
   g_string_free (current_path, TRUE);
+  g_list_free (children);
+}
+
+void
+gtk_path_bar_select_path (GtkPathBar  *self,
+                          const gchar *path)
+{
+  GtkPathBarPrivate *priv;
+  PathChunkData *data;
+  GList *children;
+  GList *l;
+
+  g_return_if_fail (GTK_IS_PATH_BAR (self));
+
+  priv = gtk_path_bar_get_instance_private (GTK_PATH_BAR (self));
+
+  g_return_if_fail (g_str_has_prefix (priv->path, path));
+
+  children = gtk_container_get_children (GTK_CONTAINER (priv->path_box));
+  for (l = children; l != NULL; l = l->next)
+    {
+      data = g_object_get_data (G_OBJECT (l->data), "data");
+      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (data->button),
+                                    g_strcmp0 (data->path->str, path) == 0);
+    }
+
+  g_list_free (children);
 }
 
 GtkWidget *
@@ -224,6 +392,7 @@ gtk_path_bar_set_property (GObject      *object,
     {
     case PROP_PATH:
       gtk_path_bar_set_path (self, g_value_get_string (value));
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
     }
@@ -250,6 +419,8 @@ get_path_preferred_width (GtkWidget *self,
       *min_width += child_min_width;
       *nat_width += child_nat_width;
     }
+
+  g_list_free (children);
 }
 
 static void
@@ -269,7 +440,6 @@ get_preferred_width (GtkWidget *self,
 
   *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
@@ -302,6 +472,8 @@ get_path_preferred_height (GtkWidget *self,
       *min_height = MAX (*min_height, child_min_height);
       *nat_height = MAX (*nat_height, child_nat_height);
     }
+
+  g_list_free (children);
 }
 
 static void
@@ -349,7 +521,6 @@ allocate_overflow_button (GtkWidget     *self,
 
   direction = gtk_widget_get_direction (self);
   gtk_widget_get_preferred_width (priv->overflow_button, &overflow_button_min_width, NULL);
-  gtk_widget_set_child_visible (priv->overflow_button, TRUE);
   child_allocation.y = container_allocation->y;
   child_allocation.height = container_allocation->height;
   child_allocation.width = overflow_button_min_width;
@@ -386,6 +557,8 @@ update_visible_children (GtkWidget     *self,
   get_path_preferred_width (self, &path_min_width, &path_nat_width);
   overflow = container_allocation->width < path_min_width;
 
+  gtk_widget_set_child_visible (priv->overflow_button, overflow);
+
   if (overflow)
     {
       gint overflow_button_min_width;
@@ -410,6 +583,8 @@ update_visible_children (GtkWidget     *self,
           allocate_more_children = FALSE;
         }
     }
+
+  g_list_free (children);
 }
 
 
@@ -423,6 +598,8 @@ size_allocate (GtkWidget     *self,
   gint path_min_width;
   gint path_nat_width;
   gint current_x_pos;
+  gint box_start_x;
+  gint box_width;
   GtkAllocation child_allocation;
   GtkTextDirection direction;
   gboolean overflow;
@@ -439,22 +616,22 @@ 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);
-  current_x_pos = direction == GTK_TEXT_DIR_LTR ? allocation->x : allocation->width;
+  box_start_x = current_x_pos = direction == GTK_TEXT_DIR_LTR ? allocation->x : allocation->width;
 
-  if (!overflow)
-    gtk_widget_set_child_visible (priv->overflow_button, FALSE);
+  update_visible_children (self, allocation);
 
   if (overflow && direction == GTK_TEXT_DIR_LTR)
-    allocate_overflow_button (self, allocation, &current_x_pos);
+    {
+      allocate_overflow_button (self, allocation, &current_x_pos);
+      box_start_x = 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);
       child_allocation.width = overflow ? child_min_width : child_nat_width;
       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 (gtk_widget_get_child_visible (l->data))
         {
           child_allocation.x = current_x_pos;
@@ -467,14 +644,18 @@ size_allocate (GtkWidget     *self,
         }
     }
 
+  box_width = current_x_pos;
+
   if (overflow && direction == GTK_TEXT_DIR_RTL)
     allocate_overflow_button (self, allocation, &current_x_pos);
 
-  child_allocation.x = allocation->x;
-  child_allocation.width = current_x_pos;
+  child_allocation.x = box_start_x;
+  child_allocation.width = box_width;
   child_allocation.y = allocation->y;
   child_allocation.height = allocation->height;
   gtk_widget_size_allocate (priv->path_box, &child_allocation);
+
+  g_list_free (children);
 }
 
 static void
@@ -540,6 +721,16 @@ gtk_path_bar_class_init (GtkPathBarClass *klass)
                         GTK_TYPE_WIDGET,
                         G_TYPE_STRING);
 
+  path_bar_signals [PATH_SELECTED] =
+          g_signal_new (I_("path-selected"),
+                        G_OBJECT_CLASS_TYPE (object_class),
+                        G_SIGNAL_RUN_FIRST,
+                        G_STRUCT_OFFSET (GtkPathBarClass, path_selected),
+                        NULL, NULL,
+                        _gtk_marshal_VOID__OBJECT_STRING,
+                        G_TYPE_NONE, 1,
+                        G_TYPE_STRING);
+
   path_bar_properties[PROP_PATH] =
           g_param_spec_string ("path",
                                P_("Path"),
@@ -562,6 +753,10 @@ gtk_path_bar_class_init (GtkPathBarClass *klass)
 static void
 gtk_path_bar_init (GtkPathBar *self)
 {
+  GtkPathBarPrivate *priv = gtk_path_bar_get_instance_private (self);
+
   g_type_ensure (GTK_TYPE_BOX);
   gtk_widget_init_template (GTK_WIDGET (self));
+
+  priv->selecting_path = FALSE;
 }
diff --git a/gtk/gtkpathbar.h b/gtk/gtkpathbar.h
index ff79e04..7fc4b2e 100644
--- a/gtk/gtkpathbar.h
+++ b/gtk/gtkpathbar.h
@@ -48,6 +48,8 @@ struct _GtkPathBarClass
 
   void                (* populate_popup)              (GtkPathBar       *path_bar,
                                                        const gchar      *selected_path);
+  void                (* path_selected)              (GtkPathBar        *path_bar,
+                                                      const gchar       *selected_path);
 
   /*< private >*/
 
@@ -66,7 +68,10 @@ GDK_AVAILABLE_IN_3_18
 GtkWidget*            gtk_path_bar_new                (void);
 GDK_AVAILABLE_IN_3_18
 void                  gtk_path_bar_set_path           (GtkPathBar       *path_bar,
-                                                       const gchar      *location);
+                                                       const gchar      *path);
+GDK_AVAILABLE_IN_3_18
+void                  gtk_path_bar_select_path        (GtkPathBar       *path_bar,
+                                                       const gchar      *path);
 GDK_AVAILABLE_IN_3_18
 const gchar*          gtk_path_bar_get_path           (GtkPathBar       *path_bar);
 
diff --git a/gtk/makefile.msc.in b/gtk/makefile.msc.in
index 78a5244..fcce86b 100644
--- a/gtk/makefile.msc.in
+++ b/gtk/makefile.msc.in
@@ -446,6 +446,7 @@ gtk_public_h_sources =              \
        gtkpagesetup.h          \
        gtkpaned.h              \
        gtkpapersize.h          \
+       gtkpathbar.h            \
        gtkplug.h               \
        gtkprintcontext.h       \
        gtkprintoperation.h     \
diff --git a/gtk/theme/Adwaita/_common.scss b/gtk/theme/Adwaita/_common.scss
index f9f587f..98756cd 100644
--- a/gtk/theme/Adwaita/_common.scss
+++ b/gtk/theme/Adwaita/_common.scss
@@ -1239,7 +1239,7 @@ headerbar {
  * Pathbars *
  ************/
 
-path-bar .button.flat {
+path-bar button.flat {
     background-image: none;
     border-radius: 0px;
     border-top-color: transparent;
diff --git a/gtk/theme/Adwaita/gtk-contained-dark.css b/gtk/theme/Adwaita/gtk-contained-dark.css
index 8fddd67..335d6b5 100644
--- a/gtk/theme/Adwaita/gtk-contained-dark.css
+++ b/gtk/theme/Adwaita/gtk-contained-dark.css
@@ -1838,7 +1838,9 @@ headerbar {
 /************
  * Pathbars *
  ************/
-path-bar .button.flat {
+path-bar button.flat, path-bar .sidebar-button.button, path-bar headerbar button.titlebutton, headerbar 
path-bar button.titlebutton,
+path-bar .titlebar button.titlebutton,
+.titlebar path-bar button.titlebutton {
   background-image: none;
   border-radius: 0px;
   border-top-color: transparent;
@@ -1847,9 +1849,13 @@ path-bar .button.flat {
   margin: 0px;
   opacity: 0.55;
   padding: 3px 8px 4px; }
-  path-bar .button.flat:hover {
+  path-bar button.flat:hover, path-bar .sidebar-button.button:hover, path-bar headerbar 
button.titlebutton:hover, headerbar path-bar button.titlebutton:hover,
+  path-bar .titlebar button.titlebutton:hover,
+  .titlebar path-bar button.titlebutton:hover {
     border-bottom-color: #5986b5; }
-  path-bar .button.flat:checked {
+  path-bar button.flat:checked, path-bar .sidebar-button.button:checked, path-bar headerbar 
button.titlebutton:checked, headerbar path-bar button.titlebutton:checked,
+  path-bar .titlebar button.titlebutton:checked,
+  .titlebar path-bar button.titlebutton:checked {
     border-bottom-color: #215d9c; }
 
 /**************
diff --git a/gtk/theme/Adwaita/gtk-contained.css b/gtk/theme/Adwaita/gtk-contained.css
index 6a478b3..5e6dc36 100644
--- a/gtk/theme/Adwaita/gtk-contained.css
+++ b/gtk/theme/Adwaita/gtk-contained.css
@@ -1838,7 +1838,9 @@ headerbar {
 /************
  * Pathbars *
  ************/
-path-bar .button.flat {
+path-bar button.flat, path-bar .sidebar-button.button, path-bar headerbar button.titlebutton, headerbar 
path-bar button.titlebutton,
+path-bar .titlebar button.titlebutton,
+.titlebar path-bar button.titlebutton {
   background-image: none;
   border-radius: 0px;
   border-top-color: transparent;
@@ -1847,9 +1849,13 @@ path-bar .button.flat {
   margin: 0px;
   opacity: 0.55;
   padding: 3px 8px 4px; }
-  path-bar .button.flat:hover {
+  path-bar button.flat:hover, path-bar .sidebar-button.button:hover, path-bar headerbar 
button.titlebutton:hover, headerbar path-bar button.titlebutton:hover,
+  path-bar .titlebar button.titlebutton:hover,
+  .titlebar path-bar button.titlebutton:hover {
     border-bottom-color: #77ace3; }
-  path-bar .button.flat:checked {
+  path-bar button.flat:checked, path-bar .sidebar-button.button:checked, path-bar headerbar 
button.titlebutton:checked, headerbar path-bar button.titlebutton:checked,
+  path-bar .titlebar button.titlebutton:checked,
+  .titlebar path-bar button.titlebutton:checked {
     border-bottom-color: #4a90d9; }
 
 /**************
diff --git a/gtk/ui/gtkpathbar.ui b/gtk/ui/gtkpathbar.ui
index 0520809..599ef70 100644
--- a/gtk/ui/gtkpathbar.ui
+++ b/gtk/ui/gtkpathbar.ui
@@ -6,7 +6,7 @@
     <property name="vexpand">false</property>
     <property name="valign">GTK_ALIGN_START</property>
     <child>
-      <object class="GtkButton" id="overflow_button">
+      <object class="GtkToggleButton" 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"/>
diff --git a/tests/testpathbar.c b/tests/testpathbar.c
index ac1cadd..1861a7f 100644
--- a/tests/testpathbar.c
+++ b/tests/testpathbar.c
@@ -1,6 +1,80 @@
 #include "config.h"
+#include "glib.h"
 #include <gtk/gtk.h>
 
+static GActionGroup *action_group;
+
+static void
+action_menu_1 (GSimpleAction *action,
+               GVariant      *variant,
+               gpointer       user_data)
+{
+  g_print ("Menu 1 action\n");
+}
+
+static void
+action_menu_2 (GSimpleAction *action,
+               GVariant      *variant,
+               gpointer       user_data)
+{
+  g_print ("Menu 2 action\n");
+}
+
+static void
+action_special (GSimpleAction *action,
+                GVariant      *variant,
+                gpointer       user_data)
+{
+  g_print ("Special action\n");
+}
+
+const GActionEntry entries[] = {
+  { "menu_1",  action_menu_1 },
+  { "menu_2",  action_menu_2 },
+  { "special", action_special },
+};
+
+static void
+on_populate_popup (GtkPathBar  *path_bar,
+                   GtkWidget   *container,
+                   const gchar *selected_path)
+{
+  GtkWidget *menu_item;
+
+  menu_item = gtk_model_button_new ();
+  gtk_actionable_set_action_name (GTK_ACTIONABLE (menu_item),
+                                  "action_group.menu_1");
+  g_object_set (menu_item, "text", "Menu 1", NULL);
+  g_print ("container %s\n", G_OBJECT_TYPE_NAME (container));
+  gtk_container_add (GTK_CONTAINER (container), menu_item);
+
+  menu_item = gtk_model_button_new ();
+  gtk_actionable_set_action_name (GTK_ACTIONABLE (menu_item),
+                                  "action_group.menu_2");
+  g_object_set (menu_item, "text", "Menu 2", NULL);
+  gtk_container_add (GTK_CONTAINER (container), menu_item);
+
+  if (g_strcmp0 (selected_path, "/test/test 2/test 3") == 0)
+    {
+      menu_item = gtk_model_button_new ();
+      gtk_actionable_set_action_name (GTK_ACTIONABLE (menu_item),
+                                      "action_group.special");
+      g_object_set (menu_item, "text", "Special", NULL);
+      gtk_container_add (GTK_CONTAINER (container), menu_item);
+    }
+
+  gtk_widget_show_all (container);
+
+  g_print ("Populate popup\n");
+}
+
+static void
+on_path_selected (GtkPathBar  *path_bar,
+                  const gchar *path)
+{
+  g_print ("Path selected: %s\n", path);
+}
+
 int
 main (int argc, char *argv[])
 {
@@ -18,12 +92,23 @@ main (int argc, char *argv[])
                              "signal::destroy", gtk_main_quit, NULL,
                              NULL);
 
+  action_group = G_ACTION_GROUP (g_simple_action_group_new ());
+  g_action_map_add_action_entries (G_ACTION_MAP (action_group), entries,
+                                   G_N_ELEMENTS (entries), window);
+
+  gtk_widget_insert_action_group (window, "action_group", action_group);
+
   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 (GTK_PATH_BAR (path_bar), "/test/test 2/pppppppppp/asda lkasdl/// alskd/");
+  gtk_path_bar_set_path (GTK_PATH_BAR (path_bar), "/test/test 2/test 3/asda lkasdl//pppppppppppppppp/ 
alskd/");
   gtk_widget_show_all (window);
 
+  g_signal_connect (GTK_PATH_BAR (path_bar), "populate-popup",
+                    G_CALLBACK (on_populate_popup), window);
+  g_signal_connect (GTK_PATH_BAR (path_bar), "path-selected",
+                    G_CALLBACK (on_path_selected), window);
+
   gtk_main ();
 
   return 0;


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