[gnome-builder/wip/chergert/perspective] libide: sketch out core objects for workbench
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-builder/wip/chergert/perspective] libide: sketch out core objects for workbench
- Date: Mon, 2 Nov 2015 02:40:17 +0000 (UTC)
commit 7f196f4bdb805f275edd28701c8747350b7d4471
Author: Christian Hergert <chergert redhat com>
Date: Sun Nov 1 18:39:59 2015 -0800
libide: sketch out core objects for workbench
Lots to think about, just some sketches.
data/ui/ide-workbench.ui | 27 +++
libide/Makefile.am | 16 ++
libide/ide-application.c | 107 +++++++++++
libide/ide-application.h | 58 ++++++
libide/ide-layout-manager.c | 72 ++++++++
libide/ide-layout-manager.h | 60 ++++++
libide/ide-perspective.c | 209 +++++++++++++++++++++
libide/ide-perspective.h | 59 ++++++
libide/ide-preferences-addin.c | 81 ++++++++
libide/ide-preferences-addin.h | 49 +++++
libide/ide-preferences.c | 116 ++++++++++++
libide/ide-preferences.h | 105 +++++++++++
libide/ide-view.c | 129 +++++++++++++
libide/ide-view.h | 61 ++++++
libide/ide-workbench-addin.c | 83 +++++++++
libide/ide-workbench-addin.h | 47 +++++
libide/ide-workbench.c | 322 +++++++++++++++++++++++++++++++++
libide/ide-workbench.h | 65 +++++++
libide/ide.h | 6 +
libide/resources/libide.gresource.xml | 2 +
20 files changed, 1674 insertions(+), 0 deletions(-)
---
diff --git a/data/ui/ide-workbench.ui b/data/ui/ide-workbench.ui
new file mode 100644
index 0000000..28b1d8c
--- /dev/null
+++ b/data/ui/ide-workbench.ui
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <!-- interface-requires gtk+ 3.15 -->
+ <template class="IdeWorkbench" parent="GtkApplicationWindow">
+ <property name="title" translatable="yes">Builder</property>
+ <child>
+ <object class="GtkBox">
+ <property name="orientation">horizontal</property>
+ <property name="homogeneous">false</property>
+ <property name="visible">true</property>
+ <child>
+ <object class="GtkStackSwitcher" id="perspectives_stack_switcher">
+ <property name="orientation">vertical</property>
+ <property name="stack">perspectives_stack</property>
+ <property name="visible">true</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkStack" id="perspectives_stack">
+ <property name="homogeneous">false</property>
+ <property name="visible">true</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </template>
+</interface>
diff --git a/libide/Makefile.am b/libide/Makefile.am
index 881f5ad..4dd716d 100644
--- a/libide/Makefile.am
+++ b/libide/Makefile.am
@@ -17,6 +17,8 @@ libide_1_0_la_public_sources = \
git/ide-git-remote-callbacks.h \
git/ide-git-vcs.c \
git/ide-git-vcs.h \
+ ide-application.c \
+ ide-application.h \
ide-back-forward-item.c \
ide-back-forward-item.h \
ide-back-forward-list.c \
@@ -86,9 +88,17 @@ libide_1_0_la_public_sources = \
ide-indent-style.h \
ide-indenter.c \
ide-indenter.h \
+ ide-layout-manager.c \
+ ide-layout-manager.h \
ide-log.c \
ide-log.h \
ide-macros.h \
+ ide-perspective.c \
+ ide-perspective.h \
+ ide-preferences.c \
+ ide-preferences.h \
+ ide-preferences-addin.c \
+ ide-preferences-addin.h \
ide-object.c \
ide-object.h \
ide-pattern-spec.c \
@@ -172,10 +182,16 @@ libide_1_0_la_public_sources = \
ide-unsaved-file.h \
ide-unsaved-files.c \
ide-unsaved-files.h \
+ ide-view.c \
+ ide-view.h \
ide-vcs-uri.c \
ide-vcs-uri.h \
ide-vcs.c \
ide-vcs.h \
+ ide-workbench.c \
+ ide-workbench.h \
+ ide-workbench-addin.c \
+ ide-workbench-addin.h \
ide-worker.c \
ide-worker.h \
ide.c \
diff --git a/libide/ide-application.c b/libide/ide-application.c
new file mode 100644
index 0000000..f692c38
--- /dev/null
+++ b/libide/ide-application.c
@@ -0,0 +1,107 @@
+/* ide-application.c
+ *
+ * Copyright (C) 2015 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-application"
+
+#include <glib/gi18n.h>
+
+#include "ide-application.h"
+#include "ide-worker-manager.h"
+
+struct _IdeApplication
+{
+ GtkApplication parent_instance;
+
+ GDateTime *startup_time;
+ IdeWorkerManager *worker_manager;
+};
+
+G_DEFINE_TYPE (IdeApplication, ide_application, GTK_TYPE_APPLICATION_WINDOW)
+
+static void
+ide_application_class_init (IdeApplicationClass *klass)
+{
+}
+
+static void
+ide_application_init (IdeApplication *self)
+{
+ self->startup_time = g_date_time_new_now_local ();
+}
+
+GDateTime *
+ide_application_get_startup_time (IdeApplication *self)
+{
+ g_return_val_if_fail (IDE_IS_APPLICATION (self), NULL);
+
+ return self->startup_time;
+}
+
+static void
+ide_application_get_worker_cb (GObject *object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ IdeWorkerManager *worker_manager = (IdeWorkerManager *)object;
+ GTask *task = user_data;
+ GError *error = NULL;
+ GDBusProxy *proxy;
+
+ g_assert (IDE_IS_WORKER_MANAGER (worker_manager));
+ g_assert (G_IS_TASK (task));
+
+ proxy = ide_worker_manager_get_worker_finish (worker_manager, result, &error);
+
+ if (proxy == NULL)
+ g_task_return_error (task, error);
+ else
+ g_task_return_pointer (task, proxy, g_object_unref);
+}
+
+void
+ide_application_get_worker_async (IdeApplication *self,
+ const gchar *plugin_name,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_autoptr(GTask) task = NULL;
+
+ g_return_if_fail (IDE_IS_APPLICATION (self));
+ g_return_if_fail (plugin_name != NULL);
+ g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable));
+
+ ide_worker_manager_get_worker_async (self->worker_manager,
+ plugin_name,
+ cancellable,
+ ide_application_get_worker_cb,
+ g_object_ref (task));
+}
+
+GDBusProxy *
+ide_application_get_worker_finish (IdeApplication *self,
+ GAsyncResult *result,
+ GError **error)
+{
+ GTask *task = (GTask *)result;
+
+ g_return_val_if_fail (IDE_IS_APPLICATION (self), NULL);
+ g_return_val_if_fail (G_IS_TASK (task), NULL);
+
+ return g_task_propagate_pointer (task, error);
+}
diff --git a/libide/ide-application.h b/libide/ide-application.h
new file mode 100644
index 0000000..91c60a7
--- /dev/null
+++ b/libide/ide-application.h
@@ -0,0 +1,58 @@
+/* ide-application.h
+ *
+ * Copyright (C) 2015 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_APPLICATION_H
+#define IDE_APPLICATION_H
+
+#include <gio/gio.h>
+#include <gtk/gtk.h>
+
+#define IDE_TYPE_APPLICATION (ide_application_get_type())
+#define IDE_APPLICATION_DEFAULT (IDE_APPLICATION(g_application_get_default()))
+
+G_DECLARE_FINAL_TYPE (IdeApplication, ide_application, IDE, APPLICATION, GtkApplication)
+
+GDateTime *ide_application_get_startup_time (IdeApplication *self);
+void ide_application_open_project_async (IdeApplication *self,
+ GFile *project_file,
+ GPtrArray *additional_files,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+gboolean ide_application_open_project_finish (IdeApplication *self,
+ GAsyncResult *result,
+ GError **error);
+void ide_application_open_files_async (IdeApplication *self,
+ GFile **files,
+ gint n_files,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+gboolean ide_application_open_files_finish (IdeApplication *self,
+ GAsyncResult *result,
+ GError **error);
+void ide_application_get_worker_async (IdeApplication *self,
+ const gchar *plugin_name,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+GDBusProxy *ide_application_get_worker_finish (IdeApplication *self,
+ GAsyncResult *result,
+ GError **error);
+
+#endif /* IDE_APPLICATION_H */
diff --git a/libide/ide-layout-manager.c b/libide/ide-layout-manager.c
new file mode 100644
index 0000000..ff37280
--- /dev/null
+++ b/libide/ide-layout-manager.c
@@ -0,0 +1,72 @@
+/* ide-layout-manager.c
+ *
+ * Copyright (C) 2015 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/>.
+ */
+
+#include "ide-layout-manager.h"
+
+G_DEFINE_INTERFACE (IdeLayoutManager, ide_layout_manager, G_TYPE_OBJECT)
+
+static void
+ide_layout_manager_default_init (IdeLayoutManagerInterface *iface)
+{
+}
+
+/**
+ * ide_layout_manager_add:
+ * @self: An #IdeLayoutManager.
+ * @hints: (nullable): optional hints for the layout.
+ * @child: A #GtkWidget.
+ *
+ * Adds @child to the layout, optionally hinting to the layout manager about where to
+ * place the child.
+ *
+ * Returns: A layout specific identifier greater than zero, which should be passed to
+ * ide_layout_manager_remove() to remove the widget from the layout.
+ */
+guint
+ide_layout_manager_add (IdeLayoutManager *self,
+ const IdeLayoutHints *hints,
+ GtkWidget *child)
+{
+ guint ret;
+
+ g_return_val_if_fail (IDE_IS_LAYOUT_MANAGER (self), 0);
+ g_return_val_if_fail (GTK_IS_WIDGET (child), 0);
+
+ ret = IDE_LAYOUT_MANAGER_GET_IFACE (self)->add (self, hints, child);
+
+ g_return_val_if_fail (ret > 0, 0);
+
+ return ret;
+}
+
+/**
+ * ide_layout_manager_remove:
+ * @self: An #IdeLayoutManager.
+ * @layout_id: The layout id from ide_layout_manager_add()
+ *
+ * Removes a widget from the layout that was generated by calling * ide_layout_manager_add().
+ */
+void
+ide_layout_manager_remove (IdeLayoutManager *self,
+ guint layout_id)
+{
+ g_return_if_fail (IDE_IS_LAYOUT_MANAGER (self));
+ g_return_if_fail (layout_id > 0);
+
+ IDE_LAYOUT_MANAGER_GET_IFACE (self)->remove (self, layout_id);
+}
diff --git a/libide/ide-layout-manager.h b/libide/ide-layout-manager.h
new file mode 100644
index 0000000..3372138
--- /dev/null
+++ b/libide/ide-layout-manager.h
@@ -0,0 +1,60 @@
+/* ide-layout-manager.h
+ *
+ * Copyright (C) 2015 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_LAYOUT_MANAGER_H
+#define IDE_LAYOUT_MANAGER_H
+
+#include <gtk/gtk.h>
+
+#include "ide-view.h"
+
+G_BEGIN_DECLS
+
+#define IDE_TYPE_LAYOUT_MANAGER (ide_layout_manager_get_type())
+
+G_DECLARE_INTERFACE (IdeLayoutManager, ide_layout_manager, IDE, LAYOUT_MANAGER, GObject)
+
+typedef struct
+{
+ GtkWidget *left_of;
+ GtkWidget *right_of;
+ GtkWidget *above;
+ GtkWidget *below;
+ gint column;
+} IdeLayoutHints;
+
+struct _IdeLayoutManagerInterface
+{
+ GTypeInterface parent_instance;
+
+ guint (*add) (IdeLayoutManager *self,
+ const IdeLayoutHints *hints,
+ GtkWidget *child);
+ void (*remove) (IdeLayoutManager *self,
+ guint layout_id);
+};
+
+guint ide_layout_manager_add (IdeLayoutManager *self,
+ const IdeLayoutHints *hints,
+ GtkWidget *child);
+void ide_layout_manager_remove (IdeLayoutManager *self,
+ guint layout_id);
+
+G_END_DECLS
+
+#endif /* IDE_LAYOUT_MANAGER_H */
diff --git a/libide/ide-perspective.c b/libide/ide-perspective.c
new file mode 100644
index 0000000..0634f34
--- /dev/null
+++ b/libide/ide-perspective.c
@@ -0,0 +1,209 @@
+/* ide-perspective.c
+ *
+ * Copyright (C) 2015 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/>.
+ */
+
+#include "ide-perspective.h"
+
+G_DEFINE_INTERFACE (IdePerspective, ide_perspective, G_TYPE_OBJECT)
+
+static gboolean
+ide_perspective_real_agree_to_shutdown (IdePerspective *self)
+{
+ return TRUE;
+}
+
+static const gchar *
+ide_perspective_real_get_icon_name (IdePerspective *self)
+{
+ return NULL;
+}
+
+static gboolean
+ide_perspective_real_get_needs_attention (IdePerspective *self)
+{
+ return FALSE;
+}
+
+static const gchar *
+ide_perspective_real_get_title (IdePerspective *self)
+{
+ return NULL;
+}
+
+static GtkWidget *
+ide_perspective_real_get_titlebar (IdePerspective *self)
+{
+ return NULL;
+}
+
+static void
+ide_perspective_real_set_fullscreen (IdePerspective *self,
+ gboolean fullscreen)
+{
+}
+
+static void
+ide_perspective_real_views_foreach (IdePerspective *self,
+ GtkCallback callback,
+ gpointer user_data)
+{
+}
+
+static void
+ide_perspective_default_init (IdePerspectiveInterface *iface)
+{
+ iface->agree_to_shutdown = ide_perspective_real_agree_to_shutdown;
+ iface->get_icon_name = ide_perspective_real_get_icon_name;
+ iface->get_needs_attention = ide_perspective_real_get_needs_attention;
+ iface->get_title = ide_perspective_real_get_title;
+ iface->get_titlebar = ide_perspective_real_get_titlebar;
+ iface->set_fullscreen = ide_perspective_real_set_fullscreen;
+ iface->views_foreach = ide_perspective_real_views_foreach;
+}
+
+/**
+ * ide_perspective_agree_to_shutdown:
+ * @self: An #IdePerspective.
+ *
+ * This interface method is called when the workbench would like to shutdown.
+ * If the perspective needs to focus and ask the user a question, this is the place
+ * to do so. You may run a #GtkDialog using gtk_dialog_run() or simply focus your
+ * perspective and return %FALSE.
+ *
+ * Returns: %TRUE to allow the workbench to continue shutting down.
+ */
+gboolean
+ide_perspective_agree_to_shutdown (IdePerspective *self)
+{
+ g_return_val_if_fail (IDE_IS_PERSPECTIVE (self), FALSE);
+
+ return IDE_PERSPECTIVE_GET_IFACE (self)->agree_to_shutdown (self);
+}
+
+/**
+ * ide_perspective_get_icon_name:
+ * @self: An #IdePerspective.
+ *
+ * This interface methods retrieves the icon name to use when displaying the
+ * perspective selection sidebar.
+ *
+ * If you implement an "icon-name" property, the icon may change at runtime.
+ *
+ * Returns: A named icon as a string which will not be modified or freed.
+ */
+const gchar *
+ide_perspective_get_icon_name (IdePerspective *self)
+{
+ g_return_val_if_fail (IDE_IS_PERSPECTIVE (self), NULL);
+
+ return IDE_PERSPECTIVE_GET_IFACE (self)->get_icon_name (self);
+}
+
+/**
+ * ide_perspective_get_needs_attention:
+ * @self: An #IdePerspective.
+ *
+ * This interface method returns %TRUE if the interface needs attention.
+ *
+ * One such use of this would be to indicate that contents within a perspective have
+ * changed since the user last focused the perspective. This should also be implemented
+ * with a boolean property named "needs-attention". If you call g_object_notify() (or one
+ * of its variants), the notifcation visual will be rendered with your icon.
+ *
+ * Returns: %TRUE if the perspective needs attention.
+ */
+gboolean
+ide_perspective_get_needs_attention (IdePerspective *self)
+{
+ g_return_val_if_fail (IDE_IS_PERSPECTIVE (self), FALSE);
+
+ return IDE_PERSPECTIVE_GET_IFACE (self)->get_needs_attention (self);
+}
+
+/**
+ * ide_perspective_get_title:
+ * @self: An #IdePerspective
+ *
+ * This interface method gets the title of the perspective. This is used for tooltips
+ * in the perspective selector and potentially other UI components.
+ *
+ * Returns: A string which will not be modified or freed.
+ */
+const gchar *
+ide_perspective_get_title (IdePerspective *self)
+{
+ g_return_val_if_fail (IDE_IS_PERSPECTIVE (self), NULL);
+
+ return IDE_PERSPECTIVE_GET_IFACE (self)->get_title (self);
+}
+
+/**
+ * ide_perspective_get_titlebar:
+ * @self: An #IdePerspective.
+ *
+ * This interface method should return a #GtkWidget suitable for being embedded as the
+ * titlebar for the application. If you return %NULL from this method, a suitable titlebar
+ * will be created for you.
+ *
+ * You may use #IdeHeaderBar for a base implementation to save you the trouble of
+ * creating a titlebar similar to other perspectives in Builder.
+ *
+ * Returns: (transfer none) (nullable): A #GtkWidget or %NULL.
+ */
+GtkWidget *
+ide_perspective_get_titlebar (IdePerspective *self)
+{
+ g_return_val_if_fail (IDE_IS_PERSPECTIVE (self), NULL);
+
+ return IDE_PERSPECTIVE_GET_IFACE (self)->get_titlebar (self);
+}
+
+/**
+ * ide_perspective_set_fullscreen:
+ * @self: An #IdePerspective.
+ * @fullscreen: If fullscreen mode should be activated.
+ *
+ * This interface method is used to notify the perspective that it is going into
+ * fullscreen mode. The #IdeWorkbench will notify the perspective before it is displayed.
+ */
+void
+ide_perspective_set_fullscreen (IdePerspective *self,
+ gboolean fullscreen)
+{
+ g_return_if_fail (IDE_IS_PERSPECTIVE (self));
+
+ IDE_PERSPECTIVE_GET_IFACE (self)->set_fullscreen (self, fullscreen);
+}
+
+/**
+ * ide_perspective_views_foreach:
+ * @self: An #IdePerspective.
+ * @callback: (scope call): A #GtkCallback.
+ * @user_data: user data for @callback.
+ *
+ * This interface method is used to iterate all #IdeView's that are descendents of @self.
+ */
+void
+ide_perspective_views_foreach (IdePerspective *self,
+ GtkCallback callback,
+ gpointer user_data)
+{
+ g_return_if_fail (IDE_IS_PERSPECTIVE (self));
+ g_return_if_fail (callback != NULL);
+
+ IDE_PERSPECTIVE_GET_IFACE (self)->views_foreach (self, callback, user_data);
+}
diff --git a/libide/ide-perspective.h b/libide/ide-perspective.h
new file mode 100644
index 0000000..caf0302
--- /dev/null
+++ b/libide/ide-perspective.h
@@ -0,0 +1,59 @@
+/* ide-perspective.h
+ *
+ * Copyright (C) 2015 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_PERSPECTIVE_H
+#define IDE_PERSPECTIVE_H
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define IDE_TYPE_PERSPECTIVE (ide_perspective_get_type())
+
+G_DECLARE_INTERFACE (IdePerspective, ide_perspective, IDE, PERSPECTIVE, GtkWidget)
+
+struct _IdePerspectiveInterface
+{
+ GTypeInterface parent;
+
+ gboolean (*agree_to_shutdown) (IdePerspective *self);
+ const gchar *(*get_icon_name) (IdePerspective *self);
+ gboolean (*get_needs_attention) (IdePerspective *self);
+ const gchar *(*get_title) (IdePerspective *self);
+ GtkWidget *(*get_titlebar) (IdePerspective *self);
+ void (*set_fullscreen) (IdePerspective *self,
+ gboolean fullscreen);
+ void (*views_foreach) (IdePerspective *self,
+ GtkCallback callback,
+ gpointer user_data);
+};
+
+gboolean ide_perspective_agree_to_shutdown (IdePerspective *self);
+const gchar *ide_perspective_get_icon_name (IdePerspective *self);
+const gchar *ide_perspective_get_title (IdePerspective *self);
+GtkWidget *ide_perspective_get_titlebar (IdePerspective *self);
+gboolean ide_perspective_get_needs_attention (IdePerspective *self);
+void ide_perspective_set_fullscreen (IdePerspective *self,
+ gboolean fullscreen);
+void ide_perspective_views_foreach (IdePerspective *self,
+ GtkCallback callback,
+ gpointer user_data);
+
+G_END_DECLS
+
+#endif /* IDE_PERSPECTIVE_H */
diff --git a/libide/ide-preferences-addin.c b/libide/ide-preferences-addin.c
new file mode 100644
index 0000000..2463942
--- /dev/null
+++ b/libide/ide-preferences-addin.c
@@ -0,0 +1,81 @@
+/* ide-preferences-addin.c
+ *
+ * Copyright (C) 2015 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/>.
+ */
+
+#include "ide-preferences-addin.h"
+
+G_DEFINE_INTERFACE (IdePreferencesAddin, ide_preferences_addin, G_TYPE_OBJECT)
+
+static void
+ide_preferences_addin_real_load (IdePreferencesAddin *self,
+ IdePreferences *preferences)
+{
+}
+
+static void
+ide_preferences_addin_real_unload (IdePreferencesAddin *self,
+ IdePreferences *preferences)
+{
+}
+
+static void
+ide_preferences_addin_default_init (IdePreferencesAddinInterface *iface)
+{
+ iface->load = ide_preferences_addin_real_load;
+ iface->unload = ide_preferences_addin_real_unload;
+}
+
+/**
+ * ide_preferences_addin_load:
+ * @self: An #IdePreferencesAddin.
+ * @preferences: The preferences container implementation.
+ *
+ * This interface method is called when a preferences addin is initialized. It could be
+ * initialized from multiple preferences implementations, so consumers should use the
+ * #IdePreferences interface to add their preferences controls to the container.
+ *
+ * Such implementations might include a preferences dialog window, or a preferences
+ * widget which could be rendered as a perspective.
+ */
+void
+ide_preferences_addin_load (IdePreferencesAddin *self,
+ IdePreferences *preferences)
+{
+ g_return_if_fail (IDE_IS_PREFERENCES_ADDIN (self));
+ g_return_if_fail (IDE_IS_PREFERENCES (preferences));
+
+ IDE_PREFERENCES_ADDIN_GET_IFACE (self)->load (self, preferences);
+}
+
+/**
+ * ide_preferences_addin_unload:
+ * @self: An #IdePreferencesAddin.
+ * @preferences: The preferences container implementation.
+ *
+ * This interface method is called when the preferences addin should remove all controls
+ * added to @preferences. This could happen during desctruction of @preferences, or when
+ * the plugin is unloaded.
+ */
+void
+ide_preferences_addin_unload (IdePreferencesAddin *self,
+ IdePreferences *preferences)
+{
+ g_return_if_fail (IDE_IS_PREFERENCES_ADDIN (self));
+ g_return_if_fail (IDE_IS_PREFERENCES (preferences));
+
+ IDE_PREFERENCES_ADDIN_GET_IFACE (self)->unload (self, preferences);
+}
diff --git a/libide/ide-preferences-addin.h b/libide/ide-preferences-addin.h
new file mode 100644
index 0000000..308b7be
--- /dev/null
+++ b/libide/ide-preferences-addin.h
@@ -0,0 +1,49 @@
+/* ide-preferences-addin.h
+ *
+ * Copyright (C) 2015 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_PREFERENCES_ADDIN_H
+#define IDE_PREFERENCES_ADDIN_H
+
+#include <gtk/gtk.h>
+
+#include "ide-preferences.h"
+
+G_BEGIN_DECLS
+
+#define IDE_TYPE_PREFERENCES_ADDIN (ide_preferences_addin_get_type())
+
+G_DECLARE_INTERFACE (IdePreferencesAddin, ide_preferences_addin, IDE, PREFERENCES_ADDIN, GObject)
+
+struct _IdePreferencesAddinInterface
+{
+ GTypeInterface parent_interface;
+
+ void (*load) (IdePreferencesAddin *self,
+ IdePreferences *preferences);
+ void (*unload) (IdePreferencesAddin *self,
+ IdePreferences *preferences);
+};
+
+void ide_preferences_addin_load (IdePreferencesAddin *self,
+ IdePreferences *preferences);
+void ide_preferences_addin_unload (IdePreferencesAddin *self,
+ IdePreferences *preferences);
+
+G_END_DECLS
+
+#endif /* IDE_PREFERENCES_ADDIN_H */
diff --git a/libide/ide-preferences.c b/libide/ide-preferences.c
new file mode 100644
index 0000000..eaae59d
--- /dev/null
+++ b/libide/ide-preferences.c
@@ -0,0 +1,116 @@
+/* ide-preferences.c
+ *
+ * Copyright (C) 2015 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/>.
+ */
+
+#include "ide-preferences.h"
+
+G_DEFINE_INTERFACE (IdePreferences, ide_preferences, G_TYPE_OBJECT)
+
+static void
+ide_preferences_default_init (IdePreferencesInterface *iface)
+{
+}
+
+void
+ide_preferences_add_page (IdePreferences *self,
+ const gchar *page_name,
+ const gchar *title,
+ gint priority)
+{
+ g_return_if_fail (IDE_IS_PREFERENCES (self));
+ g_return_if_fail (page_name != NULL);
+ g_return_if_fail (title != NULL);
+
+ IDE_PREFERENCES_GET_IFACE (self)->add_page (self, page_name, title, priority);
+}
+
+void
+ide_preferences_add_group (IdePreferences *self,
+ const gchar *page_name,
+ const gchar *group_name,
+ const gchar *title,
+ gint priority)
+{
+ g_return_if_fail (IDE_IS_PREFERENCES (self));
+ g_return_if_fail (page_name != NULL);
+ g_return_if_fail (group_name != NULL);
+ g_return_if_fail (title != NULL);
+
+ IDE_PREFERENCES_GET_IFACE (self)->add_group (self, page_name, group_name, title, priority);
+}
+
+guint
+ide_preferences_add_switch (IdePreferences *self,
+ const gchar *page_name,
+ const gchar *group_name,
+ const gchar *schema_id,
+ const gchar *key,
+ const gchar *title,
+ const gchar *subtitle,
+ const gchar *keywords,
+ gint priority)
+{
+ g_return_val_if_fail (IDE_IS_PREFERENCES (self), 0);
+ g_return_val_if_fail (page_name != NULL, 0);
+ g_return_val_if_fail (group_name != NULL, 0);
+ g_return_val_if_fail (schema_id != NULL, 0);
+ g_return_val_if_fail (key != NULL, 0);
+ g_return_val_if_fail (title != NULL, 0);
+
+ return IDE_PREFERENCES_GET_IFACE (self)->add_switch (self, page_name, group_name, schema_id, key,
+ title, subtitle, keywords, priority);
+}
+
+guint
+ide_preferences_add_spinbutton (IdePreferences *self,
+ const gchar *page_name,
+ const gchar *group_name,
+ const gchar *schema_id,
+ const gchar *key,
+ const gchar *title,
+ const gchar *subtitle,
+ const gchar *keywords,
+ gint priority)
+{
+ g_return_val_if_fail (IDE_IS_PREFERENCES (self), 0);
+ g_return_val_if_fail (page_name != NULL, 0);
+ g_return_val_if_fail (group_name != NULL, 0);
+ g_return_val_if_fail (schema_id != NULL, 0);
+ g_return_val_if_fail (key != NULL, 0);
+ g_return_val_if_fail (title != NULL, 0);
+
+ return IDE_PREFERENCES_GET_IFACE (self)->add_spinbutton (self, page_name, group_name, schema_id,
+ key, title, subtitle, keywords,
+ priority);
+}
+
+guint
+ide_preferences_add_custom (IdePreferences *self,
+ const gchar *page_name,
+ const gchar *group_name,
+ GtkWidget *widget,
+ const gchar *keywords,
+ gint priority)
+{
+ g_return_val_if_fail (IDE_IS_PREFERENCES (self), 0);
+ g_return_val_if_fail (page_name != NULL, 0);
+ g_return_val_if_fail (group_name != NULL, 0);
+ g_return_val_if_fail (GTK_IS_WIDGET (widget), 0);
+
+ return IDE_PREFERENCES_GET_IFACE (self)->add_custom (self, page_name, group_name, widget,
+ keywords, priority);
+}
diff --git a/libide/ide-preferences.h b/libide/ide-preferences.h
new file mode 100644
index 0000000..bca3d13
--- /dev/null
+++ b/libide/ide-preferences.h
@@ -0,0 +1,105 @@
+/* ide-preferences.h
+ *
+ * Copyright (C) 2015 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_PREFERENCES_H
+#define IDE_PREFERENCES_H
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define IDE_TYPE_PREFERENCES (ide_preferences_get_type())
+
+G_DECLARE_INTERFACE (IdePreferences, ide_preferences, IDE, PREFERENCES, GObject)
+
+struct _IdePreferencesInterface
+{
+ GTypeInterface parent_interface;
+
+ void (*add_page) (IdePreferences *self,
+ const gchar *page_name,
+ const gchar *title,
+ gint priority);
+ void (*add_group) (IdePreferences *self,
+ const gchar *page_name,
+ const gchar *group_name,
+ const gchar *title,
+ gint priority);
+ guint (*add_switch) (IdePreferences *self,
+ const gchar *page_name,
+ const gchar *group_name,
+ const gchar *schema_id,
+ const gchar *key,
+ const gchar *title,
+ const gchar *subtitle,
+ const gchar *keywords,
+ gint priority);
+ guint (*add_spinbutton) (IdePreferences *self,
+ const gchar *page_name,
+ const gchar *group_name,
+ const gchar *schema_id,
+ const gchar *key,
+ const gchar *title,
+ const gchar *subtitle,
+ const gchar *keywords,
+ gint priority);
+ guint (*add_custom) (IdePreferences *self,
+ const gchar *page_name,
+ const gchar *group_name,
+ GtkWidget *widget,
+ const gchar *keywords,
+ gint priority);
+};
+
+void ide_preferences_add_page (IdePreferences *self,
+ const gchar *page_name,
+ const gchar *title,
+ gint priority);
+void ide_preferences_add_group (IdePreferences *self,
+ const gchar *page_name,
+ const gchar *group_name,
+ const gchar *title,
+ gint priority);
+guint ide_preferences_add_switch (IdePreferences *self,
+ const gchar *page_name,
+ const gchar *group_name,
+ const gchar *schema_id,
+ const gchar *key,
+ const gchar *title,
+ const gchar *subtitle,
+ const gchar *keywords,
+ gint priority);
+guint ide_preferences_add_spinbutton (IdePreferences *self,
+ const gchar *page_name,
+ const gchar *group_name,
+ const gchar *schema_id,
+ const gchar *key,
+ const gchar *title,
+ const gchar *subtitle,
+ const gchar *keywords,
+ gint priority);
+guint ide_preferences_add_custom (IdePreferences *self,
+ const gchar *page_name,
+ const gchar *group_name,
+ GtkWidget *widget,
+ const gchar *keywords,
+ gint priority);
+
+G_END_DECLS
+
+#endif /* IDE_PREFERENCES_H */
diff --git a/libide/ide-view.c b/libide/ide-view.c
new file mode 100644
index 0000000..6a7ad9c
--- /dev/null
+++ b/libide/ide-view.c
@@ -0,0 +1,129 @@
+/* ide-view.c
+ *
+ * Copyright (C) 2015 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/>.
+ */
+
+#include "ide-view.h"
+
+G_DEFINE_INTERFACE (IdeView, ide_view, GTK_TYPE_WIDGET)
+
+static const gchar *
+ide_view_real_get_title (IdeView *self)
+{
+ return NULL;
+}
+
+static const gchar *
+ide_view_real_get_icon_name (IdeView *self)
+{
+ return NULL;
+}
+
+static gboolean
+ide_view_real_get_can_save (IdeView *self)
+{
+ return FALSE;
+}
+
+static gboolean
+ide_view_real_get_needs_attention (IdeView *self)
+{
+ return FALSE;
+}
+
+static void
+ide_view_real_save_async (IdeView *self,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_task_report_new_error (self, callback, user_data, ide_view_real_save_async,
+ G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, "Saving is not supported.");
+}
+
+static gboolean
+ide_view_real_save_finish (IdeView *self,
+ GAsyncResult *result,
+ GError **error)
+{
+ return g_task_propagate_boolean (G_TASK (result), error);
+}
+
+static void
+ide_view_default_init (IdeViewInterface *iface)
+{
+ iface->get_title = ide_view_real_get_title;
+ iface->get_icon_name = ide_view_real_get_icon_name;
+ iface->get_can_save = ide_view_real_get_can_save;
+ iface->get_needs_attention = ide_view_real_get_needs_attention;
+ iface->save_async = ide_view_real_save_async;
+ iface->save_finish = ide_view_real_save_finish;
+}
+
+const gchar *
+ide_view_get_title (IdeView *self)
+{
+ g_return_val_if_fail (IDE_IS_VIEW (self), NULL);
+
+ return NULL;
+}
+
+const gchar *
+ide_view_get_icon_name (IdeView *self)
+{
+ g_return_val_if_fail (IDE_IS_VIEW (self), NULL);
+
+ return IDE_VIEW_GET_IFACE (self)->get_icon_name (self);
+}
+
+gboolean
+ide_view_get_can_save (IdeView *self)
+{
+ g_return_val_if_fail (IDE_IS_VIEW (self), FALSE);
+
+ return IDE_VIEW_GET_IFACE (self)->get_can_save (self);
+}
+
+gboolean
+ide_view_get_needs_attention (IdeView *self)
+{
+ g_return_val_if_fail (IDE_IS_VIEW (self), FALSE);
+
+ return IDE_VIEW_GET_IFACE (self)->get_needs_attention (self);
+}
+
+void
+ide_view_save_async (IdeView *self,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_return_if_fail (IDE_IS_VIEW (self));
+ g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable));
+
+ IDE_VIEW_GET_IFACE (self)->save_async (self, cancellable, callback, user_data);
+}
+
+gboolean
+ide_view_save_finish (IdeView *self,
+ GAsyncResult *result,
+ GError **error)
+{
+ g_return_val_if_fail (IDE_IS_VIEW (self), FALSE);
+ g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
+
+ return IDE_VIEW_GET_IFACE (self)->save_finish (self, result, error);
+}
diff --git a/libide/ide-view.h b/libide/ide-view.h
new file mode 100644
index 0000000..d73f462
--- /dev/null
+++ b/libide/ide-view.h
@@ -0,0 +1,61 @@
+/* ide-view.h
+ *
+ * Copyright (C) 2015 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_VIEW_H
+#define IDE_VIEW_H
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define IDE_TYPE_VIEW (ide_view_get_type())
+
+G_DECLARE_INTERFACE (IdeView, ide_view, IDE, VIEW, GtkWidget)
+
+struct _IdeViewInterface
+{
+ GTypeInterface parent;
+
+ const gchar *(*get_title) (IdeView *self);
+ const gchar *(*get_icon_name) (IdeView *self);
+ gboolean (*get_can_save) (IdeView *self);
+ gboolean (*get_needs_attention) (IdeView *self);
+ void (*save_async) (IdeView *self,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+ gboolean (*save_finish) (IdeView *self,
+ GAsyncResult *result,
+ GError **error);
+};
+
+const gchar *ide_view_get_title (IdeView *self);
+const gchar *ide_view_get_icon_name (IdeView *self);
+gboolean ide_view_get_can_save (IdeView *self);
+gboolean ide_view_get_needs_attention (IdeView *self);
+void ide_view_save_async (IdeView *self,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+gboolean ide_view_save_finish (IdeView *self,
+ GAsyncResult *result,
+ GError **error);
+
+G_END_DECLS
+
+#endif /* IDE_VIEW_H */
diff --git a/libide/ide-workbench-addin.c b/libide/ide-workbench-addin.c
new file mode 100644
index 0000000..1cf1d61
--- /dev/null
+++ b/libide/ide-workbench-addin.c
@@ -0,0 +1,83 @@
+/* ide-workbench-addin.c
+ *
+ * Copyright (C) 2015 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-workbench-addin"
+
+#include "ide-workbench-addin.h"
+
+G_DEFINE_INTERFACE (IdeWorkbenchAddin, ide_workbench_addin, G_TYPE_OBJECT)
+
+static void
+ide_workbench_addin_real_load (IdeWorkbenchAddin *self,
+ IdeWorkbench *workbench)
+{
+}
+
+static void
+ide_workbench_addin_real_unload (IdeWorkbenchAddin *self,
+ IdeWorkbench *workbench)
+{
+}
+
+static void
+ide_workbench_addin_default_init (IdeWorkbenchAddinInterface *iface)
+{
+ iface->load = ide_workbench_addin_real_load;
+ iface->unload = ide_workbench_addin_real_unload;
+}
+
+/**
+ * ide_workbench_addin_load:
+ * @self: An #IdeWorkbenchAddin
+ * @workbench: An #IdeWorkbench
+ *
+ * This interface method is called to load @self. Addin implementations should add any
+ * required UI or actions to @workbench here. You should remove anything you've added
+ * in ide_workbench_addin_unload(), as that will be called when your plugin is deactivated
+ * or the workbench is in the destruction process.
+ */
+void
+ide_workbench_addin_load (IdeWorkbenchAddin *self,
+ IdeWorkbench *workbench)
+{
+ g_return_if_fail (IDE_IS_WORKBENCH_ADDIN (self));
+ g_return_if_fail (IDE_IS_WORKBENCH (workbench));
+
+ IDE_WORKBENCH_ADDIN_GET_IFACE (self)->load (self, workbench);
+}
+
+/**
+ * ide_workbench_addin_unload:
+ * @self: An #IdeWorkbenchAddin
+ * @workbench: An #IdeWorkbench
+ *
+ * This interface method should cleanup after anything added to @workbench in
+ * ide_workbench_addin_load().
+ *
+ * This might be called when a plugin is deactivated, or the workbench is in the
+ * destruction process.
+ */
+void
+ide_workbench_addin_unload (IdeWorkbenchAddin *self,
+ IdeWorkbench *workbench)
+{
+ g_return_if_fail (IDE_IS_WORKBENCH_ADDIN (self));
+ g_return_if_fail (IDE_IS_WORKBENCH (workbench));
+
+ IDE_WORKBENCH_ADDIN_GET_IFACE (self)->unload (self, workbench);
+}
diff --git a/libide/ide-workbench-addin.h b/libide/ide-workbench-addin.h
new file mode 100644
index 0000000..9897d2b
--- /dev/null
+++ b/libide/ide-workbench-addin.h
@@ -0,0 +1,47 @@
+/* ide-workbench-addin.h
+ *
+ * Copyright (C) 2015 Christian Hergert <chergert redhat com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef IDE_WORKBENCH_ADDIN_H
+#define IDE_WORKBENCH_ADDIN_H
+
+#include "ide-workbench.h"
+
+G_BEGIN_DECLS
+
+#define IDE_TYPE_WORKBENCH_ADDIN (ide_workbench_addin_get_type())
+
+G_DECLARE_INTERFACE (IdeWorkbenchAddin, ide_workbench_addin, IDE, WORKBENCH_ADDIN, GObject)
+
+struct _IdeWorkbenchAddinInterface
+{
+ GTypeInterface parent;
+
+ void (*load) (IdeWorkbenchAddin *self,
+ IdeWorkbench *workbench);
+ void (*unload) (IdeWorkbenchAddin *self,
+ IdeWorkbench *workbench);
+};
+
+void ide_workbench_addin_load (IdeWorkbenchAddin *self,
+ IdeWorkbench *workbench);
+void ide_workbench_addin_unload (IdeWorkbenchAddin *self,
+ IdeWorkbench *workbench);
+
+G_END_DECLS
+
+#endif /* IDE_WORKBENCH_ADDIN_H */
diff --git a/libide/ide-workbench.c b/libide/ide-workbench.c
new file mode 100644
index 0000000..fd5b344
--- /dev/null
+++ b/libide/ide-workbench.c
@@ -0,0 +1,322 @@
+/* ide-workbench.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-workbench"
+
+#include <libpeas/peas.h>
+
+#include "ide-macros.h"
+#include "ide-workbench.h"
+
+struct _IdeWorkbench
+{
+ GtkApplicationWindow parent;
+
+ IdeContext *context;
+
+ PeasExtensionSet *perspectives;
+ IdePerspective *perspective;
+
+ GtkStack *perspectives_stack;
+ GtkStackSwitcher *perspectives_stack_switcher;
+};
+
+typedef struct
+{
+ GtkCallback callback;
+ gpointer user_data;
+} IdeWorkbenchForeach;
+
+G_DEFINE_TYPE (IdeWorkbench, ide_workbench, GTK_TYPE_APPLICATION_WINDOW)
+
+enum {
+ PROP_0,
+ PROP_PERSPECTIVE,
+ LAST_PROP
+};
+
+static GParamSpec *gParamSpecs [LAST_PROP];
+
+static void
+ide_workbench_add_perspective (PeasExtensionSet *set,
+ PeasPluginInfo *plugin_info,
+ PeasExtension *extension,
+ gpointer user_data)
+{
+ IdeWorkbench *self = user_data;
+ IdePerspective *perspective = (IdePerspective *)extension;
+ const gchar *title;
+ const gchar *icon_name;
+
+ g_assert (IDE_IS_WORKBENCH (self));
+ g_assert (IDE_IS_PERSPECTIVE (perspective));
+
+ g_object_ref_sink (perspective);
+
+ title = ide_perspective_get_title (perspective);
+ icon_name = ide_perspective_get_icon_name (perspective);
+
+ gtk_container_add_with_properties (GTK_CONTAINER (self->perspectives_stack),
+ GTK_WIDGET (perspective),
+ "icon-name", icon_name,
+ "needs-attention", FALSE,
+ "title", title,
+ NULL);
+}
+
+static void
+ide_workbench_remove_perspective (PeasExtensionSet *set,
+ PeasPluginInfo *plugin_info,
+ PeasExtension *extension,
+ gpointer user_data)
+{
+ IdeWorkbench *self = user_data;
+ IdePerspective *perspective = (IdePerspective *)extension;
+
+ g_assert (IDE_IS_WORKBENCH (self));
+ g_assert (IDE_IS_PERSPECTIVE (perspective));
+
+ gtk_container_remove (GTK_CONTAINER (self->perspectives_stack), GTK_WIDGET (perspective));
+}
+
+static void
+ide_workbench_finalize (GObject *object)
+{
+ IdeWorkbench *self = (IdeWorkbench *)object;
+
+ ide_clear_weak_pointer (&self->perspective);
+ g_clear_object (&self->context);
+
+ G_OBJECT_CLASS (ide_workbench_parent_class)->finalize (object);
+}
+
+static void
+ide_workbench_constructed (GObject *object)
+{
+ IdeWorkbench *self = (IdeWorkbench *)object;
+
+ G_OBJECT_CLASS (ide_workbench_parent_class)->constructed (object);
+
+ self->perspectives = peas_extension_set_new (peas_engine_get_default (),
+ IDE_TYPE_PERSPECTIVE,
+ NULL);
+
+ g_signal_connect_object (self->perspectives,
+ "extension-added",
+ G_CALLBACK (ide_workbench_add_perspective),
+ self,
+ 0);
+
+ g_signal_connect_object (self->perspectives,
+ "extension-removed",
+ G_CALLBACK (ide_workbench_remove_perspective),
+ self,
+ 0);
+
+ peas_extension_set_foreach (self->perspectives,
+ ide_workbench_add_perspective,
+ self);
+}
+
+static void
+ide_workbench_destroy (GtkWidget *widget)
+{
+ IdeWorkbench *self = (IdeWorkbench *)widget;
+
+ g_assert (IDE_IS_WORKBENCH (self));
+
+ g_clear_object (&self->perspectives);
+
+ GTK_WIDGET_CLASS (ide_workbench_parent_class)->destroy (widget);
+}
+
+static void
+ide_workbench_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ IdeWorkbench *self = IDE_WORKBENCH (object);
+
+ switch (prop_id)
+ {
+ case PROP_PERSPECTIVE:
+ g_value_set_object (value, ide_workbench_get_perspective (self));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+ide_workbench_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ IdeWorkbench *self = IDE_WORKBENCH (object);
+
+ switch (prop_id)
+ {
+ case PROP_PERSPECTIVE:
+ ide_workbench_set_perspective (self, g_value_get_object (value));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+ide_workbench_class_init (IdeWorkbenchClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->constructed = ide_workbench_constructed;
+ object_class->finalize = ide_workbench_finalize;
+ object_class->get_property = ide_workbench_get_property;
+ object_class->set_property = ide_workbench_set_property;
+
+ widget_class->destroy = ide_workbench_destroy;
+
+ gParamSpecs [PROP_PERSPECTIVE] =
+ g_param_spec_object ("perspective",
+ "Perspective",
+ "Perspective",
+ IDE_TYPE_PERSPECTIVE,
+ (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_properties (object_class, LAST_PROP, gParamSpecs);
+
+ gtk_widget_class_set_template_from_resource (widget_class,
+ "/org/gnome/libide/ui/ide-workbench.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, IdeWorkbench, perspectives_stack);
+ gtk_widget_class_bind_template_child (widget_class, IdeWorkbench, perspectives_stack_switcher);
+}
+
+static void
+ide_workbench_init (IdeWorkbench *self)
+{
+ gtk_widget_init_template (GTK_WIDGET (self));
+}
+
+/**
+ * ide_workbench_get_perspective:
+ * @self: An #IdeWorkbench.
+ *
+ * Gets the current perspective.
+ *
+ * Returns: (transfer none): An #IdePerspective.
+ */
+IdePerspective *
+ide_workbench_get_perspective (IdeWorkbench *self)
+{
+ GtkWidget *visible_child;
+
+ g_return_val_if_fail (IDE_IS_WORKBENCH (self), NULL);
+
+ visible_child = gtk_stack_get_visible_child (self->perspectives_stack);
+
+ return IDE_PERSPECTIVE (visible_child);
+}
+
+void
+ide_workbench_set_perspective (IdeWorkbench *self,
+ IdePerspective *perspective)
+{
+ g_return_if_fail (IDE_IS_WORKBENCH (self));
+ g_return_if_fail (IDE_IS_PERSPECTIVE (perspective));
+ g_return_if_fail (GTK_WIDGET (self->perspectives_stack) ==
+ gtk_widget_get_parent (GTK_WIDGET (perspective)));
+
+ gtk_stack_set_visible_child (self->perspectives_stack, GTK_WIDGET (perspective));
+}
+
+static void
+ide_workbench_views_foreach_cb (GtkWidget *widget,
+ gpointer user_data)
+{
+ IdeWorkbenchForeach *foreach_data = user_data;
+
+ g_assert (foreach_data);
+ g_assert (foreach_data->callback);
+
+ foreach_data->callback (widget, foreach_data->user_data);
+}
+
+static void
+ide_workbench_views_foreach_exten_cb (PeasExtensionSet *set,
+ PeasPluginInfo *plugin_info,
+ PeasExtension *extension,
+ gpointer user_data)
+{
+ IdePerspective *perspective = user_data;
+ IdeWorkbenchForeach *foreach_data = user_data;
+
+ g_assert (PEAS_IS_EXTENSION_SET (set));
+ g_assert (plugin_info != NULL);
+ g_assert (IDE_IS_PERSPECTIVE (perspective));
+ g_assert (foreach_data != NULL);
+ g_assert (foreach_data->callback != NULL);
+
+ ide_perspective_views_foreach (IDE_PERSPECTIVE (perspective),
+ ide_workbench_views_foreach_cb,
+ foreach_data);
+}
+
+/**
+ * ide_workbench_views_foreach:
+ * @self: An #IdeWorkbench.
+ * @callback: (scope call): The callback to execute
+ * @user_data: user data for @callback.
+ *
+ * Executes @callback for every #IdeView across all perspectives.
+ */
+void
+ide_workbench_views_foreach (IdeWorkbench *self,
+ GtkCallback callback,
+ gpointer user_data)
+{
+ IdeWorkbenchForeach foreach = { callback, user_data };
+
+ g_return_if_fail (IDE_IS_WORKBENCH (self));
+ g_return_if_fail (callback != NULL);
+
+ peas_extension_set_foreach (self->perspectives,
+ ide_workbench_views_foreach_exten_cb,
+ &foreach);
+}
+
+/**
+ * ide_workbench_get_context:
+ * @self: An #IdeWorkbench.
+ *
+ * Gets the context associated with the workbench, or %NULL.
+ *
+ * Returns: (transfer none) (nullable): An #IdeContext or %NULL.
+ */
+IdeContext *
+ide_workbench_get_context (IdeWorkbench *self)
+{
+ g_return_val_if_fail (IDE_IS_WORKBENCH (self), NULL);
+
+ return self->context;
+}
diff --git a/libide/ide-workbench.h b/libide/ide-workbench.h
new file mode 100644
index 0000000..d0fb127
--- /dev/null
+++ b/libide/ide-workbench.h
@@ -0,0 +1,65 @@
+/* ide-workbench.h
+ *
+ * Copyright (C) 2015 Christian Hergert <chergert redhat com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef IDE_WORKBENCH_H
+#define IDE_WORKBENCH_H
+
+#include <gtk/gtk.h>
+
+#include "ide-context.h"
+#include "ide-perspective.h"
+
+G_BEGIN_DECLS
+
+#define IDE_TYPE_WORKBENCH (ide_workbench_get_type())
+
+G_DECLARE_FINAL_TYPE (IdeWorkbench, ide_workbench, IDE, WORKBENCH, GtkApplicationWindow)
+
+void ide_workbench_open_async (IdeWorkbench *self,
+ GFile **files,
+ gint n_files,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+gboolean ide_workbench_open_finish (IdeWorkbench *self,
+ GAsyncResult *result,
+ GError **error);
+void ide_workbench_save_all_async (IdeWorkbench *self,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+gboolean ide_workbench_save_all_finish (IdeWorkbench *self,
+ GAsyncResult *result,
+ GError **error);
+void ide_workbench_focus (IdeWorkbench *self,
+ GtkWidget *widget);
+void ide_workbench_close (IdeWorkbench *self);
+IdeContext *ide_workbench_get_context (IdeWorkbench *self);
+IdePerspective *ide_workbench_get_perspective (IdeWorkbench *self);
+void ide_workbench_set_perspective (IdeWorkbench *self,
+ IdePerspective *perspective);
+gboolean ide_workbench_get_fullscreen (IdeWorkbench *self);
+void ide_workbench_set_fullscreen (IdeWorkbench *self,
+ gboolean fullscreen);
+void ide_workbench_views_foreach (IdeWorkbench *self,
+ GtkCallback callback,
+ gpointer user_data);
+
+G_END_DECLS
+
+#endif /* IDE_WORKBENCH_H */
diff --git a/libide/ide.h b/libide/ide.h
index b6bd696..f50106c 100644
--- a/libide/ide.h
+++ b/libide/ide.h
@@ -25,6 +25,7 @@ G_BEGIN_DECLS
#define IDE_INSIDE
+#include "ide-application.h"
#include "ide-back-forward-item.h"
#include "ide-back-forward-list.h"
#include "ide-build-result.h"
@@ -56,10 +57,14 @@ G_BEGIN_DECLS
#include "ide-highlight-engine.h"
#include "ide-highlighter.h"
#include "ide-indenter.h"
+#include "ide-layout-manager.h"
#include "ide-log.h"
#include "ide-macros.h"
#include "ide-object.h"
#include "ide-pattern-spec.h"
+#include "ide-perspective.h"
+#include "ide-preferences.h"
+#include "ide-preferences-addin.h"
#include "ide-process.h"
#include "ide-progress.h"
#include "ide-project.h"
@@ -96,6 +101,7 @@ G_BEGIN_DECLS
#include "ide-unsaved-files.h"
#include "ide-vcs.h"
#include "ide-vcs-uri.h"
+#include "ide-workbench.h"
#include "directory/ide-directory-vcs.h"
#include "doap/ide-doap-person.h"
diff --git a/libide/resources/libide.gresource.xml b/libide/resources/libide.gresource.xml
index 647b0ae..20186d2 100644
--- a/libide/resources/libide.gresource.xml
+++ b/libide/resources/libide.gresource.xml
@@ -18,5 +18,7 @@
<file alias="keybindings/emacs.css">../../data/keybindings/emacs.css</file>
<file alias="keybindings/vim.css">../../data/keybindings/vim.css</file>
+
+ <file alias="ui/ide-workbench.ui">../../data/ui/ide-workbench.ui</file>
</gresource>
</gresources>
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]