OpenTTD Source 15.0-beta2
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 "window_gui.h"
15#include "textbuf_gui.h"
16#include "viewport_func.h"
17#include "company_func.h"
18#include "command_func.h"
19#include "network/network.h"
20#include "network/network_gui.h"
22#include "newgrf.h"
24#include "strings_func.h"
26#include "dropdown_type.h"
27#include "tilehighlight_func.h"
28#include "company_base.h"
30#include "object_type.h"
31#include "rail.h"
32#include "road.h"
33#include "engine_base.h"
34#include "window_func.h"
35#include "road_func.h"
36#include "water.h"
37#include "station_func.h"
38#include "zoom_func.h"
39#include "sortlist_type.h"
40#include "company_cmd.h"
41#include "economy_cmd.h"
42#include "group_cmd.h"
43#include "group_gui.h"
44#include "misc_cmd.h"
45#include "object_cmd.h"
46#include "timer/timer.h"
47#include "timer/timer_window.h"
48
50
51#include "table/strings.h"
52
54
55#include "safeguards.h"
56
57
59static void DoSelectCompanyManagerFace(Window *parent);
60static void ShowCompanyInfrastructure(CompanyID company);
61
63static const std::initializer_list<ExpensesType> _expenses_list_revenue = {
68};
69
79
81static const std::initializer_list<ExpensesType> _expenses_list_capital_costs = {
85};
86
90 const std::initializer_list<ExpensesType> &items;
91
92 ExpensesList(StringID title, const std::initializer_list<ExpensesType> &list) : title(title), items(list)
93 {
94 }
95
96 uint GetHeight() const
97 {
98 /* Add up the height of all the lines. */
99 return static_cast<uint>(this->items.size()) * GetCharacterHeight(FS_NORMAL);
100 }
101
103 uint GetListWidth() const
104 {
105 uint width = 0;
106 for (const ExpensesType &et : this->items) {
107 width = std::max(width, GetStringBoundingBox(STR_FINANCES_SECTION_CONSTRUCTION + et).width);
108 }
109 return width;
110 }
111};
112
114static const std::initializer_list<ExpensesList> _expenses_list_types = {
115 { STR_FINANCES_REVENUE_TITLE, _expenses_list_revenue },
116 { STR_FINANCES_OPERATING_EXPENSES_TITLE, _expenses_list_operating_costs },
117 { STR_FINANCES_CAPITAL_EXPENSES_TITLE, _expenses_list_capital_costs },
118};
119
125{
126 /* There's an empty line and blockspace on the year row */
128
129 for (const ExpensesList &list : _expenses_list_types) {
130 /* Title + expense list + total line + total + blockspace after category */
132 }
133
134 /* Total income */
136
137 return total_height;
138}
139
145{
146 uint max_width = GetStringBoundingBox(TimerGameEconomy::UsingWallclockUnits() ? STR_FINANCES_PERIOD_CAPTION : STR_FINANCES_YEAR_CAPTION).width;
147
148 /* Loop through categories to check max widths. */
149 for (const ExpensesList &list : _expenses_list_types) {
150 /* Title of category */
151 max_width = std::max(max_width, GetStringBoundingBox(list.title).width);
152 /* Entries in category */
153 max_width = std::max(max_width, list.GetListWidth() + WidgetDimensions::scaled.hsep_indent);
154 }
155
156 return max_width;
157}
158
162static void DrawCategory(const Rect &r, int start_y, const ExpensesList &list)
163{
165
166 tr.top = start_y;
167
168 for (const ExpensesType &et : list.items) {
169 DrawString(tr, STR_FINANCES_SECTION_CONSTRUCTION + et);
170 tr.top += GetCharacterHeight(FS_NORMAL);
171 }
172}
173
179static void DrawCategories(const Rect &r)
180{
181 int y = r.top;
182 /* Draw description of 12-minute economic period. */
183 DrawString(r.left, r.right, y, (TimerGameEconomy::UsingWallclockUnits() ? STR_FINANCES_PERIOD_CAPTION : STR_FINANCES_YEAR_CAPTION), TC_FROMSTRING, SA_LEFT, true);
185
186 for (const ExpensesList &list : _expenses_list_types) {
187 /* Draw category title and advance y */
188 DrawString(r.left, r.right, y, list.title, TC_FROMSTRING, SA_LEFT);
190
191 /* Draw category items and advance y */
192 DrawCategory(r, y, list);
193 y += list.GetHeight();
194
195 /* Advance y by the height of the horizontal line between amounts and subtotal */
197
198 /* Draw category total and advance y */
199 DrawString(r.left, r.right, y, STR_FINANCES_TOTAL_CAPTION, TC_FROMSTRING, SA_RIGHT);
201
202 /* Advance y by a blockspace after this category block */
204 }
205
206 /* Draw total profit/loss */
208 DrawString(r.left, r.right, y, STR_FINANCES_PROFIT, TC_FROMSTRING, SA_LEFT);
209}
210
219static void DrawPrice(Money amount, int left, int right, int top, TextColour colour)
220{
221 StringID str = STR_FINANCES_NEGATIVE_INCOME;
222 if (amount == 0) {
223 str = STR_FINANCES_ZERO_INCOME;
224 } else if (amount < 0) {
225 amount = -amount;
226 str = STR_FINANCES_POSITIVE_INCOME;
227 }
228 DrawString(left, right, top, GetString(str, amount), colour, SA_RIGHT | SA_FORCE);
229}
230
235static Money DrawYearCategory(const Rect &r, int start_y, const ExpensesList &list, const Expenses &tbl)
236{
237 int y = start_y;
238 Money sum = 0;
239
240 for (const ExpensesType &et : list.items) {
241 Money cost = tbl[et];
242 sum += cost;
243 if (cost != 0) DrawPrice(cost, r.left, r.right, y, TC_BLACK);
245 }
246
247 /* Draw the total at the bottom of the category. */
248 GfxFillRect(r.left, y, r.right, y + WidgetDimensions::scaled.bevel.top - 1, PC_BLACK);
250 if (sum != 0) DrawPrice(sum, r.left, r.right, y, TC_WHITE);
251
252 /* Return the sum for the yearly total. */
253 return sum;
254}
255
256
264static void DrawYearColumn(const Rect &r, TimerGameEconomy::Year year, const Expenses &tbl)
265{
266 int y = r.top;
267 Money sum;
268
269 /* Year header */
270 DrawString(r.left, r.right, y, GetString(STR_FINANCES_YEAR, year), TC_FROMSTRING, SA_RIGHT | SA_FORCE, true);
272
273 /* Categories */
274 for (const ExpensesList &list : _expenses_list_types) {
276 sum += DrawYearCategory(r, y, list, tbl);
277 /* Expense list + expense category title + expense category total + blockspace after category */
279 }
280
281 /* Total income. */
282 GfxFillRect(r.left, y, r.right, y + WidgetDimensions::scaled.bevel.top - 1, PC_BLACK);
284 DrawPrice(sum, r.left, r.right, y, TC_WHITE);
285}
286
287static constexpr NWidgetPart _nested_company_finances_widgets[] = {
289 NWidget(WWT_CLOSEBOX, COLOUR_GREY),
290 NWidget(WWT_CAPTION, COLOUR_GREY, WID_CF_CAPTION),
291 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),
292 NWidget(WWT_SHADEBOX, COLOUR_GREY),
293 NWidget(WWT_STICKYBOX, COLOUR_GREY),
294 EndContainer(),
295 NWidget(NWID_SELECTION, INVALID_COLOUR, WID_CF_SEL_PANEL),
296 NWidget(WWT_PANEL, COLOUR_GREY),
298 NWidget(WWT_EMPTY, INVALID_COLOUR, WID_CF_EXPS_CATEGORY), SetMinimalSize(120, 0), SetFill(0, 0),
299 NWidget(WWT_EMPTY, INVALID_COLOUR, WID_CF_EXPS_PRICE1), SetMinimalSize(86, 0), SetFill(0, 0),
300 NWidget(WWT_EMPTY, INVALID_COLOUR, WID_CF_EXPS_PRICE2), SetMinimalSize(86, 0), SetFill(0, 0),
301 NWidget(WWT_EMPTY, INVALID_COLOUR, WID_CF_EXPS_PRICE3), SetMinimalSize(86, 0), SetFill(0, 0),
302 EndContainer(),
303 EndContainer(),
304 EndContainer(),
305 NWidget(WWT_PANEL, COLOUR_GREY),
307 NWidget(NWID_VERTICAL), // Vertical column with 'bank balance', 'loan'
308 NWidget(WWT_TEXT, INVALID_COLOUR), SetStringTip(STR_FINANCES_OWN_FUNDS_TITLE),
309 NWidget(WWT_TEXT, INVALID_COLOUR), SetStringTip(STR_FINANCES_LOAN_TITLE),
310 NWidget(WWT_TEXT, INVALID_COLOUR), SetStringTip(STR_FINANCES_BANK_BALANCE_TITLE), SetPadding(WidgetDimensions::unscaled.vsep_normal, 0, 0, 0),
311 EndContainer(),
312 NWidget(NWID_VERTICAL), // Vertical column with bank balance amount, loan amount, and total.
317 EndContainer(),
318 NWidget(NWID_SELECTION, INVALID_COLOUR, WID_CF_SEL_MAXLOAN),
319 NWidget(NWID_VERTICAL), SetPIPRatio(0, 0, 1), // Max loan information
320 NWidget(WWT_TEXT, INVALID_COLOUR, WID_CF_INTEREST_RATE),
321 NWidget(WWT_TEXT, INVALID_COLOUR, WID_CF_MAXLOAN_VALUE),
322 EndContainer(),
323 EndContainer(),
324 EndContainer(),
325 EndContainer(),
326 NWidget(NWID_SELECTION, INVALID_COLOUR, WID_CF_SEL_BUTTONS),
328 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_CF_INCREASE_LOAN), SetFill(1, 0), SetToolTip(STR_FINANCES_BORROW_TOOLTIP),
329 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_CF_REPAY_LOAN), SetFill(1, 0), SetToolTip(STR_FINANCES_REPAY_TOOLTIP),
330 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_CF_INFRASTRUCTURE), SetFill(1, 0), SetStringTip(STR_FINANCES_INFRASTRUCTURE_BUTTON, STR_COMPANY_VIEW_INFRASTRUCTURE_TOOLTIP),
331 EndContainer(),
332 EndContainer(),
333};
334
337 static constexpr int NUM_PERIODS = WID_CF_EXPS_PRICE3 - WID_CF_EXPS_PRICE1 + 1;
338
340 bool small = false;
341 uint8_t first_visible = NUM_PERIODS - 1;
342
343 CompanyFinancesWindow(WindowDesc &desc, CompanyID company) : Window(desc)
344 {
345 this->CreateNestedTree();
346 this->SetupWidgets();
347 this->FinishInitNested(company);
348
349 this->owner = this->window_number;
350 this->InvalidateData();
351 }
352
353 std::string GetWidgetString(WidgetID widget, StringID stringid) const override
354 {
355 switch (widget) {
356 case WID_CF_CAPTION:
357 return GetString(STR_FINANCES_CAPTION, this->window_number, this->window_number);
358
360 const Company *c = Company::Get(this->window_number);
361 return GetString(STR_FINANCES_BANK_BALANCE, c->money);
362 }
363
364 case WID_CF_LOAN_VALUE: {
365 const Company *c = Company::Get(this->window_number);
366 return GetString(STR_FINANCES_TOTAL_CURRENCY, c->current_loan);
367 }
368
369 case WID_CF_OWN_VALUE: {
370 const Company *c = Company::Get(this->window_number);
371 return GetString(STR_FINANCES_TOTAL_CURRENCY, c->money - c->current_loan);
372 }
373
375 return GetString(STR_FINANCES_INTEREST_RATE, _settings_game.difficulty.initial_interest);
376
378 const Company *c = Company::Get(this->window_number);
379 return GetString(STR_FINANCES_MAX_LOAN, c->GetMaxLoan());
380 }
381
383 return GetString(STR_FINANCES_BORROW_BUTTON, LOAN_INTERVAL);
384
386 return GetString(STR_FINANCES_REPAY_BUTTON, LOAN_INTERVAL);
387
388 default:
389 return this->Window::GetWidgetString(widget, stringid);
390 }
391 }
392
393 void UpdateWidgetSize(WidgetID widget, Dimension &size, [[maybe_unused]] const Dimension &padding, [[maybe_unused]] Dimension &fill, [[maybe_unused]] Dimension &resize) override
394 {
395 switch (widget) {
397 size.width = GetMaxCategoriesWidth();
398 size.height = GetTotalCategoriesHeight();
399 break;
400
404 size.height = GetTotalCategoriesHeight();
405 [[fallthrough]];
406
409 case WID_CF_OWN_VALUE: {
411 size.width = std::max(GetStringBoundingBox(GetString(STR_FINANCES_NEGATIVE_INCOME, max_value)).width, GetStringBoundingBox(GetString(STR_FINANCES_POSITIVE_INCOME, max_value)).width);
412 size.width += padding.width;
413 break;
414 }
415
417 size.height = GetCharacterHeight(FS_NORMAL);
418 break;
419 }
420 }
421
422 void DrawWidget(const Rect &r, WidgetID widget) const override
423 {
424 switch (widget) {
427 break;
428
431 case WID_CF_EXPS_PRICE3: {
432 int period = widget - WID_CF_EXPS_PRICE1;
433 if (period < this->first_visible) break;
434
435 const Company *c = Company::Get(this->window_number);
436 const auto &expenses = c->yearly_expenses[NUM_PERIODS - period - 1];
437 DrawYearColumn(r, TimerGameEconomy::year - (NUM_PERIODS - period - 1), expenses);
438 break;
439 }
440
442 GfxFillRect(r.left, r.top, r.right, r.top + WidgetDimensions::scaled.bevel.top - 1, PC_BLACK);
443 break;
444 }
445 }
446
452 {
453 int plane = this->small ? SZSP_NONE : 0;
454 this->GetWidget<NWidgetStacked>(WID_CF_SEL_PANEL)->SetDisplayedPlane(plane);
455 this->GetWidget<NWidgetStacked>(WID_CF_SEL_MAXLOAN)->SetDisplayedPlane(plane);
456
457 CompanyID company = this->window_number;
458 plane = (company != _local_company) ? SZSP_NONE : 0;
459 this->GetWidget<NWidgetStacked>(WID_CF_SEL_BUTTONS)->SetDisplayedPlane(plane);
460 }
461
462 void OnPaint() override
463 {
464 if (!this->IsShaded()) {
465 if (!this->small) {
466 /* Check that the expenses panel height matches the height needed for the layout. */
467 if (GetTotalCategoriesHeight() != this->GetWidget<NWidgetBase>(WID_CF_EXPS_CATEGORY)->current_y) {
468 this->SetupWidgets();
469 this->ReInit();
470 return;
471 }
472 }
473
474 /* Check that the loan buttons are shown only when the user owns the company. */
475 CompanyID company = this->window_number;
476 int req_plane = (company != _local_company) ? SZSP_NONE : 0;
477 if (req_plane != this->GetWidget<NWidgetStacked>(WID_CF_SEL_BUTTONS)->shown_plane) {
478 this->SetupWidgets();
479 this->ReInit();
480 return;
481 }
482
483 const Company *c = Company::Get(company);
484 this->SetWidgetDisabledState(WID_CF_INCREASE_LOAN, c->current_loan >= c->GetMaxLoan()); // Borrow button only shows when there is any more money to loan.
485 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.
486 }
487
488 this->DrawWidgets();
489 }
490
491 void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override
492 {
493 switch (widget) {
494 case WID_CF_TOGGLE_SIZE: // toggle size
495 this->small = !this->small;
496 this->SetupWidgets();
497 if (this->IsShaded()) {
498 /* Finances window is not resizable, so size hints given during unshading have no effect
499 * on the changed appearance of the window. */
500 this->SetShaded(false);
501 } else {
502 this->ReInit();
503 }
504 break;
505
506 case WID_CF_INCREASE_LOAN: // increase loan
507 Command<CMD_INCREASE_LOAN>::Post(STR_ERROR_CAN_T_BORROW_ANY_MORE_MONEY, _ctrl_pressed ? LoanCommand::Max : LoanCommand::Interval, 0);
508 break;
509
510 case WID_CF_REPAY_LOAN: // repay loan
511 Command<CMD_DECREASE_LOAN>::Post(STR_ERROR_CAN_T_REPAY_LOAN, _ctrl_pressed ? LoanCommand::Max : LoanCommand::Interval, 0);
512 break;
513
514 case WID_CF_INFRASTRUCTURE: // show infrastructure details
516 break;
517 }
518 }
519
520 void RefreshVisibleColumns()
521 {
522 for (uint period = 0; period < this->first_visible; ++period) {
523 const Company *c = Company::Get(this->window_number);
524 const Expenses &expenses = c->yearly_expenses[NUM_PERIODS - period - 1];
525 /* Show expenses column if it has any non-zero value in it. */
526 if (std::ranges::any_of(expenses, [](const Money &value) { return value != 0; })) {
527 this->first_visible = period;
528 break;
529 }
530 }
531 }
532
533 void OnInvalidateData(int, bool) override
534 {
535 this->RefreshVisibleColumns();
536 }
537
542 IntervalTimer<TimerWindow> rescale_interval = {std::chrono::seconds(3), [this](auto) {
543 const Company *c = Company::Get(this->window_number);
546 this->SetupWidgets();
547 this->ReInit();
548 }
549 }};
550};
551
554
555static WindowDesc _company_finances_desc(
556 WDP_AUTO, "company_finances", 0, 0,
558 {},
559 _nested_company_finances_widgets
560);
561
568{
569 if (!Company::IsValidID(company)) return;
570 if (BringWindowToFrontById(WC_FINANCES, company)) return;
571
572 new CompanyFinancesWindow(_company_finances_desc, company);
573}
574
575/* Association of liveries to livery classes */
576static const LiveryClass _livery_class[LS_END] = {
577 LC_OTHER,
578 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,
579 LC_ROAD, LC_ROAD,
580 LC_SHIP, LC_SHIP,
581 LC_AIRCRAFT, LC_AIRCRAFT, LC_AIRCRAFT,
582 LC_ROAD, LC_ROAD,
583};
584
589template <SpriteID TSprite = SPR_SQUARE>
590class DropDownListColourItem : public DropDownIcon<DropDownString<DropDownListItem>> {
591public:
592 DropDownListColourItem(int colour, bool masked) : DropDownIcon<DropDownString<DropDownListItem>>(TSprite, GENERAL_SPRITE_COLOUR(colour % COLOUR_END), GetString(colour < COLOUR_END ? (STR_COLOUR_DARK_BLUE + colour) : STR_COLOUR_DEFAULT), colour, masked)
593 {
594 }
595};
596
599private:
600 uint32_t sel = 0;
601 LiveryClass livery_class{};
602 Dimension square{};
603 uint rows = 0;
604 uint line_height = 0;
605 GUIGroupList groups{};
606 Scrollbar *vscroll = nullptr;
607
608 void ShowColourDropDownMenu(uint32_t widget)
609 {
610 uint32_t used_colours = 0;
611 const Livery *livery, *default_livery = nullptr;
612 bool primary = widget == WID_SCL_PRI_COL_DROPDOWN;
613 uint8_t default_col = 0;
614
615 /* Disallow other company colours for the primary colour */
616 if (this->livery_class < LC_GROUP_RAIL && HasBit(this->sel, LS_DEFAULT) && primary) {
617 for (const Company *c : Company::Iterate()) {
618 if (c->index != _local_company) SetBit(used_colours, c->colour);
619 }
620 }
621
622 const Company *c = Company::Get(this->window_number);
623
624 if (this->livery_class < LC_GROUP_RAIL) {
625 /* Get the first selected livery to use as the default dropdown item */
626 LiveryScheme scheme;
627 for (scheme = LS_BEGIN; scheme < LS_END; scheme++) {
628 if (HasBit(this->sel, scheme)) break;
629 }
630 if (scheme == LS_END) scheme = LS_DEFAULT;
631 livery = &c->livery[scheme];
632 if (scheme != LS_DEFAULT) default_livery = &c->livery[LS_DEFAULT];
633 } else {
634 const Group *g = Group::Get(this->sel);
635 livery = &g->livery;
636 if (g->parent == GroupID::Invalid()) {
637 default_livery = &c->livery[LS_DEFAULT];
638 } else {
639 const Group *pg = Group::Get(g->parent);
640 default_livery = &pg->livery;
641 }
642 }
643
644 DropDownList list;
645 if (default_livery != nullptr) {
646 /* Add COLOUR_END to put the colour out of range, but also allow us to show what the default is */
647 default_col = (primary ? default_livery->colour1 : default_livery->colour2) + COLOUR_END;
648 list.push_back(std::make_unique<DropDownListColourItem<>>(default_col, false));
649 }
650 for (Colours colour = COLOUR_BEGIN; colour != COLOUR_END; colour++) {
651 list.push_back(std::make_unique<DropDownListColourItem<>>(colour, HasBit(used_colours, colour)));
652 }
653
654 uint8_t sel;
655 if (default_livery == nullptr || HasBit(livery->in_use, primary ? 0 : 1)) {
656 sel = primary ? livery->colour1 : livery->colour2;
657 } else {
658 sel = default_col;
659 }
660 ShowDropDownList(this, std::move(list), sel, widget);
661 }
662
663 void BuildGroupList(CompanyID owner)
664 {
665 if (!this->groups.NeedRebuild()) return;
666
667 this->groups.clear();
668
669 if (this->livery_class >= LC_GROUP_RAIL) {
670 VehicleType vtype = (VehicleType)(this->livery_class - LC_GROUP_RAIL);
671 BuildGuiGroupList(this->groups, false, owner, vtype);
672 }
673
674 this->groups.RebuildDone();
675 }
676
677 void SetRows()
678 {
679 if (this->livery_class < LC_GROUP_RAIL) {
680 this->rows = 0;
681 for (LiveryScheme scheme = LS_DEFAULT; scheme < LS_END; scheme++) {
682 if (_livery_class[scheme] == this->livery_class && HasBit(_loaded_newgrf_features.used_liveries, scheme)) {
683 this->rows++;
684 }
685 }
686 } else {
687 this->rows = (uint)this->groups.size();
688 }
689
690 this->vscroll->SetCount(this->rows);
691 }
692
693public:
694 SelectCompanyLiveryWindow(WindowDesc &desc, CompanyID company, GroupID group) : Window(desc)
695 {
696 this->CreateNestedTree();
697 this->vscroll = this->GetScrollbar(WID_SCL_MATRIX_SCROLLBAR);
698
699 if (group == GroupID::Invalid()) {
700 this->livery_class = LC_OTHER;
701 this->sel = 1;
703 this->BuildGroupList(company);
704 this->SetRows();
705 } else {
706 this->SetSelectedGroup(company, group);
707 }
708
709 this->FinishInitNested(company);
710 this->owner = company;
711 this->InvalidateData(1);
712 }
713
714 void SetSelectedGroup(CompanyID company, GroupID group)
715 {
716 this->RaiseWidget(WID_SCL_CLASS_GENERAL + this->livery_class);
717 const Group *g = Group::Get(group);
718 switch (g->vehicle_type) {
719 case VEH_TRAIN: this->livery_class = LC_GROUP_RAIL; break;
720 case VEH_ROAD: this->livery_class = LC_GROUP_ROAD; break;
721 case VEH_SHIP: this->livery_class = LC_GROUP_SHIP; break;
722 case VEH_AIRCRAFT: this->livery_class = LC_GROUP_AIRCRAFT; break;
723 default: NOT_REACHED();
724 }
725 this->sel = group.base();
726 this->LowerWidget(WID_SCL_CLASS_GENERAL + this->livery_class);
727
728 this->groups.ForceRebuild();
729 this->BuildGroupList(company);
730 this->SetRows();
731
732 /* Position scrollbar to selected group */
733 for (uint i = 0; i < this->rows; i++) {
734 if (this->groups[i].group->index == sel) {
735 this->vscroll->SetPosition(i - this->vscroll->GetCapacity() / 2);
736 break;
737 }
738 }
739 }
740
741 void UpdateWidgetSize(WidgetID widget, Dimension &size, [[maybe_unused]] const Dimension &padding, [[maybe_unused]] Dimension &fill, [[maybe_unused]] Dimension &resize) override
742 {
743 switch (widget) {
745 /* The matrix widget below needs enough room to print all the schemes. */
746 Dimension d = {0, 0};
747 for (LiveryScheme scheme = LS_DEFAULT; scheme < LS_END; scheme++) {
748 d = maxdim(d, GetStringBoundingBox(STR_LIVERY_DEFAULT + scheme));
749 }
750
751 /* And group names */
752 for (const Group *g : Group::Iterate()) {
753 if (g->owner == this->window_number) {
754 d = maxdim(d, GetStringBoundingBox(GetString(STR_GROUP_NAME, g->index)));
755 }
756 }
757
758 size.width = std::max(size.width, 5 + d.width + padding.width);
759 break;
760 }
761
762 case WID_SCL_MATRIX: {
763 /* 11 items in the default rail class */
764 this->square = GetSpriteSize(SPR_SQUARE);
765 this->line_height = std::max(this->square.height, (uint)GetCharacterHeight(FS_NORMAL)) + padding.height;
766
767 size.height = 5 * this->line_height;
768 resize.width = 1;
769 resize.height = this->line_height;
770 break;
771 }
772
775 size.width = 0;
776 break;
777 }
778 [[fallthrough]];
779
781 this->square = GetSpriteSize(SPR_SQUARE);
782 int string_padding = this->square.width + WidgetDimensions::scaled.hsep_normal + padding.width;
783 for (Colours colour = COLOUR_BEGIN; colour != COLOUR_END; colour++) {
784 size.width = std::max(size.width, GetStringBoundingBox(STR_COLOUR_DARK_BLUE + colour).width + string_padding);
785 }
786 size.width = std::max(size.width, GetStringBoundingBox(STR_COLOUR_DEFAULT).width + string_padding);
787 break;
788 }
789 }
790 }
791
792 void OnPaint() override
793 {
794 bool local = this->window_number == _local_company;
795
796 /* Disable dropdown controls if no scheme is selected */
797 bool disabled = this->livery_class < LC_GROUP_RAIL ? (this->sel == 0) : (this->sel == GroupID::Invalid());
798 this->SetWidgetDisabledState(WID_SCL_PRI_COL_DROPDOWN, !local || disabled);
799 this->SetWidgetDisabledState(WID_SCL_SEC_COL_DROPDOWN, !local || disabled);
800
801 this->BuildGroupList(this->window_number);
802
803 this->DrawWidgets();
804 }
805
806 std::string GetWidgetString(WidgetID widget, StringID stringid) const override
807 {
808 switch (widget) {
809 case WID_SCL_CAPTION:
810 return GetString(STR_LIVERY_CAPTION, this->window_number);
811
814 const Company *c = Company::Get(this->window_number);
815 bool primary = widget == WID_SCL_PRI_COL_DROPDOWN;
816 StringID colour = STR_COLOUR_DEFAULT;
817
818 if (this->livery_class < LC_GROUP_RAIL) {
819 if (this->sel != 0) {
820 LiveryScheme scheme = LS_DEFAULT;
821 for (scheme = LS_BEGIN; scheme < LS_END; scheme++) {
822 if (HasBit(this->sel, scheme)) break;
823 }
824 if (scheme == LS_END) scheme = LS_DEFAULT;
825 const Livery *livery = &c->livery[scheme];
826 if (scheme == LS_DEFAULT || HasBit(livery->in_use, primary ? 0 : 1)) {
827 colour = STR_COLOUR_DARK_BLUE + (primary ? livery->colour1 : livery->colour2);
828 }
829 }
830 } else {
831 if (this->sel != GroupID::Invalid()) {
832 const Group *g = Group::Get(this->sel);
833 const Livery *livery = &g->livery;
834 if (HasBit(livery->in_use, primary ? 0 : 1)) {
835 colour = STR_COLOUR_DARK_BLUE + (primary ? livery->colour1 : livery->colour2);
836 }
837 }
838 }
839 return GetString(colour);
840 }
841
842 default:
843 return this->Window::GetWidgetString(widget, stringid);
844 }
845 }
846
847 void DrawWidget(const Rect &r, WidgetID widget) const override
848 {
849 if (widget != WID_SCL_MATRIX) return;
850
851 bool rtl = _current_text_dir == TD_RTL;
852
853 /* Coordinates of scheme name column. */
854 const NWidgetBase *nwi = this->GetWidget<NWidgetBase>(WID_SCL_SPACER_DROPDOWN);
855 Rect sch = nwi->GetCurrentRect().Shrink(WidgetDimensions::scaled.framerect);
856 /* Coordinates of first dropdown. */
857 nwi = this->GetWidget<NWidgetBase>(WID_SCL_PRI_COL_DROPDOWN);
858 Rect pri = nwi->GetCurrentRect().Shrink(WidgetDimensions::scaled.framerect);
859 /* Coordinates of second dropdown. */
860 nwi = this->GetWidget<NWidgetBase>(WID_SCL_SEC_COL_DROPDOWN);
861 Rect sec = nwi->GetCurrentRect().Shrink(WidgetDimensions::scaled.framerect);
862
863 Rect pri_squ = pri.WithWidth(this->square.width, rtl);
864 Rect sec_squ = sec.WithWidth(this->square.width, rtl);
865
866 pri = pri.Indent(this->square.width + WidgetDimensions::scaled.hsep_normal, rtl);
867 sec = sec.Indent(this->square.width + WidgetDimensions::scaled.hsep_normal, rtl);
868
870 int square_offs = (ir.Height() - this->square.height) / 2;
871 int text_offs = (ir.Height() - GetCharacterHeight(FS_NORMAL)) / 2;
872
873 int y = ir.top;
874
875 /* Helper function to draw livery info. */
876 auto draw_livery = [&](std::string_view str, const Livery &livery, bool is_selected, bool is_default_scheme, int indent) {
877 /* Livery Label. */
878 DrawString(sch.left + (rtl ? 0 : indent), sch.right - (rtl ? indent : 0), y + text_offs, str, is_selected ? TC_WHITE : TC_BLACK);
879
880 /* Text below the first dropdown. */
881 DrawSprite(SPR_SQUARE, GENERAL_SPRITE_COLOUR(livery.colour1), pri_squ.left, y + square_offs);
882 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);
883
884 /* Text below the second dropdown. */
885 if (sec.right > sec.left) { // Second dropdown has non-zero size.
886 DrawSprite(SPR_SQUARE, GENERAL_SPRITE_COLOUR(livery.colour2), sec_squ.left, y + square_offs);
887 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);
888 }
889
890 y += this->line_height;
891 };
892
893 const Company *c = Company::Get(this->window_number);
894
895 if (livery_class < LC_GROUP_RAIL) {
896 int pos = this->vscroll->GetPosition();
897 for (LiveryScheme scheme = LS_DEFAULT; scheme < LS_END; scheme++) {
898 if (_livery_class[scheme] == this->livery_class && HasBit(_loaded_newgrf_features.used_liveries, scheme)) {
899 if (pos-- > 0) continue;
900 draw_livery(GetString(STR_LIVERY_DEFAULT + scheme), c->livery[scheme], HasBit(this->sel, scheme), scheme == LS_DEFAULT, 0);
901 }
902 }
903 } else {
904 auto [first, last] = this->vscroll->GetVisibleRangeIterators(this->groups);
905 for (auto it = first; it != last; ++it) {
906 const Group *g = it->group;
907 draw_livery(GetString(STR_GROUP_NAME, g->index), g->livery, this->sel == g->index, false, it->indent * WidgetDimensions::scaled.hsep_indent);
908 }
909
910 if (this->vscroll->GetCount() == 0) {
911 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 };
912 VehicleType vtype = (VehicleType)(this->livery_class - LC_GROUP_RAIL);
913 DrawString(ir.left, ir.right, y + text_offs, empty_labels[vtype], TC_BLACK);
914 }
915 }
916 }
917
918 void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override
919 {
920 switch (widget) {
921 /* Livery Class buttons */
931 this->RaiseWidget(WID_SCL_CLASS_GENERAL + this->livery_class);
932 this->livery_class = (LiveryClass)(widget - WID_SCL_CLASS_GENERAL);
933 this->LowerWidget(WID_SCL_CLASS_GENERAL + this->livery_class);
934
935 /* Select the first item in the list */
936 if (this->livery_class < LC_GROUP_RAIL) {
937 this->sel = 0;
938 for (LiveryScheme scheme = LS_DEFAULT; scheme < LS_END; scheme++) {
939 if (_livery_class[scheme] == this->livery_class && HasBit(_loaded_newgrf_features.used_liveries, scheme)) {
940 this->sel = 1 << scheme;
941 break;
942 }
943 }
944 } else {
945 this->sel = GroupID::Invalid().base();
946 this->groups.ForceRebuild();
947 this->BuildGroupList(this->window_number);
948
949 if (!this->groups.empty()) {
950 this->sel = this->groups[0].group->index.base();
951 }
952 }
953
954 this->SetRows();
955 this->SetDirty();
956 break;
957
958 case WID_SCL_PRI_COL_DROPDOWN: // First colour dropdown
959 ShowColourDropDownMenu(WID_SCL_PRI_COL_DROPDOWN);
960 break;
961
962 case WID_SCL_SEC_COL_DROPDOWN: // Second colour dropdown
963 ShowColourDropDownMenu(WID_SCL_SEC_COL_DROPDOWN);
964 break;
965
966 case WID_SCL_MATRIX: {
967 if (this->livery_class < LC_GROUP_RAIL) {
968 uint row = this->vscroll->GetScrolledRowFromWidget(pt.y, this, widget);
969 if (row >= this->rows) return;
970
971 LiveryScheme j = (LiveryScheme)row;
972
973 for (LiveryScheme scheme = LS_BEGIN; scheme <= j && scheme < LS_END; scheme++) {
974 if (_livery_class[scheme] != this->livery_class || !HasBit(_loaded_newgrf_features.used_liveries, scheme)) j++;
975 }
976 assert(j < LS_END);
977
978 if (_ctrl_pressed) {
979 ToggleBit(this->sel, j);
980 } else {
981 this->sel = 1 << j;
982 }
983 } else {
984 auto it = this->vscroll->GetScrolledItemFromWidget(this->groups, pt.y, this, widget);
985 if (it == std::end(this->groups)) return;
986
987 this->sel = it->group->index.base();
988 }
989 this->SetDirty();
990 break;
991 }
992 }
993 }
994
995 void OnResize() override
996 {
997 this->vscroll->SetCapacityFromWidget(this, WID_SCL_MATRIX);
998 }
999
1000 void OnDropdownSelect(WidgetID widget, int index) override
1001 {
1002 bool local = this->window_number == _local_company;
1003 if (!local) return;
1004
1005 Colours colour = static_cast<Colours>(index);
1006 if (colour >= COLOUR_END) colour = INVALID_COLOUR;
1007
1008 if (this->livery_class < LC_GROUP_RAIL) {
1009 /* Set company colour livery */
1010 for (LiveryScheme scheme = LS_DEFAULT; scheme < LS_END; scheme++) {
1011 /* Changed colour for the selected scheme, or all visible schemes if CTRL is pressed. */
1012 if (HasBit(this->sel, scheme) || (_ctrl_pressed && _livery_class[scheme] == this->livery_class && HasBit(_loaded_newgrf_features.used_liveries, scheme))) {
1014 }
1015 }
1016 } else {
1017 /* Setting group livery */
1018 Command<CMD_SET_GROUP_LIVERY>::Post(static_cast<GroupID>(this->sel), widget == WID_SCL_PRI_COL_DROPDOWN, colour);
1019 }
1020 }
1021
1027 void OnInvalidateData([[maybe_unused]] int data = 0, [[maybe_unused]] bool gui_scope = true) override
1028 {
1029 if (!gui_scope) return;
1030
1031 if (data != -1) {
1032 /* data contains a VehicleType, rebuild list if it displayed */
1033 if (this->livery_class == data + LC_GROUP_RAIL) {
1034 this->groups.ForceRebuild();
1035 this->BuildGroupList(this->window_number);
1036 this->SetRows();
1037
1038 if (!Group::IsValidID(this->sel)) {
1039 this->sel = GroupID::Invalid().base();
1040 if (!this->groups.empty()) this->sel = this->groups[0].group->index.base();
1041 }
1042
1043 this->SetDirty();
1044 }
1045 return;
1046 }
1047
1049
1050 bool current_class_valid = this->livery_class == LC_OTHER || this->livery_class >= LC_GROUP_RAIL;
1051 if (_settings_client.gui.liveries == LIT_ALL || (_settings_client.gui.liveries == LIT_COMPANY && this->window_number == _local_company)) {
1052 for (LiveryScheme scheme = LS_DEFAULT; scheme < LS_END; scheme++) {
1054 if (_livery_class[scheme] == this->livery_class) current_class_valid = true;
1055 this->EnableWidget(WID_SCL_CLASS_GENERAL + _livery_class[scheme]);
1056 } else if (this->livery_class < LC_GROUP_RAIL) {
1057 ClrBit(this->sel, scheme);
1058 }
1059 }
1060 }
1061
1062 if (!current_class_valid) {
1063 Point pt = {0, 0};
1064 this->OnClick(pt, WID_SCL_CLASS_GENERAL, 1);
1065 }
1066 }
1067};
1068
1069static constexpr NWidgetPart _nested_select_company_livery_widgets[] = {
1071 NWidget(WWT_CLOSEBOX, COLOUR_GREY),
1072 NWidget(WWT_CAPTION, COLOUR_GREY, WID_SCL_CAPTION),
1073 NWidget(WWT_SHADEBOX, COLOUR_GREY),
1074 NWidget(WWT_DEFSIZEBOX, COLOUR_GREY),
1075 NWidget(WWT_STICKYBOX, COLOUR_GREY),
1076 EndContainer(),
1078 NWidget(WWT_IMGBTN, COLOUR_GREY, WID_SCL_CLASS_GENERAL), SetMinimalSize(22, 22), SetFill(0, 1), SetSpriteTip(SPR_IMG_COMPANY_GENERAL, STR_LIVERY_GENERAL_TOOLTIP),
1079 NWidget(WWT_IMGBTN, COLOUR_GREY, WID_SCL_CLASS_RAIL), SetMinimalSize(22, 22), SetFill(0, 1), SetSpriteTip(SPR_IMG_TRAINLIST, STR_LIVERY_TRAIN_TOOLTIP),
1080 NWidget(WWT_IMGBTN, COLOUR_GREY, WID_SCL_CLASS_ROAD), SetMinimalSize(22, 22), SetFill(0, 1), SetSpriteTip(SPR_IMG_TRUCKLIST, STR_LIVERY_ROAD_VEHICLE_TOOLTIP),
1081 NWidget(WWT_IMGBTN, COLOUR_GREY, WID_SCL_CLASS_SHIP), SetMinimalSize(22, 22), SetFill(0, 1), SetSpriteTip(SPR_IMG_SHIPLIST, STR_LIVERY_SHIP_TOOLTIP),
1082 NWidget(WWT_IMGBTN, COLOUR_GREY, WID_SCL_CLASS_AIRCRAFT), SetMinimalSize(22, 22), SetFill(0, 1), SetSpriteTip(SPR_IMG_AIRPLANESLIST, STR_LIVERY_AIRCRAFT_TOOLTIP),
1083 NWidget(WWT_IMGBTN, COLOUR_GREY, WID_SCL_GROUPS_RAIL), SetMinimalSize(22, 22), SetFill(0, 1), SetSpriteTip(SPR_GROUP_LIVERY_TRAIN, STR_LIVERY_TRAIN_GROUP_TOOLTIP),
1084 NWidget(WWT_IMGBTN, COLOUR_GREY, WID_SCL_GROUPS_ROAD), SetMinimalSize(22, 22), SetFill(0, 1), SetSpriteTip(SPR_GROUP_LIVERY_ROADVEH, STR_LIVERY_ROAD_VEHICLE_GROUP_TOOLTIP),
1085 NWidget(WWT_IMGBTN, COLOUR_GREY, WID_SCL_GROUPS_SHIP), SetMinimalSize(22, 22), SetFill(0, 1), SetSpriteTip(SPR_GROUP_LIVERY_SHIP, STR_LIVERY_SHIP_GROUP_TOOLTIP),
1086 NWidget(WWT_IMGBTN, COLOUR_GREY, WID_SCL_GROUPS_AIRCRAFT), SetMinimalSize(22, 22), SetFill(0, 1), SetSpriteTip(SPR_GROUP_LIVERY_AIRCRAFT, STR_LIVERY_AIRCRAFT_GROUP_TOOLTIP),
1087 NWidget(WWT_PANEL, COLOUR_GREY), SetFill(1, 1), SetResize(1, 0), EndContainer(),
1088 EndContainer(),
1090 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),
1092 EndContainer(),
1095 NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_SCL_PRI_COL_DROPDOWN), SetFill(0, 1), SetToolTip(STR_LIVERY_PRIMARY_TOOLTIP),
1096 NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_SCL_SEC_COL_DROPDOWN), SetFill(0, 1), SetToolTip(STR_LIVERY_SECONDARY_TOOLTIP),
1097 NWidget(WWT_RESIZEBOX, COLOUR_GREY),
1098 EndContainer(),
1099};
1100
1101static WindowDesc _select_company_livery_desc(
1102 WDP_AUTO, "company_color_scheme", 0, 0,
1104 {},
1105 _nested_select_company_livery_widgets
1106);
1107
1108void ShowCompanyLiveryWindow(CompanyID company, GroupID group)
1109{
1111 if (w == nullptr) {
1112 new SelectCompanyLiveryWindow(_select_company_livery_desc, company, group);
1113 } else if (group != GroupID::Invalid()) {
1114 w->SetSelectedGroup(company, group);
1115 }
1116}
1117
1124void DrawCompanyManagerFace(CompanyManagerFace cmf, Colours colour, const Rect &r)
1125{
1127
1128 /* Determine offset from centre of drawing rect. */
1129 Dimension d = GetSpriteSize(SPR_GRADIENT);
1130 int x = CenterBounds(r.left, r.right, d.width);
1131 int y = CenterBounds(r.top, r.bottom, d.height);
1132
1133 bool has_moustache = !HasBit(ge, GENDER_FEMALE) && GetCompanyManagerFaceBits(cmf, CMFV_HAS_MOUSTACHE, ge) != 0;
1134 bool has_tie_earring = !HasBit(ge, GENDER_FEMALE) || GetCompanyManagerFaceBits(cmf, CMFV_HAS_TIE_EARRING, ge) != 0;
1135 bool has_glasses = GetCompanyManagerFaceBits(cmf, CMFV_HAS_GLASSES, ge) != 0;
1136 PaletteID pal;
1137
1138 /* Modify eye colour palette only if 2 or more valid values exist */
1139 if (_cmf_info[CMFV_EYE_COLOUR].valid_values[ge] < 2) {
1140 pal = PAL_NONE;
1141 } else {
1142 switch (GetCompanyManagerFaceBits(cmf, CMFV_EYE_COLOUR, ge)) {
1143 default: NOT_REACHED();
1144 case 0: pal = PALETTE_TO_BROWN; break;
1145 case 1: pal = PALETTE_TO_BLUE; break;
1146 case 2: pal = PALETTE_TO_GREEN; break;
1147 }
1148 }
1149
1150 /* Draw the gradient (background) */
1151 DrawSprite(SPR_GRADIENT, GENERAL_SPRITE_COLOUR(colour), x, y);
1152
1153 for (CompanyManagerFaceVariable cmfv = CMFV_CHEEKS; cmfv < CMFV_END; cmfv++) {
1154 switch (cmfv) {
1155 case CMFV_MOUSTACHE: if (!has_moustache) continue; break;
1156 case CMFV_LIPS:
1157 case CMFV_NOSE: if (has_moustache) continue; break;
1158 case CMFV_TIE_EARRING: if (!has_tie_earring) continue; break;
1159 case CMFV_GLASSES: if (!has_glasses) continue; break;
1160 default: break;
1161 }
1162 DrawSprite(GetCompanyManagerFaceSprite(cmf, cmfv, ge), (cmfv == CMFV_EYEBROWS) ? pal : PAL_NONE, x, y);
1163 }
1164}
1165
1169 NWidget(WWT_CLOSEBOX, COLOUR_GREY),
1170 NWidget(WWT_CAPTION, COLOUR_GREY, WID_SCMF_CAPTION), SetStringTip(STR_FACE_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
1171 NWidget(WWT_IMGBTN, COLOUR_GREY, WID_SCMF_TOGGLE_LARGE_SMALL), SetSpriteTip(SPR_LARGE_SMALL_WINDOW, STR_FACE_ADVANCED_TOOLTIP), SetAspect(WidgetDimensions::ASPECT_TOGGLE_SIZE),
1172 EndContainer(),
1173 NWidget(WWT_PANEL, COLOUR_GREY, WID_SCMF_SELECT_FACE),
1175 /* Left side */
1178 NWidget(WWT_EMPTY, INVALID_COLOUR, WID_SCMF_FACE), SetMinimalSize(92, 119), SetFill(1, 0),
1179 EndContainer(),
1180 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_RANDOM_NEW_FACE), SetFill(1, 0), SetStringTip(STR_FACE_NEW_FACE_BUTTON, STR_FACE_NEW_FACE_TOOLTIP),
1181 NWidget(NWID_SELECTION, INVALID_COLOUR, WID_SCMF_SEL_LOADSAVE), // Load/number/save buttons under the portrait in the advanced view.
1182 NWidget(NWID_VERTICAL), SetPIP(0, 0, 0), SetPIPRatio(1, 0, 1),
1183 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_LOAD), SetFill(1, 0), SetStringTip(STR_FACE_LOAD, STR_FACE_LOAD_TOOLTIP),
1184 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_FACECODE), SetFill(1, 0), SetStringTip(STR_FACE_FACECODE, STR_FACE_FACECODE_TOOLTIP),
1185 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_SAVE), SetFill(1, 0), SetStringTip(STR_FACE_SAVE, STR_FACE_SAVE_TOOLTIP),
1186 EndContainer(),
1187 EndContainer(),
1188 EndContainer(),
1189 /* Right side */
1191 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_TOGGLE_LARGE_SMALL_BUTTON), SetFill(1, 0), SetStringTip(STR_FACE_ADVANCED, STR_FACE_ADVANCED_TOOLTIP),
1192 NWidget(NWID_SELECTION, INVALID_COLOUR, WID_SCMF_SEL_MALEFEMALE), // Simple male/female face setting.
1194 NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_SCMF_MALE), SetFill(1, 0), SetStringTip(STR_FACE_MALE_BUTTON, STR_FACE_MALE_TOOLTIP),
1195 NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_SCMF_FEMALE), SetFill(1, 0), SetStringTip(STR_FACE_FEMALE_BUTTON, STR_FACE_FEMALE_TOOLTIP),
1196 EndContainer(),
1197 EndContainer(),
1198 NWidget(NWID_SELECTION, INVALID_COLOUR, WID_SCMF_SEL_PARTS), // Advanced face parts setting.
1201 NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_SCMF_MALE2), SetFill(1, 0), SetStringTip(STR_FACE_MALE_BUTTON, STR_FACE_MALE_TOOLTIP),
1202 NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_SCMF_FEMALE2), SetFill(1, 0), SetStringTip(STR_FACE_FEMALE_BUTTON, STR_FACE_FEMALE_TOOLTIP),
1203 EndContainer(),
1205 NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_SCMF_ETHNICITY_EUR), SetFill(1, 0), SetStringTip(STR_FACE_EUROPEAN, STR_FACE_EUROPEAN_TOOLTIP),
1206 NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_SCMF_ETHNICITY_AFR), SetFill(1, 0), SetStringTip(STR_FACE_AFRICAN, STR_FACE_AFRICAN_TOOLTIP),
1207 EndContainer(),
1211 SetStringTip(STR_FACE_EYECOLOUR), SetTextStyle(TC_GOLD), SetAlignment(SA_VERT_CENTER | SA_RIGHT),
1212 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_HAS_MOUSTACHE_EARRING), SetToolTip(STR_FACE_MOUSTACHE_EARRING_TOOLTIP), SetTextStyle(TC_WHITE),
1213 EndContainer(),
1215 NWidget(WWT_TEXT, INVALID_COLOUR, WID_SCMF_HAS_GLASSES_TEXT), SetFill(1, 0),
1216 SetStringTip(STR_FACE_GLASSES), SetTextStyle(TC_GOLD), SetAlignment(SA_VERT_CENTER | SA_RIGHT),
1217 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_HAS_GLASSES), SetToolTip(STR_FACE_GLASSES_TOOLTIP), SetTextStyle(TC_WHITE),
1218 EndContainer(),
1219 EndContainer(),
1222 NWidget(WWT_TEXT, INVALID_COLOUR, WID_SCMF_HAIR_TEXT), SetFill(1, 0),
1223 SetStringTip(STR_FACE_HAIR), SetTextStyle(TC_GOLD), SetAlignment(SA_VERT_CENTER | SA_RIGHT),
1225 NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_HAIR_L), SetArrowWidgetTypeTip(AWV_DECREASE, STR_FACE_HAIR_TOOLTIP),
1226 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_HAIR), SetToolTip(STR_FACE_HAIR_TOOLTIP), SetTextStyle(TC_WHITE),
1227 NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_HAIR_R), SetArrowWidgetTypeTip(AWV_INCREASE, STR_FACE_HAIR_TOOLTIP),
1228 EndContainer(),
1229 EndContainer(),
1231 NWidget(WWT_TEXT, INVALID_COLOUR, WID_SCMF_EYEBROWS_TEXT), SetFill(1, 0),
1232 SetStringTip(STR_FACE_EYEBROWS), SetTextStyle(TC_GOLD), SetAlignment(SA_VERT_CENTER | SA_RIGHT),
1234 NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_EYEBROWS_L), SetArrowWidgetTypeTip(AWV_DECREASE, STR_FACE_EYEBROWS_TOOLTIP),
1235 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_EYEBROWS), SetToolTip(STR_FACE_EYEBROWS_TOOLTIP), SetTextStyle(TC_WHITE),
1236 NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_EYEBROWS_R), SetArrowWidgetTypeTip(AWV_INCREASE, STR_FACE_EYEBROWS_TOOLTIP),
1237 EndContainer(),
1238 EndContainer(),
1240 NWidget(WWT_TEXT, INVALID_COLOUR, WID_SCMF_EYECOLOUR_TEXT), SetFill(1, 0),
1241 SetStringTip(STR_FACE_EYECOLOUR), SetTextStyle(TC_GOLD), SetAlignment(SA_VERT_CENTER | SA_RIGHT),
1243 NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_EYECOLOUR_L), SetArrowWidgetTypeTip(AWV_DECREASE, STR_FACE_EYECOLOUR_TOOLTIP),
1244 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_EYECOLOUR), SetToolTip(STR_FACE_EYECOLOUR_TOOLTIP), SetTextStyle(TC_WHITE),
1245 NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_EYECOLOUR_R), SetArrowWidgetTypeTip(AWV_INCREASE, STR_FACE_EYECOLOUR_TOOLTIP),
1246 EndContainer(),
1247 EndContainer(),
1249 NWidget(WWT_TEXT, INVALID_COLOUR, WID_SCMF_GLASSES_TEXT), SetFill(1, 0),
1250 SetStringTip(STR_FACE_GLASSES), SetTextStyle(TC_GOLD), SetAlignment(SA_VERT_CENTER | SA_RIGHT),
1252 NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_GLASSES_L), SetArrowWidgetTypeTip(AWV_DECREASE, STR_FACE_GLASSES_TOOLTIP_2),
1253 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_GLASSES), SetToolTip(STR_FACE_GLASSES_TOOLTIP_2), SetTextStyle(TC_WHITE),
1254 NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_GLASSES_R), SetArrowWidgetTypeTip(AWV_INCREASE, STR_FACE_GLASSES_TOOLTIP_2),
1255 EndContainer(),
1256 EndContainer(),
1258 NWidget(WWT_TEXT, INVALID_COLOUR, WID_SCMF_NOSE_TEXT), SetFill(1, 0),
1259 SetStringTip(STR_FACE_NOSE), SetTextStyle(TC_GOLD), SetAlignment(SA_VERT_CENTER | SA_RIGHT),
1261 NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_NOSE_L), SetArrowWidgetTypeTip(AWV_DECREASE, STR_FACE_NOSE_TOOLTIP),
1262 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_NOSE), SetToolTip(STR_FACE_NOSE_TOOLTIP), SetTextStyle(TC_WHITE),
1263 NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_NOSE_R), SetArrowWidgetTypeTip(AWV_INCREASE, STR_FACE_NOSE_TOOLTIP),
1264 EndContainer(),
1265 EndContainer(),
1267 NWidget(WWT_TEXT, INVALID_COLOUR, WID_SCMF_LIPS_MOUSTACHE_TEXT), SetFill(1, 0),
1268 SetStringTip(STR_FACE_MOUSTACHE), SetTextStyle(TC_GOLD), SetAlignment(SA_VERT_CENTER | SA_RIGHT),
1270 NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_LIPS_MOUSTACHE_L), SetArrowWidgetTypeTip(AWV_DECREASE, STR_FACE_LIPS_MOUSTACHE_TOOLTIP),
1271 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_LIPS_MOUSTACHE), SetToolTip(STR_FACE_LIPS_MOUSTACHE_TOOLTIP), SetTextStyle(TC_WHITE),
1272 NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_LIPS_MOUSTACHE_R), SetArrowWidgetTypeTip(AWV_INCREASE, STR_FACE_LIPS_MOUSTACHE_TOOLTIP),
1273 EndContainer(),
1274 EndContainer(),
1276 NWidget(WWT_TEXT, INVALID_COLOUR, WID_SCMF_CHIN_TEXT), SetFill(1, 0),
1277 SetStringTip(STR_FACE_CHIN), SetTextStyle(TC_GOLD), SetAlignment(SA_VERT_CENTER | SA_RIGHT),
1279 NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_CHIN_L), SetArrowWidgetTypeTip(AWV_DECREASE, STR_FACE_CHIN_TOOLTIP),
1280 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_CHIN), SetToolTip(STR_FACE_CHIN_TOOLTIP), SetTextStyle(TC_WHITE),
1281 NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_CHIN_R), SetArrowWidgetTypeTip(AWV_INCREASE, STR_FACE_CHIN_TOOLTIP),
1282 EndContainer(),
1283 EndContainer(),
1285 NWidget(WWT_TEXT, INVALID_COLOUR, WID_SCMF_JACKET_TEXT), SetFill(1, 0),
1286 SetStringTip(STR_FACE_JACKET), SetTextStyle(TC_GOLD), SetAlignment(SA_VERT_CENTER | SA_RIGHT),
1288 NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_JACKET_L), SetArrowWidgetTypeTip(AWV_DECREASE, STR_FACE_JACKET_TOOLTIP),
1289 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_JACKET), SetToolTip(STR_FACE_JACKET_TOOLTIP), SetTextStyle(TC_WHITE),
1290 NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_JACKET_R), SetArrowWidgetTypeTip(AWV_INCREASE, STR_FACE_JACKET_TOOLTIP),
1291 EndContainer(),
1292 EndContainer(),
1294 NWidget(WWT_TEXT, INVALID_COLOUR, WID_SCMF_COLLAR_TEXT), SetFill(1, 0),
1295 SetStringTip(STR_FACE_COLLAR), SetTextStyle(TC_GOLD), SetAlignment(SA_VERT_CENTER | SA_RIGHT),
1297 NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_COLLAR_L), SetArrowWidgetTypeTip(AWV_DECREASE, STR_FACE_COLLAR_TOOLTIP),
1298 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_COLLAR), SetToolTip(STR_FACE_COLLAR_TOOLTIP), SetTextStyle(TC_WHITE),
1299 NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_COLLAR_R), SetArrowWidgetTypeTip(AWV_INCREASE, STR_FACE_COLLAR_TOOLTIP),
1300 EndContainer(),
1301 EndContainer(),
1303 NWidget(WWT_TEXT, INVALID_COLOUR, WID_SCMF_TIE_EARRING_TEXT), SetFill(1, 0),
1304 SetStringTip(STR_FACE_EARRING), SetTextStyle(TC_GOLD), SetAlignment(SA_VERT_CENTER | SA_RIGHT),
1306 NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_TIE_EARRING_L), SetArrowWidgetTypeTip(AWV_DECREASE, STR_FACE_TIE_EARRING_TOOLTIP),
1307 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_TIE_EARRING), SetToolTip(STR_FACE_TIE_EARRING_TOOLTIP), SetTextStyle(TC_WHITE),
1308 NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_TIE_EARRING_R), SetArrowWidgetTypeTip(AWV_INCREASE, STR_FACE_TIE_EARRING_TOOLTIP),
1309 EndContainer(),
1310 EndContainer(),
1311 EndContainer(),
1312 EndContainer(),
1313 EndContainer(),
1314 EndContainer(),
1315 EndContainer(),
1316 EndContainer(),
1318 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_CANCEL), SetFill(1, 0), SetStringTip(STR_BUTTON_CANCEL, STR_FACE_CANCEL_TOOLTIP),
1319 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_ACCEPT), SetFill(1, 0), SetStringTip(STR_BUTTON_OK, STR_FACE_OK_TOOLTIP),
1320 EndContainer(),
1321};
1322
1325{
1327 bool advanced = false;
1328
1330 bool is_female = false;
1331 bool is_moust_male = false;
1332
1335
1344 std::string GetFaceString(WidgetID widget_index, uint8_t val, bool is_bool_widget) const
1345 {
1346 const NWidgetCore *nwi_widget = this->GetWidget<NWidgetCore>(widget_index);
1347 if (nwi_widget->IsDisabled()) return {};
1348
1349 /* If it a bool button write yes or no. */
1350 if (is_bool_widget) return GetString((val != 0) ? STR_FACE_YES : STR_FACE_NO);
1351
1352 /* Else write the value + 1. */
1353 return GetString(STR_JUST_INT, val + 1);
1354 }
1355
1356 void UpdateData()
1357 {
1358 this->ge = (GenderEthnicity)GB(this->face, _cmf_info[CMFV_GEN_ETHN].offset, _cmf_info[CMFV_GEN_ETHN].length); // get the gender and ethnicity
1359 this->is_female = HasBit(this->ge, GENDER_FEMALE); // get the gender: 0 == male and 1 == female
1360 this->is_moust_male = !is_female && GetCompanyManagerFaceBits(this->face, CMFV_HAS_MOUSTACHE, this->ge) != 0; // is a male face with moustache
1361
1362 this->GetWidget<NWidgetCore>(WID_SCMF_HAS_MOUSTACHE_EARRING_TEXT)->SetString(this->is_female ? STR_FACE_EARRING : STR_FACE_MOUSTACHE);
1363 this->GetWidget<NWidgetCore>(WID_SCMF_TIE_EARRING_TEXT)->SetString(this->is_female ? STR_FACE_EARRING : STR_FACE_TIE);
1364 this->GetWidget<NWidgetCore>(WID_SCMF_LIPS_MOUSTACHE_TEXT)->SetString(this->is_moust_male ? STR_FACE_MOUSTACHE : STR_FACE_LIPS);
1365 }
1366
1367public:
1369 {
1370 this->CreateNestedTree();
1371 this->SelectDisplayPlanes(this->advanced);
1372 this->FinishInitNested(parent->window_number);
1373 this->parent = parent;
1374 this->owner = this->window_number;
1375 this->face = Company::Get(this->window_number)->face;
1376
1377 this->UpdateData();
1378 }
1379
1385 {
1386 this->GetWidget<NWidgetStacked>(WID_SCMF_SEL_LOADSAVE)->SetDisplayedPlane(advanced ? 0 : SZSP_NONE);
1387 this->GetWidget<NWidgetStacked>(WID_SCMF_SEL_PARTS)->SetDisplayedPlane(advanced ? 0 : SZSP_NONE);
1388 this->GetWidget<NWidgetStacked>(WID_SCMF_SEL_MALEFEMALE)->SetDisplayedPlane(advanced ? SZSP_NONE : 0);
1389 this->GetWidget<NWidgetCore>(WID_SCMF_RANDOM_NEW_FACE)->SetString(advanced ? STR_FACE_RANDOM : STR_FACE_NEW_FACE_BUTTON);
1390
1391 NWidgetCore *wi = this->GetWidget<NWidgetCore>(WID_SCMF_TOGGLE_LARGE_SMALL_BUTTON);
1392 if (advanced) {
1393 wi->SetStringTip(STR_FACE_SIMPLE, STR_FACE_SIMPLE_TOOLTIP);
1394 } else {
1395 wi->SetStringTip(STR_FACE_ADVANCED, STR_FACE_ADVANCED_TOOLTIP);
1396 }
1397 }
1398
1399 void OnInit() override
1400 {
1401 /* Size of the boolean yes/no button. */
1405 /* Size of the number button + arrows. */
1406 Dimension number_dim = {0, 0};
1407 for (int val = 1; val <= 12; val++) {
1409 }
1410 uint arrows_width = GetSpriteSize(SPR_ARROW_LEFT).width + GetSpriteSize(SPR_ARROW_RIGHT).width + 2 * (WidgetDimensions::scaled.imgbtn.Horizontal());
1411 number_dim.width += WidgetDimensions::scaled.framerect.Horizontal() + arrows_width;
1413 /* Compute width of both buttons. */
1414 yesno_dim.width = std::max(yesno_dim.width, number_dim.width);
1415 number_dim.width = yesno_dim.width - arrows_width;
1416
1417 this->yesno_dim = yesno_dim;
1418 this->number_dim = number_dim;
1419 }
1420
1421 void UpdateWidgetSize(WidgetID widget, Dimension &size, [[maybe_unused]] const Dimension &padding, [[maybe_unused]] Dimension &fill, [[maybe_unused]] Dimension &resize) override
1422 {
1423 switch (widget) {
1425 size = maxdim(size, GetStringBoundingBox(STR_FACE_EARRING));
1426 size = maxdim(size, GetStringBoundingBox(STR_FACE_MOUSTACHE));
1427 break;
1428
1430 size = maxdim(size, GetStringBoundingBox(STR_FACE_EARRING));
1431 size = maxdim(size, GetStringBoundingBox(STR_FACE_TIE));
1432 break;
1433
1435 size = maxdim(size, GetStringBoundingBox(STR_FACE_LIPS));
1436 size = maxdim(size, GetStringBoundingBox(STR_FACE_MOUSTACHE));
1437 break;
1438
1439 case WID_SCMF_FACE:
1440 size = maxdim(size, GetScaledSpriteSize(SPR_GRADIENT));
1441 break;
1442
1445 size = this->yesno_dim;
1446 break;
1447
1448 case WID_SCMF_EYECOLOUR:
1449 case WID_SCMF_CHIN:
1450 case WID_SCMF_EYEBROWS:
1452 case WID_SCMF_NOSE:
1453 case WID_SCMF_HAIR:
1454 case WID_SCMF_JACKET:
1455 case WID_SCMF_COLLAR:
1457 case WID_SCMF_GLASSES:
1458 size = this->number_dim;
1459 break;
1460 }
1461 }
1462
1463 void OnPaint() override
1464 {
1465 /* lower the non-selected gender button */
1466 this->SetWidgetsLoweredState(!this->is_female, WID_SCMF_MALE, WID_SCMF_MALE2);
1468
1469 /* advanced company manager face selection window */
1470
1471 /* lower the non-selected ethnicity button */
1474
1475
1476 /* Disable dynamically the widgets which CompanyManagerFaceVariable has less than 2 options
1477 * (or in other words you haven't any choice).
1478 * If the widgets depend on a HAS-variable and this is false the widgets will be disabled, too. */
1479
1480 /* Eye colour buttons */
1481 this->SetWidgetsDisabledState(_cmf_info[CMFV_EYE_COLOUR].valid_values[this->ge] < 2,
1483
1484 /* Chin buttons */
1485 this->SetWidgetsDisabledState(_cmf_info[CMFV_CHIN].valid_values[this->ge] < 2,
1487
1488 /* Eyebrows buttons */
1489 this->SetWidgetsDisabledState(_cmf_info[CMFV_EYEBROWS].valid_values[this->ge] < 2,
1491
1492 /* Lips or (if it a male face with a moustache) moustache buttons */
1493 this->SetWidgetsDisabledState(_cmf_info[this->is_moust_male ? CMFV_MOUSTACHE : CMFV_LIPS].valid_values[this->ge] < 2,
1495
1496 /* Nose buttons | male faces with moustache haven't any nose options */
1497 this->SetWidgetsDisabledState(_cmf_info[CMFV_NOSE].valid_values[this->ge] < 2 || this->is_moust_male,
1499
1500 /* Hair buttons */
1501 this->SetWidgetsDisabledState(_cmf_info[CMFV_HAIR].valid_values[this->ge] < 2,
1503
1504 /* Jacket buttons */
1505 this->SetWidgetsDisabledState(_cmf_info[CMFV_JACKET].valid_values[this->ge] < 2,
1507
1508 /* Collar buttons */
1509 this->SetWidgetsDisabledState(_cmf_info[CMFV_COLLAR].valid_values[this->ge] < 2,
1511
1512 /* Tie/earring buttons | female faces without earring haven't any earring options */
1513 this->SetWidgetsDisabledState(_cmf_info[CMFV_TIE_EARRING].valid_values[this->ge] < 2 ||
1514 (this->is_female && GetCompanyManagerFaceBits(this->face, CMFV_HAS_TIE_EARRING, this->ge) == 0),
1516
1517 /* Glasses buttons | faces without glasses haven't any glasses options */
1518 this->SetWidgetsDisabledState(_cmf_info[CMFV_GLASSES].valid_values[this->ge] < 2 || GetCompanyManagerFaceBits(this->face, CMFV_HAS_GLASSES, this->ge) == 0,
1520
1521 this->DrawWidgets();
1522 }
1523
1524 std::string GetWidgetString(WidgetID widget, StringID stringid) const override
1525 {
1526 switch (widget) {
1528 CompanyManagerFaceVariable facepart = this->is_female ? CMFV_HAS_TIE_EARRING : CMFV_HAS_MOUSTACHE;
1529 return this->GetFaceString(widget, GetCompanyManagerFaceBits(this->face, facepart, this->ge), true);
1530 }
1531
1533 return this->GetFaceString(widget, GetCompanyManagerFaceBits(this->face, CMFV_TIE_EARRING, this->ge), false);
1534
1536 CompanyManagerFaceVariable facepart = this->is_moust_male ? CMFV_MOUSTACHE : CMFV_LIPS;
1537 return this->GetFaceString(widget, GetCompanyManagerFaceBits(this->face, facepart, this->ge), false);
1538 }
1539
1541 return this->GetFaceString(widget, GetCompanyManagerFaceBits(this->face, CMFV_HAS_GLASSES, this->ge), true );
1542
1543 case WID_SCMF_HAIR:
1544 return this->GetFaceString(widget, GetCompanyManagerFaceBits(this->face, CMFV_HAIR, this->ge), false);
1545
1546 case WID_SCMF_EYEBROWS:
1547 return this->GetFaceString(widget, GetCompanyManagerFaceBits(this->face, CMFV_EYEBROWS, this->ge), false);
1548
1549 case WID_SCMF_EYECOLOUR:
1550 return this->GetFaceString(widget, GetCompanyManagerFaceBits(this->face, CMFV_EYE_COLOUR, this->ge), false);
1551
1552 case WID_SCMF_GLASSES:
1553 return this->GetFaceString(widget, GetCompanyManagerFaceBits(this->face, CMFV_GLASSES, this->ge), false);
1554
1555 case WID_SCMF_NOSE:
1556 return this->GetFaceString(widget, GetCompanyManagerFaceBits(this->face, CMFV_NOSE, this->ge), false);
1557
1558 case WID_SCMF_CHIN:
1559 return this->GetFaceString(widget, GetCompanyManagerFaceBits(this->face, CMFV_CHIN, this->ge), false);
1560
1561 case WID_SCMF_JACKET:
1562 return this->GetFaceString(widget, GetCompanyManagerFaceBits(this->face, CMFV_JACKET, this->ge), false);
1563
1564 case WID_SCMF_COLLAR:
1565 return this->GetFaceString(widget, GetCompanyManagerFaceBits(this->face, CMFV_COLLAR, this->ge), false);
1566
1567 default:
1568 return this->Window::GetWidgetString(widget, stringid);
1569 }
1570 }
1571
1572 void DrawWidget(const Rect &r, WidgetID widget) const override
1573 {
1574 switch (widget) {
1575 case WID_SCMF_FACE:
1576 DrawCompanyManagerFace(this->face, Company::Get(this->window_number)->colour, r);
1577 break;
1578 }
1579 }
1580
1581 void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override
1582 {
1583 switch (widget) {
1584 /* Toggle size, advanced/simple face selection */
1587 this->advanced = !this->advanced;
1588 this->SelectDisplayPlanes(this->advanced);
1589 this->ReInit();
1590 break;
1591
1592 /* OK button */
1593 case WID_SCMF_ACCEPT:
1595 [[fallthrough]];
1596
1597 /* Cancel button */
1598 case WID_SCMF_CANCEL:
1599 this->Close();
1600 break;
1601
1602 /* Load button */
1603 case WID_SCMF_LOAD:
1606 ShowErrorMessage(GetEncodedString(STR_FACE_LOAD_DONE), {}, WL_INFO);
1607 this->UpdateData();
1608 this->SetDirty();
1609 break;
1610
1611 /* 'Company manager face number' button, view and/or set company manager face number */
1612 case WID_SCMF_FACECODE:
1613 ShowQueryString(GetString(STR_JUST_INT, this->face), STR_FACE_FACECODE_CAPTION, 10 + 1, this, CS_NUMERAL, {});
1614 break;
1615
1616 /* Save button */
1617 case WID_SCMF_SAVE:
1619 ShowErrorMessage(GetEncodedString(STR_FACE_SAVE_DONE), {}, WL_INFO);
1620 break;
1621
1622 /* Toggle gender (male/female) button */
1623 case WID_SCMF_MALE:
1624 case WID_SCMF_FEMALE:
1625 case WID_SCMF_MALE2:
1626 case WID_SCMF_FEMALE2:
1627 SetCompanyManagerFaceBits(this->face, CMFV_GENDER, this->ge, (widget == WID_SCMF_FEMALE || widget == WID_SCMF_FEMALE2));
1629 this->UpdateData();
1630 this->SetDirty();
1631 break;
1632
1633 /* Randomize face button */
1635 RandomCompanyManagerFaceBits(this->face, this->ge, this->advanced, _interactive_random);
1636 this->UpdateData();
1637 this->SetDirty();
1638 break;
1639
1640 /* Toggle ethnicity (european/african) button */
1643 SetCompanyManagerFaceBits(this->face, CMFV_ETHNICITY, this->ge, widget - WID_SCMF_ETHNICITY_EUR);
1645 this->UpdateData();
1646 this->SetDirty();
1647 break;
1648
1649 default:
1650 /* Here all buttons from WID_SCMF_HAS_MOUSTACHE_EARRING to WID_SCMF_GLASSES_R are handled.
1651 * First it checks which CompanyManagerFaceVariable is being changed, and then either
1652 * a: invert the value for boolean variables, or
1653 * b: it checks inside of IncreaseCompanyManagerFaceBits() if a left (_L) butten is pressed and then decrease else increase the variable */
1654 if (widget >= WID_SCMF_HAS_MOUSTACHE_EARRING && widget <= WID_SCMF_GLASSES_R) {
1655 CompanyManagerFaceVariable cmfv; // which CompanyManagerFaceVariable shall be edited
1656
1657 if (widget < WID_SCMF_EYECOLOUR_L) { // Bool buttons
1658 switch (widget - WID_SCMF_HAS_MOUSTACHE_EARRING) {
1659 default: NOT_REACHED();
1660 case 0: cmfv = this->is_female ? CMFV_HAS_TIE_EARRING : CMFV_HAS_MOUSTACHE; break; // Has earring/moustache button
1661 case 1: cmfv = CMFV_HAS_GLASSES; break; // Has glasses button
1662 }
1663 SetCompanyManagerFaceBits(this->face, cmfv, this->ge, !GetCompanyManagerFaceBits(this->face, cmfv, this->ge));
1665 } else { // Value buttons
1666 switch ((widget - WID_SCMF_EYECOLOUR_L) / 3) {
1667 default: NOT_REACHED();
1668 case 0: cmfv = CMFV_EYE_COLOUR; break; // Eye colour buttons
1669 case 1: cmfv = CMFV_CHIN; break; // Chin buttons
1670 case 2: cmfv = CMFV_EYEBROWS; break; // Eyebrows buttons
1671 case 3: cmfv = this->is_moust_male ? CMFV_MOUSTACHE : CMFV_LIPS; break; // Moustache or lips buttons
1672 case 4: cmfv = CMFV_NOSE; break; // Nose buttons
1673 case 5: cmfv = CMFV_HAIR; break; // Hair buttons
1674 case 6: cmfv = CMFV_JACKET; break; // Jacket buttons
1675 case 7: cmfv = CMFV_COLLAR; break; // Collar buttons
1676 case 8: cmfv = CMFV_TIE_EARRING; break; // Tie/earring buttons
1677 case 9: cmfv = CMFV_GLASSES; break; // Glasses buttons
1678 }
1679 /* 0 == left (_L), 1 == middle or 2 == right (_R) - button click */
1680 IncreaseCompanyManagerFaceBits(this->face, cmfv, this->ge, (((widget - WID_SCMF_EYECOLOUR_L) % 3) != 0) ? 1 : -1);
1681 }
1682 this->UpdateData();
1683 this->SetDirty();
1684 }
1685 break;
1686 }
1687 }
1688
1689 void OnQueryTextFinished(std::optional<std::string> str) override
1690 {
1691 if (!str.has_value()) return;
1692 /* Set a new company manager face number */
1693 if (!str->empty()) {
1694 this->face = std::strtoul(str->c_str(), nullptr, 10);
1696 ShowErrorMessage(GetEncodedString(STR_FACE_FACECODE_SET), {}, WL_INFO);
1697 this->UpdateData();
1698 this->SetDirty();
1699 } else {
1700 ShowErrorMessage(GetEncodedString(STR_FACE_FACECODE_ERR), {}, WL_INFO);
1701 }
1702 }
1703};
1704
1707 WDP_AUTO, nullptr, 0, 0,
1711);
1712
1725
1726static constexpr NWidgetPart _nested_company_infrastructure_widgets[] = {
1728 NWidget(WWT_CLOSEBOX, COLOUR_GREY),
1729 NWidget(WWT_CAPTION, COLOUR_GREY, WID_CI_CAPTION),
1730 NWidget(WWT_SHADEBOX, COLOUR_GREY),
1731 NWidget(WWT_STICKYBOX, COLOUR_GREY),
1732 EndContainer(),
1733 NWidget(WWT_PANEL, COLOUR_GREY),
1736 NWidget(WWT_EMPTY, INVALID_COLOUR, WID_CI_RAIL_DESC), SetMinimalTextLines(2, 0), SetFill(1, 0),
1737 NWidget(WWT_EMPTY, INVALID_COLOUR, WID_CI_RAIL_COUNT), SetMinimalTextLines(2, 0), SetFill(0, 1),
1738 EndContainer(),
1740 NWidget(WWT_EMPTY, INVALID_COLOUR, WID_CI_ROAD_DESC), SetMinimalTextLines(2, 0), SetFill(1, 0),
1741 NWidget(WWT_EMPTY, INVALID_COLOUR, WID_CI_ROAD_COUNT), SetMinimalTextLines(2, 0), SetFill(0, 1),
1742 EndContainer(),
1744 NWidget(WWT_EMPTY, INVALID_COLOUR, WID_CI_TRAM_DESC), SetMinimalTextLines(2, 0), SetFill(1, 0),
1745 NWidget(WWT_EMPTY, INVALID_COLOUR, WID_CI_TRAM_COUNT), SetMinimalTextLines(2, 0), SetFill(0, 1),
1746 EndContainer(),
1748 NWidget(WWT_EMPTY, INVALID_COLOUR, WID_CI_WATER_DESC), SetMinimalTextLines(2, 0), SetFill(1, 0),
1749 NWidget(WWT_EMPTY, INVALID_COLOUR, WID_CI_WATER_COUNT), SetMinimalTextLines(2, 0), SetFill(0, 1),
1750 EndContainer(),
1752 NWidget(WWT_EMPTY, INVALID_COLOUR, WID_CI_STATION_DESC), SetMinimalTextLines(3, 0), SetFill(1, 0),
1753 NWidget(WWT_EMPTY, INVALID_COLOUR, WID_CI_STATION_COUNT), SetMinimalTextLines(3, 0), SetFill(0, 1),
1754 EndContainer(),
1756 NWidget(WWT_EMPTY, INVALID_COLOUR, WID_CI_TOTAL_DESC), SetFill(1, 0),
1757 NWidget(WWT_EMPTY, INVALID_COLOUR, WID_CI_TOTAL), SetFill(0, 1),
1758 EndContainer(),
1759 EndContainer(),
1760 EndContainer(),
1761};
1762
1767{
1770
1771 uint total_width = 0;
1772
1774 {
1775 this->UpdateRailRoadTypes();
1776
1777 this->InitNested(window_number);
1778 this->owner = this->window_number;
1779 }
1780
1781 void UpdateRailRoadTypes()
1782 {
1783 this->railtypes = {};
1784 this->roadtypes = {};
1785
1786 /* Find the used railtypes. */
1787 for (const Engine *e : Engine::IterateType(VEH_TRAIN)) {
1788 if (!e->info.climates.Test(_settings_game.game_creation.landscape)) continue;
1789
1790 this->railtypes.Set(GetRailTypeInfo(e->u.rail.railtype)->introduces_railtypes);
1791 }
1792
1793 /* Get the date introduced railtypes as well. */
1795 this->railtypes.Reset(_railtypes_hidden_mask);
1796
1797 /* Find the used roadtypes. */
1798 for (const Engine *e : Engine::IterateType(VEH_ROAD)) {
1799 if (!e->info.climates.Test(_settings_game.game_creation.landscape)) continue;
1800
1801 this->roadtypes.Set(GetRoadTypeInfo(e->u.road.roadtype)->introduces_roadtypes);
1802 }
1803
1804 /* Get the date introduced roadtypes as well. */
1807 }
1808
1811 {
1812 const Company *c = Company::Get(this->window_number);
1813 Money total;
1814
1815 uint32_t rail_total = c->infrastructure.GetRailTotal();
1816 for (RailType rt = RAILTYPE_BEGIN; rt != RAILTYPE_END; rt++) {
1817 if (this->railtypes.Test(rt)) total += RailMaintenanceCost(rt, c->infrastructure.rail[rt], rail_total);
1818 }
1820
1821 uint32_t road_total = c->infrastructure.GetRoadTotal();
1822 uint32_t tram_total = c->infrastructure.GetTramTotal();
1823 for (RoadType rt = ROADTYPE_BEGIN; rt != ROADTYPE_END; rt++) {
1824 if (this->roadtypes.Test(rt)) total += RoadMaintenanceCost(rt, c->infrastructure.road[rt], RoadTypeIsRoad(rt) ? road_total : tram_total);
1825 }
1826
1829 total += AirportMaintenanceCost(c->index);
1830
1831 return total;
1832 }
1833
1834 std::string GetWidgetString(WidgetID widget, StringID stringid) const override
1835 {
1836 switch (widget) {
1837 case WID_CI_CAPTION:
1838 return GetString(STR_COMPANY_INFRASTRUCTURE_VIEW_CAPTION, this->window_number);
1839
1840 default:
1841 return this->Window::GetWidgetString(widget, stringid);
1842 }
1843 }
1844
1845 void UpdateWidgetSize(WidgetID widget, Dimension &size, [[maybe_unused]] const Dimension &padding, [[maybe_unused]] Dimension &fill, [[maybe_unused]] Dimension &resize) override
1846 {
1847 const Company *c = Company::Get(this->window_number);
1848
1849 switch (widget) {
1850 case WID_CI_RAIL_DESC: {
1851 uint lines = 1; // Starts at 1 because a line is also required for the section title
1852
1853 size.width = std::max(size.width, GetStringBoundingBox(STR_COMPANY_INFRASTRUCTURE_VIEW_RAIL_SECT).width + padding.width);
1854
1855 for (const auto &rt : _sorted_railtypes) {
1856 if (this->railtypes.Test(rt)) {
1857 lines++;
1858 size.width = std::max(size.width, GetStringBoundingBox(GetRailTypeInfo(rt)->strings.name).width + padding.width + WidgetDimensions::scaled.hsep_indent);
1859 }
1860 }
1861 if (this->railtypes.Any()) {
1862 lines++;
1863 size.width = std::max(size.width, GetStringBoundingBox(STR_COMPANY_INFRASTRUCTURE_VIEW_SIGNALS).width + padding.width + WidgetDimensions::scaled.hsep_indent);
1864 }
1865
1866 size.height = std::max(size.height, lines * GetCharacterHeight(FS_NORMAL));
1867 break;
1868 }
1869
1870 case WID_CI_ROAD_DESC:
1871 case WID_CI_TRAM_DESC: {
1872 uint lines = 1; // Starts at 1 because a line is also required for the section title
1873
1874 size.width = std::max(size.width, GetStringBoundingBox(widget == WID_CI_ROAD_DESC ? STR_COMPANY_INFRASTRUCTURE_VIEW_ROAD_SECT : STR_COMPANY_INFRASTRUCTURE_VIEW_TRAM_SECT).width + padding.width);
1875
1876 for (const auto &rt : _sorted_roadtypes) {
1877 if (this->roadtypes.Test(rt) && RoadTypeIsRoad(rt) == (widget == WID_CI_ROAD_DESC)) {
1878 lines++;
1879 size.width = std::max(size.width, GetStringBoundingBox(GetRoadTypeInfo(rt)->strings.name).width + padding.width + WidgetDimensions::scaled.hsep_indent);
1880 }
1881 }
1882
1883 size.height = std::max(size.height, lines * GetCharacterHeight(FS_NORMAL));
1884 break;
1885 }
1886
1887 case WID_CI_WATER_DESC:
1888 size.width = std::max(size.width, GetStringBoundingBox(STR_COMPANY_INFRASTRUCTURE_VIEW_WATER_SECT).width + padding.width);
1889 size.width = std::max(size.width, GetStringBoundingBox(STR_COMPANY_INFRASTRUCTURE_VIEW_CANALS).width + padding.width + WidgetDimensions::scaled.hsep_indent);
1890 break;
1891
1893 size.width = std::max(size.width, GetStringBoundingBox(STR_COMPANY_INFRASTRUCTURE_VIEW_STATION_SECT).width + padding.width);
1894 size.width = std::max(size.width, GetStringBoundingBox(STR_COMPANY_INFRASTRUCTURE_VIEW_STATIONS).width + padding.width + WidgetDimensions::scaled.hsep_indent);
1895 size.width = std::max(size.width, GetStringBoundingBox(STR_COMPANY_INFRASTRUCTURE_VIEW_AIRPORTS).width + padding.width + WidgetDimensions::scaled.hsep_indent);
1896 break;
1897
1898 case WID_CI_RAIL_COUNT:
1899 case WID_CI_ROAD_COUNT:
1900 case WID_CI_TRAM_COUNT:
1901 case WID_CI_WATER_COUNT:
1903 case WID_CI_TOTAL: {
1904 /* Find the maximum count that is displayed. */
1905 uint32_t max_val = 1000; // Some random number to reserve enough space.
1906 Money max_cost = 10000; // Some random number to reserve enough space.
1907 uint32_t rail_total = c->infrastructure.GetRailTotal();
1908 for (RailType rt = RAILTYPE_BEGIN; rt < RAILTYPE_END; rt++) {
1909 max_val = std::max(max_val, c->infrastructure.rail[rt]);
1910 max_cost = std::max(max_cost, RailMaintenanceCost(rt, c->infrastructure.rail[rt], rail_total));
1911 }
1912 max_val = std::max(max_val, c->infrastructure.signal);
1913 max_cost = std::max(max_cost, SignalMaintenanceCost(c->infrastructure.signal));
1914 uint32_t road_total = c->infrastructure.GetRoadTotal();
1915 uint32_t tram_total = c->infrastructure.GetTramTotal();
1916 for (RoadType rt = ROADTYPE_BEGIN; rt < ROADTYPE_END; rt++) {
1917 max_val = std::max(max_val, c->infrastructure.road[rt]);
1918 max_cost = std::max(max_cost, RoadMaintenanceCost(rt, c->infrastructure.road[rt], RoadTypeIsRoad(rt) ? road_total : tram_total));
1919
1920 }
1921 max_val = std::max(max_val, c->infrastructure.water);
1922 max_cost = std::max(max_cost, CanalMaintenanceCost(c->infrastructure.water));
1923 max_val = std::max(max_val, c->infrastructure.station);
1924 max_cost = std::max(max_cost, StationMaintenanceCost(c->infrastructure.station));
1925 max_val = std::max(max_val, c->infrastructure.airport);
1926 max_cost = std::max(max_cost, AirportMaintenanceCost(c->index));
1927
1928 uint count_width = GetStringBoundingBox(GetString(STR_JUST_COMMA, GetParamMaxValue(max_val))).width + WidgetDimensions::scaled.hsep_indent; // Reserve some wiggle room
1929
1931 StringID str_total = TimerGameEconomy::UsingWallclockUnits() ? STR_COMPANY_INFRASTRUCTURE_VIEW_TOTAL_PERIOD : STR_COMPANY_INFRASTRUCTURE_VIEW_TOTAL_YEAR;
1932 /* Convert to per year */
1933 this->total_width = GetStringBoundingBox(GetString(str_total, GetParamMaxValue(this->GetTotalMaintenanceCost() * 12))).width + WidgetDimensions::scaled.hsep_indent * 2;
1934 size.width = std::max(size.width, this->total_width);
1935
1936 /* Convert to per year */
1937 count_width += std::max(this->total_width, GetStringBoundingBox(GetString(str_total, GetParamMaxValue(max_cost * 12))).width);
1938 }
1939
1940 size.width = std::max(size.width, count_width);
1941
1942 /* Set height of the total line. */
1943 if (widget == WID_CI_TOTAL) {
1945 }
1946 break;
1947 }
1948 }
1949 }
1950
1958 void DrawCountLine(const Rect &r, int &y, int count, Money monthly_cost) const
1959 {
1960 Rect cr = r.Indent(this->total_width, _current_text_dir == TD_RTL);
1961 DrawString(cr.left, cr.right, y += GetCharacterHeight(FS_NORMAL), GetString(STR_JUST_COMMA, count), TC_WHITE, SA_RIGHT | SA_FORCE);
1962
1964 Rect tr = r.WithWidth(this->total_width, _current_text_dir == TD_RTL);
1965 DrawString(tr.left, tr.right, y,
1966 GetString(TimerGameEconomy::UsingWallclockUnits() ? STR_COMPANY_INFRASTRUCTURE_VIEW_TOTAL_PERIOD : STR_COMPANY_INFRASTRUCTURE_VIEW_TOTAL_YEAR, monthly_cost * 12),
1967 TC_FROMSTRING, SA_RIGHT | SA_FORCE);
1968 }
1969 }
1970
1971 void DrawWidget(const Rect &r, WidgetID widget) const override
1972 {
1973 const Company *c = Company::Get(this->window_number);
1974
1975 int y = r.top;
1976
1978 switch (widget) {
1979 case WID_CI_RAIL_DESC:
1980 DrawString(r.left, r.right, y, STR_COMPANY_INFRASTRUCTURE_VIEW_RAIL_SECT);
1981
1982 if (this->railtypes.Any()) {
1983 /* Draw name of each valid railtype. */
1984 for (const auto &rt : _sorted_railtypes) {
1985 if (this->railtypes.Test(rt)) {
1986 DrawString(ir.left, ir.right, y += GetCharacterHeight(FS_NORMAL), GetRailTypeInfo(rt)->strings.name, TC_WHITE);
1987 }
1988 }
1989 DrawString(ir.left, ir.right, y += GetCharacterHeight(FS_NORMAL), STR_COMPANY_INFRASTRUCTURE_VIEW_SIGNALS);
1990 } else {
1991 /* No valid railtype. */
1992 DrawString(ir.left, ir.right, y += GetCharacterHeight(FS_NORMAL), STR_COMPANY_VIEW_INFRASTRUCTURE_NONE);
1993 }
1994
1995 break;
1996
1997 case WID_CI_RAIL_COUNT: {
1998 /* Draw infrastructure count for each valid railtype. */
1999 uint32_t rail_total = c->infrastructure.GetRailTotal();
2000 for (const auto &rt : _sorted_railtypes) {
2001 if (this->railtypes.Test(rt)) {
2002 this->DrawCountLine(r, y, c->infrastructure.rail[rt], RailMaintenanceCost(rt, c->infrastructure.rail[rt], rail_total));
2003 }
2004 }
2005 if (this->railtypes.Any()) {
2007 }
2008 break;
2009 }
2010
2011 case WID_CI_ROAD_DESC:
2012 case WID_CI_TRAM_DESC: {
2013 DrawString(r.left, r.right, y, widget == WID_CI_ROAD_DESC ? STR_COMPANY_INFRASTRUCTURE_VIEW_ROAD_SECT : STR_COMPANY_INFRASTRUCTURE_VIEW_TRAM_SECT);
2014
2015 /* Draw name of each valid roadtype. */
2016 for (const auto &rt : _sorted_roadtypes) {
2017 if (this->roadtypes.Test(rt) && RoadTypeIsRoad(rt) == (widget == WID_CI_ROAD_DESC)) {
2018 DrawString(ir.left, ir.right, y += GetCharacterHeight(FS_NORMAL), GetRoadTypeInfo(rt)->strings.name, TC_WHITE);
2019 }
2020 }
2021
2022 break;
2023 }
2024
2025 case WID_CI_ROAD_COUNT:
2026 case WID_CI_TRAM_COUNT: {
2027 uint32_t road_tram_total = widget == WID_CI_ROAD_COUNT ? c->infrastructure.GetRoadTotal() : c->infrastructure.GetTramTotal();
2028 for (const auto &rt : _sorted_roadtypes) {
2029 if (this->roadtypes.Test(rt) && RoadTypeIsRoad(rt) == (widget == WID_CI_ROAD_COUNT)) {
2030 this->DrawCountLine(r, y, c->infrastructure.road[rt], RoadMaintenanceCost(rt, c->infrastructure.road[rt], road_tram_total));
2031 }
2032 }
2033 break;
2034 }
2035
2036 case WID_CI_WATER_DESC:
2037 DrawString(r.left, r.right, y, STR_COMPANY_INFRASTRUCTURE_VIEW_WATER_SECT);
2038 DrawString(ir.left, ir.right, y += GetCharacterHeight(FS_NORMAL), STR_COMPANY_INFRASTRUCTURE_VIEW_CANALS);
2039 break;
2040
2041 case WID_CI_WATER_COUNT:
2043 break;
2044
2045 case WID_CI_TOTAL:
2047 Rect tr = r.WithWidth(this->total_width, _current_text_dir == TD_RTL);
2048 GfxFillRect(tr.left, y, tr.right, y + WidgetDimensions::scaled.bevel.top - 1, PC_WHITE);
2050 DrawString(tr.left, tr.right, y,
2051 GetString(TimerGameEconomy::UsingWallclockUnits() ? STR_COMPANY_INFRASTRUCTURE_VIEW_TOTAL_PERIOD : STR_COMPANY_INFRASTRUCTURE_VIEW_TOTAL_YEAR, this->GetTotalMaintenanceCost() * 12),
2052 TC_FROMSTRING, SA_RIGHT | SA_FORCE);
2053 }
2054 break;
2055
2057 DrawString(r.left, r.right, y, STR_COMPANY_INFRASTRUCTURE_VIEW_STATION_SECT);
2058 DrawString(ir.left, ir.right, y += GetCharacterHeight(FS_NORMAL), STR_COMPANY_INFRASTRUCTURE_VIEW_STATIONS);
2059 DrawString(ir.left, ir.right, y += GetCharacterHeight(FS_NORMAL), STR_COMPANY_INFRASTRUCTURE_VIEW_AIRPORTS);
2060 break;
2061
2065 break;
2066 }
2067 }
2068
2074 void OnInvalidateData([[maybe_unused]] int data = 0, [[maybe_unused]] bool gui_scope = true) override
2075 {
2076 if (!gui_scope) return;
2077
2078 this->UpdateRailRoadTypes();
2079 this->ReInit();
2080 }
2081};
2082
2083static WindowDesc _company_infrastructure_desc(
2084 WDP_AUTO, "company_infrastructure", 0, 0,
2086 {},
2087 _nested_company_infrastructure_widgets
2088);
2089
2095{
2096 if (!Company::IsValidID(company)) return;
2097 AllocateWindowDescFront<CompanyInfrastructureWindow>(_company_infrastructure_desc, company);
2098}
2099
2100static constexpr NWidgetPart _nested_company_widgets[] = {
2102 NWidget(WWT_CLOSEBOX, COLOUR_GREY),
2103 NWidget(WWT_CAPTION, COLOUR_GREY, WID_C_CAPTION),
2104 NWidget(WWT_SHADEBOX, COLOUR_GREY),
2105 NWidget(WWT_STICKYBOX, COLOUR_GREY),
2106 EndContainer(),
2107 NWidget(WWT_PANEL, COLOUR_GREY),
2110 NWidget(WWT_EMPTY, INVALID_COLOUR, WID_C_FACE), SetMinimalSize(92, 119), SetFill(1, 0),
2111 NWidget(WWT_EMPTY, INVALID_COLOUR, WID_C_FACE_TITLE), SetFill(1, 1), SetMinimalTextLines(2, 0),
2112 EndContainer(),
2116 NWidget(WWT_TEXT, INVALID_COLOUR, WID_C_DESC_INAUGURATION), SetFill(1, 0),
2118 NWidget(WWT_LABEL, INVALID_COLOUR, WID_C_DESC_COLOUR_SCHEME), SetStringTip(STR_COMPANY_VIEW_COLOUR_SCHEME_TITLE),
2120 EndContainer(),
2122 NWidget(WWT_TEXT, INVALID_COLOUR, WID_C_DESC_VEHICLE), SetStringTip(STR_COMPANY_VIEW_VEHICLES_TITLE), SetAlignment(SA_LEFT | SA_TOP),
2124 EndContainer(),
2125 EndContainer(),
2128 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_C_VIEW_HQ), SetStringTip(STR_COMPANY_VIEW_VIEW_HQ_BUTTON, STR_COMPANY_VIEW_VIEW_HQ_TOOLTIP),
2129 NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_C_BUILD_HQ), SetStringTip(STR_COMPANY_VIEW_BUILD_HQ_BUTTON, STR_COMPANY_VIEW_BUILD_HQ_TOOLTIP),
2130 EndContainer(),
2132 NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_C_RELOCATE_HQ), SetStringTip(STR_COMPANY_VIEW_RELOCATE_HQ, STR_COMPANY_VIEW_RELOCATE_HQ_TOOLTIP),
2134 EndContainer(),
2135 EndContainer(),
2136 EndContainer(),
2137
2138 NWidget(WWT_TEXT, INVALID_COLOUR, WID_C_DESC_COMPANY_VALUE), SetFill(1, 0),
2139
2141 NWidget(WWT_TEXT, INVALID_COLOUR, WID_C_DESC_INFRASTRUCTURE), SetStringTip(STR_COMPANY_VIEW_INFRASTRUCTURE), SetAlignment(SA_LEFT | SA_TOP),
2144 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_C_VIEW_INFRASTRUCTURE), SetStringTip(STR_COMPANY_VIEW_INFRASTRUCTURE_BUTTON, STR_COMPANY_VIEW_INFRASTRUCTURE_TOOLTIP),
2145 EndContainer(),
2146 EndContainer(),
2147
2148 /* Multi player buttons. */
2152 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_C_HOSTILE_TAKEOVER), SetStringTip(STR_COMPANY_VIEW_HOSTILE_TAKEOVER_BUTTON, STR_COMPANY_VIEW_HOSTILE_TAKEOVER_TOOLTIP),
2153 EndContainer(),
2155 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_C_GIVE_MONEY), SetStringTip(STR_COMPANY_VIEW_GIVE_MONEY_BUTTON, STR_COMPANY_VIEW_GIVE_MONEY_TOOLTIP),
2156 EndContainer(),
2158 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_C_COMPANY_JOIN), SetStringTip(STR_COMPANY_VIEW_JOIN, STR_COMPANY_VIEW_JOIN_TOOLTIP),
2159 EndContainer(),
2160 EndContainer(),
2161 EndContainer(),
2162 EndContainer(),
2163 EndContainer(),
2164 EndContainer(),
2165 /* Button bars at the bottom. */
2168 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),
2169 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),
2170 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),
2171 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),
2172 EndContainer(),
2173 EndContainer(),
2174};
2175
2178 STR_COMPANY_VIEW_TRAINS, STR_COMPANY_VIEW_ROAD_VEHICLES, STR_COMPANY_VIEW_SHIPS, STR_COMPANY_VIEW_AIRCRAFT
2179};
2180
2185{
2186 CompanyWidgets query_widget{};
2187
2189 enum CompanyWindowPlanes : uint8_t {
2190 /* Display planes of the #WID_C_SELECT_VIEW_BUILD_HQ selection widget. */
2193
2194 /* Display planes of the #WID_C_SELECT_RELOCATE selection widget. */
2197 };
2198
2200 {
2201 this->InitNested(window_number);
2202 this->owner = this->window_number;
2203 this->OnInvalidateData();
2204 }
2205
2206 void OnPaint() override
2207 {
2208 const Company *c = Company::Get(this->window_number);
2209 bool local = this->window_number == _local_company;
2210
2211 if (!this->IsShaded()) {
2212 bool reinit = false;
2213
2214 /* Button bar selection. */
2215 reinit |= this->GetWidget<NWidgetStacked>(WID_C_SELECT_BUTTONS)->SetDisplayedPlane(local ? 0 : SZSP_NONE);
2216
2217 /* Build HQ button handling. */
2218 reinit |= this->GetWidget<NWidgetStacked>(WID_C_SELECT_VIEW_BUILD_HQ)->SetDisplayedPlane((local && c->location_of_HQ == INVALID_TILE) ? CWP_VB_BUILD : CWP_VB_VIEW);
2219
2221
2222 /* Enable/disable 'Relocate HQ' button. */
2223 reinit |= this->GetWidget<NWidgetStacked>(WID_C_SELECT_RELOCATE)->SetDisplayedPlane((!local || c->location_of_HQ == INVALID_TILE) ? CWP_RELOCATE_HIDE : CWP_RELOCATE_SHOW);
2224 /* Enable/disable 'Give money' button. */
2225 reinit |= this->GetWidget<NWidgetStacked>(WID_C_SELECT_GIVE_MONEY)->SetDisplayedPlane((local || _local_company == COMPANY_SPECTATOR || !_settings_game.economy.give_money) ? SZSP_NONE : 0);
2226 /* Enable/disable 'Hostile Takeover' button. */
2227 reinit |= this->GetWidget<NWidgetStacked>(WID_C_SELECT_HOSTILE_TAKEOVER)->SetDisplayedPlane((local || _local_company == COMPANY_SPECTATOR || !c->is_ai || _networking) ? SZSP_NONE : 0);
2228
2229 /* Multiplayer buttons. */
2230 reinit |= this->GetWidget<NWidgetStacked>(WID_C_SELECT_MULTIPLAYER)->SetDisplayedPlane((!_networking || !NetworkCanJoinCompany(c->index) || _local_company == c->index) ? (int)SZSP_NONE : 0);
2231
2233
2234 if (reinit) {
2235 this->ReInit();
2236 return;
2237 }
2238 }
2239
2240 this->DrawWidgets();
2241 }
2242
2243 void UpdateWidgetSize(WidgetID widget, Dimension &size, [[maybe_unused]] const Dimension &padding, [[maybe_unused]] Dimension &fill, [[maybe_unused]] Dimension &resize) override
2244 {
2245 switch (widget) {
2246 case WID_C_FACE:
2247 size = maxdim(size, GetScaledSpriteSize(SPR_GRADIENT));
2248 break;
2249
2251 Point offset;
2252 Dimension d = GetSpriteSize(SPR_VEH_BUS_SW_VIEW, &offset);
2253 d.width -= offset.x;
2254 d.height -= offset.y;
2255 size = maxdim(size, d);
2256 break;
2257 }
2258
2260 /* INT64_MAX is arguably the maximum company value */
2261 size.width = GetStringBoundingBox(GetString(STR_COMPANY_VIEW_COMPANY_VALUE, INT64_MAX)).width;
2262 break;
2263
2265 uint64_t max_value = GetParamMaxValue(5000); // Maximum number of vehicles
2266 for (const auto &count_string : _company_view_vehicle_count_strings) {
2267 size.width = std::max(size.width, GetStringBoundingBox(GetString(count_string, max_value)).width + padding.width);
2268 }
2269 break;
2270 }
2271
2273 uint64_t max_value = GetParamMaxValue(UINT_MAX);
2274 size.width = GetStringBoundingBox(GetString(STR_COMPANY_VIEW_INFRASTRUCTURE_RAIL, max_value)).width;
2275 size.width = std::max(size.width, GetStringBoundingBox(GetString(STR_COMPANY_VIEW_INFRASTRUCTURE_ROAD, max_value)).width);
2276 size.width = std::max(size.width, GetStringBoundingBox(GetString(STR_COMPANY_VIEW_INFRASTRUCTURE_WATER, max_value)).width);
2277 size.width = std::max(size.width, GetStringBoundingBox(GetString(STR_COMPANY_VIEW_INFRASTRUCTURE_STATION, max_value)).width);
2278 size.width = std::max(size.width, GetStringBoundingBox(GetString(STR_COMPANY_VIEW_INFRASTRUCTURE_AIRPORT, max_value)).width);
2279 size.width = std::max(size.width, GetStringBoundingBox(GetString(STR_COMPANY_VIEW_INFRASTRUCTURE_NONE, max_value)).width);
2280 size.width += padding.width;
2281 break;
2282 }
2283
2284 case WID_C_VIEW_HQ:
2285 case WID_C_BUILD_HQ:
2286 case WID_C_RELOCATE_HQ:
2288 case WID_C_GIVE_MONEY:
2290 case WID_C_COMPANY_JOIN:
2291 size.width = GetStringBoundingBox(STR_COMPANY_VIEW_VIEW_HQ_BUTTON).width;
2292 size.width = std::max(size.width, GetStringBoundingBox(STR_COMPANY_VIEW_BUILD_HQ_BUTTON).width);
2293 size.width = std::max(size.width, GetStringBoundingBox(STR_COMPANY_VIEW_RELOCATE_HQ).width);
2294 size.width = std::max(size.width, GetStringBoundingBox(STR_COMPANY_VIEW_INFRASTRUCTURE_BUTTON).width);
2295 size.width = std::max(size.width, GetStringBoundingBox(STR_COMPANY_VIEW_GIVE_MONEY_BUTTON).width);
2296 size.width = std::max(size.width, GetStringBoundingBox(STR_COMPANY_VIEW_HOSTILE_TAKEOVER_BUTTON).width);
2297 size.width = std::max(size.width, GetStringBoundingBox(STR_COMPANY_VIEW_JOIN).width);
2298 size.width += padding.width;
2299 break;
2300 }
2301 }
2302
2303 void DrawVehicleCountsWidget(const Rect &r, const Company *c) const
2304 {
2306
2307 int y = r.top;
2308 for (VehicleType type = VEH_BEGIN; type < VEH_COMPANY_END; type++) {
2309 uint amount = c->group_all[type].num_vehicle;
2310 if (amount != 0) {
2311 DrawString(r.left, r.right, y, GetString(_company_view_vehicle_count_strings[type], amount));
2313 }
2314 }
2315
2316 if (y == r.top) {
2317 /* No String was emitted before, so there must be no vehicles at all. */
2318 DrawString(r.left, r.right, y, STR_COMPANY_VIEW_VEHICLES_NONE);
2319 }
2320 }
2321
2322 void DrawInfrastructureCountsWidget(const Rect &r, const Company *c) const
2323 {
2324 int y = r.top;
2325
2326 uint rail_pieces = c->infrastructure.signal + c->infrastructure.GetRailTotal();
2327 if (rail_pieces != 0) {
2328 DrawString(r.left, r.right, y, GetString(STR_COMPANY_VIEW_INFRASTRUCTURE_RAIL, rail_pieces));
2330 }
2331
2332 /* GetRoadTotal() skips tram pieces, but we actually want road and tram here. */
2333 uint road_pieces = std::accumulate(std::begin(c->infrastructure.road), std::end(c->infrastructure.road), 0U);
2334 if (road_pieces != 0) {
2335 DrawString(r.left, r.right, y, GetString(STR_COMPANY_VIEW_INFRASTRUCTURE_ROAD, road_pieces));
2337 }
2338
2339 if (c->infrastructure.water != 0) {
2340 DrawString(r.left, r.right, y, GetString(STR_COMPANY_VIEW_INFRASTRUCTURE_WATER, c->infrastructure.water));
2342 }
2343
2344 if (c->infrastructure.station != 0) {
2345 DrawString(r.left, r.right, y, GetString(STR_COMPANY_VIEW_INFRASTRUCTURE_STATION, c->infrastructure.station));
2347 }
2348
2349 if (c->infrastructure.airport != 0) {
2350 DrawString(r.left, r.right, y, GetString(STR_COMPANY_VIEW_INFRASTRUCTURE_AIRPORT, c->infrastructure.airport));
2352 }
2353
2354 if (y == r.top) {
2355 /* No String was emitted before, so there must be no infrastructure at all. */
2356 DrawString(r.left, r.right, y, STR_COMPANY_VIEW_INFRASTRUCTURE_NONE);
2357 }
2358 }
2359
2360 void DrawWidget(const Rect &r, WidgetID widget) const override
2361 {
2362 const Company *c = Company::Get(this->window_number);
2363 switch (widget) {
2364 case WID_C_FACE:
2366 break;
2367
2368 case WID_C_FACE_TITLE:
2369 DrawStringMultiLine(r, GetString(STR_COMPANY_VIEW_PRESIDENT_MANAGER_TITLE, c->index), TC_FROMSTRING, SA_HOR_CENTER);
2370 break;
2371
2373 Point offset;
2374 Dimension d = GetSpriteSize(SPR_VEH_BUS_SW_VIEW, &offset);
2375 d.height -= offset.y;
2376 DrawSprite(SPR_VEH_BUS_SW_VIEW, COMPANY_SPRITE_COLOUR(c->index), r.left - offset.x, CenterBounds(r.top, r.bottom, d.height) - offset.y);
2377 break;
2378 }
2379
2381 DrawVehicleCountsWidget(r, c);
2382 break;
2383
2385 DrawInfrastructureCountsWidget(r, c);
2386 break;
2387 }
2388 }
2389
2390 std::string GetWidgetString(WidgetID widget, StringID stringid) const override
2391 {
2392 switch (widget) {
2393 case WID_C_CAPTION:
2394 return GetString(STR_COMPANY_VIEW_CAPTION, this->window_number, this->window_number);
2395
2397 const Company &c = *Company::Get(this->window_number);
2399 return GetString(STR_COMPANY_VIEW_INAUGURATED_TITLE_WALLCLOCK, c.inaugurated_year_calendar, c.inaugurated_year);
2400 }
2401 return GetString(STR_COMPANY_VIEW_INAUGURATED_TITLE, c.inaugurated_year);
2402 }
2403
2405 return GetString(STR_COMPANY_VIEW_COMPANY_VALUE, CalculateCompanyValue(Company::Get(this->window_number)));
2406
2407 default:
2408 return this->Window::GetWidgetString(widget, stringid);
2409 }
2410 }
2411
2412 void OnResize() override
2413 {
2414 NWidgetResizeBase *wid = this->GetWidget<NWidgetResizeBase>(WID_C_FACE_TITLE);
2415 int y = GetStringHeight(GetString(STR_COMPANY_VIEW_PRESIDENT_MANAGER_TITLE, this->owner), wid->current_x);
2416 if (wid->UpdateVerticalSize(y)) this->ReInit(0, 0);
2417 }
2418
2419 void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override
2420 {
2421 switch (widget) {
2422 case WID_C_NEW_FACE: DoSelectCompanyManagerFace(this); break;
2423
2425 ShowCompanyLiveryWindow(this->window_number, GroupID::Invalid());
2426 break;
2427
2429 this->query_widget = WID_C_PRESIDENT_NAME;
2430 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});
2431 break;
2432
2433 case WID_C_COMPANY_NAME:
2434 this->query_widget = WID_C_COMPANY_NAME;
2435 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});
2436 break;
2437
2438 case WID_C_VIEW_HQ: {
2439 TileIndex tile = Company::Get(this->window_number)->location_of_HQ;
2440 if (_ctrl_pressed) {
2442 } else {
2444 }
2445 break;
2446 }
2447
2448 case WID_C_BUILD_HQ:
2449 if (this->window_number != _local_company) return;
2450 if (this->IsWidgetLowered(WID_C_BUILD_HQ)) {
2452 this->RaiseButtons();
2453 break;
2454 }
2455 SetObjectToPlaceWnd(SPR_CURSOR_HQ, PAL_NONE, HT_RECT, this);
2456 SetTileSelectSize(2, 2);
2459 break;
2460
2461 case WID_C_RELOCATE_HQ:
2464 this->RaiseButtons();
2465 break;
2466 }
2467 SetObjectToPlaceWnd(SPR_CURSOR_HQ, PAL_NONE, HT_RECT, this);
2468 SetTileSelectSize(2, 2);
2471 break;
2472
2475 break;
2476
2477 case WID_C_GIVE_MONEY:
2478 this->query_widget = WID_C_GIVE_MONEY;
2479 ShowQueryString({}, STR_COMPANY_VIEW_GIVE_MONEY_QUERY_CAPTION, 30, this, CS_NUMERAL, {});
2480 break;
2481
2484 break;
2485
2486 case WID_C_COMPANY_JOIN: {
2487 this->query_widget = WID_C_COMPANY_JOIN;
2488 CompanyID company = this->window_number;
2489 if (_network_server) {
2492 } else {
2493 /* just send the join command */
2494 NetworkClientRequestMove(company);
2495 }
2496 break;
2497 }
2498 }
2499 }
2500
2502 IntervalTimer<TimerWindow> redraw_interval = {std::chrono::seconds(3), [this](auto) {
2503 this->SetDirty();
2504 }};
2505
2506 void OnPlaceObject([[maybe_unused]] Point pt, TileIndex tile) override
2507 {
2508 if (Command<CMD_BUILD_OBJECT>::Post(STR_ERROR_CAN_T_BUILD_COMPANY_HEADQUARTERS, tile, OBJECT_HQ, 0) && !_shift_pressed) {
2510 this->RaiseButtons();
2511 }
2512 }
2513
2514 void OnPlaceObjectAbort() override
2515 {
2516 this->RaiseButtons();
2517 }
2518
2519 void OnQueryTextFinished(std::optional<std::string> str) override
2520 {
2521 if (!str.has_value()) return;
2522
2523 switch (this->query_widget) {
2524 default: NOT_REACHED();
2525
2526 case WID_C_GIVE_MONEY: {
2527 Money money = std::strtoull(str->c_str(), nullptr, 10) / GetCurrency().rate;
2528 Command<CMD_GIVE_MONEY>::Post(STR_ERROR_CAN_T_GIVE_MONEY, money, this->window_number);
2529 break;
2530 }
2531
2533 Command<CMD_RENAME_PRESIDENT>::Post(STR_ERROR_CAN_T_CHANGE_PRESIDENT, *str);
2534 break;
2535
2536 case WID_C_COMPANY_NAME:
2537 Command<CMD_RENAME_COMPANY>::Post(STR_ERROR_CAN_T_CHANGE_COMPANY_NAME, *str);
2538 break;
2539 }
2540 }
2541
2542 void OnInvalidateData([[maybe_unused]] int data = 0, [[maybe_unused]] bool gui_scope = true) override
2543 {
2544 if (gui_scope && data == 1) {
2545 /* Manually call OnResize to adjust minimum height of president name widget. */
2546 OnResize();
2547 }
2548 }
2549};
2550
2551static WindowDesc _company_desc(
2552 WDP_AUTO, "company", 0, 0,
2554 {},
2555 _nested_company_widgets
2556);
2557
2563{
2564 if (!Company::IsValidID(company)) return;
2565
2566 AllocateWindowDescFront<CompanyWindow>(_company_desc, company);
2567}
2568
2578
2581 {
2582 this->InitNested(window_number);
2583
2584 const Company *c = Company::Get(this->window_number);
2585 this->company_value = hostile_takeover ? CalculateHostileTakeoverValue(c) : c->bankrupt_value;
2586 }
2587
2588 void UpdateWidgetSize(WidgetID widget, Dimension &size, [[maybe_unused]] const Dimension &padding, [[maybe_unused]] Dimension &fill, [[maybe_unused]] Dimension &resize) override
2589 {
2590 switch (widget) {
2591 case WID_BC_FACE:
2592 size = GetScaledSpriteSize(SPR_GRADIENT);
2593 break;
2594
2595 case WID_BC_QUESTION:
2596 const Company *c = Company::Get(this->window_number);
2597 size.height = GetStringHeight(GetString(this->hostile_takeover ? STR_BUY_COMPANY_HOSTILE_TAKEOVER : STR_BUY_COMPANY_MESSAGE, c->index, this->company_value), size.width);
2598 break;
2599 }
2600 }
2601
2602 std::string GetWidgetString(WidgetID widget, StringID stringid) const override
2603 {
2604 switch (widget) {
2605 case WID_BC_CAPTION:
2606 return GetString(STR_ERROR_MESSAGE_CAPTION_OTHER_COMPANY, Company::Get(this->window_number)->index);
2607
2608 default:
2609 return this->Window::GetWidgetString(widget, stringid);
2610 }
2611 }
2612
2613 void DrawWidget(const Rect &r, WidgetID widget) const override
2614 {
2615 switch (widget) {
2616 case WID_BC_FACE: {
2617 const Company *c = Company::Get(this->window_number);
2619 break;
2620 }
2621
2622 case WID_BC_QUESTION: {
2623 const Company *c = Company::Get(this->window_number);
2624 DrawStringMultiLine(r, GetString(this->hostile_takeover ? STR_BUY_COMPANY_HOSTILE_TAKEOVER : STR_BUY_COMPANY_MESSAGE, c->index, this->company_value), TC_FROMSTRING, SA_CENTER);
2625 break;
2626 }
2627 }
2628 }
2629
2630 void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override
2631 {
2632 switch (widget) {
2633 case WID_BC_NO:
2634 this->Close();
2635 break;
2636
2637 case WID_BC_YES:
2638 Command<CMD_BUY_COMPANY>::Post(STR_ERROR_CAN_T_BUY_COMPANY, this->window_number, this->hostile_takeover);
2639 break;
2640 }
2641 }
2642
2646 IntervalTimer<TimerWindow> rescale_interval = {std::chrono::seconds(3), [this](auto) {
2647 /* Value can't change when in bankruptcy. */
2648 if (!this->hostile_takeover) return;
2649
2650 const Company *c = Company::Get(this->window_number);
2651 auto new_value = CalculateHostileTakeoverValue(c);
2652 if (new_value != this->company_value) {
2653 this->company_value = new_value;
2654 this->ReInit();
2655 }
2656 }};
2657
2658private:
2659 bool hostile_takeover = false;
2661};
2662
2663static constexpr NWidgetPart _nested_buy_company_widgets[] = {
2665 NWidget(WWT_CLOSEBOX, COLOUR_LIGHT_BLUE),
2666 NWidget(WWT_CAPTION, COLOUR_LIGHT_BLUE, WID_BC_CAPTION),
2667 EndContainer(),
2668 NWidget(WWT_PANEL, COLOUR_LIGHT_BLUE),
2671 NWidget(WWT_EMPTY, INVALID_COLOUR, WID_BC_FACE), SetFill(0, 1),
2672 NWidget(WWT_EMPTY, INVALID_COLOUR, WID_BC_QUESTION), SetMinimalSize(240, 0), SetFill(1, 1),
2673 EndContainer(),
2675 NWidget(WWT_TEXTBTN, COLOUR_LIGHT_BLUE, WID_BC_NO), SetMinimalSize(60, 12), SetStringTip(STR_QUIT_NO), SetFill(1, 0),
2676 NWidget(WWT_TEXTBTN, COLOUR_LIGHT_BLUE, WID_BC_YES), SetMinimalSize(60, 12), SetStringTip(STR_QUIT_YES), SetFill(1, 0),
2677 EndContainer(),
2678 EndContainer(),
2679 EndContainer(),
2680};
2681
2682static WindowDesc _buy_company_desc(
2683 WDP_AUTO, nullptr, 0, 0,
2686 _nested_buy_company_widgets
2687);
2688
2694void ShowBuyCompanyDialog(CompanyID company, bool hostile_takeover)
2695{
2696 auto window = BringWindowToFrontById(WC_BUY_COMPANY, company);
2697 if (window == nullptr) {
2698 new BuyCompanyWindow(_buy_company_desc, company, hostile_takeover);
2699 }
2700}
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.
debug_inline static constexpr uint GB(const T x, const uint8_t s, const uint8_t n)
Fetch n bits from x, started at bit s.
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.
constexpr bool Test(Tvalue_type value) const
Test if the value-th bit is set.
constexpr Timpl & Set()
Set all bits.
constexpr bool Any(const Timpl &other) const
Test if any of the given values are set.
constexpr Timpl & Reset(Tvalue_type value)
Reset the value-th bit.
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.
bool IsDisabled() const
Return whether the widget is disabled.
void SetStringTip(StringID string, StringID tool_tip)
Set string and tool tip of the nested widget.
Definition widget.cpp:1138
Base class for a resizable nested widget.
bool UpdateVerticalSize(uint min_y)
Set absolute (post-scaling) minimal size of the widget.
Definition widget.cpp:1094
RailTypes introduces_railtypes
Bitmask of which other railtypes are introduced when this railtype is introduced.
Definition rail.h:257
StringID name
Name of this rail type.
Definition rail.h:167
RoadTypes introduces_roadtypes
Bitmask of which other roadtypes are introduced when this roadtype is introduced.
Definition road.h:168
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:2449
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:2523
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.
std::string GetFaceString(WidgetID widget_index, uint8_t val, bool is_bool_widget) const
Get the string for the value of face control buttons.
void SelectDisplayPlanes(bool advanced)
Select planes to display to the user with the NWID_SELECTION widgets WID_SCMF_SEL_LOADSAVE,...
std::string GetWidgetString(WidgetID widget, StringID stringid) const override
Get the raw string for a 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.
bool advanced
advanced company manager face selection window
bool is_moust_male
Male face with a moustache.
GenderEthnicity ge
Gender and ethnicity.
Dimension yesno_dim
Dimension of a yes/no button of a part in the advanced face window.
void DrawWidget(const Rect &r, WidgetID widget) const override
Draw the contents of a nested widget.
CompanyManagerFace face
company manager face bits
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 OnInit() override
Notification that the nested widget tree gets initialized.
void OnPaint() override
The window must be repainted.
Dimension number_dim
Dimension of a number widget of a part in the advanced face window.
static constexpr TimerGame< struct Calendar >::Date MAX_DATE
The date of the last day of the max year.
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
static WidgetDimensions scaled
Widget dimensions scaled for current zoom level.
Definition window_gui.h:29
RectPadding imgbtn
Padding around image button image.
Definition window_gui.h:34
int vsep_normal
Normal vertical spacing.
Definition window_gui.h:58
int vsep_wide
Wide vertical spacing.
Definition window_gui.h:60
static const WidgetDimensions unscaled
Unscaled widget dimensions.
Definition window_gui.h:94
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
CompanyID _local_company
Company controlled by the human player at this client. Can also be COMPANY_SPECTATOR.
CompanyManagerFace _company_manager_face
for company manager face storage in openttd.cfg
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 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 WindowDesc _select_company_manager_face_desc(WDP_AUTO, nullptr, 0, 0, WC_COMPANY_MANAGER_FACE, WC_NONE, WindowDefaultFlag::Construction, _nested_select_company_manager_face_widgets)
Company manager face selection window description.
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(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.
uint GetCompanyManagerFaceBits(CompanyManagerFace cmf, CompanyManagerFaceVariable cmfv, GenderEthnicity ge)
Make sure the table's size is right.
void SetCompanyManagerFaceBits(CompanyManagerFace &cmf, CompanyManagerFaceVariable cmfv, GenderEthnicity ge, uint val)
Sets the company manager's face bits for the given company manager's face variable.
GenderEthnicity
The gender/race combinations that we have faces for.
@ GE_WM
A male of Caucasian origin (white)
@ ETHNICITY_BLACK
This bit set means black, otherwise white.
@ GENDER_FEMALE
This bit set means a female, otherwise male.
void RandomCompanyManagerFaceBits(CompanyManagerFace &cmf, GenderEthnicity ge, bool adv, Randomizer &randomizer)
Make a random new face.
void ScaleAllCompanyManagerFaceBits(CompanyManagerFace &cmf)
Scales all company manager's face bits to the correct scope.
CompanyManagerFaceVariable
Bitgroups of the CompanyManagerFace variable.
static const CompanyManagerFaceBitsInfo _cmf_info[]
Lookup table for indices into the CompanyManagerFace, valid ranges and sprites.
void IncreaseCompanyManagerFaceBits(CompanyManagerFace &cmf, CompanyManagerFaceVariable cmfv, GenderEthnicity ge, int8_t amount)
Increase/Decrease the company manager's face variable by the given amount.
SpriteID GetCompanyManagerFaceSprite(CompanyManagerFace cmf, CompanyManagerFaceVariable cmfv, GenderEthnicity ge)
Gets the sprite to draw for the given company manager's face variable.
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.
uint32_t CompanyManagerFace
Company manager face bits, info see in company_manager_face.h.
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_NOSE_L
Nose left.
@ WID_SCMF_COLLAR_TEXT
Text about collar.
@ WID_SCMF_HAIR
Hair.
@ WID_SCMF_EYECOLOUR_L
Eyecolour left.
@ WID_SCMF_CAPTION
Caption of window.
@ WID_SCMF_TOGGLE_LARGE_SMALL_BUTTON
Toggle for large or small.
@ WID_SCMF_ETHNICITY_EUR
Text about ethnicity european.
@ WID_SCMF_CHIN_R
Chin right.
@ WID_SCMF_EYEBROWS
Eyebrows.
@ WID_SCMF_COLLAR
Collar.
@ WID_SCMF_GLASSES_R
Glasses right.
@ WID_SCMF_JACKET_L
Jacket left.
@ WID_SCMF_CHIN
Chin.
@ WID_SCMF_LIPS_MOUSTACHE_TEXT
Text about lips and moustache.
@ WID_SCMF_SELECT_FACE
Select face.
@ WID_SCMF_LIPS_MOUSTACHE
Lips / Moustache.
@ WID_SCMF_RANDOM_NEW_FACE
Create random new face.
@ WID_SCMF_GLASSES_TEXT
Text about glasses.
@ WID_SCMF_EYEBROWS_L
Eyebrows left.
@ WID_SCMF_GLASSES
Glasses.
@ WID_SCMF_LIPS_MOUSTACHE_L
Lips / Moustache left.
@ WID_SCMF_EYEBROWS_R
Eyebrows right.
@ WID_SCMF_SEL_PARTS
Selection to display the buttons for setting each part of the face in the advanced view.
@ WID_SCMF_CHIN_L
Chin left.
@ WID_SCMF_GLASSES_L
Glasses left.
@ WID_SCMF_FEMALE2
Female button in the advanced view.
@ WID_SCMF_NOSE
Nose.
@ WID_SCMF_TIE_EARRING_R
Tie / Earring right.
@ WID_SCMF_CANCEL
Cancel.
@ WID_SCMF_HAIR_TEXT
Text about hair.
@ WID_SCMF_EYECOLOUR_R
Eyecolour right.
@ WID_SCMF_NOSE_R
Nose right.
@ WID_SCMF_CHIN_TEXT
Text about chin.
@ WID_SCMF_TIE_EARRING
Tie / Earring.
@ WID_SCMF_SAVE
Save face.
@ WID_SCMF_NOSE_TEXT
Text about nose.
@ WID_SCMF_MALE
Male button in the simple view.
@ WID_SCMF_SEL_LOADSAVE
Selection to display the load/save/number buttons in the advanced view.
@ WID_SCMF_ETHNICITY_AFR
Text about ethnicity african.
@ WID_SCMF_FACE
Current face.
@ WID_SCMF_JACKET_R
Jacket right.
@ WID_SCMF_TIE_EARRING_L
Tie / Earring left.
@ WID_SCMF_LOAD
Load face.
@ WID_SCMF_ACCEPT
Accept.
@ WID_SCMF_MALE2
Male button in the advanced view.
@ WID_SCMF_EYECOLOUR_TEXT
Text about eyecolour.
@ WID_SCMF_COLLAR_L
Collar left.
@ WID_SCMF_HAS_GLASSES_TEXT
Text about glasses.
@ WID_SCMF_HAS_MOUSTACHE_EARRING_TEXT
Text about moustache and earring.
@ WID_SCMF_JACKET
Jacket.
@ WID_SCMF_SEL_MALEFEMALE
Selection to display the male/female buttons in the simple view.
@ WID_SCMF_JACKET_TEXT
Text about jacket.
@ WID_SCMF_TOGGLE_LARGE_SMALL
Toggle for large or small.
@ WID_SCMF_FACECODE
Get the face code.
@ WID_SCMF_EYECOLOUR
Eyecolour.
@ WID_SCMF_EYEBROWS_TEXT
Text about eyebrows.
@ WID_SCMF_HAIR_L
Hair left.
@ WID_SCMF_LIPS_MOUSTACHE_R
Lips / Moustache right.
@ WID_SCMF_TIE_EARRING_TEXT
Text about tie and earring.
@ WID_SCMF_FEMALE
Female button in the simple view.
@ WID_SCMF_HAS_GLASSES
Has glasses.
@ WID_SCMF_COLLAR_R
Collar right.
@ WID_SCMF_HAS_MOUSTACHE_EARRING
Has moustache or earring.
@ WID_SCMF_HAIR_R
Hair right.
@ 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_RAIL_COUNT
Count of rail.
@ WID_CI_WATER_DESC
Description of water.
@ WID_CI_TRAM_COUNT
Count of tram.
@ WID_CI_ROAD_DESC
Description of road.
@ WID_CI_CAPTION
Caption of window.
@ WID_CI_STATION_DESC
Description of station.
@ WID_CI_WATER_COUNT
Count of water.
@ WID_CI_TOTAL_DESC
Description of total.
@ WID_CI_TOTAL
Count of total.
@ WID_CI_STATION_COUNT
Count of station.
@ WID_CI_TRAM_DESC
Description of tram.
@ WID_CI_RAIL_DESC
Description of rail.
@ WID_CI_ROAD_COUNT
Count of road.
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:407
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 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:923
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:852
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
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:989
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:67
int CenterBounds(int min, int max, int size)
Determine where to draw a centred object inside a widget.
Definition gfx_func.h:166
@ FS_NORMAL
Index of the normal font in the font tables.
Definition gfx_type.h:245
@ SA_TOP
Top align the text.
Definition gfx_type.h:382
@ SA_LEFT
Left align the text.
Definition gfx_type.h:377
@ SA_RIGHT
Right align the text (must be a single bit).
Definition gfx_type.h:379
@ SA_HOR_CENTER
Horizontally center the text.
Definition gfx_type.h:378
@ SA_FORCE
Force the alignment, i.e. don't swap for RTL languages.
Definition gfx_type.h:389
@ SA_CENTER
Center both horizontally and vertically.
Definition gfx_type.h:387
@ SA_VERT_CENTER
Vertically center the text.
Definition gfx_type.h:383
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:296
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 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 SetTextStyle(TextColour colour, FontSize size=FS_NORMAL)
Widget part function for setting the text style.
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 SetArrowWidgetTypeTip(ArrowWidgetValues widget_type, StringID tip={})
Widget part function for setting the arrow widget type and tooltip.
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:945
void MarkWholeScreenDirty()
This function mark the whole screen as dirty.
Definition gfx.cpp:1500
void BuildGuiGroupList(GUIGroupList &dst, 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
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:66
bool _network_server
network-server is active
Definition network.cpp:67
bool NetworkCanJoinCompany(CompanyID company_id)
Returns whether the given company can be joined by this client.
Definition network.cpp:142
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:72
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.
RailTypes AddDateIntroducedRailTypes(RailTypes current, TimerGameCalendar::Date date)
Add the rail types that are to be introduced at the given date.
Definition rail.cpp:220
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
@ RAILTYPE_BEGIN
Used for iterations.
Definition rail_type.h:26
@ RAILTYPE_END
Used for iterations.
Definition rail_type.h:31
Randomizer _interactive_random
Random used everywhere else, where it does not (directly) influence the game state.
RoadTypes AddDateIntroducedRoadTypes(RoadTypes current, TimerGameCalendar::Date date)
Add the road types that are to be introduced at the given date.
Definition road.cpp:165
Road specific functions.
RoadTypes _roadtypes_hidden_mask
Bitset of hidden roadtypes.
Definition road_cmd.cpp:56
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
@ ROADTYPE_END
Used for iterations.
Definition road_type.h:27
@ ROADTYPE_BEGIN
Used for iterations.
Definition road_type.h:24
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:59
ClientSettings _settings_client
The current settings for this game.
Definition settings.cpp:58
Base types for having sorted lists in GUIs.
Money AirportMaintenanceCost(Owner owner)
Calculates the maintenance cost of all airports of a company.
Definition station.cpp:712
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
@ 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:246
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:424
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.
IntervalTimer< TimerWindow > rescale_interval
Check on a regular interval if the company value has changed.
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.
GUISettings gui
settings related to the GUI
Window class displaying the company finances.
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.
IntervalTimer< TimerWindow > rescale_interval
Check on a regular interval if the maximum amount of money has changed.
void OnPaint() override
The window must be repainted.
Window with detailed information about the company's infrastructure.
Money GetTotalMaintenanceCost() const
Get total infrastructure maintenance cost.
void DrawCountLine(const Rect &r, int &y, int count, Money monthly_cost) const
Helper for drawing the counts line.
RoadTypes roadtypes
Valid roadtypes.
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.
uint total_width
String width of the total cost line.
RailTypes railtypes
Valid railtypes.
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.
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.
uint8_t valid_values[GE_END]
The number of valid values per gender/ethnicity.
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.
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.
IntervalTimer< TimerWindow > redraw_interval
Redraw the window on a regular interval.
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.
bool has_2CC
Set if any vehicle is loaded which uses 2cc (two company colours).
Definition newgrf.h:187
uint64_t used_liveries
Bitmask of LiveryScheme used by the defined engines.
Definition newgrf.h:188
uint8_t liveries
options for displaying company liveries, 0=none, 1=self, 2=all
LandscapeType landscape
the landscape we're currently in
EconomySettings economy
settings to change the economy
DifficultySettings difficulty
settings related to the difficulty
GameCreationSettings game_creation
settings used during the creation of a game (map)
Group data.
Definition group.h:72
Livery livery
Custom colour scheme for vehicles in this group.
Definition group.h:78
GroupID parent
Parent group.
Definition group.h:83
VehicleType vehicle_type
Vehicle type of the group.
Definition group.h:75
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.
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 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.
uint step_height
Step-size of height resize changes.
Definition window_gui.h:213
Company livery colour scheme window.
void OnInvalidateData(int data=0, bool gui_scope=true) override
Some data on this window has become invalid.
void OnDropdownSelect(WidgetID widget, int index) override
A dropdown option associated to this window has been selected.
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.
High level window description.
Definition window_gui.h:168
Number to differentiate different windows of the same class.
Data structure for an opened window.
Definition window_gui.h:274
void ReInit(int rx=0, int ry=0, bool reposition=false)
Re-initialize a window, and optionally change its size.
Definition window.cpp:957
virtual void Close(int data=0)
Hide the window and all its child windows, and mark them for a later deletion.
Definition window.cpp:1052
void FinishInitNested(WindowNumber window_number=0)
Perform the second part of the initialization of a nested widget tree.
Definition window.cpp:1736
void DrawWidgets() const
Paint all widgets of a window.
Definition widget.cpp:744
void InvalidateData(int data=0, bool gui_scope=true)
Mark this window's data as invalid (in need of re-computing)
Definition window.cpp:3164
Window * parent
Parent window.
Definition window_gui.h:329
void RaiseWidget(WidgetID widget_index)
Marks a widget as raised.
Definition window_gui.h:470
void SetWidgetDirty(WidgetID widget_index) const
Invalidate a widget, i.e.
Definition window.cpp:556
virtual std::string GetWidgetString(WidgetID widget, StringID stringid) const
Get the raw string for a widget.
Definition window.cpp:504
ResizeInfo resize
Resize information.
Definition window_gui.h:315
void SetShaded(bool make_shaded)
Set the shaded state of the window to make_shaded.
Definition window.cpp:1000
void SetWidgetsDisabledState(bool disab_stat, Args... widgets)
Sets the enabled/disabled status of a list of widgets.
Definition window_gui.h:516
void CreateNestedTree()
Perform the first part of the initialization of a nested widget tree.
Definition window.cpp:1726
bool IsWidgetLowered(WidgetID widget_index) const
Gets the lowered state of a widget.
Definition window_gui.h:492
void RaiseButtons(bool autoraise=false)
Raise the buttons of the window.
Definition window.cpp:530
void SetWidgetsLoweredState(bool lowered_stat, Args... widgets)
Sets the lowered/raised status of a list of widgets.
Definition window_gui.h:527
Owner owner
The owner of the content shown in this window. Company colour is acquired from this variable.
Definition window_gui.h:317
void SetWidgetLoweredState(WidgetID widget_index, bool lowered_stat)
Sets the lowered/raised status of a widget.
Definition window_gui.h:442
void EnableWidget(WidgetID widget_index)
Sets a widget to Enabled.
Definition window_gui.h:401
bool IsShaded() const
Is window shaded currently?
Definition window_gui.h:558
void LowerWidget(WidgetID widget_index)
Marks a widget as lowered.
Definition window_gui.h:461
void InitNested(WindowNumber number=0)
Perform complete initialization of the Window with nested widgets, to allow use.
Definition window.cpp:1749
const Scrollbar * GetScrollbar(WidgetID widnum) const
Return the Scrollbar to a widget index.
Definition window.cpp:313
void SetWidgetDisabledState(WidgetID widget_index, bool disab_stat)
Sets the enabled/disabled status of a widget.
Definition window_gui.h:382
int width
width of the window (number of pixels to the right in x direction)
Definition window_gui.h:312
WindowNumber window_number
Window number within the window class.
Definition window_gui.h:303
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_PUSHARROWBTN
Normal push-button (no toggle button) with arrow caption.
@ WWT_LABEL
Centered label.
Definition widget_type.h:47
@ NWID_SPACER
Invisible widget that takes some space.
Definition widget_type.h:69
@ NWID_HORIZONTAL
Horizontal container.
Definition widget_type.h:65
@ 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:56
@ WWT_MATRIX
Grid of rows and columns.
Definition widget_type.h:49
@ WWT_SHADEBOX
Shade box (at top-right of a window, between WWT_DEBUGBOX and WWT_DEFSIZEBOX)
Definition widget_type.h:54
@ WWT_CAPTION
Window caption (window title between closebox and stickybox)
Definition widget_type.h:51
@ NWID_VSCROLLBAR
Vertical scrollbar.
Definition widget_type.h:75
@ NWID_VERTICAL
Vertical container.
Definition widget_type.h:67
@ WWT_CLOSEBOX
Close box (at top-left of a window)
Definition widget_type.h:59
@ 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:58
@ WWT_DEFSIZEBOX
Default window size box (at top-right of a window, between WWT_SHADEBOX and WWT_STICKYBOX)
Definition widget_type.h:55
@ WWT_DROPDOWN
Drop down list.
Definition widget_type.h:60
@ WWT_TEXT
Pure simple text.
Definition widget_type.h:48
@ NWID_SELECTION
Stacked widgets, only one visible at a time (eg in a panel with tabs).
Definition widget_type.h:70
@ SZSP_NONE
Display plane with zero size in both directions (none filling and resizing).
@ EqualSize
Containers should keep all their (resizing) children equally large.
@ AWV_DECREASE
Arrow to the left or in case of RTL to the right.
Definition widget_type.h:21
@ AWV_INCREASE
Arrow to the right or in case of RTL to the left.
Definition widget_type.h:22
Window * BringWindowToFrontById(WindowClass cls, WindowNumber number)
Find a window and make it the relative top-window on the screen.
Definition window.cpp:1226
void SetWindowDirty(WindowClass cls, WindowNumber number)
Mark window as dirty (in need of repainting)
Definition window.cpp:3106
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:145
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.