Changeset - r28088:bbe5ce044a9f
[Not reviewed]
master
0 1 0
Peter Nelson - 12 months ago 2023-11-03 23:15:37
peter1138@openttd.org
Codechange: Avoid pointers and lengthof in ExpensesList. (#11427)

Use std::initializer_list which allows iteration.
1 file changed with 30 insertions and 35 deletions:
0 comments (0 inline, 0 general)
src/company_gui.cpp
Show inline comments
 
@@ -46,156 +46,153 @@
 
#include "timer/timer_window.h"
 

	
 
#include "widgets/company_widget.h"
 

	
 
#include "safeguards.h"
 

	
 

	
 
/** Company GUI constants. */
 
static void DoSelectCompanyManagerFace(Window *parent);
 
static void ShowCompanyInfrastructure(CompanyID company);
 

	
 
/** List of revenues. */
 
static ExpensesType _expenses_list_revenue[] = {
 
static const std::initializer_list<ExpensesType> _expenses_list_revenue = {
 
	EXPENSES_TRAIN_REVENUE,
 
	EXPENSES_ROADVEH_REVENUE,
 
	EXPENSES_AIRCRAFT_REVENUE,
 
	EXPENSES_SHIP_REVENUE,
 
};
 

	
 
/** List of operating expenses. */
 
static ExpensesType _expenses_list_operating_costs[] = {
 
static const std::initializer_list<ExpensesType> _expenses_list_operating_costs = {
 
	EXPENSES_TRAIN_RUN,
 
	EXPENSES_ROADVEH_RUN,
 
	EXPENSES_AIRCRAFT_RUN,
 
	EXPENSES_SHIP_RUN,
 
	EXPENSES_PROPERTY,
 
	EXPENSES_LOAN_INTEREST,
 
};
 

	
 
/** List of capital expenses. */
 
static ExpensesType _expenses_list_capital_costs[] = {
 
static const std::initializer_list<ExpensesType> _expenses_list_capital_costs = {
 
	EXPENSES_CONSTRUCTION,
 
	EXPENSES_NEW_VEHICLES,
 
	EXPENSES_OTHER,
 
};
 

	
 
/** Expense list container. */
 
struct ExpensesList {
 
	const ExpensesType *et;   ///< Expenses items.
 
	const uint length;        ///< Number of items in list.
 

	
 
	ExpensesList(ExpensesType *et, int length) : et(et), length(length)
 
	const StringID title; ///< StringID of list title.
 
	const std::initializer_list<ExpensesType> &items; ///< List of expenses types.
 

	
 
	ExpensesList(StringID title, const std::initializer_list<ExpensesType> &list) : title(title), items(list)
 
	{
 
	}
 

	
 
	uint GetHeight() const
 
	{
 
		/* Add up the height of all the lines.  */
 
		return this->length * FONT_HEIGHT_NORMAL;
 
		return static_cast<uint>(this->items.size()) * FONT_HEIGHT_NORMAL;
 
	}
 

	
 
	/** Compute width of the expenses categories in pixels. */
 
	uint GetListWidth() const
 
	{
 
		uint width = 0;
 
		for (uint i = 0; i < this->length; i++) {
 
			ExpensesType et = this->et[i];
 
		for (const ExpensesType &et : this->items) {
 
			width = std::max(width, GetStringBoundingBox(STR_FINANCES_SECTION_CONSTRUCTION + et).width);
 
		}
 
		return width;
 
	}
 
};
 

	
 
/** Types of expense lists */
 
static const ExpensesList _expenses_list_types[] = {
 
	ExpensesList(_expenses_list_revenue, lengthof(_expenses_list_revenue)),
 
	ExpensesList(_expenses_list_operating_costs, lengthof(_expenses_list_operating_costs)),
 
	ExpensesList(_expenses_list_capital_costs, lengthof(_expenses_list_capital_costs)),
 
static const std::initializer_list<ExpensesList> _expenses_list_types = {
 
	{ STR_FINANCES_REVENUE_TITLE,            _expenses_list_revenue },
 
	{ STR_FINANCES_OPERATING_EXPENSES_TITLE, _expenses_list_operating_costs },
 
	{ STR_FINANCES_CAPITAL_EXPENSES_TITLE,   _expenses_list_capital_costs },
 
};
 

	
 
/**
 
 * Get the total height of the "categories" column.
 
 * @return The total height in pixels.
 
 */
 
static uint GetTotalCategoriesHeight()
 
{
 
	/* There's an empty line and blockspace on the year row */
 
	uint total_height = FONT_HEIGHT_NORMAL + WidgetDimensions::scaled.vsep_wide;
 

	
 
	for (uint i = 0; i < lengthof(_expenses_list_types); i++) {
 
	for (const ExpensesList &list : _expenses_list_types) {
 
		/* Title + expense list + total line + total + blockspace after category */
 
		total_height += FONT_HEIGHT_NORMAL + _expenses_list_types[i].GetHeight() + WidgetDimensions::scaled.vsep_normal + FONT_HEIGHT_NORMAL + WidgetDimensions::scaled.vsep_wide;
 
		total_height += FONT_HEIGHT_NORMAL + list.GetHeight() + WidgetDimensions::scaled.vsep_normal + FONT_HEIGHT_NORMAL + WidgetDimensions::scaled.vsep_wide;
 
	}
 

	
 
	/* Total income */
 
	total_height += WidgetDimensions::scaled.vsep_normal + FONT_HEIGHT_NORMAL + WidgetDimensions::scaled.vsep_wide;
 

	
 
	return total_height;
 
}
 

	
 
/**
 
 * Get the required width of the "categories" column, equal to the widest element.
 
 * @return The required width in pixels.
 
 */
 
static uint GetMaxCategoriesWidth()
 
{
 
	uint max_width = 0;
 

	
 
	/* Loop through categories to check max widths. */
 
	for (uint i = 0; i < lengthof(_expenses_list_types); i++) {
 
	for (const ExpensesList &list : _expenses_list_types) {
 
		/* Title of category */
 
		max_width = std::max(max_width, GetStringBoundingBox(STR_FINANCES_REVENUE_TITLE + i).width);
 
		max_width = std::max(max_width, GetStringBoundingBox(list.title).width);
 
		/* Entries in category */
 
		max_width = std::max(max_width, _expenses_list_types[i].GetListWidth() + WidgetDimensions::scaled.hsep_indent);
 
		max_width = std::max(max_width, list.GetListWidth() + WidgetDimensions::scaled.hsep_indent);
 
	}
 

	
 
	return max_width;
 
}
 

	
 
/**
 
 * Draw a category of expenses (revenue, operating expenses, capital expenses).
 
 */
 
static void DrawCategory(const Rect &r, int start_y, ExpensesList list)
 
static void DrawCategory(const Rect &r, int start_y, const ExpensesList &list)
 
{
 
	Rect tr = r.Indent(WidgetDimensions::scaled.hsep_indent, _current_text_dir == TD_RTL);
 

	
 
	tr.top = start_y;
 
	ExpensesType et;
 

	
 
	for (uint i = 0; i < list.length; i++) {
 
		et = list.et[i];
 

	
 
	for (const ExpensesType &et : list.items) {
 
		DrawString(tr, STR_FINANCES_SECTION_CONSTRUCTION + et);
 
		tr.top += FONT_HEIGHT_NORMAL;
 
	}
 
}
 

	
 
/**
 
 * Draw the expenses categories.
 
 * @param r Available space for drawing.
 
 * @note The environment must provide padding at the left and right of \a r.
 
 */
 
static void DrawCategories(const Rect &r)
 
{
 
	/* Start with an empty space in the year row, plus the blockspace under the year. */
 
	int y = r.top + FONT_HEIGHT_NORMAL + WidgetDimensions::scaled.vsep_wide;
 

	
 
	for (uint i = 0; i < lengthof(_expenses_list_types); i++) {
 
	for (const ExpensesList &list : _expenses_list_types) {
 
		/* Draw category title and advance y */
 
		DrawString(r.left, r.right, y, (STR_FINANCES_REVENUE_TITLE + i), TC_FROMSTRING, SA_LEFT);
 
		DrawString(r.left, r.right, y, list.title, TC_FROMSTRING, SA_LEFT);
 
		y += FONT_HEIGHT_NORMAL;
 

	
 
		/* Draw category items and advance y */
 
		DrawCategory(r, y, _expenses_list_types[i]);
 
		y += _expenses_list_types[i].GetHeight();
 
		DrawCategory(r, y, list);
 
		y += list.GetHeight();
 

	
 
		/* Advance y by the height of the horizontal line between amounts and subtotal */
 
		y += WidgetDimensions::scaled.vsep_normal;
 

	
 
		/* Draw category total and advance y */
 
		DrawString(r.left, r.right, y, STR_FINANCES_TOTAL_CAPTION, TC_FROMSTRING, SA_RIGHT);
 
		y += FONT_HEIGHT_NORMAL;
 

	
 
		/* Advance y by a blockspace after this category block */
 
		y += WidgetDimensions::scaled.vsep_wide;
 
	}
 

	
 
@@ -220,32 +217,30 @@ static void DrawPrice(Money amount, int 
 
	} else if (amount < 0) {
 
		amount = -amount;
 
		str = STR_FINANCES_POSITIVE_INCOME;
 
	}
 
	SetDParam(0, amount);
 
	DrawString(left, right, top, str, colour, SA_RIGHT);
 
}
 

	
 
/**
 
 * Draw a category of expenses/revenues in the year column.
 
 * @return The income sum of the category.
 
 */
 
static Money DrawYearCategory(const Rect &r, int start_y, ExpensesList list, const Expenses &tbl)
 
static Money DrawYearCategory(const Rect &r, int start_y, const ExpensesList &list, const Expenses &tbl)
 
{
 
	int y = start_y;
 
	ExpensesType et;
 
	Money sum = 0;
 

	
 
	for (uint i = 0; i < list.length; i++) {
 
		et = list.et[i];
 
	for (const ExpensesType &et : list.items) {
 
		Money cost = tbl[et];
 
		sum += cost;
 
		if (cost != 0) DrawPrice(cost, r.left, r.right, y, TC_BLACK);
 
		y += FONT_HEIGHT_NORMAL;
 
	}
 

	
 
	/* Draw the total at the bottom of the category. */
 
	GfxFillRect(r.left, y, r.right, y, PC_BLACK);
 
	y += WidgetDimensions::scaled.vsep_normal;
 
	if (sum != 0) DrawPrice(sum, r.left, r.right, y, TC_WHITE);
 

	
 
	/* Return the sum for the yearly total. */
 
@@ -262,29 +257,29 @@ static Money DrawYearCategory(const Rect
 
 */
 
static void DrawYearColumn(const Rect &r, TimerGameCalendar::Year year, const Expenses &tbl)
 
{
 
	int y = r.top;
 
	Money sum;
 

	
 
	/* Year header */
 
	SetDParam(0, year);
 
	DrawString(r.left, r.right, y, STR_FINANCES_YEAR, TC_FROMSTRING, SA_RIGHT, true);
 
	y += FONT_HEIGHT_NORMAL + WidgetDimensions::scaled.vsep_wide;
 

	
 
	/* Categories */
 
	for (uint i = 0; i < lengthof(_expenses_list_types); i++) {
 
	for (const ExpensesList &list : _expenses_list_types) {
 
		y += FONT_HEIGHT_NORMAL;
 
		sum += DrawYearCategory(r, y, _expenses_list_types[i], tbl);
 
		sum += DrawYearCategory(r, y, list, tbl);
 
		/* Expense list + expense category title + expense category total + blockspace after category */
 
		y += _expenses_list_types[i].GetHeight() + WidgetDimensions::scaled.vsep_normal + FONT_HEIGHT_NORMAL + WidgetDimensions::scaled.vsep_wide;
 
		y += list.GetHeight() + WidgetDimensions::scaled.vsep_normal + FONT_HEIGHT_NORMAL + WidgetDimensions::scaled.vsep_wide;
 
	}
 

	
 
	/* Total income. */
 
	GfxFillRect(r.left, y, r.right, y, PC_BLACK);
 
	y += WidgetDimensions::scaled.vsep_normal;
 
	DrawPrice(sum, r.left, r.right, y, TC_WHITE);
 
}
 

	
 
static const NWidgetPart _nested_company_finances_widgets[] = {
 
	NWidget(NWID_HORIZONTAL),
 
		NWidget(WWT_CLOSEBOX, COLOUR_GREY),
 
		NWidget(WWT_CAPTION, COLOUR_GREY, WID_CF_CAPTION), SetDataTip(STR_FINANCES_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
0 comments (0 inline, 0 general)