[gnome-builder] add priorty box to the header



commit 26e3c50825b1aad1d6831e7191813320c9f249f2
Author: Christian Hergert <chergert redhat com>
Date:   Mon Jun 20 00:06:44 2016 -0700

    add priorty box to the header

 contrib/egg/Makefile.am                      |    2 +
 contrib/egg/egg-priority-box.c               |  266 ++++++++++++++++++++++++++
 contrib/egg/egg-priority-box.h               |   42 ++++
 libide/workbench/ide-workbench-header-bar.c  |   52 +++++-
 libide/workbench/ide-workbench-header-bar.h  |    8 +
 libide/workbench/ide-workbench-header-bar.ui |   20 ++
 6 files changed, 385 insertions(+), 5 deletions(-)
---
diff --git a/contrib/egg/Makefile.am b/contrib/egg/Makefile.am
index 26159f8..42b02ca 100644
--- a/contrib/egg/Makefile.am
+++ b/contrib/egg/Makefile.am
@@ -20,6 +20,7 @@ headers_DATA = \
        egg-heap.h \
        egg-menu-manager.h \
        egg-pill-box.h \
+       egg-priority-box.h \
        egg-private.h \
        egg-search-bar.h \
        egg-settings-flag-action.h \
@@ -49,6 +50,7 @@ libegg_private_la_SOURCES = \
        egg-heap.c \
        egg-menu-manager.c \
        egg-pill-box.c \
+       egg-priority-box.c \
        egg-search-bar.c \
        egg-settings-flag-action.c \
        egg-settings-sandwich.c \
diff --git a/contrib/egg/egg-priority-box.c b/contrib/egg/egg-priority-box.c
new file mode 100644
index 0000000..570b7c2
--- /dev/null
+++ b/contrib/egg/egg-priority-box.c
@@ -0,0 +1,266 @@
+/* egg-priority-box.c
+ *
+ * Copyright (C) 2016 Christian Hergert <chergert redhat com>
+ *
+ * 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/>.
+ */
+
+/**
+ * SECTION:egg-priority-box:
+ * @title: EggPriorityBox
+ *
+ * This is like a #GtkBox but uses stable priorities to sort.
+ */
+
+#define G_LOG_DOMAIN "egg-priority-box"
+
+#include "egg-priority-box.h"
+
+typedef struct
+{
+  GtkWidget *widget;
+  gint       priority;
+} EggPriorityBoxChild;
+
+typedef struct
+{
+  GArray *children;
+} EggPriorityBoxPrivate;
+
+enum {
+  CHILD_PROP_0,
+  CHILD_PROP_PRIORITY,
+  N_CHILD_PROPS
+};
+
+G_DEFINE_TYPE_WITH_PRIVATE (EggPriorityBox, egg_priority_box, GTK_TYPE_BOX)
+
+static GParamSpec *child_properties [N_CHILD_PROPS];
+
+static gint
+sort_by_priority (gconstpointer a,
+                  gconstpointer b)
+{
+  const EggPriorityBoxChild *child_a = a;
+  const EggPriorityBoxChild *child_b = b;
+
+  return child_a->priority - child_b->priority;
+}
+
+static void
+egg_priority_box_resort (EggPriorityBox *self)
+{
+  EggPriorityBoxPrivate *priv = egg_priority_box_get_instance_private (self);
+  guint i;
+
+  g_assert (EGG_IS_PRIORITY_BOX (self));
+
+  g_array_sort (priv->children, sort_by_priority);
+
+  for (i = 0; i < priv->children->len; i++)
+    {
+      EggPriorityBoxChild *child = &g_array_index (priv->children, EggPriorityBoxChild, i);
+
+      gtk_container_child_set (GTK_CONTAINER (self), child->widget,
+                               "position", i,
+                               NULL);
+    }
+}
+
+static gint
+egg_priority_box_get_child_priority (EggPriorityBox *self,
+                                     GtkWidget      *widget)
+{
+  EggPriorityBoxPrivate *priv = egg_priority_box_get_instance_private (self);
+  guint i;
+
+  g_assert (EGG_IS_PRIORITY_BOX (self));
+  g_assert (GTK_IS_WIDGET (widget));
+
+  for (i = 0; i < priv->children->len; i++)
+    {
+      EggPriorityBoxChild *child = &g_array_index (priv->children, EggPriorityBoxChild, i);
+
+      if (child->widget == widget)
+        return child->priority;
+    }
+
+  g_warning ("No such child \"%s\" of \"%s\"",
+             G_OBJECT_TYPE_NAME (widget),
+             G_OBJECT_TYPE_NAME (self));
+
+  return 0;
+}
+
+static void
+egg_priority_box_set_child_priority (EggPriorityBox *self,
+                                     GtkWidget      *widget,
+                                     gint            priority)
+{
+  EggPriorityBoxPrivate *priv = egg_priority_box_get_instance_private (self);
+  guint i;
+
+  g_assert (EGG_IS_PRIORITY_BOX (self));
+  g_assert (GTK_IS_WIDGET (widget));
+
+  for (i = 0; i < priv->children->len; i++)
+    {
+      EggPriorityBoxChild *child = &g_array_index (priv->children, EggPriorityBoxChild, i);
+
+      if (child->widget == widget)
+        {
+          child->priority = priority;
+          egg_priority_box_resort (self);
+          return;
+        }
+    }
+
+  g_warning ("No such child \"%s\" of \"%s\"",
+             G_OBJECT_TYPE_NAME (widget),
+             G_OBJECT_TYPE_NAME (self));
+}
+
+static void
+egg_priority_box_add (GtkContainer *container,
+                      GtkWidget    *widget)
+{
+  EggPriorityBox *self = (EggPriorityBox *)container;
+  EggPriorityBoxPrivate *priv = egg_priority_box_get_instance_private (self);
+  EggPriorityBoxChild child;
+
+  g_assert (EGG_IS_PRIORITY_BOX (self));
+  g_assert (GTK_IS_WIDGET (widget));
+
+  child.widget = widget;
+  child.priority = 0;
+
+  g_array_append_val (priv->children, child);
+
+  GTK_CONTAINER_CLASS (egg_priority_box_parent_class)->add (container, widget);
+
+  egg_priority_box_resort (self);
+}
+
+static void
+egg_priority_box_remove (GtkContainer *container,
+                         GtkWidget    *widget)
+{
+  EggPriorityBox *self = (EggPriorityBox *)container;
+  EggPriorityBoxPrivate *priv = egg_priority_box_get_instance_private (self);
+  guint i;
+
+  g_assert (EGG_IS_PRIORITY_BOX (self));
+  g_assert (GTK_IS_WIDGET (widget));
+
+  for (i = 0; i < priv->children->len; i++)
+    {
+      EggPriorityBoxChild *child;
+
+      child = &g_array_index (priv->children, EggPriorityBoxChild, i);
+
+      if (child->widget == widget)
+        {
+          g_array_remove_index_fast (priv->children, i);
+          break;
+        }
+    }
+
+  GTK_CONTAINER_CLASS (egg_priority_box_parent_class)->remove (container, widget);
+
+  egg_priority_box_resort (self);
+}
+
+static void
+egg_priority_box_finalize (GObject *object)
+{
+  EggPriorityBox *self = (EggPriorityBox *)object;
+  EggPriorityBoxPrivate *priv = egg_priority_box_get_instance_private (self);
+
+  g_clear_pointer (&priv->children, g_array_unref);
+
+  G_OBJECT_CLASS (egg_priority_box_parent_class)->finalize (object);
+}
+
+static void
+egg_priority_box_get_child_property (GtkContainer *container,
+                                     GtkWidget    *child,
+                                     guint         prop_id,
+                                     GValue       *value,
+                                     GParamSpec   *pspec)
+{
+  EggPriorityBox *self = EGG_PRIORITY_BOX (container);
+
+  switch (prop_id)
+    {
+    case CHILD_PROP_PRIORITY:
+      g_value_set_int (value, egg_priority_box_get_child_priority (self, child));
+      break;
+
+    default:
+      GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, prop_id, pspec);
+    }
+}
+
+static void
+egg_priority_box_set_child_property (GtkContainer *container,
+                                     GtkWidget    *child,
+                                     guint         prop_id,
+                                     const GValue *value,
+                                     GParamSpec   *pspec)
+{
+  EggPriorityBox *self = EGG_PRIORITY_BOX (container);
+
+  switch (prop_id)
+    {
+    case CHILD_PROP_PRIORITY:
+      egg_priority_box_set_child_priority (self, child, g_value_get_int (value));
+      break;
+
+    default:
+      GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, prop_id, pspec);
+    }
+}
+
+static void
+egg_priority_box_class_init (EggPriorityBoxClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  GtkContainerClass *container_class = GTK_CONTAINER_CLASS (klass);
+
+  object_class->finalize = egg_priority_box_finalize;
+
+  container_class->add = egg_priority_box_add;
+  container_class->remove = egg_priority_box_remove;
+  container_class->get_child_property = egg_priority_box_get_child_property;
+  container_class->set_child_property = egg_priority_box_set_child_property;
+
+  child_properties [CHILD_PROP_PRIORITY] =
+    g_param_spec_int ("priority",
+                      "Priority",
+                      "Priority",
+                      G_MININT,
+                      G_MAXINT,
+                      0,
+                      (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+  gtk_container_class_install_child_properties (container_class, N_CHILD_PROPS, child_properties);
+}
+
+static void
+egg_priority_box_init (EggPriorityBox *self)
+{
+  EggPriorityBoxPrivate *priv = egg_priority_box_get_instance_private (self);
+
+  priv->children = g_array_new (FALSE, FALSE, sizeof (EggPriorityBoxChild));
+}
diff --git a/contrib/egg/egg-priority-box.h b/contrib/egg/egg-priority-box.h
new file mode 100644
index 0000000..36fa162
--- /dev/null
+++ b/contrib/egg/egg-priority-box.h
@@ -0,0 +1,42 @@
+/* egg-priority-box.h
+ *
+ * Copyright (C) 2016 Christian Hergert <chergert redhat com>
+ *
+ * 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/>.
+ */
+
+#ifndef EGG_PRIORITY_BOX_H
+#define EGG_PRIORITY_BOX_H
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+G_DECLARE_DERIVABLE_TYPE (EggPriorityBox, egg_priority_box, EGG, PRIORITY_BOX, GtkBox)
+
+struct _EggPriorityBoxClass
+{
+  GtkBoxClass parent_class;
+
+  gpointer _reserved1;
+  gpointer _reserved2;
+  gpointer _reserved3;
+  gpointer _reserved4;
+};
+
+GtkWidget *egg_priority_box_new (void);
+
+G_END_DECLS
+
+#endif /* EGG_PRIORITY_BOX_H */
diff --git a/libide/workbench/ide-workbench-header-bar.c b/libide/workbench/ide-workbench-header-bar.c
index fb445e1..f6f9607 100644
--- a/libide/workbench/ide-workbench-header-bar.c
+++ b/libide/workbench/ide-workbench-header-bar.c
@@ -18,6 +18,8 @@
 
 #define G_LOG_DOMAIN "ide-workbench-header-bar"
 
+#include <egg-priority-box.h>
+
 #include "application/ide-application.h"
 #include "util/ide-gtk.h"
 #include "workbench/ide-perspective.h"
@@ -27,11 +29,13 @@
 
 typedef struct
 {
-  GtkMenuButton *menu_button;
-  GtkListBox    *perspectives_list_box;
-  GtkMenuButton *perspectives_menu_button;
-  GtkImage      *perspectives_menu_button_image;
-  GtkPopover    *perspectives_popover;
+  GtkMenuButton  *menu_button;
+  GtkListBox     *perspectives_list_box;
+  GtkMenuButton  *perspectives_menu_button;
+  GtkImage       *perspectives_menu_button_image;
+  GtkPopover     *perspectives_popover;
+  EggPriorityBox *right_box;
+  EggPriorityBox *left_box;
 } IdeWorkbenchHeaderBarPrivate;
 
 G_DEFINE_TYPE_WITH_PRIVATE (IdeWorkbenchHeaderBar, ide_workbench_header_bar, GTK_TYPE_HEADER_BAR)
@@ -79,6 +83,8 @@ ide_workbench_header_bar_class_init (IdeWorkbenchHeaderBarClass *klass)
   gtk_widget_class_bind_template_child_private (widget_class, IdeWorkbenchHeaderBar, 
perspectives_menu_button);
   gtk_widget_class_bind_template_child_private (widget_class, IdeWorkbenchHeaderBar, 
perspectives_menu_button_image);
   gtk_widget_class_bind_template_child_private (widget_class, IdeWorkbenchHeaderBar, perspectives_popover);
+  gtk_widget_class_bind_template_child_private (widget_class, IdeWorkbenchHeaderBar, left_box);
+  gtk_widget_class_bind_template_child_private (widget_class, IdeWorkbenchHeaderBar, right_box);
 }
 
 static void
@@ -195,3 +201,39 @@ _ide_workbench_header_bar_set_perspective (IdeWorkbenchHeaderBar *self,
                 "icon-name", icon_name,
                 NULL);
 }
+
+void
+ide_workbench_header_bar_insert_left (IdeWorkbenchHeaderBar *self,
+                                      GtkWidget             *widget,
+                                      GtkPackType            pack_type,
+                                      gint                   priority)
+{
+  IdeWorkbenchHeaderBarPrivate *priv = ide_workbench_header_bar_get_instance_private (self);
+
+  g_return_if_fail (IDE_IS_WORKBENCH_HEADER_BAR (self));
+  g_return_if_fail (GTK_IS_WIDGET (widget));
+  g_return_if_fail (pack_type == GTK_PACK_START || pack_type == GTK_PACK_END);
+
+  gtk_container_add_with_properties (GTK_CONTAINER (priv->left_box), widget,
+                                     "pack-type", pack_type,
+                                     "priority", priority,
+                                     NULL);
+}
+
+void
+ide_workbench_header_bar_insert_right (IdeWorkbenchHeaderBar *self,
+                                       GtkWidget             *widget,
+                                       GtkPackType            pack_type,
+                                       gint                   priority)
+{
+  IdeWorkbenchHeaderBarPrivate *priv = ide_workbench_header_bar_get_instance_private (self);
+
+  g_return_if_fail (IDE_IS_WORKBENCH_HEADER_BAR (self));
+  g_return_if_fail (GTK_IS_WIDGET (widget));
+  g_return_if_fail (pack_type == GTK_PACK_START || pack_type == GTK_PACK_END);
+
+  gtk_container_add_with_properties (GTK_CONTAINER (priv->right_box), widget,
+                                     "pack-type", pack_type,
+                                     "priority", priority,
+                                     NULL);
+}
diff --git a/libide/workbench/ide-workbench-header-bar.h b/libide/workbench/ide-workbench-header-bar.h
index f58e87f..2ccd7b7 100644
--- a/libide/workbench/ide-workbench-header-bar.h
+++ b/libide/workbench/ide-workbench-header-bar.h
@@ -43,6 +43,14 @@ struct _IdeWorkbenchHeaderBarClass
 
 GtkWidget *ide_workbench_header_bar_new          (void);
 void       ide_workbench_header_bar_focus_search (IdeWorkbenchHeaderBar *self);
+void       ide_workbench_header_bar_insert_left  (IdeWorkbenchHeaderBar *self,
+                                                  GtkWidget             *widget,
+                                                  GtkPackType            pack_type,
+                                                  gint                   priority);
+void       ide_workbench_header_bar_insert_right (IdeWorkbenchHeaderBar *self,
+                                                  GtkWidget             *widget,
+                                                  GtkPackType            pack_type,
+                                                  gint                   priority);
 
 G_END_DECLS
 
diff --git a/libide/workbench/ide-workbench-header-bar.ui b/libide/workbench/ide-workbench-header-bar.ui
index bf5c0b5..b42be60 100644
--- a/libide/workbench/ide-workbench-header-bar.ui
+++ b/libide/workbench/ide-workbench-header-bar.ui
@@ -47,6 +47,16 @@
         <property name="position">0</property>
       </packing>
     </child>
+    <child>
+      <object class="EggPriorityBox" id="left_box">
+        <property name="hexpand">true</property>
+        <property name="visible">true</property>
+      </object>
+      <packing>
+        <property name="pack-type">start</property>
+        <property name="position">1</property>
+      </packing>
+    </child>
     <child type="title">
       <object class="IdeOmniSearchEntry" id="search_entry">
         <property name="tooltip-text" translatable="yes">Search for files. Shortcut: Ctrl + .</property>
@@ -76,5 +86,15 @@
         <property name="position">0</property>
       </packing>
     </child>
+    <child>
+      <object class="EggPriorityBox" id="right_box">
+        <property name="hexpand">true</property>
+        <property name="visible">true</property>
+      </object>
+      <packing>
+        <property name="pack-type">end</property>
+        <property name="position">1</property>
+      </packing>
+    </child>
   </template>
 </interface>


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