aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--widgets/text/e-completion-test.c18
-rw-r--r--widgets/text/e-completion-view.c33
-rw-r--r--widgets/text/e-completion.c64
-rw-r--r--widgets/text/e-completion.h10
-rw-r--r--widgets/text/e-entry.c65
5 files changed, 91 insertions, 99 deletions
diff --git a/widgets/text/e-completion-test.c b/widgets/text/e-completion-test.c
index 0d846ec9ff..3172cecb13 100644
--- a/widgets/text/e-completion-test.c
+++ b/widgets/text/e-completion-test.c
@@ -134,7 +134,7 @@ begin_dict_search (ECompletion *complete, const gchar *txt, gint pos, gint limit
}
static void
-end_dict_search (ECompletion *complete, gboolean finished, gpointer foo)
+end_dict_search (ECompletion *complete, gpointer user_data)
{
if (dict_tag != 0) {
gtk_timeout_remove (dict_tag);
@@ -153,11 +153,23 @@ main (int argc, gchar **argv)
read_dict ();
- complete = e_completion_new (begin_dict_search, end_dict_search, NULL);
+ complete = e_completion_new ();
+ gtk_signal_connect (GTK_OBJECT (complete),
+ "begin_completion",
+ GTK_SIGNAL_FUNC (begin_dict_search),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (complete),
+ "end_completion",
+ GTK_SIGNAL_FUNC (end_dict_search),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (complete),
+ "cancel_completion",
+ GTK_SIGNAL_FUNC (end_dict_search),
+ NULL);
win = gtk_window_new (GTK_WINDOW_TOPLEVEL);
entry = e_entry_new ();
- e_entry_enable_completion_full (E_ENTRY (entry), complete, 100, NULL);
+ e_entry_enable_completion_full (E_ENTRY (entry), complete, -1, NULL);
e_entry_set_editable (E_ENTRY (entry), TRUE);
gtk_container_add (GTK_CONTAINER (win), entry);
diff --git a/widgets/text/e-completion-view.c b/widgets/text/e-completion-view.c
index e2352ec7a9..825e7c5e11 100644
--- a/widgets/text/e-completion-view.c
+++ b/widgets/text/e-completion-view.c
@@ -305,6 +305,7 @@ e_completion_view_key_press_handler (GtkWidget *w, GdkEventKey *key_event, gpoin
{
ECompletionView *cv = E_COMPLETION_VIEW (user_data);
gint dir = 0;
+ gboolean key_handled = TRUE;
/* Start up a completion.*/
if (cv->complete_key && key_event->keyval == cv->complete_key && !cv->editable) {
@@ -332,13 +333,18 @@ e_completion_view_key_press_handler (GtkWidget *w, GdkEventKey *key_event, gpoin
case GDK_KP_Up:
dir = -1;
break;
+
+ case GDK_Tab:
+ /* Unbrowse, unhandled. */
+ cv->selection = -1;
+ dir = 0;
+ key_handled = FALSE;
+ break;
case GDK_Return:
case GDK_KP_Enter:
case GDK_space:
case GDK_KP_Space:
- case GDK_Right: /* Lynx-style "forward" */
- case GDK_KP_Right:
/* Only handle these key presses if we have an active selection;
otherwise, pass them on. */
if (cv->selection >= 0) {
@@ -353,17 +359,6 @@ e_completion_view_key_press_handler (GtkWidget *w, GdkEventKey *key_event, gpoin
dir = 0;
break;
- case GDK_Left: /* Lynx-style "back" */
- case GDK_KP_Left:
- if (cv->selection >= 0) {
- /* A hack to "unbrowse" us on these keys if we are browsing. */
- cv->selection = -1;
- dir = 0;
- break;
- }
-
- return FALSE;
-
default:
return FALSE;
}
@@ -385,13 +380,14 @@ e_completion_view_key_press_handler (GtkWidget *w, GdkEventKey *key_event, gpoin
gtk_signal_emit (GTK_OBJECT (cv), e_completion_view_signals[E_COMPLETION_VIEW_UNBROWSE]);
stop_emission:
- gtk_signal_emit_stop_by_name (GTK_OBJECT (w), "key_press_event");
+ if (key_handled)
+ gtk_signal_emit_stop_by_name (GTK_OBJECT (w), "key_press_event");
- return TRUE;
+ return key_handled;
}
static void
-begin_completion_cb (ECompletion *completion, gpointer user_data)
+begin_completion_cb (ECompletion *completion, const gchar *txt, gint pos, gint limit, gpointer user_data)
{
ECompletionView *cv = E_COMPLETION_VIEW (user_data);
@@ -405,7 +401,7 @@ static void
restart_completion_cb (ECompletion *completion, gpointer user_data)
{
/* For now, handle restarts like the beginning of a new completion. */
- begin_completion_cb (completion, user_data);
+ begin_completion_cb (completion, NULL, 0, 0, user_data);
}
static void
@@ -557,6 +553,8 @@ e_completion_view_construct (ECompletionView *cv, ECompletion *completion)
cv->table = e_table_scrolled_new (cv->model, NULL, simple_spec, NULL);
+ e_scroll_frame_set_policy (E_SCROLL_FRAME (cv->table), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
+
frame = gtk_frame_new (NULL);
gtk_container_add (GTK_CONTAINER (cv), frame);
@@ -655,6 +653,7 @@ e_completion_view_set_width (ECompletionView *cv, gint width)
e_table_group_compute_location (e_completion_view_table (cv)->group,
&dummy, &line_height, &r, &dummy);
}
+
if (line_height >= 1000) {
/* Something went wrong, so we make a (possibly very lame) guess */
line_height = 30;
diff --git a/widgets/text/e-completion.c b/widgets/text/e-completion.c
index 8b875c7af6..bf12d6a365 100644
--- a/widgets/text/e-completion.c
+++ b/widgets/text/e-completion.c
@@ -50,11 +50,6 @@ struct _Match {
};
struct _ECompletionPrivate {
-
- ECompletionBeginFn begin_search;
- ECompletionEndFn end_search;
- gpointer user_data;
-
gboolean searching;
gchar *search_text;
gint pos;
@@ -115,8 +110,9 @@ e_completion_class_init (ECompletionClass *klass)
GTK_RUN_LAST,
object_class->type,
GTK_SIGNAL_OFFSET (ECompletionClass, begin_completion),
- gtk_marshal_NONE__NONE,
- GTK_TYPE_NONE, 0);
+ gtk_marshal_NONE__POINTER_INT_INT,
+ GTK_TYPE_NONE, 3,
+ GTK_TYPE_POINTER, GTK_TYPE_INT, GTK_TYPE_INT);
e_completion_signals[E_COMPLETION_COMPLETION] =
gtk_signal_new ("completion",
@@ -259,26 +255,17 @@ e_completion_begin_search (ECompletion *complete, const gchar *text, gint pos, g
if (complete->priv->searching)
e_completion_cancel_search (complete);
- /* Without one of these, we can't search! */
- if (complete->priv->begin_search) {
-
- g_free (complete->priv->search_text);
- complete->priv->search_text = g_strdup (text);
-
- complete->priv->pos = pos;
-
- complete->priv->searching = TRUE;
+ g_free (complete->priv->search_text);
+ complete->priv->search_text = g_strdup (text);
- e_completion_clear_matches (complete);
+ complete->priv->pos = pos;
+ complete->priv->searching = TRUE;
- complete->priv->limit = limit > 0 ? limit : G_MAXINT;
+ e_completion_clear_matches (complete);
- gtk_signal_emit (GTK_OBJECT (complete), e_completion_signals[E_COMPLETION_BEGIN_COMPLETION]);
- complete->priv->begin_search (complete, text, pos, limit, complete->priv->user_data);
- return;
- }
+ complete->priv->limit = limit > 0 ? limit : G_MAXINT;
- g_warning ("Unable to search for \"%s\" - no virtual method specified.", text);
+ gtk_signal_emit (GTK_OBJECT (complete), e_completion_signals[E_COMPLETION_BEGIN_COMPLETION], text, pos, limit);
}
void
@@ -291,12 +278,9 @@ e_completion_cancel_search (ECompletion *complete)
if (!complete->priv->searching)
return;
- if (complete->priv->end_search)
- complete->priv->end_search (complete, FALSE, complete->priv->user_data);
+ gtk_signal_emit (GTK_OBJECT (complete), e_completion_signals[E_COMPLETION_CANCEL_COMPLETION]);
complete->priv->searching = FALSE;
-
- gtk_signal_emit (GTK_OBJECT (complete), e_completion_signals[E_COMPLETION_CANCEL_COMPLETION]);
}
gboolean
@@ -369,25 +353,10 @@ e_completion_find_extra_data (ECompletion *complete, const gchar *text)
return NULL;
}
-void
-e_completion_construct (ECompletion *complete, ECompletionBeginFn begin_fn, ECompletionEndFn end_fn, gpointer user_data)
-{
- g_return_if_fail (complete != NULL);
- g_return_if_fail (E_IS_COMPLETION (complete));
-
- complete->priv->begin_search = begin_fn;
- complete->priv->end_search = end_fn;
- complete->priv->user_data = user_data;
-}
-
ECompletion *
-e_completion_new (ECompletionBeginFn begin_fn, ECompletionEndFn end_fn, gpointer user_data)
+e_completion_new (void)
{
- ECompletion *complete = E_COMPLETION (gtk_type_new (e_completion_get_type ()));
-
- e_completion_construct (complete, begin_fn, end_fn, user_data);
-
- return complete;
+ return E_COMPLETION (gtk_type_new (e_completion_get_type ()));
}
static gint
@@ -501,11 +470,8 @@ e_completion_end_search (ECompletion *complete)
if (e_completion_sort_by_score (complete))
e_completion_restart (complete);
- if (complete->priv->end_search)
- complete->priv->end_search (complete, TRUE, complete->priv->user_data);
-
- complete->priv->searching = FALSE;
-
gtk_signal_emit (GTK_OBJECT (complete), e_completion_signals[E_COMPLETION_END_COMPLETION]);
+
+ complete->priv->searching = FALSE;
}
diff --git a/widgets/text/e-completion.h b/widgets/text/e-completion.h
index 41be79a927..e101d6aa55 100644
--- a/widgets/text/e-completion.h
+++ b/widgets/text/e-completion.h
@@ -43,8 +43,6 @@ typedef struct _ECompletion ECompletion;
typedef struct _ECompletionClass ECompletionClass;
struct _ECompletionPrivate;
-typedef void (*ECompletionBeginFn) (ECompletion *, const gchar *text, gint pos, gint limit, gpointer user_data);
-typedef void (*ECompletionEndFn) (ECompletion *, gboolean finished, gpointer user_data);
typedef void (*ECompletionMatchFn) (const gchar *text, double score, gpointer extra_data, gpointer user_data);
struct _ECompletion {
@@ -57,8 +55,8 @@ struct _ECompletionClass {
GtkObjectClass parent_class;
/* Signals */
- void (*begin_completion) (ECompletion *comp);
- void (*completion) (ECompletion *comp, const gchar *text, gpointer extra_data);
+ void (*begin_completion) (ECompletion *comp, const gchar *search_text, gint pos, gint limit);
+ void (*completion) (ECompletion *comp, const gchar *match_text, gpointer extra_data);
void (*restart_completion) (ECompletion *comp);
void (*cancel_completion) (ECompletion *comp);
void (*end_completion) (ECompletion *comp);
@@ -76,8 +74,7 @@ gint e_completion_match_count (ECompletion *comp);
void e_completion_foreach_match (ECompletion *comp, ECompletionMatchFn fn, gpointer user_data);
gpointer e_completion_find_extra_data (ECompletion *comp, const gchar *text);
-void e_completion_construct (ECompletion *comp, ECompletionBeginFn, ECompletionEndFn, gpointer user_data);
-ECompletion *e_completion_new (ECompletionBeginFn, ECompletionEndFn, gpointer user_data);
+ECompletion *e_completion_new (void);
@@ -93,3 +90,4 @@ END_GNOME_DECLS
#endif /* E_COMPLETION_H */
+
diff --git a/widgets/text/e-entry.c b/widgets/text/e-entry.c
index 07fddb6b87..8116895e1c 100644
--- a/widgets/text/e-entry.c
+++ b/widgets/text/e-entry.c
@@ -116,6 +116,7 @@ struct _EEntryPrivate {
gchar *pre_browse_text;
gint completion_delay;
guint completion_delay_tag;
+ gboolean ptr_grab;
guint draw_borders : 1;
};
@@ -200,8 +201,8 @@ e_entry_proxy_changed (EText *text, EEntry *entry)
e_entry_cancel_delayed_completion (entry);
e_entry_show_popup (entry, FALSE);
} else if (entry->priv->popup_is_visible)
- e_entry_start_completion (entry);
- else if (entry->priv->completion && entry->priv->completion_delay >= 0)
+ e_entry_start_delayed_completion (entry, 1);
+ else if (entry->priv->completion)
e_entry_start_delayed_completion (entry, entry->priv->completion_delay);
gtk_signal_emit (GTK_OBJECT (entry), e_entry_signals [E_ENTRY_CHANGED]);
@@ -261,7 +262,7 @@ e_entry_init (GtkObject *object)
/*
* Proxy functions: we proxy the changed and activate signals
- * from the item to outselves
+ * from the item to ourselves
*/
entry->priv->changed_proxy_tag = gtk_signal_connect (GTK_OBJECT (entry->priv->item),
"changed",
@@ -272,7 +273,7 @@ e_entry_init (GtkObject *object)
GTK_SIGNAL_FUNC (e_entry_proxy_activate),
entry);
- entry->priv->completion_delay = -1;
+ entry->priv->completion_delay = 1;
}
/**
@@ -406,27 +407,45 @@ e_entry_show_popup (EEntry *entry, gboolean visible)
if (visible) {
GtkAllocation *dim = &(GTK_WIDGET (entry)->allocation);
- gint x, y;
+ gint x, y, fudge;
+ const GdkEventMask grab_mask = (GdkEventMask)GDK_BUTTON_PRESS_MASK | GDK_BUTTON_MOTION_MASK | GDK_BUTTON_RELEASE_MASK;
/* Figure out where to put our popup. */
gdk_window_get_origin (GTK_WIDGET (entry)->window, &x, &y);
x += dim->x;
y += dim->height + dim->y;
+ /* Put our popup slightly to the right and up, to try to give a visual cue that this popup
+ is tied to this entry. Otherwise one-row popups can sort of "blend" with an entry
+ directly below. */
+ fudge = MAX (dim->height/10, 3); /* just in case we are using a really big font, etc. */
+ x += 2*fudge;
+ y -= fudge;
+
gtk_widget_set_uposition (pop, x, y);
e_completion_view_set_width (E_COMPLETION_VIEW (entry->priv->completion_view), dim->width);
gtk_widget_show (pop);
- gdk_keyboard_grab (GTK_WIDGET (entry)->window, TRUE, GDK_CURRENT_TIME);
- gdk_pointer_grab (GTK_WIDGET (entry->priv->completion_view)->window, TRUE,
- (GdkEventMask) GDK_BUTTON_PRESS_MASK | GDK_BUTTON_MOTION_MASK | GDK_BUTTON_RELEASE_MASK,
- NULL, NULL, GDK_CURRENT_TIME);
-
+
+
+ if (! entry->priv->ptr_grab) {
+ entry->priv->ptr_grab = gdk_pointer_grab (GTK_WIDGET (entry->priv->completion_view)->window, TRUE,
+ grab_mask, NULL, NULL, GDK_CURRENT_TIME);
+ if (entry->priv->ptr_grab)
+ gtk_grab_add (GTK_WIDGET (entry->priv->completion_view));
+ }
+
} else {
gtk_widget_hide (pop);
- gdk_keyboard_ungrab (GDK_CURRENT_TIME);
- gdk_pointer_ungrab (GDK_CURRENT_TIME);
+
+ if (entry->priv->ptr_grab) {
+ gdk_pointer_ungrab (GDK_CURRENT_TIME);
+ gtk_grab_remove (GTK_WIDGET (entry->priv->completion_view));
+ }
+
+ entry->priv->ptr_grab = FALSE;
+
}
@@ -452,11 +471,10 @@ e_entry_start_completion (EEntry *entry)
if (e_entry_is_empty (entry))
return;
- if (entry->priv->completion)
- e_completion_begin_search (entry->priv->completion,
- e_entry_get_text (entry),
- e_entry_get_position (entry),
- 0); /* No limit. Probably a bad idea. */
+ e_completion_begin_search (entry->priv->completion,
+ e_entry_get_text (entry),
+ e_entry_get_position (entry),
+ 0); /* No limit. Probably a bad idea. */
}
static gboolean
@@ -475,11 +493,7 @@ e_entry_start_delayed_completion (EEntry *entry, gint delay)
return;
e_entry_cancel_delayed_completion (entry);
-
- if (delay == 0)
- e_entry_start_completion (entry);
- else
- entry->priv->completion_delay_tag = gtk_timeout_add (delay, start_delayed_cb, entry);
+ entry->priv->completion_delay_tag = gtk_timeout_add (MAX (delay, 1), start_delayed_cb, entry);
}
static void
@@ -488,7 +502,6 @@ e_entry_cancel_delayed_completion (EEntry *entry)
if (entry->priv->completion == NULL)
return;
- e_completion_cancel_search (entry->priv->completion); /* just to be sure... */
if (entry->priv->completion_delay_tag) {
gtk_timeout_remove (entry->priv->completion_delay_tag);
entry->priv->completion_delay_tag = 0;
@@ -599,7 +612,8 @@ button_press_cb (GtkWidget *w, GdkEvent *ev, gpointer user_data)
}
}
- e_entry_show_popup (entry, FALSE);
+ /* Treat this as an unbrowse */
+ unbrowse_cb (E_COMPLETION_VIEW (w), entry);
}
void
@@ -976,6 +990,9 @@ e_entry_destroy (GtkObject *object)
gtk_widget_destroy (entry->priv->completion_view_popup);
g_free (entry->priv->pre_browse_text);
+ if (entry->priv->ptr_grab)
+ gdk_pointer_ungrab (GDK_CURRENT_TIME);
+
g_free (entry->priv);
entry->priv = NULL;
}