OpenTTD
statusbar_gui.cpp
Go to the documentation of this file.
1 /* $Id$ */
2 
3 /*
4  * This file is part of OpenTTD.
5  * 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.
6  * 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.
7  * 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/>.
8  */
9 
12 #include "stdafx.h"
13 #include "date_func.h"
14 #include "gfx_func.h"
15 #include "news_func.h"
16 #include "company_func.h"
17 #include "string_func.h"
18 #include "strings_func.h"
19 #include "company_base.h"
20 #include "tilehighlight_func.h"
21 #include "news_gui.h"
22 #include "company_gui.h"
23 #include "window_gui.h"
24 #include "saveload/saveload.h"
25 #include "window_func.h"
26 #include "statusbar_gui.h"
27 #include "toolbar_gui.h"
28 #include "core/geometry_func.hpp"
29 #include "guitimer_func.h"
30 #include "zoom_func.h"
31 
33 
34 #include "table/strings.h"
35 #include "table/sprites.h"
36 
37 #include "safeguards.h"
38 
39 static bool DrawScrollingStatusText(const NewsItem *ni, int scroll_pos, int left, int right, int top, int bottom)
40 {
41  CopyInDParam(0, ni->params, lengthof(ni->params));
42  StringID str = ni->string_id;
43 
44  char buf[512];
45  GetString(buf, str, lastof(buf));
46  const char *s = buf;
47 
48  char buffer[256];
49  char *d = buffer;
50  const char *last = lastof(buffer);
51 
52  for (;;) {
53  WChar c = Utf8Consume(&s);
54  if (c == 0) {
55  break;
56  } else if (c == '\n') {
57  if (d + 4 >= last) break;
58  d[0] = d[1] = d[2] = d[3] = ' ';
59  d += 4;
60  } else if (IsPrintable(c)) {
61  if (d + Utf8CharLen(c) >= last) break;
62  d += Utf8Encode(d, c);
63  }
64  }
65  *d = '\0';
66 
67  DrawPixelInfo tmp_dpi;
68  if (!FillDrawPixelInfo(&tmp_dpi, left, top, right - left, bottom)) return true;
69 
70  int width = GetStringBoundingBox(buffer).width;
71  int pos = (_current_text_dir == TD_RTL) ? (scroll_pos - width) : (right - scroll_pos - left);
72 
73  DrawPixelInfo *old_dpi = _cur_dpi;
74  _cur_dpi = &tmp_dpi;
75  DrawString(pos, INT16_MAX, 0, buffer, TC_LIGHT_BLUE, SA_LEFT | SA_FORCE);
76  _cur_dpi = old_dpi;
77 
78  return (_current_text_dir == TD_RTL) ? (pos < right - left) : (pos + width > 0);
79 }
80 
82  bool saving;
83  int ticker_scroll;
84  GUITimer ticker_timer;
85  GUITimer reminder_timeout;
86 
87  static const int TICKER_STOP = 1640;
88  static const int REMINDER_START = 1350;
89  static const int REMINDER_STOP = 0;
90  static const int COUNTER_STEP = 2;
91 
92  StatusBarWindow(WindowDesc *desc) : Window(desc)
93  {
94  this->ticker_scroll = TICKER_STOP;
95  this->ticker_timer.SetInterval(15);
96  this->reminder_timeout.SetInterval(REMINDER_STOP);
97 
98  this->InitNested();
100  PositionStatusbar(this);
101  }
102 
103  virtual Point OnInitialPosition(int16 sm_width, int16 sm_height, int window_number)
104  {
105  Point pt = { 0, _screen.height - sm_height };
106  return pt;
107  }
108 
109  virtual void FindWindowPlacementAndResize(int def_width, int def_height)
110  {
112  }
113 
114  virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize)
115  {
116  Dimension d;
117  switch (widget) {
118  case WID_S_LEFT:
120  d = GetStringBoundingBox(STR_WHITE_DATE_LONG);
121  break;
122 
123  case WID_S_RIGHT: {
124  int64 max_money = UINT32_MAX;
125  const Company *c;
126  FOR_ALL_COMPANIES(c) max_money = max<int64>(c->money, max_money);
127  SetDParam(0, 100LL * max_money);
128  d = GetStringBoundingBox(STR_COMPANY_MONEY);
129  break;
130  }
131 
132  default:
133  return;
134  }
135 
136  d.width += padding.width;
137  d.height += padding.height;
138  *size = maxdim(d, *size);
139  }
140 
141  virtual void DrawWidget(const Rect &r, int widget) const
142  {
143  switch (widget) {
144  case WID_S_LEFT:
145  /* Draw the date */
146  SetDParam(0, _date);
147  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);
148  break;
149 
150  case WID_S_RIGHT: {
151  /* Draw company money, if any */
153  if (c != NULL) {
154  SetDParam(0, c->money);
155  DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, r.top + WD_FRAMERECT_TOP, STR_COMPANY_MONEY, TC_FROMSTRING, SA_HOR_CENTER);
156  }
157  break;
158  }
159 
160  case WID_S_MIDDLE:
161  /* Draw status bar */
162  if (this->saving) { // true when saving is active
163  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);
164  } else if (_do_autosave) {
165  DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, r.top + WD_FRAMERECT_TOP, STR_STATUSBAR_AUTOSAVE, TC_FROMSTRING, SA_HOR_CENTER);
166  } else if (_pause_mode != PM_UNPAUSED) {
167  DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, r.top + WD_FRAMERECT_TOP, STR_STATUSBAR_PAUSED, TC_FROMSTRING, SA_HOR_CENTER);
168  } else if (this->ticker_scroll < TICKER_STOP && FindWindowById(WC_NEWS_WINDOW, 0) == NULL && _statusbar_news_item != NULL && _statusbar_news_item->string_id != 0) {
169  /* Draw the scrolling news text */
170  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)) {
173  /* This is the default text */
175  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);
176  }
177  }
178  } else {
180  /* This is the default text */
182  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);
183  }
184  }
185 
186  if (!this->reminder_timeout.HasElapsed()) {
187  Dimension icon_size = GetSpriteSize(SPR_UNREAD_NEWS);
188  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);
189  }
190  break;
191  }
192  }
193 
199  virtual void OnInvalidateData(int data = 0, bool gui_scope = true)
200  {
201  if (!gui_scope) return;
202  switch (data) {
203  default: NOT_REACHED();
204  case SBI_SAVELOAD_START: this->saving = true; break;
205  case SBI_SAVELOAD_FINISH: this->saving = false; break;
206  case SBI_SHOW_TICKER: this->ticker_scroll = 0; break;
207  case SBI_SHOW_REMINDER: this->reminder_timeout.SetInterval(REMINDER_START); break;
208  case SBI_NEWS_DELETED:
209  this->ticker_scroll = TICKER_STOP; // reset ticker ...
210  this->reminder_timeout.SetInterval(REMINDER_STOP); // ... and reminder
211  break;
212  }
213  }
214 
215  virtual void OnClick(Point pt, int widget, int click_count)
216  {
217  switch (widget) {
218  case WID_S_MIDDLE: ShowLastNewsMessage(); break;
220  default: ResetObjectToPlace();
221  }
222  }
223 
224  virtual void OnRealtimeTick(uint delta_ms)
225  {
226  if (_pause_mode != PM_UNPAUSED) return;
227 
228  if (this->ticker_scroll < TICKER_STOP) { // Scrolling text
229  uint count = this->ticker_timer.CountElapsed(delta_ms);
230  if (count > 0) {
231  this->ticker_scroll += count;
233  }
234  }
235 
236  // Red blot to show there are new unread newsmessages
237  if (this->reminder_timeout.Elapsed(delta_ms)) {
239  }
240  }
241 };
242 
243 static const NWidgetPart _nested_main_status_widgets[] = {
245  NWidget(WWT_PANEL, COLOUR_GREY, WID_S_LEFT), SetMinimalSize(140, 12), EndContainer(),
246  NWidget(WWT_PUSHBTN, COLOUR_GREY, WID_S_MIDDLE), SetMinimalSize(40, 12), SetDataTip(0x0, STR_STATUSBAR_TOOLTIP_SHOW_LAST_NEWS), SetResize(1, 0),
247  NWidget(WWT_PUSHBTN, COLOUR_GREY, WID_S_RIGHT), SetMinimalSize(140, 12),
248  EndContainer(),
249 };
250 
251 static WindowDesc _main_status_desc(
252  WDP_MANUAL, NULL, 0, 0,
254  WDF_NO_FOCUS,
255  _nested_main_status_widgets, lengthof(_nested_main_status_widgets)
256 );
257 
262 {
263  const StatusBarWindow *w = dynamic_cast<StatusBarWindow*>(FindWindowById(WC_STATUS_BAR, 0));
264  return w != NULL && w->ticker_scroll < StatusBarWindow::TICKER_STOP;
265 }
266 
271 {
272  new StatusBarWindow(&_main_status_desc);
273 }
Functions related to OTTD&#39;s strings.
virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize)
Update size and resize step of a widget in the window.
start scrolling news
Definition: statusbar_gui.h:19
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:257
static const int DAYS_IN_YEAR
days per year
Definition: date_type.h:31
Data about how and where to blit pixels.
Definition: gfx_type.h:156
Horizontally center the text.
Definition: gfx_func.h:99
ResizeInfo resize
Resize information.
Definition: window_gui.h:324
static NWidgetPart SetResize(int16 dx, int16 dy)
Widget part function for setting the resize step.
Definition: widget_type.h:930
A normal unpaused game.
Definition: openttd.h:58
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:168
uint CountElapsed(uint delta)
Count how many times the interval has elapsed.
Definition: guitimer_func.h:42
Middle part; current news or company name or *** SAVING *** or *** PAUSED ***.
WindowFlags flags
Window flags.
Definition: window_gui.h:312
Functions related to dates.
void SetWidgetDirty(byte widget_index) const
Invalidate a widget, i.e.
Definition: window.cpp:581
Offset at top to draw the frame rectangular area.
Definition: window_gui.h:64
Types related to the statusbar widgets.
Horizontal container.
Definition: widget_type.h:75
Window * FindWindowById(WindowClass cls, WindowNumber number)
Find a window by its class and window number.
Definition: window.cpp:1114
bool Elapsed(uint delta)
Test if a timer has elapsed.
Definition: guitimer_func.h:57
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:82
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:141
Normal push-button (no toggle button) with custom drawing.
Definition: widget_type.h:103
uint64 params[10]
Parameters for string resolving.
Definition: news_type.h:141
#define lastof(x)
Get the last element of an fixed size array.
Definition: depend.cpp:50
The client is spectating.
Definition: company_type.h:37
virtual void OnInvalidateData(int data=0, bool gui_scope=true)
Some data on this window has become invalid.
#define CLRBITS(x, y)
Clears several bits in a variable.
Right part; bank balance.
virtual void OnClick(Point pt, int widget, int click_count)
A click with the left mouse button has been made on the window.
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:1482
CompanyByte _local_company
Company controlled by the human player at this client. Can also be COMPANY_SPECTATOR.
Definition: company_cmd.cpp:46
Force the alignment, i.e. don&#39;t swap for RTL languages.
Definition: gfx_func.h:110
Partial widget specification to allow NWidgets to be written nested.
Definition: widget_type.h:910
Data structure for an opened window.
Definition: window_gui.h:278
void InitNested(WindowNumber number=0)
Perform complete initialization of the Window with nested widgets, to allow use.
Definition: window.cpp:1841
int PositionStatusbar(Window *w)
(Re)position statusbar window at the screen.
Definition: window.cpp:3499
virtual void FindWindowPlacementAndResize(int def_width, int def_height)
Resize window towards the default size.
Functions related to low-level strings.
Functions/types related to saving and loading games.
StringID string_id
Message text.
Definition: news_type.h:124
GUI Timers.
GUI functions related to the news.
#define FONT_HEIGHT_NORMAL
Height of characters in the normal (FS_NORMAL) font.
Definition: gfx_func.h:180
static NWidgetPart SetDataTip(uint32 data, StringID tip)
Widget part function for setting the data and tooltip.
Definition: widget_type.h:1014
Functions related to the gfx engine.
abort current news display (active news were deleted)
Definition: statusbar_gui.h:21
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:947
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:50
show a reminder (dot on the right side of the statusbar)
Definition: statusbar_gui.h:20
GUI Functions related to companies.
static int8 Utf8CharLen(WChar c)
Return the length of a UTF-8 encoded character.
Definition: string_func.h:99
void ShowLastNewsMessage()
Show previous news item.
Definition: news_gui.cpp:930
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:1114
Money money
Money owned by the company.
Definition: company_base.h:64
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:500
#define lengthof(x)
Return the length of an fixed size array.
Definition: depend.cpp:42
PauseModeByte _pause_mode
The current pause mode.
Definition: gfx.cpp:48
uint32 StringID
Numeric value that represents a string, independent of the selected language.
Definition: strings_type.h:18
Dimension GetStringBoundingBox(const char *str, FontSize start_fontsize)
Return the string dimension in pixels.
Definition: gfx.cpp:700
virtual void DrawWidget(const Rect &r, int widget) const
Draw the contents of a nested widget.
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:40
Functions related to companies.
uint _toolbar_width
Width of the toolbar, shared by statusbar.
Definition: toolbar_gui.cpp:63
TextDirection _current_text_dir
Text direction of the currently selected language.
Definition: strings.cpp:52
This window won&#39;t get focus/make any other window lose focus when click.
Definition: window_gui.h:212
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:108
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:999
Functions related to zooming.
Statusbar (at the bottom of your screen); Window numbers:
Definition: window_type.h:59
virtual void OnRealtimeTick(uint delta_ms)
Called periodically.
Coordinates of a point in 2D.
Dimension GetSpriteSize(SpriteID sprid, Point *offset, ZoomLevel zoom)
Get the size of a sprite.
Definition: gfx.cpp:769
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-NULL) Titem.
Definition: pool_type.hpp:235
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:488
virtual void FindWindowPlacementAndResize(int def_width, int def_height)
Resize window towards the default size.
Definition: window.cpp:1506
Offset at right to draw the frame rectangular area.
Definition: window_gui.h:63
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:3088
Specification of a rectangle with absolute coordinates of all edges.
Text is written right-to-left by default.
Definition: strings_type.h:26
WindowNumber window_number
Window number within the window class.
Definition: window_gui.h:314
Left align the text.
Definition: gfx_func.h:98
Functions related to tile highlights.
Window functions not directly related to making/drawing windows.
finished saving
Definition: statusbar_gui.h:18
Manually align the window (so no automatic location finding)
Definition: window_gui.h:155
Functions related to news.
Functions, definitions and such used only by the GUI.
virtual Point OnInitialPosition(int16 sm_width, int16 sm_height, int window_number)
Compute the initial position of the window.
Date _date
Current date in days (day counter)
Definition: date.cpp:28
uint32 WChar
Type for wide characters, i.e.
Definition: string_type.h:35
started saving
Definition: statusbar_gui.h:17
Window white border counter bit mask.
Definition: window_gui.h:242
Dimensions (a width and height) of a rectangle in 2D.
Offset at left to draw the frame rectangular area.
Definition: window_gui.h:62
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:94
bool _do_autosave
are we doing an autosave at the moment?
Definition: saveload.cpp:65
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:834
Information about a single item of news.
Definition: news_type.h:121
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:3301
News window; Window numbers:
Definition: window_type.h:243
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:201