[gnome-builder/wip/chergert/headerbar] wip



commit f442f22ce03df2a66e22e00310fc103cefa4b9e2
Author: Christian Hergert <chergert redhat com>
Date:   Fri Jun 17 21:13:08 2016 -0700

    wip

 data/theme/Adwaita-shared.css                      |   15 ++
 libide/Makefile.am                                 |    1 +
 libide/workbench/ide-perspective.c                 |   10 +-
 .../workbench/ide-workbench-header-bar-private.h   |   37 +++++
 libide/workbench/ide-workbench-header-bar.c        |  127 +++++++++++++++
 libide/workbench/ide-workbench-header-bar.ui       |   46 ++++++-
 libide/workbench/ide-workbench-private.h           |   18 +-
 libide/workbench/ide-workbench.c                   |  168 ++++++++------------
 libide/workbench/ide-workbench.ui                  |   45 +-----
 plugins/build-tools/gbp-build-perspective.c        |    2 +-
 10 files changed, 317 insertions(+), 152 deletions(-)
---
diff --git a/data/theme/Adwaita-shared.css b/data/theme/Adwaita-shared.css
index d9ca478..9742de7 100644
--- a/data/theme/Adwaita-shared.css
+++ b/data/theme/Adwaita-shared.css
@@ -130,3 +130,18 @@ entry.search-missing > image {
 /* tweak icons for treeviews */
 treeview.image { color: alpha(currentColor, 0.8); }
 treeview.image:selected { color: alpha(@theme_selected_fg_color, 0.9); }
+
+
+popover.perspectives-selector list {
+  padding: 12px;
+}
+
+popover.perspectives-selector list row {
+  padding: 8px;
+}
+
+popover.perspectives-selector list row image {
+  min-height: 16px;
+  min-width: 16px;
+  margin-right: 12px;
+}
diff --git a/libide/Makefile.am b/libide/Makefile.am
index f810e23..7ca7b65 100644
--- a/libide/Makefile.am
+++ b/libide/Makefile.am
@@ -296,6 +296,7 @@ libide_1_0_la_public_sources =                            \
        workbench/ide-layout.c                            \
        workbench/ide-perspective.c                       \
        workbench/ide-workbench-addin.c                   \
+       workbench/ide-workbench-header-bar-private.h      \
        workbench/ide-workbench-header-bar.c              \
        workbench/ide-workbench-open.c                    \
        workbench/ide-workbench.c                         \
diff --git a/libide/workbench/ide-perspective.c b/libide/workbench/ide-perspective.c
index abfafcb..f28287f 100644
--- a/libide/workbench/ide-perspective.c
+++ b/libide/workbench/ide-perspective.c
@@ -143,6 +143,8 @@ ide_perspective_get_icon_name (IdePerspective *self)
  * internal name, such as "editor" which should not be translated. Internally, the
  * default implementation of this method will return the name of the instances #GType.
  *
+ * The identifier must be alpha-numeric only (a-z A-Z 0-9).
+ *
  * This value should be unique per workspace.
  *
  * Returns: (nullable): A string identifier for the perspective.
@@ -150,9 +152,15 @@ ide_perspective_get_icon_name (IdePerspective *self)
 gchar *
 ide_perspective_get_id (IdePerspective *self)
 {
+  gchar *ret;
+
   g_return_val_if_fail (IDE_IS_PERSPECTIVE (self), NULL);
 
-  return IDE_PERSPECTIVE_GET_IFACE (self)->get_id (self);
+  ret = IDE_PERSPECTIVE_GET_IFACE (self)->get_id (self);
+
+  g_return_val_if_fail (g_str_is_ascii (ret), NULL);
+
+  return ret;
 }
 
 /**
diff --git a/libide/workbench/ide-workbench-header-bar-private.h 
b/libide/workbench/ide-workbench-header-bar-private.h
new file mode 100644
index 0000000..fac5d60
--- /dev/null
+++ b/libide/workbench/ide-workbench-header-bar-private.h
@@ -0,0 +1,37 @@
+/* ide-workbench-header-bar-private.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 IDE_WORKBENCH_HEADER_BAR_PRIVATE_H
+#define IDE_WORKBENCH_HEADER_BAR_PRIVATE_H
+
+#include "workbench/ide-workbench-header-bar.h"
+#include "workbench/ide-perspective.h"
+
+G_BEGIN_DECLS
+
+void _ide_workbench_header_bar_set_perspectives (IdeWorkbenchHeaderBar *self,
+                                                 GListModel            *model)
+  G_GNUC_INTERNAL;
+
+void _ide_workbench_header_bar_set_perspective (IdeWorkbenchHeaderBar *self,
+                                                IdePerspective        *perspective)
+  G_GNUC_INTERNAL;
+
+G_END_DECLS
+
+#endif /* IDE_WORKBENCH_HEADER_BAR_PRIVATE_H */
diff --git a/libide/workbench/ide-workbench-header-bar.c b/libide/workbench/ide-workbench-header-bar.c
index fc6e0ec..fb445e1 100644
--- a/libide/workbench/ide-workbench-header-bar.c
+++ b/libide/workbench/ide-workbench-header-bar.c
@@ -19,15 +19,49 @@
 #define G_LOG_DOMAIN "ide-workbench-header-bar"
 
 #include "application/ide-application.h"
+#include "util/ide-gtk.h"
+#include "workbench/ide-perspective.h"
+#include "workbench/ide-workbench.h"
 #include "workbench/ide-workbench-header-bar.h"
+#include "workbench/ide-workbench-header-bar-private.h"
 
 typedef struct
 {
   GtkMenuButton *menu_button;
+  GtkListBox    *perspectives_list_box;
+  GtkMenuButton *perspectives_menu_button;
+  GtkImage      *perspectives_menu_button_image;
+  GtkPopover    *perspectives_popover;
 } IdeWorkbenchHeaderBarPrivate;
 
 G_DEFINE_TYPE_WITH_PRIVATE (IdeWorkbenchHeaderBar, ide_workbench_header_bar, GTK_TYPE_HEADER_BAR)
 
+static void
+perspective_row_selected (IdeWorkbenchHeaderBar *self,
+                          GtkListBoxRow         *row,
+                          GtkListBox            *list_box)
+{
+  IdeWorkbenchHeaderBarPrivate *priv = ide_workbench_header_bar_get_instance_private (self);
+  IdeWorkbench *workbench;
+  const gchar *id;
+
+  g_assert (IDE_IS_WORKBENCH_HEADER_BAR (self));
+  g_assert (GTK_IS_LIST_BOX_ROW (row));
+  g_assert (GTK_IS_LIST_BOX (list_box));
+
+  id = g_object_get_data (G_OBJECT (row), "IDE_PERSPECTIVE_ID");
+  if (id == NULL)
+    return;
+
+  workbench = ide_widget_get_workbench (GTK_WIDGET (self));
+  if (workbench == NULL)
+    return;
+
+  gtk_widget_hide (GTK_WIDGET (priv->perspectives_popover));
+
+  ide_workbench_set_visible_perspective_name (workbench, id);
+}
+
 GtkWidget *
 ide_workbench_header_bar_new (void)
 {
@@ -41,6 +75,10 @@ ide_workbench_header_bar_class_init (IdeWorkbenchHeaderBarClass *klass)
 
   gtk_widget_class_set_template_from_resource (widget_class, 
"/org/gnome/builder/ui/ide-workbench-header-bar.ui");
   gtk_widget_class_bind_template_child_private (widget_class, IdeWorkbenchHeaderBar, menu_button);
+  gtk_widget_class_bind_template_child_private (widget_class, IdeWorkbenchHeaderBar, perspectives_list_box);
+  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);
 }
 
 static void
@@ -55,6 +93,12 @@ ide_workbench_header_bar_init (IdeWorkbenchHeaderBar *self)
   model = ide_application_get_menu_by_id (IDE_APPLICATION_DEFAULT, "gear-menu");
   popover = gtk_popover_new_from_model (NULL, G_MENU_MODEL (model));
   gtk_menu_button_set_popover (priv->menu_button, popover);
+
+  g_signal_connect_object (priv->perspectives_list_box,
+                           "row-activated",
+                           G_CALLBACK (perspective_row_selected),
+                           self,
+                           G_CONNECT_SWAPPED);
 }
 
 void
@@ -68,3 +112,86 @@ ide_workbench_header_bar_focus_search (IdeWorkbenchHeaderBar *self)
   if (GTK_IS_ENTRY (entry))
     gtk_widget_grab_focus (GTK_WIDGET (entry));
 }
+
+static GtkWidget *
+create_perspective_row (gpointer item,
+                        gpointer user_data)
+{
+  IdePerspective *perspective = item;
+  g_autofree gchar *title = NULL;
+  g_autofree gchar *icon_name = NULL;
+  GtkListBoxRow *row;
+  GtkLabel *label;
+  GtkImage *image;
+  GtkBox *box;
+
+  g_assert (IDE_IS_PERSPECTIVE (perspective));
+
+  title = ide_perspective_get_title (perspective);
+  icon_name = ide_perspective_get_icon_name (perspective);
+
+  row = g_object_new (GTK_TYPE_LIST_BOX_ROW,
+                      "can-focus", FALSE,
+                      "selectable", FALSE,
+                      "visible", TRUE,
+                      NULL);
+
+  g_object_set_data_full (G_OBJECT (row),
+                          "IDE_PERSPECTIVE_ID",
+                          ide_perspective_get_id (perspective),
+                          g_free);
+
+  box = g_object_new (GTK_TYPE_BOX,
+                      "visible", TRUE,
+                      NULL);
+  gtk_container_add (GTK_CONTAINER (row), GTK_WIDGET (box));
+
+  image = g_object_new (GTK_TYPE_IMAGE,
+                        "hexpand", FALSE,
+                        "icon-name", icon_name,
+                        "visible", TRUE,
+                        NULL);
+  gtk_container_add (GTK_CONTAINER (box), GTK_WIDGET (image));
+
+  label = g_object_new (GTK_TYPE_LABEL,
+                        "label", title,
+                        "hexpand", TRUE,
+                        "xalign", 0.0f,
+                        "visible", TRUE,
+                        NULL);
+  gtk_container_add (GTK_CONTAINER (box), GTK_WIDGET (label));
+
+  return GTK_WIDGET (row);
+}
+
+void
+_ide_workbench_header_bar_set_perspectives (IdeWorkbenchHeaderBar *self,
+                                            GListModel            *model)
+{
+  IdeWorkbenchHeaderBarPrivate *priv = ide_workbench_header_bar_get_instance_private (self);
+
+  g_assert (IDE_IS_WORKBENCH_HEADER_BAR (self));
+  g_assert (!model || G_IS_LIST_MODEL (model));
+
+  gtk_list_box_bind_model (priv->perspectives_list_box,
+                           model,
+                           create_perspective_row,
+                           NULL, NULL);
+}
+
+void
+_ide_workbench_header_bar_set_perspective (IdeWorkbenchHeaderBar *self,
+                                           IdePerspective        *perspective)
+{
+  IdeWorkbenchHeaderBarPrivate *priv = ide_workbench_header_bar_get_instance_private (self);
+  g_autofree gchar *icon_name = NULL;
+
+  g_assert (IDE_IS_WORKBENCH_HEADER_BAR (self));
+  g_assert (IDE_IS_PERSPECTIVE (perspective));
+
+  icon_name = ide_perspective_get_icon_name (perspective);
+
+  g_object_set (priv->perspectives_menu_button_image,
+                "icon-name", icon_name,
+                NULL);
+}
diff --git a/libide/workbench/ide-workbench-header-bar.ui b/libide/workbench/ide-workbench-header-bar.ui
index d9edd6a..bf5c0b5 100644
--- a/libide/workbench/ide-workbench-header-bar.ui
+++ b/libide/workbench/ide-workbench-header-bar.ui
@@ -1,8 +1,52 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <interface>
-  <!-- interface-requires gtk+ 3.18 -->
+  <object class="GtkPopover" id="perspectives_popover">
+    <property name="width-request">250</property>
+    <style>
+      <class name="perspectives-selector"/>
+    </style>
+    <child>
+      <object class="GtkListBox" id="perspectives_list_box">
+        <property name="visible">true</property>
+      </object>
+    </child>
+  </object>
+  <!-- interface-requires gtk+ 3.21 -->
   <template class="IdeWorkbenchHeaderBar" parent="GtkHeaderBar">
     <property name="show-close-button">true</property>
+    <child>
+      <object class="GtkMenuButton" id="perspectives_menu_button">
+        <property name="popover">perspectives_popover</property>
+        <property name="visible">true</property>
+        <style>
+          <class name="image-button"/>
+        </style>
+        <child>
+          <object class="GtkBox">
+            <property name="margin-end">8</property>
+            <property name="margin-start">8</property>
+            <property name="spacing">12</property>
+            <property name="visible">true</property>
+            <child>
+              <object class="GtkImage" id="perspectives_menu_button_image">
+                <property name="icon-name">builder-editor-symbolic</property>
+                <property name="visible">true</property>
+              </object>
+            </child>
+            <child>
+              <object class="GtkImage">
+                <property name="icon-name">pan-down-symbolic</property>
+                <property name="visible">true</property>
+              </object>
+            </child>
+          </object>
+        </child>
+      </object>
+      <packing>
+        <property name="pack-type">start</property>
+        <property name="position">0</property>
+      </packing>
+    </child>
     <child type="title">
       <object class="IdeOmniSearchEntry" id="search_entry">
         <property name="tooltip-text" translatable="yes">Search for files. Shortcut: Ctrl + .</property>
diff --git a/libide/workbench/ide-workbench-private.h b/libide/workbench/ide-workbench-private.h
index 382be20..b106405 100644
--- a/libide/workbench/ide-workbench-private.h
+++ b/libide/workbench/ide-workbench-private.h
@@ -21,8 +21,9 @@
 
 #include <libpeas/peas.h>
 
-#include "ide-perspective.h"
-#include "ide-workbench.h"
+#include "workbench/ide-perspective.h"
+#include "workbench/ide-workbench.h"
+#include "workbench/ide-workbench-header-bar.h"
 
 G_BEGIN_DECLS
 
@@ -35,15 +36,14 @@ struct _IdeWorkbench
   IdeContext                *context;
   GCancellable              *cancellable;
   PeasExtensionSet          *addins;
+  /*
+   * This does not contain all perspectives, just those
+   * that should be visible via the perspective selector.
+   */
+  GListStore                *perspectives;
 
-  IdePerspective            *perspective;
-
-  GtkStack                  *top_stack;
-  GtkStack                  *titlebar_stack;
+  IdeWorkbenchHeaderBar     *header_bar;
   GtkStack                  *perspectives_stack;
-  GtkStackSwitcher          *perspectives_stack_switcher;
-  GtkPopover                *perspectives_popover;
-
   GtkSizeGroup              *header_size_group;
 
   GObject                   *selection_owner;
diff --git a/libide/workbench/ide-workbench.c b/libide/workbench/ide-workbench.c
index 6e9973e..1e1d8ea 100644
--- a/libide/workbench/ide-workbench.c
+++ b/libide/workbench/ide-workbench.c
@@ -34,6 +34,7 @@
 #include "workbench/ide-layout.h"
 #include "workbench/ide-workbench-addin.h"
 #include "workbench/ide-workbench-header-bar.h"
+#include "workbench/ide-workbench-header-bar-private.h"
 #include "workbench/ide-workbench-private.h"
 #include "workbench/ide-workbench.h"
 
@@ -64,32 +65,25 @@ ide_workbench_notify_visible_child (IdeWorkbench *self,
                                     GParamSpec   *pspec,
                                     GtkStack     *stack)
 {
+  GActionGroup *actions = NULL;
   IdePerspective *perspective;
 
   g_assert (IDE_IS_WORKBENCH (self));
   g_assert (GTK_IS_STACK (stack));
 
   perspective = IDE_PERSPECTIVE (gtk_stack_get_visible_child (stack));
-
   if (perspective != NULL)
-    {
-      GActionGroup *actions;
-      gchar *id;
+    actions = ide_perspective_get_actions (perspective);
 
-      id = ide_perspective_get_id (perspective);
-      gtk_stack_set_visible_child_name (self->titlebar_stack, id);
-
-      actions = ide_perspective_get_actions (perspective);
-      gtk_widget_insert_action_group (GTK_WIDGET (self), "perspective", actions);
+  gtk_widget_insert_action_group (GTK_WIDGET (self), "perspective", actions);
 
-      g_clear_object (&actions);
-      g_free (id);
-    }
+  g_clear_object (&actions);
 }
 
 static gint
 ide_workbench_compare_perspective (gconstpointer a,
-                                   gconstpointer b)
+                                   gconstpointer b,
+                                   gpointer      data_unused)
 {
   IdePerspective *perspective_a = (IdePerspective *)a;
   IdePerspective *perspective_b = (IdePerspective *)b;
@@ -99,30 +93,6 @@ ide_workbench_compare_perspective (gconstpointer a,
 }
 
 static void
-ide_workbench_resort_perspectives (IdeWorkbench *self)
-{
-  GList *children;
-  const GList *iter;
-  gint i = 0;
-
-  g_assert (IDE_IS_WORKBENCH (self));
-
-  children = gtk_container_get_children (GTK_CONTAINER (self->perspectives_stack));
-  children = g_list_sort (children, ide_workbench_compare_perspective);
-
-  for (iter = children; iter; iter = iter->next, i++)
-    {
-      GtkWidget *child = iter->data;
-
-      gtk_container_child_set (GTK_CONTAINER (self->perspectives_stack), child,
-                               "position", i,
-                               NULL);
-    }
-
-  g_list_free (children);
-}
-
-static void
 ide_workbench_unload_cb (GObject      *object,
                          GAsyncResult *result,
                          gpointer      user_data)
@@ -236,9 +206,9 @@ ide_workbench_finalize (GObject *object)
 {
   IdeWorkbench *self = (IdeWorkbench *)object;
 
-  ide_clear_weak_pointer (&self->perspective);
   g_clear_object (&self->context);
   g_clear_object (&self->cancellable);
+  g_clear_object (&self->perspectives);
 
   G_OBJECT_CLASS (ide_workbench_parent_class)->finalize (object);
 }
@@ -396,11 +366,9 @@ ide_workbench_class_init (IdeWorkbenchClass *klass)
 
   gtk_widget_class_set_css_name (widget_class, "workbench");
   gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/builder/ui/ide-workbench.ui");
+  gtk_widget_class_bind_template_child (widget_class, IdeWorkbench, header_bar);
   gtk_widget_class_bind_template_child (widget_class, IdeWorkbench, header_size_group);
   gtk_widget_class_bind_template_child (widget_class, IdeWorkbench, perspectives_stack);
-  gtk_widget_class_bind_template_child (widget_class, IdeWorkbench, perspectives_stack_switcher);
-  gtk_widget_class_bind_template_child (widget_class, IdeWorkbench, titlebar_stack);
-  gtk_widget_class_bind_template_child (widget_class, IdeWorkbench, top_stack);
 }
 
 static void
@@ -408,6 +376,10 @@ ide_workbench_init (IdeWorkbench *self)
 {
   gtk_widget_init_template (GTK_WIDGET (self));
 
+  self->perspectives = g_list_store_new (IDE_TYPE_PERSPECTIVE);
+  _ide_workbench_header_bar_set_perspectives (self->header_bar,
+                                              G_LIST_MODEL (self->perspectives));
+
   ide_workbench_add_perspective (self,
                                  g_object_new (IDE_TYPE_GREETER_PERSPECTIVE,
                                                "visible", TRUE,
@@ -618,7 +590,7 @@ ide_workbench_set_context (IdeWorkbench *self,
    */
   if (g_settings_get_boolean (settings, "restore-previous-files"))
     {
-      duration = gtk_stack_get_transition_duration (self->top_stack);
+      duration = gtk_stack_get_transition_duration (self->perspectives_stack);
       g_timeout_add (STABLIZE_DELAY_MSEC + duration, restore_in_timeout, g_object_ref (context));
     }
 }
@@ -630,8 +602,6 @@ ide_workbench_add_perspective (IdeWorkbench   *self,
   g_autofree gchar *icon_name = NULL;
   g_autofree gchar *id = NULL;
   g_autofree gchar *title = NULL;
-  GtkStack *stack;
-  GtkWidget *titlebar;
 
   g_assert (IDE_IS_WORKBENCH (self));
   g_assert (IDE_IS_PERSPECTIVE (perspective));
@@ -640,14 +610,7 @@ ide_workbench_add_perspective (IdeWorkbench   *self,
   title = ide_perspective_get_title (perspective);
   icon_name = ide_perspective_get_icon_name (perspective);
 
-  if (ide_perspective_is_early (perspective))
-    stack = self->top_stack;
-  else
-    stack = self->perspectives_stack;
-
-  gtk_widget_set_hexpand (GTK_WIDGET (perspective), TRUE);
-
-  gtk_container_add_with_properties (GTK_CONTAINER (stack),
+  gtk_container_add_with_properties (GTK_CONTAINER (self->perspectives_stack),
                                      GTK_WIDGET (perspective),
                                      "icon-name", icon_name,
                                      "name", id,
@@ -655,36 +618,52 @@ ide_workbench_add_perspective (IdeWorkbench   *self,
                                      "title", title,
                                      NULL);
 
-  titlebar = ide_perspective_get_titlebar (perspective);
-  if (titlebar == NULL)
-    titlebar = g_object_new (IDE_TYPE_WORKBENCH_HEADER_BAR,
-                             "visible", TRUE,
-                             NULL);
+  if (!IDE_IS_GREETER_PERSPECTIVE (perspective) &&
+      !IDE_IS_GENESIS_PERSPECTIVE (perspective))
+    {
+      guint position = 0;
 
-  gtk_container_add_with_properties (GTK_CONTAINER (self->titlebar_stack), titlebar,
-                                     "name", id,
-                                     NULL);
+      gtk_container_child_get (GTK_CONTAINER (self->perspectives_stack),
+                               GTK_WIDGET (perspective),
+                               "position", &position,
+                               NULL);
 
-  ide_workbench_resort_perspectives (self);
+      g_list_store_append (self->perspectives, perspective);
+      g_list_store_sort (self->perspectives,
+                         ide_workbench_compare_perspective,
+                         NULL);
+    }
 }
 
 void
 ide_workbench_remove_perspective (IdeWorkbench   *self,
                                   IdePerspective *perspective)
 {
-  const gchar *id;
-  GtkWidget *titlebar;
+  guint n_items;
+  guint i;
 
   g_assert (IDE_IS_WORKBENCH (self));
   g_assert (IDE_IS_PERSPECTIVE (perspective));
   g_assert (gtk_widget_get_parent (GTK_WIDGET (perspective)) ==
             GTK_WIDGET (self->perspectives_stack));
 
-  id = ide_perspective_get_id (perspective);
-  titlebar = gtk_stack_get_child_by_name (self->titlebar_stack, id);
+  n_items = g_list_model_get_n_items (G_LIST_MODEL (self->perspectives));
+
+  for (i = 0; i < n_items; i++)
+    {
+      g_autoptr(IdePerspective) item = NULL;
+
+      item = g_list_model_get_item (G_LIST_MODEL (self->perspectives), i);
 
-  gtk_container_remove (GTK_CONTAINER (self->titlebar_stack), titlebar);
-  gtk_container_remove (GTK_CONTAINER (self->perspectives_stack), GTK_WIDGET (perspective));
+      if (item == perspective)
+        {
+          g_list_store_remove (self->perspectives, i);
+          break;
+        }
+    }
+
+  gtk_container_remove (GTK_CONTAINER (self->perspectives_stack),
+                        GTK_WIDGET (perspective));
 }
 
 /**
@@ -705,8 +684,6 @@ ide_workbench_get_perspective_by_name (IdeWorkbench *self,
   g_return_val_if_fail (name != NULL, NULL);
 
   ret = gtk_stack_get_child_by_name (self->perspectives_stack, name);
-  if (ret == NULL)
-    ret = gtk_stack_get_child_by_name (self->top_stack, name);
 
   return IDE_PERSPECTIVE (ret);
 }
@@ -722,18 +699,16 @@ ide_workbench_get_perspective_by_name (IdeWorkbench *self,
 IdePerspective *
 ide_workbench_get_visible_perspective (IdeWorkbench *self)
 {
-  GtkWidget *visible_child;
+  GtkWidget *ret;
 
   g_return_val_if_fail (IDE_IS_WORKBENCH (self), NULL);
 
-  visible_child = gtk_stack_get_visible_child (self->top_stack);
-
-  if (IDE_IS_PERSPECTIVE (visible_child))
-    return IDE_PERSPECTIVE (visible_child);
+  ret = gtk_stack_get_visible_child (self->perspectives_stack);
 
-  return IDE_PERSPECTIVE (gtk_stack_get_visible_child (self->perspectives_stack));
+  return IDE_PERSPECTIVE (ret);
 }
 
+#if 0
 static gboolean
 remove_early_perspectives (gpointer data)
 {
@@ -750,6 +725,7 @@ remove_early_perspectives (gpointer data)
 
   return G_SOURCE_REMOVE;
 }
+#endif
 
 static void
 ide_workbench_notify_perspective_set (PeasExtensionSet *set,
@@ -758,55 +734,46 @@ ide_workbench_notify_perspective_set (PeasExtensionSet *set,
                                       gpointer          user_data)
 {
   IdeWorkbenchAddin *addin = (IdeWorkbenchAddin *)exten;
-  IdeWorkbench *self = user_data;
+  IdePerspective *perspective = user_data;
 
-  g_assert (IDE_IS_WORKBENCH (self));
   g_assert (PEAS_IS_EXTENSION_SET (set));
   g_assert (plugin_info != NULL);
   g_assert (IDE_IS_WORKBENCH_ADDIN (addin));
+  g_assert (IDE_IS_PERSPECTIVE (perspective));
 
-  ide_workbench_addin_perspective_set (addin, self->perspective);
+  ide_workbench_addin_perspective_set (addin, perspective);
 }
 
 void
 ide_workbench_set_visible_perspective (IdeWorkbench   *self,
                                        IdePerspective *perspective)
 {
-  GActionGroup *actions;
-  GtkStack *stack;
-  gchar *id;
+  g_autofree gchar *id = NULL;
+  GActionGroup *actions = NULL;
+  const gchar *current_id;
 
   g_return_if_fail (IDE_IS_WORKBENCH (self));
   g_return_if_fail (IDE_IS_PERSPECTIVE (perspective));
 
-  stack = GTK_STACK (gtk_widget_get_ancestor (GTK_WIDGET (perspective), GTK_TYPE_STACK));
-
+  current_id = gtk_stack_get_visible_child_name (self->perspectives_stack);
   id = ide_perspective_get_id (perspective);
 
-  if (!ide_str_equal0 (gtk_stack_get_visible_child_name (stack), id))
-    {
-      gtk_stack_set_visible_child_name (stack, id);
-      gtk_stack_set_visible_child_name (self->titlebar_stack, id);
-    }
-
-  g_free (id);
+  if (!ide_str_equal0 (current_id, id))
+    gtk_stack_set_visible_child_name (self->perspectives_stack, id);
 
   actions = ide_perspective_get_actions (perspective);
   gtk_widget_insert_action_group (GTK_WIDGET (self), "perspective", actions);
 
-  if ((stack == self->perspectives_stack) &&
-      !ide_str_equal0 (gtk_stack_get_visible_child_name (self->top_stack), "perspectives"))
-    {
-      gtk_stack_set_visible_child_name (self->top_stack, "perspectives");
-      g_timeout_add (1000 + gtk_stack_get_transition_duration (self->top_stack),
-                     remove_early_perspectives,
-                     g_object_ref (self));
-    }
+  /* TODO: Possibly remove some perspectives */
 
-  if (self->addins != NULL && self->perspective != NULL)
+  _ide_workbench_header_bar_set_perspective (self->header_bar, perspective);
+
+  if (self->addins != NULL)
     peas_extension_set_foreach (self->addins,
                                 ide_workbench_notify_perspective_set,
-                                self);
+                                perspective);
+
+  g_clear_object (&actions);
 }
 
 const gchar *
@@ -844,6 +811,7 @@ ide_workbench_set_visible_perspective_name (IdeWorkbench *self,
   g_return_if_fail (name != NULL);
 
   perspective = ide_workbench_get_perspective_by_name (self, name);
+
   if (perspective != NULL)
     ide_workbench_set_visible_perspective (self, perspective);
 }
diff --git a/libide/workbench/ide-workbench.ui b/libide/workbench/ide-workbench.ui
index d4cc83a..e8bb964 100644
--- a/libide/workbench/ide-workbench.ui
+++ b/libide/workbench/ide-workbench.ui
@@ -1,57 +1,22 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <interface>
-  <!-- interface-requires gtk+ 3.17 -->
+  <!-- interface-requires gtk+ 3.21 -->
   <template class="IdeWorkbench" parent="GtkApplicationWindow">
     <child type="titlebar">
-      <object class="GtkStack" id="titlebar_stack">
+      <object class="IdeWorkbenchHeaderBar" id="header_bar">
         <property name="visible">true</property>
-        <property name="transition-type">crossfade</property>
-        <property name="transition-duration">333</property>
       </object>
     </child>
     <child>
       <object class="GtkOverlay">
         <property name="visible">true</property>
         <child>
-          <!--
-            top_stack is used so that we can have a perspective,
-            (the greeter perspective) as the initial perspective without
-            a stack switcher. Once we animate in the real perspectives, we
-            want the switcher. also, we want to animate in the switcher
-            as part of that transition, otherwise it looks clunky.
-          -->
-          <object class="GtkStack" id="top_stack">
+          <object class="GtkStack" id="perspectives_stack">
+            <property name="hexpand">true</property>
             <property name="homogeneous">false</property>
-            <property name="transition-duration">333</property>
             <property name="transition-type">crossfade</property>
-            <property name="vexpand">true</property>
+            <property name="transition-duration">333</property>
             <property name="visible">true</property>
-            <child>
-              <object class="GtkBox">
-                <property name="expand">true</property>
-                <property name="orientation">horizontal</property>
-                <property name="visible">true</property>
-                <child>
-                  <object class="IdePerspectiveSwitcher" id="perspectives_stack_switcher">
-                    <property name="icon-size">3</property>
-                    <property name="orientation">vertical</property>
-                    <property name="stack">perspectives_stack</property>
-                    <property name="visible">true</property>
-                  </object>
-                </child>
-                <child>
-                  <object class="GtkStack" id="perspectives_stack">
-                    <property name="homogeneous">false</property>
-                    <property name="transition-type">crossfade</property>
-                    <property name="transition-duration">333</property>
-                    <property name="visible">true</property>
-                  </object>
-                </child>
-              </object>
-              <packing>
-                <property name="name">perspectives</property>
-              </packing>
-            </child>
           </object>
         </child>
       </object>
diff --git a/plugins/build-tools/gbp-build-perspective.c b/plugins/build-tools/gbp-build-perspective.c
index d654d86..0c93e67 100644
--- a/plugins/build-tools/gbp-build-perspective.c
+++ b/plugins/build-tools/gbp-build-perspective.c
@@ -387,7 +387,7 @@ gbp_build_perspective_get_icon_name (IdePerspective *perspective)
 static gchar *
 gbp_build_perspective_get_title (IdePerspective *perspective)
 {
-  return g_strdup ("Build Configuration");
+  return g_strdup ("Build Preferences");
 }
 
 static gchar *


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