OpenTTD Source 20250717-master-g55605ae8f2
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 FlatSet<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() && variants.insert(parent).second) {
165 parent = Engine::Get(parent)->info.variant_id;
166 }
167 }
168 if (eid == this->sel_engine[side]) selected_engine = eid; // The selected engine is still in the list
169 }
170
171 if (side == 1) {
172 /* ensure primary engine of variant group is in list */
173 for (const auto &variant : variants) {
174 if (std::ranges::find(list, variant, &GUIEngineListItem::engine_id) == list.end()) {
175 const Engine *e = Engine::Get(variant);
176 list.emplace_back(variant, e->info.variant_id, e->display_flags | EngineDisplayFlag::Shaded, 0);
177 }
178 }
179 }
180
181 this->sel_engine[side] = selected_engine; // update which engine we selected (the same or none, if it's not in the list anymore)
182 if (draw_left) {
183 EngList_Sort(list, &EngineNumberSorter);
184 } else {
186 EngList_Sort(list, _engine_sort_functions[this->window_number][this->sort_criteria]);
187 }
188
189 this->engines[side].clear();
190 if (side == 1) {
191 GUIEngineListAddChildren(this->engines[side], list);
192 } else {
193 this->engines[side].swap(list);
194 }
195 }
196
199 {
200 EngineID e = this->sel_engine[0];
201
202 if (this->engines[0].NeedRebuild()) {
203 /* We need to rebuild the left engines list */
204 this->GenerateReplaceVehList(true);
205 this->vscroll[0]->SetCount(this->engines[0].size());
206 if (this->reset_sel_engine && this->sel_engine[0] == EngineID::Invalid() && !this->engines[0].empty()) {
207 this->sel_engine[0] = this->engines[0][0].engine_id;
208 }
209 }
210
211 if (this->engines[1].NeedRebuild() || e != this->sel_engine[0]) {
212 /* Either we got a request to rebuild the right engines list, or the left engines list selected a different engine */
213 if (this->sel_engine[0] == EngineID::Invalid()) {
214 /* Always empty the right engines list when nothing is selected in the left engines list */
215 this->engines[1].clear();
216 this->sel_engine[1] = EngineID::Invalid();
217 this->vscroll[1]->SetCount(this->engines[1].size());
218 } else {
219 if (this->reset_sel_engine && this->sel_engine[0] != EngineID::Invalid()) {
220 /* Select the current replacement for sel_engine[0]. */
222 this->sel_engine[1] = EngineReplacementForCompany(c, this->sel_engine[0], this->sel_group);
223 }
224 /* Regenerate the list on the right. Note: This resets sel_engine[1] to EngineID::Invalid(), if it is no longer available. */
225 this->GenerateReplaceVehList(false);
226 this->vscroll[1]->SetCount(this->engines[1].size());
227 if (this->reset_sel_engine && this->sel_engine[1] != EngineID::Invalid()) {
228 int position = 0;
229 for (const auto &item : this->engines[1]) {
230 if (item.engine_id == this->sel_engine[1]) break;
231 ++position;
232 }
233 this->vscroll[1]->ScrollTowards(position);
234 }
235 }
236 }
237 /* Reset the flags about needed updates */
238 this->engines[0].RebuildDone();
239 this->engines[1].RebuildDone();
240 this->reset_sel_engine = false;
241 }
242
247 void ReplaceClick_StartReplace(bool replace_when_old)
248 {
249 EngineID veh_from = this->sel_engine[0];
250 EngineID veh_to = this->sel_engine[1];
251 Command<CMD_SET_AUTOREPLACE>::Post(this->sel_group, veh_from, veh_to, replace_when_old);
252 }
253
258 {
259 /* Reset scrollbar positions */
260 this->vscroll[0]->SetPosition(0);
261 this->vscroll[1]->SetPosition(0);
262 /* Rebuild the lists */
263 this->engines[0].ForceRebuild();
264 this->engines[1].ForceRebuild();
265 this->reset_sel_engine = true;
266 this->SetDirty();
267 }
268
269public:
270 ReplaceVehicleWindow(WindowDesc &desc, VehicleType vehicletype, GroupID id_g) : Window(desc)
271 {
272 this->vehicle_type = vehicletype;
273 this->engines[0].ForceRebuild();
274 this->engines[1].ForceRebuild();
275 this->details_height = ((vehicletype == VEH_TRAIN) ? 10 : 9);
276 this->sel_engine[0] = EngineID::Invalid();
277 this->sel_engine[1] = EngineID::Invalid();
278 this->show_hidden_engines = _engine_sort_show_hidden_engines[vehicletype];
279
280 this->CreateNestedTree();
281 this->vscroll[0] = this->GetScrollbar(WID_RV_LEFT_SCROLLBAR);
282 this->vscroll[1] = this->GetScrollbar(WID_RV_RIGHT_SCROLLBAR);
283
284 NWidgetCore *widget = this->GetWidget<NWidgetCore>(WID_RV_SHOW_HIDDEN_ENGINES);
285 widget->SetStringTip(STR_SHOW_HIDDEN_ENGINES_VEHICLE_TRAIN + vehicletype, STR_SHOW_HIDDEN_ENGINES_VEHICLE_TRAIN_TOOLTIP + vehicletype);
286 widget->SetLowered(this->show_hidden_engines);
287 this->FinishInitNested(vehicletype);
288
289 this->sort_criteria = _engine_sort_last_criteria[vehicletype];
290 this->descending_sort_order = _engine_sort_last_order[vehicletype];
291 this->owner = _local_company;
292 this->sel_group = id_g;
293 }
294
295 void OnInit() override
296 {
297 this->badge_classes = GUIBadgeClasses(static_cast<GrfSpecFeature>(GSF_TRAINS + this->vehicle_type));
298 }
299
300 void UpdateWidgetSize(WidgetID widget, Dimension &size, [[maybe_unused]] const Dimension &padding, [[maybe_unused]] Dimension &fill, [[maybe_unused]] Dimension &resize) override
301 {
302 switch (widget) {
304 Dimension d = GetStringBoundingBox(this->GetWidget<NWidgetCore>(widget)->GetString());
305 d.width += padding.width + Window::SortButtonWidth() * 2; // Doubled since the string is centred and it also looks better.
306 d.height += padding.height;
307 size = maxdim(size, d);
308 break;
309 }
310
313 fill.height = resize.height = GetEngineListHeight(this->window_number);
314 size.height = (this->window_number <= VEH_ROAD ? 8 : 4) * resize.height;
315 break;
316
319 size.height = GetCharacterHeight(FS_NORMAL) * this->details_height + padding.height;
320 break;
321
323 StringID str = this->GetWidget<NWidgetCore>(widget)->GetString();
324 StringID group_str = Group::IsValidID(this->sel_group) ? STR_GROUP_NAME : STR_GROUP_DEFAULT_TRAINS + this->window_number;
325 Dimension d = GetStringBoundingBox(GetString(str, group_str, this->sel_group, STR_CONFIG_SETTING_ON));
326 d = maxdim(d, GetStringBoundingBox(GetString(str, group_str, this->sel_group, STR_CONFIG_SETTING_OFF)));
327 d.width += padding.width;
328 d.height += padding.height;
329 size = maxdim(size, d);
330 break;
331 }
332
334 Dimension d = GetStringBoundingBox(STR_REPLACE_ENGINES);
335 d = maxdim(d, GetStringBoundingBox(STR_REPLACE_WAGONS));
336 d.width += padding.width;
337 d.height += padding.height;
338 size = maxdim(size, d);
339 break;
340 }
341
342 case WID_RV_INFO_TAB: {
343 Dimension d = GetStringBoundingBox(STR_REPLACE_NOT_REPLACING);
344 d = maxdim(d, GetStringBoundingBox(STR_REPLACE_NOT_REPLACING_VEHICLE_SELECTED));
345 d.width += padding.width;
346 d.height += padding.height;
347 size = maxdim(size, d);
348 break;
349 }
350
352 Dimension d = {0, 0};
353 for (const RailType &rt : _sorted_railtypes) {
355 }
356 d.width += padding.width;
357 d.height += padding.height;
358 size = maxdim(size, d);
359 break;
360 }
361
363 Dimension d = {0, 0};
364 for (const RoadType &rt : _sorted_roadtypes) {
366 }
367 d.width += padding.width;
368 d.height += padding.height;
369 size = maxdim(size, d);
370 break;
371 }
372
374 Dimension d = GetStringBoundingBox(STR_REPLACE_VEHICLES_START);
375 d = maxdim(d, GetStringListBoundingBox(_start_replace_dropdown));
376 d.width += padding.width;
377 d.height += padding.height;
378 size = maxdim(size, d);
379 break;
380 }
381 }
382 }
383
384 std::string GetWidgetString(WidgetID widget, StringID stringid) const override
385 {
386 switch (widget) {
387 case WID_RV_CAPTION:
388 switch (this->sel_group.base()) {
389 case ALL_GROUP.base():
390 return GetString(STR_REPLACE_VEHICLES_WHITE, STR_REPLACE_VEHICLE_TRAIN + this->window_number, STR_GROUP_ALL_TRAINS + this->window_number, std::monostate{});
391 break;
392
393 case DEFAULT_GROUP.base():
394 return GetString(STR_REPLACE_VEHICLES_WHITE, STR_REPLACE_VEHICLE_TRAIN + this->window_number, STR_GROUP_DEFAULT_TRAINS + this->window_number, std::monostate{});
395 break;
396
397 default:
398 return GetString(STR_REPLACE_VEHICLES_WHITE, STR_REPLACE_VEHICLE_TRAIN + this->window_number, STR_GROUP_NAME, sel_group);
399 }
400 break;
401
403 return GetString(std::data(_engine_sort_listing[this->window_number])[this->sort_criteria]);
404
406 if (const Group *g = Group::GetIfValid(this->sel_group); g != nullptr) {
407 bool remove_wagon = g->flags.Test(GroupFlag::ReplaceWagonRemoval);
408 return GetString(STR_REPLACE_REMOVE_WAGON, STR_GROUP_NAME, sel_group, remove_wagon ? STR_CONFIG_SETTING_ON : STR_CONFIG_SETTING_OFF);
409 } else {
411 bool remove_wagon = c->settings.renew_keep_length;
412 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);
413 }
414 break;
415
417 return GetString(this->replace_engines ? STR_REPLACE_ENGINES : STR_REPLACE_WAGONS);
418
420 return GetString(this->sel_railtype == INVALID_RAILTYPE ? STR_REPLACE_ALL_RAILTYPE : GetRailTypeInfo(this->sel_railtype)->strings.replace_text);
421
423 return GetString(this->sel_roadtype == INVALID_ROADTYPE ? STR_REPLACE_ALL_ROADTYPE : GetRoadTypeInfo(this->sel_roadtype)->strings.replace_text);
424
425 default:
426 return this->Window::GetWidgetString(widget, stringid);
427 }
428 }
429
430 void DrawWidget(const Rect &r, WidgetID widget) const override
431 {
432 switch (widget) {
434 this->DrawSortButtonState(WID_RV_SORT_ASCENDING_DESCENDING, this->descending_sort_order ? SBS_DOWN : SBS_UP);
435 break;
436
437 case WID_RV_INFO_TAB: {
439 std::string str;
440 if (this->sel_engine[0] != EngineID::Invalid()) {
441 if (!EngineHasReplacementForCompany(c, this->sel_engine[0], this->sel_group)) {
442 str = GetString(STR_REPLACE_NOT_REPLACING);
443 } else {
444 bool when_old = false;
445 EngineID e = EngineReplacementForCompany(c, this->sel_engine[0], this->sel_group, &when_old);
446 str = GetString(when_old ? STR_REPLACE_REPLACING_WHEN_OLD : STR_ENGINE_NAME, PackEngineNameDParam(e, EngineNameContext::PurchaseList));
447 }
448 } else {
449 str = GetString(STR_REPLACE_NOT_REPLACING_VEHICLE_SELECTED);
450 }
451
453 break;
454 }
455
457 case WID_RV_RIGHT_MATRIX: {
458 int side = (widget == WID_RV_LEFT_MATRIX) ? 0 : 1;
459
460 /* Do the actual drawing */
461 DrawEngineList(this->window_number, r, this->engines[side], *this->vscroll[side], this->sel_engine[side], side == 0, this->sel_group, this->badge_classes);
462 break;
463 }
464 }
465 }
466
467 void OnPaint() override
468 {
469 if (this->engines[0].NeedRebuild() || this->engines[1].NeedRebuild()) this->GenerateLists();
470
472
473 /* Disable the "Start Replacing" button if:
474 * Either engines list is empty
475 * or The selected replacement engine has a replacement (to prevent loops). */
477 this->sel_engine[0] == EngineID::Invalid() || this->sel_engine[1] == EngineID::Invalid() || EngineReplacementForCompany(c, this->sel_engine[1], this->sel_group) != EngineID::Invalid());
478
479 /* Disable the "Stop Replacing" button if:
480 * The left engines list (existing vehicle) is empty
481 * or The selected vehicle has no replacement set up */
482 this->SetWidgetDisabledState(WID_RV_STOP_REPLACE, this->sel_engine[0] == EngineID::Invalid() || !EngineHasReplacementForCompany(c, this->sel_engine[0], this->sel_group));
483
484 this->DrawWidgets();
485
486 if (!this->IsShaded()) {
487 int needed_height = this->details_height;
488 /* Draw details panels. */
489 for (int side = 0; side < 2; side++) {
490 if (this->sel_engine[side] != EngineID::Invalid()) {
491 /* Use default engine details without refitting */
492 const Engine *e = Engine::Get(this->sel_engine[side]);
494 ted.cost = 0;
495 ted.FillDefaultCapacities(e);
496
497 const Rect r = this->GetWidget<NWidgetBase>(side == 0 ? WID_RV_LEFT_DETAILS : WID_RV_RIGHT_DETAILS)->GetCurrentRect()
499 int text_end = DrawVehiclePurchaseInfo(r.left, r.right, r.top, this->sel_engine[side], ted);
500 needed_height = std::max(needed_height, (text_end - r.top) / GetCharacterHeight(FS_NORMAL));
501 }
502 }
503 if (needed_height != this->details_height) { // Details window are not high enough, enlarge them.
504 this->details_height = needed_height;
505 this->ReInit();
506 return;
507 }
508 }
509 }
510
511 void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override
512 {
513 switch (widget) {
515 this->descending_sort_order ^= true;
517 this->engines[1].ForceRebuild();
518 this->SetDirty();
519 break;
520
522 this->show_hidden_engines ^= true;
524 this->engines[1].ForceRebuild();
525 this->SetWidgetLoweredState(widget, this->show_hidden_engines);
526 this->SetDirty();
527 break;
528
530 DisplayVehicleSortDropDown(this, this->window_number, this->sort_criteria, WID_RV_SORT_DROPDOWN);
531 break;
532
534 DropDownList list;
535 list.push_back(MakeDropDownListStringItem(STR_REPLACE_ENGINES, 1));
536 list.push_back(MakeDropDownListStringItem(STR_REPLACE_WAGONS, 0));
537 ShowDropDownList(this, std::move(list), this->replace_engines ? 1 : 0, WID_RV_TRAIN_ENGINEWAGON_DROPDOWN);
538 break;
539 }
540
541 case WID_RV_RAIL_TYPE_DROPDOWN: // Railtype selection dropdown menu
542 ShowDropDownList(this, GetRailTypeDropDownList(true, true), this->sel_railtype, widget);
543 break;
544
545 case WID_RV_ROAD_TYPE_DROPDOWN: // Roadtype selection dropdown menu
546 ShowDropDownList(this, GetRoadTypeDropDownList(RTTB_ROAD | RTTB_TRAM, true, true), this->sel_roadtype, widget);
547 break;
548
550 const Group *g = Group::GetIfValid(this->sel_group);
551 if (g != nullptr) {
553 } else {
554 /* toggle renew_keep_length */
555 Command<CMD_CHANGE_COMPANY_SETTING>::Post("company.renew_keep_length", Company::Get(_local_company)->settings.renew_keep_length ? 0 : 1);
556 }
557 break;
558 }
559
560 case WID_RV_START_REPLACE: { // Start replacing
561 if (this->GetWidget<NWidgetLeaf>(widget)->ButtonHit(pt)) {
564 } else {
565 bool replacment_when_old = EngineHasReplacementWhenOldForCompany(Company::Get(_local_company), this->sel_engine[0], this->sel_group);
566 ShowDropDownMenu(this, _start_replace_dropdown, replacment_when_old ? 1 : 0, WID_RV_START_REPLACE, !this->replace_engines ? 1 << 1 : 0, 0);
567 }
568 break;
569 }
570
571 case WID_RV_STOP_REPLACE: { // Stop replacing
572 EngineID veh_from = this->sel_engine[0];
573 Command<CMD_SET_AUTOREPLACE>::Post(this->sel_group, veh_from, EngineID::Invalid(), false);
574 break;
575 }
576
578 case WID_RV_RIGHT_MATRIX: {
579 uint8_t click_side;
580 if (widget == WID_RV_LEFT_MATRIX) {
581 click_side = 0;
582 } else {
583 click_side = 1;
584 }
585
586 EngineID e = EngineID::Invalid();
587 const auto it = this->vscroll[click_side]->GetScrolledItemFromWidget(this->engines[click_side], pt.y, this, widget);
588 if (it != this->engines[click_side].end()) {
589 const auto &item = *it;
590 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);
591 if (item.flags.Test(EngineDisplayFlag::HasVariants) && IsInsideMM(r.left, r.right, pt.x)) {
592 /* toggle folded flag on engine */
593 assert(item.variant_id != EngineID::Invalid());
594 Engine *engine = Engine::Get(item.variant_id);
596
597 InvalidateWindowData(WC_REPLACE_VEHICLE, this->window_number, 0); // Update the autoreplace window
598 InvalidateWindowClassesData(WC_BUILD_VEHICLE); // The build windows needs updating as well
599 return;
600 }
601 if (!item.flags.Test(EngineDisplayFlag::Shaded)) e = item.engine_id;
602 }
603
604 /* If Ctrl is pressed on the left side and we don't have any engines of the selected type, stop autoreplacing.
605 * This is most common when we have finished autoreplacing the engine and want to remove it from the list. */
606 if (click_side == 0 && _ctrl_pressed && e != EngineID::Invalid() &&
608 EngineID veh_from = e;
609 Command<CMD_SET_AUTOREPLACE>::Post(this->sel_group, veh_from, EngineID::Invalid(), false);
610 break;
611 }
612
613 if (e == this->sel_engine[click_side]) break; // we clicked the one we already selected
614 this->sel_engine[click_side] = e;
615 if (click_side == 0) {
616 this->engines[1].ForceRebuild();
617 this->reset_sel_engine = true;
618 }
619 this->SetDirty();
620 break;
621 }
622 }
623 }
624
625 void OnDropdownSelect(WidgetID widget, int index, int) override
626 {
627 switch (widget) {
629 if (this->sort_criteria != index) {
630 this->sort_criteria = index;
632 this->engines[1].ForceRebuild();
633 this->SetDirty();
634 }
635 break;
636
638 RailType temp = (RailType)index;
639 if (temp == this->sel_railtype) return; // we didn't select a new one. No need to change anything
640 this->sel_railtype = temp;
641 this->OnRailRoadTypeChange();
642 break;
643 }
644
646 RoadType temp = (RoadType)index;
647 if (temp == this->sel_roadtype) return; // we didn't select a new one. No need to change anything
648 this->sel_roadtype = temp;
649 this->OnRailRoadTypeChange();
650 break;
651 }
652
654 this->replace_engines = index != 0;
655 this->engines[0].ForceRebuild();
656 this->reset_sel_engine = true;
657 this->SetDirty();
658 break;
659 }
660
662 this->ReplaceClick_StartReplace(index != 0);
663 break;
664 }
665 }
666
667 bool OnTooltip([[maybe_unused]] Point pt, WidgetID widget, TooltipCloseCondition close_cond) override
668 {
669 if (widget != WID_RV_TRAIN_WAGONREMOVE_TOGGLE) return false;
670
671 if (Group::IsValidID(this->sel_group)) {
672 GuiShowTooltips(this, GetEncodedString(STR_REPLACE_REMOVE_WAGON_GROUP_HELP, STR_REPLACE_REMOVE_WAGON_TOOLTIP), close_cond);
673 } else {
674 GuiShowTooltips(this, GetEncodedString(STR_REPLACE_REMOVE_WAGON_TOOLTIP), close_cond);
675 }
676 return true;
677 }
678
679 void OnResize() override
680 {
681 this->vscroll[0]->SetCapacityFromWidget(this, WID_RV_LEFT_MATRIX);
682 this->vscroll[1]->SetCapacityFromWidget(this, WID_RV_RIGHT_MATRIX);
683 }
684
690 void OnInvalidateData([[maybe_unused]] int data = 0, [[maybe_unused]] bool gui_scope = true) override
691 {
692 if (data != 0) {
693 /* This needs to be done in command-scope to enforce rebuilding before resorting invalid data */
694 this->engines[0].ForceRebuild();
695 } else {
696 this->engines[1].ForceRebuild();
697 }
698 }
699};
700
701static constexpr NWidgetPart _nested_replace_rail_vehicle_widgets[] = {
703 NWidget(WWT_CLOSEBOX, COLOUR_GREY),
704 NWidget(WWT_CAPTION, COLOUR_GREY, WID_RV_CAPTION),
705 NWidget(WWT_SHADEBOX, COLOUR_GREY),
706 NWidget(WWT_DEFSIZEBOX, COLOUR_GREY),
707 NWidget(WWT_STICKYBOX, COLOUR_GREY),
708 EndContainer(),
710 NWidget(WWT_PANEL, COLOUR_GREY),
711 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),
712 EndContainer(),
713 NWidget(WWT_PANEL, COLOUR_GREY),
714 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),
715 EndContainer(),
716 EndContainer(),
720 NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_RV_RAIL_TYPE_DROPDOWN), SetMinimalSize(136, 12), SetToolTip(STR_REPLACE_RAILTYPE_TOOLTIP), SetFill(1, 0), SetResize(1, 0),
721 NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_RV_TRAIN_ENGINEWAGON_DROPDOWN), SetToolTip(STR_REPLACE_ENGINE_WAGON_SELECT_TOOLTIP),
722 EndContainer(),
723 NWidget(WWT_PANEL, COLOUR_GREY), SetResize(1, 0), EndContainer(),
724 EndContainer(),
727 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_RV_SORT_ASCENDING_DESCENDING), SetStringTip(STR_BUTTON_SORT_BY, STR_TOOLTIP_SORT_ORDER), SetFill(1, 1),
728 NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_RV_SORT_DROPDOWN), SetResize(1, 0), SetFill(1, 1), SetToolTip(STR_TOOLTIP_SORT_CRITERIA),
729 EndContainer(),
731 NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_RV_SHOW_HIDDEN_ENGINES), SetStringTip(STR_SHOW_HIDDEN_ENGINES_VEHICLE_TRAIN, STR_SHOW_HIDDEN_ENGINES_VEHICLE_TRAIN_TOOLTIP),
732 NWidget(WWT_PANEL, COLOUR_GREY), SetResize(1, 0), SetFill(1, 1), EndContainer(),
733 EndContainer(),
734 EndContainer(),
735 EndContainer(),
737 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),
739 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),
741 EndContainer(),
743 NWidget(WWT_PANEL, COLOUR_GREY, WID_RV_LEFT_DETAILS), SetMinimalSize(240, 122), SetResize(1, 0), EndContainer(),
746 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),
747 EndContainer(),
748 EndContainer(),
750 NWidget(NWID_PUSHBUTTON_DROPDOWN, COLOUR_GREY, WID_RV_START_REPLACE), SetMinimalSize(139, 12), SetStringTip(STR_REPLACE_VEHICLES_START, STR_REPLACE_START_BUTTON_TOOLTIP),
751 NWidget(WWT_PANEL, COLOUR_GREY, WID_RV_INFO_TAB), SetMinimalSize(167, 12), SetToolTip(STR_REPLACE_REPLACE_INFO_TAB_TOOLTIP), SetResize(1, 0),
752 EndContainer(),
753 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_RV_STOP_REPLACE), SetMinimalSize(150, 12), SetStringTip(STR_REPLACE_VEHICLES_STOP, STR_REPLACE_STOP_BUTTON_TOOLTIP),
754 NWidget(WWT_RESIZEBOX, COLOUR_GREY),
755 EndContainer(),
756};
757
758static WindowDesc _replace_rail_vehicle_desc(
759 WDP_AUTO, "replace_vehicle_train", 500, 140,
762 _nested_replace_rail_vehicle_widgets
763);
764
765static constexpr NWidgetPart _nested_replace_road_vehicle_widgets[] = {
767 NWidget(WWT_CLOSEBOX, COLOUR_GREY),
768 NWidget(WWT_CAPTION, COLOUR_GREY, WID_RV_CAPTION),
769 NWidget(WWT_SHADEBOX, COLOUR_GREY),
770 NWidget(WWT_DEFSIZEBOX, COLOUR_GREY),
771 NWidget(WWT_STICKYBOX, COLOUR_GREY),
772 EndContainer(),
774 NWidget(WWT_PANEL, COLOUR_GREY),
775 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),
776 EndContainer(),
777 NWidget(WWT_PANEL, COLOUR_GREY),
778 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),
779 EndContainer(),
780 EndContainer(),
783 NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_RV_ROAD_TYPE_DROPDOWN), SetMinimalSize(136, 12), SetToolTip(STR_REPLACE_ROADTYPE_TOOLTIP), SetFill(1, 0), SetResize(1, 0),
784 NWidget(WWT_PANEL, COLOUR_GREY), SetResize(1, 0), EndContainer(),
785 EndContainer(),
788 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_RV_SORT_ASCENDING_DESCENDING), SetStringTip(STR_BUTTON_SORT_BY, STR_TOOLTIP_SORT_ORDER), SetFill(1, 1),
789 NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_RV_SORT_DROPDOWN), SetResize(1, 0), SetFill(1, 1), SetToolTip(STR_TOOLTIP_SORT_CRITERIA),
790 EndContainer(),
792 NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_RV_SHOW_HIDDEN_ENGINES), SetStringTip(STR_SHOW_HIDDEN_ENGINES_VEHICLE_TRAIN, STR_SHOW_HIDDEN_ENGINES_VEHICLE_TRAIN_TOOLTIP),
793 NWidget(WWT_PANEL, COLOUR_GREY), SetResize(1, 0), SetFill(1, 1), EndContainer(),
794 EndContainer(),
795 EndContainer(),
796 EndContainer(),
798 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),
800 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),
802 EndContainer(),
804 NWidget(WWT_PANEL, COLOUR_GREY, WID_RV_LEFT_DETAILS), SetMinimalSize(240, 122), SetResize(1, 0), EndContainer(),
806 EndContainer(),
808 NWidget(NWID_PUSHBUTTON_DROPDOWN, COLOUR_GREY, WID_RV_START_REPLACE), SetMinimalSize(139, 12), SetStringTip(STR_REPLACE_VEHICLES_START, STR_REPLACE_START_BUTTON_TOOLTIP),
809 NWidget(WWT_PANEL, COLOUR_GREY, WID_RV_INFO_TAB), SetMinimalSize(167, 12), SetToolTip(STR_REPLACE_REPLACE_INFO_TAB_TOOLTIP), SetResize(1, 0),
810 EndContainer(),
811 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_RV_STOP_REPLACE), SetMinimalSize(150, 12), SetStringTip(STR_REPLACE_VEHICLES_STOP, STR_REPLACE_STOP_BUTTON_TOOLTIP),
812 NWidget(WWT_RESIZEBOX, COLOUR_GREY),
813 EndContainer(),
814};
815
816static WindowDesc _replace_road_vehicle_desc(
817 WDP_AUTO, "replace_vehicle_road", 500, 140,
820 _nested_replace_road_vehicle_widgets
821);
822
823static constexpr NWidgetPart _nested_replace_vehicle_widgets[] = {
825 NWidget(WWT_CLOSEBOX, COLOUR_GREY),
826 NWidget(WWT_CAPTION, COLOUR_GREY, WID_RV_CAPTION), SetMinimalSize(433, 14),
827 NWidget(WWT_SHADEBOX, COLOUR_GREY),
828 NWidget(WWT_DEFSIZEBOX, COLOUR_GREY),
829 NWidget(WWT_STICKYBOX, COLOUR_GREY),
830 EndContainer(),
832 NWidget(WWT_PANEL, COLOUR_GREY),
833 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),
834 EndContainer(),
835 NWidget(WWT_PANEL, COLOUR_GREY),
836 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),
837 EndContainer(),
838 EndContainer(),
840 NWidget(WWT_PANEL, COLOUR_GREY), SetResize(1, 0), EndContainer(),
843 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_RV_SORT_ASCENDING_DESCENDING), SetStringTip(STR_BUTTON_SORT_BY, STR_TOOLTIP_SORT_ORDER),
844 NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_RV_SORT_DROPDOWN), SetResize(1, 0), SetFill(1, 1), SetToolTip(STR_TOOLTIP_SORT_CRITERIA),
845 EndContainer(),
847 NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_RV_SHOW_HIDDEN_ENGINES), SetStringTip(STR_SHOW_HIDDEN_ENGINES_VEHICLE_TRAIN, STR_SHOW_HIDDEN_ENGINES_VEHICLE_TRAIN_TOOLTIP),
848 NWidget(WWT_PANEL, COLOUR_GREY), SetResize(1, 0), SetFill(1, 1), EndContainer(),
849 EndContainer(),
850 EndContainer(),
851 EndContainer(),
853 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),
855 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),
857 EndContainer(),
861 EndContainer(),
863 NWidget(NWID_PUSHBUTTON_DROPDOWN, COLOUR_GREY, WID_RV_START_REPLACE), SetMinimalSize(139, 12), SetStringTip(STR_REPLACE_VEHICLES_START, STR_REPLACE_START_BUTTON_TOOLTIP),
864 NWidget(WWT_PANEL, COLOUR_GREY, WID_RV_INFO_TAB), SetMinimalSize(167, 12), SetToolTip(STR_REPLACE_REPLACE_INFO_TAB_TOOLTIP), SetResize(1, 0), EndContainer(),
865 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_RV_STOP_REPLACE), SetMinimalSize(138, 12), SetStringTip(STR_REPLACE_VEHICLES_STOP, STR_REPLACE_STOP_BUTTON_TOOLTIP),
866 NWidget(WWT_RESIZEBOX, COLOUR_GREY),
867 EndContainer(),
868};
869
870static WindowDesc _replace_vehicle_desc(
871 WDP_AUTO, "replace_vehicle", 456, 118,
874 _nested_replace_vehicle_widgets
875);
876
883{
885 switch (vehicletype) {
886 case VEH_TRAIN: new ReplaceVehicleWindow(_replace_rail_vehicle_desc, vehicletype, id_g); break;
887 case VEH_ROAD: new ReplaceVehicleWindow(_replace_road_vehicle_desc, vehicletype, id_g); break;
888 default: new ReplaceVehicleWindow(_replace_vehicle_desc, vehicletype, id_g); break;
889 }
890}
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.
Flat set implementation that uses a sorted vector for storage.
std::pair< const_iterator, bool > insert(const Tkey &key)
Insert a key into the set, if it does not already exist.
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:1175
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:425
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: