1
0
Fork 0

Fix #9056: [interface] missing scrollbar on infrastructure window.

pull/13130/head
NahashonM 2024-12-16 03:50:33 +03:00
parent 8bf2ab62d9
commit 60f6adfea8
2 changed files with 205 additions and 259 deletions

View File

@ -1752,32 +1752,11 @@ static constexpr NWidgetPart _nested_company_infrastructure_widgets[] = {
NWidget(WWT_SHADEBOX, COLOUR_GREY),
NWidget(WWT_STICKYBOX, COLOUR_GREY),
EndContainer(),
NWidget(WWT_PANEL, COLOUR_GREY),
NWidget(NWID_VERTICAL), SetPadding(WidgetDimensions::unscaled.framerect), SetPIP(0, WidgetDimensions::unscaled.vsep_normal, 0),
NWidget(NWID_HORIZONTAL), SetPIP(0, WidgetDimensions::unscaled.hsep_wide, 0),
NWidget(WWT_EMPTY, COLOUR_GREY, WID_CI_RAIL_DESC), SetMinimalTextLines(2, 0), SetFill(1, 0),
NWidget(WWT_EMPTY, COLOUR_GREY, WID_CI_RAIL_COUNT), SetMinimalTextLines(2, 0), SetFill(0, 1),
EndContainer(),
NWidget(NWID_HORIZONTAL), SetPIP(0, WidgetDimensions::unscaled.hsep_wide, 0),
NWidget(WWT_EMPTY, COLOUR_GREY, WID_CI_ROAD_DESC), SetMinimalTextLines(2, 0), SetFill(1, 0),
NWidget(WWT_EMPTY, COLOUR_GREY, WID_CI_ROAD_COUNT), SetMinimalTextLines(2, 0), SetFill(0, 1),
EndContainer(),
NWidget(NWID_HORIZONTAL), SetPIP(0, WidgetDimensions::unscaled.hsep_wide, 0),
NWidget(WWT_EMPTY, COLOUR_GREY, WID_CI_TRAM_DESC), SetMinimalTextLines(2, 0), SetFill(1, 0),
NWidget(WWT_EMPTY, COLOUR_GREY, WID_CI_TRAM_COUNT), SetMinimalTextLines(2, 0), SetFill(0, 1),
EndContainer(),
NWidget(NWID_HORIZONTAL), SetPIP(0, WidgetDimensions::unscaled.hsep_wide, 0),
NWidget(WWT_EMPTY, COLOUR_GREY, WID_CI_WATER_DESC), SetMinimalTextLines(2, 0), SetFill(1, 0),
NWidget(WWT_EMPTY, COLOUR_GREY, WID_CI_WATER_COUNT), SetMinimalTextLines(2, 0), SetFill(0, 1),
EndContainer(),
NWidget(NWID_HORIZONTAL), SetPIP(0, WidgetDimensions::unscaled.hsep_wide, 0),
NWidget(WWT_EMPTY, COLOUR_GREY, WID_CI_STATION_DESC), SetMinimalTextLines(3, 0), SetFill(1, 0),
NWidget(WWT_EMPTY, COLOUR_GREY, WID_CI_STATION_COUNT), SetMinimalTextLines(3, 0), SetFill(0, 1),
EndContainer(),
NWidget(NWID_HORIZONTAL), SetPIP(0, WidgetDimensions::unscaled.hsep_wide, 0),
NWidget(WWT_EMPTY, COLOUR_GREY, WID_CI_TOTAL_DESC), SetFill(1, 0),
NWidget(WWT_EMPTY, COLOUR_GREY, WID_CI_TOTAL), SetFill(0, 1),
EndContainer(),
NWidget(NWID_HORIZONTAL),
NWidget(WWT_PANEL, COLOUR_GREY, WID_CI_LIST), SetFill(1, 0), SetResize(1, 1), SetScrollbar(WID_CI_SCROLLBAR), EndContainer(),
NWidget(NWID_VERTICAL),
NWidget(NWID_VSCROLLBAR, COLOUR_GREY, WID_CI_SCROLLBAR),
NWidget(WWT_RESIZEBOX, COLOUR_GREY),
EndContainer(),
EndContainer(),
};
@ -1787,16 +1766,52 @@ static constexpr NWidgetPart _nested_company_infrastructure_widgets[] = {
*/
struct CompanyInfrastructureWindow : Window
{
/* Company Ifrastructure Window infrastructure cache type. */
enum CacheEntryType : int {
ENTRY_HEADER, ///< section headers.
ENTRY_BLANK_LINE, ///< blank line.
ENTRY_LABEL_ONLY, ///< label only entry, no values.
ENTRY_LABEL_VALUES, ///< label and values (count, cost).
ENTRY_TOTAL_COST, ///< total maintenance cost.
};
/* Infrastructure count and maintenance cost cache container. */
struct InfrastructureCache {
CacheEntryType type;
StringID label;
uint count;
Money yearly_cost;
InfrastructureCache(CacheEntryType type, StringID label, uint count = 0, Money monthly_cost = 0) : type(type), label(label), count(count), yearly_cost(monthly_cost * 12)
{
}
};
RailTypes railtypes; ///< Valid railtypes.
RoadTypes roadtypes; ///< Valid roadtypes.
uint total_width; ///< String width of the total cost line.
uint total_y_padding; ///< Infrastructure label size.
uint max_label_width; ///< Infrastructure label size.
uint max_cost_width; ///< Infratructure maintenance cost text size.
uint max_count_width; ///< Infrastructure count text size.
Scrollbar *vscroll; ///< scroll bar widget.
mutable std::vector<InfrastructureCache> infrastructurelist; ///< infrastructure and total maintenance cost cache.
CompanyInfrastructureWindow(WindowDesc &desc, WindowNumber window_number) : Window(desc)
{
this->UpdateRailRoadTypes();
this->InitNested(window_number);
this->CreateNestedTree();
this->vscroll = this->GetScrollbar(WID_CI_SCROLLBAR);
this->BuildCompanyInfrastructureCache();
this->SetWidgetDirty(WID_CI_LIST); // Force repaint of company infrastructure widget.
this->FinishInitNested(window_number);
this->owner = (Owner)this->window_number;
}
@ -1827,29 +1842,89 @@ struct CompanyInfrastructureWindow : Window
this->roadtypes &= ~_roadtypes_hidden_mask;
}
/** Get total infrastructure maintenance cost. */
Money GetTotalMaintenanceCost() const
/**
* Build a vector of infrastructure types(roads, trains, trams, airports, stations, ships) to be displayed.
* Total maintenance cost of all infrastructure types is last entry in vector.
*/
void BuildCompanyInfrastructureCache() const
{
const Company *c = Company::Get((CompanyID)this->window_number);
Money total;
uint32_t rail_total = c->infrastructure.GetRailTotal();
for (RailType rt = RAILTYPE_BEGIN; rt != RAILTYPE_END; rt++) {
if (HasBit(this->railtypes, rt)) total += RailMaintenanceCost(rt, c->infrastructure.rail[rt], rail_total);
}
total += SignalMaintenanceCost(c->infrastructure.signal);
Money monthly_cost = 0;
Money total_monthly_cost = 0;
uint32_t road_total = c->infrastructure.GetRoadTotal();
uint32_t tram_total = c->infrastructure.GetTramTotal();
for (RoadType rt = ROADTYPE_BEGIN; rt != ROADTYPE_END; rt++) {
if (HasBit(this->roadtypes, rt)) total += RoadMaintenanceCost(rt, c->infrastructure.road[rt], RoadTypeIsRoad(rt) ? road_total : tram_total);
this->infrastructurelist.clear();
/* Railtypes and signals. */
this->infrastructurelist.emplace_back(ENTRY_HEADER, STR_COMPANY_INFRASTRUCTURE_VIEW_RAIL_SECT);
if (this->railtypes != RAILTYPES_NONE) {
for (const auto &rt : _sorted_railtypes) {
if (!HasBit(this->railtypes, rt)) continue;
monthly_cost = RailMaintenanceCost(rt, c->infrastructure.rail[rt], c->infrastructure.GetRailTotal());
total_monthly_cost += monthly_cost;
this->infrastructurelist.emplace_back(ENTRY_LABEL_VALUES, GetRailTypeInfo(rt)->strings.name, c->infrastructure.rail[rt], monthly_cost);
}
monthly_cost = SignalMaintenanceCost(c->infrastructure.signal);
total_monthly_cost += monthly_cost;
this->infrastructurelist.emplace_back(ENTRY_LABEL_VALUES, STR_COMPANY_INFRASTRUCTURE_VIEW_SIGNALS, c->infrastructure.signal, monthly_cost);
} else {
/* No valid railtype. */
this->infrastructurelist.emplace_back(ENTRY_LABEL_ONLY, STR_COMPANY_VIEW_INFRASTRUCTURE_NONE);
}
total += CanalMaintenanceCost(c->infrastructure.water);
total += StationMaintenanceCost(c->infrastructure.station);
total += AirportMaintenanceCost(c->index);
/* roadtypes. */
this->infrastructurelist.emplace_back(ENTRY_HEADER, STR_COMPANY_INFRASTRUCTURE_VIEW_ROAD_SECT);
return total;
for (const auto &rt : _sorted_roadtypes) {
if (!HasBit(this->roadtypes, rt) || !RoadTypeIsRoad(rt)) continue;
monthly_cost = RoadMaintenanceCost(rt, c->infrastructure.road[rt], c->infrastructure.GetRoadTotal());
total_monthly_cost += monthly_cost;
this->infrastructurelist.emplace_back(ENTRY_LABEL_VALUES, GetRoadTypeInfo(rt)->strings.name, c->infrastructure.road[rt], monthly_cost);
}
/* trams. */
this->infrastructurelist.emplace_back(ENTRY_HEADER, STR_COMPANY_INFRASTRUCTURE_VIEW_TRAM_SECT);
bool has_trams = false;
for (const auto &rt : _sorted_roadtypes) {
if (!HasBit(this->roadtypes, rt) || !RoadTypeIsTram(rt)) continue;
has_trams = true;
monthly_cost = RoadMaintenanceCost(rt, c->infrastructure.road[rt], c->infrastructure.GetRoadTotal());
total_monthly_cost += monthly_cost;
this->infrastructurelist.emplace_back(ENTRY_LABEL_VALUES, GetRoadTypeInfo(rt)->strings.name, c->infrastructure.road[rt], monthly_cost);
}
/* No valid trams. */
if (!has_trams)
this->infrastructurelist.emplace_back(ENTRY_BLANK_LINE, STR_COMPANY_VIEW_INFRASTRUCTURE_NONE);
/* Canals, locks, and ship depots (docks are counted as stations). */
this->infrastructurelist.emplace_back(ENTRY_HEADER, STR_COMPANY_INFRASTRUCTURE_VIEW_WATER_SECT);
monthly_cost = CanalMaintenanceCost(c->infrastructure.water);
total_monthly_cost += monthly_cost;
this->infrastructurelist.emplace_back(ENTRY_LABEL_VALUES, STR_COMPANY_INFRASTRUCTURE_VIEW_CANALS, c->infrastructure.water, monthly_cost);
/* Airports. */
this->infrastructurelist.emplace_back(ENTRY_HEADER, STR_COMPANY_INFRASTRUCTURE_VIEW_STATION_SECT);
monthly_cost = StationMaintenanceCost(c->infrastructure.station);
total_monthly_cost += monthly_cost;
this->infrastructurelist.emplace_back(ENTRY_LABEL_VALUES, STR_COMPANY_INFRASTRUCTURE_VIEW_STATIONS, c->infrastructure.station, monthly_cost);
monthly_cost = AirportMaintenanceCost(c->index);
total_monthly_cost += monthly_cost;
this->infrastructurelist.emplace_back(ENTRY_LABEL_VALUES, STR_COMPANY_INFRASTRUCTURE_VIEW_AIRPORTS, c->infrastructure.airport, monthly_cost);
/* Total monthly maintenance cost. */
if(_settings_game.economy.infrastructure_maintenance)
this->infrastructurelist.emplace_back(ENTRY_TOTAL_COST, STR_COMPANY_VIEW_INFRASTRUCTURE_NONE, 0, total_monthly_cost);
/* Update scrollbar as well. */
this->vscroll->SetCount(this->infrastructurelist.size());
}
void SetStringParameters(WidgetID widget) const override
@ -1863,231 +1938,110 @@ struct CompanyInfrastructureWindow : Window
void UpdateWidgetSize(WidgetID widget, Dimension &size, [[maybe_unused]] const Dimension &padding, [[maybe_unused]] Dimension &fill, [[maybe_unused]] Dimension &resize) override
{
const Company *c = Company::Get((CompanyID)this->window_number);
if (widget != WID_CI_LIST) return;
switch (widget) {
case WID_CI_RAIL_DESC: {
uint lines = 1; // Starts at 1 because a line is also required for the section title
uint max_lwidth = 0;
uint max_count = 1000; // Some random number to reserve enough space.
Money max_cost = 1000000; // Some random number to reserve enough space.
size.width = std::max(size.width, GetStringBoundingBox(STR_COMPANY_INFRASTRUCTURE_VIEW_RAIL_SECT).width + padding.width);
for (const auto &rt : _sorted_railtypes) {
if (HasBit(this->railtypes, rt)) {
lines++;
size.width = std::max(size.width, GetStringBoundingBox(GetRailTypeInfo(rt)->strings.name).width + padding.width + WidgetDimensions::scaled.hsep_indent);
}
}
if (this->railtypes != RAILTYPES_NONE) {
lines++;
size.width = std::max(size.width, GetStringBoundingBox(STR_COMPANY_INFRASTRUCTURE_VIEW_SIGNALS).width + padding.width + WidgetDimensions::scaled.hsep_indent);
}
size.height = std::max(size.height, lines * GetCharacterHeight(FS_NORMAL));
break;
}
case WID_CI_ROAD_DESC:
case WID_CI_TRAM_DESC: {
uint lines = 1; // Starts at 1 because a line is also required for the section title
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);
for (const auto &rt : _sorted_roadtypes) {
if (HasBit(this->roadtypes, rt) && RoadTypeIsRoad(rt) == (widget == WID_CI_ROAD_DESC)) {
lines++;
size.width = std::max(size.width, GetStringBoundingBox(GetRoadTypeInfo(rt)->strings.name).width + padding.width + WidgetDimensions::scaled.hsep_indent);
}
}
size.height = std::max(size.height, lines * GetCharacterHeight(FS_NORMAL));
break;
}
case WID_CI_WATER_DESC:
size.width = std::max(size.width, GetStringBoundingBox(STR_COMPANY_INFRASTRUCTURE_VIEW_WATER_SECT).width + padding.width);
size.width = std::max(size.width, GetStringBoundingBox(STR_COMPANY_INFRASTRUCTURE_VIEW_CANALS).width + padding.width + WidgetDimensions::scaled.hsep_indent);
break;
case WID_CI_STATION_DESC:
size.width = std::max(size.width, GetStringBoundingBox(STR_COMPANY_INFRASTRUCTURE_VIEW_STATION_SECT).width + padding.width);
size.width = std::max(size.width, GetStringBoundingBox(STR_COMPANY_INFRASTRUCTURE_VIEW_STATIONS).width + padding.width + WidgetDimensions::scaled.hsep_indent);
size.width = std::max(size.width, GetStringBoundingBox(STR_COMPANY_INFRASTRUCTURE_VIEW_AIRPORTS).width + padding.width + WidgetDimensions::scaled.hsep_indent);
break;
case WID_CI_RAIL_COUNT:
case WID_CI_ROAD_COUNT:
case WID_CI_TRAM_COUNT:
case WID_CI_WATER_COUNT:
case WID_CI_STATION_COUNT:
case WID_CI_TOTAL: {
/* Find the maximum count that is displayed. */
uint32_t max_val = 1000; // Some random number to reserve enough space.
Money max_cost = 10000; // Some random number to reserve enough space.
uint32_t rail_total = c->infrastructure.GetRailTotal();
for (RailType rt = RAILTYPE_BEGIN; rt < RAILTYPE_END; rt++) {
max_val = std::max(max_val, c->infrastructure.rail[rt]);
max_cost = std::max(max_cost, RailMaintenanceCost(rt, c->infrastructure.rail[rt], rail_total));
}
max_val = std::max(max_val, c->infrastructure.signal);
max_cost = std::max(max_cost, SignalMaintenanceCost(c->infrastructure.signal));
uint32_t road_total = c->infrastructure.GetRoadTotal();
uint32_t tram_total = c->infrastructure.GetTramTotal();
for (RoadType rt = ROADTYPE_BEGIN; rt < ROADTYPE_END; rt++) {
max_val = std::max(max_val, c->infrastructure.road[rt]);
max_cost = std::max(max_cost, RoadMaintenanceCost(rt, c->infrastructure.road[rt], RoadTypeIsRoad(rt) ? road_total : tram_total));
}
max_val = std::max(max_val, c->infrastructure.water);
max_cost = std::max(max_cost, CanalMaintenanceCost(c->infrastructure.water));
max_val = std::max(max_val, c->infrastructure.station);
max_cost = std::max(max_cost, StationMaintenanceCost(c->infrastructure.station));
max_val = std::max(max_val, c->infrastructure.airport);
max_cost = std::max(max_cost, AirportMaintenanceCost(c->index));
SetDParamMaxValue(0, max_val);
uint count_width = GetStringBoundingBox(STR_JUST_COMMA).width + WidgetDimensions::scaled.hsep_indent; // Reserve some wiggle room
if (_settings_game.economy.infrastructure_maintenance) {
StringID str_total = TimerGameEconomy::UsingWallclockUnits() ? STR_COMPANY_INFRASTRUCTURE_VIEW_TOTAL_PERIOD : STR_COMPANY_INFRASTRUCTURE_VIEW_TOTAL_YEAR;
SetDParamMaxValue(0, this->GetTotalMaintenanceCost() * 12); // Convert to per year
this->total_width = GetStringBoundingBox(str_total).width + WidgetDimensions::scaled.hsep_indent * 2;
size.width = std::max(size.width, this->total_width);
SetDParamMaxValue(0, max_cost * 12); // Convert to per year
count_width += std::max(this->total_width, GetStringBoundingBox(str_total).width);
}
size.width = std::max(size.width, count_width);
/* Set height of the total line. */
if (widget == WID_CI_TOTAL) {
size.height = _settings_game.economy.infrastructure_maintenance ? std::max<uint>(size.height, WidgetDimensions::scaled.vsep_normal + GetCharacterHeight(FS_NORMAL)) : 0;
}
break;
}
for (const auto &ie : this->infrastructurelist) {
max_lwidth = std::max(max_lwidth, GetStringBoundingBox(ie.label).width);
max_cost = std::max(max_cost, ie.yearly_cost);
max_count = std::max(max_count, ie.count);
}
}
/**
* Helper for drawing the counts line.
* @param r The bounds to draw in.
* @param y The y position to draw at.
* @param count The count to show on this line.
* @param monthly_cost The monthly costs.
*/
void DrawCountLine(const Rect &r, int &y, int count, Money monthly_cost) const
{
SetDParam(0, count);
DrawString(r.left, r.right, y += GetCharacterHeight(FS_NORMAL), STR_JUST_COMMA, TC_WHITE, SA_RIGHT);
/* add indent width to label text width. */
this->max_label_width = max_lwidth + WidgetDimensions::scaled.hsep_indent;
SetDParam(0, max_count);
this->max_count_width = GetStringBoundingBox(STR_JUST_COMMA).width + padding.width * 2;
if (_settings_game.economy.infrastructure_maintenance) {
SetDParam(0, monthly_cost * 12); // Convert to per year
Rect tr = r.WithWidth(this->total_width, _current_text_dir == TD_RTL);
DrawString(tr.left, tr.right, y,
TimerGameEconomy::UsingWallclockUnits() ? STR_COMPANY_INFRASTRUCTURE_VIEW_TOTAL_PERIOD : STR_COMPANY_INFRASTRUCTURE_VIEW_TOTAL_YEAR,
TC_FROMSTRING, SA_RIGHT);
SetDParam(0, max_cost);
this->max_cost_width = GetStringBoundingBox(TimerGameEconomy::UsingWallclockUnits()
? STR_COMPANY_INFRASTRUCTURE_VIEW_TOTAL_PERIOD : STR_COMPANY_INFRASTRUCTURE_VIEW_TOTAL_YEAR).width;
this->total_y_padding = WidgetDimensions::scaled.vsep_normal * 3; // padding before and after horizontal line and after total cost line.
} else {
this->max_cost_width = 0;
this->total_y_padding = WidgetDimensions::scaled.vsep_normal; // padding after last count line.
}
size.width = this->max_label_width + this->max_cost_width + this->max_count_width + WidgetDimensions::scaled.hsep_wide * 2;
size.width += WidgetDimensions::scaled.hsep_normal * 2;
/* Set max auto resize height for widget to 25 text lines. */
size.height = static_cast<uint>(this->infrastructurelist.size()) * GetCharacterHeight(FS_NORMAL);
size.height = Clamp(size.height, 0, GetCharacterHeight(FS_NORMAL) * 25);
size.height += this->total_y_padding;
resize.height = GetCharacterHeight(FS_NORMAL);
}
void DrawWidget(const Rect &r, WidgetID widget) const override
{
const Company *c = Company::Get((CompanyID)this->window_number);
if (widget != WID_CI_LIST) return;
int y = r.top;
Rect rr = r.Shrink(WidgetDimensions::scaled.hsep_normal);
Rect ir = rr.Indent(WidgetDimensions::scaled.hsep_indent, _current_text_dir == TD_RTL);
Rect ir = r.Indent(WidgetDimensions::scaled.hsep_indent, _current_text_dir == TD_RTL);
switch (widget) {
case WID_CI_RAIL_DESC:
DrawString(r.left, r.right, y, STR_COMPANY_INFRASTRUCTURE_VIEW_RAIL_SECT);
/* set boundaries for labels, infrastructure count and cost secions to handle text overflows and text direction change */
int label_right = rr.left + this->max_label_width;
int cost_left = label_right + WidgetDimensions::scaled.hsep_wide;
int cost_right = cost_left + this->max_cost_width;
int count_left = cost_right + WidgetDimensions::scaled.hsep_wide;
if (this->railtypes != RAILTYPES_NONE) {
/* Draw name of each valid railtype. */
for (const auto &rt : _sorted_railtypes) {
if (HasBit(this->railtypes, rt)) {
DrawString(ir.left, ir.right, y += GetCharacterHeight(FS_NORMAL), GetRailTypeInfo(rt)->strings.name, TC_WHITE);
auto [first, last] = this->vscroll->GetVisibleRangeIterators(this->infrastructurelist);
for (auto it = first; it != last; ++it, y += GetCharacterHeight(FS_NORMAL)) {
switch (it->type) {
case ENTRY_LABEL_VALUES:
SetDParam(0, it->count);
DrawString(count_left, ir.right, y, STR_JUST_COMMA, TC_WHITE, SA_RIGHT);
[[fallthrough]];
case ENTRY_TOTAL_COST:
if (_settings_game.economy.infrastructure_maintenance) {
if (it->type == ENTRY_TOTAL_COST) {
y += WidgetDimensions::scaled.vsep_normal;
GfxFillRect(cost_left, y, cost_right, y + WidgetDimensions::scaled.bevel.top - 1, PC_WHITE);
y += WidgetDimensions::scaled.vsep_normal;
}
}
DrawString(ir.left, ir.right, y += GetCharacterHeight(FS_NORMAL), STR_COMPANY_INFRASTRUCTURE_VIEW_SIGNALS);
} else {
/* No valid railtype. */
DrawString(ir.left, ir.right, y += GetCharacterHeight(FS_NORMAL), STR_COMPANY_VIEW_INFRASTRUCTURE_NONE);
}
break;
case WID_CI_RAIL_COUNT: {
/* Draw infrastructure count for each valid railtype. */
uint32_t rail_total = c->infrastructure.GetRailTotal();
for (const auto &rt : _sorted_railtypes) {
if (HasBit(this->railtypes, rt)) {
this->DrawCountLine(r, y, c->infrastructure.rail[rt], RailMaintenanceCost(rt, c->infrastructure.rail[rt], rail_total));
SetDParam(0, it->yearly_cost);
DrawString(cost_left, cost_right, y, TimerGameEconomy::UsingWallclockUnits()
? STR_COMPANY_INFRASTRUCTURE_VIEW_TOTAL_PERIOD : STR_COMPANY_INFRASTRUCTURE_VIEW_TOTAL_YEAR, TC_FROMSTRING, SA_RIGHT);
}
}
if (this->railtypes != RAILTYPES_NONE) {
this->DrawCountLine(r, y, c->infrastructure.signal, SignalMaintenanceCost(c->infrastructure.signal));
}
break;
if (it->type == ENTRY_TOTAL_COST) break;
[[fallthrough]];
case ENTRY_LABEL_ONLY:
DrawString(ir.left, label_right, y, it->label, TC_WHITE);
break;
case ENTRY_HEADER:
DrawString(rr.left, label_right, y, it->label);
break;
case ENTRY_BLANK_LINE:
break;
}
case WID_CI_ROAD_DESC:
case WID_CI_TRAM_DESC: {
DrawString(r.left, r.right, y, widget == WID_CI_ROAD_DESC ? STR_COMPANY_INFRASTRUCTURE_VIEW_ROAD_SECT : STR_COMPANY_INFRASTRUCTURE_VIEW_TRAM_SECT);
/* Draw name of each valid roadtype. */
for (const auto &rt : _sorted_roadtypes) {
if (HasBit(this->roadtypes, rt) && RoadTypeIsRoad(rt) == (widget == WID_CI_ROAD_DESC)) {
DrawString(ir.left, ir.right, y += GetCharacterHeight(FS_NORMAL), GetRoadTypeInfo(rt)->strings.name, TC_WHITE);
}
}
break;
}
case WID_CI_ROAD_COUNT:
case WID_CI_TRAM_COUNT: {
uint32_t road_tram_total = widget == WID_CI_ROAD_COUNT ? c->infrastructure.GetRoadTotal() : c->infrastructure.GetTramTotal();
for (const auto &rt : _sorted_roadtypes) {
if (HasBit(this->roadtypes, rt) && RoadTypeIsRoad(rt) == (widget == WID_CI_ROAD_COUNT)) {
this->DrawCountLine(r, y, c->infrastructure.road[rt], RoadMaintenanceCost(rt, c->infrastructure.road[rt], road_tram_total));
}
}
break;
}
case WID_CI_WATER_DESC:
DrawString(r.left, r.right, y, STR_COMPANY_INFRASTRUCTURE_VIEW_WATER_SECT);
DrawString(ir.left, ir.right, y += GetCharacterHeight(FS_NORMAL), STR_COMPANY_INFRASTRUCTURE_VIEW_CANALS);
break;
case WID_CI_WATER_COUNT:
this->DrawCountLine(r, y, c->infrastructure.water, CanalMaintenanceCost(c->infrastructure.water));
break;
case WID_CI_TOTAL:
if (_settings_game.economy.infrastructure_maintenance) {
Rect tr = r.WithWidth(this->total_width, _current_text_dir == TD_RTL);
GfxFillRect(tr.left, y, tr.right, y + WidgetDimensions::scaled.bevel.top - 1, PC_WHITE);
y += WidgetDimensions::scaled.vsep_normal;
SetDParam(0, this->GetTotalMaintenanceCost() * 12); // Convert to per year
DrawString(tr.left, tr.right, y,
TimerGameEconomy::UsingWallclockUnits() ? STR_COMPANY_INFRASTRUCTURE_VIEW_TOTAL_PERIOD : STR_COMPANY_INFRASTRUCTURE_VIEW_TOTAL_YEAR,
TC_FROMSTRING, SA_RIGHT);
}
break;
case WID_CI_STATION_DESC:
DrawString(r.left, r.right, y, STR_COMPANY_INFRASTRUCTURE_VIEW_STATION_SECT);
DrawString(ir.left, ir.right, y += GetCharacterHeight(FS_NORMAL), STR_COMPANY_INFRASTRUCTURE_VIEW_STATIONS);
DrawString(ir.left, ir.right, y += GetCharacterHeight(FS_NORMAL), STR_COMPANY_INFRASTRUCTURE_VIEW_AIRPORTS);
break;
case WID_CI_STATION_COUNT:
this->DrawCountLine(r, y, c->infrastructure.station, StationMaintenanceCost(c->infrastructure.station));
this->DrawCountLine(r, y, c->infrastructure.airport, AirportMaintenanceCost(c->index));
break;
}
}
/** Update cache at regular intervals. */
IntervalTimer<TimerWindow> redraw_interval = {std::chrono::seconds(1), [this](auto) {
this->BuildCompanyInfrastructureCache();
this->SetWidgetDirty(WID_CI_LIST);
}};
void OnResize() override
{
this->vscroll->SetCapacityFromWidget(this, WID_CI_LIST, this->total_y_padding);
}
/**
* Some data on this window has become invalid.
* @param data Information about the changed data.
@ -2098,6 +2052,8 @@ struct CompanyInfrastructureWindow : Window
if (!gui_scope) return;
this->UpdateRailRoadTypes();
this->BuildCompanyInfrastructureCache();
this->SetWidgetDirty(WID_CI_LIST);
this->ReInit();
}
};

View File

@ -170,18 +170,8 @@ enum SelectCompanyManagerFaceWidgets : WidgetID {
/** Widgets of the #CompanyInfrastructureWindow class. */
enum CompanyInfrastructureWidgets : WidgetID {
WID_CI_CAPTION, ///< Caption of window.
WID_CI_RAIL_DESC, ///< Description of rail.
WID_CI_RAIL_COUNT, ///< Count of rail.
WID_CI_ROAD_DESC, ///< Description of road.
WID_CI_ROAD_COUNT, ///< Count of road.
WID_CI_TRAM_DESC, ///< Description of tram.
WID_CI_TRAM_COUNT, ///< Count of tram.
WID_CI_WATER_DESC, ///< Description of water.
WID_CI_WATER_COUNT, ///< Count of water.
WID_CI_STATION_DESC, ///< Description of station.
WID_CI_STATION_COUNT, ///< Count of station.
WID_CI_TOTAL_DESC, ///< Description of total.
WID_CI_TOTAL, ///< Count of total.
WID_CI_LIST, ///< Infrastructure list.
WID_CI_SCROLLBAR, ///< Infrastructure list scroll bar.
};
/** Widgets of the #BuyCompanyWindow class. */