[gtk+/wip/csoriano/pathbar-prototype] gtkpathbarcontainer



commit 5ce402942acb47b0d97b2563126117fe28dac1ef
Author: Carlos Soriano <csoriano gnome org>
Date:   Tue Nov 10 16:43:23 2015 +0100

    gtkpathbarcontainer

 gtk/Makefile.am                  |    2 +
 gtk/gtkpathbar.c                 |    4 +-
 gtk/gtkpathbarcontainer.c        |  215 ++++++++++++++++++++++++++++++++++++++
 gtk/gtkpathbarcontainerprivate.h |   66 ++++++++++++
 gtk/ui/gtkpathbar.ui             |   14 +--
 5 files changed, 292 insertions(+), 9 deletions(-)
---
diff --git a/gtk/Makefile.am b/gtk/Makefile.am
index e75ecec..9fef535 100644
--- a/gtk/Makefile.am
+++ b/gtk/Makefile.am
@@ -484,6 +484,7 @@ gtk_private_h_sources =             \
        gtkmodulesprivate.h     \
        gtkmountoperationprivate.h \
        gtkorientableprivate.h  \
+       gtkpathbarcontainerprivate.h \
        gtkpango.h              \
        gtkplacessidebarprivate.h       \
        gtkplacesviewprivate.h  \
@@ -767,6 +768,7 @@ gtk_base_c_sources =                \
        gtkorientable.c         \
        gtkoverlay.c            \
        gtkpagesetup.c          \
+       gtkpathbarcontainer.c   \
        gtkpaned.c              \
        gtkpango.c              \
        gtkpapersize.c          \
diff --git a/gtk/gtkpathbar.c b/gtk/gtkpathbar.c
index aae7f07..208bd7f 100644
--- a/gtk/gtkpathbar.c
+++ b/gtk/gtkpathbar.c
@@ -29,6 +29,7 @@
 #include "gtkpopover.h"
 #include "gtkbuilder.h"
 #include "gtkstylecontext.h"
+#include "gtkpathbarcontainerprivate.h"
 
 #include "gtkintl.h"
 #include "gtkmarshalers.h"
@@ -450,7 +451,7 @@ gtk_path_bar_class_init (GtkPathBarClass *klass)
   object_class->set_property = gtk_path_bar_set_property;
 
   widget_class->get_request_mode = get_request_mode;
-  widget_class->size_allocate = size_allocate;
+  //widget_class->size_allocate = size_allocate;
 
   /**
    * GtkPlacesSidebar::populate-popup:
@@ -685,5 +686,6 @@ gtk_path_bar_get_hide_direction (GtkPathBar *self)
 GtkWidget *
 gtk_path_bar_new (void)
 {
+  g_type_ensure (GTK_TYPE_PATH_BAR_CONTAINER);
   return g_object_new (GTK_TYPE_PATH_BAR, NULL);
 }
diff --git a/gtk/gtkpathbarcontainer.c b/gtk/gtkpathbarcontainer.c
new file mode 100644
index 0000000..b6df1bb
--- /dev/null
+++ b/gtk/gtkpathbarcontainer.c
@@ -0,0 +1,215 @@
+/* gtkpathbarcontainer.c
+ *
+ * Copyright (C) 2015 Red Hat
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Carlos Soriano <csoriano gnome org>
+ */
+
+#include "config.h"
+
+#include "gtkpathbarcontainerprivate.h"
+#include "gtkbuildable.h"
+#include "gtkwidget.h"
+#include "gtkmenubutton.h"
+#include "gtksizerequest.h"
+#include "gtkhidingboxprivate.h"
+
+struct _GtkPathBarContainerPrivate
+{
+  GtkWidget *overflow_button;
+  GtkWidget *path_box;
+};
+
+static GtkBuildableIface *parent_buildable_iface;
+
+static GObject *
+buildable_get_internal_child (GtkBuildable *buildable,
+                              GtkBuilder   *builder,
+                              const gchar  *childname)
+{
+  g_print ("get internal child %s\n", childname);
+  if (g_strcmp0 (childname, "overflow_button") == 0)
+    return G_OBJECT (gtk_path_bar_container_get_overflow_button (GTK_PATH_BAR_CONTAINER (buildable)));
+  if (g_strcmp0 (childname, "path_box") == 0)
+    return G_OBJECT (gtk_path_bar_container_get_path_box (GTK_PATH_BAR_CONTAINER (buildable)));
+
+  return parent_buildable_iface->get_internal_child (buildable, builder, childname);
+}
+
+static void
+buildable_init (GtkBuildableIface *iface)
+{
+  parent_buildable_iface = g_type_interface_peek_parent (iface);
+  iface->get_internal_child = buildable_get_internal_child;
+}
+
+G_DEFINE_TYPE_WITH_CODE (GtkPathBarContainer, gtk_path_bar_container, GTK_TYPE_WIDGET,
+                         G_ADD_PRIVATE (GtkPathBarContainer)
+                         G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE, buildable_init))
+
+static GtkSizeRequestMode
+get_request_mode (GtkWidget *self)
+{
+  return GTK_SIZE_REQUEST_WIDTH_FOR_HEIGHT;
+}
+
+static void
+size_allocate (GtkWidget     *self,
+               GtkAllocation *allocation)
+{
+  GtkPathBarContainerPrivate *priv = gtk_path_bar_container_get_instance_private (GTK_PATH_BAR_CONTAINER 
(self));
+  gint path_min_width;
+  gint path_nat_width;
+  gint overflow_button_min_width;
+  GtkAllocation path_container_allocation;
+  GtkAllocation overflow_button_allocation;
+  GtkTextDirection direction;
+  gboolean overflow;
+  GList *overflow_children;
+  GList *children;
+
+  gtk_widget_set_allocation (self, allocation);
+
+  children = gtk_container_get_children (GTK_CONTAINER (priv->path_box));
+  gtk_widget_set_child_visible (priv->overflow_button, FALSE);
+
+  if (g_list_length (children) == 0)
+    return;
+
+  gtk_widget_get_preferred_width (priv->path_box, &path_min_width, &path_nat_width);
+  gtk_widget_get_preferred_width (priv->overflow_button, &overflow_button_min_width, NULL);
+
+  /* Try to allocate all children with our allocation so we can request if there
+   * is some overflow children */
+  path_container_allocation.x = allocation->x;
+  path_container_allocation.width = allocation->width;
+  path_container_allocation.y = allocation->y;
+  path_container_allocation.height = allocation->height;
+  gtk_widget_size_allocate (priv->path_box, &path_container_allocation);
+  overflow_children = gtk_hiding_box_get_overflow_children (GTK_HIDING_BOX (priv->path_box));
+  overflow = overflow_children != NULL;
+  g_list_free (overflow_children);
+
+  direction = gtk_widget_get_direction (self);
+
+  if (overflow && direction == GTK_TEXT_DIR_LTR)
+    {
+      overflow_button_allocation.y = allocation->y;
+      overflow_button_allocation.height = allocation->height;
+      overflow_button_allocation.width = overflow_button_min_width;
+      overflow_button_allocation.x = allocation->x;
+      gtk_widget_set_child_visible (priv->overflow_button, TRUE);
+      gtk_widget_size_allocate (priv->overflow_button, &overflow_button_allocation);
+    }
+
+  path_container_allocation.x = overflow ? allocation->x + overflow_button_min_width
+                                         : allocation->x;
+  path_container_allocation.width = overflow ? allocation->width - overflow_button_min_width
+                                             : allocation->width;
+  path_container_allocation.y = allocation->y;
+  path_container_allocation.height = allocation->height;
+  g_print ("allocating path_box\n");
+  gtk_widget_size_allocate (priv->path_box, &path_container_allocation);
+
+  if (overflow && direction == GTK_TEXT_DIR_RTL)
+    {
+      overflow_button_allocation.y = allocation->y;
+      overflow_button_allocation.height = allocation->height;
+      overflow_button_allocation.width = overflow_button_min_width;
+      overflow_button_allocation.x = path_container_allocation.x +
+                                     path_container_allocation.width -
+                                     overflow_button_min_width;
+      gtk_widget_set_child_visible (priv->overflow_button, TRUE);
+      gtk_widget_size_allocate (priv->overflow_button, &overflow_button_allocation);
+    }
+
+  g_list_free (children);
+}
+
+static void
+get_preferred_width (GtkWidget *self,
+                     gint      *minimum_width,
+                     gint      *natural_width)
+{
+  GtkPathBarContainerPrivate *priv = gtk_path_bar_container_get_instance_private (GTK_PATH_BAR_CONTAINER 
(self));
+
+  gtk_widget_get_preferred_width (priv->path_box, minimum_width, natural_width);
+}
+
+static void
+get_preferred_height (GtkWidget *self,
+                      gint      *minimum_height,
+                      gint      *natural_height)
+{
+  GtkPathBarContainerPrivate *priv = gtk_path_bar_container_get_instance_private (GTK_PATH_BAR_CONTAINER 
(self));
+
+  gtk_widget_get_preferred_height (priv->path_box, minimum_height, natural_height);
+}
+
+static void
+gtk_path_bar_container_class_init (GtkPathBarContainerClass *klass)
+{
+  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+  widget_class->get_request_mode = get_request_mode;
+  widget_class->get_preferred_width = get_preferred_width;
+  widget_class->get_preferred_height = get_preferred_height;
+  widget_class->size_allocate = size_allocate;
+}
+
+static void
+gtk_path_bar_container_init (GtkPathBarContainer *self)
+{
+  GtkPathBarContainerPrivate *priv = gtk_path_bar_container_get_instance_private (self);
+
+  gtk_widget_set_has_window (GTK_WIDGET (self), FALSE);
+  priv->overflow_button = gtk_menu_button_new ();
+  gtk_widget_show (priv->overflow_button);
+  gtk_widget_set_name (priv->overflow_button, "overflow_button");
+  priv->path_box = gtk_hiding_box_new ();
+  gtk_widget_show (priv->path_box);
+  gtk_widget_set_name (priv->path_box, "path_box");
+}
+
+GtkWidget *
+gtk_path_bar_container_new (void)
+{
+  return g_object_new (GTK_TYPE_PATH_BAR_CONTAINER, NULL);
+}
+
+GtkWidget *
+gtk_path_bar_container_get_overflow_button (GtkPathBarContainer *self)
+{
+  GtkPathBarContainerPrivate *priv;
+
+  g_return_val_if_fail (GTK_IS_PATH_BAR_CONTAINER (self), NULL);
+
+  priv = gtk_path_bar_container_get_instance_private (self);
+
+  return priv->overflow_button;
+}
+
+GtkWidget *
+gtk_path_bar_container_get_path_box (GtkPathBarContainer *self)
+{
+  GtkPathBarContainerPrivate *priv;
+
+  g_return_val_if_fail (GTK_IS_PATH_BAR_CONTAINER (self), NULL);
+
+  priv = gtk_path_bar_container_get_instance_private (self);
+
+  return priv->path_box;
+}
diff --git a/gtk/gtkpathbarcontainerprivate.h b/gtk/gtkpathbarcontainerprivate.h
new file mode 100644
index 0000000..30ce818
--- /dev/null
+++ b/gtk/gtkpathbarcontainerprivate.h
@@ -0,0 +1,66 @@
+/* gtkpathbarcontainerprivate.h
+ *
+ * Copyright (C) 2015 Red Hat
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Carlos Soriano <csoriano gnome org>
+ */
+
+#ifndef __GTK_PATH_BAR_CONTAINER_PRIVATE_H__
+#define __GTK_PATH_BAR_CONTAINER_PRIVATE_H__
+
+#if !defined (__GTK_H_INSIDE__) && !defined (GTK_COMPILATION)
+#error "Only <gtk/gtk.h> can be included directly."
+#endif
+
+#include <gtk/gtkwidget.h>
+
+G_BEGIN_DECLS
+
+#define GTK_TYPE_PATH_BAR_CONTAINER            (gtk_path_bar_container_get_type())
+#define GTK_PATH_BAR_CONTAINER(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), 
GTK_TYPE_PATH_BAR_CONTAINER, GtkPathBarContainer))
+#define GTK_PATH_BAR_CONTAINER_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), 
GTK_TYPE_PATH_BAR_CONTAINER, GtkPathBarContainerClass))
+#define GTK_IS_PATH_BAR_CONTAINER(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), 
GTK_TYPE_PATH_BAR_CONTAINER))
+#define GTK_IS_PATH_BAR_CONTAINER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), 
GTK_TYPE_PATH_BAR_CONTAINER)
+#define GTK_PATH_BAR_CONTAINER_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), 
GTK_TYPE_PATH_BAR_CONTAINER, GtkPathBarContainerClass))
+
+typedef struct _GtkPathBarContainer GtkPathBarContainer;
+typedef struct _GtkPathBarContainerClass GtkPathBarContainerClass;
+typedef struct _GtkPathBarContainerPrivate GtkPathBarContainerPrivate;
+
+struct _GtkPathBarContainerClass
+{
+  GtkWidgetClass parent;
+
+  /* Padding for future expansion */
+  gpointer reserved[10];
+};
+
+struct _GtkPathBarContainer
+{
+  GtkWidget parent_instance;
+};
+
+GType             gtk_path_bar_container_get_type                (void) G_GNUC_CONST;
+
+GtkWidget        *gtk_path_bar_container_new                     (void);
+
+GtkWidget        *gtk_path_bar_container_get_path_box            (GtkPathBarContainer       
*path_bar_container);
+
+GtkWidget        *gtk_path_bar_container_get_overflow_button     (GtkPathBarContainer       
*path_bar_container);
+
+G_END_DECLS
+
+#endif /* GTK_PATH_BAR_CONTAINER_PRIVATE_H_ */
diff --git a/gtk/ui/gtkpathbar.ui b/gtk/ui/gtkpathbar.ui
index aba2b23..dcf9dfe 100644
--- a/gtk/ui/gtkpathbar.ui
+++ b/gtk/ui/gtkpathbar.ui
@@ -17,10 +17,9 @@
     <property name="valign">GTK_ALIGN_START</property>
     <property name="vexpand">false</property>
     <child>
-      <object class="GtkBox" id="path_bar_1">
+      <object class="GtkPathBarContainer" id="path_bar_1">
         <property name="visible">true</property>
-        <property name="orientation">horizontal</property>
-        <child>
+        <child internal-child="overflow_button">
           <object class="GtkMenuButton" id="overflow_button_1">
             <property name="visible">true</property>
             <property name="no-show-all">true</property>
@@ -38,7 +37,7 @@
             </style>
           </object>
         </child>
-        <child>
+        <child internal-child="path_box">
           <object class="GtkHidingBox" id="path_box_1">
             <property name="visible">true</property>
           </object>
@@ -46,10 +45,9 @@
       </object>
     </child>
     <child>
-      <object class="GtkBox" id="path_bar_2">
+      <object class="GtkPathBarContainer" id="path_bar_2">
         <property name="visible">true</property>
-        <property name="orientation">horizontal</property>
-        <child>
+        <child internal-child="overflow_button">
           <object class="GtkMenuButton" id="overflow_button_2">
             <property name="visible">true</property>
             <property name="no-show-all">true</property>
@@ -67,7 +65,7 @@
             </style>
           </object>
         </child>
-        <child>
+        <child internal-child="path_box">
           <object class="GtkHidingBox" id="path_box_2">
             <property name="visible">true</property>
           </object>


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