OpenTTD Source 20250312-master-gcdcc6b491d
statusbar_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 "core/backup_type.hpp"
12#include "gfx_func.h"
13#include "news_func.h"
14#include "company_func.h"
15#include "string_func.h"
16#include "strings_func.h"
17#include "company_base.h"
18#include "tilehighlight_func.h"
19#include "news_gui.h"
20#include "company_gui.h"
21#include "window_gui.h"
22#include "saveload/saveload.h"
23#include "window_func.h"
24#include "statusbar_gui.h"
25#include "toolbar_gui.h"
27#include "zoom_func.h"
28#include "timer/timer.h"
30#include "timer/timer_window.h"
31
33
34#include "table/strings.h"
35#include "table/sprites.h"
36
37#include "safeguards.h"
38
39static bool DrawScrollingStatusText(const NewsItem *ni, int scroll_pos, int left, int right, int top, int bottom)
40{
41 /* Replace newlines and the likes with spaces. */
42 std::string message = StrMakeValid(ni->GetStatusText(), SVS_REPLACE_TAB_CR_NL_WITH_SPACE);
43
44 DrawPixelInfo tmp_dpi;
45 if (!FillDrawPixelInfo(&tmp_dpi, left, top, right - left, bottom)) return true;
46
47 int width = GetStringBoundingBox(message).width;
48 int pos = (_current_text_dir == TD_RTL) ? (scroll_pos - width) : (right - scroll_pos - left);
49
50 AutoRestoreBackup dpi_backup(_cur_dpi, &tmp_dpi);
51 DrawString(pos, INT16_MAX, 0, message, TC_LIGHT_BLUE, SA_LEFT | SA_FORCE);
52
53 return (_current_text_dir == TD_RTL) ? (pos < right - left) : (pos + width > 0);
54}
55
57 bool saving = false;
58 int ticker_scroll = TICKER_STOP;
59
60 static const int TICKER_STOP = 1640;
61 static const int COUNTER_STEP = 2;
62 static constexpr auto REMINDER_START = std::chrono::milliseconds(1350);
63
64 StatusBarWindow(WindowDesc &desc) : Window(desc)
65 {
66 this->InitNested();
69 }
70
72 {
73 Point pt = { 0, _screen.height - sm_height };
74 return pt;
75 }
76
81
83 {
85 switch (widget) {
86 case WID_S_LEFT:
88 break;
89
90 case WID_S_RIGHT: {
91 int64_t max_money = UINT32_MAX;
92 for (const Company *c : Company::Iterate()) max_money = std::max<int64_t>(c->money, max_money);
94 break;
95 }
96
97 default:
98 return;
99 }
100
101 d.width += padding.width;
102 d.height += padding.height;
103 size = maxdim(d, size);
104 }
105
106 void DrawWidget(const Rect &r, WidgetID widget) const override
107 {
108 Rect tr = r.Shrink(WidgetDimensions::scaled.framerect, RectPadding::zero);
109 tr.top = CenterBounds(r.top, r.bottom, GetCharacterHeight(FS_NORMAL));
110 switch (widget) {
111 case WID_S_LEFT:
112 /* Draw the date */
114 break;
115
116 case WID_S_RIGHT: {
121 } else {
122 /* Draw company money, if any */
124 if (c != nullptr) {
126 }
127 }
128 break;
129 }
130
131 case WID_S_MIDDLE:
132 /* Draw status bar */
133 if (this->saving) { // true when saving is active
135 } else if (_do_autosave) {
137 } else if (_pause_mode.Any()) {
139 DrawString(tr, msg, TC_FROMSTRING, SA_HOR_CENTER);
140 } else if (this->ticker_scroll < TICKER_STOP && GetStatusbarNews() != nullptr && !GetStatusbarNews()->headline.empty()) {
141 /* Draw the scrolling news text */
142 if (!DrawScrollingStatusText(GetStatusbarNews(), ScaleGUITrad(this->ticker_scroll), tr.left, tr.right, tr.top, tr.bottom)) {
145 /* This is the default text */
147 }
148 }
149 } else {
151 /* This is the default text */
153 }
154 }
155
156 if (!this->reminder_timeout.HasFired()) {
157 Dimension icon_size = GetSpriteSize(SPR_UNREAD_NEWS);
158 DrawSprite(SPR_UNREAD_NEWS, PAL_NONE, tr.right - icon_size.width, CenterBounds(r.top, r.bottom, icon_size.height));
159 }
160 break;
161 }
162 }
163
169 void OnInvalidateData([[maybe_unused]] int data = 0, [[maybe_unused]] bool gui_scope = true) override
170 {
171 if (!gui_scope) return;
172 switch (data) {
173 default: NOT_REACHED();
174 case SBI_SAVELOAD_START: this->saving = true; break;
175 case SBI_SAVELOAD_FINISH: this->saving = false; break;
176 case SBI_SHOW_TICKER: this->ticker_scroll = 0; break;
177 case SBI_SHOW_REMINDER: this->reminder_timeout.Reset(); break;
178 case SBI_NEWS_DELETED:
179 this->ticker_scroll = TICKER_STOP; // reset ticker ...
180 this->reminder_timeout.Abort(); // ... and reminder
181 break;
182 }
183 }
184
185 void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override
186 {
187 switch (widget) {
188 case WID_S_MIDDLE: ShowLastNewsMessage(); break;
190 default: ResetObjectToPlace();
191 }
192 }
193
195 IntervalTimer<TimerWindow> ticker_scroll_interval = {std::chrono::milliseconds(15), [this](uint count) {
196 if (_pause_mode.Any()) return;
197
198 if (this->ticker_scroll < TICKER_STOP) {
199 this->ticker_scroll += count;
201 }
202 }};
203
204 TimeoutTimer<TimerWindow> reminder_timeout = {REMINDER_START, [this]() {
206 }};
207
208 IntervalTimer<TimerGameCalendar> daily_interval = {{TimerGameCalendar::DAY, TimerGameCalendar::Priority::NONE}, [this](auto) {
210 }};
211};
212
213static constexpr NWidgetPart _nested_main_status_widgets[] = {
215 NWidget(WWT_PANEL, COLOUR_GREY, WID_S_LEFT), SetMinimalSize(140, 12), EndContainer(),
216 NWidget(WWT_PUSHBTN, COLOUR_GREY, WID_S_MIDDLE), SetMinimalSize(40, 12), SetToolTip(STR_STATUSBAR_TOOLTIP_SHOW_LAST_NEWS), SetResize(1, 0),
217 NWidget(WWT_PUSHBTN, COLOUR_GREY, WID_S_RIGHT), SetMinimalSize(140, 12),
218 EndContainer(),
219};
220
221static WindowDesc _main_status_desc(
222 WDP_MANUAL, nullptr, 0, 0,
225 _nested_main_status_widgets
226);
227
232{
233 const StatusBarWindow *w = dynamic_cast<StatusBarWindow*>(FindWindowById(WC_STATUS_BAR, 0));
234 return w != nullptr && w->ticker_scroll < StatusBarWindow::TICKER_STOP;
235}
236
241{
242 new StatusBarWindow(_main_status_desc);
243}
Class for backupping variables and making sure they are restored later.
constexpr bool Test(Tvalue_type value) const
Test if the value-th bit is set.
constexpr bool Any(const Timpl &other) const
Test if any of the given values are set.
constexpr Timpl & Reset(Tvalue_type value)
Reset the value-th bit.
An interval timer will fire every interval, and will continue to fire until it is deleted.
Definition timer.h:76
A timeout timer will fire once after the interval.
Definition timer.h:116
void Reset()
Reset the timer, so it will fire again after the timeout.
Definition timer.h:140
bool HasFired() const
Check whether the timeout occurred.
Definition timer.h:171
void Abort()
Abort the timer so it doesn't fire if it hasn't yet.
Definition timer.h:161
static Date date
Current date in days (day counter).
static constexpr TimerGame< struct Calendar >::Year MAX_YEAR
MAX_YEAR, nicely rounded value of the number of years that can be encoded in a single 32 bits date,...
static constexpr Date DateAtStartOfYear(Year year)
Calculate the date of the first day of a given year.
static WidgetDimensions scaled
Widget dimensions scaled for current zoom level.
Definition window_gui.h:29
Definition of stuff that is very close to a company, like the company struct itself.
CompanyID _local_company
Company controlled by the human player at this client. Can also be COMPANY_SPECTATOR.
Functions related to companies.
void ShowCompanyFinances(CompanyID company)
Open the finances window of a company.
GUI Functions related to companies.
static constexpr CompanyID COMPANY_SPECTATOR
The client is spectating.
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:923
Dimension GetStringBoundingBox(std::string_view str, FontSize start_fontsize)
Return the string dimension in pixels.
Definition gfx.cpp:852
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:658
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:989
PauseModes _pause_mode
The current pause mode.
Definition gfx.cpp:50
bool FillDrawPixelInfo(DrawPixelInfo *n, int left, int top, int width, int height)
Set up a clipping area for only drawing into a certain area.
Definition gfx.cpp:1519
Functions related to the gfx engine.
int CenterBounds(int min, int max, int size)
Determine where to draw a centred object inside a widget.
Definition gfx_func.h:166
@ FS_NORMAL
Index of the normal font in the font tables.
Definition gfx_type.h:243
@ SA_LEFT
Left align the text.
Definition gfx_type.h:375
@ SA_HOR_CENTER
Horizontally center the text.
Definition gfx_type.h:376
@ SA_FORCE
Force the alignment, i.e. don't swap for RTL languages.
Definition gfx_type.h:387
@ SA_VERT_CENTER
Vertically center the text.
Definition gfx_type.h:381
constexpr NWidgetPart SetMinimalSize(int16_t x, int16_t y)
Widget part function for setting the minimal size.
constexpr NWidgetPart NWidget(WidgetType tp, Colours col, WidgetID idx=-1)
Widget part function for starting a new 'real' widget.
constexpr NWidgetPart SetToolTip(StringID tip)
Widget part function for setting tooltip and clearing the widget data.
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.
Functions related to news.
const NewsItem * GetStatusbarNews()
Get pointer to the current status bar news item.
Definition news_gui.cpp:70
void ShowLastNewsMessage()
Show previous news item.
GUI functions related to the news.
@ LinkGraph
A game paused due to the link graph schedule lagging.
A number of safeguards to prevent using unsafe methods.
bool _do_autosave
are we doing an autosave at the moment?
Definition saveload.cpp:70
Functions/types related to saving and loading games.
GameSettings _settings_game
Game settings of a running game or the scenario editor.
Definition settings.cpp:58
This file contains all sprite-related enums and defines.
void ShowStatusBar()
Show our status bar.
bool IsNewsTickerShown()
Checks whether the news ticker is currently being used.
Functions, definitions and such used only by the GUI.
@ SBI_SHOW_REMINDER
show a reminder (dot on the right side of the statusbar)
@ SBI_SAVELOAD_FINISH
finished saving
@ SBI_SHOW_TICKER
start scrolling news
@ SBI_SAVELOAD_START
started saving
@ SBI_NEWS_DELETED
abort current news display (active news were deleted)
Types related to the statusbar widgets.
@ WID_S_LEFT
Left part of the statusbar; date is shown there.
@ WID_S_MIDDLE
Middle part; current news or company name or *** SAVING *** or *** PAUSED ***.
@ WID_S_RIGHT
Right part; bank balance.
Definition of base types and functions in a cross-platform compatible way.
static void StrMakeValid(T &dst, const char *str, const char *last, StringValidationSettings settings)
Copies the valid (UTF-8) characters from str up to last to the dst.
Definition string.cpp:125
Functions related to low-level strings.
@ SVS_REPLACE_TAB_CR_NL_WITH_SPACE
Replace tabs ('\t'), carriage returns ('\r') and newlines (' ') with spaces.
Definition string_type.h:54
uint64_t GetParamMaxValue(uint64_t max_value, uint min_count, FontSize size)
Get some number that is suitable for string size computations.
Definition strings.cpp:248
std::string GetString(StringID string)
Resolve the given StringID into a std::string with formatting but no parameters.
Definition strings.cpp:426
TextDirection _current_text_dir
Text direction of the currently selected language.
Definition strings.cpp:56
Functions related to OTTD's strings.
uint32_t StringID
Numeric value that represents a string, independent of the selected language.
@ TD_RTL
Text is written right-to-left by default.
Class to backup a specific variable and restore it upon destruction of this object to prevent stack v...
Money money
Money owned by the company.
bool infinite_money
whether spending money despite negative balance is allowed
Dimensions (a width and height) of a rectangle in 2D.
Data about how and where to blit pixels.
Definition gfx_type.h:156
DifficultySettings difficulty
settings related to the difficulty
Partial widget specification to allow NWidgets to be written nested.
Information about a single item of news.
Definition news_type.h:136
Coordinates of a point in 2D.
static Pool::IterateWrapper< Titem > Iterate(size_t from=0)
Returns an iterable ensemble of all valid Titem.
static bool IsValidID(auto index)
Tests whether given index can be used to get valid (non-nullptr) Titem.
static Titem * GetIfValid(auto index)
Returns Titem with given index.
Specification of a rectangle with absolute coordinates of all edges.
Rect Shrink(int s) const
Copy and shrink Rect by s pixels.
void DrawWidget(const Rect &r, WidgetID widget) const override
Draw the contents of a nested widget.
void FindWindowPlacementAndResize(int def_width, int def_height) override
Resize window towards the default size.
void OnClick(Point pt, WidgetID widget, int click_count) override
A click with the left mouse button has been made on the window.
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.
IntervalTimer< TimerWindow > ticker_scroll_interval
Move information on the ticker slowly from one side to the other.
static const int TICKER_STOP
scrolling is finished when counter reaches this value
Point OnInitialPosition(int16_t sm_width, int16_t sm_height, int window_number) override
Compute the initial position of the window.
void OnInvalidateData(int data=0, bool gui_scope=true) override
Some data on this window has become invalid.
static const int COUNTER_STEP
this is subtracted from active counters every tick
static constexpr auto REMINDER_START
time in ms for reminder notification (red dot on the right) to stay
High level window description.
Definition window_gui.h:168
Data structure for an opened window.
Definition window_gui.h:274
void SetWidgetDirty(WidgetID widget_index) const
Invalidate a widget, i.e.
Definition window.cpp:554
ResizeInfo resize
Resize information.
Definition window_gui.h:315
const NWID * GetWidget(WidgetID widnum) const
Get the nested widget with number widnum from the nested widget tree.
Definition window_gui.h:973
void InitNested(WindowNumber number=0)
Perform complete initialization of the Window with nested widgets, to allow use.
Definition window.cpp:1749
WindowFlags flags
Window flags.
Definition window_gui.h:301
virtual void FindWindowPlacementAndResize(int def_width, int def_height)
Resize window towards the default size.
Definition window.cpp:1423
WindowNumber window_number
Window number within the window class.
Definition window_gui.h:303
Functions related to tile highlights.
void ResetObjectToPlace()
Reset the cursor and mouse mode handling back to default (normal cursor, only clicking in windows).
Definition of Interval and OneShot timers.
Definition of the game-calendar-timer.
Definition of the Window system.
uint _toolbar_width
Width of the toolbar, shared by statusbar.
Stuff related to the (main) toolbar.
static RectPadding ScaleGUITrad(const RectPadding &r)
Scale a RectPadding to GUI zoom level.
Definition widget.cpp:48
@ WWT_PUSHBTN
Normal push-button (no toggle button) with custom drawing.
@ NWID_HORIZONTAL
Horizontal container.
Definition widget_type.h:65
@ WWT_PANEL
Simple depressed panel.
Definition widget_type.h:40
int PositionStatusbar(Window *w)
(Re)position statusbar window at the screen.
Definition window.cpp:3406
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:3224
Window * FindWindowById(WindowClass cls, WindowNumber number)
Find a window by its class and window number.
Definition window.cpp:1101
Window functions not directly related to making/drawing windows.
Functions, definitions and such used only by the GUI.
@ NoClose
This window can't be interactively closed.
@ NoFocus
This window won't get focus/make any other window lose focus when click.
@ WhiteBorder
Window white border counter bit mask.
@ WDP_MANUAL
Manually align the window (so no automatic location finding)
Definition window_gui.h:144
int WidgetID
Widget ID.
Definition window_type.h:20
@ WC_STATUS_BAR
Statusbar (at the bottom of your screen); Window numbers:
Definition window_type.h:66
@ WC_NONE
No window, redirects to WC_MAIN_WINDOW.
Definition window_type.h:47
Functions related to zooming.