[gnome-builder/wip/chergert/debugger: 9/100] debugger: stub out various debugger API mechanics
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-builder/wip/chergert/debugger: 9/100] debugger: stub out various debugger API mechanics
- Date: Fri, 14 Apr 2017 21:32:14 +0000 (UTC)
commit 3ca53529f57c68414a6ce114ca578d1c4e7b78e0
Author: Christian Hergert <chergert redhat com>
Date: Tue Mar 21 00:52:54 2017 -0700
debugger: stub out various debugger API mechanics
data/icons/hicolor/icons.gresource.xml | 1 +
.../scalable/actions/builder-debugger-symbolic.svg | 27 ++
libide/Makefile.am | 15 +
libide/debugger/debugger.plugin | 10 +
libide/debugger/ide-debug-manager.c | 178 ++++++++++++
libide/debugger/ide-debug-manager.h | 36 +++
libide/debugger/ide-debugger-breakpoints.c | 292 ++++++++++++++++++++
libide/debugger/ide-debugger-breakpoints.h | 49 ++++
libide/debugger/ide-debugger-controls.c | 40 +++
libide/debugger/ide-debugger-controls.h | 38 +++
libide/debugger/ide-debugger-controls.ui | 92 ++++++
libide/debugger/ide-debugger-editor-view-addin.c | 161 +++++++++++
libide/debugger/ide-debugger-editor-view-addin.h | 32 +++
libide/debugger/ide-debugger-gutter-renderer.c | 280 +++++++++++++++++++
libide/debugger/ide-debugger-gutter-renderer.h | 35 +++
libide/debugger/ide-debugger-perspective.c | 126 +++++++++
libide/debugger/ide-debugger-perspective.h | 32 +++
libide/debugger/ide-debugger-perspective.ui | 5 +
libide/debugger/ide-debugger-plugin.c | 35 +++
libide/debugger/ide-debugger-workbench-addin.c | 175 ++++++++++++
libide/debugger/ide-debugger-workbench-addin.h | 32 +++
libide/ide-context.c | 22 ++
libide/ide-context.h | 1 +
libide/ide-types.h | 3 +
libide/resources/libide.gresource.xml | 10 +-
25 files changed, 1725 insertions(+), 2 deletions(-)
---
diff --git a/data/icons/hicolor/icons.gresource.xml b/data/icons/hicolor/icons.gresource.xml
index d078183..1ced982 100644
--- a/data/icons/hicolor/icons.gresource.xml
+++ b/data/icons/hicolor/icons.gresource.xml
@@ -3,6 +3,7 @@
<gresource prefix="/org/gnome/builder/icons">
<file compressed="true">scalable/actions/builder-build-configure-symbolic.svg</file>
<file compressed="true">scalable/actions/builder-build-symbolic.svg</file>
+ <file compressed="true">scalable/actions/builder-debugger-symbolic.svg</file>
<file compressed="true">scalable/actions/builder-move-left-symbolic.svg</file>
<file compressed="true">scalable/actions/builder-move-right-symbolic.svg</file>
<file compressed="true">scalable/actions/builder-split-tab-left-symbolic.svg</file>
diff --git a/data/icons/hicolor/scalable/actions/builder-debugger-symbolic.svg
b/data/icons/hicolor/scalable/actions/builder-debugger-symbolic.svg
new file mode 100644
index 0000000..8aac791
--- /dev/null
+++ b/data/icons/hicolor/scalable/actions/builder-debugger-symbolic.svg
@@ -0,0 +1,27 @@
+<?xml version='1.0' encoding='UTF-8' standalone='no'?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg xmlns:cc='http://creativecommons.org/ns#' xmlns:dc='http://purl.org/dc/elements/1.1/'
sodipodi:docname='nemiver-symbolic.svg' height='16' id='svg7384'
xmlns:inkscape='http://www.inkscape.org/namespaces/inkscape'
xmlns:osb='http://www.openswatchbook.org/uri/2009/osb'
xmlns:rdf='http://www.w3.org/1999/02/22-rdf-syntax-ns#'
xmlns:sodipodi='http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd' xmlns:svg='http://www.w3.org/2000/svg'
version='1.1' inkscape:version='0.91 r13725' width='16' xmlns='http://www.w3.org/2000/svg'>
+ <metadata id='metadata90'>
+ <rdf:RDF>
+ <cc:Work rdf:about=''>
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type rdf:resource='http://purl.org/dc/dcmitype/StillImage'/>
+ <dc:title>Gnome Symbolic Icon Theme</dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview inkscape:bbox-paths='true' bordercolor='#666666' borderopacity='1'
inkscape:current-layer='layer9' inkscape:cx='5.1146516' inkscape:cy='-47.54864' gridtolerance='10'
inkscape:guide-bbox='true' guidetolerance='10' id='namedview88' inkscape:object-nodes='false'
inkscape:object-paths='false' objecttolerance='10' pagecolor='#555753' inkscape:pageopacity='1'
inkscape:pageshadow='2' showborder='false' showgrid='false' showguides='true' inkscape:snap-bbox='true'
inkscape:snap-bbox-midpoints='false' inkscape:snap-global='true' inkscape:snap-grids='true'
inkscape:snap-nodes='true' inkscape:snap-others='false' inkscape:snap-to-guides='true'
inkscape:window-height='1376' inkscape:window-maximized='1' inkscape:window-width='2560'
inkscape:window-x='0' inkscape:window-y='27' inkscape:zoom='4'>
+ <inkscape:grid empspacing='2' enabled='true' id='grid4866' originx='-162' originy='-382'
snapvisiblegridlinesonly='true' spacingx='1px' spacingy='1px' type='xygrid' visible='true'/>
+ </sodipodi:namedview>
+ <title id='title9167'>Gnome Symbolic Icon Theme</title>
+ <defs id='defs7386'>
+ <linearGradient id='linearGradient7212' osb:paint='solid'>
+ <stop id='stop7214' offset='0' style='stop-color:#000000;stop-opacity:1;'/>
+ </linearGradient>
+ </defs>
+ <g inkscape:groupmode='layer' id='layer9' inkscape:label='apps' style='display:inline'
transform='translate(-403.0002,165)'>
+
+ <path inkscape:connector-curvature='0' d='m 409.46895,-165 c -0.25969,0 -0.46875,0.20906
-0.46875,0.46875 l 0,1.875 c -1.03854,0.49004 -1.79689,1.48201 -1.96875,2.65625 l 6.9375,0 c
-0.17186,-1.17424 -0.93021,-2.16621 -1.96875,-2.65625 l 0,-1.875 c 0,-0.25969 -0.20906,-0.46875
-0.46875,-0.46875 z m 0.0312,1 c 0.27614,0 0.5,0.22386 0.5,0.5 0,0.27614 -0.22386,0.5 -0.5,0.5 -0.27614,0
-0.5,-0.22386 -0.5,-0.5 0,-0.27614 0.22386,-0.5 0.5,-0.5 z m -2.5,5 0,1 4.5,0 c 0.26179,3e-5 0.49997,0.23821
0.5,0.5 l 0,6 c -3e-5,0.26179 -0.23821,0.49997 -0.5,0.5 l -4.5,0 0,0.96875 c 0,0.57402 0.45723,1.03125
1.03125,1.03125 l 4.9375,0 c 0.57402,0 1.03125,-0.45723 1.03125,-1.03125 l 0,-8.96875 z m 0,2 0,5 4,0 0,-5 z'
id='rect7914' sodipodi:nodetypes='ssccccsssssssscccccccssssccccccc'
style='fill:#bebebe;fill-opacity:1;stroke:none'/>
+ </g>
+</svg>
diff --git a/libide/Makefile.am b/libide/Makefile.am
index 76e3bac..66ffe05 100644
--- a/libide/Makefile.am
+++ b/libide/Makefile.am
@@ -49,6 +49,12 @@ libide_1_0_la_public_headers = \
buildsystem/ide-configuration-provider.h \
buildsystem/ide-environment-variable.h \
buildsystem/ide-environment.h \
+ debugger/ide-debug-manager.h \
+ debugger/ide-debugger-breakpoints.h \
+ debugger/ide-debugger-editor-view-addin.h \
+ debugger/ide-debugger-perspective.h \
+ debugger/ide-debugger-workbench-addin.h \
+ debugger/ide-debugger-gutter-renderer.h \
devices/ide-device-manager.h \
devices/ide-device-provider.h \
devices/ide-device.h \
@@ -230,6 +236,12 @@ libide_1_0_la_public_sources = \
buildsystem/ide-configuration-provider.c \
buildsystem/ide-environment-variable.c \
buildsystem/ide-environment.c \
+ debugger/ide-debug-manager.c \
+ debugger/ide-debugger-breakpoints.c \
+ debugger/ide-debugger-editor-view-addin.c \
+ debugger/ide-debugger-perspective.c \
+ debugger/ide-debugger-workbench-addin.c \
+ debugger/ide-debugger-gutter-renderer.c \
devices/ide-device-manager.c \
devices/ide-device-provider.c \
devices/ide-device.c \
@@ -422,6 +434,9 @@ libide_1_0_la_SOURCES = \
buildui/ide-environment-editor-row.h \
buildui/ide-environment-editor.c \
buildui/ide-environment-editor.h \
+ debugger/ide-debugger-controls.c \
+ debugger/ide-debugger-controls.h \
+ debugger/ide-debugger-plugin.c \
editor/ide-editor-frame-actions.c \
editor/ide-editor-frame-actions.h \
editor/ide-editor-frame-private.h \
diff --git a/libide/debugger/debugger.plugin b/libide/debugger/debugger.plugin
new file mode 100644
index 0000000..8ef8a11
--- /dev/null
+++ b/libide/debugger/debugger.plugin
@@ -0,0 +1,10 @@
+[Plugin]
+Module=debugger
+Name=Debugger
+Description=Debugger integration for Builder
+Authors=Christian Hergert <chergert redhat com>
+Copyright=Copyright © 2017 Christian Hergert
+Depends=editor
+Builtin=true
+Hidden=true
+Embedded=ide_debugger_register_types
diff --git a/libide/debugger/ide-debug-manager.c b/libide/debugger/ide-debug-manager.c
new file mode 100644
index 0000000..401bbcb
--- /dev/null
+++ b/libide/debugger/ide-debug-manager.c
@@ -0,0 +1,178 @@
+/* ide-debug-manager.c
+ *
+ * Copyright (C) 2017 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-debug-manager"
+
+#include <glib/gi18n.h>
+
+#include "ide-debug-manager.h"
+
+struct _IdeDebugManager
+{
+ IdeObject parent_instance;
+ GSimpleActionGroup *actions;
+};
+
+enum {
+ PROP_0,
+ N_PROPS
+};
+
+enum {
+ BREAKPOINT_ADDED,
+ BREAKPOING_REMOVED,
+ N_SIGNALS
+};
+
+static GParamSpec *properties [N_PROPS];
+
+static gboolean
+ide_debug_manager_has_action (GActionGroup *group,
+ const gchar *action_name)
+{
+ IdeDebugManager *self = (IdeDebugManager *)group;
+
+ g_assert (IDE_IS_DEBUG_MANAGER (self));
+
+ return g_action_group_has_action (G_ACTION_GROUP (self->actions), action_name);
+}
+
+static gchar **
+ide_debug_manager_list_actions (GActionGroup *group)
+{
+ IdeDebugManager *self = (IdeDebugManager *)group;
+
+ g_assert (IDE_IS_DEBUG_MANAGER (self));
+
+ return g_action_group_list_actions (G_ACTION_GROUP (self->actions));
+}
+
+static gboolean
+ide_debug_manager_query_action (GActionGroup *group,
+ const gchar *action_name,
+ gboolean *enabled,
+ const GVariantType **parameter_type,
+ const GVariantType **state_type,
+ GVariant **state_hint,
+ GVariant **state)
+{
+ IdeDebugManager *self = (IdeDebugManager *)group;
+
+ g_assert (IDE_IS_DEBUG_MANAGER (self));
+
+ return g_action_group_query_action (G_ACTION_GROUP (self->actions),
+ action_name,
+ enabled,
+ parameter_type,
+ state_type,
+ state_hint,
+ state);
+}
+
+static void
+ide_debug_manager_activate_action (GActionGroup *group,
+ const gchar *action_name,
+ GVariant *parameter)
+{
+ IdeDebugManager *self = (IdeDebugManager *)group;
+
+ g_assert (IDE_IS_DEBUG_MANAGER (self));
+
+ g_action_group_activate_action (G_ACTION_GROUP (self->actions), action_name, parameter);
+}
+
+static void
+action_group_iface_init (GActionGroupInterface *iface)
+{
+ iface->has_action = ide_debug_manager_has_action;
+ iface->list_actions = ide_debug_manager_list_actions;
+ iface->query_action = ide_debug_manager_query_action;
+ iface->activate_action = ide_debug_manager_activate_action;
+}
+
+G_DEFINE_TYPE_EXTENDED (IdeDebugManager, ide_debug_manager, IDE_TYPE_OBJECT, 0,
+ G_IMPLEMENT_INTERFACE (G_TYPE_ACTION_GROUP, action_group_iface_init))
+
+static void
+ide_debug_manager_finalize (GObject *object)
+{
+ IdeDebugManager *self = (IdeDebugManager *)object;
+
+ g_clear_object (&self->actions);
+
+ G_OBJECT_CLASS (ide_debug_manager_parent_class)->finalize (object);
+}
+
+static void
+ide_debug_manager_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ IdeDebugManager *self = IDE_DEBUG_MANAGER (object);
+
+ switch (prop_id)
+ {
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+ide_debug_manager_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ IdeDebugManager *self = IDE_DEBUG_MANAGER (object);
+
+ switch (prop_id)
+ {
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+ide_debug_manager_class_init (IdeDebugManagerClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = ide_debug_manager_finalize;
+ object_class->get_property = ide_debug_manager_get_property;
+ object_class->set_property = ide_debug_manager_set_property;
+}
+
+static void
+ide_debug_manager_init (IdeDebugManager *self)
+{
+ self->actions = g_simple_action_group_new ();
+}
+
+gboolean
+ide_debug_manager_start (IdeDebugManager *self,
+ IdeRunner *runner,
+ GError **error)
+{
+ g_set_error (error,
+ G_IO_ERROR,
+ G_IO_ERROR_NOT_SUPPORTED,
+ _("A suitable debugger could not be found."));
+
+ return FALSE;
+}
diff --git a/libide/debugger/ide-debug-manager.h b/libide/debugger/ide-debug-manager.h
new file mode 100644
index 0000000..9453ff6
--- /dev/null
+++ b/libide/debugger/ide-debug-manager.h
@@ -0,0 +1,36 @@
+/* ide-debug-manager.h
+ *
+ * Copyright (C) 2017 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_DEBUG_MANAGER_H
+#define IDE_DEBUG_MANAGER_H
+
+#include "ide-object.h"
+
+G_BEGIN_DECLS
+
+#define IDE_TYPE_DEBUG_MANAGER (ide_debug_manager_get_type())
+
+G_DECLARE_FINAL_TYPE (IdeDebugManager, ide_debug_manager, IDE, DEBUG_MANAGER, IdeObject)
+
+gboolean ide_debug_manager_start (IdeDebugManager *self,
+ IdeRunner *runner,
+ GError **error);
+
+G_END_DECLS
+
+#endif /* IDE_DEBUG_MANAGER_H */
diff --git a/libide/debugger/ide-debugger-breakpoints.c b/libide/debugger/ide-debugger-breakpoints.c
new file mode 100644
index 0000000..6e862e4
--- /dev/null
+++ b/libide/debugger/ide-debugger-breakpoints.c
@@ -0,0 +1,292 @@
+/* ide-debugger-breakpoints.c
+ *
+ * Copyright (C) 2017 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-debugger-breakpoints"
+
+#include "ide-debugger-breakpoints.h"
+
+/**
+ * SECTION:ide-debugger-breakpoints
+ * @title: IdeDebuggerBreakpoints
+ *
+ * This object is used to track breakpoints within a certain file.
+ * This is necessary so that we can draw the gutter for breakpoints
+ * very fast by reducing our breakpoint lookup cost to simply a line
+ * number in a hashtable.
+ *
+ * To do this, the #IdeDebuggerBreakpoints object will track changes
+ * to breakpoints (and watchpoints) in the IdeDebugManager. If the
+ * breakpoint is part to the current #IdeDebuggerBreakpoints:file, then
+ * it will cache the value. The #IdeDebuggerGutterRenderer is assigned
+ * a #IdeDebuggerBreakpoints which it will use to determine what icon
+ * to render on the gutter.
+ */
+
+struct _IdeDebuggerBreakpoints
+{
+ IdeObject parent_instance;
+ GHashTable *cache;
+ GFile *file;
+};
+
+enum {
+ PROP_0,
+ PROP_FILE,
+ N_PROPS
+};
+
+enum {
+ CHANGED,
+ N_SIGNALS
+};
+
+G_DEFINE_TYPE (IdeDebuggerBreakpoints, ide_debugger_breakpoints, IDE_TYPE_OBJECT)
+
+static GParamSpec *properties [N_PROPS];
+static guint signals [N_SIGNALS];
+
+static void
+on_breakpoint_added (IdeDebuggerBreakpoints *self,
+ GFile *file,
+ guint line,
+ IdeDebuggerBreakType break_type,
+ IdeDebugManager *debug_manager)
+{
+ IdeDebuggerBreakType type;
+ gpointer key = GUINT_TO_POINTER (line);
+
+ g_assert (IDE_IS_DEBUGGER_BREAKPOINTS (self));
+ g_assert (G_IS_FILE (file));
+
+ if (!g_file_equal (file, self->file))
+ return;
+
+ type = GPOINTER_TO_UINT (g_hash_table_lookup (self->cache, key)) | break_type;
+ g_hash_table_insert (self->cache, key, GUINT_TO_POINTER (type));
+
+ g_signal_emit (self, signals [CHANGED], 0);
+}
+
+static void
+on_breakpoint_removed (IdeDebuggerBreakpoints *self,
+ GFile *file,
+ guint line,
+ IdeDebuggerBreakType break_type,
+ IdeDebugManager *debug_manager)
+{
+ IdeDebuggerBreakType type;
+ gpointer key = GUINT_TO_POINTER (line);
+
+ g_assert (IDE_IS_DEBUGGER_BREAKPOINTS (self));
+ g_assert (G_IS_FILE (file));
+
+ if (!g_file_equal (file, self->file))
+ return;
+
+ type = GPOINTER_TO_UINT (g_hash_table_lookup (self->cache, key));
+ type = type & ~break_type;
+
+ if (type == 0)
+ g_hash_table_remove (self->cache, key);
+ else
+ g_hash_table_replace (self->cache, key, GUINT_TO_POINTER (type));
+
+ g_signal_emit (self, signals [CHANGED], 0);
+}
+
+static void
+ide_debugger_breakpoints_constructed (GObject *object)
+{
+ IdeDebuggerBreakpoints *self = (IdeDebuggerBreakpoints *)object;
+ IdeDebugManager *debug_manager;
+ IdeContext *context;
+
+ g_assert (IDE_IS_DEBUGGER_BREAKPOINTS (self));
+
+ G_OBJECT_CLASS (ide_debugger_breakpoints_parent_class)->constructed (object);
+
+ context = ide_object_get_context (IDE_OBJECT (self));
+ debug_manager = ide_context_get_debug_manager (context);
+
+ g_signal_connect_object (debug_manager,
+ "breakpoint-added",
+ G_CALLBACK (on_breakpoint_added),
+ self,
+ G_CONNECT_SWAPPED);
+
+ g_signal_connect_object (debug_manager,
+ "breakpoint-removed",
+ G_CALLBACK (on_breakpoint_removed),
+ self,
+ G_CONNECT_SWAPPED);
+}
+
+static void
+ide_debugger_breakpoints_finalize (GObject *object)
+{
+ IdeDebuggerBreakpoints *self = (IdeDebuggerBreakpoints *)object;
+
+ g_clear_object (&self->file);
+ g_clear_pointer (&self->cache, g_hash_table_unref);
+
+ G_OBJECT_CLASS (ide_debugger_breakpoints_parent_class)->finalize (object);
+}
+
+static void
+ide_debugger_breakpoints_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ IdeDebuggerBreakpoints *self = IDE_DEBUGGER_BREAKPOINTS (object);
+
+ switch (prop_id)
+ {
+ case PROP_FILE:
+ g_value_set_object (value, self->file);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+ide_debugger_breakpoints_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ IdeDebuggerBreakpoints *self = IDE_DEBUGGER_BREAKPOINTS (object);
+
+ switch (prop_id)
+ {
+ case PROP_FILE:
+ self->file = g_value_dup_object (value);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+ide_debugger_breakpoints_class_init (IdeDebuggerBreakpointsClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->constructed = ide_debugger_breakpoints_constructed;
+ object_class->finalize = ide_debugger_breakpoints_finalize;
+ object_class->get_property = ide_debugger_breakpoints_get_property;
+ object_class->set_property = ide_debugger_breakpoints_set_property;
+
+ properties [PROP_FILE] =
+ g_param_spec_object ("file",
+ "File",
+ "File",
+ G_TYPE_FILE,
+ (G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_properties (object_class, N_PROPS, properties);
+
+ /**
+ * IdeDebuggerBreakpoints::changed:
+ *
+ * This signal is emitted when a breakpoint has changed with in the file
+ * indicated by IdeDebuggerBreakpoints:file.
+ */
+ signals [CHANGED] =
+ g_signal_new ("changed",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ 0, NULL, NULL, NULL, G_TYPE_NONE, 0);
+}
+
+static void
+ide_debugger_breakpoints_init (IdeDebuggerBreakpoints *self)
+{
+ self->cache = g_hash_table_new (NULL, NULL);
+}
+
+/**
+ * ide_debugger_breakpoints_get_file:
+ *
+ * Returns: (transfer none): A #GFile.
+ */
+GFile *
+ide_debugger_breakpoints_get_file (IdeDebuggerBreakpoints *self)
+{
+ g_return_val_if_fail (IDE_IS_DEBUGGER_BREAKPOINTS (self), NULL);
+
+ return self->file;
+}
+
+void
+ide_debugger_breakpoints_add (IdeDebuggerBreakpoints *self,
+ guint line,
+ IdeDebuggerBreakType break_type)
+{
+ IDE_ENTRY;
+
+ g_assert (IDE_IS_DEBUGGER_BREAKPOINTS (self));
+ g_assert (line > 0);
+ g_assert (break_type > IDE_DEBUGGER_BREAK_NONE);
+
+ /*
+ * TODO: Propagate request for breakpoint via debugger debug_manager.
+ * Instead, for testing, we will just add the breakpoint
+ * locally to our cache. However, a real implementation
+ * should possibly set a pending bit on the entry and the
+ * remove the pending bit once it has been added by the
+ * debugger (since that could involve a round trip over
+ * IPC and we don't want to show a full breakpoint before
+ * its actually available).
+ */
+
+ g_hash_table_insert (self->cache, GUINT_TO_POINTER (line), GUINT_TO_POINTER (break_type));
+ g_signal_emit (self, signals [CHANGED], 0);
+
+ IDE_EXIT;
+}
+
+void
+ide_debugger_breakpoints_remove (IdeDebuggerBreakpoints *self,
+ guint line)
+{
+ IDE_ENTRY;
+
+ g_assert (IDE_IS_DEBUGGER_BREAKPOINTS (self));
+ g_assert (line > 0);
+
+ /*
+ * TODO: Propagate request to remove breakpoint via debugger debug_manager.
+ * For testing, we can just remove the debugger from cache.
+ */
+
+ g_hash_table_remove (self->cache, GUINT_TO_POINTER (line));
+ g_signal_emit (self, signals [CHANGED], 0);
+
+ IDE_EXIT;
+}
+
+IdeDebuggerBreakType
+ide_debugger_breakpoints_lookup (IdeDebuggerBreakpoints *self,
+ guint line)
+{
+ return GPOINTER_TO_UINT (g_hash_table_lookup (self->cache, GUINT_TO_POINTER (line)));
+}
diff --git a/libide/debugger/ide-debugger-breakpoints.h b/libide/debugger/ide-debugger-breakpoints.h
new file mode 100644
index 0000000..c87842e
--- /dev/null
+++ b/libide/debugger/ide-debugger-breakpoints.h
@@ -0,0 +1,49 @@
+/* ide-debugger-breakpoints.h
+ *
+ * Copyright (C) 2017 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_DEBUGGER_BREAKPOINTS_H
+#define IDE_DEBUGGER_BREAKPOINTS_H
+
+#include <ide.h>
+
+G_BEGIN_DECLS
+
+#define IDE_TYPE_DEBUGGER_BREAKPOINTS (ide_debugger_breakpoints_get_type())
+
+G_DECLARE_FINAL_TYPE (IdeDebuggerBreakpoints, ide_debugger_breakpoints, IDE, DEBUGGER_BREAKPOINTS, IdeObject)
+
+typedef enum
+{
+ IDE_DEBUGGER_BREAK_NONE = 0,
+ IDE_DEBUGGER_BREAK_BREAKPOINT = 1 << 0,
+ IDE_DEBUGGER_BREAK_COUNTPOINT = 1 << 1,
+ IDE_DEBUGGER_BREAK_WATCHPOINT = 1 << 2,
+} IdeDebuggerBreakType;
+
+GFile *ide_debugger_breakpoints_get_file (IdeDebuggerBreakpoints *self);
+void ide_debugger_breakpoints_add (IdeDebuggerBreakpoints *self,
+ guint line,
+ IdeDebuggerBreakType break_type);
+void ide_debugger_breakpoints_remove (IdeDebuggerBreakpoints *self,
+ guint line);
+IdeDebuggerBreakType ide_debugger_breakpoints_lookup (IdeDebuggerBreakpoints *self,
+ guint line);
+
+G_END_DECLS
+
+#endif /* IDE_DEBUGGER_BREAKPOINTS_H */
diff --git a/libide/debugger/ide-debugger-controls.c b/libide/debugger/ide-debugger-controls.c
new file mode 100644
index 0000000..a2be212
--- /dev/null
+++ b/libide/debugger/ide-debugger-controls.c
@@ -0,0 +1,40 @@
+/* ide-debugger-controls.c
+ *
+ * Copyright (C) 2017 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-debugger-controls.h"
+
+struct _IdeDebuggerControls
+{
+ GtkBin parent_instance;
+};
+
+G_DEFINE_TYPE (IdeDebuggerControls, ide_debugger_controls, GTK_TYPE_BIN)
+
+static void
+ide_debugger_controls_class_init (IdeDebuggerControlsClass *klass)
+{
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ gtk_widget_class_set_template_from_resource (widget_class,
"/org/gnome/builder/ui/ide-debugger-controls.ui");
+}
+
+static void
+ide_debugger_controls_init (IdeDebuggerControls *self)
+{
+ gtk_widget_init_template (GTK_WIDGET (self));
+}
diff --git a/libide/debugger/ide-debugger-controls.h b/libide/debugger/ide-debugger-controls.h
new file mode 100644
index 0000000..0b4d4c1
--- /dev/null
+++ b/libide/debugger/ide-debugger-controls.h
@@ -0,0 +1,38 @@
+/* ide-debugger-controls.h
+ *
+ * Copyright (C) 2017 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_DEBUGGER_CONTROLS_H
+#define IDE_DEBUGGER_CONTROLS_H
+
+#include <gtk/gtk.h>
+
+#include "ide-types.h"
+
+G_BEGIN_DECLS
+
+#define IDE_TYPE_DEBUGGER_CONTROLS (ide_debugger_controls_get_type())
+
+G_DECLARE_FINAL_TYPE (IdeDebuggerControls, ide_debugger_controls, IDE, DEBUGGER_CONTROLS, GtkBin)
+
+IdeDebugger *ide_debugger_controls_get_debugger (IdeDebuggerControls *self);
+void ide_debugger_controls_set_debugger (IdeDebuggerControls *self,
+ IdeDebugger *debugger);
+
+G_END_DECLS
+
+#endif /* IDE_DEBUGGER_CONTROLS_H */
diff --git a/libide/debugger/ide-debugger-controls.ui b/libide/debugger/ide-debugger-controls.ui
new file mode 100644
index 0000000..558168e
--- /dev/null
+++ b/libide/debugger/ide-debugger-controls.ui
@@ -0,0 +1,92 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <template class="IdeDebuggerControls" parent="GtkBin">
+ <child>
+ <object class="GtkBox">
+ <property name="orientation">horizontal</property>
+ <property name="visible">true</property>
+ <style>
+ <class name="linked"/>
+ </style>
+ <child>
+ <object class="GtkButton" id="continue_button">
+ <property name="action-name">debugger.continue</property>
+ <property name="tooltip-text" translatable="yes">Continue running the program</property>
+ <property name="visible">true</property>
+ <child>
+ <object class="GtkImage">
+ <property name="icon-name">debug-continue-symbolic</property>
+ <property name="visible">true</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkButton" id="execute_from_cursor_button">
+ <property name="action-name">debugger.execute-from-cursor</property>
+ <property name="tooltip-text" translatable="yes">Execute from the current cursor
position</property>
+ <property name="visible">true</property>
+ <child>
+ <object class="GtkImage">
+ <property name="icon-name">debug-execute-from-cursor-symbolic</property>
+ <property name="visible">true</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkButton" id="execute_to_cursor_button">
+ <property name="action-name">debugger.execute-to-cursor</property>
+ <property name="tooltip-text" translatable="yes">Execute until reaching the current cursor
position</property>
+ <property name="visible">true</property>
+ <child>
+ <object class="GtkImage">
+ <property name="icon-name">debug-execute-to-cursor-symbolic</property>
+ <property name="visible">true</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkButton" id="step_in_button">
+ <property name="action-name">debugger.step-in</property>
+ <property name="tooltip-text" translatable="yes">Step into the scope</property>
+ <property name="visible">true</property>
+ <child>
+ <object class="GtkImage">
+ <property name="icon-name">debug-step-in-symbolic</property>
+ <property name="visible">true</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkButton" id="step_out_button">
+ <property name="action-name">debugger.step-out</property>
+ <property name="tooltip-text" translatable="yes">Step out of scope</property>
+ <property name="visible">true</property>
+ <child>
+ <object class="GtkImage">
+ <property name="icon-name">debug-step-out-symbolic</property>
+ <property name="visible">true</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkButton" id="step_over_button">
+ <property name="action-name">debugger.step-over</property>
+ <property name="tooltip-text" translatable="yes">Step over the operation</property>
+ <property name="visible">true</property>
+ <child>
+ <object class="GtkImage">
+ <property name="icon-name">debug-step-over-symbolic</property>
+ <property name="visible">true</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </template>
+</interface>
diff --git a/libide/debugger/ide-debugger-editor-view-addin.c
b/libide/debugger/ide-debugger-editor-view-addin.c
new file mode 100644
index 0000000..2b7a3b9
--- /dev/null
+++ b/libide/debugger/ide-debugger-editor-view-addin.c
@@ -0,0 +1,161 @@
+/* ide-debugger-editor-view-addin.c
+ *
+ * Copyright (C) 2017 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-debugger-editor-view-addin"
+
+#include "ide-debugger-breakpoints.h"
+#include "ide-debugger-editor-view-addin.h"
+#include "ide-debugger-gutter-renderer.h"
+
+static GHashTable *supported_languages;
+
+struct _IdeDebuggerEditorViewAddin
+{
+ GObject parent_instance;
+ GPtrArray *renderers;
+};
+
+static void
+ide_debugger_editor_view_addin_load_source_view (IdeEditorViewAddin *addin,
+ IdeSourceView *source_view)
+{
+ IdeDebuggerEditorViewAddin *self = (IdeDebuggerEditorViewAddin *)addin;
+ g_autoptr(IdeDebuggerBreakpoints) breakpoints = NULL;
+ GtkSourceGutterRenderer *renderer;
+ GtkSourceGutter *gutter;
+ IdeContext *context;
+ IdeBuffer *buffer;
+ IdeFile *file;
+ GFile *gfile;
+
+ IDE_ENTRY;
+
+ g_assert (IDE_IS_DEBUGGER_EDITOR_VIEW_ADDIN (addin));
+ g_assert (IDE_IS_SOURCE_VIEW (source_view));
+
+ context = ide_widget_get_context (GTK_WIDGET (source_view));
+ buffer = IDE_BUFFER (gtk_text_view_get_buffer (GTK_TEXT_VIEW (source_view)));
+ file = ide_buffer_get_file (buffer);
+ gfile = ide_file_get_file (file);
+
+ breakpoints = g_object_new (IDE_TYPE_DEBUGGER_BREAKPOINTS,
+ "context", context,
+ "file", gfile,
+ NULL);
+
+ gutter = gtk_source_view_get_gutter (GTK_SOURCE_VIEW (source_view), GTK_TEXT_WINDOW_LEFT);
+ renderer = g_object_new (IDE_TYPE_DEBUGGER_GUTTER_RENDERER,
+ "alignment-mode", GTK_SOURCE_GUTTER_RENDERER_ALIGNMENT_MODE_FIRST,
+ "breakpoints", breakpoints,
+ "size", 16,
+ "visible", TRUE,
+ "xalign", 0.5f,
+ NULL);
+ g_ptr_array_add (self->renderers, g_object_ref (renderer));
+ gtk_source_gutter_insert (gutter, renderer, -1000);
+
+ IDE_EXIT;
+}
+
+static void
+ide_debugger_editor_view_addin_unload_source_view (IdeEditorViewAddin *addin,
+ IdeSourceView *source_view)
+{
+ IdeDebuggerEditorViewAddin *self = (IdeDebuggerEditorViewAddin *)addin;
+ GtkSourceGutter *gutter;
+
+ IDE_ENTRY;
+
+ g_assert (IDE_IS_DEBUGGER_EDITOR_VIEW_ADDIN (addin));
+ g_assert (IDE_IS_SOURCE_VIEW (source_view));
+
+ gutter = gtk_source_view_get_gutter (GTK_SOURCE_VIEW (source_view), GTK_TEXT_WINDOW_LEFT);
+
+ for (guint i = self->renderers->len; i > 0; i--)
+ {
+ GtkSourceGutterRenderer *renderer = g_ptr_array_index (self->renderers, i - 1);
+
+ if ((gpointer)source_view == (gpointer)gtk_source_gutter_renderer_get_view (renderer))
+ {
+ gtk_source_gutter_remove (gutter, renderer);
+ g_ptr_array_remove_index (self->renderers, i - 1);
+ }
+ }
+
+ IDE_EXIT;
+}
+
+static void
+ide_debugger_editor_view_addin_language_changed (IdeEditorViewAddin *addin,
+ const gchar *lang_id)
+{
+ IdeDebuggerEditorViewAddin *self = (IdeDebuggerEditorViewAddin *)addin;
+ gboolean visible = FALSE;
+
+ g_assert (IDE_IS_DEBUGGER_EDITOR_VIEW_ADDIN (self));
+
+ visible = lang_id && g_hash_table_contains (supported_languages, lang_id);
+
+ for (guint i = 0; i < self->renderers->len; i++)
+ {
+ GtkSourceGutterRenderer *renderer = g_ptr_array_index (self->renderers, i);
+
+ gtk_source_gutter_renderer_set_visible (renderer, visible);
+ }
+}
+
+static void
+editor_view_addin_iface_init (IdeEditorViewAddinInterface *iface)
+{
+ iface->load_source_view = ide_debugger_editor_view_addin_load_source_view;
+ iface->unload_source_view = ide_debugger_editor_view_addin_unload_source_view;
+ iface->language_changed = ide_debugger_editor_view_addin_language_changed;
+}
+
+G_DEFINE_TYPE_EXTENDED (IdeDebuggerEditorViewAddin, ide_debugger_editor_view_addin, G_TYPE_OBJECT, 0,
+ G_IMPLEMENT_INTERFACE (IDE_TYPE_EDITOR_VIEW_ADDIN, editor_view_addin_iface_init))
+
+static void
+ide_debugger_editor_view_addin_finalize (GObject *object)
+{
+ IdeDebuggerEditorViewAddin *self = (IdeDebuggerEditorViewAddin *)object;
+
+ g_clear_pointer (&self->renderers, g_ptr_array_unref);
+
+ G_OBJECT_CLASS (ide_debugger_editor_view_addin_parent_class)->finalize (object);
+}
+
+static void
+ide_debugger_editor_view_addin_class_init (IdeDebuggerEditorViewAddinClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = ide_debugger_editor_view_addin_finalize;
+
+ supported_languages = g_hash_table_new (g_str_hash, g_str_equal);
+ g_hash_table_insert (supported_languages, (gchar *)"c", NULL);
+ g_hash_table_insert (supported_languages, (gchar *)"chdr", NULL);
+ g_hash_table_insert (supported_languages, (gchar *)"cpp", NULL);
+ g_hash_table_insert (supported_languages, (gchar *)"cpphdr", NULL);
+}
+
+static void
+ide_debugger_editor_view_addin_init (IdeDebuggerEditorViewAddin *self)
+{
+ self->renderers = g_ptr_array_new_with_free_func (g_object_unref);
+}
diff --git a/libide/debugger/ide-debugger-editor-view-addin.h
b/libide/debugger/ide-debugger-editor-view-addin.h
new file mode 100644
index 0000000..58cc06e
--- /dev/null
+++ b/libide/debugger/ide-debugger-editor-view-addin.h
@@ -0,0 +1,32 @@
+/* ide-debugger-editor-view-addin.h
+ *
+ * Copyright (C) 2017 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_DEBUGGER_EDITOR_VIEW_ADDIN_H
+#define IDE_DEBUGGER_EDITOR_VIEW_ADDIN_H
+
+#include <ide.h>
+
+G_BEGIN_DECLS
+
+#define IDE_TYPE_DEBUGGER_EDITOR_VIEW_ADDIN (ide_debugger_editor_view_addin_get_type())
+
+G_DECLARE_FINAL_TYPE (IdeDebuggerEditorViewAddin, ide_debugger_editor_view_addin, IDE,
DEBUGGER_EDITOR_VIEW_ADDIN, GObject)
+
+G_END_DECLS
+
+#endif /* IDE_DEBUGGER_EDITOR_VIEW_ADDIN_H */
diff --git a/libide/debugger/ide-debugger-gutter-renderer.c b/libide/debugger/ide-debugger-gutter-renderer.c
new file mode 100644
index 0000000..6a1bb3d
--- /dev/null
+++ b/libide/debugger/ide-debugger-gutter-renderer.c
@@ -0,0 +1,280 @@
+/* ide-debugger-gutter-renderer.c
+ *
+ * Copyright (C) 2017 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-debugger-gutter-renderer"
+
+#include <glib/gi18n.h>
+
+#include "ide-debugger-gutter-renderer.h"
+#include "ide-debugger-breakpoints.h"
+
+struct _IdeDebuggerGutterRenderer
+{
+ GtkSourceGutterRendererPixbuf parent_instance;
+ IdeDebuggerBreakpoints *breakpoints;
+ gulong breakpoints_changed_handler;
+};
+
+G_DEFINE_TYPE (IdeDebuggerGutterRenderer, ide_debugger_gutter_renderer,
GTK_SOURCE_TYPE_GUTTER_RENDERER_PIXBUF)
+
+enum {
+ PROP_0,
+ PROP_BREAKPOINTS,
+ N_PROPS
+};
+
+static GParamSpec *properties [N_PROPS];
+
+static void
+ide_debugger_gutter_renderer_activate (IdeDebuggerGutterRenderer *self,
+ const GtkTextIter *iter,
+ GdkRectangle *area,
+ GdkEvent *event)
+{
+ IdeDebuggerBreakType break_type;
+ guint line;
+
+ IDE_ENTRY;
+
+ g_assert (IDE_IS_DEBUGGER_GUTTER_RENDERER (self));
+ g_assert (iter != NULL);
+ g_assert (area != NULL);
+ g_assert (event != NULL);
+
+ line = gtk_text_iter_get_line (iter) + 1;
+
+ IDE_TRACE_MSG ("Toggle breakpoint on line %u", line);
+
+ break_type = ide_debugger_breakpoints_lookup (self->breakpoints, line);
+
+ switch (break_type)
+ {
+ case IDE_DEBUGGER_BREAK_NONE:
+ ide_debugger_breakpoints_add (self->breakpoints, line, IDE_DEBUGGER_BREAK_BREAKPOINT);
+ break;
+
+ case IDE_DEBUGGER_BREAK_BREAKPOINT:
+ case IDE_DEBUGGER_BREAK_COUNTPOINT:
+ case IDE_DEBUGGER_BREAK_WATCHPOINT:
+ ide_debugger_breakpoints_remove (self->breakpoints, line);
+ break;
+
+ default:
+ break;
+ }
+
+ IDE_EXIT;
+}
+
+static gboolean
+ide_debugger_gutter_renderer_query_activatable (IdeDebuggerGutterRenderer *self,
+ const GtkTextIter *begin,
+ const GdkRectangle *area,
+ GdkEvent *event)
+{
+ g_assert (IDE_IS_DEBUGGER_GUTTER_RENDERER (self));
+ g_assert (begin != NULL);
+ g_assert (area != NULL);
+ g_assert (event != NULL);
+
+ return TRUE;
+}
+
+static void
+ide_debugger_gutter_renderer_query_data (IdeDebuggerGutterRenderer *self,
+ const GtkTextIter *begin,
+ const GtkTextIter *end,
+ GtkSourceGutterRendererState state)
+{
+ IdeDebuggerBreakType break_type;
+ guint line;
+
+ g_assert (IDE_IS_DEBUGGER_GUTTER_RENDERER (self));
+ g_assert (begin != NULL);
+ g_assert (end != NULL);
+
+ if (self->breakpoints == NULL)
+ return;
+
+ line = gtk_text_iter_get_line (begin) + 1;
+ break_type = ide_debugger_breakpoints_lookup (self->breakpoints, line);
+
+ /*
+ * These are very much a miss-appropriation of the icon, but it works
+ * well enough for now until we get real symbolic icons for these.
+ */
+#define BREAKPOINT_ICON_NAME "edit-clear-symbolic-rtl"
+#define COUNTPOINT_ICON_NAME "edit-clear-symbolic-rtl"
+#define WATCHPOINT_ICON_NAME "edit-clear-symbolic-rtl"
+
+ switch (break_type)
+ {
+ case IDE_DEBUGGER_BREAK_BREAKPOINT:
+ gtk_source_gutter_renderer_pixbuf_set_icon_name (GTK_SOURCE_GUTTER_RENDERER_PIXBUF (self),
BREAKPOINT_ICON_NAME);
+ break;
+
+ case IDE_DEBUGGER_BREAK_COUNTPOINT:
+ gtk_source_gutter_renderer_pixbuf_set_icon_name (GTK_SOURCE_GUTTER_RENDERER_PIXBUF (self),
COUNTPOINT_ICON_NAME);
+ break;
+
+ case IDE_DEBUGGER_BREAK_WATCHPOINT:
+ gtk_source_gutter_renderer_pixbuf_set_icon_name (GTK_SOURCE_GUTTER_RENDERER_PIXBUF (self),
WATCHPOINT_ICON_NAME);
+ break;
+
+ case IDE_DEBUGGER_BREAK_NONE:
+ default:
+ /* Setting pixbuf to NULL via g_object_set() seems to be
+ * the only way to clear this without g_warning()s.
+ */
+ g_object_set (self, "pixbuf", NULL, NULL);
+ break;
+ }
+}
+
+static void
+ide_debugger_gutter_renderer_breakpoints_changed (IdeDebuggerGutterRenderer *self,
+ IdeDebuggerBreakpoints *breakpoints)
+{
+ g_assert (IDE_IS_DEBUGGER_GUTTER_RENDERER (self));
+ g_assert (IDE_IS_DEBUGGER_BREAKPOINTS (breakpoints));
+
+ gtk_source_gutter_renderer_queue_draw (GTK_SOURCE_GUTTER_RENDERER (self));
+}
+
+static void
+ide_debugger_gutter_renderer_set_breakpoints (IdeDebuggerGutterRenderer *self,
+ IdeDebuggerBreakpoints *breakpoints)
+{
+ g_return_if_fail (IDE_IS_DEBUGGER_GUTTER_RENDERER (self));
+ g_return_if_fail (!breakpoints || IDE_IS_DEBUGGER_BREAKPOINTS (breakpoints));
+
+ if (self->breakpoints != breakpoints)
+ {
+ if (self->breakpoints != NULL)
+ {
+ g_signal_handler_disconnect (self->breakpoints, self->breakpoints_changed_handler);
+ self->breakpoints_changed_handler = 0;
+ g_clear_object (&self->breakpoints);
+ }
+
+ if (breakpoints != NULL)
+ {
+ self->breakpoints = g_object_ref (breakpoints);
+ self->breakpoints_changed_handler =
+ g_signal_connect_object (breakpoints,
+ "changed",
+ G_CALLBACK (ide_debugger_gutter_renderer_breakpoints_changed),
+ self,
+ G_CONNECT_SWAPPED);
+ }
+
+ g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_BREAKPOINTS]);
+ }
+}
+
+static void
+ide_debugger_gutter_renderer_finalize (GObject *object)
+{
+ IdeDebuggerGutterRenderer *self = (IdeDebuggerGutterRenderer *)object;
+
+ g_clear_object (&self->breakpoints);
+
+ G_OBJECT_CLASS (ide_debugger_gutter_renderer_parent_class)->finalize (object);
+}
+
+static void
+ide_debugger_gutter_renderer_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ IdeDebuggerGutterRenderer *self = IDE_DEBUGGER_GUTTER_RENDERER (object);
+
+ switch (prop_id)
+ {
+ case PROP_BREAKPOINTS:
+ g_value_set_object (value, self->breakpoints);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+ide_debugger_gutter_renderer_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ IdeDebuggerGutterRenderer *self = IDE_DEBUGGER_GUTTER_RENDERER (object);
+
+ switch (prop_id)
+ {
+ case PROP_BREAKPOINTS:
+ ide_debugger_gutter_renderer_set_breakpoints (self, g_value_get_object (value));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+ide_debugger_gutter_renderer_class_init (IdeDebuggerGutterRendererClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = ide_debugger_gutter_renderer_finalize;
+ object_class->get_property = ide_debugger_gutter_renderer_get_property;
+ object_class->set_property = ide_debugger_gutter_renderer_set_property;
+
+ properties [PROP_BREAKPOINTS] =
+ g_param_spec_object ("breakpoints",
+ "Breakpoints",
+ "Breakpoints",
+ IDE_TYPE_DEBUGGER_BREAKPOINTS,
+ (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_properties (object_class, N_PROPS, properties);
+}
+
+static void
+ide_debugger_gutter_renderer_init (IdeDebuggerGutterRenderer *self)
+{
+ g_signal_connect (self,
+ "activate",
+ G_CALLBACK (ide_debugger_gutter_renderer_activate),
+ NULL);
+
+ g_signal_connect (self,
+ "query-activatable",
+ G_CALLBACK (ide_debugger_gutter_renderer_query_activatable),
+ NULL);
+
+ g_signal_connect (self,
+ "query-data",
+ G_CALLBACK (ide_debugger_gutter_renderer_query_data),
+ NULL);
+}
+
+GtkSourceGutterRenderer *
+ide_debugger_gutter_renderer_new (void)
+{
+ return g_object_new (IDE_TYPE_DEBUGGER_GUTTER_RENDERER, NULL);
+}
diff --git a/libide/debugger/ide-debugger-gutter-renderer.h b/libide/debugger/ide-debugger-gutter-renderer.h
new file mode 100644
index 0000000..e3780ff
--- /dev/null
+++ b/libide/debugger/ide-debugger-gutter-renderer.h
@@ -0,0 +1,35 @@
+/* ide-debugger-gutter-renderer.h
+ *
+ * Copyright (C) 2017 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_DEBUGGER_GUTTER_RENDERER_H
+#define IDE_DEBUGGER_GUTTER_RENDERER_H
+
+#include <gtksourceview/gtksource.h>
+#include <ide.h>
+
+G_BEGIN_DECLS
+
+#define IDE_TYPE_DEBUGGER_GUTTER_RENDERER (ide_debugger_gutter_renderer_get_type())
+
+G_DECLARE_FINAL_TYPE (IdeDebuggerGutterRenderer, ide_debugger_gutter_renderer, IDE,
DEBUGGER_GUTTER_RENDERER, GtkSourceGutterRendererPixbuf)
+
+GtkSourceGutterRenderer *ide_debugger_gutter_renderer_new (void);
+
+G_END_DECLS
+
+#endif /* IDE_DEBUGGER_GUTTER_RENDERER_H */
diff --git a/libide/debugger/ide-debugger-perspective.c b/libide/debugger/ide-debugger-perspective.c
new file mode 100644
index 0000000..a2dd8e5
--- /dev/null
+++ b/libide/debugger/ide-debugger-perspective.c
@@ -0,0 +1,126 @@
+/* ide-debugger-perspective.c
+ *
+ * Copyright (C) 2017 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-debugger-perspective"
+
+#include <glib/gi18n.h>
+
+#include "ide-debugger-perspective.h"
+
+struct _IdeDebuggerPerspective
+{
+ IdeLayout parent_instance;
+};
+
+enum {
+ PROP_0,
+ N_PROPS
+};
+
+static gchar *
+ide_debugger_perspective_get_title (IdePerspective *perspective)
+{
+ return g_strdup (_("Debugger"));
+}
+
+static gchar *
+ide_debugger_perspective_get_id (IdePerspective *perspective)
+{
+ return g_strdup ("debugger");
+}
+
+static gchar *
+ide_debugger_perspective_get_icon_name (IdePerspective *perspective)
+{
+ return g_strdup ("builder-debugger-symbolic");
+}
+
+static gchar *
+ide_debugger_perspective_get_accelerator (IdePerspective *perspective)
+{
+ return g_strdup ("<Alt>2");
+}
+
+static void
+perspective_iface_init (IdePerspectiveInterface *iface)
+{
+ iface->get_accelerator = ide_debugger_perspective_get_accelerator;
+ iface->get_icon_name = ide_debugger_perspective_get_icon_name;
+ iface->get_id = ide_debugger_perspective_get_id;
+ iface->get_title = ide_debugger_perspective_get_title;
+}
+
+G_DEFINE_TYPE_EXTENDED (IdeDebuggerPerspective, ide_debugger_perspective, IDE_TYPE_LAYOUT, 0,
+ G_IMPLEMENT_INTERFACE (IDE_TYPE_PERSPECTIVE, perspective_iface_init))
+
+static GParamSpec *properties [N_PROPS];
+
+static void
+ide_debugger_perspective_finalize (GObject *object)
+{
+ G_OBJECT_CLASS (ide_debugger_perspective_parent_class)->finalize (object);
+}
+
+static void
+ide_debugger_perspective_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ IdeDebuggerPerspective *self = IDE_DEBUGGER_PERSPECTIVE (object);
+
+ switch (prop_id)
+ {
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+ide_debugger_perspective_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ IdeDebuggerPerspective *self = IDE_DEBUGGER_PERSPECTIVE (object);
+
+ switch (prop_id)
+ {
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+ide_debugger_perspective_class_init (IdeDebuggerPerspectiveClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->finalize = ide_debugger_perspective_finalize;
+ object_class->get_property = ide_debugger_perspective_get_property;
+ object_class->set_property = ide_debugger_perspective_set_property;
+
+ gtk_widget_class_set_template_from_resource (widget_class,
"/org/gnome/builder/ui/ide-debugger-perspective.ui");
+}
+
+static void
+ide_debugger_perspective_init (IdeDebuggerPerspective *self)
+{
+ gtk_widget_init_template (GTK_WIDGET (self));
+}
diff --git a/libide/debugger/ide-debugger-perspective.h b/libide/debugger/ide-debugger-perspective.h
new file mode 100644
index 0000000..18ee206
--- /dev/null
+++ b/libide/debugger/ide-debugger-perspective.h
@@ -0,0 +1,32 @@
+/* ide-debugger-perspective.h
+ *
+ * Copyright (C) 2017 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_DEBUGGER_PERSPECTIVE_H
+#define IDE_DEBUGGER_PERSPECTIVE_H
+
+#include <ide.h>
+
+G_BEGIN_DECLS
+
+#define IDE_TYPE_DEBUGGER_PERSPECTIVE (ide_debugger_perspective_get_type())
+
+G_DECLARE_FINAL_TYPE (IdeDebuggerPerspective, ide_debugger_perspective, IDE, DEBUGGER_PERSPECTIVE, IdeLayout)
+
+G_END_DECLS
+
+#endif /* IDE_DEBUGGER_PERSPECTIVE_H */
diff --git a/libide/debugger/ide-debugger-perspective.ui b/libide/debugger/ide-debugger-perspective.ui
new file mode 100644
index 0000000..6e5eedb
--- /dev/null
+++ b/libide/debugger/ide-debugger-perspective.ui
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <template class="IdeDebuggerPerspective" parent="IdeLayout">
+ </template>
+</interface>
diff --git a/libide/debugger/ide-debugger-plugin.c b/libide/debugger/ide-debugger-plugin.c
new file mode 100644
index 0000000..846b772
--- /dev/null
+++ b/libide/debugger/ide-debugger-plugin.c
@@ -0,0 +1,35 @@
+/* ide-debugger-plugin.c
+ *
+ * Copyright (C) 2017 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 <libpeas/peas.h>
+
+#include "debugger/ide-debugger-editor-view-addin.h"
+#include "debugger/ide-debugger-workbench-addin.h"
+#include "editor/ide-editor-view-addin.h"
+#include "workbench/ide-workbench-addin.h"
+
+void
+ide_debugger_register_types (PeasObjectModule *module)
+{
+ peas_object_module_register_extension_type (module,
+ IDE_TYPE_EDITOR_VIEW_ADDIN,
+ IDE_TYPE_DEBUGGER_EDITOR_VIEW_ADDIN);
+ peas_object_module_register_extension_type (module,
+ IDE_TYPE_WORKBENCH_ADDIN,
+ IDE_TYPE_DEBUGGER_WORKBENCH_ADDIN);
+}
diff --git a/libide/debugger/ide-debugger-workbench-addin.c b/libide/debugger/ide-debugger-workbench-addin.c
new file mode 100644
index 0000000..25cb184
--- /dev/null
+++ b/libide/debugger/ide-debugger-workbench-addin.c
@@ -0,0 +1,175 @@
+/* ide-debugger-workbench-addin.c
+ *
+ * Copyright (C) 2017 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-debugger-workbench-addin"
+
+#include <glib/gi18n.h>
+
+#include "debugger/ide-debug-manager.h"
+#include "debugger/ide-debugger-controls.h"
+#include "debugger/ide-debugger-perspective.h"
+#include "debugger/ide-debugger-workbench-addin.h"
+#include "workbench/ide-workbench-message.h"
+
+struct _IdeDebuggerWorkbenchAddin
+{
+ GObject parent_instance;
+ IdeWorkbench *workbench;
+ IdeDebuggerControls *controls;
+ IdeWorkbenchMessage *message;
+ IdeDebuggerPerspective *perspective;
+};
+
+static void
+debugger_run_handler (IdeRunManager *run_manager,
+ IdeRunner *runner,
+ gpointer user_data)
+{
+ IdeDebuggerWorkbenchAddin *self = user_data;
+ IdeDebugManager *debug_manager;
+ IdeContext *context;
+ g_autoptr(GError) error = NULL;
+
+ IDE_ENTRY;
+
+ g_assert (IDE_IS_RUN_MANAGER (run_manager));
+ g_assert (IDE_IS_RUNNER (runner));
+ g_assert (IDE_IS_DEBUGGER_WORKBENCH_ADDIN (self));
+
+ ide_workbench_set_visible_perspective_name (self->workbench, "debugger");
+
+ /*
+ * Get the currently configured debugger and attach it to our runner.
+ * It might need to prepend arguments like `gdb', `pdb', `mdb', etc.
+ */
+ context = ide_object_get_context (IDE_OBJECT (run_manager));
+ debug_manager = ide_context_get_debug_manager (context);
+
+ if (!ide_debug_manager_start (debug_manager, runner, &error))
+ {
+ ide_workbench_message_set_subtitle (self->message, error->message);
+ gtk_widget_show (GTK_WIDGET (self->message));
+ }
+
+ IDE_EXIT;
+}
+
+static void
+ide_debugger_workbench_addin_load (IdeWorkbenchAddin *addin,
+ IdeWorkbench *workbench)
+{
+ IdeDebuggerWorkbenchAddin *self = (IdeDebuggerWorkbenchAddin *)addin;
+ IdeWorkbenchHeaderBar *headerbar;
+ IdeDebugManager *debug_manager;
+ IdeRunManager *run_manager;
+ IdeContext *context;
+
+ g_assert (IDE_IS_WORKBENCH_ADDIN (addin));
+ g_assert (IDE_IS_WORKBENCH (workbench));
+
+ self->workbench = workbench;
+
+ context = ide_workbench_get_context (workbench);
+ debug_manager = ide_context_get_debug_manager (context);
+ run_manager = ide_context_get_run_manager (context);
+
+ gtk_widget_insert_action_group (GTK_WIDGET (workbench),
+ "debugger",
+ G_ACTION_GROUP (debug_manager));
+
+ headerbar = ide_workbench_get_headerbar (workbench);
+
+ self->controls = g_object_new (IDE_TYPE_DEBUGGER_CONTROLS,
+ "visible", TRUE,
+ NULL);
+ ide_workbench_header_bar_insert_left (headerbar,
+ GTK_WIDGET (self->controls),
+ GTK_PACK_START,
+ 100);
+
+ ide_run_manager_add_handler (run_manager,
+ "debugger",
+ _("Run with Debugger"),
+ "builder-debugger-symbolic",
+ "F5",
+ debugger_run_handler,
+ g_object_ref (self),
+ g_object_unref);
+
+ self->perspective = g_object_new (IDE_TYPE_DEBUGGER_PERSPECTIVE,
+ "visible", TRUE,
+ NULL);
+ ide_workbench_add_perspective (workbench, IDE_PERSPECTIVE (self->perspective));
+
+ self->message = g_object_new (IDE_TYPE_WORKBENCH_MESSAGE,
+ "id", "org.gnome.builder.debugger.failure",
+ "show-close-button", TRUE,
+ "title", _("Failed to initialize the debugger"),
+ NULL);
+ ide_workbench_push_message (workbench, self->message);
+}
+
+static void
+ide_debugger_workbench_addin_unload (IdeWorkbenchAddin *addin,
+ IdeWorkbench *workbench)
+{
+ IdeDebuggerWorkbenchAddin *self = (IdeDebuggerWorkbenchAddin *)addin;
+ IdeRunManager *run_manager;
+ IdeContext *context;
+
+ g_assert (IDE_IS_WORKBENCH_ADDIN (addin));
+ g_assert (IDE_IS_WORKBENCH (workbench));
+
+ context = ide_workbench_get_context (workbench);
+ run_manager = ide_context_get_run_manager (context);
+
+ /* Remove the handler to initiate the debugger */
+ ide_run_manager_remove_handler (run_manager, "debugger");
+
+ /* Remove our debugger control widgets */
+ g_clear_pointer (&self->controls, gtk_widget_destroy);
+
+ /* Remove actions from activation */
+ gtk_widget_insert_action_group (GTK_WIDGET (workbench), "debugger", NULL);
+
+ /* Remove the debugging perspective from the UI */
+ ide_workbench_remove_perspective (workbench, IDE_PERSPECTIVE (self->perspective));
+ self->perspective = NULL;
+
+ self->workbench = NULL;
+}
+
+static void
+workbench_addin_iface_init (IdeWorkbenchAddinInterface *iface)
+{
+ iface->load = ide_debugger_workbench_addin_load;
+ iface->unload = ide_debugger_workbench_addin_unload;
+}
+
+G_DEFINE_TYPE_WITH_CODE (IdeDebuggerWorkbenchAddin, ide_debugger_workbench_addin, G_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE (IDE_TYPE_WORKBENCH_ADDIN, workbench_addin_iface_init))
+
+static void
+ide_debugger_workbench_addin_class_init (IdeDebuggerWorkbenchAddinClass *klass)
+{
+}
+
+static void
+ide_debugger_workbench_addin_init (IdeDebuggerWorkbenchAddin *self)
+{
+}
diff --git a/libide/debugger/ide-debugger-workbench-addin.h b/libide/debugger/ide-debugger-workbench-addin.h
new file mode 100644
index 0000000..ef7453e
--- /dev/null
+++ b/libide/debugger/ide-debugger-workbench-addin.h
@@ -0,0 +1,32 @@
+/* ide-debugger-workbench-addin.h
+ *
+ * Copyright (C) 2017 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_DEBUGGER_WORKBENCH_ADDIN_H
+#define IDE_DEBUGGER_WORKBENCH_ADDIN_H
+
+#include <ide.h>
+
+G_BEGIN_DECLS
+
+#define IDE_TYPE_DEBUGGER_WORKBENCH_ADDIN (ide_debugger_workbench_addin_get_type())
+
+G_DECLARE_FINAL_TYPE (IdeDebuggerWorkbenchAddin, ide_debugger_workbench_addin, IDE,
DEBUGGER_WORKBENCH_ADDIN, GObject)
+
+G_END_DECLS
+
+#endif /* IDE_DEBUGGER_WORKBENCH_ADDIN_H */
diff --git a/libide/ide-context.c b/libide/ide-context.c
index 0d170e1..85c007e 100644
--- a/libide/ide-context.c
+++ b/libide/ide-context.c
@@ -35,6 +35,7 @@
#include "buildsystem/ide-build-system.h"
#include "buildsystem/ide-build-system-discovery.h"
#include "buildsystem/ide-configuration-manager.h"
+#include "debugger/ide-debug-manager.h"
#include "diagnostics/ide-diagnostics-manager.h"
#include "devices/ide-device-manager.h"
#include "doap/ide-doap.h"
@@ -68,6 +69,7 @@ struct _IdeContext
IdeBuildSystem *build_system;
gchar *build_system_hint;
IdeConfigurationManager *configuration_manager;
+ IdeDebugManager *debug_manager;
IdeDiagnosticsManager *diagnostics_manager;
IdeDeviceManager *device_manager;
IdeDoap *doap;
@@ -816,6 +818,10 @@ ide_context_init (IdeContext *self)
"context", self,
NULL);
+ self->debug_manager = g_object_new (IDE_TYPE_DEBUG_MANAGER,
+ "context", self,
+ NULL);
+
self->device_manager = g_object_new (IDE_TYPE_DEVICE_MANAGER,
"context", self,
NULL);
@@ -2390,3 +2396,19 @@ ide_context_get_diagnostics_manager (IdeContext *self)
return self->diagnostics_manager;
}
+
+/**
+ * ide_context_get_debug_manager:
+ * @self: An #IdeContext
+ *
+ * Gets the debug manager for the context.
+ *
+ * Returns: (transfer none): An #IdeDebugManager
+ */
+IdeDebugManager *
+ide_context_get_debug_manager (IdeContext *self)
+{
+ g_return_val_if_fail (IDE_IS_CONTEXT (self), NULL);
+
+ return self->debug_manager;
+}
diff --git a/libide/ide-context.h b/libide/ide-context.h
index c180226..2d1e520 100644
--- a/libide/ide-context.h
+++ b/libide/ide-context.h
@@ -36,6 +36,7 @@ IdeBufferManager *ide_context_get_buffer_manager (IdeContext
IdeBuildManager *ide_context_get_build_manager (IdeContext *self);
IdeBuildSystem *ide_context_get_build_system (IdeContext *self);
IdeConfigurationManager *ide_context_get_configuration_manager (IdeContext *self);
+IdeDebugManager *ide_context_get_debug_manager (IdeContext *self);
IdeDiagnosticsManager *ide_context_get_diagnostics_manager (IdeContext *self);
IdeDeviceManager *ide_context_get_device_manager (IdeContext *self);
IdeProject *ide_context_get_project (IdeContext *self);
diff --git a/libide/ide-types.h b/libide/ide-types.h
index 93c889f..8643171 100644
--- a/libide/ide-types.h
+++ b/libide/ide-types.h
@@ -50,6 +50,9 @@ typedef struct _IdeConfigurationManager IdeConfigurationManager;
typedef struct _IdeContext IdeContext;
+typedef struct _IdeDebugger IdeDebugger;
+typedef struct _IdeDebugManager IdeDebugManager;
+
typedef struct _IdeDevice IdeDevice;
typedef struct _IdeDeviceManager IdeDeviceManager;
typedef struct _IdeDeviceProvider IdeDeviceProvider;
diff --git a/libide/resources/libide.gresource.xml b/libide/resources/libide.gresource.xml
index c6dd809..8d4d916 100644
--- a/libide/resources/libide.gresource.xml
+++ b/libide/resources/libide.gresource.xml
@@ -51,6 +51,8 @@
</gresource>
<gresource prefix="/org/gnome/builder/ui">
+ <file compressed="true" alias="ide-debugger-controls.ui">../debugger/ide-debugger-controls.ui</file>
+ <file compressed="true"
alias="ide-debugger-perspective.ui">../debugger/ide-debugger-perspective.ui</file>
<file compressed="true" alias="ide-editor-frame.ui">../editor/ide-editor-frame.ui</file>
<file compressed="true"
alias="ide-editor-layout-stack-controls.ui">../editor/ide-editor-layout-stack-controls.ui</file>
<file compressed="true" alias="ide-editor-perspective.ui">../editor/ide-editor-perspective.ui</file>
@@ -90,14 +92,18 @@
<file alias="buildconfig.plugin">../buildconfig/buildconfig.plugin</file>
</gresource>
- <gresource prefix="/org/gnome/builder/plugins/editor">
- <file alias="editor.plugin">../editor/editor.plugin</file>
+ <gresource prefix="/org/gnome/builder/plugins/debugger">
+ <file alias="debugger.plugin">../debugger/debugger.plugin</file>
</gresource>
<gresource prefix="/org/gnome/builder/plugins/directory">
<file alias="directory.plugin">../directory/directory.plugin</file>
</gresource>
+ <gresource prefix="/org/gnome/builder/plugins/editor">
+ <file alias="editor.plugin">../editor/editor.plugin</file>
+ </gresource>
+
<gresource prefix="/org/gnome/builder/plugins/webkit">
<file alias="webkit.plugin">../webkit/webkit.plugin</file>
</gresource>
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]