Auto-completion API proposal for GtkEntry



Hi,

So right now we have basically already decided to put the
auto-completion code in GtkEntry. Now the next (slighty more difficult)
step is to design a good API and define a good behaviour. In this mail I
will shed some light on my thoughts. Of course I am open for
suggestions.


Internal Implementation
=======================

Basically my idea is to have the user of the API provide a GtkTreeModel.
GtkEntry would then create a popup window consisting of a GtkTreeView,
displaying a FilterModel wrapping the user-provided GtkTreeModel. Then
we can easily filter completions using the FilterModel. This is all
pretty cool, BUT it's possibly slow with large GtkTreeModels ... (though
filtering happens incrementally so it might not be that bad).

If we really need something faster, then we need to take a completely
different approach. I don't really know which one right now ...


Behaviour
=========

This idea of completion behaviour is based on a discussion in #epiphany.
Basically the idea is to only use a popup window to show the matches,
also if there is only one match or when there are no matches (then we
would display one row saying "No matches" (as we have no write access to
the model, I guess I have to implement this using a trick in the
FilterModel ...)). This is because having both select-ahead and a popup
would be confusing for the users. And people seem to be happy with IE's
completion behaviour (as I got told ...), which also has a popup-only
mechanism.

I think this way we can also avoid the use of tab (I guess the usability
and accessbility folks are going to like that), as we can just display
the popup and allow to user to select a match with the arrows keys and
the enter key. Though the die-hard UNIX folks might hate this :/


API
===

Now I will move on to a short discussion of the API. IIRC I have already
done this in an earlier mail, but I will feel free to repeat it P:


  typedef gboolean (* GtkCompletionFunc) (const gchar *key,
                                          const gchar *item,
                                          GtkTreeIter *iter,
                                          gpointer     user_data);

I think this one speaks for itself. Note that item is a string extracted
from the row indicated by iter. item is provided for convenience, iter
for accessing extra data which might be needed to determine whether this
is a possible completion or not.


  [temporary weird layout to fit things in 80 columns]
  void  gtk_entry_enable_completion  (GtkEntry         *entry,
                                      GtkTreeModel     *model,
                                      gint              list_column,
                                      gint              entry_column,
                                      GtkCompletionFunc func,
                                      gpointer          func_data,
                                      GDestroyNotify    func_destroy);
  gboolean gtk_entry_completion_get_enabled (GtkEntry *entry);

The first function is quite a beast. Most parameters speak for
themselves, maybe except for list_column and entry_column. These
parameters are there in case the user wants the data in the list and the
data to be placed in the entry on a selected match to come from
different columns. Here list_column would be the column where the items
in the popup would come from and the items to be placed in the entry
would come from entry_column.


  [temporary weird layout to fit things in 80 columns]
  GtkTreeViewColumn *gtk_entry_completion_get_column (GtkEntry *entry);
  void gtk_entry_completion_get_model (GtkEntry      *entry,
                                       GtkTreeModel **model,
                                       gint          *list_column);

Both speak for themselves. The get_column method is useful if you want
to add extra cell renderers to the treeview, for example for having an
icon (favicons (: ) next to the side or if you want to have a second
column (URL + document title for example as used in browsers).


  void gtk_entry_set_minimum_key_length (GtkEntry *entry,
                                         gint      length);
  gint gtk_entry_get_minimum_key_length (GtkEntry *entry);

You can use these functions to set a minimum length before the code
starts looking for completions. This is particularly handy when you have
a very big GtkTreeModel so performance will stay at some reasonable
level. The minimum key length will of course default to 1. 


Considerations:
  * API to set max number of matches?
  * There has been some discussion on auto-completion and
    tokens/markers. Something like this is in GnuCash, I guess I just 
    need to try it one day to fully understand it. Not sure if it would
    be worth adding to the API.




thanks,


	-Kris



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