OpenTTD Source 20250717-master-g55605ae8f2
company_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 "currency.h"
12#include "error.h"
13#include "gui.h"
14#include "settings_gui.h"
15#include "window_gui.h"
16#include "textbuf_gui.h"
17#include "viewport_func.h"
18#include "company_func.h"
19#include "command_func.h"
20#include "network/network.h"
21#include "network/network_gui.h"
23#include "newgrf.h"
25#include "strings_func.h"
27#include "dropdown_type.h"
28#include "tilehighlight_func.h"
29#include "company_base.h"
31#include "object_type.h"
32#include "rail.h"
33#include "road.h"
34#include "engine_base.h"
35#include "window_func.h"
36#include "road_func.h"
37#include "water.h"
38#include "station_func.h"
39#include "zoom_func.h"
40#include "sortlist_type.h"
41#include "company_cmd.h"
42#include "economy_cmd.h"
43#include "group_cmd.h"
44#include "group_gui.h"
45#include "misc_cmd.h"
46#include "object_cmd.h"
47#include "timer/timer.h"
48#include "timer/timer_window.h"
50
52
53#include "table/strings.h"
54
56
57#include "safeguards.h"
58
59
61static void DoSelectCompanyManagerFace(Window *parent);
62static void ShowCompanyInfrastructure(CompanyID company);
63
65static const std::initializer_list<ExpensesType> _expenses_list_revenue = {
70};
71
81
83static const std::initializer_list<ExpensesType> _expenses_list_capital_costs = {
87};
88
92 const std::initializer_list<ExpensesType> &items;
93
94 ExpensesList(StringID title, const std::initializer_list<ExpensesType> &list) : title(title), items(list)
95 {
96 }
97
98 uint GetHeight() const
99 {
100 /* Add up the height of all the lines. */
101 return static_cast<uint>(this->items.size()) * GetCharacterHeight(FS_NORMAL);
102 }
103
105 uint GetListWidth() const
106 {
107 uint width = 0;
108 for (const ExpensesType &et : this->items) {
109 width = std::max(width, GetStringBoundingBox(STR_FINANCES_SECTION_CONSTRUCTION + et).width);
110 }
111 return width;
112 }
113};
114
116static const std::initializer_list<ExpensesList> _expenses_list_types = {
117 { STR_FINANCES_REVENUE_TITLE, _expenses_list_revenue },
118 { STR_FINANCES_OPERATING_EXPENSES_TITLE, _expenses_list_operating_costs },
119 { STR_FINANCES_CAPITAL_EXPENSES_TITLE, _expenses_list_capital_costs },
120};
121
127{
128 /* There's an empty line and blockspace on the year row */
130
131 for (const ExpensesList &list : _expenses_list_types) {
132 /* Title + expense list + total line + total + blockspace after category */
134 }
135
136 /* Total income */
138
139 return total_height;
140}
141
147{
148 uint max_width = GetStringBoundingBox(TimerGameEconomy::UsingWallclockUnits() ? STR_FINANCES_PERIOD_CAPTION : STR_FINANCES_YEAR_CAPTION).width;
149
150 /* Loop through categories to check max widths. */
151 for (const ExpensesList &list : _expenses_list_types) {
152 /* Title of category */
153 max_width = std::max(max_width, GetStringBoundingBox(list.title).width);
154 /* Entries in category */
155 max_width = std::max(max_width, list.GetListWidth() + WidgetDimensions::scaled.hsep_indent);
156 }
157
158 return max_width;
159}
160
164static void DrawCategory(const Rect &r, int start_y, const ExpensesList &list)
165{
167
168 tr.top = start_y;
169
170 for (const ExpensesType &et : list.items) {
171 DrawString(tr, STR_FINANCES_SECTION_CONSTRUCTION + et);
172 tr.top += GetCharacterHeight(FS_NORMAL);
173 }
174}
175
181static void DrawCategories(const Rect &r)
182{
183 int y = r.top;
184 /* Draw description of 12-minute economic period. */
185 DrawString(r.left, r.right, y, (TimerGameEconomy::UsingWallclockUnits() ? STR_FINANCES_PERIOD_CAPTION : STR_FINANCES_YEAR_CAPTION), TC_FROMSTRING, SA_LEFT, true);
187
188 for (const ExpensesList &list : _expenses_list_types) {
189 /* Draw category title and advance y */
190 DrawString(r.left, r.right, y, list.title, TC_FROMSTRING, SA_LEFT);
192
193 /* Draw category items and advance y */
194 DrawCategory(r, y, list);
195 y += list.GetHeight();
196
197 /* Advance y by the height of the horizontal line between amounts and subtotal */
199
200 /* Draw category total and advance y */
201 DrawString(r.left, r.right, y, STR_FINANCES_TOTAL_CAPTION, TC_FROMSTRING, SA_RIGHT);
203
204 /* Advance y by a blockspace after this category block */
206 }
207
208 /* Draw total profit/loss */
210 DrawString(r.left, r.right, y, STR_FINANCES_PROFIT, TC_FROMSTRING, SA_LEFT);
211}
212
221static void DrawPrice(Money amount, int left, int right, int top, TextColour colour)
222{
223 StringID str = STR_FINANCES_NEGATIVE_INCOME;
224 if (amount == 0) {
225 str = STR_FINANCES_ZERO_INCOME;
226 } else if (amount < 0) {
227 amount = -amount;
228 str = STR_FINANCES_POSITIVE_INCOME;
229 }
230 DrawString(left, right, top, GetString(str, amount), colour, SA_RIGHT | SA_FORCE);
231}
232
237static Money DrawYearCategory(const Rect &r, int start_y, const ExpensesList &list, const Expenses &tbl)
238{
239 int y = start_y;
240 Money sum = 0;
241
242 for (const ExpensesType &et : list.items) {
243 Money cost = tbl[et];
244 sum += cost;
245 if (cost != 0) DrawPrice(cost, r.left, r.right, y, TC_BLACK);
247 }
248
249 /* Draw the total at the bottom of the category. */
250 GfxFillRect(r.left, y, r.right, y + WidgetDimensions::scaled.bevel.top - 1, PC_BLACK);
252 if (sum != 0) DrawPrice(sum, r.left, r.right, y, TC_WHITE);
253
254 /* Return the sum for the yearly total. */
255 return sum;
256}
257
258
266static void DrawYearColumn(const Rect &r, TimerGameEconomy::Year year, const Expenses &tbl)
267{
268 int y = r.top;
269 Money sum;
270
271 /* Year header */
272 DrawString(r.left, r.right, y, GetString(STR_FINANCES_YEAR, year), TC_FROMSTRING, SA_RIGHT | SA_FORCE, true);
274
275 /* Categories */
276 for (const ExpensesList &list : _expenses_list_types) {
278 sum += DrawYearCategory(r, y, list, tbl);
279 /* Expense list + expense category title + expense category total + blockspace after category */
281 }
282
283 /* Total income. */
284 GfxFillRect(r.left, y, r.right, y + WidgetDimensions::scaled.bevel.top - 1, PC_BLACK);
286 DrawPrice(sum, r.left, r.right, y, TC_WHITE);
287}
288
289static constexpr NWidgetPart _nested_company_finances_widgets[] = {
291 NWidget(WWT_CLOSEBOX, COLOUR_GREY),
292 NWidget(WWT_CAPTION, COLOUR_GREY, WID_CF_CAPTION),
293 NWidget(WWT_IMGBTN, COLOUR_GREY, WID_CF_TOGGLE_SIZE), SetSpriteTip(SPR_LARGE_SMALL_WINDOW, STR_TOOLTIP_TOGGLE_LARGE_SMALL_WINDOW), SetAspect(WidgetDimensions::ASPECT_TOGGLE_SIZE),
294 NWidget(WWT_SHADEBOX, COLOUR_GREY),
295 NWidget(WWT_STICKYBOX, COLOUR_GREY),
296 EndContainer(),
297 NWidget(NWID_SELECTION, INVALID_COLOUR, WID_CF_SEL_PANEL),
298 NWidget(WWT_PANEL, COLOUR_GREY),
300 NWidget(WWT_EMPTY, INVALID_COLOUR, WID_CF_EXPS_CATEGORY), SetMinimalSize(120, 0), SetFill(0, 0),
301 NWidget(WWT_EMPTY, INVALID_COLOUR, WID_CF_EXPS_PRICE1), SetMinimalSize(86, 0), SetFill(0, 0),
302 NWidget(WWT_EMPTY, INVALID_COLOUR, WID_CF_EXPS_PRICE2), SetMinimalSize(86, 0), SetFill(0, 0),
303 NWidget(WWT_EMPTY, INVALID_COLOUR, WID_CF_EXPS_PRICE3), SetMinimalSize(86, 0), SetFill(0, 0),
304 EndContainer(),
305 EndContainer(),
306 EndContainer(),
307 NWidget(WWT_PANEL, COLOUR_GREY),
309 NWidget(NWID_VERTICAL), // Vertical column with 'bank balance', 'loan'
310 NWidget(WWT_TEXT, INVALID_COLOUR), SetStringTip(STR_FINANCES_OWN_FUNDS_TITLE),
311 NWidget(WWT_TEXT, INVALID_COLOUR), SetStringTip(STR_FINANCES_LOAN_TITLE),
312 NWidget(WWT_TEXT, INVALID_COLOUR), SetStringTip(STR_FINANCES_BANK_BALANCE_TITLE), SetPadding(WidgetDimensions::unscaled.vsep_normal, 0, 0, 0),
313 EndContainer(),
314 NWidget(NWID_VERTICAL), // Vertical column with bank balance amount, loan amount, and total.
319 EndContainer(),
320 NWidget(NWID_SELECTION, INVALID_COLOUR, WID_CF_SEL_MAXLOAN),
321 NWidget(NWID_VERTICAL), SetPIPRatio(0, 0, 1), // Max loan information
322 NWidget(WWT_TEXT, INVALID_COLOUR, WID_CF_INTEREST_RATE),
323 NWidget(WWT_TEXT, INVALID_COLOUR, WID_CF_MAXLOAN_VALUE),
324 EndContainer(),
325 EndContainer(),
326 EndContainer(),
327 EndContainer(),
328 NWidget(NWID_SELECTION, INVALID_COLOUR, WID_CF_SEL_BUTTONS),
330 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_CF_INCREASE_LOAN), SetFill(1, 0), SetToolTip(STR_FINANCES_BORROW_TOOLTIP),
331 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_CF_REPAY_LOAN), SetFill(1, 0), SetToolTip(STR_FINANCES_REPAY_TOOLTIP),
332 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_CF_INFRASTRUCTURE), SetFill(1, 0), SetStringTip(STR_FINANCES_INFRASTRUCTURE_BUTTON, STR_COMPANY_VIEW_INFRASTRUCTURE_TOOLTIP),
333 EndContainer(),
334 EndContainer(),
335};
336
339 static constexpr int NUM_PERIODS = WID_CF_EXPS_PRICE3 - WID_CF_EXPS_PRICE1 + 1;
340
342 bool small = false;
343 uint8_t first_visible = NUM_PERIODS - 1;
344
345 CompanyFinancesWindow(WindowDesc &desc, CompanyID company) : Window(desc)
346 {
347 this->CreateNestedTree();
348 this->SetupWidgets();
349 this->FinishInitNested(company);
350
351 this->owner = this->window_number;
352 this->InvalidateData();
353 }
354
355 std::string GetWidgetString(WidgetID widget, StringID stringid) const override
356 {
357 switch (widget) {
358 case WID_CF_CAPTION:
359 return GetString(STR_FINANCES_CAPTION, this->window_number, this->window_number);
360
362 const Company *c = Company::Get(this->window_number);
363 return GetString(STR_FINANCES_BANK_BALANCE, c->money);
364 }
365
366 case WID_CF_LOAN_VALUE: {
367 const Company *c = Company::Get(this->window_number);
368 return GetString(STR_FINANCES_TOTAL_CURRENCY, c->current_loan);
369 }
370
371 case WID_CF_OWN_VALUE: {
372 const Company *c = Company::Get(this->window_number);
373 return GetString(STR_FINANCES_TOTAL_CURRENCY, c->money - c->current_loan);
374 }
375
377 return GetString(STR_FINANCES_INTEREST_RATE, _settings_game.difficulty.initial_interest);
378
380 const Company *c = Company::Get(this->window_number);
381 return GetString(STR_FINANCES_MAX_LOAN, c->GetMaxLoan());
382 }
383
385 return GetString(STR_FINANCES_BORROW_BUTTON, LOAN_INTERVAL);
386
388 return GetString(STR_FINANCES_REPAY_BUTTON, LOAN_INTERVAL);
389
390 default:
391 return this->Window::GetWidgetString(widget, stringid);
392 }
393 }
394
395 void UpdateWidgetSize(WidgetID widget, Dimension &size, [[maybe_unused]] const Dimension &padding, [[maybe_unused]] Dimension &fill, [[maybe_unused]] Dimension &resize) override
396 {
397 switch (widget) {
399 size.width = GetMaxCategoriesWidth();
400 size.height = GetTotalCategoriesHeight();
401 break;
402
406 size.height = GetTotalCategoriesHeight();
407 [[fallthrough]];
408
411 case WID_CF_OWN_VALUE: {
413 size.width = std::max(GetStringBoundingBox(GetString(STR_FINANCES_NEGATIVE_INCOME, max_value)).width, GetStringBoundingBox(GetString(STR_FINANCES_POSITIVE_INCOME, max_value)).width);
414 size.width += padding.width;
415 break;
416 }
417
419 size.height = GetCharacterHeight(FS_NORMAL);
420 break;
421 }
422 }
423
424 void DrawWidget(const Rect &r, WidgetID widget) const override
425 {
426 switch (widget) {
429 break;
430
433 case WID_CF_EXPS_PRICE3: {
434 int period = widget - WID_CF_EXPS_PRICE1;
435 if (period < this->first_visible) break;
436
437 const Company *c = Company::Get(this->window_number);
438 const auto &expenses = c->yearly_expenses[NUM_PERIODS - period - 1];
439 DrawYearColumn(r, TimerGameEconomy::year - (NUM_PERIODS - period - 1), expenses);
440 break;
441 }
442
444 GfxFillRect(r.left, r.top, r.right, r.top + WidgetDimensions::scaled.bevel.top - 1, PC_BLACK);
445 break;
446 }
447 }
448
454 {
455 int plane = this->small ? SZSP_NONE : 0;
456 this->GetWidget<NWidgetStacked>(WID_CF_SEL_PANEL)->SetDisplayedPlane(plane);
457 this->GetWidget<NWidgetStacked>(WID_CF_SEL_MAXLOAN)->SetDisplayedPlane(plane);
458
459 CompanyID company = this->window_number;
460 plane = (company != _local_company) ? SZSP_NONE : 0;
461 this->GetWidget<NWidgetStacked>(WID_CF_SEL_BUTTONS)->SetDisplayedPlane(plane);
462 }
463
464 void OnPaint() override
465 {
466 if (!this->IsShaded()) {
467 if (!this->small) {
468 /* Check that the expenses panel height matches the height needed for the layout. */
469 if (GetTotalCategoriesHeight() != this->GetWidget<NWidgetBase>(WID_CF_EXPS_CATEGORY)->current_y) {
470 this->SetupWidgets();
471 this->ReInit();
472 return;
473 }
474 }
475
476 /* Check that the loan buttons are shown only when the user owns the company. */
477 CompanyID company = this->window_number;
478 int req_plane = (company != _local_company) ? SZSP_NONE : 0;
479 if (req_plane != this->GetWidget<NWidgetStacked>(WID_CF_SEL_BUTTONS)->shown_plane) {
480 this->SetupWidgets();
481 this->ReInit();
482 return;
483 }
484
485 const Company *c = Company::Get(company);
486 this->SetWidgetDisabledState(WID_CF_INCREASE_LOAN, c->current_loan >= c->GetMaxLoan()); // Borrow button only shows when there is any more money to loan.
487 this->SetWidgetDisabledState(WID_CF_REPAY_LOAN, company != _local_company || c->current_loan == 0); // Repay button only shows when there is any more money to repay.
488 }
489
490 this->DrawWidgets();
491 }
492
493 void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override
494 {
495 switch (widget) {
496 case WID_CF_TOGGLE_SIZE: // toggle size
497 this->small = !this->small;
498 this->SetupWidgets();
499 if (this->IsShaded()) {
500 /* Finances window is not resizable, so size hints given during unshading have no effect
501 * on the changed appearance of the window. */
502 this->SetShaded(false);
503 } else {
504 this->ReInit();
505 }
506 break;
507
508 case WID_CF_INCREASE_LOAN: // increase loan
509 Command<CMD_INCREASE_LOAN>::Post(STR_ERROR_CAN_T_BORROW_ANY_MORE_MONEY, _ctrl_pressed ? LoanCommand::Max : LoanCommand::Interval, 0);
510 break;
511
512 case WID_CF_REPAY_LOAN: // repay loan
513 Command<CMD_DECREASE_LOAN>::Post(STR_ERROR_CAN_T_REPAY_LOAN, _ctrl_pressed ? LoanCommand::Max : LoanCommand::Interval, 0);
514 break;
515
516 case WID_CF_INFRASTRUCTURE: // show infrastructure details
518 break;
519 }
520 }
521
522 void RefreshVisibleColumns()
523 {
524 for (uint period = 0; period < this->first_visible; ++period) {
525 const Company *c = Company::Get(this->window_number);
526 const Expenses &expenses = c->yearly_expenses[NUM_PERIODS - period - 1];
527 /* Show expenses column if it has any non-zero value in it. */
528 if (std::ranges::any_of(expenses, [](const Money &value) { return value != 0; })) {
529 this->first_visible = period;
530 break;
531 }
532 }
533 }
534
535 void OnInvalidateData(int, bool) override
536 {
537 this->RefreshVisibleColumns();
538 }
539
544 const IntervalTimer<TimerWindow> rescale_interval = {std::chrono::seconds(3), [this](auto) {
545 const Company *c = Company::Get(this->window_number);
548 this->SetupWidgets();
549 this->ReInit();
550 }
551 }};
552};
553
556
557static WindowDesc _company_finances_desc(
558 WDP_AUTO, "company_finances", 0, 0,
560 {},
561 _nested_company_finances_widgets
562);
563
570{
571 if (!Company::IsValidID(company)) return;
572 if (BringWindowToFrontById(WC_FINANCES, company)) return;
573
574 new CompanyFinancesWindow(_company_finances_desc, company);
575}
576
577/* Association of liveries to livery classes */
578static const LiveryClass _livery_class[LS_END] = {
579 LC_OTHER,
580 LC_RAIL, LC_RAIL, LC_RAIL, LC_RAIL, LC_RAIL, LC_RAIL, LC_RAIL, LC_RAIL, LC_RAIL, LC_RAIL, LC_RAIL, LC_RAIL, LC_RAIL,
581 LC_ROAD, LC_ROAD,
582 LC_SHIP, LC_SHIP,
583 LC_AIRCRAFT, LC_AIRCRAFT, LC_AIRCRAFT,
584 LC_ROAD, LC_ROAD,
585};
586
591template <SpriteID TSprite = SPR_SQUARE>
592class DropDownListColourItem : public DropDownIcon<DropDownString<DropDownListItem>> {
593public:
594 DropDownListColourItem(int colour, bool masked) :
595 DropDownIcon<DropDownString<DropDownListItem>>(TSprite, GetColourPalette(static_cast<Colours>(colour % COLOUR_END)), GetString(colour < COLOUR_END ? (STR_COLOUR_DARK_BLUE + colour) : STR_COLOUR_DEFAULT), colour, masked)
596 {
597 }
598};
599
602private:
603 uint32_t sel = 0;
604 LiveryClass livery_class{};
605 Dimension square{};
606 uint rows = 0;
607 uint line_height = 0;
608 GUIGroupList groups{};
609 Scrollbar *vscroll = nullptr;
610
611 void ShowColourDropDownMenu(uint32_t widget)
612 {
613 uint32_t used_colours = 0;
614 const Livery *livery, *default_livery = nullptr;
615 bool primary = widget == WID_SCL_PRI_COL_DROPDOWN;
616 uint8_t default_col = 0;
617
618 /* Disallow other company colours for the primary colour */
619 if (this->livery_class < LC_GROUP_RAIL && HasBit(this->sel, LS_DEFAULT) && primary) {
620 for (const Company *c : Company::Iterate()) {
621 if (c->index != _local_company) SetBit(used_colours, c->colour);
622 }
623 }
624
625 const Company *c = Company::Get(this->window_number);
626
627 if (this->livery_class < LC_GROUP_RAIL) {
628 /* Get the first selected livery to use as the default dropdown item */
629 LiveryScheme scheme;
630 for (scheme = LS_BEGIN; scheme < LS_END; scheme++) {
631 if (HasBit(this->sel, scheme)) break;
632 }
633 if (scheme == LS_END) scheme = LS_DEFAULT;
634 livery = &c->livery[scheme];
635 if (scheme != LS_DEFAULT) default_livery = &c->livery[LS_DEFAULT];
636 } else {
637 const Group *g = Group::Get(this->sel);
638 livery = &g->livery;
639 if (g->parent == GroupID::Invalid()) {
640 default_livery = &c->livery[LS_DEFAULT];
641 } else {
642 const Group *pg = Group::Get(g->parent);
643 default_livery = &pg->livery;
644 }
645 }
646
647 DropDownList list;
648 if (default_livery != nullptr) {
649 /* Add COLOUR_END to put the colour out of range, but also allow us to show what the default is */
650 default_col = (primary ? default_livery->colour1 : default_livery->colour2) + COLOUR_END;
651 list.push_back(std::make_unique<DropDownListColourItem<>>(default_col, false));
652 }
653 for (Colours colour = COLOUR_BEGIN; colour != COLOUR_END; colour++) {
654 list.push_back(std::make_unique<DropDownListColourItem<>>(colour, HasBit(used_colours, colour)));
655 }
656
657 uint8_t sel;
658 if (default_livery == nullptr || HasBit(livery->in_use, primary ? 0 : 1)) {
659 sel = primary ? livery->colour1 : livery->colour2;
660 } else {
661 sel = default_col;
662 }
663 ShowDropDownList(this, std::move(list), sel, widget);
664 }
665
666 void BuildGroupList(CompanyID owner)
667 {
668 if (!this->groups.NeedRebuild()) return;
669
670 this->groups.clear();
671
672 if (this->livery_class >= LC_GROUP_RAIL) {
673 VehicleType vtype = (VehicleType)(this->livery_class - LC_GROUP_RAIL);
674 BuildGuiGroupList(this->groups, false, owner, vtype);
675 }
676
677 this->groups.RebuildDone();
678 }
679
680 void SetRows()
681 {
682 if (this->livery_class < LC_GROUP_RAIL) {
683 this->rows = 0;
684 for (LiveryScheme scheme = LS_DEFAULT; scheme < LS_END; scheme++) {
685 if (_livery_class[scheme] == this->livery_class && HasBit(_loaded_newgrf_features.used_liveries, scheme)) {
686 this->rows++;
687 }
688 }
689 } else {
690 this->rows = (uint)this->groups.size();
691 }
692
693 this->vscroll->SetCount(this->rows);
694 }
695
696public:
697 SelectCompanyLiveryWindow(WindowDesc &desc, CompanyID company, GroupID group) : Window(desc)
698 {
699 this->CreateNestedTree();
700 this->vscroll = this->GetScrollbar(WID_SCL_MATRIX_SCROLLBAR);
701
702 if (group == GroupID::Invalid()) {
703 this->livery_class = LC_OTHER;
704 this->sel = 1;
706 this->BuildGroupList(company);
707 this->SetRows();
708 } else {
709 this->SetSelectedGroup(company, group);
710 }
711
712 this->FinishInitNested(company);
713 this->owner = company;
714 this->InvalidateData(1);
715 }
716
717 void SetSelectedGroup(CompanyID company, GroupID group)
718 {
719 this->RaiseWidget(WID_SCL_CLASS_GENERAL + this->livery_class);
720 const Group *g = Group::Get(group);
721 switch (g->vehicle_type) {
722 case VEH_TRAIN: this->livery_class = LC_GROUP_RAIL; break;
723 case VEH_ROAD: this->livery_class = LC_GROUP_ROAD; break;
724 case VEH_SHIP: this->livery_class = LC_GROUP_SHIP; break;
725 case VEH_AIRCRAFT: this->livery_class = LC_GROUP_AIRCRAFT; break;
726 default: NOT_REACHED();
727 }
728 this->sel = group.base();
729 this->LowerWidget(WID_SCL_CLASS_GENERAL + this->livery_class);
730
731 this->groups.ForceRebuild();
732 this->BuildGroupList(company);
733 this->SetRows();
734
735 /* Position scrollbar to selected group */
736 for (uint i = 0; i < this->rows; i++) {
737 if (this->groups[i].group->index == sel) {
738 this->vscroll->SetPosition(i - this->vscroll->GetCapacity() / 2);
739 break;
740 }
741 }
742 }
743
744 void UpdateWidgetSize(WidgetID widget, Dimension &size, [[maybe_unused]] const Dimension &padding, [[maybe_unused]] Dimension &fill, [[maybe_unused]] Dimension &resize) override
745 {
746 switch (widget) {
748 /* The matrix widget below needs enough room to print all the schemes. */
749 Dimension d = {0, 0};
750 for (LiveryScheme scheme = LS_DEFAULT; scheme < LS_END; scheme++) {
751 d = maxdim(d, GetStringBoundingBox(STR_LIVERY_DEFAULT + scheme));
752 }
753
754 size.width = std::max(size.width, 5 + d.width + padding.width);
755 break;
756 }
757
758 case WID_SCL_MATRIX: {
759 /* 11 items in the default rail class */
760 this->square = GetSpriteSize(SPR_SQUARE);
761 this->line_height = std::max(this->square.height, (uint)GetCharacterHeight(FS_NORMAL)) + padding.height;
762
763 size.height = 5 * this->line_height;
764 resize.width = 1;
765 fill.height = resize.height = this->line_height;
766 break;
767 }
768
771 size.width = 0;
772 break;
773 }
774 [[fallthrough]];
775
777 this->square = GetSpriteSize(SPR_SQUARE);
778 int string_padding = this->square.width + WidgetDimensions::scaled.hsep_normal + padding.width;
779 for (Colours colour = COLOUR_BEGIN; colour != COLOUR_END; colour++) {
780 size.width = std::max(size.width, GetStringBoundingBox(STR_COLOUR_DARK_BLUE + colour).width + string_padding);
781 }
782 size.width = std::max(size.width, GetStringBoundingBox(STR_COLOUR_DEFAULT).width + string_padding);
783 break;
784 }
785 }
786 }
787
788 void OnPaint() override
789 {
790 bool local = this->window_number == _local_company;
791
792 /* Disable dropdown controls if no scheme is selected */
793 bool disabled = this->livery_class < LC_GROUP_RAIL ? (this->sel == 0) : (this->sel == GroupID::Invalid());
794 this->SetWidgetDisabledState(WID_SCL_PRI_COL_DROPDOWN, !local || disabled);
795 this->SetWidgetDisabledState(WID_SCL_SEC_COL_DROPDOWN, !local || disabled);
796
797 this->BuildGroupList(this->window_number);
798
799 this->DrawWidgets();
800 }
801
802 std::string GetWidgetString(WidgetID widget, StringID stringid) const override
803 {
804 switch (widget) {
805 case WID_SCL_CAPTION:
806 return GetString(STR_LIVERY_CAPTION, this->window_number);
807
810 const Company *c = Company::Get(this->window_number);
811 bool primary = widget == WID_SCL_PRI_COL_DROPDOWN;
812 StringID colour = STR_COLOUR_DEFAULT;
813
814 if (this->livery_class < LC_GROUP_RAIL) {
815 if (this->sel != 0) {
816 LiveryScheme scheme = LS_DEFAULT;
817 for (scheme = LS_BEGIN; scheme < LS_END; scheme++) {
818 if (HasBit(this->sel, scheme)) break;
819 }
820 if (scheme == LS_END) scheme = LS_DEFAULT;
821 const Livery *livery = &c->livery[scheme];
822 if (scheme == LS_DEFAULT || HasBit(livery->in_use, primary ? 0 : 1)) {
823 colour = STR_COLOUR_DARK_BLUE + (primary ? livery->colour1 : livery->colour2);
824 }
825 }
826 } else {
827 if (this->sel != GroupID::Invalid()) {
828 const Group *g = Group::Get(this->sel);
829 const Livery *livery = &g->livery;
830 if (HasBit(livery->in_use, primary ? 0 : 1)) {
831 colour = STR_COLOUR_DARK_BLUE + (primary ? livery->colour1 : livery->colour2);
832 }
833 }
834 }
835 return GetString(colour);
836 }
837
838 default:
839 return this->Window::GetWidgetString(widget, stringid);
840 }
841 }
842
843 void DrawWidget(const Rect &r, WidgetID widget) const override
844 {
845 if (widget != WID_SCL_MATRIX) return;
846
847 bool rtl = _current_text_dir == TD_RTL;
848
849 /* Coordinates of scheme name column. */
850 const NWidgetBase *nwi = this->GetWidget<NWidgetBase>(WID_SCL_SPACER_DROPDOWN);
851 Rect sch = nwi->GetCurrentRect().Shrink(WidgetDimensions::scaled.framerect);
852 /* Coordinates of first dropdown. */
853 nwi = this->GetWidget<NWidgetBase>(WID_SCL_PRI_COL_DROPDOWN);
854 Rect pri = nwi->GetCurrentRect().Shrink(WidgetDimensions::scaled.framerect);
855 /* Coordinates of second dropdown. */
856 nwi = this->GetWidget<NWidgetBase>(WID_SCL_SEC_COL_DROPDOWN);
857 Rect sec = nwi->GetCurrentRect().Shrink(WidgetDimensions::scaled.framerect);
858
859 Rect pri_squ = pri.WithWidth(this->square.width, rtl);
860 Rect sec_squ = sec.WithWidth(this->square.width, rtl);
861
862 pri = pri.Indent(this->square.width + WidgetDimensions::scaled.hsep_normal, rtl);
863 sec = sec.Indent(this->square.width + WidgetDimensions::scaled.hsep_normal, rtl);
864
866 int square_offs = (ir.Height() - this->square.height) / 2;
867 int text_offs = (ir.Height() - GetCharacterHeight(FS_NORMAL)) / 2;
868
869 int y = ir.top;
870
871 /* Helper function to draw livery info. */
872 auto draw_livery = [&](std::string_view str, const Livery &livery, bool is_selected, bool is_default_scheme, int indent) {
873 /* Livery Label. */
874 DrawString(sch.left + (rtl ? 0 : indent), sch.right - (rtl ? indent : 0), y + text_offs, str, is_selected ? TC_WHITE : TC_BLACK);
875
876 /* Text below the first dropdown. */
877 DrawSprite(SPR_SQUARE, GetColourPalette(livery.colour1), pri_squ.left, y + square_offs);
878 DrawString(pri.left, pri.right, y + text_offs, (is_default_scheme || HasBit(livery.in_use, 0)) ? STR_COLOUR_DARK_BLUE + livery.colour1 : STR_COLOUR_DEFAULT, is_selected ? TC_WHITE : TC_GOLD);
879
880 /* Text below the second dropdown. */
881 if (sec.right > sec.left) { // Second dropdown has non-zero size.
882 DrawSprite(SPR_SQUARE, GetColourPalette(livery.colour2), sec_squ.left, y + square_offs);
883 DrawString(sec.left, sec.right, y + text_offs, (is_default_scheme || HasBit(livery.in_use, 1)) ? STR_COLOUR_DARK_BLUE + livery.colour2 : STR_COLOUR_DEFAULT, is_selected ? TC_WHITE : TC_GOLD);
884 }
885
886 y += this->line_height;
887 };
888
889 const Company *c = Company::Get(this->window_number);
890
891 if (livery_class < LC_GROUP_RAIL) {
892 int pos = this->vscroll->GetPosition();
893 for (LiveryScheme scheme = LS_DEFAULT; scheme < LS_END; scheme++) {
894 if (_livery_class[scheme] == this->livery_class && HasBit(_loaded_newgrf_features.used_liveries, scheme)) {
895 if (pos-- > 0) continue;
896 draw_livery(GetString(STR_LIVERY_DEFAULT + scheme), c->livery[scheme], HasBit(this->sel, scheme), scheme == LS_DEFAULT, 0);
897 }
898 }
899 } else {
900 auto [first, last] = this->vscroll->GetVisibleRangeIterators(this->groups);
901 for (auto it = first; it != last; ++it) {
902 const Group *g = it->group;
903 draw_livery(GetString(STR_GROUP_NAME, g->index), g->livery, this->sel == g->index, false, it->indent * WidgetDimensions::scaled.hsep_indent);
904 }
905
906 if (this->vscroll->GetCount() == 0) {
907 const StringID empty_labels[] = { STR_LIVERY_TRAIN_GROUP_EMPTY, STR_LIVERY_ROAD_VEHICLE_GROUP_EMPTY, STR_LIVERY_SHIP_GROUP_EMPTY, STR_LIVERY_AIRCRAFT_GROUP_EMPTY };
908 VehicleType vtype = (VehicleType)(this->livery_class - LC_GROUP_RAIL);
909 DrawString(ir.left, ir.right, y + text_offs, empty_labels[vtype], TC_BLACK);
910 }
911 }
912 }
913
914 void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override
915 {
916 switch (widget) {
917 /* Livery Class buttons */
927 this->RaiseWidget(WID_SCL_CLASS_GENERAL + this->livery_class);
928 this->livery_class = (LiveryClass)(widget - WID_SCL_CLASS_GENERAL);
929 this->LowerWidget(WID_SCL_CLASS_GENERAL + this->livery_class);
930
931 /* Select the first item in the list */
932 if (this->livery_class < LC_GROUP_RAIL) {
933 this->sel = 0;
934 for (LiveryScheme scheme = LS_DEFAULT; scheme < LS_END; scheme++) {
935 if (_livery_class[scheme] == this->livery_class && HasBit(_loaded_newgrf_features.used_liveries, scheme)) {
936 this->sel = 1 << scheme;
937 break;
938 }
939 }
940 } else {
941 this->sel = GroupID::Invalid().base();
942 this->groups.ForceRebuild();
943 this->BuildGroupList(this->window_number);
944
945 if (!this->groups.empty()) {
946 this->sel = this->groups[0].group->index.base();
947 }
948 }
949
950 this->SetRows();
951 this->SetDirty();
952 break;
953
954 case WID_SCL_PRI_COL_DROPDOWN: // First colour dropdown
955 ShowColourDropDownMenu(WID_SCL_PRI_COL_DROPDOWN);
956 break;
957
958 case WID_SCL_SEC_COL_DROPDOWN: // Second colour dropdown
959 ShowColourDropDownMenu(WID_SCL_SEC_COL_DROPDOWN);
960 break;
961
962 case WID_SCL_MATRIX: {
963 if (this->livery_class < LC_GROUP_RAIL) {
964 uint row = this->vscroll->GetScrolledRowFromWidget(pt.y, this, widget);
965 if (row >= this->rows) return;
966
967 LiveryScheme j = (LiveryScheme)row;
968
969 for (LiveryScheme scheme = LS_BEGIN; scheme <= j && scheme < LS_END; scheme++) {
970 if (_livery_class[scheme] != this->livery_class || !HasBit(_loaded_newgrf_features.used_liveries, scheme)) j++;
971 }
972 assert(j < LS_END);
973
974 if (_ctrl_pressed) {
975 ToggleBit(this->sel, j);
976 } else {
977 this->sel = 1 << j;
978 }
979 } else {
980 auto it = this->vscroll->GetScrolledItemFromWidget(this->groups, pt.y, this, widget);
981 if (it == std::end(this->groups)) return;
982
983 this->sel = it->group->index.base();
984 }
985 this->SetDirty();
986 break;
987 }
988 }
989 }
990
991 void OnResize() override
992 {
993 this->vscroll->SetCapacityFromWidget(this, WID_SCL_MATRIX);
994 }
995
996 void OnDropdownSelect(WidgetID widget, int index, int) override
997 {
998 bool local = this->window_number == _local_company;
999 if (!local) return;
1000
1001 Colours colour = static_cast<Colours>(index);
1002 if (colour >= COLOUR_END) colour = INVALID_COLOUR;
1003
1004 if (this->livery_class < LC_GROUP_RAIL) {
1005 /* Set company colour livery */
1006 for (LiveryScheme scheme = LS_DEFAULT; scheme < LS_END; scheme++) {
1007 /* Changed colour for the selected scheme, or all visible schemes if CTRL is pressed. */
1008 if (HasBit(this->sel, scheme) || (_ctrl_pressed && _livery_class[scheme] == this->livery_class && HasBit(_loaded_newgrf_features.used_liveries, scheme))) {
1010 }
1011 }
1012 } else {
1013 /* Setting group livery */
1014 Command<CMD_SET_GROUP_LIVERY>::Post(static_cast<GroupID>(this->sel), widget == WID_SCL_PRI_COL_DROPDOWN, colour);
1015 }
1016 }
1017
1023 void OnInvalidateData([[maybe_unused]] int data = 0, [[maybe_unused]] bool gui_scope = true) override
1024 {
1025 if (!gui_scope) return;
1026
1027 if (data != -1) {
1028 /* data contains a VehicleType, rebuild list if it displayed */
1029 if (this->livery_class == data + LC_GROUP_RAIL) {
1030 this->groups.ForceRebuild();
1031 this->BuildGroupList(this->window_number);
1032 this->SetRows();
1033
1034 if (!Group::IsValidID(this->sel)) {
1035 this->sel = GroupID::Invalid().base();
1036 if (!this->groups.empty()) this->sel = this->groups[0].group->index.base();
1037 }
1038
1039 this->SetDirty();
1040 }
1041 return;
1042 }
1043
1045
1046 bool current_class_valid = this->livery_class == LC_OTHER || this->livery_class >= LC_GROUP_RAIL;
1047 if (_settings_client.gui.liveries == LIT_ALL || (_settings_client.gui.liveries == LIT_COMPANY && this->window_number == _local_company)) {
1048 for (LiveryScheme scheme = LS_DEFAULT; scheme < LS_END; scheme++) {
1050 if (_livery_class[scheme] == this->livery_class) current_class_valid = true;
1051 this->EnableWidget(WID_SCL_CLASS_GENERAL + _livery_class[scheme]);
1052 } else if (this->livery_class < LC_GROUP_RAIL) {
1053 ClrBit(this->sel, scheme);
1054 }
1055 }
1056 }
1057
1058 if (!current_class_valid) {
1059 Point pt = {0, 0};
1060 this->OnClick(pt, WID_SCL_CLASS_GENERAL, 1);
1061 }
1062 }
1063};
1064
1065static constexpr NWidgetPart _nested_select_company_livery_widgets[] = {
1067 NWidget(WWT_CLOSEBOX, COLOUR_GREY),
1068 NWidget(WWT_CAPTION, COLOUR_GREY, WID_SCL_CAPTION),
1069 NWidget(WWT_SHADEBOX, COLOUR_GREY),
1070 NWidget(WWT_DEFSIZEBOX, COLOUR_GREY),
1071 NWidget(WWT_STICKYBOX, COLOUR_GREY),
1072 EndContainer(),
1074 NWidget(WWT_IMGBTN, COLOUR_GREY, WID_SCL_CLASS_GENERAL), SetToolbarMinimalSize(1), SetFill(0, 1), SetSpriteTip(SPR_IMG_COMPANY_GENERAL, STR_LIVERY_GENERAL_TOOLTIP),
1075 NWidget(WWT_IMGBTN, COLOUR_GREY, WID_SCL_CLASS_RAIL), SetToolbarMinimalSize(1), SetFill(0, 1), SetSpriteTip(SPR_IMG_TRAINLIST, STR_LIVERY_TRAIN_TOOLTIP),
1076 NWidget(WWT_IMGBTN, COLOUR_GREY, WID_SCL_CLASS_ROAD), SetToolbarMinimalSize(1), SetFill(0, 1), SetSpriteTip(SPR_IMG_TRUCKLIST, STR_LIVERY_ROAD_VEHICLE_TOOLTIP),
1077 NWidget(WWT_IMGBTN, COLOUR_GREY, WID_SCL_CLASS_SHIP), SetToolbarMinimalSize(1), SetFill(0, 1), SetSpriteTip(SPR_IMG_SHIPLIST, STR_LIVERY_SHIP_TOOLTIP),
1078 NWidget(WWT_IMGBTN, COLOUR_GREY, WID_SCL_CLASS_AIRCRAFT), SetToolbarMinimalSize(1), SetFill(0, 1), SetSpriteTip(SPR_IMG_AIRPLANESLIST, STR_LIVERY_AIRCRAFT_TOOLTIP),
1079 NWidget(WWT_IMGBTN, COLOUR_GREY, WID_SCL_GROUPS_RAIL), SetToolbarMinimalSize(1), SetFill(0, 1), SetSpriteTip(SPR_GROUP_LIVERY_TRAIN, STR_LIVERY_TRAIN_GROUP_TOOLTIP),
1080 NWidget(WWT_IMGBTN, COLOUR_GREY, WID_SCL_GROUPS_ROAD), SetToolbarMinimalSize(1), SetFill(0, 1), SetSpriteTip(SPR_GROUP_LIVERY_ROADVEH, STR_LIVERY_ROAD_VEHICLE_GROUP_TOOLTIP),
1081 NWidget(WWT_IMGBTN, COLOUR_GREY, WID_SCL_GROUPS_SHIP), SetToolbarMinimalSize(1), SetFill(0, 1), SetSpriteTip(SPR_GROUP_LIVERY_SHIP, STR_LIVERY_SHIP_GROUP_TOOLTIP),
1082 NWidget(WWT_IMGBTN, COLOUR_GREY, WID_SCL_GROUPS_AIRCRAFT), SetToolbarMinimalSize(1), SetFill(0, 1), SetSpriteTip(SPR_GROUP_LIVERY_AIRCRAFT, STR_LIVERY_AIRCRAFT_GROUP_TOOLTIP),
1083 NWidget(WWT_PANEL, COLOUR_GREY), SetFill(1, 1), SetResize(1, 0), EndContainer(),
1084 EndContainer(),
1086 NWidget(WWT_MATRIX, COLOUR_GREY, WID_SCL_MATRIX), SetMinimalSize(275, 0), SetResize(1, 0), SetFill(1, 1), SetMatrixDataTip(1, 0, STR_LIVERY_PANEL_TOOLTIP), SetScrollbar(WID_SCL_MATRIX_SCROLLBAR),
1088 EndContainer(),
1091 NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_SCL_PRI_COL_DROPDOWN), SetFill(0, 1), SetToolTip(STR_LIVERY_PRIMARY_TOOLTIP),
1092 NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_SCL_SEC_COL_DROPDOWN), SetFill(0, 1), SetToolTip(STR_LIVERY_SECONDARY_TOOLTIP),
1093 NWidget(WWT_RESIZEBOX, COLOUR_GREY),
1094 EndContainer(),
1095};
1096
1097static WindowDesc _select_company_livery_desc(
1098 WDP_AUTO, "company_color_scheme", 0, 0,
1100 {},
1101 _nested_select_company_livery_widgets
1102);
1103
1104void ShowCompanyLiveryWindow(CompanyID company, GroupID group)
1105{
1107 if (w == nullptr) {
1108 new SelectCompanyLiveryWindow(_select_company_livery_desc, company, group);
1109 } else if (group != GroupID::Invalid()) {
1110 w->SetSelectedGroup(company, group);
1111 }
1112}
1113
1120void DrawCompanyManagerFace(const CompanyManagerFace &cmf, Colours colour, const Rect &r)
1121{
1122 /* Determine offset from centre of drawing rect. */
1123 Dimension d = GetSpriteSize(SPR_GRADIENT);
1124 int x = CentreBounds(r.left, r.right, d.width);
1125 int y = CentreBounds(r.top, r.bottom, d.height);
1126
1127 FaceVars vars = GetCompanyManagerFaceVars(cmf.style);
1128
1129 /* First determine which parts are enabled. */
1130 uint64_t active_vars = GetActiveFaceVars(cmf, vars);
1131
1132 std::unordered_map<uint8_t, PaletteID> palettes;
1133
1134 /* Second, get palettes. */
1135 for (auto var : SetBitIterator(active_vars)) {
1136 if (vars[var].type != FaceVarType::Palette) continue;
1137
1138 PaletteID pal = PAL_NONE;
1139 switch (vars[var].GetBits(cmf)) {
1140 default: NOT_REACHED();
1141 case 0: pal = PALETTE_TO_BROWN; break;
1142 case 1: pal = PALETTE_TO_BLUE; break;
1143 case 2: pal = PALETTE_TO_GREEN; break;
1144 }
1145 for (uint8_t affected_var : SetBitIterator(std::get<uint64_t>(vars[var].data))) {
1146 palettes[affected_var] = pal;
1147 }
1148 }
1149
1150 /* Draw the gradient (background) */
1151 DrawSprite(SPR_GRADIENT, GetColourPalette(colour), x, y);
1152
1153 /* Thirdly, draw sprites. */
1154 for (auto var : SetBitIterator(active_vars)) {
1155 if (vars[var].type != FaceVarType::Sprite) continue;
1156
1157 auto it = palettes.find(var);
1158 PaletteID pal = (it == std::end(palettes)) ? PAL_NONE : it->second;
1159 DrawSprite(vars[var].GetSprite(cmf), pal, x, y);
1160 }
1161}
1162
1166 NWidget(WWT_CLOSEBOX, COLOUR_GREY),
1167 NWidget(WWT_CAPTION, COLOUR_GREY, WID_SCMF_CAPTION), SetStringTip(STR_FACE_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
1168 NWidget(WWT_IMGBTN, COLOUR_GREY, WID_SCMF_TOGGLE_LARGE_SMALL), SetSpriteTip(SPR_LARGE_SMALL_WINDOW, STR_FACE_ADVANCED_TOOLTIP), SetAspect(WidgetDimensions::ASPECT_TOGGLE_SIZE),
1169 EndContainer(),
1171 NWidget(WWT_PANEL, COLOUR_GREY, WID_SCMF_SELECT_FACE),
1172 /* Left side */
1174 NWidget(WWT_EMPTY, INVALID_COLOUR, WID_SCMF_FACE), SetMinimalSize(92, 119), SetFill(1, 0),
1175 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_RANDOM_NEW_FACE), SetFill(1, 0), SetStringTip(STR_FACE_NEW_FACE_BUTTON, STR_FACE_NEW_FACE_TOOLTIP),
1176 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_TOGGLE_LARGE_SMALL_BUTTON), SetFill(1, 0), SetStringTip(STR_FACE_ADVANCED, STR_FACE_ADVANCED_TOOLTIP),
1177 NWidget(NWID_SELECTION, INVALID_COLOUR, WID_SCMF_SEL_LOADSAVE), // Load/number/save buttons under the portrait in the advanced view.
1179 NWidget(NWID_SPACER), SetFill(1, 1), SetResize(0, 1),
1180 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_LOAD), SetFill(1, 0), SetStringTip(STR_FACE_LOAD, STR_FACE_LOAD_TOOLTIP),
1181 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_FACECODE), SetFill(1, 0), SetStringTip(STR_FACE_FACECODE, STR_FACE_FACECODE_TOOLTIP),
1182 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_SAVE), SetFill(1, 0), SetStringTip(STR_FACE_SAVE, STR_FACE_SAVE_TOOLTIP),
1183 EndContainer(),
1184 EndContainer(),
1185 EndContainer(),
1186 EndContainer(),
1187 /* Right side */
1188 NWidget(NWID_SELECTION, INVALID_COLOUR, WID_SCMF_SEL_PARTS), // Advanced face parts setting.
1190 NWidget(WWT_MATRIX, COLOUR_GREY, WID_SCMF_STYLE), SetResize(1, 0), SetFill(1, 0), SetMatrixDataTip(1, 1),
1194 EndContainer(),
1195 EndContainer(),
1196 EndContainer(),
1197 EndContainer(),
1199 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_CANCEL), SetFill(1, 0), SetResize(1, 0), SetStringTip(STR_BUTTON_CANCEL, STR_FACE_CANCEL_TOOLTIP),
1200 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_ACCEPT), SetFill(1, 0), SetResize(1, 0), SetStringTip(STR_BUTTON_OK, STR_FACE_OK_TOOLTIP),
1201 NWidget(NWID_SELECTION, INVALID_COLOUR, WID_SCMF_SEL_RESIZE),
1202 NWidget(WWT_RESIZEBOX, COLOUR_GREY),
1203 EndContainer(),
1204 EndContainer(),
1205};
1206
1209{
1211 bool advanced = false;
1212 uint selected_var = UINT_MAX;
1213 uint click_state = 0;
1214 int line_height = 0;
1215
1216 std::vector<const FaceVar *> face_vars;
1217
1222 {
1223 FaceVars vars = GetCompanyManagerFaceVars(this->face.style);
1225
1226 uint64_t active_vars = GetActiveFaceVars(this->face, vars);
1227 /* Exclude active parts which have no string. */
1228 for (auto var : SetBitIterator(active_vars)) {
1229 if (vars[var].name == STR_NULL) ClrBit(active_vars, var);
1230 }
1231
1232 /* Rebuild the sorted list of face variable pointers. */
1233 this->face_vars.clear();
1234 for (auto var : SetBitIterator(active_vars)) {
1235 this->face_vars.emplace_back(&vars[var]);
1236 }
1237 std::ranges::sort(this->face_vars, std::less{}, &FaceVar::position);
1238
1239 this->GetScrollbar(WID_SCMF_PARTS_SCROLLBAR)->SetCount(std::size(this->face_vars));
1240 }
1241
1242public:
1244 {
1245 this->CreateNestedTree();
1246 this->SelectDisplayPlanes(this->advanced);
1247 this->FinishInitNested(parent->window_number);
1248 this->parent = parent;
1249 this->owner = this->window_number;
1250 this->face = Company::Get(this->window_number)->face;
1251
1252 this->UpdateData();
1253 }
1254
1255 void OnInit() override
1256 {
1258 }
1259
1265 {
1266 this->GetWidget<NWidgetStacked>(WID_SCMF_SEL_LOADSAVE)->SetDisplayedPlane(advanced ? 0 : SZSP_HORIZONTAL);
1267 this->GetWidget<NWidgetStacked>(WID_SCMF_SEL_PARTS)->SetDisplayedPlane(advanced ? 0 : SZSP_NONE);
1268 this->GetWidget<NWidgetStacked>(WID_SCMF_SEL_RESIZE)->SetDisplayedPlane(advanced ? 0 : SZSP_NONE);
1269
1270 NWidgetCore *wi = this->GetWidget<NWidgetCore>(WID_SCMF_TOGGLE_LARGE_SMALL_BUTTON);
1271 if (advanced) {
1272 wi->SetStringTip(STR_FACE_SIMPLE, STR_FACE_SIMPLE_TOOLTIP);
1273 } else {
1274 wi->SetStringTip(STR_FACE_ADVANCED, STR_FACE_ADVANCED_TOOLTIP);
1275 }
1276 }
1277
1278 static StringID GetLongestString(StringID a, StringID b)
1279 {
1280 return GetStringBoundingBox(a).width > GetStringBoundingBox(b).width ? a : b;
1281 }
1282
1283 static uint GetMaximumFacePartsWidth()
1284 {
1285 StringID yes_no = GetLongestString(STR_FACE_YES, STR_FACE_NO);
1286
1287 uint width = 0;
1288 for (uint style_index = 0; style_index != GetNumCompanyManagerFaceStyles(); ++style_index) {
1289 FaceVars vars = GetCompanyManagerFaceVars(style_index);
1290 for (const auto &info : vars) {
1291 if (info.name == STR_NULL) continue;
1292 if (info.type == FaceVarType::Toggle) {
1293 width = std::max(width, GetStringBoundingBox(GetString(STR_FACE_SETTING_TOGGLE, info.name, yes_no)).width);
1294 } else {
1295 uint64_t max_digits = GetParamMaxValue(info.valid_values);
1296 width = std::max(width, GetStringBoundingBox(GetString(STR_FACE_SETTING_NUMERIC, info.name, max_digits, max_digits)).width);
1297 }
1298 }
1299 }
1300
1301 /* Include width of button and spacing. */
1303 return width;
1304 }
1305
1306 void UpdateWidgetSize(WidgetID widget, Dimension &size, [[maybe_unused]] const Dimension &padding, [[maybe_unused]] Dimension &fill, [[maybe_unused]] Dimension &resize) override
1307 {
1308 switch (widget) {
1309 case WID_SCMF_FACE:
1310 size = maxdim(size, GetScaledSpriteSize(SPR_GRADIENT));
1311 break;
1312
1313 case WID_SCMF_STYLE:
1314 size.height = this->line_height;
1315 break;
1316
1317 case WID_SCMF_PARTS:
1318 fill.height = resize.height = this->line_height;
1319 size.width = GetMaximumFacePartsWidth();
1320 size.height = resize.height * 5;
1321 break;
1322 }
1323 }
1324
1325 void DrawWidget(const Rect &r, WidgetID widget) const override
1326 {
1327 switch (widget) {
1328 case WID_SCMF_FACE:
1329 DrawCompanyManagerFace(this->face, Company::Get(this->window_number)->colour, r);
1330 break;
1331
1332 case WID_SCMF_STYLE: {
1333 Rect ir = r.Shrink(WidgetDimensions::scaled.frametext, RectPadding::zero).WithHeight(this->line_height);
1334 bool rtl = _current_text_dir == TD_RTL;
1335
1338
1339 DrawArrowButtons(br.left, br.top, COLOUR_YELLOW, this->selected_var == UINT_MAX - 1 ? this->click_state : 0, true, true);
1340 DrawString(tr, GetString(STR_FACE_SETTING_NUMERIC, STR_FACE_STYLE, this->face.style + 1, GetNumCompanyManagerFaceStyles()), TC_WHITE);
1341 break;
1342 }
1343
1344 case WID_SCMF_PARTS: {
1345 Rect ir = r.Shrink(WidgetDimensions::scaled.frametext, RectPadding::zero).WithHeight(this->line_height);
1346 bool rtl = _current_text_dir == TD_RTL;
1347
1348 FaceVars vars = GetCompanyManagerFaceVars(this->face.style);
1349
1350 auto [first, last] = this->GetScrollbar(WID_SCMF_PARTS_SCROLLBAR)->GetVisibleRangeIterators(this->face_vars);
1351 for (auto it = first; it != last; ++it) {
1352 const uint8_t var = static_cast<uint8_t>(*it - vars.data());
1353 const FaceVar &facevar = **it;
1354
1355 Rect br = ir.CentreTo(ir.Width(), SETTING_BUTTON_HEIGHT).WithWidth(SETTING_BUTTON_WIDTH, rtl);
1356 Rect tr = ir.Shrink(RectPadding::zero, WidgetDimensions::scaled.matrix).CentreTo(ir.Width(), GetCharacterHeight(FS_NORMAL)).Indent(SETTING_BUTTON_WIDTH + WidgetDimensions::scaled.hsep_wide, rtl);
1357
1358 uint val = vars[var].GetBits(this->face);
1359 if (facevar.type == FaceVarType::Toggle) {
1360 DrawBoolButton(br.left, br.top, COLOUR_YELLOW, COLOUR_GREY, val == 1, true);
1361 DrawString(tr, GetString(STR_FACE_SETTING_TOGGLE, facevar.name, val == 1 ? STR_FACE_YES : STR_FACE_NO), TC_WHITE);
1362 } else {
1363 DrawArrowButtons(br.left, br.top, COLOUR_YELLOW, this->selected_var == var ? this->click_state : 0, true, true);
1364 DrawString(tr, GetString(STR_FACE_SETTING_NUMERIC, facevar.name, val + 1, facevar.valid_values), TC_WHITE);
1365 }
1366
1367 ir = ir.Translate(0, this->line_height);
1368 }
1369 break;
1370 }
1371 }
1372 }
1373
1374 void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override
1375 {
1376 switch (widget) {
1377 /* Toggle size, advanced/simple face selection */
1380 this->advanced = !this->advanced;
1381 this->SelectDisplayPlanes(this->advanced);
1382 this->ReInit();
1383 break;
1384
1385 /* OK button */
1386 case WID_SCMF_ACCEPT:
1387 Command<CMD_SET_COMPANY_MANAGER_FACE>::Post(this->face.bits, this->face.style);
1388 [[fallthrough]];
1389
1390 /* Cancel button */
1391 case WID_SCMF_CANCEL:
1392 this->Close();
1393 break;
1394
1395 /* Load button */
1396 case WID_SCMF_LOAD: {
1398 if (cmf.has_value()) this->face = *cmf;
1399 ShowErrorMessage(GetEncodedString(STR_FACE_LOAD_DONE), {}, WL_INFO);
1400 this->UpdateData();
1401 this->SetDirty();
1402 break;
1403 }
1404
1405 /* 'Company manager face number' button, view and/or set company manager face number */
1406 case WID_SCMF_FACECODE:
1407 ShowQueryString(FormatCompanyManagerFaceCode(this->face), STR_FACE_FACECODE_CAPTION, 128, this, CS_ALPHANUMERAL, {});
1408 break;
1409
1410 /* Save button */
1411 case WID_SCMF_SAVE:
1413 ShowErrorMessage(GetEncodedString(STR_FACE_SAVE_DONE), {}, WL_INFO);
1414 break;
1415
1416 /* Randomize face button */
1419 this->UpdateData();
1420 this->SetDirty();
1421 break;
1422
1423 case WID_SCMF_STYLE: {
1424 bool rtl = _current_text_dir == TD_RTL;
1425 Rect ir = this->GetWidget<NWidgetCore>(widget)->GetCurrentRect().Shrink(WidgetDimensions::scaled.frametext, RectPadding::zero);
1426 Rect br = ir.WithWidth(SETTING_BUTTON_WIDTH, rtl);
1427
1428 uint num_styles = GetNumCompanyManagerFaceStyles();
1429 this->selected_var = UINT_MAX - 1;
1430 if (IsInsideBS(pt.x, br.left, SETTING_BUTTON_WIDTH / 2)) {
1431 SetCompanyManagerFaceStyle(this->face, (this->face.style + num_styles - 1) % num_styles);
1432 this->click_state = 1;
1433 } else if (IsInsideBS(pt.x, br.left + SETTING_BUTTON_WIDTH / 2, SETTING_BUTTON_WIDTH / 2)) {
1434 SetCompanyManagerFaceStyle(this->face, (this->face.style + 1) % num_styles);
1435 this->click_state = 2;
1436 }
1437
1438 this->UpdateData();
1439 this->SetTimeout();
1440 this->SetDirty();
1441 break;
1442 }
1443
1444 case WID_SCMF_PARTS: {
1445 bool rtl = _current_text_dir == TD_RTL;
1446 Rect ir = this->GetWidget<NWidgetCore>(widget)->GetCurrentRect().Shrink(WidgetDimensions::scaled.frametext, RectPadding::zero);
1447 Rect br = ir.WithWidth(SETTING_BUTTON_WIDTH, rtl);
1448
1449 this->selected_var = UINT_MAX;
1450
1451 FaceVars vars = GetCompanyManagerFaceVars(this->face.style);
1452 auto it = this->GetScrollbar(WID_SCMF_PARTS_SCROLLBAR)->GetScrolledItemFromWidget(this->face_vars, pt.y, this, widget, 0, this->line_height);
1453 if (it == std::end(this->face_vars)) break;
1454
1455 this->selected_var = static_cast<uint8_t>(*it - vars.data());
1456 const auto &facevar = **it;
1457
1458 if (facevar.type == FaceVarType::Toggle) {
1459 if (!IsInsideBS(pt.x, br.left, SETTING_BUTTON_WIDTH)) break;
1460 facevar.ChangeBits(this->face, 1);
1461 this->UpdateData();
1462 } else {
1463 if (IsInsideBS(pt.x, br.left, SETTING_BUTTON_WIDTH / 2)) {
1464 facevar.ChangeBits(this->face, -1);
1465 this->click_state = 1;
1466 } else if (IsInsideBS(pt.x, br.left + SETTING_BUTTON_WIDTH / 2, SETTING_BUTTON_WIDTH / 2)) {
1467 facevar.ChangeBits(this->face, 1);
1468 this->click_state = 2;
1469 } else {
1470 break;
1471 }
1472 }
1473
1474 this->SetTimeout();
1475 this->SetDirty();
1476 break;
1477 }
1478 }
1479 }
1480
1481 void OnResize() override
1482 {
1483 if (auto *wid = this->GetWidget<NWidgetResizeBase>(WID_SCMF_PARTS); wid != nullptr) {
1484 /* Workaround for automatic widget sizing ignoring resize steps. Manually ensure parts matrix is a
1485 * multiple of its resize step. This trick only works here as the window itself is not resizable. */
1486 if (wid->UpdateVerticalSize((wid->current_y + wid->resize_y - 1) / wid->resize_y * wid->resize_y)) {
1487 this->ReInit();
1488 return;
1489 }
1490 }
1491
1493 }
1494
1495 void OnTimeout() override
1496 {
1497 this->click_state = 0;
1498 this->selected_var = UINT_MAX;
1499 this->SetDirty();
1500 }
1501
1502 void OnQueryTextFinished(std::optional<std::string> str) override
1503 {
1504 if (!str.has_value()) return;
1505 /* Parse new company manager face number */
1506 auto cmf = ParseCompanyManagerFaceCode(*str);
1507 if (cmf.has_value()) {
1508 this->face = *cmf;
1509 ShowErrorMessage(GetEncodedString(STR_FACE_FACECODE_SET), {}, WL_INFO);
1510 this->UpdateData();
1511 this->SetDirty();
1512 } else {
1513 ShowErrorMessage(GetEncodedString(STR_FACE_FACECODE_ERR), {}, WL_INFO);
1514 }
1515 }
1516};
1517
1520 WDP_AUTO, {}, 0, 0,
1524);
1525
1538
1539static constexpr NWidgetPart _nested_company_infrastructure_widgets[] = {
1541 NWidget(WWT_CLOSEBOX, COLOUR_GREY),
1542 NWidget(WWT_CAPTION, COLOUR_GREY, WID_CI_CAPTION),
1543 NWidget(WWT_SHADEBOX, COLOUR_GREY),
1544 NWidget(WWT_DEFSIZEBOX, COLOUR_GREY),
1545 NWidget(WWT_STICKYBOX, COLOUR_GREY),
1546 EndContainer(),
1548 NWidget(WWT_PANEL, COLOUR_GREY, WID_CI_LIST), SetFill(1, 1), SetResize(0, 1),
1550 EndContainer(),
1553 NWidget(WWT_RESIZEBOX, COLOUR_GREY),
1554 EndContainer(),
1555 EndContainer(),
1556};
1557
1562{
1563 enum class InfrastructureItemType : uint8_t {
1564 Header,
1565 Spacer,
1566 Value,
1567 Total,
1568 };
1569
1572 StringID label;
1573 uint count;
1574 Money cost;
1575 };
1576
1577 uint count_width = 0;
1578 uint cost_width = 0;
1579
1580 mutable std::vector<InfrastructureItem> list;
1581
1583 {
1584 this->InitNested(window_number);
1585 this->owner = this->window_number;
1586 }
1587
1588 void OnInit() override
1589 {
1590 this->UpdateInfrastructureList();
1591 }
1592
1593 void UpdateInfrastructureList()
1594 {
1595 this->list.clear();
1596
1597 const Company *c = Company::GetIfValid(this->window_number);
1598 if (c == nullptr) return;
1599
1600 Money total_monthly_cost = 0;
1601
1602 if (uint32_t rail_total = c->infrastructure.GetRailTotal(); rail_total > 0) {
1603 /* Rail types and signals. */
1604 this->list.emplace_back(InfrastructureItemType::Header, STR_COMPANY_INFRASTRUCTURE_VIEW_RAIL_SECT);
1605
1606 for (const RailType &rt : _sorted_railtypes) {
1607 if (c->infrastructure.rail[rt] == 0) continue;
1608 Money monthly_cost = RailMaintenanceCost(rt, c->infrastructure.rail[rt], rail_total);
1609 total_monthly_cost += monthly_cost;
1610 this->list.emplace_back(InfrastructureItemType::Value, GetRailTypeInfo(rt)->strings.name, c->infrastructure.rail[rt], monthly_cost);
1611 }
1612
1613 if (c->infrastructure.signal > 0) {
1615 total_monthly_cost += monthly_cost;
1616 this->list.emplace_back(InfrastructureItemType::Value, STR_COMPANY_INFRASTRUCTURE_VIEW_SIGNALS, c->infrastructure.signal, monthly_cost);
1617 }
1618 }
1619
1620 if (uint32_t road_total = c->infrastructure.GetRoadTotal(); road_total > 0) {
1621 /* Road types. */
1622 if (!this->list.empty()) this->list.emplace_back(InfrastructureItemType::Spacer);
1623 this->list.emplace_back(InfrastructureItemType::Header, STR_COMPANY_INFRASTRUCTURE_VIEW_ROAD_SECT);
1624
1625 for (const RoadType &rt : _sorted_roadtypes) {
1626 if (!RoadTypeIsRoad(rt)) continue;
1627 if (c->infrastructure.road[rt] == 0) continue;
1628 Money monthly_cost = RoadMaintenanceCost(rt, c->infrastructure.road[rt], road_total);
1629 total_monthly_cost += monthly_cost;
1630 this->list.emplace_back(InfrastructureItemType::Value, GetRoadTypeInfo(rt)->strings.name, c->infrastructure.road[rt], monthly_cost);
1631 }
1632 }
1633
1634 if (uint32_t tram_total = c->infrastructure.GetTramTotal(); tram_total > 0) {
1635 /* Tram types. */
1636 if (!this->list.empty()) this->list.emplace_back(InfrastructureItemType::Spacer);
1637 this->list.emplace_back(InfrastructureItemType::Header, STR_COMPANY_INFRASTRUCTURE_VIEW_TRAM_SECT);
1638
1639 for (const RoadType &rt : _sorted_roadtypes) {
1640 if (!RoadTypeIsTram(rt)) continue;
1641 if (c->infrastructure.road[rt] == 0) continue;
1642 Money monthly_cost = RoadMaintenanceCost(rt, c->infrastructure.road[rt], tram_total);
1643 total_monthly_cost += monthly_cost;
1644 this->list.emplace_back(InfrastructureItemType::Value, GetRoadTypeInfo(rt)->strings.name, c->infrastructure.road[rt], monthly_cost);
1645 }
1646 }
1647
1648 if (c->infrastructure.water > 0) {
1649 /* Canals, locks, and ship depots (docks are counted as stations). */
1650 if (!this->list.empty()) this->list.emplace_back(InfrastructureItemType::Spacer);
1651 this->list.emplace_back(InfrastructureItemType::Header, STR_COMPANY_INFRASTRUCTURE_VIEW_WATER_SECT);
1652
1654 total_monthly_cost += monthly_cost;
1655 this->list.emplace_back(InfrastructureItemType::Value, STR_COMPANY_INFRASTRUCTURE_VIEW_CANALS, c->infrastructure.water, monthly_cost);
1656 }
1657
1658 if (Money airport_cost = AirportMaintenanceCost(c->index); airport_cost > 0 || c->infrastructure.station > 0) {
1659 /* Stations and airports. */
1660 if (!this->list.empty()) this->list.emplace_back(InfrastructureItemType::Spacer);
1661 this->list.emplace_back(InfrastructureItemType::Header, STR_COMPANY_INFRASTRUCTURE_VIEW_STATION_SECT);
1662
1663 if (c->infrastructure.station > 0) {
1665 total_monthly_cost += monthly_cost;
1666 this->list.emplace_back(InfrastructureItemType::Value, STR_COMPANY_INFRASTRUCTURE_VIEW_STATIONS, c->infrastructure.station, monthly_cost);
1667 }
1668
1669 if (airport_cost > 0) {
1670 Money monthly_cost = airport_cost;
1671 total_monthly_cost += monthly_cost;
1672 this->list.emplace_back(InfrastructureItemType::Value, STR_COMPANY_INFRASTRUCTURE_VIEW_AIRPORTS, c->infrastructure.airport, monthly_cost);
1673 }
1674 }
1675
1677 /* Total monthly maintenance cost. */
1678 this->list.emplace_back(InfrastructureItemType::Spacer);
1679 this->list.emplace_back(InfrastructureItemType::Total, STR_NULL, 0, total_monthly_cost);
1680 }
1681
1682 /* Update scrollbar. */
1683 this->GetScrollbar(WID_CI_SCROLLBAR)->SetCount(std::size(list));
1684 }
1685
1686 std::string GetWidgetString(WidgetID widget, StringID stringid) const override
1687 {
1688 switch (widget) {
1689 case WID_CI_CAPTION:
1690 return GetString(STR_COMPANY_INFRASTRUCTURE_VIEW_CAPTION, this->window_number);
1691
1692 default:
1693 return this->Window::GetWidgetString(widget, stringid);
1694 }
1695 }
1696
1697 void FindWindowPlacementAndResize(int def_width, int def_height, bool allow_resize) override
1698 {
1699 if (def_height == 0) {
1700 /* Try to open the window with the exact required rows, but clamp to a reasonable limit. */
1701 int rows = (this->GetWidget<NWidgetBase>(WID_CI_LIST)->current_y - WidgetDimensions::scaled.framerect.Vertical()) / GetCharacterHeight(FS_NORMAL);
1702 int delta = std::min(20, static_cast<int>(std::size(this->list))) - rows;
1703 def_height = this->height + delta * GetCharacterHeight(FS_NORMAL);
1704 }
1705
1706 this->Window::FindWindowPlacementAndResize(def_width, def_height, allow_resize);
1707 }
1708
1709 void UpdateWidgetSize(WidgetID widget, Dimension &size, [[maybe_unused]] const Dimension &padding, [[maybe_unused]] Dimension &fill, [[maybe_unused]] Dimension &resize) override
1710 {
1711 if (widget != WID_CI_LIST) return;
1712
1713 uint max_count = 1000; // Some random number to reserve minimum space.
1714 Money max_cost = 1000000; // Some random number to reserve minimum space.
1715
1716 /* List of headers that might be used. */
1717 static constexpr StringID header_strings[] = {
1718 STR_COMPANY_INFRASTRUCTURE_VIEW_RAIL_SECT,
1719 STR_COMPANY_INFRASTRUCTURE_VIEW_ROAD_SECT,
1720 STR_COMPANY_INFRASTRUCTURE_VIEW_TRAM_SECT,
1721 STR_COMPANY_INFRASTRUCTURE_VIEW_WATER_SECT,
1722 STR_COMPANY_INFRASTRUCTURE_VIEW_STATION_SECT,
1723 };
1724 /* List of labels that might be used. */
1725 static constexpr StringID label_strings[] = {
1726 STR_COMPANY_INFRASTRUCTURE_VIEW_SIGNALS,
1727 STR_COMPANY_INFRASTRUCTURE_VIEW_CANALS,
1728 STR_COMPANY_INFRASTRUCTURE_VIEW_STATIONS,
1729 STR_COMPANY_INFRASTRUCTURE_VIEW_AIRPORTS,
1730 };
1731
1732 uint max_header_width = GetStringListWidth(header_strings);
1733 uint max_label_width = GetStringListWidth(label_strings);
1734
1735 /* Include width of all possible rail and road types. */
1736 for (const RailType &rt : _sorted_railtypes) max_label_width = std::max(max_label_width, GetStringBoundingBox(GetRailTypeInfo(rt)->strings.name).width);
1737 for (const RoadType &rt : _sorted_roadtypes) max_label_width = std::max(max_label_width, GetStringBoundingBox(GetRoadTypeInfo(rt)->strings.name).width);
1738
1739 for (const InfrastructureItem &entry : this->list) {
1740 max_count = std::max(max_count, entry.count);
1741 max_cost = std::max(max_cost, entry.cost * 12);
1742 }
1743
1744 max_label_width += WidgetDimensions::scaled.hsep_indent;
1745 this->count_width = GetStringBoundingBox(GetString(STR_JUST_COMMA, max_count)).width;
1746
1748 this->cost_width = GetStringBoundingBox(GetString(TimerGameEconomy::UsingWallclockUnits() ? STR_COMPANY_INFRASTRUCTURE_VIEW_TOTAL_PERIOD : STR_COMPANY_INFRASTRUCTURE_VIEW_TOTAL_YEAR, max_cost)).width;
1749 } else {
1750 this->cost_width = 0;
1751 }
1752
1753 size.width = max_label_width + WidgetDimensions::scaled.hsep_wide + this->count_width + WidgetDimensions::scaled.hsep_wide + this->cost_width;
1754 size.width = std::max(size.width, max_header_width) + WidgetDimensions::scaled.framerect.Horizontal();
1755
1756 fill.height = resize.height = GetCharacterHeight(FS_NORMAL);
1757 }
1758
1759 void DrawWidget(const Rect &r, WidgetID widget) const override
1760 {
1761 if (widget != WID_CI_LIST) return;
1762
1763 bool rtl = _current_text_dir == TD_RTL; // We allocate space from end-to-start so the label fills.
1764 int line_height = GetCharacterHeight(FS_NORMAL);
1765
1766 Rect ir = r.Shrink(WidgetDimensions::scaled.framerect);
1767 Rect countr = ir.WithWidth(this->count_width, !rtl);
1768 Rect costr = ir.Indent(this->count_width + WidgetDimensions::scaled.hsep_wide, !rtl).WithWidth(this->cost_width, !rtl);
1769 Rect labelr = ir.Indent(this->count_width + WidgetDimensions::scaled.hsep_wide + this->cost_width + WidgetDimensions::scaled.hsep_wide, !rtl);
1770
1771 auto [first, last] = this->GetScrollbar(WID_CI_SCROLLBAR)->GetVisibleRangeIterators(this->list);
1772 for (auto it = first; it != last; ++it) {
1773 switch (it->type) {
1775 /* Header is allowed to fill the window's width. */
1776 DrawString(ir.left, ir.right, labelr.top, GetString(it->label), TC_ORANGE);
1777 break;
1778
1780 break;
1781
1783 /* Draw line in the spacer above the total. */
1785 DrawString(costr, GetString(TimerGameEconomy::UsingWallclockUnits() ? STR_COMPANY_INFRASTRUCTURE_VIEW_TOTAL_PERIOD : STR_COMPANY_INFRASTRUCTURE_VIEW_TOTAL_YEAR, it->cost * 12), TC_BLACK, SA_RIGHT | SA_FORCE);
1786 break;
1787
1789 DrawString(labelr.Indent(WidgetDimensions::scaled.hsep_indent, rtl), GetString(it->label), TC_WHITE);
1790 DrawString(countr, GetString(STR_JUST_COMMA, it->count), TC_WHITE, SA_RIGHT | SA_FORCE);
1792 DrawString(costr, GetString(TimerGameEconomy::UsingWallclockUnits() ? STR_COMPANY_INFRASTRUCTURE_VIEW_TOTAL_PERIOD : STR_COMPANY_INFRASTRUCTURE_VIEW_TOTAL_YEAR, it->cost * 12), TC_BLACK, SA_RIGHT | SA_FORCE);
1793 }
1794 break;
1795 }
1796
1797 labelr.top += line_height;
1798 countr.top += line_height;
1799 costr.top += line_height;
1800 }
1801 }
1802
1803 const IntervalTimer<TimerWindow> redraw_interval = {std::chrono::seconds(1), [this](auto) {
1804 this->UpdateInfrastructureList();
1806 }};
1807
1808 void OnResize() override
1809 {
1811 }
1812
1818 void OnInvalidateData([[maybe_unused]] int data = 0, [[maybe_unused]] bool gui_scope = true) override
1819 {
1820 if (!gui_scope) return;
1821
1822 this->ReInit();
1823 }
1824};
1825
1826static WindowDesc _company_infrastructure_desc(
1827 WDP_AUTO, "company_infrastructure", 0, 0,
1829 {},
1830 _nested_company_infrastructure_widgets
1831);
1832
1838{
1839 if (!Company::IsValidID(company)) return;
1840 AllocateWindowDescFront<CompanyInfrastructureWindow>(_company_infrastructure_desc, company);
1841}
1842
1843static constexpr NWidgetPart _nested_company_widgets[] = {
1845 NWidget(WWT_CLOSEBOX, COLOUR_GREY),
1846 NWidget(WWT_CAPTION, COLOUR_GREY, WID_C_CAPTION),
1847 NWidget(WWT_SHADEBOX, COLOUR_GREY),
1848 NWidget(WWT_STICKYBOX, COLOUR_GREY),
1849 EndContainer(),
1850 NWidget(WWT_PANEL, COLOUR_GREY),
1853 NWidget(WWT_EMPTY, INVALID_COLOUR, WID_C_FACE), SetMinimalSize(92, 119), SetFill(1, 0),
1854 NWidget(WWT_EMPTY, INVALID_COLOUR, WID_C_FACE_TITLE), SetFill(1, 1), SetMinimalTextLines(2, 0),
1855 EndContainer(),
1859 NWidget(WWT_TEXT, INVALID_COLOUR, WID_C_DESC_INAUGURATION), SetFill(1, 0),
1861 NWidget(WWT_LABEL, INVALID_COLOUR, WID_C_DESC_COLOUR_SCHEME), SetStringTip(STR_COMPANY_VIEW_COLOUR_SCHEME_TITLE),
1863 EndContainer(),
1865 NWidget(WWT_TEXT, INVALID_COLOUR, WID_C_DESC_VEHICLE), SetStringTip(STR_COMPANY_VIEW_VEHICLES_TITLE), SetAlignment(SA_LEFT | SA_TOP),
1867 EndContainer(),
1868 EndContainer(),
1871 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_C_VIEW_HQ), SetStringTip(STR_COMPANY_VIEW_VIEW_HQ_BUTTON, STR_COMPANY_VIEW_VIEW_HQ_TOOLTIP),
1872 NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_C_BUILD_HQ), SetStringTip(STR_COMPANY_VIEW_BUILD_HQ_BUTTON, STR_COMPANY_VIEW_BUILD_HQ_TOOLTIP),
1873 EndContainer(),
1875 NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_C_RELOCATE_HQ), SetStringTip(STR_COMPANY_VIEW_RELOCATE_HQ, STR_COMPANY_VIEW_RELOCATE_HQ_TOOLTIP),
1877 EndContainer(),
1878 EndContainer(),
1879 EndContainer(),
1880
1881 NWidget(WWT_TEXT, INVALID_COLOUR, WID_C_DESC_COMPANY_VALUE), SetFill(1, 0),
1882
1884 NWidget(WWT_TEXT, INVALID_COLOUR, WID_C_DESC_INFRASTRUCTURE), SetStringTip(STR_COMPANY_VIEW_INFRASTRUCTURE), SetAlignment(SA_LEFT | SA_TOP),
1887 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_C_VIEW_INFRASTRUCTURE), SetStringTip(STR_COMPANY_VIEW_INFRASTRUCTURE_BUTTON, STR_COMPANY_VIEW_INFRASTRUCTURE_TOOLTIP),
1888 EndContainer(),
1889 EndContainer(),
1890
1891 /* Multi player buttons. */
1895 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_C_HOSTILE_TAKEOVER), SetStringTip(STR_COMPANY_VIEW_HOSTILE_TAKEOVER_BUTTON, STR_COMPANY_VIEW_HOSTILE_TAKEOVER_TOOLTIP),
1896 EndContainer(),
1898 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_C_GIVE_MONEY), SetStringTip(STR_COMPANY_VIEW_GIVE_MONEY_BUTTON, STR_COMPANY_VIEW_GIVE_MONEY_TOOLTIP),
1899 EndContainer(),
1901 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_C_COMPANY_JOIN), SetStringTip(STR_COMPANY_VIEW_JOIN, STR_COMPANY_VIEW_JOIN_TOOLTIP),
1902 EndContainer(),
1903 EndContainer(),
1904 EndContainer(),
1905 EndContainer(),
1906 EndContainer(),
1907 EndContainer(),
1908 /* Button bars at the bottom. */
1911 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_C_NEW_FACE), SetFill(1, 0), SetStringTip(STR_COMPANY_VIEW_NEW_FACE_BUTTON, STR_COMPANY_VIEW_NEW_FACE_TOOLTIP),
1912 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_C_COLOUR_SCHEME), SetFill(1, 0), SetStringTip(STR_COMPANY_VIEW_COLOUR_SCHEME_BUTTON, STR_COMPANY_VIEW_COLOUR_SCHEME_TOOLTIP),
1913 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_C_PRESIDENT_NAME), SetFill(1, 0), SetStringTip(STR_COMPANY_VIEW_PRESIDENT_NAME_BUTTON, STR_COMPANY_VIEW_PRESIDENT_NAME_TOOLTIP),
1914 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_C_COMPANY_NAME), SetFill(1, 0), SetStringTip(STR_COMPANY_VIEW_COMPANY_NAME_BUTTON, STR_COMPANY_VIEW_COMPANY_NAME_TOOLTIP),
1915 EndContainer(),
1916 EndContainer(),
1917};
1918
1921 STR_COMPANY_VIEW_TRAINS, STR_COMPANY_VIEW_ROAD_VEHICLES, STR_COMPANY_VIEW_SHIPS, STR_COMPANY_VIEW_AIRCRAFT
1922};
1923
1928{
1929 CompanyWidgets query_widget{};
1930
1932 enum CompanyWindowPlanes : uint8_t {
1933 /* Display planes of the #WID_C_SELECT_VIEW_BUILD_HQ selection widget. */
1936
1937 /* Display planes of the #WID_C_SELECT_RELOCATE selection widget. */
1940 };
1941
1943 {
1944 this->InitNested(window_number);
1945 this->owner = this->window_number;
1946 this->OnInvalidateData();
1947 }
1948
1949 void OnPaint() override
1950 {
1951 const Company *c = Company::Get(this->window_number);
1952 bool local = this->window_number == _local_company;
1953
1954 if (!this->IsShaded()) {
1955 bool reinit = false;
1956
1957 /* Button bar selection. */
1958 reinit |= this->GetWidget<NWidgetStacked>(WID_C_SELECT_BUTTONS)->SetDisplayedPlane(local ? 0 : SZSP_NONE);
1959
1960 /* Build HQ button handling. */
1961 reinit |= this->GetWidget<NWidgetStacked>(WID_C_SELECT_VIEW_BUILD_HQ)->SetDisplayedPlane((local && c->location_of_HQ == INVALID_TILE) ? CWP_VB_BUILD : CWP_VB_VIEW);
1962
1964
1965 /* Enable/disable 'Relocate HQ' button. */
1966 reinit |= this->GetWidget<NWidgetStacked>(WID_C_SELECT_RELOCATE)->SetDisplayedPlane((!local || c->location_of_HQ == INVALID_TILE) ? CWP_RELOCATE_HIDE : CWP_RELOCATE_SHOW);
1967 /* Enable/disable 'Give money' button. */
1968 reinit |= this->GetWidget<NWidgetStacked>(WID_C_SELECT_GIVE_MONEY)->SetDisplayedPlane((local || _local_company == COMPANY_SPECTATOR || !_settings_game.economy.give_money) ? SZSP_NONE : 0);
1969 /* Enable/disable 'Hostile Takeover' button. */
1970 reinit |= this->GetWidget<NWidgetStacked>(WID_C_SELECT_HOSTILE_TAKEOVER)->SetDisplayedPlane((local || _local_company == COMPANY_SPECTATOR || !c->is_ai || _networking) ? SZSP_NONE : 0);
1971
1972 /* Multiplayer buttons. */
1973 reinit |= this->GetWidget<NWidgetStacked>(WID_C_SELECT_MULTIPLAYER)->SetDisplayedPlane((!_networking || !NetworkCanJoinCompany(c->index) || _local_company == c->index) ? (int)SZSP_NONE : 0);
1974
1976
1977 if (reinit) {
1978 this->ReInit();
1979 return;
1980 }
1981 }
1982
1983 this->DrawWidgets();
1984 }
1985
1986 void UpdateWidgetSize(WidgetID widget, Dimension &size, [[maybe_unused]] const Dimension &padding, [[maybe_unused]] Dimension &fill, [[maybe_unused]] Dimension &resize) override
1987 {
1988 switch (widget) {
1989 case WID_C_FACE:
1990 size = maxdim(size, GetScaledSpriteSize(SPR_GRADIENT));
1991 break;
1992
1994 Point offset;
1995 Dimension d = GetSpriteSize(SPR_VEH_BUS_SW_VIEW, &offset);
1996 d.width -= offset.x;
1997 d.height -= offset.y;
1998 size = maxdim(size, d);
1999 break;
2000 }
2001
2003 /* INT64_MAX is arguably the maximum company value */
2004 size.width = GetStringBoundingBox(GetString(STR_COMPANY_VIEW_COMPANY_VALUE, INT64_MAX)).width;
2005 break;
2006
2008 uint64_t max_value = GetParamMaxValue(5000); // Maximum number of vehicles
2009 for (const auto &count_string : _company_view_vehicle_count_strings) {
2010 size.width = std::max(size.width, GetStringBoundingBox(GetString(count_string, max_value)).width + padding.width);
2011 }
2012 break;
2013 }
2014
2016 uint64_t max_value = GetParamMaxValue(UINT_MAX);
2017 size.width = GetStringBoundingBox(GetString(STR_COMPANY_VIEW_INFRASTRUCTURE_RAIL, max_value)).width;
2018 size.width = std::max(size.width, GetStringBoundingBox(GetString(STR_COMPANY_VIEW_INFRASTRUCTURE_ROAD, max_value)).width);
2019 size.width = std::max(size.width, GetStringBoundingBox(GetString(STR_COMPANY_VIEW_INFRASTRUCTURE_WATER, max_value)).width);
2020 size.width = std::max(size.width, GetStringBoundingBox(GetString(STR_COMPANY_VIEW_INFRASTRUCTURE_STATION, max_value)).width);
2021 size.width = std::max(size.width, GetStringBoundingBox(GetString(STR_COMPANY_VIEW_INFRASTRUCTURE_AIRPORT, max_value)).width);
2022 size.width = std::max(size.width, GetStringBoundingBox(GetString(STR_COMPANY_VIEW_INFRASTRUCTURE_NONE, max_value)).width);
2023 size.width += padding.width;
2024 break;
2025 }
2026
2027 case WID_C_VIEW_HQ:
2028 case WID_C_BUILD_HQ:
2029 case WID_C_RELOCATE_HQ:
2031 case WID_C_GIVE_MONEY:
2033 case WID_C_COMPANY_JOIN:
2034 size.width = GetStringBoundingBox(STR_COMPANY_VIEW_VIEW_HQ_BUTTON).width;
2035 size.width = std::max(size.width, GetStringBoundingBox(STR_COMPANY_VIEW_BUILD_HQ_BUTTON).width);
2036 size.width = std::max(size.width, GetStringBoundingBox(STR_COMPANY_VIEW_RELOCATE_HQ).width);
2037 size.width = std::max(size.width, GetStringBoundingBox(STR_COMPANY_VIEW_INFRASTRUCTURE_BUTTON).width);
2038 size.width = std::max(size.width, GetStringBoundingBox(STR_COMPANY_VIEW_GIVE_MONEY_BUTTON).width);
2039 size.width = std::max(size.width, GetStringBoundingBox(STR_COMPANY_VIEW_HOSTILE_TAKEOVER_BUTTON).width);
2040 size.width = std::max(size.width, GetStringBoundingBox(STR_COMPANY_VIEW_JOIN).width);
2041 size.width += padding.width;
2042 break;
2043 }
2044 }
2045
2046 void DrawVehicleCountsWidget(const Rect &r, const Company *c) const
2047 {
2049
2050 int y = r.top;
2051 for (VehicleType type = VEH_BEGIN; type < VEH_COMPANY_END; type++) {
2052 uint amount = c->group_all[type].num_vehicle;
2053 if (amount != 0) {
2054 DrawString(r.left, r.right, y, GetString(_company_view_vehicle_count_strings[type], amount));
2056 }
2057 }
2058
2059 if (y == r.top) {
2060 /* No String was emitted before, so there must be no vehicles at all. */
2061 DrawString(r.left, r.right, y, STR_COMPANY_VIEW_VEHICLES_NONE);
2062 }
2063 }
2064
2065 void DrawInfrastructureCountsWidget(const Rect &r, const Company *c) const
2066 {
2067 int y = r.top;
2068
2069 uint rail_pieces = c->infrastructure.signal + c->infrastructure.GetRailTotal();
2070 if (rail_pieces != 0) {
2071 DrawString(r.left, r.right, y, GetString(STR_COMPANY_VIEW_INFRASTRUCTURE_RAIL, rail_pieces));
2073 }
2074
2075 /* GetRoadTotal() skips tram pieces, but we actually want road and tram here. */
2076 uint road_pieces = std::accumulate(std::begin(c->infrastructure.road), std::end(c->infrastructure.road), 0U);
2077 if (road_pieces != 0) {
2078 DrawString(r.left, r.right, y, GetString(STR_COMPANY_VIEW_INFRASTRUCTURE_ROAD, road_pieces));
2080 }
2081
2082 if (c->infrastructure.water != 0) {
2083 DrawString(r.left, r.right, y, GetString(STR_COMPANY_VIEW_INFRASTRUCTURE_WATER, c->infrastructure.water));
2085 }
2086
2087 if (c->infrastructure.station != 0) {
2088 DrawString(r.left, r.right, y, GetString(STR_COMPANY_VIEW_INFRASTRUCTURE_STATION, c->infrastructure.station));
2090 }
2091
2092 if (c->infrastructure.airport != 0) {
2093 DrawString(r.left, r.right, y, GetString(STR_COMPANY_VIEW_INFRASTRUCTURE_AIRPORT, c->infrastructure.airport));
2095 }
2096
2097 if (y == r.top) {
2098 /* No String was emitted before, so there must be no infrastructure at all. */
2099 DrawString(r.left, r.right, y, STR_COMPANY_VIEW_INFRASTRUCTURE_NONE);
2100 }
2101 }
2102
2103 void DrawWidget(const Rect &r, WidgetID widget) const override
2104 {
2105 const Company *c = Company::Get(this->window_number);
2106 switch (widget) {
2107 case WID_C_FACE:
2109 break;
2110
2111 case WID_C_FACE_TITLE:
2112 DrawStringMultiLine(r, GetString(STR_COMPANY_VIEW_PRESIDENT_MANAGER_TITLE, c->index), TC_FROMSTRING, SA_HOR_CENTER);
2113 break;
2114
2116 Point offset;
2117 Dimension d = GetSpriteSize(SPR_VEH_BUS_SW_VIEW, &offset);
2118 d.height -= offset.y;
2119 DrawSprite(SPR_VEH_BUS_SW_VIEW, GetCompanyPalette(c->index), r.left - offset.x, CentreBounds(r.top, r.bottom, d.height) - offset.y);
2120 break;
2121 }
2122
2124 DrawVehicleCountsWidget(r, c);
2125 break;
2126
2128 DrawInfrastructureCountsWidget(r, c);
2129 break;
2130 }
2131 }
2132
2133 std::string GetWidgetString(WidgetID widget, StringID stringid) const override
2134 {
2135 switch (widget) {
2136 case WID_C_CAPTION:
2137 return GetString(STR_COMPANY_VIEW_CAPTION, this->window_number, this->window_number);
2138
2140 const Company &c = *Company::Get(this->window_number);
2142 return GetString(STR_COMPANY_VIEW_INAUGURATED_TITLE_WALLCLOCK, c.inaugurated_year_calendar, c.inaugurated_year);
2143 }
2144 return GetString(STR_COMPANY_VIEW_INAUGURATED_TITLE, c.inaugurated_year);
2145 }
2146
2148 return GetString(STR_COMPANY_VIEW_COMPANY_VALUE, CalculateCompanyValue(Company::Get(this->window_number)));
2149
2150 default:
2151 return this->Window::GetWidgetString(widget, stringid);
2152 }
2153 }
2154
2155 void OnResize() override
2156 {
2157 NWidgetResizeBase *wid = this->GetWidget<NWidgetResizeBase>(WID_C_FACE_TITLE);
2158 int y = GetStringHeight(GetString(STR_COMPANY_VIEW_PRESIDENT_MANAGER_TITLE, this->owner), wid->current_x);
2159 if (wid->UpdateVerticalSize(y)) this->ReInit(0, 0);
2160 }
2161
2162 void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override
2163 {
2164 switch (widget) {
2165 case WID_C_NEW_FACE: DoSelectCompanyManagerFace(this); break;
2166
2168 ShowCompanyLiveryWindow(this->window_number, GroupID::Invalid());
2169 break;
2170
2172 this->query_widget = WID_C_PRESIDENT_NAME;
2173 ShowQueryString(GetString(STR_PRESIDENT_NAME, this->window_number), STR_COMPANY_VIEW_PRESIDENT_S_NAME_QUERY_CAPTION, MAX_LENGTH_PRESIDENT_NAME_CHARS, this, CS_ALPHANUMERAL, {QueryStringFlag::EnableDefault, QueryStringFlag::LengthIsInChars});
2174 break;
2175
2176 case WID_C_COMPANY_NAME:
2177 this->query_widget = WID_C_COMPANY_NAME;
2178 ShowQueryString(GetString(STR_COMPANY_NAME, this->window_number), STR_COMPANY_VIEW_COMPANY_NAME_QUERY_CAPTION, MAX_LENGTH_COMPANY_NAME_CHARS, this, CS_ALPHANUMERAL, {QueryStringFlag::EnableDefault, QueryStringFlag::LengthIsInChars});
2179 break;
2180
2181 case WID_C_VIEW_HQ: {
2182 TileIndex tile = Company::Get(this->window_number)->location_of_HQ;
2183 if (_ctrl_pressed) {
2185 } else {
2187 }
2188 break;
2189 }
2190
2191 case WID_C_BUILD_HQ:
2192 if (this->window_number != _local_company) return;
2193 if (this->IsWidgetLowered(WID_C_BUILD_HQ)) {
2195 this->RaiseButtons();
2196 break;
2197 }
2198 SetObjectToPlaceWnd(SPR_CURSOR_HQ, PAL_NONE, HT_RECT, this);
2199 SetTileSelectSize(2, 2);
2202 break;
2203
2204 case WID_C_RELOCATE_HQ:
2207 this->RaiseButtons();
2208 break;
2209 }
2210 SetObjectToPlaceWnd(SPR_CURSOR_HQ, PAL_NONE, HT_RECT, this);
2211 SetTileSelectSize(2, 2);
2214 break;
2215
2218 break;
2219
2220 case WID_C_GIVE_MONEY:
2221 this->query_widget = WID_C_GIVE_MONEY;
2222 ShowQueryString({}, STR_COMPANY_VIEW_GIVE_MONEY_QUERY_CAPTION, 30, this, CS_NUMERAL, {});
2223 break;
2224
2227 break;
2228
2229 case WID_C_COMPANY_JOIN: {
2230 this->query_widget = WID_C_COMPANY_JOIN;
2231 CompanyID company = this->window_number;
2232 if (_network_server) {
2235 } else {
2236 /* just send the join command */
2237 NetworkClientRequestMove(company);
2238 }
2239 break;
2240 }
2241 }
2242 }
2243
2245 const IntervalTimer<TimerWindow> redraw_interval = {std::chrono::seconds(3), [this](auto) {
2246 this->SetDirty();
2247 }};
2248
2249 void OnPlaceObject([[maybe_unused]] Point pt, TileIndex tile) override
2250 {
2251 if (Command<CMD_BUILD_OBJECT>::Post(STR_ERROR_CAN_T_BUILD_COMPANY_HEADQUARTERS, tile, OBJECT_HQ, 0) && !_shift_pressed) {
2253 this->RaiseButtons();
2254 }
2255 }
2256
2257 void OnPlaceObjectAbort() override
2258 {
2259 this->RaiseButtons();
2260 }
2261
2262 void OnQueryTextFinished(std::optional<std::string> str) override
2263 {
2264 if (!str.has_value()) return;
2265
2266 switch (this->query_widget) {
2267 default: NOT_REACHED();
2268
2269 case WID_C_GIVE_MONEY: {
2270 auto value = ParseInteger<uint64_t>(*str, 10, true);
2271 if (!value.has_value()) return;
2272 Money money = *value / GetCurrency().rate;
2273 Command<CMD_GIVE_MONEY>::Post(STR_ERROR_CAN_T_GIVE_MONEY, money, this->window_number);
2274 break;
2275 }
2276
2278 Command<CMD_RENAME_PRESIDENT>::Post(STR_ERROR_CAN_T_CHANGE_PRESIDENT, *str);
2279 break;
2280
2281 case WID_C_COMPANY_NAME:
2282 Command<CMD_RENAME_COMPANY>::Post(STR_ERROR_CAN_T_CHANGE_COMPANY_NAME, *str);
2283 break;
2284 }
2285 }
2286
2287 void OnInvalidateData([[maybe_unused]] int data = 0, [[maybe_unused]] bool gui_scope = true) override
2288 {
2289 if (gui_scope && data == 1) {
2290 /* Manually call OnResize to adjust minimum height of president name widget. */
2291 OnResize();
2292 }
2293 }
2294};
2295
2296static WindowDesc _company_desc(
2297 WDP_AUTO, "company", 0, 0,
2299 {},
2300 _nested_company_widgets
2301);
2302
2308{
2309 if (!Company::IsValidID(company)) return;
2310
2311 AllocateWindowDescFront<CompanyWindow>(_company_desc, company);
2312}
2313
2323
2326 {
2327 this->InitNested(window_number);
2328
2329 const Company *c = Company::Get(this->window_number);
2330 this->company_value = hostile_takeover ? CalculateHostileTakeoverValue(c) : c->bankrupt_value;
2331 }
2332
2333 void UpdateWidgetSize(WidgetID widget, Dimension &size, [[maybe_unused]] const Dimension &padding, [[maybe_unused]] Dimension &fill, [[maybe_unused]] Dimension &resize) override
2334 {
2335 switch (widget) {
2336 case WID_BC_FACE:
2337 size = GetScaledSpriteSize(SPR_GRADIENT);
2338 break;
2339
2340 case WID_BC_QUESTION:
2341 const Company *c = Company::Get(this->window_number);
2342 size.height = GetStringHeight(GetString(this->hostile_takeover ? STR_BUY_COMPANY_HOSTILE_TAKEOVER : STR_BUY_COMPANY_MESSAGE, c->index, this->company_value), size.width);
2343 break;
2344 }
2345 }
2346
2347 std::string GetWidgetString(WidgetID widget, StringID stringid) const override
2348 {
2349 switch (widget) {
2350 case WID_BC_CAPTION:
2351 return GetString(STR_ERROR_MESSAGE_CAPTION_OTHER_COMPANY, Company::Get(this->window_number)->index);
2352
2353 default:
2354 return this->Window::GetWidgetString(widget, stringid);
2355 }
2356 }
2357
2358 void DrawWidget(const Rect &r, WidgetID widget) const override
2359 {
2360 switch (widget) {
2361 case WID_BC_FACE: {
2362 const Company *c = Company::Get(this->window_number);
2364 break;
2365 }
2366
2367 case WID_BC_QUESTION: {
2368 const Company *c = Company::Get(this->window_number);
2369 DrawStringMultiLine(r, GetString(this->hostile_takeover ? STR_BUY_COMPANY_HOSTILE_TAKEOVER : STR_BUY_COMPANY_MESSAGE, c->index, this->company_value), TC_FROMSTRING, SA_CENTER);
2370 break;
2371 }
2372 }
2373 }
2374
2375 void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override
2376 {
2377 switch (widget) {
2378 case WID_BC_NO:
2379 this->Close();
2380 break;
2381
2382 case WID_BC_YES:
2383 Command<CMD_BUY_COMPANY>::Post(STR_ERROR_CAN_T_BUY_COMPANY, this->window_number, this->hostile_takeover);
2384 break;
2385 }
2386 }
2387
2391 const IntervalTimer<TimerWindow> rescale_interval = {std::chrono::seconds(3), [this](auto) {
2392 /* Value can't change when in bankruptcy. */
2393 if (!this->hostile_takeover) return;
2394
2395 const Company *c = Company::Get(this->window_number);
2396 auto new_value = CalculateHostileTakeoverValue(c);
2397 if (new_value != this->company_value) {
2398 this->company_value = new_value;
2399 this->ReInit();
2400 }
2401 }};
2402
2403private:
2404 bool hostile_takeover = false;
2406};
2407
2408static constexpr NWidgetPart _nested_buy_company_widgets[] = {
2410 NWidget(WWT_CLOSEBOX, COLOUR_LIGHT_BLUE),
2411 NWidget(WWT_CAPTION, COLOUR_LIGHT_BLUE, WID_BC_CAPTION),
2412 EndContainer(),
2413 NWidget(WWT_PANEL, COLOUR_LIGHT_BLUE),
2416 NWidget(WWT_EMPTY, INVALID_COLOUR, WID_BC_FACE), SetFill(0, 1),
2417 NWidget(WWT_EMPTY, INVALID_COLOUR, WID_BC_QUESTION), SetMinimalSize(240, 0), SetFill(1, 1),
2418 EndContainer(),
2420 NWidget(WWT_TEXTBTN, COLOUR_LIGHT_BLUE, WID_BC_NO), SetMinimalSize(60, 12), SetStringTip(STR_QUIT_NO), SetFill(1, 0),
2421 NWidget(WWT_TEXTBTN, COLOUR_LIGHT_BLUE, WID_BC_YES), SetMinimalSize(60, 12), SetStringTip(STR_QUIT_YES), SetFill(1, 0),
2422 EndContainer(),
2423 EndContainer(),
2424 EndContainer(),
2425};
2426
2427static WindowDesc _buy_company_desc(
2428 WDP_AUTO, {}, 0, 0,
2431 _nested_buy_company_widgets
2432);
2433
2439void ShowBuyCompanyDialog(CompanyID company, bool hostile_takeover)
2440{
2441 auto window = BringWindowToFrontById(WC_BUY_COMPANY, company);
2442 if (window == nullptr) {
2443 new BuyCompanyWindow(_buy_company_desc, company, hostile_takeover);
2444 }
2445}
debug_inline constexpr bool HasBit(const T x, const uint8_t y)
Checks if a bit in a value is set.
constexpr T SetBit(T &x, const uint8_t y)
Set a bit in a variable.
constexpr T ToggleBit(T &x, const uint8_t y)
Toggles a bit in a variable.
constexpr T ClrBit(T &x, const uint8_t y)
Clears a bit in a variable.
Drop down icon component.
Colour selection list item, with icon and string components.
bool masked
Masked and unselectable item.
void RebuildDone()
Notify the sortlist that the rebuild is done.
bool NeedRebuild() const
Check if a rebuild is needed.
void ForceRebuild()
Force that a rebuild is needed.
An interval timer will fire every interval, and will continue to fire until it is deleted.
Definition timer.h:76
Baseclass for nested widgets.
uint current_x
Current horizontal size (after resizing).
Base class for a 'real' widget.
void SetStringTip(StringID string, StringID tool_tip)
Set string and tool tip of the nested widget.
Definition widget.cpp:1175
Base class for a resizable nested widget.
bool UpdateVerticalSize(uint min_y)
Set absolute (post-scaling) minimal size of the widget.
Definition widget.cpp:1131
StringID name
Name of this rail type.
Definition rail.h:167
StringID name
Name of this rail type.
Definition road.h:94
Scrollbar data structure.
size_type GetCapacity() const
Gets the number of visible elements of the scrollbar.
void SetCount(size_t num)
Sets the number of elements in the list.
auto GetScrolledItemFromWidget(Tcontainer &container, int clickpos, const Window *const w, WidgetID widget, int padding=0, int line_height=-1) const
Return an iterator pointing to the element of a scrolled widget that a user clicked in.
size_type GetScrolledRowFromWidget(int clickpos, const Window *const w, WidgetID widget, int padding=0, int line_height=-1) const
Compute the row of a scrolled widget that a user clicked in.
Definition widget.cpp:2436
bool SetPosition(size_type position)
Sets the position of the first visible element.
void SetCapacityFromWidget(Window *w, WidgetID widget, int padding=0)
Set capacity of visible elements from the size and resize properties of a widget.
Definition widget.cpp:2510
size_type GetCount() const
Gets the number of elements in the list.
auto GetVisibleRangeIterators(Tcontainer &container) const
Get a pair of iterators for the range of visible elements in a container.
size_type GetPosition() const
Gets the position of the first visible element in the list.
Management class for customizing the face of the company manager.
void SelectDisplayPlanes(bool advanced)
Select planes to display to the user with the NWID_SELECTION widgets WID_SCMF_SEL_LOADSAVE,...
uint click_state
Click state on selected face variable.
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::vector< const FaceVar * > face_vars
Visible face variables.
void OnResize() override
Called after the window got resized.
bool advanced
advanced company manager face selection window
uint selected_var
Currently selected face variable. UINT_MAX for none, UINT_MAX - 1 means style is clicked instead.
void DrawWidget(const Rect &r, WidgetID widget) const override
Draw the contents of a nested widget.
CompanyManagerFace face
company manager face bits
int line_height
Height of each face variable row.
void UpdateData()
Make face bits valid and update visible face variables.
void OnQueryTextFinished(std::optional< std::string > str) override
The query window opened from this window has closed.
void OnClick(Point pt, WidgetID widget, int click_count) override
A click with the left mouse button has been made on the window.
void OnTimeout() override
Called when this window's timeout has been reached.
void OnInit() override
Notification that the nested widget tree gets initialized.
static Year year
Current year, starting at 0.
static bool UsingWallclockUnits(bool newgame=false)
Check if we are using wallclock units.
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
int vsep_normal
Normal vertical spacing.
Definition window_gui.h:58
int vsep_wide
Wide vertical spacing.
Definition window_gui.h:60
int hsep_wide
Wide horizontal spacing.
Definition window_gui.h:62
RectPadding fullbevel
Always-scaled bevel thickness.
Definition window_gui.h:39
static const WidgetDimensions unscaled
Unscaled widget dimensions.
Definition window_gui.h:93
RectPadding matrix
Padding of WWT_MATRIX items.
Definition window_gui.h:42
int hsep_normal
Normal horizontal spacing.
Definition window_gui.h:61
RectPadding bevel
Bevel thickness, affected by "scaled bevels" game option.
Definition window_gui.h:38
int hsep_indent
Width of indentation for tree layouts.
Definition window_gui.h:63
Functions related to commands.
Definition of stuff that is very close to a company, like the company struct itself.
Money CalculateHostileTakeoverValue(const Company *c)
Calculate what you have to pay to take over a company.
Definition economy.cpp:177
Money CalculateCompanyValue(const Company *c, bool including_loan=true)
Calculate the value of the company.
Definition economy.cpp:150
std::optional< CompanyManagerFace > ParseCompanyManagerFaceCode(std::string_view str)
Parse a face code into a company manager face.
FaceVars GetCompanyManagerFaceVars(uint style)
Get the face variables for a face style.
void RandomiseCompanyManagerFace(CompanyManagerFace &cmf, Randomizer &randomizer)
Completely randomise a company manager face, including style.
std::string _company_manager_face
for company manager face storage in openttd.cfg
PaletteID GetCompanyPalette(CompanyID company)
Get the palette for recolouring with a company colour.
void SetCompanyManagerFaceStyle(CompanyManagerFace &cmf, uint style)
Set a company face style.
uint GetNumCompanyManagerFaceStyles()
Get the number of company manager face styles.
std::string FormatCompanyManagerFaceCode(const CompanyManagerFace &cmf)
Get a face code representation of a company manager face.
CompanyID _local_company
Company controlled by the human player at this client. Can also be COMPANY_SPECTATOR.
Command definitions related to companies.
Functions related to companies.
void ShowCompanyFinances(CompanyID company)
Open the finances window of a company.
static Money DrawYearCategory(const Rect &r, int start_y, const ExpensesList &list, const Expenses &tbl)
Draw a category of expenses/revenues in the year column.
static uint GetMaxCategoriesWidth()
Get the required width of the "categories" column, equal to the widest element.
static WindowDesc _select_company_manager_face_desc(WDP_AUTO, {}, 0, 0, WC_COMPANY_MANAGER_FACE, WC_NONE, WindowDefaultFlag::Construction, _nested_select_company_manager_face_widgets)
Company manager face selection window description.
static void DrawYearColumn(const Rect &r, TimerGameEconomy::Year year, const Expenses &tbl)
Draw a column with prices.
static const std::initializer_list< ExpensesType > _expenses_list_capital_costs
List of capital expenses.
void ShowBuyCompanyDialog(CompanyID company, bool hostile_takeover)
Show the query to buy another company.
static const StringID _company_view_vehicle_count_strings[]
Strings for the company vehicle counts.
static const std::initializer_list< ExpensesList > _expenses_list_types
Types of expense lists.
static void DrawPrice(Money amount, int left, int right, int top, TextColour colour)
Draw an amount of money.
static void ShowCompanyInfrastructure(CompanyID company)
Open the infrastructure window of a company.
static void DrawCategories(const Rect &r)
Draw the expenses categories.
static void DoSelectCompanyManagerFace(Window *parent)
Company GUI constants.
void ShowCompany(CompanyID company)
Show the window with the overview of the company.
static constexpr NWidgetPart _nested_select_company_manager_face_widgets[]
Nested widget description for the company manager face selection dialog.
static const std::initializer_list< ExpensesType > _expenses_list_operating_costs
List of operating expenses.
static uint GetTotalCategoriesHeight()
Get the total height of the "categories" column.
static const std::initializer_list< ExpensesType > _expenses_list_revenue
List of revenues.
void DirtyCompanyInfrastructureWindows(CompanyID company)
Redraw all windows with company infrastructure counts.
void DrawCompanyManagerFace(const CompanyManagerFace &cmf, Colours colour, const Rect &r)
Draws the face of a company manager's face.
static void DrawCategory(const Rect &r, int start_y, const ExpensesList &list)
Draw a category of expenses (revenue, operating expenses, capital expenses).
Functionality related to the company manager's face.
uint64_t GetActiveFaceVars(const CompanyManagerFace &cmf, FaceVars vars)
Get a bitmask of currently active face variables.
void ScaleAllCompanyManagerFaceBits(CompanyManagerFace &cmf, FaceVars vars)
Scales all company manager's face bits to the correct scope.
static const uint MAX_LENGTH_PRESIDENT_NAME_CHARS
The maximum length of a president name in characters including '\0'.
static const uint MAX_LENGTH_COMPANY_NAME_CHARS
The maximum length of a company name in characters including '\0'.
static constexpr CompanyID COMPANY_SPECTATOR
The client is spectating.
Types related to the company widgets.
@ WID_CF_CAPTION
Caption of the window.
@ WID_CF_SEL_BUTTONS
Selection of buttons.
@ WID_CF_SEL_PANEL
Select panel or nothing.
@ WID_CF_EXPS_CATEGORY
Column for expenses category strings.
@ WID_CF_EXPS_PRICE1
Column for year Y-2 expenses.
@ WID_CF_INFRASTRUCTURE
View company infrastructure.
@ WID_CF_TOGGLE_SIZE
Toggle windows size.
@ WID_CF_EXPS_PRICE2
Column for year Y-1 expenses.
@ WID_CF_OWN_VALUE
Own funds, not including loan.
@ WID_CF_LOAN_VALUE
Loan.
@ WID_CF_INCREASE_LOAN
Increase loan.
@ WID_CF_INTEREST_RATE
Loan interest rate.
@ WID_CF_BALANCE_VALUE
Bank balance value.
@ WID_CF_EXPS_PRICE3
Column for year Y expenses.
@ WID_CF_BALANCE_LINE
Available cash.
@ WID_CF_REPAY_LOAN
Decrease loan..
@ WID_CF_SEL_MAXLOAN
Selection of maxloan column.
@ WID_CF_MAXLOAN_VALUE
Max loan widget.
@ WID_BC_NO
No button.
@ WID_BC_YES
Yes button.
@ WID_BC_QUESTION
Question text.
@ WID_BC_CAPTION
Caption of window.
@ WID_BC_FACE
Face button.
@ WID_SCMF_CAPTION
Caption of window.
@ WID_SCMF_TOGGLE_LARGE_SMALL_BUTTON
Toggle for large or small.
@ WID_SCMF_STYLE
Style selector widget.
@ WID_SCMF_SEL_RESIZE
Selection to display the resize button.
@ WID_SCMF_SELECT_FACE
Select face.
@ WID_SCMF_RANDOM_NEW_FACE
Create random new face.
@ WID_SCMF_SEL_PARTS
Selection to display the buttons for setting each part of the face in the advanced view.
@ WID_SCMF_PARTS_SCROLLBAR
Scrollbar for configuration parts widget.
@ WID_SCMF_CANCEL
Cancel.
@ WID_SCMF_SAVE
Save face.
@ WID_SCMF_SEL_LOADSAVE
Selection to display the load/save/number buttons in the advanced view.
@ WID_SCMF_FACE
Current face.
@ WID_SCMF_LOAD
Load face.
@ WID_SCMF_ACCEPT
Accept.
@ WID_SCMF_TOGGLE_LARGE_SMALL
Toggle for large or small.
@ WID_SCMF_FACECODE
Get the face code.
@ WID_SCMF_PARTS
Face configuration parts widget.
@ WID_SCL_CLASS_AIRCRAFT
Class aircraft.
@ WID_SCL_MATRIX_SCROLLBAR
Matrix scrollbar.
@ WID_SCL_CLASS_SHIP
Class ship.
@ WID_SCL_GROUPS_SHIP
Ship groups.
@ WID_SCL_GROUPS_ROAD
Road groups.
@ WID_SCL_CLASS_ROAD
Class road.
@ WID_SCL_GROUPS_AIRCRAFT
Aircraft groups.
@ WID_SCL_SEC_COL_DROPDOWN
Dropdown for secondary colour.
@ WID_SCL_SPACER_DROPDOWN
Spacer for dropdown.
@ WID_SCL_GROUPS_RAIL
Rail groups.
@ WID_SCL_PRI_COL_DROPDOWN
Dropdown for primary colour.
@ WID_SCL_CLASS_RAIL
Class rail.
@ WID_SCL_MATRIX
Matrix.
@ WID_SCL_CAPTION
Caption of window.
@ WID_SCL_CLASS_GENERAL
Class general.
@ WID_CI_SCROLLBAR
Infrastructure list scrollbar.
@ WID_CI_CAPTION
Caption of window.
@ WID_CI_LIST
Infrastructure list.
CompanyWidgets
Widgets of the CompanyWindow class.
@ WID_C_SELECT_VIEW_BUILD_HQ
Panel about HQ.
@ WID_C_DESC_INFRASTRUCTURE_COUNTS
Infrastructure count.
@ WID_C_DESC_VEHICLE
Vehicles.
@ WID_C_COLOUR_SCHEME
Button to change colour scheme.
@ WID_C_CAPTION
Caption of the window.
@ WID_C_VIEW_HQ
Button to view the HQ.
@ WID_C_SELECT_RELOCATE
Panel about 'Relocate HQ'.
@ WID_C_SELECT_BUTTONS
Selection widget for the button bar.
@ WID_C_VIEW_INFRASTRUCTURE
Panel about infrastructure.
@ WID_C_SELECT_HOSTILE_TAKEOVER
Selection widget for the hostile takeover button.
@ WID_C_SELECT_GIVE_MONEY
Selection widget for the give money button.
@ WID_C_DESC_COLOUR_SCHEME
Colour scheme.
@ WID_C_GIVE_MONEY
Button to give money.
@ WID_C_SELECT_MULTIPLAYER
Multiplayer selection panel.
@ WID_C_DESC_INAUGURATION
Inauguration.
@ WID_C_DESC_COLOUR_SCHEME_EXAMPLE
Colour scheme example.
@ WID_C_BUILD_HQ
Button to build the HQ.
@ WID_C_HOSTILE_TAKEOVER
Button to hostile takeover another company.
@ WID_C_DESC_INFRASTRUCTURE
Infrastructure.
@ WID_C_FACE_TITLE
Title for the face.
@ WID_C_DESC_COMPANY_VALUE
Company value.
@ WID_C_COMPANY_JOIN
Button to join company.
@ WID_C_PRESIDENT_NAME
Button to change president name.
@ WID_C_DESC_VEHICLE_COUNTS
Vehicle count.
@ WID_C_NEW_FACE
Button to make new face.
@ WID_C_FACE
View of the face.
@ WID_C_RELOCATE_HQ
Button to relocate the HQ.
@ WID_C_COMPANY_NAME
Button to change company name.
Functions to handle different currencies.
const CurrencySpec & GetCurrency()
Get the currently selected currency.
Definition currency.h:118
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
Common drop down list components.
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.
Command definitions related to the economy.
std::array< Money, EXPENSES_END > Expenses
Data type for storage of Money for each ExpensesType category.
ExpensesType
Types of expenses.
@ EXPENSES_ROADVEH_RUN
Running costs road vehicles.
@ EXPENSES_TRAIN_RUN
Running costs trains.
@ EXPENSES_AIRCRAFT_REVENUE
Revenue from aircraft.
@ EXPENSES_CONSTRUCTION
Construction costs.
@ EXPENSES_AIRCRAFT_RUN
Running costs aircraft.
@ EXPENSES_ROADVEH_REVENUE
Revenue from road vehicles.
@ EXPENSES_PROPERTY
Property costs.
@ EXPENSES_OTHER
Other expenses.
@ EXPENSES_SHIP_REVENUE
Revenue from ships.
@ EXPENSES_LOAN_INTEREST
Interest payments over the loan.
@ EXPENSES_TRAIN_REVENUE
Revenue from trains.
@ EXPENSES_SHIP_RUN
Running costs ships.
@ EXPENSES_NEW_VEHICLES
New vehicles.
static const int LOAN_INTERVAL
The "steps" in loan size, in British Pounds!
Base class for engines.
Functions related to errors.
@ WL_INFO
Used for DoCommand-like (and some non-fatal AI GUI) errors/information.
Definition error.h:24
void ShowErrorMessage(EncodedString &&summary_msg, int x, int y, CommandCost &cc)
Display an error message in a window.
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.
int CentreBounds(int min, int max, int size)
Determine where to position a centred object.
int GetStringHeight(std::string_view str, int maxw, FontSize fontsize)
Calculates height of string (in pixels).
Definition gfx.cpp:705
Dimension GetSpriteSize(SpriteID sprid, Point *offset, ZoomLevel zoom)
Get the size of a sprite.
Definition gfx.cpp:958
bool _shift_pressed
Is Shift pressed?
Definition gfx.cpp:39
Dimension GetStringBoundingBox(std::string_view str, FontSize start_fontsize)
Return the string dimension in pixels.
Definition gfx.cpp:887
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
uint GetStringListWidth(std::span< const StringID > list, FontSize fontsize)
Get maximum width of a list of strings.
Definition gfx.cpp:910
void GfxFillRect(int left, int top, int right, int bottom, int colour, FillRectMode mode)
Applies a certain FillRectMode-operation to a rectangle [left, right] x [top, bottom] on the screen.
Definition gfx.cpp:115
void DrawSprite(SpriteID img, PaletteID pal, int x, int y, const SubSprite *sub, ZoomLevel zoom)
Draw a sprite, not in a viewport.
Definition gfx.cpp:1024
int DrawStringMultiLine(int left, int right, int top, int bottom, std::string_view str, TextColour colour, StringAlignment align, bool underline, FontSize fontsize)
Draw string, possibly over multiple lines.
Definition gfx.cpp:775
Dimension GetScaledSpriteSize(SpriteID sprid)
Scale sprite size for GUI.
Definition widget.cpp:68
@ FS_NORMAL
Index of the normal font in the font tables.
Definition gfx_type.h:251
@ SA_TOP
Top align the text.
Definition gfx_type.h:388
@ SA_LEFT
Left align the text.
Definition gfx_type.h:383
@ SA_RIGHT
Right align the text (must be a single bit).
Definition gfx_type.h:385
@ SA_HOR_CENTER
Horizontally center the text.
Definition gfx_type.h:384
@ SA_FORCE
Force the alignment, i.e. don't swap for RTL languages.
Definition gfx_type.h:395
@ SA_CENTER
Center both horizontally and vertically.
Definition gfx_type.h:393
@ SA_VERT_CENTER
Vertically center the text.
Definition gfx_type.h:389
uint32_t PaletteID
The number of the palette.
Definition gfx_type.h:18
TextColour
Colour of the strings, see _string_colourmap in table/string_colours.h or docs/ottd-colourtext-palett...
Definition gfx_type.h:302
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 SetSpriteTip(SpriteID sprite, StringID tip={})
Widget part function for setting the sprite and tooltip.
constexpr NWidgetPart SetToolbarMinimalSize(int width)
Widget part function to setting the minimal size for a toolbar button.
constexpr NWidgetPart SetPIP(uint8_t pre, uint8_t inter, uint8_t post)
Widget part function for setting a pre/inter/post spaces.
constexpr NWidgetPart SetScrollbar(WidgetID index)
Attach a scrollbar to a widget.
constexpr NWidgetPart SetPadding(uint8_t top, uint8_t right, uint8_t bottom, uint8_t left)
Widget part function for setting additional space around a widget.
constexpr NWidgetPart SetStringTip(StringID string, StringID tip={})
Widget part function for setting the string and tooltip.
constexpr NWidgetPart SetAspect(float ratio, AspectFlags flags=AspectFlag::ResizeX)
Widget part function for setting the aspect ratio.
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 SetAlignment(StringAlignment align)
Widget part function for setting the alignment of text/images.
constexpr NWidgetPart SetResize(int16_t dx, int16_t dy)
Widget part function for setting the resize step.
constexpr NWidgetPart SetPIPRatio(uint8_t ratio_pre, uint8_t ratio_inter, uint8_t ratio_post)
Widget part function for setting a pre/inter/post ratio.
Command definitions related to engine groups.
void SetDirty() const
Mark entire window as dirty (in need of re-paint)
Definition window.cpp:955
void MarkWholeScreenDirty()
This function mark the whole screen as dirty.
Definition gfx.cpp:1535
void BuildGuiGroupList(GUIGroupList &list, bool fold, Owner owner, VehicleType veh_type)
Build GUI group list, a sorted hierarchical list of groups for owner and vehicle type.
Functions/definitions that have something to do with groups.
GUI functions that shouldn't be here.
void ShowExtraViewportWindow(TileIndex tile=INVALID_TILE)
Show a new Extra Viewport window.
static const uint8_t LIT_ALL
Show the liveries of all companies.
Definition livery.h:18
LiveryScheme
List of different livery schemes.
Definition livery.h:21
static const uint8_t LIT_COMPANY
Show the liveries of your own company.
Definition livery.h:17
LiveryClass
List of different livery classes, used only by the livery GUI.
Definition livery.h:63
constexpr bool IsInsideBS(const T x, const size_t base, const size_t size)
Checks if a value is between a window started at some base point.
Miscellaneous command definitions.
void ShowQueryString(std::string_view str, StringID caption, uint maxsize, Window *parent, CharSetFilter afilter, QueryStringFlags flags)
Show a query popup window with a textbox in it.
bool _networking
are we in networking mode?
Definition network.cpp:67
bool _network_server
network-server is active
Definition network.cpp:68
bool NetworkCanJoinCompany(CompanyID company_id)
Returns whether the given company can be joined by this client.
Definition network.cpp:143
Basic functions/variables used all over the place.
void NetworkClientRequestMove(CompanyID company_id)
Notify the server of this client wanting to be moved to another company.
Network functions used by other parts of OpenTTD.
void NetworkServerDoMove(ClientID client_id, CompanyID company_id)
Handle the tid-bits of moving a client from one company to another.
GUIs related to networking.
@ CLIENT_ID_SERVER
Servers always have this ID.
GRFLoadedFeatures _loaded_newgrf_features
Indicates which are the newgrf features currently loaded ingame.
Definition newgrf.cpp:74
Base for the NewGRF implementation.
Command definitions related to objects.
Types related to object tiles.
static const ObjectType OBJECT_HQ
HeadQuarter of a player.
Definition object_type.h:22
static const uint8_t PC_WHITE
White palette colour.
static const uint8_t PC_BLACK
Black palette colour.
Rail specific functions.
std::vector< RailType > _sorted_railtypes
Sorted list of rail types.
Definition rail_cmd.cpp:47
Money RailMaintenanceCost(RailType railtype, uint32_t num, uint32_t total_num)
Calculates the maintenance cost of a number of track bits.
Definition rail.h:436
Money SignalMaintenanceCost(uint32_t num)
Calculates the maintenance cost of a number of signals.
Definition rail.h:447
const RailTypeInfo * GetRailTypeInfo(RailType railtype)
Returns a pointer to the Railtype information for a given railtype.
Definition rail.h:300
RailType
Enumeration for all possible railtypes.
Definition rail_type.h:25
Randomizer _interactive_random
Random used everywhere else, where it does not (directly) influence the game state.
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 related to roads.
Money RoadMaintenanceCost(RoadType roadtype, uint32_t num, uint32_t total_num)
Calculates the maintenance cost of a number of road bits.
Definition road_func.h:125
RoadType
The different roadtypes we support.
Definition road_type.h:23
A number of safeguards to prevent using unsafe methods.
GameSettings _settings_game
Game settings of a running game or the scenario editor.
Definition settings.cpp:61
ClientSettings _settings_client
The current settings for this game.
Definition settings.cpp:60
void DrawArrowButtons(int x, int y, Colours button_colour, uint8_t state, bool clickable_left, bool clickable_right)
Draw [<][>] boxes.
void DrawBoolButton(int x, int y, Colours button_colour, Colours background, bool state, bool clickable)
Draw a toggle button.
Functions for setting GUIs.
#define SETTING_BUTTON_WIDTH
Width of setting buttons.
#define SETTING_BUTTON_HEIGHT
Height of setting buttons.
Base types for having sorted lists in GUIs.
static PaletteID GetColourPalette(Colours colour)
Get recolour palette for a colour.
Definition sprite.h:184
Money AirportMaintenanceCost(Owner owner)
Calculates the maintenance cost of all airports of a company.
Definition station.cpp:713
Functions related to stations.
Money StationMaintenanceCost(uint32_t num)
Calculates the maintenance cost of a number of station tiles.
Definition of base types and functions in a cross-platform compatible way.
#define lengthof(array)
Return the length of an fixed size array.
Definition stdafx.h:271
Parse strings.
@ CS_NUMERAL
Only numeric ones.
Definition string_type.h:26
@ CS_ALPHANUMERAL
Both numeric and alphabetic and spaces and stuff.
Definition string_type.h:25
uint64_t GetParamMaxValue(uint64_t max_value, uint min_count, FontSize size)
Get some number that is suitable for string size computations.
Definition strings.cpp:237
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.
void DrawWidget(const Rect &r, WidgetID widget) const override
Draw the contents of a nested widget.
Money company_value
The value of the company for which the user can buy it.
std::string GetWidgetString(WidgetID widget, StringID stringid) const override
Get the raw string for a widget.
void OnClick(Point pt, WidgetID widget, int click_count) override
A click with the left mouse button has been made on the window.
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.
bool hostile_takeover
Whether the window is showing a hostile takeover.
const IntervalTimer< TimerWindow > rescale_interval
Check on a regular interval if the company value has changed.
GUISettings gui
settings related to the GUI
Window class displaying the company finances.
const IntervalTimer< TimerWindow > rescale_interval
Check on a regular interval if the maximum amount of money has changed.
void DrawWidget(const Rect &r, WidgetID widget) const override
Draw the contents of a nested widget.
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.
void OnClick(Point pt, WidgetID widget, int click_count) override
A click with the left mouse button has been made on the window.
void OnInvalidateData(int, bool) override
Some data on this window has become invalid.
std::string GetWidgetString(WidgetID widget, StringID stringid) const override
Get the raw string for a widget.
bool small
Window is toggled to 'small'.
static Money max_money
The maximum amount of money a company has had this 'run'.
uint8_t first_visible
First visible expenses column. The last column (current) is always visible.
void SetupWidgets()
Setup the widgets in the nested tree, such that the finances window is displayed properly.
void OnPaint() override
The window must be repainted.
Window with detailed information about the company's infrastructure.
void OnInit() override
Notification that the nested widget tree gets initialized.
void OnInvalidateData(int data=0, bool gui_scope=true) override
Some data on this window has become invalid.
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.
void FindWindowPlacementAndResize(int def_width, int def_height, bool allow_resize) override
Resize window towards the default size.
void DrawWidget(const Rect &r, WidgetID widget) const override
Draw the contents of a nested widget.
std::string GetWidgetString(WidgetID widget, StringID stringid) const override
Get the raw string for a widget.
void OnResize() override
Called after the window got resized.
std::array< uint32_t, ROADTYPE_END > road
Count of company owned track bits for each road type.
uint32_t GetRailTotal() const
Get total sum of all owned track bits.
uint32_t GetRoadTotal() const
Get total sum of all owned road bits.
uint32_t station
Count of company owned station tiles.
uint32_t signal
Count of company owned signals.
std::array< uint32_t, RAILTYPE_END > rail
Count of company owned track bits for each rail type.
uint32_t GetTramTotal() const
Get total sum of all owned tram bits.
uint32_t airport
Count of company owned airports.
uint32_t water
Count of company owned track bits for canals.
uint32_t bits
Company manager face bits, meaning is dependent on style.
uint style
Company manager face style.
TileIndex location_of_HQ
Northern tile of HQ; INVALID_TILE when there is none.
bool is_ai
If true, the company is (also) controlled by the computer (a NoAI program).
Money current_loan
Amount of money borrowed from the bank.
TimerGameCalendar::Year inaugurated_year_calendar
Calendar year of starting the company. Used to display proper Inauguration year while in wallclock mo...
TimerGameEconomy::Year inaugurated_year
Economy year of starting the company.
Colours colour
Company colour.
CompanyManagerFace face
Face description of the president.
std::array< Expenses, 3 > yearly_expenses
Expenses of the company for the last three years.
Money money
Money owned by the company.
Window with general information about a company.
void OnResize() override
Called after the window got resized.
const IntervalTimer< TimerWindow > redraw_interval
Redraw the window on a regular interval.
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.
void OnClick(Point pt, WidgetID widget, int click_count) override
A click with the left mouse button has been made on the window.
void OnPlaceObjectAbort() override
The user cancelled a tile highlight mode that has been set.
std::string GetWidgetString(WidgetID widget, StringID stringid) const override
Get the raw string for a widget.
void OnPlaceObject(Point pt, TileIndex tile) override
The user clicked some place on the map when a tile highlight mode has been set.
void DrawWidget(const Rect &r, WidgetID widget) const override
Draw the contents of a nested widget.
void OnQueryTextFinished(std::optional< std::string > str) override
The query window opened from this window has closed.
void OnInvalidateData(int data=0, bool gui_scope=true) override
Some data on this window has become invalid.
CompanyWindowPlanes
Display planes in the company window.
@ CWP_RELOCATE_SHOW
Show the relocate HQ button.
@ CWP_RELOCATE_HIDE
Hide the relocate HQ button.
@ CWP_VB_BUILD
Display the build button.
@ CWP_VB_VIEW
Display the view button.
void OnPaint() override
The window must be repainted.
Money GetMaxLoan() const
Calculate the max allowed loan for this company.
CompanyInfrastructure infrastructure
NOSAVE: Counts of company owned infrastructure.
std::array< GroupStatistics, VEH_COMPANY_END > group_all
NOSAVE: Statistics for the ALL_GROUP group.
uint16_t rate
The conversion rate compared to the base currency.
Definition currency.h:77
uint8_t initial_interest
amount of interest (to pay over the loan)
Dimensions (a width and height) of a rectangle in 2D.
bool infrastructure_maintenance
enable monthly maintenance fee for owner infrastructure
bool give_money
allow giving other companies money
Expense list container.
uint GetListWidth() const
Compute width of the expenses categories in pixels.
const std::initializer_list< ExpensesType > & items
List of expenses types.
const StringID title
StringID of list title.
Information about the valid values of CompanyManagerFace bitgroups as well as the sprites to draw.
uint8_t position
Position in UI.
uint8_t valid_values
The number of valid values.
bool has_2CC
Set if any vehicle is loaded which uses 2cc (two company colours).
Definition newgrf.h:189
uint64_t used_liveries
Bitmask of LiveryScheme used by the defined engines.
Definition newgrf.h:190
uint8_t liveries
options for displaying company liveries, 0=none, 1=self, 2=all
EconomySettings economy
settings to change the economy
DifficultySettings difficulty
settings related to the difficulty
Group data.
Definition group.h:73
Livery livery
Custom colour scheme for vehicles in this group.
Definition group.h:79
GroupID parent
Parent group.
Definition group.h:85
VehicleType vehicle_type
Vehicle type of the group.
Definition group.h:76
Information about a particular livery.
Definition livery.h:78
Colours colour2
Second colour, for vehicles with 2CC support.
Definition livery.h:81
Colours colour1
First colour, for all vehicles.
Definition livery.h:80
uint8_t in_use
Bit 0 set if this livery should override the default livery first colour, Bit 1 for the second colour...
Definition livery.h:79
Partial widget specification to allow NWidgets to be written nested.
Coordinates of a point in 2D.
static Pool::IterateWrapper< Titem > Iterate(size_t from=0)
Returns an iterable ensemble of all valid Titem.
static Titem * Get(auto index)
Returns Titem with given index.
Tindex index
Index of this pool item.
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.
constexpr uint Horizontal() const
Get total horizontal padding of RectPadding.
constexpr uint Vertical() const
Get total vertical padding of RectPadding.
Specification of a rectangle with absolute coordinates of all edges.
Rect WithWidth(int width, bool end) const
Copy Rect and set its width.
Rect CentreTo(int width, int height) const
Centre a dimension within this Rect.
int Width() const
Get width of Rect.
Rect Shrink(int s) const
Copy and shrink Rect by s pixels.
Rect WithHeight(int height, bool end=false) const
Copy Rect and set its height.
Rect Indent(int indent, bool end) const
Copy Rect and indent it from its position.
int Height() const
Get height of Rect.
Rect Translate(int x, int y) const
Copy and translate Rect by x,y pixels.
uint step_height
Step-size of height resize changes.
Definition window_gui.h:212
Company livery colour scheme window.
void OnDropdownSelect(WidgetID widget, int index, int) override
A dropdown option associated to this window has been selected.
void OnInvalidateData(int data=0, bool gui_scope=true) override
Some data on this window has become invalid.
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.
void OnPaint() override
The window must be repainted.
void DrawWidget(const Rect &r, WidgetID widget) const override
Draw the contents of a nested widget.
void OnClick(Point pt, WidgetID widget, int click_count) override
A click with the left mouse button has been made on the window.
std::string GetWidgetString(WidgetID widget, StringID stringid) const override
Get the raw string for a widget.
void OnResize() override
Called after the window got resized.
Iterable ensemble of each set bit in a value.
Templated helper to make a type-safe 'typedef' representing a single POD value.
High level window description.
Definition window_gui.h:167
Number to differentiate different windows of the same class.
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
virtual void Close(int data=0)
Hide the window and all its child windows, and mark them for a later deletion.
Definition window.cpp:1091
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
void InvalidateData(int data=0, bool gui_scope=true)
Mark this window's data as invalid (in need of re-computing)
Definition window.cpp:3205
Window * parent
Parent window.
Definition window_gui.h:328
void RaiseWidget(WidgetID widget_index)
Marks a widget as raised.
Definition window_gui.h:469
void SetWidgetDirty(WidgetID widget_index) const
Invalidate a widget, i.e.
Definition window.cpp:555
virtual std::string GetWidgetString(WidgetID widget, StringID stringid) const
Get the raw string for a widget.
Definition window.cpp:503
ResizeInfo resize
Resize information.
Definition window_gui.h:314
void SetShaded(bool make_shaded)
Set the shaded state of the window to make_shaded.
Definition window.cpp:1010
void SetWidgetsDisabledState(bool disab_stat, Args... widgets)
Sets the enabled/disabled status of a list of widgets.
Definition window_gui.h:515
void CreateNestedTree()
Perform the first part of the initialization of a nested widget tree.
Definition window.cpp:1768
bool IsWidgetLowered(WidgetID widget_index) const
Gets the lowered state of a widget.
Definition window_gui.h:491
void RaiseButtons(bool autoraise=false)
Raise the buttons of the window.
Definition window.cpp:529
Owner owner
The owner of the content shown in this window. Company colour is acquired from this variable.
Definition window_gui.h:316
void EnableWidget(WidgetID widget_index)
Sets a widget to Enabled.
Definition window_gui.h:400
virtual void FindWindowPlacementAndResize(int def_width, int def_height, bool allow_resize)
Resize window towards the default size.
Definition window.cpp:1463
bool IsShaded() const
Is window shaded currently?
Definition window_gui.h:559
void SetTimeout()
Set the timeout flag of the window and initiate the timer.
Definition window_gui.h:355
void LowerWidget(WidgetID widget_index)
Marks a widget as lowered.
Definition window_gui.h:460
void InitNested(WindowNumber number=0)
Perform complete initialization of the Window with nested widgets, to allow use.
Definition window.cpp:1791
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
int height
Height of the window (number of pixels down in y direction)
Definition window_gui.h:312
int width
width of the window (number of pixels to the right in x direction)
Definition window_gui.h:311
WindowNumber window_number
Window number within the window class.
Definition window_gui.h:302
Stuff related to the text buffer GUI.
@ EnableDefault
enable the 'Default' button ("\0" is returned)
@ LengthIsInChars
the length of the string is counted in characters
constexpr TileIndex INVALID_TILE
The very nice invalid tile marker.
Definition tile_type.h:95
Functions related to tile highlights.
void ResetObjectToPlace()
Reset the cursor and mouse mode handling back to default (normal cursor, only clicking in windows).
void SetObjectToPlaceWnd(CursorID icon, PaletteID pal, HighLightStyle mode, Window *w)
Change the cursor and mouse click/drag handling to a mode for performing special operations like tile...
@ HT_RECT
rectangle (stations, depots, ...)
Definition of Interval and OneShot timers.
Definition of the game-economy-timer.
Definition of the Window system.
VehicleType
Available vehicle types.
@ VEH_ROAD
Road vehicle type.
@ VEH_AIRCRAFT
Aircraft vehicle type.
@ VEH_SHIP
Ship vehicle type.
@ VEH_TRAIN
Train vehicle type.
@ VEH_COMPANY_END
Last company-ownable type.
void SetTileSelectSize(int w, int h)
Highlight w by h tiles at the cursor.
bool ScrollMainWindowToTile(TileIndex tile, bool instant)
Scrolls the viewport of the main window to a given location.
Functions related to (drawing on) viewports.
Functions related to water (management)
Money CanalMaintenanceCost(uint32_t num)
Calculates the maintenance cost of a number of canal tiles.
Definition water.h:51
@ WWT_PUSHTXTBTN
Normal push-button (no toggle button) with text caption.
@ WWT_IMGBTN
(Toggle) Button with image
Definition widget_type.h:42
@ WWT_LABEL
Centered label.
Definition widget_type.h:49
@ NWID_SPACER
Invisible widget that takes some space.
Definition widget_type.h:71
@ 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_EMPTY
Empty widget, place holder to reserve space in widget tree.
Definition widget_type.h:38
@ 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
@ WWT_TEXT
Pure simple text.
Definition widget_type.h:50
@ NWID_SELECTION
Stacked widgets, only one visible at a time (eg in a panel with tabs).
Definition widget_type.h:72
@ SZSP_HORIZONTAL
Display plane with zero size vertically, and filling and resizing horizontally.
@ SZSP_NONE
Display plane with zero size in both directions (none filling and resizing).
@ EqualSize
Containers should keep all their (resizing) children equally large.
Window * BringWindowToFrontById(WindowClass cls, WindowNumber number)
Find a window and make it the relative top-window on the screen.
Definition window.cpp:1265
void SetWindowDirty(WindowClass cls, WindowNumber number)
Mark window as dirty (in need of repainting)
Definition window.cpp:3147
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.
@ WDP_AUTO
Find a place automatically.
Definition window_gui.h:144
int WidgetID
Widget ID.
Definition window_type.h:20
@ WC_BUY_COMPANY
Buyout company (merger); Window numbers:
@ WC_COMPANY_INFRASTRUCTURE
Company infrastructure overview; Window numbers:
@ WC_COMPANY_COLOUR
Company colour selection; Window numbers:
@ WC_NONE
No window, redirects to WC_MAIN_WINDOW.
Definition window_type.h:47
@ WC_FINANCES
Finances of a company; Window numbers:
@ WC_COMPANY_MANAGER_FACE
Alter company face window; Window numbers:
@ WC_COMPANY
Company view; Window numbers:
Functions related to zooming.