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/>.
8 /** @file widget_type.h Definitions about widgets. */
13 #include "core/alloc_type.hpp"
14 #include "core/bitmath_func.hpp"
15 #include "core/math_func.hpp"
16 #include "strings_type.h"
18 #include "window_type.h"
20 /** Bits of the #WWT_MATRIX widget data. */
21 /* Number of column bits of the WWT_MATRIX widget data. */
22 static constexpr uint8_t MAT_COL_START
= 0; ///< Lowest bit of the number of columns.
23 static constexpr uint8_t MAT_COL_BITS
= 8; ///< Number of bits for the number of columns in the matrix.
25 /* Number of row bits of the WWT_MATRIX widget data. */
26 static constexpr uint8_t MAT_ROW_START
= 8; ///< Lowest bit of the number of rows.
27 static constexpr uint8_t MAT_ROW_BITS
= 8; ///< Number of bits for the number of rows in the matrix.
29 /** Values for an arrow widget */
30 enum ArrowWidgetValues
{
31 AWV_DECREASE
, ///< Arrow to the left or in case of RTL to the right
32 AWV_INCREASE
, ///< Arrow to the right or in case of RTL to the left
33 AWV_LEFT
, ///< Force the arrow to the left
34 AWV_RIGHT
, ///< Force the arrow to the right
37 /** WidgetData values for a resize box widget. */
38 enum ResizeWidgetValues
{
39 RWV_SHOW_BEVEL
, ///< Bevel of resize box is shown.
40 RWV_HIDE_BEVEL
, ///< Bevel of resize box is hidden.
44 * Window widget types, nested widget types, and nested widget part types.
47 /* Window widget types. */
48 WWT_EMPTY
, ///< Empty widget, place holder to reserve space in widget tree.
50 WWT_PANEL
, ///< Simple depressed panel
51 WWT_INSET
, ///< Pressed (inset) panel, most commonly used as combo box _text_ area
52 WWT_IMGBTN
, ///< (Toggle) Button with image
53 WWT_IMGBTN_2
, ///< (Toggle) Button with diff image when clicked
54 WWT_ARROWBTN
, ///< (Toggle) Button with an arrow
55 WWT_TEXTBTN
, ///< (Toggle) Button with text
56 WWT_TEXTBTN_2
, ///< (Toggle) Button with diff text when clicked
57 WWT_LABEL
, ///< Centered label
58 WWT_TEXT
, ///< Pure simple text
59 WWT_MATRIX
, ///< Grid of rows and columns. @see MatrixWidgetValues
61 WWT_CAPTION
, ///< Window caption (window title between closebox and stickybox)
63 WWT_DEBUGBOX
, ///< NewGRF debug box (at top-right of a window, between WWT_CAPTION and WWT_SHADEBOX)
64 WWT_SHADEBOX
, ///< Shade box (at top-right of a window, between WWT_DEBUGBOX and WWT_DEFSIZEBOX)
65 WWT_DEFSIZEBOX
, ///< Default window size box (at top-right of a window, between WWT_SHADEBOX and WWT_STICKYBOX)
66 WWT_STICKYBOX
, ///< Sticky box (at top-right of a window, after WWT_DEFSIZEBOX)
68 WWT_RESIZEBOX
, ///< Resize box (normally at bottom-right of a window)
69 WWT_CLOSEBOX
, ///< Close box (at top-left of a window)
70 WWT_DROPDOWN
, ///< Drop down list
71 WWT_EDITBOX
, ///< a textbox for typing
72 WWT_LAST
, ///< Last Item. use WIDGETS_END to fill up padding!!
74 /* Nested widget types. */
75 NWID_HORIZONTAL
, ///< Horizontal container.
76 NWID_HORIZONTAL_LTR
, ///< Horizontal container that doesn't change the order of the widgets for RTL languages.
77 NWID_VERTICAL
, ///< Vertical container.
78 NWID_MATRIX
, ///< Matrix container.
79 NWID_SPACER
, ///< Invisible widget that takes some space.
80 NWID_SELECTION
, ///< Stacked widgets, only one visible at a time (eg in a panel with tabs).
81 NWID_VIEWPORT
, ///< Nested widget containing a viewport.
82 NWID_BUTTON_DROPDOWN
, ///< Button with a drop-down.
83 NWID_HSCROLLBAR
, ///< Horizontal scrollbar
84 NWID_VSCROLLBAR
, ///< Vertical scrollbar
85 NWID_CUSTOM
, ///< General Custom widget.
87 /* Nested widget part types. */
88 WPT_ATTRIBUTE_BEGIN
, ///< Begin marker for attribute NWidgetPart types.
89 WPT_RESIZE
, ///< Widget part for specifying resizing.
90 WPT_MINSIZE
, ///< Widget part for specifying minimal size.
91 WPT_MINTEXTLINES
, ///< Widget part for specifying minimal number of lines of text.
92 WPT_FILL
, ///< Widget part for specifying fill.
93 WPT_DATATIP
, ///< Widget part for specifying data and tooltip.
94 WPT_PADDING
, ///< Widget part for specifying a padding.
95 WPT_PIPSPACE
, ///< Widget part for specifying pre/inter/post space for containers.
96 WPT_PIPRATIO
, ///< Widget part for specifying pre/inter/post ratio for containers.
97 WPT_TEXTSTYLE
, ///< Widget part for specifying text colour.
98 WPT_ALIGNMENT
, ///< Widget part for specifying text/image alignment.
99 WPT_SCROLLBAR
, ///< Widget part for attaching a scrollbar.
100 WPT_ASPECT
, ///< Widget part for sepcifying aspect ratio.
101 WPT_ATTRIBUTE_END
, ///< End marker for attribute NWidgetPart types.
103 WPT_FUNCTION
, ///< Widget part for calling a user function.
104 WPT_ENDCONTAINER
, ///< Widget part to denote end of a container.
106 /* Pushable window widget types. */
109 WWB_PUSHBUTTON
= 1 << 7,
111 WWT_PUSHBTN
= WWT_PANEL
| WWB_PUSHBUTTON
, ///< Normal push-button (no toggle button) with custom drawing
112 WWT_PUSHTXTBTN
= WWT_TEXTBTN
| WWB_PUSHBUTTON
, ///< Normal push-button (no toggle button) with text caption
113 WWT_PUSHIMGBTN
= WWT_IMGBTN
| WWB_PUSHBUTTON
, ///< Normal push-button (no toggle button) with image caption
114 WWT_PUSHARROWBTN
= WWT_ARROWBTN
| WWB_PUSHBUTTON
, ///< Normal push-button (no toggle button) with arrow caption
115 NWID_PUSHBUTTON_DROPDOWN
= NWID_BUTTON_DROPDOWN
| WWB_PUSHBUTTON
,
118 /** Different forms of sizing nested widgets, using NWidgetBase::AssignSizePosition() */
120 ST_SMALLEST
, ///< Initialize nested widget tree to smallest size. Also updates \e current_x and \e current_y.
121 ST_RESIZE
, ///< Resize the nested widget tree.
124 enum class AspectFlags
: uint8_t {
127 ResizeXY
= ResizeX
| ResizeY
,
129 DECLARE_ENUM_AS_BIT_SET(AspectFlags
)
131 /* Forward declarations. */
135 /** Lookup between widget IDs and NWidget objects. */
136 using WidgetLookup
= std::map
<WidgetID
, class NWidgetBase
*>;
139 * Baseclass for nested widgets.
140 * @invariant After initialization, \f$current\_x = smallest\_x + n * resize\_x, for n \geq 0\f$.
141 * @invariant After initialization, \f$current\_y = smallest\_y + m * resize\_y, for m \geq 0\f$.
142 * @ingroup NestedWidgets
144 class NWidgetBase
: public ZeroedMemoryAllocator
{
146 NWidgetBase(WidgetType tp
);
148 void ApplyAspectRatio();
149 virtual void AdjustPaddingForZoom();
150 virtual void SetupSmallestSize(Window
*w
) = 0;
151 virtual void AssignSizePosition(SizingType sizing
, int x
, int y
, uint given_width
, uint given_height
, bool rtl
) = 0;
153 virtual void FillWidgetLookup(WidgetLookup
&widget_lookup
) = 0;
155 virtual NWidgetCore
*GetWidgetFromPos(int x
, int y
) = 0;
156 virtual NWidgetBase
*GetWidgetOfType(WidgetType tp
);
159 * Get parent widget of type NWID.
160 * @tparam NWID Type of the nested widget.
161 * @returns Parent widget, or nullptr if no widget of the specified type is found.
163 template <class NWID
>
164 NWID
*GetParentWidget()
166 for (NWidgetBase
*nwid_parent
= this->parent
; nwid_parent
!= nullptr; nwid_parent
= nwid_parent
->parent
) {
167 if (NWID
*nwid
= dynamic_cast<NWID
*>(nwid_parent
); nwid
!= nullptr) return nwid
;
173 * Get parent widget of type NWID.
174 * @tparam NWID Type of the nested widget.
175 * @returns Parent widget, or nullptr if no widget of the specified type is found.
177 template <class NWID
>
178 const NWID
*GetParentWidget() const
180 for (const NWidgetBase
*nwid_parent
= this->parent
; nwid_parent
!= nullptr; nwid_parent
= nwid_parent
->parent
) {
181 if (const NWID
*nwid
= dynamic_cast<const NWID
*>(nwid_parent
); nwid
!= nullptr) return nwid
;
186 virtual bool IsHighlighted() const { return false; }
187 virtual TextColour
GetHighlightColour() const { return TC_INVALID
; }
188 virtual void SetHighlighted([[maybe_unused
]] TextColour highlight_colour
) {}
191 * Set additional space (padding) around the widget.
192 * @param top Amount of additional space above the widget.
193 * @param right Amount of additional space right of the widget.
194 * @param bottom Amount of additional space below the widget.
195 * @param left Amount of additional space left of the widget.
197 inline void SetPadding(uint8_t top
, uint8_t right
, uint8_t bottom
, uint8_t left
)
199 this->uz_padding
.top
= top
;
200 this->uz_padding
.right
= right
;
201 this->uz_padding
.bottom
= bottom
;
202 this->uz_padding
.left
= left
;
203 this->AdjustPaddingForZoom();
207 * Set additional space (padding) around the widget.
208 * @param padding Amount of padding around the widget.
210 inline void SetPadding(const RectPadding
&padding
)
212 this->uz_padding
= padding
;
213 this->AdjustPaddingForZoom();
216 inline uint
GetHorizontalStepSize(SizingType sizing
) const;
217 inline uint
GetVerticalStepSize(SizingType sizing
) const;
219 virtual void Draw(const Window
*w
) = 0;
220 virtual void SetDirty(const Window
*w
) const;
222 Rect
GetCurrentRect() const
225 r
.left
= this->pos_x
;
227 r
.right
= this->pos_x
+ this->current_x
- 1;
228 r
.bottom
= this->pos_y
+ this->current_y
- 1;
232 WidgetType type
; ///< Type of the widget / nested widget.
233 uint fill_x
; ///< Horizontal fill stepsize (from initial size, \c 0 means not resizable).
234 uint fill_y
; ///< Vertical fill stepsize (from initial size, \c 0 means not resizable).
235 uint resize_x
; ///< Horizontal resize step (\c 0 means not resizable).
236 uint resize_y
; ///< Vertical resize step (\c 0 means not resizable).
237 /* Size of the widget in the smallest window possible.
238 * Computed by #SetupSmallestSize() followed by #AssignSizePosition().
240 uint smallest_x
; ///< Smallest horizontal size of the widget in a filled window.
241 uint smallest_y
; ///< Smallest vertical size of the widget in a filled window.
242 /* Current widget size (that is, after resizing). */
243 uint current_x
; ///< Current horizontal size (after resizing).
244 uint current_y
; ///< Current vertical size (after resizing).
245 float aspect_ratio
= 0; ///< Desired aspect ratio of widget.
246 AspectFlags aspect_flags
= AspectFlags::ResizeX
; ///< Which dimensions can be resized.
248 int pos_x
; ///< Horizontal position of top-left corner of the widget in the window.
249 int pos_y
; ///< Vertical position of top-left corner of the widget in the window.
251 RectPadding padding
; ///< Padding added to the widget. Managed by parent container widget. (parent container may swap left and right for RTL)
252 RectPadding uz_padding
; ///< Unscaled padding, for resize calculation.
254 NWidgetBase
*parent
; ///< Parent widget of this widget, automatically filled in when added to container.
257 inline void StoreSizePosition(SizingType sizing
, int x
, int y
, uint given_width
, uint given_height
);
261 * Get the horizontal sizing step.
262 * @param sizing Type of resize being performed.
264 inline uint
NWidgetBase::GetHorizontalStepSize(SizingType sizing
) const
266 return (sizing
== ST_RESIZE
) ? this->resize_x
: this->fill_x
;
270 * Get the vertical sizing step.
271 * @param sizing Type of resize being performed.
273 inline uint
NWidgetBase::GetVerticalStepSize(SizingType sizing
) const
275 return (sizing
== ST_RESIZE
) ? this->resize_y
: this->fill_y
;
279 * Store size and position.
280 * @param sizing Type of resizing to perform.
281 * @param x Horizontal offset of the widget relative to the left edge of the window.
282 * @param y Vertical offset of the widget relative to the top edge of the window.
283 * @param given_width Width allocated to the widget.
284 * @param given_height Height allocated to the widget.
286 inline void NWidgetBase::StoreSizePosition(SizingType sizing
, int x
, int y
, uint given_width
, uint given_height
)
290 if (sizing
== ST_SMALLEST
) {
291 this->smallest_x
= given_width
;
292 this->smallest_y
= given_height
;
294 this->current_x
= given_width
;
295 this->current_y
= given_height
;
300 * Base class for a resizable nested widget.
301 * @ingroup NestedWidgets
303 class NWidgetResizeBase
: public NWidgetBase
{
305 NWidgetResizeBase(WidgetType tp
, uint fill_x
, uint fill_y
);
307 void AdjustPaddingForZoom() override
;
308 void SetMinimalSize(uint min_x
, uint min_y
);
309 void SetMinimalSizeAbsolute(uint min_x
, uint min_y
);
310 void SetMinimalTextLines(uint8_t min_lines
, uint8_t spacing
, FontSize size
);
311 void SetFill(uint fill_x
, uint fill_y
);
312 void SetResize(uint resize_x
, uint resize_y
);
313 void SetAspect(float ratio
, AspectFlags flags
= AspectFlags::ResizeX
);
314 void SetAspect(int x_ratio
, int y_ratio
, AspectFlags flags
= AspectFlags::ResizeX
);
316 bool UpdateMultilineWidgetSize(const std::string
&str
, int max_lines
);
317 bool UpdateSize(uint min_x
, uint min_y
);
318 bool UpdateVerticalSize(uint min_y
);
320 void AssignSizePosition(SizingType sizing
, int x
, int y
, uint given_width
, uint given_height
, bool rtl
) override
;
322 uint min_x
; ///< Minimal horizontal size of only this widget.
323 uint min_y
; ///< Minimal vertical size of only this widget.
325 bool absolute
; ///< Set if minimum size is fixed and should not be resized.
326 uint uz_min_x
; ///< Unscaled Minimal horizontal size of only this widget.
327 uint uz_min_y
; ///< Unscaled Minimal vertical size of only this widget.
329 uint8_t uz_text_lines
; ///< 'Unscaled' text lines, stored for resize calculation.
330 uint8_t uz_text_spacing
; ///< 'Unscaled' text padding, stored for resize calculation.
331 FontSize uz_text_size
; ///< 'Unscaled' font size, stored for resize calculation.
334 /** Nested widget flags that affect display and interaction with 'real' widgets. */
335 enum NWidgetDisplay
{
337 NDB_LOWERED
= 0, ///< Widget is lowered (pressed down) bit.
338 NDB_DISABLED
= 1, ///< Widget is disabled (greyed out) bit.
339 /* Viewport widget. */
340 NDB_NO_TRANSPARENCY
= 2, ///< Viewport is never transparent.
341 NDB_SHADE_GREY
= 3, ///< Shade viewport to grey-scale.
342 NDB_SHADE_DIMMED
= 4, ///< Display dimmed colours in the viewport.
343 /* Button dropdown widget. */
344 NDB_DROPDOWN_ACTIVE
= 5, ///< Dropdown menu of the button dropdown widget is active. @see #NWID_BUTTON_DROPDOWN
345 /* Scrollbar widget. */
346 NDB_SCROLLBAR_UP
= 6, ///< Up-button is lowered bit.
347 NDB_SCROLLBAR_DOWN
= 7, ///< Down-button is lowered bit.
349 NDB_HIGHLIGHT
= 8, ///< Highlight of widget is on.
350 NDB_DROPDOWN_CLOSED
= 9, ///< Dropdown menu of the dropdown widget has closed.
352 ND_LOWERED
= 1 << NDB_LOWERED
, ///< Bit value of the lowered flag.
353 ND_DISABLED
= 1 << NDB_DISABLED
, ///< Bit value of the disabled flag.
354 ND_HIGHLIGHT
= 1 << NDB_HIGHLIGHT
, ///< Bit value of the highlight flag.
355 ND_NO_TRANSPARENCY
= 1 << NDB_NO_TRANSPARENCY
, ///< Bit value of the 'no transparency' flag.
356 ND_SHADE_GREY
= 1 << NDB_SHADE_GREY
, ///< Bit value of the 'shade to grey' flag.
357 ND_SHADE_DIMMED
= 1 << NDB_SHADE_DIMMED
, ///< Bit value of the 'dimmed colours' flag.
358 ND_DROPDOWN_ACTIVE
= 1 << NDB_DROPDOWN_ACTIVE
, ///< Bit value of the 'dropdown active' flag.
359 ND_SCROLLBAR_UP
= 1 << NDB_SCROLLBAR_UP
, ///< Bit value of the 'scrollbar up' flag.
360 ND_SCROLLBAR_DOWN
= 1 << NDB_SCROLLBAR_DOWN
, ///< Bit value of the 'scrollbar down' flag.
361 ND_SCROLLBAR_BTN
= ND_SCROLLBAR_UP
| ND_SCROLLBAR_DOWN
, ///< Bit value of the 'scrollbar up' or 'scrollbar down' flag.
362 ND_DROPDOWN_CLOSED
= 1 << NDB_DROPDOWN_CLOSED
, ///< Bit value of the 'dropdown closed' flag.
364 DECLARE_ENUM_AS_BIT_SET(NWidgetDisplay
)
367 * Base class for a 'real' widget.
368 * @ingroup NestedWidgets
370 class NWidgetCore
: public NWidgetResizeBase
{
372 NWidgetCore(WidgetType tp
, Colours colour
, WidgetID index
, uint fill_x
, uint fill_y
, uint32_t widget_data
, StringID tool_tip
);
374 void SetDataTip(uint32_t widget_data
, StringID tool_tip
);
375 void SetToolTip(StringID tool_tip
);
376 void SetTextStyle(TextColour colour
, FontSize size
);
377 void SetAlignment(StringAlignment align
);
379 inline void SetLowered(bool lowered
);
380 inline bool IsLowered() const;
381 inline void SetDisabled(bool disabled
);
382 inline bool IsDisabled() const;
384 void FillWidgetLookup(WidgetLookup
&widget_lookup
) override
;
385 NWidgetCore
*GetWidgetFromPos(int x
, int y
) override
;
386 bool IsHighlighted() const override
;
387 TextColour
GetHighlightColour() const override
;
388 void SetHighlighted(TextColour highlight_colour
) override
;
390 NWidgetDisplay disp_flags
; ///< Flags that affect display and interaction with the widget.
391 Colours colour
; ///< Colour of this widget.
392 const WidgetID index
; ///< Index of the nested widget (\c -1 means 'not used').
393 uint32_t widget_data
; ///< Data of the widget. @see Widget::data
394 StringID tool_tip
; ///< Tooltip of the widget. @see Widget::tootips
395 WidgetID scrollbar_index
; ///< Index of an attached scrollbar.
396 TextColour highlight_colour
; ///< Colour of highlight.
397 TextColour text_colour
; ///< Colour of text within widget.
398 FontSize text_size
; ///< Size of text within widget.
399 StringAlignment align
; ///< Alignment of text/image within widget.
403 * Highlight the widget or not.
404 * @param highlight_colour Widget must be highlighted (blink).
406 inline void NWidgetCore::SetHighlighted(TextColour highlight_colour
)
408 this->disp_flags
= highlight_colour
!= TC_INVALID
? SETBITS(this->disp_flags
, ND_HIGHLIGHT
) : CLRBITS(this->disp_flags
, ND_HIGHLIGHT
);
409 this->highlight_colour
= highlight_colour
;
412 /** Return whether the widget is highlighted. */
413 inline bool NWidgetCore::IsHighlighted() const
415 return HasBit(this->disp_flags
, NDB_HIGHLIGHT
);
418 /** Return the colour of the highlight. */
419 inline TextColour
NWidgetCore::GetHighlightColour() const
421 return this->highlight_colour
;
425 * Lower or raise the widget.
426 * @param lowered Widget must be lowered (drawn pressed down).
428 inline void NWidgetCore::SetLowered(bool lowered
)
430 this->disp_flags
= lowered
? SETBITS(this->disp_flags
, ND_LOWERED
) : CLRBITS(this->disp_flags
, ND_LOWERED
);
433 /** Return whether the widget is lowered. */
434 inline bool NWidgetCore::IsLowered() const
436 return HasBit(this->disp_flags
, NDB_LOWERED
);
440 * Disable (grey-out) or enable the widget.
441 * @param disabled Widget must be disabled.
443 inline void NWidgetCore::SetDisabled(bool disabled
)
445 this->disp_flags
= disabled
? SETBITS(this->disp_flags
, ND_DISABLED
) : CLRBITS(this->disp_flags
, ND_DISABLED
);
448 /** Return whether the widget is disabled. */
449 inline bool NWidgetCore::IsDisabled() const
451 return HasBit(this->disp_flags
, NDB_DISABLED
);
456 * Baseclass for container widgets.
457 * @ingroup NestedWidgets
459 class NWidgetContainer
: public NWidgetBase
{
461 NWidgetContainer(WidgetType tp
) : NWidgetBase(tp
) { }
463 void AdjustPaddingForZoom() override
;
464 void Add(std::unique_ptr
<NWidgetBase
> &&wid
);
465 void FillWidgetLookup(WidgetLookup
&widget_lookup
) override
;
467 void Draw(const Window
*w
) override
;
468 NWidgetCore
*GetWidgetFromPos(int x
, int y
) override
;
470 /** Return whether the container is empty. */
471 inline bool IsEmpty() { return this->children
.empty(); }
473 NWidgetBase
*GetWidgetOfType(WidgetType tp
) override
;
476 std::vector
<std::unique_ptr
<NWidgetBase
>> children
; ///< Child widgets in contaier.
479 /** Display planes with zero size for #NWidgetStacked. */
480 enum StackedZeroSizePlanes
{
481 SZSP_VERTICAL
= INT_MAX
/ 2, ///< Display plane with zero size horizontally, and filling and resizing vertically.
482 SZSP_HORIZONTAL
, ///< Display plane with zero size vertically, and filling and resizing horizontally.
483 SZSP_NONE
, ///< Display plane with zero size in both directions (none filling and resizing).
485 SZSP_BEGIN
= SZSP_VERTICAL
, ///< First zero-size plane.
489 * Stacked widgets, widgets all occupying the same space in the window.
490 * #NWID_SELECTION allows for selecting one of several panels (planes) to tbe displayed. All planes must have the same size.
491 * Since all planes are also initialized, switching between different planes can be done while the window is displayed.
493 * There are also a number of special planes (defined in #StackedZeroSizePlanes) that have zero size in one direction (and are stretchable in
494 * the other direction) or have zero size in both directions. They are used to make all child planes of the widget disappear.
495 * 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
496 * a #Window::ReInit() is needed to re-initialize the window since its size changes.
498 class NWidgetStacked
: public NWidgetContainer
{
500 NWidgetStacked(WidgetID index
);
502 void AdjustPaddingForZoom() override
;
503 void SetupSmallestSize(Window
*w
) override
;
504 void AssignSizePosition(SizingType sizing
, int x
, int y
, uint given_width
, uint given_height
, bool rtl
) override
;
505 void FillWidgetLookup(WidgetLookup
&widget_lookup
) override
;
507 void Draw(const Window
*w
) override
;
508 NWidgetCore
*GetWidgetFromPos(int x
, int y
) override
;
510 bool SetDisplayedPlane(int plane
);
512 int shown_plane
; ///< Plane being displayed (for #NWID_SELECTION only).
513 const WidgetID index
; ///< If non-negative, index in the #Window::widget_lookup.
515 WidgetLookup
*widget_lookup
; ///< Window's widget lookup, updated in SetDisplayedPlane().
518 /** Nested widget container flags, */
519 enum NWidContainerFlags
{
520 NCB_EQUALSIZE
= 0, ///< Containers should keep all their (resizing) children equally large.
521 NCB_BIGFIRST
= 1, ///< Allocate space to biggest resize first.
523 NC_NONE
= 0, ///< All flags cleared.
524 NC_EQUALSIZE
= 1 << NCB_EQUALSIZE
, ///< Value of the #NCB_EQUALSIZE flag.
525 NC_BIGFIRST
= 1 << NCB_BIGFIRST
, ///< Value of the #NCB_BIGFIRST flag.
527 DECLARE_ENUM_AS_BIT_SET(NWidContainerFlags
)
529 /** Container with pre/inter/post child space. */
530 class NWidgetPIPContainer
: public NWidgetContainer
{
532 NWidgetPIPContainer(WidgetType tp
, NWidContainerFlags flags
= NC_NONE
);
534 void AdjustPaddingForZoom() override
;
535 void SetPIP(uint8_t pip_pre
, uint8_t pip_inter
, uint8_t pip_post
);
536 void SetPIPRatio(uint8_t pip_ratio_pre
, uint8_t pip_ratio_inter
, uint8_t pip_rato_post
);
539 NWidContainerFlags flags
; ///< Flags of the container.
540 uint8_t pip_pre
; ///< Amount of space before first widget.
541 uint8_t pip_inter
; ///< Amount of space between widgets.
542 uint8_t pip_post
; ///< Amount of space after last widget.
543 uint8_t pip_ratio_pre
; ///< Ratio of remaining space before first widget.
544 uint8_t pip_ratio_inter
; ///< Ratio of remaining space between widgets.
545 uint8_t pip_ratio_post
; ///< Ratio of remaining space after last widget.
547 uint8_t uz_pip_pre
; ///< Unscaled space before first widget.
548 uint8_t uz_pip_inter
; ///< Unscaled space between widgets.
549 uint8_t uz_pip_post
; ///< Unscaled space after last widget.
551 uint8_t gaps
; ///< Number of gaps between widgets.
555 * Horizontal container.
556 * @ingroup NestedWidgets
558 class NWidgetHorizontal
: public NWidgetPIPContainer
{
560 NWidgetHorizontal(NWidContainerFlags flags
= NC_NONE
);
562 void SetupSmallestSize(Window
*w
) override
;
563 void AssignSizePosition(SizingType sizing
, int x
, int y
, uint given_width
, uint given_height
, bool rtl
) override
;
567 * Horizontal container that doesn't change the direction of the widgets for RTL languages.
568 * @ingroup NestedWidgets
570 class NWidgetHorizontalLTR
: public NWidgetHorizontal
{
572 NWidgetHorizontalLTR(NWidContainerFlags flags
= NC_NONE
);
574 void AssignSizePosition(SizingType sizing
, int x
, int y
, uint given_width
, uint given_height
, bool rtl
) override
;
578 * Vertical container.
579 * @ingroup NestedWidgets
581 class NWidgetVertical
: public NWidgetPIPContainer
{
583 NWidgetVertical(NWidContainerFlags flags
= NC_NONE
);
585 void SetupSmallestSize(Window
*w
) override
;
586 void AssignSizePosition(SizingType sizing
, int x
, int y
, uint given_width
, uint given_height
, bool rtl
) override
;
590 * Matrix container with implicitly equal sized (virtual) sub-widgets.
591 * This widget must have exactly one sub-widget. After that this sub-widget
592 * is used to draw all of the data within the matrix piece by piece.
593 * DrawWidget and OnClick calls will be done to that sub-widget, where the
594 * 16 high bits are used to encode the index into the matrix.
595 * @ingroup NestedWidgets
597 class NWidgetMatrix
: public NWidgetPIPContainer
{
599 NWidgetMatrix(Colours colour
, WidgetID index
);
601 void SetClicked(int clicked
);
602 void SetCount(int count
);
603 void SetScrollbar(Scrollbar
*sb
);
604 int GetCurrentElement() const;
606 void SetupSmallestSize(Window
*w
) override
;
607 void AssignSizePosition(SizingType sizing
, int x
, int y
, uint given_width
, uint given_height
, bool rtl
) override
;
608 void FillWidgetLookup(WidgetLookup
&widget_lookup
) override
;
610 NWidgetCore
*GetWidgetFromPos(int x
, int y
) override
;
611 void Draw(const Window
*w
) override
;
613 const WidgetID index
; ///< If non-negative, index in the #Window::widget_lookup.
614 Colours colour
; ///< Colour of this widget.
615 int clicked
; ///< The currently clicked element.
616 int count
; ///< Amount of valid elements.
617 int current_element
; ///< The element currently being processed.
618 Scrollbar
*sb
; ///< The scrollbar we're associated with.
620 int widget_w
; ///< The width of the child widget including inter spacing.
621 int widget_h
; ///< The height of the child widget including inter spacing.
622 int widgets_x
; ///< The number of visible widgets in horizontal direction.
623 int widgets_y
; ///< The number of visible widgets in vertical direction.
625 void GetScrollOffsets(int &start_x
, int &start_y
, int &base_offs_x
, int &base_offs_y
);
631 * @ingroup NestedWidgets
633 class NWidgetSpacer
: public NWidgetResizeBase
{
635 NWidgetSpacer(int width
, int height
);
637 void SetupSmallestSize(Window
*w
) override
;
638 void FillWidgetLookup(WidgetLookup
&widget_lookup
) override
;
640 void Draw(const Window
*w
) override
;
641 void SetDirty(const Window
*w
) const override
;
642 NWidgetCore
*GetWidgetFromPos(int x
, int y
) override
;
646 * Nested widget with a child.
647 * @ingroup NestedWidgets
649 class NWidgetBackground
: public NWidgetCore
{
651 NWidgetBackground(WidgetType tp
, Colours colour
, WidgetID index
, std::unique_ptr
<NWidgetPIPContainer
> &&child
= nullptr);
653 void Add(std::unique_ptr
<NWidgetBase
> &&nwid
);
654 void SetPIP(uint8_t pip_pre
, uint8_t pip_inter
, uint8_t pip_post
);
655 void SetPIPRatio(uint8_t pip_ratio_pre
, uint8_t pip_ratio_inter
, uint8_t pip_ratio_post
);
657 void AdjustPaddingForZoom() override
;
658 void SetupSmallestSize(Window
*w
) override
;
659 void AssignSizePosition(SizingType sizing
, int x
, int y
, uint given_width
, uint given_height
, bool rtl
) override
;
661 void FillWidgetLookup(WidgetLookup
&widget_lookup
) override
;
663 void Draw(const Window
*w
) override
;
664 NWidgetCore
*GetWidgetFromPos(int x
, int y
) override
;
665 NWidgetBase
*GetWidgetOfType(WidgetType tp
) override
;
668 std::unique_ptr
<NWidgetPIPContainer
> child
; ///< Child widget.
672 * Nested widget to display a viewport in a window.
673 * After initializing the nested widget tree, call #InitializeViewport(). After changing the window size,
674 * call #UpdateViewportCoordinates() eg from Window::OnResize().
675 * If the #disp_flags field contains the #ND_NO_TRANSPARENCY bit, the viewport will disable transparency.
676 * 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).
677 * @todo Class derives from #NWidgetCore, but does not use #colour, #widget_data, or #tool_tip.
678 * @ingroup NestedWidgets
680 class NWidgetViewport
: public NWidgetCore
{
682 NWidgetViewport(WidgetID index
);
684 void SetupSmallestSize(Window
*w
) override
;
685 void Draw(const Window
*w
) override
;
687 void InitializeViewport(Window
*w
, std::variant
<TileIndex
, VehicleID
> focus
, ZoomLevel zoom
);
688 void UpdateViewportCoordinates(Window
*w
);
692 * Scrollbar data structure
696 using size_type
= int32_t;
697 static constexpr size_type max_size_type
= std::numeric_limits
<size_type
>::max();
698 static constexpr size_type npos
= max_size_type
;
700 const bool is_vertical
; ///< Scrollbar has vertical orientation.
701 size_type count
; ///< Number of elements in the list.
702 size_type cap
; ///< Number of visible elements of the scroll bar.
703 size_type pos
; ///< Index of first visible item of the list.
704 size_type stepsize
; ///< Distance to scroll, when pressing the buttons or using the wheel.
707 /** Stepping sizes when scrolling */
708 enum ScrollbarStepping
{
709 SS_RAW
, ///< Step in single units.
710 SS_SMALL
, ///< Step in #stepsize units.
711 SS_BIG
, ///< Step in #cap units.
714 Scrollbar(bool is_vertical
) : is_vertical(is_vertical
), stepsize(1)
719 * Gets the number of elements in the list
720 * @return the number of elements
722 inline size_type
GetCount() const
728 * Gets the number of visible elements of the scrollbar
729 * @return the number of visible elements
731 inline size_type
GetCapacity() const
737 * Gets the position of the first visible element in the list
738 * @return the position of the element
740 inline size_type
GetPosition() const
746 * Checks whether given current item is visible in the list
747 * @param item to check
748 * @return true iff the item is visible
750 inline bool IsVisible(size_type item
) const
752 return IsInsideBS(item
, this->GetPosition(), this->GetCapacity());
756 * Is the scrollbar vertical or not?
757 * @return True iff the scrollbar is vertical.
759 inline bool IsVertical() const
761 return this->is_vertical
;
765 * Set the distance to scroll when using the buttons or the wheel.
766 * @param stepsize Scrolling speed.
768 void SetStepSize(size_t stepsize
)
770 assert(stepsize
> 0);
772 this->stepsize
= ClampTo
<size_type
>(stepsize
);
776 * Sets the number of elements in the list
777 * @param num the number of elements in the list
778 * @note updates the position if needed
780 void SetCount(size_t num
)
782 assert(num
< Scrollbar::max_size_type
);
784 this->count
= ClampTo
<size_type
>(num
);
785 /* Ensure position is within bounds */
786 this->SetPosition(this->pos
);
790 * Set the capacity of visible elements.
791 * @param capacity the new capacity
792 * @note updates the position if needed
794 void SetCapacity(size_t capacity
)
796 assert(capacity
< Scrollbar::max_size_type
);
798 this->cap
= ClampTo
<size_type
>(capacity
);
799 /* Ensure position is within bounds */
800 this->SetPosition(this->pos
);
803 void SetCapacityFromWidget(Window
*w
, WidgetID widget
, int padding
= 0);
806 * Sets the position of the first visible element
807 * @param position the position of the element
808 * @return true iff the position has changed
810 bool SetPosition(size_type position
)
812 size_type old_pos
= this->pos
;
813 this->pos
= Clamp(position
, 0, std::max(this->count
- this->cap
, 0));
814 return this->pos
!= old_pos
;
818 * Updates the position of the first visible element by the given amount.
819 * If the position would be too low or high it will be clamped appropriately
820 * @param difference the amount of change requested
821 * @param unit The stepping unit of \a difference
822 * @return true iff the position has changed
824 bool UpdatePosition(int difference
, ScrollbarStepping unit
= SS_SMALL
)
826 if (difference
== 0) return false;
828 case SS_SMALL
: difference
*= this->stepsize
; break;
829 case SS_BIG
: difference
*= this->cap
; break;
832 return this->SetPosition(this->pos
+ difference
);
836 * Scroll towards the given position; if the item is visible nothing
837 * happens, otherwise it will be shown either at the bottom or top of
838 * the window depending on where in the list it was.
839 * @param position the position to scroll towards.
841 void ScrollTowards(size_type position
)
843 if (position
< this->GetPosition()) {
844 /* scroll up to the item */
845 this->SetPosition(position
);
846 } else if (position
>= this->GetPosition() + this->GetCapacity()) {
847 /* scroll down so that the item is at the bottom */
848 this->SetPosition(position
- this->GetCapacity() + 1);
852 size_type
GetScrolledRowFromWidget(int clickpos
, const Window
* const w
, WidgetID widget
, int padding
= 0, int line_height
= -1) const;
855 * Get a pair of iterators for the range of visible elements in a container.
856 * @param container Container of elements represented by the scrollbar.
857 * @returns Pair of iterators of visible elements.
859 template <typename Tcontainer
>
860 auto GetVisibleRangeIterators(Tcontainer
&container
) const
862 assert(static_cast<size_t>(this->GetCount()) == container
.size()); // Scrollbar and container size must match.
863 auto first
= std::next(std::begin(container
), this->GetPosition());
864 auto last
= std::next(first
, std::min
<size_t>(this->GetCapacity(), this->GetCount() - this->GetPosition()));
865 return std::make_pair(first
, last
);
869 * Return an iterator pointing to the element of a scrolled widget that a user clicked in.
870 * @param container Container of elements represented by the scrollbar.
871 * @param clickpos Vertical position of the mouse click (without taking scrolling into account).
872 * @param w The window the click was in.
873 * @param widget Widget number of the widget clicked in.
874 * @param padding Amount of empty space between the widget edge and the top of the first row. Default value is \c 0.
875 * @param line_height Height of a single row. A negative value means using the vertical resize step of the widget.
876 * @return Iterator to the element clicked at. If clicked at a wrong position, returns as interator to the end of the container.
878 template <typename Tcontainer
>
879 auto GetScrolledItemFromWidget(Tcontainer
&container
, int clickpos
, const Window
* const w
, WidgetID widget
, int padding
= 0, int line_height
= -1) const
881 assert(static_cast<size_t>(this->GetCount()) == container
.size()); // Scrollbar and container size must match.
882 size_type row
= this->GetScrolledRowFromWidget(clickpos
, w
, widget
, padding
, line_height
);
883 if (row
== Scrollbar::npos
) return std::end(container
);
885 return std::next(std::begin(container
), row
);
888 EventState
UpdateListPositionOnKeyPress(int &list_position
, uint16_t keycode
) const;
892 * Nested widget to display and control a scrollbar in a window.
893 * Also assign the scrollbar to other widgets using #SetScrollbar() to make the mousewheel work.
894 * @ingroup NestedWidgets
896 class NWidgetScrollbar
: public NWidgetCore
, public Scrollbar
{
898 NWidgetScrollbar(WidgetType tp
, Colours colour
, WidgetID index
);
900 void SetupSmallestSize(Window
*w
) override
;
901 void Draw(const Window
*w
) override
;
903 static void InvalidateDimensionCache();
904 static Dimension
GetVerticalDimension();
905 static Dimension
GetHorizontalDimension();
908 static Dimension vertical_dimension
; ///< Cached size of vertical scrollbar button.
909 static Dimension horizontal_dimension
; ///< Cached size of horizontal scrollbar button.
914 * @ingroup NestedWidgets
916 class NWidgetLeaf
: public NWidgetCore
{
918 NWidgetLeaf(WidgetType tp
, Colours colour
, WidgetID index
, uint32_t data
, StringID tip
);
920 void SetupSmallestSize(Window
*w
) override
;
921 void Draw(const Window
*w
) override
;
923 bool ButtonHit(const Point
&pt
);
925 static void InvalidateDimensionCache();
927 static Dimension dropdown_dimension
; ///< Cached size of a dropdown widget.
928 static Dimension resizebox_dimension
; ///< Cached size of a resizebox widget.
929 static Dimension closebox_dimension
; ///< Cached size of a closebox widget.
931 static Dimension shadebox_dimension
; ///< Cached size of a shadebox widget.
932 static Dimension debugbox_dimension
; ///< Cached size of a debugbox widget.
933 static Dimension defsizebox_dimension
; ///< Cached size of a defsizebox widget.
934 static Dimension stickybox_dimension
; ///< Cached size of a stickybox widget.
938 * Return the biggest possible size of a nested widget.
939 * @param base Base size of the widget.
940 * @param max_space Available space for the widget.
941 * @param step Stepsize of the widget.
942 * @return Biggest possible size of the widget, assuming that \a base may only be incremented by \a step size steps.
944 inline uint
ComputeMaxSize(uint base
, uint max_space
, uint step
)
946 if (base
>= max_space
|| step
== 0) return base
;
947 if (step
== 1) return max_space
;
948 uint increment
= max_space
- base
;
949 increment
-= increment
% step
;
950 return base
+ increment
;
954 * @defgroup NestedWidgetParts Hierarchical widget parts
955 * 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.
957 * - Leaf widgets start with a #NWidget(WidgetType tp, Colours col, int16_t idx) part.
958 * Next, specify its properties with one or more of
959 * - #SetMinimalSize Define the minimal size of the widget.
960 * - #SetFill Define how the widget may grow to make it nicely.
961 * - #SetDataTip Define the data and the tooltip of the widget.
962 * - #SetResize Define how the widget may resize.
963 * - #SetPadding Create additional space around the widget.
965 * - To insert a nested widget tree from an external source, nested widget part #NWidgetFunction exists.
966 * For further customization, the #SetPadding part may be used.
968 * - Space widgets (#NWidgetSpacer) start with a #NWidget(WidgetType tp), followed by one or more of
969 * - #SetMinimalSize Define the minimal size of the widget.
970 * - #SetFill Define how the widget may grow to make it nicely.
971 * - #SetResize Define how the widget may resize.
972 * - #SetPadding Create additional space around the widget.
974 * - Container widgets #NWidgetHorizontal, #NWidgetHorizontalLTR, #NWidgetVertical, and #NWidgetMatrix, start with a #NWidget(WidgetType tp) part.
975 * Their properties are derived from the child widgets so they cannot be specified.
976 * You can however use
977 * - #SetPadding Define additional padding around the container.
978 * - #SetPIP Set additional pre/inter/post child widget space.
980 * 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
981 * the child widgets (it has no meaning for the compiler but it makes the widget parts easier to read).
982 * Below the last child widget, use an #EndContainer part. This part should be aligned with the #NWidget part that started the container.
984 * - 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,
985 * so the widget does not support #SetPIP. #SetPadding is allowed though.
986 * Like the other container widgets, below the last child widgets, a #EndContainer part should be used to denote the end of the stacked widget.
988 * - Background widgets #NWidgetBackground start with a #NWidget(WidgetType tp, Colours col, int16_t idx) part.
989 * What follows depends on how the widget is used.
990 * - 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
991 * leaf widgets to define how it behaves.
992 * - 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 * In both cases, the background widget \b MUST end with a #EndContainer widget part.
1001 * Widget part for storing data and tooltip information.
1002 * @ingroup NestedWidgetParts
1004 struct NWidgetPartDataTip
{
1005 uint32_t data
; ///< Data value of the widget.
1006 StringID tooltip
; ///< Tooltip of the widget.
1010 * Widget part for storing basic widget information.
1011 * @ingroup NestedWidgetParts
1013 struct NWidgetPartWidget
{
1014 Colours colour
; ///< Widget colour.
1015 WidgetID index
; ///< Index of the widget.
1019 * Widget part for storing padding.
1020 * @ingroup NestedWidgetParts
1022 struct NWidgetPartPaddings
: RectPadding
{
1026 * Widget part for storing pre/inter/post spaces.
1027 * @ingroup NestedWidgetParts
1029 struct NWidgetPartPIP
{
1030 uint8_t pre
, inter
, post
; ///< Amount of space before/between/after child widgets.
1034 * Widget part for storing minimal text line data.
1035 * @ingroup NestedWidgetParts
1037 struct NWidgetPartTextLines
{
1038 uint8_t lines
; ///< Number of text lines.
1039 uint8_t spacing
; ///< Extra spacing around lines.
1040 FontSize size
; ///< Font size of text lines.
1044 * Widget part for storing text colour.
1045 * @ingroup NestedWidgetParts
1047 struct NWidgetPartTextStyle
{
1048 TextColour colour
; ///< TextColour for DrawString.
1049 FontSize size
; ///< Font size of text.
1053 * Widget part for setting text/image alignment within a widget.
1054 * @ingroup NestedWidgetParts
1056 struct NWidgetPartAlignment
{
1057 StringAlignment align
; ///< Alignment of text/image.
1060 struct NWidgetPartAspect
{
1066 * Pointer to function returning a nested widget.
1067 * @return Nested widget (tree).
1069 typedef std::unique_ptr
<NWidgetBase
> NWidgetFunctionType();
1072 * Partial widget specification to allow NWidgets to be written nested.
1073 * @ingroup NestedWidgetParts
1075 struct NWidgetPart
{
1076 WidgetType type
; ///< Type of the part. @see NWidgetPartType.
1077 union NWidgetPartUnion
{
1078 Point xy
; ///< Part with an x/y size.
1079 NWidgetPartDataTip data_tip
; ///< Part with a data/tooltip.
1080 NWidgetPartWidget widget
; ///< Part with a start of a widget.
1081 NWidgetPartPaddings padding
; ///< Part with paddings.
1082 NWidgetPartPIP pip
; ///< Part with pre/inter/post spaces.
1083 NWidgetPartTextLines text_lines
; ///< Part with text line data.
1084 NWidgetPartTextStyle text_style
; ///< Part with text style data.
1085 NWidgetPartAlignment align
; ///< Part with internal alignment.
1086 NWidgetFunctionType
*func_ptr
; ///< Part with a function call.
1087 NWidContainerFlags cont_flags
; ///< Part with container flags.
1088 NWidgetPartAspect aspect
; ///< Part to set aspect ratio.
1090 /* Constructors for each NWidgetPartUnion data type. */
1091 constexpr NWidgetPartUnion() : xy() {}
1092 constexpr NWidgetPartUnion(Point xy
) : xy(xy
) {}
1093 constexpr NWidgetPartUnion(NWidgetPartDataTip data_tip
) : data_tip(data_tip
) {}
1094 constexpr NWidgetPartUnion(NWidgetPartWidget widget
) : widget(widget
) {}
1095 constexpr NWidgetPartUnion(NWidgetPartPaddings padding
) : padding(padding
) {}
1096 constexpr NWidgetPartUnion(NWidgetPartPIP pip
) : pip(pip
) {}
1097 constexpr NWidgetPartUnion(NWidgetPartTextLines text_lines
) : text_lines(text_lines
) {}
1098 constexpr NWidgetPartUnion(NWidgetPartTextStyle text_style
) : text_style(text_style
) {}
1099 constexpr NWidgetPartUnion(NWidgetPartAlignment align
) : align(align
) {}
1100 constexpr NWidgetPartUnion(NWidgetFunctionType
*func_ptr
) : func_ptr(func_ptr
) {}
1101 constexpr NWidgetPartUnion(NWidContainerFlags cont_flags
) : cont_flags(cont_flags
) {}
1102 constexpr NWidgetPartUnion(NWidgetPartAspect aspect
) : aspect(aspect
) {}
1105 /* Constructors for each NWidgetPart data type. */
1106 explicit constexpr NWidgetPart(WidgetType type
) : type(type
), u() {}
1107 constexpr NWidgetPart(WidgetType type
, Point xy
) : type(type
), u(xy
) {}
1108 constexpr NWidgetPart(WidgetType type
, NWidgetPartDataTip data_tip
) : type(type
), u(data_tip
) {}
1109 constexpr NWidgetPart(WidgetType type
, NWidgetPartWidget widget
) : type(type
), u(widget
) {}
1110 constexpr NWidgetPart(WidgetType type
, NWidgetPartPaddings padding
) : type(type
), u(padding
) {}
1111 constexpr NWidgetPart(WidgetType type
, NWidgetPartPIP pip
) : type(type
), u(pip
) {}
1112 constexpr NWidgetPart(WidgetType type
, NWidgetPartTextLines text_lines
) : type(type
), u(text_lines
) {}
1113 constexpr NWidgetPart(WidgetType type
, NWidgetPartTextStyle text_style
) : type(type
), u(text_style
) {}
1114 constexpr NWidgetPart(WidgetType type
, NWidgetPartAlignment align
) : type(type
), u(align
) {}
1115 constexpr NWidgetPart(WidgetType type
, NWidgetFunctionType
*func_ptr
) : type(type
), u(func_ptr
) {}
1116 constexpr NWidgetPart(WidgetType type
, NWidContainerFlags cont_flags
) : type(type
), u(cont_flags
) {}
1117 constexpr NWidgetPart(WidgetType type
, NWidgetPartAspect aspect
) : type(type
), u(aspect
) {}
1121 * Widget part function for setting the resize step.
1122 * @param dx Horizontal resize step. 0 means no horizontal resizing.
1123 * @param dy Vertical resize step. 0 means no vertical resizing.
1124 * @ingroup NestedWidgetParts
1126 constexpr NWidgetPart
SetResize(int16_t dx
, int16_t dy
)
1128 return NWidgetPart
{WPT_RESIZE
, Point
{dx
, dy
}};
1132 * Widget part function for setting the minimal size.
1133 * @param x Horizontal minimal size.
1134 * @param y Vertical minimal size.
1135 * @ingroup NestedWidgetParts
1137 constexpr NWidgetPart
SetMinimalSize(int16_t x
, int16_t y
)
1139 return NWidgetPart
{WPT_MINSIZE
, Point
{x
, y
}};
1143 * Widget part function for setting the minimal text lines.
1144 * @param lines Number of text lines.
1145 * @param spacing Extra spacing required.
1146 * @param size Font size of text.
1147 * @ingroup NestedWidgetParts
1149 constexpr NWidgetPart
SetMinimalTextLines(uint8_t lines
, uint8_t spacing
, FontSize size
= FS_NORMAL
)
1151 return NWidgetPart
{WPT_MINTEXTLINES
, NWidgetPartTextLines
{lines
, spacing
, size
}};
1155 * Widget part function for setting the text style.
1156 * @param colour Colour to draw string within widget.
1157 * @param size Font size to draw string within widget.
1158 * @ingroup NestedWidgetParts
1160 constexpr NWidgetPart
SetTextStyle(TextColour colour
, FontSize size
= FS_NORMAL
)
1162 return NWidgetPart
{WPT_TEXTSTYLE
, NWidgetPartTextStyle
{colour
, size
}};
1166 * Widget part function for setting the alignment of text/images.
1167 * @param align Alignment of text/image within widget.
1168 * @ingroup NestedWidgetParts
1170 constexpr NWidgetPart
SetAlignment(StringAlignment align
)
1172 return NWidgetPart
{WPT_ALIGNMENT
, NWidgetPartAlignment
{align
}};
1176 * Widget part function for setting filling.
1177 * @param fill_x Horizontal filling step from minimal size.
1178 * @param fill_y Vertical filling step from minimal size.
1179 * @ingroup NestedWidgetParts
1181 constexpr NWidgetPart
SetFill(uint16_t fill_x
, uint16_t fill_y
)
1183 return NWidgetPart
{WPT_FILL
, Point
{fill_x
, fill_y
}};
1187 * Widget part function for denoting the end of a container
1188 * (horizontal, vertical, WWT_FRAME, WWT_INSET, or WWT_PANEL).
1189 * @ingroup NestedWidgetParts
1191 constexpr NWidgetPart
EndContainer()
1193 return NWidgetPart
{WPT_ENDCONTAINER
};
1197 * Widget part function for setting the data and tooltip.
1198 * @param data Data of the widget.
1199 * @param tip Tooltip of the widget.
1200 * @ingroup NestedWidgetParts
1202 constexpr NWidgetPart
SetDataTip(uint32_t data
, StringID tip
)
1204 return NWidgetPart
{WPT_DATATIP
, NWidgetPartDataTip
{data
, tip
}};
1208 * Widget part function for setting the data and tooltip of WWT_MATRIX widgets
1209 * @param cols Number of columns. \c 0 means to use draw columns with width according to the resize step size.
1210 * @param rows Number of rows. \c 0 means to use draw rows with height according to the resize step size.
1211 * @param tip Tooltip of the widget.
1212 * @ingroup NestedWidgetParts
1214 constexpr NWidgetPart
SetMatrixDataTip(uint8_t cols
, uint8_t rows
, StringID tip
)
1216 return SetDataTip((rows
<< MAT_ROW_START
) | (cols
<< MAT_COL_START
), tip
);
1220 * Widget part function for setting additional space around a widget.
1221 * Parameters start above the widget, and are specified in clock-wise direction.
1222 * @param top The padding above the widget.
1223 * @param right The padding right of the widget.
1224 * @param bottom The padding below the widget.
1225 * @param left The padding left of the widget.
1226 * @ingroup NestedWidgetParts
1228 constexpr NWidgetPart
SetPadding(uint8_t top
, uint8_t right
, uint8_t bottom
, uint8_t left
)
1230 return NWidgetPart
{WPT_PADDING
, NWidgetPartPaddings
{left
, top
, right
, bottom
}};
1234 * Widget part function for setting additional space around a widget.
1235 * @param r The padding around the widget.
1236 * @ingroup NestedWidgetParts
1238 constexpr NWidgetPart
SetPadding(const RectPadding
&padding
)
1240 return NWidgetPart
{WPT_PADDING
, NWidgetPartPaddings
{padding
}};
1244 * Widget part function for setting a padding.
1245 * @param padding The padding to use for all directions.
1246 * @ingroup NestedWidgetParts
1248 constexpr NWidgetPart
SetPadding(uint8_t padding
)
1250 return SetPadding(padding
, padding
, padding
, padding
);
1254 * Widget part function for setting a pre/inter/post spaces.
1255 * @param pre The amount of space before the first widget.
1256 * @param inter The amount of space between widgets.
1257 * @param post The amount of space after the last widget.
1258 * @ingroup NestedWidgetParts
1260 constexpr NWidgetPart
SetPIP(uint8_t pre
, uint8_t inter
, uint8_t post
)
1262 return NWidgetPart
{WPT_PIPSPACE
, NWidgetPartPIP
{pre
, inter
, post
}};
1266 * Widget part function for setting a pre/inter/post ratio.
1267 * @param pre The ratio of space before the first widget.
1268 * @param inter The ratio of space between widgets.
1269 * @param post The ratio of space after the last widget.
1270 * @ingroup NestedWidgetParts
1272 constexpr NWidgetPart
SetPIPRatio(uint8_t ratio_pre
, uint8_t ratio_inter
, uint8_t ratio_post
)
1274 return NWidgetPart
{WPT_PIPRATIO
, NWidgetPartPIP
{ratio_pre
, ratio_inter
, ratio_post
}};
1278 * Attach a scrollbar to a widget.
1279 * The scrollbar is controlled when using the mousewheel on the widget.
1280 * Multiple widgets can refer to the same scrollbar to make the mousewheel work in all of them.
1281 * @param index Widget index of the scrollbar.
1282 * @ingroup NestedWidgetParts
1284 constexpr NWidgetPart
SetScrollbar(WidgetID index
)
1286 return NWidgetPart
{WPT_SCROLLBAR
, NWidgetPartWidget
{INVALID_COLOUR
, index
}};
1290 * Widget part function for setting the aspect ratio.
1291 * @param ratio Desired aspect ratio, or 0 for none.
1292 * @param flags Dimensions which should be resized.
1293 * @ingroup NestedWidgetParts
1295 constexpr NWidgetPart
SetAspect(float ratio
, AspectFlags flags
= AspectFlags::ResizeX
)
1297 return NWidgetPart
{WPT_ASPECT
, NWidgetPartAspect
{ratio
, flags
}};
1301 * Widget part function for starting a new 'real' widget.
1302 * @param tp Type of the new nested widget.
1303 * @param col Colour of the new widget.
1304 * @param idx Index of the widget.
1305 * @note with #WWT_PANEL, #WWT_FRAME, #WWT_INSET, a new container is started.
1306 * Child widgets must have a index bigger than the parent index.
1307 * @ingroup NestedWidgetParts
1309 constexpr NWidgetPart
NWidget(WidgetType tp
, Colours col
, WidgetID idx
= -1)
1311 return NWidgetPart
{tp
, NWidgetPartWidget
{col
, idx
}};
1315 * Widget part function for starting a new horizontal container, vertical container, or spacer widget.
1316 * @param tp Type of the new nested widget, #NWID_HORIZONTAL, #NWID_VERTICAL, #NWID_SPACER, #NWID_SELECTION, and #NWID_MATRIX.
1317 * @param cont_flags Flags for the containers (#NWID_HORIZONTAL and #NWID_VERTICAL).
1318 * @ingroup NestedWidgetParts
1320 constexpr NWidgetPart
NWidget(WidgetType tp
, NWidContainerFlags cont_flags
= NC_NONE
)
1322 return NWidgetPart
{tp
, NWidContainerFlags
{cont_flags
}};
1326 * Obtain a nested widget (sub)tree from an external source.
1327 * @param func_ptr Pointer to function that returns the tree.
1328 * @ingroup NestedWidgetParts
1330 constexpr NWidgetPart
NWidgetFunction(NWidgetFunctionType
*func_ptr
)
1332 return NWidgetPart
{WPT_FUNCTION
, func_ptr
};
1335 bool IsContainerWidgetType(WidgetType tp
);
1336 std::unique_ptr
<NWidgetBase
> MakeNWidgets(std::span
<const NWidgetPart
> nwid_parts
, std::unique_ptr
<NWidgetBase
> &&container
);
1337 std::unique_ptr
<NWidgetBase
> MakeWindowNWidgetTree(std::span
<const NWidgetPart
> nwid_parts
, NWidgetStacked
**shade_select
);
1339 std::unique_ptr
<NWidgetBase
> MakeCompanyButtonRows(WidgetID widget_first
, WidgetID widget_last
, Colours button_colour
, int max_length
, StringID button_tooltip
, bool resizable
= true);
1341 void SetupWidgetDimensions();
1343 #endif /* WIDGET_TYPE_H */