[gnome-builder/wip/chergert/bug1: 3/3] perspective port wip
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-builder/wip/chergert/bug1: 3/3] perspective port wip
- Date: Fri, 25 Aug 2017 08:34:39 +0000 (UTC)
commit 41e503295824d799c4a6e9d63cfbb0772cf46beb
Author: Christian Hergert <chergert redhat com>
Date: Fri Aug 25 01:33:49 2017 -0700
perspective port wip
libide/debugger/ide-debug-manager.c | 84 +++++-
libide/debugger/ide-debugger-breakpoints.c | 189 ++++++++++++
libide/debugger/ide-debugger-breakpoints.h | 37 +++
libide/debugger/ide-debugger-controls.c | 40 +++
libide/debugger/ide-debugger-controls.h | 40 +++
libide/debugger/ide-debugger-controls.ui | 92 ++++++
libide/debugger/ide-debugger-gutter-renderer.c | 282 ++++++++++++++++++
libide/debugger/ide-debugger-gutter-renderer.h | 37 +++
libide/debugger/ide-debugger-perspective.c | 370 ++++++++++++++++++++++++
libide/debugger/ide-debugger-perspective.h | 35 +++
libide/debugger/ide-debugger-perspective.ui | 177 +++++++++++
libide/debugger/ide-debugger-private.h | 142 +++++-----
libide/debugger/ide-debugger-types.c | 1 +
libide/debugger/ide-debugger-types.h | 2 +
libide/debugger/ide-debugger-view.c | 155 ++++++++++
libide/debugger/ide-debugger-view.h | 36 +++
libide/debugger/ide-debugger-view.ui | 20 ++
libide/debugger/ide-debugger-workbench-addin.c | 243 ++++++++++++++++
libide/debugger/ide-debugger-workbench-addin.h | 29 ++
libide/ide-context.h | 1 +
libide/ide-types.h | 8 +
libide/libide.gresource.xml | 2 +
libide/meson.build | 12 +
23 files changed, 1960 insertions(+), 74 deletions(-)
---
diff --git a/libide/debugger/ide-debug-manager.c b/libide/debugger/ide-debug-manager.c
index ee7f6a9..f6fa47f 100644
--- a/libide/debugger/ide-debug-manager.c
+++ b/libide/debugger/ide-debug-manager.c
@@ -25,6 +25,7 @@
#include "debugger/ide-debug-manager.h"
#include "debugger/ide-debugger.h"
+#include "debugger/ide-debugger-private.h"
#include "plugins/ide-extension-util.h"
#include "runner/ide-runner.h"
@@ -32,6 +33,7 @@ struct _IdeDebugManager
{
IdeObject parent_instance;
+ GHashTable *breakpoints;
IdeDebugger *debugger;
DzlBindingGroup *debugger_bindings;
DzlSignalGroup *debugger_signals;
@@ -125,6 +127,63 @@ ide_debug_manager_debugger_stopped (IdeDebugManager *self,
}
static void
+ide_debug_manager_breakpoint_added (IdeDebugManager *self,
+ IdeDebuggerBreakpoint *breakpoint,
+ IdeDebugger *debugger)
+{
+ IdeDebuggerBreakpoints *breakpoints;
+ IdeDebuggerBreakMode mode;
+ g_autoptr(GFile) file = NULL;
+ const gchar *path;
+ guint line;
+
+ g_assert (IDE_IS_DEBUG_MANAGER (self));
+ g_assert (IDE_IS_DEBUGGER_BREAKPOINT (breakpoint));
+ g_assert (IDE_IS_DEBUGGER (debugger));
+
+ path = ide_debugger_breakpoint_get_file (breakpoint);
+ file = g_file_new_for_path (path);
+
+ breakpoints = g_hash_table_lookup (self->breakpoints, file);
+
+ if (breakpoints == NULL)
+ {
+ breakpoints = g_object_new (IDE_TYPE_DEBUGGER_BREAKPOINTS,
+ "file", file,
+ NULL);
+ g_hash_table_insert (self->breakpoints, g_steal_pointer (&file), breakpoints);
+ }
+
+ mode = ide_debugger_breakpoint_get_mode (breakpoint);
+ line = ide_debugger_breakpoint_get_line (breakpoint);
+
+ ide_debugger_breakpoints_set_line (breakpoints, line, mode);
+}
+
+static void
+ide_debug_manager_breakpoint_removed (IdeDebugManager *self,
+ IdeDebuggerBreakpoint *breakpoint,
+ IdeDebugger *debugger)
+{
+ IdeDebuggerBreakpoints *breakpoints;
+ g_autoptr(GFile) file = NULL;
+ const gchar *path;
+ guint line;
+
+ g_assert (IDE_IS_DEBUG_MANAGER (self));
+ g_assert (IDE_IS_DEBUGGER_BREAKPOINT (breakpoint));
+ g_assert (IDE_IS_DEBUGGER (debugger));
+
+ line = ide_debugger_breakpoint_get_line (breakpoint);
+ path = ide_debugger_breakpoint_get_file (breakpoint);
+ file = g_file_new_for_path (path);
+
+ breakpoints = g_hash_table_lookup (self->breakpoints, file);
+ if (breakpoints != NULL)
+ ide_debugger_breakpoints_set_line (breakpoints, line, IDE_DEBUGGER_BREAK_NONE);
+}
+
+static void
ide_debug_manager_finalize (GObject *object)
{
IdeDebugManager *self = (IdeDebugManager *)object;
@@ -133,6 +192,7 @@ ide_debug_manager_finalize (GObject *object)
g_clear_object (&self->debugger_bindings);
g_clear_object (&self->debugger_signals);
g_clear_object (&self->runner);
+ g_clear_pointer (&self->breakpoints, g_hash_table_unref);
G_OBJECT_CLASS (ide_debug_manager_parent_class)->finalize (object);
}
@@ -217,13 +277,27 @@ ide_debug_manager_class_init (IdeDebugManagerClass *klass)
static void
ide_debug_manager_init (IdeDebugManager *self)
{
+ self->breakpoints = g_hash_table_new_full ((GHashFunc)g_file_hash,
+ (GEqualFunc)g_file_equal,
+ g_object_unref,
+ g_object_unref);
+
self->debugger_signals = dzl_signal_group_new (IDE_TYPE_DEBUGGER);
- dzl_signal_group_connect_object (self->debugger_signals,
- "stopped",
- G_CALLBACK (ide_debug_manager_debugger_stopped),
- self,
- G_CONNECT_SWAPPED);
+ dzl_signal_group_connect_swapped (self->debugger_signals,
+ "stopped",
+ G_CALLBACK (ide_debug_manager_debugger_stopped),
+ self);
+
+ dzl_signal_group_connect_swapped (self->debugger_signals,
+ "breakpoint-added",
+ G_CALLBACK (ide_debug_manager_breakpoint_added),
+ self);
+
+ dzl_signal_group_connect_swapped (self->debugger_signals,
+ "breakpoint-removed",
+ G_CALLBACK (ide_debug_manager_breakpoint_removed),
+ self);
}
static void
diff --git a/libide/debugger/ide-debugger-breakpoints.c b/libide/debugger/ide-debugger-breakpoints.c
new file mode 100644
index 0000000..d65567c
--- /dev/null
+++ b/libide/debugger/ide-debugger-breakpoints.c
@@ -0,0 +1,189 @@
+/* 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 <stdlib.h>
+
+#include "ide-debug.h"
+
+#include "debugger/ide-debugger-breakpoints.h"
+
+typedef struct
+{
+ guint line;
+ IdeDebuggerBreakMode mode;
+} LineInfo;
+
+struct _IdeDebuggerBreakpoints
+{
+ GObject parent_instance;
+ GArray *lines;
+ GFile *file;
+};
+
+enum {
+ PROP_0,
+ PROP_FILE,
+ N_PROPS
+};
+
+G_DEFINE_TYPE (IdeDebuggerBreakpoints, ide_debugger_breakpoints, G_TYPE_OBJECT)
+
+static GParamSpec *properties [N_PROPS];
+
+static gint
+line_info_compare (gconstpointer a,
+ gconstpointer b)
+{
+ const LineInfo *lia = a;
+ const LineInfo *lib = b;
+
+ return (gint)lia->line - (gint)lib->line;
+}
+
+static void
+ide_debugger_breakpoints_finalize (GObject *object)
+{
+ IdeDebuggerBreakpoints *self = (IdeDebuggerBreakpoints *)object;
+
+ g_clear_object (&self->file);
+ g_clear_pointer (&self->lines, g_array_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->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",
+ "The file for the breakpoints",
+ G_TYPE_FILE,
+ (G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_properties (object_class, N_PROPS, properties);
+}
+
+static void
+ide_debugger_breakpoints_init (IdeDebuggerBreakpoints *self)
+{
+}
+
+IdeDebuggerBreakMode
+ide_debugger_breakpoints_get_line (IdeDebuggerBreakpoints *self,
+ guint line)
+{
+ g_return_val_if_fail (IDE_IS_DEBUGGER_BREAKPOINTS (self), 0);
+
+ if (self->lines != NULL)
+ {
+ LineInfo info = { line, 0 };
+ LineInfo *ret;
+
+ ret = bsearch (&info, (gpointer)self->lines->data,
+ self->lines->len, sizeof (LineInfo),
+ line_info_compare);
+
+ if (ret)
+ return ret->mode;
+ }
+
+ return 0;
+}
+
+void
+ide_debugger_breakpoints_set_line (IdeDebuggerBreakpoints *self,
+ guint line,
+ IdeDebuggerBreakMode mode)
+{
+ LineInfo info;
+
+ g_return_if_fail (IDE_IS_DEBUGGER_BREAKPOINTS (self));
+
+ if (self->lines != NULL)
+ {
+ for (guint i = 0; i < self->lines->len; i++)
+ {
+ LineInfo *ele = &g_array_index (self->lines, LineInfo, i);
+
+ if (ele->line == line)
+ {
+ g_array_remove_index_fast (self->lines, i);
+ break;
+ }
+ }
+ }
+
+ if (mode == IDE_DEBUGGER_BREAK_NONE)
+ return;
+
+ if (self->lines == NULL)
+ self->lines = g_array_new (FALSE, FALSE, sizeof (LineInfo));
+
+ info.line = line;
+ info.mode = mode;
+
+ g_array_append_val (self->lines, info);
+ g_array_sort (self->lines, line_info_compare);
+}
diff --git a/libide/debugger/ide-debugger-breakpoints.h b/libide/debugger/ide-debugger-breakpoints.h
new file mode 100644
index 0000000..1db82c4
--- /dev/null
+++ b/libide/debugger/ide-debugger-breakpoints.h
@@ -0,0 +1,37 @@
+/* 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/>.
+ */
+
+#pragma once
+
+#include <glib-object.h>
+
+#include "ide-debugger-types.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, GObject)
+
+IdeDebuggerBreakMode ide_debugger_breakpoints_get_line (IdeDebuggerBreakpoints *self,
+ guint line);
+void ide_debugger_breakpoints_set_line (IdeDebuggerBreakpoints *self,
+ guint line,
+ IdeDebuggerBreakMode mode);
+
+G_END_DECLS
diff --git a/libide/debugger/ide-debugger-controls.c b/libide/debugger/ide-debugger-controls.c
new file mode 100644
index 0000000..71295b0
--- /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_REVEALER)
+
+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..3e7bd2d
--- /dev/null
+++ b/libide/debugger/ide-debugger-controls.h
@@ -0,0 +1,40 @@
+/* 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"
+
+#include "debugger/ide-debugger.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, GtkRevealer)
+
+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..33a6cd9
--- /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="GtkRevealer">
+ <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">debug-manager.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">debug-manager.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">debug-manager.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">debug-manager.step-in</property>
+ <property name="tooltip-text" translatable="yes">Execute the current line, stepping into any
function calls</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_over_button">
+ <property name="action-name">debug-manager.step-over</property>
+ <property name="tooltip-text" translatable="yes">Execute the current line, stepping over any
function calls</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>
+ <child>
+ <object class="GtkButton" id="finish_button">
+ <property name="action-name">debug-manager.finish</property>
+ <property name="tooltip-text" translatable="yes">Run until the end of the function</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>
+ </object>
+ </child>
+ </template>
+</interface>
diff --git a/libide/debugger/ide-debugger-gutter-renderer.c b/libide/debugger/ide-debugger-gutter-renderer.c
new file mode 100644
index 0000000..e46406e
--- /dev/null
+++ b/libide/debugger/ide-debugger-gutter-renderer.c
@@ -0,0 +1,282 @@
+/* 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-debug.h"
+
+#include "debugger/ide-debugger-gutter-renderer.h"
+#include "debugger/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)
+{
+ IdeDebuggerBreakMode 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)
+{
+ IdeDebuggerBreakMode 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));
+}
+
+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..dd11d35
--- /dev/null
+++ b/libide/debugger/ide-debugger-gutter-renderer.h
@@ -0,0 +1,37 @@
+/* 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/>.
+ */
+
+#pragma once
+
+#include <gtksourceview/gtksource.h>
+
+#include "ide-types.h"
+
+#include "debugger/ide-debugger-breakpoints.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);
+void ide_debugger_gutter_renderer_set_breakpoints (IdeDebuggerGutterRenderer *self,
+ IdeDebuggerBreakpoints
*breakpoints);
+
+G_END_DECLS
diff --git a/libide/debugger/ide-debugger-perspective.c b/libide/debugger/ide-debugger-perspective.c
new file mode 100644
index 0000000..a817e84
--- /dev/null
+++ b/libide/debugger/ide-debugger-perspective.c
@@ -0,0 +1,370 @@
+/* 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 <dazzle.h>
+#include <glib/gi18n.h>
+
+#include "ide-debug.h"
+
+#include "buffers/ide-buffer.h"
+#include "debugger/ide-debugger.h"
+#include "debugger/ide-debugger-perspective.h"
+#include "debugger/ide-debugger-view.h"
+#include "layout/ide-layout-grid.h"
+#include "workbench/ide-perspective.h"
+
+struct _IdeDebuggerPerspective
+{
+ IdeLayout parent_instance;
+
+ IdeDebugger *debugger;
+ DzlSignalGroup *debugger_signals;
+ GSettings *terminal_settings;
+ GtkCssProvider *log_css;
+
+ GtkTextBuffer *log_buffer;
+ GtkTextView *log_text_view;
+ IdeLayoutGrid *layout_grid;
+};
+
+enum {
+ PROP_0,
+ PROP_DEBUGGER,
+ 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_WITH_CODE (IdeDebuggerPerspective, ide_debugger_perspective, IDE_TYPE_LAYOUT,
+ G_IMPLEMENT_INTERFACE (IDE_TYPE_PERSPECTIVE, perspective_iface_init))
+
+static GParamSpec *properties [N_PROPS];
+
+static void
+on_debugger_log (IdeDebuggerPerspective *self,
+ IdeDebuggerStream stream,
+ GBytes *content,
+ IdeDebugger *debugger)
+{
+ g_assert (IDE_IS_DEBUGGER_PERSPECTIVE (self));
+ g_assert (IDE_IS_DEBUGGER_STREAM (stream));
+ g_assert (IDE_IS_DEBUGGER (debugger));
+
+ if (stream == IDE_DEBUGGER_CONSOLE)
+ {
+ const gchar *str;
+ GtkTextIter iter;
+ gsize len;
+
+ str = (gchar *)g_bytes_get_data (content, &len);
+
+ gtk_text_buffer_get_end_iter (self->log_buffer, &iter);
+ gtk_text_buffer_insert (self->log_buffer, &iter, str, len);
+ gtk_text_buffer_select_range (self->log_buffer, &iter, &iter);
+ gtk_text_view_scroll_to_iter (self->log_text_view, &iter, 0.0, FALSE, 1.0, 1.0);
+ }
+}
+
+void
+ide_debugger_perspective_set_debugger (IdeDebuggerPerspective *self,
+ IdeDebugger *debugger)
+{
+ IDE_ENTRY;
+
+ g_return_if_fail (IDE_IS_DEBUGGER_PERSPECTIVE (self));
+ g_return_if_fail (!debugger || IDE_IS_DEBUGGER (debugger));
+
+ if (g_set_object (&self->debugger, debugger))
+ {
+ dzl_signal_group_set_target (self->debugger_signals, debugger);
+ gtk_text_buffer_set_text (self->log_buffer, "", 0);
+ g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_DEBUGGER]);
+ }
+
+ IDE_EXIT;
+}
+
+static void
+log_panel_changed_font_name (IdeDebuggerPerspective *self,
+ const gchar *key,
+ GSettings *settings)
+{
+ gchar *font_name;
+ PangoFontDescription *font_desc;
+
+ g_assert (IDE_IS_DEBUGGER_PERSPECTIVE (self));
+ g_assert (g_strcmp0 (key, "font-name") == 0);
+ g_assert (G_IS_SETTINGS (settings));
+
+ font_name = g_settings_get_string (settings, key);
+ font_desc = pango_font_description_from_string (font_name);
+
+ if (font_desc != NULL)
+ {
+ gchar *fragment;
+ gchar *css;
+
+ fragment = dzl_pango_font_description_to_css (font_desc);
+ css = g_strdup_printf ("textview { %s }", fragment);
+
+ gtk_css_provider_load_from_data (self->log_css, css, -1, NULL);
+
+ pango_font_description_free (font_desc);
+ g_free (fragment);
+ g_free (css);
+ }
+
+ g_free (font_name);
+}
+
+static void
+on_debugger_stopped (IdeDebuggerPerspective *self,
+ IdeDebuggerStopReason reason,
+ IdeDebuggerBreakpoint *breakpoint,
+ IdeDebugger *debugger)
+{
+ IDE_ENTRY;
+
+ g_assert (IDE_IS_DEBUGGER_PERSPECTIVE (self));
+ g_assert (!breakpoint || IDE_IS_DEBUGGER_BREAKPOINT (breakpoint));
+ g_assert (IDE_IS_DEBUGGER (debugger));
+
+ if (breakpoint != NULL)
+ ide_debugger_perspective_navigate_to_breakpoint (self, breakpoint);
+
+ IDE_EXIT;
+}
+
+static void
+ide_debugger_perspective_finalize (GObject *object)
+{
+ IdeDebuggerPerspective *self = (IdeDebuggerPerspective *)object;
+
+ g_clear_object (&self->debugger);
+ g_clear_object (&self->debugger_signals);
+ g_clear_object (&self->terminal_settings);
+ g_clear_object (&self->log_css);
+
+ 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)
+ {
+ case PROP_DEBUGGER:
+ g_value_set_object (value, self->debugger);
+ break;
+
+ 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)
+ {
+ case PROP_DEBUGGER:
+ ide_debugger_perspective_set_debugger (self, g_value_get_object (value));
+ break;
+
+ 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;
+
+ properties [PROP_DEBUGGER] =
+ g_param_spec_object ("debugger",
+ "Debugger",
+ "The current debugger instance",
+ IDE_TYPE_DEBUGGER,
+ (G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_properties (object_class, N_PROPS, properties);
+
+ gtk_widget_class_set_template_from_resource (widget_class,
"/org/gnome/builder/ui/ide-debugger-perspective.ui");
+ gtk_widget_class_bind_template_child (widget_class, IdeDebuggerPerspective, layout_grid);
+ gtk_widget_class_bind_template_child (widget_class, IdeDebuggerPerspective, log_text_view);
+ gtk_widget_class_bind_template_child (widget_class, IdeDebuggerPerspective, log_buffer);
+}
+
+static void
+ide_debugger_perspective_init (IdeDebuggerPerspective *self)
+{
+ GtkStyleContext *context;
+
+ gtk_widget_init_template (GTK_WIDGET (self));
+
+ self->debugger_signals = dzl_signal_group_new (IDE_TYPE_DEBUGGER);
+
+ dzl_signal_group_connect_object (self->debugger_signals,
+ "log",
+ G_CALLBACK (on_debugger_log),
+ self,
+ G_CONNECT_SWAPPED);
+
+ dzl_signal_group_connect_object (self->debugger_signals,
+ "stopped",
+ G_CALLBACK (on_debugger_stopped),
+ self,
+ G_CONNECT_SWAPPED);
+
+ self->log_css = gtk_css_provider_new ();
+ context = gtk_widget_get_style_context (GTK_WIDGET (self->log_text_view));
+ gtk_style_context_add_provider (context,
+ GTK_STYLE_PROVIDER (self->log_css),
+ GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
+
+ self->terminal_settings = g_settings_new ("org.gnome.builder.terminal");
+ g_signal_connect_object (self->terminal_settings,
+ "changed::font-name",
+ G_CALLBACK (log_panel_changed_font_name),
+ self,
+ G_CONNECT_SWAPPED);
+ log_panel_changed_font_name (self, "font-name", self->terminal_settings);
+}
+
+static void
+ide_debugger_perspective_load_source_cb (GObject *object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ IdeDebugger *debugger = (IdeDebugger *)object;
+ g_autoptr(IdeDebuggerPerspective) self = user_data;
+ g_autoptr(IdeBuffer) buffer = NULL;
+ g_autoptr(GError) error = NULL;
+ IdeLayoutView *view;
+ GtkWidget *stack;
+
+ IDE_ENTRY;
+
+ g_assert (IDE_IS_DEBUGGER (debugger));
+ g_assert (G_IS_ASYNC_RESULT (result));
+ g_assert (IDE_IS_DEBUGGER_PERSPECTIVE (self));
+
+ buffer = ide_debugger_load_source_finish (debugger, result, &error);
+
+ if (buffer == NULL)
+ {
+ g_warning ("%s", error->message);
+ IDE_GOTO (failure);
+ }
+
+ view = g_object_new (IDE_TYPE_DEBUGGER_VIEW,
+ "buffer", buffer,
+ "visible", TRUE,
+ NULL);
+
+ stack = ide_layout_grid_get_last_focus (self->layout_grid);
+ gtk_container_add (GTK_CONTAINER (stack), GTK_WIDGET (view));
+
+failure:
+ IDE_EXIT;
+}
+
+void
+ide_debugger_perspective_navigate_to_breakpoint (IdeDebuggerPerspective *self,
+ IdeDebuggerBreakpoint *breakpoint)
+{
+ IDE_ENTRY;
+
+ g_return_if_fail (IDE_IS_DEBUGGER_PERSPECTIVE (self));
+ g_return_if_fail (IDE_IS_DEBUGGER_BREAKPOINT (breakpoint));
+ g_return_if_fail (IDE_IS_DEBUGGER (self->debugger));
+
+ /*
+ * To display the source for the breakpoint, first we need to discover what
+ * file contains the source. If there is no file, then we need to ask the
+ * IdeDebugger to retrieve the disassembly for us so that we can show
+ * something "useful" to the developer.
+ *
+ * If we also fail to get the disassembly for the current breakpoint, we
+ * need to load some dummy text into a buffer to denote to the developer
+ * that technically they can click forward, but the behavior is rather
+ * undefined.
+ *
+ * If the file on disk is out of date (due to changes behind the scenes) we
+ * will likely catch that with a CRC check. We will show the file, but the
+ * user will have an infobar displayed that denotes that the file is not
+ * longer in sync with the debugged executable.
+ */
+
+ ide_debugger_load_source_async (self->debugger,
+ breakpoint,
+ NULL,
+ ide_debugger_perspective_load_source_cb,
+ g_object_ref (self));
+
+ IDE_EXIT;
+}
diff --git a/libide/debugger/ide-debugger-perspective.h b/libide/debugger/ide-debugger-perspective.h
new file mode 100644
index 0000000..d83075e
--- /dev/null
+++ b/libide/debugger/ide-debugger-perspective.h
@@ -0,0 +1,35 @@
+/* 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/>.
+ */
+
+#pragma once
+
+#include "debugger/ide-debugger-breakpoint.h"
+#include "layout/ide-layout.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)
+
+void ide_debugger_perspective_set_debugger (IdeDebuggerPerspective *self,
+ IdeDebugger *debugger);
+void ide_debugger_perspective_navigate_to_breakpoint (IdeDebuggerPerspective *self,
+ IdeDebuggerBreakpoint *breakpoint);
+
+G_END_DECLS
diff --git a/libide/debugger/ide-debugger-perspective.ui b/libide/debugger/ide-debugger-perspective.ui
new file mode 100644
index 0000000..7b7b212
--- /dev/null
+++ b/libide/debugger/ide-debugger-perspective.ui
@@ -0,0 +1,177 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <template class="IdeDebuggerPerspective" parent="IdeLayout">
+ <child>
+ <object class="IdeLayoutGrid" id="layout_grid">
+ <property name="visible">true</property>
+ </object>
+ </child>
+ <child internal-child="left">
+ <object class="DzlDockBinEdge">
+ <property name="reveal-child">true</property>
+ </object>
+ </child>
+ <child type="left">
+ <object class="DzlDockStack">
+ <property name="visible">true</property>
+ <property name="vexpand">true</property>
+ <child>
+ <object class="DzlDockWidget">
+ <property name="title" translatable="yes">Threads</property>
+ <property name="expand">true</property>
+ <property name="visible">true</property>
+ <child>
+ <object class="GtkScrolledWindow">
+ <property name="min-content-width">200</property>
+ <property name="propagate-natural-height">true</property>
+ <property name="visible">true</property>
+ <child>
+ <object class="GtkTreeView">
+ <property name="visible">true</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child type="left">
+ <object class="DzlDockStack">
+ <property name="visible">true</property>
+ <property name="vexpand">true</property>
+ <child>
+ <object class="DzlDockWidget">
+ <property name="title" translatable="yes">Stack</property>
+ <property name="expand">true</property>
+ <property name="visible">true</property>
+ <child>
+ <object class="GtkScrolledWindow">
+ <property name="min-content-width">200</property>
+ <property name="propagate-natural-height">true</property>
+ <property name="visible">true</property>
+ <child>
+ <object class="GtkTreeView">
+ <property name="visible">true</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child internal-child="right">
+ <object class="DzlDockBinEdge">
+ <property name="reveal-child">true</property>
+ </object>
+ </child>
+ <child type="right">
+ <object class="DzlDockStack">
+ <property name="visible">true</property>
+ <property name="vexpand">true</property>
+ <child>
+ <object class="DzlDockWidget">
+ <property name="title" translatable="yes">Variables</property>
+ <property name="expand">true</property>
+ <property name="visible">true</property>
+ <child>
+ <object class="GtkScrolledWindow">
+ <property name="min-content-width">200</property>
+ <property name="propagate-natural-height">true</property>
+ <property name="visible">true</property>
+ <child>
+ <object class="GtkTreeView">
+ <property name="visible">true</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child type="right">
+ <object class="DzlDockStack">
+ <property name="visible">true</property>
+ <property name="vexpand">true</property>
+ <child>
+ <object class="DzlDockWidget">
+ <property name="title" translatable="yes">Registers</property>
+ <property name="expand">true</property>
+ <property name="visible">true</property>
+ <child>
+ <object class="GtkScrolledWindow">
+ <property name="min-content-width">200</property>
+ <property name="propagate-natural-height">true</property>
+ <property name="visible">true</property>
+ <child>
+ <object class="GtkTreeView">
+ <property name="visible">true</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+
+ <child internal-child="bottom">
+ <object class="DzlDockBinEdge">
+ <property name="reveal-child">true</property>
+ </object>
+ </child>
+ <child type="bottom">
+ <object class="DzlDockStack">
+ <property name="hexpand">true</property>
+ <property name="visible">true</property>
+ <child>
+ <object class="DzlDockWidget">
+ <property name="title" translatable="yes">Application Output</property>
+ <property name="expand">true</property>
+ <property name="visible">true</property>
+ </object>
+ </child>
+ <child>
+ <object class="DzlDockWidget">
+ <property name="title" translatable="yes">Breakpoints</property>
+ <property name="expand">true</property>
+ <property name="visible">true</property>
+ <child>
+ <object class="GtkScrolledWindow">
+ <property name="visible">true</property>
+ <child>
+ <object class="GtkTreeView" id="breakpoints_tree_view">
+ <property name="visible">true</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="DzlDockWidget">
+ <property name="title" translatable="yes">Log</property>
+ <property name="visible">true</property>
+ <child>
+ <object class="GtkScrolledWindow">
+ <property name="visible">true</property>
+ <child>
+ <object class="GtkTextView" id="log_text_view">
+ <property name="buffer">log_buffer</property>
+ <property name="editable">false</property>
+ <property name="monospace">true</property>
+ <property name="vexpand">true</property>
+ <property name="visible">true</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </template>
+ <object class="GtkTextBuffer" id="log_buffer"/>
+</interface>
diff --git a/libide/debugger/ide-debugger-private.h b/libide/debugger/ide-debugger-private.h
index 3641bf3..fd20f5b 100644
--- a/libide/debugger/ide-debugger-private.h
+++ b/libide/debugger/ide-debugger-private.h
@@ -18,78 +18,82 @@
#pragma once
+#include "ide-debug-manager.h"
#include "ide-debugger.h"
+#include "ide-debugger-breakpoints.h"
G_BEGIN_DECLS
-void _ide_debugger_class_init_actions (GActionGroupInterface *iface);
-void _ide_debugger_update_actions (IdeDebugger *self);
-gboolean _ide_debugger_get_has_started (IdeDebugger *self);
-void _ide_debugger_real_list_frames_async (IdeDebugger *self,
- IdeDebuggerThread *thread,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data);
-GPtrArray *_ide_debugger_real_list_frames_finish (IdeDebugger *self,
- GAsyncResult *result,
- GError **error);
-void _ide_debugger_real_interrupt_async (IdeDebugger *self,
- IdeDebuggerThreadGroup *thread_group,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data);
-gboolean _ide_debugger_real_interrupt_finish (IdeDebugger *self,
- GAsyncResult *result,
- GError **error);
-void _ide_debugger_real_send_signal_async (IdeDebugger *self,
- gint signum,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data);
-gboolean _ide_debugger_real_send_signal_finish (IdeDebugger *self,
- GAsyncResult *result,
- GError **error);
-void _ide_debugger_real_modify_breakpoint_async (IdeDebugger *self,
- IdeDebuggerBreakpointChange change,
- IdeDebuggerBreakpoint *breakpoint,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data);
-gboolean _ide_debugger_real_modify_breakpoint_finish (IdeDebugger *self,
- GAsyncResult *result,
- GError **error);
-void _ide_debugger_real_list_params_async (IdeDebugger *self,
- IdeDebuggerThread *thread,
- IdeDebuggerFrame *frame,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data);
-GPtrArray *_ide_debugger_real_list_params_finish (IdeDebugger *self,
- GAsyncResult *result,
- GError **error);
-void _ide_debugger_real_list_locals_async (IdeDebugger *self,
- IdeDebuggerThread *thread,
- IdeDebuggerFrame *frame,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data);
-GPtrArray *_ide_debugger_real_list_locals_finish (IdeDebugger *self,
- GAsyncResult *result,
- GError **error);
-void _ide_debugger_real_list_registers_async (IdeDebugger *self,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data);
-GPtrArray *_ide_debugger_real_list_registers_finish (IdeDebugger *self,
- GAsyncResult *result,
- GError **error);
-void _ide_debugger_real_disassemble_async (IdeDebugger *self,
- const IdeDebuggerAddressRange *range,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data);
-GPtrArray *_ide_debugger_real_disassemble_finish (IdeDebugger *self,
- GAsyncResult *result,
- GError **error);
+IdeDebuggerBreakpoints *_ide_debug_manager_get_breakpoints (IdeDebugManager *self,
+ GFile *file);
+void _ide_debugger_class_init_actions (GActionGroupInterface *iface);
+void _ide_debugger_update_actions (IdeDebugger *self);
+gboolean _ide_debugger_get_has_started (IdeDebugger *self);
+void _ide_debugger_real_list_frames_async (IdeDebugger *self,
+ IdeDebuggerThread *thread,
+ GCancellable
*cancellable,
+ GAsyncReadyCallback
callback,
+ gpointer
user_data);
+GPtrArray *_ide_debugger_real_list_frames_finish (IdeDebugger *self,
+ GAsyncResult *result,
+ GError **error);
+void _ide_debugger_real_interrupt_async (IdeDebugger *self,
+ IdeDebuggerThreadGroup
*thread_group,
+ GCancellable
*cancellable,
+ GAsyncReadyCallback
callback,
+ gpointer
user_data);
+gboolean _ide_debugger_real_interrupt_finish (IdeDebugger *self,
+ GAsyncResult *result,
+ GError **error);
+void _ide_debugger_real_send_signal_async (IdeDebugger *self,
+ gint signum,
+ GCancellable
*cancellable,
+ GAsyncReadyCallback
callback,
+ gpointer
user_data);
+gboolean _ide_debugger_real_send_signal_finish (IdeDebugger *self,
+ GAsyncResult *result,
+ GError **error);
+void _ide_debugger_real_modify_breakpoint_async (IdeDebugger *self,
+ IdeDebuggerBreakpointChange change,
+ IdeDebuggerBreakpoint
*breakpoint,
+ GCancellable
*cancellable,
+ GAsyncReadyCallback
callback,
+ gpointer
user_data);
+gboolean _ide_debugger_real_modify_breakpoint_finish (IdeDebugger *self,
+ GAsyncResult *result,
+ GError **error);
+void _ide_debugger_real_list_params_async (IdeDebugger *self,
+ IdeDebuggerThread *thread,
+ IdeDebuggerFrame *frame,
+ GCancellable
*cancellable,
+ GAsyncReadyCallback
callback,
+ gpointer
user_data);
+GPtrArray *_ide_debugger_real_list_params_finish (IdeDebugger *self,
+ GAsyncResult *result,
+ GError **error);
+void _ide_debugger_real_list_locals_async (IdeDebugger *self,
+ IdeDebuggerThread *thread,
+ IdeDebuggerFrame *frame,
+ GCancellable
*cancellable,
+ GAsyncReadyCallback
callback,
+ gpointer
user_data);
+GPtrArray *_ide_debugger_real_list_locals_finish (IdeDebugger *self,
+ GAsyncResult *result,
+ GError **error);
+void _ide_debugger_real_list_registers_async (IdeDebugger *self,
+ GCancellable
*cancellable,
+ GAsyncReadyCallback
callback,
+ gpointer
user_data);
+GPtrArray *_ide_debugger_real_list_registers_finish (IdeDebugger *self,
+ GAsyncResult *result,
+ GError **error);
+void _ide_debugger_real_disassemble_async (IdeDebugger *self,
+ const IdeDebuggerAddressRange *range,
+ GCancellable
*cancellable,
+ GAsyncReadyCallback
callback,
+ gpointer
user_data);
+GPtrArray *_ide_debugger_real_disassemble_finish (IdeDebugger *self,
+ GAsyncResult *result,
+ GError **error);
G_END_DECLS
diff --git a/libide/debugger/ide-debugger-types.c b/libide/debugger/ide-debugger-types.c
index 80cd7c5..47b92c1 100644
--- a/libide/debugger/ide-debugger-types.c
+++ b/libide/debugger/ide-debugger-types.c
@@ -102,6 +102,7 @@ ide_debugger_break_mode_get_type (void)
{
GType _type_id;
static const GEnumValue values[] = {
+ { IDE_DEBUGGER_BREAK_NONE, "IDE_DEBUGGER_BREAK_NONE", "none" },
{ IDE_DEBUGGER_BREAK_BREAKPOINT, "IDE_DEBUGGER_BREAK_BREAKPOINT", "breakpoint" },
{ IDE_DEBUGGER_BREAK_COUNTPOINT, "IDE_DEBUGGER_BREAK_COUNTPOINT", "countpoint" },
{ IDE_DEBUGGER_BREAK_WATCHPOINT, "IDE_DEBUGGER_BREAK_WATCHPOINT", "watchpoint" },
diff --git a/libide/debugger/ide-debugger-types.h b/libide/debugger/ide-debugger-types.h
index a2a1353..96435c1 100644
--- a/libide/debugger/ide-debugger-types.h
+++ b/libide/debugger/ide-debugger-types.h
@@ -104,6 +104,7 @@ typedef enum
/**
* IdeDebuggerBreakMode:
+ * @IDE_DEBUGGER_BREAK_NONE: No breakpoint is set
* @IDE_DEBUGGER_BREAK_BREAKPOINT: A simple breakpoint that stops the debugger
* when reaching a given location.
* @IDE_DEBUGGER_BREAK_COUNTPOINT: A counter that is incremented when the
@@ -115,6 +116,7 @@ typedef enum
*/
typedef enum
{
+ IDE_DEBUGGER_BREAK_NONE = 0,
IDE_DEBUGGER_BREAK_BREAKPOINT,
IDE_DEBUGGER_BREAK_COUNTPOINT,
IDE_DEBUGGER_BREAK_WATCHPOINT,
diff --git a/libide/debugger/ide-debugger-view.c b/libide/debugger/ide-debugger-view.c
new file mode 100644
index 0000000..69149cc
--- /dev/null
+++ b/libide/debugger/ide-debugger-view.c
@@ -0,0 +1,155 @@
+/* ide-debugger-view.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-view"
+
+#include <gtksourceview/gtksource.h>
+
+#include "ide-debug.h"
+
+#include "buffers/ide-buffer.h"
+#include "debugger/ide-debugger-gutter-renderer.h"
+#include "debugger/ide-debugger-view.h"
+
+struct _IdeDebuggerView
+{
+ IdeLayoutView parent_instance;
+
+ GtkSourceView *source_view;
+ IdeDebuggerGutterRenderer *breakpoints_gutter;
+};
+
+enum {
+ PROP_0,
+ PROP_BUFFER,
+ N_PROPS
+};
+
+G_DEFINE_TYPE (IdeDebuggerView, ide_debugger_view, IDE_TYPE_LAYOUT_VIEW)
+
+static GParamSpec *properties [N_PROPS];
+
+static void
+ide_debugger_view_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ IdeDebuggerView *self = IDE_DEBUGGER_VIEW (object);
+
+ switch (prop_id)
+ {
+ case PROP_BUFFER:
+ g_value_set_object (value, ide_debugger_view_get_buffer (self));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+ide_debugger_view_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ IdeDebuggerView *self = IDE_DEBUGGER_VIEW (object);
+
+ switch (prop_id)
+ {
+ case PROP_BUFFER:
+ ide_debugger_view_set_buffer (self, g_value_get_object (value));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+ide_debugger_view_class_init (IdeDebuggerViewClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->get_property = ide_debugger_view_get_property;
+ object_class->set_property = ide_debugger_view_set_property;
+
+ properties [PROP_BUFFER] =
+ g_param_spec_object ("buffer",
+ "Buffer",
+ "The buffer for the view",
+ GTK_SOURCE_TYPE_BUFFER,
+ (G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_properties (object_class, N_PROPS, properties);
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/builder/ui/ide-debugger-view.ui");
+ gtk_widget_class_bind_template_child (widget_class, IdeDebuggerView, source_view);
+}
+
+static void
+ide_debugger_view_init (IdeDebuggerView *self)
+{
+ GtkSourceGutter *gutter;
+
+ gtk_widget_init_template (GTK_WIDGET (self));
+
+ gutter = gtk_source_view_get_gutter (GTK_SOURCE_VIEW (self->source_view), GTK_TEXT_WINDOW_LEFT);
+ self->breakpoints_gutter = g_object_new (IDE_TYPE_DEBUGGER_GUTTER_RENDERER,
+ "visible", TRUE,
+ NULL);
+ gtk_source_gutter_insert (gutter, GTK_SOURCE_GUTTER_RENDERER (self->breakpoints_gutter), -100);
+}
+
+GtkWidget *
+ide_debugger_view_new (void)
+{
+ return g_object_new (IDE_TYPE_DEBUGGER_VIEW, NULL);
+}
+
+/**
+ * ide_debugger_view_get_buffer:
+ * @self: a #IdeDebuggerView
+ *
+ * Gets the buffer for the view.
+ *
+ * Returns: (transfer none): A #GtkSourceBuffer
+ */
+GtkSourceBuffer *
+ide_debugger_view_get_buffer (IdeDebuggerView *self)
+{
+ g_return_val_if_fail (IDE_IS_DEBUGGER_VIEW (self), NULL);
+
+ return GTK_SOURCE_BUFFER (gtk_text_view_get_buffer (GTK_TEXT_VIEW (self->source_view)));
+}
+
+void
+ide_debugger_view_set_buffer (IdeDebuggerView *self,
+ GtkSourceBuffer *buffer)
+{
+ g_return_if_fail (IDE_IS_DEBUGGER_VIEW (self));
+ g_return_if_fail (GTK_SOURCE_IS_BUFFER (buffer));
+
+ if (buffer != ide_debugger_view_get_buffer (self))
+ {
+ gtk_text_view_set_buffer (GTK_TEXT_VIEW (self->source_view), GTK_TEXT_BUFFER (buffer));
+ g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_BUFFER]);
+ }
+}
diff --git a/libide/debugger/ide-debugger-view.h b/libide/debugger/ide-debugger-view.h
new file mode 100644
index 0000000..5151c04
--- /dev/null
+++ b/libide/debugger/ide-debugger-view.h
@@ -0,0 +1,36 @@
+/* ide-debugger-view.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/>.
+ */
+
+#pragma once
+
+#include <gtksourceview/gtksource.h>
+
+#include "layout/ide-layout-view.h"
+
+G_BEGIN_DECLS
+
+#define IDE_TYPE_DEBUGGER_VIEW (ide_debugger_view_get_type())
+
+G_DECLARE_FINAL_TYPE (IdeDebuggerView, ide_debugger_view, IDE, DEBUGGER_VIEW, IdeLayoutView)
+
+GtkWidget *ide_debugger_view_new (void);
+GtkSourceBuffer *ide_debugger_view_get_buffer (IdeDebuggerView *self);
+void ide_debugger_view_set_buffer (IdeDebuggerView *self,
+ GtkSourceBuffer *buffer);
+
+G_END_DECLS
diff --git a/libide/debugger/ide-debugger-view.ui b/libide/debugger/ide-debugger-view.ui
new file mode 100644
index 0000000..42c911e
--- /dev/null
+++ b/libide/debugger/ide-debugger-view.ui
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<interface>
+ <template class="IdeDebuggerView" parent="IdeLayoutView">
+ <child>
+ <object class="GtkScrolledWindow">
+ <property name="expand">true</property>
+ <property name="visible">true</property>
+ <child>
+ <object class="GtkSourceView" id="source_view">
+ <property name="highlight-current-line">true</property>
+ <property name="show-line-numbers">true</property>
+ <property name="monospace">true</property>
+ <property name="editable">false</property>
+ <property name="visible">true</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </template>
+</interface>
diff --git a/libide/debugger/ide-debugger-workbench-addin.c b/libide/debugger/ide-debugger-workbench-addin.c
new file mode 100644
index 0000000..ac6f414
--- /dev/null
+++ b/libide/debugger/ide-debugger-workbench-addin.c
@@ -0,0 +1,243 @@
+/* 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 <dazzle.h>
+#include <glib/gi18n.h>
+#include <gtksourceview/gtksource.h>
+
+#include "ide-context.h"
+#include "ide-debug.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 "runner/ide-run-manager.h"
+#include "workbench/ide-workbench-addin.h"
+#include "workbench/ide-workbench-message.h"
+
+struct _IdeDebuggerWorkbenchAddin
+{
+ GObject parent_instance;
+ IdeWorkbench *workbench;
+ IdeDebuggerControls *controls;
+ IdeWorkbenchMessage *message;
+ IdeDebuggerPerspective *perspective;
+ DzlSignalGroup *debug_manager_signals;
+};
+
+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
+debug_manager_notify_active (IdeDebuggerWorkbenchAddin *self,
+ GParamSpec *pspec,
+ IdeDebugManager *debug_manager)
+{
+ g_assert (IDE_IS_DEBUGGER_WORKBENCH_ADDIN (self));
+ g_assert (IDE_IS_DEBUG_MANAGER (debug_manager));
+
+ /*
+ * Instead of using a property binding, we use this signal callback so
+ * that we can adjust the reveal-child and visible. Otherwise the widgets
+ * will take up space+padding when reveal-child is FALSE.
+ */
+
+ if (ide_debug_manager_get_active (debug_manager))
+ {
+ gtk_widget_show (GTK_WIDGET (self->controls));
+ gtk_revealer_set_reveal_child (GTK_REVEALER (self->controls), TRUE);
+ }
+ else
+ {
+ gtk_revealer_set_reveal_child (GTK_REVEALER (self->controls), FALSE);
+ }
+}
+
+static void
+controls_notify_child_revealed (IdeDebuggerWorkbenchAddin *self,
+ GParamSpec *pspec,
+ IdeDebuggerControls *controls)
+{
+ g_assert (IDE_IS_DEBUGGER_WORKBENCH_ADDIN (self));
+ g_assert (IDE_IS_DEBUGGER_CONTROLS (controls));
+
+ if (!gtk_revealer_get_child_revealed (GTK_REVEALER (controls)))
+ gtk_widget_hide (GTK_WIDGET (controls));
+}
+
+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->debug_manager_signals = dzl_signal_group_new (IDE_TYPE_DEBUG_MANAGER);
+
+ dzl_signal_group_connect_object (self->debug_manager_signals,
+ "notify::active",
+ G_CALLBACK (debug_manager_notify_active),
+ self,
+ G_CONNECT_SWAPPED);
+
+ dzl_signal_group_set_target (self->debug_manager_signals, debug_manager);
+
+ self->controls = g_object_new (IDE_TYPE_DEBUGGER_CONTROLS,
+ "transition-duration", 500,
+ "transition-type", GTK_REVEALER_TRANSITION_TYPE_SLIDE_RIGHT,
+ "reveal-child", FALSE,
+ "visible", FALSE,
+ NULL);
+ g_signal_connect_object (self->controls,
+ "notify::child-revealed",
+ G_CALLBACK (controls_notify_child_revealed),
+ self,
+ G_CONNECT_SWAPPED);
+ 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);
+ g_object_bind_property (debug_manager, "debugger",
+ self->perspective, "debugger",
+ G_BINDING_SYNC_CREATE);
+ 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);
+
+ g_clear_object (&self->debug_manager_signals);
+
+ /* 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..df10b61
--- /dev/null
+++ b/libide/debugger/ide-debugger-workbench-addin.h
@@ -0,0 +1,29 @@
+/* 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/>.
+ */
+
+#pragma once
+
+#include <glib-object.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
diff --git a/libide/ide-context.h b/libide/ide-context.h
index 7c6c50f..55a06ae 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);
IdeDocumentation *ide_context_get_documentation (IdeContext *self);
diff --git a/libide/ide-types.h b/libide/ide-types.h
index 9a02b4a..0661c15 100644
--- a/libide/ide-types.h
+++ b/libide/ide-types.h
@@ -47,6 +47,14 @@ typedef struct _IdeConfigurationManager IdeConfigurationManager;
typedef struct _IdeContext IdeContext;
+typedef struct _IdeDebugManager IdeDebugManager;
+typedef struct _IdeDebugger IdeDebugger;
+typedef struct _IdeDebuggerBreakpoint IdeDebuggerBreakpoint;
+typedef struct _IdeDebuggerFrame IdeDebuggerFrame;
+typedef struct _IdeDebuggerInstruction IdeDebuggerInstruction;
+typedef struct _IdeDebuggerRegister IdeDebuggerRegister;
+typedef struct _IdeDebuggerVariable IdeDebuggerVariable;
+
typedef struct _IdeDevice IdeDevice;
typedef struct _IdeDeviceManager IdeDeviceManager;
typedef struct _IdeDeviceProvider IdeDeviceProvider;
diff --git a/libide/libide.gresource.xml b/libide/libide.gresource.xml
index a5b295c..c609570 100644
--- a/libide/libide.gresource.xml
+++ b/libide/libide.gresource.xml
@@ -55,6 +55,8 @@
</gresource>
<gresource prefix="/org/gnome/builder/ui">
+ <file compressed="true" preprocess="xml-stripblanks"
alias="ide-debugger-controls.ui">debugger/ide-debugger-controls.ui</file>
+ <file compressed="true" preprocess="xml-stripblanks"
alias="ide-debugger-view.ui">debugger/ide-debugger-view.ui</file>
<file compressed="true" preprocess="xml-stripblanks"
alias="ide-layout-pane.ui">layout/ide-layout-pane.ui</file>
<file compressed="true" preprocess="xml-stripblanks"
alias="ide-layout-stack-header.ui">layout/ide-layout-stack-header.ui</file>
<file compressed="true" preprocess="xml-stripblanks"
alias="ide-layout-stack.ui">layout/ide-layout-stack.ui</file>
diff --git a/libide/meson.build b/libide/meson.build
index 26a18cd..e2985df 100644
--- a/libide/meson.build
+++ b/libide/meson.build
@@ -90,6 +90,7 @@ libide_public_headers = [
'debugger/ide-debugger-frame.h',
'debugger/ide-debugger-instruction.h',
'debugger/ide-debugger-library.h',
+ 'debugger/ide-debugger-perspective.h',
'debugger/ide-debugger-register.h',
'debugger/ide-debugger-thread-group.h',
'debugger/ide-debugger-thread.h',
@@ -302,6 +303,7 @@ libide_public_sources = [
'debugger/ide-debugger-frame.c',
'debugger/ide-debugger-instruction.c',
'debugger/ide-debugger-library.c',
+ 'debugger/ide-debugger-perspective.c',
'debugger/ide-debugger-register.c',
'debugger/ide-debugger-thread-group.c',
'debugger/ide-debugger-thread.c',
@@ -507,7 +509,13 @@ libide_sources = libide_generated_headers + libide_public_sources + [
'debugger/ide-debugger-address-map.h',
'debugger/ide-debugger-breakpoints-view.c',
'debugger/ide-debugger-breakpoints-view.h',
+ 'debugger/ide-debugger-controls.c',
+ 'debugger/ide-debugger-controls.h',
'debugger/ide-debugger-fallbacks.c',
+ 'debugger/ide-debugger-breakpoints.c',
+ 'debugger/ide-debugger-breakpoints.h',
+ 'debugger/ide-debugger-gutter-renderer.c',
+ 'debugger/ide-debugger-gutter-renderer.h',
'debugger/ide-debugger-libraries-view.c',
'debugger/ide-debugger-libraries-view.h',
'debugger/ide-debugger-locals-view.c',
@@ -517,6 +525,10 @@ libide_sources = libide_generated_headers + libide_public_sources + [
'debugger/ide-debugger-registers-view.h',
'debugger/ide-debugger-threads-view.c',
'debugger/ide-debugger-threads-view.h',
+ 'debugger/ide-debugger-view.c',
+ 'debugger/ide-debugger-view.h',
+ 'debugger/ide-debugger-workbench-addin.c',
+ 'debugger/ide-debugger-workbench-addin.h',
'editor/ide-editor-layout-stack-addin.c',
'editor/ide-editor-layout-stack-addin.h',
'editor/ide-editor-layout-stack-controls.c',
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]