mirror of https://github.com/OpenTTD/OpenTTD
Fix: Make station list filters use per-window state instead of global state.
Changing filters with multiple windows open would have unexpected effects leading to inconsistent state. Now state is loaded and saved when the window is opened and closed, so state is still persistent.pull/11539/head
parent
dcf730f1f6
commit
07a8bd21e4
|
@ -218,17 +218,26 @@ class CompanyStationsWindow : public Window
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
/* Runtime saved values */
|
/* Runtime saved values */
|
||||||
static Listing last_sorting;
|
struct FilterState {
|
||||||
static byte facilities; // types of stations of interest
|
Listing last_sorting;
|
||||||
static bool include_empty; // whether we should include stations without waiting cargo
|
byte facilities; ///< types of stations of interest
|
||||||
static const CargoTypes cargo_filter_max;
|
bool include_empty; ///< whether we should include stations without waiting cargo
|
||||||
static CargoTypes cargo_filter; // bitmap of cargo types to include
|
CargoTypes cargoes; ///< bitmap of cargo types to include
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline FilterState initial_state = {
|
||||||
|
{false, 0},
|
||||||
|
FACIL_TRAIN | FACIL_TRUCK_STOP | FACIL_BUS_STOP | FACIL_AIRPORT | FACIL_DOCK,
|
||||||
|
true,
|
||||||
|
ALL_CARGOTYPES,
|
||||||
|
};
|
||||||
|
|
||||||
/* Constants for sorting stations */
|
/* Constants for sorting stations */
|
||||||
static const StringID sorter_names[];
|
static const StringID sorter_names[];
|
||||||
static GUIStationList::SortFunction * const sorter_funcs[];
|
static GUIStationList::SortFunction * const sorter_funcs[];
|
||||||
|
|
||||||
GUIStationList stations{cargo_filter};
|
FilterState filter;
|
||||||
|
GUIStationList stations{filter.cargoes};
|
||||||
Scrollbar *vscroll;
|
Scrollbar *vscroll;
|
||||||
uint rating_width;
|
uint rating_width;
|
||||||
|
|
||||||
|
@ -247,19 +256,19 @@ protected:
|
||||||
|
|
||||||
for (const Station *st : Station::Iterate()) {
|
for (const Station *st : Station::Iterate()) {
|
||||||
if (st->owner == owner || (st->owner == OWNER_NONE && HasStationInUse(st->index, true, owner))) {
|
if (st->owner == owner || (st->owner == OWNER_NONE && HasStationInUse(st->index, true, owner))) {
|
||||||
if (this->facilities & st->facilities) { // only stations with selected facilities
|
if (this->filter.facilities & st->facilities) { // only stations with selected facilities
|
||||||
int num_waiting_cargo = 0;
|
int num_waiting_cargo = 0;
|
||||||
for (CargoID j = 0; j < NUM_CARGO; j++) {
|
for (CargoID j = 0; j < NUM_CARGO; j++) {
|
||||||
if (st->goods[j].HasRating()) {
|
if (st->goods[j].HasRating()) {
|
||||||
num_waiting_cargo++; // count number of waiting cargo
|
num_waiting_cargo++; // count number of waiting cargo
|
||||||
if (HasBit(this->cargo_filter, j)) {
|
if (HasBit(this->filter.cargoes, j)) {
|
||||||
this->stations.push_back(st);
|
this->stations.push_back(st);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* stations without waiting cargo */
|
/* stations without waiting cargo */
|
||||||
if (num_waiting_cargo == 0 && this->include_empty) {
|
if (num_waiting_cargo == 0 && this->filter.include_empty) {
|
||||||
this->stations.push_back(st);
|
this->stations.push_back(st);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -350,8 +359,12 @@ protected:
|
||||||
public:
|
public:
|
||||||
CompanyStationsWindow(WindowDesc *desc, WindowNumber window_number) : Window(desc)
|
CompanyStationsWindow(WindowDesc *desc, WindowNumber window_number) : Window(desc)
|
||||||
{
|
{
|
||||||
this->stations.SetListing(this->last_sorting);
|
/* Load initial filter state. */
|
||||||
this->stations.SetSortFuncs(this->sorter_funcs);
|
this->filter = CompanyStationsWindow::initial_state;
|
||||||
|
if (this->filter.cargoes == ALL_CARGOTYPES) this->filter.cargoes = _cargo_mask;
|
||||||
|
|
||||||
|
this->stations.SetListing(this->filter.last_sorting);
|
||||||
|
this->stations.SetSortFuncs(CompanyStationsWindow::sorter_funcs);
|
||||||
this->stations.ForceRebuild();
|
this->stations.ForceRebuild();
|
||||||
this->stations.NeedResort();
|
this->stations.NeedResort();
|
||||||
this->SortStationsList();
|
this->SortStationsList();
|
||||||
|
@ -363,25 +376,27 @@ public:
|
||||||
|
|
||||||
uint8_t index = 0;
|
uint8_t index = 0;
|
||||||
for (const CargoSpec *cs : _sorted_standard_cargo_specs) {
|
for (const CargoSpec *cs : _sorted_standard_cargo_specs) {
|
||||||
if (HasBit(this->cargo_filter, cs->Index())) {
|
if (HasBit(this->filter.cargoes, cs->Index())) {
|
||||||
this->LowerWidget(WID_STL_CARGOSTART + index);
|
this->LowerWidget(WID_STL_CARGOSTART + index);
|
||||||
}
|
}
|
||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this->cargo_filter == this->cargo_filter_max) this->cargo_filter = _cargo_mask;
|
if (this->filter.cargoes == ALL_CARGOTYPES) this->filter.cargoes = _cargo_mask;
|
||||||
|
|
||||||
for (uint i = 0; i < 5; i++) {
|
for (uint i = 0; i < 5; i++) {
|
||||||
if (HasBit(this->facilities, i)) this->LowerWidget(i + WID_STL_TRAIN);
|
if (HasBit(this->filter.facilities, i)) this->LowerWidget(i + WID_STL_TRAIN);
|
||||||
}
|
}
|
||||||
this->SetWidgetLoweredState(WID_STL_NOCARGOWAITING, this->include_empty);
|
this->SetWidgetLoweredState(WID_STL_NOCARGOWAITING, this->filter.include_empty);
|
||||||
|
|
||||||
this->GetWidget<NWidgetCore>(WID_STL_SORTDROPBTN)->widget_data = this->sorter_names[this->stations.SortType()];
|
this->GetWidget<NWidgetCore>(WID_STL_SORTDROPBTN)->widget_data = this->sorter_names[this->stations.SortType()];
|
||||||
}
|
}
|
||||||
|
|
||||||
~CompanyStationsWindow()
|
~CompanyStationsWindow()
|
||||||
{
|
{
|
||||||
this->last_sorting = this->stations.GetListing();
|
/* Save filter state. */
|
||||||
|
this->filter.last_sorting = this->stations.GetListing();
|
||||||
|
CompanyStationsWindow::initial_state = this->filter;
|
||||||
}
|
}
|
||||||
|
|
||||||
void UpdateWidgetSize(int widget, Dimension *size, [[maybe_unused]] const Dimension &padding, [[maybe_unused]] Dimension *fill, [[maybe_unused]] Dimension *resize) override
|
void UpdateWidgetSize(int widget, Dimension *size, [[maybe_unused]] const Dimension &padding, [[maybe_unused]] Dimension *fill, [[maybe_unused]] Dimension *resize) override
|
||||||
|
@ -397,8 +412,8 @@ public:
|
||||||
|
|
||||||
case WID_STL_SORTDROPBTN: {
|
case WID_STL_SORTDROPBTN: {
|
||||||
Dimension d = {0, 0};
|
Dimension d = {0, 0};
|
||||||
for (int i = 0; this->sorter_names[i] != INVALID_STRING_ID; i++) {
|
for (int i = 0; CompanyStationsWindow::sorter_names[i] != INVALID_STRING_ID; i++) {
|
||||||
d = maxdim(d, GetStringBoundingBox(this->sorter_names[i]));
|
d = maxdim(d, GetStringBoundingBox(CompanyStationsWindow::sorter_names[i]));
|
||||||
}
|
}
|
||||||
d.width += padding.width;
|
d.width += padding.width;
|
||||||
d.height += padding.height;
|
d.height += padding.height;
|
||||||
|
@ -502,7 +517,7 @@ public:
|
||||||
if (widget >= WID_STL_CARGOSTART) {
|
if (widget >= WID_STL_CARGOSTART) {
|
||||||
Rect br = r.Shrink(WidgetDimensions::scaled.bevel);
|
Rect br = r.Shrink(WidgetDimensions::scaled.bevel);
|
||||||
const CargoSpec *cs = _sorted_cargo_specs[widget - WID_STL_CARGOSTART];
|
const CargoSpec *cs = _sorted_cargo_specs[widget - WID_STL_CARGOSTART];
|
||||||
int cg_ofst = HasBit(this->cargo_filter, cs->Index()) ? WidgetDimensions::scaled.pressed : 0;
|
int cg_ofst = HasBit(this->filter.cargoes, cs->Index()) ? WidgetDimensions::scaled.pressed : 0;
|
||||||
br = br.Translate(cg_ofst, cg_ofst);
|
br = br.Translate(cg_ofst, cg_ofst);
|
||||||
GfxFillRect(br, cs->rating_colour);
|
GfxFillRect(br, cs->rating_colour);
|
||||||
TextColour tc = GetContrastColour(cs->rating_colour);
|
TextColour tc = GetContrastColour(cs->rating_colour);
|
||||||
|
@ -545,13 +560,13 @@ public:
|
||||||
case WID_STL_AIRPLANE:
|
case WID_STL_AIRPLANE:
|
||||||
case WID_STL_SHIP:
|
case WID_STL_SHIP:
|
||||||
if (_ctrl_pressed) {
|
if (_ctrl_pressed) {
|
||||||
ToggleBit(this->facilities, widget - WID_STL_TRAIN);
|
ToggleBit(this->filter.facilities, widget - WID_STL_TRAIN);
|
||||||
this->ToggleWidgetLoweredState(widget);
|
this->ToggleWidgetLoweredState(widget);
|
||||||
} else {
|
} else {
|
||||||
for (uint i : SetBitIterator(this->facilities)) {
|
for (uint i : SetBitIterator(this->filter.facilities)) {
|
||||||
this->RaiseWidget(i + WID_STL_TRAIN);
|
this->RaiseWidget(i + WID_STL_TRAIN);
|
||||||
}
|
}
|
||||||
this->facilities = 1 << (widget - WID_STL_TRAIN);
|
this->filter.facilities = 1 << (widget - WID_STL_TRAIN);
|
||||||
this->LowerWidget(widget);
|
this->LowerWidget(widget);
|
||||||
}
|
}
|
||||||
this->stations.ForceRebuild();
|
this->stations.ForceRebuild();
|
||||||
|
@ -563,7 +578,7 @@ public:
|
||||||
this->LowerWidget(i);
|
this->LowerWidget(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
this->facilities = FACIL_TRAIN | FACIL_TRUCK_STOP | FACIL_BUS_STOP | FACIL_AIRPORT | FACIL_DOCK;
|
this->filter.facilities = FACIL_TRAIN | FACIL_TRUCK_STOP | FACIL_BUS_STOP | FACIL_AIRPORT | FACIL_DOCK;
|
||||||
this->stations.ForceRebuild();
|
this->stations.ForceRebuild();
|
||||||
this->SetDirty();
|
this->SetDirty();
|
||||||
break;
|
break;
|
||||||
|
@ -574,8 +589,8 @@ public:
|
||||||
}
|
}
|
||||||
this->LowerWidget(WID_STL_NOCARGOWAITING);
|
this->LowerWidget(WID_STL_NOCARGOWAITING);
|
||||||
|
|
||||||
this->cargo_filter = _cargo_mask;
|
this->filter.cargoes = _cargo_mask;
|
||||||
this->include_empty = true;
|
this->filter.include_empty = true;
|
||||||
this->stations.ForceRebuild();
|
this->stations.ForceRebuild();
|
||||||
this->SetDirty();
|
this->SetDirty();
|
||||||
break;
|
break;
|
||||||
|
@ -592,15 +607,15 @@ public:
|
||||||
|
|
||||||
case WID_STL_NOCARGOWAITING:
|
case WID_STL_NOCARGOWAITING:
|
||||||
if (_ctrl_pressed) {
|
if (_ctrl_pressed) {
|
||||||
this->include_empty = !this->include_empty;
|
this->filter.include_empty = !this->filter.include_empty;
|
||||||
this->ToggleWidgetLoweredState(WID_STL_NOCARGOWAITING);
|
this->ToggleWidgetLoweredState(WID_STL_NOCARGOWAITING);
|
||||||
} else {
|
} else {
|
||||||
for (uint i = 0; i < _sorted_standard_cargo_specs.size(); i++) {
|
for (uint i = 0; i < _sorted_standard_cargo_specs.size(); i++) {
|
||||||
this->RaiseWidget(WID_STL_CARGOSTART + i);
|
this->RaiseWidget(WID_STL_CARGOSTART + i);
|
||||||
}
|
}
|
||||||
|
|
||||||
this->cargo_filter = 0;
|
this->filter.cargoes = 0;
|
||||||
this->include_empty = true;
|
this->filter.include_empty = true;
|
||||||
|
|
||||||
this->LowerWidget(WID_STL_NOCARGOWAITING);
|
this->LowerWidget(WID_STL_NOCARGOWAITING);
|
||||||
}
|
}
|
||||||
|
@ -614,7 +629,7 @@ public:
|
||||||
const CargoSpec *cs = _sorted_cargo_specs[widget - WID_STL_CARGOSTART];
|
const CargoSpec *cs = _sorted_cargo_specs[widget - WID_STL_CARGOSTART];
|
||||||
|
|
||||||
if (_ctrl_pressed) {
|
if (_ctrl_pressed) {
|
||||||
ToggleBit(this->cargo_filter, cs->Index());
|
ToggleBit(this->filter.cargoes, cs->Index());
|
||||||
this->ToggleWidgetLoweredState(widget);
|
this->ToggleWidgetLoweredState(widget);
|
||||||
} else {
|
} else {
|
||||||
for (uint i = 0; i < _sorted_standard_cargo_specs.size(); i++) {
|
for (uint i = 0; i < _sorted_standard_cargo_specs.size(); i++) {
|
||||||
|
@ -622,10 +637,10 @@ public:
|
||||||
}
|
}
|
||||||
this->RaiseWidget(WID_STL_NOCARGOWAITING);
|
this->RaiseWidget(WID_STL_NOCARGOWAITING);
|
||||||
|
|
||||||
this->cargo_filter = 0;
|
this->filter.cargoes = 0;
|
||||||
this->include_empty = false;
|
this->filter.include_empty = false;
|
||||||
|
|
||||||
SetBit(this->cargo_filter, cs->Index());
|
SetBit(this->filter.cargoes, cs->Index());
|
||||||
this->LowerWidget(widget);
|
this->LowerWidget(widget);
|
||||||
}
|
}
|
||||||
this->stations.ForceRebuild();
|
this->stations.ForceRebuild();
|
||||||
|
@ -642,7 +657,7 @@ public:
|
||||||
this->stations.SetSortType(index);
|
this->stations.SetSortType(index);
|
||||||
|
|
||||||
/* Display the current sort variant */
|
/* Display the current sort variant */
|
||||||
this->GetWidget<NWidgetCore>(WID_STL_SORTDROPBTN)->widget_data = this->sorter_names[this->stations.SortType()];
|
this->GetWidget<NWidgetCore>(WID_STL_SORTDROPBTN)->widget_data = CompanyStationsWindow::sorter_names[this->stations.SortType()];
|
||||||
|
|
||||||
this->SetDirty();
|
this->SetDirty();
|
||||||
}
|
}
|
||||||
|
@ -678,12 +693,6 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Listing CompanyStationsWindow::last_sorting = {false, 0};
|
|
||||||
byte CompanyStationsWindow::facilities = FACIL_TRAIN | FACIL_TRUCK_STOP | FACIL_BUS_STOP | FACIL_AIRPORT | FACIL_DOCK;
|
|
||||||
bool CompanyStationsWindow::include_empty = true;
|
|
||||||
const CargoTypes CompanyStationsWindow::cargo_filter_max = ALL_CARGOTYPES;
|
|
||||||
CargoTypes CompanyStationsWindow::cargo_filter = ALL_CARGOTYPES;
|
|
||||||
|
|
||||||
/* Available station sorting functions */
|
/* Available station sorting functions */
|
||||||
GUIStationList::SortFunction * const CompanyStationsWindow::sorter_funcs[] = {
|
GUIStationList::SortFunction * const CompanyStationsWindow::sorter_funcs[] = {
|
||||||
&StationNameSorter,
|
&StationNameSorter,
|
||||||
|
|
Loading…
Reference in New Issue