gtksourceview r2272 - in branches/gtksourcecompletion: gtksourceview tests



Author: jessevdk
Date: Sun Apr 12 19:47:46 2009
New Revision: 2272
URL: http://svn.gnome.org/viewvc/gtksourceview?rev=2272&view=rev

Log:
First revision of API, removed unnecessary API and changed implementation/style details in
gtksourcecompletion.c


Added:
   branches/gtksourcecompletion/gtksourceview/gtksourcecompletionpage.h
Modified:
   branches/gtksourcecompletion/gtksourceview/gtksourcecompletion.c
   branches/gtksourcecompletion/gtksourceview/gtksourcecompletion.h
   branches/gtksourcecompletion/gtksourceview/gtksourcecompletioninfo.c
   branches/gtksourcecompletion/gtksourceview/gtksourcecompletioninfo.h
   branches/gtksourcecompletion/gtksourceview/gtksourcecompletionitem.c
   branches/gtksourcecompletion/gtksourceview/gtksourcecompletionprovider.c
   branches/gtksourcecompletion/gtksourceview/gtksourcecompletionprovider.h
   branches/gtksourcecompletion/gtksourceview/gtksourcecompletiontriggerkey.c
   branches/gtksourcecompletion/gtksourceview/gtksourcecompletionutils.c
   branches/gtksourcecompletion/tests/completion-simple.c
   branches/gtksourcecompletion/tests/gsc-provider-devhelp.c
   branches/gtksourcecompletion/tests/gsc-provider-test.c
   branches/gtksourcecompletion/tests/gsc-provider-test.h

Modified: branches/gtksourcecompletion/gtksourceview/gtksourcecompletion.c
==============================================================================
--- branches/gtksourcecompletion/gtksourceview/gtksourcecompletion.c	(original)
+++ branches/gtksourcecompletion/gtksourceview/gtksourcecompletion.c	Sun Apr 12 19:47:46 2009
@@ -47,15 +47,15 @@
 {
 	COLUMN_PIXBUF,
 	COLUMN_NAME,
-	COLUMN_DATA,
+	COLUMN_PROPOSAL,
+	COLUMN_PROVIDER,
 	N_COLUMNS
 };
 
 /* Signals */
 enum
 {
-	PROPOSAL_SELECTED,
-	DISPLAY_INFO,
+	PROPOSAL_ACTIVATED,
 	LAST_SIGNAL
 };
 
@@ -79,12 +79,11 @@
 {
 	GtkSourceCompletionTrigger *trigger;
 	GtkSourceCompletionProvider *provider;
-} PTPair;
+} ProviderTriggerPair;
 
-typedef struct _GtkSourceCompletionPage GtkSourceCompletionPage;
 struct _GtkSourceCompletionPage
 {
-	gchar *name;
+	gchar *label;
 	
 	GtkScrolledWindow *scroll;
 	GtkTreeView *treeview;
@@ -106,9 +105,11 @@
 	GtkWidget *next_page_button;
 	GtkWidget *prev_page_button;
 	GtkWidget *bottom_bar;
+	GtkWidget *default_info;
 	
 	GList *pages;
 	GtkSourceCompletionPage *active_page;
+	
 	gboolean destroy_has_run;
 	gboolean manage_keys;
 	gboolean remember_info_visibility;
@@ -117,8 +118,7 @@
 	
 	/* Completion management */
 	GtkTextView *view;
-	GList *triggers;
-	GList *prov_trig;
+	GHashTable *triggers;
 	GtkSourceCompletionTrigger *active_trigger;
 	
 	gulong signals_ids[LAST_EXTERNAL_SIGNAL];
@@ -129,23 +129,32 @@
 G_DEFINE_TYPE(GtkSourceCompletion, gtk_source_completion, GTK_TYPE_WINDOW);
 
 static gboolean
-get_selected_proposal (GtkSourceCompletionPage *page,
+get_selected_proposal (GtkSourceCompletion          *completion,
+                       GtkTreeIter                  *iter,
 		       GtkSourceCompletionProposal **proposal)
 {
-	GtkTreeIter iter;
+	GtkTreeIter piter;
 	GtkTreeModel *model;
 	GtkTreeSelection *selection;
+	GtkSourceCompletionPage *page;
+	
+	page = completion->priv->active_page;
 	
 	selection = gtk_tree_view_get_selection (page->treeview);
 	
-	if (gtk_tree_selection_get_selected (selection, NULL, &iter))
+	if (gtk_tree_selection_get_selected (selection, NULL, &piter))
 	{
 		model = gtk_tree_view_get_model (page->treeview);
 		
-		gtk_tree_model_get (model, &iter,
-				    COLUMN_DATA,
+		gtk_tree_model_get (model, &piter,
+				    COLUMN_PROPOSAL,
 				    proposal, -1);
 		
+		if (iter != NULL)
+		{
+			*iter = piter;
+		}
+
 		return TRUE;
 	}
 	
@@ -153,82 +162,58 @@
 }
 
 static gboolean
-select_current_proposal (GtkSourceCompletion *self)
+activate_current_proposal (GtkSourceCompletion *completion)
 {
-	gboolean selected = TRUE;
+	gboolean activated = FALSE;
 	GtkSourceCompletionProposal *prop = NULL;
 	
-	if (get_selected_proposal (self->priv->active_page, &prop))
-	{
-		g_signal_emit (G_OBJECT (self), signals[PROPOSAL_SELECTED],
-			       0, prop, &selected);
-		selected = TRUE;
-	}
-	else
+	if (get_selected_proposal (completion, NULL, &prop))
 	{
-		selected = FALSE;
+		g_signal_emit (G_OBJECT (completion), signals[PROPOSAL_ACTIVATED],
+			       0, prop, &activated);
+		
+		g_object_unref (prop);
 	}
 	
-	return selected;
+	return activated;
 }
 
+typedef gboolean (*ProposalSelector)(GtkTreeModel *model, GtkTreeIter *iter, gboolean hasselection, gpointer userdata);
+
 static gboolean
-select_first_proposal (GtkSourceCompletionPage *page)
+select_proposal (GtkSourceCompletion *completion,
+                 ProposalSelector     selector,
+                 gpointer             userdata)
 {
+	GtkTreeSelection *selection;
 	GtkTreeIter iter;
-	GtkTreePath* path;
-	GtkTreeModel* model;
-	GtkTreeSelection* selection;
+	GtkTreePath *path;
+	GtkTreeModel *model;
+	GtkSourceCompletionPage *page;
+	gboolean hasselection;
 	
-	selection = gtk_tree_view_get_selection (page->treeview);
-
-	if (gtk_tree_selection_get_mode (selection) == GTK_SELECTION_NONE)
-		return FALSE;
+	page = completion->priv->active_page;
 
-	model = gtk_tree_view_get_model (page->treeview);
-		
-	if (gtk_tree_model_get_iter_first (model, &iter))
+	if (!GTK_WIDGET_VISIBLE (page->treeview))
 	{
-		gtk_tree_selection_select_iter (selection, &iter);
-		path = gtk_tree_model_get_path (model, &iter);
-		gtk_tree_view_scroll_to_cell (page->treeview,
-					      path, 
-					      NULL, 
-					      FALSE, 
-					      0, 
-					      0);
-		gtk_tree_path_free (path);
-		return TRUE;
+		return FALSE;
 	}
 	
-	return FALSE;
-}
+	selection = gtk_tree_view_get_selection (page->treeview);
 
-static gboolean 
-select_last_proposal (GtkSourceCompletionPage *page)
-{
-	GtkTreeIter iter;
-	GtkTreeModel* model;
-	GtkTreeSelection* selection;
-	GtkTreePath* path;
-	gint children;
-	
-	if (!GTK_WIDGET_VISIBLE (page->treeview))
+	if (gtk_tree_selection_get_mode (selection) == GTK_SELECTION_NONE)
+	{
 		return FALSE;
-	
-	selection = gtk_tree_view_get_selection (page->treeview);
+	}
+
 	model = gtk_tree_view_get_model (page->treeview);
 	
-	if (gtk_tree_selection_get_mode (selection) == GTK_SELECTION_NONE)
-		return FALSE;
+	hasselection = gtk_tree_selection_get_selected (selection, NULL, &iter);
 	
-	children = gtk_tree_model_iter_n_children (model, NULL);
-	if (children > 0)
+	if (selector (model, &iter, hasselection, userdata))
 	{
-		gtk_tree_model_iter_nth_child (model, &iter,
-					       NULL, children - 1);
-	
 		gtk_tree_selection_select_iter (selection, &iter);
+		
 		path = gtk_tree_model_get_path (model, &iter);
 		gtk_tree_view_scroll_to_cell (page->treeview,
 					      path, 
@@ -236,126 +221,144 @@
 					      FALSE, 
 					      0, 
 					      0);
+
 		gtk_tree_path_free (path);
-		return TRUE;
 	}
 	
-	return FALSE;
+	/* Always return TRUE to consume the key press event */
+	return TRUE;
 }
 
 static gboolean
-select_previous_proposal (GtkSourceCompletionPage *page,
-			  gint rows)
+selector_first (GtkTreeModel *model,
+                GtkTreeIter  *iter,
+                gboolean      hasselection,
+                gpointer      userdata)
 {
-	GtkTreeIter iter;
-	GtkTreePath* path;
-	GtkTreeModel* model;
-	GtkTreeSelection* selection;
-	
-	if (!GTK_WIDGET_VISIBLE (page->treeview))
-		return FALSE;
-	
-	selection = gtk_tree_view_get_selection (page->treeview);
-	
-	if (gtk_tree_selection_get_mode (selection) == GTK_SELECTION_NONE)
-		return FALSE;
+	return gtk_tree_model_get_iter_first (model, iter);
+}
+
+static gboolean
+selector_last (GtkTreeModel *model,
+               GtkTreeIter  *iter,
+               gboolean      hasselection,
+               gpointer      userdata)
+{
+	gint num = gtk_tree_model_iter_n_children (model, NULL);
+	return gtk_tree_model_iter_nth_child (model, iter, NULL, num - 1);
+}
+
+static gboolean
+selector_previous (GtkTreeModel *model,
+                   GtkTreeIter  *iter,
+                   gboolean      hasselection,
+                   gpointer      userdata)
+{
+	gint num = GPOINTER_TO_INT (userdata);
+	GtkTreePath *path;
+	gboolean ret = FALSE;
 	
-	if (gtk_tree_selection_get_selected (selection, &model, &iter))
+	if (!hasselection)
 	{
-		gint i;
-		
-		path = gtk_tree_model_get_path (model, &iter);
-		
-		for (i=0; i  < rows; i++)
-			gtk_tree_path_prev (path);
-		
-		if (gtk_tree_model_get_iter(model, &iter, path))
-		{
-			gtk_tree_selection_select_iter (selection, &iter);
-			gtk_tree_view_scroll_to_cell (page->treeview,
-						      path, 
-						      NULL, 
-						      FALSE, 
-						      0, 
-						      0);
-		}
-		gtk_tree_path_free (path);
+		return selector_last (model, iter, hasselection, userdata);
 	}
-	else
+	
+	path = gtk_tree_model_get_path (model, iter);
+	
+	while (num > 0 && gtk_tree_path_prev (path))
 	{
-		return select_first_proposal (page);
+		ret = TRUE;
+		--num;
 	}
 	
-	return TRUE;
+	ret = ret && gtk_tree_model_get_iter (model, iter, path);
+	gtk_tree_path_free (path);
+	
+	return ret;
 }
 
 static gboolean
-select_next_proposal (GtkSourceCompletionPage *page,
-		      gint rows)
+selector_next (GtkTreeModel *model,
+               GtkTreeIter  *iter,
+               gboolean      hasselection,
+               gpointer      userdata)
 {
-	GtkTreeIter iter;
-	GtkTreeModel* model;
-	GtkTreeSelection* selection;
-	
-	if (!GTK_WIDGET_VISIBLE (page->treeview))
-		return FALSE;
-	
-	selection = gtk_tree_view_get_selection (page->treeview);
-	if (gtk_tree_selection_get_mode (selection) == GTK_SELECTION_NONE)
-		return FALSE;
-	
-	if (gtk_tree_selection_get_selected (selection, &model, &iter))
+	gint num = GPOINTER_TO_INT (userdata);
+	gboolean ret = FALSE;
+	GtkTreeIter next;
+
+	if (!hasselection)
 	{
-		GtkTreePath* path;
-		gint i;
-		
-		for (i = 0; i < rows; i++)
-		{
-			if (!gtk_tree_model_iter_next (model, &iter))
-				return select_last_proposal (page);
-		}
-		gtk_tree_selection_select_iter (selection, &iter);
-		path = gtk_tree_model_get_path (model, &iter);
-		gtk_tree_view_scroll_to_cell (page->treeview,
-					      path, 
-					      NULL, 
-					      FALSE, 
-					      0, 
-					      0);
-		gtk_tree_path_free (path);
+		return selector_first (model, iter, hasselection, userdata);
 	}
-	else
+	
+	next = *iter;
+
+	while (num > 0 && gtk_tree_model_iter_next (model, &next))
 	{
-		return select_first_proposal (page);
+		ret = TRUE;
+		
+		*iter = next;
+		--num;
 	}
 	
-	return TRUE;
+	return ret;
+}
+
+static gboolean
+select_first_proposal (GtkSourceCompletion *completion)
+{
+	return select_proposal (completion, selector_first, NULL);
+}
+
+static gboolean 
+select_last_proposal (GtkSourceCompletion *completion)
+{
+	return select_proposal (completion, selector_last, NULL);
+}
+
+static gboolean
+select_previous_proposal (GtkSourceCompletion *completion,
+			  gint                 rows)
+{
+	return select_proposal (completion, selector_previous, GINT_TO_POINTER (rows));
+}
+
+static gboolean
+select_next_proposal (GtkSourceCompletion *completion,
+		      gint                 rows)
+{
+	return select_proposal (completion, selector_next, GINT_TO_POINTER (rows));
 }
 
 static void
-update_info_pos (GtkSourceCompletion *self)
+update_info_position (GtkSourceCompletion *completion)
 {
-	GtkSourceCompletionProposal *proposal = NULL;
-	gint y, x, sw, sh;
+	gint x, y;
+	gint width, height;
+	gint sw, sh;
+	gint info_width;
+	GdkScreen *screen;
+	
+	gtk_window_get_position (GTK_WINDOW (completion), &x, &y);
+	gtk_window_get_size (GTK_WINDOW (completion), &width, &height);
+	gtk_window_get_size (GTK_WINDOW (completion->priv->info_window), &info_width, NULL);
+
+	screen = gtk_window_get_screen (GTK_WINDOW (completion));
+	sw = gdk_screen_get_width (screen);
+	sh = gdk_screen_get_height (screen);
 	
-	if (get_selected_proposal (self->priv->active_page, &proposal))
+	/* Determine on which side to place it */
+	if (x + width + info_width >= sw)
 	{
-		gboolean ret = TRUE;
-		g_signal_emit (self, signals[DISPLAY_INFO], 0, proposal, &ret);
+		x -= info_width;
 	}
-	
-	gtk_window_get_position (GTK_WINDOW (self), &x, &y);
-	sw = gdk_screen_width ();
-	sh = gdk_screen_height ();
-	x += WINDOW_WIDTH;
-
-	if (x + WINDOW_WIDTH >= sw)
+	else
 	{
-		x -= (WINDOW_WIDTH * 2);
+		x += width;
 	}
-	gtk_window_move (GTK_WINDOW (self->priv->info_window), x, y);
-	gtk_window_set_transient_for (GTK_WINDOW (self->priv->info_window),
-				      gtk_window_get_transient_for (GTK_WINDOW (self)));
+
+	gtk_window_move (GTK_WINDOW (completion->priv->info_window), x, y);
 }
 
 static gboolean
@@ -365,85 +368,140 @@
 {
 	GtkSourceCompletionPage *page = (GtkSourceCompletionPage *)data;
 	GtkSourceCompletionProposal *proposal = NULL;
+	gboolean ret;
 	
 	if (!page->filter_active || !page->filter_func)
 		return TRUE;
 		
 	gtk_tree_model_get (model,
 			    iter,
-			    COLUMN_DATA,
+			    COLUMN_PROPOSAL,
 			    &proposal,
 			    -1);
 	
 	if (proposal == NULL)
 		return TRUE;
 	
-	return page->filter_func (proposal, page->filter_data);
+	ret = page->filter_func (proposal, page->filter_data);
+	g_object_unref (proposal);
+	
+	return ret;
+}
+
+static void
+row_activated_cb (GtkTreeView         *tree_view,
+		  GtkTreePath         *path,
+		  GtkTreeViewColumn   *column,
+		  GtkSourceCompletion *completion)
+{
+	activate_current_proposal (completion);
+}
+
+static void
+update_proposal_info_real (GtkSourceCompletion         *completion,
+                           GtkSourceCompletionProvider *provider,
+                           GtkSourceCompletionProposal *proposal)
+{
+	GtkWidget *info_widget;
+	const gchar *text;
+	
+	if (proposal == NULL)
+	{
+		/* Set to default widget */
+		info_widget = completion->priv->default_info;
+		gtk_label_set_markup (GTK_LABEL (info_widget), "");
+	}
+	else
+	{
+		info_widget = gtk_source_completion_provider_get_info_widget (provider, 
+		                                                              proposal);
+
+		/* If there is no special custom widget, use the default */
+		if (info_widget == NULL)
+		{
+			info_widget = completion->priv->default_info;
+			text = gtk_source_completion_proposal_get_info (proposal);
+			
+			gtk_label_set_markup (GTK_LABEL (info_widget), text != NULL ? text : "");
+		}
+	}
+
+	gtk_source_completion_info_set_widget (GTK_SOURCE_COMPLETION_INFO (completion->priv->info_window),
+	                                       info_widget);
 }
 
 static void
-row_activated_cb (GtkTreeView *tree_view,
-		  GtkTreePath *path,
-		  GtkTreeViewColumn *column,
-		  GtkSourceCompletion *self)
+update_proposal_info (GtkSourceCompletion *completion)
 {
-	select_current_proposal (self);
+	GtkSourceCompletionProposal *proposal = NULL;
+	GtkSourceCompletionProvider *provider;
+	GtkTreeModel *model;
+	GtkTreeIter iter;
+	
+	if (get_selected_proposal (completion, &iter, &proposal))
+	{
+		model = gtk_tree_view_get_model (completion->priv->active_page->treeview);
+		gtk_tree_model_get (model, &iter, COLUMN_PROVIDER, &provider, -1);
+		
+		update_proposal_info_real (completion, provider, proposal);
+		
+		g_object_unref (proposal);
+		g_object_unref (provider);
+	}
+	else
+	{
+		update_proposal_info_real (completion, NULL, NULL);
+	}
 }
 
 static void 
-selection_changed_cd (GtkTreeSelection *selection, 
-		      GtkSourceCompletion *self)
+selection_changed_cb (GtkTreeSelection    *selection, 
+		      GtkSourceCompletion *completion)
 {
-	if (GTK_WIDGET_VISIBLE (self->priv->info_window))
+	if (GTK_WIDGET_VISIBLE (completion->priv->info_window))
 	{
-		update_info_pos (self);
+		update_proposal_info (completion);
 	}
 }
 
 static void
-add_proposal (GtkSourceCompletionPage *page,
-	      GtkSourceCompletionProposal *data)
+add_proposal (GtkSourceCompletion         *completion,
+              GtkSourceCompletionProvider *provider,
+              GtkSourceCompletionProposal *proposal,
+              GtkSourceCompletionPage     *page)
 {
 	GtkTreeIter iter;
 
-	g_assert (data != NULL);
-	
+	if (page == NULL || g_list_find (completion->priv->pages, page) == NULL)
+	{
+		page = (GtkSourceCompletionPage *)completion->priv->pages->data;
+	}
+
 	gtk_list_store_append (page->list_store, &iter);
-			
 	gtk_list_store_set (page->list_store, 
 			    &iter,
-			    COLUMN_PIXBUF, gtk_source_completion_proposal_get_icon (data),
-			    COLUMN_NAME, gtk_source_completion_proposal_get_label (data),
-			    COLUMN_DATA, data,
+			    COLUMN_PIXBUF, gtk_source_completion_proposal_get_icon (proposal),
+			    COLUMN_NAME, gtk_source_completion_proposal_get_label (proposal),
+			    COLUMN_PROPOSAL, proposal,
+			    COLUMN_PROVIDER, provider,
 			    -1);
+
+	g_object_unref (proposal);
 }
 
 static void
-clear_treeview (GtkSourceCompletionPage *page)
+clear_page (GtkSourceCompletionPage *page)
 {
-	GtkTreeModel *model = GTK_TREE_MODEL (page->list_store);
-	GtkTreeIter iter;
-	GtkSourceCompletionProposal *data;
-	
-	if (gtk_tree_model_get_iter_first (model, &iter))
-	{
-		do
-		{
-			gtk_tree_model_get (model, &iter,
-					    COLUMN_DATA, &data, -1);
-			g_object_unref (data);
-		} while (gtk_tree_model_iter_next (model, &iter));
-	}
-	
 	gtk_list_store_clear (page->list_store);
 }
 
-static gint 
-get_num_proposals (GtkSourceCompletionPage *page)
+static gboolean 
+page_has_proposals (GtkSourceCompletionPage *page)
 {
-	GtkTreeModel *model = gtk_tree_view_get_model (page->treeview);
-	
-	return gtk_tree_model_iter_n_children (model, NULL);
+	GtkTreeIter iter;
+	return gtk_tree_model_iter_children (gtk_tree_view_get_model (page->treeview), 
+	                                     &iter, 
+	                                     NULL);
 }
 
 static void
@@ -454,233 +512,175 @@
 	page->filter_active = TRUE;
 	page->filter_data = user_data;
 	page->filter_func = func;
+
 	gtk_tree_model_filter_refilter (page->model_filter);
+
 	page->filter_active = FALSE;
 	page->filter_data = NULL;
 	page->filter_func = NULL;
 }
 
 static void
-free_pair (gpointer data)
-{
-	PTPair *ptp = (PTPair *)data;
-	g_object_unref (ptp->provider);
-	g_slice_free (PTPair, ptp);
-}
-
-static void
-end_completion (GtkSourceCompletion *self)
-{
-	if (GTK_WIDGET_VISIBLE (self))
-	{
-		gtk_widget_hide (GTK_WIDGET (self));
-		/*
-		* We are connected to the hide signal too. Then end_completion 
-		* will be called again but the popup will not be visible
-		*/
-	}
-	else
-	{
-		self->priv->active_trigger = NULL;
-	}
-}
-
-static void
-gtk_source_completion_clear (GtkSourceCompletion *self)
+gtk_source_completion_clear (GtkSourceCompletion *completion)
 {
 	GList *l;
 	
-	g_return_if_fail (GTK_IS_SOURCE_COMPLETION (self));
+	g_return_if_fail (GTK_IS_SOURCE_COMPLETION (completion));
 	
-	for (l = self->priv->pages; l != NULL; l = g_list_next (l))
+	for (l = completion->priv->pages; l != NULL; l = g_list_next (l))
 	{
 		GtkSourceCompletionPage *page = (GtkSourceCompletionPage *)l->data;
 		
-		clear_treeview (page);
+		clear_page (page);
 	}
 }
 
 static gboolean
-update_pages_visibility (GtkSourceCompletion *self)
+update_pages_visibility (GtkSourceCompletion *completion)
 {
 	GList *l;
 	gboolean first_set = FALSE;
-	guint num_pages_with_data = 0;
+	gboolean more_pages = FALSE;
+
 	gint i = 0;
 	GtkAdjustment *ad;
 	
-	for (l = self->priv->pages; l != NULL; l = g_list_next (l))
+	for (l = completion->priv->pages; l != NULL; l = g_list_next (l))
 	{
 		GtkSourceCompletionPage *page = (GtkSourceCompletionPage *)l->data;
 		
-		if (get_num_proposals (page) > 0)
+		if (page_has_proposals (page))
 		{
-			/*Selects the first page with data*/
+			/* Selects the first page with data */
 			if (!first_set)
 			{
-				gtk_notebook_set_current_page (GTK_NOTEBOOK (self->priv->notebook),
+				gtk_notebook_set_current_page (GTK_NOTEBOOK (completion->priv->notebook),
 							       i);
+							       
 				ad = gtk_tree_view_get_vadjustment (page->treeview);
 				gtk_adjustment_set_value (ad, 0);
+				
 				ad = gtk_tree_view_get_hadjustment (page->treeview);
 				gtk_adjustment_set_value (ad, 0);
+
 				first_set = TRUE;
 			}
-			num_pages_with_data++;
+			else
+			{
+				more_pages = TRUE;
+				break;
+			}
 		}
+
 		i++;
 	}
-	if (num_pages_with_data > 1)
+	
+	if (more_pages)
 	{
-		gtk_widget_show (self->priv->next_page_button);
-		gtk_widget_show (self->priv->prev_page_button);
+		gtk_widget_show (completion->priv->next_page_button);
+		gtk_widget_show (completion->priv->prev_page_button);
 	}
 	else
 	{
-		gtk_widget_hide (self->priv->next_page_button);
-		gtk_widget_hide (self->priv->prev_page_button);
+		gtk_widget_hide (completion->priv->next_page_button);
+		gtk_widget_hide (completion->priv->prev_page_button);
 	}
 	
-	return num_pages_with_data > 0;
+	return first_set;
 }
 
 static void
-gtk_source_completion_show_or_update (GtkWidget *widget)
+gtk_source_completion_show (GtkWidget *widget)
 {
 	gboolean data;
 	
-	/*Only show the popup, the positions is set before this function*/
-	GtkSourceCompletion *self = GTK_SOURCE_COMPLETION (widget);
-	
-	data = update_pages_visibility (self);
-	
-	if (data && !GTK_WIDGET_VISIBLE (self))
+	/* Only show the popup, the positions is set before this function */
+	GtkSourceCompletion *completion = GTK_SOURCE_COMPLETION (widget);
+
+	/* Call update_pages_visibility selects first page */
+	data = update_pages_visibility (completion);
+
+	if (data && !GTK_WIDGET_VISIBLE (completion))
 	{
 		GTK_WIDGET_CLASS (gtk_source_completion_parent_class)->show (widget);
 		
-		if (!self->priv->remember_info_visibility)
-			self->priv->info_visible = FALSE;
+		if (!completion->priv->remember_info_visibility)
+			completion->priv->info_visible = FALSE;
 		
-		gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (self->priv->info_button),
-					      self->priv->info_visible);
+		gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (completion->priv->info_button),
+					      completion->priv->info_visible);
 	}
 }
 
 static void
-gtk_source_completion_page_next (GtkSourceCompletion *self)
+advance_page (GtkSourceCompletion  *completion,
+              GList                *(*advance)(GList *),
+              GList                *(*cycle)(GList *))
 {
-	gint pages;
-	gint current_page;
-	gint page;
-	GtkSourceCompletionPage *popup_page;
+	GList *page;
+	GList *orig;
 	
-	g_return_if_fail (GTK_IS_SOURCE_COMPLETION (self));
+	orig = g_list_find (completion->priv->pages, completion->priv->active_page);
+	page = orig;
 
-	pages = g_list_length (self->priv->pages);
-	current_page = g_list_index (self->priv->pages, self->priv->active_page);
-	page = current_page;
-	
+	/* Find next page with any proposals in them */
 	do
 	{
-		if (page == pages - 1)
-		{
-			page = 0;
-		}
-		else
-		{
-			page++;
-		}
-		popup_page = (GtkSourceCompletionPage *)g_list_nth_data (self->priv->pages, page);
-	}
-	while (get_num_proposals (popup_page) == 0 &&
-	       page != current_page);
-
-	if (page != current_page)
-	{
-		gtk_notebook_set_current_page (GTK_NOTEBOOK (self->priv->notebook),
-					       page);
+		page = advance (page);
 	
-		/*
-		 * After setting the page the active_page was updated
-		 * so we can update the tree
-		 */
-		select_first_proposal (popup_page);
+		if (!page)
+			page = cycle (completion->priv->pages);
+	} while (page_has_proposals ((GtkSourceCompletionPage *)page->data) == 0 && page != orig);
 	
-		if (GTK_WIDGET_VISIBLE (self->priv->info_window))
-		{
-			update_info_pos (self);
-		}
+	if (page != orig)
+	{
+		gtk_notebook_set_current_page (GTK_NOTEBOOK (completion->priv->notebook),
+					       g_list_position (completion->priv->pages, page));
+
+		select_first_proposal (completion);
 	}
 }
 
+static GList *
+list_wrap_next (GList *current)
+{
+	return g_list_next (current);
+}
+
+static GList *
+list_wrap_prev (GList *current)
+{
+	return g_list_previous (current);
+}
+
 static void
-gtk_source_completion_page_previous (GtkSourceCompletion *self)
+gtk_source_completion_page_next (GtkSourceCompletion *completion)
 {
-	gint pages;
-	gint current_page;
-	gint page;
-	GtkSourceCompletionPage *popup_page;
-	
-	g_return_if_fail (GTK_IS_SOURCE_COMPLETION (self));
-	
-	pages = g_list_length (self->priv->pages);
-	current_page = g_list_index (self->priv->pages,
-				     self->priv->active_page);
-	page = current_page;
-	
-	do
-	{
-		if (page == 0)
-		{
-			page = pages - 1;
-		}
-		else
-		{
-			page--;
-		}
-		popup_page = (GtkSourceCompletionPage *)g_list_nth_data (self->priv->pages,
-									 page);
-	}
-	while (get_num_proposals (popup_page) == 0 &&
-	       page != current_page);
-	
-	if (page != current_page)
-	{
-		gtk_notebook_set_current_page (GTK_NOTEBOOK (self->priv->notebook),
-					       page);
-	
-		/*
-		 * After setting the page the active_page was updated
-		 * so we can update the tree
-		 */
-		select_first_proposal (popup_page);
-	
-		if (GTK_WIDGET_VISIBLE (self->priv->info_window))
-		{
-			update_info_pos (self);
-		}
-	}
+	advance_page (completion, list_wrap_next, g_list_first);
+}
+
+static void
+gtk_source_completion_page_previous (GtkSourceCompletion *completion)
+{
+	advance_page (completion, list_wrap_prev, g_list_last);
 }
 
 static GtkSourceCompletionPage *
-gtk_source_completion_page_new (GtkSourceCompletion *self,
-				const gchar *tree_name)
+gtk_source_completion_page_new (GtkSourceCompletion *completion,
+				const gchar         *label)
 {
-	/*Creates the new trees*/
 	GtkSourceCompletionPage *page;
 	GtkCellRenderer *renderer;
 	GtkTreeViewColumn *column;
-	GtkCellRenderer* renderer_pixbuf;
-	GtkTreeViewColumn* column_pixbuf;
 	GtkTreeModel *model;
 	GtkTreeSelection *selection;
-	GtkWidget *label;
 	
 	page = g_slice_new (GtkSourceCompletionPage);
-	
-	page->name = g_strdup (tree_name);
-	
+
+	page->label = g_strdup (label);
+
 	page->treeview = GTK_TREE_VIEW (gtk_tree_view_new ());
+	
 	gtk_widget_show (GTK_WIDGET (page->treeview));
 	
 	page->filter_data = NULL;
@@ -691,28 +691,25 @@
 	gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (page->treeview),
 					   FALSE);
 	
-	/* Create the Tree */
-	renderer_pixbuf = gtk_cell_renderer_pixbuf_new ();
-	column_pixbuf = gtk_tree_view_column_new_with_attributes ("Pixbuf",
-								  renderer_pixbuf, 
-								  "pixbuf", 
-								  COLUMN_PIXBUF, 
-								  NULL);
-	
+	/* Create the tree */
 	column = gtk_tree_view_column_new ();
-	renderer = gtk_cell_renderer_text_new ();
+	renderer = gtk_cell_renderer_pixbuf_new ();
+	
 	gtk_tree_view_column_pack_start (column, renderer, FALSE);
-	gtk_tree_view_column_set_attributes (column, renderer,
-					     "text", COLUMN_NAME, NULL);
+	gtk_tree_view_column_set_attributes (column, renderer, "pixbuf", COLUMN_PIXBUF, NULL);
+	
+	renderer = gtk_cell_renderer_text_new ();
+	gtk_tree_view_column_pack_start (column, renderer, TRUE);
 
-	gtk_tree_view_append_column (page->treeview, column_pixbuf);
+	gtk_tree_view_column_set_attributes (column, renderer, "text", COLUMN_NAME, NULL);
 	gtk_tree_view_append_column (page->treeview, column);
 	
 	/* Create the model */
 	page->list_store = gtk_list_store_new (N_COLUMNS,
 					       GDK_TYPE_PIXBUF, 
 					       G_TYPE_STRING, 
-					       G_TYPE_POINTER);
+					       G_TYPE_OBJECT,
+					       G_TYPE_OBJECT);
 	
 	model = gtk_tree_model_filter_new (GTK_TREE_MODEL (page->list_store),
 					   NULL);
@@ -730,16 +727,13 @@
 	g_signal_connect (page->treeview,
 			  "row-activated",
 			  G_CALLBACK (row_activated_cb),
-			  self);
+			  completion);
 	
 	selection = gtk_tree_view_get_selection (page->treeview);
 	g_signal_connect (selection,
 			  "changed",
-			  G_CALLBACK (selection_changed_cd),
-			  self);
-	
-	self->priv->pages = g_list_append (self->priv->pages,
-					   page);
+			  G_CALLBACK (selection_changed_cb),
+			  completion);
 	
 	page->scroll = GTK_SCROLLED_WINDOW (gtk_scrolled_window_new (NULL, NULL));
 	gtk_widget_show (GTK_WIDGET (page->scroll));
@@ -751,48 +745,20 @@
 	gtk_container_add (GTK_CONTAINER (page->scroll),
 			   GTK_WIDGET (page->treeview));
 	
-	label = gtk_label_new (tree_name);
-	
-	gtk_notebook_append_page (GTK_NOTEBOOK (self->priv->notebook),
-				  GTK_WIDGET (page->scroll),
-				  label);
-	
-	return page;
-}
-
-static GtkSourceCompletionPage *
-get_page_by_name (GtkSourceCompletion *self,
-		  const gchar* tree_name)
-{
-	GtkSourceCompletionPage *page;
-	GList *l;
-	
-	for (l = self->priv->pages; l != NULL; l = g_list_next (l))
-	{
-		page = (GtkSourceCompletionPage *)l->data;
-	
-		if (strcmp (page->name, tree_name) == 0)
-			return page;
-	}
-	
-	page = gtk_source_completion_page_new (self, tree_name);
-
 	return page;
 }
 
 static void
-info_toggled_cb (GtkToggleButton *widget,
-		 gpointer user_data)
+info_toggled_cb (GtkToggleButton     *widget,
+		 GtkSourceCompletion *completion)
 {
-	GtkSourceCompletion *self = GTK_SOURCE_COMPLETION (user_data);
-	
 	if (gtk_toggle_button_get_active (widget))
 	{
-		gtk_widget_show (self->priv->info_window);
+		gtk_widget_show (completion->priv->info_window);
 	}
 	else
 	{
-		gtk_widget_hide (self->priv->info_window);
+		gtk_widget_hide (completion->priv->info_window);
 	}
 }
 
@@ -800,145 +766,124 @@
 next_page_cb (GtkWidget *widget,
 	      gpointer user_data)
 {
-	GtkSourceCompletion *self = GTK_SOURCE_COMPLETION (user_data);
+	GtkSourceCompletion *completion = GTK_SOURCE_COMPLETION (user_data);
 	
-	gtk_source_completion_page_next (self);
+	gtk_source_completion_page_next (completion);
 }
 
 static void
 prev_page_cb (GtkWidget *widget,
 	      gpointer user_data)
 {
-	GtkSourceCompletion *self = GTK_SOURCE_COMPLETION (user_data);
+	GtkSourceCompletion *completion = GTK_SOURCE_COMPLETION (user_data);
 	
-	gtk_source_completion_page_previous (self);
+	gtk_source_completion_page_previous (completion);
 }
 
 static gboolean
-switch_page_cb (GtkNotebook *notebook, 
-		GtkNotebookPage *n_page,
-		gint page_num, 
-		gpointer user_data)
+switch_page_cb (GtkNotebook         *notebook, 
+		GtkNotebookPage     *n_page,
+		gint                 page_num, 
+		GtkSourceCompletion *completion)
 {
-	GtkSourceCompletion *self = GTK_SOURCE_COMPLETION (user_data);
-	
 	/* Update the active page */
-	self->priv->active_page = (GtkSourceCompletionPage *)g_list_nth_data (self->priv->pages,
-									      page_num);
-	
-	gtk_label_set_label (GTK_LABEL (self->priv->tab_label),
-			     self->priv->active_page->name);
+	completion->priv->active_page = g_list_nth_data (completion->priv->pages, page_num);
 
+	gtk_label_set_label (GTK_LABEL (completion->priv->tab_label),
+			     completion->priv->active_page->label);
+
+	update_proposal_info (completion);
 	return FALSE;
 }
 
 static void
-show_info_cb (GtkWidget *widget,
-	      gpointer user_data)
+show_info_cb (GtkWidget           *widget,
+	      GtkSourceCompletion *completion)
 {
-	GtkSourceCompletion *self = GTK_SOURCE_COMPLETION (user_data);
+	g_return_if_fail (GTK_WIDGET_VISIBLE (GTK_WIDGET (completion)));
 	
-	g_return_if_fail (GTK_WIDGET_VISIBLE (GTK_WIDGET (self)));
+	update_info_position (completion);
+	update_proposal_info (completion);
 	
-	update_info_pos (self);
-	self->priv->info_visible = TRUE;
-	gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (self->priv->info_button),
+	gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (completion->priv->info_button),
 				      TRUE);
 }
 
 static void
-hide_info_cb (GtkWidget *widget,
-	      gpointer user_data)
+show_info_after_cb (GtkWidget           *widget,
+	            GtkSourceCompletion *completion)
 {
-	GtkSourceCompletion *self = GTK_SOURCE_COMPLETION (user_data);
+	g_return_if_fail (GTK_WIDGET_VISIBLE (GTK_WIDGET (completion)));
 	
-	self->priv->info_visible = FALSE;
-	gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (self->priv->info_button),
-				      FALSE);
+	/* We do this here because GtkLabel does not properly handle
+	 * can-focus = FALSE and selects all the text when it gets focus from
+	 * showing the info window for the first time */
+	gtk_label_select_region (GTK_LABEL (completion->priv->default_info), 0, 0);
 }
 
-static gboolean
-gtk_source_completion_display_info_default (GtkSourceCompletion *self,
-					    GtkSourceCompletionProposal *proposal)
-{
-	if (proposal)
-	{
-		const gchar *info;
-		
-		info = gtk_source_completion_proposal_get_info (proposal);
-		
-		if (info != NULL)
-		{
-			gtk_source_completion_info_set_markup (GTK_SOURCE_COMPLETION_INFO (self->priv->info_window),
-							       info);
-		}
-		else
-		{
-			gtk_source_completion_info_set_markup (GTK_SOURCE_COMPLETION_INFO (self->priv->info_window),
-							       _("There is no info for the current proposal"));
-		}
-		return TRUE;
-	}
-	
-	return FALSE;
+static void
+hide_info_cb (GtkWidget *widget,
+	      gpointer user_data)
+{
+	GtkSourceCompletion *completion = GTK_SOURCE_COMPLETION (user_data);
+
+	gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (completion->priv->info_button),
+				      FALSE);
 }
 
 static gboolean
-gtk_source_completion_proposal_selected_default (GtkSourceCompletion *self,
-						 GtkSourceCompletionProposal *proposal)
+gtk_source_completion_proposal_activated_default (GtkSourceCompletion         *completion,
+						  GtkSourceCompletionProposal *proposal)
 {
-	gtk_source_completion_proposal_activate (proposal, 
-	                                         GTK_SOURCE_BUFFER (gtk_text_view_get_buffer (
-	                                         	self->priv->view)));
-	end_completion (self);
+	gboolean ret;
 	
-	return FALSE;
+	ret = gtk_source_completion_proposal_activate (proposal, 
+	                                               GTK_SOURCE_BUFFER (gtk_text_view_get_buffer (
+	                                                                  completion->priv->view)));
+	gtk_source_completion_finish (completion);
+	return ret;
 }
 
 static void
-gtk_source_completion_hide (GtkWidget *widget)
+gtk_source_completion_finish_real (GtkSourceCompletion *completion)
 {
-	GtkSourceCompletion *self = GTK_SOURCE_COMPLETION (widget);
-	gboolean info_visible = self->priv->info_visible;
+	gboolean info_visible = GTK_WIDGET_VISIBLE (completion->priv->info_window);
 	
-	GTK_WIDGET_CLASS (gtk_source_completion_parent_class)->hide (widget);
+	GTK_WIDGET_CLASS (gtk_source_completion_parent_class)->hide (GTK_WIDGET (completion));
 	
-	//setting to FALSE, hide the info window
-	gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (self->priv->info_button),
+	/* setting to FALSE, hide the info window */
+	gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (completion->priv->info_button),
 				      FALSE);
 	
-	self->priv->info_visible = info_visible;
+	completion->priv->info_visible = info_visible;
+	completion->priv->active_trigger = NULL;
+	
+	gtk_label_set_markup (GTK_LABEL (completion->priv->default_info), "");
+}
+
+static void
+gtk_source_completion_hide (GtkWidget *widget)
+{
+	gtk_source_completion_finish_real (GTK_SOURCE_COMPLETION (widget));	
 }
 
 static void
 gtk_source_completion_realize (GtkWidget *widget)
 {
-	GtkSourceCompletion *self = GTK_SOURCE_COMPLETION (widget);
+	GtkSourceCompletion *completion = GTK_SOURCE_COMPLETION (widget);
 	
-	gtk_container_set_border_width (GTK_CONTAINER (self), 1);
-	gtk_widget_set_size_request (GTK_WIDGET (self),
+	gtk_container_set_border_width (GTK_CONTAINER (completion), 1);
+	gtk_widget_set_size_request (GTK_WIDGET (completion),
 				     WINDOW_WIDTH, WINDOW_HEIGHT);
-	gtk_window_set_resizable (GTK_WINDOW (self), TRUE);
+	gtk_window_set_resizable (GTK_WINDOW (completion), TRUE);
 	
 	GTK_WIDGET_CLASS (gtk_source_completion_parent_class)->realize (widget);
 }
 
-static gboolean
-gtk_source_completion_delete_event_cb (GtkWidget *widget,
-				       GdkEvent  *event,
-				       gpointer   user_data) 
-{
-	/*Prevent the alt+F4 keys*/
-	return TRUE;
-}
-
 static void
-free_page (gpointer data,
-	   gpointer user_data)
+free_page (GtkSourceCompletionPage *page)
 {
-	GtkSourceCompletionPage *page = (GtkSourceCompletionPage *)data;
-	
-	g_free (page->name);
+	g_free (page->label);
 	g_slice_free (GtkSourceCompletionPage, page);
 }
 
@@ -946,13 +891,13 @@
 gtk_source_completion_configure_event (GtkWidget *widget,
 				       GdkEventConfigure *event)
 {
-	GtkSourceCompletion *self = GTK_SOURCE_COMPLETION (widget);
+	GtkSourceCompletion *completion = GTK_SOURCE_COMPLETION (widget);
 	gboolean ret;
 	
 	ret = GTK_WIDGET_CLASS (gtk_source_completion_parent_class)->configure_event (widget, event);
 	
-	if (GTK_WIDGET_VISIBLE (self->priv->info_window))
-		update_info_pos (self);
+	if (ret && GTK_WIDGET_VISIBLE (completion->priv->info_window))
+		update_info_position (completion);
 	
 	return ret;
 }
@@ -962,24 +907,27 @@
 			 GdkEventFocus *event,
 			 gpointer user_data)
 {
-	GtkSourceCompletion *self = GTK_SOURCE_COMPLETION (user_data);
+	GtkSourceCompletion *completion = GTK_SOURCE_COMPLETION (user_data);
 	
-	if (GTK_WIDGET_VISIBLE (self)
-	    && !GTK_WIDGET_HAS_FOCUS (self))
-		end_completion (self);
+	if (GTK_WIDGET_VISIBLE (completion) && !GTK_WIDGET_HAS_FOCUS (completion))
+	{
+		gtk_source_completion_finish (completion);
+	}
 	
 	return FALSE;
 }
 
 static gboolean
-view_button_press_event_cb (GtkWidget *widget,
+view_button_press_event_cb (GtkWidget      *widget,
 			    GdkEventButton *event,
-			    gpointer user_data)
+			    gpointer        user_data)
 {
-	GtkSourceCompletion *self = GTK_SOURCE_COMPLETION (user_data);
+	GtkSourceCompletion *completion = GTK_SOURCE_COMPLETION (user_data);
 	
-	if (GTK_WIDGET_VISIBLE (self))
-		end_completion (self);
+	if (GTK_WIDGET_VISIBLE (completion))
+	{
+		gtk_source_completion_finish (completion);
+	}
 
 	return FALSE;
 }
@@ -987,45 +935,46 @@
 static void
 gtk_source_completion_finalize (GObject *object)
 {
-	GtkSourceCompletion *self = GTK_SOURCE_COMPLETION (object);
-	
-	if (self->priv->pages != NULL)
-	{
-		g_list_foreach (self->priv->pages, (GFunc) free_page, NULL);
-		g_list_free (self->priv->pages);
-	}
+	GtkSourceCompletion *completion = GTK_SOURCE_COMPLETION (object);
 	
-	if (self->priv->triggers != NULL)
-	{
-		g_list_foreach (self->priv->triggers, (GFunc) g_object_unref,
-				NULL);
-		g_list_free (self->priv->triggers);
-	}
+	g_list_foreach (completion->priv->pages, (GFunc)free_page, NULL);
+	g_list_free (completion->priv->pages);
+
+	g_hash_table_destroy (completion->priv->triggers);
 	
-	if (self->priv->prov_trig != NULL)
-	{
-		g_list_foreach (self->priv->prov_trig, (GFunc) free_pair,
-				NULL);
-		g_list_free (self->priv->prov_trig);
-	}
+	G_OBJECT_CLASS (gtk_source_completion_parent_class)->finalize (object);
+}
+
+static gboolean
+remove_from_hash (GtkSourceCompletionTrigger *trigger,
+                  GList                      *providers)
+{
+	g_list_foreach (providers, (GFunc)g_object_unref, NULL);
+	g_list_free (providers);
 	
-	g_signal_handler_disconnect (self->priv->view,
-				     self->priv->signals_ids[TEXT_VIEW_FOCUS_OUT]);
-	g_signal_handler_disconnect (self->priv->view,
-				     self->priv->signals_ids[TEXT_VIEW_BUTTON_PRESS]);
+	g_object_unref (trigger);
 	
-	G_OBJECT_CLASS (gtk_source_completion_parent_class)->finalize (object);
+	return TRUE;
 }
 
 static void
 gtk_source_completion_destroy (GtkObject *object)
 {
-	GtkSourceCompletion *self = GTK_SOURCE_COMPLETION (object);
+	GtkSourceCompletion *completion = GTK_SOURCE_COMPLETION (object);
 	
-	if (!self->priv->destroy_has_run)
+	if (!completion->priv->destroy_has_run)
 	{
-		gtk_source_completion_clear (self);
-		self->priv->destroy_has_run = TRUE;
+		gtk_source_completion_clear (completion);
+		g_hash_table_foreach_remove (completion->priv->triggers, (GHRFunc)remove_from_hash, NULL);
+	
+		g_signal_handler_disconnect (completion->priv->view,
+				     completion->priv->signals_ids[TEXT_VIEW_FOCUS_OUT]);
+		g_signal_handler_disconnect (completion->priv->view,
+					     completion->priv->signals_ids[TEXT_VIEW_BUTTON_PRESS]);
+
+		g_object_unref (completion->priv->view);
+
+		completion->priv->destroy_has_run = TRUE;
 	}
 	GTK_OBJECT_CLASS (gtk_source_completion_parent_class)->destroy (object);
 }
@@ -1036,71 +985,71 @@
 			 gpointer user_data)
 {
 	gboolean ret = FALSE;
-	GtkSourceCompletion *self;
+	GtkSourceCompletion *completion;
 	
 	g_return_val_if_fail (GTK_IS_SOURCE_COMPLETION (user_data), FALSE);
 	
-	self = GTK_SOURCE_COMPLETION (user_data);
+	completion = GTK_SOURCE_COMPLETION (user_data);
 	
-	if (!GTK_WIDGET_VISIBLE (self))
+	if (!GTK_WIDGET_VISIBLE (completion))
 		return FALSE;
 	
 	switch (event->keyval)
  	{
 		case GDK_Escape:
 		{
-			gtk_widget_hide (GTK_WIDGET (self));
+			gtk_widget_hide (GTK_WIDGET (completion));
 			ret = TRUE;
 			break;
 		}
  		case GDK_Down:
 		{
-			ret = select_next_proposal (self->priv->active_page, 1);
+			select_next_proposal (completion, 1);
 			break;
 		}
 		case GDK_Page_Down:
 		{
-			ret = select_next_proposal (self->priv->active_page, 5);
+			ret = select_next_proposal (completion, 5);
 			break;
 		}
 		case GDK_Up:
 		{
-			ret = select_previous_proposal (self->priv->active_page, 1);
+			ret = select_previous_proposal (completion, 1);
 			if (!ret)
-				ret = select_first_proposal (self->priv->active_page);
+				ret = select_first_proposal (completion);
 			break;
 		}
 		case GDK_Page_Up:
 		{
-			ret = select_previous_proposal (self->priv->active_page, 5);
+			ret = select_previous_proposal (completion, 5);
 			break;
 		}
 		case GDK_Home:
 		{
-			ret = select_first_proposal (self->priv->active_page);
+			ret = select_first_proposal (completion);
 			break;
 		}
 		case GDK_End:
 		{
-			ret = select_last_proposal (self->priv->active_page);
+			ret = select_last_proposal (completion);
 			break;
 		}
 		case GDK_Return:
 		case GDK_Tab:
 		{
-			ret = select_current_proposal (self);
-			gtk_widget_hide (GTK_WIDGET (self));
+			ret = activate_current_proposal (completion);
+			gtk_widget_hide (GTK_WIDGET (completion));
 			break;
 		}
 		case GDK_Right:
 		{
-			gtk_source_completion_page_next (self);
+			gtk_source_completion_page_next (completion);
 			ret = TRUE;
 			break;
 		}
 		case GDK_Left:
 		{
-			gtk_source_completion_page_previous (self);
+			gtk_source_completion_page_previous (completion);
 			ret = TRUE;
 			break;
 		}
@@ -1108,8 +1057,8 @@
 		{
 			if ((event->state & GDK_CONTROL_MASK) != 0)
 			{
-				gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (self->priv->info_button),
-					!gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (self->priv->info_button)));
+				gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (completion->priv->info_button),
+					!gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (completion->priv->info_button)));
 				ret = TRUE;
 			}
 		}
@@ -1118,22 +1067,28 @@
 }
 
 static void
-set_manage_keys (GtkSourceCompletion *self)
+set_manage_keys (GtkSourceCompletion *completion)
 {
-	if (self->priv->manage_keys && self->priv->signals_ids[TEXT_VIEW_KP] == 0)
+	if (completion->priv->view == NULL)
+	{
+		/* This happens on gobject construction, its ok */
+		return;
+	}
+
+	if (completion->priv->manage_keys && completion->priv->signals_ids[TEXT_VIEW_KP] == 0)
 	{
-		self->priv->signals_ids[TEXT_VIEW_KP] = 
-			g_signal_connect (self->priv->view,
+		completion->priv->signals_ids[TEXT_VIEW_KP] = 
+			g_signal_connect (completion->priv->view,
 					  "key-press-event",
 					  G_CALLBACK (view_key_press_event_cb),
-					  self);
+					  completion);
 	}
 	
-	if (!self->priv->manage_keys && self->priv->signals_ids[TEXT_VIEW_KP] != 0)
+	if (!completion->priv->manage_keys && completion->priv->signals_ids[TEXT_VIEW_KP] != 0)
 	{
-		g_signal_handler_disconnect (self->priv->view,
-					     self->priv->signals_ids[TEXT_VIEW_KP]);
-		self->priv->signals_ids[TEXT_VIEW_KP] = 0;
+		g_signal_handler_disconnect (completion->priv->view,
+					     completion->priv->signals_ids[TEXT_VIEW_KP]);
+		completion->priv->signals_ids[TEXT_VIEW_KP] = 0;
 	}
 }
 
@@ -1143,22 +1098,22 @@
 				    GValue     *value,
 				    GParamSpec *pspec)
 {
-	GtkSourceCompletion *self;
+	GtkSourceCompletion *completion;
 	
 	g_return_if_fail (GTK_IS_SOURCE_COMPLETION (object));
 	
-	self = GTK_SOURCE_COMPLETION (object);
+	completion = GTK_SOURCE_COMPLETION (object);
 
 	switch (prop_id)
 	{
 		case PROP_MANAGE_KEYS:
-			g_value_set_boolean (value, self->priv->manage_keys);
+			g_value_set_boolean (value, completion->priv->manage_keys);
 			break;
 		case PROP_REMEMBER_INFO_VISIBILITY:
-			g_value_set_boolean (value, self->priv->remember_info_visibility);
+			g_value_set_boolean (value, completion->priv->remember_info_visibility);
 			break;
 		case PROP_SELECT_ON_SHOW:
-			g_value_set_boolean (value, self->priv->select_on_show);
+			g_value_set_boolean (value, completion->priv->select_on_show);
 			break;
 		default:
 			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -1172,23 +1127,23 @@
 				    const GValue *value,
 				    GParamSpec   *pspec)
 {
-	GtkSourceCompletion *self;
+	GtkSourceCompletion *completion;
 	
 	g_return_if_fail (GTK_IS_SOURCE_COMPLETION (object));
 	
-	self = GTK_SOURCE_COMPLETION (object);
+	completion = GTK_SOURCE_COMPLETION (object);
 
 	switch (prop_id)
 	{
 		case PROP_MANAGE_KEYS:
-			self->priv->manage_keys = g_value_get_boolean (value);
-			set_manage_keys (self);
+			completion->priv->manage_keys = g_value_get_boolean (value);
+			set_manage_keys (completion);
 			break;
 		case PROP_REMEMBER_INFO_VISIBILITY:
-			self->priv->remember_info_visibility = g_value_get_boolean (value);
+			completion->priv->remember_info_visibility = g_value_get_boolean (value);
 			break;
 		case PROP_SELECT_ON_SHOW:
-			self->priv->select_on_show = g_value_get_boolean (value);
+			completion->priv->select_on_show = g_value_get_boolean (value);
 			break;
 		default:
 			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -1208,13 +1163,15 @@
 	object_class->get_property = gtk_source_completion_get_property;
 	object_class->set_property = gtk_source_completion_set_property;
 	object_class->finalize = gtk_source_completion_finalize;
+	
 	gtkobject_class->destroy = gtk_source_completion_destroy;
-	widget_class->show = gtk_source_completion_show_or_update;
+	
+	widget_class->show = gtk_source_completion_show;
 	widget_class->hide = gtk_source_completion_hide;
 	widget_class->realize = gtk_source_completion_realize;
 	widget_class->configure_event = gtk_source_completion_configure_event;
-	klass->display_info = gtk_source_completion_display_info_default;
-	klass->proposal_selected = gtk_source_completion_proposal_selected_default;
+
+	klass->proposal_activated = gtk_source_completion_proposal_activated_default;
 	
 	/**
 	 * GtkSourceCompletion:manage-completion-keys:
@@ -1228,7 +1185,7 @@
 							      _("Manage Up, Down etc. keys when the completion is visible"),
 							      _("Manage Up, Down etc. keys when the completion is visible"),
 							      TRUE,
-							      G_PARAM_READWRITE));
+							      G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
 	/**
 	 * GtkSourceCompletion:remember-info-visibility:
 	 *
@@ -1241,7 +1198,7 @@
 							      _("Remember the last info state (visible or hidden)"),
 							      _("Remember the last info state (visible or hidden)"),
 							      FALSE,
-							      G_PARAM_READWRITE));
+							      G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
 	/**
 	 * GtkSourceCompletion:select-on-show:
 	 *
@@ -1254,7 +1211,7 @@
 							      _("Completion mark as selected the first proposal on show"),
 							      _("Completion mark as selected the first proposal on show"),
 							      FALSE,
-							      G_PARAM_READWRITE));
+							      G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
 	
 	/**
 	 * GtkSourceCompletion::proposal-selected:
@@ -1263,40 +1220,30 @@
 	 *
 	 * When the user selects a proposal
 	 **/
-	signals[PROPOSAL_SELECTED] =
-		g_signal_new ("proposal-selected",
-			      G_TYPE_FROM_CLASS (klass),
-			      G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
-			      G_STRUCT_OFFSET (GtkSourceCompletionClass, proposal_selected),
-			      g_signal_accumulator_true_handled, 
-			      NULL,
-			      _gtksourceview_marshal_BOOLEAN__POINTER, 
-			      G_TYPE_BOOLEAN,
-			      1,
-			      GTK_TYPE_POINTER);
-	
-	/**
-	 * GtkSourceCompletion::display-info:
-	 * @completion: The #GtkSourceCompletion who emits the signal
-	 * @proposal: The #GtkSourceCompletionProposal the user wants to see the information
-	 *
-	 * When the user want to see the information of a proposal
-	 **/	      
-	signals[DISPLAY_INFO] =
-		g_signal_new ("display-info",
+	signals[PROPOSAL_ACTIVATED] =
+		g_signal_new ("proposal-activated",
 			      G_TYPE_FROM_CLASS (klass),
 			      G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
-			      G_STRUCT_OFFSET (GtkSourceCompletionClass, display_info),
+			      G_STRUCT_OFFSET (GtkSourceCompletionClass, proposal_activated),
 			      g_signal_accumulator_true_handled, 
 			      NULL,
-			      _gtksourceview_marshal_BOOLEAN__POINTER,
+			      _gtksourceview_marshal_BOOLEAN__OBJECT, 
 			      G_TYPE_BOOLEAN,
 			      1,
-			      GTK_TYPE_POINTER);
+			      G_TYPE_OBJECT);
+}
+
+static void
+update_transient_for_info (GtkSourceCompletion *completion,
+                           GParamSpec          *spec)
+{
+	gtk_window_set_transient_for (GTK_WINDOW (completion->priv->info_window),
+				      gtk_window_get_transient_for (GTK_WINDOW (completion)));
+
 }
 
 static void
-gtk_source_completion_init (GtkSourceCompletion *self)
+initialize_ui (GtkSourceCompletion *completion)
 {
 	GtkWidget *info_icon;
 	GtkWidget *info_button;
@@ -1304,36 +1251,26 @@
 	GtkWidget *prev_page_icon;
 	GtkWidget *vbox;
 
-	self->priv = GTK_SOURCE_COMPLETION_GET_PRIVATE (self);
-	self->priv->destroy_has_run = FALSE;
-	self->priv->active_trigger = NULL;
-	self->priv->manage_keys = TRUE;
-	self->priv->remember_info_visibility = FALSE;
-	self->priv->info_visible = FALSE;
-	self->priv->select_on_show = FALSE;
-
-	gtk_window_set_type_hint (GTK_WINDOW (self),
-				  GDK_WINDOW_TYPE_HINT_NORMAL);
-	gtk_window_set_focus_on_map (GTK_WINDOW (self), FALSE);
-	gtk_widget_set_size_request (GTK_WIDGET (self),
-				     WINDOW_WIDTH,WINDOW_HEIGHT);
-	gtk_window_set_decorated (GTK_WINDOW (self), FALSE);
-	
-	/*Notebook*/
-	self->priv->notebook = gtk_notebook_new ();
-	gtk_widget_show (self->priv->notebook);
-	g_object_set (G_OBJECT (self->priv->notebook), "can-focus",
-		      FALSE, NULL);
-	gtk_notebook_set_show_tabs (GTK_NOTEBOOK (self->priv->notebook), FALSE);
-	gtk_notebook_set_show_border (GTK_NOTEBOOK (self->priv->notebook),
-				      FALSE);
-	
-	/* Add default page */
-	self->priv->active_page = gtk_source_completion_page_new (self, DEFAULT_PAGE);
-	
-	/*Icon list*/
-	info_icon = gtk_image_new_from_stock (GTK_STOCK_INFO,
-					      GTK_ICON_SIZE_SMALL_TOOLBAR);
+	gtk_window_set_type_hint (GTK_WINDOW (completion), GDK_WINDOW_TYPE_HINT_NORMAL);
+	gtk_window_set_focus_on_map (GTK_WINDOW (completion), FALSE);
+	gtk_widget_set_size_request (GTK_WIDGET (completion), WINDOW_WIDTH, WINDOW_HEIGHT);
+	gtk_window_set_decorated (GTK_WINDOW (completion), FALSE);
+
+	/* Notebook */
+	completion->priv->notebook = gtk_notebook_new ();
+	gtk_widget_show (completion->priv->notebook);
+
+	g_object_set (G_OBJECT (completion->priv->notebook), "can-focus", FALSE, NULL);
+
+	gtk_notebook_set_show_tabs (GTK_NOTEBOOK (completion->priv->notebook), FALSE);
+	gtk_notebook_set_show_border (GTK_NOTEBOOK (completion->priv->notebook), FALSE);
+
+	/* Bottom bar */
+	completion->priv->bottom_bar = gtk_hbox_new (FALSE, 1);
+	gtk_widget_show (completion->priv->bottom_bar);
+
+	/* Info button */
+	info_icon = gtk_image_new_from_stock (GTK_STOCK_INFO, GTK_ICON_SIZE_MENU);
 	gtk_widget_show (info_icon);
 	gtk_widget_set_tooltip_text (info_icon, _("Show Proposal Info"));
 	
@@ -1341,180 +1278,208 @@
 	gtk_widget_show (info_button);
 	g_object_set (G_OBJECT (info_button), "can-focus", FALSE, NULL);
 	
-	self->priv->info_button = info_button;
 	gtk_button_set_focus_on_click (GTK_BUTTON (info_button), FALSE);
 	gtk_container_add (GTK_CONTAINER (info_button), info_icon);
 	g_signal_connect (G_OBJECT (info_button),
 			  "toggled",
 			  G_CALLBACK (info_toggled_cb),
-			  self);
+			  completion);
 
-	self->priv->bottom_bar = gtk_hbox_new (FALSE, 1);
-	gtk_widget_show (self->priv->bottom_bar);
-	gtk_box_pack_start (GTK_BOX (self->priv->bottom_bar), info_button,
-			    FALSE, FALSE, 0);
+	completion->priv->info_button = info_button;
 
-	/*Next/Previous page buttons*/
-	
+	gtk_box_pack_start (GTK_BOX (completion->priv->bottom_bar), 
+	                    info_button,
+	                    FALSE, 
+	                    FALSE, 
+	                    0);
+
+	/* Next/Previous page buttons */
 	next_page_icon = gtk_image_new_from_stock (GTK_STOCK_GO_FORWARD,
-						   GTK_ICON_SIZE_SMALL_TOOLBAR);
+						   GTK_ICON_SIZE_MENU);
 	gtk_widget_show (next_page_icon);
+
 	prev_page_icon = gtk_image_new_from_stock (GTK_STOCK_GO_BACK,
-						   GTK_ICON_SIZE_SMALL_TOOLBAR);
+						   GTK_ICON_SIZE_MENU);
 	gtk_widget_show (prev_page_icon);
 	
-	self->priv->next_page_button = gtk_button_new ();
-	gtk_widget_show (self->priv->next_page_button);
-	g_object_set (G_OBJECT (self->priv->next_page_button),
+	completion->priv->next_page_button = gtk_button_new ();
+	gtk_widget_show (completion->priv->next_page_button);
+	g_object_set (G_OBJECT (completion->priv->next_page_button),
 		      "can-focus", FALSE,
 		      "focus-on-click", FALSE,
 		      NULL);
-	gtk_widget_set_tooltip_text (self->priv->next_page_button,
-				     _("Next page"));
-	gtk_container_add (GTK_CONTAINER (self->priv->next_page_button),
-			   next_page_icon);
-	g_signal_connect (G_OBJECT (self->priv->next_page_button),
+
+	gtk_widget_set_tooltip_text (completion->priv->next_page_button, _("Next page"));
+	gtk_container_add (GTK_CONTAINER (completion->priv->next_page_button), next_page_icon);
+	g_signal_connect (G_OBJECT (completion->priv->next_page_button),
 			  "clicked",
 			  G_CALLBACK (next_page_cb),
-			  self);
+			  completion);
 	
-	self->priv->prev_page_button = gtk_button_new ();
-	gtk_widget_show (self->priv->prev_page_button);
-	g_object_set (G_OBJECT (self->priv->prev_page_button),
+	completion->priv->prev_page_button = gtk_button_new ();
+	gtk_widget_show (completion->priv->prev_page_button);
+	g_object_set (G_OBJECT (completion->priv->prev_page_button),
 		      "can-focus", FALSE,
 		      "focus-on-click", FALSE,
 		      NULL);
-	gtk_widget_set_tooltip_text (self->priv->prev_page_button,
-				     _("Previous page"));
-	gtk_container_add (GTK_CONTAINER (self->priv->prev_page_button),
-			   prev_page_icon);
-	g_signal_connect (G_OBJECT (self->priv->prev_page_button),
+
+	gtk_widget_set_tooltip_text (completion->priv->prev_page_button, _("Previous page"));
+	gtk_container_add (GTK_CONTAINER (completion->priv->prev_page_button), prev_page_icon);
+	g_signal_connect (G_OBJECT (completion->priv->prev_page_button),
 			  "clicked",
 			  G_CALLBACK (prev_page_cb),
-			  self);
+			  completion);
 
-	gtk_box_pack_end (GTK_BOX (self->priv->bottom_bar),
-			  self->priv->next_page_button,
+	gtk_box_pack_end (GTK_BOX (completion->priv->bottom_bar),
+			  completion->priv->next_page_button,
 			  FALSE, FALSE, 1);
-	gtk_box_pack_end (GTK_BOX (self->priv->bottom_bar),
-			  self->priv->prev_page_button,
+
+	gtk_box_pack_end (GTK_BOX (completion->priv->bottom_bar),
+			  completion->priv->prev_page_button,
 			  FALSE, FALSE, 1);
-	/*Page label*/
-	self->priv->tab_label = gtk_label_new (DEFAULT_PAGE);
-	gtk_widget_show (self->priv->tab_label);
-	gtk_box_pack_end (GTK_BOX (self->priv->bottom_bar),
-			  self->priv->tab_label,
-			  FALSE, TRUE, 10);
+	/* Page label */
+	completion->priv->tab_label = gtk_label_new (NULL);
+	gtk_widget_show (completion->priv->tab_label);
+	gtk_box_pack_end (GTK_BOX (completion->priv->bottom_bar),
+			  completion->priv->tab_label,
+			  FALSE, 
+			  TRUE, 
+			  10);
 	
-	/*Main vbox*/
+	/* Main vbox */
 	vbox = gtk_vbox_new (FALSE, 1);
 	gtk_widget_show (vbox);
-	gtk_box_pack_start (GTK_BOX (vbox), self->priv->notebook,
-			    TRUE, TRUE, 0);
-
-	gtk_box_pack_end (GTK_BOX (vbox), self->priv->bottom_bar,
-			  FALSE, FALSE, 0);
-
-	gtk_container_add (GTK_CONTAINER (self), vbox);
-
-	/*Info window*/
-	self->priv->info_window = GTK_WIDGET (gtk_source_completion_info_new ());
+	gtk_box_pack_start (GTK_BOX (vbox), 
+	                    completion->priv->notebook,
+	                    TRUE,
+	                    TRUE, 
+	                    0);
+
+	gtk_box_pack_end (GTK_BOX (vbox), 
+	                  completion->priv->bottom_bar,
+	                  FALSE, 
+	                  FALSE, 
+	                  0);
+
+	gtk_container_add (GTK_CONTAINER (completion), vbox);
+
+	/* Info window */
+	completion->priv->info_window = GTK_WIDGET (gtk_source_completion_info_new ());
+	g_signal_connect (completion, 
+	                  "notify::transient-for",
+	                  G_CALLBACK (update_transient_for_info),
+	                  NULL);
+
+	/* Default info widget */
+	completion->priv->default_info = gtk_label_new (NULL);
+	
+	gtk_misc_set_alignment (GTK_MISC (completion->priv->default_info), 0, 0.5);
+	gtk_label_set_selectable (GTK_LABEL (completion->priv->default_info), TRUE);
+	gtk_widget_show (completion->priv->default_info);
+	
+	gtk_source_completion_info_set_widget (GTK_SOURCE_COMPLETION_INFO (completion->priv->info_window), 
+	                                       completion->priv->default_info);
 
 	/* Connect signals */
-			
-	g_signal_connect (self->priv->notebook, 
+	g_signal_connect (completion->priv->notebook, 
 			  "switch-page",
 			  G_CALLBACK (switch_page_cb),
-			  self);
+			  completion);
 			
-	g_signal_connect (self,
+	g_signal_connect (completion,
 			  "delete-event",
-			  G_CALLBACK (gtk_source_completion_delete_event_cb),
+			  G_CALLBACK (gtk_widget_hide_on_delete),
 			  NULL);
 
-	g_signal_connect (self->priv->info_window,
-			  "show-info",
+	g_signal_connect (completion->priv->info_window,
+			  "before-show",
 			  G_CALLBACK (show_info_cb),
-			  self);
+			  completion);
+
+	g_signal_connect (completion->priv->info_window,
+			  "show",
+			  G_CALLBACK (show_info_after_cb),
+			  completion);
 			  
-	g_signal_connect (self->priv->info_window,
+	g_signal_connect (completion->priv->info_window,
 			  "hide",
 			  G_CALLBACK (hide_info_cb),
-			  self);
+			  completion);
+			  
+	/* Add default page */
+	completion->priv->active_page = gtk_source_completion_add_page (completion, _("Default"));
+}
+
+static void
+gtk_source_completion_init (GtkSourceCompletion *completion)
+{
+	completion->priv = GTK_SOURCE_COMPLETION_GET_PRIVATE (completion);
+
+	completion->priv->triggers = g_hash_table_new (g_direct_hash,
+	                                               g_direct_equal);
+
+	initialize_ui (completion);
+}
+
+static void
+add_proposals (GtkSourceCompletion         *completion,
+               GtkSourceCompletionProvider *provider,
+               GtkSourceCompletionTrigger  *trigger)
+{
+	GList *proposals;
+	GList *item;
+	GtkSourceCompletionPage *page;
+	GtkSourceCompletionProposal *proposal;
 
-	self->priv->triggers = NULL;
-	self->priv->prov_trig = NULL;
+	proposals = gtk_source_completion_provider_get_proposals (provider, trigger);
+	
+	for (item = proposals; item; item = g_list_next (item))
+	{
+		if (GTK_IS_SOURCE_COMPLETION_PROPOSAL (item->data))
+		{
+			proposal = GTK_SOURCE_COMPLETION_PROPOSAL (item->data);
+			page = gtk_source_completion_provider_get_page (provider, proposal);
+			
+			add_proposal (completion, provider, proposal, page);
+		}
+	}
+	
+	g_list_free (proposals);
 }
 
 static void
 trigger_activate_cb (GtkSourceCompletionTrigger *trigger,
-		     GtkSourceCompletion *self)
+		     GtkSourceCompletion        *completion)
 {
 	GList *l;
-	GList *data_list;
-	GList *final_list = NULL;
-	GtkSourceCompletionProposal *last_proposal = NULL;
 	gint x, y;
 
-	g_return_if_fail (GTK_IS_SOURCE_COMPLETION (self));
+	g_return_if_fail (GTK_IS_SOURCE_COMPLETION (completion));
 	g_return_if_fail (GTK_IS_SOURCE_COMPLETION_TRIGGER (trigger));
 	
 	/*
 	 * If the completion is visble and there is a trigger active, you cannot
-	 * raise a different trigger until the current trigger finish o_O
+	 * raise a different trigger until the current trigger finished
 	 */
-	if (GTK_WIDGET_VISIBLE (self)
-	    && self->priv->active_trigger != trigger)
+	if (GTK_WIDGET_VISIBLE (completion) && completion->priv->active_trigger != trigger)
 	{
 		return;
 	}
 	
-	end_completion (self);
-	gtk_source_completion_clear (self);
+	/* End any ongoing completion */
+	gtk_source_completion_finish (completion);
+	gtk_source_completion_clear (completion);
 	
-	for (l = self->priv->prov_trig; l != NULL; l = g_list_next (l))
-	{
-		PTPair *ptp = (PTPair *)l->data;
-		
-		if (ptp->trigger == trigger)
-		{
-			data_list = gtk_source_completion_provider_get_proposals (ptp->provider,
-										  trigger);
-			if (data_list != NULL)
-			{
-				final_list = g_list_concat (final_list,
-							    data_list);
-			}
-		}
-	}
+	/* Collect all the proposals */
+	l = g_hash_table_lookup (completion->priv->triggers, trigger);
 	
-	if (final_list == NULL)
+	while (l != NULL)
 	{
-		if (GTK_WIDGET_VISIBLE (self))
-			end_completion (self);
-		return;
+		add_proposals (completion, GTK_SOURCE_COMPLETION_PROVIDER (l->data), trigger);
+		l = g_list_next (l);
 	}
 	
-	data_list = final_list;
-	/* Insert the data into the model */
-	do
-	{
-		GtkSourceCompletionPage *page;
-		
-		last_proposal = GTK_SOURCE_COMPLETION_PROPOSAL (data_list->data);
-		
-		/* FIXME: do something about the page */
-		/*page = get_page_by_name (self,
-					 gtk_source_completion_proposal_get_page_name (last_proposal));*/
-		page = get_page_by_name (self, DEFAULT_PAGE);
-		
-		add_proposal (page,
-			      last_proposal);
-	} while ((data_list = g_list_next (data_list)) != NULL);
-	
-	g_list_free (final_list);
-	
-	if (!GTK_WIDGET_HAS_FOCUS (self->priv->view))
+	if (!GTK_WIDGET_HAS_FOCUS (completion->priv->view))
 		return;
 	
 	/*
@@ -1522,25 +1487,21 @@
 	 *add a new "position-type": cursor, center_screen,
 	 *center_window, custom etc.
 	 */
-	gtk_source_completion_utils_get_pos_at_cursor (GTK_WINDOW (self),
-						       GTK_SOURCE_VIEW (self->priv->view),
+	gtk_source_completion_utils_get_pos_at_cursor (GTK_WINDOW (completion),
+						       GTK_SOURCE_VIEW (completion->priv->view),
 						       &x, &y, NULL);
 
-	gtk_window_move (GTK_WINDOW (self),
-			 x, y);
+	gtk_window_move (GTK_WINDOW (completion), x, y);
 	
-	/*
-	* We must call to gtk_widget_show and not to gsc_completion_show_or_update
-	* because if we don't call to gtk_widget_show, the show signal is not emitted
-	*/
-	gtk_widget_show (GTK_WIDGET (self));
-
-	gtk_widget_grab_focus (GTK_WIDGET (self->priv->view));
+	gtk_widget_show (GTK_WIDGET (completion));
+	gtk_widget_grab_focus (GTK_WIDGET (completion->priv->view));
 
-	self->priv->active_trigger = trigger;
+	completion->priv->active_trigger = trigger;
 	
-	if (self->priv->select_on_show)
-		select_first_proposal (self->priv->active_page);
+	if (completion->priv->select_on_show)
+	{
+		select_first_proposal (completion);
+	}
 }
 
 /**
@@ -1551,69 +1512,31 @@
 GtkSourceCompletion *
 _gtk_source_completion_new (GtkTextView *view)
 {
-	GtkSourceCompletion *self = GTK_SOURCE_COMPLETION (g_object_new (GTK_TYPE_SOURCE_COMPLETION,
+	GtkSourceCompletion *completion = GTK_SOURCE_COMPLETION (g_object_new (GTK_TYPE_SOURCE_COMPLETION,
 									 "type", GTK_WINDOW_POPUP,
 									 NULL));
-	self->priv->view = view;
+	completion->priv->view = g_object_ref (view);
 	
-	self->priv->signals_ids[TEXT_VIEW_FOCUS_OUT] = 
-		g_signal_connect (self->priv->view,
+	completion->priv->signals_ids[TEXT_VIEW_FOCUS_OUT] = 
+		g_signal_connect (completion->priv->view,
 				  "focus-out-event",
 				  G_CALLBACK (view_focus_out_event_cb),
-				  self);
+				  completion);
 	
-	self->priv->signals_ids[TEXT_VIEW_BUTTON_PRESS] =
-		g_signal_connect (self->priv->view,
+	completion->priv->signals_ids[TEXT_VIEW_BUTTON_PRESS] =
+		g_signal_connect (completion->priv->view,
 				  "button-press-event",
 				  G_CALLBACK (view_button_press_event_cb),
-				  self);
-	
-	set_manage_keys (self);
-	
-	return self;
-}
-
-/**
- * gtk_source_completion_add_trigger:
- * @self: The #GtkSourceCompletion
- * @trigger: The trigger to register
- *
- * This function register a completion trigger. If the completion is actived
- * then this method activate the trigger. This function reference the trigger
- * object
- *
- * Returns: %TRUE if the trigger has been registered
- */
-gboolean
-gtk_source_completion_add_trigger (GtkSourceCompletion *self,
-				   GtkSourceCompletionTrigger *trigger)
-{
-	GList *l;
-	
-	g_return_val_if_fail (GTK_IS_SOURCE_COMPLETION (self), FALSE);
+				  completion);
 	
-	l = g_list_find (self->priv->triggers, trigger);
-	/*Only register the trigger if it has not been registered yet*/
-	if (l == NULL)
-	{
-	
-		self->priv->triggers = g_list_append (self->priv->triggers,
-						      trigger);
-		g_object_ref (trigger);
-		
-		g_signal_connect (trigger, "activate",
-				  G_CALLBACK (trigger_activate_cb),
-				  self);
-		
-		return TRUE;
-	}
+	set_manage_keys (completion);
 	
-	return FALSE;
+	return completion;
 }
 
 /**
  * gtk_source_completion_add_provider:
- * @self: the #GtkSourceCompletion
+ * @completion: the #GtkSourceCompletion
  * @provider: The #GtkSourceCompletionProvider.
  * @trigger: The trigger name what you want to register this provider
  *
@@ -1626,122 +1549,86 @@
  * or the trigger doesn't exists)
  **/
 gboolean
-gtk_source_completion_add_provider (GtkSourceCompletion *self,
+gtk_source_completion_add_provider (GtkSourceCompletion         *completion,
 				    GtkSourceCompletionProvider *provider,
-				    GtkSourceCompletionTrigger *trigger)
+				    GtkSourceCompletionTrigger  *trigger)
 {
-	PTPair *ptp;
-	GList *l;
+	GList *providers = NULL;
+	gboolean found;
 	
-	g_return_val_if_fail (GTK_IS_SOURCE_COMPLETION (self), FALSE);
+	g_return_val_if_fail (GTK_IS_SOURCE_COMPLETION (completion), FALSE);
 	g_return_val_if_fail (GTK_IS_SOURCE_COMPLETION_PROVIDER (provider), FALSE);
 	g_return_val_if_fail (GTK_IS_SOURCE_COMPLETION_TRIGGER (trigger), FALSE);
-	g_return_val_if_fail (g_list_find (self->priv->triggers, trigger) != NULL,
-			      FALSE);
+	
+	/* Check if provider/trigger is already registered */
+	found = g_hash_table_lookup_extended (completion->priv->triggers, 
+	                                      trigger,
+	                                      NULL,
+	                                      (gpointer *)&providers);
 
-	/*Check if the provider-trigger pair has been registered*/
-	for (l = self->priv->prov_trig; l != NULL; l = g_list_next (l))
+	if (g_list_find (providers, provider) != NULL)
 	{
-		ptp = (PTPair *)l->data;
-		if (ptp->trigger == trigger && ptp->provider == provider)
-			return FALSE;
+		return FALSE;
 	}
 
-	ptp = g_slice_new (PTPair);
-	ptp->provider = provider;
-	ptp->trigger = trigger;
-	self->priv->prov_trig = g_list_append (self->priv->prov_trig, ptp);
-	
-	g_object_ref (provider);
-
-	return TRUE;
-}
-
-/**
- * gtk_source_completion_remove_trigger:
- * @self: The #GtkSourceCompletion
- * @trigger: The trigger to unregister
- *
- * This function unregister a completion trigger. If the completion is actived
- * then this method deactivate the trigger. This function unreference the trigger
- * object
- *
- * Returns: %TRUE if the trigger has been unregistered or %FALSE if not (because
- * the trigger has not been registered)
- */
-gboolean
-gtk_source_completion_remove_trigger (GtkSourceCompletion *self,
-				      GtkSourceCompletionTrigger *trigger)
-{
-	GList *l;
-	
-	g_return_val_if_fail (GTK_IS_SOURCE_COMPLETION (self), FALSE);
-	g_return_val_if_fail (g_list_find (self->priv->triggers, trigger) != NULL,
-			      FALSE);
-	
-	self->priv->triggers = g_list_remove (self->priv->triggers, trigger);
-	
-	for (l = self->priv->prov_trig; l != NULL; l = g_list_next (l))
+	if (!found)
 	{
-		PTPair *ptp = (PTPair *)l->data;
-		
-		if (ptp->trigger == trigger)
-		{
-			free_pair (ptp);
-			self->priv->prov_trig = g_list_remove_link (self->priv->prov_trig, l);
-			//TODO we need start the list again
-		}
-	}
+		g_object_ref (trigger);
 
-	g_signal_handlers_disconnect_by_func (trigger, trigger_activate_cb,
-					      self);
-	g_object_unref (trigger);
+		g_signal_connect (trigger, 
+		                  "activate", 
+		                  G_CALLBACK (trigger_activate_cb), 
+		                  completion);
+	}
 	
+	providers = g_list_prepend (providers, g_object_ref (provider));
+	g_hash_table_insert (completion->priv->triggers, trigger, providers);
+
 	return TRUE;
 }
 
 /**
  * gtk_source_completion_remove_provider:
- * @self: the #GtkSourceCompletion
+ * @completion: the #GtkSourceCompletion
  * @provider: The #GtkSourceCompletionProvider.
  * @trigger: The trigger what you want to unregister this provider
  *
  * This function unregister the provider.
  * 
- * Returns: %TRUE if it was unregistered or %FALSE if not (because it doesn't exists,
- * or the trigger don't exists)
+ * Returns: %TRUE if @provider was unregistered for @trigger, or %FALSE 
+ *          otherwise
  **/
 gboolean
-gtk_source_completion_remove_provider (GtkSourceCompletion *self,
+gtk_source_completion_remove_provider (GtkSourceCompletion         *completion,
 				       GtkSourceCompletionProvider *provider,
-				       GtkSourceCompletionTrigger *trigger)
+				       GtkSourceCompletionTrigger  *trigger)
 {
-	GList *l;
-	gboolean ret = FALSE;
+	GList *providers = NULL;
+	GList *item;
 	
-	g_return_val_if_fail (GTK_IS_SOURCE_COMPLETION (self), FALSE);
-	g_return_val_if_fail (g_list_find (self->priv->triggers, trigger) != NULL,
-			      FALSE);
+	g_return_val_if_fail (GTK_IS_SOURCE_COMPLETION (completion), FALSE);
+	g_return_val_if_fail (GTK_IS_SOURCE_COMPLETION_PROVIDER (provider), FALSE);
+	g_return_val_if_fail (GTK_IS_SOURCE_COMPLETION_TRIGGER (trigger), FALSE);
 	
-	for (l = self->priv->prov_trig; l != NULL; l = g_list_next (l))
+	providers = g_hash_table_lookup (completion->priv->triggers, trigger);
+	item = g_list_find (providers, provider);
+
+	if (item != NULL)
 	{
-		PTPair *ptp = (PTPair *)l->data;
-		
-		if (ptp->provider == provider)
-		{
-			free_pair (ptp);
-			self->priv->prov_trig = g_list_remove_link (self->priv->prov_trig, l);
-			//TODO we need start the list again
-			ret = TRUE;
-		}
+		providers = g_list_remove_link (providers, item);
+		g_hash_table_insert (completion->priv->triggers, trigger, providers);
+
+		return TRUE;
+	}
+	else
+	{		
+		return FALSE;
 	}
-		
-	return ret;
 }
 
 /**
  * gtk_source_completion_get_active_trigger:
- * @self: The #GtkSourceCompletion
+ * @completion: The #GtkSourceCompletion
  *
  * This function return the active trigger. The active trigger is the last
  * trigger raised if the completion is active. If the completion is not visible then
@@ -1750,48 +1637,46 @@
  * Returns: The trigger or NULL if completion is not active
  */
 GtkSourceCompletionTrigger*
-gtk_source_completion_get_active_trigger (GtkSourceCompletion *self)
+gtk_source_completion_get_active_trigger (GtkSourceCompletion *completion)
 {
-	g_return_val_if_fail (GTK_IS_SOURCE_COMPLETION (self), NULL);
+	g_return_val_if_fail (GTK_IS_SOURCE_COMPLETION (completion), NULL);
 
-	return self->priv->active_trigger;
+	return completion->priv->active_trigger;
 }
 
 
 /**
  * gtk_source_completion_get_view:
- * @self: The #GtkSourceCompletion
+ * @completion: The #GtkSourceCompletion
  *
  * Returns: The view associated with this completion.
  */
 GtkTextView*
-gtk_source_completion_get_view (GtkSourceCompletion *self)
+gtk_source_completion_get_view (GtkSourceCompletion *completion)
 {
-	g_return_val_if_fail (GTK_SOURCE_COMPLETION (self), NULL);
+	g_return_val_if_fail (GTK_SOURCE_COMPLETION (completion), NULL);
 	
-	return self->priv->view;
+	return completion->priv->view;
 }
 
 /**
  * gtk_source_completion_finish:
- * @self: a #GtkSourceCompletion
+ * @completion: a #GtkSourceCompletion
  * 
  * Finishes the completion if it is active (visible).
  */
 void
-gtk_source_completion_finish (GtkSourceCompletion *self)
+gtk_source_completion_finish (GtkSourceCompletion *completion)
 {
-	g_return_if_fail (GTK_IS_SOURCE_COMPLETION (self));
+	g_return_if_fail (GTK_IS_SOURCE_COMPLETION (completion));
 	
-	if (GTK_WIDGET_VISIBLE (self))
-	{
-		end_completion (self);
-	}
+	/* Hiding the completion window will trigger the actual finish */
+	gtk_widget_hide (GTK_WIDGET (completion));
 }
 
 /**
  * gtk_source_completion_filter_proposals:
- * @self: the #GtkSourceCompletion
+ * @completion: the #GtkSourceCompletion
  * @func: function to filter the proposals visibility
  * @user_data: user data to pass to func
  *
@@ -1801,57 +1686,43 @@
  * 
  **/
 void
-gtk_source_completion_filter_proposals (GtkSourceCompletion *self,
+gtk_source_completion_filter_proposals (GtkSourceCompletion *completion,
 					GtkSourceCompletionFilterFunc func,
 					gpointer user_data)
 {
 	GList *l;
 	
-	g_return_if_fail (GTK_IS_SOURCE_COMPLETION (self));
+	g_return_if_fail (GTK_IS_SOURCE_COMPLETION (completion));
 	g_return_if_fail (func);
 	
-	if (!GTK_WIDGET_VISIBLE (self))
+	if (!GTK_WIDGET_VISIBLE (completion))
 		return;
 	
-	for (l = self->priv->pages; l != NULL; l = g_list_next (l))
+	for (l = completion->priv->pages; l != NULL; l = g_list_next (l))
 	{
 		GtkSourceCompletionPage *page = (GtkSourceCompletionPage *)l->data;
-		if (get_num_proposals (page) > 0)
+		if (page_has_proposals (page))
 		{
 			filter_visible (page,
-					(GtkSourceCompletionFilterFunc) func,
+					func,
 					user_data);
 		}
 	}
 
-	if (!update_pages_visibility (self))
+	if (!update_pages_visibility (completion))
 	{
-		end_completion (self);
+		gtk_source_completion_finish (completion);
 	}
 	else
 	{
-		if (self->priv->select_on_show)
-			select_first_proposal (self->priv->active_page);
+		if (completion->priv->select_on_show)
+			select_first_proposal (completion);
 	}
 }
 
 /**
- * gtk_source_completion_get_bottom_bar:
- * @self: The #GtkSourceCompletion
- *
- * The bottom bar is the widgetwith the info button, the page name etc.
- *
- * Returns: The bottom bar widget (it is a #GtkBox by now)
- */
-GtkWidget*
-gtk_source_completion_get_bottom_bar (GtkSourceCompletion *self)
-{
-	return self->priv->bottom_bar;
-}
-
-/**
  * gtk_source_completion_get_info_widget:
- * @self: The #GtkSourceCompletion
+ * @completion: The #GtkSourceCompletion
  *
  * The info widget is the window where the completion shows the
  * proposal info or help. DO NOT USE IT (only to connect to some signal
@@ -1860,151 +1731,54 @@
  * Returns: The internal #GtkSourceCompletionInfo widget.
  */
 GtkSourceCompletionInfo *
-gtk_source_completion_get_info_widget (GtkSourceCompletion *self)
+gtk_source_completion_get_info_window (GtkSourceCompletion *completion)
 {
-	return GTK_SOURCE_COMPLETION_INFO (self->priv->info_window);
+	return GTK_SOURCE_COMPLETION_INFO (completion->priv->info_window);
 }
 
-/**
- * gtk_source_completion_get_trigger:
- * @self: The #GtkSourceCompletion
- * @trigger_name: The trigger name to find
- *
- * Returns: The #GtkSourceCompletionTrigger registered with @trigger_name, %NULL if it cannot
- * be found
- */
-GtkSourceCompletionTrigger*
-gtk_source_completion_get_trigger (GtkSourceCompletion *self,
-				   const gchar *trigger_name)
+GtkSourceCompletionPage *
+gtk_source_completion_add_page (GtkSourceCompletion *completion,
+                                const gchar         *label)
 {
-
-	GList *l;
-	GtkSourceCompletionTrigger *trigger;
+	GtkSourceCompletionPage *page;
 	
-	g_return_val_if_fail (GTK_IS_SOURCE_COMPLETION (self), NULL);
-
-	for (l = self->priv->triggers; l != NULL; l = g_list_next (l))
-	{
-		trigger =  GTK_SOURCE_COMPLETION_TRIGGER (l->data);
-		
-		if (g_strcmp0 (gtk_source_completion_trigger_get_name (trigger), trigger_name) == 0)
-			return trigger;
-	}
+	g_return_val_if_fail (GTK_IS_SOURCE_COMPLETION (completion), NULL);
+	g_return_val_if_fail (label != NULL, NULL);
 	
-	return NULL;
-}
+	page = gtk_source_completion_page_new (completion, label);
 
-/**
- * gtk_source_completion_get_provider:
- * @self: The #GtkSourceCompletion
- * @prov_name: The provider name to find
- *
- * Returns: The #GtkSourceCompletionProvider registered with @prov_name
- */
-GtkSourceCompletionProvider*
-gtk_source_completion_get_provider (GtkSourceCompletion *self,
-				    const gchar *prov_name)
-{
-
-	GList *l;
+	completion->priv->pages = g_list_append (completion->priv->pages, page);
 	
-	g_return_val_if_fail (GTK_IS_SOURCE_COMPLETION (self), NULL);
+	gtk_notebook_append_page (GTK_NOTEBOOK (completion->priv->notebook),
+				  GTK_WIDGET (page->scroll),
+				  gtk_label_new (page->label));
 
-	for (l = self->priv->prov_trig; l != NULL; l = g_list_next (l))
-	{
-		PTPair *ptp = (PTPair *)l->data;
-		if (g_strcmp0 (gtk_source_completion_provider_get_name (ptp->provider), prov_name) == 0)
-			return ptp->provider;
-	}
-		
-	return NULL;
+	return page;
 }
 
-/**
- * gtk_source_completion_get_page_pos:
- * @self: The #GtkSourceCompletion
- * @page_name: The page name to search
- *
- * Search the page position with the given name
- *
- * Returns: the page position or -1 if it is not found
- */
-gint
-gtk_source_completion_get_page_pos (GtkSourceCompletion *self,
-				    const gchar *page_name)
+gboolean
+gtk_source_completion_remove_page (GtkSourceCompletion     *completion,
+                                   GtkSourceCompletionPage *page)
 {
-	GList *l;
-	gint pos = 0;
-	
-	g_return_val_if_fail (GTK_IS_SOURCE_COMPLETION (self), -1);
-	
-	for (l = self->priv->pages; l != NULL; l = g_list_next (l))
-	{
-		GtkSourceCompletionPage *page = (GtkSourceCompletionPage *)l->data;
-		if (g_strcmp0 (page_name, page->name) == 0)
-			return pos;
-		
-		pos++;
-	}
+	gint idx;
+	GList *item;
 	
-	return -1;
-}
-
-/**
- * gtk_source_completion_get_n_pages:
- * @self: The #GtkSourceCompletion
- * 
- * Returns: The number of pages
- */
-gint
-gtk_source_completion_get_n_pages (GtkSourceCompletion *self)
-{
-	g_return_val_if_fail (GTK_IS_SOURCE_COMPLETION (self), -1);
+	g_return_val_if_fail (GTK_IS_SOURCE_COMPLETION (completion), FALSE);
+	g_return_val_if_fail (page != NULL, FALSE);
 	
-	return g_list_length (self->priv->pages);
-}
-
-/**
- * gtk_source_completion_set_page_pos:
- * @self: The #GtkSourceCompletion
- * @page_name: The page name you want to set the position (stating by 1 because 
- * 0 is the default page)
- * @position: The new position of the page. If this is negative, or is larger
- * than the number of elements in the list, the new element is added on to
- * the end of the list
- * 
- */
-void
-gtk_source_completion_set_page_pos (GtkSourceCompletion *self,
-				    const gchar *page_name,
-				    gint position)
-{
-	GList *l;
-	GtkSourceCompletionPage *page;
+	item = g_list_find (completion->priv->pages, page);
 	
-	g_return_if_fail (GTK_IS_SOURCE_COMPLETION (self));
-
-	for (l = self->priv->pages; l != NULL; l = g_list_next (l))
+	if (item == NULL || item == completion->priv->pages)
 	{
-		page = (GtkSourceCompletionPage *)l->data;
-		if (g_strcmp0 (page_name, page->name) == 0)
-		{
-			break;
-		}
-		page = NULL;
+		return FALSE;
 	}
 	
-	if (page == NULL)
-	{
-		page = gtk_source_completion_page_new (self, page_name);
-	}
+	idx = g_list_index (completion->priv->pages, item);
+	completion->priv->pages = g_list_remove_link (completion->priv->pages, item);
+	
+	gtk_notebook_remove_page (GTK_NOTEBOOK (completion->priv->notebook),
+	                          idx);
 	
-	self->priv->pages = g_list_remove (self->priv->pages, page);
-	self->priv->pages = g_list_insert (self->priv->pages, page, position);
-	gtk_notebook_reorder_child (GTK_NOTEBOOK (self->priv->notebook),
-				    GTK_WIDGET (page->scroll),
-				    position);
-	if (GTK_WIDGET_VISIBLE (self))
-		update_pages_visibility (self);
+	free_page (page);
+	return TRUE;
 }
-

Modified: branches/gtksourcecompletion/gtksourceview/gtksourcecompletion.h
==============================================================================
--- branches/gtksourcecompletion/gtksourceview/gtksourcecompletion.h	(original)
+++ branches/gtksourcecompletion/gtksourceview/gtksourcecompletion.h	Sun Apr 12 19:47:46 2009
@@ -24,17 +24,12 @@
 #define GTK_SOURCE_COMPLETION_H
 
 #include <gtk/gtk.h>
-#include <gtksourceview/gtksourcecompletionprovider.h>
 #include <gtksourceview/gtksourcecompletioninfo.h>
+#include <gtksourceview/gtksourcecompletionprovider.h>
 
 G_BEGIN_DECLS
 
 /*
- * FIXME: And this here?
- */
-#define USER_REQUEST_TRIGGER_NAME "user-request"
-
-/*
  * Type checking and casting macros
  */
 #define GTK_TYPE_SOURCE_COMPLETION              (gtk_source_completion_get_type())
@@ -44,8 +39,6 @@
 #define GTK_IS_SOURCE_COMPLETION_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_SOURCE_COMPLETION))
 #define GTK_SOURCE_COMPLETION_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS((obj), GTK_TYPE_SOURCE_COMPLETION, GtkSourceCompletionClass))
 
-#define DEFAULT_PAGE "Default"
-
 typedef gboolean (* GtkSourceCompletionFilterFunc) (GtkSourceCompletionProposal *proposal,
 						    gpointer     user_data);
 
@@ -64,10 +57,8 @@
 {
 	GtkWindowClass parent_class;
 
-	gboolean (* proposal_selected)(GtkSourceCompletion *completion,
-				       GtkSourceCompletionProposal *proposal);
-	gboolean (* display_info)     (GtkSourceCompletion *completion,
-				       GtkSourceCompletionProposal *proposal);
+	gboolean (* proposal_activated)		(GtkSourceCompletion         *completion,
+						 GtkSourceCompletionProposal *proposal);
 };
 
 GType		 gtk_source_completion_get_type			(void) G_GNUC_CONST;
@@ -77,14 +68,6 @@
 
 GtkTextView	*gtk_source_completion_get_view			(GtkSourceCompletion *self);
 
-GtkSourceCompletionTrigger *
-		 gtk_source_completion_get_trigger		(GtkSourceCompletion *self,
-								 const gchar *trigger_name);
-
-GtkSourceCompletionProvider *
-		 gtk_source_completion_get_provider		(GtkSourceCompletion *self,
-								 const gchar *prov_name);
-
 gboolean	 gtk_source_completion_add_provider		(GtkSourceCompletion *self,
 								 GtkSourceCompletionProvider *provider,
 								 GtkSourceCompletionTrigger *trigger);
@@ -93,12 +76,6 @@
 								 GtkSourceCompletionProvider *provider,
 								 GtkSourceCompletionTrigger *trigger);
 
-gboolean	 gtk_source_completion_add_trigger		(GtkSourceCompletion *self,
-								 GtkSourceCompletionTrigger *trigger);
-
-gboolean	 gtk_source_completion_remove_trigger		(GtkSourceCompletion *self,
-								 GtkSourceCompletionTrigger *trigger);
-
 GtkSourceCompletionTrigger *
 		 gtk_source_completion_get_active_trigger	(GtkSourceCompletion *self);
 
@@ -108,25 +85,15 @@
 								 GtkSourceCompletionFilterFunc func,
 								 gpointer user_data);
 
-void		 gtk_source_completion_set_active 		(GtkSourceCompletion *self,
-								 gboolean active);
-
-gboolean	 gtk_source_completion_get_active 		(GtkSourceCompletion *self);
-
-GtkWidget	*gtk_source_completion_get_bottom_bar		(GtkSourceCompletion *self);
-
 GtkSourceCompletionInfo *
-		 gtk_source_completion_get_info_widget		(GtkSourceCompletion *self);
-
-gint		 gtk_source_completion_get_page_pos		(GtkSourceCompletion *self,
-								 const gchar *page_name);
-
-gint		 gtk_source_completion_get_n_pages		(GtkSourceCompletion *self);
+		 gtk_source_completion_get_info_window		(GtkSourceCompletion *self);
 
-void		 gtk_source_completion_set_page_pos		(GtkSourceCompletion *self,
-								 const gchar *page_name,
-								 gint position);
+GtkSourceCompletionPage *
+		gtk_source_completion_add_page			(GtkSourceCompletion *self,
+								 const gchar         *title);
 
+gboolean	gtk_source_completion_remove_page 		(GtkSourceCompletion     *completion,
+								 GtkSourceCompletionPage *page);
 G_END_DECLS
 
 #endif 

Modified: branches/gtksourcecompletion/gtksourceview/gtksourcecompletioninfo.c
==============================================================================
--- branches/gtksourcecompletion/gtksourceview/gtksourcecompletioninfo.c	(original)
+++ branches/gtksourcecompletion/gtksourceview/gtksourcecompletioninfo.c	Sun Apr 12 19:47:46 2009
@@ -32,192 +32,250 @@
 #include "gtksourcecompletionutils.h"
 #include "gtksourceview-i18n.h"
 
+#ifndef MIN
+#define MIN (a, b) ((a) < (b) ? (a) : (b))
+#endif
+
+#ifndef MAX
+#define MAX (a, b) ((a) > (b) ? (a) : (b))
+#endif
+
 struct _GtkSourceCompletionInfoPrivate
 {
-	GtkWidget *box;
-	GtkWidget *info_scroll;
-	GtkWidget *label;
-	GtkWidget *custom_widget;
+	GtkWidget *scroll;
+	GtkWidget *widget;
 	
-	gboolean adjust_height;
-	gboolean adjust_width;
 	gint max_height;
 	gint max_width;
+	
+	gboolean shrink_height;
+	gboolean shrink_width;
+	
+	guint idle_resize;
+	guint request_id;
 };
 
 /* Signals */
 enum
 {
-	SHOW_INFO,
+	BEFORE_SHOW,
 	LAST_SIGNAL
 };
 
+/* Properties */
+enum
+{
+	PROP_0,
+	PROP_MAX_WIDTH,
+	PROP_MAX_HEIGHT,
+	PROP_SHRINK_WIDTH,
+	PROP_SHRINK_HEIGHT
+};
+
 static guint signals[LAST_SIGNAL] = { 0 };
 
-/*Type definition*/
 G_DEFINE_TYPE(GtkSourceCompletionInfo, gtk_source_completion_info, GTK_TYPE_WINDOW);
 
 #define GTK_SOURCE_COMPLETION_INFO_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), GTK_TYPE_SOURCE_COMPLETION_INFO, GtkSourceCompletionInfoPrivate))
-#define WINDOW_WIDTH 350
-#define WINDOW_HEIGHT 200
-
 
 static void
-get_max_size (GtkSourceCompletionInfo *self,
-	      GtkWidget *widget,
-	      gint *w,
-	      gint *h)
+window_resize (GtkSourceCompletionInfo *self)
 {
 	GtkRequisition req;
-	
-	gtk_widget_size_request (widget, &req);
+	gint width;
+	gint height;
+	gint off;
+	GtkWidget *scrollbar;
+	GtkStyle *style = GTK_WIDGET (self)->style;
+
+	gtk_window_get_default_size (GTK_WINDOW (self), &width, &height);
+
+	if (self->priv->widget != NULL)
+	{
+		/* Try to resize to fit widget, if necessary */
+		gtk_widget_size_request (self->priv->widget, &req);
+		off = (gtk_container_get_border_width (GTK_CONTAINER (self)) +
+		       gtk_container_get_border_width (GTK_CONTAINER (self->priv->scroll))) * 2;
 
-	if (self->priv->adjust_height)
-	{
-		if (req.height > self->priv->max_height)
-		{
-			*h = self->priv->max_height;
-		}
-		else
+		if (self->priv->shrink_height)
 		{
-			*h = req.height;
+			scrollbar = gtk_scrolled_window_get_hscrollbar (GTK_SCROLLED_WINDOW (self->priv->scroll));
+			
+			if (GTK_WIDGET_VISIBLE (scrollbar))
+			{
+				off = off + scrollbar->allocation.height;
+			}
+			
+			if (self->priv->max_height == -1)
+			{
+				height = req.height + style->ythickness * 2;
+			}
+			else
+			{
+				height = MIN (req.height + style->ythickness * 2, self->priv->max_height);
+			}
 		}
-	}
-	else
-	{
-		*h = WINDOW_HEIGHT;
-	}
 	
-	if (self->priv->adjust_width)
-	{
-		if (req.width > self->priv->max_width)
-		{
-			*w = self->priv->max_width;
-		}
-		else
+		if (self->priv->shrink_width)
 		{
-			*w = req.width;
+			scrollbar = gtk_scrolled_window_get_vscrollbar (GTK_SCROLLED_WINDOW (self->priv->scroll));
+			
+			if (GTK_WIDGET_VISIBLE (scrollbar))
+			{
+				off = off + scrollbar->allocation.width;
+			}
+			
+			if (self->priv->max_width == -1)
+			{
+				width = req.width + style->xthickness * 2;
+			}
+			else
+			{
+				width = MIN (req.width + style->xthickness * 2, self->priv->max_width);
+			}
 		}
 	}
-	else
-	{
-		*w = WINDOW_WIDTH;
-	}
-}
-
-static void
-adjust_resize (GtkSourceCompletionInfo *self)
-{
-	gint w, h;
-	
-	if (!self->priv->custom_widget)
-	{
-		/* Default widget */
-		get_max_size (self, self->priv->label, &w, &h);
-		w = w + 5 + GTK_WIDGET (self->priv->info_scroll)->style->ythickness * 2;
-		h = h + 5 + GTK_WIDGET (self->priv->info_scroll)->style->xthickness * 2;
-	}
-	else
-	{
-		/* Custom widget */
-		get_max_size (self, self->priv->custom_widget, &w, &h);
-	}
 	
-	gtk_window_resize (GTK_WINDOW (self), w, h);
-}
-
-static void
-show (GtkWidget *widget)
-{
-	GtkSourceCompletionInfo *self = GTK_SOURCE_COMPLETION_INFO (widget);
-	
-	g_signal_emit (self, signals[SHOW_INFO], 0);
-	
-	GTK_WIDGET_CLASS (gtk_source_completion_info_parent_class)->show (GTK_WIDGET (self));
-	
-	gtk_label_select_region (GTK_LABEL (self->priv->label), 0, 0);
-}
-
-static void
-hide (GtkWidget *widget)
-{
-	GtkSourceCompletionInfo *self = GTK_SOURCE_COMPLETION_INFO (widget);
-	
-	gtk_label_set_label (GTK_LABEL (self->priv->label), "");
-	
-	GTK_WIDGET_CLASS (gtk_source_completion_info_parent_class)->hide (GTK_WIDGET (self));
+	gtk_window_resize (GTK_WINDOW (self), width, height);
 }
 
 static void
 gtk_source_completion_info_init (GtkSourceCompletionInfo *self)
 {
 	self->priv = GTK_SOURCE_COMPLETION_INFO_GET_PRIVATE (self);
-	self->priv->adjust_height = FALSE;
-	self->priv->adjust_width = FALSE;
-	self->priv->max_height = WINDOW_HEIGHT;
-	self->priv->max_width = WINDOW_WIDTH;
-	self->priv->custom_widget = NULL;
-	
-	/*
-	 * Make it look like a tooltip
-	 */
+	
+	/* Tooltip style */
+	gtk_window_set_title (GTK_WINDOW (self), _("Completion Info"));
 	gtk_widget_set_name (GTK_WIDGET (self), "gtk-tooltip");
 	gtk_widget_ensure_style (GTK_WIDGET (self));
 	
 	gtk_window_set_type_hint (GTK_WINDOW (self),
 				  GDK_WINDOW_TYPE_HINT_NORMAL);
-	gtk_window_set_decorated (GTK_WINDOW (self), FALSE);
-	gtk_window_set_default_size (GTK_WINDOW (self),
-				     WINDOW_WIDTH, WINDOW_HEIGHT);
 
-	self->priv->info_scroll = gtk_scrolled_window_new (NULL, NULL);
+	gtk_window_set_default_size (GTK_WINDOW (self), 300, 200);
 
-	gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (self->priv->info_scroll),
+	/* Create scrolled window main widget */
+	self->priv->scroll = gtk_scrolled_window_new (NULL, NULL);
+
+	gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (self->priv->scroll),
 					GTK_POLICY_AUTOMATIC,
 					GTK_POLICY_AUTOMATIC);
-	gtk_widget_show (self->priv->info_scroll);
 
-	self->priv->label = gtk_label_new (" ");
-	/*Top left position*/
-	gtk_misc_set_alignment (GTK_MISC (self->priv->label), 0, 0.5);
-	gtk_misc_set_padding (GTK_MISC (self->priv->label), 5, 5);
-	gtk_label_set_selectable (GTK_LABEL (self->priv->label), TRUE);
+	gtk_widget_show (self->priv->scroll);
+	gtk_container_add (GTK_CONTAINER (self), self->priv->scroll);
+}
+
+static gboolean
+idle_resize (GtkSourceCompletionInfo *self)
+{
+	self->priv->idle_resize = 0;
 	
-	gtk_widget_show (self->priv->label);
+	window_resize (self);
+	return FALSE;
+}
 
-	gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (self->priv->info_scroll),
-					       self->priv->label);
+static void
+queue_resize (GtkSourceCompletionInfo *self)
+{
+	if (self->priv->idle_resize == 0)
+	{
+		self->priv->idle_resize = g_idle_add ((GSourceFunc)idle_resize, self);
+	}
+}
 
-	self->priv->box = gtk_vbox_new (FALSE, 1);
-	
-	gtk_widget_show (self->priv->box);
-	gtk_box_pack_start (GTK_BOX (self->priv->box),
-			    self->priv->info_scroll,
-			    TRUE, TRUE, 0);
-	
-	gtk_container_add (GTK_CONTAINER (self), 
-			   self->priv->box);
+static void
+gtk_source_completion_info_get_property (GObject    *object, 
+                                         guint       prop_id, 
+                                         GValue     *value, 
+                                         GParamSpec *pspec)
+{
+	GtkSourceCompletionInfo *self = GTK_SOURCE_COMPLETION_INFO (object);
+	
+	switch (prop_id)
+	{
+		case PROP_MAX_WIDTH:
+			g_value_set_int (value, self->priv->max_width);
+			break;
+		case PROP_MAX_HEIGHT:
+			g_value_set_int (value, self->priv->max_height);
+			break;
+		case PROP_SHRINK_WIDTH:
+			g_value_set_boolean (value, self->priv->shrink_width);
+			break;
+		case PROP_SHRINK_HEIGHT:
+			g_value_set_boolean (value, self->priv->shrink_height);
+			break;
+		default:
+			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+			break;
+	}
+}
+
+static void
+gtk_source_completion_info_set_property (GObject      *object, 
+                                         guint         prop_id, 
+                                         const GValue *value, 
+                                         GParamSpec   *pspec)
+{
+	GtkSourceCompletionInfo *self = GTK_SOURCE_COMPLETION_INFO (object);
+	
+	switch (prop_id)
+	{
+		case PROP_MAX_WIDTH:
+			self->priv->max_width = g_value_get_int (value);
+			queue_resize (self);
+			break;
+		case PROP_MAX_HEIGHT:
+			self->priv->max_height = g_value_get_int (value);
+			queue_resize (self);
+			break;
+		case PROP_SHRINK_WIDTH:
+			self->priv->shrink_width = g_value_get_boolean (value);
+			queue_resize (self);
+			break;
+		case PROP_SHRINK_HEIGHT:
+			self->priv->shrink_height = g_value_get_boolean (value);
+			queue_resize (self);
+			break;
+		default:
+			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+		break;
+	}
 }
 
 static void
 gtk_source_completion_info_finalize (GObject *object)
 {
-	/*GtkSourceCompletionInfo *self = GTK_SOURCE_COMPLETION_INFO(object);*/
+	GtkSourceCompletionInfo *self = GTK_SOURCE_COMPLETION_INFO (object);
+	
+	if (self->priv->idle_resize != 0)
+	{
+		g_source_remove (self->priv->idle_resize);
+	}
 	
 	G_OBJECT_CLASS (gtk_source_completion_info_parent_class)->finalize (object);
 }
 
 static void
+gtk_source_completion_info_show (GtkWidget *widget)
+{
+	/* First emit BEFORE_SHOW and then chain up */
+	g_signal_emit (widget, signals[BEFORE_SHOW], 0);
+	
+	GTK_WIDGET_CLASS (gtk_source_completion_info_parent_class)->show (widget);	
+}
+
+static void
 gtk_source_completion_info_class_init (GtkSourceCompletionInfoClass *klass)
 {
-	GObjectClass* object_class = G_OBJECT_CLASS (klass);
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
 	GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
-
-	g_type_class_add_private (object_class, sizeof (GtkSourceCompletionInfoPrivate));
-
+	
+	object_class->get_property = gtk_source_completion_info_get_property;
+	object_class->set_property = gtk_source_completion_info_set_property;
 	object_class->finalize = gtk_source_completion_info_finalize;
-	widget_class->show = show;
-	widget_class->hide = hide;
+	
+	widget_class->show = gtk_source_completion_info_show;
 	
 	/**
 	 * GtkSourceCompletionInfo::show-info:
@@ -227,8 +285,8 @@
 	 * to this signal if you want to change some properties or position
 	 * before to so the real "show".
 	 **/
-	signals[SHOW_INFO] =
-		g_signal_new ("show-info",
+	signals[BEFORE_SHOW] =
+		g_signal_new ("before-show",
 			      G_TYPE_FROM_CLASS (klass),
 			      G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
 			      0,
@@ -237,6 +295,46 @@
 			      g_cclosure_marshal_VOID__VOID, 
 			      G_TYPE_NONE,
 			      0);
+
+	/* Properties */
+	g_object_class_install_property (object_class,
+					 PROP_MAX_WIDTH,
+					 g_param_spec_int ("max-width",
+							    _("Maximum width"),
+							    _("The maximum allowed width"),
+							    -1,
+							    G_MAXINT,
+							    -1,
+							    G_PARAM_READWRITE));
+
+	g_object_class_install_property (object_class,
+					 PROP_MAX_HEIGHT,
+					 g_param_spec_int ("max-height",
+							    _("Maximum height"),
+							    _("The maximum allowed height"),
+							    -1,
+							    G_MAXINT,
+							    -1,
+							    G_PARAM_READWRITE));
+							    
+
+	g_object_class_install_property (object_class,
+					 PROP_SHRINK_WIDTH,
+					 g_param_spec_boolean ("shrink-width",
+							       _("Shrink width"),
+							       _("Whether the window should shrink width to fit the contents"),
+							       FALSE,
+							       G_PARAM_READWRITE));
+
+	g_object_class_install_property (object_class,
+					 PROP_SHRINK_HEIGHT,
+					 g_param_spec_boolean ("shrink-height",
+							       _("Shrink height"),
+							       _("Whether the window should shrink height to fit the contents"),
+							       FALSE,
+							       G_PARAM_READWRITE));
+						       
+	g_type_class_add_private (object_class, sizeof (GtkSourceCompletionInfoPrivate));
 }
 
 /**
@@ -248,10 +346,9 @@
 GtkSourceCompletionInfo*
 gtk_source_completion_info_new (void)
 {
-	GtkSourceCompletionInfo *self = GTK_SOURCE_COMPLETION_INFO (g_object_new (GTK_TYPE_SOURCE_COMPLETION_INFO,
-										  "type", GTK_WINDOW_POPUP,
-										  NULL));
-	return self;
+	return g_object_new (GTK_TYPE_SOURCE_COMPLETION_INFO, 
+	                     "type", GTK_WINDOW_POPUP, 
+	                     NULL);
 }
 
 /**
@@ -264,175 +361,157 @@
  *
  */
 void
-gtk_source_completion_info_move_to_cursor (GtkSourceCompletionInfo* self,
-					   GtkTextView *view)
+gtk_source_completion_info_move_to_cursor (GtkSourceCompletionInfo *self,
+					   GtkTextView             *view)
 {
-	int x,y;
-	gboolean resized = FALSE;
+	gint x;
+	gint y;
 	
-	g_return_if_fail  (GTK_IS_SOURCE_COMPLETION_INFO (self));
-
-	adjust_resize (self);
+	g_return_if_fail (GTK_IS_SOURCE_COMPLETION_INFO (self));
+	g_return_if_fail (GTK_IS_SOURCE_VIEW (view));
 	
 	gtk_source_completion_utils_get_pos_at_cursor (GTK_WINDOW (self),
 						       GTK_SOURCE_VIEW (view),
 						       &x,
 						       &y,
-						       &resized);
-	if (resized)
-	{
-		gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (self->priv->info_scroll),
-						GTK_POLICY_ALWAYS,
-						GTK_POLICY_ALWAYS);
-	}
-	else
-	{
-		gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (self->priv->info_scroll),
-						GTK_POLICY_NEVER,
-						GTK_POLICY_NEVER);
-	}
+						       NULL);
+
 	gtk_window_move (GTK_WINDOW (self), x, y);
 }
 
 /**
- * gtk_source_completion_info_set_markup:
+ * gtk_source_completion_info_set_sizing:
  * @self: The #GtkSourceCompletionInfo
- * @markup: Text markup to be shown (see <link 
- * linkend="PangoMarkupFormat">Pango markup format</link>). 
- *
- * Sets the text markup to be shown into the GtkSourceCompletionInfo window.
+ * @width: the maximum/requested width of the window (-1 to default)
+ * @height: the maximum/requested height of the window (-1 to default)
+ * @shrink_width: whether to shrink the width of the window to fit its contents
+ * @shrink_height: whether to shrink the height of the window to fit its
+ *                 contents
+ *
+ * Set sizing information for the info window. If @shrink_width or
+ * @shrink_height is %TRUE, the info window will try to resize to fit the
+ * window contents, with a maximum size given by @width and @height. Setting
+ * @width or @height to -1 removes the maximum size of respectively the width
+ * and height of the window.
  *
  */
 void
-gtk_source_completion_info_set_markup (GtkSourceCompletionInfo* self,
-				       const gchar* markup)
+gtk_source_completion_info_set_sizing (GtkSourceCompletionInfo *self,
+				       gint                     width,
+				       gint                     height,
+				       gboolean                 shrink_width,
+				       gboolean                 shrink_height)
 {
 	g_return_if_fail  (GTK_IS_SOURCE_COMPLETION_INFO (self));
 
-	gtk_label_set_markup (GTK_LABEL (self->priv->label), markup);
+	self->priv->max_width = width;
+	self->priv->max_height = height;
+	self->priv->shrink_width = shrink_width;
+	self->priv->shrink_height = shrink_height;
 }
 
-/**
- * gtk_source_completion_info_set_adjust_height:
- * @self: The #GtkSourceCompletionInfo
- * @adjust: TRUE to adjust height to content, FALSE to fixed height
- * @max_height: if adjust = TRUE, set the max height. -1 to preserve the 
- * current value
- *
- * %TRUE adjust height to the content. If the content is only a line, the info
- * will be small and if there are a lot of lines, the info will be large to the 
- * max_height
- *
- */
-void
-gtk_source_completion_info_set_adjust_height (GtkSourceCompletionInfo* self,
-					      gboolean adjust,
-					      gint max_height)
+static gboolean
+needs_viewport (GtkWidget *widget)
 {
-	g_return_if_fail  (GTK_IS_SOURCE_COMPLETION_INFO (self));
-
-	self->priv->adjust_height = adjust;
+	guint id;
 	
-	if (max_height > 0)
-	{
-		self->priv->max_height = max_height;
-	}
+	id = g_signal_lookup ("set-scroll-adjustments", G_TYPE_FROM_INSTANCE (widget));
+	
+	return id == 0;
 }
 
-/**
- * gtk_source_completion_info_set_adjust_width:
- * @self: The #GtkSourceCompletionInfo
- * @adjust: TRUE to adjust width to content, FALSE to fixed width
- * @max_width: if adjust = TRUE, set the max height. -1 to preserve the 
- * current value
- *
- * %TRUE adjust width to the content. If the content is only a line, the info
- * will be small and if there are a lot of lines, the info will be large to the 
- * max_width
- *
- */
-void
-gtk_source_completion_info_set_adjust_width (GtkSourceCompletionInfo* self,
-					     gboolean adjust,
-					     gint max_width)
+static void
+widget_size_request_cb (GtkWidget               *widget,
+                        GtkRequisition          *requisition,
+                        GtkSourceCompletionInfo *info)
 {
-	g_return_if_fail  (GTK_IS_SOURCE_COMPLETION_INFO (self));
-	
-	self->priv->adjust_width = adjust;
-	
-	if (max_width > 0)
-	{
-		self->priv->max_width = max_width;
-	}
+	queue_resize (info);
 }
 
 /**
- * gtk_source_completion_info_set_custom:
+ * gtk_source_completion_info_set_widget:
  * @self: The #GtkSourceCompletionInfo
- * @custom_widget: A #GtkWidget
+ * @widget: A #GtkWidget
  *
- * Replaces the widget packed into the window with custom_widget. By default a
- * box with a #GtkScrolledWindow and a #GtkLabel is embedded in the window.
+ * Sets the contents widget of the info window.
  *
  */
 void
-gtk_source_completion_info_set_custom (GtkSourceCompletionInfo* self,
-				       GtkWidget *custom_widget)
+gtk_source_completion_info_set_widget (GtkSourceCompletionInfo *self,
+				       GtkWidget               *widget)
 {
+	GtkWidget *child;
+
 	g_return_if_fail (GTK_IS_SOURCE_COMPLETION_INFO (self));
-	
-	if (self->priv->custom_widget == custom_widget)
+	g_return_if_fail (widget == NULL || GTK_IS_WIDGET (widget));
+
+	if (self->priv->widget == widget)
+	{
 		return;
-		
-	if (custom_widget)
+	}
+	
+	if (self->priv->widget != NULL)
 	{
-		g_return_if_fail (GTK_IS_WIDGET (custom_widget));
+		child = gtk_bin_get_child (GTK_BIN (self->priv->scroll));
 		
-		if (self->priv->custom_widget)
+		if (child != self->priv->widget)
 		{
-			gtk_container_remove (GTK_CONTAINER (self->priv->box),
-					      self->priv->custom_widget);
-			g_object_unref (self->priv->custom_widget);
-			self->priv->custom_widget = NULL;
+			gtk_container_remove (GTK_CONTAINER (child), self->priv->widget);
+			gtk_widget_destroy (child);
 		}
 		else
 		{
-			gtk_widget_hide (self->priv->info_scroll);
+			gtk_container_remove (GTK_CONTAINER (self->priv->scroll),
+			                      self->priv->widget);
 		}
 		
-		self->priv->custom_widget = g_object_ref (custom_widget);
-		gtk_container_add (GTK_CONTAINER (self->priv->box),
-				   custom_widget);
-		gtk_widget_show (self->priv->custom_widget);
+		g_signal_handler_disconnect (self->priv->widget, self->priv->request_id);
 	}
-	else
+	
+	self->priv->widget = widget;
+	
+	if (widget != NULL)
 	{
+		child = widget;
 
-		if (self->priv->custom_widget)
+		self->priv->request_id = g_signal_connect_after (widget, 
+                                                                 "size-request", 
+                                                                 G_CALLBACK (widget_size_request_cb), 
+                                                                 self);
+		
+		/* See if it needs a viewport */
+		if (needs_viewport (widget))
 		{
-			gtk_container_remove (GTK_CONTAINER (self->priv->box),
-					      self->priv->custom_widget);
-			g_object_unref (self->priv->custom_widget);
-			self->priv->custom_widget = NULL;
-			gtk_widget_show (self->priv->info_scroll);
+			child = gtk_viewport_new (NULL, NULL);
+			gtk_widget_show (child);
+
+			gtk_container_add (GTK_CONTAINER (child), widget);
 		}
 		
+
+		
+		gtk_container_add (GTK_CONTAINER (self->priv->scroll), child);
+		gtk_widget_show (widget);
 	}
+	
+	window_resize (self);
 }
 
 /**
- * gtk_source_completion_info_get_custom:
+ * gtk_source_completion_info_get_widget:
  * @self: The #GtkSourceCompletionInfo
  *
- * Returns: The custom widget setted or NULL.
+ * Get the current contents widget
+ *
+ * Returns: The current contents widget
  *
  */
-GtkWidget*
-gtk_source_completion_info_get_custom (GtkSourceCompletionInfo* self)
+GtkWidget *
+gtk_source_completion_info_get_widget (GtkSourceCompletionInfo* self)
 {
 	g_return_val_if_fail (GTK_IS_SOURCE_COMPLETION_INFO (self), NULL);
 
-	return self->priv->custom_widget;
+	return self->priv->widget;
 }
 
 

Modified: branches/gtksourcecompletion/gtksourceview/gtksourcecompletioninfo.h
==============================================================================
--- branches/gtksourcecompletion/gtksourceview/gtksourcecompletioninfo.h	(original)
+++ branches/gtksourcecompletion/gtksourceview/gtksourcecompletioninfo.h	Sun Apr 12 19:47:46 2009
@@ -20,11 +20,10 @@
  * Boston, MA 02111-1307, USA.
  */
 
-#ifndef _GTK_SOURCE_COMPLETION_INFO_H
-#define _GTK_SOURCE_COMPLETION_INFO_H
+#ifndef __GTK_SOURCE_COMPLETION_INFO_H__
+#define __GTK_SOURCE_COMPLETION_INFO_H__
 
 #include <glib-object.h>
-#include <glib.h>
 #include <gtk/gtk.h>
 
 G_BEGIN_DECLS
@@ -52,32 +51,29 @@
 struct _GtkSourceCompletionInfoClass
 {
 	GtkWindowClass parent_class;
+	
+	void	(*before_show)	(GtkSourceCompletionInfo *info);
 };
 
 GType		 gtk_source_completion_info_get_type		(void) G_GNUC_CONST;
 
 GtkSourceCompletionInfo *
-		 gtk_source_completion_info_new		(void);
-
-void		 gtk_source_completion_info_move_to_cursor	(GtkSourceCompletionInfo* self,
-								 GtkTextView *view);
-
-void		 gtk_source_completion_info_set_markup		(GtkSourceCompletionInfo* self,
-								 const gchar* markup);
+		 gtk_source_completion_info_new			(void);
 
-void		 gtk_source_completion_info_set_adjust_height	(GtkSourceCompletionInfo* self,
-								 gboolean adjust,
-								 gint max_height);
+void		 gtk_source_completion_info_move_to_cursor	(GtkSourceCompletionInfo *self,
+								 GtkTextView             *view);
 
-void		 gtk_source_completion_info_set_adjust_width	(GtkSourceCompletionInfo* self,
-								 gboolean adjust,
-								 gint max_width);
+void		 gtk_source_completion_info_set_sizing		(GtkSourceCompletionInfo *self,
+								 gint                     width,
+								 gint                     height,
+								 gboolean                 shrink_width,
+								 gboolean                 shrink_height);
 
-void		 gtk_source_completion_info_set_custom		(GtkSourceCompletionInfo* self,
-								 GtkWidget *custom_widget);
+void		 gtk_source_completion_info_set_widget		(GtkSourceCompletionInfo *self,
+								 GtkWidget               *widget);
 
-GtkWidget	*gtk_source_completion_info_get_custom		(GtkSourceCompletionInfo* self);
+GtkWidget	*gtk_source_completion_info_get_widget		(GtkSourceCompletionInfo *self);
 
 G_END_DECLS
 
-#endif
+#endif /* __GTK_SOURCE_COMPLETION_INFO_H__ */

Modified: branches/gtksourcecompletion/gtksourceview/gtksourcecompletionitem.c
==============================================================================
--- branches/gtksourcecompletion/gtksourceview/gtksourcecompletionitem.c	(original)
+++ branches/gtksourcecompletion/gtksourceview/gtksourcecompletionitem.c	Sun Apr 12 19:47:46 2009
@@ -38,7 +38,7 @@
 	gtk_source_completion_utils_replace_current_word (buffer,
 							  item->priv->label,
 							  -1);
-	return FALSE;
+	return TRUE;
 }
 
 static const gchar *

Added: branches/gtksourcecompletion/gtksourceview/gtksourcecompletionpage.h
==============================================================================
--- (empty file)
+++ branches/gtksourcecompletion/gtksourceview/gtksourcecompletionpage.h	Sun Apr 12 19:47:46 2009
@@ -0,0 +1,29 @@
+/*
+ * gtksourcecompletionpage.h
+ * This file is part of gtksourcecompletion
+ *
+ * Copyright (C) 2009 - Jesse van den Kieboom
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, 
+ * Boston, MA  02110-1301  USA
+ */
+
+#ifndef __GTK_SOURCE_COMPLETION_PAGE_H__
+#define __GTK_SOURCE_COMPLETION_PAGE_H__
+
+typedef struct _GtkSourceCompletionPage GtkSourceCompletionPage;
+
+#endif /* __GTK_SOURCE_COMPLETION_PAGE_H__ */
+

Modified: branches/gtksourcecompletion/gtksourceview/gtksourcecompletionprovider.c
==============================================================================
--- branches/gtksourcecompletion/gtksourceview/gtksourcecompletionprovider.c	(original)
+++ branches/gtksourcecompletion/gtksourceview/gtksourcecompletionprovider.c	Sun Apr 12 19:47:46 2009
@@ -35,62 +35,141 @@
 
 /**
  * gtk_source_completion_provider_get_name:
- * @self: The #GtkSourceCompletionProvider
+ * @provider: The #GtkSourceCompletionProvider
  *
- * The provider name. By example: "Document word completion provider"
+ * The provider name. For example: "Document word completion provider"
  *
  * Returns: The provider's name 
  */
-const gchar*
-gtk_source_completion_provider_get_name (GtkSourceCompletionProvider *self)
+const gchar *
+gtk_source_completion_provider_get_name (GtkSourceCompletionProvider *provider)
 {
-	g_return_val_if_fail (GTK_IS_SOURCE_COMPLETION_PROVIDER (self), NULL);
-	return GTK_SOURCE_COMPLETION_PROVIDER_GET_INTERFACE (self)->get_name (self);
+	g_return_val_if_fail (GTK_IS_SOURCE_COMPLETION_PROVIDER (provider), NULL);
+	return GTK_SOURCE_COMPLETION_PROVIDER_GET_INTERFACE (provider)->get_name (provider);
 }
 
-/* Default implementation */
-static const gchar *
-gtk_source_completion_provider_get_name_default (GtkSourceCompletionProvider *self)
+/**
+ * gtk_source_completion_provider_get_proposals:
+ * @provider: The #GtkSourceCompletionProvider
+ * @trigger: The #GtkSourceViewTrigger that triggered the completion
+ *
+ * Get the proposals from the provider triggered by @trigger for completion.
+ *
+ * Returns: a list of #GtkSourceViewProposal or NULL if there are no proposals.
+ *          The returned list is owned by the caller and is freed when no
+ *          longer needed.
+ */
+GList * 
+gtk_source_completion_provider_get_proposals (GtkSourceCompletionProvider *provider,
+					      GtkSourceCompletionTrigger  *trigger)
 {
-	g_return_val_if_reached (NULL);
+	g_return_val_if_fail (GTK_IS_SOURCE_COMPLETION_PROVIDER (provider), NULL);
+	return GTK_SOURCE_COMPLETION_PROVIDER_GET_INTERFACE (provider)->get_proposals (provider, trigger);
 }
 
 /**
- * gtk_source_completion_provider_get_proposals:
- * @self: The #GtkSourceCompletionProvider
- * @trigger: The #GscTrigger that raise the event
+ * gtk_source_completion_provider_get_page:
+ * @provider: The #GtkSourceCompletionProvider
+ * @proposal: The #GtkSourceViewProposal
  *
- * The completion call this function when an event is raised.
- * This function may return a list of #GscProposal to be shown
- * in the popup to the user.
+ * Get the page on which @proposal should be placed
  *
- * Returns: a list of #GscProposal or NULL if there are no proposals
+ * Returns: the #GtkSourceCompletionPage on which @proposal should be placed,
+ *          or %NULL to put @proposal on the default page
  */
-GList* 
-gtk_source_completion_provider_get_proposals (GtkSourceCompletionProvider* self,
-					      GtkSourceCompletionTrigger *trigger)
+GtkSourceCompletionPage *
+gtk_source_completion_provider_get_page (GtkSourceCompletionProvider *provider,
+                                         GtkSourceCompletionProposal *proposal)
 {
-	g_return_val_if_fail (GTK_IS_SOURCE_COMPLETION_PROVIDER (self), NULL);
-	return GTK_SOURCE_COMPLETION_PROVIDER_GET_INTERFACE (self)->get_proposals (self, trigger);
+	g_return_val_if_fail (GTK_IS_SOURCE_COMPLETION_PROVIDER (provider), NULL);
+	g_return_val_if_fail (GTK_IS_SOURCE_COMPLETION_PROPOSAL (proposal), NULL);
+	
+	return GTK_SOURCE_COMPLETION_PROVIDER_GET_INTERFACE (provider)->get_page (provider, proposal);
 }
 
-/* Default implementation */
-static GList *
-gtk_source_completion_provider_get_proposals_default (GtkSourceCompletionProvider *self,
-						      GtkSourceCompletionTrigger *trigger)
+/**
+ * gtk_source_completion_provider_get_info_widget:
+ * @provider: The #GtkSourceCompletionProvider
+ * @proposal: The currently selected #GtkSourceCompletionProposal
+ *
+ * Get a customized info widget to show extra information of a proposal with.
+ * This allows for customized widgets on a proposal basis, although in general
+ * providers will have the same custom widget for all their proposals and
+ * @proposal is ignored. The implementation of this function is optional.
+ *
+ * Returns: a custom #GtkWidget to show extra information about @proposal
+ */
+GtkWidget *
+gtk_source_completion_provider_get_info_widget (GtkSourceCompletionProvider *provider,
+                                                GtkSourceCompletionProposal *proposal)
+{
+	g_return_val_if_fail (GTK_IS_SOURCE_COMPLETION_PROVIDER (provider), NULL);
+	g_return_val_if_fail (GTK_IS_SOURCE_COMPLETION_PROPOSAL (proposal), NULL);
+	
+	return GTK_SOURCE_COMPLETION_PROVIDER_GET_INTERFACE (provider)->get_info_widget (provider, proposal);
+}
+
+void 
+gtk_source_completion_provider_update_info (GtkSourceCompletionProvider *provider,
+                                            GtkSourceCompletionProposal *proposal,
+                                            GtkSourceCompletionInfo     *info)
+{
+	g_return_if_fail (GTK_IS_SOURCE_COMPLETION_PROVIDER (provider));
+	g_return_if_fail (GTK_IS_SOURCE_COMPLETION_PROPOSAL (proposal));
+	g_return_if_fail (GTK_IS_SOURCE_COMPLETION_INFO (info));
+	
+	GTK_SOURCE_COMPLETION_PROVIDER_GET_INTERFACE (provider)->update_info (provider, proposal, info);
+}
+
+/* Default implementations */
+static const gchar *
+gtk_source_completion_provider_get_name_default (GtkSourceCompletionProvider *provider)
 {
 	g_return_val_if_reached (NULL);
 }
 
+static GList *
+gtk_source_completion_provider_get_proposals_default (GtkSourceCompletionProvider *provider,
+						      GtkSourceCompletionTrigger  *trigger)
+{
+	return NULL;
+}
+
+static GtkSourceCompletionPage *
+gtk_source_completion_provider_get_page_default (GtkSourceCompletionProvider *provider,
+                                                 GtkSourceCompletionProposal *proposal)
+{
+	return NULL;
+}
+
+static GtkWidget *
+gtk_source_completion_provider_get_info_widget_default (GtkSourceCompletionProvider *provider,
+                                                        GtkSourceCompletionProposal *proposal)
+{
+	return NULL;
+}
+
+static void
+gtk_source_completion_provider_update_info_default (GtkSourceCompletionProvider *provider,
+                                                    GtkSourceCompletionProposal *proposal,
+                                                    GtkSourceCompletionInfo     *info)
+{
+}
+
 static void 
-gtk_source_completion_provider_base_init (GtkSourceCompletionProviderIface * iface)
+gtk_source_completion_provider_base_init (GtkSourceCompletionProviderIface *iface)
 {
 	static gboolean initialized = FALSE;
 	
 	iface->get_name = gtk_source_completion_provider_get_name_default;
 	iface->get_proposals = gtk_source_completion_provider_get_proposals_default;
+	iface->get_page = gtk_source_completion_provider_get_page_default;
+
+	iface->get_info_widget = gtk_source_completion_provider_get_info_widget_default;
+	iface->update_info = gtk_source_completion_provider_update_info_default;
 	
-	if (!initialized) {
+	if (!initialized)
+	{
 		initialized = TRUE;
 	}
 }
@@ -100,7 +179,9 @@
 gtk_source_completion_provider_get_type ()
 {
 	static GType gtk_source_completion_provider_type_id = 0;
-	if (!gtk_source_completion_provider_type_id) {
+
+	if (!gtk_source_completion_provider_type_id)
+	{
 		static const GTypeInfo g_define_type_info = 
 		{ 
 			sizeof (GtkSourceCompletionProviderIface), 
@@ -120,6 +201,7 @@
 							&g_define_type_info, 
 							0);
 	}
+
 	return gtk_source_completion_provider_type_id;
 }
 

Modified: branches/gtksourcecompletion/gtksourceview/gtksourcecompletionprovider.h
==============================================================================
--- branches/gtksourcecompletion/gtksourceview/gtksourcecompletionprovider.h	(original)
+++ branches/gtksourcecompletion/gtksourceview/gtksourcecompletionprovider.h	Sun Apr 12 19:47:46 2009
@@ -28,14 +28,16 @@
 #include <gtk/gtk.h>
 #include <gtksourceview/gtksourcecompletionproposal.h>
 #include <gtksourceview/gtksourcecompletiontrigger.h>
+#include <gtksourceview/gtksourcecompletionpage.h>
+#include <gtksourceview/gtksourcecompletioninfo.h>
 
 G_BEGIN_DECLS
 
 
-#define GTK_TYPE_SOURCE_COMPLETION_PROVIDER (gtk_source_completion_provider_get_type ())
-#define GTK_SOURCE_COMPLETION_PROVIDER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_SOURCE_COMPLETION_PROVIDER, GtkSourceCompletionProvider))
-#define GTK_IS_SOURCE_COMPLETION_PROVIDER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_SOURCE_COMPLETION_PROVIDER))
-#define GTK_SOURCE_COMPLETION_PROVIDER_GET_INTERFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), GTK_TYPE_SOURCE_COMPLETION_PROVIDER, GtkSourceCompletionProviderIface))
+#define GTK_TYPE_SOURCE_COMPLETION_PROVIDER 			(gtk_source_completion_provider_get_type ())
+#define GTK_SOURCE_COMPLETION_PROVIDER(obj) 			(G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_SOURCE_COMPLETION_PROVIDER, GtkSourceCompletionProvider))
+#define GTK_IS_SOURCE_COMPLETION_PROVIDER(obj) 			(G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_SOURCE_COMPLETION_PROVIDER))
+#define GTK_SOURCE_COMPLETION_PROVIDER_GET_INTERFACE(obj) 	(G_TYPE_INSTANCE_GET_INTERFACE ((obj), GTK_TYPE_SOURCE_COMPLETION_PROVIDER, GtkSourceCompletionProviderIface))
 
 typedef struct _GtkSourceCompletionProvider GtkSourceCompletionProvider;
 typedef struct _GtkSourceCompletionProviderIface GtkSourceCompletionProviderIface;
@@ -44,19 +46,39 @@
 {
 	GTypeInterface g_iface;
 	
-	const gchar* (*get_name)       (GtkSourceCompletionProvider *self);
-	GList*       (*get_proposals)  (GtkSourceCompletionProvider *self,
-				        GtkSourceCompletionTrigger *trigger);
+	const gchar	*(*get_name)       	(GtkSourceCompletionProvider *provider);
+	GList 		*(*get_proposals) 	(GtkSourceCompletionProvider *provider,
+						 GtkSourceCompletionTrigger  *trigger);
+	GtkSourceCompletionPage *
+			 (*get_page)		(GtkSourceCompletionProvider *provider,
+			 			 GtkSourceCompletionProposal *proposal);
+						 
+	GtkWidget 	*(*get_info_widget)	(GtkSourceCompletionProvider *provider,
+						 GtkSourceCompletionProposal *proposal);
+	void		 (*update_info)		(GtkSourceCompletionProvider *provider,
+						 GtkSourceCompletionProposal *proposal,
+						 GtkSourceCompletionInfo     *info);
 };
 
 GType		 gtk_source_completion_provider_get_type	(void);
 
 
-const gchar	*gtk_source_completion_provider_get_name	(GtkSourceCompletionProvider *self);
+const gchar	*gtk_source_completion_provider_get_name	(GtkSourceCompletionProvider *provider);
 
-GList		*gtk_source_completion_provider_get_proposals	(GtkSourceCompletionProvider *self, 
+GList		*gtk_source_completion_provider_get_proposals	(GtkSourceCompletionProvider *provider, 
 								 GtkSourceCompletionTrigger  *trigger);
 
+GtkWidget	*gtk_source_completion_provider_get_info_widget	(GtkSourceCompletionProvider *provider,
+								 GtkSourceCompletionProposal *proposal);
+
+void 		 gtk_source_completion_provider_update_info	(GtkSourceCompletionProvider *provider,
+								 GtkSourceCompletionProposal *proposal,
+								 GtkSourceCompletionInfo     *info);
+
+GtkSourceCompletionPage *
+		gtk_source_completion_provider_get_page		(GtkSourceCompletionProvider *provider,
+								 GtkSourceCompletionProposal *proposal);
+
 G_END_DECLS
 
 #endif

Modified: branches/gtksourcecompletion/gtksourceview/gtksourcecompletiontriggerkey.c
==============================================================================
--- branches/gtksourcecompletion/gtksourceview/gtksourcecompletiontriggerkey.c	(original)
+++ branches/gtksourcecompletion/gtksourceview/gtksourcecompletiontriggerkey.c	Sun Apr 12 19:47:46 2009
@@ -46,7 +46,9 @@
 enum
 {
 	PROP_0,
-	PROP_ENABLE_FILTER
+	PROP_ENABLE_FILTER,
+	PROP_KEY,
+	PROP_MODIFIER
 };
 
 struct _GtkSourceCompletionTriggerKeyPrivate
@@ -153,7 +155,7 @@
 		gint			       len,
 		GtkSourceCompletionTriggerKey *self)
 {
-	/* Raise the event if completion is not visible */
+	/* Raise the event if completion is visible */
 	if (GTK_WIDGET_VISIBLE (self->priv->completion) && self->priv->filter &&
 	    gtk_source_completion_get_active_trigger (self->priv->completion) == GTK_SOURCE_COMPLETION_TRIGGER (self))
 	{
@@ -195,11 +197,6 @@
 	self->priv->line = 0;
 	self->priv->line_offset = 0;
 	self->priv->filter = TRUE;
-	
-	/* Default accelerator <Control>Space */
-	gtk_source_completion_trigger_key_set_accelerator (self,
-							   GDK_space,
-							   GDK_CONTROL_MASK);
 }
 
 static void 
@@ -248,6 +245,12 @@
 			g_value_set_boolean (value,
 					     gtk_source_completion_trigger_key_get_enable_filter (self));
 			break;
+		case PROP_KEY:
+			g_value_set_uint (value, self->priv->key);
+			break;
+		case PROP_MODIFIER:
+			g_value_set_flags (value, self->priv->mod);
+			break;
 		default:
 			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 			break;
@@ -272,6 +275,12 @@
 			gtk_source_completion_trigger_key_set_enable_filter (self,
 									     g_value_get_boolean (value));
 			break;
+		case PROP_KEY:
+			self->priv->key = g_value_get_uint (value);
+			break;
+		case PROP_MODIFIER:
+			self->priv->mod = g_value_get_flags (value);
+			break;
 		default:
 			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 			break;
@@ -299,8 +308,27 @@
 							       _("Enable filter"),
 							       _("Whether the proposals must be filtered"),
 							       TRUE,
-							       G_PARAM_READWRITE));
+							       G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+
+	g_object_class_install_property (object_class,
+					 PROP_KEY,
+					 g_param_spec_uint ("key",
+							    _("Accelerator key"),
+							    _("The accelerator key which activates the trigger"),
+							    0,
+							    G_MAXUINT,
+							    GDK_space,
+							    G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
 
+	g_object_class_install_property (object_class,
+					 PROP_MODIFIER,
+					 g_param_spec_flags ("modifier",
+							      _("Accelerator modifier"),
+							      _("The accelerator modifier which activates the trigger"),
+							       GDK_TYPE_MODIFIER_TYPE,
+							       GDK_CONTROL_MASK,
+							       G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+							       
 	g_type_class_add_private (klass, sizeof (GtkSourceCompletionTriggerKeyPrivate));
 }
 

Modified: branches/gtksourcecompletion/gtksourceview/gtksourcecompletionutils.c
==============================================================================
--- branches/gtksourcecompletion/gtksourceview/gtksourcecompletionutils.c	(original)
+++ branches/gtksourcecompletion/gtksourceview/gtksourcecompletionutils.c	Sun Apr 12 19:47:46 2009
@@ -266,13 +266,13 @@
 	{
 		/* Resize to view all the window */
 		resize = TRUE;
-		w = sw -8;
+		w = sw - 8;
 	}
 	
 	/* Move position to view all the window */
 	if ((*x + w) > (sw - 4))
 	{
-		*x = sw - w -4;
+		*x = sw - w - 4;
 	}
 
 	/* Processing y position and height */
@@ -284,9 +284,11 @@
 	if ((*y + h) > sh)
 	{
 		PangoLayout* layout = 
-			gtk_widget_create_pango_layout(GTK_WIDGET(view), NULL);
-		pango_layout_get_pixel_size(layout,&xtext,&ytext);
+			gtk_widget_create_pango_layout (GTK_WIDGET(view), NULL);
+
+		pango_layout_get_pixel_size (layout, &xtext, &ytext);
 		ytemp = *y - ytext;
+
 		/* Cabe arriba? */
 		if ((ytemp - h) >= 4)
 		{
@@ -309,13 +311,15 @@
 				h = ytemp -4;
 				up = TRUE;
 			}
+
 			resize = TRUE;
 		}
-		g_object_unref(layout);
+
+		g_object_unref (layout);
 	}
 	
 	if (resize)
-		gtk_window_resize(window, w, h);
+		gtk_window_resize (window, w, h);
 
 	if (resized != NULL)
 		*resized = resize;

Modified: branches/gtksourcecompletion/tests/completion-simple.c
==============================================================================
--- branches/gtksourcecompletion/tests/completion-simple.c	(original)
+++ branches/gtksourcecompletion/tests/completion-simple.c	Sun Apr 12 19:47:46 2009
@@ -35,12 +35,8 @@
 #include "gsc-provider-test.h"
 #include "gsc-provider-devhelp.h"
 
-#define TEST_PAGE "Page 3"
-#define FIXED_PAGE "Fixed"
-
 static GtkWidget *view;
 static GtkSourceCompletion *comp;
-static GtkSourceCompletionInfo *info;
 
 static const gboolean change_keys = FALSE;
 
@@ -52,34 +48,6 @@
 	GtkWidget *foot;
 } CustomWidget;
 
-static void
-show_completion_cb (GtkWidget *w,
-		    gpointer user_data)
-{
-	gint n;
-	gint pos;
-	
-	n = gtk_source_completion_get_n_pages (comp);
-	pos = gtk_source_completion_get_page_pos (comp, TEST_PAGE);
-	
-	if (pos == n -1)
-		pos = 1;
-	else
-		pos++;
-	
-	gtk_source_completion_set_page_pos (comp, TEST_PAGE, pos);
-	g_debug ("pos: %d, urpos: %d", pos, 
-		gtk_source_completion_get_page_pos (comp, TEST_PAGE));
-	g_assert (gtk_source_completion_get_page_pos (comp, TEST_PAGE) == pos);
-}
-
-static void
-hide_completion_cb (GtkWidget *w,
-		    gpointer user_data)
-{
-	
-}
-
 static gboolean
 filter_func (GtkSourceCompletionProposal *proposal,
 	     gpointer user_data)
@@ -125,37 +93,10 @@
 }
 
 static gboolean
-display_info_cb (GtkSourceCompletion *comp,
-		 GtkSourceCompletionProposal *prop,
-		 gpointer user_data)
-{
-	CustomWidget *cw = (CustomWidget *) user_data;
-	gchar *text;
-	
-	text = g_strdup_printf ("Header of: %s", gtk_source_completion_proposal_get_label (prop));
-	gtk_label_set_text (GTK_LABEL (cw->header), text);
-	g_free (text);
-	
-	text = g_strdup_printf ("Content: %s", gtk_source_completion_proposal_get_info (prop));
-	gtk_label_set_text (GTK_LABEL (cw->content), text);
-	g_free (text);
-	
-	text = g_strdup_printf ("Foot of: %s", gtk_source_completion_proposal_get_label (prop));
-	gtk_label_set_text (GTK_LABEL (cw->foot), text);
-	g_free (text);
-	
-	return TRUE;
-}
-
-static gboolean
 key_press (GtkWidget   *widget,
 	   GdkEventKey *event,
 	   gpointer     user_data)
 {
-	GdkModifierType mod;
-	guint key = 0;
-	guint s;
-
 	if (event->keyval == GDK_F9)
 	{
 		gtk_source_completion_filter_proposals (comp,
@@ -167,7 +108,7 @@
 	{
 		GtkSourceCompletionInfo *gsc_info;
 		
-		gsc_info = gtk_source_completion_get_info_widget (comp);
+		gsc_info = gtk_source_completion_get_info_window (comp);
 		
 		if (GTK_WIDGET_VISIBLE (GTK_WIDGET (gsc_info)))
 			gtk_widget_hide (GTK_WIDGET (gsc_info));
@@ -175,31 +116,6 @@
 			gtk_widget_show (GTK_WIDGET (gsc_info));
 	}
 	
-	gtk_accelerator_parse ("<Control>b", &key, &mod);
-	
-	s = event->state & gtk_accelerator_get_default_mod_mask ();
-	
-	if (s == mod && gdk_keyval_to_lower (event->keyval) == key)
-	{
-		if (!GTK_WIDGET_VISIBLE (info))
-		{
-			gchar *text;
-			gchar *word;
-			
-			word = gsc_get_last_word (GTK_TEXT_VIEW (view));
-			text = g_strdup_printf ("<b>Calltip</b>: %s", word);
-			
-			gtk_source_completion_info_set_markup (info, text);
-			g_free (text);
-			gtk_source_completion_info_move_to_cursor (info, GTK_TEXT_VIEW (view));
-			gtk_widget_show (GTK_WIDGET (info));
-		}
-		else
-		{
-			gtk_widget_hide (GTK_WIDGET (info));
-		}
-	}
-	
 	return FALSE;
 }
 
@@ -227,7 +143,7 @@
 	activate = gtk_check_button_new_with_label ("Active");
 	remember = gtk_check_button_new_with_label ("Remember info visibility");
 	select_on_show = gtk_check_button_new_with_label ("Select first on show");
-	label = gtk_label_new ("F9 filter by \"sp\"\n<Control>b to show a calltip\nF8 show/hide info");
+	label = gtk_label_new ("F9 filter by \"sp\"");
 	gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (activate), TRUE);
 	gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (remember), FALSE);
 	gtk_box_pack_start (GTK_BOX (hbox), label, TRUE, FALSE, 0);
@@ -260,76 +176,24 @@
 }
 
 static void
-create_custom_info_widget (CustomWidget *custom)
-{
-	GtkWidget *btbox;
-	GtkWidget *next_page_icon;
-	GtkWidget *prev_page_icon;
-
-	custom->box = gtk_vbox_new (FALSE, 0);
-	custom->header = gtk_label_new ("Header");
-	custom->content = gtk_label_new ("Content");
-	custom->foot = gtk_label_new ("Foot");
-	
-	btbox = gtk_hbox_new (FALSE, 2);
-	next_page_icon = gtk_image_new_from_stock (GTK_STOCK_GO_FORWARD,
-						   GTK_ICON_SIZE_SMALL_TOOLBAR);
-	prev_page_icon = gtk_image_new_from_stock (GTK_STOCK_GO_BACK,
-						   GTK_ICON_SIZE_SMALL_TOOLBAR);
-	gtk_box_pack_start (GTK_BOX (btbox),
-			    next_page_icon,
-			    FALSE,
-			    FALSE,
-			    0);
-	gtk_box_pack_start (GTK_BOX (btbox),
-			    prev_page_icon,
-			    FALSE,
-			    FALSE,
-			    0);
-	
-	gtk_box_pack_start (GTK_BOX (custom->box),
-			    custom->header,
-			    FALSE,
-			    FALSE,
-			    1);
-	gtk_box_pack_start (GTK_BOX (custom->box),
-			    custom->content,
-			    TRUE,
-			    TRUE,
-			    1);
-	gtk_box_pack_start (GTK_BOX (custom->box),
-			    custom->foot,
-			    FALSE,
-			    FALSE,
-			    1);
-	gtk_box_pack_end (GTK_BOX (custom->box),
-			  btbox,
-			  FALSE,
-			  FALSE,
-			  1);
-	
-	gtk_widget_show_all (custom->box);
-}
-
-static void
 create_completion(void)
 {
 	GscProviderTest *prov_test;
 	GscProviderDevhelp *prov_devhelp;
 	GtkSourceCompletionTriggerKey *ur_trigger;
 	GtkSourceCompletionTriggerWords *words_trigger;
-	CustomWidget *custom;
-	GtkSourceCompletionInfo *info;
+	GtkSourceCompletionPage *page;
 	
-	prov_test = gsc_provider_test_new ();
+	comp = gtk_source_view_get_completion (GTK_SOURCE_VIEW (view));
+	page = gtk_source_completion_add_page (comp, "Second page");
+	
+	prov_test = gsc_provider_test_new (page);
 	prov_devhelp = gsc_provider_devhelp_new (GTK_SOURCE_VIEW (view));
 	
-	comp = gtk_source_view_get_completion (GTK_SOURCE_VIEW (view));
+	
 	
 	ur_trigger = gtk_source_completion_trigger_key_new (comp, "Key Trigger");
 	
-	gtk_source_completion_add_trigger (comp, GTK_SOURCE_COMPLETION_TRIGGER (ur_trigger));
-
 	gtk_source_completion_add_provider (comp, GTK_SOURCE_COMPLETION_PROVIDER (prov_test),
 					    GTK_SOURCE_COMPLETION_TRIGGER (ur_trigger));
 
@@ -338,39 +202,11 @@
 	
 	words_trigger = gtk_source_completion_trigger_words_new (comp);
 	
-	gtk_source_completion_add_trigger (comp, GTK_SOURCE_COMPLETION_TRIGGER (words_trigger));
-	
 	gtk_source_completion_add_provider (comp, GTK_SOURCE_COMPLETION_PROVIDER (prov_devhelp),
 					    GTK_SOURCE_COMPLETION_TRIGGER (words_trigger));
 	
 	gtk_source_completion_add_provider (comp, GTK_SOURCE_COMPLETION_PROVIDER (prov_test),
 					    GTK_SOURCE_COMPLETION_TRIGGER (words_trigger));
-	
-	g_signal_connect (comp, "show", G_CALLBACK (show_completion_cb), NULL);
-	g_signal_connect (comp, "hide", G_CALLBACK (hide_completion_cb), NULL);
-	
-	/* Custom Widget */
-	custom = g_slice_new (CustomWidget);
-	
-	create_custom_info_widget (custom);
-	g_signal_connect(comp, "display-info",
-			 G_CALLBACK(display_info_cb),
-			 custom);
-			 
-	info = gtk_source_completion_get_info_widget (comp);
-	gtk_source_completion_info_set_custom (info, custom->box);
-}
-
-static void
-create_info ()
-{
-	info = gtk_source_completion_info_new ();
-	gtk_source_completion_info_set_adjust_height (info,
-						      TRUE,
-						      -1);
-	gtk_source_completion_info_set_adjust_width (info,
-						     TRUE,
-						     -1);
 }
 
 int
@@ -383,10 +219,6 @@
 
 	window = create_window ();
 	create_completion ();
-	create_info ();
-	
-	g_assert (gtk_source_completion_get_n_pages (comp) == 1);
-	gtk_source_completion_set_page_pos (comp, FIXED_PAGE, 0);
 	
 	gtk_widget_show_all (window);
 

Modified: branches/gtksourcecompletion/tests/gsc-provider-devhelp.c
==============================================================================
--- branches/gtksourcecompletion/tests/gsc-provider-devhelp.c	(original)
+++ branches/gtksourcecompletion/tests/gsc-provider-devhelp.c	Sun Apr 12 19:47:46 2009
@@ -34,6 +34,12 @@
 				         GtkSourceCompletionTrigger  *trigger)
 {
 	GscProviderDevhelp *devhelp = GSC_PROVIDER_DEVHELP(base);
+	static GdkPixbuf *pixbuf = NULL;
+	
+	if (pixbuf == NULL)
+	{
+		pixbuf = gdk_pixbuf_new_from_file ("/usr/share/icons/hicolor/16x16/apps/devhelp.png", NULL);
+	}
 	
 	gchar *word = gsc_get_last_word (GTK_TEXT_VIEW (devhelp->priv->view));
 	
@@ -43,7 +49,7 @@
 	for (; items; items = g_list_next(items))
 	{
 		DhLink *link = (DhLink *)items->data;
-		ret = g_list_prepend(ret, gtk_source_completion_item_new (link->name, NULL, link->uri));
+		ret = g_list_prepend(ret, gtk_source_completion_item_new (link->name, pixbuf, link->uri));
 	}
 
 	g_free(word);

Modified: branches/gtksourcecompletion/tests/gsc-provider-test.c
==============================================================================
--- branches/gtksourcecompletion/tests/gsc-provider-test.c	(original)
+++ branches/gtksourcecompletion/tests/gsc-provider-test.c	Sun Apr 12 19:47:46 2009
@@ -20,8 +20,15 @@
 #include "gsc-provider-test.h"
 #include <gtksourceview/gtksourcecompletionitem.h>
 
+#define GSC_PROVIDER_TEST_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE((object), GSC_TYPE_PROVIDER_TEST, GscProviderTestPrivate))
+
 static void	 gsc_provider_test_iface_init	(GtkSourceCompletionProviderIface *iface);
 
+struct _GscProviderTestPrivate
+{
+	GtkSourceCompletionPage *page;
+};
+
 G_DEFINE_TYPE_WITH_CODE (GscProviderTest,
 			 gsc_provider_test,
 			 G_TYPE_OBJECT,
@@ -34,49 +41,32 @@
 	return GSC_PROVIDER_TEST_NAME;
 }
 
-static GList* 
+static GList *
+append_item (GList *list, const gchar *name, GdkPixbuf *icon, const gchar *info, GtkSourceCompletionPage *page)
+{
+	GtkSourceCompletionItem *prop;
+	
+	prop = gtk_source_completion_item_new (name, icon, info);
+	g_object_set_data (G_OBJECT (prop), "GscProviderTestPage", page);
+
+	return g_list_append (list, prop);
+}
+
+static GList *
 gsc_provider_test_real_get_proposals (GtkSourceCompletionProvider *base,
 				      GtkSourceCompletionTrigger  *trigger)
 {
+	GscProviderTest *self = GSC_PROVIDER_TEST (base);
 	GList *list = NULL;
-	GtkSourceCompletionItem *prop;
 	
-	prop = gtk_source_completion_item_new ("Proposal 1",
-	                                       NULL,
-	                                       "Info proposal 1");
-
-	list = g_list_append (list, prop);
-	prop = gtk_source_completion_item_new ("Proposal 2",
-	                                       NULL,
-	                                       "Info proposal 2");
-
-	list = g_list_append (list, prop);
-	prop = gtk_source_completion_item_new ("Proposal 3",
-	                                       NULL,
-	                                       "Info proposal 3");
-	list = g_list_append (list, prop);
-	
-	/*Page 2*/
-	/*prop = gtk_source_completion_proposal_new("Proposal 1,2",
-				"Info proposal 1,2",
-				NULL);
-	gtk_source_completion_proposal_set_page_name(prop,"Page 2");
-	list = g_list_append (list, prop);
-	prop = gtk_source_completion_proposal_new("Proposal 2,2",
-				"Info proposal 2,2",
-				NULL);
-	gtk_source_completion_proposal_set_page_name(prop,"Page 2");
-	list = g_list_append (list, prop);
-	prop = gtk_source_completion_proposal_new("Proposal 3,3",
-				"Info proposal 3,3",
-				NULL);
-	gtk_source_completion_proposal_set_page_name(prop,"Page 3");
-	list = g_list_append (list, prop);
-	prop = gtk_source_completion_proposal_new("Proposal Fixed page",
-				"Info proposal fixed",
-				NULL);
-	gtk_source_completion_proposal_set_page_name(prop,"Fixed");
-	list = g_list_append (list, prop);*/
+	list = append_item (list, "Proposal 1.1", NULL, "Info proposal 1.1", NULL);
+	list = append_item (list, "Proposal 1.2", NULL, "Info proposal 1.2", NULL);
+	list = append_item (list, "Proposal 1.3", NULL, "Info proposal 1.3", NULL);
+	
+	list = append_item (list, "Proposal 2.1", NULL, "Info proposal 2.1", self->priv->page);
+	list = append_item (list, "Proposal 2.2", NULL, "Info proposal 2.2", self->priv->page);
+	list = append_item (list, "Proposal 2.3", NULL, "Info proposal 2.3", self->priv->page);
+
 	return list;
 }
 
@@ -90,7 +80,18 @@
 static void 
 gsc_provider_test_class_init (GscProviderTestClass *klass)
 {
-	G_OBJECT_CLASS (klass)->finalize = gsc_provider_test_finalize;
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+	
+	object_class->finalize = gsc_provider_test_finalize;
+	
+	g_type_class_add_private (object_class, sizeof(GscProviderTestPrivate));
+}
+
+static GtkSourceCompletionPage *
+gsc_provider_test_real_get_page (GtkSourceCompletionProvider *provider,
+                                 GtkSourceCompletionProposal *proposal)
+{
+	return g_object_get_data (G_OBJECT (proposal), "GscProviderTestPage");
 }
 
 static void
@@ -98,17 +99,20 @@
 {
 	iface->get_name = gsc_provider_test_real_get_name;
 	iface->get_proposals = gsc_provider_test_real_get_proposals;
+	iface->get_page = gsc_provider_test_real_get_page;
 }
 
-
 static void 
 gsc_provider_test_init (GscProviderTest * self)
 {
+	self->priv = GSC_PROVIDER_TEST_GET_PRIVATE (self);
 }
 
 GscProviderTest *
-gsc_provider_test_new ()
+gsc_provider_test_new (GtkSourceCompletionPage *page)
 {
-	return GSC_PROVIDER_TEST (g_object_new (GSC_TYPE_PROVIDER_TEST, NULL));
+	GscProviderTest *ret = g_object_new (GSC_TYPE_PROVIDER_TEST, NULL);
+	ret->priv->page = page;
+	
+	return ret;
 }
-

Modified: branches/gtksourcecompletion/tests/gsc-provider-test.h
==============================================================================
--- branches/gtksourcecompletion/tests/gsc-provider-test.h	(original)
+++ branches/gtksourcecompletion/tests/gsc-provider-test.h	Sun Apr 12 19:47:46 2009
@@ -35,11 +35,14 @@
 #define GSC_PROVIDER_TEST_NAME "GscProviderTest"
 
 typedef struct _GscProviderTest GscProviderTest;
+typedef struct _GscProviderTestPrivate GscProviderTestPrivate;
 typedef struct _GscProviderTestClass GscProviderTestClass;
 
 struct _GscProviderTest
 {
 	GObject parent;
+	
+	GscProviderTestPrivate *priv;
 };
 
 struct _GscProviderTestClass
@@ -49,7 +52,7 @@
 
 GType		 gsc_provider_test_get_type	(void) G_GNUC_CONST;
 
-GscProviderTest *gsc_provider_test_new (void);
+GscProviderTest *gsc_provider_test_new (GtkSourceCompletionPage *page);
 
 G_END_DECLS
 



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