OpenTTD Source: src/graph_gui.cpp Source File

OpenTTD Source 15.0-beta1

graph_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 "graph_gui.h"
12#include "window_gui.h"
13#include "company_base.h"
14#include "company_gui.h"
15#include "economy_func.h"
16#include "cargotype.h"
17#include "strings_func.h"
18#include "window_func.h"
19#include "gfx_func.h"
20#include "core/geometry_func.hpp"
21#include "currency.h"
22#include "timer/timer.h"
23#include "timer/timer_window.h"
24#include "timer/timer_game_tick.h"
25#include "timer/timer_game_economy.h"
26#include "zoom_func.h"
27#include "industry.h"
28
29#include "widgets/graph_widget.h"
30
31#include "table/strings.h"
32#include "table/sprites.h"
33
34#include "safeguards.h"
35
36/* Bitmasks of company and cargo indices that shouldn't be drawn. */
37static CompanyMask _legend_excluded_companies;
38static CargoTypes _legend_excluded_cargo_payment_rates;
39static CargoTypes _legend_excluded_cargo_production_history;
40
41/* Apparently these don't play well with enums. */
42static const OverflowSafeInt64 INVALID_DATAPOINT(INT64_MAX); // Value used for a datapoint that shouldn't be drawn.
43static const uint INVALID_DATAPOINT_POS = UINT_MAX; // Used to determine if the previous point was drawn.
44
45 constexpr double INT64_MAX_IN_DOUBLE = static_cast<double>(INT64_MAX - 512);
46static_assert(static_cast<int64_t>(INT64_MAX_IN_DOUBLE) < INT64_MAX);
47
48/****************/
49/* GRAPH LEGEND */
50/****************/
51
52 struct GraphLegendWindow : Window {
53 GraphLegendWindow(WindowDesc &desc, WindowNumber window_number) : Window(desc)
54 {
55 this->InitNested(window_number);
56
57 for (CompanyID c = COMPANY_FIRST; c < MAX_COMPANIES; c++) {
58 if (!HasBit(_legend_excluded_companies, c)) this->LowerWidget(WID_GL_FIRST_COMPANY + c);
59
60 this->OnInvalidateData(c);
61 }
62 }
63
64 void DrawWidget(const Rect &r, WidgetID widget) const override
65 {
66 if (!IsInsideMM(widget, WID_GL_FIRST_COMPANY, WID_GL_FIRST_COMPANY + MAX_COMPANIES)) return;
67
68 CompanyID cid = (CompanyID)(widget - WID_GL_FIRST_COMPANY);
69
70 if (!Company::IsValidID(cid)) return;
71
72 bool rtl = _current_text_dir == TD_RTL;
73
74 const Rect ir = r.Shrink(WidgetDimensions::scaled.framerect);
75 Dimension d = GetSpriteSize(SPR_COMPANY_ICON);
76 DrawCompanyIcon(cid, rtl ? ir.right - d.width : ir.left, CenterBounds(ir.top, ir.bottom, d.height));
77
78 const Rect tr = ir.Indent(d.width + WidgetDimensions::scaled.hsep_normal, rtl);
79 SetDParam(0, cid);
80 SetDParam(1, cid);
81 DrawString(tr.left, tr.right, CenterBounds(tr.top, tr.bottom, GetCharacterHeight(FS_NORMAL)), STR_COMPANY_NAME_COMPANY_NUM, HasBit(_legend_excluded_companies, cid) ? TC_BLACK : TC_WHITE);
82 }
83
84 void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override
85 {
86 if (!IsInsideMM(widget, WID_GL_FIRST_COMPANY, WID_GL_FIRST_COMPANY + MAX_COMPANIES)) return;
87
88 ToggleBit(_legend_excluded_companies, widget - WID_GL_FIRST_COMPANY);
89 this->ToggleWidgetLoweredState(widget);
90 this->SetDirty();
91 InvalidateWindowData(WC_INCOME_GRAPH, 0);
92 InvalidateWindowData(WC_OPERATING_PROFIT, 0);
93 InvalidateWindowData(WC_DELIVERED_CARGO, 0);
94 InvalidateWindowData(WC_PERFORMANCE_HISTORY, 0);
95 InvalidateWindowData(WC_COMPANY_VALUE, 0);
96 }
97
103 void OnInvalidateData([[maybe_unused]] int data = 0, [[maybe_unused]] bool gui_scope = true) override
104 {
105 if (!gui_scope) return;
106 if (Company::IsValidID(data)) return;
107
108 SetBit(_legend_excluded_companies, data);
109 this->RaiseWidget(data + WID_GL_FIRST_COMPANY);
110 }
111};
112
117 static std::unique_ptr<NWidgetBase> MakeNWidgetCompanyLines()
118{
119 auto vert = std::make_unique<NWidgetVertical>(NC_EQUALSIZE);
120 vert->SetPadding(2, 2, 2, 2);
121 uint sprite_height = GetSpriteSize(SPR_COMPANY_ICON, nullptr, ZOOM_LVL_NORMAL).height;
122
123 for (WidgetID widnum = WID_GL_FIRST_COMPANY; widnum <= WID_GL_LAST_COMPANY; widnum++) {
124 auto panel = std::make_unique<NWidgetBackground>(WWT_PANEL, COLOUR_BROWN, widnum);
125 panel->SetMinimalSize(246, sprite_height + WidgetDimensions::unscaled.framerect.Vertical());
126 panel->SetMinimalTextLines(1, WidgetDimensions::unscaled.framerect.Vertical(), FS_NORMAL);
127 panel->SetFill(1, 1);
128 panel->SetDataTip(0x0, STR_GRAPH_KEY_COMPANY_SELECTION_TOOLTIP);
129 vert->Add(std::move(panel));
130 }
131 return vert;
132}
133
134static constexpr NWidgetPart _nested_graph_legend_widgets[] = {
135 NWidget(NWID_HORIZONTAL),
136 NWidget(WWT_CLOSEBOX, COLOUR_BROWN),
137 NWidget(WWT_CAPTION, COLOUR_BROWN), SetDataTip(STR_GRAPH_KEY_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
138 NWidget(WWT_SHADEBOX, COLOUR_BROWN),
139 NWidget(WWT_STICKYBOX, COLOUR_BROWN),
140 EndContainer(),
141 NWidget(WWT_PANEL, COLOUR_BROWN, WID_GL_BACKGROUND),
142 NWidgetFunction(MakeNWidgetCompanyLines),
143 EndContainer(),
144};
145
146static WindowDesc _graph_legend_desc(
147 WDP_AUTO, "graph_legend", 0, 0,
148 WC_GRAPH_LEGEND, WC_NONE,
149 0,
150 _nested_graph_legend_widgets
151);
152
153static void ShowGraphLegend()
154{
155 AllocateWindowDescFront<GraphLegendWindow>(_graph_legend_desc, 0);
156}
157
159 struct ValuesInterval {
160 OverflowSafeInt64 highest;
161 OverflowSafeInt64 lowest;
162};
163
164/******************/
165/* BASE OF GRAPHS */
166/*****************/
167
168 struct BaseGraphWindow : Window {
169protected:
170 static const int GRAPH_MAX_DATASETS = 64;
171 static const int GRAPH_BASE_COLOUR = GREY_SCALE(2);
172 static const int GRAPH_GRID_COLOUR = GREY_SCALE(3);
173 static const int GRAPH_AXIS_LINE_COLOUR = GREY_SCALE(1);
174 static const int GRAPH_ZERO_LINE_COLOUR = GREY_SCALE(8);
175 static const int GRAPH_YEAR_LINE_COLOUR = GREY_SCALE(5);
176 static const int GRAPH_NUM_MONTHS = 24;
177 static const int PAYMENT_GRAPH_X_STEP_DAYS = 10;
178 static const int PAYMENT_GRAPH_X_STEP_SECONDS = 20;
179 static const int ECONOMY_QUARTER_MINUTES = 3;
180 static const int ECONOMY_MONTH_MINUTES = 1;
181
182 static const TextColour GRAPH_AXIS_LABEL_COLOUR = TC_BLACK;
183
184 static const int MIN_GRAPH_NUM_LINES_Y = 9;
185 static const int MIN_GRID_PIXEL_SIZE = 20;
186
187 uint64_t excluded_data;
188 uint64_t excluded_range;
189 uint8_t num_on_x_axis;
190 uint8_t num_vert_lines;
191
192 /* The starting month and year that values are plotted against. */
193 TimerGameEconomy::Month month;
194 TimerGameEconomy::Year year;
195 uint8_t month_increment;
196
197 bool draw_dates = true;
198
199 /* These values are used if the graph is being plotted against values
200 * rather than the dates specified by month and year. */
201 uint16_t x_values_start;
202 uint16_t x_values_increment;
203
204 StringID format_str_y_axis;
205
206 struct DataSet {
207 std::array<OverflowSafeInt64, GRAPH_NUM_MONTHS> values;
208 uint8_t colour;
209 uint8_t exclude_bit;
210 uint8_t range_bit;
211 uint8_t dash;
212 };
213 std::vector<DataSet> data;
214
215 std::span<const StringID> ranges = {};
216
222 std::span<const OverflowSafeInt64> GetDataSetRange(const DataSet &dataset) const
223 {
224 return {std::begin(dataset.values), std::begin(dataset.values) + this->num_on_x_axis};
225 }
226
233 ValuesInterval GetValuesInterval(int num_hori_lines) const
234 {
235 assert(num_hori_lines > 0);
236
237 ValuesInterval current_interval;
238 current_interval.highest = INT64_MIN;
239 current_interval.lowest = INT64_MAX;
240
241 for (const DataSet &dataset : this->data) {
242 if (HasBit(this->excluded_data, dataset.exclude_bit)) continue;
243 if (HasBit(this->excluded_range, dataset.range_bit)) continue;
244
245 for (const OverflowSafeInt64 &datapoint : this->GetDataSetRange(dataset)) {
246 if (datapoint != INVALID_DATAPOINT) {
247 current_interval.highest = std::max(current_interval.highest, datapoint);
248 current_interval.lowest = std::min(current_interval.lowest, datapoint);
249 }
250 }
251 }
252
253 /* Always include zero in the shown range. */
254 double abs_lower = (current_interval.lowest > 0) ? 0 : (double)abs(current_interval.lowest);
255 double abs_higher = (current_interval.highest < 0) ? 0 : (double)current_interval.highest;
256
257 /* Prevent showing values too close to the graph limits. */
258 abs_higher = (11.0 * abs_higher) / 10.0;
259 abs_lower = (11.0 * abs_lower) / 10.0;
260
261 int num_pos_grids;
262 OverflowSafeInt64 grid_size;
263
264 if (abs_lower != 0 || abs_higher != 0) {
265 /* The number of grids to reserve for the positive part is: */
266 num_pos_grids = (int)floor(0.5 + num_hori_lines * abs_higher / (abs_higher + abs_lower));
267
268 /* If there are any positive or negative values, force that they have at least one grid. */
269 if (num_pos_grids == 0 && abs_higher != 0) num_pos_grids++;
270 if (num_pos_grids == num_hori_lines && abs_lower != 0) num_pos_grids--;
271
272 /* Get the required grid size for each side and use the maximum one. */
273
274 OverflowSafeInt64 grid_size_higher = 0;
275 if (abs_higher > 0) {
276 grid_size_higher = abs_higher > INT64_MAX_IN_DOUBLE ? INT64_MAX : static_cast<int64_t>(abs_higher);
277 grid_size_higher = (grid_size_higher + num_pos_grids - 1) / num_pos_grids;
278 }
279
280 OverflowSafeInt64 grid_size_lower = 0;
281 if (abs_lower > 0) {
282 grid_size_lower = abs_lower > INT64_MAX_IN_DOUBLE ? INT64_MAX : static_cast<int64_t>(abs_lower);
283 grid_size_lower = (grid_size_lower + num_hori_lines - num_pos_grids - 1) / (num_hori_lines - num_pos_grids);
284 }
285
286 grid_size = std::max(grid_size_higher, grid_size_lower);
287 } else {
288 /* If both values are zero, show an empty graph. */
289 num_pos_grids = num_hori_lines / 2;
290 grid_size = 1;
291 }
292
293 current_interval.highest = num_pos_grids * grid_size;
294 current_interval.lowest = -(num_hori_lines - num_pos_grids) * grid_size;
295 return current_interval;
296 }
297
303 uint GetYLabelWidth(ValuesInterval current_interval, int num_hori_lines) const
304 {
305 /* draw text strings on the y axis */
306 int64_t y_label = current_interval.highest;
307 int64_t y_label_separation = (current_interval.highest - current_interval.lowest) / num_hori_lines;
308
309 uint max_width = 0;
310
311 for (int i = 0; i < (num_hori_lines + 1); i++) {
312 SetDParam(0, this->format_str_y_axis);
313 SetDParam(1, y_label);
314 Dimension d = GetStringBoundingBox(STR_GRAPH_Y_LABEL);
315 if (d.width > max_width) max_width = d.width;
316
317 y_label -= y_label_separation;
318 }
319
320 return max_width;
321 }
322
327 void DrawGraph(Rect r) const
328 {
329 uint x, y;
330 ValuesInterval interval;
331 int x_axis_offset;
332
333 /* the colours and cost array of GraphDrawer must accommodate
334 * both values for cargo and companies. So if any are higher, quit */
335 static_assert(GRAPH_MAX_DATASETS >= (int)NUM_CARGO && GRAPH_MAX_DATASETS >= (int)MAX_COMPANIES);
336 assert(this->num_vert_lines > 0);
337
338 /* Rect r will be adjusted to contain just the graph, with labels being
339 * placed outside the area. */
340 r.top += ScaleGUITrad(5) + GetCharacterHeight(FS_SMALL) / 2;
341 r.bottom -= (this->draw_dates ? 2 : 1) * GetCharacterHeight(FS_SMALL) + ScaleGUITrad(4);
342 r.left += ScaleGUITrad(9);
343 r.right -= ScaleGUITrad(5);
344
345 /* Initial number of horizontal lines. */
346 int num_hori_lines = 160 / ScaleGUITrad(MIN_GRID_PIXEL_SIZE);
347 /* For the rest of the height, the number of horizontal lines will increase more slowly. */
348 int resize = (r.bottom - r.top - 160) / (2 * ScaleGUITrad(MIN_GRID_PIXEL_SIZE));
349 if (resize > 0) num_hori_lines += resize;
350
351 interval = GetValuesInterval(num_hori_lines);
352
353 int label_width = GetYLabelWidth(interval, num_hori_lines);
354
355 r.left += label_width;
356
357 int x_sep = (r.right - r.left) / this->num_vert_lines;
358 int y_sep = (r.bottom - r.top) / num_hori_lines;
359
360 /* Redetermine right and bottom edge of graph to fit with the integer
361 * separation values. */
362 r.right = r.left + x_sep * this->num_vert_lines;
363 r.bottom = r.top + y_sep * num_hori_lines;
364
365 OverflowSafeInt64 interval_size = interval.highest + abs(interval.lowest);
366 /* Where to draw the X axis. Use floating point to avoid overflowing and results of zero. */
367 x_axis_offset = (int)((r.bottom - r.top) * (double)interval.highest / (double)interval_size);
368
369 /* Draw the background of the graph itself. */
370 GfxFillRect(r.left, r.top, r.right, r.bottom, GRAPH_BASE_COLOUR);
371
372 /* Draw the vertical grid lines. */
373
374 /* Don't draw the first line, as that's where the axis will be. */
375 x = r.left + x_sep;
376
377 int grid_colour = GRAPH_GRID_COLOUR;
378 for (int i = 1; i < this->num_vert_lines + 1; i++) {
379 /* If using wallclock units, we separate periods with a lighter line. */
380 if (TimerGameEconomy::UsingWallclockUnits()) {
381 grid_colour = (i % 4 == 0) ? GRAPH_YEAR_LINE_COLOUR : GRAPH_GRID_COLOUR;
382 }
383 GfxFillRect(x, r.top, x, r.bottom, grid_colour);
384 x += x_sep;
385 }
386
387 /* Draw the horizontal grid lines. */
388 y = r.bottom;
389
390 for (int i = 0; i < (num_hori_lines + 1); i++) {
391 GfxFillRect(r.left - ScaleGUITrad(3), y, r.left - 1, y, GRAPH_AXIS_LINE_COLOUR);
392 GfxFillRect(r.left, y, r.right, y, GRAPH_GRID_COLOUR);
393 y -= y_sep;
394 }
395
396 /* Draw the y axis. */
397 GfxFillRect(r.left, r.top, r.left, r.bottom, GRAPH_AXIS_LINE_COLOUR);
398
399 /* Draw the x axis. */
400 y = x_axis_offset + r.top;
401 GfxFillRect(r.left, y, r.right, y, GRAPH_ZERO_LINE_COLOUR);
402
403 /* Find the largest value that will be drawn. */
404 if (this->num_on_x_axis == 0) return;
405
406 assert(this->num_on_x_axis > 0);
407
408 /* draw text strings on the y axis */
409 int64_t y_label = interval.highest;
410 int64_t y_label_separation = abs(interval.highest - interval.lowest) / num_hori_lines;
411
412 y = r.top - GetCharacterHeight(FS_SMALL) / 2;
413
414 for (int i = 0; i < (num_hori_lines + 1); i++) {
415 SetDParam(0, this->format_str_y_axis);
416 SetDParam(1, y_label);
417 DrawString(r.left - label_width - ScaleGUITrad(4), r.left - ScaleGUITrad(4), y, STR_GRAPH_Y_LABEL, GRAPH_AXIS_LABEL_COLOUR, SA_RIGHT);
418
419 y_label -= y_label_separation;
420 y += y_sep;
421 }
422
423 /* Draw x-axis labels and markings for graphs based on financial quarters and years. */
424 if (this->draw_dates) {
425 x = r.left;
426 y = r.bottom + ScaleGUITrad(2);
427 TimerGameEconomy::Month month = this->month;
428 TimerGameEconomy::Year year = this->year;
429 for (int i = 0; i < this->num_on_x_axis; i++) {
430 SetDParam(0, month + STR_MONTH_ABBREV_JAN);
431 SetDParam(1, year);
432 DrawStringMultiLine(x, x + x_sep, y, this->height, month == 0 ? STR_GRAPH_X_LABEL_MONTH_YEAR : STR_GRAPH_X_LABEL_MONTH, GRAPH_AXIS_LABEL_COLOUR, SA_LEFT);
433
434 month += this->month_increment;
435 if (month >= 12) {
436 month = 0;
437 year++;
438
439 /* Draw a lighter grid line between years. Top and bottom adjustments ensure we don't draw over top and bottom horizontal grid lines. */
440 GfxFillRect(x + x_sep, r.top + 1, x + x_sep, r.bottom - 1, GRAPH_YEAR_LINE_COLOUR);
441 }
442 x += x_sep;
443 }
444 } else {
445 /* Draw x-axis labels for graphs not based on quarterly performance (cargo payment rates, and all graphs when using wallclock units). */
446 x = r.left;
447 y = r.bottom + ScaleGUITrad(2);
448 uint16_t label = this->x_values_start;
449
450 for (int i = 0; i < this->num_on_x_axis; i++) {
451 SetDParam(0, label);
452 DrawString(x + 1, x + x_sep - 1, y, STR_GRAPH_Y_LABEL_NUMBER, GRAPH_AXIS_LABEL_COLOUR, SA_HOR_CENTER);
453
454 label += this->x_values_increment;
455 x += x_sep;
456 }
457 }
458
459 /* draw lines and dots */
460 uint linewidth = _settings_client.gui.graph_line_thickness;
461 uint pointoffs1 = (linewidth + 1) / 2;
462 uint pointoffs2 = linewidth + 1 - pointoffs1;
463
464 for (const DataSet &dataset : this->data) {
465 if (HasBit(this->excluded_data, dataset.exclude_bit)) continue;
466 if (HasBit(this->excluded_range, dataset.range_bit)) continue;
467
468 /* Centre the dot between the grid lines. */
469 x = r.left + (x_sep / 2);
470
471 uint prev_x = INVALID_DATAPOINT_POS;
472 uint prev_y = INVALID_DATAPOINT_POS;
473
474 const uint dash = ScaleGUITrad(dataset.dash);
475 for (OverflowSafeInt64 datapoint : this->GetDataSetRange(dataset)) {
476 if (datapoint != INVALID_DATAPOINT) {
477 /*
478 * Check whether we need to reduce the 'accuracy' of the
479 * datapoint value and the highest value to split overflows.
480 * And when 'drawing' 'one million' or 'one million and one'
481 * there is no significant difference, so the least
482 * significant bits can just be removed.
483 *
484 * If there are more bits needed than would fit in a 32 bits
485 * integer, so at about 31 bits because of the sign bit, the
486 * least significant bits are removed.
487 */
488 int mult_range = FindLastBit<uint32_t>(x_axis_offset) + FindLastBit<uint64_t>(abs(datapoint));
489 int reduce_range = std::max(mult_range - 31, 0);
490
491 /* Handle negative values differently (don't shift sign) */
492 if (datapoint < 0) {
493 datapoint = -(abs(datapoint) >> reduce_range);
494 } else {
495 datapoint >>= reduce_range;
496 }
497 y = r.top + x_axis_offset - ((r.bottom - r.top) * datapoint) / (interval_size >> reduce_range);
498
499 /* Draw the point. */
500 GfxFillRect(x - pointoffs1, y - pointoffs1, x + pointoffs2, y + pointoffs2, dataset.colour);
501
502 /* Draw the line connected to the previous point. */
503 if (prev_x != INVALID_DATAPOINT_POS) GfxDrawLine(prev_x, prev_y, x, y, dataset.colour, linewidth, dash);
504
505 prev_x = x;
506 prev_y = y;
507 } else {
508 prev_x = INVALID_DATAPOINT_POS;
509 prev_y = INVALID_DATAPOINT_POS;
510 }
511
512 x += x_sep;
513 }
514 }
515 }
516
517 BaseGraphWindow(WindowDesc &desc, StringID format_str_y_axis) :
518 Window(desc),
519 format_str_y_axis(format_str_y_axis)
520 {
521 SetWindowDirty(WC_GRAPH_LEGEND, 0);
522 this->num_vert_lines = GRAPH_NUM_MONTHS;
523 this->month_increment = 3;
524 }
525
526 void InitializeWindow(WindowNumber number)
527 {
528 /* Initialise the dataset */
529 this->UpdateStatistics(true);
530
531 this->CreateNestedTree();
532
533 auto *wid = this->GetWidget<NWidgetCore>(WID_GRAPH_FOOTER);
534 if (wid != nullptr && TimerGameEconomy::UsingWallclockUnits()) {
535 wid->SetDataTip(STR_GRAPH_LAST_72_MINUTES_TIME_LABEL, STR_NULL);
536 }
537
538 this->FinishInitNested(number);
539 }
540
541public:
542 void UpdateWidgetSize(WidgetID widget, Dimension &size, [[maybe_unused]] const Dimension &padding, [[maybe_unused]] Dimension &fill, [[maybe_unused]] Dimension &resize) override
543 {
544 switch (widget) {
545 case WID_GRAPH_RANGE_MATRIX:
546 for (const StringID &str : this->ranges) {
547 size = maxdim(size, GetStringBoundingBox(str, FS_SMALL));
548 }
549
550 size.width += WidgetDimensions::scaled.framerect.Horizontal();
551 size.height += WidgetDimensions::scaled.framerect.Vertical();
552
553 /* Set fixed height for number of ranges. */
554 size.height *= static_cast<uint>(std::size(this->ranges));
555
556 resize.width = 0;
557 resize.height = 0;
558 this->GetWidget<NWidgetCore>(WID_GRAPH_RANGE_MATRIX)->SetDataTip((1 << MAT_COL_START) | (static_cast<uint16_t>(std::size(this->ranges)) << MAT_ROW_START), 0);
559 break;
560
561 case WID_GRAPH_GRAPH: {
562 uint x_label_width = 0;
563
564 /* Draw x-axis labels and markings for graphs based on financial quarters and years. */
565 if (this->draw_dates) {
566 TimerGameEconomy::Month month = this->month;
567 TimerGameEconomy::Year year = this->year;
568 for (int i = 0; i < this->num_on_x_axis; i++) {
569 SetDParam(0, month + STR_MONTH_ABBREV_JAN);
570 SetDParam(1, year);
571 x_label_width = std::max(x_label_width, GetStringBoundingBox(month == 0 ? STR_GRAPH_X_LABEL_MONTH_YEAR : STR_GRAPH_X_LABEL_MONTH).width);
572
573 month += this->month_increment;
574 if (month >= 12) {
575 month = 0;
576 year++;
577 }
578 }
579 } else {
580 /* Draw x-axis labels for graphs not based on quarterly performance (cargo payment rates). */
581 SetDParamMaxValue(0, this->x_values_start + this->num_on_x_axis * this->x_values_increment, 0, FS_SMALL);
582 x_label_width = GetStringBoundingBox(STR_GRAPH_Y_LABEL_NUMBER).width;
583 }
584
585 SetDParam(0, this->format_str_y_axis);
586 SetDParam(1, INT64_MAX);
587 uint y_label_width = GetStringBoundingBox(STR_GRAPH_Y_LABEL).width;
588
589 size.width = std::max<uint>(size.width, ScaleGUITrad(5) + y_label_width + this->num_vert_lines * (x_label_width + ScaleGUITrad(5)) + ScaleGUITrad(9));
590 size.height = std::max<uint>(size.height, ScaleGUITrad(5) + (1 + MIN_GRAPH_NUM_LINES_Y * 2 + (this->draw_dates ? 3 : 1)) * GetCharacterHeight(FS_SMALL) + ScaleGUITrad(4));
591 size.height = std::max<uint>(size.height, size.width / 3);
592 break;
593 }
594
595 default: break;
596 }
597 }
598
599 void DrawWidget(const Rect &r, WidgetID widget) const override
600 {
601 switch (widget) {
602 case WID_GRAPH_GRAPH:
603 this->DrawGraph(r);
604 break;
605
606 case WID_GRAPH_RANGE_MATRIX: {
607 uint line_height = GetCharacterHeight(FS_SMALL) + WidgetDimensions::scaled.framerect.Vertical();
608 uint index = 0;
609 Rect line = r.WithHeight(line_height);
610 for (const auto &str : this->ranges) {
611 bool lowered = !HasBit(this->excluded_range, index);
612
613 /* Redraw frame if lowered */
614 if (lowered) DrawFrameRect(line, COLOUR_BROWN, FR_LOWERED);
615
616 const Rect text = line.Shrink(WidgetDimensions::scaled.framerect);
617 DrawString(text, str, TC_BLACK, SA_CENTER, false, FS_SMALL);
618
619 line = line.Translate(0, line_height);
620 ++index;
621 }
622 break;
623 }
624
625 default: break;
626 }
627 }
628
629 virtual OverflowSafeInt64 GetGraphData(const Company *, int)
630 {
631 return INVALID_DATAPOINT;
632 }
633
634 void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override
635 {
636 /* Clicked on legend? */
637 switch (widget) {
638 case WID_GRAPH_KEY_BUTTON:
639 ShowGraphLegend();
640 break;
641
642 case WID_GRAPH_RANGE_MATRIX: {
643 int row = GetRowFromWidget(pt.y, widget, 0, GetCharacterHeight(FS_SMALL) + WidgetDimensions::scaled.framerect.Vertical());
644
645 ToggleBit(this->excluded_range, row);
646 this->SetDirty();
647 break;
648 }
649
650 default: break;
651 }
652 }
653
654 void OnGameTick() override
655 {
656 this->UpdateStatistics(false);
657 }
658
664 void OnInvalidateData([[maybe_unused]] int data = 0, [[maybe_unused]] bool gui_scope = true) override
665 {
666 if (!gui_scope) return;
667 this->UpdateStatistics(true);
668 }
669
674 virtual void UpdateStatistics(bool initialize)
675 {
676 CompanyMask excluded_companies = _legend_excluded_companies;
677
678 /* Exclude the companies which aren't valid */
679 for (CompanyID c = COMPANY_FIRST; c < MAX_COMPANIES; c++) {
680 if (!Company::IsValidID(c)) SetBit(excluded_companies, c);
681 }
682
683 uint8_t nums = 0;
684 for (const Company *c : Company::Iterate()) {
685 nums = std::min(this->num_vert_lines, std::max(nums, c->num_valid_stat_ent));
686 }
687
688 int mo = (TimerGameEconomy::month / this->month_increment - nums) * this->month_increment;
689 auto yr = TimerGameEconomy::year;
690 while (mo < 0) {
691 yr--;
692 mo += 12;
693 }
694
695 if (!initialize && this->excluded_data == excluded_companies && this->num_on_x_axis == nums &&
696 this->year == yr && this->month == mo) {
697 /* There's no reason to get new stats */
698 return;
699 }
700
701 this->excluded_data = excluded_companies;
702 this->num_on_x_axis = nums;
703 this->year = yr;
704 this->month = mo;
705
706 this->data.clear();
707 for (CompanyID k = COMPANY_FIRST; k < MAX_COMPANIES; k++) {
708 const Company *c = Company::GetIfValid(k);
709 if (c == nullptr) continue;
710
711 DataSet &dataset = this->data.emplace_back();
712 dataset.colour = GetColourGradient(c->colour, SHADE_LIGHTER);
713 dataset.exclude_bit = k;
714
715 for (int j = this->num_on_x_axis, i = 0; --j >= 0;) {
716 if (j >= c->num_valid_stat_ent) {
717 dataset.values[i] = INVALID_DATAPOINT;
718 } else {
719 /* Ensure we never assign INVALID_DATAPOINT, as that has another meaning.
720 * Instead, use the value just under it. Hopefully nobody will notice. */
721 dataset.values[i] = std::min(GetGraphData(c, j), INVALID_DATAPOINT - 1);
722 }
723 i++;
724 }
725 }
726 }
727};
728
729
730/********************/
731/* OPERATING PROFIT */
732/********************/
733
734 struct OperatingProfitGraphWindow : BaseGraphWindow {
735 OperatingProfitGraphWindow(WindowDesc &desc, WindowNumber window_number) :
736 BaseGraphWindow(desc, STR_JUST_CURRENCY_SHORT)
737 {
738 this->num_on_x_axis = GRAPH_NUM_MONTHS;
739 this->num_vert_lines = GRAPH_NUM_MONTHS;
740 this->x_values_start = ECONOMY_QUARTER_MINUTES;
741 this->x_values_increment = ECONOMY_QUARTER_MINUTES;
742 this->draw_dates = !TimerGameEconomy::UsingWallclockUnits();
743
744 this->InitializeWindow(window_number);
745 }
746
747 OverflowSafeInt64 GetGraphData(const Company *c, int j) override
748 {
749 return c->old_economy[j].income + c->old_economy[j].expenses;
750 }
751};
752
753static constexpr NWidgetPart _nested_operating_profit_widgets[] = {
754 NWidget(NWID_HORIZONTAL),
755 NWidget(WWT_CLOSEBOX, COLOUR_BROWN),
756 NWidget(WWT_CAPTION, COLOUR_BROWN), SetDataTip(STR_GRAPH_OPERATING_PROFIT_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
757 NWidget(WWT_PUSHTXTBTN, COLOUR_BROWN, WID_GRAPH_KEY_BUTTON), SetMinimalSize(50, 0), SetDataTip(STR_GRAPH_KEY_BUTTON, STR_GRAPH_KEY_TOOLTIP),
758 NWidget(WWT_SHADEBOX, COLOUR_BROWN),
759 NWidget(WWT_DEFSIZEBOX, COLOUR_BROWN),
760 NWidget(WWT_STICKYBOX, COLOUR_BROWN),
761 EndContainer(),
762 NWidget(WWT_PANEL, COLOUR_BROWN, WID_GRAPH_BACKGROUND),
763 NWidget(NWID_VERTICAL),
764 NWidget(WWT_EMPTY, COLOUR_BROWN, WID_GRAPH_GRAPH), SetMinimalSize(576, 160), SetFill(1, 1), SetResize(1, 1),
765 NWidget(NWID_HORIZONTAL),
766 NWidget(NWID_SPACER), SetMinimalSize(12, 0), SetFill(1, 0), SetResize(1, 0),
767 NWidget(WWT_TEXT, COLOUR_BROWN, WID_GRAPH_FOOTER), SetMinimalSize(0, 6), SetPadding(2, 0, 2, 0), SetDataTip(STR_EMPTY, STR_NULL),
768 NWidget(NWID_SPACER), SetFill(1, 0), SetResize(1, 0),
769 NWidget(WWT_RESIZEBOX, COLOUR_BROWN, WID_GRAPH_RESIZE), SetDataTip(RWV_HIDE_BEVEL, STR_TOOLTIP_RESIZE),
770 EndContainer(),
771 EndContainer(),
772 EndContainer(),
773};
774
775static WindowDesc _operating_profit_desc(
776 WDP_AUTO, "graph_operating_profit", 0, 0,
777 WC_OPERATING_PROFIT, WC_NONE,
778 0,
779 _nested_operating_profit_widgets
780);
781
782
783void ShowOperatingProfitGraph()
784{
785 AllocateWindowDescFront<OperatingProfitGraphWindow>(_operating_profit_desc, 0);
786}
787
788
789/****************/
790/* INCOME GRAPH */
791/****************/
792
793 struct IncomeGraphWindow : BaseGraphWindow {
794 IncomeGraphWindow(WindowDesc &desc, WindowNumber window_number) :
795 BaseGraphWindow(desc, STR_JUST_CURRENCY_SHORT)
796 {
797 this->num_on_x_axis = GRAPH_NUM_MONTHS;
798 this->num_vert_lines = GRAPH_NUM_MONTHS;
799 this->x_values_start = ECONOMY_QUARTER_MINUTES;
800 this->x_values_increment = ECONOMY_QUARTER_MINUTES;
801 this->draw_dates = !TimerGameEconomy::UsingWallclockUnits();
802
803 this->InitializeWindow(window_number);
804 }
805
806 OverflowSafeInt64 GetGraphData(const Company *c, int j) override
807 {
808 return c->old_economy[j].income;
809 }
810};
811
812static constexpr NWidgetPart _nested_income_graph_widgets[] = {
813 NWidget(NWID_HORIZONTAL),
814 NWidget(WWT_CLOSEBOX, COLOUR_BROWN),
815 NWidget(WWT_CAPTION, COLOUR_BROWN), SetDataTip(STR_GRAPH_INCOME_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
816 NWidget(WWT_PUSHTXTBTN, COLOUR_BROWN, WID_GRAPH_KEY_BUTTON), SetMinimalSize(50, 0), SetDataTip(STR_GRAPH_KEY_BUTTON, STR_GRAPH_KEY_TOOLTIP),
817 NWidget(WWT_SHADEBOX, COLOUR_BROWN),
818 NWidget(WWT_DEFSIZEBOX, COLOUR_BROWN),
819 NWidget(WWT_STICKYBOX, COLOUR_BROWN),
820 EndContainer(),
821 NWidget(WWT_PANEL, COLOUR_BROWN, WID_GRAPH_BACKGROUND),
822 NWidget(NWID_VERTICAL),
823 NWidget(WWT_EMPTY, COLOUR_BROWN, WID_GRAPH_GRAPH), SetMinimalSize(576, 128), SetFill(1, 1), SetResize(1, 1),
824 NWidget(NWID_HORIZONTAL),
825 NWidget(NWID_SPACER), SetMinimalSize(12, 0), SetFill(1, 0), SetResize(1, 0),
826 NWidget(WWT_TEXT, COLOUR_BROWN, WID_GRAPH_FOOTER), SetMinimalSize(0, 6), SetPadding(2, 0, 2, 0), SetDataTip(STR_EMPTY, STR_NULL),
827 NWidget(NWID_SPACER), SetFill(1, 0), SetResize(1, 0),
828 NWidget(WWT_RESIZEBOX, COLOUR_BROWN, WID_GRAPH_RESIZE), SetDataTip(RWV_HIDE_BEVEL, STR_TOOLTIP_RESIZE),
829 EndContainer(),
830 EndContainer(),
831 EndContainer(),
832};
833
834static WindowDesc _income_graph_desc(
835 WDP_AUTO, "graph_income", 0, 0,
836 WC_INCOME_GRAPH, WC_NONE,
837 0,
838 _nested_income_graph_widgets
839);
840
841void ShowIncomeGraph()
842{
843 AllocateWindowDescFront<IncomeGraphWindow>(_income_graph_desc, 0);
844}
845
846/*******************/
847/* DELIVERED CARGO */
848/*******************/
849
850 struct DeliveredCargoGraphWindow : BaseGraphWindow {
851 DeliveredCargoGraphWindow(WindowDesc &desc, WindowNumber window_number) :
852 BaseGraphWindow(desc, STR_JUST_COMMA)
853 {
854 this->num_on_x_axis = GRAPH_NUM_MONTHS;
855 this->num_vert_lines = GRAPH_NUM_MONTHS;
856 this->x_values_start = ECONOMY_QUARTER_MINUTES;
857 this->x_values_increment = ECONOMY_QUARTER_MINUTES;
858 this->draw_dates = !TimerGameEconomy::UsingWallclockUnits();
859
860 this->InitializeWindow(window_number);
861 }
862
863 OverflowSafeInt64 GetGraphData(const Company *c, int j) override
864 {
865 return c->old_economy[j].delivered_cargo.GetSum<OverflowSafeInt64>();
866 }
867};
868
869static constexpr NWidgetPart _nested_delivered_cargo_graph_widgets[] = {
870 NWidget(NWID_HORIZONTAL),
871 NWidget(WWT_CLOSEBOX, COLOUR_BROWN),
872 NWidget(WWT_CAPTION, COLOUR_BROWN), SetDataTip(STR_GRAPH_CARGO_DELIVERED_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
873 NWidget(WWT_PUSHTXTBTN, COLOUR_BROWN, WID_GRAPH_KEY_BUTTON), SetMinimalSize(50, 0), SetDataTip(STR_GRAPH_KEY_BUTTON, STR_GRAPH_KEY_TOOLTIP),
874 NWidget(WWT_SHADEBOX, COLOUR_BROWN),
875 NWidget(WWT_DEFSIZEBOX, COLOUR_BROWN),
876 NWidget(WWT_STICKYBOX, COLOUR_BROWN),
877 EndContainer(),
878 NWidget(WWT_PANEL, COLOUR_BROWN, WID_GRAPH_BACKGROUND),
879 NWidget(NWID_VERTICAL),
880 NWidget(WWT_EMPTY, COLOUR_BROWN, WID_GRAPH_GRAPH), SetMinimalSize(576, 128), SetFill(1, 1), SetResize(1, 1),
881 NWidget(NWID_HORIZONTAL),
882 NWidget(NWID_SPACER), SetMinimalSize(12, 0), SetFill(1, 0), SetResize(1, 0),
883 NWidget(WWT_TEXT, COLOUR_BROWN, WID_GRAPH_FOOTER), SetMinimalSize(0, 6), SetPadding(2, 0, 2, 0), SetDataTip(STR_EMPTY, STR_NULL),
884 NWidget(NWID_SPACER), SetFill(1, 0), SetResize(1, 0),
885 NWidget(WWT_RESIZEBOX, COLOUR_BROWN, WID_GRAPH_RESIZE), SetDataTip(RWV_HIDE_BEVEL, STR_TOOLTIP_RESIZE),
886 EndContainer(),
887 EndContainer(),
888 EndContainer(),
889};
890
891static WindowDesc _delivered_cargo_graph_desc(
892 WDP_AUTO, "graph_delivered_cargo", 0, 0,
893 WC_DELIVERED_CARGO, WC_NONE,
894 0,
895 _nested_delivered_cargo_graph_widgets
896);
897
898void ShowDeliveredCargoGraph()
899{
900 AllocateWindowDescFront<DeliveredCargoGraphWindow>(_delivered_cargo_graph_desc, 0);
901}
902
903/***********************/
904/* PERFORMANCE HISTORY */
905/***********************/
906
907 struct PerformanceHistoryGraphWindow : BaseGraphWindow {
908 PerformanceHistoryGraphWindow(WindowDesc &desc, WindowNumber window_number) :
909 BaseGraphWindow(desc, STR_JUST_COMMA)
910 {
911 this->num_on_x_axis = GRAPH_NUM_MONTHS;
912 this->num_vert_lines = GRAPH_NUM_MONTHS;
913 this->x_values_start = ECONOMY_QUARTER_MINUTES;
914 this->x_values_increment = ECONOMY_QUARTER_MINUTES;
915 this->draw_dates = !TimerGameEconomy::UsingWallclockUnits();
916
917 this->InitializeWindow(window_number);
918 }
919
920 OverflowSafeInt64 GetGraphData(const Company *c, int j) override
921 {
922 return c->old_economy[j].performance_history;
923 }
924
925 void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override
926 {
927 if (widget == WID_PHG_DETAILED_PERFORMANCE) ShowPerformanceRatingDetail();
928 this->BaseGraphWindow::OnClick(pt, widget, click_count);
929 }
930};
931
932static constexpr NWidgetPart _nested_performance_history_widgets[] = {
933 NWidget(NWID_HORIZONTAL),
934 NWidget(WWT_CLOSEBOX, COLOUR_BROWN),
935 NWidget(WWT_CAPTION, COLOUR_BROWN), SetDataTip(STR_GRAPH_COMPANY_PERFORMANCE_RATINGS_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
936 NWidget(WWT_PUSHTXTBTN, COLOUR_BROWN, WID_PHG_DETAILED_PERFORMANCE), SetMinimalSize(50, 0), SetDataTip(STR_PERFORMANCE_DETAIL_KEY, STR_GRAPH_PERFORMANCE_DETAIL_TOOLTIP),
937 NWidget(WWT_PUSHTXTBTN, COLOUR_BROWN, WID_GRAPH_KEY_BUTTON), SetMinimalSize(50, 0), SetDataTip(STR_GRAPH_KEY_BUTTON, STR_GRAPH_KEY_TOOLTIP),
938 NWidget(WWT_SHADEBOX, COLOUR_BROWN),
939 NWidget(WWT_DEFSIZEBOX, COLOUR_BROWN),
940 NWidget(WWT_STICKYBOX, COLOUR_BROWN),
941 EndContainer(),
942 NWidget(WWT_PANEL, COLOUR_BROWN, WID_GRAPH_BACKGROUND),
943 NWidget(NWID_VERTICAL),
944 NWidget(WWT_EMPTY, COLOUR_BROWN, WID_GRAPH_GRAPH), SetMinimalSize(576, 224), SetFill(1, 1), SetResize(1, 1),
945 NWidget(NWID_HORIZONTAL),
946 NWidget(NWID_SPACER), SetMinimalSize(12, 0), SetFill(1, 0), SetResize(1, 0),
947 NWidget(WWT_TEXT, COLOUR_BROWN, WID_GRAPH_FOOTER), SetMinimalSize(0, 6), SetPadding(2, 0, 2, 0), SetDataTip(STR_EMPTY, STR_NULL),
948 NWidget(NWID_SPACER), SetFill(1, 0), SetResize(1, 0),
949 NWidget(WWT_RESIZEBOX, COLOUR_BROWN, WID_GRAPH_RESIZE), SetDataTip(RWV_HIDE_BEVEL, STR_TOOLTIP_RESIZE),
950 EndContainer(),
951 EndContainer(),
952 EndContainer(),
953};
954
955static WindowDesc _performance_history_desc(
956 WDP_AUTO, "graph_performance", 0, 0,
957 WC_PERFORMANCE_HISTORY, WC_NONE,
958 0,
959 _nested_performance_history_widgets
960);
961
962void ShowPerformanceHistoryGraph()
963{
964 AllocateWindowDescFront<PerformanceHistoryGraphWindow>(_performance_history_desc, 0);
965}
966
967/*****************/
968/* COMPANY VALUE */
969/*****************/
970
971 struct CompanyValueGraphWindow : BaseGraphWindow {
972 CompanyValueGraphWindow(WindowDesc &desc, WindowNumber window_number) :
973 BaseGraphWindow(desc, STR_JUST_CURRENCY_SHORT)
974 {
975 this->num_on_x_axis = GRAPH_NUM_MONTHS;
976 this->num_vert_lines = GRAPH_NUM_MONTHS;
977 this->x_values_start = ECONOMY_QUARTER_MINUTES;
978 this->x_values_increment = ECONOMY_QUARTER_MINUTES;
979 this->draw_dates = !TimerGameEconomy::UsingWallclockUnits();
980
981 this->InitializeWindow(window_number);
982 }
983
984 OverflowSafeInt64 GetGraphData(const Company *c, int j) override
985 {
986 return c->old_economy[j].company_value;
987 }
988};
989
990static constexpr NWidgetPart _nested_company_value_graph_widgets[] = {
991 NWidget(NWID_HORIZONTAL),
992 NWidget(WWT_CLOSEBOX, COLOUR_BROWN),
993 NWidget(WWT_CAPTION, COLOUR_BROWN), SetDataTip(STR_GRAPH_COMPANY_VALUES_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
994 NWidget(WWT_PUSHTXTBTN, COLOUR_BROWN, WID_GRAPH_KEY_BUTTON), SetMinimalSize(50, 0), SetDataTip(STR_GRAPH_KEY_BUTTON, STR_GRAPH_KEY_TOOLTIP),
995 NWidget(WWT_SHADEBOX, COLOUR_BROWN),
996 NWidget(WWT_DEFSIZEBOX, COLOUR_BROWN),
997 NWidget(WWT_STICKYBOX, COLOUR_BROWN),
998 EndContainer(),
999 NWidget(WWT_PANEL, COLOUR_BROWN, WID_GRAPH_BACKGROUND),
1000 NWidget(NWID_VERTICAL),
1001 NWidget(WWT_EMPTY, COLOUR_BROWN, WID_GRAPH_GRAPH), SetMinimalSize(576, 224), SetFill(1, 1), SetResize(1, 1),
1002 NWidget(NWID_HORIZONTAL),
1003 NWidget(NWID_SPACER), SetMinimalSize(12, 0), SetFill(1, 0), SetResize(1, 0),
1004 NWidget(WWT_TEXT, COLOUR_BROWN, WID_GRAPH_FOOTER), SetMinimalSize(0, 6), SetPadding(2, 0, 2, 0), SetDataTip(STR_EMPTY, STR_NULL),
1005 NWidget(NWID_SPACER), SetFill(1, 0), SetResize(1, 0),
1006 NWidget(WWT_RESIZEBOX, COLOUR_BROWN, WID_GRAPH_RESIZE), SetDataTip(RWV_HIDE_BEVEL, STR_TOOLTIP_RESIZE),
1007 EndContainer(),
1008 EndContainer(),
1009 EndContainer(),
1010};
1011
1012static WindowDesc _company_value_graph_desc(
1013 WDP_AUTO, "graph_company_value", 0, 0,
1014 WC_COMPANY_VALUE, WC_NONE,
1015 0,
1016 _nested_company_value_graph_widgets
1017);
1018
1019void ShowCompanyValueGraph()
1020{
1021 AllocateWindowDescFront<CompanyValueGraphWindow>(_company_value_graph_desc, 0);
1022}
1023
1024/*****************/
1025/* PAYMENT RATES */
1026/*****************/
1027
1028 struct PaymentRatesGraphWindow : BaseGraphWindow {
1029 uint line_height;
1030 Scrollbar *vscroll;
1031 uint legend_width;
1032
1033 PaymentRatesGraphWindow(WindowDesc &desc, WindowNumber window_number) :
1034 BaseGraphWindow(desc, STR_JUST_CURRENCY_SHORT)
1035 {
1036 this->num_on_x_axis = 20;
1037 this->num_vert_lines = 20;
1038 this->draw_dates = false;
1039 /* The x-axis is labeled in either seconds or days. A day is two seconds, so we adjust the label if needed. */
1040 this->x_values_start = (TimerGameEconomy::UsingWallclockUnits() ? PAYMENT_GRAPH_X_STEP_SECONDS : PAYMENT_GRAPH_X_STEP_DAYS);
1041 this->x_values_increment = (TimerGameEconomy::UsingWallclockUnits() ? PAYMENT_GRAPH_X_STEP_SECONDS : PAYMENT_GRAPH_X_STEP_DAYS);
1042
1043 this->CreateNestedTree();
1044 this->vscroll = this->GetScrollbar(WID_GRAPH_MATRIX_SCROLLBAR);
1045 this->vscroll->SetCount(_sorted_standard_cargo_specs.size());
1046
1047 auto *wid = this->GetWidget<NWidgetCore>(WID_GRAPH_FOOTER);
1048 wid->SetDataTip(TimerGameEconomy::UsingWallclockUnits() ? STR_GRAPH_CARGO_PAYMENT_RATES_SECONDS: STR_GRAPH_CARGO_PAYMENT_RATES_DAYS, STR_NULL);
1049
1050 /* Initialise the dataset */
1051 this->UpdatePaymentRates();
1052
1053 this->FinishInitNested(window_number);
1054 }
1055
1056 void OnInit() override
1057 {
1058 /* Width of the legend blob. */
1059 this->legend_width = GetCharacterHeight(FS_SMALL) * 9 / 6;
1060 }
1061
1062 void UpdateExcludedData()
1063 {
1064 this->excluded_data = 0;
1065
1066 int i = 0;
1067 for (const CargoSpec *cs : _sorted_standard_cargo_specs) {
1068 if (HasBit(_legend_excluded_cargo_payment_rates, cs->Index())) SetBit(this->excluded_data, i);
1069 i++;
1070 }
1071 }
1072
1073 void UpdateWidgetSize(WidgetID widget, Dimension &size, [[maybe_unused]] const Dimension &padding, [[maybe_unused]] Dimension &fill, [[maybe_unused]] Dimension &resize) override
1074 {
1075 if (widget != WID_GRAPH_MATRIX) {
1076 BaseGraphWindow::UpdateWidgetSize(widget, size, padding, fill, resize);
1077 return;
1078 }
1079
1080 size.height = GetCharacterHeight(FS_SMALL) + WidgetDimensions::scaled.framerect.Vertical();
1081
1082 for (const CargoSpec *cs : _sorted_standard_cargo_specs) {
1083 SetDParam(0, cs->name);
1084 Dimension d = GetStringBoundingBox(STR_GRAPH_CARGO_PAYMENT_CARGO);
1085 d.width += this->legend_width + WidgetDimensions::scaled.hsep_normal; // colour field
1086 d.width += WidgetDimensions::scaled.framerect.Horizontal();
1087 d.height += WidgetDimensions::scaled.framerect.Vertical();
1088 size = maxdim(d, size);
1089 }
1090
1091 this->line_height = size.height;
1092 size.height = this->line_height * 11; /* Default number of cargo types in most climates. */
1093 resize.width = 0;
1094 resize.height = this->line_height;
1095 }
1096
1097 void DrawWidget(const Rect &r, WidgetID widget) const override
1098 {
1099 if (widget != WID_GRAPH_MATRIX) {
1100 BaseGraphWindow::DrawWidget(r, widget);
1101 return;
1102 }
1103
1104 bool rtl = _current_text_dir == TD_RTL;
1105
1106 auto [first, last] = this->vscroll->GetVisibleRangeIterators(_sorted_standard_cargo_specs);
1107
1108 Rect line = r.WithHeight(this->line_height);
1109 for (auto it = first; it != last; ++it) {
1110 const CargoSpec *cs = *it;
1111
1112 bool lowered = !HasBit(_legend_excluded_cargo_payment_rates, cs->Index());
1113
1114 /* Redraw frame if lowered */
1115 if (lowered) DrawFrameRect(line, COLOUR_BROWN, FR_LOWERED);
1116
1117 const Rect text = line.Shrink(WidgetDimensions::scaled.framerect);
1118
1119 /* Cargo-colour box with outline */
1120 const Rect cargo = text.WithWidth(this->legend_width, rtl);
1121 GfxFillRect(cargo, PC_BLACK);
1122 GfxFillRect(cargo.Shrink(WidgetDimensions::scaled.bevel), cs->legend_colour);
1123
1124 /* Cargo name */
1125 SetDParam(0, cs->name);
1126 DrawString(text.Indent(this->legend_width + WidgetDimensions::scaled.hsep_normal, rtl), STR_GRAPH_CARGO_PAYMENT_CARGO);
1127
1128 line = line.Translate(0, this->line_height);
1129 }
1130 }
1131
1132 void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override
1133 {
1134 switch (widget) {
1135 case WID_GRAPH_ENABLE_CARGOES:
1136 /* Remove all cargoes from the excluded lists. */
1137 _legend_excluded_cargo_payment_rates = 0;
1138 this->excluded_data = 0;
1139 this->SetDirty();
1140 break;
1141
1142 case WID_GRAPH_DISABLE_CARGOES: {
1143 /* Add all cargoes to the excluded lists. */
1144 int i = 0;
1145 for (const CargoSpec *cs : _sorted_standard_cargo_specs) {
1146 SetBit(_legend_excluded_cargo_payment_rates, cs->Index());
1147 SetBit(this->excluded_data, i);
1148 i++;
1149 }
1150 this->SetDirty();
1151 break;
1152 }
1153
1154 case WID_GRAPH_MATRIX: {
1155 auto it = this->vscroll->GetScrolledItemFromWidget(_sorted_standard_cargo_specs, pt.y, this, WID_GRAPH_MATRIX);
1156 if (it != _sorted_standard_cargo_specs.end()) {
1157 ToggleBit(_legend_excluded_cargo_payment_rates, (*it)->Index());
1158 this->UpdateExcludedData();
1159 this->SetDirty();
1160 }
1161 break;
1162 }
1163
1164 default:
1165 this->BaseGraphWindow::OnClick(pt, widget, click_count);
1166 break;
1167 }
1168 }
1169
1170 void OnResize() override
1171 {
1172 this->vscroll->SetCapacityFromWidget(this, WID_GRAPH_MATRIX);
1173 }
1174
1175 void OnGameTick() override
1176 {
1177 /* Override default OnGameTick */
1178 }
1179
1185 void OnInvalidateData([[maybe_unused]] int data = 0, [[maybe_unused]] bool gui_scope = true) override
1186 {
1187 if (!gui_scope) return;
1188 this->UpdatePaymentRates();
1189 }
1190
1192 IntervalTimer<TimerWindow> update_payment_interval = {std::chrono::seconds(3), [this](auto) {
1193 this->UpdatePaymentRates();
1194 }};
1195
1199 void UpdatePaymentRates()
1200 {
1201 this->UpdateExcludedData();
1202
1203 this->data.clear();
1204 for (const CargoSpec *cs : _sorted_standard_cargo_specs) {
1205 DataSet &dataset = this->data.emplace_back();
1206 dataset.colour = cs->legend_colour;
1207 dataset.exclude_bit = cs->Index();
1208
1209 for (uint j = 0; j != this->num_on_x_axis; j++) {
1210 dataset.values[j] = GetTransportedGoodsIncome(10, 20, j * 4 + 4, cs->Index());
1211 }
1212 }
1213 }
1214};
1215
1216static constexpr NWidgetPart _nested_cargo_payment_rates_widgets[] = {
1217 NWidget(NWID_HORIZONTAL),
1218 NWidget(WWT_CLOSEBOX, COLOUR_BROWN),
1219 NWidget(WWT_CAPTION, COLOUR_BROWN), SetDataTip(STR_GRAPH_CARGO_PAYMENT_RATES_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
1220 NWidget(WWT_SHADEBOX, COLOUR_BROWN),
1221 NWidget(WWT_DEFSIZEBOX, COLOUR_BROWN),
1222 NWidget(WWT_STICKYBOX, COLOUR_BROWN),
1223 EndContainer(),
1224 NWidget(WWT_PANEL, COLOUR_BROWN, WID_GRAPH_BACKGROUND), SetMinimalSize(568, 128),
1225 NWidget(NWID_HORIZONTAL),
1226 NWidget(NWID_SPACER), SetFill(1, 0), SetResize(1, 0),
1227 NWidget(WWT_TEXT, COLOUR_BROWN, WID_GRAPH_HEADER), SetMinimalSize(0, 6), SetPadding(2, 0, 2, 0), SetDataTip(STR_GRAPH_CARGO_PAYMENT_RATES_TITLE, STR_NULL),
1228 NWidget(NWID_SPACER), SetFill(1, 0), SetResize(1, 0),
1229 EndContainer(),
1230 NWidget(NWID_HORIZONTAL),
1231 NWidget(WWT_EMPTY, COLOUR_BROWN, WID_GRAPH_GRAPH), SetMinimalSize(495, 0), SetFill(1, 1), SetResize(1, 1),
1232 NWidget(NWID_VERTICAL),
1233 NWidget(NWID_SPACER), SetMinimalSize(0, 24), SetFill(0, 1),
1234 NWidget(WWT_PUSHTXTBTN, COLOUR_BROWN, WID_GRAPH_ENABLE_CARGOES), SetDataTip(STR_GRAPH_CARGO_ENABLE_ALL, STR_GRAPH_CARGO_TOOLTIP_ENABLE_ALL), SetFill(1, 0),
1235 NWidget(WWT_PUSHTXTBTN, COLOUR_BROWN, WID_GRAPH_DISABLE_CARGOES), SetDataTip(STR_GRAPH_CARGO_DISABLE_ALL, STR_GRAPH_CARGO_TOOLTIP_DISABLE_ALL), SetFill(1, 0),
1236 NWidget(NWID_SPACER), SetMinimalSize(0, 4),
1237 NWidget(NWID_HORIZONTAL),
1238 NWidget(WWT_MATRIX, COLOUR_BROWN, WID_GRAPH_MATRIX), SetFill(1, 0), SetResize(0, 2), SetMatrixDataTip(1, 0, STR_GRAPH_CARGO_PAYMENT_TOGGLE_CARGO), SetScrollbar(WID_GRAPH_MATRIX_SCROLLBAR),
1239 NWidget(NWID_VSCROLLBAR, COLOUR_BROWN, WID_GRAPH_MATRIX_SCROLLBAR),
1240 EndContainer(),
1241 NWidget(NWID_SPACER), SetMinimalSize(0, 24), SetFill(0, 1),
1242 EndContainer(),
1243 NWidget(NWID_SPACER), SetMinimalSize(5, 0), SetFill(0, 1), SetResize(0, 1),
1244 EndContainer(),
1245 NWidget(NWID_HORIZONTAL),
1246 NWidget(NWID_SPACER), SetMinimalSize(12, 0), SetFill(1, 0), SetResize(1, 0),
1247 NWidget(WWT_TEXT, COLOUR_BROWN, WID_GRAPH_FOOTER), SetMinimalSize(0, 6), SetPadding(2, 0, 2, 0), SetDataTip(STR_NULL, STR_NULL),
1248 NWidget(NWID_SPACER), SetFill(1, 0), SetResize(1, 0),
1249 NWidget(WWT_RESIZEBOX, COLOUR_BROWN, WID_GRAPH_RESIZE), SetDataTip(RWV_HIDE_BEVEL, STR_TOOLTIP_RESIZE),
1250 EndContainer(),
1251 EndContainer(),
1252};
1253
1254static WindowDesc _cargo_payment_rates_desc(
1255 WDP_AUTO, "graph_cargo_payment_rates", 0, 0,
1256 WC_PAYMENT_RATES, WC_NONE,
1257 0,
1258 _nested_cargo_payment_rates_widgets
1259);
1260
1261
1262void ShowCargoPaymentRates()
1263{
1264 AllocateWindowDescFront<PaymentRatesGraphWindow>(_cargo_payment_rates_desc, 0);
1265}
1266
1267/*****************************/
1268/* PERFORMANCE RATING DETAIL */
1269/*****************************/
1270
1271 struct PerformanceRatingDetailWindow : Window {
1272 static CompanyID company;
1273 int timeout;
1274
1275 PerformanceRatingDetailWindow(WindowDesc &desc, WindowNumber window_number) : Window(desc)
1276 {
1277 this->UpdateCompanyStats();
1278
1279 this->InitNested(window_number);
1280 this->OnInvalidateData(INVALID_COMPANY);
1281 }
1282
1283 void UpdateCompanyStats()
1284 {
1285 /* Update all company stats with the current data
1286 * (this is because _score_info is not saved to a savegame) */
1287 for (Company *c : Company::Iterate()) {
1288 UpdateCompanyRatingAndValue(c, false);
1289 }
1290
1291 this->timeout = Ticks::DAY_TICKS * 5;
1292 }
1293
1294 uint score_info_left;
1295 uint score_info_right;
1296 uint bar_left;
1297 uint bar_right;
1298 uint bar_width;
1299 uint bar_height;
1300 uint score_detail_left;
1301 uint score_detail_right;
1302
1303 void UpdateWidgetSize(WidgetID widget, Dimension &size, [[maybe_unused]] const Dimension &padding, [[maybe_unused]] Dimension &fill, [[maybe_unused]] Dimension &resize) override
1304 {
1305 switch (widget) {
1306 case WID_PRD_SCORE_FIRST:
1307 this->bar_height = GetCharacterHeight(FS_NORMAL) + WidgetDimensions::scaled.fullbevel.Vertical();
1308 size.height = this->bar_height + WidgetDimensions::scaled.matrix.Vertical();
1309
1310 uint score_info_width = 0;
1311 for (uint i = SCORE_BEGIN; i < SCORE_END; i++) {
1312 score_info_width = std::max(score_info_width, GetStringBoundingBox(STR_PERFORMANCE_DETAIL_VEHICLES + i).width);
1313 }
1314 SetDParamMaxValue(0, 1000);
1315 score_info_width += GetStringBoundingBox(STR_JUST_COMMA).width + WidgetDimensions::scaled.hsep_wide;
1316
1317 SetDParamMaxValue(0, 100);
1318 this->bar_width = GetStringBoundingBox(STR_PERFORMANCE_DETAIL_PERCENT).width + WidgetDimensions::scaled.hsep_indent * 2; // Wide bars!
1319
1320 /* At this number we are roughly at the max; it can become wider,
1321 * but then you need at 1000 times more money. At that time you're
1322 * not that interested anymore in the last few digits anyway.
1323 * The 500 is because 999 999 500 to 999 999 999 are rounded to
1324 * 1 000 M, and not 999 999 k. Use negative numbers to account for
1325 * the negative income/amount of money etc. as well. */
1326 int max = -(999999999 - 500);
1327
1328 /* Scale max for the display currency. Prior to rendering the value
1329 * is converted into the display currency, which may cause it to
1330 * raise significantly. We need to compensate for that since {{CURRCOMPACT}}
1331 * is used, which can produce quite short renderings of very large
1332 * values. Otherwise the calculated width could be too narrow.
1333 * Note that it doesn't work if there was a currency with an exchange
1334 * rate greater than max.
1335 * When the currency rate is more than 1000, the 999 999 k becomes at
1336 * least 999 999 M which roughly is equally long. Furthermore if the
1337 * exchange rate is that high, 999 999 k is usually not enough anymore
1338 * to show the different currency numbers. */
1339 if (GetCurrency().rate < 1000) max /= GetCurrency().rate;
1340 SetDParam(0, max);
1341 SetDParam(1, max);
1342 uint score_detail_width = GetStringBoundingBox(STR_PERFORMANCE_DETAIL_AMOUNT_CURRENCY).width;
1343
1344 size.width = WidgetDimensions::scaled.frametext.Horizontal() + score_info_width + WidgetDimensions::scaled.hsep_wide + this->bar_width + WidgetDimensions::scaled.hsep_wide + score_detail_width;
1345 uint left = WidgetDimensions::scaled.frametext.left;
1346 uint right = size.width - WidgetDimensions::scaled.frametext.right;
1347
1348 bool rtl = _current_text_dir == TD_RTL;
1349 this->score_info_left = rtl ? right - score_info_width : left;
1350 this->score_info_right = rtl ? right : left + score_info_width;
1351
1352 this->score_detail_left = rtl ? left : right - score_detail_width;
1353 this->score_detail_right = rtl ? left + score_detail_width : right;
1354
1355 this->bar_left = left + (rtl ? score_detail_width : score_info_width) + WidgetDimensions::scaled.hsep_wide;
1356 this->bar_right = this->bar_left + this->bar_width - 1;
1357 break;
1358 }
1359 }
1360
1361 void DrawWidget(const Rect &r, WidgetID widget) const override
1362 {
1363 /* No need to draw when there's nothing to draw */
1364 if (this->company == INVALID_COMPANY) return;
1365
1366 if (IsInsideMM(widget, WID_PRD_COMPANY_FIRST, WID_PRD_COMPANY_LAST + 1)) {
1367 if (this->IsWidgetDisabled(widget)) return;
1368 CompanyID cid = (CompanyID)(widget - WID_PRD_COMPANY_FIRST);
1369 Dimension sprite_size = GetSpriteSize(SPR_COMPANY_ICON);
1370 DrawCompanyIcon(cid, CenterBounds(r.left, r.right, sprite_size.width), CenterBounds(r.top, r.bottom, sprite_size.height));
1371 return;
1372 }
1373
1374 if (!IsInsideMM(widget, WID_PRD_SCORE_FIRST, WID_PRD_SCORE_LAST + 1)) return;
1375
1376 ScoreID score_type = (ScoreID)(widget - WID_PRD_SCORE_FIRST);
1377
1378 /* The colours used to show how the progress is going */
1379 int colour_done = GetColourGradient(COLOUR_GREEN, SHADE_NORMAL);
1380 int colour_notdone = GetColourGradient(COLOUR_RED, SHADE_NORMAL);
1381
1382 /* Draw all the score parts */
1383 int64_t val = _score_part[company][score_type];
1384 int64_t needed = _score_info[score_type].needed;
1385 int score = _score_info[score_type].score;
1386
1387 /* SCORE_TOTAL has its own rules ;) */
1388 if (score_type == SCORE_TOTAL) {
1389 for (ScoreID i = SCORE_BEGIN; i < SCORE_END; i++) score += _score_info[i].score;
1390 needed = SCORE_MAX;
1391 }
1392
1393 uint bar_top = CenterBounds(r.top, r.bottom, this->bar_height);
1394 uint text_top = CenterBounds(r.top, r.bottom, GetCharacterHeight(FS_NORMAL));
1395
1396 DrawString(this->score_info_left, this->score_info_right, text_top, STR_PERFORMANCE_DETAIL_VEHICLES + score_type);
1397
1398 /* Draw the score */
1399 SetDParam(0, score);
1400 DrawString(this->score_info_left, this->score_info_right, text_top, STR_JUST_COMMA, TC_BLACK, SA_RIGHT);
1401
1402 /* Calculate the %-bar */
1403 uint x = Clamp<int64_t>(val, 0, needed) * this->bar_width / needed;
1404 bool rtl = _current_text_dir == TD_RTL;
1405 if (rtl) {
1406 x = this->bar_right - x;
1407 } else {
1408 x = this->bar_left + x;
1409 }
1410
1411 /* Draw the bar */
1412 if (x != this->bar_left) GfxFillRect(this->bar_left, bar_top, x, bar_top + this->bar_height - 1, rtl ? colour_notdone : colour_done);
1413 if (x != this->bar_right) GfxFillRect(x, bar_top, this->bar_right, bar_top + this->bar_height - 1, rtl ? colour_done : colour_notdone);
1414
1415 /* Draw it */
1416 SetDParam(0, Clamp<int64_t>(val, 0, needed) * 100 / needed);
1417 DrawString(this->bar_left, this->bar_right, text_top, STR_PERFORMANCE_DETAIL_PERCENT, TC_FROMSTRING, SA_HOR_CENTER);
1418
1419 /* SCORE_LOAN is inversed */
1420 if (score_type == SCORE_LOAN) val = needed - val;
1421
1422 /* Draw the amount we have against what is needed
1423 * For some of them it is in currency format */
1424 SetDParam(0, val);
1425 SetDParam(1, needed);
1426 switch (score_type) {
1427 case SCORE_MIN_PROFIT:
1428 case SCORE_MIN_INCOME:
1429 case SCORE_MAX_INCOME:
1430 case SCORE_MONEY:
1431 case SCORE_LOAN:
1432 DrawString(this->score_detail_left, this->score_detail_right, text_top, STR_PERFORMANCE_DETAIL_AMOUNT_CURRENCY);
1433 break;
1434 default:
1435 DrawString(this->score_detail_left, this->score_detail_right, text_top, STR_PERFORMANCE_DETAIL_AMOUNT_INT);
1436 }
1437 }
1438
1439 void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override
1440 {
1441 /* Check which button is clicked */
1442 if (IsInsideMM(widget, WID_PRD_COMPANY_FIRST, WID_PRD_COMPANY_LAST + 1)) {
1443 /* Is it no on disable? */
1444 if (!this->IsWidgetDisabled(widget)) {
1445 this->RaiseWidget(WID_PRD_COMPANY_FIRST + this->company);
1446 this->company = (CompanyID)(widget - WID_PRD_COMPANY_FIRST);
1447 this->LowerWidget(WID_PRD_COMPANY_FIRST + this->company);
1448 this->SetDirty();
1449 }
1450 }
1451 }
1452
1453 void OnGameTick() override
1454 {
1455 /* Update the company score every 5 days */
1456 if (--this->timeout == 0) {
1457 this->UpdateCompanyStats();
1458 this->SetDirty();
1459 }
1460 }
1461
1467 void OnInvalidateData([[maybe_unused]] int data = 0, [[maybe_unused]] bool gui_scope = true) override
1468 {
1469 if (!gui_scope) return;
1470 /* Disable the companies who are not active */
1471 for (CompanyID i = COMPANY_FIRST; i < MAX_COMPANIES; i++) {
1472 this->SetWidgetDisabledState(WID_PRD_COMPANY_FIRST + i, !Company::IsValidID(i));
1473 }
1474
1475 /* Check if the currently selected company is still active. */
1476 if (this->company != INVALID_COMPANY && !Company::IsValidID(this->company)) {
1477 /* Raise the widget for the previous selection. */
1478 this->RaiseWidget(WID_PRD_COMPANY_FIRST + this->company);
1479 this->company = INVALID_COMPANY;
1480 }
1481
1482 if (this->company == INVALID_COMPANY) {
1483 for (const Company *c : Company::Iterate()) {
1484 this->company = c->index;
1485 break;
1486 }
1487 }
1488
1489 /* Make sure the widget is lowered */
1490 if (this->company != INVALID_COMPANY) {
1491 this->LowerWidget(WID_PRD_COMPANY_FIRST + this->company);
1492 }
1493 }
1494};
1495
1496 CompanyID PerformanceRatingDetailWindow::company = INVALID_COMPANY;
1497
1498/*******************************/
1499/* INDUSTRY PRODUCTION HISTORY */
1500/*******************************/
1501
1502 struct IndustryProductionGraphWindow : BaseGraphWindow {
1503 uint line_height;
1504 Scrollbar *vscroll;
1505 uint legend_width;
1506
1507 static inline constexpr StringID RANGE_LABELS[] = {
1508 STR_GRAPH_INDUSTRY_RANGE_PRODUCED,
1509 STR_GRAPH_INDUSTRY_RANGE_TRANSPORTED
1510 };
1511
1512 IndustryProductionGraphWindow(WindowDesc &desc, WindowNumber window_number) :
1513 BaseGraphWindow(desc, STR_JUST_COMMA)
1514 {
1515 this->num_on_x_axis = GRAPH_NUM_MONTHS;
1516 this->num_vert_lines = GRAPH_NUM_MONTHS;
1517 this->month_increment = 1;
1518 this->x_values_start = ECONOMY_MONTH_MINUTES;
1519 this->x_values_increment = ECONOMY_MONTH_MINUTES;
1520 this->draw_dates = !TimerGameEconomy::UsingWallclockUnits();
1521 this->ranges = RANGE_LABELS;
1522
1523 this->CreateNestedTree();
1524 this->vscroll = this->GetScrollbar(WID_GRAPH_MATRIX_SCROLLBAR);
1525
1526 int count = 0;
1527 const Industry *i = Industry::Get(window_number);
1528 for (const auto &p : i->produced) {
1529 if (!IsValidCargoID(p.cargo)) continue;
1530 count++;
1531 }
1532 this->vscroll->SetCount(count);
1533
1534 auto *wid = this->GetWidget<NWidgetCore>(WID_GRAPH_FOOTER);
1535 wid->SetDataTip(TimerGameEconomy::UsingWallclockUnits() ? STR_GRAPH_LAST_24_MINUTES_TIME_LABEL : STR_EMPTY, STR_NULL);
1536
1537 this->FinishInitNested(window_number);
1538
1539 /* Initialise the dataset */
1540 this->UpdateStatistics(true);
1541 }
1542
1543 void OnInit() override
1544 {
1545 /* Width of the legend blob. */
1546 this->legend_width = GetCharacterHeight(FS_SMALL) * 9 / 6;
1547 }
1548
1549 void UpdateExcludedData()
1550 {
1551 this->excluded_data = 0;
1552
1553 const Industry *i = Industry::Get(this->window_number);
1554 for (const auto &p : i->produced) {
1555 if (!IsValidCargoID(p.cargo)) continue;
1556 if (HasBit(_legend_excluded_cargo_production_history, p.cargo)) SetBit(this->excluded_data, p.cargo);
1557 }
1558 }
1559
1560 void UpdateWidgetSize(WidgetID widget, Dimension &size, [[maybe_unused]] const Dimension &padding, [[maybe_unused]] Dimension &fill, [[maybe_unused]] Dimension &resize) override
1561 {
1562 if (widget != WID_GRAPH_MATRIX) {
1563 BaseGraphWindow::UpdateWidgetSize(widget, size, padding, fill, resize);
1564 return;
1565 }
1566
1567 const Industry *i = Industry::Get(this->window_number);
1568 const CargoSpec *cs;
1569 for (const auto &p : i->produced) {
1570 if (!IsValidCargoID(p.cargo)) continue;
1571
1572 cs = CargoSpec::Get(p.cargo);
1573 SetDParam(0, cs->name);
1574 Dimension d = GetStringBoundingBox(STR_GRAPH_CARGO_PAYMENT_CARGO);
1575 d.width += this->legend_width + WidgetDimensions::scaled.hsep_normal; // colour field
1576 d.width += WidgetDimensions::scaled.framerect.Horizontal();
1577 d.height += WidgetDimensions::scaled.framerect.Vertical();
1578 size = maxdim(d, size);
1579 }
1580
1581 this->line_height = size.height;
1582 size.height = this->line_height * 11; /* Default number of cargo types in most climates. */
1583 resize.width = 0;
1584 resize.height = this->line_height;
1585 }
1586
1587 void DrawWidget(const Rect &r, WidgetID widget) const override
1588 {
1589 if (widget != WID_GRAPH_MATRIX) {
1590 BaseGraphWindow::DrawWidget(r, widget);
1591 return;
1592 }
1593
1594 bool rtl = _current_text_dir == TD_RTL;
1595
1596 int pos = this->vscroll->GetPosition();
1597 int max = pos + this->vscroll->GetCapacity();
1598
1599 Rect line = r.WithHeight(this->line_height);
1600 const Industry *i = Industry::Get(this->window_number);
1601 const CargoSpec *cs;
1602
1603 for (const auto &p : i->produced) {
1604 if (!IsValidCargoID(p.cargo)) continue;
1605
1606 if (pos-- > 0) continue;
1607 if (--max < 0) break;
1608
1609 cs = CargoSpec::Get(p.cargo);
1610
1611 bool lowered = !HasBit(_legend_excluded_cargo_production_history, p.cargo);
1612
1613 /* Redraw frame if lowered */
1614 if (lowered) DrawFrameRect(line, COLOUR_BROWN, FR_LOWERED);
1615
1616 const Rect text = line.Shrink(WidgetDimensions::scaled.framerect);
1617
1618 /* Cargo-colour box with outline */
1619 const Rect cargo = text.WithWidth(this->legend_width, rtl);
1620 GfxFillRect(cargo, PC_BLACK);
1621 GfxFillRect(cargo.Shrink(WidgetDimensions::scaled.bevel), cs->legend_colour);
1622
1623 /* Cargo name */
1624 SetDParam(0, cs->name);
1625 DrawString(text.Indent(this->legend_width + WidgetDimensions::scaled.hsep_normal, rtl), STR_GRAPH_CARGO_PAYMENT_CARGO);
1626
1627 line = line.Translate(0, this->line_height);
1628 }
1629 }
1630
1631 void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override
1632 {
1633 switch (widget) {
1634 case WID_GRAPH_ENABLE_CARGOES:
1635 /* Remove all cargoes from the excluded lists. */
1636 _legend_excluded_cargo_production_history = 0;
1637 this->excluded_data = 0;
1638 this->SetDirty();
1639 break;
1640
1641 case WID_GRAPH_DISABLE_CARGOES: {
1642 /* Add all cargoes to the excluded lists. */
1643 const Industry *i = Industry::Get(this->window_number);
1644 for (const auto &p : i->produced) {
1645 if (!IsValidCargoID(p.cargo)) continue;
1646
1647 SetBit(_legend_excluded_cargo_production_history, p.cargo);
1648 SetBit(this->excluded_data, p.cargo);
1649 }
1650 this->SetDirty();
1651 break;
1652 }
1653
1654 case WID_GRAPH_MATRIX: {
1655 int row = this->vscroll->GetScrolledRowFromWidget(pt.y, this, WID_GRAPH_MATRIX);
1656 if (row >= this->vscroll->GetCount()) return;
1657
1658 const Industry *i = Industry::Get(this->window_number);
1659 for (const auto &p : i->produced) {
1660 if (!IsValidCargoID(p.cargo)) continue;
1661 if (row-- > 0) continue;
1662
1663 ToggleBit(_legend_excluded_cargo_production_history, p.cargo);
1664 this->UpdateExcludedData();
1665 this->SetDirty();
1666 break;
1667 }
1668 break;
1669 }
1670
1671 default:
1672 this->BaseGraphWindow::OnClick(pt, widget, click_count);
1673 break;
1674 }
1675 }
1676
1677 void SetStringParameters(WidgetID widget) const override
1678 {
1679 if (widget == WID_GRAPH_CAPTION) SetDParam(0, this->window_number);
1680 }
1681
1682 void OnResize() override
1683 {
1684 this->vscroll->SetCapacityFromWidget(this, WID_GRAPH_MATRIX);
1685 }
1686
1687 void UpdateStatistics(bool initialize) override
1688 {
1689 CargoTypes excluded_cargo = this->excluded_data;
1690 this->UpdateExcludedData();
1691
1692 int mo = TimerGameEconomy::month - this->num_vert_lines;
1693 auto yr = TimerGameEconomy::year;
1694 while (mo < 0) {
1695 yr--;
1696 mo += 12;
1697 }
1698
1699 if (!initialize && this->excluded_data == excluded_cargo && this->num_on_x_axis == this->num_vert_lines && this->year == yr && this->month == mo) {
1700 /* There's no reason to get new stats */
1701 return;
1702 }
1703
1704 this->year = yr;
1705 this->month = mo;
1706
1707 const Industry *i = Industry::Get(this->window_number);
1708
1709 this->data.clear();
1710 for (const auto &p : i->produced) {
1711 if (!IsValidCargoID(p.cargo)) continue;
1712 const CargoSpec *cs = CargoSpec::Get(p.cargo);
1713
1714 DataSet &produced = this->data.emplace_back();
1715 produced.colour = cs->legend_colour;
1716 produced.exclude_bit = cs->Index();
1717 produced.range_bit = 0;
1718
1719 for (uint j = 0; j < GRAPH_NUM_MONTHS; j++) {
1720 produced.values[j] = p.history[GRAPH_NUM_MONTHS - j].production;
1721 }
1722
1723 DataSet &transported = this->data.emplace_back();
1724 transported.colour = cs->legend_colour;
1725 transported.exclude_bit = cs->Index();
1726 transported.range_bit = 1;
1727 transported.dash = 2;
1728
1729 for (uint j = 0; j < GRAPH_NUM_MONTHS; j++) {
1730 transported.values[j] = p.history[GRAPH_NUM_MONTHS - j].transported;
1731 }
1732 }
1733
1734 this->vscroll->SetCount(std::size(this->data));
1735
1736 this->SetDirty();
1737 }
1738};
1739
1740static constexpr NWidgetPart _nested_industry_production_widgets[] = {
1741 NWidget(NWID_HORIZONTAL),
1742 NWidget(WWT_CLOSEBOX, COLOUR_BROWN),
1743 NWidget(WWT_CAPTION, COLOUR_BROWN, WID_GRAPH_CAPTION), SetDataTip(STR_GRAPH_INDUSTRY_PRODUCTION_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
1744 NWidget(WWT_SHADEBOX, COLOUR_BROWN),
1745 NWidget(WWT_DEFSIZEBOX, COLOUR_BROWN),
1746 NWidget(WWT_STICKYBOX, COLOUR_BROWN),
1747 EndContainer(),
1748 NWidget(WWT_PANEL, COLOUR_BROWN, WID_GRAPH_BACKGROUND), SetMinimalSize(568, 128),
1749 NWidget(NWID_HORIZONTAL),
1750 NWidget(WWT_EMPTY, COLOUR_BROWN, WID_GRAPH_GRAPH), SetMinimalSize(495, 0), SetFill(1, 1), SetResize(1, 1),
1751 NWidget(NWID_VERTICAL),
1752 NWidget(NWID_SPACER), SetMinimalSize(0, 24), SetFill(0, 1),
1753 NWidget(WWT_MATRIX, COLOUR_BROWN, WID_GRAPH_RANGE_MATRIX), SetFill(1, 0), SetResize(0, 0), SetMatrixDataTip(1, 0, STR_GRAPH_CARGO_PAYMENT_TOGGLE_CARGO),
1754 NWidget(NWID_SPACER), SetMinimalSize(0, 4),
1755 NWidget(WWT_PUSHTXTBTN, COLOUR_BROWN, WID_GRAPH_ENABLE_CARGOES), SetDataTip(STR_GRAPH_CARGO_ENABLE_ALL, STR_GRAPH_CARGO_TOOLTIP_ENABLE_ALL), SetFill(1, 0),
1756 NWidget(WWT_PUSHTXTBTN, COLOUR_BROWN, WID_GRAPH_DISABLE_CARGOES), SetDataTip(STR_GRAPH_CARGO_DISABLE_ALL, STR_GRAPH_CARGO_TOOLTIP_DISABLE_ALL), SetFill(1, 0),
1757 NWidget(NWID_SPACER), SetMinimalSize(0, 4),
1758 NWidget(NWID_HORIZONTAL),
1759 NWidget(WWT_MATRIX, COLOUR_BROWN, WID_GRAPH_MATRIX), SetFill(1, 0), SetResize(0, 2), SetMatrixDataTip(1, 0, STR_GRAPH_CARGO_PAYMENT_TOGGLE_CARGO), SetScrollbar(WID_GRAPH_MATRIX_SCROLLBAR),
1760 NWidget(NWID_VSCROLLBAR, COLOUR_BROWN, WID_GRAPH_MATRIX_SCROLLBAR),
1761 EndContainer(),
1762 NWidget(NWID_SPACER), SetMinimalSize(0, 24), SetFill(0, 1),
1763 EndContainer(),
1764 NWidget(NWID_SPACER), SetMinimalSize(5, 0), SetFill(0, 1), SetResize(0, 1),
1765 EndContainer(),
1766 NWidget(NWID_HORIZONTAL),
1767 NWidget(NWID_SPACER), SetMinimalSize(12, 0), SetFill(1, 0), SetResize(1, 0),
1768 NWidget(WWT_TEXT, COLOUR_BROWN, WID_GRAPH_FOOTER), SetMinimalSize(0, 6), SetPadding(2, 0, 2, 0), SetDataTip(STR_EMPTY, STR_NULL),
1769 NWidget(NWID_SPACER), SetFill(1, 0), SetResize(1, 0),
1770 NWidget(WWT_RESIZEBOX, COLOUR_BROWN, WID_GRAPH_RESIZE), SetDataTip(RWV_HIDE_BEVEL, STR_TOOLTIP_RESIZE),
1771 EndContainer(),
1772 EndContainer(),
1773};
1774
1775static WindowDesc _industry_production_desc(
1776 WDP_AUTO, "graph_industry_production", 0, 0,
1777 WC_INDUSTRY_PRODUCTION, WC_INDUSTRY_VIEW,
1778 0,
1779 _nested_industry_production_widgets
1780);
1781
1782void ShowIndustryProductionGraph(WindowNumber window_number)
1783{
1784 AllocateWindowDescFront<IndustryProductionGraphWindow>(_industry_production_desc, window_number);
1785}
1786
1791 static std::unique_ptr<NWidgetBase> MakePerformanceDetailPanels()
1792{
1793 auto realtime = TimerGameEconomy::UsingWallclockUnits();
1794 const StringID performance_tips[] = {
1795 realtime ? STR_PERFORMANCE_DETAIL_VEHICLES_TOOLTIP_PERIODS : STR_PERFORMANCE_DETAIL_VEHICLES_TOOLTIP_YEARS,
1796 STR_PERFORMANCE_DETAIL_STATIONS_TOOLTIP,
1797 realtime ? STR_PERFORMANCE_DETAIL_MIN_PROFIT_TOOLTIP_PERIODS : STR_PERFORMANCE_DETAIL_MIN_PROFIT_TOOLTIP_YEARS,
1798 STR_PERFORMANCE_DETAIL_MIN_INCOME_TOOLTIP,
1799 STR_PERFORMANCE_DETAIL_MAX_INCOME_TOOLTIP,
1800 STR_PERFORMANCE_DETAIL_DELIVERED_TOOLTIP,
1801 STR_PERFORMANCE_DETAIL_CARGO_TOOLTIP,
1802 STR_PERFORMANCE_DETAIL_MONEY_TOOLTIP,
1803 STR_PERFORMANCE_DETAIL_LOAN_TOOLTIP,
1804 STR_PERFORMANCE_DETAIL_TOTAL_TOOLTIP,
1805 };
1806
1807 static_assert(lengthof(performance_tips) == SCORE_END - SCORE_BEGIN);
1808
1809 auto vert = std::make_unique<NWidgetVertical>(NC_EQUALSIZE);
1810 for (WidgetID widnum = WID_PRD_SCORE_FIRST; widnum <= WID_PRD_SCORE_LAST; widnum++) {
1811 auto panel = std::make_unique<NWidgetBackground>(WWT_PANEL, COLOUR_BROWN, widnum);
1812 panel->SetFill(1, 1);
1813 panel->SetDataTip(0x0, performance_tips[widnum - WID_PRD_SCORE_FIRST]);
1814 vert->Add(std::move(panel));
1815 }
1816 return vert;
1817}
1818
1820std::unique_ptr<NWidgetBase> MakeCompanyButtonRowsGraphGUI()
1821{
1822 return MakeCompanyButtonRows(WID_PRD_COMPANY_FIRST, WID_PRD_COMPANY_LAST, COLOUR_BROWN, 8, STR_PERFORMANCE_DETAIL_SELECT_COMPANY_TOOLTIP);
1823}
1824
1825static constexpr NWidgetPart _nested_performance_rating_detail_widgets[] = {
1826 NWidget(NWID_HORIZONTAL),
1827 NWidget(WWT_CLOSEBOX, COLOUR_BROWN),
1828 NWidget(WWT_CAPTION, COLOUR_BROWN), SetDataTip(STR_PERFORMANCE_DETAIL, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
1829 NWidget(WWT_SHADEBOX, COLOUR_BROWN),
1830 NWidget(WWT_STICKYBOX, COLOUR_BROWN),
1831 EndContainer(),
1832 NWidget(WWT_PANEL, COLOUR_BROWN),
1833 NWidgetFunction(MakeCompanyButtonRowsGraphGUI), SetPadding(2),
1834 EndContainer(),
1835 NWidgetFunction(MakePerformanceDetailPanels),
1836};
1837
1838static WindowDesc _performance_rating_detail_desc(
1839 WDP_AUTO, "league_details", 0, 0,
1840 WC_PERFORMANCE_DETAIL, WC_NONE,
1841 0,
1842 _nested_performance_rating_detail_widgets
1843);
1844
1845void ShowPerformanceRatingDetail()
1846{
1847 AllocateWindowDescFront<PerformanceRatingDetailWindow>(_performance_rating_detail_desc, 0);
1848}
1849
1850void InitializeGraphGui()
1851{
1852 _legend_excluded_companies = 0;
1853 _legend_excluded_cargo_payment_rates = 0;
1854 _legend_excluded_cargo_production_history = 0;
1855}
HasBit
debug_inline constexpr bool HasBit(const T x, const uint8_t y)
Checks if a bit in a value is set.
Definition bitmath_func.hpp:103
SetBit
constexpr T SetBit(T &x, const uint8_t y)
Set a bit in a variable.
Definition bitmath_func.hpp:121
ToggleBit
constexpr T ToggleBit(T &x, const uint8_t y)
Toggles a bit in a variable.
Definition bitmath_func.hpp:181
IsValidCargoID
bool IsValidCargoID(CargoID t)
Test whether cargo type is not INVALID_CARGO.
Definition cargo_type.h:107
NUM_CARGO
static const CargoID NUM_CARGO
Maximum number of cargo types in a game.
Definition cargo_type.h:74
_sorted_standard_cargo_specs
std::span< const CargoSpec * > _sorted_standard_cargo_specs
Standard cargo specifications sorted alphabetically by name.
Definition cargotype.cpp:193
cargotype.h
Types/functions related to cargoes.
IntervalTimer
An interval timer will fire every interval, and will continue to fire until it is deleted.
Definition timer.h:76
OverflowSafeInt< int64_t >
Scrollbar
Scrollbar data structure.
Definition widget_type.h:694
Scrollbar::GetCapacity
size_type GetCapacity() const
Gets the number of visible elements of the scrollbar.
Definition widget_type.h:731
Scrollbar::SetCount
void SetCount(size_t num)
Sets the number of elements in the list.
Definition widget_type.h:780
Scrollbar::GetScrolledItemFromWidget
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.
Definition widget_type.h:879
Scrollbar::GetScrolledRowFromWidget
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:2377
Scrollbar::SetCapacityFromWidget
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:2451
Scrollbar::GetCount
size_type GetCount() const
Gets the number of elements in the list.
Definition widget_type.h:722
Scrollbar::GetVisibleRangeIterators
auto GetVisibleRangeIterators(Tcontainer &container) const
Get a pair of iterators for the range of visible elements in a container.
Definition widget_type.h:860
Scrollbar::GetPosition
size_type GetPosition() const
Gets the position of the first visible element in the list.
Definition widget_type.h:740
Ticks::DAY_TICKS
static constexpr TimerGameTick::Ticks DAY_TICKS
1 day is 74 ticks; TimerGameCalendar::date_fract used to be uint16_t and incremented by 885.
Definition timer_game_tick.h:75
TimerGameEconomy::year
static Year year
Current year, starting at 0.
Definition timer_game_economy.h:36
TimerGameEconomy::month
static Month month
Current month (0..11).
Definition timer_game_economy.h:37
TimerGameEconomy::UsingWallclockUnits
static bool UsingWallclockUnits(bool newgame=false)
Check if we are using wallclock units.
Definition timer_game_economy.cpp:97
TimerGame< struct Economy >::Month
uint8_t Month
Type for the month, note: 0 based, i.e.
Definition timer_game_common.h:44
WidgetDimensions::framerect
RectPadding framerect
Standard padding inside many panels.
Definition window_gui.h:42
WidgetDimensions::frametext
RectPadding frametext
Padding inside frame with text.
Definition window_gui.h:43
WidgetDimensions::scaled
static WidgetDimensions scaled
Widget dimensions scaled for current zoom level.
Definition window_gui.h:28
WidgetDimensions::hsep_wide
int hsep_wide
Wide horizontal spacing.
Definition window_gui.h:64
WidgetDimensions::fullbevel
RectPadding fullbevel
Always-scaled bevel thickness.
Definition window_gui.h:41
WidgetDimensions::unscaled
static const WidgetDimensions unscaled
Unscaled widget dimensions.
Definition window_gui.h:96
WidgetDimensions::matrix
RectPadding matrix
Padding of WWT_MATRIX items.
Definition window_gui.h:44
WidgetDimensions::hsep_normal
int hsep_normal
Normal horizontal spacing.
Definition window_gui.h:63
WidgetDimensions::bevel
RectPadding bevel
Bevel thickness, affected by "scaled bevels" game option.
Definition window_gui.h:40
WidgetDimensions::hsep_indent
int hsep_indent
Width of identation for tree layouts.
Definition window_gui.h:65
company_base.h
Definition of stuff that is very close to a company, like the company struct itself.
DrawCompanyIcon
void DrawCompanyIcon(CompanyID c, int x, int y)
Draw the icon of a company.
Definition company_cmd.cpp:161
company_gui.h
GUI Functions related to companies.
Owner
Owner
Enum for all companies/owners.
Definition company_type.h:18
INVALID_COMPANY
@ INVALID_COMPANY
An invalid company.
Definition company_type.h:30
COMPANY_FIRST
@ COMPANY_FIRST
First company, same as owner.
Definition company_type.h:22
MAX_COMPANIES
@ MAX_COMPANIES
Maximum number of companies.
Definition company_type.h:23
currency.h
Functions to handle different currencies.
GetCurrency
const CurrencySpec & GetCurrency()
Get the currently selected currency.
Definition currency.h:117
UpdateCompanyRatingAndValue
int UpdateCompanyRatingAndValue(Company *c, bool update)
if update is set to true, the economy is updated with this score (also the house is updated,...
Definition economy.cpp:201
_score_info
const ScoreInfo _score_info[]
Score info, values used for computing the detailed performance rating.
Definition economy.cpp:90
economy_func.h
Functions related to the economy.
ScoreID
ScoreID
Score categories in the detailed performance rating.
Definition economy_type.h:60
SCORE_END
@ SCORE_END
How many scores are there..
Definition economy_type.h:72
SCORE_MAX
@ SCORE_MAX
The max score that can be in the performance history.
Definition economy_type.h:74
SCORE_TOTAL
@ SCORE_TOTAL
This must always be the last entry.
Definition economy_type.h:71
GetCharacterHeight
int GetCharacterHeight(FontSize size)
Get height of a character for a given font size.
Definition fontcache.cpp:77
maxdim
Dimension maxdim(const Dimension &d1, const Dimension &d2)
Compute bounding box of both dimensions.
Definition geometry_func.cpp:22
geometry_func.hpp
Geometry functions.
GetSpriteSize
Dimension GetSpriteSize(SpriteID sprid, Point *offset, ZoomLevel zoom)
Get the size of a sprite.
Definition gfx.cpp:922
GetStringBoundingBox
Dimension GetStringBoundingBox(std::string_view str, FontSize start_fontsize)
Return the string dimension in pixels.
Definition gfx.cpp:851
DrawString
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:657
GfxFillRect
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:114
DrawStringMultiLine
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:774
gfx_func.h
Functions related to the gfx engine.
CenterBounds
int CenterBounds(int min, int max, int size)
Determine where to draw a centred object inside a widget.
Definition gfx_func.h:166
SA_LEFT
@ SA_LEFT
Left align the text.
Definition gfx_type.h:343
SA_RIGHT
@ SA_RIGHT
Right align the text (must be a single bit).
Definition gfx_type.h:345
SA_HOR_CENTER
@ SA_HOR_CENTER
Horizontally center the text.
Definition gfx_type.h:344
SA_CENTER
@ SA_CENTER
Center both horizontally and vertically.
Definition gfx_type.h:353
FS_SMALL
@ FS_SMALL
Index of the small font in the font tables.
Definition gfx_type.h:210
FS_NORMAL
@ FS_NORMAL
Index of the normal font in the font tables.
Definition gfx_type.h:209
TextColour
TextColour
Colour of the strings, see _string_colourmap in table/string_colours.h or docs/ottd-colourtext-palett...
Definition gfx_type.h:260
INT64_MAX_IN_DOUBLE
constexpr double INT64_MAX_IN_DOUBLE
The biggest double that when cast to int64_t still fits in a int64_t.
Definition graph_gui.cpp:45
MakeNWidgetCompanyLines
static std::unique_ptr< NWidgetBase > MakeNWidgetCompanyLines()
Construct a vertical list of buttons, one for each company.
Definition graph_gui.cpp:117
MakeCompanyButtonRowsGraphGUI
std::unique_ptr< NWidgetBase > MakeCompanyButtonRowsGraphGUI()
Make a number of rows with buttons for each company for the performance rating detail window.
Definition graph_gui.cpp:1820
MakePerformanceDetailPanels
static std::unique_ptr< NWidgetBase > MakePerformanceDetailPanels()
Make a vertical list of panels for outputting score details.
Definition graph_gui.cpp:1791
graph_gui.h
Graph GUI functions.
graph_widget.h
Types related to the graph widgets.
WID_GRAPH_FOOTER
@ WID_GRAPH_FOOTER
Footer.
Definition graph_widget.h:32
WID_GRAPH_RESIZE
@ WID_GRAPH_RESIZE
Resize button.
Definition graph_widget.h:30
WID_GRAPH_BACKGROUND
@ WID_GRAPH_BACKGROUND
Background of the window.
Definition graph_widget.h:27
WID_GRAPH_GRAPH
@ WID_GRAPH_GRAPH
Graph itself.
Definition graph_widget.h:29
WID_PHG_DETAILED_PERFORMANCE
@ WID_PHG_DETAILED_PERFORMANCE
Detailed performance.
Definition graph_widget.h:41
WID_GRAPH_HEADER
@ WID_GRAPH_HEADER
Header.
Definition graph_widget.h:31
WID_GRAPH_MATRIX_SCROLLBAR
@ WID_GRAPH_MATRIX_SCROLLBAR
Cargo list scrollbar.
Definition graph_widget.h:37
WID_GRAPH_DISABLE_CARGOES
@ WID_GRAPH_DISABLE_CARGOES
Disable cargoes button.
Definition graph_widget.h:35
WID_GRAPH_CAPTION
@ WID_GRAPH_CAPTION
Caption.
Definition graph_widget.h:28
WID_GRAPH_KEY_BUTTON
@ WID_GRAPH_KEY_BUTTON
Key button.
Definition graph_widget.h:26
WID_GRAPH_MATRIX
@ WID_GRAPH_MATRIX
Cargo list.
Definition graph_widget.h:36
WID_GRAPH_ENABLE_CARGOES
@ WID_GRAPH_ENABLE_CARGOES
Enable cargoes button.
Definition graph_widget.h:34
WID_GRAPH_RANGE_MATRIX
@ WID_GRAPH_RANGE_MATRIX
Range list.
Definition graph_widget.h:39
WID_GL_FIRST_COMPANY
@ WID_GL_FIRST_COMPANY
First company in the legend.
Definition graph_widget.h:20
WID_GL_LAST_COMPANY
@ WID_GL_LAST_COMPANY
Last company in the legend.
Definition graph_widget.h:21
WID_GL_BACKGROUND
@ WID_GL_BACKGROUND
Background of the window.
Definition graph_widget.h:18
WID_PRD_COMPANY_FIRST
@ WID_PRD_COMPANY_FIRST
First company.
Definition graph_widget.h:49
WID_PRD_SCORE_FIRST
@ WID_PRD_SCORE_FIRST
First entry in the score list.
Definition graph_widget.h:46
WID_PRD_SCORE_LAST
@ WID_PRD_SCORE_LAST
Last entry in the score list.
Definition graph_widget.h:47
WID_PRD_COMPANY_LAST
@ WID_PRD_COMPANY_LAST
Last company.
Definition graph_widget.h:50
NWidgetFunction
constexpr NWidgetPart NWidgetFunction(NWidgetFunctionType *func_ptr)
Obtain a nested widget (sub)tree from an external source.
Definition widget_type.h:1341
SetFill
constexpr NWidgetPart SetFill(uint16_t fill_x, uint16_t fill_y)
Widget part function for setting filling.
Definition widget_type.h:1181
SetScrollbar
constexpr NWidgetPart SetScrollbar(WidgetID index)
Attach a scrollbar to a widget.
Definition widget_type.h:1295
SetPadding
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.
Definition widget_type.h:1228
SetDataTip
constexpr NWidgetPart SetDataTip(uint32_t data, StringID tip)
Widget part function for setting the data and tooltip.
Definition widget_type.h:1202
SetMinimalSize
constexpr NWidgetPart SetMinimalSize(int16_t x, int16_t y)
Widget part function for setting the minimal size.
Definition widget_type.h:1137
NWidget
constexpr NWidgetPart NWidget(WidgetType tp, Colours col, WidgetID idx=-1)
Widget part function for starting a new 'real' widget.
Definition widget_type.h:1320
SetMatrixDataTip
constexpr NWidgetPart SetMatrixDataTip(uint8_t cols, uint8_t rows, StringID tip)
Widget part function for setting the data and tooltip of WWT_MATRIX widgets.
Definition widget_type.h:1214
EndContainer
constexpr NWidgetPart EndContainer()
Widget part function for denoting the end of a container (horizontal, vertical, WWT_FRAME,...
Definition widget_type.h:1191
SetResize
constexpr NWidgetPart SetResize(int16_t dx, int16_t dy)
Widget part function for setting the resize step.
Definition widget_type.h:1126
Window::SetDirty
void SetDirty() const
Mark entire window as dirty (in need of re-paint)
Definition window.cpp:940
industry.h
Base of all industries.
abs
constexpr T abs(const T a)
Returns the absolute value of (scalar) variable.
Definition math_func.hpp:23
IsInsideMM
constexpr bool IsInsideMM(const T x, const size_t min, const size_t max) noexcept
Checks if a value is in an interval.
Definition math_func.hpp:268
GetColourGradient
uint8_t GetColourGradient(Colours colour, ColourShade shade)
Get colour gradient palette index.
Definition palette.cpp:314
PC_BLACK
static const uint8_t PC_BLACK
Black palette colour.
Definition palette_func.h:67
GREY_SCALE
#define GREY_SCALE(level)
Return the colour for a particular greyscale level.
Definition palette_func.h:65
safeguards.h
A number of safeguards to prevent using unsafe methods.
_settings_client
ClientSettings _settings_client
The current settings for this game.
Definition settings.cpp:56
sprites.h
This file contains all sprite-related enums and defines.
stdafx.h
Definition of base types and functions in a cross-platform compatible way.
lengthof
#define lengthof(array)
Return the length of an fixed size array.
Definition stdafx.h:280
SetDParamMaxValue
void SetDParamMaxValue(size_t n, uint64_t max_value, uint min_count, FontSize size)
Set DParam n to some number that is suitable for string size computations.
Definition strings.cpp:127
SetDParam
void SetDParam(size_t n, uint64_t v)
Set a string parameter v at index n in the global string parameter array.
Definition strings.cpp:104
_current_text_dir
TextDirection _current_text_dir
Text direction of the currently selected language.
Definition strings.cpp:56
strings_func.h
Functions related to OTTD's strings.
TD_RTL
@ TD_RTL
Text is written right-to-left by default.
Definition strings_type.h:24
StringID
uint32_t StringID
Numeric value that represents a string, independent of the selected language.
Definition strings_type.h:16
BaseGraphWindow::DataSet
Definition graph_gui.cpp:206
BaseGraphWindow
Definition graph_gui.cpp:168
BaseGraphWindow::GetYLabelWidth
uint GetYLabelWidth(ValuesInterval current_interval, int num_hori_lines) const
Get width for Y labels.
Definition graph_gui.cpp:303
BaseGraphWindow::OnGameTick
void OnGameTick() override
Called once per (game) tick.
Definition graph_gui.cpp:654
BaseGraphWindow::MIN_GRID_PIXEL_SIZE
static const int MIN_GRID_PIXEL_SIZE
Minimum distance between graph lines.
Definition graph_gui.cpp:185
BaseGraphWindow::GRAPH_NUM_MONTHS
static const int GRAPH_NUM_MONTHS
Number of months displayed in the graph.
Definition graph_gui.cpp:176
BaseGraphWindow::DrawWidget
void DrawWidget(const Rect &r, WidgetID widget) const override
Draw the contents of a nested widget.
Definition graph_gui.cpp:599
BaseGraphWindow::ECONOMY_QUARTER_MINUTES
static const int ECONOMY_QUARTER_MINUTES
Minutes per economic quarter.
Definition graph_gui.cpp:179
BaseGraphWindow::GetDataSetRange
std::span< const OverflowSafeInt64 > GetDataSetRange(const DataSet &dataset) const
Get appropriate part of dataset values for the current number of horizontal points.
Definition graph_gui.cpp:222
BaseGraphWindow::OnClick
void OnClick(Point pt, WidgetID widget, int click_count) override
A click with the left mouse button has been made on the window.
Definition graph_gui.cpp:634
BaseGraphWindow::ECONOMY_MONTH_MINUTES
static const int ECONOMY_MONTH_MINUTES
Minutes per economic month.
Definition graph_gui.cpp:180
BaseGraphWindow::excluded_data
uint64_t excluded_data
bitmask of the datasets that shouldn't be displayed.
Definition graph_gui.cpp:187
BaseGraphWindow::draw_dates
bool draw_dates
Should we draw months and years on the time axis?
Definition graph_gui.cpp:197
BaseGraphWindow::MIN_GRAPH_NUM_LINES_Y
static const int MIN_GRAPH_NUM_LINES_Y
Minimal number of horizontal lines to draw.
Definition graph_gui.cpp:184
BaseGraphWindow::excluded_range
uint64_t excluded_range
bitmask of ranges that should not be displayed.
Definition graph_gui.cpp:188
BaseGraphWindow::month_increment
uint8_t month_increment
month increment between vertical lines. must be divisor of 12.
Definition graph_gui.cpp:195
BaseGraphWindow::PAYMENT_GRAPH_X_STEP_DAYS
static const int PAYMENT_GRAPH_X_STEP_DAYS
X-axis step label for cargo payment rates "Days in transit".
Definition graph_gui.cpp:177
BaseGraphWindow::GetValuesInterval
ValuesInterval GetValuesInterval(int num_hori_lines) const
Get the interval that contains the graph's data.
Definition graph_gui.cpp:233
BaseGraphWindow::UpdateStatistics
virtual void UpdateStatistics(bool initialize)
Update the statistics.
Definition graph_gui.cpp:674
BaseGraphWindow::GRAPH_AXIS_LABEL_COLOUR
static const TextColour GRAPH_AXIS_LABEL_COLOUR
colour of the graph axis label.
Definition graph_gui.cpp:182
BaseGraphWindow::OnInvalidateData
void OnInvalidateData(int data=0, bool gui_scope=true) override
Some data on this window has become invalid.
Definition graph_gui.cpp:664
BaseGraphWindow::DrawGraph
void DrawGraph(Rect r) const
Actually draw the graph.
Definition graph_gui.cpp:327
BaseGraphWindow::PAYMENT_GRAPH_X_STEP_SECONDS
static const int PAYMENT_GRAPH_X_STEP_SECONDS
X-axis step label for cargo payment rates "Seconds in transit".
Definition graph_gui.cpp:178
BaseGraphWindow::UpdateWidgetSize
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.
Definition graph_gui.cpp:542
CargoArray::GetSum
const T GetSum() const
Get the sum of all cargo amounts.
Definition cargo_type.h:120
CargoSpec
Specification of a cargo type.
Definition cargotype.h:76
CargoSpec::Get
static CargoSpec * Get(size_t index)
Retrieve cargo details for the given cargo ID.
Definition cargotype.h:139
CargoSpec::Index
CargoID Index() const
Determines index of this cargospec.
Definition cargotype.h:110
CargoSpec::name
StringID name
Name of this type of cargo.
Definition cargotype.h:93
ClientSettings::gui
GUISettings gui
settings related to the GUI
Definition settings_type.h:610
CompanyEconomyEntry::income
Money income
The amount of income.
Definition company_base.h:25
CompanyEconomyEntry::expenses
Money expenses
The amount of expenses.
Definition company_base.h:26
CompanyEconomyEntry::company_value
Money company_value
The value of the company.
Definition company_base.h:29
CompanyEconomyEntry::delivered_cargo
CargoArray delivered_cargo
The amount of delivered cargo.
Definition company_base.h:27
CompanyEconomyEntry::performance_history
int32_t performance_history
Company score (scale 0-1000)
Definition company_base.h:28
CompanyProperties::old_economy
CompanyEconomyEntry old_economy[MAX_HISTORY_QUARTERS]
Economic data of the company of the last MAX_HISTORY_QUARTERS quarters.
Definition company_base.h:116
CompanyProperties::colour
Colours colour
Company colour.
Definition company_base.h:87
CompanyProperties::num_valid_stat_ent
uint8_t num_valid_stat_ent
Number of valid statistical entries in old_economy.
Definition company_base.h:117
CompanyValueGraphWindow
Definition graph_gui.cpp:971
Company
Definition company_base.h:133
CurrencySpec::rate
uint16_t rate
The conversion rate compared to the base currency.
Definition currency.h:76
DeliveredCargoGraphWindow
Definition graph_gui.cpp:850
Dimension
Dimensions (a width and height) of a rectangle in 2D.
Definition geometry_type.hpp:30
GUISettings::graph_line_thickness
uint8_t graph_line_thickness
the thickness of the lines in the various graph guis
Definition settings_type.h:202
GraphLegendWindow
Definition graph_gui.cpp:52
GraphLegendWindow::OnClick
void OnClick(Point pt, WidgetID widget, int click_count) override
A click with the left mouse button has been made on the window.
Definition graph_gui.cpp:84
GraphLegendWindow::DrawWidget
void DrawWidget(const Rect &r, WidgetID widget) const override
Draw the contents of a nested widget.
Definition graph_gui.cpp:64
GraphLegendWindow::OnInvalidateData
void OnInvalidateData(int data=0, bool gui_scope=true) override
Some data on this window has become invalid.
Definition graph_gui.cpp:103
IncomeGraphWindow
Definition graph_gui.cpp:793
IndustryProductionGraphWindow
Definition graph_gui.cpp:1502
IndustryProductionGraphWindow::UpdateStatistics
void UpdateStatistics(bool initialize) override
Update the statistics.
Definition graph_gui.cpp:1687
IndustryProductionGraphWindow::UpdateWidgetSize
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.
Definition graph_gui.cpp:1560
IndustryProductionGraphWindow::OnResize
void OnResize() override
Called after the window got resized.
Definition graph_gui.cpp:1682
IndustryProductionGraphWindow::OnClick
void OnClick(Point pt, WidgetID widget, int click_count) override
A click with the left mouse button has been made on the window.
Definition graph_gui.cpp:1631
IndustryProductionGraphWindow::DrawWidget
void DrawWidget(const Rect &r, WidgetID widget) const override
Draw the contents of a nested widget.
Definition graph_gui.cpp:1587
IndustryProductionGraphWindow::line_height
uint line_height
Pixel height of each cargo type row.
Definition graph_gui.cpp:1503
IndustryProductionGraphWindow::legend_width
uint legend_width
Width of legend 'blob'.
Definition graph_gui.cpp:1505
IndustryProductionGraphWindow::OnInit
void OnInit() override
Notification that the nested widget tree gets initialized.
Definition graph_gui.cpp:1543
IndustryProductionGraphWindow::SetStringParameters
void SetStringParameters(WidgetID widget) const override
Initialize string parameters for a widget.
Definition graph_gui.cpp:1677
IndustryProductionGraphWindow::vscroll
Scrollbar * vscroll
Cargo list scrollbar.
Definition graph_gui.cpp:1504
Industry
Defines the internal data of a functional industry.
Definition industry.h:66
Industry::produced
ProducedCargoes produced
produced cargo slots
Definition industry.h:97
NWidgetPart
Partial widget specification to allow NWidgets to be written nested.
Definition widget_type.h:1075
OperatingProfitGraphWindow
Definition graph_gui.cpp:734
PaymentRatesGraphWindow
Definition graph_gui.cpp:1028
PaymentRatesGraphWindow::line_height
uint line_height
Pixel height of each cargo type row.
Definition graph_gui.cpp:1029
PaymentRatesGraphWindow::OnResize
void OnResize() override
Called after the window got resized.
Definition graph_gui.cpp:1170
PaymentRatesGraphWindow::OnInit
void OnInit() override
Notification that the nested widget tree gets initialized.
Definition graph_gui.cpp:1056
PaymentRatesGraphWindow::OnGameTick
void OnGameTick() override
Called once per (game) tick.
Definition graph_gui.cpp:1175
PaymentRatesGraphWindow::UpdateWidgetSize
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.
Definition graph_gui.cpp:1073
PaymentRatesGraphWindow::UpdatePaymentRates
void UpdatePaymentRates()
Update the payment rates according to the latest information.
Definition graph_gui.cpp:1199
PaymentRatesGraphWindow::update_payment_interval
IntervalTimer< TimerWindow > update_payment_interval
Update the payment rates on a regular interval.
Definition graph_gui.cpp:1192
PaymentRatesGraphWindow::OnClick
void OnClick(Point pt, WidgetID widget, int click_count) override
A click with the left mouse button has been made on the window.
Definition graph_gui.cpp:1132
PaymentRatesGraphWindow::legend_width
uint legend_width
Width of legend 'blob'.
Definition graph_gui.cpp:1031
PaymentRatesGraphWindow::DrawWidget
void DrawWidget(const Rect &r, WidgetID widget) const override
Draw the contents of a nested widget.
Definition graph_gui.cpp:1097
PaymentRatesGraphWindow::OnInvalidateData
void OnInvalidateData(int data=0, bool gui_scope=true) override
Some data on this window has become invalid.
Definition graph_gui.cpp:1185
PaymentRatesGraphWindow::vscroll
Scrollbar * vscroll
Cargo list scrollbar.
Definition graph_gui.cpp:1030
PerformanceHistoryGraphWindow
Definition graph_gui.cpp:907
PerformanceHistoryGraphWindow::OnClick
void OnClick(Point pt, WidgetID widget, int click_count) override
A click with the left mouse button has been made on the window.
Definition graph_gui.cpp:925
PerformanceRatingDetailWindow
Definition graph_gui.cpp:1271
PerformanceRatingDetailWindow::OnGameTick
void OnGameTick() override
Called once per (game) tick.
Definition graph_gui.cpp:1453
PerformanceRatingDetailWindow::OnInvalidateData
void OnInvalidateData(int data=0, bool gui_scope=true) override
Some data on this window has become invalid.
Definition graph_gui.cpp:1467
PerformanceRatingDetailWindow::DrawWidget
void DrawWidget(const Rect &r, WidgetID widget) const override
Draw the contents of a nested widget.
Definition graph_gui.cpp:1361
PerformanceRatingDetailWindow::UpdateWidgetSize
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.
Definition graph_gui.cpp:1303
PerformanceRatingDetailWindow::OnClick
void OnClick(Point pt, WidgetID widget, int click_count) override
A click with the left mouse button has been made on the window.
Definition graph_gui.cpp:1439
Point
Coordinates of a point in 2D.
Definition geometry_type.hpp:21
Pool::PoolItem<&_company_pool >::IsValidID
static bool IsValidID(size_t index)
Tests whether given index can be used to get valid (non-nullptr) Titem.
Definition pool_type.hpp:328
Pool::PoolItem<&_company_pool >::Iterate
static Pool::IterateWrapper< Titem > Iterate(size_t from=0)
Returns an iterable ensemble of all valid Titem.
Definition pool_type.hpp:388
Pool::PoolItem<&_company_pool >::GetIfValid
static Titem * GetIfValid(size_t index)
Returns Titem with given index.
Definition pool_type.hpp:350
Pool::PoolItem<&_industry_pool >::Get
static Titem * Get(size_t index)
Returns Titem with given index.
Definition pool_type.hpp:339
RectPadding::Horizontal
constexpr uint Horizontal() const
Get total horizontal padding of RectPadding.
Definition geometry_type.hpp:63
RectPadding::Vertical
constexpr uint Vertical() const
Get total vertical padding of RectPadding.
Definition geometry_type.hpp:69
Rect
Specification of a rectangle with absolute coordinates of all edges.
Definition geometry_type.hpp:75
Rect::WithWidth
Rect WithWidth(int width, bool end) const
Copy Rect and set its width.
Definition geometry_type.hpp:185
Rect::Shrink
Rect Shrink(int s) const
Copy and shrink Rect by s pixels.
Definition geometry_type.hpp:98
Rect::WithHeight
Rect WithHeight(int height, bool end=false) const
Copy Rect and set its height.
Definition geometry_type.hpp:211
Rect::Indent
Rect Indent(int indent, bool end) const
Copy Rect and indent it from its position.
Definition geometry_type.hpp:198
Rect::Translate
Rect Translate(int x, int y) const
Copy and translate Rect by x,y pixels.
Definition geometry_type.hpp:174
ScoreInfo::needed
int needed
How much you need to get the perfect score.
Definition economy_type.h:81
ScoreInfo::score
int score
How much score it will give.
Definition economy_type.h:82
StrongType::Typedef
Templated helper to make a type-safe 'typedef' representing a single POD value.
Definition strong_typedef_type.hpp:150
ValuesInterval
Contains the interval of a graph's data.
Definition graph_gui.cpp:159
ValuesInterval::lowest
OverflowSafeInt64 lowest
Lowest value of this interval. Must be zero or less.
Definition graph_gui.cpp:161
ValuesInterval::highest
OverflowSafeInt64 highest
Highest value of this interval. Must be zero or greater.
Definition graph_gui.cpp:160
WindowDesc
High level window description.
Definition window_gui.h:159
Window
Data structure for an opened window.
Definition window_gui.h:273
Window::FinishInitNested
void FinishInitNested(WindowNumber window_number=0)
Perform the second part of the initialization of a nested widget tree.
Definition window.cpp:1733
Window::RaiseWidget
void RaiseWidget(WidgetID widget_index)
Marks a widget as raised.
Definition window_gui.h:475
Window::resize
ResizeInfo resize
Resize information.
Definition window_gui.h:314
Window::CreateNestedTree
void CreateNestedTree()
Perform the first part of the initialization of a nested widget tree.
Definition window.cpp:1723
Window::IsWidgetDisabled
bool IsWidgetDisabled(WidgetID widget_index) const
Gets the enabled/disabled status of a widget.
Definition window_gui.h:416
Window::left
int left
x position of left edge of the window
Definition window_gui.h:309
Window::GetRowFromWidget
int GetRowFromWidget(int clickpos, WidgetID widget, int padding, int line_height=-1) const
Compute the row of a widget that a user clicked in.
Definition window.cpp:213
Window::GetWidget
const NWID * GetWidget(WidgetID widnum) const
Get the nested widget with number widnum from the nested widget tree.
Definition window_gui.h:977
Window::LowerWidget
void LowerWidget(WidgetID widget_index)
Marks a widget as lowered.
Definition window_gui.h:466
Window::InitNested
void InitNested(WindowNumber number=0)
Perform complete initialization of the Window with nested widgets, to allow use.
Definition window.cpp:1746
Window::GetScrollbar
const Scrollbar * GetScrollbar(WidgetID widnum) const
Return the Scrollbar to a widget index.
Definition window.cpp:314
Window::SetWidgetDisabledState
void SetWidgetDisabledState(WidgetID widget_index, bool disab_stat)
Sets the enabled/disabled status of a widget.
Definition window_gui.h:387
Window::height
int height
Height of the window (number of pixels down in y direction)
Definition window_gui.h:312
Window::width
int width
width of the window (number of pixels to the right in x direction)
Definition window_gui.h:311
Window::ToggleWidgetLoweredState
void ToggleWidgetLoweredState(WidgetID widget_index)
Invert the lowered/raised status of a widget.
Definition window_gui.h:456
Window::window_number
WindowNumber window_number
Window number within the window class.
Definition window_gui.h:302
timer.h
Definition of Interval and OneShot timers.
timer_game_economy.h
Definition of the game-economy-timer.
timer_game_tick.h
Definition of the tick-based game-timer.
timer_window.h
Definition of the Window system.
DrawFrameRect
void DrawFrameRect(int left, int top, int right, int bottom, Colours colour, FrameFlags flags)
Draw frame rectangle.
Definition widget.cpp:283
ScaleGUITrad
static RectPadding ScaleGUITrad(const RectPadding &r)
Scale a RectPadding to GUI zoom level.
Definition widget.cpp:35
MakeCompanyButtonRows
std::unique_ptr< NWidgetBase > MakeCompanyButtonRows(WidgetID widget_first, WidgetID widget_last, Colours button_colour, int max_length, StringID button_tooltip, bool resizable)
Make a number of rows with button-like graphics, for enabling/disabling each company.
Definition widget.cpp:3358
NC_EQUALSIZE
@ NC_EQUALSIZE
Value of the NCB_EQUALSIZE flag.
Definition widget_type.h:524
WWT_PUSHTXTBTN
@ WWT_PUSHTXTBTN
Normal push-button (no toggle button) with text caption.
Definition widget_type.h:113
NWID_SPACER
@ NWID_SPACER
Invisible widget that takes some space.
Definition widget_type.h:79
NWID_HORIZONTAL
@ NWID_HORIZONTAL
Horizontal container.
Definition widget_type.h:75
WWT_PANEL
@ WWT_PANEL
Simple depressed panel.
Definition widget_type.h:50
WWT_STICKYBOX
@ WWT_STICKYBOX
Sticky box (at top-right of a window, after WWT_DEFSIZEBOX)
Definition widget_type.h:66
WWT_MATRIX
@ WWT_MATRIX
Grid of rows and columns.
Definition widget_type.h:59
WWT_SHADEBOX
@ WWT_SHADEBOX
Shade box (at top-right of a window, between WWT_DEBUGBOX and WWT_DEFSIZEBOX)
Definition widget_type.h:64
WWT_CAPTION
@ WWT_CAPTION
Window caption (window title between closebox and stickybox)
Definition widget_type.h:61
NWID_VSCROLLBAR
@ NWID_VSCROLLBAR
Vertical scrollbar.
Definition widget_type.h:85
NWID_VERTICAL
@ NWID_VERTICAL
Vertical container.
Definition widget_type.h:77
WWT_CLOSEBOX
@ WWT_CLOSEBOX
Close box (at top-left of a window)
Definition widget_type.h:69
WWT_EMPTY
@ WWT_EMPTY
Empty widget, place holder to reserve space in widget tree.
Definition widget_type.h:48
WWT_RESIZEBOX
@ WWT_RESIZEBOX
Resize box (normally at bottom-right of a window)
Definition widget_type.h:68
WWT_DEFSIZEBOX
@ WWT_DEFSIZEBOX
Default window size box (at top-right of a window, between WWT_SHADEBOX and WWT_STICKYBOX)
Definition widget_type.h:65
WWT_TEXT
@ WWT_TEXT
Pure simple text.
Definition widget_type.h:58
MAT_ROW_START
static constexpr uint8_t MAT_ROW_START
Lowest bit of the number of rows.
Definition widget_type.h:26
MAT_COL_START
static constexpr uint8_t MAT_COL_START
Bits of the WWT_MATRIX widget data.
Definition widget_type.h:22
RWV_HIDE_BEVEL
@ RWV_HIDE_BEVEL
Bevel of resize box is hidden.
Definition widget_type.h:40
InvalidateWindowData
void InvalidateWindowData(WindowClass cls, WindowNumber number, int data, bool gui_scope)
Mark window data of the window of a given class and specific window number as invalid (in need of re-...
Definition window.cpp:3219
SetWindowDirty
void SetWindowDirty(WindowClass cls, WindowNumber number)
Mark window as dirty (in need of repainting)
Definition window.cpp:3101
window_func.h
Window functions not directly related to making/drawing windows.
window_gui.h
Functions, definitions and such used only by the GUI.
FR_LOWERED
@ FR_LOWERED
If set the frame is lowered and the background colour brighter (ie. buttons when pressed)
Definition window_gui.h:28
WDP_AUTO
@ WDP_AUTO
Find a place automatically.
Definition window_gui.h:147
WidgetID
int WidgetID
Widget ID.
Definition window_type.h:18
WindowNumber
int32_t WindowNumber
Number to differentiate different windows of the same class.
Definition window_type.h:740
WC_PERFORMANCE_HISTORY
@ WC_PERFORMANCE_HISTORY
Performance history graph; Window numbers:
Definition window_type.h:551
WC_PERFORMANCE_DETAIL
@ WC_PERFORMANCE_DETAIL
Performance detail window; Window numbers:
Definition window_type.h:575
WC_PAYMENT_RATES
@ WC_PAYMENT_RATES
Payment rates graph; Window numbers:
Definition window_type.h:569
WC_GRAPH_LEGEND
@ WC_GRAPH_LEGEND
Legend for graphs; Window numbers:
Definition window_type.h:521
WC_NONE
@ WC_NONE
No window, redirects to WC_MAIN_WINDOW.
Definition window_type.h:45
WC_OPERATING_PROFIT
@ WC_OPERATING_PROFIT
Operating profit graph; Window numbers:
Definition window_type.h:539
WC_INDUSTRY_PRODUCTION
@ WC_INDUSTRY_PRODUCTION
Industry production history graph; Window numbers:
Definition window_type.h:581
WC_INDUSTRY_VIEW
@ WC_INDUSTRY_VIEW
Industry view; Window numbers:
Definition window_type.h:363
WC_INCOME_GRAPH
@ WC_INCOME_GRAPH
Income graph; Window numbers:
Definition window_type.h:533
WC_DELIVERED_CARGO
@ WC_DELIVERED_CARGO
Delivered cargo graph; Window numbers:
Definition window_type.h:545
WC_COMPANY_VALUE
@ WC_COMPANY_VALUE
Company value graph; Window numbers:
Definition window_type.h:557
zoom_func.h
Functions related to zooming.
ZOOM_LVL_NORMAL
@ ZOOM_LVL_NORMAL
The normal zoom level.
Definition zoom_type.h:21