mirror of https://github.com/OpenTTD/OpenTTD.git
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.
This commit is contained in:
parent
4d9f335f36
commit
dcf730f1f6
|
@ -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);
|
||||
|
|
|
@ -1245,7 +1245,7 @@ static const NWidgetPart _nested_industry_directory_widgets[] = {
|
|||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -79,7 +79,7 @@ static DropDownList BuildVisibilityDropDownList()
|
|||
return list;
|
||||
}
|
||||
|
||||
typedef GUIList<NetworkGameList*, StringFilter&> GUIGameServerList;
|
||||
typedef GUIList<NetworkGameList*, std::nullptr_t, StringFilter&> GUIGameServerList;
|
||||
typedef int ServerListPosition;
|
||||
static const ServerListPosition SLP_INVALID = -1;
|
||||
|
||||
|
|
|
@ -602,7 +602,7 @@ static void ShowSavePresetWindow(const char *initial_text);
|
|||
* 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;
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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<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;
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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 {
|
||||
|
||||
|
|
Loading…
Reference in New Issue