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
8 /** @file widget_type.h Definitions about widgets. */
9
10 #ifndef WIDGET_TYPE_H
11 #define WIDGET_TYPE_H
12
13 #include "core/alloc_type.hpp"
14 #include "core/bitmath_func.hpp"
15 #include "core/math_func.hpp"
16 #include "strings_type.h"
17 #include "gfx_type.h"
18 #include "window_type.h"
19
20 static const int WIDGET_LIST_END = -1; ///< indicate the end of widgets' list for vararg functions
21
22 /** Bits of the #WWT_MATRIX widget data. */
23 enum MatrixWidgetValues {
24 /* Number of column bits of the WWT_MATRIX widget data. */
25 MAT_COL_START = 0, ///< Lowest bit of the number of columns.
26 MAT_COL_BITS = 8, ///< Number of bits for the number of columns in the matrix.
27
28 /* Number of row bits of the WWT_MATRIX widget data. */
29 MAT_ROW_START = 8, ///< Lowest bit of the number of rows.
30 MAT_ROW_BITS = 8, ///< Number of bits for the number of rows in the matrix.
31 };
32
33 /** Values for an arrow widget */
34 enum ArrowWidgetValues {
35 AWV_DECREASE, ///< Arrow to the left or in case of RTL to the right
36 AWV_INCREASE, ///< Arrow to the right or in case of RTL to the left
37 AWV_LEFT, ///< Force the arrow to the left
38 AWV_RIGHT, ///< Force the arrow to the right
39 };
40
41 /**
42 * Window widget types, nested widget types, and nested widget part types.
43 */
44 enum WidgetType {
45 /* Window widget types. */
46 WWT_EMPTY, ///< Empty widget, place holder to reserve space in widget array
47
48 WWT_PANEL, ///< Simple depressed panel
49 WWT_INSET, ///< Pressed (inset) panel, most commonly used as combo box _text_ area
50 WWT_IMGBTN, ///< (Toggle) Button with image
51 WWT_IMGBTN_2, ///< (Toggle) Button with diff image when clicked
52 WWT_ARROWBTN, ///< (Toggle) Button with an arrow
53 WWT_TEXTBTN, ///< (Toggle) Button with text
54 WWT_TEXTBTN_2, ///< (Toggle) Button with diff text when clicked
55 WWT_LABEL, ///< Centered label
56 WWT_TEXT, ///< Pure simple text
57 WWT_MATRIX, ///< Grid of rows and columns. @see MatrixWidgetValues
58 WWT_FRAME, ///< Frame
59 WWT_CAPTION, ///< Window caption (window title between closebox and stickybox)
60
61 WWT_DEBUGBOX, ///< NewGRF debug box (at top-right of a window, between WWT_CAPTION and WWT_SHADEBOX)
62 WWT_SHADEBOX, ///< Shade box (at top-right of a window, between WWT_DEBUGBOX and WWT_DEFSIZEBOX)
63 WWT_DEFSIZEBOX, ///< Default window size box (at top-right of a window, between WWT_SHADEBOX and WWT_STICKYBOX)
64 WWT_STICKYBOX, ///< Sticky box (at top-right of a window, after WWT_DEFSIZEBOX)
65
66 WWT_RESIZEBOX, ///< Resize box (normally at bottom-right of a window)
67 WWT_CLOSEBOX, ///< Close box (at top-left of a window)
68 WWT_DROPDOWN, ///< Drop down list
69 WWT_EDITBOX, ///< a textbox for typing
70 WWT_LAST, ///< Last Item. use WIDGETS_END to fill up padding!!
71
72 /* Nested widget types. */
73 NWID_HORIZONTAL, ///< Horizontal container.
74 NWID_HORIZONTAL_LTR, ///< Horizontal container that doesn't change the order of the widgets for RTL languages.
75 NWID_VERTICAL, ///< Vertical container.
76 NWID_MATRIX, ///< Matrix container.
77 NWID_SPACER, ///< Invisible widget that takes some space.
78 NWID_SELECTION, ///< Stacked widgets, only one visible at a time (eg in a panel with tabs).
79 NWID_VIEWPORT, ///< Nested widget containing a viewport.
80 NWID_BUTTON_DROPDOWN, ///< Button with a drop-down.
81 NWID_HSCROLLBAR, ///< Horizontal scrollbar
82 NWID_VSCROLLBAR, ///< Vertical scrollbar
83
84 /* Nested widget part types. */
85 WPT_RESIZE, ///< Widget part for specifying resizing.
86 WPT_MINSIZE, ///< Widget part for specifying minimal size.
87 WPT_MINTEXTLINES, ///< Widget part for specifying minimal number of lines of text.
88 WPT_FILL, ///< Widget part for specifying fill.
89 WPT_DATATIP, ///< Widget part for specifying data and tooltip.
90 WPT_PADDING, ///< Widget part for specifying a padding.
91 WPT_PIPSPACE, ///< Widget part for specifying pre/inter/post space for containers.
92 WPT_TEXTCOLOUR, ///< Widget part for specifying text colour.
93 WPT_ALIGNMENT, ///< Widget part for specifying text/image alignment.
94 WPT_ENDCONTAINER, ///< Widget part to denote end of a container.
95 WPT_FUNCTION, ///< Widget part for calling a user function.
96 WPT_SCROLLBAR, ///< Widget part for attaching a scrollbar.
97
98 /* Pushable window widget types. */
99 WWT_MASK = 0x7F,
100
101 WWB_PUSHBUTTON = 1 << 7,
102
103 WWT_PUSHBTN = WWT_PANEL | WWB_PUSHBUTTON, ///< Normal push-button (no toggle button) with custom drawing
104 WWT_PUSHTXTBTN = WWT_TEXTBTN | WWB_PUSHBUTTON, ///< Normal push-button (no toggle button) with text caption
105 WWT_PUSHIMGBTN = WWT_IMGBTN | WWB_PUSHBUTTON, ///< Normal push-button (no toggle button) with image caption
106 WWT_PUSHARROWBTN = WWT_ARROWBTN | WWB_PUSHBUTTON, ///< Normal push-button (no toggle button) with arrow caption
107 NWID_PUSHBUTTON_DROPDOWN = NWID_BUTTON_DROPDOWN | WWB_PUSHBUTTON,
108 };
109
110 /** Different forms of sizing nested widgets, using NWidgetBase::AssignSizePosition() */
111 enum SizingType {
112 ST_SMALLEST, ///< Initialize nested widget tree to smallest size. Also updates \e current_x and \e current_y.
113 ST_RESIZE, ///< Resize the nested widget tree.
114 };
115
116 /* Forward declarations. */
117 class NWidgetCore;
118 class Scrollbar;
119
120 /**
121 * Baseclass for nested widgets.
122 * @invariant After initialization, \f$current\_x = smallest\_x + n * resize\_x, for n \geq 0\f$.
123 * @invariant After initialization, \f$current\_y = smallest\_y + m * resize\_y, for m \geq 0\f$.
124 * @ingroup NestedWidgets
125 */
126 class NWidgetBase : public ZeroedMemoryAllocator {
127 public:
128 NWidgetBase(WidgetType tp);
129
130 virtual void AdjustPaddingForZoom();
131 virtual void SetupSmallestSize(Window *w, bool init_array) = 0;
132 virtual void AssignSizePosition(SizingType sizing, uint x, uint y, uint given_width, uint given_height, bool rtl) = 0;
133
134 virtual void FillNestedArray(NWidgetBase **array, uint length) = 0;
135
136 virtual NWidgetCore *GetWidgetFromPos(int x, int y) = 0;
137 virtual NWidgetBase *GetWidgetOfType(WidgetType tp);
138
IsHighlighted()139 virtual bool IsHighlighted() const { return false; }
GetHighlightColour()140 virtual TextColour GetHighlightColour() const { return TC_INVALID; }
SetHighlighted(TextColour highlight_colour)141 virtual void SetHighlighted(TextColour highlight_colour) {}
142
143 /**
144 * Set additional space (padding) around the widget.
145 * @param top Amount of additional space above the widget.
146 * @param right Amount of additional space right of the widget.
147 * @param bottom Amount of additional space below the widget.
148 * @param left Amount of additional space left of the widget.
149 */
SetPadding(uint8 top,uint8 right,uint8 bottom,uint8 left)150 inline void SetPadding(uint8 top, uint8 right, uint8 bottom, uint8 left)
151 {
152 this->uz_padding_top = top;
153 this->uz_padding_right = right;
154 this->uz_padding_bottom = bottom;
155 this->uz_padding_left = left;
156 this->AdjustPaddingForZoom();
157 }
158
159 inline uint GetHorizontalStepSize(SizingType sizing) const;
160 inline uint GetVerticalStepSize(SizingType sizing) const;
161
162 virtual void Draw(const Window *w) = 0;
163 virtual void SetDirty(const Window *w) const;
164
GetCurrentRect()165 Rect GetCurrentRect() const
166 {
167 Rect r;
168 r.left = this->pos_x;
169 r.top = this->pos_y;
170 r.right = this->pos_x + this->current_x - 1;
171 r.bottom = this->pos_y + this->current_y - 1;
172 return r;
173 }
174
175 WidgetType type; ///< Type of the widget / nested widget.
176 uint fill_x; ///< Horizontal fill stepsize (from initial size, \c 0 means not resizable).
177 uint fill_y; ///< Vertical fill stepsize (from initial size, \c 0 means not resizable).
178 uint resize_x; ///< Horizontal resize step (\c 0 means not resizable).
179 uint resize_y; ///< Vertical resize step (\c 0 means not resizable).
180 /* Size of the widget in the smallest window possible.
181 * Computed by #SetupSmallestSize() followed by #AssignSizePosition().
182 */
183 uint smallest_x; ///< Smallest horizontal size of the widget in a filled window.
184 uint smallest_y; ///< Smallest vertical size of the widget in a filled window.
185 /* Current widget size (that is, after resizing). */
186 uint current_x; ///< Current horizontal size (after resizing).
187 uint current_y; ///< Current vertical size (after resizing).
188
189 int pos_x; ///< Horizontal position of top-left corner of the widget in the window.
190 int pos_y; ///< Vertical position of top-left corner of the widget in the window.
191
192 NWidgetBase *next; ///< Pointer to next widget in container. Managed by parent container widget.
193 NWidgetBase *prev; ///< Pointer to previous widget in container. Managed by parent container widget.
194
195 uint8 padding_top; ///< Paddings added to the top of the widget. Managed by parent container widget.
196 uint8 padding_right; ///< Paddings added to the right of the widget. Managed by parent container widget. (parent container may swap this with padding_left for RTL)
197 uint8 padding_bottom; ///< Paddings added to the bottom of the widget. Managed by parent container widget.
198 uint8 padding_left; ///< Paddings added to the left of the widget. Managed by parent container widget. (parent container may swap this with padding_right for RTL)
199
200 uint8 uz_padding_top; ///< Unscaled top padding, for resize calculation.
201 uint8 uz_padding_right; ///< Unscaled right padding, for resize calculation.
202 uint8 uz_padding_bottom; ///< Unscaled bottom padding, for resize calculation.
203 uint8 uz_padding_left; ///< Unscaled left padding, for resize calculation.
204
205 protected:
206 inline void StoreSizePosition(SizingType sizing, uint x, uint y, uint given_width, uint given_height);
207 };
208
209 /**
210 * Get the horizontal sizing step.
211 * @param sizing Type of resize being performed.
212 */
GetHorizontalStepSize(SizingType sizing)213 inline uint NWidgetBase::GetHorizontalStepSize(SizingType sizing) const
214 {
215 return (sizing == ST_RESIZE) ? this->resize_x : this->fill_x;
216 }
217
218 /**
219 * Get the vertical sizing step.
220 * @param sizing Type of resize being performed.
221 */
GetVerticalStepSize(SizingType sizing)222 inline uint NWidgetBase::GetVerticalStepSize(SizingType sizing) const
223 {
224 return (sizing == ST_RESIZE) ? this->resize_y : this->fill_y;
225 }
226
227 /**
228 * Store size and position.
229 * @param sizing Type of resizing to perform.
230 * @param x Horizontal offset of the widget relative to the left edge of the window.
231 * @param y Vertical offset of the widget relative to the top edge of the window.
232 * @param given_width Width allocated to the widget.
233 * @param given_height Height allocated to the widget.
234 */
StoreSizePosition(SizingType sizing,uint x,uint y,uint given_width,uint given_height)235 inline void NWidgetBase::StoreSizePosition(SizingType sizing, uint x, uint y, uint given_width, uint given_height)
236 {
237 this->pos_x = x;
238 this->pos_y = y;
239 if (sizing == ST_SMALLEST) {
240 this->smallest_x = given_width;
241 this->smallest_y = given_height;
242 }
243 this->current_x = given_width;
244 this->current_y = given_height;
245 }
246
247
248 /**
249 * Base class for a resizable nested widget.
250 * @ingroup NestedWidgets
251 */
252 class NWidgetResizeBase : public NWidgetBase {
253 public:
254 NWidgetResizeBase(WidgetType tp, uint fill_x, uint fill_y);
255
256 void AdjustPaddingForZoom() override;
257 void SetMinimalSize(uint min_x, uint min_y);
258 void SetMinimalSizeAbsolute(uint min_x, uint min_y);
259 void SetMinimalTextLines(uint8 min_lines, uint8 spacing, FontSize size);
260 void SetFill(uint fill_x, uint fill_y);
261 void SetResize(uint resize_x, uint resize_y);
262
263 void AssignSizePosition(SizingType sizing, uint x, uint y, uint given_width, uint given_height, bool rtl) override;
264
265 uint min_x; ///< Minimal horizontal size of only this widget.
266 uint min_y; ///< Minimal vertical size of only this widget.
267
268 bool absolute; ///< Set if minimum size is fixed and should not be resized.
269 uint uz_min_x; ///< Unscaled Minimal horizontal size of only this widget.
270 uint uz_min_y; ///< Unscaled Minimal vertical size of only this widget.
271
272 uint8 uz_text_lines; ///< 'Unscaled' text lines, stored for resize calculation.
273 uint8 uz_text_spacing; ///< 'Unscaled' text padding, stored for resize calculation.
274 FontSize uz_text_size; ///< 'Unscaled' font size, stored for resize calculation.
275 };
276
277 /** Nested widget flags that affect display and interaction with 'real' widgets. */
278 enum NWidgetDisplay {
279 /* Generic. */
280 NDB_LOWERED = 0, ///< Widget is lowered (pressed down) bit.
281 NDB_DISABLED = 1, ///< Widget is disabled (greyed out) bit.
282 /* Viewport widget. */
283 NDB_NO_TRANSPARENCY = 2, ///< Viewport is never transparent.
284 NDB_SHADE_GREY = 3, ///< Shade viewport to grey-scale.
285 NDB_SHADE_DIMMED = 4, ///< Display dimmed colours in the viewport.
286 /* Button dropdown widget. */
287 NDB_DROPDOWN_ACTIVE = 5, ///< Dropdown menu of the button dropdown widget is active. @see #NWID_BUTTON_DROPDOWN
288 /* Scrollbar widget. */
289 NDB_SCROLLBAR_UP = 6, ///< Up-button is lowered bit.
290 NDB_SCROLLBAR_DOWN = 7, ///< Down-button is lowered bit.
291 /* Generic. */
292 NDB_HIGHLIGHT = 8, ///< Highlight of widget is on.
293
294 ND_LOWERED = 1 << NDB_LOWERED, ///< Bit value of the lowered flag.
295 ND_DISABLED = 1 << NDB_DISABLED, ///< Bit value of the disabled flag.
296 ND_HIGHLIGHT = 1 << NDB_HIGHLIGHT, ///< Bit value of the highlight flag.
297 ND_NO_TRANSPARENCY = 1 << NDB_NO_TRANSPARENCY, ///< Bit value of the 'no transparency' flag.
298 ND_SHADE_GREY = 1 << NDB_SHADE_GREY, ///< Bit value of the 'shade to grey' flag.
299 ND_SHADE_DIMMED = 1 << NDB_SHADE_DIMMED, ///< Bit value of the 'dimmed colours' flag.
300 ND_DROPDOWN_ACTIVE = 1 << NDB_DROPDOWN_ACTIVE, ///< Bit value of the 'dropdown active' flag.
301 ND_SCROLLBAR_UP = 1 << NDB_SCROLLBAR_UP, ///< Bit value of the 'scrollbar up' flag.
302 ND_SCROLLBAR_DOWN = 1 << NDB_SCROLLBAR_DOWN, ///< Bit value of the 'scrollbar down' flag.
303 ND_SCROLLBAR_BTN = ND_SCROLLBAR_UP | ND_SCROLLBAR_DOWN, ///< Bit value of the 'scrollbar up' or 'scrollbar down' flag.
304 };
DECLARE_ENUM_AS_BIT_SET(NWidgetDisplay)305 DECLARE_ENUM_AS_BIT_SET(NWidgetDisplay)
306
307 /**
308 * Base class for a 'real' widget.
309 * @ingroup NestedWidgets
310 */
311 class NWidgetCore : public NWidgetResizeBase {
312 public:
313 NWidgetCore(WidgetType tp, Colours colour, uint fill_x, uint fill_y, uint32 widget_data, StringID tool_tip);
314
315 void SetIndex(int index);
316 void SetDataTip(uint32 widget_data, StringID tool_tip);
317 void SetToolTip(StringID tool_tip);
318 void SetTextColour(TextColour colour);
319 void SetAlignment(StringAlignment align);
320
321 inline void SetLowered(bool lowered);
322 inline bool IsLowered() const;
323 inline void SetDisabled(bool disabled);
324 inline bool IsDisabled() const;
325
326 void FillNestedArray(NWidgetBase **array, uint length) override;
327 NWidgetCore *GetWidgetFromPos(int x, int y) override;
328 bool IsHighlighted() const override;
329 TextColour GetHighlightColour() const override;
330 void SetHighlighted(TextColour highlight_colour) override;
331
332 NWidgetDisplay disp_flags; ///< Flags that affect display and interaction with the widget.
333 Colours colour; ///< Colour of this widget.
334 int index; ///< Index of the nested widget in the widget array of the window (\c -1 means 'not used').
335 uint32 widget_data; ///< Data of the widget. @see Widget::data
336 StringID tool_tip; ///< Tooltip of the widget. @see Widget::tootips
337 int scrollbar_index; ///< Index of an attached scrollbar.
338 TextColour highlight_colour; ///< Colour of highlight.
339 TextColour text_colour; ///< Colour of text within widget.
340 StringAlignment align; ///< Alignment of text/image within widget.
341 };
342
343 /**
344 * Highlight the widget or not.
345 * @param highlight_colour Widget must be highlighted (blink).
346 */
SetHighlighted(TextColour highlight_colour)347 inline void NWidgetCore::SetHighlighted(TextColour highlight_colour)
348 {
349 this->disp_flags = highlight_colour != TC_INVALID ? SETBITS(this->disp_flags, ND_HIGHLIGHT) : CLRBITS(this->disp_flags, ND_HIGHLIGHT);
350 this->highlight_colour = highlight_colour;
351 }
352
353 /** Return whether the widget is highlighted. */
IsHighlighted()354 inline bool NWidgetCore::IsHighlighted() const
355 {
356 return HasBit(this->disp_flags, NDB_HIGHLIGHT);
357 }
358
359 /** Return the colour of the highlight. */
GetHighlightColour()360 inline TextColour NWidgetCore::GetHighlightColour() const
361 {
362 return this->highlight_colour;
363 }
364
365 /**
366 * Lower or raise the widget.
367 * @param lowered Widget must be lowered (drawn pressed down).
368 */
SetLowered(bool lowered)369 inline void NWidgetCore::SetLowered(bool lowered)
370 {
371 this->disp_flags = lowered ? SETBITS(this->disp_flags, ND_LOWERED) : CLRBITS(this->disp_flags, ND_LOWERED);
372 }
373
374 /** Return whether the widget is lowered. */
IsLowered()375 inline bool NWidgetCore::IsLowered() const
376 {
377 return HasBit(this->disp_flags, NDB_LOWERED);
378 }
379
380 /**
381 * Disable (grey-out) or enable the widget.
382 * @param disabled Widget must be disabled.
383 */
SetDisabled(bool disabled)384 inline void NWidgetCore::SetDisabled(bool disabled)
385 {
386 this->disp_flags = disabled ? SETBITS(this->disp_flags, ND_DISABLED) : CLRBITS(this->disp_flags, ND_DISABLED);
387 }
388
389 /** Return whether the widget is disabled. */
IsDisabled()390 inline bool NWidgetCore::IsDisabled() const
391 {
392 return HasBit(this->disp_flags, NDB_DISABLED);
393 }
394
395
396 /**
397 * Baseclass for container widgets.
398 * @ingroup NestedWidgets
399 */
400 class NWidgetContainer : public NWidgetBase {
401 public:
402 NWidgetContainer(WidgetType tp);
403 ~NWidgetContainer();
404
405 void AdjustPaddingForZoom() override;
406 void Add(NWidgetBase *wid);
407 void FillNestedArray(NWidgetBase **array, uint length) override;
408
409 /** Return whether the container is empty. */
IsEmpty()410 inline bool IsEmpty() { return head == nullptr; }
411
412 NWidgetBase *GetWidgetOfType(WidgetType tp) override;
413
414 protected:
415 NWidgetBase *head; ///< Pointer to first widget in container.
416 NWidgetBase *tail; ///< Pointer to last widget in container.
417 };
418
419 /** Display planes with zero size for #NWidgetStacked. */
420 enum StackedZeroSizePlanes {
421 SZSP_VERTICAL = INT_MAX / 2, ///< Display plane with zero size horizontally, and filling and resizing vertically.
422 SZSP_HORIZONTAL, ///< Display plane with zero size vertically, and filling and resizing horizontally.
423 SZSP_NONE, ///< Display plane with zero size in both directions (none filling and resizing).
424
425 SZSP_BEGIN = SZSP_VERTICAL, ///< First zero-size plane.
426 };
427
428 /**
429 * Stacked widgets, widgets all occupying the same space in the window.
430 * #NWID_SELECTION allows for selecting one of several panels (planes) to tbe displayed. All planes must have the same size.
431 * Since all planes are also initialized, switching between different planes can be done while the window is displayed.
432 *
433 * There are also a number of special planes (defined in #StackedZeroSizePlanes) that have zero size in one direction (and are stretchable in
434 * the other direction) or have zero size in both directions. They are used to make all child planes of the widget disappear.
435 * Unlike switching between the regular display planes (that all have the same size), switching from or to one of the zero-sized planes means that
436 * a #Window::ReInit() is needed to re-initialize the window since its size changes.
437 */
438 class NWidgetStacked : public NWidgetContainer {
439 public:
440 NWidgetStacked();
441
442 void SetIndex(int index);
443
444 void AdjustPaddingForZoom() override;
445 void SetupSmallestSize(Window *w, bool init_array) override;
446 void AssignSizePosition(SizingType sizing, uint x, uint y, uint given_width, uint given_height, bool rtl) override;
447 void FillNestedArray(NWidgetBase **array, uint length) override;
448
449 void Draw(const Window *w) override;
450 NWidgetCore *GetWidgetFromPos(int x, int y) override;
451
452 void SetDisplayedPlane(int plane);
453
454 int shown_plane; ///< Plane being displayed (for #NWID_SELECTION only).
455 int index; ///< If non-negative, index in the #Window::nested_array.
456 };
457
458 /** Nested widget container flags, */
459 enum NWidContainerFlags {
460 NCB_EQUALSIZE = 0, ///< Containers should keep all their (resizing) children equally large.
461
462 NC_NONE = 0, ///< All flags cleared.
463 NC_EQUALSIZE = 1 << NCB_EQUALSIZE, ///< Value of the #NCB_EQUALSIZE flag.
464 };
DECLARE_ENUM_AS_BIT_SET(NWidContainerFlags)465 DECLARE_ENUM_AS_BIT_SET(NWidContainerFlags)
466
467 /** Container with pre/inter/post child space. */
468 class NWidgetPIPContainer : public NWidgetContainer {
469 public:
470 NWidgetPIPContainer(WidgetType tp, NWidContainerFlags flags = NC_NONE);
471
472 void AdjustPaddingForZoom() override;
473 void SetPIP(uint8 pip_pre, uint8 pip_inter, uint8 pip_post);
474
475 void Draw(const Window *w) override;
476 NWidgetCore *GetWidgetFromPos(int x, int y) override;
477
478 protected:
479 NWidContainerFlags flags; ///< Flags of the container.
480 uint8 pip_pre; ///< Amount of space before first widget.
481 uint8 pip_inter; ///< Amount of space between widgets.
482 uint8 pip_post; ///< Amount of space after last widget.
483
484 uint8 uz_pip_pre; ///< Unscaled space before first widget.
485 uint8 uz_pip_inter; ///< Unscaled space between widgets.
486 uint8 uz_pip_post; ///< Unscaled space after last widget.
487 };
488
489 /**
490 * Horizontal container.
491 * @ingroup NestedWidgets
492 */
493 class NWidgetHorizontal : public NWidgetPIPContainer {
494 public:
495 NWidgetHorizontal(NWidContainerFlags flags = NC_NONE);
496
497 void SetupSmallestSize(Window *w, bool init_array) override;
498 void AssignSizePosition(SizingType sizing, uint x, uint y, uint given_width, uint given_height, bool rtl) override;
499 };
500
501 /**
502 * Horizontal container that doesn't change the direction of the widgets for RTL languages.
503 * @ingroup NestedWidgets
504 */
505 class NWidgetHorizontalLTR : public NWidgetHorizontal {
506 public:
507 NWidgetHorizontalLTR(NWidContainerFlags flags = NC_NONE);
508
509 void AssignSizePosition(SizingType sizing, uint x, uint y, uint given_width, uint given_height, bool rtl) override;
510 };
511
512 /**
513 * Vertical container.
514 * @ingroup NestedWidgets
515 */
516 class NWidgetVertical : public NWidgetPIPContainer {
517 public:
518 NWidgetVertical(NWidContainerFlags flags = NC_NONE);
519
520 void SetupSmallestSize(Window *w, bool init_array) override;
521 void AssignSizePosition(SizingType sizing, uint x, uint y, uint given_width, uint given_height, bool rtl) override;
522 };
523
524 /**
525 * Matrix container with implicitly equal sized (virtual) sub-widgets.
526 * This widget must have exactly one sub-widget. After that this sub-widget
527 * is used to draw all of the data within the matrix piece by piece.
528 * DrawWidget and OnClick calls will be done to that sub-widget, where the
529 * 16 high bits are used to encode the index into the matrix.
530 * @ingroup NestedWidgets
531 */
532 class NWidgetMatrix : public NWidgetPIPContainer {
533 public:
534 NWidgetMatrix();
535
536 void SetIndex(int index);
537 void SetColour(Colours colour);
538 void SetClicked(int clicked);
539 void SetCount(int count);
540 void SetScrollbar(Scrollbar *sb);
541
542 void SetupSmallestSize(Window *w, bool init_array) override;
543 void AssignSizePosition(SizingType sizing, uint x, uint y, uint given_width, uint given_height, bool rtl) override;
544 void FillNestedArray(NWidgetBase **array, uint length) override;
545
546 NWidgetCore *GetWidgetFromPos(int x, int y) override;
547 void Draw(const Window *w) override;
548 protected:
549 int index; ///< If non-negative, index in the #Window::nested_array.
550 Colours colour; ///< Colour of this widget.
551 int clicked; ///< The currently clicked widget.
552 int count; ///< Amount of valid widgets.
553 Scrollbar *sb; ///< The scrollbar we're associated with.
554 private:
555 int widget_w; ///< The width of the child widget including inter spacing.
556 int widget_h; ///< The height of the child widget including inter spacing.
557 int widgets_x; ///< The number of visible widgets in horizontal direction.
558 int widgets_y; ///< The number of visible widgets in vertical direction.
559
560 void GetScrollOffsets(int &start_x, int &start_y, int &base_offs_x, int &base_offs_y);
561 };
562
563
564 /**
565 * Spacer widget.
566 * @ingroup NestedWidgets
567 */
568 class NWidgetSpacer : public NWidgetResizeBase {
569 public:
570 NWidgetSpacer(int width, int height);
571
572 void SetupSmallestSize(Window *w, bool init_array) override;
573 void FillNestedArray(NWidgetBase **array, uint length) override;
574
575 void Draw(const Window *w) override;
576 void SetDirty(const Window *w) const override;
577 NWidgetCore *GetWidgetFromPos(int x, int y) override;
578 };
579
580 /**
581 * Nested widget with a child.
582 * @ingroup NestedWidgets
583 */
584 class NWidgetBackground : public NWidgetCore {
585 public:
586 NWidgetBackground(WidgetType tp, Colours colour, int index, NWidgetPIPContainer *child = nullptr);
587 ~NWidgetBackground();
588
589 void Add(NWidgetBase *nwid);
590 void SetPIP(uint8 pip_pre, uint8 pip_inter, uint8 pip_post);
591
592 void AdjustPaddingForZoom() override;
593 void SetupSmallestSize(Window *w, bool init_array) override;
594 void AssignSizePosition(SizingType sizing, uint x, uint y, uint given_width, uint given_height, bool rtl) override;
595
596 void FillNestedArray(NWidgetBase **array, uint length) override;
597
598 void Draw(const Window *w) override;
599 NWidgetCore *GetWidgetFromPos(int x, int y) override;
600 NWidgetBase *GetWidgetOfType(WidgetType tp) override;
601
602 private:
603 NWidgetPIPContainer *child; ///< Child widget.
604 };
605
606 /**
607 * Nested widget to display a viewport in a window.
608 * After initializing the nested widget tree, call #InitializeViewport(). After changing the window size,
609 * call #UpdateViewportCoordinates() eg from Window::OnResize().
610 * If the #disp_flags field contains the #ND_NO_TRANSPARENCY bit, the viewport will disable transparency.
611 * Shading to grey-scale is controlled with the #ND_SHADE_GREY bit (used for B&W news papers), the #ND_SHADE_DIMMED gives dimmed colours (for colour news papers).
612 * @todo Class derives from #NWidgetCore, but does not use #colour, #widget_data, or #tool_tip.
613 * @ingroup NestedWidgets
614 */
615 class NWidgetViewport : public NWidgetCore {
616 public:
617 NWidgetViewport(int index);
618
619 void SetupSmallestSize(Window *w, bool init_array) override;
620 void Draw(const Window *w) override;
621
622 void InitializeViewport(Window *w, uint32 follow_flags, ZoomLevel zoom);
623 void UpdateViewportCoordinates(Window *w);
624 };
625
626 /**
627 * Scrollbar data structure
628 */
629 class Scrollbar {
630 private:
631 const bool is_vertical; ///< Scrollbar has vertical orientation.
632 uint16 count; ///< Number of elements in the list.
633 uint16 cap; ///< Number of visible elements of the scroll bar.
634 uint16 pos; ///< Index of first visible item of the list.
635 uint16 stepsize; ///< Distance to scroll, when pressing the buttons or using the wheel.
636
637 public:
638 /** Stepping sizes when scrolling */
639 enum ScrollbarStepping {
640 SS_RAW, ///< Step in single units.
641 SS_SMALL, ///< Step in #stepsize units.
642 SS_BIG, ///< Step in #cap units.
643 };
644
Scrollbar(bool is_vertical)645 Scrollbar(bool is_vertical) : is_vertical(is_vertical), stepsize(1)
646 {
647 }
648
649 /**
650 * Gets the number of elements in the list
651 * @return the number of elements
652 */
GetCount()653 inline uint16 GetCount() const
654 {
655 return this->count;
656 }
657
658 /**
659 * Gets the number of visible elements of the scrollbar
660 * @return the number of visible elements
661 */
GetCapacity()662 inline uint16 GetCapacity() const
663 {
664 return this->cap;
665 }
666
667 /**
668 * Gets the position of the first visible element in the list
669 * @return the position of the element
670 */
GetPosition()671 inline uint16 GetPosition() const
672 {
673 return this->pos;
674 }
675
676 /**
677 * Checks whether given current item is visible in the list
678 * @param item to check
679 * @return true iff the item is visible
680 */
IsVisible(uint16 item)681 inline bool IsVisible(uint16 item) const
682 {
683 return IsInsideBS(item, this->GetPosition(), this->GetCapacity());
684 }
685
686 /**
687 * Is the scrollbar vertical or not?
688 * @return True iff the scrollbar is vertical.
689 */
IsVertical()690 inline bool IsVertical() const
691 {
692 return this->is_vertical;
693 }
694
695 /**
696 * Set the distance to scroll when using the buttons or the wheel.
697 * @param stepsize Scrolling speed.
698 */
SetStepSize(uint16 stepsize)699 void SetStepSize(uint16 stepsize)
700 {
701 assert(stepsize > 0);
702 this->stepsize = stepsize;
703 }
704
705 /**
706 * Sets the number of elements in the list
707 * @param num the number of elements in the list
708 * @note updates the position if needed
709 */
SetCount(int num)710 void SetCount(int num)
711 {
712 assert(num >= 0);
713 assert(num <= MAX_UVALUE(uint16));
714
715 this->count = num;
716 num -= this->cap;
717 if (num < 0) num = 0;
718 if (num < this->pos) this->pos = num;
719 }
720
721 /**
722 * Set the capacity of visible elements.
723 * @param capacity the new capacity
724 * @note updates the position if needed
725 */
SetCapacity(int capacity)726 void SetCapacity(int capacity)
727 {
728 assert(capacity > 0);
729 assert(capacity <= MAX_UVALUE(uint16));
730
731 this->cap = capacity;
732 if (this->cap + this->pos > this->count) this->pos = std::max(0, this->count - this->cap);
733 }
734
735 void SetCapacityFromWidget(Window *w, int widget, int padding = 0);
736
737 /**
738 * Sets the position of the first visible element
739 * @param position the position of the element
740 * @return true iff the position has changed
741 */
SetPosition(int position)742 bool SetPosition(int position)
743 {
744 assert(position >= 0);
745 assert(this->count <= this->cap ? (position == 0) : (position + this->cap <= this->count));
746 uint16 old_pos = this->pos;
747 this->pos = position;
748 return this->pos != old_pos;
749 }
750
751 /**
752 * Updates the position of the first visible element by the given amount.
753 * If the position would be too low or high it will be clamped appropriately
754 * @param difference the amount of change requested
755 * @param unit The stepping unit of \a difference
756 * @return true iff the position has changed
757 */
758 bool UpdatePosition(int difference, ScrollbarStepping unit = SS_SMALL)
759 {
760 if (difference == 0) return false;
761 switch (unit) {
762 case SS_SMALL: difference *= this->stepsize; break;
763 case SS_BIG: difference *= this->cap; break;
764 default: break;
765 }
766 return this->SetPosition(Clamp(this->pos + difference, 0, std::max(this->count - this->cap, 0)));
767 }
768
769 /**
770 * Scroll towards the given position; if the item is visible nothing
771 * happens, otherwise it will be shown either at the bottom or top of
772 * the window depending on where in the list it was.
773 * @param position the position to scroll towards.
774 */
ScrollTowards(int position)775 void ScrollTowards(int position)
776 {
777 if (position < this->GetPosition()) {
778 /* scroll up to the item */
779 this->SetPosition(position);
780 } else if (position >= this->GetPosition() + this->GetCapacity()) {
781 /* scroll down so that the item is at the bottom */
782 this->SetPosition(position - this->GetCapacity() + 1);
783 }
784 }
785
786 int GetScrolledRowFromWidget(int clickpos, const Window * const w, int widget, int padding = 0) const;
787 EventState UpdateListPositionOnKeyPress(int &list_position, uint16 keycode) const;
788 };
789
790 /**
791 * Nested widget to display and control a scrollbar in a window.
792 * Also assign the scrollbar to other widgets using #SetScrollbar() to make the mousewheel work.
793 * @ingroup NestedWidgets
794 */
795 class NWidgetScrollbar : public NWidgetCore, public Scrollbar {
796 public:
797 NWidgetScrollbar(WidgetType tp, Colours colour, int index);
798
799 void SetupSmallestSize(Window *w, bool init_array) override;
800 void Draw(const Window *w) override;
801
802 static void InvalidateDimensionCache();
803 static Dimension GetVerticalDimension();
804 static Dimension GetHorizontalDimension();
805
806 private:
807 static Dimension vertical_dimension; ///< Cached size of vertical scrollbar button.
808 static Dimension horizontal_dimension; ///< Cached size of horizontal scrollbar button.
809 };
810
811 /**
812 * Leaf widget.
813 * @ingroup NestedWidgets
814 */
815 class NWidgetLeaf : public NWidgetCore {
816 public:
817 NWidgetLeaf(WidgetType tp, Colours colour, int index, uint32 data, StringID tip);
818
819 void SetupSmallestSize(Window *w, bool init_array) override;
820 void Draw(const Window *w) override;
821
822 bool ButtonHit(const Point &pt);
823
824 static void InvalidateDimensionCache();
825
826 static Dimension dropdown_dimension; ///< Cached size of a dropdown widget.
827 static Dimension resizebox_dimension; ///< Cached size of a resizebox widget.
828 static Dimension closebox_dimension; ///< Cached size of a closebox widget.
829 private:
830 static Dimension shadebox_dimension; ///< Cached size of a shadebox widget.
831 static Dimension debugbox_dimension; ///< Cached size of a debugbox widget.
832 static Dimension defsizebox_dimension; ///< Cached size of a defsizebox widget.
833 static Dimension stickybox_dimension; ///< Cached size of a stickybox widget.
834 };
835
836 /**
837 * Return the biggest possible size of a nested widget.
838 * @param base Base size of the widget.
839 * @param max_space Available space for the widget.
840 * @param step Stepsize of the widget.
841 * @return Biggest possible size of the widget, assuming that \a base may only be incremented by \a step size steps.
842 */
ComputeMaxSize(uint base,uint max_space,uint step)843 static inline uint ComputeMaxSize(uint base, uint max_space, uint step)
844 {
845 if (base >= max_space || step == 0) return base;
846 if (step == 1) return max_space;
847 uint increment = max_space - base;
848 increment -= increment % step;
849 return base + increment;
850 }
851
852 /**
853 * @defgroup NestedWidgetParts Hierarchical widget parts
854 * To make nested widgets easier to enter, nested widget parts have been created. They allow the tree to be defined in a flat array of parts.
855 *
856 * - Leaf widgets start with a #NWidget(WidgetType tp, Colours col, int16 idx) part.
857 * Next, specify its properties with one or more of
858 * - #SetMinimalSize Define the minimal size of the widget.
859 * - #SetFill Define how the widget may grow to make it nicely.
860 * - #SetDataTip Define the data and the tooltip of the widget.
861 * - #SetResize Define how the widget may resize.
862 * - #SetPadding Create additional space around the widget.
863 *
864 * - To insert a nested widget tree from an external source, nested widget part #NWidgetFunction exists.
865 * For further customization, the #SetPadding part may be used.
866 *
867 * - Space widgets (#NWidgetSpacer) start with a #NWidget(WidgetType tp), followed by one or more of
868 * - #SetMinimalSize Define the minimal size of the widget.
869 * - #SetFill Define how the widget may grow to make it nicely.
870 * - #SetResize Define how the widget may resize.
871 * - #SetPadding Create additional space around the widget.
872 *
873 * - Container widgets #NWidgetHorizontal, #NWidgetHorizontalLTR, #NWidgetVertical, and #NWidgetMatrix, start with a #NWidget(WidgetType tp) part.
874 * Their properties are derived from the child widgets so they cannot be specified.
875 * You can however use
876 * - #SetPadding Define additional padding around the container.
877 * - #SetPIP Set additional pre/inter/post child widget space.
878 * .
879 * Underneath these properties, all child widgets of the container must be defined. To denote that they are childs, add an indent before the nested widget parts of
880 * the child widgets (it has no meaning for the compiler but it makes the widget parts easier to read).
881 * Below the last child widget, use an #EndContainer part. This part should be aligned with the #NWidget part that started the container.
882 *
883 * - Stacked widgets #NWidgetStacked map each of their children onto the same space. It behaves like a container, except there is no pre/inter/post space,
884 * so the widget does not support #SetPIP. #SetPadding is allowed though.
885 * Like the other container widgets, below the last child widgets, a #EndContainer part should be used to denote the end of the stacked widget.
886 *
887 * - Background widgets #NWidgetBackground start with a #NWidget(WidgetType tp, Colours col, int16 idx) part.
888 * What follows depends on how the widget is used.
889 * - If the widget is used as a leaf widget, that is, to create some space in the window to display a viewport or some text, use the properties of the
890 * leaf widgets to define how it behaves.
891 * - If the widget is used a background behind other widgets, it is considered to be a container widgets. Use the properties listed there to define its
892 * behaviour.
893 * .
894 * In both cases, the background widget \b MUST end with a #EndContainer widget part.
895 *
896 * @see NestedWidgets
897 */
898
899 /**
900 * Widget part for storing data and tooltip information.
901 * @ingroup NestedWidgetParts
902 */
903 struct NWidgetPartDataTip {
904 uint32 data; ///< Data value of the widget.
905 StringID tooltip; ///< Tooltip of the widget.
906 };
907
908 /**
909 * Widget part for storing basic widget information.
910 * @ingroup NestedWidgetParts
911 */
912 struct NWidgetPartWidget {
913 Colours colour; ///< Widget colour.
914 int16 index; ///< Widget index in the widget array.
915 };
916
917 /**
918 * Widget part for storing padding.
919 * @ingroup NestedWidgetParts
920 */
921 struct NWidgetPartPaddings {
922 uint8 top, right, bottom, left; ///< Paddings for all directions.
923 };
924
925 /**
926 * Widget part for storing pre/inter/post spaces.
927 * @ingroup NestedWidgetParts
928 */
929 struct NWidgetPartPIP {
930 uint8 pre, inter, post; ///< Amount of space before/between/after child widgets.
931 };
932
933 /**
934 * Widget part for storing minimal text line data.
935 * @ingroup NestedWidgetParts
936 */
937 struct NWidgetPartTextLines {
938 uint8 lines; ///< Number of text lines.
939 uint8 spacing; ///< Extra spacing around lines.
940 FontSize size; ///< Font size of text lines.
941 };
942
943 /**
944 * Widget part for storing text colour.
945 * @ingroup NestedWidgetParts
946 */
947 struct NWidgetPartTextColour {
948 TextColour colour; ///< TextColour for DrawString.
949 };
950
951 /**
952 * Widget part for setting text/image alignment within a widget.
953 * @ingroup NestedWidgetParts
954 */
955 struct NWidgetPartAlignment {
956 StringAlignment align; ///< Alignment of text/image.
957 };
958
959 /**
960 * Pointer to function returning a nested widget.
961 * @param biggest_index Pointer to storage for collecting the biggest index used in the nested widget.
962 * @return Nested widget (tree).
963 * @post \c *biggest_index must contain the value of the biggest index in the returned tree.
964 */
965 typedef NWidgetBase *NWidgetFunctionType(int *biggest_index);
966
967 /**
968 * Partial widget specification to allow NWidgets to be written nested.
969 * @ingroup NestedWidgetParts
970 */
971 struct NWidgetPart {
972 WidgetType type; ///< Type of the part. @see NWidgetPartType.
973 union {
974 Point xy; ///< Part with an x/y size.
975 NWidgetPartDataTip data_tip; ///< Part with a data/tooltip.
976 NWidgetPartWidget widget; ///< Part with a start of a widget.
977 NWidgetPartPaddings padding; ///< Part with paddings.
978 NWidgetPartPIP pip; ///< Part with pre/inter/post spaces.
979 NWidgetPartTextLines text_lines; ///< Part with text line data.
980 NWidgetPartTextColour colour; ///< Part with text colour data.
981 NWidgetPartAlignment align; ///< Part with internal alignment.
982 NWidgetFunctionType *func_ptr; ///< Part with a function call.
983 NWidContainerFlags cont_flags; ///< Part with container flags.
984 } u;
985 };
986
987 /**
988 * Widget part function for setting the resize step.
989 * @param dx Horizontal resize step. 0 means no horizontal resizing.
990 * @param dy Vertical resize step. 0 means no vertical resizing.
991 * @ingroup NestedWidgetParts
992 */
SetResize(int16 dx,int16 dy)993 static inline NWidgetPart SetResize(int16 dx, int16 dy)
994 {
995 NWidgetPart part;
996
997 part.type = WPT_RESIZE;
998 part.u.xy.x = dx;
999 part.u.xy.y = dy;
1000
1001 return part;
1002 }
1003
1004 /**
1005 * Widget part function for setting the minimal size.
1006 * @param x Horizontal minimal size.
1007 * @param y Vertical minimal size.
1008 * @ingroup NestedWidgetParts
1009 */
SetMinimalSize(int16 x,int16 y)1010 static inline NWidgetPart SetMinimalSize(int16 x, int16 y)
1011 {
1012 NWidgetPart part;
1013
1014 part.type = WPT_MINSIZE;
1015 part.u.xy.x = x;
1016 part.u.xy.y = y;
1017
1018 return part;
1019 }
1020
1021 /**
1022 * Widget part function for setting the minimal text lines.
1023 * @param lines Number of text lines.
1024 * @param spacing Extra spacing required.
1025 * @param size Font size of text.
1026 * @ingroup NestedWidgetParts
1027 */
1028 static inline NWidgetPart SetMinimalTextLines(uint8 lines, uint8 spacing, FontSize size = FS_NORMAL)
1029 {
1030 NWidgetPart part;
1031
1032 part.type = WPT_MINTEXTLINES;
1033 part.u.text_lines.lines = lines;
1034 part.u.text_lines.spacing = spacing;
1035 part.u.text_lines.size = size;
1036
1037 return part;
1038 }
1039
1040 /**
1041 * Widget part function for setting the text colour.
1042 * @param colour Colour to draw string within widget.
1043 * @ingroup NestedWidgetParts
1044 */
SetTextColour(TextColour colour)1045 static inline NWidgetPart SetTextColour(TextColour colour)
1046 {
1047 NWidgetPart part;
1048
1049 part.type = WPT_TEXTCOLOUR;
1050 part.u.colour.colour = colour;
1051
1052 return part;
1053 }
1054
1055 /**
1056 * Widget part function for setting the alignment of text/images.
1057 * @param align Alignment of text/image within widget.
1058 * @ingroup NestedWidgetParts
1059 */
SetAlignment(StringAlignment align)1060 static inline NWidgetPart SetAlignment(StringAlignment align)
1061 {
1062 NWidgetPart part;
1063
1064 part.type = WPT_ALIGNMENT;
1065 part.u.align.align = align;
1066
1067 return part;
1068 }
1069
1070 /**
1071 * Widget part function for setting filling.
1072 * @param fill_x Horizontal filling step from minimal size.
1073 * @param fill_y Vertical filling step from minimal size.
1074 * @ingroup NestedWidgetParts
1075 */
SetFill(uint fill_x,uint fill_y)1076 static inline NWidgetPart SetFill(uint fill_x, uint fill_y)
1077 {
1078 NWidgetPart part;
1079
1080 part.type = WPT_FILL;
1081 part.u.xy.x = fill_x;
1082 part.u.xy.y = fill_y;
1083
1084 return part;
1085 }
1086
1087 /**
1088 * Widget part function for denoting the end of a container
1089 * (horizontal, vertical, WWT_FRAME, WWT_INSET, or WWT_PANEL).
1090 * @ingroup NestedWidgetParts
1091 */
EndContainer()1092 static inline NWidgetPart EndContainer()
1093 {
1094 NWidgetPart part;
1095
1096 part.type = WPT_ENDCONTAINER;
1097
1098 return part;
1099 }
1100
1101 /**
1102 * Widget part function for setting the data and tooltip.
1103 * @param data Data of the widget.
1104 * @param tip Tooltip of the widget.
1105 * @ingroup NestedWidgetParts
1106 */
SetDataTip(uint32 data,StringID tip)1107 static inline NWidgetPart SetDataTip(uint32 data, StringID tip)
1108 {
1109 NWidgetPart part;
1110
1111 part.type = WPT_DATATIP;
1112 part.u.data_tip.data = data;
1113 part.u.data_tip.tooltip = tip;
1114
1115 return part;
1116 }
1117
1118 /**
1119 * Widget part function for setting the data and tooltip of WWT_MATRIX widgets
1120 * @param cols Number of columns. \c 0 means to use draw columns with width according to the resize step size.
1121 * @param rows Number of rows. \c 0 means to use draw rows with height according to the resize step size.
1122 * @param tip Tooltip of the widget.
1123 * @ingroup NestedWidgetParts
1124 */
SetMatrixDataTip(uint8 cols,uint8 rows,StringID tip)1125 static inline NWidgetPart SetMatrixDataTip(uint8 cols, uint8 rows, StringID tip)
1126 {
1127 return SetDataTip((rows << MAT_ROW_START) | (cols << MAT_COL_START), tip);
1128 }
1129
1130 /**
1131 * Widget part function for setting additional space around a widget.
1132 * Parameters start above the widget, and are specified in clock-wise direction.
1133 * @param top The padding above the widget.
1134 * @param right The padding right of the widget.
1135 * @param bottom The padding below the widget.
1136 * @param left The padding left of the widget.
1137 * @ingroup NestedWidgetParts
1138 */
SetPadding(uint8 top,uint8 right,uint8 bottom,uint8 left)1139 static inline NWidgetPart SetPadding(uint8 top, uint8 right, uint8 bottom, uint8 left)
1140 {
1141 NWidgetPart part;
1142
1143 part.type = WPT_PADDING;
1144 part.u.padding.top = top;
1145 part.u.padding.right = right;
1146 part.u.padding.bottom = bottom;
1147 part.u.padding.left = left;
1148
1149 return part;
1150 }
1151
1152 /**
1153 * Widget part function for setting a padding.
1154 * @param padding The padding to use for all directions.
1155 * @ingroup NestedWidgetParts
1156 */
SetPadding(uint8 padding)1157 static inline NWidgetPart SetPadding(uint8 padding)
1158 {
1159 return SetPadding(padding, padding, padding, padding);
1160 }
1161
1162 /**
1163 * Widget part function for setting a pre/inter/post spaces.
1164 * @param pre The amount of space before the first widget.
1165 * @param inter The amount of space between widgets.
1166 * @param post The amount of space after the last widget.
1167 * @ingroup NestedWidgetParts
1168 */
SetPIP(uint8 pre,uint8 inter,uint8 post)1169 static inline NWidgetPart SetPIP(uint8 pre, uint8 inter, uint8 post)
1170 {
1171 NWidgetPart part;
1172
1173 part.type = WPT_PIPSPACE;
1174 part.u.pip.pre = pre;
1175 part.u.pip.inter = inter;
1176 part.u.pip.post = post;
1177
1178 return part;
1179 }
1180
1181 /**
1182 * Attach a scrollbar to a widget.
1183 * The scrollbar is controlled when using the mousewheel on the widget.
1184 * Multiple widgets can refer to the same scrollbar to make the mousewheel work in all of them.
1185 * @param index Widget index of the scrollbar.
1186 * @ingroup NestedWidgetParts
1187 */
SetScrollbar(int index)1188 static inline NWidgetPart SetScrollbar(int index)
1189 {
1190 NWidgetPart part;
1191
1192 part.type = WPT_SCROLLBAR;
1193 part.u.widget.index = index;
1194
1195 return part;
1196 }
1197
1198 /**
1199 * Widget part function for starting a new 'real' widget.
1200 * @param tp Type of the new nested widget.
1201 * @param col Colour of the new widget.
1202 * @param idx Index of the widget in the widget array.
1203 * @note with #WWT_PANEL, #WWT_FRAME, #WWT_INSET, a new container is started.
1204 * Child widgets must have a index bigger than the parent index.
1205 * @ingroup NestedWidgetParts
1206 */
1207 static inline NWidgetPart NWidget(WidgetType tp, Colours col, int16 idx = -1)
1208 {
1209 NWidgetPart part;
1210
1211 part.type = tp;
1212 part.u.widget.colour = col;
1213 part.u.widget.index = idx;
1214
1215 return part;
1216 }
1217
1218 /**
1219 * Widget part function for starting a new horizontal container, vertical container, or spacer widget.
1220 * @param tp Type of the new nested widget, #NWID_HORIZONTAL, #NWID_VERTICAL, #NWID_SPACER, #NWID_SELECTION, and #NWID_MATRIX.
1221 * @param cont_flags Flags for the containers (#NWID_HORIZONTAL and #NWID_VERTICAL).
1222 * @ingroup NestedWidgetParts
1223 */
1224 static inline NWidgetPart NWidget(WidgetType tp, NWidContainerFlags cont_flags = NC_NONE)
1225 {
1226 NWidgetPart part;
1227
1228 part.type = tp;
1229 part.u.cont_flags = cont_flags;
1230
1231 return part;
1232 }
1233
1234 /**
1235 * Obtain a nested widget (sub)tree from an external source.
1236 * @param func_ptr Pointer to function that returns the tree.
1237 * @ingroup NestedWidgetParts
1238 */
NWidgetFunction(NWidgetFunctionType * func_ptr)1239 static inline NWidgetPart NWidgetFunction(NWidgetFunctionType *func_ptr)
1240 {
1241 NWidgetPart part;
1242
1243 part.type = WPT_FUNCTION;
1244 part.u.func_ptr = func_ptr;
1245
1246 return part;
1247 }
1248
1249 NWidgetContainer *MakeNWidgets(const NWidgetPart *parts, int count, int *biggest_index, NWidgetContainer *container);
1250 NWidgetContainer *MakeWindowNWidgetTree(const NWidgetPart *parts, int count, int *biggest_index, NWidgetStacked **shade_select);
1251
1252 NWidgetBase *MakeCompanyButtonRows(int *biggest_index, int widget_first, int widget_last, Colours button_colour, int max_length, StringID button_tooltip);
1253
1254 #endif /* WIDGET_TYPE_H */
1255