OpenTTD Source 20241222-master-gc72542431a
subsidy_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 "industry.h"
12#include "town.h"
13#include "window_gui.h"
14#include "strings_func.h"
16#include "viewport_func.h"
17#include "gui.h"
18#include "subsidy_func.h"
19#include "subsidy_base.h"
21
23
24#include "table/strings.h"
25
26#include "safeguards.h"
27
29 Scrollbar *vscroll;
30 Dimension cargo_icon_size;
31
33 {
34 this->CreateNestedTree();
35 this->vscroll = this->GetScrollbar(WID_SUL_SCROLLBAR);
36 this->FinishInitNested(window_number);
37 this->OnInvalidateData(0);
38 }
39
40 void OnInit() override
41 {
42 this->cargo_icon_size = GetLargestCargoIconSize();
43 }
44
45 void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override
46 {
47 if (widget != WID_SUL_PANEL) return;
48
50 int num = 0;
51 for (const Subsidy *s : Subsidy::Iterate()) {
52 if (!s->IsAwarded()) {
53 y--;
54 if (y == 0) {
55 this->HandleClick(s);
56 return;
57 }
58 num++;
59 }
60 }
61
62 if (num == 0) {
63 y--; // "None"
64 if (y < 0) return;
65 }
66
67 y -= 2; // "Services already subsidised:"
68 if (y < 0) return;
69
70 for (const Subsidy *s : Subsidy::Iterate()) {
71 if (s->IsAwarded()) {
72 y--;
73 if (y == 0) {
74 this->HandleClick(s);
75 return;
76 }
77 }
78 }
79 }
80
81 void HandleClick(const Subsidy *s)
82 {
83 /* determine src coordinate for subsidy and try to scroll to it */
84 TileIndex xy;
85 switch (s->src_type) {
86 case SourceType::Industry: xy = Industry::Get(s->src)->location.tile; break;
87 case SourceType::Town: xy = Town::Get(s->src)->xy; break;
88 default: NOT_REACHED();
89 }
90
93
94 /* otherwise determine dst coordinate for subsidy and scroll to it */
95 switch (s->dst_type) {
96 case SourceType::Industry: xy = Industry::Get(s->dst)->location.tile; break;
97 case SourceType::Town: xy = Town::Get(s->dst)->xy; break;
98 default: NOT_REACHED();
99 }
100
101 if (_ctrl_pressed) {
103 } else {
105 }
106 }
107 }
108
114 {
115 /* Count number of (non) awarded subsidies */
116 uint num_awarded = 0;
117 uint num_not_awarded = 0;
118 for (const Subsidy *s : Subsidy::Iterate()) {
119 if (!s->IsAwarded()) {
121 } else {
122 num_awarded++;
123 }
124 }
125
126 /* Count the 'none' lines */
127 if (num_awarded == 0) num_awarded = 1;
128 if (num_not_awarded == 0) num_not_awarded = 1;
129
130 /* Offered, accepted and an empty line before the accepted ones. */
131 return 3 + num_awarded + num_not_awarded;
132 }
133
146
147 void DrawCargoIcon(const Rect &r, int y_offset, CargoID cid) const
148 {
149 bool rtl = _current_text_dir == TD_RTL;
151 Dimension d = GetSpriteSize(icon);
152 Rect ir = r.WithWidth(this->cargo_icon_size.width, rtl).WithHeight(GetCharacterHeight(FS_NORMAL));
153 DrawSprite(icon, PAL_NONE, CenterBounds(ir.left, ir.right, d.width), CenterBounds(ir.top, ir.bottom, this->cargo_icon_size.height) + y_offset);
154 }
155
156 void DrawWidget(const Rect &r, WidgetID widget) const override
157 {
158 if (widget != WID_SUL_PANEL) return;
159
160 TimerGameEconomy::YearMonthDay ymd = TimerGameEconomy::ConvertDateToYMD(TimerGameEconomy::date);
161
162 Rect tr = r.Shrink(WidgetDimensions::scaled.framerect);
163 Rect sr = tr.Indent(this->cargo_icon_size.width + WidgetDimensions::scaled.hsep_normal, _current_text_dir == TD_RTL);
164
165 int pos = -this->vscroll->GetPosition();
166 const int cap = this->vscroll->GetCapacity();
167
168 /* Section for drawing the offered subsidies */
169 if (IsInsideMM(pos, 0, cap)) DrawString(tr.left, tr.right, tr.top + pos * GetCharacterHeight(FS_NORMAL), STR_SUBSIDIES_OFFERED_TITLE);
170 pos++;
171
172 uint num = 0;
173 for (const Subsidy *s : Subsidy::Iterate()) {
174 if (!s->IsAwarded()) {
175 if (IsInsideMM(pos, 0, cap)) {
176 /* Displays the two offered towns */
178 /* If using wallclock units, show minutes remaining. Otherwise show the date when the subsidy ends. */
181 SetDParam(8, s->remaining + 1); // We get the rest of the current economy month for free, since the expiration is checked on each new month.
182 } else {
184 SetDParam(8, TimerGameEconomy::date - ymd.day + s->remaining * 32);
185 }
186
187 DrawCargoIcon(tr, pos * GetCharacterHeight(FS_NORMAL), s->cargo_type);
189 }
190 pos++;
191 num++;
192 }
193 }
194
195 if (num == 0) {
196 if (IsInsideMM(pos, 0, cap)) DrawString(tr.left, tr.right, tr.top + pos * GetCharacterHeight(FS_NORMAL), STR_SUBSIDIES_NONE);
197 pos++;
198 }
199
200 /* Section for drawing the already granted subsidies */
201 pos++;
202 if (IsInsideMM(pos, 0, cap)) DrawString(tr.left, tr.right, tr.top + pos * GetCharacterHeight(FS_NORMAL), STR_SUBSIDIES_SUBSIDISED_TITLE);
203 pos++;
204 num = 0;
205
206 for (const Subsidy *s : Subsidy::Iterate()) {
207 if (s->IsAwarded()) {
208 if (IsInsideMM(pos, 0, cap)) {
210 SetDParam(7, s->awarded);
211 /* If using wallclock units, show minutes remaining. Otherwise show the date when the subsidy ends. */
214 SetDParam(9, s->remaining);
215 }
216 else {
218 SetDParam(9, TimerGameEconomy::date - ymd.day + s->remaining * 32);
219 }
220
221 /* Displays the two connected stations */
222 DrawCargoIcon(tr, pos * GetCharacterHeight(FS_NORMAL), s->cargo_type);
224 }
225 pos++;
226 num++;
227 }
228 }
229
230 if (num == 0) {
231 if (IsInsideMM(pos, 0, cap)) DrawString(tr.left, tr.right, tr.top + pos * GetCharacterHeight(FS_NORMAL), STR_SUBSIDIES_NONE);
232 pos++;
233 }
234 }
235
236 void OnResize() override
237 {
238 this->vscroll->SetCapacityFromWidget(this, WID_SUL_PANEL, WidgetDimensions::scaled.framerect.Vertical());
239 }
240
246 void OnInvalidateData([[maybe_unused]] int data = 0, [[maybe_unused]] bool gui_scope = true) override
247 {
248 if (!gui_scope) return;
249 this->vscroll->SetCount(this->CountLines());
250 }
251};
252
253static constexpr NWidgetPart _nested_subsidies_list_widgets[] = {
255 NWidget(WWT_CLOSEBOX, COLOUR_BROWN),
256 NWidget(WWT_CAPTION, COLOUR_BROWN), SetDataTip(STR_SUBSIDIES_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
257 NWidget(WWT_SHADEBOX, COLOUR_BROWN),
258 NWidget(WWT_DEFSIZEBOX, COLOUR_BROWN),
259 NWidget(WWT_STICKYBOX, COLOUR_BROWN),
260 EndContainer(),
262 NWidget(WWT_PANEL, COLOUR_BROWN, WID_SUL_PANEL), SetDataTip(0x0, STR_SUBSIDIES_TOOLTIP_CLICK_ON_SERVICE_TO_CENTER), SetResize(1, 1), SetScrollbar(WID_SUL_SCROLLBAR), EndContainer(),
265 NWidget(WWT_RESIZEBOX, COLOUR_BROWN),
266 EndContainer(),
267 EndContainer(),
268};
269
270static WindowDesc _subsidies_list_desc(
271 WDP_AUTO, "list_subsidies", 500, 127,
273 0,
274 _nested_subsidies_list_widgets
275);
276
277
278void ShowSubsidiesList()
279{
280 AllocateWindowDescFront<SubsidyListWindow>(_subsidies_list_desc, 0);
281}
uint8_t CargoID
Cargo slots to indicate a cargo type within a game.
Definition cargo_type.h:22
@ Industry
Source/destination is an industry.
@ Town
Source/destination is a town.
Dimension GetLargestCargoIconSize()
Get dimensions of largest cargo icon.
Scrollbar data structure.
size_type GetCapacity() const
Gets the number of visible elements of the scrollbar.
void SetCount(size_t num)
Sets the number of elements in the list.
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
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
size_type GetPosition() const
Gets the position of the first visible element in the list.
static Date date
Current date in days (day counter).
static bool UsingWallclockUnits(bool newgame=false)
Check if we are using wallclock units.
static YearMonthDay ConvertDateToYMD(Date date)
Converts a Date to a Year, Month & Day.
RectPadding framerect
Standard padding inside many panels.
Definition window_gui.h:42
static WidgetDimensions scaled
Widget dimensions scaled for current zoom level.
Definition window_gui.h:28
int hsep_normal
Normal horizontal spacing.
Definition window_gui.h:63
int GetCharacterHeight(FontSize size)
Get height of a character for a given font size.
Definition fontcache.cpp:77
Dimension maxdim(const Dimension &d1, const Dimension &d2)
Compute bounding box of both dimensions.
Geometry functions.
Dimension GetSpriteSize(SpriteID sprid, Point *offset, ZoomLevel zoom)
Get the size of a sprite.
Definition gfx.cpp:922
Dimension GetStringBoundingBox(std::string_view str, FontSize start_fontsize)
Return the string dimension in pixels.
Definition gfx.cpp:851
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
bool _ctrl_pressed
Is Ctrl pressed?
Definition gfx.cpp:38
void DrawSprite(SpriteID img, PaletteID pal, int x, int y, const SubSprite *sub, ZoomLevel zoom)
Draw a sprite, not in a viewport.
Definition gfx.cpp:988
int CenterBounds(int min, int max, int size)
Determine where to draw a centred object inside a widget.
Definition gfx_func.h:166
uint32_t SpriteID
The number of a sprite, without mapping bits and colourtables.
Definition gfx_type.h:18
@ FS_NORMAL
Index of the normal font in the font tables.
Definition gfx_type.h:209
constexpr NWidgetPart SetScrollbar(WidgetID index)
Attach a scrollbar to a widget.
constexpr NWidgetPart SetDataTip(uint32_t data, StringID tip)
Widget part function for setting the data and tooltip.
constexpr NWidgetPart NWidget(WidgetType tp, Colours col, WidgetID idx=-1)
Widget part function for starting a new 'real' widget.
constexpr NWidgetPart EndContainer()
Widget part function for denoting the end of a container (horizontal, vertical, WWT_FRAME,...
constexpr NWidgetPart SetResize(int16_t dx, int16_t dy)
Widget part function for setting the resize step.
GUI functions that shouldn't be here.
void ShowExtraViewportWindow(TileIndex tile=INVALID_TILE)
Show a new Extra Viewport window.
Base of all industries.
constexpr bool IsInsideMM(const T x, const size_t min, const size_t max) noexcept
Checks if a value is in an interval.
A number of safeguards to prevent using unsafe methods.
Definition of base types and functions in a cross-platform compatible way.
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
TextDirection _current_text_dir
Text direction of the currently selected language.
Definition strings.cpp:56
Functions related to OTTD's strings.
@ TD_RTL
Text is written right-to-left by default.
static CargoSpec * Get(size_t index)
Retrieve cargo details for the given cargo ID.
Definition cargotype.h:139
SpriteID GetCargoIcon() const
Get sprite for showing cargo of this type.
Dimensions (a width and height) of a rectangle in 2D.
Partial widget specification to allow NWidgets to be written nested.
Coordinates of a point in 2D.
static Pool::IterateWrapper< Titem > Iterate(size_t from=0)
Returns an iterable ensemble of all valid Titem.
static Titem * Get(size_t index)
Returns Titem with given index.
constexpr uint Horizontal() const
Get total horizontal padding of RectPadding.
constexpr uint Vertical() const
Get total vertical padding of RectPadding.
Specification of a rectangle with absolute coordinates of all edges.
Rect WithWidth(int width, bool end) const
Copy Rect and set its width.
Rect Shrink(int s) const
Copy and shrink Rect by s pixels.
Rect WithHeight(int height, bool end=false) const
Copy Rect and set its height.
Rect Indent(int indent, bool end) const
Copy Rect and indent it from its position.
uint CountLines()
Count the number of lines in this window.
void OnInit() override
Notification that the nested widget tree gets initialized.
void OnClick(Point pt, WidgetID widget, int click_count) override
A click with the left mouse button has been made on the window.
void DrawWidget(const Rect &r, WidgetID widget) const override
Draw the contents of a nested widget.
void OnInvalidateData(int data=0, bool gui_scope=true) override
Some data on this window has become invalid.
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.
void OnResize() override
Called after the window got resized.
Struct about subsidies, offered and awarded.
bool IsAwarded() const
Tests whether this subsidy has been awarded to someone.
SourceType dst_type
Destination of subsidised path (SourceType::Industry or SourceType::Town)
SourceType src_type
Source of subsidised path (SourceType::Industry or SourceType::Town)
CompanyID awarded
Subsidy is awarded to this company; INVALID_COMPANY if it's not awarded to anyone.
CargoID cargo_type
Cargo type involved in this subsidy, INVALID_CARGO for invalid subsidy.
uint16_t remaining
Remaining months when this subsidy is valid.
SourceID src
Index of source. Either TownID or IndustryID.
SourceID dst
Index of destination. Either TownID or IndustryID.
High level window description.
Definition window_gui.h:159
Data structure for an opened window.
Definition window_gui.h:273
void FinishInitNested(WindowNumber window_number=0)
Perform the second part of the initialization of a nested widget tree.
Definition window.cpp:1733
ResizeInfo resize
Resize information.
Definition window_gui.h:314
void CreateNestedTree()
Perform the first part of the initialization of a nested widget tree.
Definition window.cpp:1723
const NWID * GetWidget(WidgetID widnum) const
Get the nested widget with number widnum from the nested widget tree.
Definition window_gui.h:977
const Scrollbar * GetScrollbar(WidgetID widnum) const
Return the Scrollbar to a widget index.
Definition window.cpp:314
WindowNumber window_number
Window number within the window class.
Definition window_gui.h:302
std::pair< NewsReferenceType, NewsReferenceType > SetupSubsidyDecodeParam(const Subsidy *s, SubsidyDecodeParamType mode, uint parameter_offset)
Setup the string parameters for printing the subsidy at the screen, and compute the news reference fo...
Definition subsidy.cpp:75
Subsidy base class.
@ Gui
Subsidies listed in the Subsidy GUI.
Functions related to subsidies.
Types related to the subsidy widgets.
@ WID_SUL_PANEL
Main panel of window.
@ WID_SUL_SCROLLBAR
Scrollbar of panel.
Definition of the game-calendar-timer.
Base of the town class.
bool ScrollMainWindowToTile(TileIndex tile, bool instant)
Scrolls the viewport of the main window to a given location.
Functions related to (drawing on) viewports.
@ NWID_HORIZONTAL
Horizontal container.
Definition widget_type.h:75
@ WWT_PANEL
Simple depressed panel.
Definition widget_type.h:50
@ WWT_STICKYBOX
Sticky box (at top-right of a window, after WWT_DEFSIZEBOX)
Definition widget_type.h:66
@ WWT_SHADEBOX
Shade box (at top-right of a window, between WWT_DEBUGBOX and WWT_DEFSIZEBOX)
Definition widget_type.h:64
@ WWT_CAPTION
Window caption (window title between closebox and stickybox)
Definition widget_type.h:61
@ NWID_VSCROLLBAR
Vertical scrollbar.
Definition widget_type.h:85
@ NWID_VERTICAL
Vertical container.
Definition widget_type.h:77
@ WWT_CLOSEBOX
Close box (at top-left of a window)
Definition widget_type.h:69
@ WWT_RESIZEBOX
Resize box (normally at bottom-right of a window)
Definition widget_type.h:68
@ WWT_DEFSIZEBOX
Default window size box (at top-right of a window, between WWT_SHADEBOX and WWT_STICKYBOX)
Definition widget_type.h:65
Functions, definitions and such used only by the GUI.
@ WDP_AUTO
Find a place automatically.
Definition window_gui.h:147
int WidgetID
Widget ID.
Definition window_type.h:18
int32_t WindowNumber
Number to differentiate different windows of the same class.
@ WC_NONE
No window, redirects to WC_MAIN_WINDOW.
Definition window_type.h:45
@ WC_SUBSIDIES_LIST
Subsidies list; Window numbers: