diff --git a/src/engine_gui.h b/src/engine_gui.h index 56a2409035..21e09b0f9d 100644 --- a/src/engine_gui.h +++ b/src/engine_gui.h @@ -28,7 +28,7 @@ struct GUIEngineListItem { bool operator == (const EngineID &other) const { return this->engine_id == other; } }; -typedef GUIList GUIEngineList; +typedef GUIList GUIEngineList; typedef bool EngList_SortTypeFunction(const GUIEngineListItem&, const GUIEngineListItem&); ///< argument type for #EngList_Sort. void EngList_Sort(GUIEngineList &el, EngList_SortTypeFunction compare); diff --git a/src/industry_gui.cpp b/src/industry_gui.cpp index 530b1a37fb..828ceebcd1 100644 --- a/src/industry_gui.cpp +++ b/src/industry_gui.cpp @@ -1245,7 +1245,7 @@ static const NWidgetPart _nested_industry_directory_widgets[] = { EndContainer(), }; -typedef GUIList &> GUIIndustryList; +typedef GUIList &> GUIIndustryList; /** Special cargo filter criteria */ enum CargoFilterSpecialType { @@ -1315,7 +1315,7 @@ protected: static const StringID sorter_names[]; static GUIIndustryList::SortFunction * const sorter_funcs[]; - GUIIndustryList industries; + GUIIndustryList industries{IndustryDirectoryWindow::produced_cargo_filter}; Scrollbar *vscroll; Scrollbar *hscroll; @@ -1484,7 +1484,7 @@ protected: } /** Sort industries by name */ - static bool IndustryNameSorter(const Industry * const &a, const Industry * const &b) + static bool IndustryNameSorter(const Industry * const &a, const Industry * const &b, const CargoID &) { int r = StrNaturalCompare(a->GetCachedName(), b->GetCachedName()); // Sort by name (natural sorting). if (r == 0) return a->index < b->index; @@ -1492,21 +1492,20 @@ protected: } /** Sort industries by type and name */ - static bool IndustryTypeSorter(const Industry * const &a, const Industry * const &b) + static bool IndustryTypeSorter(const Industry * const &a, const Industry * const &b, const CargoID &filter) { int it_a = 0; while (it_a != NUM_INDUSTRYTYPES && a->type != _sorted_industry_types[it_a]) it_a++; int it_b = 0; while (it_b != NUM_INDUSTRYTYPES && b->type != _sorted_industry_types[it_b]) it_b++; int r = it_a - it_b; - return (r == 0) ? IndustryNameSorter(a, b) : r < 0; + return (r == 0) ? IndustryNameSorter(a, b, filter) : r < 0; } /** Sort industries by production and name */ - static bool IndustryProductionSorter(const Industry * const &a, const Industry * const &b) + static bool IndustryProductionSorter(const Industry * const &a, const Industry * const &b, const CargoID &filter) { - CargoID filter = IndustryDirectoryWindow::produced_cargo_filter; - if (filter == CF_NONE) return IndustryTypeSorter(a, b); + if (filter == CF_NONE) return IndustryTypeSorter(a, b, filter); uint prod_a = 0, prod_b = 0; if (filter == CF_ANY) { @@ -1522,14 +1521,14 @@ protected: } int r = prod_a - prod_b; - return (r == 0) ? IndustryTypeSorter(a, b) : r < 0; + return (r == 0) ? IndustryTypeSorter(a, b, filter) : r < 0; } /** Sort industries by transported cargo and name */ - static bool IndustryTransportedCargoSorter(const Industry * const &a, const Industry * const &b) + static bool IndustryTransportedCargoSorter(const Industry * const &a, const Industry * const &b, const CargoID &filter) { int r = GetCargoTransportedSortValue(a) - GetCargoTransportedSortValue(b); - return (r == 0) ? IndustryNameSorter(a, b) : r < 0; + return (r == 0) ? IndustryNameSorter(a, b, filter) : r < 0; } /** diff --git a/src/network/network_content_gui.cpp b/src/network/network_content_gui.cpp index 2adaacaf88..d201e87338 100644 --- a/src/network/network_content_gui.cpp +++ b/src/network/network_content_gui.cpp @@ -326,7 +326,7 @@ enum ContentListFilterCriteria { /** Window that lists the content that's at the content server */ class NetworkContentListWindow : public Window, ContentCallback { /** List with content infos. */ - typedef GUIList GUIContentList; + typedef GUIList GUIContentList; static const uint EDITBOX_MAX_SIZE = 50; ///< Maximum size of the editbox in characters. diff --git a/src/network/network_gui.cpp b/src/network/network_gui.cpp index 3e084919bc..0955b335f7 100644 --- a/src/network/network_gui.cpp +++ b/src/network/network_gui.cpp @@ -79,7 +79,7 @@ static DropDownList BuildVisibilityDropDownList() return list; } -typedef GUIList GUIGameServerList; +typedef GUIList GUIGameServerList; typedef int ServerListPosition; static const ServerListPosition SLP_INVALID = -1; diff --git a/src/newgrf_gui.cpp b/src/newgrf_gui.cpp index c6d618e9a2..048ec5222e 100644 --- a/src/newgrf_gui.cpp +++ b/src/newgrf_gui.cpp @@ -602,7 +602,7 @@ static void ShowSavePresetWindow(const char *initial_text); * Window for showing NewGRF files */ struct NewGRFWindow : public Window, NewGRFScanCallback { - typedef GUIList GUIGRFConfigList; + typedef GUIList GUIGRFConfigList; static const uint EDITBOX_MAX_SIZE = 50; diff --git a/src/object_gui.cpp b/src/object_gui.cpp index 8144a810ec..8740a4f25c 100644 --- a/src/object_gui.cpp +++ b/src/object_gui.cpp @@ -45,7 +45,7 @@ enum BuildObjectHotkeys { /** The window used for building objects. */ class BuildObjectWindow : public Window { - typedef GUIList GUIObjectClassList; ///< Type definition for the list to hold available object classes. + typedef GUIList GUIObjectClassList; ///< Type definition for the list to hold available object classes. static const uint EDITBOX_MAX_SIZE = 16; ///< The maximum number of characters for the filter edit box. diff --git a/src/rail_gui.cpp b/src/rail_gui.cpp index 8a1efbae41..224eb51643 100644 --- a/src/rail_gui.cpp +++ b/src/rail_gui.cpp @@ -903,7 +903,7 @@ private: Scrollbar *vscroll; ///< Vertical scrollbar of the new station list. Scrollbar *vscroll2; ///< Vertical scrollbar of the matrix with new stations. - typedef GUIList GUIStationClassList; ///< Type definition for the list to hold available station classes. + typedef GUIList GUIStationClassList; ///< Type definition for the list to hold available station classes. static const uint EDITBOX_MAX_SIZE = 16; ///< The maximum number of characters for the filter edit box. diff --git a/src/road_gui.cpp b/src/road_gui.cpp index 0878c5135e..d289753022 100644 --- a/src/road_gui.cpp +++ b/src/road_gui.cpp @@ -1101,7 +1101,7 @@ private: Scrollbar *vscrollList; ///< Vertical scrollbar of the new station list. Scrollbar *vscrollMatrix; ///< Vertical scrollbar of the station picker matrix. - typedef GUIList GUIRoadStopClassList; ///< Type definition for the list to hold available road stop classes. + typedef GUIList GUIRoadStopClassList; ///< Type definition for the list to hold available road stop classes. static const uint EDITBOX_MAX_SIZE = 16; ///< The maximum number of characters for the filter edit box. diff --git a/src/signs_gui.cpp b/src/signs_gui.cpp index b52b1c3a92..f5ebdb9e8f 100644 --- a/src/signs_gui.cpp +++ b/src/signs_gui.cpp @@ -41,7 +41,7 @@ struct SignList { /** * A GUIList contains signs and uses a StringFilter for filtering. */ - typedef GUIList GUISignList; + typedef GUIList GUISignList; GUISignList signs; diff --git a/src/sortlist_type.h b/src/sortlist_type.h index feb02dce53..d9fc170581 100644 --- a/src/sortlist_type.h +++ b/src/sortlist_type.h @@ -40,12 +40,13 @@ struct Filtering { /** * List template of 'things' \p T to sort in a GUI. * @tparam T Type of data stored in the list to represent each item. + * @tparam P Tyoe of data passed as additional parameter to the sort function. * @tparam F Type of data fed as additional value to the filter function. @see FilterFunction */ -template +template class GUIList : public std::vector { public: - typedef bool SortFunction(const T&, const T&); ///< Signature of sort function. + using SortFunction = std::conditional_t, bool (const T&, const T&), bool (const T&, const T&, const P)>; ///< Signature of sort function. typedef bool CDECL FilterFunction(const T*, F); ///< Signature of filter function. protected: @@ -56,6 +57,11 @@ protected: uint8_t filter_type; ///< what criteria to filter on uint16_t resort_timer; ///< resort list after a given amount of ticks if set + /* If sort parameters are used then params must be a reference, however if not then params cannot be a reference as + * it will not be able to reference anything. */ + using SortParameterReference = std::conditional_t, P, P&>; + const SortParameterReference params; + /** * Check if the list is sortable * @@ -76,13 +82,28 @@ protected: } public: + /* If sort parameters are not used then we don't require a reference to the params. */ + template >* = nullptr> GUIList() : sort_func_list(nullptr), filter_func_list(nullptr), flags(VL_NONE), sort_type(0), filter_type(0), - resort_timer(1) + resort_timer(1), + params(nullptr) + {}; + + /* If sort parameters are used then we require a reference to the params. */ + template >* = nullptr> + GUIList(const P& params) : + sort_func_list(nullptr), + filter_func_list(nullptr), + flags(VL_NONE), + sort_type(0), + filter_type(0), + resort_timer(1), + params(params) {}; /** @@ -258,7 +279,11 @@ public: const bool desc = (this->flags & VL_DESC) != 0; - std::sort(std::vector::begin(), std::vector::end(), [&](const T &a, const T &b) { return desc ? compare(b, a) : compare(a, b); }); + if constexpr (std::is_same_v) { + std::sort(std::vector::begin(), std::vector::end(), [&](const T &a, const T &b) { return desc ? compare(b, a) : compare(a, b); }); + } else { + std::sort(std::vector::begin(), std::vector::end(), [&](const T &a, const T &b) { return desc ? compare(b, a, params) : compare(a, b, params); }); + } return true; } diff --git a/src/station_gui.cpp b/src/station_gui.cpp index 7dcdab6e92..2899829fc4 100644 --- a/src/station_gui.cpp +++ b/src/station_gui.cpp @@ -209,7 +209,7 @@ static void StationsWndShowStationRating(int left, int right, int y, CargoID typ if (w != 0) GfxFillRect(left + padding, y, left + w - 1, y + padding - 1, PC_GREEN); } -typedef GUIList GUIStationList; +typedef GUIList GUIStationList; /** * The list of stations per company. @@ -228,7 +228,7 @@ protected: static const StringID sorter_names[]; static GUIStationList::SortFunction * const sorter_funcs[]; - GUIStationList stations; + GUIStationList stations{cargo_filter}; Scrollbar *vscroll; uint rating_width; @@ -273,7 +273,7 @@ protected: } /** Sort stations by their name */ - static bool StationNameSorter(const Station * const &a, const Station * const &b) + static bool StationNameSorter(const Station * const &a, const Station * const &b, const CargoTypes &) { int r = StrNaturalCompare(a->GetCachedName(), b->GetCachedName()); // Sort by name (natural sorting). if (r == 0) return a->index < b->index; @@ -281,13 +281,13 @@ protected: } /** Sort stations by their type */ - static bool StationTypeSorter(const Station * const &a, const Station * const &b) + static bool StationTypeSorter(const Station * const &a, const Station * const &b, const CargoTypes &) { return a->facilities < b->facilities; } /** Sort stations by their waiting cargo */ - static bool StationWaitingTotalSorter(const Station * const &a, const Station * const &b) + static bool StationWaitingTotalSorter(const Station * const &a, const Station * const &b, const CargoTypes &cargo_filter) { int diff = 0; @@ -299,7 +299,7 @@ protected: } /** Sort stations by their available waiting cargo */ - static bool StationWaitingAvailableSorter(const Station * const &a, const Station * const &b) + static bool StationWaitingAvailableSorter(const Station * const &a, const Station * const &b, const CargoTypes &cargo_filter) { int diff = 0; @@ -311,7 +311,7 @@ protected: } /** Sort stations by their rating */ - static bool StationRatingMaxSorter(const Station * const &a, const Station * const &b) + static bool StationRatingMaxSorter(const Station * const &a, const Station * const &b, const CargoTypes &cargo_filter) { byte maxr1 = 0; byte maxr2 = 0; @@ -325,7 +325,7 @@ protected: } /** Sort stations by their rating */ - static bool StationRatingMinSorter(const Station * const &a, const Station * const &b) + static bool StationRatingMinSorter(const Station * const &a, const Station * const &b, const CargoTypes &cargo_filter) { byte minr1 = 255; byte minr2 = 255; diff --git a/src/town_gui.cpp b/src/town_gui.cpp index 19c28fcb46..c7c33cddb3 100644 --- a/src/town_gui.cpp +++ b/src/town_gui.cpp @@ -47,7 +47,7 @@ TownKdtree _town_local_authority_kdtree(&Kdtree_TownXYFunc); -typedef GUIList GUITownList; +typedef GUIList GUITownList; static const NWidgetPart _nested_town_authority_widgets[] = { NWidget(NWID_HORIZONTAL), @@ -707,7 +707,7 @@ private: StringFilter string_filter; ///< Filter for towns QueryString townname_editbox; ///< Filter editbox - GUITownList towns; + GUITownList towns{TownDirectoryWindow::last_sorting.order}; Scrollbar *vscroll; @@ -736,31 +736,31 @@ private: } /** Sort by town name */ - static bool TownNameSorter(const Town * const &a, const Town * const &b) + static bool TownNameSorter(const Town * const &a, const Town * const &b, const bool &) { return StrNaturalCompare(a->GetCachedName(), b->GetCachedName()) < 0; // Sort by name (natural sorting). } /** Sort by population (default descending, as big towns are of the most interest). */ - static bool TownPopulationSorter(const Town * const &a, const Town * const &b) + static bool TownPopulationSorter(const Town * const &a, const Town * const &b, const bool &order) { uint32_t a_population = a->cache.population; uint32_t b_population = b->cache.population; - if (a_population == b_population) return TownDirectoryWindow::TownNameSorter(a, b); + if (a_population == b_population) return TownDirectoryWindow::TownNameSorter(a, b, order); return a_population < b_population; } /** Sort by town rating */ - static bool TownRatingSorter(const Town * const &a, const Town * const &b) + static bool TownRatingSorter(const Town * const &a, const Town * const &b, const bool &order) { - bool before = !TownDirectoryWindow::last_sorting.order; // Value to get 'a' before 'b'. + bool before = !order; // Value to get 'a' before 'b'. /* Towns without rating are always after towns with rating. */ if (HasBit(a->have_ratings, _local_company)) { if (HasBit(b->have_ratings, _local_company)) { int16_t a_rating = a->ratings[_local_company]; int16_t b_rating = b->ratings[_local_company]; - if (a_rating == b_rating) return TownDirectoryWindow::TownNameSorter(a, b); + if (a_rating == b_rating) return TownDirectoryWindow::TownNameSorter(a, b, order); return a_rating < b_rating; } return before; @@ -768,8 +768,8 @@ private: if (HasBit(b->have_ratings, _local_company)) return !before; /* Sort unrated towns always on ascending town name. */ - if (before) return TownDirectoryWindow::TownNameSorter(a, b); - return TownDirectoryWindow::TownNameSorter(b, a); + if (before) return TownDirectoryWindow::TownNameSorter(a, b, order); + return TownDirectoryWindow::TownNameSorter(b, a, order); } public: diff --git a/src/vehicle_gui_base.h b/src/vehicle_gui_base.h index a20bbd802c..734053949c 100644 --- a/src/vehicle_gui_base.h +++ b/src/vehicle_gui_base.h @@ -19,7 +19,7 @@ #include "window_gui.h" #include "widgets/dropdown_type.h" -typedef GUIList GUIVehicleList; +typedef GUIList GUIVehicleList; struct GUIVehicleGroup { VehicleList::const_iterator vehicles_begin; ///< Pointer to beginning element of this vehicle group. @@ -62,7 +62,7 @@ struct GUIVehicleGroup { } }; -typedef GUIList GUIVehicleGroupList; +typedef GUIList GUIVehicleGroupList; struct BaseVehicleListWindow : public Window {