Feature: Add cargo filter support to vehicle list. (#8308)
This commit is contained in:
@@ -139,6 +139,7 @@ const StringID BaseVehicleListWindow::vehicle_depot_name[] = {
|
||||
|
||||
BaseVehicleListWindow::BaseVehicleListWindow(WindowDesc *desc, WindowNumber wno) : Window(desc), vli(VehicleListIdentifier::UnPack(wno))
|
||||
{
|
||||
this->vehicle_sel = INVALID_VEHICLE;
|
||||
this->grouping = _grouping[vli.type][vli.vtype];
|
||||
this->UpdateSortingFromGrouping();
|
||||
}
|
||||
@@ -195,6 +196,8 @@ void BaseVehicleListWindow::BuildVehicleList()
|
||||
max_unitnumber = std::max<uint>(max_unitnumber, (*it)->unitnumber);
|
||||
}
|
||||
this->unitnumber_digits = CountDigitsForAllocatingSpace(max_unitnumber);
|
||||
|
||||
this->FilterVehicleList();
|
||||
} else {
|
||||
/* Sort by the primary vehicle; we just want all vehicles that share the same orders to form a contiguous range. */
|
||||
std::stable_sort(this->vehicles.begin(), this->vehicles.end(), [](const Vehicle * const &u, const Vehicle * const &v) {
|
||||
@@ -223,6 +226,118 @@ void BaseVehicleListWindow::BuildVehicleList()
|
||||
this->vscroll->SetCount(static_cast<int>(this->vehgroups.size()));
|
||||
}
|
||||
|
||||
|
||||
/** Cargo filter functions */
|
||||
/**
|
||||
* Check whether a vehicle can carry a specific cargo.
|
||||
* @param vehgroup The vehicle group which contains the vehicle to be checked
|
||||
* @param cid The cargo what we are looking for
|
||||
* @return Whether the vehicle can carry the specified cargo or not
|
||||
*/
|
||||
static bool CDECL CargoFilter(const GUIVehicleGroup *vehgroup, const CargoID cid)
|
||||
{
|
||||
const Vehicle *v = (*vehgroup).GetSingleVehicle();
|
||||
if (cid == BaseVehicleListWindow::CF_ANY) {
|
||||
return true;
|
||||
} else if (cid == BaseVehicleListWindow::CF_NONE) {
|
||||
for (const Vehicle *w = v; w != nullptr; w = w->Next()) {
|
||||
if (w->cargo_cap > 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
} else if (cid == BaseVehicleListWindow::CF_FREIGHT) {
|
||||
bool have_capacity = false;
|
||||
for (const Vehicle *w = v; w != nullptr; w = w->Next()) {
|
||||
if (w->cargo_cap > 0) {
|
||||
if (IsCargoInClass(w->cargo_type, CC_PASSENGERS)) {
|
||||
return false;
|
||||
} else {
|
||||
have_capacity = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return have_capacity;
|
||||
} else {
|
||||
for (const Vehicle *w = v; w != nullptr; w = w->Next()) {
|
||||
if (w->cargo_cap > 0 && w->cargo_type == cid) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static GUIVehicleGroupList::FilterFunction * const _filter_funcs[] = {
|
||||
&CargoFilter,
|
||||
};
|
||||
|
||||
/**
|
||||
* Set cargo filter list item index.
|
||||
* @param index The index to be set
|
||||
*/
|
||||
void BaseVehicleListWindow::SetCargoFilterIndex(byte index)
|
||||
{
|
||||
if (this->cargo_filter_criteria != index) {
|
||||
this->cargo_filter_criteria = index;
|
||||
/* Deactivate filter if criteria is 'Show All', activate it otherwise. */
|
||||
this->vehgroups.SetFilterState(this->cargo_filter[this->cargo_filter_criteria] != CF_ANY);
|
||||
this->vehgroups.SetFilterType(0);
|
||||
this->vehgroups.ForceRebuild();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*Populate the filter list and set the cargo filter criteria.
|
||||
*/
|
||||
void BaseVehicleListWindow::SetCargoFilterArray()
|
||||
{
|
||||
byte filter_items = 0;
|
||||
|
||||
/* Add item for disabling filtering. */
|
||||
this->cargo_filter[filter_items] = CF_ANY;
|
||||
this->cargo_filter_texts[filter_items] = STR_CARGO_TYPE_FILTER_ALL;
|
||||
this->cargo_filter_criteria = filter_items;
|
||||
filter_items++;
|
||||
|
||||
/* Add item for freight (i.e. vehicles with cargo capacity and with no passenger capacity). */
|
||||
this->cargo_filter[filter_items] = CF_FREIGHT;
|
||||
this->cargo_filter_texts[filter_items] = STR_CARGO_TYPE_FILTER_FREIGHT;
|
||||
filter_items++;
|
||||
|
||||
/* Add item for vehicles not carrying anything, e.g. train engines. */
|
||||
this->cargo_filter[filter_items] = CF_NONE;
|
||||
this->cargo_filter_texts[filter_items] = STR_CARGO_TYPE_FILTER_NONE;
|
||||
filter_items++;
|
||||
|
||||
/* Collect available cargo types for filtering. */
|
||||
for (const auto &cs : _sorted_cargo_specs) {
|
||||
this->cargo_filter[filter_items] = cs->Index();
|
||||
this->cargo_filter_texts[filter_items] = cs->name;
|
||||
filter_items++;
|
||||
}
|
||||
|
||||
/* Terminate the filter list. */
|
||||
this->cargo_filter_texts[filter_items] = INVALID_STRING_ID;
|
||||
|
||||
this->vehgroups.SetFilterFuncs(_filter_funcs);
|
||||
this->vehgroups.SetFilterState(this->cargo_filter[this->cargo_filter_criteria] != CF_ANY);
|
||||
}
|
||||
|
||||
/**
|
||||
*Filter the engine list against the currently selected cargo filter.
|
||||
*/
|
||||
void BaseVehicleListWindow::FilterVehicleList()
|
||||
{
|
||||
this->vehgroups.Filter(this->cargo_filter[this->cargo_filter_criteria]);
|
||||
if (this->vehicles.size() == 0) {
|
||||
/* No vehicle passed through the filter, invalidate the previously selected vehicle */
|
||||
this->vehicle_sel = INVALID_VEHICLE;
|
||||
} else if (this->vehicle_sel != INVALID_VEHICLE && std::find(this->vehicles.begin(), this->vehicles.end(), Vehicle::Get(this->vehicle_sel)) == this->vehicles.end()) { // previously selected engine didn't pass the filter, remove selection
|
||||
this->vehicle_sel = INVALID_VEHICLE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute the size for the Action dropdown.
|
||||
* @param show_autoreplace If true include the autoreplace item.
|
||||
@@ -248,6 +363,7 @@ Dimension BaseVehicleListWindow::GetActionDropdownSize(bool show_autoreplace, bo
|
||||
void BaseVehicleListWindow::OnInit()
|
||||
{
|
||||
this->order_arrow_width = GetStringBoundingBox(STR_TINY_RIGHT_ARROW).width;
|
||||
this->SetCargoFilterArray();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1391,6 +1507,9 @@ static const NWidgetPart _nested_vehicle_list[] = {
|
||||
NWidget(NWID_HORIZONTAL),
|
||||
NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_VL_SORT_ORDER), SetMinimalSize(81, 12), SetFill(0, 1), SetDataTip(STR_BUTTON_SORT_BY, STR_TOOLTIP_SORT_ORDER),
|
||||
NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_VL_SORT_BY_PULLDOWN), SetMinimalSize(167, 12), SetFill(0, 1), SetDataTip(0x0, STR_TOOLTIP_SORT_CRITERIA),
|
||||
NWidget(NWID_SELECTION, INVALID_COLOUR, WID_VL_FILTER_BY_CARGO_SEL),
|
||||
NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_VL_FILTER_BY_CARGO), SetMinimalSize(167, 12), SetFill(0, 1), SetDataTip(STR_JUST_STRING, STR_TOOLTIP_FILTER_CRITERIA),
|
||||
EndContainer(),
|
||||
NWidget(WWT_PANEL, COLOUR_GREY), SetMinimalSize(12, 12), SetFill(1, 1), SetResize(1, 0), EndContainer(),
|
||||
EndContainer(),
|
||||
|
||||
@@ -1662,6 +1781,8 @@ public:
|
||||
{
|
||||
this->CreateNestedTree();
|
||||
|
||||
this->GetWidget<NWidgetStacked>(WID_VL_FILTER_BY_CARGO_SEL)->SetDisplayedPlane((this->vli.type == VL_SHARED_ORDERS) ? SZSP_NONE : 0);
|
||||
|
||||
this->vscroll = this->GetScrollbar(WID_VL_SCROLLBAR);
|
||||
|
||||
this->BuildVehicleList();
|
||||
@@ -1736,6 +1857,10 @@ public:
|
||||
SetDParam(0, STR_VEHICLE_LIST_AVAILABLE_TRAINS + this->vli.vtype);
|
||||
break;
|
||||
|
||||
case WID_VL_FILTER_BY_CARGO:
|
||||
SetDParam(0, this->cargo_filter_texts[this->cargo_filter_criteria]);
|
||||
break;
|
||||
|
||||
case WID_VL_CAPTION:
|
||||
case WID_VL_CAPTION_SHARED_ORDERS: {
|
||||
switch (this->vli.type) {
|
||||
@@ -1819,6 +1944,8 @@ public:
|
||||
/* Set text of sort by dropdown widget. */
|
||||
this->GetWidget<NWidgetCore>(WID_VL_SORT_BY_PULLDOWN)->widget_data = this->GetVehicleSorterNames()[this->vehgroups.SortType()];
|
||||
|
||||
this->GetWidget<NWidgetCore>(WID_VL_FILTER_BY_CARGO)->widget_data = this->cargo_filter_texts[this->cargo_filter_criteria];
|
||||
|
||||
this->DrawWidgets();
|
||||
}
|
||||
|
||||
@@ -1845,6 +1972,10 @@ public:
|
||||
(this->vli.vtype == VEH_TRAIN || this->vli.vtype == VEH_ROAD) ? 0 : (1 << 10));
|
||||
return;
|
||||
|
||||
case WID_VL_FILTER_BY_CARGO: // Cargo filter dropdown
|
||||
ShowDropDownMenu(this, this->cargo_filter_texts, this->cargo_filter_criteria, WID_VL_FILTER_BY_CARGO, 0, 0);
|
||||
break;
|
||||
|
||||
case WID_VL_LIST: { // Matrix to show vehicles
|
||||
uint id_v = this->vscroll->GetScrolledRowFromWidget(pt.y, this, WID_VL_LIST);
|
||||
if (id_v >= this->vehgroups.size()) return; // click out of list bound
|
||||
@@ -1913,6 +2044,10 @@ public:
|
||||
this->vehgroups.SetSortType(index);
|
||||
break;
|
||||
|
||||
case WID_VL_FILTER_BY_CARGO:
|
||||
this->SetCargoFilterIndex(index);
|
||||
break;
|
||||
|
||||
case WID_VL_MANAGE_VEHICLES_DROPDOWN:
|
||||
assert(this->vehicles.size() != 0);
|
||||
|
||||
|
Reference in New Issue
Block a user