[gnome-builder] libide: start on editor as an embedded plugin



commit c3d0fb557e88a257101f6014577f7b85326402b6
Author: Christian Hergert <christian hergert me>
Date:   Mon Nov 16 16:28:17 2015 -0800

    libide: start on editor as an embedded plugin
    
    We still need some features in libpeas to complete this, but this will
    start hooking the file loading into the editor using the IdeWorkbenchAddin
    abstraction.

 libide/Makefile.am                         |    2 +
 libide/editor/ide-editor-perspective.c     |  124 +++++++++++++++
 libide/editor/ide-editor-view-actions.c    |    4 +-
 libide/editor/ide-editor-view.c            |    8 +
 libide/editor/ide-editor-view.h            |    3 +
 libide/editor/ide-editor-workbench-addin.c |  225 ++++++++++++++++++++++++++++
 libide/editor/ide-editor-workbench-addin.h |   32 ++++
 libide/ide-buffer-manager.h                |    1 +
 8 files changed, 398 insertions(+), 1 deletions(-)
---
diff --git a/libide/Makefile.am b/libide/Makefile.am
index 842edca..7a357e2 100644
--- a/libide/Makefile.am
+++ b/libide/Makefile.am
@@ -246,6 +246,8 @@ libide_1_0_la_SOURCES = \
        editor/ide-editor-view-actions.h \
        editor/ide-editor-view-addin-private.h \
        editor/ide-editor-view-private.h \
+       editor/ide-editor-workbench-addin.c \
+       editor/ide-editor-workbench-addin.h \
        gconstructor.h \
        git/ide-git-buffer-change-monitor.c \
        git/ide-git-buffer-change-monitor.h \
diff --git a/libide/editor/ide-editor-perspective.c b/libide/editor/ide-editor-perspective.c
index 9b4fb6f..aad9de7 100644
--- a/libide/editor/ide-editor-perspective.c
+++ b/libide/editor/ide-editor-perspective.c
@@ -20,14 +20,26 @@
 
 #include <glib/gi18n.h>
 
+#include "egg-signal-group.h"
+
+#include "ide-buffer.h"
+#include "ide-buffer-manager.h"
+#include "ide-context.h"
+#include "ide-debug.h"
 #include "ide-editor-perspective.h"
+#include "ide-editor-view.h"
+#include "ide-gtk.h"
+#include "ide-layout-grid.h"
 #include "ide-workbench-header-bar.h"
 
 struct _IdeEditorPerspective
 {
   IdeLayout              parent_instance;
 
+  IdeLayoutGrid         *grid;
   IdeWorkbenchHeaderBar *titlebar;
+
+  EggSignalGroup        *buffer_manager_signals;
 };
 
 static void ide_perspective_iface_init (IdePerspectiveInterface *iface);
@@ -80,8 +92,101 @@ ide_editor_perspective_restore_panel_state (IdeEditorPerspective *self)
 }
 
 static void
+ide_editor_perspective_context_set (GtkWidget  *widget,
+                                    IdeContext *context)
+{
+  IdeEditorPerspective *self = (IdeEditorPerspective *)widget;
+  IdeBufferManager *buffer_manager = NULL;
+
+  g_assert (IDE_IS_EDITOR_PERSPECTIVE (self));
+  g_assert (!context || IDE_IS_CONTEXT (context));
+
+  if (context != NULL)
+    buffer_manager = ide_context_get_buffer_manager (context);
+
+  egg_signal_group_set_target (self->buffer_manager_signals, buffer_manager);
+}
+
+static void
+ide_editor_perspective_load_buffer (IdeEditorPerspective *self,
+                                    IdeBuffer            *buffer,
+                                    IdeBufferManager     *buffer_manager)
+{
+  IdeEditorView *view;
+  GtkWidget *stack;
+
+  g_assert (IDE_IS_EDITOR_PERSPECTIVE (self));
+  g_assert (IDE_IS_BUFFER (buffer));
+  g_assert (IDE_IS_BUFFER_MANAGER (buffer_manager));
+
+  IDE_TRACE_MSG ("Loading %s", ide_buffer_get_title (buffer));
+
+  view = g_object_new (IDE_TYPE_EDITOR_VIEW,
+                       "document", buffer,
+                       "visible", TRUE,
+                       NULL);
+
+  stack = ide_layout_grid_get_last_focus (self->grid);
+
+  gtk_container_add (GTK_CONTAINER (stack), GTK_WIDGET (view));
+}
+
+static void
+ide_editor_perspective_locate_buffer (GtkWidget *view,
+                                      gpointer   user_data)
+{
+  IdeBuffer **buffer = user_data;
+
+  g_assert (IDE_IS_LAYOUT_VIEW (view));
+  g_assert (buffer != NULL);
+  g_assert (!*buffer || IDE_IS_BUFFER (*buffer));
+
+  if (!*buffer)
+    return;
+
+  if (IDE_IS_EDITOR_VIEW (view))
+    {
+      if (*buffer == ide_editor_view_get_document (IDE_EDITOR_VIEW (view)))
+        {
+          GtkWidget *stack;
+
+          stack = gtk_widget_get_ancestor (view, IDE_TYPE_LAYOUT_STACK);
+
+          if (stack != NULL)
+            {
+              ide_layout_stack_set_active_view (IDE_LAYOUT_STACK (stack), view);
+              *buffer = NULL;
+            }
+        }
+    }
+}
+
+static void
+ide_editor_perspective_focus_buffer (IdeEditorPerspective *self,
+                                     GParamSpec           *pspec,
+                                     IdeBufferManager     *buffer_manager)
+{
+  IdeBuffer *buffer;
+
+  g_assert (IDE_IS_EDITOR_PERSPECTIVE (self));
+  g_assert (IDE_IS_BUFFER_MANAGER (buffer_manager));
+
+  buffer = ide_buffer_manager_get_focus_buffer (buffer_manager);
+  if (buffer == NULL)
+    return;
+
+  ide_layout_grid_foreach_view (self->grid,
+                                ide_editor_perspective_locate_buffer,
+                                &buffer);
+}
+
+static void
 ide_editor_perspective_finalize (GObject *object)
 {
+  IdeEditorPerspective *self = (IdeEditorPerspective *)object;
+
+  g_clear_object (&self->buffer_manager_signals);
+
   G_OBJECT_CLASS (ide_editor_perspective_parent_class)->finalize (object);
 }
 
@@ -121,7 +226,9 @@ ide_editor_perspective_class_init (IdeEditorPerspectiveClass *klass)
   object_class->get_property = ide_editor_perspective_get_property;
   object_class->set_property = ide_editor_perspective_set_property;
 
+  gtk_widget_class_set_css_name (widget_class, "editorperspective");
   gtk_widget_class_set_template_from_resource (widget_class, 
"/org/gnome/builder/ui/ide-editor-perspective.ui");
+  gtk_widget_class_bind_template_child (widget_class, IdeEditorPerspective, grid);
   gtk_widget_class_bind_template_child (widget_class, IdeEditorPerspective, titlebar);
 }
 
@@ -130,12 +237,29 @@ ide_editor_perspective_init (IdeEditorPerspective *self)
 {
   GActionGroup *actions;
 
+  self->buffer_manager_signals = egg_signal_group_new (IDE_TYPE_BUFFER_MANAGER);
+
+  egg_signal_group_connect_object (self->buffer_manager_signals,
+                                   "load-buffer",
+                                   G_CALLBACK (ide_editor_perspective_load_buffer),
+                                   self,
+                                   G_CONNECT_SWAPPED);
+
+  egg_signal_group_connect_object (self->buffer_manager_signals,
+                                   "notify::focus-buffer",
+                                   G_CALLBACK (ide_editor_perspective_focus_buffer),
+                                   self,
+                                   G_CONNECT_SWAPPED);
+
   gtk_widget_init_template (GTK_WIDGET (self));
 
   actions = gtk_widget_get_action_group (GTK_WIDGET (self), "panels");
   gtk_widget_insert_action_group (GTK_WIDGET (self->titlebar), "panels", actions);
 
   ide_editor_perspective_restore_panel_state (self);
+
+  ide_widget_set_context_handler (GTK_WIDGET (self),
+                                  ide_editor_perspective_context_set);
 }
 
 static gchar *
diff --git a/libide/editor/ide-editor-view-actions.c b/libide/editor/ide-editor-view-actions.c
index 8604215..e382d09 100644
--- a/libide/editor/ide-editor-view-actions.c
+++ b/libide/editor/ide-editor-view-actions.c
@@ -659,18 +659,20 @@ ide_editor_view_actions_reveal (GSimpleAction *action,
                                 gpointer       user_data)
 {
   IdeEditorView *self = user_data;
+#if 0
   IdeWorkbench *workbench;
   IdeFile *file;
   GFile *gfile;
+#endif
 
   g_assert (G_IS_SIMPLE_ACTION (action));
   g_assert (IDE_IS_EDITOR_VIEW (self));
 
+#if 0
   file = ide_buffer_get_file (IDE_BUFFER (self->document));
   gfile = ide_file_get_file (file);
   workbench = ide_widget_get_workbench (GTK_WIDGET (self));
 
-#if 0
   gb_workbench_reveal_file (workbench, gfile);
 #endif
 }
diff --git a/libide/editor/ide-editor-view.c b/libide/editor/ide-editor-view.c
index 64ac974..4e4e153 100644
--- a/libide/editor/ide-editor-view.c
+++ b/libide/editor/ide-editor-view.c
@@ -930,3 +930,11 @@ ide_editor_view_init (IdeEditorView *self)
                            self,
                            G_CONNECT_SWAPPED);
 }
+
+IdeBuffer *
+ide_editor_view_get_document (IdeEditorView *self)
+{
+  g_return_val_if_fail (IDE_IS_EDITOR_VIEW (self), NULL);
+
+  return self->document;
+}
diff --git a/libide/editor/ide-editor-view.h b/libide/editor/ide-editor-view.h
index e7dba5b..353390b 100644
--- a/libide/editor/ide-editor-view.h
+++ b/libide/editor/ide-editor-view.h
@@ -19,6 +19,7 @@
 #ifndef IDE_EDITOR_VIEW_H
 #define IDE_EDITOR_VIEW_H
 
+#include "ide-buffer.h"
 #include "ide-layout-view.h"
 
 G_BEGIN_DECLS
@@ -27,6 +28,8 @@ G_BEGIN_DECLS
 
 G_DECLARE_FINAL_TYPE (IdeEditorView, ide_editor_view, IDE, EDITOR_VIEW, IdeLayoutView)
 
+IdeBuffer *ide_editor_view_get_document (IdeEditorView *self);
+
 G_END_DECLS
 
 #endif /* IDE_EDITOR_VIEW_H */
diff --git a/libide/editor/ide-editor-workbench-addin.c b/libide/editor/ide-editor-workbench-addin.c
new file mode 100644
index 0000000..0de3809
--- /dev/null
+++ b/libide/editor/ide-editor-workbench-addin.c
@@ -0,0 +1,225 @@
+/* ide-editor-workbench-addin.c
+ *
+ * Copyright (C) 2015 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
+ * 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-workbench-addin"
+
+#include <gtksourceview/gtksource.h>
+
+#include "ide-buffer.h"
+#include "ide-buffer-manager.h"
+#include "ide-context.h"
+#include "ide-editor-perspective.h"
+#include "ide-editor-workbench-addin.h"
+
+struct _IdeEditorWorkbenchAddin
+{
+  GObject               parent_instance;
+  IdeEditorPerspective *perspective;
+  IdeWorkbench         *workbench;
+};
+
+static void ide_workbench_addin_iface_init (IdeWorkbenchAddinInterface *iface);
+
+G_DEFINE_TYPE_EXTENDED (IdeEditorWorkbenchAddin, ide_editor_workbench_addin, G_TYPE_OBJECT, 0,
+                        G_IMPLEMENT_INTERFACE (IDE_TYPE_WORKBENCH_ADDIN,
+                                               ide_workbench_addin_iface_init))
+
+static void
+ide_editor_workbench_addin_class_init (IdeEditorWorkbenchAddinClass *klass)
+{
+}
+
+static void
+ide_editor_workbench_addin_init (IdeEditorWorkbenchAddin *addin)
+{
+}
+
+static void
+ide_editor_workbench_addin_load (IdeWorkbenchAddin *addin,
+                                 IdeWorkbench      *workbench)
+{
+  IdeEditorWorkbenchAddin *self = (IdeEditorWorkbenchAddin *)addin;
+
+  g_assert (IDE_IS_EDITOR_WORKBENCH_ADDIN (self));
+  g_assert (IDE_IS_WORKBENCH (workbench));
+
+  self->workbench = workbench;
+
+  self->perspective = g_object_new (IDE_TYPE_EDITOR_PERSPECTIVE,
+                                    "visible", TRUE,
+                                    NULL);
+  ide_workbench_add_perspective (workbench, IDE_PERSPECTIVE (self->perspective));
+}
+
+static void
+ide_editor_workbench_addin_unload (IdeWorkbenchAddin *addin,
+                                   IdeWorkbench      *workbench)
+{
+  IdeEditorWorkbenchAddin *self = (IdeEditorWorkbenchAddin *)addin;
+  IdePerspective *perspective;
+
+  g_assert (IDE_IS_EDITOR_WORKBENCH_ADDIN (self));
+  g_assert (IDE_IS_WORKBENCH (workbench));
+
+  perspective = IDE_PERSPECTIVE (self->perspective);
+  self->perspective = NULL;
+
+  self->workbench = NULL;
+
+  ide_workbench_remove_perspective (workbench, perspective);
+}
+
+static gboolean
+ide_editor_workbench_addin_can_open (IdeWorkbenchAddin *addin,
+                                     IdeUri            *uri,
+                                     const gchar       *content_type,
+                                     gint              *priority)
+{
+  const gchar *path;
+
+  g_assert (IDE_IS_EDITOR_WORKBENCH_ADDIN (addin));
+  g_assert (uri != NULL);
+  g_assert (priority != NULL);
+
+  *priority = 0;
+
+  path = ide_uri_get_path (uri);
+
+  if ((path != NULL) || (content_type != NULL))
+    {
+      GtkSourceLanguageManager *manager;
+      GtkSourceLanguage *language;
+
+      manager = gtk_source_language_manager_get_default ();
+      language = gtk_source_language_manager_guess_language (manager, path, content_type);
+
+      if (language != NULL)
+        return TRUE;
+    }
+
+  if (content_type != NULL)
+    {
+      gchar *text_type;
+      gboolean ret;
+
+      text_type = g_content_type_from_mime_type ("text/plain");
+      ret = g_content_type_is_a (content_type, text_type);
+      g_free (text_type);
+
+      return ret;
+    }
+
+  return FALSE;
+}
+
+static void
+ide_editor_workbench_addin_open_cb (GObject      *object,
+                                    GAsyncResult *result,
+                                    gpointer      user_data)
+{
+  IdeBufferManager *buffer_manager = (IdeBufferManager *)object;
+  g_autoptr(IdeBuffer) buffer = NULL;
+  g_autoptr(GTask) task = NULL;
+  GError *error = NULL;
+
+  g_assert (IDE_IS_BUFFER_MANAGER (buffer_manager));
+  g_assert (G_IS_TASK (task));
+
+  buffer = ide_buffer_manager_load_file_finish (buffer_manager, result, &error);
+
+  if (buffer == NULL)
+    g_task_return_error (task, error);
+  else
+    g_task_return_boolean (task, TRUE);
+}
+
+static void
+ide_editor_workbench_addin_open_async (IdeWorkbenchAddin   *addin,
+                                       IdeUri              *uri,
+                                       const gchar         *content_type,
+                                       GCancellable        *cancellable,
+                                       GAsyncReadyCallback  callback,
+                                       gpointer             user_data)
+{
+  IdeEditorWorkbenchAddin *self = (IdeEditorWorkbenchAddin *)addin;
+  IdeBufferManager *buffer_manager;
+  IdeContext *context;
+  g_autoptr(GTask) task = NULL;
+  g_autoptr(IdeFile) ifile = NULL;
+  g_autoptr(GFile) gfile = NULL;
+
+  g_assert (IDE_IS_EDITOR_WORKBENCH_ADDIN (self));
+  g_assert (uri != NULL);
+  g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));
+  g_assert (IDE_IS_WORKBENCH (self->workbench));
+
+  task = g_task_new (self, cancellable, callback, user_data);
+
+  context = ide_workbench_get_context (self->workbench);
+  buffer_manager = ide_context_get_buffer_manager (context);
+
+  gfile = ide_uri_to_file (uri);
+
+  if (gfile == NULL)
+    {
+      gchar *uristr;
+
+      uristr = ide_uri_to_string (uri, IDE_URI_HIDE_AUTH_PARAMS);
+      g_task_return_new_error (task,
+                               G_IO_ERROR,
+                               G_IO_ERROR_INVALID_FILENAME,
+                               "Failed to create resource for \"%s\"",
+                               uristr);
+      g_free (uristr);
+      return;
+    }
+
+  ifile = g_object_new (IDE_TYPE_FILE,
+                        "context", context,
+                        "file", gfile,
+                        NULL);
+
+  ide_buffer_manager_load_file_async (buffer_manager,
+                                      ifile,
+                                      FALSE,
+                                      NULL,
+                                      cancellable,
+                                      ide_editor_workbench_addin_open_cb,
+                                      g_object_ref (task));
+}
+
+static gboolean
+ide_editor_workbench_addin_open_finish (IdeWorkbenchAddin  *addin,
+                                        GAsyncResult       *result,
+                                        GError            **error)
+{
+  g_assert (IDE_IS_EDITOR_WORKBENCH_ADDIN (addin));
+  g_assert (G_IS_TASK (result));
+
+  return g_task_propagate_boolean (G_TASK (result), error);
+}
+
+static void
+ide_workbench_addin_iface_init (IdeWorkbenchAddinInterface *iface)
+{
+  iface->load = ide_editor_workbench_addin_load;
+  iface->unload = ide_editor_workbench_addin_unload;
+  iface->can_open = ide_editor_workbench_addin_can_open;
+  iface->open_async = ide_editor_workbench_addin_open_async;
+  iface->open_finish = ide_editor_workbench_addin_open_finish;
+}
diff --git a/libide/editor/ide-editor-workbench-addin.h b/libide/editor/ide-editor-workbench-addin.h
new file mode 100644
index 0000000..1fba5e9
--- /dev/null
+++ b/libide/editor/ide-editor-workbench-addin.h
@@ -0,0 +1,32 @@
+/* ide-editor-workbench-addin.h
+ *
+ * Copyright (C) 2015 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
+ * 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_WORKBENCH_ADDIN_H
+#define IDE_EDITOR_WORKBENCH_ADDIN_H
+
+#include "ide-workbench-addin.h"
+
+G_BEGIN_DECLS
+
+#define IDE_TYPE_EDITOR_WORKBENCH_ADDIN (ide_editor_workbench_addin_get_type())
+
+G_DECLARE_FINAL_TYPE (IdeEditorWorkbenchAddin, ide_editor_workbench_addin, IDE, EDITOR_WORKBENCH_ADDIN, 
GObject)
+
+G_END_DECLS
+
+#endif /* IDE_EDITOR_WORKBENCH_ADDIN_H */
diff --git a/libide/ide-buffer-manager.h b/libide/ide-buffer-manager.h
index 04d8de1..009c7c2 100644
--- a/libide/ide-buffer-manager.h
+++ b/libide/ide-buffer-manager.h
@@ -22,6 +22,7 @@
 #include <gtk/gtk.h>
 #include <gtksourceview/completion-providers/words/gtksourcecompletionwords.h>
 
+#include "ide-file.h"
 #include "ide-object.h"
 
 G_BEGIN_DECLS


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