Codechange: Use dynamic string list for contents of land info window.

This commit is contained in:
Michael Lutz 2021-06-12 19:13:22 +02:00
parent 8dd846bad4
commit 418e0ea85f
3 changed files with 63 additions and 70 deletions

View File

@ -889,6 +889,21 @@ Dimension GetStringBoundingBox(const char *str, FontSize start_fontsize)
return layout.GetBounds(); return layout.GetBounds();
} }
/**
* Return the string dimension in pixels. The height and width are returned
* in a single Dimension value. TINYFONT, BIGFONT modifiers are only
* supported as the first character of the string. The returned dimensions
* are therefore a rough estimation correct for all the current strings
* but not every possible combination
* @param str string to calculate pixel-width
* @param start_fontsize Fontsize to start the text with
* @return string width and height in pixels
*/
Dimension GetStringBoundingBox(const std::string &str, FontSize start_fontsize)
{
return GetStringBoundingBox(str.c_str(), start_fontsize);
}
/** /**
* Get bounding box of a string. Uses parameters set by #SetDParam if needed. * Get bounding box of a string. Uses parameters set by #SetDParam if needed.
* Has the same restrictions as #GetStringBoundingBox(const char *str, FontSize start_fontsize). * Has the same restrictions as #GetStringBoundingBox(const char *str, FontSize start_fontsize).

View File

@ -106,6 +106,7 @@ void GfxDrawLine(int left, int top, int right, int bottom, int colour, int width
void DrawBox(int x, int y, int dx1, int dy1, int dx2, int dy2, int dx3, int dy3); void DrawBox(int x, int y, int dx1, int dy1, int dx2, int dy2, int dx3, int dy3);
Dimension GetStringBoundingBox(const char *str, FontSize start_fontsize = FS_NORMAL); Dimension GetStringBoundingBox(const char *str, FontSize start_fontsize = FS_NORMAL);
Dimension GetStringBoundingBox(const std::string &str, FontSize start_fontsize = FS_NORMAL);
Dimension GetStringBoundingBox(StringID strid); Dimension GetStringBoundingBox(StringID strid);
int GetStringHeight(const char *str, int maxw, FontSize fontsize = FS_NORMAL); int GetStringHeight(const char *str, int maxw, FontSize fontsize = FS_NORMAL);
int GetStringHeight(StringID str, int maxw); int GetStringHeight(StringID str, int maxw);

View File

@ -32,6 +32,9 @@
#include "table/strings.h" #include "table/strings.h"
#include <sstream>
#include <iomanip>
#include "safeguards.h" #include "safeguards.h"
/** Method to open the OSK. */ /** Method to open the OSK. */
@ -61,16 +64,10 @@ static WindowDesc _land_info_desc(
); );
class LandInfoWindow : public Window { class LandInfoWindow : public Window {
enum LandInfoLines { StringList landinfo_data; ///< Info lines to show.
LAND_INFO_CENTERED_LINES = 32, ///< Up to 32 centered lines (arbitrary limit) std::string cargo_acceptance; ///< Centered multi-line string for cargo acceptance.
LAND_INFO_MULTICENTER_LINE = LAND_INFO_CENTERED_LINES, ///< One multicenter line
LAND_INFO_LINE_END,
};
static const uint LAND_INFO_LINE_BUFF_SIZE = 512;
public: public:
char landinfo_data[LAND_INFO_LINE_END][LAND_INFO_LINE_BUFF_SIZE];
TileIndex tile; TileIndex tile;
void DrawWidget(const Rect &r, int widget) const override void DrawWidget(const Rect &r, int widget) const override
@ -78,16 +75,14 @@ public:
if (widget != WID_LI_BACKGROUND) return; if (widget != WID_LI_BACKGROUND) return;
uint y = r.top + WD_TEXTPANEL_TOP; uint y = r.top + WD_TEXTPANEL_TOP;
for (uint i = 0; i < LAND_INFO_CENTERED_LINES; i++) { for (size_t i = 0; i < this->landinfo_data.size(); i++) {
if (StrEmpty(this->landinfo_data[i])) break;
DrawString(r.left + WD_FRAMETEXT_LEFT, r.right - WD_FRAMETEXT_RIGHT, y, this->landinfo_data[i], i == 0 ? TC_LIGHT_BLUE : TC_FROMSTRING, SA_HOR_CENTER); DrawString(r.left + WD_FRAMETEXT_LEFT, r.right - WD_FRAMETEXT_RIGHT, y, this->landinfo_data[i], i == 0 ? TC_LIGHT_BLUE : TC_FROMSTRING, SA_HOR_CENTER);
y += FONT_HEIGHT_NORMAL + WD_PAR_VSEP_NORMAL; y += FONT_HEIGHT_NORMAL + WD_PAR_VSEP_NORMAL;
if (i == 0) y += 4; if (i == 0) y += 4;
} }
if (!StrEmpty(this->landinfo_data[LAND_INFO_MULTICENTER_LINE])) { if (!this->cargo_acceptance.empty()) {
SetDParamStr(0, this->landinfo_data[LAND_INFO_MULTICENTER_LINE]); SetDParamStr(0, this->cargo_acceptance);
DrawStringMultiLine(r.left + WD_FRAMETEXT_LEFT, r.right - WD_FRAMETEXT_RIGHT, y, r.bottom - WD_TEXTPANEL_BOTTOM, STR_JUST_RAW_STRING, TC_FROMSTRING, SA_CENTER); DrawStringMultiLine(r.left + WD_FRAMETEXT_LEFT, r.right - WD_FRAMETEXT_RIGHT, y, r.bottom - WD_TEXTPANEL_BOTTOM, STR_JUST_RAW_STRING, TC_FROMSTRING, SA_CENTER);
} }
} }
@ -97,9 +92,7 @@ public:
if (widget != WID_LI_BACKGROUND) return; if (widget != WID_LI_BACKGROUND) return;
size->height = WD_TEXTPANEL_TOP + WD_TEXTPANEL_BOTTOM; size->height = WD_TEXTPANEL_TOP + WD_TEXTPANEL_BOTTOM;
for (uint i = 0; i < LAND_INFO_CENTERED_LINES; i++) { for (size_t i = 0; i < this->landinfo_data.size(); i++) {
if (StrEmpty(this->landinfo_data[i])) break;
uint width = GetStringBoundingBox(this->landinfo_data[i]).width + WD_FRAMETEXT_LEFT + WD_FRAMETEXT_RIGHT; uint width = GetStringBoundingBox(this->landinfo_data[i]).width + WD_FRAMETEXT_LEFT + WD_FRAMETEXT_RIGHT;
size->width = std::max(size->width, width); size->width = std::max(size->width, width);
@ -107,10 +100,10 @@ public:
if (i == 0) size->height += 4; if (i == 0) size->height += 4;
} }
if (!StrEmpty(this->landinfo_data[LAND_INFO_MULTICENTER_LINE])) { if (!this->cargo_acceptance.empty()) {
uint width = GetStringBoundingBox(this->landinfo_data[LAND_INFO_MULTICENTER_LINE]).width + WD_FRAMETEXT_LEFT + WD_FRAMETEXT_RIGHT; uint width = GetStringBoundingBox(this->cargo_acceptance).width + WD_FRAMETEXT_LEFT + WD_FRAMETEXT_RIGHT;
size->width = std::max(size->width, std::min(300u, width)); size->width = std::max(size->width, std::min(300u, width));
SetDParamStr(0, this->landinfo_data[LAND_INFO_MULTICENTER_LINE]); SetDParamStr(0, cargo_acceptance);
size->height += GetStringHeight(STR_JUST_RAW_STRING, size->width - WD_FRAMETEXT_LEFT - WD_FRAMETEXT_RIGHT); size->height += GetStringHeight(STR_JUST_RAW_STRING, size->width - WD_FRAMETEXT_LEFT - WD_FRAMETEXT_RIGHT);
} }
} }
@ -178,12 +171,11 @@ public:
AddAcceptedCargo(tile, acceptance, nullptr); AddAcceptedCargo(tile, acceptance, nullptr);
GetTileDesc(tile, &td); GetTileDesc(tile, &td);
uint line_nr = 0; this->landinfo_data.clear();
/* Tiletype */ /* Tiletype */
SetDParam(0, td.dparam[0]); SetDParam(0, td.dparam[0]);
GetString(this->landinfo_data[line_nr], td.str, lastof(this->landinfo_data[line_nr])); this->landinfo_data.push_back(GetString(td.str));
line_nr++;
/* Up to four owners */ /* Up to four owners */
for (uint i = 0; i < 4; i++) { for (uint i = 0; i < 4; i++) {
@ -191,8 +183,7 @@ public:
SetDParam(0, STR_LAND_AREA_INFORMATION_OWNER_N_A); SetDParam(0, STR_LAND_AREA_INFORMATION_OWNER_N_A);
if (td.owner[i] != OWNER_NONE && td.owner[i] != OWNER_WATER) GetNameOfOwner(td.owner[i], tile); if (td.owner[i] != OWNER_NONE && td.owner[i] != OWNER_WATER) GetNameOfOwner(td.owner[i], tile);
GetString(this->landinfo_data[line_nr], td.owner_type[i], lastof(this->landinfo_data[line_nr])); this->landinfo_data.push_back(GetString(td.owner_type[i]));
line_nr++;
} }
/* Cost to clear/revenue when cleared */ /* Cost to clear/revenue when cleared */
@ -212,18 +203,18 @@ public:
SetDParam(0, cost); SetDParam(0, cost);
} }
} }
GetString(this->landinfo_data[line_nr], str, lastof(this->landinfo_data[line_nr])); this->landinfo_data.push_back(GetString(str));
line_nr++;
/* Location */ /* Location */
char tmp[16]; std::stringstream tile_ss;
seprintf(tmp, lastof(tmp), "0x%.4X", tile); tile_ss << "0x" << std::setfill('0') << std::setw(4) << std::hex << std::uppercase << tile; // 0x%.4X
std::string tile_str = tile_ss.str(); // Can't pass it directly to SetDParamStr as the string is only a temporary and would be destructed before the GetString call.
SetDParam(0, TileX(tile)); SetDParam(0, TileX(tile));
SetDParam(1, TileY(tile)); SetDParam(1, TileY(tile));
SetDParam(2, GetTileZ(tile)); SetDParam(2, GetTileZ(tile));
SetDParamStr(3, tmp); SetDParamStr(3, tile_str);
GetString(this->landinfo_data[line_nr], STR_LAND_AREA_INFORMATION_LANDINFO_COORDS, lastof(this->landinfo_data[line_nr])); this->landinfo_data.push_back(GetString(STR_LAND_AREA_INFORMATION_LANDINFO_COORDS));
line_nr++;
/* Local authority */ /* Local authority */
SetDParam(0, STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY_NONE); SetDParam(0, STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY_NONE);
@ -231,126 +222,112 @@ public:
SetDParam(0, STR_TOWN_NAME); SetDParam(0, STR_TOWN_NAME);
SetDParam(1, t->index); SetDParam(1, t->index);
} }
GetString(this->landinfo_data[line_nr], STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY, lastof(this->landinfo_data[line_nr])); this->landinfo_data.push_back(GetString(STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY));
line_nr++;
/* Build date */ /* Build date */
if (td.build_date != INVALID_DATE) { if (td.build_date != INVALID_DATE) {
SetDParam(0, td.build_date); SetDParam(0, td.build_date);
GetString(this->landinfo_data[line_nr], STR_LAND_AREA_INFORMATION_BUILD_DATE, lastof(this->landinfo_data[line_nr])); this->landinfo_data.push_back(GetString(STR_LAND_AREA_INFORMATION_BUILD_DATE));
line_nr++;
} }
/* Station class */ /* Station class */
if (td.station_class != STR_NULL) { if (td.station_class != STR_NULL) {
SetDParam(0, td.station_class); SetDParam(0, td.station_class);
GetString(this->landinfo_data[line_nr], STR_LAND_AREA_INFORMATION_STATION_CLASS, lastof(this->landinfo_data[line_nr])); this->landinfo_data.push_back(GetString(STR_LAND_AREA_INFORMATION_STATION_CLASS));
line_nr++;
} }
/* Station type name */ /* Station type name */
if (td.station_name != STR_NULL) { if (td.station_name != STR_NULL) {
SetDParam(0, td.station_name); SetDParam(0, td.station_name);
GetString(this->landinfo_data[line_nr], STR_LAND_AREA_INFORMATION_STATION_TYPE, lastof(this->landinfo_data[line_nr])); this->landinfo_data.push_back(GetString(STR_LAND_AREA_INFORMATION_STATION_TYPE));
line_nr++;
} }
/* Airport class */ /* Airport class */
if (td.airport_class != STR_NULL) { if (td.airport_class != STR_NULL) {
SetDParam(0, td.airport_class); SetDParam(0, td.airport_class);
GetString(this->landinfo_data[line_nr], STR_LAND_AREA_INFORMATION_AIRPORT_CLASS, lastof(this->landinfo_data[line_nr])); this->landinfo_data.push_back(GetString(STR_LAND_AREA_INFORMATION_AIRPORT_CLASS));
line_nr++;
} }
/* Airport name */ /* Airport name */
if (td.airport_name != STR_NULL) { if (td.airport_name != STR_NULL) {
SetDParam(0, td.airport_name); SetDParam(0, td.airport_name);
GetString(this->landinfo_data[line_nr], STR_LAND_AREA_INFORMATION_AIRPORT_NAME, lastof(this->landinfo_data[line_nr])); this->landinfo_data.push_back(GetString(STR_LAND_AREA_INFORMATION_AIRPORT_NAME));
line_nr++;
} }
/* Airport tile name */ /* Airport tile name */
if (td.airport_tile_name != STR_NULL) { if (td.airport_tile_name != STR_NULL) {
SetDParam(0, td.airport_tile_name); SetDParam(0, td.airport_tile_name);
GetString(this->landinfo_data[line_nr], STR_LAND_AREA_INFORMATION_AIRPORTTILE_NAME, lastof(this->landinfo_data[line_nr])); this->landinfo_data.push_back(GetString(STR_LAND_AREA_INFORMATION_AIRPORTTILE_NAME));
line_nr++;
} }
/* Rail type name */ /* Rail type name */
if (td.railtype != STR_NULL) { if (td.railtype != STR_NULL) {
SetDParam(0, td.railtype); SetDParam(0, td.railtype);
GetString(this->landinfo_data[line_nr], STR_LANG_AREA_INFORMATION_RAIL_TYPE, lastof(this->landinfo_data[line_nr])); this->landinfo_data.push_back(GetString(STR_LANG_AREA_INFORMATION_RAIL_TYPE));
line_nr++;
} }
/* Rail speed limit */ /* Rail speed limit */
if (td.rail_speed != 0) { if (td.rail_speed != 0) {
SetDParam(0, td.rail_speed); SetDParam(0, td.rail_speed);
GetString(this->landinfo_data[line_nr], STR_LANG_AREA_INFORMATION_RAIL_SPEED_LIMIT, lastof(this->landinfo_data[line_nr])); this->landinfo_data.push_back(GetString(STR_LANG_AREA_INFORMATION_RAIL_SPEED_LIMIT));
line_nr++;
} }
/* Road type name */ /* Road type name */
if (td.roadtype != STR_NULL) { if (td.roadtype != STR_NULL) {
SetDParam(0, td.roadtype); SetDParam(0, td.roadtype);
GetString(this->landinfo_data[line_nr], STR_LANG_AREA_INFORMATION_ROAD_TYPE, lastof(this->landinfo_data[line_nr])); this->landinfo_data.push_back(GetString(STR_LANG_AREA_INFORMATION_ROAD_TYPE));
line_nr++;
} }
/* Road speed limit */ /* Road speed limit */
if (td.road_speed != 0) { if (td.road_speed != 0) {
SetDParam(0, td.road_speed); SetDParam(0, td.road_speed);
GetString(this->landinfo_data[line_nr], STR_LANG_AREA_INFORMATION_ROAD_SPEED_LIMIT, lastof(this->landinfo_data[line_nr])); this->landinfo_data.push_back(GetString(STR_LANG_AREA_INFORMATION_ROAD_SPEED_LIMIT));
line_nr++;
} }
/* Tram type name */ /* Tram type name */
if (td.tramtype != STR_NULL) { if (td.tramtype != STR_NULL) {
SetDParam(0, td.tramtype); SetDParam(0, td.tramtype);
GetString(this->landinfo_data[line_nr], STR_LANG_AREA_INFORMATION_TRAM_TYPE, lastof(this->landinfo_data[line_nr])); this->landinfo_data.push_back(GetString(STR_LANG_AREA_INFORMATION_TRAM_TYPE));
line_nr++;
} }
/* Tram speed limit */ /* Tram speed limit */
if (td.tram_speed != 0) { if (td.tram_speed != 0) {
SetDParam(0, td.tram_speed); SetDParam(0, td.tram_speed);
GetString(this->landinfo_data[line_nr], STR_LANG_AREA_INFORMATION_TRAM_SPEED_LIMIT, lastof(this->landinfo_data[line_nr])); this->landinfo_data.push_back(GetString(STR_LANG_AREA_INFORMATION_TRAM_SPEED_LIMIT));
line_nr++;
} }
/* NewGRF name */ /* NewGRF name */
if (td.grf != nullptr) { if (td.grf != nullptr) {
SetDParamStr(0, td.grf); SetDParamStr(0, td.grf);
GetString(this->landinfo_data[line_nr], STR_LAND_AREA_INFORMATION_NEWGRF_NAME, lastof(this->landinfo_data[line_nr])); this->landinfo_data.push_back(GetString(STR_LAND_AREA_INFORMATION_NEWGRF_NAME));
line_nr++;
} }
assert(line_nr < LAND_INFO_CENTERED_LINES);
/* Mark last line empty */
this->landinfo_data[line_nr][0] = '\0';
/* Cargo acceptance is displayed in a extra multiline */ /* Cargo acceptance is displayed in a extra multiline */
char *strp = GetString(this->landinfo_data[LAND_INFO_MULTICENTER_LINE], STR_LAND_AREA_INFORMATION_CARGO_ACCEPTED, lastof(this->landinfo_data[LAND_INFO_MULTICENTER_LINE])); std::stringstream line;
bool found = false; line << GetString(STR_LAND_AREA_INFORMATION_CARGO_ACCEPTED);
bool found = false;
for (CargoID i = 0; i < NUM_CARGO; ++i) { for (CargoID i = 0; i < NUM_CARGO; ++i) {
if (acceptance[i] > 0) { if (acceptance[i] > 0) {
/* Add a comma between each item. */ /* Add a comma between each item. */
if (found) strp = strecpy(strp, ", ", lastof(this->landinfo_data[LAND_INFO_MULTICENTER_LINE])); if (found) line << ", ";
found = true; found = true;
/* If the accepted value is less than 8, show it in 1/8:ths */ /* If the accepted value is less than 8, show it in 1/8:ths */
if (acceptance[i] < 8) { if (acceptance[i] < 8) {
SetDParam(0, acceptance[i]); SetDParam(0, acceptance[i]);
SetDParam(1, CargoSpec::Get(i)->name); SetDParam(1, CargoSpec::Get(i)->name);
strp = GetString(strp, STR_LAND_AREA_INFORMATION_CARGO_EIGHTS, lastof(this->landinfo_data[LAND_INFO_MULTICENTER_LINE])); line << GetString(STR_LAND_AREA_INFORMATION_CARGO_EIGHTS);
} else { } else {
strp = GetString(strp, CargoSpec::Get(i)->name, lastof(this->landinfo_data[LAND_INFO_MULTICENTER_LINE])); line << GetString(CargoSpec::Get(i)->name);
} }
} }
} }
if (!found) this->landinfo_data[LAND_INFO_MULTICENTER_LINE][0] = '\0'; if (found) {
this->cargo_acceptance = line.str();
} else {
this->cargo_acceptance.clear();
}
} }
bool IsNewGRFInspectable() const override bool IsNewGRFInspectable() const override