Changeset - r28236:3864664b5c22
[Not reviewed]
master
0 13 0
Peter Nelson - 6 months ago 2023-12-02 23:28:01
peter1138@openttd.org
Codechange: Optionally allow passing state to GUIList sorter function.

GUIList sorter functions can currently only use global state, which makes per-window-instance sorting difficult.
13 files changed with 67 insertions and 43 deletions:
0 comments (0 inline, 0 general)
src/engine_gui.h
Show inline comments
 
@@ -28,7 +28,7 @@ struct GUIEngineListItem {
 
	bool operator == (const EngineID &other) const { return this->engine_id == other; }
 
};
 

	
 
typedef GUIList<GUIEngineListItem, CargoID> GUIEngineList;
 
typedef GUIList<GUIEngineListItem, std::nullptr_t, CargoID> GUIEngineList;
 

	
 
typedef bool EngList_SortTypeFunction(const GUIEngineListItem&, const GUIEngineListItem&); ///< argument type for #EngList_Sort.
 
void EngList_Sort(GUIEngineList &el, EngList_SortTypeFunction compare);
src/industry_gui.cpp
Show inline comments
 
@@ -1245,7 +1245,7 @@ static const NWidgetPart _nested_industr
 
	EndContainer(),
 
};
 

	
 
typedef GUIList<const Industry *, const std::pair<CargoID, CargoID> &> GUIIndustryList;
 
typedef GUIList<const Industry *, const CargoID &, const std::pair<CargoID, CargoID> &> 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;
 
	}
 

	
 
	/**
src/network/network_content_gui.cpp
Show inline comments
 
@@ -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<const ContentInfo *, ContentListFilterData &> GUIContentList;
 
	typedef GUIList<const ContentInfo *, std::nullptr_t, ContentListFilterData &> GUIContentList;
 

	
 
	static const uint EDITBOX_MAX_SIZE   =  50; ///< Maximum size of the editbox in characters.
 

	
src/network/network_gui.cpp
Show inline comments
 
@@ -79,7 +79,7 @@ static DropDownList BuildVisibilityDropD
 
	return list;
 
}
 

	
 
typedef GUIList<NetworkGameList*, StringFilter&> GUIGameServerList;
 
typedef GUIList<NetworkGameList*, std::nullptr_t, StringFilter&> GUIGameServerList;
 
typedef int ServerListPosition;
 
static const ServerListPosition SLP_INVALID = -1;
 

	
src/newgrf_gui.cpp
Show inline comments
 
@@ -602,7 +602,7 @@ static void ShowSavePresetWindow(const c
 
 * Window for showing NewGRF files
 
 */
 
struct NewGRFWindow : public Window, NewGRFScanCallback {
 
	typedef GUIList<const GRFConfig *, StringFilter &> GUIGRFConfigList;
 
	typedef GUIList<const GRFConfig *, std::nullptr_t, StringFilter &> GUIGRFConfigList;
 

	
 
	static const uint EDITBOX_MAX_SIZE   =  50;
 

	
src/object_gui.cpp
Show inline comments
 
@@ -45,7 +45,7 @@ enum BuildObjectHotkeys {
 

	
 
/** The window used for building objects. */
 
class BuildObjectWindow : public Window {
 
	typedef GUIList<ObjectClassID, StringFilter &> GUIObjectClassList; ///< Type definition for the list to hold available object classes.
 
	typedef GUIList<ObjectClassID, std::nullptr_t, StringFilter &> 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.
 

	
src/rail_gui.cpp
Show inline comments
 
@@ -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<StationClassID, StringFilter &> GUIStationClassList; ///< Type definition for the list to hold available station classes.
 
	typedef GUIList<StationClassID, std::nullptr_t, StringFilter &> 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.
 

	
src/road_gui.cpp
Show inline comments
 
@@ -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<RoadStopClassID, StringFilter &> GUIRoadStopClassList; ///< Type definition for the list to hold available road stop classes.
 
	typedef GUIList<RoadStopClassID, std::nullptr_t, StringFilter &> 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.
 

	
src/signs_gui.cpp
Show inline comments
 
@@ -41,7 +41,7 @@ struct SignList {
 
	/**
 
	 * A GUIList contains signs and uses a StringFilter for filtering.
 
	 */
 
	typedef GUIList<const Sign *, StringFilter &> GUISignList;
 
	typedef GUIList<const Sign *, std::nullptr_t, StringFilter &> GUISignList;
 

	
 
	GUISignList signs;
 

	
src/sortlist_type.h
Show inline comments
 
@@ -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 <typename T, typename F = const char*>
 
template <typename T, typename P = std::nullptr_t, typename F = const char*>
 
class GUIList : public std::vector<T> {
 
public:
 
	typedef bool SortFunction(const T&, const T&);  ///< Signature of sort function.
 
	using SortFunction = std::conditional_t<std::is_same_v<P, std::nullptr_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<std::is_same_v<P, std::nullptr_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 <typename T_ = T, typename P_ = P, typename _F = F, std::enable_if_t<std::is_same_v<P_, std::nullptr_t>>* = 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 <typename T_ = T, typename P_ = P, typename _F = F, std::enable_if_t<!std::is_same_v<P_, std::nullptr_t>>* = 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<T>::begin(), std::vector<T>::end(), [&](const T &a, const T &b) { return desc ? compare(b, a) : compare(a, b); });
 
		if constexpr (std::is_same_v<P, std::nullptr_t>) {
 
			std::sort(std::vector<T>::begin(), std::vector<T>::end(), [&](const T &a, const T &b) { return desc ? compare(b, a) : compare(a, b); });
 
		} else {
 
			std::sort(std::vector<T>::begin(), std::vector<T>::end(), [&](const T &a, const T &b) { return desc ? compare(b, a, params) : compare(a, b, params); });
 
		}
 
		return true;
 
	}
 

	
src/station_gui.cpp
Show inline comments
 
@@ -209,7 +209,7 @@ static void StationsWndShowStationRating
 
	if (w != 0) GfxFillRect(left + padding, y, left + w - 1, y + padding - 1, PC_GREEN);
 
}
 

	
 
typedef GUIList<const Station*> GUIStationList;
 
typedef GUIList<const Station*, const CargoTypes &> 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;
src/town_gui.cpp
Show inline comments
 
@@ -47,7 +47,7 @@
 

	
 
TownKdtree _town_local_authority_kdtree(&Kdtree_TownXYFunc);
 

	
 
typedef GUIList<const Town*> GUITownList;
 
typedef GUIList<const Town*, const bool &> 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:
src/vehicle_gui_base.h
Show inline comments
 
@@ -19,7 +19,7 @@
 
#include "window_gui.h"
 
#include "widgets/dropdown_type.h"
 

	
 
typedef GUIList<const Vehicle*, CargoID> GUIVehicleList;
 
typedef GUIList<const Vehicle*, std::nullptr_t, CargoID> GUIVehicleList;
 

	
 
struct GUIVehicleGroup {
 
	VehicleList::const_iterator vehicles_begin;    ///< Pointer to beginning element of this vehicle group.
 
@@ -62,7 +62,7 @@ struct GUIVehicleGroup {
 
	}
 
};
 

	
 
typedef GUIList<GUIVehicleGroup, CargoID> GUIVehicleGroupList;
 
typedef GUIList<GUIVehicleGroup, std::nullptr_t, CargoID> GUIVehicleGroupList;
 

	
 
struct BaseVehicleListWindow : public Window {
 

	
0 comments (0 inline, 0 general)