Codechange: Use cached town, station, industry names for list window sorting
[openttd-github.git] / src / widget_type.h
blob3a36d9aad93061fce046aabbb403ec6e51380431
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 static const int WIDGET_LIST_END = -1; ///< indicate the end of widgets' list for vararg functions
22 /** Bits of the #WWT_MATRIX widget data. */
23 enum MatrixWidgetValues {
24 /* Number of column bits of the WWT_MATRIX widget data. */
25 MAT_COL_START = 0, ///< Lowest bit of the number of columns.
26 MAT_COL_BITS = 8, ///< Number of bits for the number of columns in the matrix.
28 /* Number of row bits of the WWT_MATRIX widget data. */
29 MAT_ROW_START = 8, ///< Lowest bit of the number of rows.
30 MAT_ROW_BITS = 8, ///< Number of bits for the number of rows in the matrix.
33 /** Values for an arrow widget */
34 enum ArrowWidgetValues {
35 AWV_DECREASE, ///< Arrow to the left or in case of RTL to the right
36 AWV_INCREASE, ///< Arrow to the right or in case of RTL to the left
37 AWV_LEFT, ///< Force the arrow to the left
38 AWV_RIGHT, ///< Force the arrow to the right
41 /**
42 * Window widget types, nested widget types, and nested widget part types.
44 enum WidgetType {
45 /* Window widget types. */
46 WWT_EMPTY, ///< Empty widget, place holder to reserve space in widget array
48 WWT_PANEL, ///< Simple depressed panel
49 WWT_INSET, ///< Pressed (inset) panel, most commonly used as combo box _text_ area
50 WWT_IMGBTN, ///< (Toggle) Button with image
51 WWT_IMGBTN_2, ///< (Toggle) Button with diff image when clicked
52 WWT_ARROWBTN, ///< (Toggle) Button with an arrow
53 WWT_TEXTBTN, ///< (Toggle) Button with text
54 WWT_TEXTBTN_2, ///< (Toggle) Button with diff text when clicked
55 WWT_LABEL, ///< Centered label
56 WWT_TEXT, ///< Pure simple text
57 WWT_MATRIX, ///< Grid of rows and columns. @see MatrixWidgetValues
58 WWT_FRAME, ///< Frame
59 WWT_CAPTION, ///< Window caption (window title between closebox and stickybox)
61 WWT_DEBUGBOX, ///< NewGRF debug box (at top-right of a window, between WWT_CAPTION and WWT_SHADEBOX)
62 WWT_SHADEBOX, ///< Shade box (at top-right of a window, between WWT_DEBUGBOX and WWT_DEFSIZEBOX)
63 WWT_DEFSIZEBOX, ///< Default window size box (at top-right of a window, between WWT_SHADEBOX and WWT_STICKYBOX)
64 WWT_STICKYBOX, ///< Sticky box (at top-right of a window, after WWT_DEFSIZEBOX)
66 WWT_RESIZEBOX, ///< Resize box (normally at bottom-right of a window)
67 WWT_CLOSEBOX, ///< Close box (at top-left of a window)
68 WWT_DROPDOWN, ///< Drop down list
69 WWT_EDITBOX, ///< a textbox for typing
70 WWT_LAST, ///< Last Item. use WIDGETS_END to fill up padding!!
72 /* Nested widget types. */
73 NWID_HORIZONTAL, ///< Horizontal container.
74 NWID_HORIZONTAL_LTR, ///< Horizontal container that doesn't change the order of the widgets for RTL languages.
75 NWID_VERTICAL, ///< Vertical container.
76 NWID_MATRIX, ///< Matrix container.
77 NWID_SPACER, ///< Invisible widget that takes some space.
78 NWID_SELECTION, ///< Stacked widgets, only one visible at a time (eg in a panel with tabs).
79 NWID_VIEWPORT, ///< Nested widget containing a viewport.
80 NWID_BUTTON_DROPDOWN, ///< Button with a drop-down.
81 NWID_HSCROLLBAR, ///< Horizontal scrollbar
82 NWID_VSCROLLBAR, ///< Vertical scrollbar
84 /* Nested widget part types. */
85 WPT_RESIZE, ///< Widget part for specifying resizing.
86 WPT_MINSIZE, ///< Widget part for specifying minimal size.
87 WPT_MINTEXTLINES, ///< Widget part for specifying minimal number of lines of text.
88 WPT_FILL, ///< Widget part for specifying fill.
89 WPT_DATATIP, ///< Widget part for specifying data and tooltip.
90 WPT_PADDING, ///< Widget part for specifying a padding.
91 WPT_PIPSPACE, ///< Widget part for specifying pre/inter/post space for containers.
92 WPT_ENDCONTAINER, ///< Widget part to denote end of a container.
93 WPT_FUNCTION, ///< Widget part for calling a user function.
94 WPT_SCROLLBAR, ///< Widget part for attaching a scrollbar.
96 /* Pushable window widget types. */
97 WWT_MASK = 0x7F,
99 WWB_PUSHBUTTON = 1 << 7,
101 WWT_PUSHBTN = WWT_PANEL | WWB_PUSHBUTTON, ///< Normal push-button (no toggle button) with custom drawing
102 WWT_PUSHTXTBTN = WWT_TEXTBTN | WWB_PUSHBUTTON, ///< Normal push-button (no toggle button) with text caption
103 WWT_PUSHIMGBTN = WWT_IMGBTN | WWB_PUSHBUTTON, ///< Normal push-button (no toggle button) with image caption
104 WWT_PUSHARROWBTN = WWT_ARROWBTN | WWB_PUSHBUTTON, ///< Normal push-button (no toggle button) with arrow caption
105 NWID_PUSHBUTTON_DROPDOWN = NWID_BUTTON_DROPDOWN | WWB_PUSHBUTTON,
108 /** Different forms of sizing nested widgets, using NWidgetBase::AssignSizePosition() */
109 enum SizingType {
110 ST_SMALLEST, ///< Initialize nested widget tree to smallest size. Also updates \e current_x and \e current_y.
111 ST_RESIZE, ///< Resize the nested widget tree.
114 /* Forward declarations. */
115 class NWidgetCore;
116 class Scrollbar;
119 * Baseclass for nested widgets.
120 * @invariant After initialization, \f$current\_x = smallest\_x + n * resize\_x, for n \geq 0\f$.
121 * @invariant After initialization, \f$current\_y = smallest\_y + m * resize\_y, for m \geq 0\f$.
122 * @ingroup NestedWidgets
124 class NWidgetBase : public ZeroedMemoryAllocator {
125 public:
126 NWidgetBase(WidgetType tp);
128 virtual void SetupSmallestSize(Window *w, bool init_array) = 0;
129 virtual void AssignSizePosition(SizingType sizing, uint x, uint y, uint given_width, uint given_height, bool rtl) = 0;
131 virtual void FillNestedArray(NWidgetBase **array, uint length) = 0;
133 virtual NWidgetCore *GetWidgetFromPos(int x, int y) = 0;
134 virtual NWidgetBase *GetWidgetOfType(WidgetType tp);
136 virtual bool IsHighlighted() const { return false; }
137 virtual TextColour GetHighlightColour() const { return TC_INVALID; }
138 virtual void SetHighlighted(TextColour highlight_colour) {}
141 * Set additional space (padding) around the widget.
142 * @param top Amount of additional space above the widget.
143 * @param right Amount of additional space right of the widget.
144 * @param bottom Amount of additional space below the widget.
145 * @param left Amount of additional space left of the widget.
147 inline void SetPadding(uint8 top, uint8 right, uint8 bottom, uint8 left)
149 this->padding_top = top;
150 this->padding_right = right;
151 this->padding_bottom = bottom;
152 this->padding_left = left;
155 inline uint GetHorizontalStepSize(SizingType sizing) const;
156 inline uint GetVerticalStepSize(SizingType sizing) const;
158 virtual void Draw(const Window *w) = 0;
159 virtual void SetDirty(const Window *w) const;
161 WidgetType type; ///< Type of the widget / nested widget.
162 uint fill_x; ///< Horizontal fill stepsize (from initial size, \c 0 means not resizable).
163 uint fill_y; ///< Vertical fill stepsize (from initial size, \c 0 means not resizable).
164 uint resize_x; ///< Horizontal resize step (\c 0 means not resizable).
165 uint resize_y; ///< Vertical resize step (\c 0 means not resizable).
166 /* Size of the widget in the smallest window possible.
167 * Computed by #SetupSmallestSize() followed by #AssignSizePosition().
169 uint smallest_x; ///< Smallest horizontal size of the widget in a filled window.
170 uint smallest_y; ///< Smallest vertical size of the widget in a filled window.
171 /* Current widget size (that is, after resizing). */
172 uint current_x; ///< Current horizontal size (after resizing).
173 uint current_y; ///< Current vertical size (after resizing).
175 int pos_x; ///< Horizontal position of top-left corner of the widget in the window.
176 int pos_y; ///< Vertical position of top-left corner of the widget in the window.
178 NWidgetBase *next; ///< Pointer to next widget in container. Managed by parent container widget.
179 NWidgetBase *prev; ///< Pointer to previous widget in container. Managed by parent container widget.
181 uint8 padding_top; ///< Paddings added to the top of the widget. Managed by parent container widget.
182 uint8 padding_right; ///< Paddings added to the right of the widget. Managed by parent container widget. (parent container may swap this with padding_left for RTL)
183 uint8 padding_bottom; ///< Paddings added to the bottom of the widget. Managed by parent container widget.
184 uint8 padding_left; ///< Paddings added to the left of the widget. Managed by parent container widget. (parent container may swap this with padding_right for RTL)
186 protected:
187 inline void StoreSizePosition(SizingType sizing, uint x, uint y, uint given_width, uint given_height);
191 * Get the horizontal sizing step.
192 * @param sizing Type of resize being performed.
194 inline uint NWidgetBase::GetHorizontalStepSize(SizingType sizing) const
196 return (sizing == ST_RESIZE) ? this->resize_x : this->fill_x;
200 * Get the vertical sizing step.
201 * @param sizing Type of resize being performed.
203 inline uint NWidgetBase::GetVerticalStepSize(SizingType sizing) const
205 return (sizing == ST_RESIZE) ? this->resize_y : this->fill_y;
209 * Store size and position.
210 * @param sizing Type of resizing to perform.
211 * @param x Horizontal offset of the widget relative to the left edge of the window.
212 * @param y Vertical offset of the widget relative to the top edge of the window.
213 * @param given_width Width allocated to the widget.
214 * @param given_height Height allocated to the widget.
216 inline void NWidgetBase::StoreSizePosition(SizingType sizing, uint x, uint y, uint given_width, uint given_height)
218 this->pos_x = x;
219 this->pos_y = y;
220 if (sizing == ST_SMALLEST) {
221 this->smallest_x = given_width;
222 this->smallest_y = given_height;
224 this->current_x = given_width;
225 this->current_y = given_height;
230 * Base class for a resizable nested widget.
231 * @ingroup NestedWidgets
233 class NWidgetResizeBase : public NWidgetBase {
234 public:
235 NWidgetResizeBase(WidgetType tp, uint fill_x, uint fill_y);
237 void SetMinimalSize(uint min_x, uint min_y);
238 void SetMinimalTextLines(uint8 min_lines, uint8 spacing, FontSize size);
239 void SetFill(uint fill_x, uint fill_y);
240 void SetResize(uint resize_x, uint resize_y);
242 void AssignSizePosition(SizingType sizing, uint x, uint y, uint given_width, uint given_height, bool rtl);
244 uint min_x; ///< Minimal horizontal size of only this widget.
245 uint min_y; ///< Minimal vertical size of only this widget.
248 /** Nested widget flags that affect display and interaction with 'real' widgets. */
249 enum NWidgetDisplay {
250 /* Generic. */
251 NDB_LOWERED = 0, ///< Widget is lowered (pressed down) bit.
252 NDB_DISABLED = 1, ///< Widget is disabled (greyed out) bit.
253 /* Viewport widget. */
254 NDB_NO_TRANSPARENCY = 2, ///< Viewport is never transparent.
255 NDB_SHADE_GREY = 3, ///< Shade viewport to grey-scale.
256 NDB_SHADE_DIMMED = 4, ///< Display dimmed colours in the viewport.
257 /* Button dropdown widget. */
258 NDB_DROPDOWN_ACTIVE = 5, ///< Dropdown menu of the button dropdown widget is active. @see #NWID_BUTTON_DROPDOWN
259 /* Scrollbar widget. */
260 NDB_SCROLLBAR_UP = 6, ///< Up-button is lowered bit.
261 NDB_SCROLLBAR_DOWN = 7, ///< Down-button is lowered bit.
262 /* Generic. */
263 NDB_HIGHLIGHT = 8, ///< Highlight of widget is on.
265 ND_LOWERED = 1 << NDB_LOWERED, ///< Bit value of the lowered flag.
266 ND_DISABLED = 1 << NDB_DISABLED, ///< Bit value of the disabled flag.
267 ND_HIGHLIGHT = 1 << NDB_HIGHLIGHT, ///< Bit value of the highlight flag.
268 ND_NO_TRANSPARENCY = 1 << NDB_NO_TRANSPARENCY, ///< Bit value of the 'no transparency' flag.
269 ND_SHADE_GREY = 1 << NDB_SHADE_GREY, ///< Bit value of the 'shade to grey' flag.
270 ND_SHADE_DIMMED = 1 << NDB_SHADE_DIMMED, ///< Bit value of the 'dimmed colours' flag.
271 ND_DROPDOWN_ACTIVE = 1 << NDB_DROPDOWN_ACTIVE, ///< Bit value of the 'dropdown active' flag.
272 ND_SCROLLBAR_UP = 1 << NDB_SCROLLBAR_UP, ///< Bit value of the 'scrollbar up' flag.
273 ND_SCROLLBAR_DOWN = 1 << NDB_SCROLLBAR_DOWN, ///< Bit value of the 'scrollbar down' flag.
274 ND_SCROLLBAR_BTN = ND_SCROLLBAR_UP | ND_SCROLLBAR_DOWN, ///< Bit value of the 'scrollbar up' or 'scrollbar down' flag.
276 DECLARE_ENUM_AS_BIT_SET(NWidgetDisplay)
279 * Base class for a 'real' widget.
280 * @ingroup NestedWidgets
282 class NWidgetCore : public NWidgetResizeBase {
283 public:
284 NWidgetCore(WidgetType tp, Colours colour, uint fill_x, uint fill_y, uint32 widget_data, StringID tool_tip);
286 void SetIndex(int index);
287 void SetDataTip(uint32 widget_data, StringID tool_tip);
289 inline void SetLowered(bool lowered);
290 inline bool IsLowered() const;
291 inline void SetDisabled(bool disabled);
292 inline bool IsDisabled() const;
294 void FillNestedArray(NWidgetBase **array, uint length) override;
295 NWidgetCore *GetWidgetFromPos(int x, int y) override;
296 bool IsHighlighted() const override;
297 TextColour GetHighlightColour() const override;
298 void SetHighlighted(TextColour highlight_colour) override;
300 NWidgetDisplay disp_flags; ///< Flags that affect display and interaction with the widget.
301 Colours colour; ///< Colour of this widget.
302 int index; ///< Index of the nested widget in the widget array of the window (\c -1 means 'not used').
303 uint32 widget_data; ///< Data of the widget. @see Widget::data
304 StringID tool_tip; ///< Tooltip of the widget. @see Widget::tootips
305 int scrollbar_index; ///< Index of an attached scrollbar.
306 TextColour highlight_colour; ///< Colour of highlight.
310 * Highlight the widget or not.
311 * @param highlight_colour Widget must be highlighted (blink).
313 inline void NWidgetCore::SetHighlighted(TextColour highlight_colour)
315 this->disp_flags = highlight_colour != TC_INVALID ? SETBITS(this->disp_flags, ND_HIGHLIGHT) : CLRBITS(this->disp_flags, ND_HIGHLIGHT);
316 this->highlight_colour = highlight_colour;
319 /** Return whether the widget is highlighted. */
320 inline bool NWidgetCore::IsHighlighted() const
322 return HasBit(this->disp_flags, NDB_HIGHLIGHT);
325 /** Return the colour of the highlight. */
326 inline TextColour NWidgetCore::GetHighlightColour() const
328 return this->highlight_colour;
332 * Lower or raise the widget.
333 * @param lowered Widget must be lowered (drawn pressed down).
335 inline void NWidgetCore::SetLowered(bool lowered)
337 this->disp_flags = lowered ? SETBITS(this->disp_flags, ND_LOWERED) : CLRBITS(this->disp_flags, ND_LOWERED);
340 /** Return whether the widget is lowered. */
341 inline bool NWidgetCore::IsLowered() const
343 return HasBit(this->disp_flags, NDB_LOWERED);
347 * Disable (grey-out) or enable the widget.
348 * @param disabled Widget must be disabled.
350 inline void NWidgetCore::SetDisabled(bool disabled)
352 this->disp_flags = disabled ? SETBITS(this->disp_flags, ND_DISABLED) : CLRBITS(this->disp_flags, ND_DISABLED);
355 /** Return whether the widget is disabled. */
356 inline bool NWidgetCore::IsDisabled() const
358 return HasBit(this->disp_flags, NDB_DISABLED);
363 * Baseclass for container widgets.
364 * @ingroup NestedWidgets
366 class NWidgetContainer : public NWidgetBase {
367 public:
368 NWidgetContainer(WidgetType tp);
369 ~NWidgetContainer();
371 void Add(NWidgetBase *wid);
372 void FillNestedArray(NWidgetBase **array, uint length) override;
374 /** Return whether the container is empty. */
375 inline bool IsEmpty() { return head == nullptr; }
377 NWidgetBase *GetWidgetOfType(WidgetType tp) override;
379 protected:
380 NWidgetBase *head; ///< Pointer to first widget in container.
381 NWidgetBase *tail; ///< Pointer to last widget in container.
384 /** Display planes with zero size for #NWidgetStacked. */
385 enum StackedZeroSizePlanes {
386 SZSP_VERTICAL = INT_MAX / 2, ///< Display plane with zero size horizontally, and filling and resizing vertically.
387 SZSP_HORIZONTAL, ///< Display plane with zero size vertically, and filling and resizing horizontally.
388 SZSP_NONE, ///< Display plane with zero size in both directions (none filling and resizing).
390 SZSP_BEGIN = SZSP_VERTICAL, ///< First zero-size plane.
394 * Stacked widgets, widgets all occupying the same space in the window.
395 * #NWID_SELECTION allows for selecting one of several panels (planes) to tbe displayed. All planes must have the same size.
396 * Since all planes are also initialized, switching between different planes can be done while the window is displayed.
398 * There are also a number of special planes (defined in #StackedZeroSizePlanes) that have zero size in one direction (and are stretchable in
399 * the other direction) or have zero size in both directions. They are used to make all child planes of the widget disappear.
400 * 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
401 * a #Window::ReInit() is needed to re-initialize the window since its size changes.
403 class NWidgetStacked : public NWidgetContainer {
404 public:
405 NWidgetStacked();
407 void SetIndex(int index);
409 void SetupSmallestSize(Window *w, bool init_array) override;
410 void AssignSizePosition(SizingType sizing, uint x, uint y, uint given_width, uint given_height, bool rtl) override;
411 void FillNestedArray(NWidgetBase **array, uint length) override;
413 void Draw(const Window *w) override;
414 NWidgetCore *GetWidgetFromPos(int x, int y) override;
416 void SetDisplayedPlane(int plane);
418 int shown_plane; ///< Plane being displayed (for #NWID_SELECTION only).
419 int index; ///< If non-negative, index in the #Window::nested_array.
422 /** Nested widget container flags, */
423 enum NWidContainerFlags {
424 NCB_EQUALSIZE = 0, ///< Containers should keep all their (resizing) children equally large.
426 NC_NONE = 0, ///< All flags cleared.
427 NC_EQUALSIZE = 1 << NCB_EQUALSIZE, ///< Value of the #NCB_EQUALSIZE flag.
429 DECLARE_ENUM_AS_BIT_SET(NWidContainerFlags)
431 /** Container with pre/inter/post child space. */
432 class NWidgetPIPContainer : public NWidgetContainer {
433 public:
434 NWidgetPIPContainer(WidgetType tp, NWidContainerFlags flags = NC_NONE);
436 void SetPIP(uint8 pip_pre, uint8 pip_inter, uint8 pip_post);
438 void Draw(const Window *w) override;
439 NWidgetCore *GetWidgetFromPos(int x, int y) override;
441 protected:
442 NWidContainerFlags flags; ///< Flags of the container.
443 uint8 pip_pre; ///< Amount of space before first widget.
444 uint8 pip_inter; ///< Amount of space between widgets.
445 uint8 pip_post; ///< Amount of space after last widget.
449 * Horizontal container.
450 * @ingroup NestedWidgets
452 class NWidgetHorizontal : public NWidgetPIPContainer {
453 public:
454 NWidgetHorizontal(NWidContainerFlags flags = NC_NONE);
456 void SetupSmallestSize(Window *w, bool init_array);
457 void AssignSizePosition(SizingType sizing, uint x, uint y, uint given_width, uint given_height, bool rtl);
461 * Horizontal container that doesn't change the direction of the widgets for RTL languages.
462 * @ingroup NestedWidgets
464 class NWidgetHorizontalLTR : public NWidgetHorizontal {
465 public:
466 NWidgetHorizontalLTR(NWidContainerFlags flags = NC_NONE);
468 void AssignSizePosition(SizingType sizing, uint x, uint y, uint given_width, uint given_height, bool rtl);
472 * Vertical container.
473 * @ingroup NestedWidgets
475 class NWidgetVertical : public NWidgetPIPContainer {
476 public:
477 NWidgetVertical(NWidContainerFlags flags = NC_NONE);
479 void SetupSmallestSize(Window *w, bool init_array);
480 void AssignSizePosition(SizingType sizing, uint x, uint y, uint given_width, uint given_height, bool rtl);
484 * Matrix container with implicitly equal sized (virtual) sub-widgets.
485 * This widget must have exactly one sub-widget. After that this sub-widget
486 * is used to draw all of the data within the matrix piece by piece.
487 * DrawWidget and OnClick calls will be done to that sub-widget, where the
488 * 16 high bits are used to encode the index into the matrix.
489 * @ingroup NestedWidgets
491 class NWidgetMatrix : public NWidgetPIPContainer {
492 public:
493 NWidgetMatrix();
495 void SetIndex(int index);
496 void SetColour(Colours colour);
497 void SetClicked(int clicked);
498 void SetCount(int count);
499 void SetScrollbar(Scrollbar *sb);
501 void SetupSmallestSize(Window *w, bool init_array) override;
502 void AssignSizePosition(SizingType sizing, uint x, uint y, uint given_width, uint given_height, bool rtl) override;
503 void FillNestedArray(NWidgetBase **array, uint length) override;
505 NWidgetCore *GetWidgetFromPos(int x, int y) override;
506 void Draw(const Window *w) override;
507 protected:
508 int index; ///< If non-negative, index in the #Window::nested_array.
509 Colours colour; ///< Colour of this widget.
510 int clicked; ///< The currently clicked widget.
511 int count; ///< Amount of valid widgets.
512 Scrollbar *sb; ///< The scrollbar we're associated with.
513 private:
514 int widget_w; ///< The width of the child widget including inter spacing.
515 int widget_h; ///< The height of the child widget including inter spacing.
516 int widgets_x; ///< The number of visible widgets in horizontal direction.
517 int widgets_y; ///< The number of visible widgets in vertical direction.
519 void GetScrollOffsets(int &start_x, int &start_y, int &base_offs_x, int &base_offs_y);
524 * Spacer widget.
525 * @ingroup NestedWidgets
527 class NWidgetSpacer : public NWidgetResizeBase {
528 public:
529 NWidgetSpacer(int length, int height);
531 void SetupSmallestSize(Window *w, bool init_array) override;
532 void FillNestedArray(NWidgetBase **array, uint length) override;
534 void Draw(const Window *w) override;
535 void SetDirty(const Window *w) const override;
536 NWidgetCore *GetWidgetFromPos(int x, int y) override;
540 * Nested widget with a child.
541 * @ingroup NestedWidgets
543 class NWidgetBackground : public NWidgetCore {
544 public:
545 NWidgetBackground(WidgetType tp, Colours colour, int index, NWidgetPIPContainer *child = nullptr);
546 ~NWidgetBackground();
548 void Add(NWidgetBase *nwid);
549 void SetPIP(uint8 pip_pre, uint8 pip_inter, uint8 pip_post);
551 void SetupSmallestSize(Window *w, bool init_array) override;
552 void AssignSizePosition(SizingType sizing, uint x, uint y, uint given_width, uint given_height, bool rtl) override;
554 void FillNestedArray(NWidgetBase **array, uint length) override;
556 void Draw(const Window *w) override;
557 NWidgetCore *GetWidgetFromPos(int x, int y) override;
558 NWidgetBase *GetWidgetOfType(WidgetType tp) override;
560 private:
561 NWidgetPIPContainer *child; ///< Child widget.
565 * Nested widget to display a viewport in a window.
566 * After initializing the nested widget tree, call #InitializeViewport(). After changing the window size,
567 * call #UpdateViewportCoordinates() eg from Window::OnResize().
568 * If the #disp_flags field contains the #ND_NO_TRANSPARENCY bit, the viewport will disable transparency.
569 * 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).
570 * @todo Class derives from #NWidgetCore, but does not use #colour, #widget_data, or #tool_tip.
571 * @ingroup NestedWidgets
573 class NWidgetViewport : public NWidgetCore {
574 public:
575 NWidgetViewport(int index);
577 void SetupSmallestSize(Window *w, bool init_array) override;
578 void Draw(const Window *w) override;
580 void InitializeViewport(Window *w, uint32 follow_flags, ZoomLevel zoom);
581 void UpdateViewportCoordinates(Window *w);
585 * Scrollbar data structure
587 class Scrollbar {
588 private:
589 const bool is_vertical; ///< Scrollbar has vertical orientation.
590 uint16 count; ///< Number of elements in the list.
591 uint16 cap; ///< Number of visible elements of the scroll bar.
592 uint16 pos; ///< Index of first visible item of the list.
593 uint16 stepsize; ///< Distance to scroll, when pressing the buttons or using the wheel.
595 public:
596 /** Stepping sizes when scrolling */
597 enum ScrollbarStepping {
598 SS_RAW, ///< Step in single units.
599 SS_SMALL, ///< Step in #stepsize units.
600 SS_BIG, ///< Step in #cap units.
603 Scrollbar(bool is_vertical) : is_vertical(is_vertical), stepsize(1)
608 * Gets the number of elements in the list
609 * @return the number of elements
611 inline uint16 GetCount() const
613 return this->count;
617 * Gets the number of visible elements of the scrollbar
618 * @return the number of visible elements
620 inline uint16 GetCapacity() const
622 return this->cap;
626 * Gets the position of the first visible element in the list
627 * @return the position of the element
629 inline uint16 GetPosition() const
631 return this->pos;
635 * Checks whether given current item is visible in the list
636 * @param item to check
637 * @return true iff the item is visible
639 inline bool IsVisible(uint16 item) const
641 return IsInsideBS(item, this->GetPosition(), this->GetCapacity());
645 * Is the scrollbar vertical or not?
646 * @return True iff the scrollbar is vertical.
648 inline bool IsVertical() const
650 return this->is_vertical;
654 * Set the distance to scroll when using the buttons or the wheel.
655 * @param stepsize Scrolling speed.
657 void SetStepSize(uint16 stepsize)
659 assert(stepsize > 0);
660 this->stepsize = stepsize;
664 * Sets the number of elements in the list
665 * @param num the number of elements in the list
666 * @note updates the position if needed
668 void SetCount(int num)
670 assert(num >= 0);
671 assert(num <= MAX_UVALUE(uint16));
673 this->count = num;
674 num -= this->cap;
675 if (num < 0) num = 0;
676 if (num < this->pos) this->pos = num;
680 * Set the capacity of visible elements.
681 * @param capacity the new capacity
682 * @note updates the position if needed
684 void SetCapacity(int capacity)
686 assert(capacity > 0);
687 assert(capacity <= MAX_UVALUE(uint16));
689 this->cap = capacity;
690 if (this->cap + this->pos > this->count) this->pos = max(0, this->count - this->cap);
693 void SetCapacityFromWidget(Window *w, int widget, int padding = 0);
696 * Sets the position of the first visible element
697 * @param position the position of the element
699 void SetPosition(int position)
701 assert(position >= 0);
702 assert(this->count <= this->cap ? (position == 0) : (position + this->cap <= this->count));
703 this->pos = position;
707 * Updates the position of the first visible element by the given amount.
708 * If the position would be too low or high it will be clamped appropriately
709 * @param difference the amount of change requested
710 * @param unit The stepping unit of \a difference
712 void UpdatePosition(int difference, ScrollbarStepping unit = SS_SMALL)
714 if (difference == 0) return;
715 switch (unit) {
716 case SS_SMALL: difference *= this->stepsize; break;
717 case SS_BIG: difference *= this->cap; break;
718 default: break;
720 this->SetPosition(Clamp(this->pos + difference, 0, max(this->count - this->cap, 0)));
724 * Scroll towards the given position; if the item is visible nothing
725 * happens, otherwise it will be shown either at the bottom or top of
726 * the window depending on where in the list it was.
727 * @param position the position to scroll towards.
729 void ScrollTowards(int position)
731 if (position < this->GetPosition()) {
732 /* scroll up to the item */
733 this->SetPosition(position);
734 } else if (position >= this->GetPosition() + this->GetCapacity()) {
735 /* scroll down so that the item is at the bottom */
736 this->SetPosition(position - this->GetCapacity() + 1);
740 int GetScrolledRowFromWidget(int clickpos, const Window * const w, int widget, int padding = 0, int line_height = -1) const;
744 * Nested widget to display and control a scrollbar in a window.
745 * Also assign the scrollbar to other widgets using #SetScrollbar() to make the mousewheel work.
746 * @ingroup NestedWidgets
748 class NWidgetScrollbar : public NWidgetCore, public Scrollbar {
749 public:
750 NWidgetScrollbar(WidgetType tp, Colours colour, int index);
752 void SetupSmallestSize(Window *w, bool init_array) override;
753 void Draw(const Window *w) override;
755 static void InvalidateDimensionCache();
756 static Dimension GetVerticalDimension();
757 static Dimension GetHorizontalDimension();
759 private:
760 static Dimension vertical_dimension; ///< Cached size of vertical scrollbar button.
761 static Dimension horizontal_dimension; ///< Cached size of horizontal scrollbar button.
765 * Leaf widget.
766 * @ingroup NestedWidgets
768 class NWidgetLeaf : public NWidgetCore {
769 public:
770 NWidgetLeaf(WidgetType tp, Colours colour, int index, uint32 data, StringID tip);
772 void SetupSmallestSize(Window *w, bool init_array) override;
773 void Draw(const Window *w) override;
775 bool ButtonHit(const Point &pt);
777 static void InvalidateDimensionCache();
779 static Dimension dropdown_dimension; ///< Cached size of a dropdown widget.
780 static Dimension resizebox_dimension; ///< Cached size of a resizebox widget.
781 static Dimension closebox_dimension; ///< Cached size of a closebox widget.
782 private:
783 static Dimension shadebox_dimension; ///< Cached size of a shadebox widget.
784 static Dimension debugbox_dimension; ///< Cached size of a debugbox widget.
785 static Dimension defsizebox_dimension; ///< Cached size of a defsizebox widget.
786 static Dimension stickybox_dimension; ///< Cached size of a stickybox widget.
790 * Return the biggest possible size of a nested widget.
791 * @param base Base size of the widget.
792 * @param max_space Available space for the widget.
793 * @param step Stepsize of the widget.
794 * @return Biggest possible size of the widget, assuming that \a base may only be incremented by \a step size steps.
796 static inline uint ComputeMaxSize(uint base, uint max_space, uint step)
798 if (base >= max_space || step == 0) return base;
799 if (step == 1) return max_space;
800 uint increment = max_space - base;
801 increment -= increment % step;
802 return base + increment;
806 * @defgroup NestedWidgetParts Hierarchical widget parts
807 * 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.
809 * - Leaf widgets start with a #NWidget(WidgetType tp, Colours col, int16 idx) part.
810 * Next, specify its properties with one or more of
811 * - #SetMinimalSize Define the minimal size of the widget.
812 * - #SetFill Define how the widget may grow to make it nicely.
813 * - #SetDataTip Define the data and the tooltip of the widget.
814 * - #SetResize Define how the widget may resize.
815 * - #SetPadding Create additional space around the widget.
817 * - To insert a nested widget tree from an external source, nested widget part #NWidgetFunction exists.
818 * For further customization, the #SetPadding part may be used.
820 * - Space widgets (#NWidgetSpacer) start with a #NWidget(WidgetType tp), followed by one or more of
821 * - #SetMinimalSize Define the minimal size of the widget.
822 * - #SetFill Define how the widget may grow to make it nicely.
823 * - #SetResize Define how the widget may resize.
824 * - #SetPadding Create additional space around the widget.
826 * - Container widgets #NWidgetHorizontal, #NWidgetHorizontalLTR, #NWidgetVertical, and #NWidgetMatrix, start with a #NWidget(WidgetType tp) part.
827 * Their properties are derived from the child widgets so they cannot be specified.
828 * You can however use
829 * - #SetPadding Define additional padding around the container.
830 * - #SetPIP Set additional pre/inter/post child widget space.
832 * 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
833 * the child widgets (it has no meaning for the compiler but it makes the widget parts easier to read).
834 * Below the last child widget, use an #EndContainer part. This part should be aligned with the #NWidget part that started the container.
836 * - 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,
837 * so the widget does not support #SetPIP. #SetPadding is allowed though.
838 * Like the other container widgets, below the last child widgets, a #EndContainer part should be used to denote the end of the stacked widget.
840 * - Background widgets #NWidgetBackground start with a #NWidget(WidgetType tp, Colours col, int16 idx) part.
841 * What follows depends on how the widget is used.
842 * - 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
843 * leaf widgets to define how it behaves.
844 * - 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
845 * behaviour.
847 * In both cases, the background widget \b MUST end with a #EndContainer widget part.
849 * @see NestedWidgets
853 * Widget part for storing data and tooltip information.
854 * @ingroup NestedWidgetParts
856 struct NWidgetPartDataTip {
857 uint32 data; ///< Data value of the widget.
858 StringID tooltip; ///< Tooltip of the widget.
862 * Widget part for storing basic widget information.
863 * @ingroup NestedWidgetParts
865 struct NWidgetPartWidget {
866 Colours colour; ///< Widget colour.
867 int16 index; ///< Widget index in the widget array.
871 * Widget part for storing padding.
872 * @ingroup NestedWidgetParts
874 struct NWidgetPartPaddings {
875 uint8 top, right, bottom, left; ///< Paddings for all directions.
879 * Widget part for storing pre/inter/post spaces.
880 * @ingroup NestedWidgetParts
882 struct NWidgetPartPIP {
883 uint8 pre, inter, post; ///< Amount of space before/between/after child widgets.
887 * Widget part for storing minimal text line data.
888 * @ingroup NestedWidgetParts
890 struct NWidgetPartTextLines {
891 uint8 lines; ///< Number of text lines.
892 uint8 spacing; ///< Extra spacing around lines.
893 FontSize size; ///< Font size of text lines.
897 * Pointer to function returning a nested widget.
898 * @param biggest_index Pointer to storage for collecting the biggest index used in the nested widget.
899 * @return Nested widget (tree).
900 * @post \c *biggest_index must contain the value of the biggest index in the returned tree.
902 typedef NWidgetBase *NWidgetFunctionType(int *biggest_index);
905 * Partial widget specification to allow NWidgets to be written nested.
906 * @ingroup NestedWidgetParts
908 struct NWidgetPart {
909 WidgetType type; ///< Type of the part. @see NWidgetPartType.
910 union {
911 Point xy; ///< Part with an x/y size.
912 NWidgetPartDataTip data_tip; ///< Part with a data/tooltip.
913 NWidgetPartWidget widget; ///< Part with a start of a widget.
914 NWidgetPartPaddings padding; ///< Part with paddings.
915 NWidgetPartPIP pip; ///< Part with pre/inter/post spaces.
916 NWidgetPartTextLines text_lines; ///< Part with text line data.
917 NWidgetFunctionType *func_ptr; ///< Part with a function call.
918 NWidContainerFlags cont_flags; ///< Part with container flags.
919 } u;
923 * Widget part function for setting the resize step.
924 * @param dx Horizontal resize step. 0 means no horizontal resizing.
925 * @param dy Vertical resize step. 0 means no vertical resizing.
926 * @ingroup NestedWidgetParts
928 static inline NWidgetPart SetResize(int16 dx, int16 dy)
930 NWidgetPart part;
932 part.type = WPT_RESIZE;
933 part.u.xy.x = dx;
934 part.u.xy.y = dy;
936 return part;
940 * Widget part function for setting the minimal size.
941 * @param x Horizontal minimal size.
942 * @param y Vertical minimal size.
943 * @ingroup NestedWidgetParts
945 static inline NWidgetPart SetMinimalSize(int16 x, int16 y)
947 NWidgetPart part;
949 part.type = WPT_MINSIZE;
950 part.u.xy.x = x;
951 part.u.xy.y = y;
953 return part;
957 * Widget part function for setting the minimal text lines.
958 * @param lines Number of text lines.
959 * @param spacing Extra spacing required.
960 * @param size Font size of text.
961 * @ingroup NestedWidgetParts
963 static inline NWidgetPart SetMinimalTextLines(uint8 lines, uint8 spacing, FontSize size = FS_NORMAL)
965 NWidgetPart part;
967 part.type = WPT_MINTEXTLINES;
968 part.u.text_lines.lines = lines;
969 part.u.text_lines.spacing = spacing;
970 part.u.text_lines.size = size;
972 return part;
976 * Widget part function for setting filling.
977 * @param fill_x Horizontal filling step from minimal size.
978 * @param fill_y Vertical filling step from minimal size.
979 * @ingroup NestedWidgetParts
981 static inline NWidgetPart SetFill(uint fill_x, uint fill_y)
983 NWidgetPart part;
985 part.type = WPT_FILL;
986 part.u.xy.x = fill_x;
987 part.u.xy.y = fill_y;
989 return part;
993 * Widget part function for denoting the end of a container
994 * (horizontal, vertical, WWT_FRAME, WWT_INSET, or WWT_PANEL).
995 * @ingroup NestedWidgetParts
997 static inline NWidgetPart EndContainer()
999 NWidgetPart part;
1001 part.type = WPT_ENDCONTAINER;
1003 return part;
1007 * Widget part function for setting the data and tooltip.
1008 * @param data Data of the widget.
1009 * @param tip Tooltip of the widget.
1010 * @ingroup NestedWidgetParts
1012 static inline NWidgetPart SetDataTip(uint32 data, StringID tip)
1014 NWidgetPart part;
1016 part.type = WPT_DATATIP;
1017 part.u.data_tip.data = data;
1018 part.u.data_tip.tooltip = tip;
1020 return part;
1024 * Widget part function for setting the data and tooltip of WWT_MATRIX widgets
1025 * @param cols Number of columns. \c 0 means to use draw columns with width according to the resize step size.
1026 * @param rows Number of rows. \c 0 means to use draw rows with height according to the resize step size.
1027 * @param tip Tooltip of the widget.
1028 * @ingroup NestedWidgetParts
1030 static inline NWidgetPart SetMatrixDataTip(uint8 cols, uint8 rows, StringID tip)
1032 return SetDataTip((rows << MAT_ROW_START) | (cols << MAT_COL_START), tip);
1036 * Widget part function for setting additional space around a widget.
1037 * Parameters start above the widget, and are specified in clock-wise direction.
1038 * @param top The padding above the widget.
1039 * @param right The padding right of the widget.
1040 * @param bottom The padding below the widget.
1041 * @param left The padding left of the widget.
1042 * @ingroup NestedWidgetParts
1044 static inline NWidgetPart SetPadding(uint8 top, uint8 right, uint8 bottom, uint8 left)
1046 NWidgetPart part;
1048 part.type = WPT_PADDING;
1049 part.u.padding.top = top;
1050 part.u.padding.right = right;
1051 part.u.padding.bottom = bottom;
1052 part.u.padding.left = left;
1054 return part;
1058 * Widget part function for setting a padding.
1059 * @param padding The padding to use for all directions.
1060 * @ingroup NestedWidgetParts
1062 static inline NWidgetPart SetPadding(uint8 padding)
1064 return SetPadding(padding, padding, padding, padding);
1068 * Widget part function for setting a pre/inter/post spaces.
1069 * @param pre The amount of space before the first widget.
1070 * @param inter The amount of space between widgets.
1071 * @param post The amount of space after the last widget.
1072 * @ingroup NestedWidgetParts
1074 static inline NWidgetPart SetPIP(uint8 pre, uint8 inter, uint8 post)
1076 NWidgetPart part;
1078 part.type = WPT_PIPSPACE;
1079 part.u.pip.pre = pre;
1080 part.u.pip.inter = inter;
1081 part.u.pip.post = post;
1083 return part;
1087 * Attach a scrollbar to a widget.
1088 * The scrollbar is controlled when using the mousewheel on the widget.
1089 * Multiple widgets can refer to the same scrollbar to make the mousewheel work in all of them.
1090 * @param index Widget index of the scrollbar.
1091 * @ingroup NestedWidgetParts
1093 static inline NWidgetPart SetScrollbar(int index)
1095 NWidgetPart part;
1097 part.type = WPT_SCROLLBAR;
1098 part.u.widget.index = index;
1100 return part;
1104 * Widget part function for starting a new 'real' widget.
1105 * @param tp Type of the new nested widget.
1106 * @param col Colour of the new widget.
1107 * @param idx Index of the widget in the widget array.
1108 * @note with #WWT_PANEL, #WWT_FRAME, #WWT_INSET, a new container is started.
1109 * Child widgets must have a index bigger than the parent index.
1110 * @ingroup NestedWidgetParts
1112 static inline NWidgetPart NWidget(WidgetType tp, Colours col, int16 idx = -1)
1114 NWidgetPart part;
1116 part.type = tp;
1117 part.u.widget.colour = col;
1118 part.u.widget.index = idx;
1120 return part;
1124 * Widget part function for starting a new horizontal container, vertical container, or spacer widget.
1125 * @param tp Type of the new nested widget, #NWID_HORIZONTAL, #NWID_VERTICAL, #NWID_SPACER, #NWID_SELECTION, and #NWID_MATRIX.
1126 * @param cont_flags Flags for the containers (#NWID_HORIZONTAL and #NWID_VERTICAL).
1127 * @ingroup NestedWidgetParts
1129 static inline NWidgetPart NWidget(WidgetType tp, NWidContainerFlags cont_flags = NC_NONE)
1131 NWidgetPart part;
1133 part.type = tp;
1134 part.u.cont_flags = cont_flags;
1136 return part;
1140 * Obtain a nested widget (sub)tree from an external source.
1141 * @param func_ptr Pointer to function that returns the tree.
1142 * @ingroup NestedWidgetParts
1144 static inline NWidgetPart NWidgetFunction(NWidgetFunctionType *func_ptr)
1146 NWidgetPart part;
1148 part.type = WPT_FUNCTION;
1149 part.u.func_ptr = func_ptr;
1151 return part;
1154 NWidgetContainer *MakeNWidgets(const NWidgetPart *parts, int count, int *biggest_index, NWidgetContainer *container);
1155 NWidgetContainer *MakeWindowNWidgetTree(const NWidgetPart *parts, int count, int *biggest_index, NWidgetStacked **shade_select);
1157 NWidgetBase *MakeCompanyButtonRows(int *biggest_index, int widget_first, int widget_last, int max_length, StringID button_tooltip);
1159 #endif /* WIDGET_TYPE_H */