[gnome-builder/wip/chergert/glade3] glade: start on basic glade plugin for gtk3 support
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-builder/wip/chergert/glade3] glade: start on basic glade plugin for gtk3 support
- Date: Fri, 19 Oct 2018 22:27:31 +0000 (UTC)
commit 862989b02e7d63c6a742272fd1ad9a6ef7c4848b
Author: Christian Hergert <chergert redhat com>
Date: Wed Oct 17 20:47:37 2018 -0700
glade: start on basic glade plugin for gtk3 support
I'm not sure the lifetime of the glade plugin, because we know that
we'll have to write something new for gtk4. But we have a couple of more
releases with gtk3, so we can use this for now.
We still need to add the signal panel, and do our modified version of
the editor panel. We also need a couple accessor widgets.
This is just a minimal prototype for the mechanics.
build-aux/flatpak/org.gnome.Builder.json | 9 +
meson_options.txt | 1 +
po/POTFILES.in | 6 +
src/plugins/glade/gbp-glade-editor-addin.c | 240 +++++++++++++++++++++++
src/plugins/glade/gbp-glade-editor-addin.h | 33 ++++
src/plugins/glade/gbp-glade-layout-stack-addin.c | 227 +++++++++++++++++++++
src/plugins/glade/gbp-glade-layout-stack-addin.h | 31 +++
src/plugins/glade/gbp-glade-plugin.c | 40 ++++
src/plugins/glade/gbp-glade-private.h | 40 ++++
src/plugins/glade/gbp-glade-properties.c | 125 ++++++++++++
src/plugins/glade/gbp-glade-properties.h | 35 ++++
src/plugins/glade/gbp-glade-properties.ui | 77 ++++++++
src/plugins/glade/gbp-glade-view-actions.c | 71 +++++++
src/plugins/glade/gbp-glade-view.c | 189 ++++++++++++++++++
src/plugins/glade/gbp-glade-view.h | 43 ++++
src/plugins/glade/gbp-glade-workbench-addin.c | 172 ++++++++++++++++
src/plugins/glade/gbp-glade-workbench-addin.h | 31 +++
src/plugins/glade/glade.gresource.xml | 16 ++
src/plugins/glade/glade.plugin | 9 +
src/plugins/glade/gtk/menus.ui | 14 ++
src/plugins/glade/meson.build | 26 +++
src/plugins/glade/themes/Adwaita-dark.css | 9 +
src/plugins/glade/themes/Adwaita-shared.css | 37 ++++
src/plugins/glade/themes/Adwaita.css | 9 +
src/plugins/glade/themes/shared.css | 23 +++
src/plugins/meson.build | 2 +
26 files changed, 1515 insertions(+)
---
diff --git a/build-aux/flatpak/org.gnome.Builder.json b/build-aux/flatpak/org.gnome.Builder.json
index 83336470d..f94a58f8f 100644
--- a/build-aux/flatpak/org.gnome.Builder.json
+++ b/build-aux/flatpak/org.gnome.Builder.json
@@ -322,6 +322,15 @@
}
]
},
+ {
+ "name" : "glade",
+ "sources" : [
+ {
+ "type" : "git",
+ "url" : "https://gitlab.gnome.org/GNOME/glade.git"
+ }
+ ]
+ },
{
"name" : "sysprof",
"config-opts" : [
diff --git a/meson_options.txt b/meson_options.txt
index c87f021ab..24cc3dd8a 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -49,6 +49,7 @@ option('with_gdb', type: 'boolean')
option('with_gettext', type: 'boolean')
option('with_git', type: 'boolean')
option('with_gjs_symbols', type: 'boolean')
+option('with_glade', type: 'boolean')
option('with_gnome_code_assistance', type: 'boolean')
option('with_go_langserv', type: 'boolean')
option('with_history', type: 'boolean')
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 6a8372693..dfc7093f3 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -182,6 +182,12 @@ src/plugins/git/ide-git-pipeline-addin.c
src/plugins/git/ide-git-remote-callbacks.c
src/plugins/git/ide-git-submodule-stage.c
src/plugins/git/ide-git-vcs.c
+src/plugins/glade/gbp-glade-editor-addin.c
+src/plugins/glade/gbp-glade-layout-stack-addin.c
+src/plugins/glade/gbp-glade-properties.c
+src/plugins/glade/gbp-glade-properties.ui
+src/plugins/glade/gbp-glade-view.c
+src/plugins/glade/gbp-glade-view-actions.c
src/plugins/gnome-code-assistance/ide-gca-diagnostic-provider.c
src/plugins/gnome-code-assistance/ide-gca-preferences-addin.c
src/plugins/gnome-code-assistance/ide-gca-service.c
diff --git a/src/plugins/glade/gbp-glade-editor-addin.c b/src/plugins/glade/gbp-glade-editor-addin.c
new file mode 100644
index 000000000..97ba39dd3
--- /dev/null
+++ b/src/plugins/glade/gbp-glade-editor-addin.c
@@ -0,0 +1,240 @@
+/* gbp-glade-editor-addin.c
+ *
+ * Copyright 2018 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/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#include "config.h"
+
+#define G_LOG_DOMAIN "gbp-glade-editor-addin"
+
+#include <glib/gi18n.h>
+
+#include "gbp-glade-editor-addin.h"
+#include "gbp-glade-properties.h"
+#include "gbp-glade-view.h"
+
+struct _GbpGladeEditorAddin
+{
+ GObject parent_instance;
+
+ /* Widgets */
+ IdeEditorPerspective *editor;
+ GbpGladeProperties *properties;
+ GladeSignalEditor *signals;
+ DzlDockWidget *signals_dock;
+
+ /* Owned references */
+ DzlSignalGroup *project_signals;
+
+ guint has_hold : 1;
+};
+
+static void editor_addin_iface_init (IdeEditorAddinInterface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (GbpGladeEditorAddin, gbp_glade_editor_addin, G_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE (IDE_TYPE_EDITOR_ADDIN, editor_addin_iface_init))
+
+static void
+gbp_glade_editor_addin_dispose (GObject *object)
+{
+ GbpGladeEditorAddin *self = (GbpGladeEditorAddin *)object;
+
+ dzl_signal_group_set_target (self->project_signals, NULL);
+ g_clear_object (&self->project_signals);
+
+ G_OBJECT_CLASS (gbp_glade_editor_addin_parent_class)->dispose (object);
+}
+
+static void
+gbp_glade_editor_addin_class_init (GbpGladeEditorAddinClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->dispose = gbp_glade_editor_addin_dispose;
+}
+
+static void
+gbp_glade_editor_addin_selection_changed_cb (GbpGladeEditorAddin *self,
+ GladeProject *project)
+{
+ GList *selection = NULL;
+
+ g_assert (GBP_IS_GLADE_EDITOR_ADDIN (self));
+ g_assert (!project || GLADE_IS_PROJECT (project));
+
+ if (project != NULL)
+ selection = glade_project_selection_get (project);
+
+ if (selection != NULL && selection->next == NULL)
+ {
+ GtkWidget *widget = selection->data;
+ GladeWidget *glade = glade_widget_get_from_gobject (widget);
+
+ gbp_glade_properties_set_widget (self->properties, glade);
+ glade_signal_editor_load_widget (self->signals, glade);
+ gtk_widget_show (GTK_WIDGET (self->signals_dock));
+ }
+ else
+ {
+ gbp_glade_properties_set_widget (self->properties, NULL);
+ glade_signal_editor_load_widget (self->signals, NULL);
+ gtk_widget_hide (GTK_WIDGET (self->signals_dock));
+ }
+}
+
+static void
+gbp_glade_editor_addin_bind_cb (GbpGladeEditorAddin *self,
+ GladeProject *project,
+ DzlSignalGroup *project_signals)
+{
+ g_assert (GBP_IS_GLADE_EDITOR_ADDIN (self));
+ g_assert (GLADE_IS_PROJECT (project));
+ g_assert (DZL_IS_SIGNAL_GROUP (project_signals));
+
+ gbp_glade_editor_addin_selection_changed_cb (self, project);
+}
+
+static void
+gbp_glade_editor_addin_init (GbpGladeEditorAddin *self)
+{
+ self->project_signals = dzl_signal_group_new (GLADE_TYPE_PROJECT);
+
+ g_signal_connect_object (self->project_signals,
+ "bind",
+ G_CALLBACK (gbp_glade_editor_addin_bind_cb),
+ self,
+ G_CONNECT_SWAPPED);
+
+ dzl_signal_group_connect_object (self->project_signals,
+ "selection-changed",
+ G_CALLBACK (gbp_glade_editor_addin_selection_changed_cb),
+ self,
+ G_CONNECT_SWAPPED);
+}
+
+static void
+gbp_glade_editor_addin_set_project (GbpGladeEditorAddin *self,
+ GladeProject *project)
+{
+ g_assert (GBP_IS_GLADE_EDITOR_ADDIN (self));
+ g_assert (!project || GLADE_IS_PROJECT (project));
+
+ dzl_signal_group_set_target (self->project_signals, project);
+}
+
+static void
+gbp_glade_editor_addin_view_set (IdeEditorAddin *addin,
+ IdeLayoutView *view)
+{
+ GbpGladeEditorAddin *self = (GbpGladeEditorAddin *)addin;
+ IdeLayoutTransientSidebar *transient;
+ GladeProject *project = NULL;
+
+ g_assert (GBP_IS_GLADE_EDITOR_ADDIN (self));
+ g_assert (!view || IDE_IS_LAYOUT_VIEW (view));
+
+ transient = ide_editor_perspective_get_transient_sidebar (self->editor);
+
+ if (self->has_hold)
+ {
+ ide_layout_transient_sidebar_unlock (transient);
+ self->has_hold = FALSE;
+ }
+
+ if (GBP_IS_GLADE_VIEW (view))
+ {
+ project = gbp_glade_view_get_project (GBP_GLADE_VIEW (view));
+ ide_layout_transient_sidebar_set_view (transient, view);
+ ide_layout_transient_sidebar_lock (transient);
+ gtk_widget_show (GTK_WIDGET (transient));
+ dzl_dock_item_present (DZL_DOCK_ITEM (self->properties));
+ self->has_hold = TRUE;
+ }
+ else
+ {
+ gtk_widget_hide (GTK_WIDGET (self->signals_dock));
+ }
+
+ gbp_glade_editor_addin_set_project (self, project);
+}
+
+static void
+gbp_glade_editor_addin_load (IdeEditorAddin *addin,
+ IdeEditorPerspective *editor)
+{
+ GbpGladeEditorAddin *self = (GbpGladeEditorAddin *)addin;
+ IdeLayoutTransientSidebar *transient;
+ GtkWidget *utils;
+
+ g_assert (GBP_IS_GLADE_EDITOR_ADDIN (self));
+ g_assert (IDE_IS_EDITOR_PERSPECTIVE (editor));
+
+ self->editor = editor;
+
+ transient = ide_editor_perspective_get_transient_sidebar (self->editor);
+ utils = ide_editor_perspective_get_utilities (self->editor);
+
+ self->properties = g_object_new (GBP_TYPE_GLADE_PROPERTIES,
+ "visible", TRUE,
+ NULL);
+ gtk_container_add (GTK_CONTAINER (transient), GTK_WIDGET (self->properties));
+
+ self->signals_dock = g_object_new (DZL_TYPE_DOCK_WIDGET,
+ "title", _("Signals"),
+ "icon-name", "glade-symbolic",
+ "visible", TRUE,
+ NULL);
+ gtk_container_add (GTK_CONTAINER (utils), GTK_WIDGET (self->signals_dock));
+
+ self->signals = g_object_new (GLADE_TYPE_SIGNAL_EDITOR,
+ "visible", TRUE,
+ NULL);
+ gtk_container_add (GTK_CONTAINER (self->signals_dock), GTK_WIDGET (self->signals));
+}
+
+static void
+gbp_glade_editor_addin_unload (IdeEditorAddin *addin,
+ IdeEditorPerspective *editor)
+{
+ GbpGladeEditorAddin *self = (GbpGladeEditorAddin *)addin;
+ IdeLayoutTransientSidebar *transient;
+
+ g_assert (GBP_IS_GLADE_EDITOR_ADDIN (self));
+ g_assert (IDE_IS_EDITOR_PERSPECTIVE (editor));
+
+ transient = ide_editor_perspective_get_transient_sidebar (self->editor);
+
+ if (self->has_hold)
+ {
+ ide_layout_transient_sidebar_unlock (transient);
+ self->has_hold = FALSE;
+ }
+
+ gtk_widget_insert_action_group (GTK_WIDGET (editor), "glade", NULL);
+ gtk_widget_destroy (GTK_WIDGET (self->properties));
+
+ self->editor = NULL;
+}
+
+static void
+editor_addin_iface_init (IdeEditorAddinInterface *iface)
+{
+ iface->load = gbp_glade_editor_addin_load;
+ iface->unload = gbp_glade_editor_addin_unload;
+ iface->view_set = gbp_glade_editor_addin_view_set;
+}
diff --git a/src/plugins/glade/gbp-glade-editor-addin.h b/src/plugins/glade/gbp-glade-editor-addin.h
new file mode 100644
index 000000000..0124f88ff
--- /dev/null
+++ b/src/plugins/glade/gbp-glade-editor-addin.h
@@ -0,0 +1,33 @@
+/* gbp-glade-editor-addin.h
+ *
+ * Copyright 2018 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/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+
+#pragma once
+
+#include <gladeui/glade.h>
+#include <ide.h>
+
+G_BEGIN_DECLS
+
+#define GBP_TYPE_GLADE_EDITOR_ADDIN (gbp_glade_editor_addin_get_type())
+
+G_DECLARE_FINAL_TYPE (GbpGladeEditorAddin, gbp_glade_editor_addin, GBP, GLADE_EDITOR_ADDIN, GObject)
+
+G_END_DECLS
diff --git a/src/plugins/glade/gbp-glade-layout-stack-addin.c
b/src/plugins/glade/gbp-glade-layout-stack-addin.c
new file mode 100644
index 000000000..666fd2890
--- /dev/null
+++ b/src/plugins/glade/gbp-glade-layout-stack-addin.c
@@ -0,0 +1,227 @@
+/* gbp-glade-layout-stack-addin.c
+ *
+ * Copyright 2018 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/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#include "config.h"
+
+#define G_LOG_DOMAIN "gbp-glade-layout-stack-addin"
+
+#include <glib/gi18n.h>
+#include <gladeui/glade.h>
+
+#include "gbp-glade-layout-stack-addin.h"
+#include "gbp-glade-view.h"
+
+struct _GbpGladeLayoutStackAddin
+{
+ GObject parent_instance;
+ GtkMenuButton *button;
+ GtkLabel *label;
+ GtkImage *image;
+ GladeInspector *inspector;
+ DzlSignalGroup *project_signals;
+};
+
+static void layout_stack_addin_iface_init (IdeLayoutStackAddinInterface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (GbpGladeLayoutStackAddin, gbp_glade_layout_stack_addin, G_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE (IDE_TYPE_LAYOUT_STACK_ADDIN,
+ layout_stack_addin_iface_init))
+
+
+
+static void
+gbp_glade_layout_stack_addin_selection_changed_cb (GbpGladeLayoutStackAddin *self,
+ GladeProject *project)
+{
+ GList *selection = NULL;
+
+ g_assert (GBP_IS_GLADE_LAYOUT_STACK_ADDIN (self));
+ g_assert (!project || GLADE_IS_PROJECT (project));
+
+ if (project != NULL)
+ selection = glade_project_selection_get (project);
+
+ if (selection != NULL && selection->next == NULL)
+ {
+ GtkWidget *widget = selection->data;
+ GladeWidget *glade = glade_widget_get_from_gobject (widget);
+ GladeWidgetAdaptor *adapter = glade_widget_get_adaptor (glade);
+ g_autofree gchar *format = NULL;
+ const gchar *display_name;
+ const gchar *name;
+ const gchar *icon_name;
+
+ g_assert (GTK_IS_WIDGET (widget));
+
+ name = glade_widget_get_name (glade);
+ display_name = glade_widget_get_display_name (glade);
+ icon_name = glade_widget_adaptor_get_icon_name (adapter);
+
+ if (display_name != NULL &&
+ display_name[0] != '(' &&
+ name != NULL &&
+ !g_str_equal (display_name, name))
+ name = format = g_strdup_printf ("%s — %s", display_name, name);
+
+ gtk_label_set_label (GTK_LABEL (self->label), name);
+ g_object_set (self->image,
+ "icon-name", icon_name,
+ "visible", icon_name != NULL,
+ NULL);
+
+ return;
+ }
+
+ gtk_label_set_label (GTK_LABEL (self->label), _("Select Widget…"));
+ gtk_widget_hide (GTK_WIDGET (self->image));
+}
+
+static void
+gbp_glade_layout_stack_addin_dispose (GObject *object)
+{
+ GbpGladeLayoutStackAddin *self = (GbpGladeLayoutStackAddin *)object;
+
+ if (self->project_signals != NULL)
+ {
+ dzl_signal_group_set_target (self->project_signals, NULL);
+ g_clear_object (&self->project_signals);
+ }
+
+ G_OBJECT_CLASS (gbp_glade_layout_stack_addin_parent_class)->dispose (object);
+}
+
+static void
+gbp_glade_layout_stack_addin_class_init (GbpGladeLayoutStackAddinClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->dispose = gbp_glade_layout_stack_addin_dispose;
+}
+
+static void
+gbp_glade_layout_stack_addin_init (GbpGladeLayoutStackAddin *self)
+{
+ self->project_signals = dzl_signal_group_new (GLADE_TYPE_PROJECT);
+
+ dzl_signal_group_connect_object (self->project_signals,
+ "selection-changed",
+ G_CALLBACK (gbp_glade_layout_stack_addin_selection_changed_cb),
+ self,
+ G_CONNECT_SWAPPED);
+}
+
+static void
+gbp_glade_layout_stack_addin_load (IdeLayoutStackAddin *addin,
+ IdeLayoutStack *stack)
+{
+ GbpGladeLayoutStackAddin *self = (GbpGladeLayoutStackAddin *)addin;
+ GtkPopover *popover;
+ GtkWidget *header;
+ GtkBox *box;
+
+ g_assert (GBP_IS_GLADE_LAYOUT_STACK_ADDIN (self));
+ g_assert (IDE_IS_LAYOUT_STACK (stack));
+
+ header = ide_layout_stack_get_titlebar (stack);
+
+ popover = g_object_new (GTK_TYPE_POPOVER,
+ "width-request", 400,
+ "height-request", 400,
+ "position", GTK_POS_BOTTOM,
+ NULL);
+ dzl_gtk_widget_add_style_class (GTK_WIDGET (popover), "glade-stack-header");
+
+ self->button = g_object_new (GTK_TYPE_MENU_BUTTON,
+ "popover", popover,
+ "visible", FALSE,
+ NULL);
+ g_signal_connect (self->button,
+ "destroy",
+ G_CALLBACK (gtk_widget_destroyed),
+ &self->button);
+ ide_layout_stack_header_add_custom_title (IDE_LAYOUT_STACK_HEADER (header),
+ GTK_WIDGET (self->button),
+ 200);
+
+ box = g_object_new (GTK_TYPE_BOX,
+ "halign", GTK_ALIGN_CENTER,
+ "orientation", GTK_ORIENTATION_HORIZONTAL,
+ "spacing", 6,
+ "visible", TRUE,
+ NULL);
+ gtk_container_add (GTK_CONTAINER (self->button), GTK_WIDGET (box));
+
+ self->image = g_object_new (GTK_TYPE_IMAGE,
+ "icon-size", GTK_ICON_SIZE_MENU,
+ NULL);
+ gtk_container_add (GTK_CONTAINER (box), GTK_WIDGET (self->image));
+
+ self->label = g_object_new (GTK_TYPE_LABEL,
+ "label", _("Select Widget…"),
+ "visible", TRUE,
+ NULL);
+ gtk_container_add (GTK_CONTAINER (box), GTK_WIDGET (self->label));
+
+ self->inspector = g_object_new (GLADE_TYPE_INSPECTOR,
+ "visible", TRUE,
+ NULL);
+ gtk_container_add (GTK_CONTAINER (popover), GTK_WIDGET (self->inspector));
+}
+
+static void
+gbp_glade_layout_stack_addin_unload (IdeLayoutStackAddin *addin,
+ IdeLayoutStack *stack)
+{
+ GbpGladeLayoutStackAddin *self = (GbpGladeLayoutStackAddin *)addin;
+
+ g_assert (GBP_IS_GLADE_LAYOUT_STACK_ADDIN (self));
+ g_assert (IDE_IS_LAYOUT_STACK (stack));
+
+ if (self->button != NULL)
+ gtk_widget_destroy (GTK_WIDGET (self->button));
+}
+
+static void
+gbp_glade_layout_stack_addin_set_view (IdeLayoutStackAddin *addin,
+ IdeLayoutView *view)
+{
+ GbpGladeLayoutStackAddin *self = (GbpGladeLayoutStackAddin *)addin;
+ GladeProject *project = NULL;
+
+ g_assert (GBP_IS_GLADE_LAYOUT_STACK_ADDIN (self));
+ g_assert (!view || IDE_IS_LAYOUT_VIEW (view));
+
+ if (GBP_IS_GLADE_VIEW (view))
+ project = gbp_glade_view_get_project (GBP_GLADE_VIEW (view));
+
+ glade_inspector_set_project (self->inspector, project);
+ gtk_widget_set_visible (GTK_WIDGET (self->button), project != NULL);
+
+ dzl_signal_group_set_target (self->project_signals, project);
+ gbp_glade_layout_stack_addin_selection_changed_cb (self, project);
+}
+
+static void
+layout_stack_addin_iface_init (IdeLayoutStackAddinInterface *iface)
+{
+ iface->load = gbp_glade_layout_stack_addin_load;
+ iface->unload = gbp_glade_layout_stack_addin_unload;
+ iface->set_view = gbp_glade_layout_stack_addin_set_view;
+}
diff --git a/src/plugins/glade/gbp-glade-layout-stack-addin.h
b/src/plugins/glade/gbp-glade-layout-stack-addin.h
new file mode 100644
index 000000000..401762b53
--- /dev/null
+++ b/src/plugins/glade/gbp-glade-layout-stack-addin.h
@@ -0,0 +1,31 @@
+/* gbp-glade-layout-stack-addin.h
+ *
+ * Copyright 2018 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/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#pragma once
+
+#include <ide.h>
+
+G_BEGIN_DECLS
+
+#define GBP_TYPE_GLADE_LAYOUT_STACK_ADDIN (gbp_glade_layout_stack_addin_get_type())
+
+G_DECLARE_FINAL_TYPE (GbpGladeLayoutStackAddin, gbp_glade_layout_stack_addin, GBP, GLADE_LAYOUT_STACK_ADDIN,
GObject)
+
+G_END_DECLS
diff --git a/src/plugins/glade/gbp-glade-plugin.c b/src/plugins/glade/gbp-glade-plugin.c
new file mode 100644
index 000000000..6f6d784e1
--- /dev/null
+++ b/src/plugins/glade/gbp-glade-plugin.c
@@ -0,0 +1,40 @@
+/* gbp-glade-plugin.c
+ *
+ * Copyright 2018 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 "gbp-glade-plugin"
+
+#include <ide.h>
+#include <libpeas/peas.h>
+
+#include "gbp-glade-editor-addin.h"
+#include "gbp-glade-layout-stack-addin.h"
+#include "gbp-glade-workbench-addin.h"
+
+void
+gbp_glade_register_types (PeasObjectModule *module)
+{
+ peas_object_module_register_extension_type (module,
+ IDE_TYPE_EDITOR_ADDIN,
+ GBP_TYPE_GLADE_EDITOR_ADDIN);
+ peas_object_module_register_extension_type (module,
+ IDE_TYPE_LAYOUT_STACK_ADDIN,
+ GBP_TYPE_GLADE_LAYOUT_STACK_ADDIN);
+ peas_object_module_register_extension_type (module,
+ IDE_TYPE_WORKBENCH_ADDIN,
+ GBP_TYPE_GLADE_WORKBENCH_ADDIN);
+}
diff --git a/src/plugins/glade/gbp-glade-private.h b/src/plugins/glade/gbp-glade-private.h
new file mode 100644
index 000000000..f577b751c
--- /dev/null
+++ b/src/plugins/glade/gbp-glade-private.h
@@ -0,0 +1,40 @@
+/* gbp-glade-private.h
+ *
+ * Copyright 2018 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/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#pragma once
+
+#include <ide.h>
+#include <gladeui/glade.h>
+
+#include "gbp-glade-view.h"
+
+G_BEGIN_DECLS
+
+struct _GbpGladeView
+{
+ IdeLayoutView parent_instance;
+ GFile *file;
+ GladeProject *project;
+ GladeDesignView *designer;
+};
+
+void _gbp_glade_view_init_actions (GbpGladeView *self);
+
+G_END_DECLS
diff --git a/src/plugins/glade/gbp-glade-properties.c b/src/plugins/glade/gbp-glade-properties.c
new file mode 100644
index 000000000..3b5b0e53a
--- /dev/null
+++ b/src/plugins/glade/gbp-glade-properties.c
@@ -0,0 +1,125 @@
+/* gbp-glade-properties.c
+ *
+ * Copyright 2018 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/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#include "config.h"
+
+#define G_LOG_DOMAIN "gbp-glade-properties"
+
+#include <glib/gi18n.h>
+
+#include "gbp-glade-properties.h"
+
+struct _GbpGladeProperties
+{
+ DzlDockWidget parent_instance;
+ GtkStackSwitcher *stack_switcher;
+ GtkStack *stack;
+ DzlDockWidget *a11y_dock;
+ DzlDockWidget *common_dock;
+ DzlDockWidget *general_dock;
+ DzlDockWidget *packing_dock;
+};
+
+G_DEFINE_TYPE (GbpGladeProperties, gbp_glade_properties, DZL_TYPE_DOCK_WIDGET)
+
+static void
+adjust_radio_hexpand (GtkWidget *widget,
+ gpointer user_data)
+{
+ gtk_widget_set_hexpand (widget, TRUE);
+}
+
+static void
+gbp_glade_properties_class_init (GbpGladePropertiesClass *klass)
+{
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ gtk_widget_class_set_template_from_resource (widget_class,
"/org/gnome/builder/plugins/glade-plugin/gbp-glade-properties.ui");
+ gtk_widget_class_set_css_name (widget_class, "gbpgladeproperties");
+ gtk_widget_class_bind_template_child (widget_class, GbpGladeProperties, stack);
+ gtk_widget_class_bind_template_child (widget_class, GbpGladeProperties, stack_switcher);
+ gtk_widget_class_bind_template_child (widget_class, GbpGladeProperties, a11y_dock);
+ gtk_widget_class_bind_template_child (widget_class, GbpGladeProperties, common_dock);
+ gtk_widget_class_bind_template_child (widget_class, GbpGladeProperties, general_dock);
+ gtk_widget_class_bind_template_child (widget_class, GbpGladeProperties, packing_dock);
+}
+
+static void
+gbp_glade_properties_init (GbpGladeProperties *self)
+{
+ gtk_widget_init_template (GTK_WIDGET (self));
+
+ dzl_dock_widget_set_title (DZL_DOCK_WIDGET (self), _("Unnamed Glade Project"));
+ dzl_dock_widget_set_icon_name (DZL_DOCK_WIDGET (self), "glade-symbolic");
+
+ gtk_container_foreach (GTK_CONTAINER (self->stack_switcher), adjust_radio_hexpand, NULL);
+}
+
+void
+gbp_glade_properties_set_widget (GbpGladeProperties *self,
+ GladeWidget *widget)
+{
+ GladeWidgetAdaptor *adapter;
+ GladeEditable *editable;
+ GladeWidget *parent;
+
+ g_return_if_fail (GBP_IS_GLADE_PROPERTIES (self));
+ g_return_if_fail (!widget || GLADE_IS_WIDGET (widget));
+
+ gtk_container_foreach (GTK_CONTAINER (self->a11y_dock), (GtkCallback)gtk_widget_destroy, NULL);
+ gtk_container_foreach (GTK_CONTAINER (self->general_dock), (GtkCallback)gtk_widget_destroy, NULL);
+ gtk_container_foreach (GTK_CONTAINER (self->common_dock), (GtkCallback)gtk_widget_destroy, NULL);
+ gtk_container_foreach (GTK_CONTAINER (self->packing_dock), (GtkCallback)gtk_widget_destroy, NULL);
+
+ if (widget == NULL)
+ return;
+
+ adapter = glade_widget_get_adaptor (widget);
+
+ /* General page */
+ editable = glade_widget_adaptor_create_editable (adapter, GLADE_PAGE_GENERAL);
+ gtk_container_add (GTK_CONTAINER (self->general_dock), GTK_WIDGET (editable));
+ glade_editable_load (editable, widget);
+ gtk_widget_show (GTK_WIDGET (editable));
+
+ /* Packing page */
+ if ((parent = glade_widget_get_parent (widget)))
+ {
+ GladeWidgetAdaptor *parent_adapter;
+
+ parent_adapter = glade_widget_get_adaptor (parent);
+ editable = glade_widget_adaptor_create_editable (parent_adapter, GLADE_PAGE_PACKING);
+ gtk_container_add (GTK_CONTAINER (self->packing_dock), GTK_WIDGET (editable));
+ glade_editable_load (editable, widget);
+ gtk_widget_show (GTK_WIDGET (editable));
+ }
+
+ /* Common page */
+ editable = glade_widget_adaptor_create_editable (adapter, GLADE_PAGE_COMMON);
+ gtk_container_add (GTK_CONTAINER (self->common_dock), GTK_WIDGET (editable));
+ glade_editable_load (editable, widget);
+ gtk_widget_show (GTK_WIDGET (editable));
+
+ /* A11y page */
+ editable = glade_widget_adaptor_create_editable (adapter, GLADE_PAGE_ATK);
+ gtk_container_add (GTK_CONTAINER (self->a11y_dock), GTK_WIDGET (editable));
+ glade_editable_load (editable, widget);
+ gtk_widget_show (GTK_WIDGET (editable));
+}
diff --git a/src/plugins/glade/gbp-glade-properties.h b/src/plugins/glade/gbp-glade-properties.h
new file mode 100644
index 000000000..352b150b2
--- /dev/null
+++ b/src/plugins/glade/gbp-glade-properties.h
@@ -0,0 +1,35 @@
+/* gbp-glade-properties.h
+ *
+ * Copyright 2018 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/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#pragma once
+
+#include <gladeui/glade.h>
+#include <ide.h>
+
+G_BEGIN_DECLS
+
+#define GBP_TYPE_GLADE_PROPERTIES (gbp_glade_properties_get_type())
+
+G_DECLARE_FINAL_TYPE (GbpGladeProperties, gbp_glade_properties, GBP, GLADE_PROPERTIES, DzlDockWidget)
+
+void gbp_glade_properties_set_widget (GbpGladeProperties *self,
+ GladeWidget *widget);
+
+G_END_DECLS
diff --git a/src/plugins/glade/gbp-glade-properties.ui b/src/plugins/glade/gbp-glade-properties.ui
new file mode 100644
index 000000000..b748d0726
--- /dev/null
+++ b/src/plugins/glade/gbp-glade-properties.ui
@@ -0,0 +1,77 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <template class="GbpGladeProperties" parent="DzlDockWidget">
+ <child>
+ <object class="GtkScrolledWindow">
+ <property name="hscrollbar-policy">never</property>
+ <property name="visible">true</property>
+ <child>
+ <object class="GtkBox">
+ <property name="border-width">6</property>
+ <property name="spacing">6</property>
+ <property name="vexpand">true</property>
+ <property name="orientation">vertical</property>
+ <property name="visible">true</property>
+ <child>
+ <object class="GtkStackSwitcher" id="stack_switcher">
+ <property name="halign">fill</property>
+ <property name="hexpand">true</property>
+ <property name="stack">stack</property>
+ <property name="visible">true</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkStack" id="stack">
+ <property name="interpolate-size">true</property>
+ <property name="transition-type">crossfade</property>
+ <property name="homogeneous">false</property>
+ <property name="vexpand">true</property>
+ <property name="visible">true</property>
+ <child>
+ <object class="DzlDockWidget" id="general_dock">
+ <property name="visible">true</property>
+ </object>
+ <packing>
+ <property name="name">general</property>
+ <property name="title" translatable="yes">General</property>
+ <property name="icon-name">system-run-symbolic</property>
+ </packing>
+ </child>
+ <child>
+ <object class="DzlDockWidget" id="packing_dock">
+ <property name="visible">true</property>
+ </object>
+ <packing>
+ <property name="name">packing</property>
+ <property name="title" translatable="yes">Packing</property>
+ <property name="icon-name">system-run-symbolic</property>
+ </packing>
+ </child>
+ <child>
+ <object class="DzlDockWidget" id="common_dock">
+ <property name="visible">true</property>
+ </object>
+ <packing>
+ <property name="name">common</property>
+ <property name="title" translatable="yes">Common</property>
+ <property name="icon-name">system-run-symbolic</property>
+ </packing>
+ </child>
+ <child>
+ <object class="DzlDockWidget" id="a11y_dock">
+ <property name="visible">true</property>
+ </object>
+ <packing>
+ <property name="name">a11y</property>
+ <property name="title" translatable="yes">Accessibility</property>
+ <property name="icon-name">preferences-desktop-accessibility-symbolic</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </template>
+</interface>
diff --git a/src/plugins/glade/gbp-glade-view-actions.c b/src/plugins/glade/gbp-glade-view-actions.c
new file mode 100644
index 000000000..2de792da3
--- /dev/null
+++ b/src/plugins/glade/gbp-glade-view-actions.c
@@ -0,0 +1,71 @@
+/* gbp-glade-view-actions.c
+ *
+ * Copyright 2018 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/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#include "config.h"
+
+#define G_LOG_DOMAIN "gbp-glade-view-actions"
+
+#include <glib/gi18n.h>
+
+#include "gbp-glade-private.h"
+
+static void
+gbp_glade_view_action_save (GSimpleAction *action,
+ GVariant *param,
+ gpointer user_data)
+{
+ GbpGladeView *self = user_data;
+ g_autoptr(GError) error = NULL;
+ const gchar *path;
+
+ g_assert (G_IS_SIMPLE_ACTION (action));
+ g_assert (GBP_IS_GLADE_VIEW (self));
+
+ if (self->file == NULL || !(path = g_file_peek_path (self->file)))
+ {
+ g_warning ("GbpGladeView is missing a file");
+ return;
+ }
+
+ if (!glade_project_save (self->project, path, &error))
+ /* translators: %s is replaced with the specific error message */
+ ide_widget_warning (self, _("Failed to save glade document: %s"), error->message);
+}
+
+static GActionEntry actions[] = {
+ { "save", gbp_glade_view_action_save },
+};
+
+void
+_gbp_glade_view_init_actions (GbpGladeView *self)
+{
+ g_autoptr(GSimpleActionGroup) group = NULL;
+
+ g_assert (GBP_IS_GLADE_VIEW (self));
+
+ group = g_simple_action_group_new ();
+ g_action_map_add_action_entries (G_ACTION_MAP (group),
+ actions,
+ G_N_ELEMENTS (actions),
+ self);
+ gtk_widget_insert_action_group (GTK_WIDGET (self),
+ "glade-view",
+ G_ACTION_GROUP (group));
+}
diff --git a/src/plugins/glade/gbp-glade-view.c b/src/plugins/glade/gbp-glade-view.c
new file mode 100644
index 000000000..2993871a6
--- /dev/null
+++ b/src/plugins/glade/gbp-glade-view.c
@@ -0,0 +1,189 @@
+/* gbp-glade-view.c
+ *
+ * Copyright 2018 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/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#include "config.h"
+
+#define G_LOG_DOMAIN "gbp-glade-view"
+
+#include <glib/gi18n.h>
+
+#include "gbp-glade-view.h"
+#include "gbp-glade-private.h"
+
+G_DEFINE_TYPE (GbpGladeView, gbp_glade_view, IDE_TYPE_LAYOUT_VIEW)
+
+/**
+ * gbp_glade_view_new:
+ *
+ * Create a new #GbpGladeView.
+ *
+ * Returns: (transfer full): a newly created #GbpGladeView
+ */
+GbpGladeView *
+gbp_glade_view_new (void)
+{
+ return g_object_new (GBP_TYPE_GLADE_VIEW, NULL);
+}
+
+static void
+gbp_glade_view_dispose (GObject *object)
+{
+ GbpGladeView *self = (GbpGladeView *)object;
+
+ g_clear_object (&self->project);
+
+ G_OBJECT_CLASS (gbp_glade_view_parent_class)->dispose (object);
+}
+
+static void
+gbp_glade_view_class_init (GbpGladeViewClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->dispose = gbp_glade_view_dispose;
+
+ gtk_widget_class_set_css_name (widget_class, "gbpgladeview");
+}
+
+static void
+gbp_glade_view_init (GbpGladeView *self)
+{
+ ide_layout_view_set_menu_id (IDE_LAYOUT_VIEW (self), "gbp-glade-view-menu");
+ ide_layout_view_set_title (IDE_LAYOUT_VIEW (self), _("Unnamed Glade project"));
+ ide_layout_view_set_icon_name (IDE_LAYOUT_VIEW (self), "glade-symbolic");
+ ide_layout_view_set_menu_id (IDE_LAYOUT_VIEW (self), "gbp-glade-view-document-menu");
+
+ self->project = glade_project_new ();
+ self->designer = g_object_new (GLADE_TYPE_DESIGN_VIEW,
+ "project", self->project,
+ "vexpand", TRUE,
+ "visible", TRUE,
+ NULL);
+ dzl_gtk_widget_add_style_class (GTK_WIDGET (self->designer), "glade-designer");
+ gtk_container_add (GTK_CONTAINER (self), GTK_WIDGET (self->designer));
+
+ glade_app_add_project (self->project);
+
+ g_object_bind_property (G_OBJECT (self->project), "modified", self, "modified", G_BINDING_DEFAULT);
+
+ _gbp_glade_view_init_actions (self);
+}
+
+/**
+ * gbp_glade_view_get_project:
+ *
+ * Returns: (transfer none): A #GladeProject or %NULL
+ */
+GladeProject *
+gbp_glade_view_get_project (GbpGladeView *self)
+{
+ g_return_val_if_fail (GBP_IS_GLADE_VIEW (self), NULL);
+
+ return self->project;
+}
+
+static void
+gbp_glade_view_load_file_map_cb (GladeDesignView *designer,
+ IdeTask *task)
+{
+ g_autofree gchar *name = NULL;
+ GbpGladeView *self;
+ const gchar *path;
+ GFile *file;
+
+ g_assert (GLADE_IS_DESIGN_VIEW (designer));
+ g_assert (IDE_IS_TASK (task));
+ g_assert (gtk_widget_get_mapped (GTK_WIDGET (designer)));
+
+ self = ide_task_get_source_object (task);
+ file = ide_task_get_task_data (task);
+
+ g_signal_handlers_disconnect_by_func (self->designer,
+ G_CALLBACK (gbp_glade_view_load_file_map_cb),
+ task);
+
+ if (!g_file_is_native (file))
+ {
+ ide_task_return_new_error (task,
+ G_IO_ERROR,
+ G_IO_ERROR_INVALID_FILENAME,
+ "File must be a local file");
+ return;
+ }
+
+ path = g_file_peek_path (file);
+
+ if (!glade_project_load_from_file (self->project, path))
+ ide_task_return_new_error (task,
+ G_IO_ERROR,
+ G_IO_ERROR_FAILED,
+ "Failed to load glade project");
+ else
+ ide_task_return_boolean (task, TRUE);
+
+ name = glade_project_get_name (self->project);
+ ide_layout_view_set_title (IDE_LAYOUT_VIEW (self), name);
+}
+
+void
+gbp_glade_view_load_file_async (GbpGladeView *self,
+ GFile *file,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_autoptr(IdeTask) task = NULL;
+
+ g_return_if_fail (GBP_IS_GLADE_VIEW (self));
+ g_return_if_fail (G_IS_FILE (file));
+ g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable));
+
+ task = ide_task_new (self, cancellable, callback, user_data);
+ ide_task_set_source_tag (task, gbp_glade_view_load_file_async);
+ ide_task_set_task_data (task, g_object_ref (file), g_object_unref);
+
+ g_set_object (&self->file, file);
+
+ /* We can't load the file until we have been mapped or else we see an issue
+ * where toplevels cannot be parented properly. If we come across that, then
+ * delay until the widget is mapped.
+ */
+ if (!gtk_widget_get_mapped (GTK_WIDGET (self->designer)))
+ g_signal_connect_data (self->designer,
+ "map",
+ G_CALLBACK (gbp_glade_view_load_file_map_cb),
+ g_steal_pointer (&task),
+ (GClosureNotify)g_object_unref,
+ 0);
+ else
+ gbp_glade_view_load_file_map_cb (self->designer, task);
+}
+
+gboolean
+gbp_glade_view_load_file_finish (GbpGladeView *self,
+ GAsyncResult *result,
+ GError **error)
+{
+ g_return_val_if_fail (GBP_IS_GLADE_VIEW (self), FALSE);
+ g_return_val_if_fail (IDE_IS_TASK (result), FALSE);
+
+ return ide_task_propagate_boolean (IDE_TASK (result), error);
+}
diff --git a/src/plugins/glade/gbp-glade-view.h b/src/plugins/glade/gbp-glade-view.h
new file mode 100644
index 000000000..c82a447ac
--- /dev/null
+++ b/src/plugins/glade/gbp-glade-view.h
@@ -0,0 +1,43 @@
+/* gbp-glade-view.h
+ *
+ * Copyright 2018 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/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#pragma once
+
+#include <gladeui/glade.h>
+#include <ide.h>
+
+G_BEGIN_DECLS
+
+#define GBP_TYPE_GLADE_VIEW (gbp_glade_view_get_type())
+
+G_DECLARE_FINAL_TYPE (GbpGladeView, gbp_glade_view, GBP, GLADE_VIEW, IdeLayoutView)
+
+GbpGladeView *gbp_glade_view_new (void);
+void gbp_glade_view_load_file_async (GbpGladeView *self,
+ GFile *file,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+gboolean gbp_glade_view_load_file_finish (GbpGladeView *self,
+ GAsyncResult *result,
+ GError **error);
+GladeProject *gbp_glade_view_get_project (GbpGladeView *self);
+
+G_END_DECLS
diff --git a/src/plugins/glade/gbp-glade-workbench-addin.c b/src/plugins/glade/gbp-glade-workbench-addin.c
new file mode 100644
index 000000000..fefd72b3b
--- /dev/null
+++ b/src/plugins/glade/gbp-glade-workbench-addin.c
@@ -0,0 +1,172 @@
+/* gbp-glade-workbench-addin.c
+ *
+ * Copyright 2018 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/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#include "config.h"
+
+#define G_LOG_DOMAIN "gbp-glade-workbench-addin"
+
+#include "gbp-glade-view.h"
+#include "gbp-glade-workbench-addin.h"
+
+struct _GbpGladeWorkbenchAddin
+{
+ GObject parent_instance;
+ IdeWorkbench *workbench;
+};
+
+static gchar *
+gbp_glade_workbench_addin_get_id (IdeWorkbenchAddin *addin)
+{
+ return g_strdup ("glade");
+}
+
+static gboolean
+gbp_glade_workbench_addin_can_open (IdeWorkbenchAddin *addin,
+ IdeUri *uri,
+ const gchar *content_type,
+ gint *priority)
+{
+ g_assert (GBP_IS_GLADE_WORKBENCH_ADDIN (addin));
+ g_assert (priority != NULL);
+
+ if (g_strcmp0 (content_type, "application/x-gtk-builder") == 0 ||
+ g_strcmp0 (content_type, "application/x-designer") == 0)
+ {
+ *priority = -100;
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static void
+gbp_glade_workbench_addin_open_cb (GObject *object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ GbpGladeView *view = (GbpGladeView *)object;
+ g_autoptr(GError) error = NULL;
+ g_autoptr(IdeTask) task = user_data;
+
+ g_assert (GBP_IS_GLADE_VIEW (view));
+ g_assert (G_IS_ASYNC_RESULT (result));
+ g_assert (IDE_IS_TASK (task));
+
+ if (!gbp_glade_view_load_file_finish (view, result, &error))
+ ide_task_return_error (task, g_steal_pointer (&error));
+ else
+ ide_task_return_boolean (task, TRUE);
+}
+
+static void
+gbp_glade_workbench_addin_open_async (IdeWorkbenchAddin *addin,
+ IdeUri *uri,
+ const gchar *content_type,
+ IdeWorkbenchOpenFlags flags,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GbpGladeWorkbenchAddin *self = (GbpGladeWorkbenchAddin *)addin;
+ g_autoptr(IdeTask) task = NULL;
+ g_autoptr(GFile) file = NULL;
+ IdePerspective *editor;
+ GbpGladeView *view;
+
+ g_assert (GBP_IS_GLADE_WORKBENCH_ADDIN (self));
+ g_assert (IDE_IS_WORKBENCH (self->workbench));
+ g_assert (uri != NULL);
+ g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));
+
+ task = ide_task_new (self, cancellable, callback, user_data);
+ ide_task_set_source_tag (task, gbp_glade_workbench_addin_open_async);
+
+ editor = ide_workbench_get_perspective_by_name (self->workbench, "editor");
+ file = ide_uri_to_file (uri);
+
+ view = gbp_glade_view_new ();
+ gtk_container_add (GTK_CONTAINER (editor), GTK_WIDGET (view));
+ gtk_widget_show (GTK_WIDGET (view));
+
+ gbp_glade_view_load_file_async (view,
+ file,
+ cancellable,
+ gbp_glade_workbench_addin_open_cb,
+ g_steal_pointer (&task));
+}
+
+static gboolean
+gbp_glade_workbench_addin_open_finish (IdeWorkbenchAddin *addin,
+ GAsyncResult *result,
+ GError **error)
+{
+ g_assert (GBP_IS_GLADE_WORKBENCH_ADDIN (addin));
+ g_assert (IDE_IS_TASK (result));
+
+ return ide_task_propagate_boolean (IDE_TASK (result), error);
+}
+
+static void
+gbp_glade_workbench_addin_load (IdeWorkbenchAddin *addin,
+ IdeWorkbench *workbench)
+{
+ GbpGladeWorkbenchAddin *self = (GbpGladeWorkbenchAddin *)addin;
+
+ g_assert (GBP_IS_GLADE_WORKBENCH_ADDIN (self));
+ g_assert (IDE_IS_WORKBENCH (workbench));
+
+ self->workbench = workbench;
+}
+
+static void
+gbp_glade_workbench_addin_unload (IdeWorkbenchAddin *addin,
+ IdeWorkbench *workbench)
+{
+ GbpGladeWorkbenchAddin *self = (GbpGladeWorkbenchAddin *)addin;
+
+ g_assert (GBP_IS_GLADE_WORKBENCH_ADDIN (self));
+ g_assert (IDE_IS_WORKBENCH (workbench));
+
+ self->workbench = NULL;
+}
+
+static void
+workbench_addin_iface_init (IdeWorkbenchAddinInterface *iface)
+{
+ iface->get_id = gbp_glade_workbench_addin_get_id;
+ iface->load = gbp_glade_workbench_addin_load;
+ iface->unload = gbp_glade_workbench_addin_unload;
+ iface->can_open = gbp_glade_workbench_addin_can_open;
+ iface->open_async = gbp_glade_workbench_addin_open_async;
+ iface->open_finish = gbp_glade_workbench_addin_open_finish;
+}
+
+G_DEFINE_TYPE_WITH_CODE (GbpGladeWorkbenchAddin, gbp_glade_workbench_addin, G_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE (IDE_TYPE_WORKBENCH_ADDIN, workbench_addin_iface_init))
+
+static void
+gbp_glade_workbench_addin_class_init (GbpGladeWorkbenchAddinClass *klass)
+{
+}
+
+static void
+gbp_glade_workbench_addin_init (GbpGladeWorkbenchAddin *self)
+{
+}
diff --git a/src/plugins/glade/gbp-glade-workbench-addin.h b/src/plugins/glade/gbp-glade-workbench-addin.h
new file mode 100644
index 000000000..1310d7178
--- /dev/null
+++ b/src/plugins/glade/gbp-glade-workbench-addin.h
@@ -0,0 +1,31 @@
+/* gbp-glade-workbench-addin.h
+ *
+ * Copyright 2018 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/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#pragma once
+
+#include <ide.h>
+
+G_BEGIN_DECLS
+
+#define GBP_TYPE_GLADE_WORKBENCH_ADDIN (gbp_glade_workbench_addin_get_type())
+
+G_DECLARE_FINAL_TYPE (GbpGladeWorkbenchAddin, gbp_glade_workbench_addin, GBP, GLADE_WORKBENCH_ADDIN, GObject)
+
+G_END_DECLS
diff --git a/src/plugins/glade/glade.gresource.xml b/src/plugins/glade/glade.gresource.xml
new file mode 100644
index 000000000..fc9b5e994
--- /dev/null
+++ b/src/plugins/glade/glade.gresource.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<gresources>
+ <gresource prefix="/org/gnome/builder/plugins">
+ <file>glade.plugin</file>
+ </gresource>
+ <gresource prefix="/org/gnome/builder/plugins/glade-plugin">
+ <file>gtk/menus.ui</file>
+
+ <file>gbp-glade-properties.ui</file>
+
+ <file>themes/shared.css</file>
+ <file>themes/Adwaita.css</file>
+ <file>themes/Adwaita-dark.css</file>
+ <file>themes/Adwaita-shared.css</file>
+ </gresource>
+</gresources>
diff --git a/src/plugins/glade/glade.plugin b/src/plugins/glade/glade.plugin
new file mode 100644
index 000000000..d818163e1
--- /dev/null
+++ b/src/plugins/glade/glade.plugin
@@ -0,0 +1,9 @@
+[Plugin]
+Module=glade-plugin
+Name=Glade
+Description=Integration with Glade UI designer for Gtk
+Authors=Christian Hergert <christian hergert me>
+Copyright=Copyright © 2018 Christian Hergert
+Depends=editor;
+Builtin=true
+Embedded=gbp_glade_register_types
diff --git a/src/plugins/glade/gtk/menus.ui b/src/plugins/glade/gtk/menus.ui
new file mode 100644
index 000000000..9c18b6883
--- /dev/null
+++ b/src/plugins/glade/gtk/menus.ui
@@ -0,0 +1,14 @@
+<?xml version="1.0"?>
+<interface>
+ <menu id="gbp-glade-view-document-menu">
+ <section id="glade-document-section">
+ <attribute name="label" translatable="yes">Glade</attribute>
+ <item>
+ <attribute name="action">glade-view.save</attribute>
+ <attribute name="label" translatable="yes">_Save</attribute>
+ <attribute name="accel"><primary>s</attribute>
+ </item>
+ </section>
+ </menu>
+</interface>
+
diff --git a/src/plugins/glade/meson.build b/src/plugins/glade/meson.build
new file mode 100644
index 000000000..190fedaa1
--- /dev/null
+++ b/src/plugins/glade/meson.build
@@ -0,0 +1,26 @@
+if get_option('with_glade')
+
+glade_resources = gnome.compile_resources(
+ 'glade-resources',
+ 'glade.gresource.xml',
+ c_name: 'gbp_glade',
+)
+
+glade_sources = [
+ 'gbp-glade-editor-addin.c',
+ 'gbp-glade-layout-stack-addin.c',
+ 'gbp-glade-plugin.c',
+ 'gbp-glade-properties.c',
+ 'gbp-glade-view.c',
+ 'gbp-glade-view-actions.c',
+ 'gbp-glade-workbench-addin.c',
+]
+
+gnome_builder_plugins_deps += [
+ dependency('gladeui-2.0', version: '>=3.22.0'),
+]
+
+gnome_builder_plugins_sources += files(glade_sources)
+gnome_builder_plugins_sources += glade_resources[0]
+
+endif
diff --git a/src/plugins/glade/themes/Adwaita-dark.css b/src/plugins/glade/themes/Adwaita-dark.css
new file mode 100644
index 000000000..d07260036
--- /dev/null
+++ b/src/plugins/glade/themes/Adwaita-dark.css
@@ -0,0 +1,9 @@
+@import url("resource:///org/gnome/builder/plugins/glade-plugin/themes/Adwaita-shared.css");
+
+/* Draw our grid over the glade background pattern */
+gbpgladeview viewport {
+ background-color: #232729;
+ background-size: 8px 8px;
+ background-image: repeating-linear-gradient(0deg, #2e2e2e, #2e2e2e 1px, transparent 1px, transparent 8px),
+ repeating-linear-gradient(-90deg, #2e2e2e, #2e2e2e 1px, transparent 1px, transparent
8px);
+}
diff --git a/src/plugins/glade/themes/Adwaita-shared.css b/src/plugins/glade/themes/Adwaita-shared.css
new file mode 100644
index 000000000..600aafbdb
--- /dev/null
+++ b/src/plugins/glade/themes/Adwaita-shared.css
@@ -0,0 +1,37 @@
+@import url("resource:///org/gnome/builder/plugins/glade-plugin/themes/shared.css");
+
+gbpgladeproperties {
+ font-size: 0.83333em;
+}
+
+gbpgladeproperties entry,
+gbpgladeproperties spinbutton {
+ min-height: 24px;
+}
+
+gbpgladeproperties checkbutton check {
+ min-width: 10px;
+ min-height: 10px;
+}
+
+gbpgladeproperties spinbutton button {
+ min-height: 0px;
+ min-width: 0px;
+ padding: 0 4px;
+}
+
+gbpgladeproperties spinbutton entry {
+ min-height: 0px;
+ min-width: 0px;
+ padding: 0 4px;
+}
+
+gbpgladeproperties switch slider {
+ min-height: 18px;
+ min-width: 32px;
+}
+
+gbpgladeproperties button.combo {
+ min-height: 18px;
+ padding: 2px;
+}
diff --git a/src/plugins/glade/themes/Adwaita.css b/src/plugins/glade/themes/Adwaita.css
new file mode 100644
index 000000000..f7efb392b
--- /dev/null
+++ b/src/plugins/glade/themes/Adwaita.css
@@ -0,0 +1,9 @@
+@import url("resource:///org/gnome/builder/plugins/glade-plugin/themes/Adwaita-shared.css");
+
+/* Draw our grid over the glade background pattern */
+gbpgladeview viewport {
+ background-color: #f6f7f8;
+ background-size: 8px 8px;
+ background-image: repeating-linear-gradient(0deg, #f0f1f2, #f0f1f2 1px, transparent 1px, transparent 8px),
+ repeating-linear-gradient(-90deg, #f0f1f2, #f0f1f2 1px, transparent 1px, transparent
8px);
+}
diff --git a/src/plugins/glade/themes/shared.css b/src/plugins/glade/themes/shared.css
new file mode 100644
index 000000000..d1a3e856e
--- /dev/null
+++ b/src/plugins/glade/themes/shared.css
@@ -0,0 +1,23 @@
+gbpgladeproperties {
+ font-size: 0.83333em;
+}
+
+popover.glade-stack-header {
+ padding: 12px;
+}
+
+popover.glade-stack-header treeview {
+ background: transparent;
+ margin: 12px;
+ color: @theme_fg_color;
+}
+
+popover.glade-stack-header scrolledwindow {
+ border: none;
+}
+
+popover.glade-stack-header entry {
+ margin-bottom: 12px;
+}
+
+
diff --git a/src/plugins/meson.build b/src/plugins/meson.build
index f5a60d7b0..9ca823dae 100644
--- a/src/plugins/meson.build
+++ b/src/plugins/meson.build
@@ -34,6 +34,7 @@ subdir('gdb')
subdir('gettext')
subdir('git')
subdir('gjs-symbols')
+subdir('glade')
subdir('gnome-code-assistance')
subdir('go-langserv')
subdir('history')
@@ -118,6 +119,7 @@ status += [
'Gettext ............... : @0@'.format(get_option('with_gettext')),
'Git ................... : @0@'.format(get_option('with_git')),
'GJS Symbol Resolver ... : @0@'.format(get_option('with_gjs_symbols')),
+ 'Glade ................. : @0@'.format(get_option('with_glade')),
'GNOME Code Assistance . : @0@'.format(get_option('with_gnome_code_assistance')),
'Go Language Server .... : @0@'.format(get_option('with_go_langserv')),
'History ............... : @0@'.format(get_option('with_history')),
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]