OpenTTD Source 20250528-master-g3aca5d62a8
autoreplace_gui.cpp
Go to the documentation of this file.
1/*
2 * This file is part of OpenTTD.
3 * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
4 * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
5 * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
6 */
7
10#include "stdafx.h"
11#include "command_func.h"
12#include "vehicle_gui.h"
13#include "newgrf_badge.h"
14#include "newgrf_engine.h"
15#include "rail.h"
16#include "road.h"
17#include "strings_func.h"
18#include "window_func.h"
19#include "autoreplace_func.h"
20#include "company_func.h"
21#include "engine_base.h"
22#include "window_gui.h"
23#include "engine_gui.h"
24#include "settings_func.h"
26#include "rail_gui.h"
27#include "road_gui.h"
28#include "dropdown_type.h"
29#include "dropdown_func.h"
30#include "autoreplace_cmd.h"
31#include "group_cmd.h"
32#include "settings_cmd.h"
33
35
36#include "table/strings.h"
37
38#include "safeguards.h"
39
40static bool EngineNumberSorter(const GUIEngineListItem &a, const GUIEngineListItem &b)
41{
42 return Engine::Get(a.engine_id)->list_position < Engine::Get(b.engine_id)->list_position;
43}
44
55{
57 /* We don't have any of this engine type.
58 * Either we just sold the last one, we build a new one or we stopped replacing it.
59 * In all cases, we need to update the left list */
61 }
62}
63
69{
70 InvalidateWindowData(WC_REPLACE_VEHICLE, type, 0); // Update the autoreplace window
71 InvalidateWindowClassesData(WC_BUILD_VEHICLE); // The build windows needs updating as well
72}
73
74static const StringID _start_replace_dropdown[] = {
75 STR_REPLACE_VEHICLES_NOW,
76 STR_REPLACE_VEHICLES_WHEN_OLD,
77};
78
83 std::array<EngineID, 2> sel_engine{};
84 std::array<GUIEngineList, 2> engines{};
85 bool replace_engines = true;
86 bool reset_sel_engine = true;
87 GroupID sel_group = GroupID::Invalid();
90 uint8_t sort_criteria = 0;
91 bool descending_sort_order = false;
92 bool show_hidden_engines = false;
95 std::array<Scrollbar *, 2> vscroll{};
96 GUIBadgeClasses badge_classes{};
97
105 bool GenerateReplaceRailList(EngineID e, bool draw_left, bool show_engines)
106 {
107 const RailVehicleInfo *rvi = RailVehInfo(e);
108
109 /* Ensure that the wagon/engine selection fits the engine. */
110 if ((rvi->railveh_type == RAILVEH_WAGON) == show_engines) return false;
111
112 if (draw_left && this->sel_railtype != INVALID_RAILTYPE) {
113 /* Ensure that the railtype is specific to the selected one */
114 if (rvi->railtype != this->sel_railtype) return false;
115 }
116 return true;
117 }
118
123 void GenerateReplaceVehList(bool draw_left)
124 {
125 std::vector<EngineID> variants;
126 EngineID selected_engine = EngineID::Invalid();
127 VehicleType type = this->window_number;
128 uint8_t side = draw_left ? 0 : 1;
129
130 GUIEngineList list;
131
132 for (const Engine *e : Engine::IterateType(type)) {
133 if (!draw_left && !this->show_hidden_engines && e->IsVariantHidden(_local_company)) continue;
134 EngineID eid = e->index;
135 switch (type) {
136 case VEH_TRAIN:
137 if (!this->GenerateReplaceRailList(eid, draw_left, this->replace_engines)) continue; // special rules for trains
138 break;
139
140 case VEH_ROAD:
141 if (draw_left && this->sel_roadtype != INVALID_ROADTYPE) {
142 /* Ensure that the roadtype is specific to the selected one */
143 if (e->u.road.roadtype != this->sel_roadtype) continue;
144 }
145 break;
146
147 default:
148 break;
149 }
150
151 if (draw_left) {
152 const uint num_engines = GetGroupNumEngines(_local_company, this->sel_group, eid);
153
154 /* Skip drawing the engines we don't have any of and haven't set for replacement */
155 if (num_engines == 0 && EngineReplacementForCompany(Company::Get(_local_company), eid, this->sel_group) == EngineID::Invalid()) continue;
156 } else {
157 if (!CheckAutoreplaceValidity(this->sel_engine[0], eid, _local_company)) continue;
158 }
159
160 list.emplace_back(eid, e->info.variant_id, (side == 0) ? EngineDisplayFlags{} : e->display_flags, 0);
161
162 if (side == 1) {
163 EngineID parent = e->info.variant_id;
164 while (parent != EngineID::Invalid()) {
165 variants.push_back(parent);
166 parent = Engine::Get(parent)->info.variant_id;
167 }
168 }
169 if (eid == this->sel_engine[side]) selected_engine = eid; // The selected engine is still in the list
170 }
171
172 if (side == 1) {
173 /* ensure primary engine of variant group is in list */
174 for (const auto &variant : variants) {
175 if (std::ranges::find(list, variant, &GUIEngineListItem::engine_id) == list.end()) {
176 const Engine *e = Engine::Get(variant);
177 list.emplace_back(variant, e->info.variant_id, e->display_flags | EngineDisplayFlag::Shaded, 0);
178 }
179 }
180 }
181
182 this->sel_engine[side] = selected_engine; // update which engine we selected (the same or none, if it's not in the list anymore)
183 if (draw_left) {
184 EngList_Sort(list, &EngineNumberSorter);
185 } else {
187 EngList_Sort(list, _engine_sort_functions[this->window_number][this->sort_criteria]);
188 }
189
190 this->engines[side].clear();
191 if (side == 1) {
192 GUIEngineListAddChildren(this->engines[side], list);
193 } else {
194 this->engines[side].swap(list);
195 }
196 }
197
200 {
201 EngineID e = this->sel_engine[0];
202
203 if (this->engines[0].NeedRebuild()) {
204 /* We need to rebuild the left engines list */
205 this->GenerateReplaceVehList(true);
206 this->vscroll[0]->SetCount(this->engines[0].size());
207 if (this->reset_sel_engine && this->sel_engine[0] == EngineID::Invalid() && !this->engines[0].empty()) {
208 this->sel_engine[0] = this->engines[0][0].engine_id;
209 }
210 }
211
212 if (this->engines[1].NeedRebuild() || e != this->sel_engine[0]) {
213 /* Either we got a request to rebuild the right engines list, or the left engines list selected a different engine */
214 if (this->sel_engine[0] == EngineID::Invalid()) {
215 /* Always empty the right engines list when nothing is selected in the left engines list */
216 this->engines[1].clear();
217 this->sel_engine[1] = EngineID::Invalid();
218 this->vscroll[1]->SetCount(this->engines[1].size());
219 } else {
220 if (this->reset_sel_engine && this->sel_engine[0] != EngineID::Invalid()) {
221 /* Select the current replacement for sel_engine[0]. */
223 this->sel_engine[1] = EngineReplacementForCompany(c, this->sel_engine[0], this->sel_group);
224 }
225 /* Regenerate the list on the right. Note: This resets sel_engine[1] to EngineID::Invalid(), if it is no longer available. */
226 this->GenerateReplaceVehList(false);
227 this->vscroll[1]->SetCount(this->engines[1].size());
228 if (this->reset_sel_engine && this->sel_engine[1] != EngineID::Invalid()) {
229 int position = 0;
230 for (const auto &item : this->engines[1]) {
231 if (item.engine_id == this->sel_engine[1]) break;
232 ++position;
233 }
234 this->vscroll[1]->ScrollTowards(position);
235 }
236 }
237 }
238 /* Reset the flags about needed updates */
239 this->engines[0].RebuildDone();
240 this->engines[1].RebuildDone();
241 this->reset_sel_engine = false;
242 }
243
248 void ReplaceClick_StartReplace(bool replace_when_old)
249 {
250 EngineID veh_from = this->sel_engine[0];
251 EngineID veh_to = this->sel_engine[1];
252 Command<CMD_SET_AUTOREPLACE>::Post(this->sel_group, veh_from, veh_to, replace_when_old);
253 }
254
259 {
260 /* Reset scrollbar positions */
261 this->vscroll[0]->SetPosition(0);
262 this->vscroll[1]->SetPosition(0);
263 /* Rebuild the lists */
264 this->engines[0].ForceRebuild();
265 this->engines[1].ForceRebuild();
266 this->reset_sel_engine = true;
267 this->SetDirty();
268 }
269
270public:
271 ReplaceVehicleWindow(WindowDesc &desc, VehicleType vehicletype, GroupID id_g) : Window(desc)
272 {
273 this->vehicle_type = vehicletype;
274 this->engines[0].ForceRebuild();
275 this->engines[1].ForceRebuild();
276 this->details_height = ((vehicletype == VEH_TRAIN) ? 10 : 9);
277 this->sel_engine[0] = EngineID::Invalid();
278 this->sel_engine[1] = EngineID::Invalid();
279 this->show_hidden_engines = _engine_sort_show_hidden_engines[vehicletype];
280
281 this->CreateNestedTree();
282 this->vscroll[0] = this->GetScrollbar(WID_RV_LEFT_SCROLLBAR);
283 this->vscroll[1] = this->GetScrollbar(WID_RV_RIGHT_SCROLLBAR);
284
285 NWidgetCore *widget = this->GetWidget<NWidgetCore>(WID_RV_SHOW_HIDDEN_ENGINES);
286 widget->SetStringTip(STR_SHOW_HIDDEN_ENGINES_VEHICLE_TRAIN + vehicletype, STR_SHOW_HIDDEN_ENGINES_VEHICLE_TRAIN_TOOLTIP + vehicletype);
287 widget->SetLowered(this->show_hidden_engines);
288 this->FinishInitNested(vehicletype);
289
290 this->sort_criteria = _engine_sort_last_criteria[vehicletype];
291 this->descending_sort_order = _engine_sort_last_order[vehicletype];
292 this->owner = _local_company;
293 this->sel_group = id_g;
294 }
295
296 void OnInit() override
297 {
298 this->badge_classes = GUIBadgeClasses(static_cast<GrfSpecFeature>(GSF_TRAINS + this->vehicle_type));
299 }
300
301 void UpdateWidgetSize(WidgetID widget, Dimension &size, [[maybe_unused]] const Dimension &padding, [[maybe_unused]] Dimension &fill, [[maybe_unused]] Dimension &resize) override
302 {
303 switch (widget) {
305 Dimension d = GetStringBoundingBox(this->GetWidget<NWidgetCore>(widget)->GetString());
306 d.width += padding.width + Window::SortButtonWidth() * 2; // Doubled since the string is centred and it also looks better.
307 d.height += padding.height;
308 size = maxdim(size, d);
309 break;
310 }
311
315 size.height = (this->window_number <= VEH_ROAD ? 8 : 4) * resize.height;
316 break;
317
320 size.height = GetCharacterHeight(FS_NORMAL) * this->details_height + padding.height;
321 break;
322
324 StringID str = this->GetWidget<NWidgetCore>(widget)->GetString();
325 StringID group_str = Group::IsValidID(this->sel_group) ? STR_GROUP_NAME : STR_GROUP_DEFAULT_TRAINS + this->window_number;
326 Dimension d = GetStringBoundingBox(GetString(str, group_str, this->sel_group, STR_CONFIG_SETTING_ON));
327 d = maxdim(d, GetStringBoundingBox(GetString(str, group_str, this->sel_group, STR_CONFIG_SETTING_OFF)));
328 d.width += padding.width;
329 d.height += padding.height;
330 size = maxdim(size, d);
331 break;
332 }
333
335 Dimension d = GetStringBoundingBox(STR_REPLACE_ENGINES);
336 d = maxdim(d, GetStringBoundingBox(STR_REPLACE_WAGONS));
337 d.width += padding.width;
338 d.height += padding.height;
339 size = maxdim(size, d);
340 break;
341 }
342
343 case WID_RV_INFO_TAB: {
344 Dimension d = GetStringBoundingBox(STR_REPLACE_NOT_REPLACING);
345 d = maxdim(d, GetStringBoundingBox(STR_REPLACE_NOT_REPLACING_VEHICLE_SELECTED));
346 d.width += padding.width;
347 d.height += padding.height;
348 size = maxdim(size, d);
349 break;
350 }
351
353 Dimension d = {0, 0};
354 for (const RailType &rt : _sorted_railtypes) {
356 }
357 d.width += padding.width;
358 d.height += padding.height;
359 size = maxdim(size, d);
360 break;
361 }
362
364 Dimension d = {0, 0};
365 for (const RoadType &rt : _sorted_roadtypes) {
367 }
368 d.width += padding.width;
369 d.height += padding.height;
370 size = maxdim(size, d);
371 break;
372 }
373
375 Dimension d = GetStringBoundingBox(STR_REPLACE_VEHICLES_START);
376 d = maxdim(d, GetStringListBoundingBox(_start_replace_dropdown));
377 d.width += padding.width;
378 d.height += padding.height;
379 size = maxdim(size, d);
380 break;
381 }
382 }
383 }
384
385 std::string GetWidgetString(WidgetID widget, StringID stringid) const override
386 {
387 switch (widget) {
388 case WID_RV_CAPTION:
389 switch (this->sel_group.base()) {
390 case ALL_GROUP.base():
391 return GetString(STR_REPLACE_VEHICLES_WHITE, STR_REPLACE_VEHICLE_TRAIN + this->window_number, STR_GROUP_ALL_TRAINS + this->window_number, std::monostate{});
392 break;
393
394 case DEFAULT_GROUP.base():
395 return GetString(STR_REPLACE_VEHICLES_WHITE, STR_REPLACE_VEHICLE_TRAIN + this->window_number, STR_GROUP_DEFAULT_TRAINS + this->window_number, std::monostate{});
396 break;
397
398 default:
399 return GetString(STR_REPLACE_VEHICLES_WHITE, STR_REPLACE_VEHICLE_TRAIN + this->window_number, STR_GROUP_NAME, sel_group);
400 }
401 break;
402
404 return GetString(std::data(_engine_sort_listing[this->window_number])[this->sort_criteria]);
405
407 if (const Group *g = Group::GetIfValid(this->sel_group); g != nullptr) {
408 bool remove_wagon = g->flags.Test(GroupFlag::ReplaceWagonRemoval);
409 return GetString(STR_REPLACE_REMOVE_WAGON, STR_GROUP_NAME, sel_group, remove_wagon ? STR_CONFIG_SETTING_ON : STR_CONFIG_SETTING_OFF);
410 } else {
412 bool remove_wagon = c->settings.renew_keep_length;
413 return GetString(STR_REPLACE_REMOVE_WAGON, STR_GROUP_DEFAULT_TRAINS + this->window_number, std::monostate{}, remove_wagon ? STR_CONFIG_SETTING_ON : STR_CONFIG_SETTING_OFF);
414 }
415 break;
416
418 return GetString(this->replace_engines ? STR_REPLACE_ENGINES : STR_REPLACE_WAGONS);
419
421 return GetString(this->sel_railtype == INVALID_RAILTYPE ? STR_REPLACE_ALL_RAILTYPE : GetRailTypeInfo(this->sel_railtype)->strings.replace_text);
422
424 return GetString(this->sel_roadtype == INVALID_ROADTYPE ? STR_REPLACE_ALL_ROADTYPE : GetRoadTypeInfo(this->sel_roadtype)->strings.replace_text);
425
426 default:
427 return this->Window::GetWidgetString(widget, stringid);
428 }
429 }
430
431 void DrawWidget(const Rect &r, WidgetID widget) const override
432 {
433 switch (widget) {
435 this->DrawSortButtonState(WID_RV_SORT_ASCENDING_DESCENDING, this->descending_sort_order ? SBS_DOWN : SBS_UP);
436 break;
437
438 case WID_RV_INFO_TAB: {
440 std::string str;
441 if (this->sel_engine[0] != EngineID::Invalid()) {
442 if (!EngineHasReplacementForCompany(c, this->sel_engine[0], this->sel_group)) {
443 str = GetString(STR_REPLACE_NOT_REPLACING);
444 } else {
445 bool when_old = false;
446 EngineID e = EngineReplacementForCompany(c, this->sel_engine[0], this->sel_group, &when_old);
447 str = GetString(when_old ? STR_REPLACE_REPLACING_WHEN_OLD : STR_ENGINE_NAME, PackEngineNameDParam(e, EngineNameContext::PurchaseList));
448 }
449 } else {
450 str = GetString(STR_REPLACE_NOT_REPLACING_VEHICLE_SELECTED);
451 }
452
454 break;
455 }
456
458 case WID_RV_RIGHT_MATRIX: {
459 int side = (widget == WID_RV_LEFT_MATRIX) ? 0 : 1;
460
461 /* Do the actual drawing */
462 DrawEngineList(this->window_number, r, this->engines[side], *this->vscroll[side], this->sel_engine[side], side == 0, this->sel_group, this->badge_classes);
463 break;
464 }
465 }
466 }
467
468 void OnPaint() override
469 {
470 if (this->engines[0].NeedRebuild() || this->engines[1].NeedRebuild()) this->GenerateLists();
471
473
474 /* Disable the "Start Replacing" button if:
475 * Either engines list is empty
476 * or The selected replacement engine has a replacement (to prevent loops). */
478 this->sel_engine[0] == EngineID::Invalid() || this->sel_engine[1] == EngineID::Invalid() || EngineReplacementForCompany(c, this->sel_engine[1], this->sel_group) != EngineID::Invalid());
479
480 /* Disable the "Stop Replacing" button if:
481 * The left engines list (existing vehicle) is empty
482 * or The selected vehicle has no replacement set up */
483 this->SetWidgetDisabledState(WID_RV_STOP_REPLACE, this->sel_engine[0] == EngineID::Invalid() || !EngineHasReplacementForCompany(c, this->sel_engine[0], this->sel_group));
484
485 this->DrawWidgets();
486
487 if (!this->IsShaded()) {
488 int needed_height = this->details_height;
489 /* Draw details panels. */
490 for (int side = 0; side < 2; side++) {
491 if (this->sel_engine[side] != EngineID::Invalid()) {
492 /* Use default engine details without refitting */
493 const Engine *e = Engine::Get(this->sel_engine[side]);
495 ted.cost = 0;
496 ted.FillDefaultCapacities(e);
497
498 const Rect r = this->GetWidget<NWidgetBase>(side == 0 ? WID_RV_LEFT_DETAILS : WID_RV_RIGHT_DETAILS)->GetCurrentRect()
500 int text_end = DrawVehiclePurchaseInfo(r.left, r.right, r.top, this->sel_engine[side], ted);
501 needed_height = std::max(needed_height, (text_end - r.top) / GetCharacterHeight(FS_NORMAL));
502 }
503 }
504 if (needed_height != this->details_height) { // Details window are not high enough, enlarge them.
505 this->details_height = needed_height;
506 this->ReInit();
507 return;
508 }
509 }
510 }
511
512 void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override
513 {
514 switch (widget) {
516 this->descending_sort_order ^= true;
518 this->engines[1].ForceRebuild();
519 this->SetDirty();
520 break;
521
523 this->show_hidden_engines ^= true;
525 this->engines[1].ForceRebuild();
526 this->SetWidgetLoweredState(widget, this->show_hidden_engines);
527 this->SetDirty();
528 break;
529
531 DisplayVehicleSortDropDown(this, this->window_number, this->sort_criteria, WID_RV_SORT_DROPDOWN);
532 break;
533
535 DropDownList list;
536 list.push_back(MakeDropDownListStringItem(STR_REPLACE_ENGINES, 1));
537 list.push_back(MakeDropDownListStringItem(STR_REPLACE_WAGONS, 0));
538 ShowDropDownList(this, std::move(list), this->replace_engines ? 1 : 0, WID_RV_TRAIN_ENGINEWAGON_DROPDOWN);
539 break;
540 }
541
542 case WID_RV_RAIL_TYPE_DROPDOWN: // Railtype selection dropdown menu
543 ShowDropDownList(this, GetRailTypeDropDownList(true, true), this->sel_railtype, widget);
544 break;
545
546 case WID_RV_ROAD_TYPE_DROPDOWN: // Roadtype selection dropdown menu
547 ShowDropDownList(this, GetRoadTypeDropDownList(RTTB_ROAD | RTTB_TRAM, true, true), this->sel_roadtype, widget);
548 break;
549
551 const Group *g = Group::GetIfValid(this->sel_group);
552 if (g != nullptr) {
554 } else {
555 /* toggle renew_keep_length */
556 Command<CMD_CHANGE_COMPANY_SETTING>::Post("company.renew_keep_length", Company::Get(_local_company)->settings.renew_keep_length ? 0 : 1);
557 }
558 break;
559 }
560
561 case WID_RV_START_REPLACE: { // Start replacing
562 if (this->GetWidget<NWidgetLeaf>(widget)->ButtonHit(pt)) {
565 } else {
566 bool replacment_when_old = EngineHasReplacementWhenOldForCompany(Company::Get(_local_company), this->sel_engine[0], this->sel_group);
567 ShowDropDownMenu(this, _start_replace_dropdown, replacment_when_old ? 1 : 0, WID_RV_START_REPLACE, !this->replace_engines ? 1 << 1 : 0, 0);
568 }
569 break;
570 }
571
572 case WID_RV_STOP_REPLACE: { // Stop replacing
573 EngineID veh_from = this->sel_engine[0];
574 Command<CMD_SET_AUTOREPLACE>::Post(this->sel_group, veh_from, EngineID::Invalid(), false);
575 break;
576 }
577
579 case WID_RV_RIGHT_MATRIX: {
580 uint8_t click_side;
581 if (widget == WID_RV_LEFT_MATRIX) {
582 click_side = 0;
583 } else {
584 click_side = 1;
585 }
586
587 EngineID e = EngineID::Invalid();
588 const auto it = this->vscroll[click_side]->GetScrolledItemFromWidget(this->engines[click_side], pt.y, this, widget);
589 if (it != this->engines[click_side].end()) {
590 const auto &item = *it;
591 const Rect r = this->GetWidget<NWidgetBase>(widget)->GetCurrentRect().Shrink(WidgetDimensions::scaled.matrix).WithWidth(WidgetDimensions::scaled.hsep_indent * (item.indent + 1), _current_text_dir == TD_RTL);
592 if (item.flags.Test(EngineDisplayFlag::HasVariants) && IsInsideMM(r.left, r.right, pt.x)) {
593 /* toggle folded flag on engine */
594 assert(item.variant_id != EngineID::Invalid());
595 Engine *engine = Engine::Get(item.variant_id);
597
598 InvalidateWindowData(WC_REPLACE_VEHICLE, this->window_number, 0); // Update the autoreplace window
599 InvalidateWindowClassesData(WC_BUILD_VEHICLE); // The build windows needs updating as well
600 return;
601 }
602 if (!item.flags.Test(EngineDisplayFlag::Shaded)) e = item.engine_id;
603 }
604
605 /* If Ctrl is pressed on the left side and we don't have any engines of the selected type, stop autoreplacing.
606 * This is most common when we have finished autoreplacing the engine and want to remove it from the list. */
607 if (click_side == 0 && _ctrl_pressed && e != EngineID::Invalid() &&
609 EngineID veh_from = e;
610 Command<CMD_SET_AUTOREPLACE>::Post(this->sel_group, veh_from, EngineID::Invalid(), false);
611 break;
612 }
613
614 if (e == this->sel_engine[click_side]) break; // we clicked the one we already selected
615 this->sel_engine[click_side] = e;
616 if (click_side == 0) {
617 this->engines[1].ForceRebuild();
618 this->reset_sel_engine = true;
619 }
620 this->SetDirty();
621 break;
622 }
623 }
624 }
625
626 void OnDropdownSelect(WidgetID widget, int index, int) override
627 {
628 switch (widget) {
630 if (this->sort_criteria != index) {
631 this->sort_criteria = index;
633 this->engines[1].ForceRebuild();
634 this->SetDirty();
635 }
636 break;
637
639 RailType temp = (RailType)index;
640 if (temp == this->sel_railtype) return; // we didn't select a new one. No need to change anything
641 this->sel_railtype = temp;
642 this->OnRailRoadTypeChange();
643 break;
644 }
645
647 RoadType temp = (RoadType)index;
648 if (temp == this->sel_roadtype) return; // we didn't select a new one. No need to change anything
649 this->sel_roadtype = temp;
650 this->OnRailRoadTypeChange();
651 break;
652 }
653
655 this->replace_engines = index != 0;
656 this->engines[0].ForceRebuild();
657 this->reset_sel_engine = true;
658 this->SetDirty();
659 break;
660 }
661
663 this->ReplaceClick_StartReplace(index != 0);
664 break;
665 }
666 }
667
668 bool OnTooltip([[maybe_unused]] Point pt, WidgetID widget, TooltipCloseCondition close_cond) override
669 {
670 if (widget != WID_RV_TRAIN_WAGONREMOVE_TOGGLE) return false;
671
672 if (Group::IsValidID(this->sel_group)) {
673 GuiShowTooltips(this, GetEncodedString(STR_REPLACE_REMOVE_WAGON_GROUP_HELP, STR_REPLACE_REMOVE_WAGON_TOOLTIP), close_cond);
674 } else {
675 GuiShowTooltips(this, GetEncodedString(STR_REPLACE_REMOVE_WAGON_TOOLTIP), close_cond);
676 }
677 return true;
678 }
679
680 void OnResize() override
681 {
682 this->vscroll[0]->SetCapacityFromWidget(this, WID_RV_LEFT_MATRIX);
683 this->vscroll[1]->SetCapacityFromWidget(this, WID_RV_RIGHT_MATRIX);
684 }
685
691 void OnInvalidateData([[maybe_unused]] int data = 0, [[maybe_unused]] bool gui_scope = true) override
692 {
693 if (data != 0) {
694 /* This needs to be done in command-scope to enforce rebuilding before resorting invalid data */
695 this->engines[0].ForceRebuild();
696 } else {
697 this->engines[1].ForceRebuild();
698 }
699 }
700};
701
702static constexpr NWidgetPart _nested_replace_rail_vehicle_widgets[] = {
704 NWidget(WWT_CLOSEBOX, COLOUR_GREY),
705 NWidget(WWT_CAPTION, COLOUR_GREY, WID_RV_CAPTION),
706 NWidget(WWT_SHADEBOX, COLOUR_GREY),
707 NWidget(WWT_DEFSIZEBOX, COLOUR_GREY),
708 NWidget(WWT_STICKYBOX, COLOUR_GREY),
709 EndContainer(),
711 NWidget(WWT_PANEL, COLOUR_GREY),
712 NWidget(WWT_LABEL, INVALID_COLOUR), SetStringTip(STR_REPLACE_VEHICLE_VEHICLES_IN_USE, STR_REPLACE_VEHICLE_VEHICLES_IN_USE_TOOLTIP), SetFill(1, 1), SetMinimalTextLines(1, WidgetDimensions::unscaled.framerect.Vertical()), SetResize(1, 0),
713 EndContainer(),
714 NWidget(WWT_PANEL, COLOUR_GREY),
715 NWidget(WWT_LABEL, INVALID_COLOUR), SetStringTip(STR_REPLACE_VEHICLE_AVAILABLE_VEHICLES, STR_REPLACE_VEHICLE_AVAILABLE_VEHICLES_TOOLTIP), SetFill(1, 1), SetMinimalTextLines(1, WidgetDimensions::unscaled.framerect.Vertical()), SetResize(1, 0),
716 EndContainer(),
717 EndContainer(),
721 NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_RV_RAIL_TYPE_DROPDOWN), SetMinimalSize(136, 12), SetToolTip(STR_REPLACE_RAILTYPE_TOOLTIP), SetFill(1, 0), SetResize(1, 0),
722 NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_RV_TRAIN_ENGINEWAGON_DROPDOWN), SetToolTip(STR_REPLACE_ENGINE_WAGON_SELECT_TOOLTIP),
723 EndContainer(),
724 NWidget(WWT_PANEL, COLOUR_GREY), SetResize(1, 0), EndContainer(),
725 EndContainer(),
728 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_RV_SORT_ASCENDING_DESCENDING), SetStringTip(STR_BUTTON_SORT_BY, STR_TOOLTIP_SORT_ORDER), SetFill(1, 1),
729 NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_RV_SORT_DROPDOWN), SetResize(1, 0), SetFill(1, 1), SetToolTip(STR_TOOLTIP_SORT_CRITERIA),
730 EndContainer(),
732 NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_RV_SHOW_HIDDEN_ENGINES), SetStringTip(STR_SHOW_HIDDEN_ENGINES_VEHICLE_TRAIN, STR_SHOW_HIDDEN_ENGINES_VEHICLE_TRAIN_TOOLTIP),
733 NWidget(WWT_PANEL, COLOUR_GREY), SetResize(1, 0), SetFill(1, 1), EndContainer(),
734 EndContainer(),
735 EndContainer(),
736 EndContainer(),
738 NWidget(WWT_MATRIX, COLOUR_GREY, WID_RV_LEFT_MATRIX), SetMinimalSize(216, 0), SetFill(1, 1), SetMatrixDataTip(1, 0, STR_REPLACE_LEFT_ARRAY_TOOLTIP), SetResize(1, 1), SetScrollbar(WID_RV_LEFT_SCROLLBAR),
740 NWidget(WWT_MATRIX, COLOUR_GREY, WID_RV_RIGHT_MATRIX), SetMinimalSize(216, 0), SetFill(1, 1), SetMatrixDataTip(1, 0, STR_REPLACE_RIGHT_ARRAY_TOOLTIP), SetResize(1, 1), SetScrollbar(WID_RV_RIGHT_SCROLLBAR),
742 EndContainer(),
744 NWidget(WWT_PANEL, COLOUR_GREY, WID_RV_LEFT_DETAILS), SetMinimalSize(240, 122), SetResize(1, 0), EndContainer(),
747 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_RV_TRAIN_WAGONREMOVE_TOGGLE), SetMinimalSize(138, 12), SetToolTip(STR_REPLACE_REMOVE_WAGON_TOOLTIP), SetFill(1, 0), SetResize(1, 0),
748 EndContainer(),
749 EndContainer(),
751 NWidget(NWID_PUSHBUTTON_DROPDOWN, COLOUR_GREY, WID_RV_START_REPLACE), SetMinimalSize(139, 12), SetStringTip(STR_REPLACE_VEHICLES_START, STR_REPLACE_START_BUTTON_TOOLTIP),
752 NWidget(WWT_PANEL, COLOUR_GREY, WID_RV_INFO_TAB), SetMinimalSize(167, 12), SetToolTip(STR_REPLACE_REPLACE_INFO_TAB_TOOLTIP), SetResize(1, 0),
753 EndContainer(),
754 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_RV_STOP_REPLACE), SetMinimalSize(150, 12), SetStringTip(STR_REPLACE_VEHICLES_STOP, STR_REPLACE_STOP_BUTTON_TOOLTIP),
755 NWidget(WWT_RESIZEBOX, COLOUR_GREY),
756 EndContainer(),
757};
758
759static WindowDesc _replace_rail_vehicle_desc(
760 WDP_AUTO, "replace_vehicle_train", 500, 140,
763 _nested_replace_rail_vehicle_widgets
764);
765
766static constexpr NWidgetPart _nested_replace_road_vehicle_widgets[] = {
768 NWidget(WWT_CLOSEBOX, COLOUR_GREY),
769 NWidget(WWT_CAPTION, COLOUR_GREY, WID_RV_CAPTION),
770 NWidget(WWT_SHADEBOX, COLOUR_GREY),
771 NWidget(WWT_DEFSIZEBOX, COLOUR_GREY),
772 NWidget(WWT_STICKYBOX, COLOUR_GREY),
773 EndContainer(),
775 NWidget(WWT_PANEL, COLOUR_GREY),
776 NWidget(WWT_LABEL, INVALID_COLOUR), SetStringTip(STR_REPLACE_VEHICLE_VEHICLES_IN_USE, STR_REPLACE_VEHICLE_VEHICLES_IN_USE_TOOLTIP), SetFill(1, 1), SetMinimalTextLines(1, WidgetDimensions::unscaled.framerect.Vertical()), SetResize(1, 0),
777 EndContainer(),
778 NWidget(WWT_PANEL, COLOUR_GREY),
779 NWidget(WWT_LABEL, INVALID_COLOUR), SetStringTip(STR_REPLACE_VEHICLE_AVAILABLE_VEHICLES, STR_REPLACE_VEHICLE_AVAILABLE_VEHICLES_TOOLTIP), SetFill(1, 1), SetMinimalTextLines(1, WidgetDimensions::unscaled.framerect.Vertical()), SetResize(1, 0),
780 EndContainer(),
781 EndContainer(),
784 NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_RV_ROAD_TYPE_DROPDOWN), SetMinimalSize(136, 12), SetToolTip(STR_REPLACE_ROADTYPE_TOOLTIP), SetFill(1, 0), SetResize(1, 0),
785 NWidget(WWT_PANEL, COLOUR_GREY), SetResize(1, 0), EndContainer(),
786 EndContainer(),
789 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_RV_SORT_ASCENDING_DESCENDING), SetStringTip(STR_BUTTON_SORT_BY, STR_TOOLTIP_SORT_ORDER), SetFill(1, 1),
790 NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_RV_SORT_DROPDOWN), SetResize(1, 0), SetFill(1, 1), SetToolTip(STR_TOOLTIP_SORT_CRITERIA),
791 EndContainer(),
793 NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_RV_SHOW_HIDDEN_ENGINES), SetStringTip(STR_SHOW_HIDDEN_ENGINES_VEHICLE_TRAIN, STR_SHOW_HIDDEN_ENGINES_VEHICLE_TRAIN_TOOLTIP),
794 NWidget(WWT_PANEL, COLOUR_GREY), SetResize(1, 0), SetFill(1, 1), EndContainer(),
795 EndContainer(),
796 EndContainer(),
797 EndContainer(),
799 NWidget(WWT_MATRIX, COLOUR_GREY, WID_RV_LEFT_MATRIX), SetMinimalSize(216, 0), SetFill(1, 1), SetMatrixDataTip(1, 0, STR_REPLACE_LEFT_ARRAY_TOOLTIP), SetResize(1, 1), SetScrollbar(WID_RV_LEFT_SCROLLBAR),
801 NWidget(WWT_MATRIX, COLOUR_GREY, WID_RV_RIGHT_MATRIX), SetMinimalSize(216, 0), SetFill(1, 1), SetMatrixDataTip(1, 0, STR_REPLACE_RIGHT_ARRAY_TOOLTIP), SetResize(1, 1), SetScrollbar(WID_RV_RIGHT_SCROLLBAR),
803 EndContainer(),
805 NWidget(WWT_PANEL, COLOUR_GREY, WID_RV_LEFT_DETAILS), SetMinimalSize(240, 122), SetResize(1, 0), EndContainer(),
807 EndContainer(),
809 NWidget(NWID_PUSHBUTTON_DROPDOWN, COLOUR_GREY, WID_RV_START_REPLACE), SetMinimalSize(139, 12), SetStringTip(STR_REPLACE_VEHICLES_START, STR_REPLACE_START_BUTTON_TOOLTIP),
810 NWidget(WWT_PANEL, COLOUR_GREY, WID_RV_INFO_TAB), SetMinimalSize(167, 12), SetToolTip(STR_REPLACE_REPLACE_INFO_TAB_TOOLTIP), SetResize(1, 0),
811 EndContainer(),
812 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_RV_STOP_REPLACE), SetMinimalSize(150, 12), SetStringTip(STR_REPLACE_VEHICLES_STOP, STR_REPLACE_STOP_BUTTON_TOOLTIP),
813 NWidget(WWT_RESIZEBOX, COLOUR_GREY),
814 EndContainer(),
815};
816
817static WindowDesc _replace_road_vehicle_desc(
818 WDP_AUTO, "replace_vehicle_road", 500, 140,
821 _nested_replace_road_vehicle_widgets
822);
823
824static constexpr NWidgetPart _nested_replace_vehicle_widgets[] = {
826 NWidget(WWT_CLOSEBOX, COLOUR_GREY),
827 NWidget(WWT_CAPTION, COLOUR_GREY, WID_RV_CAPTION), SetMinimalSize(433, 14),
828 NWidget(WWT_SHADEBOX, COLOUR_GREY),
829 NWidget(WWT_DEFSIZEBOX, COLOUR_GREY),
830 NWidget(WWT_STICKYBOX, COLOUR_GREY),
831 EndContainer(),
833 NWidget(WWT_PANEL, COLOUR_GREY),
834 NWidget(WWT_LABEL, INVALID_COLOUR), SetStringTip(STR_REPLACE_VEHICLE_VEHICLES_IN_USE, STR_REPLACE_VEHICLE_VEHICLES_IN_USE_TOOLTIP), SetFill(1, 1), SetMinimalTextLines(1, WidgetDimensions::unscaled.framerect.Vertical()), SetResize(1, 0),
835 EndContainer(),
836 NWidget(WWT_PANEL, COLOUR_GREY),
837 NWidget(WWT_LABEL, INVALID_COLOUR), SetStringTip(STR_REPLACE_VEHICLE_AVAILABLE_VEHICLES, STR_REPLACE_VEHICLE_AVAILABLE_VEHICLES_TOOLTIP), SetFill(1, 1), SetMinimalTextLines(1, WidgetDimensions::unscaled.framerect.Vertical()), SetResize(1, 0),
838 EndContainer(),
839 EndContainer(),
841 NWidget(WWT_PANEL, COLOUR_GREY), SetResize(1, 0), EndContainer(),
844 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_RV_SORT_ASCENDING_DESCENDING), SetStringTip(STR_BUTTON_SORT_BY, STR_TOOLTIP_SORT_ORDER),
845 NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_RV_SORT_DROPDOWN), SetResize(1, 0), SetFill(1, 1), SetToolTip(STR_TOOLTIP_SORT_CRITERIA),
846 EndContainer(),
848 NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_RV_SHOW_HIDDEN_ENGINES), SetStringTip(STR_SHOW_HIDDEN_ENGINES_VEHICLE_TRAIN, STR_SHOW_HIDDEN_ENGINES_VEHICLE_TRAIN_TOOLTIP),
849 NWidget(WWT_PANEL, COLOUR_GREY), SetResize(1, 0), SetFill(1, 1), EndContainer(),
850 EndContainer(),
851 EndContainer(),
852 EndContainer(),
854 NWidget(WWT_MATRIX, COLOUR_GREY, WID_RV_LEFT_MATRIX), SetMinimalSize(216, 0), SetFill(1, 1), SetMatrixDataTip(1, 0, STR_REPLACE_LEFT_ARRAY_TOOLTIP), SetResize(1, 1), SetScrollbar(WID_RV_LEFT_SCROLLBAR),
856 NWidget(WWT_MATRIX, COLOUR_GREY, WID_RV_RIGHT_MATRIX), SetMinimalSize(216, 0), SetFill(1, 1), SetMatrixDataTip(1, 0, STR_REPLACE_RIGHT_ARRAY_TOOLTIP), SetResize(1, 1), SetScrollbar(WID_RV_RIGHT_SCROLLBAR),
858 EndContainer(),
862 EndContainer(),
864 NWidget(NWID_PUSHBUTTON_DROPDOWN, COLOUR_GREY, WID_RV_START_REPLACE), SetMinimalSize(139, 12), SetStringTip(STR_REPLACE_VEHICLES_START, STR_REPLACE_START_BUTTON_TOOLTIP),
865 NWidget(WWT_PANEL, COLOUR_GREY, WID_RV_INFO_TAB), SetMinimalSize(167, 12), SetToolTip(STR_REPLACE_REPLACE_INFO_TAB_TOOLTIP), SetResize(1, 0), EndContainer(),
866 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_RV_STOP_REPLACE), SetMinimalSize(138, 12), SetStringTip(STR_REPLACE_VEHICLES_STOP, STR_REPLACE_STOP_BUTTON_TOOLTIP),
867 NWidget(WWT_RESIZEBOX, COLOUR_GREY),
868 EndContainer(),
869};
870
871static WindowDesc _replace_vehicle_desc(
872 WDP_AUTO, "replace_vehicle", 456, 118,
875 _nested_replace_vehicle_widgets
876);
877
884{
886 switch (vehicletype) {
887 case VEH_TRAIN: new ReplaceVehicleWindow(_replace_rail_vehicle_desc, vehicletype, id_g); break;
888 case VEH_ROAD: new ReplaceVehicleWindow(_replace_road_vehicle_desc, vehicletype, id_g); break;
889 default: new ReplaceVehicleWindow(_replace_vehicle_desc, vehicletype, id_g); break;
890 }
891}
bool CheckAutoreplaceValidity(EngineID from, EngineID to, CompanyID company)
Checks some basic properties whether autoreplace is allowed.
Command definitions related to autoreplace.
Functions related to autoreplacing.
bool EngineHasReplacementWhenOldForCompany(const Company *c, EngineID engine, GroupID group)
Check if a company has a replacement set up for the given engine when it gets old.
EngineID EngineReplacementForCompany(const Company *c, EngineID engine, GroupID group, bool *replace_when_old=nullptr)
Retrieve the engine replacement for the given company and original engine type.
bool EngineHasReplacementForCompany(const Company *c, EngineID engine, GroupID group)
Check if a company has a replacement set up for the given engine.
void ShowReplaceGroupVehicleWindow(GroupID id_g, VehicleType vehicletype)
Show the autoreplace configuration window for a particular group.
void InvalidateAutoreplaceWindow(EngineID e, GroupID id_g)
Rebuild the left autoreplace list if an engine is removed or added.
void AddRemoveEngineFromAutoreplaceAndBuildWindows(VehicleType type)
When an engine is made buildable or is removed from being buildable, add/remove it from the build/aut...
Types related to the autoreplace widgets.
@ WID_RV_SHOW_HIDDEN_ENGINES
Toggle whether to display the hidden vehicles.
@ WID_RV_TRAIN_ENGINEWAGON_DROPDOWN
Dropdown to select engines and/or wagons.
@ WID_RV_LEFT_SCROLLBAR
The scrollbar for the matrix on the left.
@ WID_RV_CAPTION
Caption of the window.
@ WID_RV_RIGHT_DETAILS
Details of the entry on the right.
@ WID_RV_TRAIN_WAGONREMOVE_TOGGLE
Button to toggle removing wagons.
@ WID_RV_STOP_REPLACE
Stop Replacing button.
@ WID_RV_ROAD_TYPE_DROPDOWN
Dropdown to select roadtype.
@ WID_RV_RIGHT_MATRIX
The matrix on the right.
@ WID_RV_INFO_TAB
Info tab.
@ WID_RV_RAIL_TYPE_DROPDOWN
Dropdown to select railtype.
@ WID_RV_LEFT_MATRIX
The matrix on the left.
@ WID_RV_SORT_ASCENDING_DESCENDING
Ascending/descending sort order button.
@ WID_RV_RIGHT_SCROLLBAR
The scrollbar for the matrix on the right.
@ WID_RV_START_REPLACE
Start Replacing button.
@ WID_RV_SORT_DROPDOWN
Dropdown for the sort criteria.
@ WID_RV_LEFT_DETAILS
Details of the entry on the left.
void GUIEngineListAddChildren(GUIEngineList &dst, const GUIEngineList &src, EngineID parent, uint8_t indent)
Add children to GUI engine list to build a hierarchical tree.
void DrawEngineList(VehicleType type, const Rect &r, const GUIEngineList &eng_list, const Scrollbar &sb, EngineID selected_id, bool show_count, GroupID selected_group, const GUIBadgeClasses &badge_classes)
Engine drawing loop.
bool _engine_sort_last_order[]
Last set direction of the sort order, for each vehicle type.
uint GetEngineListHeight(VehicleType type)
Get the height of a single 'entry' in the engine lists.
const std::initializer_list< const StringID > _engine_sort_listing[]
Dropdown menu strings for the vehicle sort criteria.
uint8_t _engine_sort_last_criteria[]
Last set sort criteria, for each vehicle type.
int DrawVehiclePurchaseInfo(int left, int right, int y, EngineID engine_number, TestedEngineDetails &te)
Draw the purchase info details of a vehicle at a given location.
EngList_SortTypeFunction *const _engine_sort_functions[][11]
Sort functions for the vehicle sort criteria, for each vehicle type.
void DisplayVehicleSortDropDown(Window *w, VehicleType vehicle_type, int selected, WidgetID button)
Display the dropdown for the vehicle sort criteria.
bool _engine_sort_direction
false = descending, true = ascending.
bool _engine_sort_show_hidden_engines[]
Last set 'show hidden engines' setting for each vehicle type.
constexpr bool Test(Tvalue_type value) const
Test if the value-th bit is set.
constexpr Timpl & Flip(Tvalue_type value)
Flip the value-th bit.
Base class for a 'real' widget.
void SetLowered(bool lowered)
Lower or raise the widget.
void SetStringTip(StringID string, StringID tool_tip)
Set string and tool tip of the nested widget.
Definition widget.cpp:1171
StringID replace_text
Text used in the autoreplace GUI.
Definition rail.h:171
struct RailTypeInfo::@23 strings
Strings associated with the rail type.
Window for the autoreplacing of vehicles.
void OnInit() override
Notification that the nested widget tree gets initialized.
void OnResize() override
Called after the window got resized.
bool GenerateReplaceRailList(EngineID e, bool draw_left, bool show_engines)
Figure out if an engine should be added to a list.
void DrawWidget(const Rect &r, WidgetID widget) const override
Draw the contents of a nested widget.
void ReplaceClick_StartReplace(bool replace_when_old)
Handle click on the start replace button.
void OnDropdownSelect(WidgetID widget, int index, int) override
A dropdown option associated to this window has been selected.
bool OnTooltip(Point pt, WidgetID widget, TooltipCloseCondition close_cond) override
Event to display a custom tooltip.
void OnClick(Point pt, WidgetID widget, int click_count) override
A click with the left mouse button has been made on the window.
uint8_t sort_criteria
Criteria of sorting vehicles.
void OnInvalidateData(int data=0, bool gui_scope=true) override
Some data on this window has become invalid.
RailType sel_railtype
Type of rail tracks selected. INVALID_RAILTYPE to show all.
void UpdateWidgetSize(WidgetID widget, Dimension &size, const Dimension &padding, Dimension &fill, Dimension &resize) override
Update size and resize step of a widget in the window.
std::string GetWidgetString(WidgetID widget, StringID stringid) const override
Get the raw string for a widget.
bool replace_engines
If true, engines are replaced, if false, wagons are replaced (only for trains).
bool reset_sel_engine
Also reset sel_engine while updating left and/or right and no valid engine selected.
void OnPaint() override
The window must be repainted.
bool show_hidden_engines
Whether to show the hidden engines.
void GenerateLists()
Generate the lists.
RoadType sel_roadtype
Type of road selected. INVALID_ROADTYPE to show all.
std::array< GUIEngineList, 2 > engines
Left and right list of engines.
VehicleType vehicle_type
Type of vehicle in this window.
int details_height
Minimal needed height of the details panels, in text lines (found so far).
void GenerateReplaceVehList(bool draw_left)
Generate an engines list.
GroupID sel_group
Group selected to replace.
std::array< EngineID, 2 > sel_engine
Selected engine left and right.
bool descending_sort_order
Order of sorting vehicles.
void OnRailRoadTypeChange()
Perform tasks after rail or road type is changed.
StringID replace_text
Text used in the autoreplace GUI.
Definition road.h:98
struct RoadTypeInfo::@26 strings
Strings associated with the rail type.
RectPadding framerect
Standard padding inside many panels.
Definition window_gui.h:40
RectPadding frametext
Padding inside frame with text.
Definition window_gui.h:41
static WidgetDimensions scaled
Widget dimensions scaled for current zoom level.
Definition window_gui.h:30
static const WidgetDimensions unscaled
Unscaled widget dimensions.
Definition window_gui.h:93
Functions related to commands.
CompanyID _local_company
Company controlled by the human player at this client. Can also be COMPANY_SPECTATOR.
Functions related to companies.
void ShowDropDownMenu(Window *w, std::span< const StringID > strings, int selected, WidgetID button, uint32_t disabled_mask, uint32_t hidden_mask, uint width)
Show a dropdown menu window near a widget of the parent window.
Definition dropdown.cpp:451
void ShowDropDownList(Window *w, DropDownList &&list, int selected, WidgetID button, uint width, bool instant_close, bool persist)
Show a drop down list.
Definition dropdown.cpp:414
Functions related to the drop down widget.
Types related to the drop down widget.
std::vector< std::unique_ptr< const DropDownListItem > > DropDownList
A drop down list is a collection of drop down list items.
Base class for engines.
@ HasVariants
Set if engine has variants.
@ IsFolded
Set if display of variants should be folded (hidden).
@ Shaded
Set if engine should be masked.
void EngList_Sort(GUIEngineList &el, EngList_SortTypeFunction compare)
Sort all items using quick sort and given 'CompareItems' function.
Engine GUI functions, used by build_vehicle_gui and autoreplace_gui
uint64_t PackEngineNameDParam(EngineID engine_id, EngineNameContext context, uint32_t extra_data=0)
Combine an engine ID and a name context to an engine name dparam.
@ PurchaseList
Name is shown in the purchase list (including autoreplace window 'Available vehicles' panel).
@ RAILVEH_WAGON
simple wagon, not motorized
Definition engine_type.h:34
fluid_settings_t * settings
FluidSynth settings handle.
int GetCharacterHeight(FontSize size)
Get height of a character for a given font size.
Definition fontcache.cpp:77
Dimension maxdim(const Dimension &d1, const Dimension &d2)
Compute bounding box of both dimensions.
Geometry functions.
Dimension GetStringBoundingBox(std::string_view str, FontSize start_fontsize)
Return the string dimension in pixels.
Definition gfx.cpp:887
Dimension GetStringListBoundingBox(std::span< const StringID > list, FontSize fontsize)
Get maximum dimension of a list of strings.
Definition gfx.cpp:925
int DrawString(int left, int right, int top, std::string_view str, TextColour colour, StringAlignment align, bool underline, FontSize fontsize)
Draw string, possibly truncated to make it fit in its allocated space.
Definition gfx.cpp:658
bool _ctrl_pressed
Is Ctrl pressed?
Definition gfx.cpp:38
@ FS_NORMAL
Index of the normal font in the font tables.
Definition gfx_type.h:251
@ SA_HOR_CENTER
Horizontally center the text.
Definition gfx_type.h:384
@ ReplaceWagonRemoval
If set, autoreplace will perform wagon removal on vehicles in this group.
uint GetGroupNumEngines(CompanyID company, GroupID id_g, EngineID id_e)
Get the number of engines with EngineID id_e in the group with GroupID id_g and its sub-groups.
constexpr NWidgetPart SetMatrixDataTip(uint32_t cols, uint32_t rows, StringID tip={})
Widget part function for setting the data and tooltip of WWT_MATRIX widgets.
constexpr NWidgetPart SetFill(uint16_t fill_x, uint16_t fill_y)
Widget part function for setting filling.
constexpr NWidgetPart SetScrollbar(WidgetID index)
Attach a scrollbar to a widget.
constexpr NWidgetPart SetStringTip(StringID string, StringID tip={})
Widget part function for setting the string and tooltip.
constexpr NWidgetPart SetMinimalSize(int16_t x, int16_t y)
Widget part function for setting the minimal size.
constexpr NWidgetPart NWidget(WidgetType tp, Colours col, WidgetID idx=-1)
Widget part function for starting a new 'real' widget.
constexpr NWidgetPart SetToolTip(StringID tip)
Widget part function for setting tooltip and clearing the widget data.
constexpr NWidgetPart EndContainer()
Widget part function for denoting the end of a container (horizontal, vertical, WWT_FRAME,...
constexpr NWidgetPart SetMinimalTextLines(uint8_t lines, uint8_t spacing, FontSize size=FS_NORMAL)
Widget part function for setting the minimal text lines.
constexpr NWidgetPart SetResize(int16_t dx, int16_t dy)
Widget part function for setting the resize step.
Command definitions related to engine groups.
void SetDirty() const
Mark entire window as dirty (in need of re-paint)
Definition window.cpp:955
static constexpr GroupID DEFAULT_GROUP
Ungrouped vehicles are in this group.
Definition group_type.h:18
static constexpr GroupID ALL_GROUP
All vehicles are in this group.
Definition group_type.h:17
constexpr bool IsInsideMM(const size_t x, const size_t min, const size_t max) noexcept
Checks if a value is in an interval.
void GuiShowTooltips(Window *parent, EncodedString &&text, TooltipCloseCondition close_tooltip)
Shows a tooltip.
Definition misc_gui.cpp:688
GrfSpecFeature
Definition newgrf.h:69
Functions related to NewGRF badges.
Functions for NewGRF engines.
Rail specific functions.
std::vector< RailType > _sorted_railtypes
Sorted list of rail types.
Definition rail_cmd.cpp:47
const RailTypeInfo * GetRailTypeInfo(RailType railtype)
Returns a pointer to the Railtype information for a given railtype.
Definition rail.h:300
DropDownList GetRailTypeDropDownList(bool for_replacement, bool all_option)
Create a drop down list for all the rail types of the local company.
Functions/types etc.
RailType
Enumeration for all possible railtypes.
Definition rail_type.h:25
@ INVALID_RAILTYPE
Flag for invalid railtype.
Definition rail_type.h:32
Road specific functions.
const RoadTypeInfo * GetRoadTypeInfo(RoadType roadtype)
Returns a pointer to the Roadtype information for a given roadtype.
Definition road.h:230
std::vector< RoadType > _sorted_roadtypes
Sorted list of road types.
Definition road_cmd.cpp:55
Functions/types related to the road GUIs.
RoadType
The different roadtypes we support.
Definition road_type.h:23
@ INVALID_ROADTYPE
flag for invalid roadtype
Definition road_type.h:28
A number of safeguards to prevent using unsafe methods.
Command definitions related to settings.
Functions related to setting/changing the settings.
Definition of base types and functions in a cross-platform compatible way.
EncodedString GetEncodedString(StringID str)
Encode a string with no parameters into an encoded string.
Definition strings.cpp:91
std::string GetString(StringID string)
Resolve the given StringID into a std::string with formatting but no parameters.
Definition strings.cpp:415
TextDirection _current_text_dir
Text direction of the currently selected language.
Definition strings.cpp:57
Functions related to OTTD's strings.
uint32_t StringID
Numeric value that represents a string, independent of the selected language.
@ TD_RTL
Text is written right-to-left by default.
CompanySettings settings
settings specific for each company
bool renew_keep_length
sell some wagons if after autoreplace the train is longer than before
Dimensions (a width and height) of a rectangle in 2D.
EngineID variant_id
Engine variant ID. If set, will be treated specially in purchase lists.
static Pool::IterateWrapperFiltered< Engine, EngineTypeFilter > IterateType(VehicleType vt, size_t from=0)
Returns an iterable ensemble of all valid engines of the given type.
EngineDisplayFlags display_flags
NOSAVE client-side-only display flags for build engine list.
Definition engine_base.h:63
EngineID engine_id
Engine to display in build purchase list.
Definition engine_gui.h:22
Group data.
Definition group.h:73
GroupFlags flags
Group flags.
Definition group.h:78
Partial widget specification to allow NWidgets to be written nested.
Coordinates of a point in 2D.
static Titem * Get(auto index)
Returns Titem with given index.
static bool IsValidID(auto index)
Tests whether given index can be used to get valid (non-nullptr) Titem.
static Titem * GetIfValid(auto index)
Returns Titem with given index.
Information about a rail vehicle.
Definition engine_type.h:47
RailType railtype
Railtype, mangled if elrail is disabled.
Definition engine_type.h:51
Specification of a rectangle with absolute coordinates of all edges.
Rect WithWidth(int width, bool end) const
Copy Rect and set its width.
Rect Shrink(int s) const
Copy and shrink Rect by s pixels.
Extra information about refitted cargo and capacity.
Definition vehicle_gui.h:42
Money cost
Refit cost.
Definition vehicle_gui.h:43
High level window description.
Definition window_gui.h:167
Data structure for an opened window.
Definition window_gui.h:273
void ReInit(int rx=0, int ry=0, bool reposition=false)
Re-initialize a window, and optionally change its size.
Definition window.cpp:967
static int SortButtonWidth()
Get width of up/down arrow of sort button state.
Definition widget.cpp:826
void FinishInitNested(WindowNumber window_number=0)
Perform the second part of the initialization of a nested widget tree.
Definition window.cpp:1778
void DrawWidgets() const
Paint all widgets of a window.
Definition widget.cpp:777
Window * parent
Parent window.
Definition window_gui.h:328
virtual std::string GetWidgetString(WidgetID widget, StringID stringid) const
Get the raw string for a widget.
Definition window.cpp:503
void DrawSortButtonState(WidgetID widget, SortButtonState state) const
Draw a sort button's up or down arrow symbol.
Definition widget.cpp:809
ResizeInfo resize
Resize information.
Definition window_gui.h:314
void CreateNestedTree()
Perform the first part of the initialization of a nested widget tree.
Definition window.cpp:1768
Owner owner
The owner of the content shown in this window. Company colour is acquired from this variable.
Definition window_gui.h:316
void SetWidgetLoweredState(WidgetID widget_index, bool lowered_stat)
Sets the lowered/raised status of a widget.
Definition window_gui.h:441
bool IsShaded() const
Is window shaded currently?
Definition window_gui.h:559
void HandleButtonClick(WidgetID widget)
Do all things to make a button look clicked and mark it to be unclicked in a few ticks.
Definition window.cpp:594
const Scrollbar * GetScrollbar(WidgetID widnum) const
Return the Scrollbar to a widget index.
Definition window.cpp:312
void SetWidgetDisabledState(WidgetID widget_index, bool disab_stat)
Sets the enabled/disabled status of a widget.
Definition window_gui.h:381
WindowNumber window_number
Window number within the window class.
Definition window_gui.h:302
Functions related to the vehicle's GUIs.
VehicleType
Available vehicle types.
@ VEH_INVALID
Non-existing type of vehicle.
@ VEH_ROAD
Road vehicle type.
@ VEH_TRAIN
Train vehicle type.
@ WWT_PUSHTXTBTN
Normal push-button (no toggle button) with text caption.
@ WWT_LABEL
Centered label.
Definition widget_type.h:49
@ NWID_HORIZONTAL
Horizontal container.
Definition widget_type.h:67
@ WWT_TEXTBTN
(Toggle) Button with text
Definition widget_type.h:45
@ WWT_PANEL
Simple depressed panel.
Definition widget_type.h:40
@ WWT_STICKYBOX
Sticky box (at top-right of a window, after WWT_DEFSIZEBOX)
Definition widget_type.h:58
@ WWT_MATRIX
Grid of rows and columns.
Definition widget_type.h:51
@ WWT_SHADEBOX
Shade box (at top-right of a window, between WWT_DEBUGBOX and WWT_DEFSIZEBOX)
Definition widget_type.h:56
@ WWT_CAPTION
Window caption (window title between closebox and stickybox)
Definition widget_type.h:53
@ NWID_VSCROLLBAR
Vertical scrollbar.
Definition widget_type.h:77
@ NWID_VERTICAL
Vertical container.
Definition widget_type.h:69
@ WWT_CLOSEBOX
Close box (at top-left of a window)
Definition widget_type.h:61
@ WWT_RESIZEBOX
Resize box (normally at bottom-right of a window)
Definition widget_type.h:60
@ WWT_DEFSIZEBOX
Default window size box (at top-right of a window, between WWT_SHADEBOX and WWT_STICKYBOX)
Definition widget_type.h:57
@ WWT_DROPDOWN
Drop down list.
Definition widget_type.h:62
@ EqualSize
Containers should keep all their (resizing) children equally large.
void CloseWindowById(WindowClass cls, WindowNumber number, bool force, int data)
Close a window by its class and window number (if it is open).
Definition window.cpp:1182
void InvalidateWindowData(WindowClass cls, WindowNumber number, int data, bool gui_scope)
Mark window data of the window of a given class and specific window number as invalid (in need of re-...
Definition window.cpp:3265
void InvalidateWindowClassesData(WindowClass cls, int data, bool gui_scope)
Mark window data of all windows of a given class as invalid (in need of re-computing) Note that by de...
Definition window.cpp:3282
Window functions not directly related to making/drawing windows.
Functions, definitions and such used only by the GUI.
@ Construction
This window is used for construction; close it whenever changing company.
@ SBS_DOWN
Sort ascending.
Definition window_gui.h:218
@ SBS_UP
Sort descending.
Definition window_gui.h:219
@ WDP_AUTO
Find a place automatically.
Definition window_gui.h:144
int WidgetID
Widget ID.
Definition window_type.h:20
@ WC_REPLACE_VEHICLE
Replace vehicle window; Window numbers:
@ WC_NONE
No window, redirects to WC_MAIN_WINDOW.
Definition window_type.h:47
@ WC_BUILD_VEHICLE
Build vehicle; Window numbers: