[gnome-builder/wip/chergert/bug1: 63/69] debugger: highlight the current breakpoint position



commit ac4f0ff781dd8684b06c7df6b0cbc6846d07ea27
Author: Christian Hergert <chergert redhat com>
Date:   Thu Aug 31 16:55:19 2017 -0700

    debugger: highlight the current breakpoint position

 libide/buffers/ide-buffer.c         |   15 ++++
 libide/debugger/ide-debug-manager.c |  150 +++++++++++++++++++++++++++++++++++
 2 files changed, 165 insertions(+), 0 deletions(-)
---
diff --git a/libide/buffers/ide-buffer.c b/libide/buffers/ide-buffer.c
index e7150d1..d186430 100644
--- a/libide/buffers/ide-buffer.c
+++ b/libide/buffers/ide-buffer.c
@@ -63,11 +63,14 @@
 #define TAG_NOTE             "diagnostician::note"
 #define TAG_SNIPPET_TAB_STOP "snippet::tab-stop"
 #define TAG_DEFINITION       "action::hover-definition"
+#define TAG_CURRENT_BKPT     "debugger::current-breakpoint"
 
 #define DEPRECATED_COLOR "#babdb6"
 #define ERROR_COLOR      "#ff0000"
 #define NOTE_COLOR       "#708090"
 #define WARNING_COLOR    "#fcaf3e"
+#define CURRENT_BKPT_FG  "#fffffe"
+#define CURRENT_BKPT_BG  "#fcaf3e"
 
 typedef struct
 {
@@ -1033,6 +1036,14 @@ ide_buffer_notify_style_scheme (IdeBuffer  *self,
         apply_style (GET_TAG (TAG_DEFINITION),
                      "underline", PANGO_UNDERLINE_SINGLE,
                      NULL);
+
+      if (!ide_source_style_scheme_apply_style (style_scheme,
+                                                TAG_CURRENT_BKPT,
+                                                GET_TAG (TAG_CURRENT_BKPT)))
+        apply_style (GET_TAG (TAG_CURRENT_BKPT),
+                     "paragraph-background", CURRENT_BKPT_BG,
+                     "foreground", CURRENT_BKPT_FG,
+                     NULL);
     }
 
 #undef GET_TAG
@@ -1289,6 +1300,10 @@ ide_buffer_init_tags (IdeBuffer *self)
   gtk_text_buffer_create_tag (GTK_TEXT_BUFFER (self), TAG_DEFINITION,
                               "underline", PANGO_UNDERLINE_SINGLE,
                               NULL);
+  gtk_text_buffer_create_tag (GTK_TEXT_BUFFER (self), TAG_CURRENT_BKPT,
+                              "paragraph-background", CURRENT_BKPT_BG,
+                              "foreground", CURRENT_BKPT_FG,
+                              NULL);
 
   g_signal_connect_object (tag_table,
                            "tag-added",
diff --git a/libide/debugger/ide-debug-manager.c b/libide/debugger/ide-debug-manager.c
index 83c7f01..0d0e55a 100644
--- a/libide/debugger/ide-debug-manager.c
+++ b/libide/debugger/ide-debug-manager.c
@@ -23,12 +23,17 @@
 
 #include "ide-debug.h"
 
+#include "buffers/ide-buffer.h"
+#include "buffers/ide-buffer-manager.h"
 #include "debugger/ide-debug-manager.h"
 #include "debugger/ide-debugger.h"
 #include "debugger/ide-debugger-private.h"
+#include "files/ide-file.h"
 #include "plugins/ide-extension-util.h"
 #include "runner/ide-runner.h"
 
+#define TAG_CURRENT_BKPT "debugger::current-breakpoint"
+
 struct _IdeDebugManager
 {
   IdeObject           parent_instance;
@@ -195,13 +200,153 @@ ide_debug_manager_breakpoint_modified (IdeDebugManager       *self,
 }
 
 static void
+ide_debug_manager_unmark_stopped (IdeDebugManager *self,
+                                  IdeBuffer       *buffer)
+{
+  GtkTextIter begin;
+  GtkTextIter end;
+
+  g_assert (IDE_IS_DEBUG_MANAGER (self));
+  g_assert (IDE_IS_BUFFER (buffer));
+
+  gtk_text_buffer_get_bounds (GTK_TEXT_BUFFER (buffer), &begin, &end);
+  gtk_text_buffer_remove_tag_by_name (GTK_TEXT_BUFFER (buffer),
+                                      TAG_CURRENT_BKPT,
+                                      &begin, &end);
+}
+
+static void
+ide_debug_manager_debugger_running (IdeDebugManager *self,
+                                    IdeDebugger     *debugger)
+{
+  IdeBufferManager *bufmgr;
+  IdeContext *context;
+  guint n_items;
+
+  IDE_ENTRY;
+
+  g_assert (IDE_IS_DEBUG_MANAGER (self));
+  g_assert (IDE_IS_DEBUGGER (debugger));
+
+  context = ide_object_get_context (IDE_OBJECT (self));
+  bufmgr = ide_context_get_buffer_manager (context);
+
+  n_items = g_list_model_get_n_items (G_LIST_MODEL (bufmgr));
+
+  /*
+   * This might be bordering on "too much work to do at once" if there is a
+   * sufficient number of buffers open. I'm not sure how much btree scanning is
+   * required to clear the tags.
+   *
+   * Alternatively, we could store the buffers we've touched and then just clear
+   * them, which would be strictly better (but annoying from object life-cycle
+   * standpoint).
+   */
+
+  for (guint i = 0; i < n_items; i++)
+    {
+      g_autoptr(IdeBuffer) buffer = g_list_model_get_item (G_LIST_MODEL (bufmgr), i);
+
+      ide_debug_manager_unmark_stopped (self, buffer);
+    }
+
+  IDE_EXIT;
+}
+
+static void
+ide_debug_manager_mark_stopped (IdeDebugManager       *self,
+                                IdeBuffer             *buffer,
+                                IdeDebuggerBreakpoint *breakpoint)
+{
+  GtkTextIter iter;
+  GtkTextIter end;
+  guint line;
+
+  g_assert (IDE_IS_DEBUG_MANAGER (self));
+  g_assert (IDE_IS_BUFFER (buffer));
+  g_assert (IDE_IS_DEBUGGER_BREAKPOINT (breakpoint));
+
+  line = ide_debugger_breakpoint_get_line (breakpoint);
+
+  if (line > 0)
+    line--;
+
+  gtk_text_buffer_get_iter_at_line (GTK_TEXT_BUFFER (buffer), &iter, line);
+  end = iter;
+  gtk_text_iter_forward_line (&iter);
+
+  gtk_text_buffer_apply_tag_by_name (GTK_TEXT_BUFFER (buffer),
+                                     TAG_CURRENT_BKPT,
+                                     &iter, &end);
+}
+
+static void
+ide_debug_manager_load_file_cb (GObject      *object,
+                                GAsyncResult *result,
+                                gpointer      user_data)
+{
+  IdeBufferManager *bufmgr = (IdeBufferManager *)object;
+  g_autoptr(GTask) task = user_data;
+  g_autoptr(IdeBuffer) buffer = NULL;
+  g_autoptr(GError) error = NULL;
+  IdeDebuggerBreakpoint *breakpoint;
+  IdeDebugManager *self;
+
+  IDE_ENTRY;
+
+  g_assert (IDE_IS_BUFFER_MANAGER (bufmgr));
+  g_assert (G_IS_ASYNC_RESULT (result));
+  g_assert (G_IS_TASK (task));
+
+  buffer = ide_buffer_manager_load_file_finish (bufmgr, result, &error);
+
+  if (buffer == NULL)
+    {
+      g_warning ("%s", error->message);
+      IDE_EXIT;
+    }
+
+  self = g_task_get_source_object (task);
+  g_assert (IDE_IS_DEBUG_MANAGER (self));
+
+  breakpoint = g_task_get_task_data (task);
+  g_assert (IDE_IS_DEBUGGER_BREAKPOINT (breakpoint));
+
+  ide_debug_manager_mark_stopped (self, buffer, breakpoint);
+
+  IDE_EXIT;
+}
+
+static void
 ide_debug_manager_real_breakpoint_reached (IdeDebugManager       *self,
                                            IdeDebuggerBreakpoint *breakpoint)
 {
+  const gchar *path;
 
   g_assert (IDE_IS_DEBUG_MANAGER (self));
   g_assert (IDE_IS_DEBUGGER_BREAKPOINT (breakpoint));
 
+  path = ide_debugger_breakpoint_get_file (breakpoint);
+
+  if (path != NULL)
+    {
+      IdeContext *context = ide_object_get_context (IDE_OBJECT (self));
+      IdeBufferManager *bufmgr = ide_context_get_buffer_manager (context);
+      g_autoptr(IdeFile) file = ide_file_new_for_path (context, path);
+      g_autoptr(GTask) task = NULL;
+
+      task = g_task_new (self, NULL, NULL, NULL);
+      g_task_set_task_data (task, g_object_ref (breakpoint), g_object_unref);
+
+      ide_buffer_manager_load_file_async (bufmgr,
+                                          file,
+                                          FALSE,
+                                          IDE_WORKBENCH_OPEN_FLAGS_NONE,
+                                          NULL,
+                                          NULL,
+                                          ide_debug_manager_load_file_cb,
+                                          g_steal_pointer (&task));
+    }
 }
 
 static void
@@ -361,6 +506,11 @@ ide_debug_manager_init (IdeDebugManager *self)
                                     self);
 
   dzl_signal_group_connect_swapped (self->debugger_signals,
+                                    "running",
+                                    G_CALLBACK (ide_debug_manager_debugger_running),
+                                    self);
+
+  dzl_signal_group_connect_swapped (self->debugger_signals,
                                     "breakpoint-added",
                                     G_CALLBACK (ide_debug_manager_breakpoint_added),
                                     self);


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