[gnome-builder] editor: bring back simplified form of the overview map



commit 98ae8e9c7ee6da5cc093cb69a71347768dfe274d
Author: Christian Hergert <chergert redhat com>
Date:   Sat Jul 1 02:07:04 2017 -0700

    editor: bring back simplified form of the overview map
    
    This gets rid of a bunch of the junk we had previously while
    bringing back the overview map feature. The MapBin is no
    longer necessary and we can vastly simplify how we track
    events to bring the map back into display.

 libide/editor/ide-editor-private.h |   10 ++-
 libide/editor/ide-editor-view.c    |  234 ++++++++++++++++++++++++++++++++++--
 libide/editor/ide-editor-view.h    |   16 ++-
 libide/editor/ide-editor-view.ui   |   24 +++-
 4 files changed, 265 insertions(+), 19 deletions(-)
---
diff --git a/libide/editor/ide-editor-private.h b/libide/editor/ide-editor-private.h
index 1bece92..1f61388 100644
--- a/libide/editor/ide-editor-private.h
+++ b/libide/editor/ide-editor-private.h
@@ -37,12 +37,20 @@ struct _IdeEditorView
   DzlBindingGroup         *buffer_bindings;
   DzlSignalGroup          *buffer_signals;
 
+  GtkSourceMap            *map;
+  GtkRevealer             *map_revealer;
   GtkOverlay              *overlay;
+  GtkProgressBar          *progress_bar;
   IdeSourceView           *source_view;
   GtkScrolledWindow       *scroller;
+  GtkBox                  *scroller_box;
   IdeEditorSearchBar      *search_bar;
   GtkRevealer             *search_revealer;
-  GtkProgressBar          *progress_bar;
+
+  guint                    toggle_map_source;
+
+  guint                    auto_hide_map : 1;
+  guint                    show_map : 1;
 };
 
 void _ide_editor_view_init_actions          (IdeEditorView        *self);
diff --git a/libide/editor/ide-editor-view.c b/libide/editor/ide-editor-view.c
index 7ad6740..6d7478c 100644
--- a/libide/editor/ide-editor-view.c
+++ b/libide/editor/ide-editor-view.c
@@ -18,17 +18,25 @@
 
 #define G_LOG_DOMAIN "ide-editor-view"
 
+#include "config.h"
+
 #include <dazzle.h>
 #include <libpeas/peas.h>
+#include <pango/pangofc-fontmap.h>
 
 #include "ide-internal.h"
+#include "ide-macros.h"
 
 #include "editor/ide-editor-private.h"
 #include "util/ide-gtk.h"
 
+#define AUTO_HIDE_TIMEOUT_SECONDS 5
+
 enum {
   PROP_0,
+  PROP_AUTO_HIDE_MAP,
   PROP_BUFFER,
+  PROP_SHOW_MAP,
   PROP_VIEW,
   N_PROPS
 };
@@ -37,9 +45,42 @@ enum {
   DND_TARGET_URI_LIST = 100,
 };
 
+static void ide_editor_view_update_reveal_timer (IdeEditorView *self);
+
 G_DEFINE_TYPE (IdeEditorView, ide_editor_view, IDE_TYPE_LAYOUT_VIEW)
 
 static GParamSpec *properties [N_PROPS];
+static FcConfig *localFontConfig;
+
+static void
+ide_editor_view_load_fonts (IdeEditorView *self)
+{
+  PangoFontMap *font_map;
+  PangoFontDescription *font_desc;
+
+  if (g_once_init_enter (&localFontConfig))
+    {
+      const gchar *font_path = PACKAGE_DATADIR"/gnome-builder/fonts/BuilderBlocks.ttf";
+      FcConfig *config = FcInitLoadConfigAndFonts ();
+
+      if (g_getenv ("GB_IN_TREE_FONTS") != NULL)
+        font_path = "data/fonts/BuilderBlocks.ttf";
+
+      FcConfigAppFontAddFile (localFontConfig, (const FcChar8 *)font_path);
+
+      g_once_init_leave (&localFontConfig, config);
+    }
+
+  font_map = pango_cairo_font_map_new_for_font_type (CAIRO_FONT_TYPE_FT);
+  pango_fc_font_map_set_config (PANGO_FC_FONT_MAP (font_map), localFontConfig);
+  gtk_widget_set_font_map (GTK_WIDGET (self->map), font_map);
+
+  font_desc = pango_font_description_from_string ("Builder Blocks 1");
+  g_object_set (self->map, "font-desc", font_desc, NULL);
+
+  g_object_unref (font_map);
+  pango_font_description_free (font_desc);
+}
 
 static void
 ide_editor_view_notify_child_revealed (IdeEditorView *self,
@@ -160,6 +201,24 @@ ide_editor_view_buffer_notify_language_cb (IdeExtensionSetAdapter *set,
   ide_editor_view_addin_language_changed (IDE_EDITOR_VIEW_ADDIN (exten), language_id);
 }
 
+static gboolean
+ide_editor_view_source_view_event (IdeEditorView *self,
+                                   GdkEvent      *event,
+                                   IdeSourceView *source_view)
+{
+  g_assert (IDE_IS_EDITOR_VIEW (self));
+  g_assert (event != NULL);
+  g_assert (IDE_IS_SOURCE_VIEW (source_view) || GTK_SOURCE_IS_MAP (source_view));
+
+  if (self->auto_hide_map)
+    {
+      ide_editor_view_update_reveal_timer (self);
+      gtk_revealer_set_reveal_child (self->map_revealer, TRUE);
+    }
+
+  return GDK_EVENT_PROPAGATE;
+}
+
 static void
 ide_editor_view_buffer_notify_language (IdeEditorView *self,
                                         GParamSpec    *pspec,
@@ -320,6 +379,21 @@ ide_editor_view_constructed (GObject *object)
                             "focus-in-event",
                             G_CALLBACK (ide_editor_view_focus_in_event),
                             self);
+
+  g_signal_connect_swapped (self->source_view,
+                            "motion-notify-event",
+                            G_CALLBACK (ide_editor_view_source_view_event),
+                            self);
+
+  g_signal_connect_swapped (self->source_view,
+                            "scroll-event",
+                            G_CALLBACK (ide_editor_view_source_view_event),
+                            self);
+
+  g_signal_connect_swapped (self->map,
+                            "motion-notify-event",
+                            G_CALLBACK (ide_editor_view_source_view_event),
+                            self);
 }
 
 static void
@@ -344,6 +418,7 @@ ide_editor_view_destroy (GtkWidget *widget)
     }
 
   g_clear_object (&self->buffer);
+  ide_clear_source (&self->toggle_map_source);
 
   GTK_WIDGET_CLASS (ide_editor_view_parent_class)->destroy (widget);
 }
@@ -358,6 +433,10 @@ ide_editor_view_get_property (GObject    *object,
 
   switch (prop_id)
     {
+    case PROP_AUTO_HIDE_MAP:
+      g_value_set_boolean (value, ide_editor_view_get_auto_hide_map (self));
+      break;
+
     case PROP_BUFFER:
       g_value_set_object (value, ide_editor_view_get_buffer (self));
       break;
@@ -366,6 +445,10 @@ ide_editor_view_get_property (GObject    *object,
       g_value_set_object (value, ide_editor_view_get_view (self));
       break;
 
+    case PROP_SHOW_MAP:
+      g_value_set_boolean (value, ide_editor_view_get_show_map (self));
+      break;
+
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
     }
@@ -381,10 +464,18 @@ ide_editor_view_set_property (GObject      *object,
 
   switch (prop_id)
     {
+    case PROP_AUTO_HIDE_MAP:
+      ide_editor_view_set_auto_hide_map (self, g_value_get_boolean (value));
+      break;
+
     case PROP_BUFFER:
       ide_editor_view_set_buffer (self, g_value_get_object (value));
       break;
 
+    case PROP_SHOW_MAP:
+      ide_editor_view_set_show_map (self, g_value_get_boolean (value));
+      break;
+
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
     }
@@ -413,6 +504,20 @@ ide_editor_view_class_init (IdeEditorViewClass *klass)
                          IDE_TYPE_BUFFER,
                          (G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
 
+  properties [PROP_SHOW_MAP] =
+    g_param_spec_boolean ("show-map",
+                          "Show Map",
+                          "If the overview map should be shown",
+                          FALSE,
+                          (G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS));
+
+  properties [PROP_AUTO_HIDE_MAP] =
+    g_param_spec_boolean ("auto-hide-map",
+                          "Auto Hide Map",
+                          "If the overview map should be auto-hidden",
+                          FALSE,
+                          (G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS));
+
   properties [PROP_VIEW] =
     g_param_spec_object ("view",
                          "View",
@@ -423,9 +528,12 @@ ide_editor_view_class_init (IdeEditorViewClass *klass)
   g_object_class_install_properties (object_class, N_PROPS, properties);
 
   gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/builder/ui/ide-editor-view.ui");
+  gtk_widget_class_bind_template_child (widget_class, IdeEditorView, map);
+  gtk_widget_class_bind_template_child (widget_class, IdeEditorView, map_revealer);
   gtk_widget_class_bind_template_child (widget_class, IdeEditorView, overlay);
   gtk_widget_class_bind_template_child (widget_class, IdeEditorView, progress_bar);
   gtk_widget_class_bind_template_child (widget_class, IdeEditorView, scroller);
+  gtk_widget_class_bind_template_child (widget_class, IdeEditorView, scroller_box);
   gtk_widget_class_bind_template_child (widget_class, IdeEditorView, search_bar);
   gtk_widget_class_bind_template_child (widget_class, IdeEditorView, search_revealer);
   gtk_widget_class_bind_template_child (widget_class, IdeEditorView, source_view);
@@ -445,9 +553,7 @@ ide_editor_view_init (IdeEditorView *self)
   ide_layout_view_set_can_split (IDE_LAYOUT_VIEW (self), TRUE);
   ide_layout_view_set_menu_id (IDE_LAYOUT_VIEW (self), "ide-editor-view-document-menu");
 
-  /*
-   * Setup signals to monitor on the buffer.
-   */
+  /* Setup signals to monitor on the buffer. */
   self->buffer_signals = dzl_signal_group_new (IDE_TYPE_BUFFER);
 
   dzl_signal_group_connect_swapped (self->buffer_signals,
@@ -470,18 +576,18 @@ ide_editor_view_init (IdeEditorView *self)
                             G_CALLBACK (ide_editor_view_bind_signals),
                             self);
 
-  /*
-   * Setup bindings for the buffer.
-   */
+  /* Setup bindings for the buffer. */
   self->buffer_bindings = dzl_binding_group_new ();
   dzl_binding_group_bind (self->buffer_bindings, "title", self, "title", 0);
 
-  /*
-   * Setup Drag and Drop support.
-   */
+  /* Setup Drag and Drop support. */
   target_list = gtk_drag_dest_get_target_list (GTK_WIDGET (self->source_view));
   if (target_list != NULL)
     gtk_target_list_add_uri_targets (target_list, DND_TARGET_URI_LIST);
+
+  /* Load our custom font for the overview map. */
+  ide_editor_view_load_fonts (self);
+  gtk_source_map_set_view (self->map, GTK_SOURCE_VIEW (self->source_view));
 }
 
 /**
@@ -569,3 +675,113 @@ ide_editor_view_scroll_to_line (IdeEditorView *self,
   gtk_text_buffer_select_range (GTK_TEXT_BUFFER (self->buffer), &iter, &iter);
   ide_source_view_scroll_to_insert (self->source_view);
 }
+
+gboolean
+ide_editor_view_get_auto_hide_map (IdeEditorView *self)
+{
+  g_return_val_if_fail (IDE_IS_EDITOR_VIEW (self), FALSE);
+
+  return self->auto_hide_map;
+}
+
+static gboolean
+ide_editor_view_auto_hide_cb (gpointer user_data)
+{
+  IdeEditorView *self = user_data;
+
+  g_assert (IDE_IS_EDITOR_VIEW (self));
+
+  self->toggle_map_source = 0;
+  gtk_revealer_set_reveal_child (self->map_revealer, FALSE);
+
+  return G_SOURCE_REMOVE;
+}
+
+static void
+ide_editor_view_update_reveal_timer (IdeEditorView *self)
+{
+  g_assert (IDE_IS_EDITOR_VIEW (self));
+
+  ide_clear_source (&self->toggle_map_source);
+
+  if (self->auto_hide_map && gtk_revealer_get_reveal_child (self->map_revealer))
+    {
+      self->toggle_map_source =
+        gdk_threads_add_timeout_seconds_full (G_PRIORITY_LOW,
+                                              AUTO_HIDE_TIMEOUT_SECONDS,
+                                              ide_editor_view_auto_hide_cb,
+                                              g_object_ref (self),
+                                              g_object_unref);
+    }
+}
+
+static void
+ide_editor_view_update_map (IdeEditorView *self)
+{
+  GtkWidget *parent;
+
+  g_assert (IDE_IS_EDITOR_VIEW (self));
+
+  parent = gtk_widget_get_parent (GTK_WIDGET (self->map));
+
+  g_object_ref (self->map);
+
+  gtk_container_remove (GTK_CONTAINER (parent), GTK_WIDGET (self->map));
+
+  if (self->auto_hide_map)
+    gtk_container_add (GTK_CONTAINER (self->map_revealer), GTK_WIDGET (self->map));
+  else
+    gtk_container_add (GTK_CONTAINER (self->scroller_box), GTK_WIDGET (self->map));
+
+  gtk_widget_set_visible (GTK_WIDGET (self->map_revealer), self->show_map);
+  gtk_widget_set_visible (GTK_WIDGET (self->map), self->show_map);
+  gtk_revealer_set_reveal_child (self->map_revealer, self->show_map);
+
+  g_object_set (self->scroller,
+                "vscrollbar-policy", self->show_map ? GTK_POLICY_EXTERNAL : GTK_POLICY_AUTOMATIC,
+                NULL);
+
+  ide_editor_view_update_reveal_timer (self);
+
+  g_object_unref (self->map);
+}
+
+void
+ide_editor_view_set_auto_hide_map (IdeEditorView *self,
+                                   gboolean       auto_hide_map)
+{
+  g_return_if_fail (IDE_IS_EDITOR_VIEW (self));
+
+  auto_hide_map = !!auto_hide_map;
+
+  if (auto_hide_map != self->auto_hide_map)
+    {
+      self->auto_hide_map = auto_hide_map;
+      ide_editor_view_update_map (self);
+      g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_AUTO_HIDE_MAP]);
+    }
+}
+
+gboolean
+ide_editor_view_get_show_map (IdeEditorView *self)
+{
+  g_return_val_if_fail (IDE_IS_EDITOR_VIEW (self), FALSE);
+
+  return self->show_map;
+}
+
+void
+ide_editor_view_set_show_map (IdeEditorView *self,
+                              gboolean       show_map)
+{
+  g_return_if_fail (IDE_IS_EDITOR_VIEW (self));
+
+  show_map = !!show_map;
+
+  if (show_map != self->show_map)
+    {
+      self->show_map = show_map;
+      ide_editor_view_update_map (self);
+      g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_AUTO_HIDE_MAP]);
+    }
+}
diff --git a/libide/editor/ide-editor-view.h b/libide/editor/ide-editor-view.h
index f3392d7..b46b2eb 100644
--- a/libide/editor/ide-editor-view.h
+++ b/libide/editor/ide-editor-view.h
@@ -30,10 +30,16 @@ G_BEGIN_DECLS
 
 G_DECLARE_FINAL_TYPE (IdeEditorView, ide_editor_view, IDE, EDITOR_VIEW, IdeLayoutView)
 
-IdeBuffer     *ide_editor_view_get_buffer      (IdeEditorView *self);
-IdeSourceView *ide_editor_view_get_view        (IdeEditorView *self);
-const gchar   *ide_editor_view_get_language_id (IdeEditorView *self);
-void           ide_editor_view_scroll_to_line  (IdeEditorView *self,
-                                                guint          line);
+IdeBuffer     *ide_editor_view_get_buffer        (IdeEditorView *self);
+IdeSourceView *ide_editor_view_get_view          (IdeEditorView *self);
+const gchar   *ide_editor_view_get_language_id   (IdeEditorView *self);
+void           ide_editor_view_scroll_to_line    (IdeEditorView *self,
+                                                  guint          line);
+gboolean       ide_editor_view_get_auto_hide_map (IdeEditorView *self);
+void           ide_editor_view_set_auto_hide_map (IdeEditorView *self,
+                                                  gboolean       auto_hide_map);
+gboolean       ide_editor_view_get_show_map      (IdeEditorView *self);
+void           ide_editor_view_set_show_map      (IdeEditorView *self,
+                                                  gboolean       show_map);
 
 G_END_DECLS
diff --git a/libide/editor/ide-editor-view.ui b/libide/editor/ide-editor-view.ui
index d5d618a..d70d766 100644
--- a/libide/editor/ide-editor-view.ui
+++ b/libide/editor/ide-editor-view.ui
@@ -25,16 +25,32 @@
             <property name="valign">start</property>
           </object>
         </child>
+        <child type="overlay">
+          <object class="GtkRevealer" id="map_revealer">
+            <property name="halign">end</property>
+            <property name="transition-type">slide-left</property>
+            <property name="vexpand">true</property>
+          </object>
+        </child>
         <child>
-          <object class="GtkScrolledWindow" id="scroller">
-            <property name="expand">true</property>
+          <object class="GtkBox" id="scroller_box">
+            <property name="orientation">horizontal</property>
             <property name="visible">true</property>
             <child>
-              <object class="IdeSourceView" id="source_view">
-                <property name="show-line-numbers">true</property>
+              <object class="GtkScrolledWindow" id="scroller">
+                <property name="expand">true</property>
                 <property name="visible">true</property>
+                <child>
+                  <object class="IdeSourceView" id="source_view">
+                    <property name="show-line-numbers">true</property>
+                    <property name="visible">true</property>
+                  </object>
+                </child>
               </object>
             </child>
+            <child>
+              <object class="GtkSourceMap" id="map"/>
+            </child>
           </object>
         </child>
       </object>


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