[gnome-builder/editor-layout] more experiments



commit dfe279bc6bed998dff65669b82da70003f2e5e63
Author: Christian Hergert <christian hergert me>
Date:   Tue Nov 25 03:56:05 2014 -0800

    more experiments

 src/editor/gb-editor-workspace.c          |    1 +
 src/resources/css/builder.Adwaita.css     |   18 +-
 src/resources/gnome-builder.gresource.xml |    1 +
 src/resources/ui/gb-editor-tab.ui         |   32 ++
 src/resources/ui/gb-editor-workspace.ui   |   16 +-
 src/resources/ui/gb-tab-stack.ui          |   73 +++
 src/resources/ui/gb-tab.ui                |   67 ---
 src/tabs/gb-tab-grid.c                    |    2 +
 src/tabs/gb-tab-stack.c                   |  868 ++++++++++-------------------
 src/tabs/gb-tab.c                         |   69 +--
 10 files changed, 458 insertions(+), 689 deletions(-)
---
diff --git a/src/editor/gb-editor-workspace.c b/src/editor/gb-editor-workspace.c
index 78d6adc..c80755e 100644
--- a/src/editor/gb-editor-workspace.c
+++ b/src/editor/gb-editor-workspace.c
@@ -111,6 +111,7 @@ gb_editor_workspace_class_init (GbEditorWorkspaceClass *klass)
   gtk_widget_class_bind_template_child_private (widget_class, GbEditorWorkspace, multi_notebook);
   gtk_widget_class_bind_template_child_private (widget_class, GbEditorWorkspace, paned);
 
+  g_type_ensure (GB_TYPE_EDITOR_TAB);
   g_type_ensure (GB_TYPE_MULTI_NOTEBOOK);
   g_type_ensure (GB_TYPE_TAB_GRID);
   g_type_ensure (GB_TYPE_TREE);
diff --git a/src/resources/css/builder.Adwaita.css b/src/resources/css/builder.Adwaita.css
index 2fc5ad8..3823297 100644
--- a/src/resources/css/builder.Adwaita.css
+++ b/src/resources/css/builder.Adwaita.css
@@ -172,16 +172,30 @@ GbWorkbench GtkHeaderBar {
 /*
  * Tab header styling.
  */
-GtkComboBox.tab-header-first .button {
+GtkComboBox.tab-header-first .button,
+GtkButton.tab-header-first {
     border-left: none;
     border-top-left-radius: 0px;
     border-bottom-left-radius: 0px;
 }
-.tab-header-last {
+GtkComboBox.tab-header-last .button,
+GtkButton.tab-header-last {
     border-right: none;
     border-top-right-radius: 0px;
     border-bottom-right-radius: 0px;
 }
+GtkComboBox.tab-control-first .button,
+GtkButton.tab-control-first {
+    border-left: none;
+    border-top-left-radius: 0px;
+    border-bottom-left-radius: 0px;
+}
+GtkComboBox.tab-control-last .button,
+GtkButton.tab-control-last {
+    border-right: 1px solid @borders;
+    border-top-right-radius: 0px;
+    border-bottom-right-radius: 0px;
+}
 
 
 
diff --git a/src/resources/gnome-builder.gresource.xml b/src/resources/gnome-builder.gresource.xml
index 5ee89cd..96516db 100644
--- a/src/resources/gnome-builder.gresource.xml
+++ b/src/resources/gnome-builder.gresource.xml
@@ -31,6 +31,7 @@
     <file>ui/gb-preferences-page-language.ui</file>
     <file>ui/gb-tab.ui</file>
     <file>ui/gb-tab-label.ui</file>
+    <file>ui/gb-tab-stack.ui</file>
     <file>ui/gb-workbench.ui</file>
   </gresource>
 </gresources>
diff --git a/src/resources/ui/gb-editor-tab.ui b/src/resources/ui/gb-editor-tab.ui
index 010563a..b1113d1 100644
--- a/src/resources/ui/gb-editor-tab.ui
+++ b/src/resources/ui/gb-editor-tab.ui
@@ -5,6 +5,38 @@
     <property name="visible">True</property>
     <property name="can_focus">False</property>
     <property name="expand">True</property>
+    <child internal-child="controls">
+      <object class="GtkBox">
+        <property name="visible">True</property>
+        <style>
+          <class name="linked"/>
+        </style>
+        <child>
+          <object class="GtkComboBox" id="symbol_browser">
+            <property name="visible">true</property>
+            <property name="hexpand">true</property>
+            <style>
+              <class name="tab-control-first"/>
+            </style>
+          </object>
+        </child>
+        <child>
+          <object class="GtkButton" id="split_button">
+            <property name="visible">True</property>
+            <style>
+              <class name="tab-control-last"/>
+            </style>
+            <child>
+              <object class="GtkImage">
+                <property name="visible">True</property>
+                <property name="icon_size">1</property>
+                <property name="icon_name">builder-split-tab</property>
+              </object>
+            </child>
+          </object>
+        </child>
+      </object>
+    </child>
     <child internal-child="content">
       <object class="GtkBox" id="content">
         <child>
diff --git a/src/resources/ui/gb-editor-workspace.ui b/src/resources/ui/gb-editor-workspace.ui
index 9b7eb13..b3846cd 100644
--- a/src/resources/ui/gb-editor-workspace.ui
+++ b/src/resources/ui/gb-editor-workspace.ui
@@ -36,20 +36,34 @@
             </child>
           </object>
         </child>
+<child><object class="GtkBox"><property name="visible">True</property>
         <child>
           <object class="GbTabGrid" id="tab_grid">
             <property name="visible">True</property>
             <property name="hexpand">True</property>
+            <child>
+              <object class="GbEditorTab">
+                <property name="visible">True</property>
+                <property name="title">Foo.c</property>
+              </object>
+            </child>
+            <child>
+              <object class="GbEditorTab">
+                <property name="visible">True</property>
+                <property name="title">Foo2.c</property>
+              </object>
+            </child>
           </object>
         </child>
         <child>
           <object class="GbMultiNotebook" id="multi_notebook">
             <property name="group-name">GB_EDITOR_WORKSPACE</property>
             <property name="hexpand">True</property>
-            <property name="visible">True</property>
+            <property name="visible">false</property>
             <property name="show-tabs">False</property>
           </object>
         </child>
+</object></child>
       </object>
     </child>
   </template>
diff --git a/src/resources/ui/gb-tab-stack.ui b/src/resources/ui/gb-tab-stack.ui
new file mode 100644
index 0000000..b592bf4
--- /dev/null
+++ b/src/resources/ui/gb-tab-stack.ui
@@ -0,0 +1,73 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <!-- interface-requires gtk+ 3.8 -->
+  <template class="GbTabStack" parent="GtkBox">
+    <property name="orientation">vertical</property>
+    <child>
+      <object class="GtkBox">
+        <property name="visible">true</property>
+        <property name="orientation">horizontal</property>
+        <style>
+          <class name="linked"/>
+        </style>
+        <child>
+          <object class="GtkComboBox" id="combo">
+            <property name="visible">true</property>
+            <property name="hexpand">true</property>
+            <property name="model">store</property>
+            <style>
+              <class name="tab-header-first"/>
+            </style>
+          </object>
+        </child>
+        <child>
+          <object class="GtkStack" id="controls">
+            <property name="visible">true</property>
+          </object>
+        </child>
+        <child>
+          <object class="GtkButton" id="move_right">
+            <property name="visible">true</property>
+            <style>
+              <class name="image-button"/>
+            </style>
+            <child>
+              <object class="GtkImage">
+                <property name="visible">true</property>
+                <property name="icon_name">builder-drag-tab</property>
+              </object>
+            </child>
+          </object>
+        </child>
+        <child>
+          <object class="GtkButton" id="close">
+            <property name="visible">true</property>
+            <property name="sensitive">false</property>
+            <style>
+              <class name="image-button"/>
+              <class name="tab-header-last"/>
+            </style>
+            <child>
+              <object class="GtkImage">
+                <property name="visible">true</property>
+                <property name="icon_name">window-close-symbolic</property>
+              </object>
+            </child>
+          </object>
+        </child>
+      </object>
+    </child>
+    <child>
+      <object class="GtkStack" id="stack">
+        <property name="visible">true</property>
+        <property name="expand">true</property>
+      </object>
+    </child>
+  </template>
+  <object class="GtkListStore" id="store">
+    <columns>
+      <!-- column-name tab -->
+      <column type="GbTab"/>
+    </columns>
+  </object>
+</interface>
diff --git a/src/resources/ui/gb-tab.ui b/src/resources/ui/gb-tab.ui
index 2c43c83..80f8d62 100644
--- a/src/resources/ui/gb-tab.ui
+++ b/src/resources/ui/gb-tab.ui
@@ -7,73 +7,6 @@
         <property name="orientation">GTK_ORIENTATION_HORIZONTAL</property>
         <property name="visible">True</property>
         <property name="vexpand">False</property>
-        <style>
-          <class name="linked"/>
-        </style>
-        <child>
-          <object class="GtkComboBox" id="documents_combo">
-            <property name="visible">True</property>
-            <property name="hexpand">True</property>
-            <style>
-              <class name="tab-header-first"/>
-            </style>
-          </object>
-        </child>
-        <child>
-          <object class="GtkComboBox" id="symbols_combo">
-            <property name="visible">True</property>
-            <property name="hexpand">True</property>
-          </object>
-        </child>
-        <child>
-          <object class="GtkButton" id="drag_button">
-            <property name="visible">True</property>
-            <property name="hexpand">False</property>
-            <style>
-              <class name="image-button"/>
-            </style>
-            <child>
-              <object class="GtkImage">
-                <property name="visible">True</property>
-                <property name="icon-name">builder-drag-tab</property>
-                <property name="icon-size">1</property>
-              </object>
-            </child>
-          </object>
-        </child>
-        <child>
-          <object class="GtkButton" id="split_button">
-            <property name="visible">True</property>
-            <property name="hexpand">False</property>
-            <style>
-              <class name="image-button"/>
-              <class name="tab-header-last"/>
-            </style>
-            <child>
-              <object class="GtkImage">
-                <property name="visible">True</property>
-                <property name="icon-name">builder-split-tab</property>
-                <property name="icon-size">1</property>
-              </object>
-            </child>
-          </object>
-        </child>
-        <child>
-          <object class="GtkButton" id="close_button">
-            <property name="visible">False</property>
-            <property name="hexpand">False</property>
-            <style>
-              <class name="image-button"/>
-            </style>
-            <child>
-              <object class="GtkImage">
-                <property name="visible">True</property>
-                <property name="icon-name">window-close-symbolic</property>
-                <property name="icon-size">1</property>
-              </object>
-            </child>
-          </object>
-        </child>
       </object>
     </child>
     <child>
diff --git a/src/tabs/gb-tab-grid.c b/src/tabs/gb-tab-grid.c
index c04372d..720225a 100644
--- a/src/tabs/gb-tab-grid.c
+++ b/src/tabs/gb-tab-grid.c
@@ -16,6 +16,8 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#define G_LOG_DOMAIN "tab-grid"
+
 #include <glib/gi18n.h>
 
 #include "gb-log.h"
diff --git a/src/tabs/gb-tab-stack.c b/src/tabs/gb-tab-stack.c
index 16f6039..3ccc553 100644
--- a/src/tabs/gb-tab-stack.c
+++ b/src/tabs/gb-tab-stack.c
@@ -1,6 +1,6 @@
 /* gb-tab-stack.c
  *
- * Copyright (C) 2011 Christian Hergert <chris dronelabs com>
+ * Copyright (C) 2014 Christian Hergert <christian hergert me>
  *
  * 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
@@ -18,696 +18,430 @@
 
 #include <glib/gi18n.h>
 
-#include "gb-log.h"
-#include "gb-tab.h"
 #include "gb-tab-stack.h"
 
 struct _GbTabStackPrivate
 {
-   GtkListStore *tabs;
-   GtkWidget    *combo;
-   GtkWidget    *controls;
-   GtkWidget    *close;
-   GtkWidget    *notebook;
+  GtkButton    *close;
+  GtkComboBox  *combo;
+  GtkStack     *controls;
+  GtkStack     *stack;
+  GtkListStore *store;
 };
 
-G_DEFINE_TYPE_WITH_PRIVATE (GbTabStack, gb_tab_stack, GTK_TYPE_BOX)
-
 enum
 {
-   PROP_0,
-   LAST_PROP
+  PROP_0,
+  LAST_PROP
 };
 
-enum
-{
-   CHANGED,
-   LAST_SIGNAL
-};
+G_DEFINE_TYPE_WITH_PRIVATE (GbTabStack, gb_tab_stack, GTK_TYPE_BOX)
 
-//static GParamSpec *gParamSpecs[LAST_PROP];
-static guint gSignals[LAST_SIGNAL];
+#if 0
+static GParamSpec *gParamSpecs [LAST_PROP];
+#endif
+
+GtkWidget *
+gb_tab_stack_new (void)
+{
+  return g_object_new (GB_TYPE_TAB_STACK, NULL);
+}
 
 guint
 gb_tab_stack_get_n_tabs (GbTabStack *stack)
 {
-   guint ret;
+  GbTabStackPrivate *priv;
+  GList *children;
+  guint n_tabs;
+
+  g_return_val_if_fail (GB_IS_TAB_STACK (stack), 0);
+
+  priv = stack->priv;
 
-   ENTRY;
-   g_return_val_if_fail(GB_IS_TAB_STACK(stack), 0);
-   ret = gtk_tree_model_iter_n_children(GTK_TREE_MODEL(stack->priv->tabs), NULL);
-   RETURN(ret);
+  children = gtk_container_get_children (GTK_CONTAINER (priv->stack));
+  n_tabs = g_list_length (children);
+  g_list_free (children);
+
+  return n_tabs;
 }
 
-gboolean
-gb_tab_stack_focus_first (GbTabStack *stack)
+/**
+ * gb_tab_stack_get_tabs:
+ * @stack: (in): A #GbTabStack.
+ *
+ * Returns all of the tabs within the stack.
+ *
+ * Returns: (transfer container) (element-type GbTab*): A #GList of #GbTab.
+ */
+GList *
+gb_tab_stack_get_tabs (GbTabStack *stack)
 {
-   GbTabStackPrivate *priv;
-   GtkTreeIter iter;
+  g_return_val_if_fail (GB_IS_TAB_STACK (stack), NULL);
 
-   ENTRY;
+  return gtk_container_get_children (GTK_CONTAINER (stack->priv->stack));
+}
 
-   g_return_val_if_fail(GB_IS_TAB_STACK(stack), FALSE);
+static gboolean
+gb_tab_stack_get_tab_iter (GbTabStack  *stack,
+                           GbTab       *tab,
+                           GtkTreeIter *iter)
+{
+  GtkTreeModel *model;
+  gint position = -1;
+
+  g_return_val_if_fail (GB_IS_TAB_STACK (stack), FALSE);
+  g_return_val_if_fail (iter, FALSE);
+
+  gtk_container_child_get (GTK_CONTAINER (stack->priv->stack), GTK_WIDGET (tab),
+                           "position", &position,
+                           NULL);
+
+  if (position != -1)
+    {
+      model = GTK_TREE_MODEL (stack->priv->store);
+
+      if (gtk_tree_model_get_iter_first (model, iter))
+        {
+          for (; position; position--)
+            {
+              if (!gtk_tree_model_iter_next (model, iter))
+                return FALSE;
+            }
+          return TRUE;
+        }
+    }
+
+  return FALSE;
+}
 
-   priv = stack->priv;
+void
+gb_tab_stack_remove_tab (GbTabStack *stack,
+                         GbTab      *tab)
+{
+  GtkTreeIter iter;
 
-   if (gtk_tree_model_get_iter_first(GTK_TREE_MODEL(priv->tabs), &iter)) {
-      gtk_combo_box_set_active_iter(GTK_COMBO_BOX(priv->combo), &iter);
-      RETURN(TRUE);
-   }
+  g_return_if_fail (GB_IS_TAB_STACK (stack));
+  g_return_if_fail (GB_IS_TAB (tab));
 
-   RETURN(FALSE);
+  if (gb_tab_stack_get_tab_iter (stack, tab, &iter))
+    {
+      gtk_container_remove (GTK_CONTAINER (stack->priv->stack),
+                            GTK_WIDGET (tab));
+      gtk_list_store_remove (stack->priv->store, &iter);
+    }
 }
 
-gboolean
-gb_tab_stack_focus_next (GbTabStack *stack)
+static gboolean
+gb_tab_stack_focus_iter (GbTabStack  *stack,
+                         GtkTreeIter *iter)
 {
-   GbTabStackPrivate *priv;
-   guint n_tabs;
-   gint idx;
+  gboolean ret = FALSE;
+  GbTab *tab = NULL;
 
-   ENTRY;
+  g_return_val_if_fail (GB_IS_TAB_STACK (stack), FALSE);
+  g_return_val_if_fail (iter, FALSE);
 
-   g_return_val_if_fail(GB_IS_TAB_STACK(stack), FALSE);
+  gtk_tree_model_get (GTK_TREE_MODEL (stack->priv->store), iter,
+                      0, &tab,
+                      -1);
 
-   priv = stack->priv;
+  if (GB_IS_TAB (tab))
+    {
+      gtk_combo_box_set_active_iter (stack->priv->combo, iter);
+      ret = TRUE;
+    }
 
-   if ((idx = gtk_combo_box_get_active(GTK_COMBO_BOX(priv->combo))) >= 0) {
-      n_tabs = gb_tab_stack_get_n_tabs(stack);
-      if ((idx + 1) < n_tabs) {
-         gtk_combo_box_set_active(GTK_COMBO_BOX(priv->combo), idx + 1);
-         RETURN(TRUE);
-      }
-   }
+  g_clear_object (&tab);
 
-   RETURN(FALSE);
+  return ret;
 }
 
 gboolean
-gb_tab_stack_focus_previous (GbTabStack *stack)
+gb_tab_stack_focus_next (GbTabStack *stack)
 {
-   GbTabStackPrivate *priv;
-   gint idx;
+  GtkWidget *child;
+  GtkTreeIter iter;
+  gboolean ret = FALSE;
 
-   ENTRY;
+  g_return_val_if_fail (GB_IS_TAB_STACK (stack), FALSE);
 
-   g_return_val_if_fail(GB_IS_TAB_STACK(stack), FALSE);
+  if (!(child = gtk_stack_get_visible_child (stack->priv->stack)))
+    return FALSE;
 
-   priv = stack->priv;
+  if (gb_tab_stack_get_tab_iter (stack, GB_TAB (child), &iter) &&
+      gtk_tree_model_iter_next (GTK_TREE_MODEL (stack->priv->store), &iter))
+    ret = gb_tab_stack_focus_iter (stack, &iter);
 
-   if ((idx = gtk_combo_box_get_active(GTK_COMBO_BOX(priv->combo))) > 0) {
-      gtk_combo_box_set_active(GTK_COMBO_BOX(priv->combo), idx - 1);
-      RETURN(TRUE);
-   }
-
-   RETURN(FALSE);
+  return ret;
 }
 
 gboolean
-gb_tab_stack_focus_view (GbTabStack *stack,
-                          GbTab      *view)
+gb_tab_stack_focus_previous (GbTabStack *stack)
 {
-   GbTabStackPrivate *priv;
-   GtkTreeModel *model;
-   GtkTreeIter iter;
-   GObject *object;
+  GtkWidget *child;
+  GtkTreeIter iter;
+  gboolean ret = FALSE;
 
-   ENTRY;
+  g_return_val_if_fail (GB_IS_TAB_STACK (stack), FALSE);
 
-   g_return_val_if_fail(GB_IS_TAB_STACK(stack), FALSE);
+  if (!(child = gtk_stack_get_visible_child (stack->priv->stack)))
+    return FALSE;
 
-   priv = stack->priv;
+  if (gb_tab_stack_get_tab_iter (stack, GB_TAB (child), &iter) &&
+      gtk_tree_model_iter_previous (GTK_TREE_MODEL (stack->priv->store), &iter))
+    ret = gb_tab_stack_focus_iter (stack, &iter);
 
-   model = gtk_combo_box_get_model(GTK_COMBO_BOX(priv->combo));
+  return ret;
+}
 
-   if (gtk_tree_model_get_iter_first(model, &iter)) {
-      do {
-         gtk_tree_model_get(model, &iter, 0, &object, -1);
-         g_object_unref(object);
-         if (object == (GObject *)view) {
-            gtk_combo_box_set_active_iter(GTK_COMBO_BOX(priv->combo), &iter);
-            RETURN(TRUE);
-         }
-      } while (gtk_tree_model_iter_next(model, &iter));
-   }
+gboolean
+gb_tab_stack_focus_first (GbTabStack *stack)
+{
+  GtkTreeIter iter;
 
-   RETURN(FALSE);
+  g_return_val_if_fail (GB_IS_TAB_STACK (stack), FALSE);
+
+  if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (stack->priv->store),
+                                     &iter))
+    return gb_tab_stack_focus_iter (stack, &iter);
+
+  return FALSE;
 }
 
 gboolean
 gb_tab_stack_contains_tab (GbTabStack *stack,
-                           GbTab      *view)
+                           GbTab      *tab)
 {
-   GbTabStackPrivate *priv;
-   GtkTreeModel *model;
-   GtkTreeIter iter;
-   GObject *object;
+  gboolean ret = FALSE;
+  GList *list;
+  GList *iter;
 
-   ENTRY;
+  g_return_val_if_fail (GB_IS_TAB_STACK (stack), FALSE);
+  g_return_val_if_fail (GB_IS_TAB (tab), FALSE);
 
-   g_return_val_if_fail(GB_IS_TAB_STACK(stack), FALSE);
-   g_return_val_if_fail(GB_IS_TAB(view), FALSE);
+  list = gb_tab_stack_get_tabs (stack);
 
-   priv = stack->priv;
+  for (iter = list; iter; iter = iter->next)
+    {
+      if (iter->data == (void *)tab)
+        {
+          ret = TRUE;
+          break;
+        }
+    }
 
-   model = GTK_TREE_MODEL(priv->tabs);
+  g_list_free (list);
 
-   if (gtk_tree_model_get_iter_first(model, &iter)) {
-      do {
-         gtk_tree_model_get(model, &iter, 0, &object, -1);
-         g_object_unref(object);
-         if (object == (GObject *)view) {
-            RETURN(TRUE);
-         }
-      } while (gtk_tree_model_iter_next(model, &iter));
-   }
-
-   RETURN(FALSE);
+  return ret;
 }
 
 static void
-gb_tab_stack_set_page (GbTabStack *stack,
-                        gint         page)
+gb_tab_stack_combobox_changed (GbTabStack  *stack,
+                               GtkComboBox *combobox)
 {
-   GbTabStackPrivate *priv;
-   GtkWidget *controls;
-   GtkWidget *view;
-   gint current;
+  GtkTreeModel *model;
+  GtkTreeIter iter;
+  GbTab *tab = NULL;
 
-   ENTRY;
+  g_return_if_fail (GB_IS_TAB_STACK (stack));
+  g_print ("changed\n");
 
-   g_return_if_fail(GB_IS_TAB_STACK(stack));
-   g_return_if_fail(page >= 0);
+  model = gtk_combo_box_get_model (combobox);
 
-   priv = stack->priv;
+  if (gtk_combo_box_get_active_iter (combobox, &iter))
+    {
+      gtk_tree_model_get (model, &iter, 0, &tab, -1);
 
-   current = gtk_notebook_get_current_page(GTK_NOTEBOOK(priv->controls));
-   if (current >= 0) {
-      controls = gtk_notebook_get_nth_page(GTK_NOTEBOOK(priv->controls), current);
-      gtk_widget_hide(controls);
-   }
+      if (GB_IS_TAB (tab))
+        {
+          GtkWidget *controls;
 
-   gtk_notebook_set_current_page(GTK_NOTEBOOK(priv->notebook), page);
-   gtk_notebook_set_current_page(GTK_NOTEBOOK(priv->controls), page);
+          gtk_stack_set_visible_child (stack->priv->stack, GTK_WIDGET (tab));
+          gtk_widget_set_sensitive (GTK_WIDGET (stack->priv->close), TRUE);
 
-   if ((controls = gtk_notebook_get_nth_page(GTK_NOTEBOOK(priv->controls), page))) {
-      gtk_widget_show(controls);
-   }
+          if ((controls = gb_tab_get_controls (tab)))
+            gtk_stack_set_visible_child (stack->priv->controls, controls);
 
-   if ((view = gtk_notebook_get_nth_page(GTK_NOTEBOOK(priv->notebook), page))) {
-      gtk_widget_grab_focus(view);
-   }
+          g_print ("Controls: %p\n", controls);
+        }
+      else
+        {
+          gtk_widget_set_sensitive (GTK_WIDGET (stack->priv->close), FALSE);
+        }
 
-   EXIT;
-}
-
-void
-gb_tab_stack_remove_tab (GbTabStack *stack,
-                         GbTab      *view)
-{
-   GbTabStackPrivate *priv;
-   GtkTreeModel *model;
-   GtkTreeIter iter;
-   GtkWidget *controls;
-   GObject *object;
-   gint page = 0;
-   gboolean active = FALSE;
-
-   ENTRY;
-
-   g_return_if_fail(GB_IS_TAB_STACK(stack));
-   g_return_if_fail(GB_IS_TAB(view));
-
-   priv = stack->priv;
-
-   if (!gb_tab_stack_contains_tab (stack, view)) {
-      g_warning ("%s(): view is missing from stack.", G_STRFUNC);
-      EXIT;
-   }
-
-   /*
-    * TODO: Disconnect signals.
-    */
-
-   /*
-    * Remove the view from the drop down list.
-    */
-   model = GTK_TREE_MODEL(priv->tabs);
-   if (gtk_tree_model_get_iter_first(model, &iter)) {
-      do {
-         gtk_tree_model_get(model, &iter, 0, &object, -1);
-         g_object_unref(object);
-         if (object == (GObject *)view) {
-            active = (page == gtk_combo_box_get_active(GTK_COMBO_BOX(priv->combo)));
-            gtk_list_store_remove(priv->tabs, &iter);
-            break;
-         }
-         page++;
-      } while (gtk_tree_model_iter_next(model, &iter));
-   }
-
-   /*
-    * Remove the controls from the notebook.
-    */
-   if ((controls = gb_tab_get_controls(view))) {
-      gtk_container_remove(GTK_CONTAINER(priv->controls), controls);
-   }
-
-   /*
-    * Remove the view from the notebook.
-    */
-   gtk_container_remove(GTK_CONTAINER(priv->notebook), GTK_WIDGET(view));
-
-   /*
-    * Hide the close button if there are no views left.
-    */
-   if (!gtk_notebook_get_n_pages(GTK_NOTEBOOK(priv->notebook))) {
-      gtk_widget_hide(priv->close);
-   }
-
-   /*
-    * Try to set the page to the new item in the same slot if we can,
-    * otherwise the item previous.
-    */
-   if (active) {
-      page = MIN(page, gtk_notebook_get_n_pages(GTK_NOTEBOOK(priv->notebook)) - 1);
-      if (page >= 0) {
-         gtk_combo_box_set_active(GTK_COMBO_BOX(priv->combo), page);
-      }
-   }
-
-   g_signal_emit(stack, gSignals[CHANGED], 0);
-
-   EXIT;
+      g_clear_object (&tab);
+    }
 }
 
-static void
-gb_tab_stack_remove (GtkContainer *container,
-                      GtkWidget    *child)
+static gboolean
+gb_tab_stack_queue_draw (gpointer data)
 {
-   GbTabStack *stack = (GbTabStack *)container;
-
-   ENTRY;
-
-   g_return_if_fail(GB_IS_TAB_STACK(stack));
-   g_return_if_fail(GTK_IS_WIDGET(child));
+  g_return_val_if_fail (GTK_IS_WIDGET (data), NULL);
 
-   if (GB_IS_TAB(child)) {
-      gb_tab_stack_remove_tab (stack, GB_TAB(child));
-   } else {
-      GTK_CONTAINER_CLASS(gb_tab_stack_parent_class)->remove(container, child);
-   }
+  gtk_widget_queue_draw (GTK_WIDGET (data));
 
-   EXIT;
+  return G_SOURCE_REMOVE;
 }
 
-/**
- * gb_tab_stack_add_view:
- * @stack: (in): A #GbTabStack.
- * @view: (in): A #GbTab.
- *
- * Adds a view to the stack. An item is added to the #GtkComboBox
- * for the view. When selected from the combo box, the view will be
- * raised in the stack.
- *
- * The stack will take ownership of any of the controls provided by
- * the view. In the case the view is removed from the stack, the
- * controls will no longer be children of the stack. TODO
- */
 static void
-gb_tab_stack_add_view (GbTabStack *stack,
-                        GbTab      *view)
+gb_tab_stack_add_tab (GbTabStack *stack,
+                      GbTab      *tab)
 {
-   GbTabStackPrivate *priv;
-   GtkTreeIter iter;
-   gint page;
-
-   ENTRY;
-
-   g_return_if_fail(GB_IS_TAB_STACK(stack));
-   g_return_if_fail(GB_IS_TAB(view));
-
-   priv = stack->priv;
-
-   gtk_container_add(GTK_CONTAINER(priv->notebook), GTK_WIDGET(view));
-
-   gtk_list_store_append(priv->tabs, &iter);
-   gtk_list_store_set(priv->tabs, &iter, 0, view, -1);
-   gtk_combo_box_set_active_iter(GTK_COMBO_BOX(priv->combo), &iter);
-   gtk_container_add(GTK_CONTAINER(priv->controls), gb_tab_get_controls(view));
-
-   g_signal_connect_swapped(view, "notify::can-save",
-                            G_CALLBACK(gtk_widget_queue_draw),
-                            priv->combo);
-   g_signal_connect_swapped(view, "notify::name",
-                            G_CALLBACK(gtk_widget_queue_draw),
-                            priv->combo);
-   g_signal_connect_swapped(view, "closed",
-                            G_CALLBACK(gb_tab_stack_remove_tab),
-                            stack);
-
-   if ((page = gtk_notebook_get_n_pages(GTK_NOTEBOOK(priv->notebook)))) {
-      gb_tab_stack_set_page(stack, page - 1);
-   }
-
-   gtk_widget_show(priv->close);
-
-   g_signal_emit(stack, gSignals[CHANGED], 0);
-
-   EXIT;
+  GtkTreeIter iter;
+  GtkWidget *controls;
+
+  g_return_if_fail (GB_IS_TAB_STACK (stack));
+  g_return_if_fail (GB_IS_TAB (tab));
+
+  gtk_list_store_append (stack->priv->store, &iter);
+  g_object_freeze_notify (G_OBJECT (stack->priv->stack));
+  gtk_list_store_set (stack->priv->store, &iter, 0, tab, -1);
+  gtk_container_add (GTK_CONTAINER (stack->priv->stack), GTK_WIDGET (tab));
+  if ((controls = gb_tab_get_controls (tab)))
+    gtk_container_add (GTK_CONTAINER (stack->priv->controls), controls);
+  g_object_thaw_notify (G_OBJECT (stack->priv->stack));
+  gtk_combo_box_set_active_iter (stack->priv->combo, &iter);
+
+  /* TODO: need to disconnect on (re)move */
+  g_signal_connect_object (tab,
+                           "notify::title",
+                           G_CALLBACK (gb_tab_stack_queue_draw),
+                           stack,
+                           G_CONNECT_SWAPPED);
 }
 
-/**
- * gb_tab_stack_add:
- * @container: (in): A #GbTabStack.
- * @child: (in): A #GtkWidget.
- *
- * Handle the addition of a child to the view. If the child is a view,
- * then we pack it into our internal notebook.
- */
 static void
 gb_tab_stack_add (GtkContainer *container,
-                   GtkWidget    *child)
+                  GtkWidget    *widget)
 {
-   GbTabStack *stack = (GbTabStack *)container;
-
-   ENTRY;
+  GbTabStack *stack = (GbTabStack *)container;
 
-   g_return_if_fail(GB_IS_TAB_STACK(stack));
-   g_return_if_fail(GTK_IS_WIDGET(child));
+  g_return_if_fail (GB_IS_TAB_STACK (stack));
+  g_return_if_fail (GTK_IS_WIDGET (widget));
 
-   if (GB_IS_TAB(child)) {
-      gb_tab_stack_add_view(stack, GB_TAB(child));
-   } else {
-      GTK_CONTAINER_CLASS(gb_tab_stack_parent_class)->add(container, child);
-   }
-
-   EXIT;
+  if (GB_IS_TAB (widget))
+    gb_tab_stack_add_tab (stack, GB_TAB (widget));
+  else
+    GTK_CONTAINER_CLASS (gb_tab_stack_parent_class)->add (container, widget);
 }
 
-/**
- * gb_tab_stack_get_active:
- * @stack: (in): A #GbTabStack.
- *
- * Gets the active view based on the current focus.
- *
- * Returns: (transfer none): A #GtkWidget or %NULL.
- */
-GtkWidget *
-gb_tab_stack_get_active (GbTabStack *stack)
+static void
+gb_tab_stack_combobox_text_func (GtkCellLayout   *cell_layout,
+                                 GtkCellRenderer *cell,
+                                 GtkTreeModel    *tree_model,
+                                 GtkTreeIter     *iter,
+                                 gpointer         data)
 {
-   GtkWidget *toplevel;
-   GtkWidget *focus = NULL;
+  const gchar *title = NULL;
+  gchar *str = NULL;
+  GbTab *tab = NULL;
 
-   ENTRY;
+  gtk_tree_model_get (tree_model, iter, 0, &tab, -1);
 
-   g_return_val_if_fail(GB_IS_TAB_STACK(stack), NULL);
+  if (GB_IS_TAB (tab))
+    title = gb_tab_get_title (tab);
 
-   if ((toplevel = gtk_widget_get_toplevel(GTK_WIDGET(stack)))) {
-      if ((focus = gtk_window_get_focus(GTK_WINDOW(toplevel)))) {
-         while (focus && !GB_IS_TAB(focus)) {
-            focus = gtk_widget_get_parent(focus);
-         }
-      }
-   }
+  if (!title)
+    {
+      /* TODO: temp tab name */
+      title = _("untitled");
+    }
 
-   RETURN(focus);
-}
-
-static void
-gb_tab_stack_icon_name_func (GtkCellLayout   *cell_layout,
-                              GtkCellRenderer *cell,
-                              GtkTreeModel    *tree_model,
-                              GtkTreeIter     *iter,
-                              gpointer         user_data)
-{
-   GbTab *view;
+  g_object_set (cell, "text", title, NULL);
 
-   gtk_tree_model_get(tree_model, iter, 0, &view, -1);
-   g_assert(GB_IS_TAB(view));
-   g_object_set(cell, "icon-name", gb_tab_get_icon_name(view), NULL);
-   g_object_unref(view);
+  g_clear_object (&tab);
+  g_free (str);
 }
 
 static void
-gb_tab_stack_name_func (GtkCellLayout   *cell_layout,
-                         GtkCellRenderer *cell,
-                         GtkTreeModel    *tree_model,
-                         GtkTreeIter     *iter,
-                         gpointer         user_data)
+gb_tab_stack_finalize (GObject *object)
 {
-   gchar *text;
-   GbTab *view;
-
-   gtk_tree_model_get(tree_model, iter, 0, &view, -1);
-   g_assert(GB_IS_TAB(view));
-   text = g_strdup_printf("%s%s",
-                          gb_tab_get_title (view),
-                          gb_tab_get_dirty (view) ? " •" : "");
-   g_object_set(cell, "text", text, NULL);
-   g_object_unref(view);
-   g_free(text);
+  G_OBJECT_CLASS (gb_tab_stack_parent_class)->finalize (object);
 }
 
 static void
-gb_tab_stack_combo_changed (GbTabStack *stack,
-                             GtkComboBox *combo)
+gb_tab_stack_get_property (GObject    *object,
+                           guint       prop_id,
+                           GValue     *value,
+                           GParamSpec *pspec)
 {
-   gint page;
-
-   g_return_if_fail(GB_IS_TAB_STACK(stack));
-   g_return_if_fail(GTK_IS_COMBO_BOX(combo));
-
-   if ((page = gtk_combo_box_get_active(combo)) >= 0) {
-      gb_tab_stack_set_page(stack, page);
-      gtk_widget_grab_focus(stack->priv->notebook);
-   }
+#if 0
+  GbTabStack *stack = GB_TAB_STACK (object);
+#endif
+
+  switch (prop_id)
+    {
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
 }
 
 static void
-gb_tab_stack_grab_focus (GtkWidget *widget)
+gb_tab_stack_set_property (GObject      *object,
+                           guint         prop_id,
+                           const GValue *value,
+                           GParamSpec   *pspec)
 {
-   GbTabStack *stack = (GbTabStack *)widget;
-   g_return_if_fail(GB_IS_TAB_STACK(stack));
-   gtk_widget_grab_focus(stack->priv->notebook);
+#if 0
+  GbTabStack *stack = GB_TAB_STACK (object);
+#endif
+
+  switch (prop_id)
+    {
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
 }
 
 static void
-gb_tab_stack_close_current (GbTabStack *stack,
-                             GtkButton   *button)
+gb_tab_stack_class_init (GbTabStackClass *klass)
 {
-   GbTabStackPrivate *priv;
-   GtkWidget *child;
-   gint page;
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+  GtkContainerClass *container_class = GTK_CONTAINER_CLASS (klass);
 
-   ENTRY;
+  object_class->finalize = gb_tab_stack_finalize;
+  object_class->get_property = gb_tab_stack_get_property;
+  object_class->set_property = gb_tab_stack_set_property;
 
-   g_return_if_fail(GB_IS_TAB_STACK(stack));
+  container_class->add = gb_tab_stack_add;
 
-   priv = stack->priv;
+  gtk_widget_class_set_template_from_resource (widget_class,
+                                               "/org/gnome/builder/ui/gb-tab-stack.ui");
+  gtk_widget_class_bind_template_child_internal_private (widget_class, GbTabStack, controls);
+  gtk_widget_class_bind_template_child_private (widget_class, GbTabStack, close);
+  gtk_widget_class_bind_template_child_private (widget_class, GbTabStack, combo);
+  gtk_widget_class_bind_template_child_private (widget_class, GbTabStack, stack);
+  gtk_widget_class_bind_template_child_private (widget_class, GbTabStack, store);
 
-   page = gtk_notebook_get_current_page(GTK_NOTEBOOK(priv->notebook));
-   if (page >= 0) {
-      child = gtk_notebook_get_nth_page(GTK_NOTEBOOK(priv->notebook), page);
-      if (GB_IS_TAB(child)) {
-         gb_tab_close(GB_TAB(child));
-      }
-   }
-
-   EXIT;
+  g_type_ensure (GB_TYPE_TAB);
 }
 
-/**
- * gb_tab_stack_get_tabs:
- * @stack: (in): A #GbTabStack.
- *
- * Get all views in the stack.
- *
- * Returns: (transfer container) (element-type GbTab*): A #GList.
- */
-GList *
-gb_tab_stack_get_tabs (GbTabStack *stack)
-{
-   GtkTreeModel *model;
-   GtkTreeIter iter;
-   GbTab *view;
-   GList *ret = NULL;
-
-   ENTRY;
-
-   g_return_val_if_fail(GB_IS_TAB_STACK(stack), NULL);
-
-   model = GTK_TREE_MODEL(stack->priv->tabs);
-   if (gtk_tree_model_get_iter_first(model, &iter)) {
-      do {
-         /*
-          * The code below looks unsafe. However, the model holds our
-          * reference to the view, so it is fine.
-          */
-         gtk_tree_model_get(model, &iter, 0, &view, -1);
-         ret = g_list_append(ret, view);
-         g_object_unref(view);
-      } while (gtk_tree_model_iter_next(model, &iter));
-   }
-
-   RETURN(ret);
-}
-
-/**
- * gb_tab_stack_finalize:
- * @object: (in): A #GbTabStack.
- *
- * Finalizer for a #GbTabStack instance. Frees any resources held by
- * the instance.
- */
 static void
-gb_tab_stack_finalize (GObject *object)
+gb_tab_stack_init (GbTabStack *stack)
 {
-   GbTabStackPrivate *priv;
-
-   ENTRY;
-
-   priv = GB_TAB_STACK(object)->priv;
+  GtkCellLayout *layout;
+  GtkCellRenderer *cell;
 
-   g_clear_object(&priv->tabs);
+  stack->priv = gb_tab_stack_get_instance_private (stack);
 
-   G_OBJECT_CLASS(gb_tab_stack_parent_class)->finalize(object);
+  gtk_orientable_set_orientation (GTK_ORIENTABLE (stack),
+                                  GTK_ORIENTATION_VERTICAL);
 
-   EXIT;
-}
-
-/**
- * gb_tab_stack_class_init:
- * @klass: (in): A #GbTabStackClass.
- *
- * Initializes the #GbTabStackClass and prepares the vtable.
- */
-static void
-gb_tab_stack_class_init (GbTabStackClass *klass)
-{
-   GObjectClass *object_class;
-   GtkWidgetClass *widget_class;
-   GtkContainerClass *container_class;
-
-   object_class = G_OBJECT_CLASS(klass);
-   object_class->finalize = gb_tab_stack_finalize;
-
-   widget_class = GTK_WIDGET_CLASS(klass);
-   widget_class->grab_focus = gb_tab_stack_grab_focus;
-
-   container_class = GTK_CONTAINER_CLASS(klass);
-   container_class->add = gb_tab_stack_add;
-   container_class->remove = gb_tab_stack_remove;
-
-   /**
-    * GbTabStack::changed:
-    *
-    * The "changed" signal is emitted when the children of the stack have
-    * changed.
-    */
-   gSignals[CHANGED] = g_signal_new("changed",
-                                    GB_TYPE_TAB_STACK,
-                                    G_SIGNAL_RUN_LAST,
-                                    0,
-                                    NULL,
-                                    NULL,
-                                    g_cclosure_marshal_VOID__VOID,
-                                    G_TYPE_NONE,
-                                    0);
-}
+  gtk_widget_init_template (GTK_WIDGET (stack));
 
-/**
- * gb_tab_stack_init:
- * @stack: (in): A #GbTabStack.
- *
- * Initializes the newly created #GbTabStack instance.
- */
-static void
-gb_tab_stack_init (GbTabStack *stack)
-{
-   GbTabStackPrivate *priv;
-   GtkCellRenderer *cell;
-   GtkWidget *hbox;
-
-   stack->priv = priv = gb_tab_stack_get_instance_private (stack);
-
-   gtk_orientable_set_orientation (GTK_ORIENTABLE (stack),
-                                   GTK_ORIENTATION_VERTICAL);
-
-   priv->tabs = gtk_list_store_new(1, GB_TYPE_TAB);
-
-   hbox = g_object_new(GTK_TYPE_BOX,
-                       "orientation", GTK_ORIENTATION_HORIZONTAL,
-                       "visible", TRUE,
-                       NULL);
-   gtk_container_add_with_properties(GTK_CONTAINER(stack), hbox,
-                                     "expand", FALSE,
-                                     NULL);
-
-   priv->combo = g_object_new(GTK_TYPE_COMBO_BOX,
-                              "has-frame", FALSE,
-                              "height-request", 30,
-                              "model", priv->tabs,
-                              "visible", TRUE,
-                              NULL);
-   gtk_container_add_with_properties(GTK_CONTAINER(hbox), priv->combo,
-                                     "expand", TRUE,
-                                     NULL);
-   g_signal_connect_swapped(priv->combo, "changed",
-                            G_CALLBACK(gb_tab_stack_combo_changed),
-                            stack);
-
-   priv->controls = g_object_new(GTK_TYPE_NOTEBOOK,
-                                 "visible", TRUE,
-                                 "show-border", FALSE,
-                                 "show-tabs", FALSE,
-                                 NULL);
-   gtk_container_add_with_properties(GTK_CONTAINER(hbox), priv->controls,
-                                     "expand", FALSE,
-                                     NULL);
-
-   priv->close = g_object_new(GTK_TYPE_BUTTON,
-                              "child", g_object_new(GTK_TYPE_IMAGE,
-                                                    "icon-name", "window-close-symbolic",
-                                                    "icon-size", GTK_ICON_SIZE_MENU,
-                                                    "visible", TRUE,
-                                                    "tooltip-text", _("Close the current view."),
-                                                    NULL),
-                              "visible", FALSE,
-                              NULL);
-   g_signal_connect_swapped(priv->close, "clicked",
-                            G_CALLBACK(gb_tab_stack_close_current),
-                            stack);
-   gtk_container_add_with_properties(GTK_CONTAINER(hbox), priv->close,
-                                     "expand", FALSE,
-                                     NULL);
-
-   cell = g_object_new(GTK_TYPE_CELL_RENDERER_PIXBUF,
-                       "icon-name", "text-x-generic",
-                       "width", 24,
-                       "xalign", 0.5f,
-                       "xpad", 3,
-                       NULL);
-   gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(priv->combo), cell, FALSE);
-   gtk_cell_layout_set_cell_data_func(GTK_CELL_LAYOUT(priv->combo), cell,
-                                      gb_tab_stack_icon_name_func,
-                                      NULL, NULL);
+  g_signal_connect_object (stack->priv->combo,
+                           "changed",
+                           G_CALLBACK (gb_tab_stack_combobox_changed),
+                           stack,
+                           G_CONNECT_SWAPPED);
 
-   cell = g_object_new(GTK_TYPE_CELL_RENDERER_TEXT,
-                       "size-points", 9.0,
-                       "xpad", 3,
-                       NULL);
-   gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(priv->combo), cell, TRUE);
-   gtk_cell_layout_set_cell_data_func(GTK_CELL_LAYOUT(priv->combo), cell,
-                                      gb_tab_stack_name_func,
+  layout = GTK_CELL_LAYOUT (stack->priv->combo);
+  cell = gtk_cell_renderer_text_new ();
+  gtk_cell_layout_pack_start (layout, cell, TRUE);
+  gtk_cell_layout_set_cell_data_func (layout, cell,
+                                      gb_tab_stack_combobox_text_func,
                                       NULL, NULL);
-
-   priv->notebook = g_object_new(GTK_TYPE_NOTEBOOK,
-                                 "visible", TRUE,
-                                 "show-border", FALSE,
-                                 "show-tabs", FALSE,
-                                 NULL);
-   gtk_container_add_with_properties(GTK_CONTAINER(stack), priv->notebook,
-                                     "expand", TRUE,
-                                     NULL);
+  gtk_cell_renderer_text_set_fixed_height_from_font (
+      GTK_CELL_RENDERER_TEXT (cell), 1);
 }
diff --git a/src/tabs/gb-tab.c b/src/tabs/gb-tab.c
index 508c669..ba52786 100644
--- a/src/tabs/gb-tab.c
+++ b/src/tabs/gb-tab.c
@@ -27,9 +27,9 @@
 struct _GbTabPrivate
 {
   GtkWidget *content;
+  GtkBox    *controls;
   GtkWidget *footer_box;
   GtkWidget *header_box;
-  GtkWidget *drag_button;
 
   gchar    *icon_name;
   gchar    *title;
@@ -59,11 +59,8 @@ G_DEFINE_TYPE_EXTENDED (GbTab, gb_tab, GTK_TYPE_BOX, 0,
                         G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
                                                buildable_init))
 
-static GParamSpec     *gParamSpecs [LAST_PROP];
-static guint           gSignals [LAST_SIGNAL];
-static GtkTargetEntry  gTargets [] = {
-  { "GTK_NOTEBOOK_TAB", GTK_TARGET_SAME_APP, 0 },
-};
+static GParamSpec *gParamSpecs [LAST_PROP];
+static guint       gSignals [LAST_SIGNAL];
 
 GtkWidget *
 gb_tab_get_header_area (GbTab *tab)
@@ -74,9 +71,11 @@ gb_tab_get_header_area (GbTab *tab)
 }
 
 GtkWidget *
-gb_tab_get_controls(GbTab *tab)
+gb_tab_get_controls (GbTab *tab)
 {
-  return tab->priv->header_box;
+  g_return_val_if_fail (GB_IS_TAB (tab), NULL);
+
+  return GTK_WIDGET (tab->priv->controls);
 }
 
 GtkWidget *
@@ -175,33 +174,6 @@ gb_tab_thaw_drag (GbTab *tab)
   g_signal_emit (tab, gSignals[THAW_DRAG], 0);
 }
 
-static gboolean
-gb_tab_on_drag_button_press (GtkWidget      *button,
-                             GdkEventButton *event,
-                             GbTab          *tab)
-{
-  GtkTargetList *source_targets;
-  GtkWidget *parent;
-
-  ENTRY;
-
-  g_return_if_fail (GB_IS_TAB (tab));
-
-  if ((event->button == GDK_BUTTON_PRIMARY) &&
-      (parent = gtk_widget_get_parent (GTK_WIDGET (tab))) &&
-      GB_IS_NOTEBOOK (parent))
-    {
-      source_targets = gtk_target_list_new (gTargets, G_N_ELEMENTS (gTargets));
-      gtk_drag_begin_with_coordinates (parent, source_targets, GDK_ACTION_MOVE,
-                                       event->button, (GdkEvent *)event,
-                                       event->x, event->y);
-      gtk_target_list_unref (source_targets);
-      RETURN (TRUE);
-    }
-
-  RETURN (FALSE);
-}
-
 static void
 gb_tab_finalize (GObject *object)
 {
@@ -209,6 +181,7 @@ gb_tab_finalize (GObject *object)
 
   g_clear_pointer (&tab->priv->icon_name, g_free);
   g_clear_pointer (&tab->priv->title, g_free);
+  g_clear_object (&tab->priv->controls);
 
   G_OBJECT_CLASS (gb_tab_parent_class)->finalize (object);
 }
@@ -268,27 +241,11 @@ gb_tab_set_property (GObject      *object,
 }
 
 static void
-gb_tab_constructed (GObject *object)
-{
-  GbTab *tab = (GbTab *)object;
-
-  g_return_if_fail (GB_IS_TAB (tab));
-
-  G_OBJECT_CLASS (gb_tab_parent_class)->constructed (object);
-
-  g_signal_connect (tab->priv->drag_button,
-                    "button-press-event",
-                    G_CALLBACK (gb_tab_on_drag_button_press),
-                    tab);
-}
-
-static void
 gb_tab_class_init (GbTabClass *klass)
 {
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
   GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
 
-  object_class->constructed = gb_tab_constructed;
   object_class->finalize = gb_tab_finalize;
   object_class->get_property = gb_tab_get_property;
   object_class->set_property = gb_tab_set_property;
@@ -296,7 +253,6 @@ gb_tab_class_init (GbTabClass *klass)
   gtk_widget_class_set_template_from_resource (widget_class,
                                                "/org/gnome/builder/ui/gb-tab.ui");
   gtk_widget_class_bind_template_child_private (widget_class, GbTab, content);
-  gtk_widget_class_bind_template_child_private (widget_class, GbTab, drag_button);
   gtk_widget_class_bind_template_child_private (widget_class, GbTab, footer_box);
   gtk_widget_class_bind_template_child_private (widget_class, GbTab, header_box);
 
@@ -369,6 +325,13 @@ gb_tab_init (GbTab *tab)
   gtk_orientable_set_orientation (GTK_ORIENTABLE (tab),
                                   GTK_ORIENTATION_VERTICAL);
 
+  tab->priv->controls =
+    g_object_new (GTK_TYPE_BOX,
+                  "orientation", GTK_ORIENTATION_HORIZONTAL,
+                  "visible", TRUE,
+                  NULL);
+  g_object_ref_sink (tab->priv->controls);
+
   gtk_widget_init_template (GTK_WIDGET (tab));
 }
 
@@ -387,6 +350,8 @@ gb_tab_get_internal_child (GtkBuildable *buildable,
     return G_OBJECT (tab->priv->header_box);
   else if (g_strcmp0 (childname, "footer") == 0)
     return G_OBJECT (tab->priv->footer_box);
+  else if (g_strcmp0 (childname, "controls") == 0)
+    return G_OBJECT (tab->priv->controls);
 
   return NULL;
 }



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