diff options
-rw-r--r-- | widgets/text/e-completion-test.c | 18 | ||||
-rw-r--r-- | widgets/text/e-completion-view.c | 33 | ||||
-rw-r--r-- | widgets/text/e-completion.c | 64 | ||||
-rw-r--r-- | widgets/text/e-completion.h | 10 | ||||
-rw-r--r-- | widgets/text/e-entry.c | 65 |
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; } |