Select the correct item in a filtered and sorted generator (#4585)

In the load-game dialog, this makes deleting a file select the next
visible game save, thus it fixes #4125.

Credit and many thanks to DisherProject for the inspiration and hard
work of debugging where to fix this.
This commit is contained in:
Steve Cotton 2019-11-25 18:48:47 +01:00 committed by GitHub
parent e50fd80d53
commit 63ebe48d64
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 37 additions and 30 deletions

View file

@ -35,13 +35,30 @@ void one_item::set_item_shown(const unsigned index, const bool show)
do_select_item(index);
} else if(!show && is_selected(index)) {
do_deselect_item(index);
for(unsigned i = 1; i < get_item_count(); ++i) {
unsigned new_index = (index + i) % get_item_count();
if(get_item_shown(new_index)) {
do_select_item(new_index);
break;
if(get_selected_item_count() == 0) {
bool found_new_item = false;
const unsigned item_count = get_item_count();
const unsigned ordered_index = get_ordered_index(index);
// find the next shown item
for(unsigned i = ordered_index + 1; i < item_count; ++i) {
unsigned new_index = get_item_at_ordered(i);
if(get_item_shown(new_index)) {
do_select_item(new_index);
found_new_item = true;
break;
}
}
// fall back to finding the previous shown item
if(!found_new_item) {
for(signed i = static_cast<signed>(ordered_index) - 1; i >= 0; --i) {
unsigned new_index = get_item_at_ordered(static_cast<unsigned>(i));
if(get_item_shown(new_index)) {
do_select_item(new_index);
break;
}
}
}
// if neither search found a new item, accept that there are zero items selected
}
}
}
@ -65,28 +82,8 @@ bool one_item::deselect_item(const unsigned index)
void one_item::delete_item(const unsigned index)
{
/** @todo do_select_item needs to test for shown flag. */
if(is_selected(index)) {
do_deselect_item(index);
if(get_selected_item_count() == 0) {
// Are there items left?
const unsigned item_count = get_item_count();
const unsigned visible_index = get_ordered_index(index);
if(item_count > 1) {
// Is the last item deselected?
if(visible_index == item_count - 1) {
// Select the second last.
do_select_item(get_item_at_ordered(visible_index - 1));
} else {
// Select the next item.
do_select_item(get_item_at_ordered(visible_index + 1));
}
}
}
}
// this needs the same logic for ensuring that at least one item is selected
set_item_shown(index, false);
}
void no_item::set_item_shown(const unsigned index, const bool show)

View file

@ -56,7 +56,7 @@ public:
/**
* Create a new generator.
*
* @param has_minimum Does one item need to be selected.
* @param has_minimum Does one item need to be selected?
* @param has_maximum Is one the maximum number of items that can
* be selected?
* @param placement The placement of the grids, see tplacement
@ -105,7 +105,9 @@ public:
/**
* Shows or hides an item.
*
* The caller is responsible for reformatting the grid.
* The caller is responsible for reformatting the grid. If a selected item
* is hidden then it will be automatically deselected; if no items are
* shown then no items will be selected, even if has_minimum was requested.
*
* @param index The item to show or hide.
* @param show If true shows the item, else hides it.
@ -372,8 +374,16 @@ protected:
virtual const grid& item_ordered(const unsigned index) const = 0;
public:
/**
* If a sort-order is being applied, maps from unsorted to sorted indicies.
* This does not take account of whether each object is shown or not.
*/
virtual unsigned get_ordered_index(unsigned index) const = 0;
/**
* If a sort-order is being applied, maps from sorted to unsorted indicies.
* This does not take account of whether each object is shown or not.
*/
virtual unsigned get_item_at_ordered(unsigned index_ordered) const = 0;
};