Support inline-selection in entries (#318459)

Support inline-selection in entries (#318459)
	
	* gtk/gtkentry.c:
	* gtk/gtkentrycompletion.c:
	* gtk/gtkentrycompletion.h:
	* gtk/gtkentryprivate.h:

	When enabled cursor-match is emited when the cursor is on
	a possible completion on the list. The default implementation
	will replace the contents on the entry with the contents of
	the text column in the completion model.

	Review and improvements by Matthias Clasen.

svn path=/trunk/; revision=17660
This commit is contained in:
Xan Lopez 2007-04-27 16:50:04 +00:00
parent 533d3fcc76
commit f478d9f0f6
5 changed files with 216 additions and 9 deletions

View File

@ -1,3 +1,19 @@
2007-04-27 Xan Lopez <xan@gnome.org>
Support inline-selection in entries (#318459)
* gtk/gtkentry.c:
* gtk/gtkentrycompletion.c:
* gtk/gtkentrycompletion.h:
* gtk/gtkentryprivate.h:
When enabled cursor-match is emited when the cursor is on
a possible completion on the list. The default implementation
will replace the contents on the entry with the contents of
the text column in the completion model.
Review and improvements by Matthias Clasen.
2007-04-27 Michael Natterer <mitch@imendio.com>
Merged heavily modified patch from maemo-gtk which enables opening

View File

@ -5679,6 +5679,22 @@ gtk_entry_completion_key_press (GtkWidget *widget,
path = gtk_tree_path_new_from_indices (completion->priv->current_selected, -1);
gtk_tree_view_set_cursor (GTK_TREE_VIEW (completion->priv->tree_view),
path, NULL, FALSE);
if (completion->priv->inline_selection)
{
GtkTreeIter iter;
GtkTreeModel *model = NULL;
GtkTreeSelection *sel;
gboolean entry_set;
sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (completion->priv->tree_view));
if (!gtk_tree_selection_get_selected (sel, &model, &iter))
return FALSE;
g_signal_emit_by_name (completion, "cursor_on_match", model,
&iter, &entry_set);
}
}
else if (completion->priv->current_selected - matches >= 0)
{
@ -5693,11 +5709,23 @@ gtk_entry_completion_key_press (GtkWidget *widget,
return TRUE;
}
else if (event->keyval == GDK_Escape)
else if (event->keyval == GDK_Escape ||
event->keyval == GDK_Left ||
event->keyval == GDK_KP_Left ||
event->keyval == GDK_Right ||
event->keyval == GDK_KP_Right)
{
_gtk_entry_reset_im_context (GTK_ENTRY (widget));
_gtk_entry_completion_popdown (completion);
if (completion->priv->inline_selection)
{
if (event->keyval == GDK_Escape)
gtk_editable_delete_selection (GTK_EDITABLE (widget));
/* Move the cursor to the end */
gtk_editable_set_position (GTK_EDITABLE (widget), -1);
}
return TRUE;
}
else if (event->keyval == GDK_Tab ||
@ -5750,7 +5778,7 @@ gtk_entry_completion_key_press (GtkWidget *widget,
/* move the cursor to the end */
gtk_editable_set_position (GTK_EDITABLE (widget), -1);
g_free (str);
g_free (str);
}
return TRUE;
@ -5880,12 +5908,18 @@ disconnect_completion_signals (GtkEntry *entry,
G_CALLBACK (completion_changed), entry);
if (completion->priv->changed_id > 0 &&
g_signal_handler_is_connected (entry, completion->priv->changed_id))
g_signal_handler_disconnect (entry, completion->priv->changed_id);
{
g_signal_handler_disconnect (entry, completion->priv->changed_id);
completion->priv->changed_id = 0;
}
g_signal_handlers_disconnect_by_func (entry,
G_CALLBACK (gtk_entry_completion_key_press), completion);
if (completion->priv->insert_text_id > 0 &&
g_signal_handler_is_connected (entry, completion->priv->insert_text_id))
g_signal_handler_disconnect (entry, completion->priv->insert_text_id);
{
g_signal_handler_disconnect (entry, completion->priv->insert_text_id);
completion->priv->insert_text_id = 0;
}
g_signal_handlers_disconnect_by_func (entry,
G_CALLBACK (completion_insert_text_callback), completion);
g_signal_handlers_disconnect_by_func (entry,
@ -5919,6 +5953,7 @@ connect_completion_signals (GtkEntry *entry,
g_signal_connect (entry, "focus_out_event",
G_CALLBACK (accept_completion_callback), completion);
}
g_signal_connect (completion, "notify",
G_CALLBACK (completion_changed), entry);
}

View File

@ -47,6 +47,7 @@ enum
INSERT_PREFIX,
MATCH_SELECTED,
ACTION_ACTIVATED,
CURSOR_ON_MATCH,
LAST_SIGNAL
};
@ -60,7 +61,8 @@ enum
PROP_INLINE_COMPLETION,
PROP_POPUP_COMPLETION,
PROP_POPUP_SET_WIDTH,
PROP_POPUP_SINGLE_MATCH
PROP_POPUP_SINGLE_MATCH,
PROP_INLINE_SELECTION
};
#define GTK_ENTRY_COMPLETION_GET_PRIVATE(obj)(G_TYPE_INSTANCE_GET_PRIVATE ((obj), GTK_TYPE_ENTRY_COMPLETION, GtkEntryCompletionPrivate))
@ -136,6 +138,9 @@ static gboolean gtk_entry_completion_match_selected (GtkEntryCompletion *co
GtkTreeIter *iter);
static gboolean gtk_entry_completion_real_insert_prefix (GtkEntryCompletion *completion,
const gchar *prefix);
static gboolean gtk_entry_completion_cursor_on_match (GtkEntryCompletion *completion,
GtkTreeModel *model,
GtkTreeIter *iter);
static guint entry_completion_signals[LAST_SIGNAL] = { 0 };
@ -156,6 +161,7 @@ gtk_entry_completion_class_init (GtkEntryCompletionClass *klass)
klass->match_selected = gtk_entry_completion_match_selected;
klass->insert_prefix = gtk_entry_completion_real_insert_prefix;
klass->cursor_on_match = gtk_entry_completion_cursor_on_match;
/**
* GtkEntryCompletion::insert-prefix:
@ -210,6 +216,32 @@ gtk_entry_completion_class_init (GtkEntryCompletionClass *klass)
G_TYPE_BOOLEAN, 2,
GTK_TYPE_TREE_MODEL,
GTK_TYPE_TREE_ITER);
/**
* GtkEntryCompletion::cursor-on-match:
* @widget: the object which received the signal
* @model: the #GtkTreeModel containing the matches
* @iter: a #GtkTreeIter positioned at the selected match
*
* Gets emitted when a match from the cursor is on a match
* of the list.The default behaviour is to replace the contents
* of the entry with the contents of the text column in the row
* pointed to by @iter.
*
* Return value: %TRUE if the signal has been handled
*
* Since: 2.12
*/
entry_completion_signals[CURSOR_ON_MATCH] =
g_signal_new (I_("cursor_on_match"),
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GtkEntryCompletionClass, cursor_on_match),
_gtk_boolean_handled_accumulator, NULL,
_gtk_marshal_BOOLEAN__OBJECT_BOXED,
G_TYPE_BOOLEAN, 2,
GTK_TYPE_TREE_MODEL,
GTK_TYPE_TREE_ITER);
/**
* GtkEntryCompletion::action-activated:
@ -330,6 +362,21 @@ gtk_entry_completion_class_init (GtkEntryCompletionClass *klass)
P_("If TRUE, the popup window will appear for a single match."),
TRUE,
GTK_PARAM_READWRITE));
/**
* GtkEntryCompletion:inline-selection:
*
* Determines whether the possible completions on the popup
* will appear in the entry as you navigate through them.
* Since: 2.12
*/
g_object_class_install_property (object_class,
PROP_INLINE_SELECTION,
g_param_spec_boolean ("inline-selection",
P_("Inline selection"),
P_("Your description here"),
FALSE,
GTK_PARAM_READWRITE));
g_type_class_add_private (object_class, sizeof (GtkEntryCompletionPrivate));
}
@ -364,6 +411,7 @@ gtk_entry_completion_init (GtkEntryCompletion *completion)
priv->popup_completion = TRUE;
priv->popup_set_width = TRUE;
priv->popup_single_match = TRUE;
priv->inline_selection = FALSE;
/* completions */
priv->filter_model = NULL;
@ -378,6 +426,7 @@ gtk_entry_completion_init (GtkEntryCompletion *completion)
g_signal_connect (priv->tree_view, "motion_notify_event",
G_CALLBACK (gtk_entry_completion_list_motion_notify),
completion);
gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (priv->tree_view), FALSE);
gtk_tree_view_set_hover_selection (GTK_TREE_VIEW (priv->tree_view), TRUE);
@ -505,6 +554,10 @@ gtk_entry_completion_set_property (GObject *object,
priv->popup_single_match = g_value_get_boolean (value);
break;
case PROP_INLINE_SELECTION:
priv->inline_selection = g_value_get_boolean (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@ -550,6 +603,10 @@ gtk_entry_completion_get_property (GObject *object,
g_value_set_boolean (value, gtk_entry_completion_get_popup_single_match (completion));
break;
case PROP_INLINE_SELECTION:
g_value_set_boolean (value, gtk_entry_completion_get_inline_selection (completion));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@ -1277,7 +1334,7 @@ gtk_entry_completion_list_motion_notify (GtkWidget *widget,
{
GtkEntryCompletion *completion = GTK_ENTRY_COMPLETION (data);
completion->priv->ignore_enter = FALSE;
completion->priv->ignore_enter = FALSE;
return FALSE;
}
@ -1468,6 +1525,15 @@ gtk_entry_completion_match_selected (GtkEntryCompletion *completion,
return TRUE;
}
static gboolean
gtk_entry_completion_cursor_on_match (GtkEntryCompletion *completion,
GtkTreeModel *model,
GtkTreeIter *iter)
{
gtk_entry_completion_insert_completion (completion, model, iter);
return TRUE;
}
static gchar *
gtk_entry_completion_compute_prefix (GtkEntryCompletion *completion)
@ -1565,6 +1631,65 @@ gtk_entry_completion_real_insert_prefix (GtkEntryCompletion *completion,
return TRUE;
}
void
gtk_entry_completion_insert_completion_text (GtkEntryCompletion *completion,
const gchar *text)
{
GtkEntryCompletionPrivate *priv = completion->priv;
gint len;
if (priv->changed_id > 0)
{
g_signal_handler_block (priv->entry,
priv->changed_id);
}
if (priv->insert_text_id > 0)
{
g_signal_handler_block (completion->priv->entry,
completion->priv->insert_text_id);
}
gtk_editable_get_selection_bounds (GTK_EDITABLE (priv->entry), &len, NULL);
gtk_entry_set_text (GTK_ENTRY (priv->entry), text);
gtk_editable_select_region (GTK_EDITABLE (priv->entry), len, -1);
if (priv->changed_id > 0)
{
g_signal_handler_unblock (priv->entry,
priv->changed_id);
}
if (priv->insert_text_id > 0)
{
g_signal_handler_unblock (priv->entry,
priv->insert_text_id);
}
}
gboolean
gtk_entry_completion_insert_completion (GtkEntryCompletion *completion,
GtkTreeModel *model,
GtkTreeIter *iter)
{
gchar *str = NULL;
g_return_val_if_fail (GTK_IS_TREE_MODEL (model), FALSE);
if (completion->priv->text_column < 0)
return FALSE;
gtk_tree_model_get (model, iter,
completion->priv->text_column, &str,
-1);
gtk_entry_completion_insert_completion_text (completion, str);
g_free (str);
return TRUE;
}
/**
* gtk_entry_completion_insert_prefix:
* @completion: a #GtkEntryCompletion
@ -1573,6 +1698,7 @@ gtk_entry_completion_real_insert_prefix (GtkEntryCompletion *completion,
*
* Since: 2.6
**/
void
gtk_entry_completion_insert_prefix (GtkEntryCompletion *completion)
{
@ -1622,7 +1748,6 @@ gtk_entry_completion_set_inline_completion (GtkEntryCompletion *completion,
}
}
/**
* gtk_entry_completion_get_inline_completion:
* @completion: a #GtkEntryCompletion
@ -1782,6 +1907,29 @@ gtk_entry_completion_get_popup_single_match (GtkEntryCompletion *completion)
return completion->priv->popup_single_match;
}
void
gtk_entry_completion_set_inline_selection (GtkEntryCompletion *completion,
gboolean inline_selection)
{
g_return_if_fail (GTK_IS_ENTRY_COMPLETION (completion));
inline_selection = inline_selection != FALSE;
if (completion->priv->inline_selection != inline_selection)
{
completion->priv->inline_selection = inline_selection;
g_object_notify (G_OBJECT (completion), "inline-selection");
}
}
gboolean
gtk_entry_completion_get_inline_selection (GtkEntryCompletion *completion)
{
g_return_val_if_fail (GTK_IS_ENTRY_COMPLETION (completion), FALSE);
return completion->priv->inline_selection;
}
#define __GTK_ENTRY_COMPLETION_C__
#include "gtkaliasdef.c"

View File

@ -65,11 +65,13 @@ struct _GtkEntryCompletionClass
gint index_);
gboolean (* insert_prefix) (GtkEntryCompletion *completion,
const gchar *prefix);
gboolean (* cursor_on_match) (GtkEntryCompletion *completion,
GtkTreeModel *model,
GtkTreeIter *iter);
/* Padding for future expansion */
void (*_gtk_reserved0) (void);
void (*_gtk_reserved1) (void);
void (*_gtk_reserved2) (void);
};
/* core */
@ -104,6 +106,9 @@ void gtk_entry_completion_delete_action (GtkEntryComplet
void gtk_entry_completion_set_inline_completion (GtkEntryCompletion *completion,
gboolean inline_completion);
gboolean gtk_entry_completion_get_inline_completion (GtkEntryCompletion *completion);
void gtk_entry_completion_set_inline_selection (GtkEntryCompletion *completion,
gboolean inline_selection);
gboolean gtk_entry_completion_get_inline_selection (GtkEntryCompletion *completion);
void gtk_entry_completion_set_popup_completion (GtkEntryCompletion *completion,
gboolean popup_completion);
gboolean gtk_entry_completion_get_popup_completion (GtkEntryCompletion *completion);
@ -114,7 +119,8 @@ void gtk_entry_completion_set_popup_single_match (GtkEntryComplet
gboolean popup_single_match);
gboolean gtk_entry_completion_get_popup_single_match (GtkEntryCompletion *completion);
void gtk_entry_completion_insert_completion_text (GtkEntryCompletion *completion,
const gchar *text);
/* convenience */
void gtk_entry_completion_set_text_column (GtkEntryCompletion *completion,
gint column);

View File

@ -64,6 +64,8 @@ struct _GtkEntryCompletionPrivate
guint popup_completion : 1;
guint popup_set_width : 1;
guint popup_single_match : 1;
guint inline_selection : 1;
GSource *check_completion_idle;
};