[gtksourceview] Use a mark to keep track of the completion position



commit e4a842c497bcf423779b85ed7a4af88c22801eab
Author: Paolo Borelli <pborelli gnome org>
Date:   Sun Jan 10 18:08:00 2010 +0100

    Use a mark to keep track of the completion position

 gtksourceview/gtksourcecompletion.c        |   39 ++-----
 gtksourceview/gtksourcecompletioncontext.c |  181 ++++++++++++++++++++--------
 gtksourceview/gtksourcecompletioncontext.h |    7 +-
 3 files changed, 144 insertions(+), 83 deletions(-)
---
diff --git a/gtksourceview/gtksourcecompletion.c b/gtksourceview/gtksourcecompletion.c
index 8fffd2f..2bc82a3 100644
--- a/gtksourceview/gtksourcecompletion.c
+++ b/gtksourceview/gtksourcecompletion.c
@@ -1671,21 +1671,16 @@ update_interactive_completion (GtkSourceCompletion *completion,
 		}
 	}
 	else if ((gtk_source_completion_context_get_activation (completion->priv->context) &
-	         GTK_SOURCE_COMPLETION_ACTIVATION_INTERACTIVE) &&
-	         gtk_text_iter_get_line (iter) != completion->priv->typing_line)
+		 GTK_SOURCE_COMPLETION_ACTIVATION_INTERACTIVE) &&
+		 gtk_text_iter_get_line (iter) != completion->priv->typing_line)
 	{
 		gtk_source_completion_hide (completion);
 	}
 	else
 	{
-		/* Update iter in context */
-		g_object_set (completion->priv->context,
-		              "iter", iter,
-	                      NULL);
-
-		update_completion (completion, 
-			           completion->priv->active_providers,
-			           completion->priv->context);
+		update_completion (completion,
+				   completion->priv->active_providers,
+				   completion->priv->context);
 	}
 }
 
@@ -1732,10 +1727,6 @@ buffer_mark_set_cb (GtkTextBuffer       *buffer,
 		gtk_source_completion_hide (completion);
 		return;
 	}
-	
-	/* Repopulate completion at the new iterator */
-	g_object_set (completion->priv->context,
-	              "iter", iter, NULL);
 
 	update_completion (completion,
 	                   completion->priv->active_providers,
@@ -3126,7 +3117,6 @@ update_completion (GtkSourceCompletion        *completion,
                    GList                      *providers,
                    GtkSourceCompletionContext *context)
 {
-	GtkTextIter location;
 	GList *item;
 	
 	DEBUG({
@@ -3135,8 +3125,6 @@ update_completion (GtkSourceCompletion        *completion,
 
 	update_typing_offsets (completion);
 	
-	gtk_source_completion_context_get_iter (context, &location);
-	
 	if (GTK_WIDGET_VISIBLE (completion->priv->info_window))
 	{
 		/* Move info window accordingly */
@@ -3562,27 +3550,20 @@ GtkSourceCompletionContext *
 gtk_source_completion_create_context (GtkSourceCompletion *completion,
                                       GtkTextIter         *position)
 {
-	GtkSourceCompletionContext *context;
-	
+	GtkTextIter iter;
+
 	g_return_val_if_fail (GTK_IS_SOURCE_COMPLETION (completion), NULL);
-	
-	context = g_object_new (GTK_TYPE_SOURCE_COMPLETION_CONTEXT,
-	                        "completion", completion,
-	                        NULL);
 
 	if (position == NULL)
 	{
-		GtkTextIter iter;
-		
 		get_iter_at_insert (completion, &iter);
-		g_object_set (context, "iter", &iter, NULL);
 	}
 	else
 	{
-		g_object_set (context, "iter", position, NULL);
+		iter = *position;
 	}
-	
-	return context;
+
+	return _gtk_source_completion_context_new (completion, &iter);
 }
 
 /**
diff --git a/gtksourceview/gtksourcecompletioncontext.c b/gtksourceview/gtksourcecompletioncontext.c
index ec38a84..8571647 100644
--- a/gtksourceview/gtksourcecompletioncontext.c
+++ b/gtksourceview/gtksourcecompletioncontext.c
@@ -31,17 +31,18 @@ struct _GtkSourceCompletionContextPrivate
 {
 	GtkSourceCompletion *completion;
 
-	GtkTextIter iter;
+	GtkTextMark *mark;
 	GtkSourceCompletionActivation activation;
+
+	gulong mark_set_id;
 };
 
 /* Properties */
 enum
 {
 	PROP_0,
-	
+
 	PROP_COMPLETION,
-	PROP_VIEW,
 	PROP_ITER,
 	PROP_ACTIVATION
 };
@@ -57,38 +58,83 @@ guint context_signals[NUM_SIGNALS] = {0,};
 
 G_DEFINE_TYPE (GtkSourceCompletionContext, gtk_source_completion_context, G_TYPE_INITIALLY_UNOWNED)
 
+/* FIXME: we use this util to get the buffer from the completion
+   but this object is not robust to a change of the buffer associated
+   to the view. Context lifetime should be short enough to not really
+   matter.
+*/
+
+static GtkTextBuffer *
+get_buffer (GtkSourceCompletionContext *context)
+{
+	GtkSourceView *view = gtk_source_completion_get_view (context->priv->completion);
+	return gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
+}
+
 static void
 gtk_source_completion_context_dispose (GObject *object)
 {
-	GtkSourceCompletionContext *context = GTK_SOURCE_COMPLETION_CONTEXT (object);
-	
+	GtkSourceCompletionContext *context;
+	GtkTextBuffer *buffer;
+
+	context = GTK_SOURCE_COMPLETION_CONTEXT (object);
+	buffer = get_buffer (context);
+
+	if (context->priv->mark_set_id)
+	{
+		g_signal_handler_disconnect (buffer, context->priv->mark_set_id);
+		context->priv->mark_set_id = 0;
+	}
+
 	if (context->priv->completion)
 	{
 		g_object_unref (context->priv->completion);
 		context->priv->completion = NULL;
 	}
 
+	if (context->priv->mark)
+	{
+		gtk_text_buffer_delete_mark (buffer, context->priv->mark);
+		context->priv->mark = NULL;
+	}
+
 	G_OBJECT_CLASS (gtk_source_completion_context_parent_class)->dispose (object);
 }
 
 static void
+gtk_source_completion_context_set_iter (GtkSourceCompletionContext *context,
+                                        GtkTextIter                *iter)
+{
+	GtkTextBuffer *buffer = get_buffer (context);
+
+	if (context->priv->mark == NULL)
+	{
+		context->priv->mark = gtk_text_buffer_create_mark (buffer, NULL, iter, FALSE);
+	}
+	else
+	{
+		gtk_text_buffer_move_mark (buffer, context->priv->mark, iter);
+	}
+}
+
+static void
 gtk_source_completion_context_set_property (GObject      *object,
                                             guint         prop_id,
                                             const GValue *value,
                                             GParamSpec   *pspec)
 {
-	GtkSourceCompletionContext *self = GTK_SOURCE_COMPLETION_CONTEXT (object);
-	
+	GtkSourceCompletionContext *context = GTK_SOURCE_COMPLETION_CONTEXT (object);
+
 	switch (prop_id)
 	{
 		case PROP_COMPLETION:
-			self->priv->completion = g_value_dup_object (value);
+			context->priv->completion = g_value_dup_object (value);
 			break;
 		case PROP_ITER:
-			self->priv->iter = *((GtkTextIter *)g_value_get_boxed (value));
+			gtk_source_completion_context_set_iter (context, (GtkTextIter *) g_value_get_boxed (value));
 			break;
 		case PROP_ACTIVATION:
-			self->priv->activation = g_value_get_flags (value);
+			context->priv->activation = g_value_get_flags (value);
 			break;
 		default:
 			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -101,21 +147,22 @@ gtk_source_completion_context_get_property (GObject    *object,
                                             GValue     *value,
                                             GParamSpec *pspec)
 {
-	GtkSourceCompletionContext *self = GTK_SOURCE_COMPLETION_CONTEXT (object);
-	
+	GtkSourceCompletionContext *context = GTK_SOURCE_COMPLETION_CONTEXT (object);
+
 	switch (prop_id)
 	{
 		case PROP_COMPLETION:
-			g_value_set_object (value, self->priv->completion);
-			break;
-		case PROP_VIEW:
-			g_value_set_object (value, gtk_source_completion_get_view (self->priv->completion));
+			g_value_set_object (value, context->priv->completion);
 			break;
 		case PROP_ITER:
-			g_value_set_boxed (value, &(self->priv->iter));
+			{
+				GtkTextIter iter;
+				gtk_source_completion_context_get_iter (context, &iter);
+				g_value_set_boxed (value, &iter);
+			}
 			break;
 		case PROP_ACTIVATION:
-			g_value_set_flags (value, self->priv->activation);
+			g_value_set_flags (value, context->priv->activation);
 			break;
 		default:
 			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -123,12 +170,49 @@ gtk_source_completion_context_get_property (GObject    *object,
 }
 
 static void
+buffer_mark_set_cb (GtkTextBuffer              *buffer,
+                    GtkTextIter                *iter,
+                    GtkTextMark                *mark,
+                    GtkSourceCompletionContext *context)
+{
+	if (mark == context->priv->mark)
+	{
+		g_object_notify (G_OBJECT (buffer), "iter");
+	}
+}
+
+static GObject *
+gtk_source_completion_context_constructor (GType                  type,
+                                           guint                  n_construct_properties,
+                                           GObjectConstructParam *construct_param)
+{
+	GObject *object;
+	GtkTextBuffer *buffer;
+	GtkSourceCompletionContext *context;
+
+	object = G_OBJECT_CLASS (gtk_source_completion_context_parent_class)->constructor (type,
+											   n_construct_properties,
+									 		   construct_param);
+
+	/* we need to connect after the completion property is set */
+	context = GTK_SOURCE_COMPLETION_CONTEXT (object);
+	buffer = get_buffer (context);
+	context->priv->mark_set_id = g_signal_connect (buffer,
+						       "mark-set",
+						       G_CALLBACK (buffer_mark_set_cb),
+						       context);
+
+	return object;
+}
+
+static void
 gtk_source_completion_context_class_init (GtkSourceCompletionContextClass *klass)
 {
 	GObjectClass *object_class = G_OBJECT_CLASS (klass);
 	
 	object_class->set_property = gtk_source_completion_context_set_property;
 	object_class->get_property = gtk_source_completion_context_get_property;
+	object_class->constructor = gtk_source_completion_context_constructor;
 	object_class->dispose = gtk_source_completion_context_dispose;
 
 	/**
@@ -163,19 +247,6 @@ gtk_source_completion_context_class_init (GtkSourceCompletionContextClass *klass
 	                                                      G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
 
 	/**
-	 * GtkSourceCompletionContext:view:
-	 *
-	 * The #GtkSourceView associated with the context.
-	 **/
-	g_object_class_install_property (object_class,
-	                                 PROP_VIEW,
-	                                 g_param_spec_object ("view",
-	                                                      _("View"),
-	                                                      _("The GtkSourceView"),
-	                                                      GTK_TYPE_SOURCE_VIEW,
-	                                                      G_PARAM_READABLE));
-
-	/**
 	 * GtkSourceCompletionContext:iter:
 	 *
 	 * The #GtkTextIter at which the completion is invoked.
@@ -207,9 +278,9 @@ gtk_source_completion_context_class_init (GtkSourceCompletionContextClass *klass
 }
 
 static void
-gtk_source_completion_context_init (GtkSourceCompletionContext *self)
+gtk_source_completion_context_init (GtkSourceCompletionContext *context)
 {
-	self->priv = GTK_SOURCE_COMPLETION_CONTEXT_GET_PRIVATE (self);
+	context->priv = GTK_SOURCE_COMPLETION_CONTEXT_GET_PRIVATE (context);
 }
 
 /**
@@ -242,23 +313,6 @@ gtk_source_completion_context_add_proposals (GtkSourceCompletionContext  *contex
 }
 
 /**
- * gtk_source_completion_context_get_view:
- * @context: A #GtkSourceCompletionContext
- * 
- * Get the #GtkSourceView to which the context applies
- *
- * Returns: A #GtkSourceView
- *
- **/
-GtkSourceView *
-gtk_source_completion_context_get_view (GtkSourceCompletionContext *context)
-{
-	g_return_val_if_fail (GTK_IS_SOURCE_COMPLETION_CONTEXT (context), NULL);
-
-	return gtk_source_completion_get_view (context->priv->completion);
-}
-
-/**
  * gtk_source_completion_context_get_iter:
  * @context: A #GtkSourceCompletionContext
  * @iter: A #GtkTextIter
@@ -271,9 +325,22 @@ void
 gtk_source_completion_context_get_iter (GtkSourceCompletionContext *context,
                                         GtkTextIter                *iter)
 {
+	GtkTextBuffer *buffer;
+
 	g_return_if_fail (GTK_IS_SOURCE_COMPLETION_CONTEXT (context));
 
-	*iter = context->priv->iter;
+	buffer = get_buffer (context);
+
+	if (context->priv->mark != NULL)
+	{
+		gtk_text_buffer_get_iter_at_mark (buffer, iter, context->priv->mark);
+	}
+	else
+	{
+		/* This should never happen: context should be always be created
+		   providing a position iter */
+		g_warning ("Completion context without mark");
+	}
 }
 
 /**
@@ -299,3 +366,15 @@ _gtk_source_completion_context_cancel (GtkSourceCompletionContext *context)
 
 	g_signal_emit (context, context_signals[CANCELLED], 0);
 }
+
+GtkSourceCompletionContext *
+_gtk_source_completion_context_new (GtkSourceCompletion *completion, GtkTextIter *position)
+{
+	g_return_val_if_fail (GTK_IS_SOURCE_COMPLETION (completion), NULL);
+	g_return_val_if_fail (position != NULL, NULL);
+
+	return g_object_new (GTK_TYPE_SOURCE_COMPLETION_CONTEXT,
+	                     "completion", completion,
+	                     "iter", position,
+	                      NULL);
+}
diff --git a/gtksourceview/gtksourcecompletioncontext.h b/gtksourceview/gtksourcecompletioncontext.h
index 0cbbd9a..1c39909 100644
--- a/gtksourceview/gtksourcecompletioncontext.h
+++ b/gtksourceview/gtksourcecompletioncontext.h
@@ -56,7 +56,6 @@ typedef enum
 /* Forward declaration */
 struct _GtkSourceCompletionProvider;
 struct _GtkSourceCompletion;
-struct _GtkSourceView;
 
 struct _GtkSourceCompletionContext {
 	GInitiallyUnowned parent;
@@ -82,14 +81,16 @@ void 		 gtk_source_completion_context_add_proposals 	(GtkSourceCompletionContext
 								 GList                               *proposals,
 								 gboolean                             finished);
 
-struct _GtkSourceView *
-		 gtk_source_completion_context_get_view		(GtkSourceCompletionContext          *context);
 void		 gtk_source_completion_context_get_iter		(GtkSourceCompletionContext          *context,
 								 GtkTextIter                         *iter);
 
 GtkSourceCompletionActivation
 		 gtk_source_completion_context_get_activation	(GtkSourceCompletionContext          *context);
 
+GtkSourceCompletionContext *
+		_gtk_source_completion_context_new		(struct _GtkSourceCompletion         *completion,
+								 GtkTextIter                         *position);
+
 void		_gtk_source_completion_context_cancel		(GtkSourceCompletionContext          *context);
 
 G_END_DECLS



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