[gnome-builder/wip/chergert/headerbar: 11/34] add priorty box to the header
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-builder/wip/chergert/headerbar: 11/34] add priorty box to the header
- Date: Wed, 22 Jun 2016 03:30:21 +0000 (UTC)
commit f1961401f800eb9a423b8dd470abc6a95225570a
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]