Update: Translations from eints
[openttd-github.git] / src / widget_type.h
blobc00cff700c9e9668b38580cd079fcb704ef292eb
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 */
8 /** @file widget_type.h Definitions about widgets. */
10 #ifndef WIDGET_TYPE_H
11 #define WIDGET_TYPE_H
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"
20 /** Bits of the #WWT_MATRIX widget data. */
21 enum MatrixWidgetValues {
22 /* Number of column bits of the WWT_MATRIX widget data. */
23 MAT_COL_START = 0, ///< Lowest bit of the number of columns.
24 MAT_COL_BITS = 8, ///< Number of bits for the number of columns in the matrix.
26 /* Number of row bits of the WWT_MATRIX widget data. */
27 MAT_ROW_START = 8, ///< Lowest bit of the number of rows.
28 MAT_ROW_BITS = 8, ///< Number of bits for the number of rows in the matrix.
31 /** Values for an arrow widget */
32 enum ArrowWidgetValues {
33 AWV_DECREASE, ///< Arrow to the left or in case of RTL to the right
34 AWV_INCREASE, ///< Arrow to the right or in case of RTL to the left
35 AWV_LEFT, ///< Force the arrow to the left
36 AWV_RIGHT, ///< Force the arrow to the right
39 /** WidgetData values for a resize box widget. */
40 enum ResizeWidgetValues {
41 RWV_SHOW_BEVEL, ///< Bevel of resize box is shown.
42 RWV_HIDE_BEVEL, ///< Bevel of resize box is hidden.
45 /**
46 * Window widget types, nested widget types, and nested widget part types.
48 enum WidgetType {
49 /* Window widget types. */
50 WWT_EMPTY, ///< Empty widget, place holder to reserve space in widget tree.
52 WWT_PANEL, ///< Simple depressed panel
53 WWT_INSET, ///< Pressed (inset) panel, most commonly used as combo box _text_ area
54 WWT_IMGBTN, ///< (Toggle) Button with image
55 WWT_IMGBTN_2, ///< (Toggle) Button with diff image when clicked
56 WWT_ARROWBTN, ///< (Toggle) Button with an arrow
57 WWT_TEXTBTN, ///< (Toggle) Button with text
58 WWT_TEXTBTN_2, ///< (Toggle) Button with diff text when clicked
59 WWT_LABEL, ///< Centered label
60 WWT_TEXT, ///< Pure simple text
61 WWT_MATRIX, ///< Grid of rows and columns. @see MatrixWidgetValues
62 WWT_FRAME, ///< Frame
63 WWT_CAPTION, ///< Window caption (window title between closebox and stickybox)
65 WWT_DEBUGBOX, ///< NewGRF debug box (at top-right of a window, between WWT_CAPTION and WWT_SHADEBOX)
66 WWT_SHADEBOX, ///< Shade box (at top-right of a window, between WWT_DEBUGBOX and WWT_DEFSIZEBOX)
67 WWT_DEFSIZEBOX, ///< Default window size box (at top-right of a window, between WWT_SHADEBOX and WWT_STICKYBOX)
68 WWT_STICKYBOX, ///< Sticky box (at top-right of a window, after WWT_DEFSIZEBOX)
70 WWT_RESIZEBOX, ///< Resize box (normally at bottom-right of a window)
71 WWT_CLOSEBOX, ///< Close box (at top-left of a window)
72 WWT_DROPDOWN, ///< Drop down list
73 WWT_EDITBOX, ///< a textbox for typing
74 WWT_LAST, ///< Last Item. use WIDGETS_END to fill up padding!!
76 /* Nested widget types. */
77 NWID_HORIZONTAL, ///< Horizontal container.
78 NWID_HORIZONTAL_LTR, ///< Horizontal container that doesn't change the order of the widgets for RTL languages.
79 NWID_VERTICAL, ///< Vertical container.
80 NWID_MATRIX, ///< Matrix container.
81 NWID_SPACER, ///< Invisible widget that takes some space.
82 NWID_SELECTION, ///< Stacked widgets, only one visible at a time (eg in a panel with tabs).
83 NWID_VIEWPORT, ///< Nested widget containing a viewport.
84 NWID_BUTTON_DROPDOWN, ///< Button with a drop-down.
85 NWID_HSCROLLBAR, ///< Horizontal scrollbar
86 NWID_VSCROLLBAR, ///< Vertical scrollbar
87 NWID_CUSTOM, ///< General Custom widget.
89 /* Nested widget part types. */
90 WPT_ATTRIBUTE_BEGIN, ///< Begin marker for attribute NWidgetPart types.
91 WPT_RESIZE, ///< Widget part for specifying resizing.
92 WPT_MINSIZE, ///< Widget part for specifying minimal size.
93 WPT_MINTEXTLINES, ///< Widget part for specifying minimal number of lines of text.
94 WPT_FILL, ///< Widget part for specifying fill.
95 WPT_DATATIP, ///< Widget part for specifying data and tooltip.
96 WPT_PADDING, ///< Widget part for specifying a padding.
97 WPT_PIPSPACE, ///< Widget part for specifying pre/inter/post space for containers.
98 WPT_PIPRATIO, ///< Widget part for specifying pre/inter/post ratio for containers.
99 WPT_TEXTSTYLE, ///< Widget part for specifying text colour.
100 WPT_ALIGNMENT, ///< Widget part for specifying text/image alignment.
101 WPT_SCROLLBAR, ///< Widget part for attaching a scrollbar.
102 WPT_ASPECT, ///< Widget part for sepcifying aspect ratio.
103 WPT_ATTRIBUTE_END, ///< End marker for attribute NWidgetPart types.
105 WPT_FUNCTION, ///< Widget part for calling a user function.
106 WPT_ENDCONTAINER, ///< Widget part to denote end of a container.
108 /* Pushable window widget types. */
109 WWT_MASK = 0x7F,
111 WWB_PUSHBUTTON = 1 << 7,
113 WWT_PUSHBTN = WWT_PANEL | WWB_PUSHBUTTON, ///< Normal push-button (no toggle button) with custom drawing
114 WWT_PUSHTXTBTN = WWT_TEXTBTN | WWB_PUSHBUTTON, ///< Normal push-button (no toggle button) with text caption
115 WWT_PUSHIMGBTN = WWT_IMGBTN | WWB_PUSHBUTTON, ///< Normal push-button (no toggle button) with image caption
116 WWT_PUSHARROWBTN = WWT_ARROWBTN | WWB_PUSHBUTTON, ///< Normal push-button (no toggle button) with arrow caption
117 NWID_PUSHBUTTON_DROPDOWN = NWID_BUTTON_DROPDOWN | WWB_PUSHBUTTON,
120 /** Different forms of sizing nested widgets, using NWidgetBase::AssignSizePosition() */
121 enum SizingType {
122 ST_SMALLEST, ///< Initialize nested widget tree to smallest size. Also updates \e current_x and \e current_y.
123 ST_RESIZE, ///< Resize the nested widget tree.
126 enum class AspectFlags : uint8_t {
127 ResizeX = 1U << 0,
128 ResizeY = 1U << 1,
129 ResizeXY = ResizeX | ResizeY,
131 DECLARE_ENUM_AS_BIT_SET(AspectFlags)
133 /* Forward declarations. */
134 class NWidgetCore;
135 class Scrollbar;
137 /** Lookup between widget IDs and NWidget objects. */
138 using WidgetLookup = std::map<WidgetID, class NWidgetBase *>;
141 * Baseclass for nested widgets.
142 * @invariant After initialization, \f$current\_x = smallest\_x + n * resize\_x, for n \geq 0\f$.
143 * @invariant After initialization, \f$current\_y = smallest\_y + m * resize\_y, for m \geq 0\f$.
144 * @ingroup NestedWidgets
146 class NWidgetBase : public ZeroedMemoryAllocator {
147 public:
148 NWidgetBase(WidgetType tp);
150 void ApplyAspectRatio();
151 virtual void AdjustPaddingForZoom();
152 virtual void SetupSmallestSize(Window *w) = 0;
153 virtual void AssignSizePosition(SizingType sizing, int x, int y, uint given_width, uint given_height, bool rtl) = 0;
155 virtual void FillWidgetLookup(WidgetLookup &widget_lookup) = 0;
157 virtual NWidgetCore *GetWidgetFromPos(int x, int y) = 0;
158 virtual NWidgetBase *GetWidgetOfType(WidgetType tp);
161 * Get parent widget of type NWID.
162 * @tparam NWID Type of the nested widget.
163 * @returns Parent widget, or nullptr if no widget of the specified type is found.
165 template <class NWID>
166 NWID *GetParentWidget()
168 for (NWidgetBase *nwid_parent = this->parent; nwid_parent != nullptr; nwid_parent = nwid_parent->parent) {
169 if (NWID *nwid = dynamic_cast<NWID *>(nwid_parent); nwid != nullptr) return nwid;
171 return nullptr;
175 * Get parent widget of type NWID.
176 * @tparam NWID Type of the nested widget.
177 * @returns Parent widget, or nullptr if no widget of the specified type is found.
179 template <class NWID>
180 const NWID *GetParentWidget() const
182 for (const NWidgetBase *nwid_parent = this->parent; nwid_parent != nullptr; nwid_parent = nwid_parent->parent) {
183 if (const NWID *nwid = dynamic_cast<const NWID *>(nwid_parent); nwid != nullptr) return nwid;
185 return nullptr;
188 virtual bool IsHighlighted() const { return false; }
189 virtual TextColour GetHighlightColour() const { return TC_INVALID; }
190 virtual void SetHighlighted([[maybe_unused]] TextColour highlight_colour) {}
193 * Set additional space (padding) around the widget.
194 * @param top Amount of additional space above the widget.
195 * @param right Amount of additional space right of the widget.
196 * @param bottom Amount of additional space below the widget.
197 * @param left Amount of additional space left of the widget.
199 inline void SetPadding(uint8_t top, uint8_t right, uint8_t bottom, uint8_t left)
201 this->uz_padding.top = top;
202 this->uz_padding.right = right;
203 this->uz_padding.bottom = bottom;
204 this->uz_padding.left = left;
205 this->AdjustPaddingForZoom();
209 * Set additional space (padding) around the widget.
210 * @param padding Amount of padding around the widget.
212 inline void SetPadding(const RectPadding &padding)
214 this->uz_padding = padding;
215 this->AdjustPaddingForZoom();
218 inline uint GetHorizontalStepSize(SizingType sizing) const;
219 inline uint GetVerticalStepSize(SizingType sizing) const;
221 virtual void Draw(const Window *w) = 0;
222 virtual void SetDirty(const Window *w) const;
224 Rect GetCurrentRect() const
226 Rect r;
227 r.left = this->pos_x;
228 r.top = this->pos_y;
229 r.right = this->pos_x + this->current_x - 1;
230 r.bottom = this->pos_y + this->current_y - 1;
231 return r;
234 WidgetType type; ///< Type of the widget / nested widget.
235 uint fill_x; ///< Horizontal fill stepsize (from initial size, \c 0 means not resizable).
236 uint fill_y; ///< Vertical fill stepsize (from initial size, \c 0 means not resizable).
237 uint resize_x; ///< Horizontal resize step (\c 0 means not resizable).
238 uint resize_y; ///< Vertical resize step (\c 0 means not resizable).
239 /* Size of the widget in the smallest window possible.
240 * Computed by #SetupSmallestSize() followed by #AssignSizePosition().
242 uint smallest_x; ///< Smallest horizontal size of the widget in a filled window.
243 uint smallest_y; ///< Smallest vertical size of the widget in a filled window.
244 /* Current widget size (that is, after resizing). */
245 uint current_x; ///< Current horizontal size (after resizing).
246 uint current_y; ///< Current vertical size (after resizing).
247 float aspect_ratio = 0; ///< Desired aspect ratio of widget.
248 AspectFlags aspect_flags = AspectFlags::ResizeX; ///< Which dimensions can be resized.
250 int pos_x; ///< Horizontal position of top-left corner of the widget in the window.
251 int pos_y; ///< Vertical position of top-left corner of the widget in the window.
253 RectPadding padding; ///< Padding added to the widget. Managed by parent container widget. (parent container may swap left and right for RTL)
254 RectPadding uz_padding; ///< Unscaled padding, for resize calculation.
256 NWidgetBase *parent; ///< Parent widget of this widget, automatically filled in when added to container.
258 protected:
259 inline void StoreSizePosition(SizingType sizing, int x, int y, uint given_width, uint given_height);
263 * Get the horizontal sizing step.
264 * @param sizing Type of resize being performed.
266 inline uint NWidgetBase::GetHorizontalStepSize(SizingType sizing) const
268 return (sizing == ST_RESIZE) ? this->resize_x : this->fill_x;
272 * Get the vertical sizing step.
273 * @param sizing Type of resize being performed.
275 inline uint NWidgetBase::GetVerticalStepSize(SizingType sizing) const
277 return (sizing == ST_RESIZE) ? this->resize_y : this->fill_y;
281 * Store size and position.
282 * @param sizing Type of resizing to perform.
283 * @param x Horizontal offset of the widget relative to the left edge of the window.
284 * @param y Vertical offset of the widget relative to the top edge of the window.
285 * @param given_width Width allocated to the widget.
286 * @param given_height Height allocated to the widget.
288 inline void NWidgetBase::StoreSizePosition(SizingType sizing, int x, int y, uint given_width, uint given_height)
290 this->pos_x = x;
291 this->pos_y = y;
292 if (sizing == ST_SMALLEST) {
293 this->smallest_x = given_width;
294 this->smallest_y = given_height;
296 this->current_x = given_width;
297 this->current_y = given_height;
302 * Base class for a resizable nested widget.
303 * @ingroup NestedWidgets
305 class NWidgetResizeBase : public NWidgetBase {
306 public:
307 NWidgetResizeBase(WidgetType tp, uint fill_x, uint fill_y);
309 void AdjustPaddingForZoom() override;
310 void SetMinimalSize(uint min_x, uint min_y);
311 void SetMinimalSizeAbsolute(uint min_x, uint min_y);
312 void SetMinimalTextLines(uint8_t min_lines, uint8_t spacing, FontSize size);
313 void SetFill(uint fill_x, uint fill_y);
314 void SetResize(uint resize_x, uint resize_y);
315 void SetAspect(float ratio, AspectFlags flags = AspectFlags::ResizeX);
316 void SetAspect(int x_ratio, int y_ratio, AspectFlags flags = AspectFlags::ResizeX);
318 bool UpdateMultilineWidgetSize(const std::string &str, int max_lines);
319 bool UpdateSize(uint min_x, uint min_y);
320 bool UpdateVerticalSize(uint min_y);
322 void AssignSizePosition(SizingType sizing, int x, int y, uint given_width, uint given_height, bool rtl) override;
324 uint min_x; ///< Minimal horizontal size of only this widget.
325 uint min_y; ///< Minimal vertical size of only this widget.
327 bool absolute; ///< Set if minimum size is fixed and should not be resized.
328 uint uz_min_x; ///< Unscaled Minimal horizontal size of only this widget.
329 uint uz_min_y; ///< Unscaled Minimal vertical size of only this widget.
331 uint8_t uz_text_lines; ///< 'Unscaled' text lines, stored for resize calculation.
332 uint8_t uz_text_spacing; ///< 'Unscaled' text padding, stored for resize calculation.
333 FontSize uz_text_size; ///< 'Unscaled' font size, stored for resize calculation.
336 /** Nested widget flags that affect display and interaction with 'real' widgets. */
337 enum NWidgetDisplay {
338 /* Generic. */
339 NDB_LOWERED = 0, ///< Widget is lowered (pressed down) bit.
340 NDB_DISABLED = 1, ///< Widget is disabled (greyed out) bit.
341 /* Viewport widget. */
342 NDB_NO_TRANSPARENCY = 2, ///< Viewport is never transparent.
343 NDB_SHADE_GREY = 3, ///< Shade viewport to grey-scale.
344 NDB_SHADE_DIMMED = 4, ///< Display dimmed colours in the viewport.
345 /* Button dropdown widget. */
346 NDB_DROPDOWN_ACTIVE = 5, ///< Dropdown menu of the button dropdown widget is active. @see #NWID_BUTTON_DROPDOWN
347 /* Scrollbar widget. */
348 NDB_SCROLLBAR_UP = 6, ///< Up-button is lowered bit.
349 NDB_SCROLLBAR_DOWN = 7, ///< Down-button is lowered bit.
350 /* Generic. */
351 NDB_HIGHLIGHT = 8, ///< Highlight of widget is on.
352 NDB_DROPDOWN_CLOSED = 9, ///< Dropdown menu of the dropdown widget has closed.
354 ND_LOWERED = 1 << NDB_LOWERED, ///< Bit value of the lowered flag.
355 ND_DISABLED = 1 << NDB_DISABLED, ///< Bit value of the disabled flag.
356 ND_HIGHLIGHT = 1 << NDB_HIGHLIGHT, ///< Bit value of the highlight flag.
357 ND_NO_TRANSPARENCY = 1 << NDB_NO_TRANSPARENCY, ///< Bit value of the 'no transparency' flag.
358 ND_SHADE_GREY = 1 << NDB_SHADE_GREY, ///< Bit value of the 'shade to grey' flag.
359 ND_SHADE_DIMMED = 1 << NDB_SHADE_DIMMED, ///< Bit value of the 'dimmed colours' flag.
360 ND_DROPDOWN_ACTIVE = 1 << NDB_DROPDOWN_ACTIVE, ///< Bit value of the 'dropdown active' flag.
361 ND_SCROLLBAR_UP = 1 << NDB_SCROLLBAR_UP, ///< Bit value of the 'scrollbar up' flag.
362 ND_SCROLLBAR_DOWN = 1 << NDB_SCROLLBAR_DOWN, ///< Bit value of the 'scrollbar down' flag.
363 ND_SCROLLBAR_BTN = ND_SCROLLBAR_UP | ND_SCROLLBAR_DOWN, ///< Bit value of the 'scrollbar up' or 'scrollbar down' flag.
364 ND_DROPDOWN_CLOSED = 1 << NDB_DROPDOWN_CLOSED, ///< Bit value of the 'dropdown closed' flag.
366 DECLARE_ENUM_AS_BIT_SET(NWidgetDisplay)
369 * Base class for a 'real' widget.
370 * @ingroup NestedWidgets
372 class NWidgetCore : public NWidgetResizeBase {
373 public:
374 NWidgetCore(WidgetType tp, Colours colour, WidgetID index, uint fill_x, uint fill_y, uint32_t widget_data, StringID tool_tip);
376 void SetDataTip(uint32_t widget_data, StringID tool_tip);
377 void SetToolTip(StringID tool_tip);
378 void SetTextStyle(TextColour colour, FontSize size);
379 void SetAlignment(StringAlignment align);
381 inline void SetLowered(bool lowered);
382 inline bool IsLowered() const;
383 inline void SetDisabled(bool disabled);
384 inline bool IsDisabled() const;
386 void FillWidgetLookup(WidgetLookup &widget_lookup) override;
387 NWidgetCore *GetWidgetFromPos(int x, int y) override;
388 bool IsHighlighted() const override;
389 TextColour GetHighlightColour() const override;
390 void SetHighlighted(TextColour highlight_colour) override;
392 NWidgetDisplay disp_flags; ///< Flags that affect display and interaction with the widget.
393 Colours colour; ///< Colour of this widget.
394 const WidgetID index; ///< Index of the nested widget (\c -1 means 'not used').
395 uint32_t widget_data; ///< Data of the widget. @see Widget::data
396 StringID tool_tip; ///< Tooltip of the widget. @see Widget::tootips
397 WidgetID scrollbar_index; ///< Index of an attached scrollbar.
398 TextColour highlight_colour; ///< Colour of highlight.
399 TextColour text_colour; ///< Colour of text within widget.
400 FontSize text_size; ///< Size of text within widget.
401 StringAlignment align; ///< Alignment of text/image within widget.
405 * Highlight the widget or not.
406 * @param highlight_colour Widget must be highlighted (blink).
408 inline void NWidgetCore::SetHighlighted(TextColour highlight_colour)
410 this->disp_flags = highlight_colour != TC_INVALID ? SETBITS(this->disp_flags, ND_HIGHLIGHT) : CLRBITS(this->disp_flags, ND_HIGHLIGHT);
411 this->highlight_colour = highlight_colour;
414 /** Return whether the widget is highlighted. */
415 inline bool NWidgetCore::IsHighlighted() const
417 return HasBit(this->disp_flags, NDB_HIGHLIGHT);
420 /** Return the colour of the highlight. */
421 inline TextColour NWidgetCore::GetHighlightColour() const
423 return this->highlight_colour;
427 * Lower or raise the widget.
428 * @param lowered Widget must be lowered (drawn pressed down).
430 inline void NWidgetCore::SetLowered(bool lowered)
432 this->disp_flags = lowered ? SETBITS(this->disp_flags, ND_LOWERED) : CLRBITS(this->disp_flags, ND_LOWERED);
435 /** Return whether the widget is lowered. */
436 inline bool NWidgetCore::IsLowered() const
438 return HasBit(this->disp_flags, NDB_LOWERED);
442 * Disable (grey-out) or enable the widget.
443 * @param disabled Widget must be disabled.
445 inline void NWidgetCore::SetDisabled(bool disabled)
447 this->disp_flags = disabled ? SETBITS(this->disp_flags, ND_DISABLED) : CLRBITS(this->disp_flags, ND_DISABLED);
450 /** Return whether the widget is disabled. */
451 inline bool NWidgetCore::IsDisabled() const
453 return HasBit(this->disp_flags, NDB_DISABLED);
458 * Baseclass for container widgets.
459 * @ingroup NestedWidgets
461 class NWidgetContainer : public NWidgetBase {
462 public:
463 NWidgetContainer(WidgetType tp) : NWidgetBase(tp) { }
465 void AdjustPaddingForZoom() override;
466 void Add(std::unique_ptr<NWidgetBase> &&wid);
467 void FillWidgetLookup(WidgetLookup &widget_lookup) override;
469 void Draw(const Window *w) override;
470 NWidgetCore *GetWidgetFromPos(int x, int y) override;
472 /** Return whether the container is empty. */
473 inline bool IsEmpty() { return this->children.empty(); }
475 NWidgetBase *GetWidgetOfType(WidgetType tp) override;
477 protected:
478 std::vector<std::unique_ptr<NWidgetBase>> children; ///< Child widgets in contaier.
481 /** Display planes with zero size for #NWidgetStacked. */
482 enum StackedZeroSizePlanes {
483 SZSP_VERTICAL = INT_MAX / 2, ///< Display plane with zero size horizontally, and filling and resizing vertically.
484 SZSP_HORIZONTAL, ///< Display plane with zero size vertically, and filling and resizing horizontally.
485 SZSP_NONE, ///< Display plane with zero size in both directions (none filling and resizing).
487 SZSP_BEGIN = SZSP_VERTICAL, ///< First zero-size plane.
491 * Stacked widgets, widgets all occupying the same space in the window.
492 * #NWID_SELECTION allows for selecting one of several panels (planes) to tbe displayed. All planes must have the same size.
493 * Since all planes are also initialized, switching between different planes can be done while the window is displayed.
495 * There are also a number of special planes (defined in #StackedZeroSizePlanes) that have zero size in one direction (and are stretchable in
496 * the other direction) or have zero size in both directions. They are used to make all child planes of the widget disappear.
497 * 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
498 * a #Window::ReInit() is needed to re-initialize the window since its size changes.
500 class NWidgetStacked : public NWidgetContainer {
501 public:
502 NWidgetStacked(WidgetID index);
504 void AdjustPaddingForZoom() override;
505 void SetupSmallestSize(Window *w) override;
506 void AssignSizePosition(SizingType sizing, int x, int y, uint given_width, uint given_height, bool rtl) override;
507 void FillWidgetLookup(WidgetLookup &widget_lookup) override;
509 void Draw(const Window *w) override;
510 NWidgetCore *GetWidgetFromPos(int x, int y) override;
512 bool SetDisplayedPlane(int plane);
514 int shown_plane; ///< Plane being displayed (for #NWID_SELECTION only).
515 const WidgetID index; ///< If non-negative, index in the #Window::widget_lookup.
516 private:
517 WidgetLookup *widget_lookup; ///< Window's widget lookup, updated in SetDisplayedPlane().
520 /** Nested widget container flags, */
521 enum NWidContainerFlags {
522 NCB_EQUALSIZE = 0, ///< Containers should keep all their (resizing) children equally large.
523 NCB_BIGFIRST = 1, ///< Allocate space to biggest resize first.
525 NC_NONE = 0, ///< All flags cleared.
526 NC_EQUALSIZE = 1 << NCB_EQUALSIZE, ///< Value of the #NCB_EQUALSIZE flag.
527 NC_BIGFIRST = 1 << NCB_BIGFIRST, ///< Value of the #NCB_BIGFIRST flag.
529 DECLARE_ENUM_AS_BIT_SET(NWidContainerFlags)
531 /** Container with pre/inter/post child space. */
532 class NWidgetPIPContainer : public NWidgetContainer {
533 public:
534 NWidgetPIPContainer(WidgetType tp, NWidContainerFlags flags = NC_NONE);
536 void AdjustPaddingForZoom() override;
537 void SetPIP(uint8_t pip_pre, uint8_t pip_inter, uint8_t pip_post);
538 void SetPIPRatio(uint8_t pip_ratio_pre, uint8_t pip_ratio_inter, uint8_t pip_rato_post);
540 protected:
541 NWidContainerFlags flags; ///< Flags of the container.
542 uint8_t pip_pre; ///< Amount of space before first widget.
543 uint8_t pip_inter; ///< Amount of space between widgets.
544 uint8_t pip_post; ///< Amount of space after last widget.
545 uint8_t pip_ratio_pre; ///< Ratio of remaining space before first widget.
546 uint8_t pip_ratio_inter; ///< Ratio of remaining space between widgets.
547 uint8_t pip_ratio_post; ///< Ratio of remaining space after last widget.
549 uint8_t uz_pip_pre; ///< Unscaled space before first widget.
550 uint8_t uz_pip_inter; ///< Unscaled space between widgets.
551 uint8_t uz_pip_post; ///< Unscaled space after last widget.
553 uint8_t gaps; ///< Number of gaps between widgets.
557 * Horizontal container.
558 * @ingroup NestedWidgets
560 class NWidgetHorizontal : public NWidgetPIPContainer {
561 public:
562 NWidgetHorizontal(NWidContainerFlags flags = NC_NONE);
564 void SetupSmallestSize(Window *w) override;
565 void AssignSizePosition(SizingType sizing, int x, int y, uint given_width, uint given_height, bool rtl) override;
569 * Horizontal container that doesn't change the direction of the widgets for RTL languages.
570 * @ingroup NestedWidgets
572 class NWidgetHorizontalLTR : public NWidgetHorizontal {
573 public:
574 NWidgetHorizontalLTR(NWidContainerFlags flags = NC_NONE);
576 void AssignSizePosition(SizingType sizing, int x, int y, uint given_width, uint given_height, bool rtl) override;
580 * Vertical container.
581 * @ingroup NestedWidgets
583 class NWidgetVertical : public NWidgetPIPContainer {
584 public:
585 NWidgetVertical(NWidContainerFlags flags = NC_NONE);
587 void SetupSmallestSize(Window *w) override;
588 void AssignSizePosition(SizingType sizing, int x, int y, uint given_width, uint given_height, bool rtl) override;
592 * Matrix container with implicitly equal sized (virtual) sub-widgets.
593 * This widget must have exactly one sub-widget. After that this sub-widget
594 * is used to draw all of the data within the matrix piece by piece.
595 * DrawWidget and OnClick calls will be done to that sub-widget, where the
596 * 16 high bits are used to encode the index into the matrix.
597 * @ingroup NestedWidgets
599 class NWidgetMatrix : public NWidgetPIPContainer {
600 public:
601 NWidgetMatrix(Colours colour, WidgetID index);
603 void SetClicked(int clicked);
604 void SetCount(int count);
605 void SetScrollbar(Scrollbar *sb);
606 int GetCurrentElement() const;
608 void SetupSmallestSize(Window *w) override;
609 void AssignSizePosition(SizingType sizing, int x, int y, uint given_width, uint given_height, bool rtl) override;
610 void FillWidgetLookup(WidgetLookup &widget_lookup) override;
612 NWidgetCore *GetWidgetFromPos(int x, int y) override;
613 void Draw(const Window *w) override;
614 protected:
615 const WidgetID index; ///< If non-negative, index in the #Window::widget_lookup.
616 Colours colour; ///< Colour of this widget.
617 int clicked; ///< The currently clicked element.
618 int count; ///< Amount of valid elements.
619 int current_element; ///< The element currently being processed.
620 Scrollbar *sb; ///< The scrollbar we're associated with.
621 private:
622 int widget_w; ///< The width of the child widget including inter spacing.
623 int widget_h; ///< The height of the child widget including inter spacing.
624 int widgets_x; ///< The number of visible widgets in horizontal direction.
625 int widgets_y; ///< The number of visible widgets in vertical direction.
627 void GetScrollOffsets(int &start_x, int &start_y, int &base_offs_x, int &base_offs_y);
632 * Spacer widget.
633 * @ingroup NestedWidgets
635 class NWidgetSpacer : public NWidgetResizeBase {
636 public:
637 NWidgetSpacer(int width, int height);
639 void SetupSmallestSize(Window *w) override;
640 void FillWidgetLookup(WidgetLookup &widget_lookup) override;
642 void Draw(const Window *w) override;
643 void SetDirty(const Window *w) const override;
644 NWidgetCore *GetWidgetFromPos(int x, int y) override;
648 * Nested widget with a child.
649 * @ingroup NestedWidgets
651 class NWidgetBackground : public NWidgetCore {
652 public:
653 NWidgetBackground(WidgetType tp, Colours colour, WidgetID index, std::unique_ptr<NWidgetPIPContainer> &&child = nullptr);
655 void Add(std::unique_ptr<NWidgetBase> &&nwid);
656 void SetPIP(uint8_t pip_pre, uint8_t pip_inter, uint8_t pip_post);
657 void SetPIPRatio(uint8_t pip_ratio_pre, uint8_t pip_ratio_inter, uint8_t pip_ratio_post);
659 void AdjustPaddingForZoom() override;
660 void SetupSmallestSize(Window *w) override;
661 void AssignSizePosition(SizingType sizing, int x, int y, uint given_width, uint given_height, bool rtl) override;
663 void FillWidgetLookup(WidgetLookup &widget_lookup) override;
665 void Draw(const Window *w) override;
666 NWidgetCore *GetWidgetFromPos(int x, int y) override;
667 NWidgetBase *GetWidgetOfType(WidgetType tp) override;
669 private:
670 std::unique_ptr<NWidgetPIPContainer> child; ///< Child widget.
674 * Nested widget to display a viewport in a window.
675 * After initializing the nested widget tree, call #InitializeViewport(). After changing the window size,
676 * call #UpdateViewportCoordinates() eg from Window::OnResize().
677 * If the #disp_flags field contains the #ND_NO_TRANSPARENCY bit, the viewport will disable transparency.
678 * 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).
679 * @todo Class derives from #NWidgetCore, but does not use #colour, #widget_data, or #tool_tip.
680 * @ingroup NestedWidgets
682 class NWidgetViewport : public NWidgetCore {
683 public:
684 NWidgetViewport(WidgetID index);
686 void SetupSmallestSize(Window *w) override;
687 void Draw(const Window *w) override;
689 void InitializeViewport(Window *w, std::variant<TileIndex, VehicleID> focus, ZoomLevel zoom);
690 void UpdateViewportCoordinates(Window *w);
694 * Scrollbar data structure
696 class Scrollbar {
697 public:
698 using size_type = int32_t;
699 static constexpr size_type max_size_type = std::numeric_limits<size_type>::max();
700 static constexpr size_type npos = max_size_type;
701 private:
702 const bool is_vertical; ///< Scrollbar has vertical orientation.
703 size_type count; ///< Number of elements in the list.
704 size_type cap; ///< Number of visible elements of the scroll bar.
705 size_type pos; ///< Index of first visible item of the list.
706 size_type stepsize; ///< Distance to scroll, when pressing the buttons or using the wheel.
708 public:
709 /** Stepping sizes when scrolling */
710 enum ScrollbarStepping {
711 SS_RAW, ///< Step in single units.
712 SS_SMALL, ///< Step in #stepsize units.
713 SS_BIG, ///< Step in #cap units.
716 Scrollbar(bool is_vertical) : is_vertical(is_vertical), stepsize(1)
721 * Gets the number of elements in the list
722 * @return the number of elements
724 inline size_type GetCount() const
726 return this->count;
730 * Gets the number of visible elements of the scrollbar
731 * @return the number of visible elements
733 inline size_type GetCapacity() const
735 return this->cap;
739 * Gets the position of the first visible element in the list
740 * @return the position of the element
742 inline size_type GetPosition() const
744 return this->pos;
748 * Checks whether given current item is visible in the list
749 * @param item to check
750 * @return true iff the item is visible
752 inline bool IsVisible(size_type item) const
754 return IsInsideBS(item, this->GetPosition(), this->GetCapacity());
758 * Is the scrollbar vertical or not?
759 * @return True iff the scrollbar is vertical.
761 inline bool IsVertical() const
763 return this->is_vertical;
767 * Set the distance to scroll when using the buttons or the wheel.
768 * @param stepsize Scrolling speed.
770 void SetStepSize(size_t stepsize)
772 assert(stepsize > 0);
774 this->stepsize = ClampTo<size_type>(stepsize);
778 * Sets the number of elements in the list
779 * @param num the number of elements in the list
780 * @note updates the position if needed
782 void SetCount(size_t num)
784 assert(num < Scrollbar::max_size_type);
786 this->count = ClampTo<size_type>(num);
787 /* Ensure position is within bounds */
788 this->SetPosition(this->pos);
792 * Set the capacity of visible elements.
793 * @param capacity the new capacity
794 * @note updates the position if needed
796 void SetCapacity(size_t capacity)
798 assert(capacity < Scrollbar::max_size_type);
800 this->cap = ClampTo<size_type>(capacity);
801 /* Ensure position is within bounds */
802 this->SetPosition(this->pos);
805 void SetCapacityFromWidget(Window *w, WidgetID widget, int padding = 0);
808 * Sets the position of the first visible element
809 * @param position the position of the element
810 * @return true iff the position has changed
812 bool SetPosition(size_type position)
814 size_type old_pos = this->pos;
815 this->pos = Clamp(position, 0, std::max(this->count - this->cap, 0));
816 return this->pos != old_pos;
820 * Updates the position of the first visible element by the given amount.
821 * If the position would be too low or high it will be clamped appropriately
822 * @param difference the amount of change requested
823 * @param unit The stepping unit of \a difference
824 * @return true iff the position has changed
826 bool UpdatePosition(int difference, ScrollbarStepping unit = SS_SMALL)
828 if (difference == 0) return false;
829 switch (unit) {
830 case SS_SMALL: difference *= this->stepsize; break;
831 case SS_BIG: difference *= this->cap; break;
832 default: break;
834 return this->SetPosition(this->pos + difference);
838 * Scroll towards the given position; if the item is visible nothing
839 * happens, otherwise it will be shown either at the bottom or top of
840 * the window depending on where in the list it was.
841 * @param position the position to scroll towards.
843 void ScrollTowards(size_type position)
845 if (position < this->GetPosition()) {
846 /* scroll up to the item */
847 this->SetPosition(position);
848 } else if (position >= this->GetPosition() + this->GetCapacity()) {
849 /* scroll down so that the item is at the bottom */
850 this->SetPosition(position - this->GetCapacity() + 1);
854 size_type GetScrolledRowFromWidget(int clickpos, const Window * const w, WidgetID widget, int padding = 0, int line_height = -1) const;
857 * Get a pair of iterators for the range of visible elements in a container.
858 * @param container Container of elements represented by the scrollbar.
859 * @returns Pair of iterators of visible elements.
861 template <typename Tcontainer>
862 auto GetVisibleRangeIterators(Tcontainer &container) const
864 assert(static_cast<size_t>(this->GetCount()) == container.size()); // Scrollbar and container size must match.
865 auto first = std::next(std::begin(container), this->GetPosition());
866 auto last = std::next(first, std::min<size_t>(this->GetCapacity(), this->GetCount() - this->GetPosition()));
867 return std::make_pair(first, last);
871 * Return an iterator pointing to the element of a scrolled widget that a user clicked in.
872 * @param container Container of elements represented by the scrollbar.
873 * @param clickpos Vertical position of the mouse click (without taking scrolling into account).
874 * @param w The window the click was in.
875 * @param widget Widget number of the widget clicked in.
876 * @param padding Amount of empty space between the widget edge and the top of the first row. Default value is \c 0.
877 * @param line_height Height of a single row. A negative value means using the vertical resize step of the widget.
878 * @return Iterator to the element clicked at. If clicked at a wrong position, returns as interator to the end of the container.
880 template <typename Tcontainer>
881 auto GetScrolledItemFromWidget(Tcontainer &container, int clickpos, const Window * const w, WidgetID widget, int padding = 0, int line_height = -1) const
883 assert(static_cast<size_t>(this->GetCount()) == container.size()); // Scrollbar and container size must match.
884 size_type row = this->GetScrolledRowFromWidget(clickpos, w, widget, padding, line_height);
885 if (row == Scrollbar::npos) return std::end(container);
887 return std::next(std::begin(container), row);
890 EventState UpdateListPositionOnKeyPress(int &list_position, uint16_t keycode) const;
894 * Nested widget to display and control a scrollbar in a window.
895 * Also assign the scrollbar to other widgets using #SetScrollbar() to make the mousewheel work.
896 * @ingroup NestedWidgets
898 class NWidgetScrollbar : public NWidgetCore, public Scrollbar {
899 public:
900 NWidgetScrollbar(WidgetType tp, Colours colour, WidgetID index);
902 void SetupSmallestSize(Window *w) override;
903 void Draw(const Window *w) override;
905 static void InvalidateDimensionCache();
906 static Dimension GetVerticalDimension();
907 static Dimension GetHorizontalDimension();
909 private:
910 static Dimension vertical_dimension; ///< Cached size of vertical scrollbar button.
911 static Dimension horizontal_dimension; ///< Cached size of horizontal scrollbar button.
915 * Leaf widget.
916 * @ingroup NestedWidgets
918 class NWidgetLeaf : public NWidgetCore {
919 public:
920 NWidgetLeaf(WidgetType tp, Colours colour, WidgetID index, uint32_t data, StringID tip);
922 void SetupSmallestSize(Window *w) override;
923 void Draw(const Window *w) override;
925 bool ButtonHit(const Point &pt);
927 static void InvalidateDimensionCache();
929 static Dimension dropdown_dimension; ///< Cached size of a dropdown widget.
930 static Dimension resizebox_dimension; ///< Cached size of a resizebox widget.
931 static Dimension closebox_dimension; ///< Cached size of a closebox widget.
932 private:
933 static Dimension shadebox_dimension; ///< Cached size of a shadebox widget.
934 static Dimension debugbox_dimension; ///< Cached size of a debugbox widget.
935 static Dimension defsizebox_dimension; ///< Cached size of a defsizebox widget.
936 static Dimension stickybox_dimension; ///< Cached size of a stickybox widget.
940 * Return the biggest possible size of a nested widget.
941 * @param base Base size of the widget.
942 * @param max_space Available space for the widget.
943 * @param step Stepsize of the widget.
944 * @return Biggest possible size of the widget, assuming that \a base may only be incremented by \a step size steps.
946 inline uint ComputeMaxSize(uint base, uint max_space, uint step)
948 if (base >= max_space || step == 0) return base;
949 if (step == 1) return max_space;
950 uint increment = max_space - base;
951 increment -= increment % step;
952 return base + increment;
956 * @defgroup NestedWidgetParts Hierarchical widget parts
957 * 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.
959 * - Leaf widgets start with a #NWidget(WidgetType tp, Colours col, int16_t idx) part.
960 * Next, specify its properties with one or more of
961 * - #SetMinimalSize Define the minimal size of the widget.
962 * - #SetFill Define how the widget may grow to make it nicely.
963 * - #SetDataTip Define the data and the tooltip of the widget.
964 * - #SetResize Define how the widget may resize.
965 * - #SetPadding Create additional space around the widget.
967 * - To insert a nested widget tree from an external source, nested widget part #NWidgetFunction exists.
968 * For further customization, the #SetPadding part may be used.
970 * - Space widgets (#NWidgetSpacer) start with a #NWidget(WidgetType tp), followed by one or more of
971 * - #SetMinimalSize Define the minimal size of the widget.
972 * - #SetFill Define how the widget may grow to make it nicely.
973 * - #SetResize Define how the widget may resize.
974 * - #SetPadding Create additional space around the widget.
976 * - Container widgets #NWidgetHorizontal, #NWidgetHorizontalLTR, #NWidgetVertical, and #NWidgetMatrix, start with a #NWidget(WidgetType tp) part.
977 * Their properties are derived from the child widgets so they cannot be specified.
978 * You can however use
979 * - #SetPadding Define additional padding around the container.
980 * - #SetPIP Set additional pre/inter/post child widget space.
982 * 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
983 * the child widgets (it has no meaning for the compiler but it makes the widget parts easier to read).
984 * Below the last child widget, use an #EndContainer part. This part should be aligned with the #NWidget part that started the container.
986 * - 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,
987 * so the widget does not support #SetPIP. #SetPadding is allowed though.
988 * Like the other container widgets, below the last child widgets, a #EndContainer part should be used to denote the end of the stacked widget.
990 * - Background widgets #NWidgetBackground start with a #NWidget(WidgetType tp, Colours col, int16_t idx) part.
991 * What follows depends on how the widget is used.
992 * - 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
993 * leaf widgets to define how it behaves.
994 * - 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
995 * behaviour.
997 * In both cases, the background widget \b MUST end with a #EndContainer widget part.
999 * @see NestedWidgets
1003 * Widget part for storing data and tooltip information.
1004 * @ingroup NestedWidgetParts
1006 struct NWidgetPartDataTip {
1007 uint32_t data; ///< Data value of the widget.
1008 StringID tooltip; ///< Tooltip of the widget.
1012 * Widget part for storing basic widget information.
1013 * @ingroup NestedWidgetParts
1015 struct NWidgetPartWidget {
1016 Colours colour; ///< Widget colour.
1017 WidgetID index; ///< Index of the widget.
1021 * Widget part for storing padding.
1022 * @ingroup NestedWidgetParts
1024 struct NWidgetPartPaddings : RectPadding {
1028 * Widget part for storing pre/inter/post spaces.
1029 * @ingroup NestedWidgetParts
1031 struct NWidgetPartPIP {
1032 uint8_t pre, inter, post; ///< Amount of space before/between/after child widgets.
1036 * Widget part for storing minimal text line data.
1037 * @ingroup NestedWidgetParts
1039 struct NWidgetPartTextLines {
1040 uint8_t lines; ///< Number of text lines.
1041 uint8_t spacing; ///< Extra spacing around lines.
1042 FontSize size; ///< Font size of text lines.
1046 * Widget part for storing text colour.
1047 * @ingroup NestedWidgetParts
1049 struct NWidgetPartTextStyle {
1050 TextColour colour; ///< TextColour for DrawString.
1051 FontSize size; ///< Font size of text.
1055 * Widget part for setting text/image alignment within a widget.
1056 * @ingroup NestedWidgetParts
1058 struct NWidgetPartAlignment {
1059 StringAlignment align; ///< Alignment of text/image.
1062 struct NWidgetPartAspect {
1063 float ratio;
1064 AspectFlags flags;
1068 * Pointer to function returning a nested widget.
1069 * @return Nested widget (tree).
1071 typedef std::unique_ptr<NWidgetBase> NWidgetFunctionType();
1074 * Partial widget specification to allow NWidgets to be written nested.
1075 * @ingroup NestedWidgetParts
1077 struct NWidgetPart {
1078 WidgetType type; ///< Type of the part. @see NWidgetPartType.
1079 union NWidgetPartUnion {
1080 Point xy; ///< Part with an x/y size.
1081 NWidgetPartDataTip data_tip; ///< Part with a data/tooltip.
1082 NWidgetPartWidget widget; ///< Part with a start of a widget.
1083 NWidgetPartPaddings padding; ///< Part with paddings.
1084 NWidgetPartPIP pip; ///< Part with pre/inter/post spaces.
1085 NWidgetPartTextLines text_lines; ///< Part with text line data.
1086 NWidgetPartTextStyle text_style; ///< Part with text style data.
1087 NWidgetPartAlignment align; ///< Part with internal alignment.
1088 NWidgetFunctionType *func_ptr; ///< Part with a function call.
1089 NWidContainerFlags cont_flags; ///< Part with container flags.
1090 NWidgetPartAspect aspect; ///< Part to set aspect ratio.
1092 /* Constructors for each NWidgetPartUnion data type. */
1093 constexpr NWidgetPartUnion() : xy() {}
1094 constexpr NWidgetPartUnion(Point xy) : xy(xy) {}
1095 constexpr NWidgetPartUnion(NWidgetPartDataTip data_tip) : data_tip(data_tip) {}
1096 constexpr NWidgetPartUnion(NWidgetPartWidget widget) : widget(widget) {}
1097 constexpr NWidgetPartUnion(NWidgetPartPaddings padding) : padding(padding) {}
1098 constexpr NWidgetPartUnion(NWidgetPartPIP pip) : pip(pip) {}
1099 constexpr NWidgetPartUnion(NWidgetPartTextLines text_lines) : text_lines(text_lines) {}
1100 constexpr NWidgetPartUnion(NWidgetPartTextStyle text_style) : text_style(text_style) {}
1101 constexpr NWidgetPartUnion(NWidgetPartAlignment align) : align(align) {}
1102 constexpr NWidgetPartUnion(NWidgetFunctionType *func_ptr) : func_ptr(func_ptr) {}
1103 constexpr NWidgetPartUnion(NWidContainerFlags cont_flags) : cont_flags(cont_flags) {}
1104 constexpr NWidgetPartUnion(NWidgetPartAspect aspect) : aspect(aspect) {}
1105 } u;
1107 /* Constructors for each NWidgetPart data type. */
1108 explicit constexpr NWidgetPart(WidgetType type) : type(type), u() {}
1109 constexpr NWidgetPart(WidgetType type, Point xy) : type(type), u(xy) {}
1110 constexpr NWidgetPart(WidgetType type, NWidgetPartDataTip data_tip) : type(type), u(data_tip) {}
1111 constexpr NWidgetPart(WidgetType type, NWidgetPartWidget widget) : type(type), u(widget) {}
1112 constexpr NWidgetPart(WidgetType type, NWidgetPartPaddings padding) : type(type), u(padding) {}
1113 constexpr NWidgetPart(WidgetType type, NWidgetPartPIP pip) : type(type), u(pip) {}
1114 constexpr NWidgetPart(WidgetType type, NWidgetPartTextLines text_lines) : type(type), u(text_lines) {}
1115 constexpr NWidgetPart(WidgetType type, NWidgetPartTextStyle text_style) : type(type), u(text_style) {}
1116 constexpr NWidgetPart(WidgetType type, NWidgetPartAlignment align) : type(type), u(align) {}
1117 constexpr NWidgetPart(WidgetType type, NWidgetFunctionType *func_ptr) : type(type), u(func_ptr) {}
1118 constexpr NWidgetPart(WidgetType type, NWidContainerFlags cont_flags) : type(type), u(cont_flags) {}
1119 constexpr NWidgetPart(WidgetType type, NWidgetPartAspect aspect) : type(type), u(aspect) {}
1123 * Widget part function for setting the resize step.
1124 * @param dx Horizontal resize step. 0 means no horizontal resizing.
1125 * @param dy Vertical resize step. 0 means no vertical resizing.
1126 * @ingroup NestedWidgetParts
1128 constexpr NWidgetPart SetResize(int16_t dx, int16_t dy)
1130 return NWidgetPart{WPT_RESIZE, Point{dx, dy}};
1134 * Widget part function for setting the minimal size.
1135 * @param x Horizontal minimal size.
1136 * @param y Vertical minimal size.
1137 * @ingroup NestedWidgetParts
1139 constexpr NWidgetPart SetMinimalSize(int16_t x, int16_t y)
1141 return NWidgetPart{WPT_MINSIZE, Point{x, y}};
1145 * Widget part function for setting the minimal text lines.
1146 * @param lines Number of text lines.
1147 * @param spacing Extra spacing required.
1148 * @param size Font size of text.
1149 * @ingroup NestedWidgetParts
1151 constexpr NWidgetPart SetMinimalTextLines(uint8_t lines, uint8_t spacing, FontSize size = FS_NORMAL)
1153 return NWidgetPart{WPT_MINTEXTLINES, NWidgetPartTextLines{lines, spacing, size}};
1157 * Widget part function for setting the text style.
1158 * @param colour Colour to draw string within widget.
1159 * @param size Font size to draw string within widget.
1160 * @ingroup NestedWidgetParts
1162 constexpr NWidgetPart SetTextStyle(TextColour colour, FontSize size = FS_NORMAL)
1164 return NWidgetPart{WPT_TEXTSTYLE, NWidgetPartTextStyle{colour, size}};
1168 * Widget part function for setting the alignment of text/images.
1169 * @param align Alignment of text/image within widget.
1170 * @ingroup NestedWidgetParts
1172 constexpr NWidgetPart SetAlignment(StringAlignment align)
1174 return NWidgetPart{WPT_ALIGNMENT, NWidgetPartAlignment{align}};
1178 * Widget part function for setting filling.
1179 * @param fill_x Horizontal filling step from minimal size.
1180 * @param fill_y Vertical filling step from minimal size.
1181 * @ingroup NestedWidgetParts
1183 constexpr NWidgetPart SetFill(uint16_t fill_x, uint16_t fill_y)
1185 return NWidgetPart{WPT_FILL, Point{fill_x, fill_y}};
1189 * Widget part function for denoting the end of a container
1190 * (horizontal, vertical, WWT_FRAME, WWT_INSET, or WWT_PANEL).
1191 * @ingroup NestedWidgetParts
1193 constexpr NWidgetPart EndContainer()
1195 return NWidgetPart{WPT_ENDCONTAINER};
1199 * Widget part function for setting the data and tooltip.
1200 * @param data Data of the widget.
1201 * @param tip Tooltip of the widget.
1202 * @ingroup NestedWidgetParts
1204 constexpr NWidgetPart SetDataTip(uint32_t data, StringID tip)
1206 return NWidgetPart{WPT_DATATIP, NWidgetPartDataTip{data, tip}};
1210 * Widget part function for setting the data and tooltip of WWT_MATRIX widgets
1211 * @param cols Number of columns. \c 0 means to use draw columns with width according to the resize step size.
1212 * @param rows Number of rows. \c 0 means to use draw rows with height according to the resize step size.
1213 * @param tip Tooltip of the widget.
1214 * @ingroup NestedWidgetParts
1216 constexpr NWidgetPart SetMatrixDataTip(uint8_t cols, uint8_t rows, StringID tip)
1218 return SetDataTip((rows << MAT_ROW_START) | (cols << MAT_COL_START), tip);
1222 * Widget part function for setting additional space around a widget.
1223 * Parameters start above the widget, and are specified in clock-wise direction.
1224 * @param top The padding above the widget.
1225 * @param right The padding right of the widget.
1226 * @param bottom The padding below the widget.
1227 * @param left The padding left of the widget.
1228 * @ingroup NestedWidgetParts
1230 constexpr NWidgetPart SetPadding(uint8_t top, uint8_t right, uint8_t bottom, uint8_t left)
1232 return NWidgetPart{WPT_PADDING, NWidgetPartPaddings{left, top, right, bottom}};
1236 * Widget part function for setting additional space around a widget.
1237 * @param r The padding around the widget.
1238 * @ingroup NestedWidgetParts
1240 constexpr NWidgetPart SetPadding(const RectPadding &padding)
1242 return NWidgetPart{WPT_PADDING, NWidgetPartPaddings{padding}};
1246 * Widget part function for setting a padding.
1247 * @param padding The padding to use for all directions.
1248 * @ingroup NestedWidgetParts
1250 constexpr NWidgetPart SetPadding(uint8_t padding)
1252 return SetPadding(padding, padding, padding, padding);
1256 * Widget part function for setting a pre/inter/post spaces.
1257 * @param pre The amount of space before the first widget.
1258 * @param inter The amount of space between widgets.
1259 * @param post The amount of space after the last widget.
1260 * @ingroup NestedWidgetParts
1262 constexpr NWidgetPart SetPIP(uint8_t pre, uint8_t inter, uint8_t post)
1264 return NWidgetPart{WPT_PIPSPACE, NWidgetPartPIP{pre, inter, post}};
1268 * Widget part function for setting a pre/inter/post ratio.
1269 * @param pre The ratio of space before the first widget.
1270 * @param inter The ratio of space between widgets.
1271 * @param post The ratio of space after the last widget.
1272 * @ingroup NestedWidgetParts
1274 constexpr NWidgetPart SetPIPRatio(uint8_t ratio_pre, uint8_t ratio_inter, uint8_t ratio_post)
1276 return NWidgetPart{WPT_PIPRATIO, NWidgetPartPIP{ratio_pre, ratio_inter, ratio_post}};
1280 * Attach a scrollbar to a widget.
1281 * The scrollbar is controlled when using the mousewheel on the widget.
1282 * Multiple widgets can refer to the same scrollbar to make the mousewheel work in all of them.
1283 * @param index Widget index of the scrollbar.
1284 * @ingroup NestedWidgetParts
1286 constexpr NWidgetPart SetScrollbar(WidgetID index)
1288 return NWidgetPart{WPT_SCROLLBAR, NWidgetPartWidget{INVALID_COLOUR, index}};
1292 * Widget part function for setting the aspect ratio.
1293 * @param ratio Desired aspect ratio, or 0 for none.
1294 * @param flags Dimensions which should be resized.
1295 * @ingroup NestedWidgetParts
1297 constexpr NWidgetPart SetAspect(float ratio, AspectFlags flags = AspectFlags::ResizeX)
1299 return NWidgetPart{WPT_ASPECT, NWidgetPartAspect{ratio, flags}};
1303 * Widget part function for starting a new 'real' widget.
1304 * @param tp Type of the new nested widget.
1305 * @param col Colour of the new widget.
1306 * @param idx Index of the widget.
1307 * @note with #WWT_PANEL, #WWT_FRAME, #WWT_INSET, a new container is started.
1308 * Child widgets must have a index bigger than the parent index.
1309 * @ingroup NestedWidgetParts
1311 constexpr NWidgetPart NWidget(WidgetType tp, Colours col, WidgetID idx = -1)
1313 return NWidgetPart{tp, NWidgetPartWidget{col, idx}};
1317 * Widget part function for starting a new horizontal container, vertical container, or spacer widget.
1318 * @param tp Type of the new nested widget, #NWID_HORIZONTAL, #NWID_VERTICAL, #NWID_SPACER, #NWID_SELECTION, and #NWID_MATRIX.
1319 * @param cont_flags Flags for the containers (#NWID_HORIZONTAL and #NWID_VERTICAL).
1320 * @ingroup NestedWidgetParts
1322 constexpr NWidgetPart NWidget(WidgetType tp, NWidContainerFlags cont_flags = NC_NONE)
1324 return NWidgetPart{tp, NWidContainerFlags{cont_flags}};
1328 * Obtain a nested widget (sub)tree from an external source.
1329 * @param func_ptr Pointer to function that returns the tree.
1330 * @ingroup NestedWidgetParts
1332 constexpr NWidgetPart NWidgetFunction(NWidgetFunctionType *func_ptr)
1334 return NWidgetPart{WPT_FUNCTION, func_ptr};
1337 bool IsContainerWidgetType(WidgetType tp);
1338 std::unique_ptr<NWidgetBase> MakeNWidgets(std::span<const NWidgetPart> nwid_parts, std::unique_ptr<NWidgetBase> &&container);
1339 std::unique_ptr<NWidgetBase> MakeWindowNWidgetTree(std::span<const NWidgetPart> nwid_parts, NWidgetStacked **shade_select);
1341 std::unique_ptr<NWidgetBase> MakeCompanyButtonRows(WidgetID widget_first, WidgetID widget_last, Colours button_colour, int max_length, StringID button_tooltip, bool resizable = true);
1343 void SetupWidgetDimensions();
1345 #endif /* WIDGET_TYPE_H */