diff --git a/src/group_gui.cpp b/src/group_gui.cpp index 5016759356..39c74b27cd 100644 --- a/src/group_gui.cpp +++ b/src/group_gui.cpp @@ -33,7 +33,7 @@ #include "table/sprites.h" #include "safeguards.h" -#include "engine_gui.h" +//#include "engine_gui.h" static const int LEVEL_WIDTH = 10; ///< Indenting width of a sub-group in pixels @@ -104,34 +104,6 @@ static const NWidgetPart _nested_group_widgets[] = { EndContainer(), EndContainer(), }; -/** Special cargo filter criteria */ -static const CargoID CF_ANY = CT_NO_REFIT; ///< Show all vehicles independent of carried cargo (i.e. no filtering) -static const CargoID CF_NONE = CT_INVALID; ///< Show only vehicles which do not carry cargo (e.g. train engines) -/** Cargo filter functions */ -static bool CDECL CargoFilter(const Vehicle * const *vid, const CargoID cid) -{ - if (cid == CF_ANY) { - return true; - } else if (cid == CF_NONE) { - for (const Vehicle *w = (*vid); w != NULL; w = w->Next()) { - if (w->cargo_cap > 0) { - return false; - } - } - return true; - } else { - for (const Vehicle *w = (*vid); w != NULL; w = w->Next()) { - if (w->cargo_cap > 0 && w->cargo_type == cid) { - return true; - } - } - return false; - } -} - -static GUIVehicleList::FilterFunction * const _filter_funcs[] = { - &CargoFilter, -}; /** Sort the groups by their name */ int CDECL GroupNameSorter(const Group * const *a, const Group * const *b) @@ -170,7 +142,6 @@ private: VGC_END }; - VehicleID vehicle_sel; ///< Selected vehicle GroupID group_sel; ///< Selected group (for drag/drop) GroupID group_rename; ///< Group being renamed, INVALID_GROUP if none GroupID group_over; ///< Group over which a vehicle is dragged, INVALID_GROUP if none @@ -181,62 +152,11 @@ private: SmallVector all_groups; ///< List of all groups, including hidden ones SmallVector collapsed_groups; ///< List of collapsed groups SmallVector collapsable_groups; ///< List of collapsable groups - CargoID cargo_filter[NUM_CARGO + 2]; ///< Available cargo filters; CargoID or CF_ANY or CF_NONE - StringID cargo_filter_texts[NUM_CARGO + 3]; ///< Texts for filter_cargo, terminated by INVALID_STRING_ID - byte cargo_filter_criteria; ///< Selected cargo filter SmallVector indents; ///< Indentation levels Dimension column_size[VGC_END]; ///< Size of the columns in the group list. - /** Populate the filter list and set the cargo filter criteria. */ - void SetCargoFilterArray() - { - uint filter_items = 0; - - /* Add item for disabling filtering. */ - this->cargo_filter[filter_items] = CF_ANY; - this->cargo_filter_texts[filter_items] = STR_PURCHASE_INFO_ALL_TYPES; - this->cargo_filter_criteria = filter_items; - filter_items++; - - /* Add item for vehicles not carrying anything, e.g. train engines. - * This could also be useful for eyecandy vehicles of other types, but is likely too confusing for joe, */ - this->cargo_filter[filter_items] = CF_NONE; - this->cargo_filter_texts[filter_items] = STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY_NONE; - filter_items++; - - /* Collect available cargo types for filtering. */ - const CargoSpec *cs; - FOR_ALL_SORTED_STANDARD_CARGOSPECS(cs) { - 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->vehicles.SetFilterFuncs(_filter_funcs); - this->vehicles.SetFilterState(this->cargo_filter[this->cargo_filter_criteria] != CF_ANY); - } - /** Filter the engine list against the currently selected cargo filter */ - void FilterVehicleList() - { - this->vehicles.Filter(this->cargo_filter[this->cargo_filter_criteria]); - if (0 == this->vehicles.Length()) { // no engine passed through the filter, invalidate the previously selected engine - this->vehicle_sel = INVALID_VEHICLE; - } - else if (this->vehicle_sel != INVALID_VEHICLE && !this->vehicles.Contains(Vehicle::Get(this->vehicle_sel))) { // previously selected engine didn't pass the filter, select the first engine of the list - this->vehicle_sel = this->vehicles[0]->index; - } - } - - void OnInit() - { - this->SetCargoFilterArray(); - } - /** return true if group has children */ bool AddParents(GUIGroupList *source, GroupID parent, int indent, bool parent_collapsed) { @@ -448,7 +368,6 @@ public: } this->vli.index = ALL_GROUP; - this->vehicle_sel = INVALID_VEHICLE; this->group_sel = INVALID_GROUP; this->group_rename = INVALID_GROUP; this->group_over = INVALID_GROUP; @@ -609,7 +528,6 @@ public: * else this->list will contain all vehicles which belong to the selected group */ this->BuildVehicleList(); this->SortVehicleList(); - this->FilterVehicleList(); this->BuildGroupList(this->owner); @@ -1019,13 +937,7 @@ public: this->vehicles.SetSortType(index); break; case WID_GL_FILTER_BY_CARGO: // Select a cargo filter criteria - if (this->cargo_filter_criteria != index) { - this->cargo_filter_criteria = index; - /* deactivate filter if criteria is 'Show All', activate it otherwise */ - this->vehicles.SetFilterState(this->cargo_filter[this->cargo_filter_criteria] != CF_ANY); - this->vehicles.SetFilterType(0); - this->vehicles.ForceRebuild(); - } + this->SetCargoFilterIndex(index); break; case WID_GL_MANAGE_VEHICLES_DROPDOWN: assert(this->ShouldShowActionDropdownList()); diff --git a/src/tracerestrict_gui.cpp b/src/tracerestrict_gui.cpp index 129d045f4c..b95d6e0f57 100644 --- a/src/tracerestrict_gui.cpp +++ b/src/tracerestrict_gui.cpp @@ -2596,6 +2596,7 @@ enum TraceRestrictSlotWindowWidgets { WID_TRSL_SET_SLOT_MAX_OCCUPANCY, WID_TRSL_SORT_BY_ORDER, WID_TRSL_SORT_BY_DROPDOWN, + WID_TRSL_FILTER_BY_CARGO, WID_TRSL_LIST_VEHICLE, WID_TRSL_LIST_VEHICLE_SCROLLBAR, }; @@ -2636,6 +2637,7 @@ static const NWidgetPart _nested_slot_widgets[] = { NWidget(NWID_HORIZONTAL), NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_TRSL_SORT_BY_ORDER), SetMinimalSize(81, 12), SetDataTip(STR_BUTTON_SORT_BY, STR_TOOLTIP_SORT_ORDER), NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_TRSL_SORT_BY_DROPDOWN), SetMinimalSize(167, 12), SetDataTip(0x0, STR_TOOLTIP_SORT_CRITERIA), + NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_TRSL_FILTER_BY_CARGO), SetMinimalSize(167, 12), SetDataTip(STR_JUST_STRING, STR_TOOLTIP_FILTER_CRITERIA), NWidget(WWT_PANEL, COLOUR_GREY), SetMinimalSize(12, 12), SetResize(1, 0), EndContainer(), EndContainer(), NWidget(NWID_HORIZONTAL), @@ -2661,7 +2663,6 @@ private: VGC_END }; - VehicleID vehicle_sel; ///< Selected vehicle TraceRestrictSlotID slot_sel; ///< Selected slot (for drag/drop) bool slot_set_max_occupancy; ///< True if slot max occupancy is being changed, instead of renaming TraceRestrictSlotID slot_rename; ///< Slot being renamed or max occupancy changed, INVALID_TRACE_RESTRICT_SLOT_ID if none @@ -2784,7 +2785,6 @@ public: this->sorting = &_sorting.train; this->vli.index = ALL_TRAINS_TRACE_RESTRICT_SLOT_ID; - this->vehicle_sel = INVALID_VEHICLE; this->slot_sel = INVALID_TRACE_RESTRICT_SLOT_ID; this->slot_rename = INVALID_TRACE_RESTRICT_SLOT_ID; this->slot_set_max_occupancy = false; @@ -2881,6 +2881,15 @@ public: this->SetDirty(); } + virtual void SetStringParameters(int widget) const + { + switch (widget) { + case WID_TRSL_FILTER_BY_CARGO: + SetDParam(0, this->cargo_filter_texts[this->cargo_filter_criteria]); + break; + } + } + virtual void OnPaint() { /* If we select the all vehicles, this->list will contain all vehicles of the owner @@ -2913,6 +2922,8 @@ public: /* Set text of sort by dropdown */ this->GetWidget(WID_TRSL_SORT_BY_DROPDOWN)->widget_data = this->vehicle_sorter_names[this->vehicles.SortType()]; + this->GetWidget(WID_TRSL_FILTER_BY_CARGO)->widget_data = this->cargo_filter_texts[this->cargo_filter_criteria]; + this->DrawWidgets(); } @@ -2969,6 +2980,10 @@ public: ShowDropDownMenu(this, this->vehicle_sorter_names, this->vehicles.SortType(), WID_TRSL_SORT_BY_DROPDOWN, 0, 0); return; + case WID_TRSL_FILTER_BY_CARGO: // Cargo filter dropdown + ShowDropDownMenu(this, this->cargo_filter_texts, this->cargo_filter_criteria, WID_TRSL_FILTER_BY_CARGO, 0, 0); + break; + case WID_TRSL_ALL_VEHICLES: // All vehicles button if (this->vli.index != ALL_TRAINS_TRACE_RESTRICT_SLOT_ID) { this->vli.index = ALL_TRAINS_TRACE_RESTRICT_SLOT_ID; @@ -3107,6 +3122,10 @@ public: this->vehicles.SetSortType(index); break; + case WID_TRSL_FILTER_BY_CARGO: // Select a cargo filter criteria + this->SetCargoFilterIndex(index); + break; + default: NOT_REACHED(); } diff --git a/src/vehicle_gui.cpp b/src/vehicle_gui.cpp index ef1822cf01..a17c7666a5 100644 --- a/src/vehicle_gui.cpp +++ b/src/vehicle_gui.cpp @@ -142,12 +142,101 @@ void BaseVehicleListWindow::BuildVehicleList() GenerateVehicleSortList(&this->vehicles, this->vli); + this->FilterVehicleList(); + this->unitnumber_digits = GetUnitNumberDigits(this->vehicles); this->vehicles.RebuildDone(); this->vscroll->SetCount(this->vehicles.Length()); } +/** Cargo filter functions */ +static bool CDECL CargoFilter(const Vehicle * const *vid, const CargoID cid) +{ + if (cid == BaseVehicleListWindow::CF_ANY) { + return true; + } else if (cid == BaseVehicleListWindow::CF_NONE) { + for (const Vehicle *w = (*vid); w != NULL; w = w->Next()) { + if (w->cargo_cap > 0) { + return false; + } + } + return true; + } else { + for (const Vehicle *w = (*vid); w != NULL; w = w->Next()) { + if (w->cargo_cap > 0 && w->cargo_type == cid) { + return true; + } + } + return false; + } +} + +static GUIVehicleList::FilterFunction * const _filter_funcs[] = { + &CargoFilter, +}; + +/** Set cargo filter list item index. */ +void BaseVehicleListWindow::SetCargoFilterIndex(int index) +{ + if (this->cargo_filter_criteria != index) { + this->cargo_filter_criteria = index; + /* deactivate filter if criteria is 'Show All', activate it otherwise */ + this->vehicles.SetFilterState(this->cargo_filter[this->cargo_filter_criteria] != CF_ANY); + this->vehicles.SetFilterType(0); + this->vehicles.ForceRebuild(); + } +} + +/** Populate the filter list and set the cargo filter criteria. */ +void BaseVehicleListWindow::SetCargoFilterArray() +{ + uint filter_items = 0; + + /* Add item for disabling filtering. */ + this->cargo_filter[filter_items] = CF_ANY; + this->cargo_filter_texts[filter_items] = STR_PURCHASE_INFO_ALL_TYPES; + this->cargo_filter_criteria = filter_items; + filter_items++; + + /* Add item for vehicles not carrying anything, e.g. train engines. + * This could also be useful for eyecandy vehicles of other types, but is likely too confusing for joe, */ + this->cargo_filter[filter_items] = CF_NONE; + this->cargo_filter_texts[filter_items] = STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY_NONE; + filter_items++; + + /* Collect available cargo types for filtering. */ + const CargoSpec *cs; + FOR_ALL_SORTED_STANDARD_CARGOSPECS(cs) { + 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->vehicles.SetFilterFuncs(_filter_funcs); + this->vehicles.SetFilterState(this->cargo_filter[this->cargo_filter_criteria] != CF_ANY); +} + +/** Filter the engine list against the currently selected cargo filter */ +void BaseVehicleListWindow::FilterVehicleList() +{ + this->vehicles.Filter(this->cargo_filter[this->cargo_filter_criteria]); + if (0 == this->vehicles.Length()) { + // no vehicle passed through the filter, invalidate the previously selected vehicle + this->vehicle_sel = INVALID_VEHICLE; + } else if (this->vehicle_sel != INVALID_VEHICLE && !this->vehicles.Contains(Vehicle::Get(this->vehicle_sel))) { // previously selected engine didn't pass the filter, remove selection + this->vehicle_sel = INVALID_VEHICLE; + } +} + +void BaseVehicleListWindow::OnInit() +{ + this->SetCargoFilterArray(); +} + /** * Compute the size for the Action dropdown. * @param show_autoreplace If true include the autoreplace item. @@ -1384,6 +1473,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(), @@ -1603,6 +1695,8 @@ public: this->CreateNestedTree(); + this->GetWidget(WID_VL_FILTER_BY_CARGO_SEL)->SetDisplayedPlane((this->vli.type == VL_SHARED_ORDERS || this->vli.type == VL_SINGLE_VEH) ? SZSP_NONE : 0); + this->vscroll = this->GetScrollbar(WID_VL_SCROLLBAR); this->vehicles.SetListing(*this->sorting); @@ -1674,6 +1768,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: { switch (this->vli.type) { case VL_SHARED_ORDERS: // Shared Orders @@ -1753,6 +1851,8 @@ public: /* Set text of sort by dropdown widget. */ this->GetWidget(WID_VL_SORT_BY_PULLDOWN)->widget_data = this->vehicle_sorter_names[this->vehicles.SortType()]; + this->GetWidget(WID_VL_FILTER_BY_CARGO)->widget_data = this->cargo_filter_texts[this->cargo_filter_criteria]; + this->DrawWidgets(); } @@ -1769,6 +1869,10 @@ public: (this->vli.vtype == VEH_TRAIN || this->vli.vtype == VEH_ROAD) ? 0 : this->vehicle_sorter_non_ground_veh_disable_mask, 0, DDSF_LOST_FOCUS); 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->vehicles.Length()) return; // click out of list bound @@ -1802,6 +1906,9 @@ public: case WID_VL_SORT_BY_PULLDOWN: this->vehicles.SetSortType(index); break; + case WID_VL_FILTER_BY_CARGO: + this->SetCargoFilterIndex(index); + break; case WID_VL_MANAGE_VEHICLES_DROPDOWN: assert(this->ShouldShowActionDropdownList()); diff --git a/src/vehicle_gui_base.h b/src/vehicle_gui_base.h index 94a71db714..5bbe9c498e 100644 --- a/src/vehicle_gui_base.h +++ b/src/vehicle_gui_base.h @@ -26,6 +26,17 @@ struct BaseVehicleListWindow : public Window { byte unitnumber_digits; ///< The number of digits of the highest unit number Scrollbar *vscroll; VehicleListIdentifier vli; ///< Identifier of the vehicle list we want to currently show. + VehicleID vehicle_sel; ///< Selected vehicle + + /** Special cargo filter criteria */ + enum CargoFilterSpecialType { + CF_ANY = CT_NO_REFIT, ///< Show all vehicles independent of carried cargo (i.e. no filtering) + CF_NONE = CT_INVALID, ///< Show only vehicles which do not carry cargo (e.g. train engines) + }; + + CargoID cargo_filter[NUM_CARGO + 2]; ///< Available cargo filters; CargoID or CF_ANY or CF_NONE + StringID cargo_filter_texts[NUM_CARGO + 3]; ///< Texts for filter_cargo, terminated by INVALID_STRING_ID + byte cargo_filter_criteria; ///< Selected cargo filter enum ActionDropdownItem { ADI_TEMPLATE_REPLACE, @@ -46,12 +57,17 @@ struct BaseVehicleListWindow : public Window { BaseVehicleListWindow(WindowDesc *desc, WindowNumber wno) : Window(desc), vli(VehicleListIdentifier::UnPack(wno)) { + this->vehicle_sel = INVALID_VEHICLE; this->vehicles.SetSortFuncs(this->vehicle_sorter_funcs); } void DrawVehicleListItems(VehicleID selected_vehicle, int line_height, const Rect &r) const; void SortVehicleList(); void BuildVehicleList(); + void SetCargoFilterIndex(int index); + void SetCargoFilterArray(); + void FilterVehicleList(); + void OnInit() override; Dimension GetActionDropdownSize(bool show_autoreplace, bool show_group, bool show_template_replace, StringID change_order_str = 0); DropDownList *BuildActionDropdownList(bool show_autoreplace, bool show_group, bool show_template_replace, StringID change_order_str = 0, bool show_create_group = false); diff --git a/src/widgets/vehicle_widget.h b/src/widgets/vehicle_widget.h index a0902dab44..eefcaad398 100644 --- a/src/widgets/vehicle_widget.h +++ b/src/widgets/vehicle_widget.h @@ -65,6 +65,8 @@ enum VehicleListWidgets { WID_VL_CAPTION, ///< Caption of window. WID_VL_SORT_ORDER, ///< Sort order. WID_VL_SORT_BY_PULLDOWN, ///< Sort by dropdown list. + WID_VL_FILTER_BY_CARGO, ///< Cargo filter dropdown list + WID_VL_FILTER_BY_CARGO_SEL, ///< Cargo filter dropdown list panel selector WID_VL_LIST, ///< List of the vehicles. WID_VL_SCROLLBAR, ///< Scrollbar for the list. WID_VL_HIDE_BUTTONS, ///< Selection to hide the buttons.