diff options
Diffstat (limited to 'src/gui/gcal-search-button.c')
-rw-r--r-- | src/gui/gcal-search-button.c | 147 |
1 files changed, 102 insertions, 45 deletions
diff --git a/src/gui/gcal-search-button.c b/src/gui/gcal-search-button.c index 3f5e4d13..d8ed14d1 100644 --- a/src/gui/gcal-search-button.c +++ b/src/gui/gcal-search-button.c @@ -24,7 +24,6 @@ #include "gcal-debug.h" #include "gcal-search-button.h" #include "gcal-search-hit.h" -#include "gcal-search-hit-row.h" #include <math.h> @@ -36,8 +35,9 @@ struct _GcalSearchButton GtkEditable *entry; GtkWidget *popover; - GtkListBox *results_listbox; + GtkListView *results_listview; GtkRevealer *results_revealer; + GtkSingleSelection *results_selection_model; GtkStack *stack; GCancellable *cancellable; @@ -88,11 +88,14 @@ quit_search_entry (GcalSearchButton *self) gtk_editable_set_text (self->entry, ""); } -static GtkWidget * -create_widget_func (gpointer item, - gpointer user_data) +static inline void +scroll_to_result (GcalSearchButton *self, + guint position) { - return gcal_search_hit_row_new (item); + gtk_widget_activate_action (GTK_WIDGET (self->results_listview), + "list.scroll-to-item", + "u", + position); } static void @@ -101,11 +104,7 @@ set_model (GcalSearchButton *self, { GCAL_ENTRY; - gtk_list_box_bind_model (self->results_listbox, - model, - create_widget_func, - self, - NULL); + gtk_single_selection_set_model (self->results_selection_model, model); if (model) show_suggestions (self); @@ -120,6 +119,18 @@ set_model (GcalSearchButton *self, * Callbacks */ +static gchar * +escape_markup_cb (GcalSearchHit *hit, + const gchar *string) +{ + g_autofree gchar *escaped_string = NULL; + + escaped_string = g_markup_escape_text (string, -1); + escaped_string = g_strstrip (escaped_string); + + return g_steal_pointer (&escaped_string); +} + static void on_button_clicked_cb (GtkButton *button, GcalSearchButton *self) @@ -165,6 +176,68 @@ on_search_finished_cb (GObject *source_object, } static void +on_entry_activate_cb (GtkSearchEntry *entry, + GcalSearchButton *self) +{ + GcalSearchHit *hit; + + GCAL_ENTRY; + + hit = gtk_single_selection_get_selected_item (self->results_selection_model); + + if (hit) + { + GCAL_TRACE_MSG ("Activating \"%s\"", gcal_search_hit_get_title (hit)); + + gcal_search_hit_activate (hit, GTK_WIDGET (self)); + quit_search_entry (self); + } + + GCAL_EXIT; +} + +static void +on_entry_next_match_cb (GtkSearchEntry *entry, + GcalSearchButton *self) +{ + guint selected; + + GCAL_ENTRY; + + selected = gtk_single_selection_get_selected (self->results_selection_model); + + if (selected != GTK_INVALID_LIST_POSITION && + selected + 1 < g_list_model_get_n_items (G_LIST_MODEL (self->results_selection_model))) + { + GCAL_TRACE_MSG ("Changing selection to %u", selected + 1); + gtk_single_selection_set_selected (self->results_selection_model, selected + 1); + scroll_to_result (self, selected + 1); + } + + GCAL_EXIT; +} + +static void +on_entry_previous_match_cb (GtkSearchEntry *entry, + GcalSearchButton *self) +{ + guint selected; + + GCAL_ENTRY; + + selected = gtk_single_selection_get_selected (self->results_selection_model); + + if (selected > 0 && selected != GTK_INVALID_LIST_POSITION) + { + GCAL_TRACE_MSG ("Changing selection to %u", selected - 1); + gtk_single_selection_set_selected (self->results_selection_model, selected - 1); + scroll_to_result (self, selected - 1); + } + + GCAL_EXIT; +} + +static void on_entry_search_changed_cb (GtkSearchEntry *entry, GcalSearchButton *self) { @@ -204,16 +277,18 @@ on_entry_stop_search_cb (GtkSearchEntry *search_entry, } static void -on_results_listbox_row_activated_cb (GtkListBox *listbox, - GcalSearchHitRow *row, - GcalSearchButton *self) +on_results_listview_activated_cb (GtkListBox *listbox, + guint position, + GcalSearchButton *self) { GcalSearchHit *search_hit; - search_hit = gcal_search_hit_row_get_search_hit (row); + search_hit = g_list_model_get_item (G_LIST_MODEL (self->results_selection_model), position); + g_assert (GCAL_IS_SEARCH_HIT (search_hit)); + gcal_search_hit_activate (search_hit, GTK_WIDGET (self)); - hide_suggestions (self); + quit_search_entry (self); } static void @@ -225,32 +300,11 @@ on_results_revealer_child_reveal_state_changed_cb (GtkRevealer *revealer, gtk_popover_popdown (GTK_POPOVER (self->popover)); } - -/* - * GtkWidget overrides - */ - static gboolean -gcal_search_button_focus (GtkWidget *widget, - GtkDirectionType direction) +string_is_not_empty_cb (GcalSearchHit *hit, + const gchar *string) { - GcalSearchButton *self = GCAL_SEARCH_BUTTON (widget); - - if (!gtk_widget_get_visible (GTK_WIDGET (self->popover))) - return gtk_widget_child_focus (GTK_WIDGET (self->stack), direction); - - if (direction == GTK_DIR_DOWN) - { - GtkListBoxRow *first_row = gtk_list_box_get_row_at_index (self->results_listbox, 0); - - if (!first_row) - return gtk_widget_child_focus (GTK_WIDGET (self->stack), direction); - - gtk_widget_grab_focus (GTK_WIDGET (first_row)); - return TRUE; - } - - return gtk_widget_child_focus (GTK_WIDGET (self->stack), direction); + return string != NULL && *string != '\0'; } @@ -319,7 +373,6 @@ gcal_search_button_set_property (GObject *object, } } - static void gcal_search_button_class_init (GcalSearchButtonClass *klass) { @@ -331,8 +384,6 @@ gcal_search_button_class_init (GcalSearchButtonClass *klass) object_class->get_property = gcal_search_button_get_property; object_class->set_property = gcal_search_button_set_property; - widget_class->focus = gcal_search_button_focus; - /** * GcalSearchButton::context: * @@ -350,16 +401,22 @@ gcal_search_button_class_init (GcalSearchButtonClass *klass) gtk_widget_class_bind_template_child (widget_class, GcalSearchButton, entry); gtk_widget_class_bind_template_child (widget_class, GcalSearchButton, popover); - gtk_widget_class_bind_template_child (widget_class, GcalSearchButton, results_listbox); + gtk_widget_class_bind_template_child (widget_class, GcalSearchButton, results_listview); + gtk_widget_class_bind_template_child (widget_class, GcalSearchButton, results_selection_model); gtk_widget_class_bind_template_child (widget_class, GcalSearchButton, results_revealer); gtk_widget_class_bind_template_child (widget_class, GcalSearchButton, stack); + gtk_widget_class_bind_template_callback (widget_class, escape_markup_cb); gtk_widget_class_bind_template_callback (widget_class, on_button_clicked_cb); gtk_widget_class_bind_template_callback (widget_class, on_focus_controller_leave_cb); + gtk_widget_class_bind_template_callback (widget_class, on_entry_activate_cb); + gtk_widget_class_bind_template_callback (widget_class, on_entry_next_match_cb); + gtk_widget_class_bind_template_callback (widget_class, on_entry_previous_match_cb); gtk_widget_class_bind_template_callback (widget_class, on_entry_search_changed_cb); gtk_widget_class_bind_template_callback (widget_class, on_entry_stop_search_cb); - gtk_widget_class_bind_template_callback (widget_class, on_results_listbox_row_activated_cb); + gtk_widget_class_bind_template_callback (widget_class, on_results_listview_activated_cb); gtk_widget_class_bind_template_callback (widget_class, on_results_revealer_child_reveal_state_changed_cb); + gtk_widget_class_bind_template_callback (widget_class, string_is_not_empty_cb); gtk_widget_class_set_css_name (widget_class, "searchbutton"); } |