[gtksourceview] Implemented per-provider delay handling
- From: Jesse van den Kieboom <jessevdk src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [gtksourceview] Implemented per-provider delay handling
- Date: Fri, 1 Jan 2010 22:50:43 +0000 (UTC)
commit dd41491a762dc05a6dabc16cc16c565430c2fb17
Author: Jesse van den Kieboom <jesse vandenkieboom epfl ch>
Date: Thu Dec 31 19:22:58 2009 +0100
Implemented per-provider delay handling
.../words/gtksourcecompletionwords.c | 30 +++-
gtksourceview/gtksourcecompletion.c | 231 ++++++++++++++++----
2 files changed, 213 insertions(+), 48 deletions(-)
---
diff --git a/gtksourceview/completion-providers/words/gtksourcecompletionwords.c b/gtksourceview/completion-providers/words/gtksourcecompletionwords.c
index f4295cf..905508f 100644
--- a/gtksourceview/completion-providers/words/gtksourcecompletionwords.c
+++ b/gtksourceview/completion-providers/words/gtksourcecompletionwords.c
@@ -43,7 +43,8 @@ enum
PROP_ICON,
PROP_PROPOSALS_BATCH_SIZE,
PROP_SCAN_BATCH_SIZE,
- PROP_MINIMUM_WORD_SIZE
+ PROP_MINIMUM_WORD_SIZE,
+ PROP_INTERACTIVE_DELAY
};
struct _GtkSourceCompletionWordsPrivate
@@ -66,6 +67,8 @@ struct _GtkSourceCompletionWordsPrivate
GtkSourceCompletionWordsLibrary *library;
GList *buffers;
+
+ gint interactive_delay;
};
typedef struct
@@ -406,6 +409,9 @@ gtk_source_completion_words_set_property (GObject *object,
self->priv->minimum_word_size = g_value_get_uint (value);
update_buffers_minimum_word_size (self);
break;
+ case PROP_INTERACTIVE_DELAY:
+ self->priv->interactive_delay = g_value_get_int (value);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -437,6 +443,9 @@ gtk_source_completion_words_get_property (GObject *object,
case PROP_MINIMUM_WORD_SIZE:
g_value_set_uint (value, self->priv->minimum_word_size);
break;
+ case PROP_INTERACTIVE_DELAY:
+ g_value_set_int (value, self->priv->interactive_delay);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -496,8 +505,18 @@ gtk_source_completion_words_class_init (GtkSourceCompletionWordsClass *klass)
_("The minimum word size to complete"),
2,
G_MAXUINT,
- 3,
+ 2,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+
+ g_object_class_install_property (object_class,
+ PROP_INTERACTIVE_DELAY,
+ g_param_spec_int ("interactive-delay",
+ _("Interactive Delay"),
+ _("The delay before initiating interactive completion"),
+ -1,
+ G_MAXINT,
+ 50,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
g_type_class_add_private (object_class, sizeof(GtkSourceCompletionWordsPrivate));
}
@@ -523,6 +542,12 @@ gtk_source_completion_words_get_start_iter (GtkSourceCompletionProvider *provide
return TRUE;
}
+static gint
+gtk_source_completion_words_get_interactive_delay (GtkSourceCompletionProvider *provider)
+{
+ return GTK_SOURCE_COMPLETION_WORDS (provider)->priv->interactive_delay;
+}
+
static void
gtk_source_completion_words_iface_init (GtkSourceCompletionProviderIface *iface)
{
@@ -533,6 +558,7 @@ gtk_source_completion_words_iface_init (GtkSourceCompletionProviderIface *iface)
iface->match = gtk_source_completion_words_match;
iface->get_start_iter = gtk_source_completion_words_get_start_iter;
+ iface->get_interactive_delay = gtk_source_completion_words_get_interactive_delay;
}
static void
diff --git a/gtksourceview/gtksourcecompletion.c b/gtksourceview/gtksourcecompletion.c
index 1e062ef..2fc5372 100644
--- a/gtksourceview/gtksourcecompletion.c
+++ b/gtksourceview/gtksourcecompletion.c
@@ -146,6 +146,10 @@ struct _GtkSourceCompletionPrivate
gulong signals_ids[LAST_EXTERNAL_SIGNAL];
gboolean select_first;
+
+ gint min_auto_complete_delay;
+ GList *auto_completion_selection;
+ GtkSourceCompletionContext *auto_completion_context;
};
static guint signals[LAST_SIGNAL] = { 0 };
@@ -1397,13 +1401,110 @@ update_typing_offsets (GtkSourceCompletion *completion)
completion->priv->typing_line_offset = gtk_text_iter_get_line_offset (&start);
}
+static GList *
+select_providers (GtkSourceCompletion *completion,
+ GList *providers,
+ GtkSourceCompletionContext *context)
+{
+ /* Select providers based on selection */
+ GList *selection = NULL;
+
+ if (providers == NULL)
+ {
+ providers = completion->priv->providers;
+ }
+
+ while (providers)
+ {
+ GtkSourceCompletionProvider *provider =
+ GTK_SOURCE_COMPLETION_PROVIDER (providers->data);
+
+ if (gtk_source_completion_provider_match (provider, context))
+ {
+ selection = g_list_prepend (selection, provider);
+ }
+
+ providers = g_list_next (providers);
+ }
+
+ return g_list_reverse (selection);
+}
+
+static gboolean
+auto_completion_final (GtkSourceCompletion *completion)
+{
+ /* Store and set to NULL because update_completion will cancel the last
+ completion, which will also remove the timeout source which in turn
+ would free these guys */
+ GtkSourceCompletionContext *context = completion->priv->auto_completion_context;
+ GList *selection = completion->priv->auto_completion_selection;
+
+ completion->priv->auto_completion_context = NULL;
+ completion->priv->auto_completion_selection = NULL;
+
+ update_completion (completion, selection, context);
+
+ /* No need to free the context since it was a floating reference which
+ has been taken over by update_completion */
+ g_list_free (selection);
+ return FALSE;
+}
+
+static void
+auto_completion_destroy (GtkSourceCompletion *completion)
+{
+ if (completion->priv->auto_completion_context != NULL)
+ {
+ g_object_ref_sink (completion->priv->auto_completion_context);
+ g_object_unref (completion->priv->auto_completion_context);
+ }
+
+ g_list_free (completion->priv->auto_completion_selection);
+
+ completion->priv->auto_completion_context = NULL;
+ completion->priv->auto_completion_selection = NULL;
+}
+
+static gint
+minimum_auto_complete_delay (GtkSourceCompletion *completion,
+ GList *providers)
+{
+ gint min_delay = completion->priv->auto_complete_delay;
+
+ while (providers)
+ {
+ GtkSourceCompletionProvider *provider = providers->data;
+ gint delay = gtk_source_completion_provider_get_interactive_delay (provider);
+
+ if (delay < 0)
+ {
+ delay = completion->priv->auto_complete_delay;
+ }
+
+ if (delay < min_delay)
+ {
+ min_delay = delay;
+ }
+
+ providers = g_list_next (providers);
+ }
+
+ return min_delay;
+}
+
static gboolean
-show_auto_completion (GtkSourceCompletion *completion)
+auto_completion_prematch (GtkSourceCompletion *completion)
{
GtkTextBuffer *buffer;
GtkTextIter iter;
GtkSourceCompletionContext *context;
-
+ gint delay;
+ GList *selection;
+
+ /* Do a prematch on the available interactive providers and determine
+ the minimum delay to the real selection that matches the current
+ context */
+
completion->priv->show_timed_out_id = 0;
if (GTK_WIDGET_VISIBLE (completion->priv->window))
@@ -1426,10 +1527,39 @@ show_auto_completion (GtkSourceCompletion *completion)
"activation",
GTK_SOURCE_COMPLETION_ACTIVATION_INTERACTIVE,
NULL);
-
- gtk_source_completion_show (completion,
- completion->priv->interactive_providers,
- context);
+
+ g_signal_emit (completion, signals[POPULATE_CONTEXT], 0, context);
+
+ selection = select_providers (completion,
+ completion->priv->interactive_providers,
+ context);
+
+ if (selection == NULL)
+ {
+ g_object_ref_sink (context);
+ g_object_unref (context);
+
+ return FALSE;
+ }
+
+ /* Check the minimum delay on this set */
+ delay = minimum_auto_complete_delay (completion, selection);
+ completion->priv->auto_completion_context = context;
+ completion->priv->auto_completion_selection = selection;
+
+ if (delay > completion->priv->min_auto_complete_delay)
+ {
+ completion->priv->show_timed_out_id =
+ g_timeout_add_full (G_PRIORITY_DEFAULT,
+ delay - completion->priv->min_auto_complete_delay,
+ (GSourceFunc)auto_completion_final,
+ completion,
+ (GDestroyNotify)auto_completion_destroy);
+ }
+ else
+ {
+ auto_completion_final (completion);
+ }
return FALSE;
}
@@ -1437,6 +1567,11 @@ show_auto_completion (GtkSourceCompletion *completion)
static void
interactive_do_show (GtkSourceCompletion *completion)
{
+ if (completion->priv->interactive_providers == NULL)
+ {
+ return;
+ }
+
update_typing_offsets (completion);
if (completion->priv->show_timed_out_id != 0)
@@ -1444,10 +1579,12 @@ interactive_do_show (GtkSourceCompletion *completion)
g_source_remove (completion->priv->show_timed_out_id);
}
+ /* Install first handler to do the match on the minimum auto complete
+ delay */
completion->priv->show_timed_out_id =
- g_timeout_add (completion->priv->auto_complete_delay,
- (GSourceFunc)show_auto_completion,
- completion);
+ g_timeout_add (completion->priv->min_auto_complete_delay,
+ (GSourceFunc)auto_completion_prematch,
+ completion);
}
static void
@@ -1533,12 +1670,11 @@ buffer_mark_set_cb (GtkTextBuffer *buffer,
/* Repopulate completion at the new iterator */
g_object_set (completion->priv->context,
- "iter", iter,
- NULL);
+ "iter", iter, NULL);
update_completion (completion,
- completion->priv->active_providers,
- completion->priv->context);
+ completion->priv->active_providers,
+ completion->priv->context);
}
static void
@@ -1692,6 +1828,14 @@ gtk_source_completion_finalize (GObject *object)
}
static void
+update_min_auto_complete_delay (GtkSourceCompletion *completion)
+{
+ completion->priv->min_auto_complete_delay =
+ minimum_auto_complete_delay (completion,
+ completion->priv->interactive_providers);
+}
+
+static void
gtk_source_completion_get_property (GObject *object,
guint prop_id,
GValue *value,
@@ -1780,6 +1924,7 @@ gtk_source_completion_set_property (GObject *object,
break;
case PROP_AUTO_COMPLETE_DELAY:
completion->priv->auto_complete_delay = g_value_get_uint (value);
+ update_min_auto_complete_delay (completion);
break;
case PROP_PROPOSAL_PAGE_SIZE:
completion->priv->proposal_page_size = g_value_get_uint (value);
@@ -2948,35 +3093,6 @@ _gtk_source_completion_add_proposals (GtkSourceCompletion *completion,
}
}
-static GList *
-select_providers (GtkSourceCompletion *completion,
- GList *providers,
- GtkSourceCompletionContext *context)
-{
- /* Select providers based on selection */
- GList *selection = NULL;
-
- if (providers == NULL)
- {
- providers = completion->priv->providers;
- }
-
- while (providers)
- {
- GtkSourceCompletionProvider *provider =
- GTK_SOURCE_COMPLETION_PROVIDER (providers->data);
-
- if (gtk_source_completion_provider_match (provider, context))
- {
- selection = g_list_prepend (selection, provider);
- }
-
- providers = g_list_next (providers);
- }
-
- return g_list_reverse (selection);
-}
-
/**
* gtk_source_completion_show:
* @completion: A #GtkSourceCompletion
@@ -3126,8 +3242,21 @@ gtk_source_completion_add_provider (GtkSourceCompletion *completion,
if (gtk_source_completion_provider_get_activation (provider) &
GTK_SOURCE_COMPLETION_ACTIVATION_INTERACTIVE)
{
- completion->priv->interactive_providers = g_list_append (completion->priv->interactive_providers,
- provider);
+ gint delay = gtk_source_completion_provider_get_interactive_delay (provider);
+
+ completion->priv->interactive_providers =
+ g_list_append (completion->priv->interactive_providers,
+ provider);
+
+ if (delay >= 0 && delay < completion->priv->min_auto_complete_delay)
+ {
+ completion->priv->min_auto_complete_delay = delay;
+ }
+ else if (delay < 0 && completion->priv->auto_complete_delay <
+ completion->priv->min_auto_complete_delay)
+ {
+ completion->priv->min_auto_complete_delay = completion->priv->auto_complete_delay;
+ }
}
if (error)
@@ -3168,8 +3297,18 @@ gtk_source_completion_remove_provider (GtkSourceCompletion *completion,
if (gtk_source_completion_provider_get_activation (provider) &
GTK_SOURCE_COMPLETION_ACTIVATION_INTERACTIVE)
{
- completion->priv->interactive_providers = g_list_remove (completion->priv->interactive_providers,
- provider);
+ gint delay = gtk_source_completion_provider_get_interactive_delay (provider);
+
+ completion->priv->interactive_providers =
+ g_list_remove (completion->priv->interactive_providers,
+ provider);
+
+ if (delay == completion->priv->min_auto_complete_delay ||
+ (delay == -1 && completion->priv->min_auto_complete_delay ==
+ completion->priv->auto_complete_delay))
+ {
+ update_min_auto_complete_delay (completion);
+ }
}
g_object_unref (provider);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]