[gnome-builder] editor: use single instance of tab controls per stack



commit 8616b9aa60066f78eae88e49e3a897bb53337c55
Author: Christian Hergert <chergert redhat com>
Date:   Tue Jul 19 18:28:53 2016 -0700

    editor: use single instance of tab controls per stack
    
    Instead of creatin new popovers and lists for every document that is
    opened, use a single instance of the controls per stack. This saves on
    lots of popovers when lots of documents are opened as well as cutting down
    on the amount of style validation that has to occur with those additional
    widgets.

 libide/Makefile.am                                |    4 +
 libide/editor/ide-editor-layout-stack-addin.c     |  108 +++++++
 libide/editor/ide-editor-layout-stack-addin.h     |   34 ++
 libide/editor/ide-editor-layout-stack-controls.c  |  350 +++++++++++++++++++++
 libide/editor/ide-editor-layout-stack-controls.h  |   37 +++
 libide/editor/ide-editor-layout-stack-controls.ui |  117 +++++++
 libide/editor/ide-editor-plugin.c                 |    5 +-
 libide/editor/ide-editor-view-actions.c           |    3 +-
 libide/editor/ide-editor-view-private.h           |    9 -
 libide/editor/ide-editor-view.c                   |  216 -------------
 libide/editor/ide-editor-view.ui                  |  103 ------
 libide/resources/libide.gresource.xml             |    3 +-
 12 files changed, 658 insertions(+), 331 deletions(-)
---
diff --git a/libide/Makefile.am b/libide/Makefile.am
index 0374543..467472c 100644
--- a/libide/Makefile.am
+++ b/libide/Makefile.am
@@ -332,6 +332,10 @@ libide_1_0_la_SOURCES =                                   \
        editor/ide-editor-map-bin.c                       \
        editor/ide-editor-map-bin.h                       \
        editor/ide-editor-plugin.c                        \
+       editor/ide-editor-layout-stack-addin.c            \
+       editor/ide-editor-layout-stack-addin.h            \
+       editor/ide-editor-layout-stack-controls.c         \
+       editor/ide-editor-layout-stack-controls.h         \
        editor/ide-editor-print-operation.c               \
        editor/ide-editor-print-operation.h               \
        editor/ide-editor-tweak-widget.c                  \
diff --git a/libide/editor/ide-editor-layout-stack-addin.c b/libide/editor/ide-editor-layout-stack-addin.c
new file mode 100644
index 0000000..f669e0e
--- /dev/null
+++ b/libide/editor/ide-editor-layout-stack-addin.c
@@ -0,0 +1,108 @@
+/* ide-editor-layout-stack-addin.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/>.
+ */
+
+#define G_LOG_DOMAIN "ide-editor-layout-stack-view"
+
+#include <glib/gi18n.h>
+
+#include "editor/ide-editor-layout-stack-addin.h"
+#include "editor/ide-editor-layout-stack-controls.h"
+#include "editor/ide-editor-view.h"
+
+struct _IdeEditorLayoutStackAddin
+{
+  GObject parent_instance;
+  IdeEditorLayoutStackControls *controls;
+};
+
+static void layout_stack_addin_iface_init (IdeLayoutStackAddinInterface *iface);
+
+G_DEFINE_TYPE_EXTENDED (IdeEditorLayoutStackAddin,
+                        ide_editor_layout_stack_addin,
+                        G_TYPE_OBJECT,
+                        0,
+                        G_IMPLEMENT_INTERFACE (IDE_TYPE_LAYOUT_STACK_ADDIN,
+                                               layout_stack_addin_iface_init))
+
+static void
+ide_editor_layout_stack_addin_class_init (IdeEditorLayoutStackAddinClass *klass)
+{
+}
+
+static void
+ide_editor_layout_stack_addin_init (IdeEditorLayoutStackAddin *self)
+{
+}
+
+static void
+ide_editor_layout_stack_addin_load (IdeLayoutStackAddin *addin,
+                                    IdeLayoutStack      *stack)
+{
+  IdeEditorLayoutStackAddin *self = (IdeEditorLayoutStackAddin *)addin;
+
+  g_assert (IDE_IS_EDITOR_LAYOUT_STACK_ADDIN (self));
+  g_assert (IDE_IS_LAYOUT_STACK (stack));
+
+  self->controls = g_object_new (IDE_TYPE_EDITOR_LAYOUT_STACK_CONTROLS, NULL);
+  g_signal_connect (self->controls,
+                    "destroy",
+                    G_CALLBACK (gtk_widget_destroyed),
+                    &self->controls);
+  ide_layout_stack_add_control (stack, GTK_WIDGET (self->controls), 0);
+}
+
+static void
+ide_editor_layout_stack_addin_unload (IdeLayoutStackAddin *addin,
+                                      IdeLayoutStack      *stack)
+{
+  IdeEditorLayoutStackAddin *self = (IdeEditorLayoutStackAddin *)addin;
+
+  g_assert (IDE_IS_EDITOR_LAYOUT_STACK_ADDIN (self));
+  g_assert (IDE_IS_LAYOUT_STACK (stack));
+
+  gtk_widget_destroy (GTK_WIDGET (self->controls));
+}
+
+static void
+ide_editor_layout_stack_addin_set_view (IdeLayoutStackAddin *addin,
+                                        IdeLayoutView       *view)
+{
+  IdeEditorLayoutStackAddin *self = (IdeEditorLayoutStackAddin *)addin;
+
+  g_assert (IDE_IS_EDITOR_LAYOUT_STACK_ADDIN (self));
+  g_assert (!view || IDE_IS_LAYOUT_VIEW (view));
+
+  if (IDE_IS_EDITOR_VIEW (view))
+    {
+      ide_editor_layout_stack_controls_set_view (self->controls, IDE_EDITOR_VIEW (view));
+      gtk_widget_show (GTK_WIDGET (self->controls));
+    }
+  else
+    {
+      gtk_widget_hide (GTK_WIDGET (self->controls));
+      ide_editor_layout_stack_controls_set_view (self->controls, NULL);
+    }
+}
+
+static void
+layout_stack_addin_iface_init (IdeLayoutStackAddinInterface *iface)
+{
+  iface->load = ide_editor_layout_stack_addin_load;
+  iface->unload = ide_editor_layout_stack_addin_unload;
+  iface->set_view = ide_editor_layout_stack_addin_set_view;
+}
diff --git a/libide/editor/ide-editor-layout-stack-addin.h b/libide/editor/ide-editor-layout-stack-addin.h
new file mode 100644
index 0000000..4fbeaf5
--- /dev/null
+++ b/libide/editor/ide-editor-layout-stack-addin.h
@@ -0,0 +1,34 @@
+/* ide-editor-layout-stack-addin.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_EDITOR_LAYOUT_STACK_ADDIN_H
+#define IDE_EDITOR_LAYOUT_STACK_ADDIN_H
+
+#include <gtk/gtk.h>
+
+#include "workbench/ide-layout-stack-addin.h"
+
+G_BEGIN_DECLS
+
+#define IDE_TYPE_EDITOR_LAYOUT_STACK_ADDIN (ide_editor_layout_stack_addin_get_type())
+
+G_DECLARE_FINAL_TYPE (IdeEditorLayoutStackAddin, ide_editor_layout_stack_addin, IDE, 
EDITOR_LAYOUT_STACK_ADDIN, GObject)
+
+G_END_DECLS
+
+#endif /* IDE_EDITOR_LAYOUT_STACK_ADDIN_H */
diff --git a/libide/editor/ide-editor-layout-stack-controls.c 
b/libide/editor/ide-editor-layout-stack-controls.c
new file mode 100644
index 0000000..fe592b7
--- /dev/null
+++ b/libide/editor/ide-editor-layout-stack-controls.c
@@ -0,0 +1,350 @@
+/* ide-editor-layout-stack-controls.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/>.
+ */
+
+#define G_LOG_DOMAIN "ide-editor-layout-stack-controls"
+
+#include <egg-binding-group.h>
+#include <egg-signal-group.h>
+#include <egg-simple-popover.h>
+#include <glib/gi18n.h>
+
+#include "editor/ide-editor-frame.h"
+#include "editor/ide-editor-frame-private.h"
+#include "editor/ide-editor-layout-stack-controls.h"
+#include "editor/ide-editor-tweak-widget.h"
+#include "editor/ide-editor-view.h"
+#include "editor/ide-editor-view-private.h"
+
+struct _IdeEditorLayoutStackControls
+{
+  GtkBox                parent_instance;
+
+  IdeEditorView        *view;
+  EggBindingGroup      *document_bindings;
+  EggSignalGroup       *document_signals;
+
+  EggSimplePopover     *goto_line_popover;
+  GtkButton            *warning_button;
+  EggSimpleLabel       *line_label;
+  EggSimpleLabel       *column_label;
+  GtkLabel             *range_label;
+  GtkMenuButton        *tweak_button;
+  IdeEditorTweakWidget *tweak_widget;
+};
+
+G_DEFINE_TYPE (IdeEditorLayoutStackControls, ide_editor_layout_stack_controls, GTK_TYPE_BOX)
+
+static gboolean
+language_to_string (GBinding     *binding,
+                    const GValue *from_value,
+                    GValue       *to_value,
+                    gpointer      user_data)
+{
+  GtkSourceLanguage *language;
+
+  g_assert (G_VALUE_HOLDS (from_value, GTK_SOURCE_TYPE_LANGUAGE));
+  g_assert (G_VALUE_HOLDS_STRING (to_value));
+  g_assert (user_data == NULL);
+
+  language = g_value_get_object (from_value);
+
+  if (language != NULL)
+    g_value_set_string (to_value, gtk_source_language_get_name (language));
+  else
+    g_value_set_string (to_value, _("Plain Text"));
+
+  return TRUE;
+}
+
+static void
+document_cursor_moved (IdeEditorLayoutStackControls *self,
+                       const GtkTextIter            *iter,
+                       GtkTextBuffer                *buffer)
+{
+  IdeSourceView *source_view;
+  GtkTextIter bounds;
+  GtkTextMark *mark;
+  gchar str[32];
+  guint line;
+  gint column;
+  gint column2;
+
+  g_assert (IDE_IS_EDITOR_LAYOUT_STACK_CONTROLS (self));
+  g_assert (iter != NULL);
+  g_assert (IDE_IS_BUFFER (buffer));
+
+  if (self->view == NULL)
+    return;
+
+  source_view = ide_editor_view_get_active_source_view (self->view);
+
+  ide_source_view_get_visual_position (source_view, &line, (guint *)&column);
+
+  mark = gtk_text_buffer_get_selection_bound (buffer);
+  gtk_text_buffer_get_iter_at_mark (buffer, &bounds, mark);
+
+  g_snprintf (str, sizeof str, "%d", line + 1);
+  egg_simple_label_set_label (self->line_label, str);
+
+  g_snprintf (str, sizeof str, "%d", column + 1);
+  egg_simple_label_set_label (self->column_label, str);
+
+  if (!gtk_widget_has_focus (GTK_WIDGET (source_view)) ||
+      gtk_text_iter_equal (&bounds, iter) ||
+      (gtk_text_iter_get_line (iter) != gtk_text_iter_get_line (&bounds)))
+    {
+      gtk_widget_set_visible (GTK_WIDGET (self->range_label), FALSE);
+      return;
+    }
+
+  /* We have a selection that is on the same line.
+   * Lets give some detail as to how long the selection is.
+   */
+  column2 = gtk_source_view_get_visual_column (GTK_SOURCE_VIEW (source_view), &bounds);
+
+  g_snprintf (str, sizeof str, "%u", ABS (column2 - column));
+  gtk_label_set_label (self->range_label, str);
+  gtk_widget_set_visible (GTK_WIDGET (self->range_label), TRUE);
+}
+
+
+static void
+goto_line_activate (IdeEditorLayoutStackControls *self,
+                    const gchar                  *text,
+                    EggSimplePopover             *popover)
+{
+  gint64 value;
+
+  g_assert (IDE_IS_EDITOR_LAYOUT_STACK_CONTROLS (self));
+  g_assert (EGG_IS_SIMPLE_POPOVER (popover));
+
+  if (self->view == NULL)
+    return;
+
+  if (!ide_str_empty0 (text))
+    {
+      value = g_ascii_strtoll (text, NULL, 10);
+
+      if ((value > 0) && (value < G_MAXINT))
+        {
+          GtkTextIter iter;
+          GtkTextBuffer *buffer = GTK_TEXT_BUFFER (self->view->document);
+
+          gtk_widget_grab_focus (GTK_WIDGET (self->view->frame1->source_view));
+          gtk_text_buffer_get_iter_at_line (buffer, &iter, value - 1);
+          gtk_text_buffer_select_range (buffer, &iter, &iter);
+          ide_source_view_scroll_to_iter (self->view->frame1->source_view,
+                                          &iter, 0.25, TRUE, 1.0, 0.5, TRUE);
+        }
+    }
+}
+
+static gboolean
+goto_line_insert_text (IdeEditorLayoutStackControls *self,
+                       guint                         position,
+                       const gchar                  *chars,
+                       guint                         n_chars,
+                       EggSimplePopover             *popover)
+{
+  g_assert (IDE_IS_EDITOR_LAYOUT_STACK_CONTROLS (self));
+  g_assert (EGG_IS_SIMPLE_POPOVER (popover));
+  g_assert (chars != NULL);
+
+  for (; *chars; chars = g_utf8_next_char (chars))
+    {
+      if (!g_unichar_isdigit (g_utf8_get_char (chars)))
+        return GDK_EVENT_STOP;
+    }
+
+  return GDK_EVENT_PROPAGATE;
+}
+
+static void
+goto_line_changed (IdeEditorLayoutStackControls *self,
+                   EggSimplePopover             *popover)
+{
+  gchar *message;
+  const gchar *text;
+  GtkTextIter begin;
+  GtkTextIter end;
+
+  g_assert (IDE_IS_EDITOR_LAYOUT_STACK_CONTROLS (self));
+  g_assert (EGG_IS_SIMPLE_POPOVER (popover));
+
+  if (self->view == NULL)
+    return;
+
+  text = egg_simple_popover_get_text (popover);
+
+  gtk_text_buffer_get_bounds (GTK_TEXT_BUFFER (self->view->document), &begin, &end);
+
+  if (!ide_str_empty0 (text))
+    {
+      gint64 value;
+
+      value = g_ascii_strtoll (text, NULL, 10);
+
+      if (value > 0)
+        {
+          if (value <= gtk_text_iter_get_line (&end) + 1)
+            {
+              egg_simple_popover_set_message (popover, NULL);
+              egg_simple_popover_set_ready (popover, TRUE);
+              return;
+            }
+        }
+    }
+
+  /* translators: the user selected a number outside the value range for the document. */
+  message = g_strdup_printf (_("Provide a number between 1 and %u"),
+                             gtk_text_iter_get_line (&end) + 1);
+  egg_simple_popover_set_message (popover, message);
+  egg_simple_popover_set_ready (popover, FALSE);
+
+  g_free (message);
+}
+
+static void
+warning_button_clicked (IdeEditorLayoutStackControls *self,
+                        GtkButton                    *button)
+{
+  IdeSourceView *source_view;
+
+  g_assert (IDE_IS_EDITOR_LAYOUT_STACK_CONTROLS (self));
+  g_assert (GTK_IS_BUTTON (button));
+
+  if (self->view == NULL)
+    return;
+
+  source_view = ide_editor_view_get_active_source_view (self->view);
+  gtk_widget_grab_focus (GTK_WIDGET (source_view));
+  g_signal_emit_by_name (source_view, "move-error", GTK_DIR_DOWN);
+}
+
+static void
+ide_editor_layout_stack_controls_finalize (GObject *object)
+{
+  IdeEditorLayoutStackControls *self = (IdeEditorLayoutStackControls *)object;
+
+  g_clear_object (&self->document_bindings);
+  g_clear_object (&self->document_signals);
+
+  self->view = NULL;
+
+  G_OBJECT_CLASS (ide_editor_layout_stack_controls_parent_class)->finalize (object);
+}
+
+static void
+ide_editor_layout_stack_controls_class_init (IdeEditorLayoutStackControlsClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+  object_class->finalize = ide_editor_layout_stack_controls_finalize;
+
+  gtk_widget_class_set_template_from_resource (widget_class, 
"/org/gnome/builder/ui/ide-editor-layout-stack-controls.ui");
+  gtk_widget_class_bind_template_child (widget_class, IdeEditorLayoutStackControls, column_label);
+  gtk_widget_class_bind_template_child (widget_class, IdeEditorLayoutStackControls, goto_line_popover);
+  gtk_widget_class_bind_template_child (widget_class, IdeEditorLayoutStackControls, line_label);
+  gtk_widget_class_bind_template_child (widget_class, IdeEditorLayoutStackControls, range_label);
+  gtk_widget_class_bind_template_child (widget_class, IdeEditorLayoutStackControls, warning_button);
+  gtk_widget_class_bind_template_child (widget_class, IdeEditorLayoutStackControls, tweak_button);
+  gtk_widget_class_bind_template_child (widget_class, IdeEditorLayoutStackControls, tweak_widget);
+}
+
+static void
+ide_editor_layout_stack_controls_init (IdeEditorLayoutStackControls *self)
+{
+  gtk_widget_init_template (GTK_WIDGET (self));
+
+  g_signal_connect_object (self->goto_line_popover,
+                           "activate",
+                           G_CALLBACK (goto_line_activate),
+                           self,
+                           G_CONNECT_SWAPPED);
+
+  g_signal_connect_object (self->goto_line_popover,
+                           "insert-text",
+                           G_CALLBACK (goto_line_insert_text),
+                           self,
+                           G_CONNECT_SWAPPED);
+
+  g_signal_connect_object (self->goto_line_popover,
+                           "changed",
+                           G_CALLBACK (goto_line_changed),
+                           self,
+                           G_CONNECT_SWAPPED);
+
+  g_signal_connect_object (self->warning_button,
+                           "clicked",
+                           G_CALLBACK (warning_button_clicked),
+                           self,
+                           G_CONNECT_SWAPPED);
+
+  self->document_bindings = egg_binding_group_new ();
+
+  egg_binding_group_bind (self->document_bindings, "has-diagnostics",
+                          self->warning_button, "visible",
+                          G_BINDING_SYNC_CREATE);
+
+  egg_binding_group_bind_full (self->document_bindings, "language",
+                               self->tweak_button, "label",
+                               G_BINDING_SYNC_CREATE,
+                               language_to_string, NULL, NULL, NULL);
+
+  self->document_signals = egg_signal_group_new (IDE_TYPE_BUFFER);
+
+  egg_signal_group_connect_object (self->document_signals,
+                                   "cursor-moved",
+                                   G_CALLBACK (document_cursor_moved),
+                                   self,
+                                   G_CONNECT_SWAPPED);
+}
+
+void
+ide_editor_layout_stack_controls_set_view (IdeEditorLayoutStackControls *self,
+                                           IdeEditorView                *view)
+{
+  g_return_if_fail (IDE_IS_EDITOR_LAYOUT_STACK_CONTROLS (self));
+  g_return_if_fail (!view || IDE_IS_EDITOR_VIEW (view));
+
+  if (self->view == view)
+    return;
+
+  egg_binding_group_set_source (self->document_bindings, NULL);
+  egg_signal_group_set_target (self->document_signals, NULL);
+
+  if (self->view != NULL)
+    {
+      g_signal_handlers_disconnect_by_func (self->view,
+                                            G_CALLBACK (gtk_widget_destroyed),
+                                            &self->view);
+      self->view = NULL;
+    }
+
+  if (view != NULL)
+    {
+      self->view = view;
+      g_signal_connect (view,
+                        "destroy",
+                        G_CALLBACK (gtk_widget_destroyed),
+                        &self->view);
+      egg_binding_group_set_source (self->document_bindings, view->document);
+      egg_signal_group_set_target (self->document_signals, view->document);
+    }
+}
diff --git a/libide/editor/ide-editor-layout-stack-controls.h 
b/libide/editor/ide-editor-layout-stack-controls.h
new file mode 100644
index 0000000..935e5f5
--- /dev/null
+++ b/libide/editor/ide-editor-layout-stack-controls.h
@@ -0,0 +1,37 @@
+/* ide-editor-layout-stack-controls.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_EDITOR_LAYOUT_STACK_CONTROLS_H
+#define IDE_EDITOR_LAYOUT_STACK_CONTROLS_H
+
+#include <gtk/gtk.h>
+
+#include "editor/ide-editor-view.h"
+
+G_BEGIN_DECLS
+
+#define IDE_TYPE_EDITOR_LAYOUT_STACK_CONTROLS (ide_editor_layout_stack_controls_get_type())
+
+G_DECLARE_FINAL_TYPE (IdeEditorLayoutStackControls, ide_editor_layout_stack_controls, IDE, 
EDITOR_LAYOUT_STACK_CONTROLS, GtkBox)
+
+void ide_editor_layout_stack_controls_set_view (IdeEditorLayoutStackControls *self,
+                                                IdeEditorView                *view);
+
+G_END_DECLS
+
+#endif /* IDE_EDITOR_LAYOUT_STACK_CONTROLS_H */
diff --git a/libide/editor/ide-editor-layout-stack-controls.ui 
b/libide/editor/ide-editor-layout-stack-controls.ui
new file mode 100644
index 0000000..8fe6828
--- /dev/null
+++ b/libide/editor/ide-editor-layout-stack-controls.ui
@@ -0,0 +1,117 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <template class="IdeEditorLayoutStackControls">
+    <property name="orientation">horizontal</property>
+    <child>
+      <object class="GtkButton" id="warning_button">
+        <property name="margin-start">6</property>
+        <property name="margin-end">6</property>
+        <property name="visible">false</property>
+        <child>
+          <object class="GtkImage">
+            <property name="icon-name">dialog-warning-symbolic</property>
+            <property name="visible">true</property>
+            <style>
+              <class name="dim-label"/>
+            </style>
+          </object>
+        </child>
+      </object>
+    </child>
+    <child>
+      <object class="GtkSeparator">
+        <property name="orientation">vertical</property>
+        <property name="visible">true</property>
+      </object>
+    </child>
+    <child>
+      <object class="GtkMenuButton">
+        <property name="popover">goto_line_popover</property>
+        <property name="focus-on-click">false</property>
+        <property name="tooltip-text" translatable="yes">Go to line number</property>
+        <property name="valign">baseline</property>
+        <property name="visible">true</property>
+        <child>
+          <object class="GtkBox">
+            <property name="margin-start">3</property>
+            <property name="margin-end">3</property>
+            <property name="valign">baseline</property>
+            <property name="visible">true</property>
+            <child type="center">
+              <object class="GtkLabel">
+                <property name="label">:</property>
+                <property name="visible">true</property>
+                <style>
+                  <class name="dim-label"/>
+                </style>
+              </object>
+            </child>
+            <child>
+              <object class="EggSimpleLabel" id="line_label">
+                <property name="label">1</property>
+                <property name="width-chars">3</property>
+                <property name="xalign">1.0</property>
+                <property name="valign">baseline</property>
+                <property name="visible">true</property>
+              </object>
+              <packing>
+                <property name="pack-type">start</property>
+              </packing>
+            </child>
+            <child>
+              <object class="EggSimpleLabel" id="column_label">
+                <property name="label">1</property>
+                <property name="width-chars">3</property>
+                <property name="xalign">0.0</property>
+                <property name="valign">baseline</property>
+                <property name="visible">true</property>
+              </object>
+              <packing>
+                <property name="position">1</property>
+                <property name="pack-type">end</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkLabel" id="range_label">
+                <property name="valign">baseline</property>
+                <style>
+                  <class name="dim-label"/>
+                </style>
+              </object>
+              <packing>
+                <property name="position">0</property>
+                <property name="pack-type">end</property>
+              </packing>
+            </child>
+          </object>
+        </child>
+      </object>
+    </child>
+    <child>
+      <object class="GtkSeparator">
+        <property name="orientation">vertical</property>
+        <property name="visible">true</property>
+      </object>
+    </child>
+    <child>
+      <object class="GtkMenuButton" id="tweak_button">
+        <property name="focus-on-click">false</property>
+        <property name="popover">tweak_popover</property>
+        <property name="tooltip-text" translatable="yes">Change editor settings and language</property>
+        <property name="visible">true</property>
+      </object>
+    </child>
+  </template>
+  <object class="GtkPopover" id="tweak_popover">
+    <child>
+      <object class="IdeEditorTweakWidget" id="tweak_widget">
+        <property name="border-width">12</property>
+        <property name="visible">true</property>
+      </object>
+    </child>
+  </object>
+  <object class="EggSimplePopover" id="goto_line_popover">
+    <property name="title" translatable="yes">Go to Line</property>
+    <property name="button-text" translatable="yes">Go</property>
+  </object>
+</interface>
diff --git a/libide/editor/ide-editor-plugin.c b/libide/editor/ide-editor-plugin.c
index d678f6e..e47b6d8 100644
--- a/libide/editor/ide-editor-plugin.c
+++ b/libide/editor/ide-editor-plugin.c
@@ -21,7 +21,7 @@
 #include <libpeas/peas.h>
 
 #include "editor/ide-editor-workbench-addin.h"
-#include "workbench/ide-workbench-addin.h"
+#include "editor/ide-editor-layout-stack-addin.h"
 
 void
 ide_editor_register_types (PeasObjectModule *module)
@@ -29,4 +29,7 @@ ide_editor_register_types (PeasObjectModule *module)
   peas_object_module_register_extension_type (module,
                                               IDE_TYPE_WORKBENCH_ADDIN,
                                               IDE_TYPE_EDITOR_WORKBENCH_ADDIN);
+  peas_object_module_register_extension_type (module,
+                                              IDE_TYPE_LAYOUT_STACK_ADDIN,
+                                              IDE_TYPE_EDITOR_LAYOUT_STACK_ADDIN);
 }
diff --git a/libide/editor/ide-editor-view-actions.c b/libide/editor/ide-editor-view-actions.c
index c80fcf9..e7447eb 100644
--- a/libide/editor/ide-editor-view-actions.c
+++ b/libide/editor/ide-editor-view-actions.c
@@ -674,7 +674,8 @@ ide_editor_view_actions_goto_line (GSimpleAction *action,
 
   g_assert (IDE_IS_EDITOR_VIEW (self));
 
-  gtk_widget_activate (GTK_WIDGET (self->goto_line_button));
+  /* TODO: Reimplement goto as action from layoutstack */
+  //gtk_widget_activate (GTK_WIDGET (self->goto_line_button));
 }
 
 static GActionEntry IdeEditorViewActions[] = {
diff --git a/libide/editor/ide-editor-view-private.h b/libide/editor/ide-editor-view-private.h
index 63f6bfc..1046b72 100644
--- a/libide/editor/ide-editor-view-private.h
+++ b/libide/editor/ide-editor-view-private.h
@@ -40,9 +40,6 @@ struct _IdeEditorView
   GSettings            *settings;
   gchar                *title;
 
-  EggSimpleLabel       *line_label;
-  EggSimpleLabel       *column_label;
-  GtkLabel             *range_label;
   IdeEditorFrame       *frame1;
   IdeEditorFrame       *frame2;
   IdeEditorFrame       *last_focused_frame;
@@ -50,12 +47,6 @@ struct _IdeEditorView
   GtkRevealer          *modified_revealer;
   GtkPaned             *paned;
   GtkProgressBar       *progress_bar;
-  GtkMenuButton        *tweak_button;
-  GtkPopover           *tweak_popover;
-  IdeEditorTweakWidget *tweak_widget;
-  GtkMenuButton        *goto_line_button;
-  EggSimplePopover     *goto_line_popover;
-  GtkButton            *warning_button;
 };
 
 G_END_DECLS
diff --git a/libide/editor/ide-editor-view.c b/libide/editor/ide-editor-view.c
index 23257cd..fdea589 100644
--- a/libide/editor/ide-editor-view.c
+++ b/libide/editor/ide-editor-view.c
@@ -97,24 +97,6 @@ ide_editor_view_navigate_to (IdeLayoutView     *view,
 }
 
 static gboolean
-language_to_string (GBinding     *binding,
-                    const GValue *from_value,
-                    GValue       *to_value,
-                    gpointer      user_data)
-{
-  GtkSourceLanguage *language;
-
-  language = g_value_get_object (from_value);
-
-  if (language != NULL)
-    g_value_set_string (to_value, gtk_source_language_get_name (language));
-  else
-    g_value_set_string (to_value, _("Plain Text"));
-
-  return TRUE;
-}
-
-static gboolean
 ide_editor_view_get_modified (IdeLayoutView *view)
 {
   IdeEditorView *self = (IdeEditorView *)view;
@@ -288,53 +270,6 @@ ide_editor_view__buffer_notify_language (IdeEditorView *self,
 }
 
 static void
-ide_editor_view__buffer_cursor_moved (IdeEditorView     *self,
-                                      const GtkTextIter *iter,
-                                      GtkTextBuffer     *buffer)
-{
-  GtkTextIter bounds;
-  GtkTextMark *mark;
-  gchar str[32];
-  guint line;
-  gint column;
-  gint column2;
-
-  g_assert (IDE_IS_EDITOR_VIEW (self));
-  g_assert (iter != NULL);
-  g_assert (IDE_IS_BUFFER (buffer));
-
-  ide_source_view_get_visual_position (self->frame1->source_view, &line, (guint *)&column);
-
-  mark = gtk_text_buffer_get_selection_bound (buffer);
-  gtk_text_buffer_get_iter_at_mark (buffer, &bounds, mark);
-
-  g_snprintf (str, sizeof str, "%d", line + 1);
-  egg_simple_label_set_label (self->line_label, str);
-
-  g_snprintf (str, sizeof str, "%d", column + 1);
-  egg_simple_label_set_label (self->column_label, str);
-
-  if (!gtk_widget_has_focus (GTK_WIDGET (self->frame1->source_view)) ||
-      gtk_text_iter_equal (&bounds, iter) ||
-      (gtk_text_iter_get_line (iter) != gtk_text_iter_get_line (&bounds)))
-    {
-      gtk_widget_set_visible (GTK_WIDGET (self->range_label), FALSE);
-      return;
-    }
-
-  /* We have a selection that is on the same line.
-   * Lets give some detail as to how long the selection is.
-   */
-  column2 = gtk_source_view_get_visual_column (
-      GTK_SOURCE_VIEW (self->frame1->source_view),
-      &bounds);
-
-  g_snprintf (str, sizeof str, "%d", ABS (column2 - column));
-  gtk_label_set_label (self->range_label, str);
-  gtk_widget_set_visible (GTK_WIDGET (self->range_label), TRUE);
-}
-
-static void
 ide_editor_view_set_document (IdeEditorView *self,
                               IdeBuffer     *document)
 {
@@ -357,16 +292,6 @@ ide_editor_view_set_document (IdeEditorView *self,
                        G_SETTINGS_BIND_GET);
 
       g_signal_connect_object (document,
-                               "cursor-moved",
-                               G_CALLBACK (ide_editor_view__buffer_cursor_moved),
-                               self,
-                               G_CONNECT_SWAPPED);
-
-      g_object_bind_property_full (document, "language", self->tweak_button,
-                                   "label", G_BINDING_SYNC_CREATE,
-                                   language_to_string, NULL, NULL, NULL);
-
-      g_signal_connect_object (document,
                                "modified-changed",
                                G_CALLBACK (ide_editor_view__buffer_modified_changed),
                                self,
@@ -392,10 +317,6 @@ ide_editor_view_set_document (IdeEditorView *self,
 
       g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_DOCUMENT]);
 
-      g_object_bind_property (document, "has-diagnostics",
-                              self->warning_button, "visible",
-                              G_BINDING_SYNC_CREATE);
-
       ide_editor_view__buffer_notify_language (self, NULL, document);
       ide_editor_view__buffer_notify_title (self, NULL, IDE_BUFFER (document));
 
@@ -604,97 +525,6 @@ ide_editor_view_get_preferred_height (GtkWidget *widget,
 }
 
 static void
-ide_editor_view_goto_line_activate (IdeEditorView    *self,
-                                    const gchar      *text,
-                                    EggSimplePopover *popover)
-{
-  gint64 value;
-
-  g_assert (IDE_IS_EDITOR_VIEW (self));
-  g_assert (EGG_IS_SIMPLE_POPOVER (popover));
-
-  if (!ide_str_empty0 (text))
-    {
-      value = g_ascii_strtoll (text, NULL, 10);
-
-      if ((value > 0) && (value < G_MAXINT))
-        {
-          GtkTextIter iter;
-          GtkTextBuffer *buffer = GTK_TEXT_BUFFER (self->document);
-
-          gtk_widget_grab_focus (GTK_WIDGET (self->frame1->source_view));
-          gtk_text_buffer_get_iter_at_line (buffer, &iter, value - 1);
-          gtk_text_buffer_select_range (buffer, &iter, &iter);
-          ide_source_view_scroll_to_iter (self->frame1->source_view,
-                                          &iter, 0.25, TRUE, 1.0, 0.5, TRUE);
-        }
-    }
-}
-
-static gboolean
-ide_editor_view_goto_line_insert_text (IdeEditorView    *self,
-                                       guint             position,
-                                       const gchar      *chars,
-                                       guint             n_chars,
-                                       EggSimplePopover *popover)
-{
-  g_assert (IDE_IS_EDITOR_VIEW (self));
-  g_assert (EGG_IS_SIMPLE_POPOVER (popover));
-  g_assert (chars != NULL);
-
-  for (; *chars; chars = g_utf8_next_char (chars))
-    {
-      if (!g_unichar_isdigit (g_utf8_get_char (chars)))
-        return GDK_EVENT_STOP;
-    }
-
-  return GDK_EVENT_PROPAGATE;
-}
-
-static void
-ide_editor_view_goto_line_changed (IdeEditorView    *self,
-                                   EggSimplePopover *popover)
-{
-  gchar *message;
-  const gchar *text;
-  GtkTextIter begin;
-  GtkTextIter end;
-
-  g_assert (IDE_IS_EDITOR_VIEW (self));
-  g_assert (EGG_IS_SIMPLE_POPOVER (popover));
-
-  text = egg_simple_popover_get_text (popover);
-
-  gtk_text_buffer_get_bounds (GTK_TEXT_BUFFER (self->document), &begin, &end);
-
-  if (!ide_str_empty0 (text))
-    {
-      gint64 value;
-
-      value = g_ascii_strtoll (text, NULL, 10);
-
-      if (value > 0)
-        {
-          if (value <= gtk_text_iter_get_line (&end) + 1)
-            {
-              egg_simple_popover_set_message (popover, NULL);
-              egg_simple_popover_set_ready (popover, TRUE);
-              return;
-            }
-
-        }
-    }
-
-  /* translators: the user selected a number outside the value range for the document. */
-  message = g_strdup_printf (_("Provide a number between 1 and %u"),
-                             gtk_text_iter_get_line (&end) + 1);
-  egg_simple_popover_set_message (popover, message);
-  egg_simple_popover_set_ready (popover, FALSE);
-
-  g_free (message);
-}
-
-static void
 ide_editor_view__extension_added (PeasExtensionSet *set,
                                   PeasPluginInfo   *info,
                                   PeasExtension    *exten,
@@ -744,20 +574,6 @@ ide_editor_view__extension_removed (PeasExtensionSet *set,
 }
 
 static void
-ide_editor_view_warning_button_clicked (IdeEditorView *self,
-                                        GtkButton     *button)
-{
-  IdeEditorFrame *frame;
-
-  g_assert (IDE_IS_EDITOR_VIEW (self));
-  g_assert (GTK_IS_BUTTON (button));
-
-  frame = ide_editor_view_get_last_focused (self);
-  gtk_widget_grab_focus (GTK_WIDGET (frame));
-  g_signal_emit_by_name (frame->source_view, "move-error", GTK_DIR_DOWN);
-}
-
-static void
 ide_editor_view_load_addins (IdeEditorView *self)
 {
   PeasEngine *engine;
@@ -978,19 +794,11 @@ ide_editor_view_class_init (IdeEditorViewClass *klass)
 
   gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/builder/ui/ide-editor-view.ui");
 
-  gtk_widget_class_bind_template_child (widget_class, IdeEditorView, column_label);
   gtk_widget_class_bind_template_child (widget_class, IdeEditorView, frame1);
-  gtk_widget_class_bind_template_child (widget_class, IdeEditorView, goto_line_button);
-  gtk_widget_class_bind_template_child (widget_class, IdeEditorView, goto_line_popover);
-  gtk_widget_class_bind_template_child (widget_class, IdeEditorView, line_label);
   gtk_widget_class_bind_template_child (widget_class, IdeEditorView, modified_cancel_button);
   gtk_widget_class_bind_template_child (widget_class, IdeEditorView, modified_revealer);
   gtk_widget_class_bind_template_child (widget_class, IdeEditorView, paned);
   gtk_widget_class_bind_template_child (widget_class, IdeEditorView, progress_bar);
-  gtk_widget_class_bind_template_child (widget_class, IdeEditorView, range_label);
-  gtk_widget_class_bind_template_child (widget_class, IdeEditorView, tweak_button);
-  gtk_widget_class_bind_template_child (widget_class, IdeEditorView, tweak_widget);
-  gtk_widget_class_bind_template_child (widget_class, IdeEditorView, warning_button);
 
   g_type_ensure (IDE_TYPE_EDITOR_FRAME);
   g_type_ensure (IDE_TYPE_EDITOR_TWEAK_WIDGET);
@@ -1033,30 +841,6 @@ ide_editor_view_init (IdeEditorView *self)
                            G_CALLBACK (ide_editor_view__focus_in_event),
                            self,
                            G_CONNECT_SWAPPED);
-
-  g_signal_connect_object (self->goto_line_popover,
-                           "activate",
-                           G_CALLBACK (ide_editor_view_goto_line_activate),
-                           self,
-                           G_CONNECT_SWAPPED);
-
-  g_signal_connect_object (self->goto_line_popover,
-                           "insert-text",
-                           G_CALLBACK (ide_editor_view_goto_line_insert_text),
-                           self,
-                           G_CONNECT_SWAPPED);
-
-  g_signal_connect_object (self->goto_line_popover,
-                           "changed",
-                           G_CALLBACK (ide_editor_view_goto_line_changed),
-                           self,
-                           G_CONNECT_SWAPPED);
-
-  g_signal_connect_object (self->warning_button,
-                           "clicked",
-                           G_CALLBACK (ide_editor_view_warning_button_clicked),
-                           self,
-                           G_CONNECT_SWAPPED);
 }
 
 /**
diff --git a/libide/editor/ide-editor-view.ui b/libide/editor/ide-editor-view.ui
index 1f6772b..3e93b4f 100644
--- a/libide/editor/ide-editor-view.ui
+++ b/libide/editor/ide-editor-view.ui
@@ -85,109 +85,6 @@
             </child>
           </object>
         </child>
-        <child internal-child="controls">
-          <object class="GtkBox">
-            <child>
-              <object class="GtkButton" id="warning_button">
-                <property name="margin-start">6</property>
-                <property name="margin-end">6</property>
-                <property name="visible">false</property>
-                <child>
-                  <object class="GtkImage">
-                    <property name="icon-name">dialog-warning-symbolic</property>
-                    <property name="visible">true</property>
-                    <style>
-                      <class name="dim-label"/>
-                    </style>
-                  </object>
-                </child>
-              </object>
-            </child>
-            <child>
-              <object class="GtkSeparator">
-                <property name="orientation">vertical</property>
-                <property name="visible">true</property>
-              </object>
-            </child>
-            <child>
-              <object class="GtkMenuButton" id="goto_line_button">
-                <property name="popover">goto_line_popover</property>
-                <property name="focus-on-click">false</property>
-                <property name="tooltip-text" translatable="yes">Go to line number</property>
-                <property name="valign">baseline</property>
-                <property name="visible">true</property>
-                <child>
-                  <object class="GtkBox">
-                    <property name="margin-start">3</property>
-                    <property name="margin-end">3</property>
-                    <property name="valign">baseline</property>
-                    <property name="visible">true</property>
-                    <child type="center">
-                      <object class="GtkLabel">
-                        <property name="label">:</property>
-                        <property name="visible">true</property>
-                        <style>
-                          <class name="dim-label"/>
-                        </style>
-                      </object>
-                    </child>
-                    <child>
-                      <object class="EggSimpleLabel" id="line_label">
-                        <property name="label">1</property>
-                        <property name="width-chars">3</property>
-                        <property name="xalign">1.0</property>
-                        <property name="valign">baseline</property>
-                        <property name="visible">true</property>
-                      </object>
-                      <packing>
-                        <property name="pack-type">start</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="EggSimpleLabel" id="column_label">
-                        <property name="label">1</property>
-                        <property name="width-chars">3</property>
-                        <property name="xalign">0.0</property>
-                        <property name="valign">baseline</property>
-                        <property name="visible">true</property>
-                      </object>
-                      <packing>
-                        <property name="position">1</property>
-                        <property name="pack-type">end</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkLabel" id="range_label">
-                        <property name="valign">baseline</property>
-                        <style>
-                          <class name="dim-label"/>
-                        </style>
-                      </object>
-                      <packing>
-                        <property name="position">0</property>
-                        <property name="pack-type">end</property>
-                      </packing>
-                    </child>
-                  </object>
-                </child>
-              </object>
-            </child>
-            <child>
-              <object class="GtkSeparator">
-                <property name="orientation">vertical</property>
-                <property name="visible">true</property>
-              </object>
-            </child>
-            <child>
-              <object class="GtkMenuButton" id="tweak_button">
-                <property name="focus-on-click">false</property>
-                <property name="popover">tweak_popover</property>
-                <property name="tooltip-text" translatable="yes">Change editor settings and 
language</property>
-                <property name="visible">true</property>
-              </object>
-            </child>
-          </object>
-        </child>
       </object>
     </child>
   </template>
diff --git a/libide/resources/libide.gresource.xml b/libide/resources/libide.gresource.xml
index b0ea3ae..63254ca 100644
--- a/libide/resources/libide.gresource.xml
+++ b/libide/resources/libide.gresource.xml
@@ -50,8 +50,9 @@
   </gresource>
 
   <gresource prefix="/org/gnome/builder/ui">
-    <file compressed="true" alias="ide-editor-perspective.ui">../editor/ide-editor-perspective.ui</file>
     <file compressed="true" alias="ide-editor-frame.ui">../editor/ide-editor-frame.ui</file>
+    <file compressed="true" 
alias="ide-editor-layout-stack-controls.ui">../editor/ide-editor-layout-stack-controls.ui</file>
+    <file compressed="true" alias="ide-editor-perspective.ui">../editor/ide-editor-perspective.ui</file>
     <file compressed="true" alias="ide-editor-tweak-widget.ui">../editor/ide-editor-tweak-widget.ui</file>
     <file compressed="true" alias="ide-editor-view.ui">../editor/ide-editor-view.ui</file>
     <file compressed="true" alias="ide-greeter-perspective.ui">../greeter/ide-greeter-perspective.ui</file>



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