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; } }