85 const std::initializer_list<ExpensesType> &
items;
91 uint GetHeight()
const
164 DrawString(tr, STR_FINANCES_SECTION_CONSTRUCTION + et);
188 y += list.GetHeight();
216 StringID str = STR_FINANCES_NEGATIVE_INCOME;
218 str = STR_FINANCES_ZERO_INCOME;
219 }
else if (amount < 0) {
221 str = STR_FINANCES_POSITIVE_INCOME;
237 Money cost = tbl[et];
239 if (cost != 0)
DrawPrice(cost, r.left, r.right, y, TC_BLACK);
246 if (sum != 0)
DrawPrice(sum, r.left, r.right, y, TC_WHITE);
281 DrawPrice(sum, r.left, r.right, y, TC_WHITE);
284 static constexpr
NWidgetPart _nested_company_finances_widgets[] = {
347 void SetStringParameters(
WidgetID widget)
const override
417 void DrawWidget(
const Rect &r,
WidgetID widget)
const override
430 if (wid_offset <= age) {
449 this->GetWidget<NWidgetStacked>(
WID_CF_SEL_PANEL)->SetDisplayedPlane(plane);
486 void OnClick([[maybe_unused]]
Point pt,
WidgetID widget, [[maybe_unused]]
int click_count)
override
490 this->small = !this->
small;
532 static WindowDesc _company_finances_desc(__FILE__, __LINE__,
536 std::begin(_nested_company_finances_widgets), std::end(_nested_company_finances_widgets)
553 static const StringID _colour_dropdown[] = {
554 STR_COLOUR_DARK_BLUE,
555 STR_COLOUR_PALE_GREEN,
559 STR_COLOUR_LIGHT_BLUE,
561 STR_COLOUR_DARK_GREEN,
575 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,
578 LC_AIRCRAFT, LC_AIRCRAFT, LC_AIRCRAFT,
586 template <SpriteID TSprite = SPR_SQUARE>
605 std::vector<int> indents;
608 void ShowColourDropDownMenu(uint32_t widget)
610 uint32_t used_colours = 0;
611 const Livery *livery, *default_livery =
nullptr;
613 byte default_col = 0;
616 if (this->livery_class < LC_GROUP_RAIL &&
HasBit(this->sel, LS_DEFAULT) && primary) {
624 if (this->livery_class < LC_GROUP_RAIL) {
627 for (scheme = LS_BEGIN; scheme < LS_END; scheme++) {
628 if (
HasBit(this->sel, scheme))
break;
630 if (scheme == LS_END) scheme = LS_DEFAULT;
631 livery = &c->livery[scheme];
632 if (scheme != LS_DEFAULT) default_livery = &c->livery[LS_DEFAULT];
637 default_livery = &c->livery[LS_DEFAULT];
640 default_livery = &pg->
livery;
645 if (default_livery !=
nullptr) {
647 default_col = (primary ? default_livery->
colour1 : default_livery->
colour2) + COLOUR_END;
650 for (uint i = 0; i <
lengthof(_colour_dropdown); i++) {
655 if (default_livery ==
nullptr ||
HasBit(livery->
in_use, primary ? 0 : 1)) {
665 for (
const Group *g : source) {
666 if (g->parent !=
parent)
continue;
667 this->groups.push_back(g);
668 this->indents.push_back(indent);
669 AddChildren(source, g->index, indent + 1);
677 this->groups.clear();
678 this->indents.clear();
680 if (this->livery_class >= LC_GROUP_RAIL) {
685 if (g->owner ==
owner && g->vehicle_type == vtype) {
693 const Group *last_group[2] = {
nullptr,
nullptr };
694 std::string last_name[2] = { {}, {} };
695 list.
Sort([&](
const Group *
const &a,
const Group *
const &b) ->
bool {
696 if (a != last_group[0]) {
699 last_name[0] =
GetString(STR_GROUP_NAME);
702 if (b != last_group[1]) {
705 last_name[1] =
GetString(STR_GROUP_NAME);
716 this->groups.shrink_to_fit();
722 if (this->livery_class < LC_GROUP_RAIL) {
724 for (
LiveryScheme scheme = LS_DEFAULT; scheme < LS_END; scheme++) {
730 this->rows = (uint)this->groups.size();
733 this->vscroll->
SetCount(this->rows);
743 this->livery_class = LC_OTHER;
746 this->BuildGroupList(company);
749 this->SetSelectedGroup(company, group);
753 this->owner = company;
762 case VEH_TRAIN: this->livery_class = LC_GROUP_RAIL;
break;
763 case VEH_ROAD: this->livery_class = LC_GROUP_ROAD;
break;
764 case VEH_SHIP: this->livery_class = LC_GROUP_SHIP;
break;
765 case VEH_AIRCRAFT: this->livery_class = LC_GROUP_AIRCRAFT;
break;
766 default: NOT_REACHED();
772 this->BuildGroupList(company);
776 for (uint i = 0; i < this->rows; i++) {
777 if (this->groups[i]->index == sel) {
790 for (
LiveryScheme scheme = LS_DEFAULT; scheme < LS_END; scheme++) {
796 if (g->owner == (
CompanyID)this->window_number) {
802 size->width = std::max(size->width, 5 + d.width + padding.width);
811 size->height = 5 * this->line_height;
813 resize->height = this->line_height;
827 for (
const StringID *
id = _colour_dropdown;
id !=
endof(_colour_dropdown);
id++) {
841 bool disabled = this->livery_class < LC_GROUP_RAIL ? (this->sel == 0) : (this->sel ==
INVALID_GROUP);
850 void SetStringParameters(
WidgetID widget)
const override
861 StringID colour = STR_COLOUR_DEFAULT;
863 if (this->livery_class < LC_GROUP_RAIL) {
864 if (this->sel != 0) {
866 for (scheme = LS_BEGIN; scheme < LS_END; scheme++) {
867 if (
HasBit(this->sel, scheme))
break;
869 if (scheme == LS_END) scheme = LS_DEFAULT;
870 const Livery *livery = &c->livery[scheme];
871 if (scheme == LS_DEFAULT ||
HasBit(livery->
in_use, primary ? 0 : 1)) {
872 colour = STR_COLOUR_DARK_BLUE + (primary ? livery->
colour1 : livery->
colour2);
880 colour = STR_COLOUR_DARK_BLUE + (primary ? livery->
colour1 : livery->
colour2);
890 void DrawWidget(
const Rect &r,
WidgetID widget)
const override
913 int square_offs = (ir.
Height() - this->square.height) / 2;
919 auto draw_livery = [&](
StringID str,
const Livery &livery,
bool is_selected,
bool is_default_scheme,
int indent) {
921 DrawString(sch.left + (rtl ? 0 : indent), sch.right - (rtl ? indent : 0), y + text_offs, str, is_selected ? TC_WHITE : TC_BLACK);
924 DrawSprite(SPR_SQUARE, GENERAL_SPRITE_COLOUR(livery.colour1), pri_squ.left, y + square_offs);
925 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);
928 if (sec.right > sec.left) {
929 DrawSprite(SPR_SQUARE, GENERAL_SPRITE_COLOUR(livery.colour2), sec_squ.left, y + square_offs);
930 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);
933 y += this->line_height;
938 if (livery_class < LC_GROUP_RAIL) {
940 for (
LiveryScheme scheme = LS_DEFAULT; scheme < LS_END; scheme++) {
942 if (pos-- > 0)
continue;
943 draw_livery(STR_LIVERY_DEFAULT + scheme, c->livery[scheme],
HasBit(this->sel, scheme), scheme == LS_DEFAULT, 0);
947 uint max =
static_cast<uint
>(std::min<size_t>(this->vscroll->
GetPosition() + this->vscroll->GetCapacity(), this->groups.size()));
948 for (uint i = this->vscroll->
GetPosition(); i < max; ++i) {
949 const Group *g = this->groups[i];
954 if (this->vscroll->
GetCount() == 0) {
955 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 };
957 DrawString(ir.left, ir.right, y + text_offs, empty_labels[vtype], TC_BLACK);
962 void OnClick([[maybe_unused]]
Point pt,
WidgetID widget, [[maybe_unused]]
int click_count)
override
980 if (this->livery_class < LC_GROUP_RAIL) {
982 for (
LiveryScheme scheme = LS_DEFAULT; scheme < LS_END; scheme++) {
984 this->sel = 1 << scheme;
993 if (!this->groups.empty()) {
994 this->sel = this->groups[0]->index;
1012 if (row >= this->rows)
return;
1014 if (this->livery_class < LC_GROUP_RAIL) {
1017 for (
LiveryScheme scheme = LS_BEGIN; scheme <= j && scheme < LS_END; scheme++) {
1028 this->sel = this->groups[row]->index;
1041 void OnDropdownSelect(
WidgetID widget,
int index)
override
1046 Colours colour =
static_cast<Colours
>(index);
1047 if (colour >= COLOUR_END) colour = INVALID_COLOUR;
1049 if (this->livery_class < LC_GROUP_RAIL) {
1051 for (
LiveryScheme scheme = LS_DEFAULT; scheme < LS_END; scheme++) {
1068 void OnInvalidateData([[maybe_unused]]
int data = 0, [[maybe_unused]]
bool gui_scope =
true)
override
1070 if (!gui_scope)
return;
1074 if (this->livery_class == data + LC_GROUP_RAIL) {
1081 if (!this->groups.empty()) this->sel = this->groups[0]->index;
1091 bool current_class_valid = this->livery_class == LC_OTHER || this->livery_class >= LC_GROUP_RAIL;
1093 for (
LiveryScheme scheme = LS_DEFAULT; scheme < LS_END; scheme++) {
1095 if (_livery_class[scheme] == this->livery_class) current_class_valid =
true;
1097 }
else if (this->livery_class < LC_GROUP_RAIL) {
1098 ClrBit(this->sel, scheme);
1103 if (!current_class_valid) {
1110 static constexpr
NWidgetPart _nested_select_company_livery_widgets[] = {
1128 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),
1139 static WindowDesc _select_company_livery_desc(__FILE__, __LINE__,
1143 std::begin(_nested_select_company_livery_widgets), std::end(_nested_select_company_livery_widgets)
1152 w->SetSelectedGroup(company, group);
1177 if (
_cmf_info[CMFV_EYE_COLOUR].valid_values[ge] < 2) {
1181 default: NOT_REACHED();
1182 case 0: pal = PALETTE_TO_BROWN;
break;
1183 case 1: pal = PALETTE_TO_BLUE;
break;
1184 case 2: pal = PALETTE_TO_GREEN;
break;
1189 DrawSprite(SPR_GRADIENT, GENERAL_SPRITE_COLOUR(colour), x, y);
1191 for (CompanyManagerFaceVariable cmfv = CMFV_CHEEKS; cmfv < CMFV_END; cmfv++) {
1193 case CMFV_MOUSTACHE:
if (!has_moustache)
continue;
break;
1195 case CMFV_NOSE:
if (has_moustache)
continue;
break;
1196 case CMFV_TIE_EARRING:
if (!has_tie_earring)
continue;
break;
1197 case CMFV_GLASSES:
if (!has_glasses)
continue;
break;
1383 const NWidgetCore *nwi_widget = this->GetWidget<NWidgetCore>(widget_index);
1387 if (is_bool_widget) {
1389 SetDParam(0, (val != 0) ? STR_FACE_YES : STR_FACE_NO);
1405 this->GetWidget<NWidgetCore>(
WID_SCMF_TIE_EARRING_TEXT)->widget_data = this->is_female ? STR_FACE_EARRING : STR_FACE_TIE;
1412 this->advanced =
false;
1436 wi->
SetDataTip(STR_FACE_SIMPLE, STR_FACE_SIMPLE_TOOLTIP);
1438 wi->
SetDataTip(STR_FACE_ADVANCED, STR_FACE_ADVANCED_TOOLTIP);
1450 for (
int val = 1; val <= 12; val++) {
1568 void SetStringParameters(
WidgetID widget)
const override
1572 if (this->is_female) {
1584 if (this->is_moust_male) {
1629 void DrawWidget(
const Rect &r,
WidgetID widget)
const override
1638 void OnClick([[maybe_unused]]
Point pt,
WidgetID widget, [[maybe_unused]]
int click_count)
override
1713 CompanyManagerFaceVariable cmfv;
1717 default: NOT_REACHED();
1718 case 0: cmfv = this->is_female ? CMFV_HAS_TIE_EARRING : CMFV_HAS_MOUSTACHE;
break;
1719 case 1: cmfv = CMFV_HAS_GLASSES;
break;
1725 default: NOT_REACHED();
1726 case 0: cmfv = CMFV_EYE_COLOUR;
break;
1727 case 1: cmfv = CMFV_CHIN;
break;
1728 case 2: cmfv = CMFV_EYEBROWS;
break;
1729 case 3: cmfv = this->is_moust_male ? CMFV_MOUSTACHE : CMFV_LIPS;
break;
1730 case 4: cmfv = CMFV_NOSE;
break;
1731 case 5: cmfv = CMFV_HAIR;
break;
1732 case 6: cmfv = CMFV_JACKET;
break;
1733 case 7: cmfv = CMFV_COLLAR;
break;
1734 case 8: cmfv = CMFV_TIE_EARRING;
break;
1735 case 9: cmfv = CMFV_GLASSES;
break;
1747 void OnQueryTextFinished(
char *str)
override
1749 if (str ==
nullptr)
return;
1752 this->face = std::strtoul(str,
nullptr, 10);
1784 static constexpr
NWidgetPart _nested_company_infrastructure_widgets[] = {
1833 this->UpdateRailRoadTypes();
1836 this->owner = (
Owner)this->window_number;
1839 void UpdateRailRoadTypes()
1863 this->roadtypes &= ~_roadtypes_hidden_mask;
1891 void SetStringParameters(
WidgetID widget)
const override
1908 size->width = std::max(size->width,
GetStringBoundingBox(STR_COMPANY_INFRASTRUCTURE_VIEW_RAIL_SECT).
width + padding.width);
1910 for (
const auto &rt : _sorted_railtypes) {
1911 if (
HasBit(this->railtypes, rt)) {
1931 for (
const auto &rt : _sorted_roadtypes) {
1943 size->width = std::max(size->width,
GetStringBoundingBox(STR_COMPANY_INFRASTRUCTURE_VIEW_WATER_SECT).
width + padding.width);
1948 size->width = std::max(size->width,
GetStringBoundingBox(STR_COMPANY_INFRASTRUCTURE_VIEW_STATION_SECT).
width + padding.width);
1960 uint32_t max_val = 1000;
1961 Money max_cost = 10000;
1990 size->width = std::max(size->width, this->total_width);
1996 size->width = std::max(size->width, count_width);
2028 void DrawWidget(
const Rect &r,
WidgetID widget)
const override
2037 DrawString(r.left, r.right, y, STR_COMPANY_INFRASTRUCTURE_VIEW_RAIL_SECT);
2041 for (
const auto &rt : _sorted_railtypes) {
2042 if (
HasBit(this->railtypes, rt)) {
2057 for (
const auto &rt : _sorted_railtypes) {
2058 if (
HasBit(this->railtypes, rt)) {
2070 DrawString(r.left, r.right, y, widget ==
WID_CI_ROAD_DESC ? STR_COMPANY_INFRASTRUCTURE_VIEW_ROAD_SECT : STR_COMPANY_INFRASTRUCTURE_VIEW_TRAM_SECT);
2073 for (
const auto &rt : _sorted_roadtypes) {
2085 for (
const auto &rt : _sorted_roadtypes) {
2094 DrawString(r.left, r.right, y, STR_COMPANY_INFRASTRUCTURE_VIEW_WATER_SECT);
2115 DrawString(r.left, r.right, y, STR_COMPANY_INFRASTRUCTURE_VIEW_STATION_SECT);
2132 void OnInvalidateData([[maybe_unused]]
int data = 0, [[maybe_unused]]
bool gui_scope =
true)
override
2134 if (!gui_scope)
return;
2136 this->UpdateRailRoadTypes();
2141 static WindowDesc _company_infrastructure_desc(__FILE__, __LINE__,
2142 WDP_AUTO,
"company_infrastructure", 0, 0,
2145 std::begin(_nested_company_infrastructure_widgets), std::end(_nested_company_infrastructure_widgets)
2155 AllocateWindowDescFront<CompanyInfrastructureWindow>(&_company_infrastructure_desc, company);
2158 static constexpr
NWidgetPart _nested_company_widgets[] = {
2240 STR_COMPANY_VIEW_TRAINS, STR_COMPANY_VIEW_ROAD_VEHICLES, STR_COMPANY_VIEW_SHIPS, STR_COMPANY_VIEW_AIRCRAFT
2268 this->owner = (
Owner)this->window_number;
2278 bool reinit =
false;
2319 d.width -= offset.x;
2320 d.height -= offset.y;
2321 *size =
maxdim(*size, d);
2345 size->width += padding.width;
2364 size->width += padding.width;
2373 void DrawVehicleCountsWidget(
const Rect &r,
const Company *c)
const
2389 DrawString(r.left, r.right, y, STR_COMPANY_VIEW_VEHICLES_NONE);
2393 void DrawInfrastructureCountsWidget(
const Rect &r,
const Company *c)
const
2399 if (rail_pieces != 0) {
2401 DrawString(r.left, r.right, y, STR_COMPANY_VIEW_INFRASTRUCTURE_RAIL);
2405 uint road_pieces = 0;
2407 if (road_pieces != 0) {
2409 DrawString(r.left, r.right, y, STR_COMPANY_VIEW_INFRASTRUCTURE_ROAD);
2415 DrawString(r.left, r.right, y, STR_COMPANY_VIEW_INFRASTRUCTURE_WATER);
2421 DrawString(r.left, r.right, y, STR_COMPANY_VIEW_INFRASTRUCTURE_STATION);
2427 DrawString(r.left, r.right, y, STR_COMPANY_VIEW_INFRASTRUCTURE_AIRPORT);
2433 DrawString(r.left, r.right, y, STR_COMPANY_VIEW_INFRASTRUCTURE_NONE);
2437 void DrawWidget(
const Rect &r,
WidgetID widget)
const override
2453 d.height -= offset.y;
2454 DrawSprite(SPR_VEH_BUS_SW_VIEW, COMPANY_SPRITE_COLOUR(c->
index), r.left - offset.x,
CenterBounds(r.top, r.bottom, d.height) - offset.y);
2459 DrawVehicleCountsWidget(r, c);
2463 DrawInfrastructureCountsWidget(r, c);
2468 DrawSprite(SPR_LOCK, PAL_NONE, r.left, r.top);
2474 void SetStringParameters(
WidgetID widget)
const override
2492 void OnClick([[maybe_unused]]
Point pt,
WidgetID widget, [[maybe_unused]]
int click_count)
override
2588 void OnPlaceObject([[maybe_unused]]
Point pt,
TileIndex tile)
override
2601 void OnQueryTextFinished(
char *str)
override
2603 if (str ==
nullptr)
return;
2605 switch (this->query_widget) {
2606 default: NOT_REACHED();
2609 Money money = std::strtoull(str,
nullptr, 10) / _currency->rate;
2629 static WindowDesc _company_desc(__FILE__, __LINE__,
2633 std::begin(_nested_company_widgets), std::end(_nested_company_widgets)
2644 AllocateWindowDescFront<CompanyWindow>(&_company_desc, company);
2677 size->height =
GetStringHeight(this->hostile_takeover ? STR_BUY_COMPANY_HOSTILE_TAKEOVER : STR_BUY_COMPANY_MESSAGE, size->width);
2682 void SetStringParameters(
WidgetID widget)
const override
2692 void DrawWidget(
const Rect &r,
WidgetID widget)
const override
2705 DrawStringMultiLine(r.left, r.right, r.top, r.bottom, this->hostile_takeover ? STR_BUY_COMPANY_HOSTILE_TAKEOVER : STR_BUY_COMPANY_MESSAGE, TC_FROMSTRING,
SA_CENTER);
2711 void OnClick([[maybe_unused]]
Point pt,
WidgetID widget, [[maybe_unused]]
int click_count)
override
2729 if (!this->hostile_takeover)
return;
2744 static constexpr
NWidgetPart _nested_buy_company_widgets[] = {
2763 static WindowDesc _buy_company_desc(__FILE__, __LINE__,
2767 std::begin(_nested_buy_company_widgets), std::end(_nested_buy_company_widgets)
2778 if (window ==
nullptr) {