From 0cbbfd3eaeb84448d0f6ad5aec43caa3fdc67190 Mon Sep 17 00:00:00 2001 From: PeterN Date: Fri, 19 May 2023 22:19:00 +0100 Subject: [PATCH] Codechange: Use display list instead of exclude list for file window. (#10845) This simplifies retrieving the correct data for each row when data is filtered. The background FileList is left intact so that savegame data does not have to be rescanned when the filter is changed, and sorting still remains the task of the background FileList. --- src/fios_gui.cpp | 89 +++++++++++++++++++++--------------------------- 1 file changed, 39 insertions(+), 50 deletions(-) diff --git a/src/fios_gui.cpp b/src/fios_gui.cpp index 7d0e8fe556..b23d20b3fa 100644 --- a/src/fios_gui.cpp +++ b/src/fios_gui.cpp @@ -280,7 +280,7 @@ private: StringFilter string_filter; ///< Filter for available games. QueryString filter_editbox; ///< Filter editbox; - std::vector fios_items_shown; ///< Map of the filtered out fios items + std::vector display_list; ///< Filtered display list static void SaveGameConfirmationCallback(Window *w, bool confirmed) { @@ -443,14 +443,8 @@ public: Rect tr = r.Shrink(WidgetDimensions::scaled.inset).WithHeight(this->resize.step_height); uint scroll_pos = this->vscroll->GetPosition(); - for (uint row = 0; row < this->fios_items.size() && tr.top < br.bottom; row++) { - if (!this->fios_items_shown[row]) { - /* The current item is filtered out : we do not show it */ - scroll_pos++; - continue; - } - if (row < scroll_pos) continue; - const FiosItem *item = &this->fios_items[row]; + for (auto it = this->display_list.begin() + scroll_pos; it != this->display_list.end() && tr.top < br.bottom; ++it) { + const FiosItem *item = *it; if (item == this->selected) { GfxFillRect(br.left, tr.top, br.right, tr.bottom, PC_DARK_BLUE); @@ -654,16 +648,11 @@ public: break; case WID_SL_DRIVES_DIRECTORIES_LIST: { // Click the listbox - int y = this->vscroll->GetScrolledRowFromWidget(pt.y, this, WID_SL_DRIVES_DIRECTORIES_LIST, WidgetDimensions::scaled.inset.top); - if (y == INT_MAX) return; + auto it = this->vscroll->GetScrolledItemFromWidget(this->display_list, pt.y, this, WID_SL_DRIVES_DIRECTORIES_LIST, WidgetDimensions::scaled.inset.top); + if (it == this->display_list.end()) return; /* Get the corresponding non-filtered out item from the list */ - int i = 0; - while (i <= y) { - if (!this->fios_items_shown[i]) y++; - i++; - } - const FiosItem *file = &this->fios_items[y]; + const FiosItem *file = *it; if (FiosBrowseTo(file)) { /* Changed directory, need refresh. */ @@ -731,16 +720,11 @@ public: void OnMouseOver(Point pt, int widget) override { if (widget == WID_SL_DRIVES_DIRECTORIES_LIST) { - int y = this->vscroll->GetScrolledRowFromWidget(pt.y, this, WID_SL_DRIVES_DIRECTORIES_LIST, WidgetDimensions::scaled.inset.top); - if (y == INT_MAX) return; + auto it = this->vscroll->GetScrolledItemFromWidget(this->display_list, pt.y, this, WID_SL_DRIVES_DIRECTORIES_LIST, WidgetDimensions::scaled.inset.top); + if (it == this->display_list.end()) return; /* Get the corresponding non-filtered out item from the list */ - int i = 0; - while (i <= y) { - if (!this->fios_items_shown[i]) y++; - i++; - } - const FiosItem *file = &this->fios_items[y]; + const FiosItem *file = *it; if (file != this->highlighted) { this->highlighted = file; @@ -802,6 +786,35 @@ public: this->vscroll->SetCapacityFromWidget(this, WID_SL_DRIVES_DIRECTORIES_LIST); } + void BuildDisplayList() + { + /* Filter changes */ + this->display_list.clear(); + this->display_list.reserve(this->fios_items.size()); + + if (this->string_filter.IsEmpty()) { + /* We don't filter anything out if the filter editbox is empty */ + for (auto &it : this->fios_items) { + this->display_list.push_back(&it); + } + } else { + for (auto &it : this->fios_items) { + this->string_filter.ResetState(); + this->string_filter.AddLine(it.title); + /* We set the vector to show this fios element as filtered depending on the result of the filter */ + if (this->string_filter.GetState()) { + this->display_list.push_back(&it); + } else if (&it == this->selected) { + /* The selected element has been filtered out */ + this->selected = nullptr; + this->OnInvalidateData(SLIWD_SELECTION_CHANGES); + } + } + } + + this->vscroll->SetCount(this->display_list.size()); + } + /** * Some data on this window has become invalid. * @param data Information about the changed data. @@ -818,7 +831,6 @@ public: _fios_path_changed = true; this->fios_items.BuildFileList(this->abstract_filetype, this->fop); - this->vscroll->SetCount(this->fios_items.size()); this->selected = nullptr; _load_check_data.Clear(); @@ -857,30 +869,7 @@ public: break; case SLIWD_FILTER_CHANGES: - /* Filter changes */ - this->fios_items_shown.resize(this->fios_items.size()); - uint items_shown_count = 0; ///< The number of items shown in the list - /* We pass through every fios item */ - for (uint i = 0; i < this->fios_items.size(); i++) { - if (this->string_filter.IsEmpty()) { - /* We don't filter anything out if the filter editbox is empty */ - this->fios_items_shown[i] = true; - items_shown_count++; - } else { - this->string_filter.ResetState(); - this->string_filter.AddLine(this->fios_items[i].title.c_str()); - /* We set the vector to show this fios element as filtered depending on the result of the filter */ - this->fios_items_shown[i] = this->string_filter.GetState(); - if (this->fios_items_shown[i]) items_shown_count++; - - if (&(this->fios_items[i]) == this->selected && !this->fios_items_shown[i]) { - /* The selected element has been filtered out */ - this->selected = nullptr; - this->OnInvalidateData(SLIWD_SELECTION_CHANGES); - } - } - } - this->vscroll->SetCount(items_shown_count); + this->BuildDisplayList(); break; } }