From c0a7639cbe4271d7930bdee9be9fa5c9bf663083 Mon Sep 17 00:00:00 2001 From: Benjamin Otte Date: Sat, 19 Oct 2019 21:29:52 +0200 Subject: [PATCH] selectionmodel: Add gtk_selection_model_user_select_item() I'm not sure this should be public API because it's incredibly awkward. But it should definitely be shared between list widget implementations. --- docs/reference/gtk/gtk4-sections.txt | 2 + gtk/gtklistview.c | 60 ++----------------- gtk/gtkselectionmodel.c | 87 ++++++++++++++++++++++++++++ gtk/gtkselectionmodel.h | 5 ++ 4 files changed, 99 insertions(+), 55 deletions(-) diff --git a/docs/reference/gtk/gtk4-sections.txt b/docs/reference/gtk/gtk4-sections.txt index 9addc49a0a..d15afda38b 100644 --- a/docs/reference/gtk/gtk4-sections.txt +++ b/docs/reference/gtk/gtk4-sections.txt @@ -352,6 +352,8 @@ gtk_selection_model_select_all gtk_selection_model_unselect_all gtk_selection_model_query_range +gtk_selection_model_user_select_item + gtk_selection_model_selection_changed GTK_SELECTION_MODEL diff --git a/gtk/gtklistview.c b/gtk/gtklistview.c index e2eb610597..e9fd7b7eb5 100644 --- a/gtk/gtklistview.c +++ b/gtk/gtklistview.c @@ -616,61 +616,11 @@ gtk_list_view_select_item (GtkListView *self, gboolean modify, gboolean extend) { - GtkSelectionModel *selection_model; - gboolean success = FALSE; - - selection_model = gtk_list_item_manager_get_model (self->item_manager); - - if (extend) - { - guint start_pos = gtk_list_item_tracker_get_position (self->item_manager, self->selected); - if (start_pos != GTK_INVALID_LIST_POSITION) - { - guint max = MAX (start_pos, pos); - guint min = MIN (start_pos, pos); - if (modify) - { - if (gtk_selection_model_is_selected (selection_model, start_pos)) - { - success = gtk_selection_model_select_range (selection_model, - min, - max - min + 1, - FALSE); - } - else - { - success = gtk_selection_model_unselect_range (selection_model, - min, - max - min + 1); - } - } - else - { - success = gtk_selection_model_select_range (selection_model, - min, - max - min + 1, - TRUE); - } - } - /* If there's no range to select or selecting ranges isn't supported - * by the model, fall through to normal setting. - */ - } - if (success) - return; - - if (modify) - { - if (gtk_selection_model_is_selected (selection_model, pos)) - success = gtk_selection_model_unselect_item (selection_model, pos); - else - success = gtk_selection_model_select_item (selection_model, pos, FALSE); - } - else - { - success = gtk_selection_model_select_item (selection_model, pos, TRUE); - } - if (success) + if (gtk_selection_model_user_select_item (gtk_list_item_manager_get_model (self->item_manager), + pos, + modify, + extend ? gtk_list_item_tracker_get_position (self->item_manager, self->selected) + : GTK_INVALID_LIST_POSITION)) { gtk_list_item_tracker_set_position (self->item_manager, self->selected, diff --git a/gtk/gtkselectionmodel.c b/gtk/gtkselectionmodel.c index 7be454fd74..c5853e87a7 100644 --- a/gtk/gtkselectionmodel.c +++ b/gtk/gtkselectionmodel.c @@ -382,3 +382,90 @@ gtk_selection_model_selection_changed (GtkSelectionModel *model, g_signal_emit (model, signals[SELECTION_CHANGED], 0, position, n_items); } +/** + * gtk_selection_model_user_select_item: + * @self: a #GtkSelectionModel + * @pos: position selected by the user. If this position is invalid + * no selection will be done. + * @modify: %TRUE if the selection should be modified, %FALSE + * if a new selection should be done. This is usually set + * to %TRUE if the user keeps the key pressed. + * @extend_pos: the position to extend the selection from or + * an invalid position like #GTK_INVALID_LIST_POSITION to not + * extend the selection. Selections are usually extended + * from the last selected position if the user presses the + * key. The last selected position is stored by the + * widget + * + * Does a selection according to how GTK list widgets modify + * selections, both when clicking rows with the mouse or when using + * the keyboard. + * + * Returns: %TRUE if the last selected position for further calls + * to this function should be updated to @pos, %FALSE if the + * last selected position should not change. + **/ +gboolean +gtk_selection_model_user_select_item (GtkSelectionModel *self, + guint pos, + gboolean modify, + guint extend_pos) +{ + gboolean success = FALSE; + guint n_items; + + g_return_val_if_fail (GTK_IS_SELECTION_MODEL (self), FALSE); + + n_items = g_list_model_get_n_items (G_LIST_MODEL (self)); + if (pos >= n_items) + return FALSE; + + if (extend_pos < n_items) + { + guint max = MAX (extend_pos, pos); + guint min = MIN (extend_pos, pos); + if (modify) + { + if (gtk_selection_model_is_selected (self, extend_pos)) + { + success = gtk_selection_model_select_range (self, + min, + max - min + 1, + FALSE); + } + else + { + success = gtk_selection_model_unselect_range (self, + min, + max - min + 1); + } + } + else + { + success = gtk_selection_model_select_range (self, + min, + max - min + 1, + TRUE); + } + /* If there's no range to select or selecting ranges isn't supported + * by the model, fall through to normal setting. + */ + } + if (success) + return FALSE; + + if (modify) + { + if (gtk_selection_model_is_selected (self, pos)) + success = gtk_selection_model_unselect_item (self, pos); + else + success = gtk_selection_model_select_item (self, pos, FALSE); + } + else + { + success = gtk_selection_model_select_item (self, pos, TRUE); + } + + return success; +} + diff --git a/gtk/gtkselectionmodel.h b/gtk/gtkselectionmodel.h index c982a918ad..6f3dcb28e1 100644 --- a/gtk/gtkselectionmodel.h +++ b/gtk/gtkselectionmodel.h @@ -130,6 +130,11 @@ void gtk_selection_model_query_range (GtkSelectionMod guint *n_items, gboolean *selected); +GDK_AVAILABLE_IN_ALL +gboolean gtk_selection_model_user_select_item (GtkSelectionModel *self, + guint pos, + gboolean modify, + guint extend_pos); /* for implementations only */ GDK_AVAILABLE_IN_ALL void gtk_selection_model_selection_changed (GtkSelectionModel *model,