[gtksourceview] Completion: simplify move_cursor()



commit ca2a7ee2ad0bdf474ba90aa25fc9dd10b313e229
Author: Sébastien Wilmet <swilmet gnome org>
Date:   Mon Feb 25 23:05:42 2013 +0100

    Completion: simplify move_cursor()
    
    Add some higher level functions in the CompletionModel.

 gtksourceview/gtksourcecompletion.c      |  263 ++++++++----------------------
 gtksourceview/gtksourcecompletionmodel.c |   94 +++++++++++
 gtksourceview/gtksourcecompletionmodel.h |   16 ++
 3 files changed, 176 insertions(+), 197 deletions(-)
---
diff --git a/gtksourceview/gtksourcecompletion.c b/gtksourceview/gtksourcecompletion.c
index d56615c..5593c25 100644
--- a/gtksourceview/gtksourcecompletion.c
+++ b/gtksourceview/gtksourcecompletion.c
@@ -390,66 +390,27 @@ gtk_source_completion_activate_proposal (GtkSourceCompletion *completion)
        g_object_unref (proposal);
 }
 
-typedef gboolean (*ProposalSelector)(GtkSourceCompletion *completion,
-                                     GtkTreeModel        *model,
-                                     GtkTreeIter         *iter,
-                                     gboolean             hasselection,
-                                     gpointer             userdata);
-
-static gboolean
-select_proposal (GtkSourceCompletion *completion,
-                 ProposalSelector     selector,
-                 gpointer             userdata)
+static void
+scroll_to_iter (GtkSourceCompletion *completion,
+                GtkTreeIter         *iter)
 {
-       GtkTreeSelection *selection;
-       GtkTreeIter iter;
        GtkTreePath *path;
-       GtkTreeModel *model;
-       gboolean hasselection;
+       GtkTreeIter prev_iter = *iter;
 
-       if (!gtk_widget_get_visible (GTK_WIDGET (completion->priv->tree_view_proposals)))
+       /* If we want to scroll to the first proposal of a provider, it's better
+        * to show the header too, if there is a header. */
+       if (gtk_source_completion_model_iter_previous (completion->priv->model_proposals, &prev_iter) &&
+           gtk_source_completion_model_iter_is_header (completion->priv->model_proposals, &prev_iter))
        {
-               return FALSE;
+               path = gtk_tree_model_get_path (GTK_TREE_MODEL (completion->priv->model_proposals),
+                                               &prev_iter);
        }
-
-       selection = gtk_tree_view_get_selection (completion->priv->tree_view_proposals);
-
-       if (gtk_tree_selection_get_mode (selection) == GTK_SELECTION_NONE)
-       {
-               return FALSE;
-       }
-
-       model = GTK_TREE_MODEL (completion->priv->model_proposals);
-
-       hasselection = gtk_tree_selection_get_selected (selection, NULL, &iter);
-
-       if (selector (completion, model, &iter, hasselection, userdata))
+       else
        {
-               gtk_tree_selection_select_iter (selection, &iter);
-
-               path = gtk_tree_model_get_path (model, &iter);
-               gtk_tree_view_scroll_to_cell (completion->priv->tree_view_proposals,
-                                             path,
-                                             NULL,
-                                             FALSE,
-                                             0,
-                                             0);
-
-               gtk_tree_path_free (path);
+               path = gtk_tree_model_get_path (GTK_TREE_MODEL (completion->priv->model_proposals),
+                                               iter);
        }
 
-       /* Always return TRUE to consume the key press event */
-       return TRUE;
-}
-
-static void
-scroll_to_iter (GtkSourceCompletion *completion,
-                GtkTreeIter         *iter)
-{
-       GtkTreePath *path;
-
-       path = gtk_tree_model_get_path (GTK_TREE_MODEL (completion->priv->model_proposals), iter);
-
        gtk_tree_view_scroll_to_cell (completion->priv->tree_view_proposals,
                                      path,
                                      NULL,
@@ -460,173 +421,66 @@ scroll_to_iter (GtkSourceCompletion *completion,
 }
 
 static gboolean
-selector_first (GtkSourceCompletion *completion,
-                GtkTreeModel        *model,
-                GtkTreeIter         *iter,
-                gboolean             hasselection,
-                gpointer             userdata)
+get_previous_iter (GtkSourceCompletion *completion,
+                  gint                 num,
+                  GtkTreeIter         *iter)
 {
-       gboolean ret;
-       gboolean hasfirst;
-       GtkTreeIter first;
-
-       ret = gtk_tree_model_get_iter_first (model, iter);
-       hasfirst = ret;
-       first = *iter;
-
-       while (ret && gtk_source_completion_model_iter_is_header (
-                       GTK_SOURCE_COMPLETION_MODEL (model), iter))
-       {
-               ret = gtk_tree_model_iter_next (model, iter);
-       }
-
-       if (hasfirst && !ret)
-       {
-               scroll_to_iter (completion, &first);
-       }
-
-       return ret;
-}
-
-static gboolean
-selector_last (GtkSourceCompletion *completion,
-               GtkTreeModel        *model,
-               GtkTreeIter         *iter,
-               gboolean             hasselection,
-               gpointer             userdata)
-{
-       gboolean ret;
-       gboolean haslast;
-       GtkTreeIter last;
-
-       ret = gtk_source_completion_model_iter_last (GTK_SOURCE_COMPLETION_MODEL (model),
-                                                    iter);
+       GtkTreeSelection *selection;
+       gboolean has_selection;
 
-       haslast = ret;
-       last = *iter;
+       selection = gtk_tree_view_get_selection (completion->priv->tree_view_proposals);
+       has_selection = gtk_tree_selection_get_selected (selection, NULL, iter);
 
-       while (ret && gtk_source_completion_model_iter_is_header (
-                       GTK_SOURCE_COMPLETION_MODEL (model), iter))
+       if (!has_selection)
        {
-               ret = gtk_source_completion_model_iter_previous (GTK_SOURCE_COMPLETION_MODEL (model),
-                                                                iter);
+               return gtk_source_completion_model_last_proposal (completion->priv->model_proposals,
+                                                                 iter);
        }
 
-       if (haslast && !ret)
+       while (num > 0)
        {
-               scroll_to_iter (completion, &last);
-       }
-
-       return ret;
-}
-
-static gboolean
-selector_previous (GtkSourceCompletion *completion,
-                   GtkTreeModel        *model,
-                   GtkTreeIter         *iter,
-                   gboolean             hasselection,
-                   gpointer             userdata)
-{
-       gint num = GPOINTER_TO_INT (userdata);
-       gboolean ret = FALSE;
-       GtkTreeIter next;
-       GtkTreeIter last;
-
-       if (!hasselection)
-       {
-               return selector_last (completion, model, iter, hasselection, userdata);
-       }
-
-       next = *iter;
-       last = *iter;
-
-       while (num > 0 && gtk_source_completion_model_iter_previous (
-                               GTK_SOURCE_COMPLETION_MODEL (model), &next))
-       {
-               if (!gtk_source_completion_model_iter_is_header (GTK_SOURCE_COMPLETION_MODEL (model),
-                                                                &next))
+               if (!gtk_source_completion_model_previous_proposal (completion->priv->model_proposals,
+                                                                   iter))
                {
-                       ret = TRUE;
-                       *iter = next;
-                       --num;
+                       return gtk_source_completion_model_first_proposal (completion->priv->model_proposals,
+                                                                          iter);
                }
 
-               last = next;
-       }
-
-       if (!ret)
-       {
-               scroll_to_iter (completion, &last);
+               num--;
        }
 
-       return ret;
+       return TRUE;
 }
 
 static gboolean
-selector_next (GtkSourceCompletion *completion,
-               GtkTreeModel        *model,
-               GtkTreeIter         *iter,
-               gboolean             hasselection,
-               gpointer             userdata)
+get_next_iter (GtkSourceCompletion *completion,
+              gint                 num,
+              GtkTreeIter         *iter)
 {
-       gint num = GPOINTER_TO_INT (userdata);
-       gboolean ret = FALSE;
-       GtkTreeIter next;
-       GtkTreeIter last;
+       GtkTreeSelection *selection;
+       gboolean has_selection;
 
-       if (!hasselection)
+       selection = gtk_tree_view_get_selection (completion->priv->tree_view_proposals);
+       has_selection = gtk_tree_selection_get_selected (selection, NULL, iter);
+
+       if (!has_selection)
        {
-               return selector_first (completion, model, iter, hasselection, userdata);
+               return gtk_source_completion_model_first_proposal (completion->priv->model_proposals,
+                                                                  iter);
        }
 
-       next = *iter;
-       last = *iter;
-
-       while (num > 0 && gtk_tree_model_iter_next (model, &next))
+       while (num > 0)
        {
-               if (!gtk_source_completion_model_iter_is_header (GTK_SOURCE_COMPLETION_MODEL (model),
-                                                                &next))
+               if (!gtk_source_completion_model_next_proposal (completion->priv->model_proposals, iter))
                {
-                       ret = TRUE;
-                       *iter = next;
-                       --num;
+                       return gtk_source_completion_model_last_proposal (completion->priv->model_proposals,
+                                                                         iter);
                }
 
-               last = next;
-       }
-
-       if (!ret)
-       {
-               scroll_to_iter (completion, &last);
+               num--;
        }
 
-       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));
+       return TRUE;
 }
 
 static GtkSourceCompletionProvider *
@@ -1099,15 +953,20 @@ gtk_source_completion_move_cursor (GtkSourceCompletion *completion,
                                    GtkScrollStep        step,
                                    gint                 num)
 {
+       GtkTreeIter iter;
+       gboolean ok;
+
        if (step == GTK_SCROLL_ENDS)
        {
                if (num > 0)
                {
-                       select_last_proposal (completion);
+                       ok = gtk_source_completion_model_last_proposal (completion->priv->model_proposals,
+                                                                       &iter);
                }
                else
                {
-                       select_first_proposal (completion);
+                       ok = gtk_source_completion_model_first_proposal (completion->priv->model_proposals,
+                                                                        &iter);
                }
        }
        else
@@ -1119,13 +978,23 @@ gtk_source_completion_move_cursor (GtkSourceCompletion *completion,
 
                if (num > 0)
                {
-                       select_next_proposal (completion, num);
+                       ok = get_next_iter (completion, num, &iter);
                }
                else
                {
-                       select_previous_proposal (completion, -1 * num);
+                       ok = get_previous_iter (completion, -1 * num, &iter);
                }
        }
+
+       if (ok)
+       {
+               GtkTreeSelection *selection;
+
+               selection = gtk_tree_view_get_selection (completion->priv->tree_view_proposals);
+               gtk_tree_selection_select_iter (selection, &iter);
+
+               scroll_to_iter (completion, &iter);
+       }
 }
 
 static void
diff --git a/gtksourceview/gtksourcecompletionmodel.c b/gtksourceview/gtksourcecompletionmodel.c
index 4d1f57f..edd2cfb 100644
--- a/gtksourceview/gtksourcecompletionmodel.c
+++ b/gtksourceview/gtksourcecompletionmodel.c
@@ -1128,6 +1128,100 @@ gtk_source_completion_model_get_providers (GtkSourceCompletionModel *model)
        return g_list_reverse (ret);
 }
 
+/* Get the first proposal. Headers are skipped.
+ * Returns TRUE on success.
+ */
+gboolean
+gtk_source_completion_model_first_proposal (GtkSourceCompletionModel *model,
+                                           GtkTreeIter              *iter)
+{
+       g_return_val_if_fail (GTK_SOURCE_IS_COMPLETION_MODEL (model), FALSE);
+       g_return_val_if_fail (iter != NULL, FALSE);
+
+       if (!gtk_tree_model_get_iter_first (GTK_TREE_MODEL (model), iter))
+       {
+               return FALSE;
+       }
+
+       while (gtk_source_completion_model_iter_is_header (model, iter))
+       {
+               if (!gtk_tree_model_iter_next (GTK_TREE_MODEL (model), iter))
+               {
+                       return FALSE;
+               }
+       }
+
+       return TRUE;
+}
+
+/* Get the last proposal. Headers are skipped.
+ * Returns TRUE on success.
+ */
+gboolean
+gtk_source_completion_model_last_proposal (GtkSourceCompletionModel *model,
+                                          GtkTreeIter              *iter)
+{
+       g_return_val_if_fail (GTK_SOURCE_IS_COMPLETION_MODEL (model), FALSE);
+       g_return_val_if_fail (iter != NULL, FALSE);
+
+       if (!gtk_source_completion_model_iter_last (model, iter))
+       {
+               return FALSE;
+       }
+
+       while (gtk_source_completion_model_iter_is_header (model, iter))
+       {
+               if (!gtk_source_completion_model_iter_previous (model, iter))
+               {
+                       return FALSE;
+               }
+       }
+
+       return TRUE;
+}
+
+/* Get the next proposal. Headers are skipped.
+ * Returns TRUE on success.
+ */
+gboolean
+gtk_source_completion_model_next_proposal (GtkSourceCompletionModel *model,
+                                          GtkTreeIter              *iter)
+{
+       g_return_val_if_fail (GTK_SOURCE_IS_COMPLETION_MODEL (model), FALSE);
+       g_return_val_if_fail (iter != NULL && iter->user_data != NULL, FALSE);
+
+       do
+       {
+               if (!gtk_tree_model_iter_next (GTK_TREE_MODEL (model), iter))
+               {
+                       return FALSE;
+               }
+       } while (gtk_source_completion_model_iter_is_header (model, iter));
+
+       return TRUE;
+}
+
+/* Get the previous proposal. Headers are skipped.
+ * Returns TRUE on success.
+ */
+gboolean
+gtk_source_completion_model_previous_proposal (GtkSourceCompletionModel *model,
+                                              GtkTreeIter              *iter)
+{
+       g_return_val_if_fail (GTK_SOURCE_IS_COMPLETION_MODEL (model), FALSE);
+       g_return_val_if_fail (iter != NULL && iter->user_data != NULL, FALSE);
+
+       do
+       {
+               if (!gtk_source_completion_model_iter_previous (model, iter))
+               {
+                       return FALSE;
+               }
+       } while (gtk_source_completion_model_iter_is_header (model, iter));
+
+       return TRUE;
+}
+
 gboolean
 gtk_source_completion_model_iter_equal (GtkSourceCompletionModel *model,
                                         GtkTreeIter              *iter1,
diff --git a/gtksourceview/gtksourcecompletionmodel.h b/gtksourceview/gtksourcecompletionmodel.h
index 983999f..e0b52c8 100644
--- a/gtksourceview/gtksourcecompletionmodel.h
+++ b/gtksourceview/gtksourcecompletionmodel.h
@@ -108,6 +108,22 @@ gboolean gtk_source_completion_model_iter_last                     
(GtkSourceCompletionModel    *m
                                                                 GtkTreeIter                 *iter);
 
 G_GNUC_INTERNAL
+gboolean gtk_source_completion_model_first_proposal             (GtkSourceCompletionModel    *model,
+                                                                GtkTreeIter                 *iter);
+
+G_GNUC_INTERNAL
+gboolean gtk_source_completion_model_last_proposal              (GtkSourceCompletionModel    *model,
+                                                                GtkTreeIter                 *iter);
+
+G_GNUC_INTERNAL
+gboolean gtk_source_completion_model_next_proposal              (GtkSourceCompletionModel    *model,
+                                                                GtkTreeIter                 *iter);
+
+G_GNUC_INTERNAL
+gboolean gtk_source_completion_model_previous_proposal          (GtkSourceCompletionModel    *model,
+                                                                GtkTreeIter                 *iter);
+
+G_GNUC_INTERNAL
 gboolean gtk_source_completion_model_iter_equal                        (GtkSourceCompletionModel    *model,
                                                                 GtkTreeIter                 *iter1,
                                                                 GtkTreeIter                 *iter2);


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