[gnome-builder/wip/chergert/completion] completion: move a number of components into IdeCompletion



commit 9f7082fb220d543bc1f9081a432248a53a1bb4e7
Author: Christian Hergert <chergert redhat com>
Date:   Wed May 9 23:06:12 2018 -0700

    completion: move a number of components into IdeCompletion
    
    This starts ripping stuff out of sourceview and into our new completion
    engine. We still have a bunch more to change, but this compiles so it seems
    like a natural point to commit.

 src/libide/completion/ide-completion-display.c  |  10 +
 src/libide/completion/ide-completion-display.h  |   7 +
 src/libide/completion/ide-completion-overlay.c  |  11 +
 src/libide/completion/ide-completion-overlay.h  |   6 -
 src/libide/completion/ide-completion-private.h  |   5 +
 src/libide/completion/ide-completion-provider.c |   8 +-
 src/libide/completion/ide-completion-provider.h |   4 +-
 src/libide/completion/ide-completion-types.h    |   3 +-
 src/libide/completion/ide-completion-view.c     |  10 +
 src/libide/completion/ide-completion-window.c   |  12 ++
 src/libide/completion/ide-completion.c          | 268 +++++++++++++++++++-----
 src/libide/completion/ide-completion.h          |  36 ++--
 src/libide/editor/ide-editor-view-settings.c    |   4 -
 src/libide/sourceview/ide-source-view.c         | 231 ++++++--------------
 14 files changed, 365 insertions(+), 250 deletions(-)
---
diff --git a/src/libide/completion/ide-completion-display.c b/src/libide/completion/ide-completion-display.c
index e760a8835..c6cef90db 100644
--- a/src/libide/completion/ide-completion-display.c
+++ b/src/libide/completion/ide-completion-display.c
@@ -71,3 +71,13 @@ ide_completion_display_attach (IdeCompletionDisplay *self,
 
   IDE_COMPLETION_DISPLAY_GET_IFACE (self)->attach (self, view);
 }
+
+void
+ide_completion_display_move_cursor (IdeCompletionDisplay *self,
+                                    GtkMovementStep       step,
+                                    gint                  count)
+{
+  g_return_if_fail (IDE_IS_COMPLETION_DISPLAY (self));
+
+  IDE_COMPLETION_DISPLAY_GET_IFACE (self)->move_cursor (self, step, count);
+}
diff --git a/src/libide/completion/ide-completion-display.h b/src/libide/completion/ide-completion-display.h
index d37e810a0..0405f8d20 100644
--- a/src/libide/completion/ide-completion-display.h
+++ b/src/libide/completion/ide-completion-display.h
@@ -43,6 +43,9 @@ struct _IdeCompletionDisplayInterface
                                GtkSourceView        *view);
   void     (*set_n_rows)      (IdeCompletionDisplay *self,
                                guint                 n_rows);
+  void     (*move_cursor)     (IdeCompletionDisplay *self,
+                               GtkMovementStep       step,
+                               gint                  count);
 };
 
 IDE_AVAILABLE_IN_3_30
@@ -57,5 +60,9 @@ gboolean ide_completion_display_key_press_event (IdeCompletionDisplay *self,
 IDE_AVAILABLE_IN_3_30
 void     ide_completion_display_set_n_rows      (IdeCompletionDisplay *self,
                                                  guint                 n_rows);
+IDE_AVAILABLE_IN_3_30
+void     ide_completion_display_move_cursor     (IdeCompletionDisplay *self,
+                                                 GtkMovementStep       step,
+                                                 gint                  count);
 
 G_END_DECLS
diff --git a/src/libide/completion/ide-completion-overlay.c b/src/libide/completion/ide-completion-overlay.c
index 880e1d9ee..985ae7d31 100644
--- a/src/libide/completion/ide-completion-overlay.c
+++ b/src/libide/completion/ide-completion-overlay.c
@@ -279,6 +279,16 @@ ide_completion_overlay_set_context (IdeCompletionOverlay *self,
   g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_CONTEXT]);
 }
 
+static void
+ide_completion_overlay_move_cursor (IdeCompletionDisplay *display,
+                                    GtkMovementStep       step,
+                                    gint                  count)
+{
+  g_assert (IDE_IS_COMPLETION_OVERLAY (display));
+
+  _ide_completion_view_move_cursor (IDE_COMPLETION_OVERLAY (display)->view, step, count);
+}
+
 static void
 completion_display_iface_init (IdeCompletionDisplayInterface *iface)
 {
@@ -286,4 +296,5 @@ completion_display_iface_init (IdeCompletionDisplayInterface *iface)
   iface->attach = ide_completion_overlay_attach;
   iface->key_press_event = ide_completion_overlay_key_press_event;
   iface->set_n_rows = ide_completion_overlay_set_n_rows;
+  iface->move_cursor = ide_completion_overlay_move_cursor;
 }
diff --git a/src/libide/completion/ide-completion-overlay.h b/src/libide/completion/ide-completion-overlay.h
index d0489a1f7..780adb591 100644
--- a/src/libide/completion/ide-completion-overlay.h
+++ b/src/libide/completion/ide-completion-overlay.h
@@ -31,10 +31,4 @@ G_BEGIN_DECLS
 IDE_AVAILABLE_IN_3_30
 G_DECLARE_FINAL_TYPE (IdeCompletionOverlay, ide_completion_overlay, IDE, COMPLETION_OVERLAY, DzlBin)
 
-IDE_AVAILABLE_IN_3_30
-IdeCompletionContext *ide_completion_overlay_get_context (IdeCompletionOverlay *self);
-IDE_AVAILABLE_IN_3_30
-void                  ide_completion_overlay_set_context (IdeCompletionOverlay *self,
-                                                          IdeCompletionContext *context);
-
 G_END_DECLS
diff --git a/src/libide/completion/ide-completion-private.h b/src/libide/completion/ide-completion-private.h
index bc872dc40..73b4f161b 100644
--- a/src/libide/completion/ide-completion-private.h
+++ b/src/libide/completion/ide-completion-private.h
@@ -29,7 +29,12 @@ void                     _ide_completion_view_set_n_rows           (IdeCompletio
 gint                     _ide_completion_view_get_x_offset         (IdeCompletionView        *self);
 gboolean                 _ide_completion_view_handle_key_press     (IdeCompletionView        *self,
                                                                     const GdkEventKey        *event);
+void                     _ide_completion_view_move_cursor          (IdeCompletionView        *self,
+                                                                    GtkMovementStep           step,
+                                                                    gint                      count);
 IdeCompletion           *_ide_completion_new                       (GtkSourceView            *view);
+void                     _ide_completion_set_language_id           (IdeCompletion            *self,
+                                                                    const gchar              *language_id);
 void                     _ide_completion_activate                  (IdeCompletion            *self,
                                                                     IdeCompletionContext     *context,
                                                                     IdeCompletionProvider    *provider,
diff --git a/src/libide/completion/ide-completion-provider.c b/src/libide/completion/ide-completion-provider.c
index 53b0ded09..fbecf3626 100644
--- a/src/libide/completion/ide-completion-provider.c
+++ b/src/libide/completion/ide-completion-provider.c
@@ -174,7 +174,7 @@ ide_completion_provider_activate_poposal (IdeCompletionProvider *self,
  * ide_completion_provider_refilter:
  * @self: an #IdeCompletionProvider
  * @context: an #IdeCompletionContext
- * @results: a #GListModel of results previously provided to the context
+ * @proposals: a #GListModel of results previously provided to the context
  *
  * This requests that the completion provider refilter the results based on
  * changes to the #IdeCompletionContext, such as additional text typed by the
@@ -191,14 +191,14 @@ ide_completion_provider_activate_poposal (IdeCompletionProvider *self,
 gboolean
 ide_completion_provider_refilter (IdeCompletionProvider *self,
                                   IdeCompletionContext  *context,
-                                  GListModel            *results)
+                                  GListModel            *proposals)
 {
   g_return_val_if_fail (IDE_IS_COMPLETION_PROVIDER (self), FALSE);
   g_return_val_if_fail (IDE_IS_COMPLETION_CONTEXT (context), FALSE);
-  g_return_val_if_fail (G_IS_LIST_MODEL (results), FALSE);
+  g_return_val_if_fail (G_IS_LIST_MODEL (proposals), FALSE);
 
   if (IDE_COMPLETION_PROVIDER_GET_IFACE (self)->refilter)
-    return IDE_COMPLETION_PROVIDER_GET_IFACE (self)->refilter (self, context, results);
+    return IDE_COMPLETION_PROVIDER_GET_IFACE (self)->refilter (self, context, proposals);
 
   return FALSE;
 }
diff --git a/src/libide/completion/ide-completion-provider.h b/src/libide/completion/ide-completion-provider.h
index 506a40cdd..8aef10eda 100644
--- a/src/libide/completion/ide-completion-provider.h
+++ b/src/libide/completion/ide-completion-provider.h
@@ -44,7 +44,7 @@ struct _IdeCompletionProviderInterface
   gchar      *(*get_title)         (IdeCompletionProvider  *self);
   void        (*populate_async)    (IdeCompletionProvider  *self,
                                     GCancellable           *cancellable,
-                                    GListModel            **results,
+                                    GListModel            **proposals,
                                     GAsyncReadyCallback     callback,
                                     gpointer                user_data);
   GListModel *(*populate_finish)   (IdeCompletionProvider  *self,
@@ -77,7 +77,7 @@ gchar      *ide_completion_provider_get_title        (IdeCompletionProvider  *se
 IDE_AVAILABLE_IN_3_30
 void        ide_completion_provider_populate_async   (IdeCompletionProvider  *self,
                                                       GCancellable           *cancellable,
-                                                      GListModel            **results,
+                                                      GListModel            **proposals,
                                                       GAsyncReadyCallback     callback,
                                                       gpointer                user_data);
 IDE_AVAILABLE_IN_3_30
diff --git a/src/libide/completion/ide-completion-types.h b/src/libide/completion/ide-completion-types.h
index ef7c1d6a1..46df79312 100644
--- a/src/libide/completion/ide-completion-types.h
+++ b/src/libide/completion/ide-completion-types.h
@@ -24,6 +24,7 @@ G_BEGIN_DECLS
 
 typedef struct _IdeCompletion           IdeCompletion;
 typedef struct _IdeCompletionContext    IdeCompletionContext;
+typedef struct _IdeCompletionDisplay    IdeCompletionDisplay;
 typedef struct _IdeCompletionListBox    IdeCompletionListBox;
 typedef struct _IdeCompletionListBoxRow IdeCompletionListBoxRow;
 typedef struct _IdeCompletionOverlay    IdeCompletionOverlay;
@@ -32,8 +33,6 @@ typedef struct _IdeCompletionProvider   IdeCompletionProvider;
 typedef struct _IdeCompletionView       IdeCompletionView;
 typedef struct _IdeCompletionWindow     IdeCompletionWindow;
 
-typedef struct _IdeSourceView           IdeSourceView;
-
 typedef enum
 {
   IDE_COMPLETION_COLUMN_ICON,
diff --git a/src/libide/completion/ide-completion-view.c b/src/libide/completion/ide-completion-view.c
index d5961bd87..fdf164dd6 100644
--- a/src/libide/completion/ide-completion-view.c
+++ b/src/libide/completion/ide-completion-view.c
@@ -409,3 +409,13 @@ _ide_completion_view_handle_key_press (IdeCompletionView *self,
 
   return gtk_binding_set_activate (binding_set, event->keyval, event->state, G_OBJECT (self));
 }
+
+void
+_ide_completion_view_move_cursor (IdeCompletionView *self,
+                                  GtkMovementStep    step,
+                                  gint               count)
+{
+  g_return_if_fail (IDE_IS_COMPLETION_VIEW (self));
+
+  g_signal_emit (self, signals [MOVE_CURSOR], 0, step, count);
+}
diff --git a/src/libide/completion/ide-completion-window.c b/src/libide/completion/ide-completion-window.c
index 4e5d1716a..88169de4f 100644
--- a/src/libide/completion/ide-completion-window.c
+++ b/src/libide/completion/ide-completion-window.c
@@ -349,6 +349,17 @@ ide_completion_window_attach (IdeCompletionDisplay *display,
     gtk_window_set_transient_for (GTK_WINDOW (display), GTK_WINDOW (toplevel));
 }
 
+
+static void
+ide_completion_window_move_cursor (IdeCompletionDisplay *display,
+                                   GtkMovementStep       step,
+                                   gint                  count)
+{
+  g_assert (IDE_IS_COMPLETION_WINDOW (display));
+
+  _ide_completion_view_move_cursor (IDE_COMPLETION_WINDOW (display)->view, step, count);
+}
+
 static void
 completion_display_iface_init (IdeCompletionDisplayInterface *iface)
 {
@@ -356,4 +367,5 @@ completion_display_iface_init (IdeCompletionDisplayInterface *iface)
   iface->set_n_rows = ide_completion_window_set_n_rows;
   iface->attach = ide_completion_window_attach;
   iface->key_press_event = ide_completion_window_key_press_event;
+  iface->move_cursor = ide_completion_window_move_cursor;
 }
diff --git a/src/libide/completion/ide-completion.c b/src/libide/completion/ide-completion.c
index b41ad0f44..1071dfe24 100644
--- a/src/libide/completion/ide-completion.c
+++ b/src/libide/completion/ide-completion.c
@@ -23,18 +23,20 @@
 #include <gtk/gtk.h>
 #include <dazzle.h>
 #include <gtksourceview/gtksource.h>
+#include <libpeas/peas.h>
 
 #ifdef GDK_WINDOWING_WAYLAND
 # include <gdk/gdkwayland.h>
 #endif
 
-#include "ide-completion.h"
-#include "ide-completion-context.h"
-#include "ide-completion-display.h"
-#include "ide-completion-overlay.h"
-#include "ide-completion-private.h"
-#include "ide-completion-proposal.h"
-#include "ide-completion-provider.h"
+#include "buffers/ide-buffer.h"
+#include "completion/ide-completion.h"
+#include "completion/ide-completion-context.h"
+#include "completion/ide-completion-display.h"
+#include "completion/ide-completion-overlay.h"
+#include "completion/ide-completion-private.h"
+#include "completion/ide-completion-proposal.h"
+#include "completion/ide-completion-provider.h"
 
 #define DEFAULT_N_ROWS 5
 
@@ -55,6 +57,13 @@ struct _IdeCompletion
    */
   GCancellable *cancellable;
 
+  /*
+   * Our extension manager to get providers that were registered by plugins.
+   * We handle extension-added/extension-removed and add the results to the
+   * @providers array so that we can allow manual adding of providers too.
+   */
+  IdeExtensionSetAdapter *addins;
+
   /*
    * An array of providers that have been registered. These will be queried
    * when input is provided for completion.
@@ -390,43 +399,19 @@ ide_completion_create_display (IdeCompletion *self)
 static void
 ide_completion_real_show (IdeCompletion *self)
 {
-  g_assert (IDE_IS_COMPLETION (self));
+  IdeCompletionDisplay *display;
 
-  if (self->display == NULL)
-    {
-      self->display = ide_completion_create_display (self);
-      ide_completion_display_set_n_rows (self->display, self->n_rows);
-      ide_completion_display_attach (self->display, self->view);
+  g_assert (IDE_IS_COMPLETION (self));
 
-#if 0
-#ifdef GDK_WINDOWING_WAYLAND
-      /*
-       * HACK: We need to show the window and hide it so that we get a proper
-       * positioning on the first "visible" display to the user. To make that
-       * work, we set opacity to transparent and then go through the dance.
-       *
-       * We could remove this if we had the ability to set_use_subsurface() on
-       * the window.
-       *
-       * We only do this on Wayland as it is not an issue on Xorg.
-       */
-      if (GDK_IS_WAYLAND_DISPLAY (gdk_display_get_default ()))
-        {
-          gtk_widget_set_opacity (GTK_WIDGET (self->window), 0.0);
-          g_signal_connect (self->window, "configure-event", G_CALLBACK (configure_hack_cb), NULL);
-          gtk_window_present (GTK_WINDOW (self->window));
-        }
-#endif
-#endif
-    }
+  display = ide_completion_get_display (self);
 
   if (self->context == NULL)
     ide_completion_start (self, IDE_COMPLETION_USER_REQUESTED);
 
-  ide_completion_display_set_context (self->display, self->context);
+  ide_completion_display_set_context (display, self->context);
 
   if (!ide_completion_context_is_empty (self->context))
-    gtk_widget_show (GTK_WIDGET (self->display));
+    gtk_widget_show (GTK_WIDGET (display));
 }
 
 static void
@@ -639,6 +624,119 @@ ide_completion_set_view (IdeCompletion *self,
     }
 }
 
+static void
+ide_completion_addins_extension_added_cb (IdeExtensionSetAdapter *adapter,
+                                          PeasPluginInfo         *plugin_info,
+                                          PeasExtension          *exten,
+                                          gpointer                user_data)
+{
+  IdeCompletionProvider *provider = (IdeCompletionProvider *)exten;
+  IdeCompletion *self = user_data;
+  GtkTextBuffer *buffer;
+
+  g_assert (IDE_IS_EXTENSION_SET_ADAPTER (adapter));
+  g_assert (plugin_info != NULL);
+  g_assert (IDE_IS_COMPLETION_PROVIDER (provider));
+
+  /* TODO: Remove this when no longer necessary */
+
+  if ((buffer = ide_completion_get_buffer (self)) && IDE_IS_BUFFER (buffer))
+    {
+      IdeContext *context = ide_buffer_get_context (IDE_BUFFER (buffer));
+      ide_completion_provider_load (provider, context);
+    }
+
+  ide_completion_add_provider (self, provider);
+}
+
+static void
+ide_completion_addins_extension_removed_cb (IdeExtensionSetAdapter *adapter,
+                                            PeasPluginInfo         *plugin_info,
+                                            PeasExtension          *exten,
+                                            gpointer                user_data)
+{
+  IdeCompletionProvider *provider = (IdeCompletionProvider *)exten;
+  IdeCompletion *self = user_data;
+
+  g_assert (IDE_IS_EXTENSION_SET_ADAPTER (adapter));
+  g_assert (plugin_info != NULL);
+  g_assert (IDE_IS_COMPLETION_PROVIDER (provider));
+
+  ide_completion_remove_provider (self, provider);
+}
+
+static void
+ide_completion_buffer_signals_bind_cb (IdeCompletion   *self,
+                                       GtkSourceBuffer *buffer,
+                                       DzlSignalGroup  *group)
+{
+  GtkSourceLanguage *language;
+  const gchar *language_id = NULL;
+  IdeContext *context;
+
+  g_assert (IDE_IS_COMPLETION (self));
+  g_assert (GTK_SOURCE_IS_BUFFER (buffer));
+  g_assert (DZL_IS_SIGNAL_GROUP (group));
+
+  if (!IDE_IS_BUFFER (buffer))
+    return;
+
+  if ((language = gtk_source_buffer_get_language (buffer)))
+    language_id = gtk_source_language_get_id (language);
+
+  context = ide_buffer_get_context (IDE_BUFFER (buffer));
+
+  self->addins = ide_extension_set_adapter_new (context,
+                                                peas_engine_get_default (),
+                                                IDE_TYPE_COMPLETION_PROVIDER,
+                                                "Completion-Provider-Languages",
+                                                language_id);
+
+  g_signal_connect (self->addins,
+                    "extension-added",
+                    G_CALLBACK (ide_completion_addins_extension_added_cb),
+                    self);
+  g_signal_connect (self->addins,
+                    "extension-removed",
+                    G_CALLBACK (ide_completion_addins_extension_removed_cb),
+                    self);
+
+  ide_extension_set_adapter_foreach (self->addins,
+                                     ide_completion_addins_extension_added_cb,
+                                     self);
+}
+
+static void
+ide_completion_buffer_signals_unbind_cb (IdeCompletion   *self,
+                                         DzlSignalGroup  *group)
+{
+  g_assert (IDE_IS_COMPLETION (self));
+  g_assert (DZL_IS_SIGNAL_GROUP (group));
+
+  g_clear_object (&self->addins);
+}
+
+static void
+ide_completion_buffer_notify_language_cb (IdeCompletion   *self,
+                                          GParamSpec      *pspec,
+                                          GtkSourceBuffer *buffer)
+{
+  g_assert (IDE_IS_COMPLETION (self));
+  g_assert (pspec != NULL);
+  g_assert (GTK_SOURCE_IS_BUFFER (buffer));
+
+  if (self->addins != NULL)
+    {
+      GtkSourceLanguage *language;
+      const gchar *language_id = NULL;
+
+      if ((language = gtk_source_buffer_get_language (buffer)))
+        language_id = gtk_source_language_get_id (language);
+
+      ide_extension_set_adapter_set_value (self->addins, language_id);
+    }
+}
+
 static void
 ide_completion_dispose (GObject *object)
 {
@@ -897,6 +995,21 @@ ide_completion_init (IdeCompletion *self)
    * possibly start showing the results, or update our previous completion
    * request.
    */
+  g_signal_connect_object (self->buffer_signals,
+                           "bind",
+                           G_CALLBACK (ide_completion_buffer_signals_bind_cb),
+                           self,
+                           G_CONNECT_SWAPPED);
+  g_signal_connect_object (self->buffer_signals,
+                           "unbind",
+                           G_CALLBACK (ide_completion_buffer_signals_unbind_cb),
+                           self,
+                           G_CONNECT_SWAPPED);
+  dzl_signal_group_connect_object (self->buffer_signals,
+                                   "notify::language",
+                                   G_CALLBACK (ide_completion_buffer_notify_language_cb),
+                                   self,
+                                   G_CONNECT_AFTER | G_CONNECT_SWAPPED);
   dzl_signal_group_connect_object (self->buffer_signals,
                                    "delete-range",
                                    G_CALLBACK (ide_completion_buffer_delete_range_cb),
@@ -1085,22 +1198,6 @@ ide_completion_cancel (IdeCompletion *self)
     }
 }
 
-/**
- * ide_completion_is_visible:
- * @self: a #IdeCompletion
- *
- * Checks if the window is currently being displayed.
- *
- * Returns: %TRUE if the window is being displayed
- */
-gboolean
-ide_completion_is_visible (IdeCompletion *self)
-{
-  g_return_val_if_fail (IDE_IS_COMPLETION (self), FALSE);
-
-  return gtk_widget_get_visible (GTK_WIDGET (self->display));
-}
-
 void
 ide_completion_block_interactive (IdeCompletion *self)
 {
@@ -1158,3 +1255,70 @@ _ide_completion_activate (IdeCompletion         *self,
   ide_completion_provider_activate_poposal (provider, context, proposal, self->current_event);
   self->block_count--;
 }
+
+void
+_ide_completion_set_language_id (IdeCompletion *self,
+                                 const gchar   *language_id)
+{
+  g_return_if_fail (IDE_IS_COMPLETION (self));
+  g_return_if_fail (language_id != NULL);
+
+  ide_extension_set_adapter_set_value (self->addins, language_id);
+}
+
+/**
+ * ide_completion_is_visible:
+ * @self: a #IdeCompletion
+ *
+ * Checks if the completion display is visible.
+ *
+ * Returns: %TRUE if the display is visible
+ *
+ * Since: 3.30
+ */
+gboolean
+ide_completion_is_visible (IdeCompletion *self)
+{
+  g_return_val_if_fail (IDE_IS_COMPLETION (self), FALSE);
+
+  if (self->display != NULL)
+    return gtk_widget_get_visible (GTK_WIDGET (self->display));
+
+  return FALSE;
+}
+
+/**
+ * ide_completion_get_display:
+ * @self: a #IdeCompletion
+ *
+ * Gets the display for completion.
+ *
+ * Returns: (transfer none): an #IdeCompletionDisplay
+ *
+ * Since: 3.30
+ */
+IdeCompletionDisplay *
+ide_completion_get_display (IdeCompletion *self)
+{
+  g_return_val_if_fail (IDE_IS_COMPLETION (self), NULL);
+
+  if (self->display == NULL)
+    {
+      self->display = ide_completion_create_display (self);
+      ide_completion_display_set_n_rows (self->display, self->n_rows);
+      ide_completion_display_attach (self->display, self->view);
+    }
+
+  return self->display;
+}
+
+void
+ide_completion_move_cursor (IdeCompletion   *self,
+                            GtkMovementStep  step,
+                            gint             direction)
+{
+  g_return_if_fail (IDE_IS_COMPLETION (self));
+
+  if (self->display != NULL)
+    ide_completion_display_move_cursor (self->display, step, direction);
+}
diff --git a/src/libide/completion/ide-completion.h b/src/libide/completion/ide-completion.h
index ce9081895..217e9708a 100644
--- a/src/libide/completion/ide-completion.h
+++ b/src/libide/completion/ide-completion.h
@@ -40,29 +40,37 @@ IDE_AVAILABLE_IN_3_30
 G_DECLARE_FINAL_TYPE (IdeCompletion, ide_completion, IDE, COMPLETION, GObject)
 
 IDE_AVAILABLE_IN_3_30
-GtkSourceView *ide_completion_get_view            (IdeCompletion         *self);
+IdeCompletionDisplay *ide_completion_get_display         (IdeCompletion *self);
 IDE_AVAILABLE_IN_3_30
-GtkTextBuffer *ide_completion_get_buffer          (IdeCompletion         *self);
+GtkSourceView        *ide_completion_get_view            (IdeCompletion         *self);
 IDE_AVAILABLE_IN_3_30
-void           ide_completion_block_interactive   (IdeCompletion         *self);
+GtkTextBuffer        *ide_completion_get_buffer          (IdeCompletion         *self);
 IDE_AVAILABLE_IN_3_30
-void           ide_completion_unblock_interactive (IdeCompletion         *self);
+void                  ide_completion_block_interactive   (IdeCompletion         *self);
 IDE_AVAILABLE_IN_3_30
-void           ide_completion_add_provider        (IdeCompletion         *self,
-                                                   IdeCompletionProvider *provider);
+void                  ide_completion_unblock_interactive (IdeCompletion         *self);
 IDE_AVAILABLE_IN_3_30
-void           ide_completion_remove_provider     (IdeCompletion         *self,
-                                                   IdeCompletionProvider *provider);
+void                  ide_completion_add_provider        (IdeCompletion         *self,
+                                                          IdeCompletionProvider *provider);
 IDE_AVAILABLE_IN_3_30
-guint          ide_completion_get_n_rows          (IdeCompletion         *self);
+void                  ide_completion_remove_provider     (IdeCompletion         *self,
+                                                          IdeCompletionProvider *provider);
 IDE_AVAILABLE_IN_3_30
-void           ide_completion_set_n_rows          (IdeCompletion         *self,
-                                                   guint                  n_rows);
+guint                 ide_completion_get_n_rows          (IdeCompletion         *self);
 IDE_AVAILABLE_IN_3_30
-void           ide_completion_hide                (IdeCompletion         *self);
+void                  ide_completion_set_n_rows          (IdeCompletion         *self,
+                                                          guint                  n_rows);
 IDE_AVAILABLE_IN_3_30
-void           ide_completion_show                (IdeCompletion         *self);
+void                  ide_completion_hide                (IdeCompletion         *self);
 IDE_AVAILABLE_IN_3_30
-void           ide_completion_cancel              (IdeCompletion         *self);
+void                  ide_completion_show                (IdeCompletion         *self);
+IDE_AVAILABLE_IN_3_30
+void                  ide_completion_cancel              (IdeCompletion         *self);
+IDE_AVAILABLE_IN_3_30
+gboolean              ide_completion_is_visible          (IdeCompletion         *self);
+IDE_AVAILABLE_IN_3_30
+void                  ide_completion_move_cursor         (IdeCompletion         *self,
+                                                          GtkMovementStep        step,
+                                                          gint                   direction);
 
 G_END_DECLS
diff --git a/src/libide/editor/ide-editor-view-settings.c b/src/libide/editor/ide-editor-view-settings.c
index 6578d2625..cbf4325fe 100644
--- a/src/libide/editor/ide-editor-view-settings.c
+++ b/src/libide/editor/ide-editor-view-settings.c
@@ -220,8 +220,4 @@ _ide_editor_view_init_settings (IdeEditorView *self)
   on_draw_spaces_changed (self, "draw-spaces", self->editor_settings);
 
   self->insight_settings = g_settings_new ("org.gnome.builder.code-insight");
-
-  g_settings_bind (self->insight_settings, "word-completion",
-                   source_view, "enable-word-completion",
-                   G_SETTINGS_BIND_GET);
 }
diff --git a/src/libide/sourceview/ide-source-view.c b/src/libide/sourceview/ide-source-view.c
index eeb683567..1817c7195 100644
--- a/src/libide/sourceview/ide-source-view.c
+++ b/src/libide/sourceview/ide-source-view.c
@@ -33,7 +33,8 @@
 #include "buffers/ide-buffer-manager.h"
 #include "buffers/ide-buffer.h"
 #include "buffers/ide-buffer-private.h"
-#include "completion/ide-completion-provider.h"
+#include "completion/ide-completion.h"
+#include "completion/ide-completion-private.h"
 #include "diagnostics/ide-diagnostic.h"
 #include "diagnostics/ide-fixit.h"
 #include "diagnostics/ide-source-location.h"
@@ -114,8 +115,7 @@ typedef struct
   DzlAnimation                *vadj_animation;
   IdeOmniGutterRenderer       *omni_renderer;
 
-  IdeExtensionSetAdapter      *completion_providers;
-  DzlSignalGroup              *completion_providers_signals;
+  IdeCompletion               *completion;
 
   DzlBindingGroup             *file_setting_bindings;
   DzlSignalGroup              *buffer_signals;
@@ -161,7 +161,6 @@ typedef struct
 
   guint                        auto_indent : 1;
   guint                        completion_blocked : 1;
-  guint                        completion_visible : 1;
   guint                        highlight_current_line : 1;
   guint                        in_replay_macro : 1;
   guint                        insert_mark_cleared : 1;
@@ -317,6 +316,26 @@ find_references_task_data_free (FindReferencesTaskData *data)
   g_slice_free (FindReferencesTaskData, data);
 }
 
+static void
+block_interactive (IdeSourceView *self)
+{
+  IdeSourceViewPrivate *priv = ide_source_view_get_instance_private (self);
+
+  g_assert (IDE_IS_SOURCE_VIEW (self));
+
+  ide_completion_block_interactive (priv->completion);
+}
+
+static void
+unblock_interactive (IdeSourceView *self)
+{
+  IdeSourceViewPrivate *priv = ide_source_view_get_instance_private (self);
+
+  g_assert (IDE_IS_SOURCE_VIEW (self));
+
+  ide_completion_unblock_interactive (priv->completion);
+}
+
 static void
 find_references_task_get_extension (IdeExtensionSetAdapter *set,
                                     PeasPluginInfo         *plugin_info,
@@ -868,12 +887,6 @@ ide_source_view__buffer_notify_language_cb (IdeSourceView *self,
   ide_source_view_update_auto_indent_override (self);
   g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_INDENTER]);
 
-  /*
-   * Update the completion providers, which are provided by plugins.
-   */
-  if (priv->completion_providers != NULL)
-    ide_extension_set_adapter_set_value (priv->completion_providers, lang_id);
-
   /*
    * Make sure the snippet engine reloads for the new language.
    */
@@ -1216,10 +1229,7 @@ ide_source_view__buffer_loaded_cb (IdeSourceView *self,
 
   if (priv->completion_blocked)
     {
-      GtkSourceCompletion *completion;
-
-      completion = gtk_source_view_get_completion (GTK_SOURCE_VIEW (self));
-      gtk_source_completion_unblock_interactive (completion);
+      unblock_interactive (self);
       priv->completion_blocked = FALSE;
     }
 
@@ -1238,50 +1248,6 @@ ide_source_view__buffer_loaded_cb (IdeSourceView *self,
   IDE_EXIT;
 }
 
-static void
-ide_source_view__completion_provider_added (IdeExtensionSetAdapter *adapter,
-                                            PeasPluginInfo         *plugin_info,
-                                            PeasExtension          *extension,
-                                            IdeSourceView          *self)
-{
-  IdeSourceViewPrivate *priv = ide_source_view_get_instance_private (self);
-  GtkSourceCompletion *completion;
-
-  g_assert (IDE_IS_SOURCE_VIEW (self));
-  g_assert (plugin_info != NULL);
-  g_assert (IDE_IS_COMPLETION_PROVIDER (extension));
-  g_assert (IDE_IS_EXTENSION_SET_ADAPTER (adapter));
-
-  completion = gtk_source_view_get_completion (GTK_SOURCE_VIEW (self));
-
-  gtk_source_completion_add_provider (completion,
-                                      GTK_SOURCE_COMPLETION_PROVIDER (extension),
-                                      NULL);
-
-  ide_completion_provider_load (IDE_COMPLETION_PROVIDER (extension),
-                                ide_buffer_get_context (priv->buffer));
-}
-
-static void
-ide_source_view__completion_provider_removed (IdeExtensionSetAdapter *adapter,
-                                              PeasPluginInfo         *plugin_info,
-                                              PeasExtension          *extension,
-                                              IdeSourceView          *self)
-{
-  GtkSourceCompletion *completion;
-
-  g_assert (IDE_IS_SOURCE_VIEW (self));
-  g_assert (plugin_info != NULL);
-  g_assert (IDE_IS_COMPLETION_PROVIDER (extension));
-  g_assert (IDE_IS_EXTENSION_SET_ADAPTER (adapter));
-
-  completion = gtk_source_view_get_completion (GTK_SOURCE_VIEW (self));
-
-  gtk_source_completion_remove_provider (completion,
-                                         GTK_SOURCE_COMPLETION_PROVIDER (extension),
-                                         NULL);
-}
-
 static void
 ide_source_view_set_cursor_from_name (IdeSourceView *self,
                                       const gchar   *cursor_name)
@@ -1384,10 +1350,7 @@ ide_source_view_bind_buffer (IdeSourceView  *self,
 
   if (ide_buffer_get_loading (buffer))
     {
-      GtkSourceCompletion *completion;
-
-      completion = gtk_source_view_get_completion (GTK_SOURCE_VIEW (self));
-      gtk_source_completion_block_interactive (completion);
+      block_interactive (self);
       priv->completion_blocked = TRUE;
     }
 
@@ -1399,19 +1362,6 @@ ide_source_view_bind_buffer (IdeSourceView  *self,
                                                       "Indenter-Languages",
                                                       NULL);
 
-  priv->completion_providers = ide_extension_set_adapter_new (context,
-                                                              peas_engine_get_default (),
-                                                              IDE_TYPE_COMPLETION_PROVIDER,
-                                                              "Completion-Provider-Languages",
-                                                              NULL);
-
-  dzl_signal_group_set_target (priv->completion_providers_signals,
-                               priv->completion_providers);
-
-  ide_extension_set_adapter_foreach (priv->completion_providers,
-                                     
(IdeExtensionSetAdapterForeachFunc)ide_source_view__completion_provider_added,
-                                     self);
-
   priv->cursor = g_object_new (IDE_TYPE_CURSOR,
                                "ide-source-view", self,
                                NULL);
@@ -1460,19 +1410,10 @@ ide_source_view_unbind_buffer (IdeSourceView  *self,
 
   if (priv->completion_blocked)
     {
-      GtkSourceCompletion *completion;
-
-      completion = gtk_source_view_get_completion (GTK_SOURCE_VIEW (self));
-      gtk_source_completion_unblock_interactive (completion);
+      unblock_interactive (self);
       priv->completion_blocked = FALSE;
     }
 
-  ide_extension_set_adapter_foreach (priv->completion_providers,
-                                     
(IdeExtensionSetAdapterForeachFunc)ide_source_view__completion_provider_removed,
-                                     self);
-
-  dzl_signal_group_set_target (priv->completion_providers_signals, NULL);
-
   if (priv->cursor != NULL)
     {
       g_object_run_dispose (G_OBJECT (priv->cursor));
@@ -1480,7 +1421,6 @@ ide_source_view_unbind_buffer (IdeSourceView  *self,
     }
 
   g_clear_object (&priv->indenter_adapter);
-  g_clear_object (&priv->completion_providers);
   g_clear_object (&priv->definition_highlight_start_mark);
   g_clear_object (&priv->definition_highlight_end_mark);
 
@@ -2194,7 +2134,7 @@ ide_source_view_key_press_event (GtkWidget   *widget,
    * move between snippets at a higher priority than the completion window.
    * If we don't have a snippet active
    */
-  if (priv->completion_visible && event->keyval == GDK_KEY_Tab)
+  if (ide_completion_is_visible (priv->completion) && event->keyval == GDK_KEY_Tab)
     {
       GtkSourceCompletion *completion = gtk_source_view_get_completion (GTK_SOURCE_VIEW (self));
       g_signal_emit_by_name (completion, "activate-proposal");
@@ -2206,7 +2146,7 @@ ide_source_view_key_press_event (GtkWidget   *widget,
    * Avoid conflicts with global <alt>+N perspective movements.
    * We might want to adjust those keybindings at somepoint.
    */
-  if (priv->completion_visible && event->state == GDK_MOD1_MASK)
+  if (ide_completion_is_visible (priv->completion) && event->state == GDK_MOD1_MASK)
     {
       if ((event->keyval >= GDK_KEY_0 && event->keyval <= GDK_KEY_9) ||
           (event->keyval >= GDK_KEY_KP_0 && event->keyval <= GDK_KEY_KP_9))
@@ -2883,30 +2823,25 @@ static void
 ide_source_view_real_cycle_completion (IdeSourceView    *self,
                                        GtkDirectionType  direction)
 {
-  IdeSourceViewPrivate *priv = ide_source_view_get_instance_private (self);
-  GtkSourceView *source_view = (GtkSourceView *)self;
-  GtkSourceCompletion *completion;
+  IdeCompletion *completion;
 
   g_assert (IDE_IS_SOURCE_VIEW (self));
 
-  completion = gtk_source_view_get_completion (source_view);
+  completion = ide_source_view_get_completion (self);
 
-  if (!priv->completion_visible)
-    {
-      g_signal_emit_by_name (self, "show-completion");
-      return;
-    }
+  if (!ide_completion_is_visible (completion))
+    return;
 
   switch (direction)
     {
     case GTK_DIR_TAB_FORWARD:
     case GTK_DIR_DOWN:
-      g_signal_emit_by_name (completion, "move-cursor", GTK_SCROLL_STEPS, 1);
+      ide_completion_move_cursor (completion, GTK_MOVEMENT_DISPLAY_LINES, 1);
       break;
 
     case GTK_DIR_TAB_BACKWARD:
     case GTK_DIR_UP:
-      g_signal_emit_by_name (completion, "move-cursor", GTK_SCROLL_STEPS, -1);
+      ide_completion_move_cursor (completion, GTK_MOVEMENT_DISPLAY_LINES, -1);
       break;
 
     case GTK_DIR_LEFT:
@@ -3670,22 +3605,6 @@ ide_source_view_real_select_tag (IdeSourceView *self,
   _ide_source_view_select_tag (self, priv->count, exclusive);
 }
 
-static void
-ide_source_view__completion_hide_cb (IdeSourceView       *self,
-                                     GtkSourceCompletion *completion)
-{
-  IdeSourceViewPrivate *priv = ide_source_view_get_instance_private (self);
-  priv->completion_visible = FALSE;
-}
-
-static void
-ide_source_view__completion_show_cb (IdeSourceView       *self,
-                                     GtkSourceCompletion *completion)
-{
-  IdeSourceViewPrivate *priv = ide_source_view_get_instance_private (self);
-  priv->completion_visible = TRUE;
-}
-
 static void
 ide_source_view_real_pop_selection (IdeSourceView *self)
 {
@@ -3951,7 +3870,6 @@ ide_source_view_constructed (GObject *object)
 {
   IdeSourceView *self = (IdeSourceView *)object;
   IdeSourceViewPrivate *priv = ide_source_view_get_instance_private (self);
-  GtkSourceCompletion *completion;
   GtkSourceGutter *gutter;
 
   G_OBJECT_CLASS (ide_source_view_parent_class)->constructed (object);
@@ -3960,23 +3878,6 @@ ide_source_view_constructed (GObject *object)
 
   ide_source_view_real_set_mode (self, NULL, IDE_SOURCE_VIEW_MODE_TYPE_PERMANENT);
 
-  /*
-   * Completion does not have a way to retrieve visibility, so we need to track that ourselves
-   * by connecting to hide/show. We use this to know if we need to move to the next item in the
-   * result set during IdeSourceView:cycle-completion.
-   */
-  completion = gtk_source_view_get_completion (GTK_SOURCE_VIEW (self));
-  g_signal_connect_object (completion,
-                           "show",
-                           G_CALLBACK (ide_source_view__completion_show_cb),
-                           self,
-                           G_CONNECT_SWAPPED | G_CONNECT_AFTER);
-  g_signal_connect_object (completion,
-                           "hide",
-                           G_CALLBACK (ide_source_view__completion_hide_cb),
-                           self,
-                           G_CONNECT_SWAPPED | G_CONNECT_AFTER);
-
   priv->definition_src_location = NULL;
   ide_source_view_reset_definition_highlight (self);
 
@@ -3986,6 +3887,14 @@ ide_source_view_constructed (GObject *object)
                                       NULL);
   g_object_ref_sink (priv->omni_renderer);
   gtk_source_gutter_insert (gutter, GTK_SOURCE_GUTTER_RENDERER (priv->omni_renderer), 0);
+
+  priv->completion = _ide_completion_new (GTK_SOURCE_VIEW (self));
+
+  /* Disable sourceview completion always */
+  gtk_source_completion_block_interactive (gtk_source_view_get_completion (GTK_SOURCE_VIEW (self)));
+
+  /* Disable completion until focus-in-event */
+  ide_completion_block_interactive (priv->completion);
 }
 
 static void
@@ -4148,17 +4057,13 @@ ide_source_view_focus_in_event (GtkWidget     *widget,
 {
   IdeSourceView *self = (IdeSourceView *)widget;
   IdeSourceViewPrivate *priv = ide_source_view_get_instance_private (self);
-  GtkSourceCompletion *completion;
   IdeWorkbench *workbench;
   gboolean ret;
 
   g_assert (IDE_IS_SOURCE_VIEW (self));
 
-  /*
-   * Restore the completion window now that we have regained focus.
-   */
-  completion = gtk_source_view_get_completion (GTK_SOURCE_VIEW (self));
-  gtk_source_completion_unblock_interactive (completion);
+  /* Restore the completion window now that we have regained focus. */
+  unblock_interactive (self);
 
   /*
    * Restore the insert mark, but ignore selections (since we cant ensure they
@@ -4188,7 +4093,6 @@ ide_source_view_focus_out_event (GtkWidget     *widget,
                                  GdkEventFocus *event)
 {
   IdeSourceView *self = (IdeSourceView *)widget;
-  GtkSourceCompletion *completion;
   gboolean ret;
 
   g_assert (IDE_IS_SOURCE_VIEW (self));
@@ -4204,8 +4108,7 @@ ide_source_view_focus_out_event (GtkWidget     *widget,
    * Block the completion window while we are not focused. It confuses text
    * insertion and such.
    */
-  completion = gtk_source_view_get_completion (GTK_SOURCE_VIEW (self));
-  gtk_source_completion_block_interactive (completion);
+  block_interactive (self);
 
   /* We don't want highlight-current-line unless the widget is in focus, so
    * disable it until we get re-focused.
@@ -5498,7 +5401,6 @@ ide_source_view_finalize (GObject *object)
   IdeSourceView *self = (IdeSourceView *)object;
   IdeSourceViewPrivate *priv = ide_source_view_get_instance_private (self);
 
-  g_clear_object (&priv->completion_providers_signals);
   g_clear_pointer (&priv->display_name, g_free);
   g_clear_pointer (&priv->font_desc, pango_font_description_free);
   g_clear_pointer (&priv->selections, g_queue_free);
@@ -6611,7 +6513,6 @@ static void
 ide_source_view_init (IdeSourceView *self)
 {
   IdeSourceViewPrivate *priv = ide_source_view_get_instance_private (self);
-  GtkSourceCompletion *completion;
 
   priv->include_regex = g_regex_new (INCLUDE_STATEMENTS,
                                      G_REGEX_OPTIMIZE,
@@ -6627,20 +6528,6 @@ ide_source_view_init (IdeSourceView *self)
   priv->command_str = g_string_sized_new (32);
   priv->overscroll_num_lines = DEFAULT_OVERSCROLL_NUM_LINES;
 
-  priv->completion_providers_signals = dzl_signal_group_new (IDE_TYPE_EXTENSION_SET_ADAPTER);
-
-  dzl_signal_group_connect_object (priv->completion_providers_signals,
-                                   "extension-added",
-                                   G_CALLBACK (ide_source_view__completion_provider_added),
-                                   self,
-                                   0);
-
-  dzl_signal_group_connect_object (priv->completion_providers_signals,
-                                   "extension-removed",
-                                   G_CALLBACK (ide_source_view__completion_provider_removed),
-                                   self,
-                                   0);
-
   priv->file_setting_bindings = dzl_binding_group_new ();
   dzl_binding_group_bind (priv->file_setting_bindings, "auto-indent",
                           self, "auto-indent", G_BINDING_SYNC_CREATE);
@@ -6745,14 +6632,6 @@ ide_source_view_init (IdeSourceView *self)
   g_object_bind_property_full (self, "buffer", priv->buffer_signals, "target", 0,
                                ignore_invalid_buffers, NULL, NULL, NULL);
 
-  /*
-   * We block completion when we are not focused so that two SourceViews
-   * viewing the same GtkTextBuffer do not both show completion
-   * windows.
-   */
-  completion = gtk_source_view_get_completion (GTK_SOURCE_VIEW (self));
-  gtk_source_completion_block_interactive (completion);
-
   dzl_widget_action_group_attach (self, "sourceview");
 }
 
@@ -7932,3 +7811,23 @@ ide_source_view_is_processing_key (IdeSourceView *self)
 
   return priv->in_key_press > 0;
 }
+
+/**
+ * ide_source_view_get_completion:
+ * @self: a #IdeSourceView
+ *
+ * Get the completion for the #IdeSourceView
+ *
+ * Returns: (transfer none): an #IdeCompletion
+ *
+ * Since: 3.30
+ */
+IdeCompletion *
+ide_source_view_get_completion (IdeSourceView *self)
+{
+  IdeSourceViewPrivate *priv = ide_source_view_get_instance_private (self);
+
+  g_return_val_if_fail (IDE_IS_SOURCE_VIEW (self), NULL);
+
+  return priv->completion;
+}



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