Skip to content

Commit

Permalink
Fix: Make station list filters use per-window state instead of global…
Browse files Browse the repository at this point in the history
… 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.
  • Loading branch information
PeterN committed Dec 3, 2023
1 parent 0af9028 commit 743d612
Showing 1 changed file with 48 additions and 39 deletions.
87 changes: 48 additions & 39 deletions src/station_gui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -218,17 +218,26 @@ class CompanyStationsWindow : public Window
{
protected:
/* Runtime saved values */
static Listing last_sorting;
static byte facilities; // types of stations of interest
static bool include_empty; // whether we should include stations without waiting cargo
static const CargoTypes cargo_filter_max;
static CargoTypes cargo_filter; // bitmap of cargo types to include
struct FilterState {
Listing last_sorting;
byte facilities; ///< types of stations of interest
bool include_empty; ///< whether we should include stations without waiting cargo
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 */
static const StringID sorter_names[];
static GUIStationList::SortFunction * const sorter_funcs[];

GUIStationList stations{cargo_filter};
FilterState filter;
GUIStationList stations{filter.cargoes};
Scrollbar *vscroll;
uint rating_width;

Expand All @@ -247,19 +256,19 @@ class CompanyStationsWindow : public Window

for (const Station *st : Station::Iterate()) {
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;
for (CargoID j = 0; j < NUM_CARGO; j++) {
if (st->goods[j].HasRating()) {
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);
break;
}
}
}
/* 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);
}
}
Expand Down Expand Up @@ -350,8 +359,12 @@ class CompanyStationsWindow : public Window
public:
CompanyStationsWindow(WindowDesc *desc, WindowNumber window_number) : Window(desc)
{
this->stations.SetListing(this->last_sorting);
this->stations.SetSortFuncs(this->sorter_funcs);
/* Load initial filter state. */
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.NeedResort();
this->SortStationsList();
Expand All @@ -363,25 +376,27 @@ class CompanyStationsWindow : public Window

uint8_t index = 0;
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);
}
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++) {
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()];
}

~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
Expand All @@ -397,8 +412,8 @@ class CompanyStationsWindow : public Window

case WID_STL_SORTDROPBTN: {
Dimension d = {0, 0};
for (int i = 0; this->sorter_names[i] != INVALID_STRING_ID; i++) {
d = maxdim(d, GetStringBoundingBox(this->sorter_names[i]));
for (int i = 0; CompanyStationsWindow::sorter_names[i] != INVALID_STRING_ID; i++) {
d = maxdim(d, GetStringBoundingBox(CompanyStationsWindow::sorter_names[i]));
}
d.width += padding.width;
d.height += padding.height;
Expand Down Expand Up @@ -502,7 +517,7 @@ class CompanyStationsWindow : public Window
if (widget >= WID_STL_CARGOSTART) {
Rect br = r.Shrink(WidgetDimensions::scaled.bevel);
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);
GfxFillRect(br, cs->rating_colour);
TextColour tc = GetContrastColour(cs->rating_colour);
Expand Down Expand Up @@ -545,13 +560,13 @@ class CompanyStationsWindow : public Window
case WID_STL_AIRPLANE:
case WID_STL_SHIP:
if (_ctrl_pressed) {
ToggleBit(this->facilities, widget - WID_STL_TRAIN);
ToggleBit(this->filter.facilities, widget - WID_STL_TRAIN);
this->ToggleWidgetLoweredState(widget);
} else {
for (uint i : SetBitIterator(this->facilities)) {
for (uint i : SetBitIterator(this->filter.facilities)) {
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->stations.ForceRebuild();
Expand All @@ -563,7 +578,7 @@ class CompanyStationsWindow : public Window
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->SetDirty();
break;
Expand All @@ -574,8 +589,8 @@ class CompanyStationsWindow : public Window
}
this->LowerWidget(WID_STL_NOCARGOWAITING);

this->cargo_filter = _cargo_mask;
this->include_empty = true;
this->filter.cargoes = _cargo_mask;
this->filter.include_empty = true;
this->stations.ForceRebuild();
this->SetDirty();
break;
Expand All @@ -592,15 +607,15 @@ class CompanyStationsWindow : public Window

case WID_STL_NOCARGOWAITING:
if (_ctrl_pressed) {
this->include_empty = !this->include_empty;
this->filter.include_empty = !this->filter.include_empty;
this->ToggleWidgetLoweredState(WID_STL_NOCARGOWAITING);
} else {
for (uint i = 0; i < _sorted_standard_cargo_specs.size(); i++) {
this->RaiseWidget(WID_STL_CARGOSTART + i);
}

this->cargo_filter = 0;
this->include_empty = true;
this->filter.cargoes = 0;
this->filter.include_empty = true;

this->LowerWidget(WID_STL_NOCARGOWAITING);
}
Expand All @@ -614,18 +629,18 @@ class CompanyStationsWindow : public Window
const CargoSpec *cs = _sorted_cargo_specs[widget - WID_STL_CARGOSTART];

if (_ctrl_pressed) {
ToggleBit(this->cargo_filter, cs->Index());
ToggleBit(this->filter.cargoes, cs->Index());
this->ToggleWidgetLoweredState(widget);
} else {
for (uint i = 0; i < _sorted_standard_cargo_specs.size(); i++) {
this->RaiseWidget(WID_STL_CARGOSTART + i);
}
this->RaiseWidget(WID_STL_NOCARGOWAITING);

this->cargo_filter = 0;
this->include_empty = false;
this->filter.cargoes = 0;
this->filter.include_empty = false;

SetBit(this->cargo_filter, cs->Index());
SetBit(this->filter.cargoes, cs->Index());
this->LowerWidget(widget);
}
this->stations.ForceRebuild();
Expand All @@ -642,7 +657,7 @@ class CompanyStationsWindow : public Window
this->stations.SetSortType(index);

/* 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();
}
Expand Down Expand Up @@ -678,12 +693,6 @@ class CompanyStationsWindow : public Window
}
};

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 */
GUIStationList::SortFunction * const CompanyStationsWindow::sorter_funcs[] = {
&StationNameSorter,
Expand Down

0 comments on commit 743d612

Please sign in to comment.