OpenTTD
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 "date_func.h"
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"
26 #include "core/geometry_func.hpp"
27 #include "guitimer_func.h"
28 #include "zoom_func.h"
29 
31 
32 #include "table/strings.h"
33 #include "table/sprites.h"
34 
35 #include "safeguards.h"
36 
37 static bool DrawScrollingStatusText(const NewsItem *ni, int scroll_pos, int left, int right, int top, int bottom)
38 {
39  CopyInDParam(0, ni->params, lengthof(ni->params));
40  StringID str = ni->string_id;
41 
42  char buf[512];
43  GetString(buf, str, lastof(buf));
44  const char *s = buf;
45 
46  char buffer[256];
47  char *d = buffer;
48  const char *last = lastof(buffer);
49 
50  for (;;) {
51  WChar c = Utf8Consume(&s);
52  if (c == 0) {
53  break;
54  } else if (c == '\n') {
55  if (d + 4 >= last) break;
56  d[0] = d[1] = d[2] = d[3] = ' ';
57  d += 4;
58  } else if (IsPrintable(c)) {
59  if (d + Utf8CharLen(c) >= last) break;
60  d += Utf8Encode(d, c);
61  }
62  }
63  *d = '\0';
64 
65  DrawPixelInfo tmp_dpi;
66  if (!FillDrawPixelInfo(&tmp_dpi, left, top, right - left, bottom)) return true;
67 
68  int width = GetStringBoundingBox(buffer).width;
69  int pos = (_current_text_dir == TD_RTL) ? (scroll_pos - width) : (right - scroll_pos - left);
70 
71  DrawPixelInfo *old_dpi = _cur_dpi;
72  _cur_dpi = &tmp_dpi;
73  DrawString(pos, INT16_MAX, 0, buffer, TC_LIGHT_BLUE, SA_LEFT | SA_FORCE);
74  _cur_dpi = old_dpi;
75 
76  return (_current_text_dir == TD_RTL) ? (pos < right - left) : (pos + width > 0);
77 }
78 
80  bool saving;
81  int ticker_scroll;
82  GUITimer ticker_timer;
83  GUITimer reminder_timeout;
84 
85  static const int TICKER_STOP = 1640;
86  static const int REMINDER_START = 1350;
87  static const int REMINDER_STOP = 0;
88  static const int COUNTER_STEP = 2;
89 
90  StatusBarWindow(WindowDesc *desc) : Window(desc)
91  {
92  this->ticker_scroll = TICKER_STOP;
93  this->ticker_timer.SetInterval(15);
94  this->reminder_timeout.SetInterval(REMINDER_STOP);
95 
96  this->InitNested();
98  PositionStatusbar(this);
99  }
100 
101  Point OnInitialPosition(int16 sm_width, int16 sm_height, int window_number) override
102  {
103  Point pt = { 0, _screen.height - sm_height };
104  return pt;
105  }
106 
107  void FindWindowPlacementAndResize(int def_width, int def_height) override
108  {
110  }
111 
112  void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) override
113  {
114  Dimension d;
115  switch (widget) {
116  case WID_S_LEFT:
118  d = GetStringBoundingBox(STR_WHITE_DATE_LONG);
119  break;
120 
121  case WID_S_RIGHT: {
122  int64 max_money = UINT32_MAX;
123  for (const Company *c : Company::Iterate()) max_money = max<int64>(c->money, max_money);
124  SetDParam(0, 100LL * max_money);
125  d = GetStringBoundingBox(STR_COMPANY_MONEY);
126  break;
127  }
128 
129  default:
130  return;
131  }
132 
133  d.width += padding.width;
134  d.height += padding.height;
135  *size = maxdim(d, *size);
136  }
137 
138  void DrawWidget(const Rect &r, int widget) const override
139  {
140  switch (widget) {
141  case WID_S_LEFT:
142  /* Draw the date */
143  SetDParam(0, _date);
144  DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, r.top + WD_FRAMERECT_TOP, STR_WHITE_DATE_LONG, TC_FROMSTRING, SA_HOR_CENTER);
145  break;
146 
147  case WID_S_RIGHT: {
148  /* Draw company money, if any */
150  if (c != nullptr) {
151  SetDParam(0, c->money);
152  DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, r.top + WD_FRAMERECT_TOP, STR_COMPANY_MONEY, TC_FROMSTRING, SA_HOR_CENTER);
153  }
154  break;
155  }
156 
157  case WID_S_MIDDLE:
158  /* Draw status bar */
159  if (this->saving) { // true when saving is active
160  DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, r.top + WD_FRAMERECT_TOP, STR_STATUSBAR_SAVING_GAME, TC_FROMSTRING, SA_HOR_CENTER);
161  } else if (_do_autosave) {
162  DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, r.top + WD_FRAMERECT_TOP, STR_STATUSBAR_AUTOSAVE, TC_FROMSTRING, SA_HOR_CENTER);
163  } else if (_pause_mode != PM_UNPAUSED) {
164  DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, r.top + WD_FRAMERECT_TOP, STR_STATUSBAR_PAUSED, TC_FROMSTRING, SA_HOR_CENTER);
165  } else if (this->ticker_scroll < TICKER_STOP && _statusbar_news_item != nullptr && _statusbar_news_item->string_id != 0) {
166  /* Draw the scrolling news text */
167  if (!DrawScrollingStatusText(_statusbar_news_item, ScaleGUITrad(this->ticker_scroll), r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, r.top + WD_FRAMERECT_TOP, r.bottom)) {
170  /* This is the default text */
172  DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, r.top + WD_FRAMERECT_TOP, STR_STATUSBAR_COMPANY_NAME, TC_FROMSTRING, SA_HOR_CENTER);
173  }
174  }
175  } else {
177  /* This is the default text */
179  DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, r.top + WD_FRAMERECT_TOP, STR_STATUSBAR_COMPANY_NAME, TC_FROMSTRING, SA_HOR_CENTER);
180  }
181  }
182 
183  if (!this->reminder_timeout.HasElapsed()) {
184  Dimension icon_size = GetSpriteSize(SPR_UNREAD_NEWS);
185  DrawSprite(SPR_UNREAD_NEWS, PAL_NONE, r.right - WD_FRAMERECT_RIGHT - icon_size.width, r.top + WD_FRAMERECT_TOP + (int)(FONT_HEIGHT_NORMAL - icon_size.height) / 2);
186  }
187  break;
188  }
189  }
190 
196  void OnInvalidateData(int data = 0, bool gui_scope = true) override
197  {
198  if (!gui_scope) return;
199  switch (data) {
200  default: NOT_REACHED();
201  case SBI_SAVELOAD_START: this->saving = true; break;
202  case SBI_SAVELOAD_FINISH: this->saving = false; break;
203  case SBI_SHOW_TICKER: this->ticker_scroll = 0; break;
204  case SBI_SHOW_REMINDER: this->reminder_timeout.SetInterval(REMINDER_START); break;
205  case SBI_NEWS_DELETED:
206  this->ticker_scroll = TICKER_STOP; // reset ticker ...
207  this->reminder_timeout.SetInterval(REMINDER_STOP); // ... and reminder
208  break;
209  }
210  }
211 
212  void OnClick(Point pt, int widget, int click_count) override
213  {
214  switch (widget) {
215  case WID_S_MIDDLE: ShowLastNewsMessage(); break;
217  default: ResetObjectToPlace();
218  }
219  }
220 
221  void OnRealtimeTick(uint delta_ms) override
222  {
223  if (_pause_mode != PM_UNPAUSED) return;
224 
225  if (this->ticker_scroll < TICKER_STOP) { // Scrolling text
226  uint count = this->ticker_timer.CountElapsed(delta_ms);
227  if (count > 0) {
228  this->ticker_scroll += count;
230  }
231  }
232 
233  // Red blot to show there are new unread newsmessages
234  if (this->reminder_timeout.Elapsed(delta_ms)) {
236  }
237  }
238 };
239 
240 static const NWidgetPart _nested_main_status_widgets[] = {
242  NWidget(WWT_PANEL, COLOUR_GREY, WID_S_LEFT), SetMinimalSize(140, 12), EndContainer(),
243  NWidget(WWT_PUSHBTN, COLOUR_GREY, WID_S_MIDDLE), SetMinimalSize(40, 12), SetDataTip(0x0, STR_STATUSBAR_TOOLTIP_SHOW_LAST_NEWS), SetResize(1, 0),
244  NWidget(WWT_PUSHBTN, COLOUR_GREY, WID_S_RIGHT), SetMinimalSize(140, 12),
245  EndContainer(),
246 };
247 
248 static WindowDesc _main_status_desc(
249  WDP_MANUAL, nullptr, 0, 0,
251  WDF_NO_FOCUS,
252  _nested_main_status_widgets, lengthof(_nested_main_status_widgets)
253 );
254 
259 {
260  const StatusBarWindow *w = dynamic_cast<StatusBarWindow*>(FindWindowById(WC_STATUS_BAR, 0));
261  return w != nullptr && w->ticker_scroll < StatusBarWindow::TICKER_STOP;
262 }
263 
268 {
269  new StatusBarWindow(&_main_status_desc);
270 }
Functions related to OTTD&#39;s strings.
start scrolling news
Definition: statusbar_gui.h:17
Definition of stuff that is very close to a company, like the company struct itself.
static Titem * GetIfValid(size_t index)
Returns Titem with given index.
Definition: pool_type.hpp:302
static const int DAYS_IN_YEAR
days per year
Definition: date_type.h:29
Data about how and where to blit pixels.
Definition: gfx_type.h:154
Horizontally center the text.
Definition: gfx_func.h:95
ResizeInfo resize
Resize information.
Definition: window_gui.h:322
static NWidgetPart SetResize(int16 dx, int16 dy)
Widget part function for setting the resize step.
Definition: widget_type.h:928
static const int REMINDER_START
time in ms for reminder notification (red dot on the right) to stay
High level window description.
Definition: window_gui.h:166
uint CountElapsed(uint delta)
Count how many times the interval has elapsed.
Definition: guitimer_func.h:40
Middle part; current news or company name or *** SAVING *** or *** PAUSED ***.
WindowFlags flags
Window flags.
Definition: window_gui.h:310
void FindWindowPlacementAndResize(int def_width, int def_height) override
Resize window towards the default size.
Functions related to dates.
void SetWidgetDirty(byte widget_index) const
Invalidate a widget, i.e.
Definition: window.cpp:597
Offset at top to draw the frame rectangular area.
Definition: window_gui.h:62
Types related to the statusbar widgets.
Horizontal container.
Definition: widget_type.h:73
Window * FindWindowById(WindowClass cls, WindowNumber number)
Find a window by its class and window number.
Definition: window.cpp:1130
bool Elapsed(uint delta)
Test if a timer has elapsed.
Definition: guitimer_func.h:55
Left part of the statusbar; date is shown there.
static int ScaleGUITrad(int value)
Scale traditional pixel dimensions to GUI zoom level.
Definition: zoom_func.h:76
void CopyInDParam(int offs, const uint64 *src, int num)
Copy num string parameters from array src into the global string parameter array. ...
Definition: strings.cpp:138
Normal push-button (no toggle button) with custom drawing.
Definition: widget_type.h:101
uint64 params[10]
Parameters for string resolving.
Definition: news_type.h:139
void DrawWidget(const Rect &r, int widget) const override
Draw the contents of a nested widget.
#define lastof(x)
Get the last element of an fixed size array.
Definition: depend.cpp:48
#define CLRBITS(x, y)
Clears several bits in a variable.
Right part; bank balance.
Functions, definitions and such used only by the GUI.
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:1481
Force the alignment, i.e. don&#39;t swap for RTL languages.
Definition: gfx_func.h:106
Partial widget specification to allow NWidgets to be written nested.
Definition: widget_type.h:908
Data structure for an opened window.
Definition: window_gui.h:276
void InitNested(WindowNumber number=0)
Perform complete initialization of the Window with nested widgets, to allow use.
Definition: window.cpp:1857
int PositionStatusbar(Window *w)
(Re)position statusbar window at the screen.
Definition: window.cpp:3513
Functions related to low-level strings.
Functions/types related to saving and loading games.
StringID string_id
Message text.
Definition: news_type.h:122
GUI Timers.
A normal unpaused game.
Definition: openttd.h:56
The client is spectating.
Definition: company_type.h:35
GUI functions related to the news.
#define FONT_HEIGHT_NORMAL
Height of characters in the normal (FS_NORMAL) font.
Definition: gfx_func.h:176
static NWidgetPart SetDataTip(uint32 data, StringID tip)
Widget part function for setting the data and tooltip.
Definition: widget_type.h:1012
Functions related to the gfx engine.
abort current news display (active news were deleted)
Definition: statusbar_gui.h:19
static const int COUNTER_STEP
this is subtracted from active counters every tick
static NWidgetPart SetMinimalSize(int16 x, int16 y)
Widget part function for setting the minimal size.
Definition: widget_type.h:945
void OnRealtimeTick(uint delta_ms) override
Called periodically.
Definition of base types and functions in a cross-platform compatible way.
A number of safeguards to prevent using unsafe methods.
Geometry functions.
Simple depressed panel.
Definition: widget_type.h:48
show a reminder (dot on the right side of the statusbar)
Definition: statusbar_gui.h:18
void OnClick(Point pt, int widget, int click_count) override
A click with the left mouse button has been made on the window.
GUI Functions related to companies.
static int8 Utf8CharLen(WChar c)
Return the length of a UTF-8 encoded character.
Definition: string_func.h:97
void ShowLastNewsMessage()
Show previous news item.
Definition: news_gui.cpp:1026
static NWidgetPart NWidget(WidgetType tp, Colours col, int16 idx=-1)
Widget part function for starting a new &#39;real&#39; widget.
Definition: widget_type.h:1112
Money money
Money owned by the company.
Definition: company_base.h:65
int DrawString(int left, int right, int top, const char *str, TextColour colour, StringAlignment align, bool underline, FontSize fontsize)
Draw string, possibly truncated to make it fit in its allocated space.
Definition: gfx.cpp:498
#define lengthof(x)
Return the length of an fixed size array.
Definition: depend.cpp:40
PauseMode _pause_mode
The current pause mode.
Definition: gfx.cpp:47
uint32 StringID
Numeric value that represents a string, independent of the selected language.
Definition: strings_type.h:16
void OnInvalidateData(int data=0, bool gui_scope=true) override
Some data on this window has become invalid.
Dimension GetStringBoundingBox(const char *str, FontSize start_fontsize)
Return the string dimension in pixels.
Definition: gfx.cpp:700
Dimension maxdim(const Dimension &d1, const Dimension &d2)
Compute bounding box of both dimensions.
No window, redirects to WC_MAIN_WINDOW.
Definition: window_type.h:38
Functions related to companies.
static Pool::IterateWrapper< Titem > Iterate(size_t from=0)
Returns an iterable ensemble of all valid Titem.
Definition: pool_type.hpp:340
uint _toolbar_width
Width of the toolbar, shared by statusbar.
Definition: toolbar_gui.cpp:62
Point OnInitialPosition(int16 sm_width, int16 sm_height, int window_number) override
Compute the initial position of the window.
TextDirection _current_text_dir
Text direction of the currently selected language.
Definition: strings.cpp:48
This window won&#39;t get focus/make any other window lose focus when click.
Definition: window_gui.h:210
void SetDParamMaxValue(uint n, uint64 max_value, uint min_count, FontSize size)
Set DParam n to some number that is suitable for string size computations.
Definition: strings.cpp:104
static NWidgetPart EndContainer()
Widget part function for denoting the end of a container (horizontal, vertical, WWT_FRAME, WWT_INSET, or WWT_PANEL).
Definition: widget_type.h:997
Functions related to zooming.
Statusbar (at the bottom of your screen); Window numbers:
Definition: window_type.h:57
Coordinates of a point in 2D.
Dimension GetSpriteSize(SpriteID sprid, Point *offset, ZoomLevel zoom)
Get the size of a sprite.
Definition: gfx.cpp:770
void ShowCompanyFinances(CompanyID company)
Open the finances window of a company.
static bool IsValidID(size_t index)
Tests whether given index can be used to get valid (non-nullptr) Titem.
Definition: pool_type.hpp:280
bool IsNewsTickerShown()
Checks whether the news ticker is currently being used.
static const int REMINDER_STOP
reminder disappears when counter reaches this value
size_t Utf8Encode(char *buf, WChar c)
Encode a unicode character and place it in the buffer.
Definition: string.cpp:486
virtual void FindWindowPlacementAndResize(int def_width, int def_height)
Resize window towards the default size.
Definition: window.cpp:1522
Offset at right to draw the frame rectangular area.
Definition: window_gui.h:61
void ShowStatusBar()
Show our status bar.
void ResetObjectToPlace()
Reset the cursor and mouse mode handling back to default (normal cursor, only clicking in windows)...
Definition: viewport.cpp:3353
Specification of a rectangle with absolute coordinates of all edges.
Text is written right-to-left by default.
Definition: strings_type.h:24
WindowNumber window_number
Window number within the window class.
Definition: window_gui.h:312
Left align the text.
Definition: gfx_func.h:94
Functions related to tile highlights.
Window functions not directly related to making/drawing windows.
finished saving
Definition: statusbar_gui.h:16
Manually align the window (so no automatic location finding)
Definition: window_gui.h:153
Functions related to news.
Functions, definitions and such used only by the GUI.
Date _date
Current date in days (day counter)
Definition: date.cpp:26
uint32 WChar
Type for wide characters, i.e.
Definition: string_type.h:35
started saving
Definition: statusbar_gui.h:15
Window white border counter bit mask.
Definition: window_gui.h:240
CompanyID _local_company
Company controlled by the human player at this client. Can also be COMPANY_SPECTATOR.
Definition: company_cmd.cpp:44
Dimensions (a width and height) of a rectangle in 2D.
Offset at left to draw the frame rectangular area.
Definition: window_gui.h:60
static const Year MAX_YEAR
MAX_YEAR, nicely rounded value of the number of years that can be encoded in a single 32 bits date...
Definition: date_type.h:92
bool _do_autosave
are we doing an autosave at the moment?
Definition: saveload.cpp:64
This file contains all sprite-related enums and defines.
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:835
void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) override
Update size and resize step of a widget in the window.
Information about a single item of news.
Definition: news_type.h:119
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:3316
static const int TICKER_STOP
scrolling is finished when counter reaches this value
Stuff related to the (main) toolbar.
static void SetDParam(uint n, uint64 v)
Set a string parameter v at index n in the global string parameter array.
Definition: strings_func.h:199