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 dropdown_type.h Types related to the drop down widget. */
10 #ifndef WIDGETS_DROPDOWN_TYPE_H
11 #define WIDGETS_DROPDOWN_TYPE_H
13 #include "../window_type.h"
14 #include "../gfx_func.h"
15 #include "../gfx_type.h"
16 #include "../palette_func.h"
17 #include "../string_func.h"
18 #include "../strings_func.h"
19 #include "../table/strings.h"
20 #include "../window_gui.h"
23 * Base list item class from which others are derived.
25 class DropDownListItem
{
27 int result
; ///< Result value to return to window on selection.
28 bool masked
; ///< Masked and unselectable item.
29 bool shaded
; ///< Shaded item, affects text colour.
31 explicit DropDownListItem(int result
, bool masked
= false, bool shaded
= false) : result(result
), masked(masked
), shaded(shaded
) {}
32 virtual ~DropDownListItem() = default;
34 virtual bool Selectable() const { return true; }
35 virtual uint
Height() const { return 0; }
36 virtual uint
Width() const { return 0; }
38 virtual void Draw(const Rect
&full
, const Rect
&, bool, Colours bg_colour
) const
40 if (this->masked
) GfxFillRect(full
, _colour_gradient
[bg_colour
][5], FILLRECT_CHECKER
);
43 TextColour
GetColour(bool sel
) const
45 if (this->shaded
) return (sel
? TC_SILVER
: TC_GREY
) | TC_NO_SHADE
;
46 return sel
? TC_WHITE
: TC_BLACK
;
51 * Drop down divider component.
52 * @tparam TBase Base component.
53 * @tparam TFs Font size -- used to determine height.
55 template<class TBase
, FontSize TFs
= FS_NORMAL
>
56 class DropDownDivider
: public TBase
{
58 template <typename
... Args
>
59 explicit DropDownDivider(Args
&&... args
) : TBase(std::forward
<Args
>(args
)...) {}
61 bool Selectable() const override
{ return false; }
62 uint
Height() const override
{ return std::max
<uint
>(GetCharacterHeight(TFs
), this->TBase::Height()); }
64 void Draw(const Rect
&full
, const Rect
&, bool, Colours bg_colour
) const override
66 uint8_t c1
= _colour_gradient
[bg_colour
][3];
67 uint8_t c2
= _colour_gradient
[bg_colour
][7];
69 int mid
= CenterBounds(full
.top
, full
.bottom
, 0);
70 GfxFillRect(full
.left
, mid
- WidgetDimensions::scaled
.bevel
.bottom
, full
.right
, mid
- 1, c1
);
71 GfxFillRect(full
.left
, mid
, full
.right
, mid
+ WidgetDimensions::scaled
.bevel
.top
- 1, c2
);
76 * Drop down string component.
77 * @tparam TBase Base component.
78 * @tparam TFs Font size.
79 * @tparam TEnd Position string at end if true, or start if false.
81 template<class TBase
, FontSize TFs
= FS_NORMAL
, bool TEnd
= false>
82 class DropDownString
: public TBase
{
83 std::string string
; ///< String to be drawn.
84 Dimension dim
; ///< Dimensions of string.
86 template <typename
... Args
>
87 explicit DropDownString(StringID string
, Args
&&... args
) : TBase(std::forward
<Args
>(args
)...)
89 this->SetString(GetString(string
));
92 template <typename
... Args
>
93 explicit DropDownString(const std::string
&string
, Args
&&... args
) : TBase(std::forward
<Args
>(args
)...)
95 SetDParamStr(0, string
);
96 this->SetString(GetString(STR_JUST_RAW_STRING
));
99 void SetString(std::string
&&string
)
101 this->string
= std::move(string
);
102 this->dim
= GetStringBoundingBox(this->string
, TFs
);
105 uint
Height() const override
107 return std::max
<uint
>(this->dim
.height
, this->TBase::Height());
110 uint
Width() const override
{ return this->dim
.width
+ this->TBase::Width(); }
112 void Draw(const Rect
&full
, const Rect
&r
, bool sel
, Colours bg_colour
) const override
114 bool rtl
= TEnd
^ (_current_text_dir
== TD_RTL
);
115 DrawStringMultiLine(r
.WithWidth(this->dim
.width
, rtl
), this->string
, this->GetColour(sel
), SA_CENTER
, false, TFs
);
116 this->TBase::Draw(full
, r
.Indent(this->dim
.width
, rtl
), sel
, bg_colour
);
120 * Natural sorting comparator function for DropDownList::sort().
121 * @param first Left side of comparison.
122 * @param second Right side of comparison.
123 * @return true if \a first precedes \a second.
124 * @warning All items in the list need to be derivates of DropDownListStringItem.
126 static bool NatSortFunc(std::unique_ptr
<const DropDownListItem
> const &first
, std::unique_ptr
<const DropDownListItem
> const &second
)
128 const std::string
&str1
= static_cast<const DropDownString
*>(first
.get())->string
;
129 const std::string
&str2
= static_cast<const DropDownString
*>(second
.get())->string
;
130 return StrNaturalCompare(str1
, str2
) < 0;
135 * Drop down icon component.
136 * @tparam TBase Base component.
137 * @tparam TEnd Position icon at end if true, or start if false.
139 template<class TBase
, bool TEnd
= false>
140 class DropDownIcon
: public TBase
{
141 SpriteID sprite
; ///< Sprite ID to be drawn.
142 PaletteID palette
; ///< Palette ID to use.
143 Dimension dsprite
; ///< Bounding box dimensions of sprite.
144 Dimension dbounds
; ///< Bounding box dimensions of bounds.
146 template <typename
... Args
>
147 explicit DropDownIcon(SpriteID sprite
, PaletteID palette
, Args
&&... args
) : TBase(std::forward
<Args
>(args
)...), sprite(sprite
), palette(palette
)
149 this->dsprite
= GetSpriteSize(this->sprite
);
150 this->dbounds
= this->dsprite
;
153 template <typename
... Args
>
154 explicit DropDownIcon(const Dimension
&dim
, SpriteID sprite
, PaletteID palette
, Args
&&... args
) : TBase(std::forward
<Args
>(args
)...), sprite(sprite
), palette(palette
), dbounds(dim
)
156 this->dsprite
= GetSpriteSize(this->sprite
);
159 uint
Height() const override
{ return std::max(this->dbounds
.height
, this->TBase::Height()); }
160 uint
Width() const override
{ return this->dbounds
.width
+ WidgetDimensions::scaled
.hsep_normal
+ this->TBase::Width(); }
162 void Draw(const Rect
&full
, const Rect
&r
, bool sel
, Colours bg_colour
) const override
164 bool rtl
= TEnd
^ (_current_text_dir
== TD_RTL
);
165 Rect ir
= r
.WithWidth(this->dbounds
.width
, rtl
);
166 DrawSprite(this->sprite
, this->palette
, CenterBounds(ir
.left
, ir
.right
, this->dsprite
.width
), CenterBounds(r
.top
, r
.bottom
, this->dsprite
.height
));
167 this->TBase::Draw(full
, r
.Indent(this->dbounds
.width
+ WidgetDimensions::scaled
.hsep_normal
, rtl
), sel
, bg_colour
);
172 * Drop down checkmark component.
173 * @tparam TBase Base component.
174 * @tparam TFs Font size.
175 * @tparam TEnd Position checkmark at end if true, or start if false.
177 template<class TBase
, bool TEnd
= false, FontSize TFs
= FS_NORMAL
>
178 class DropDownCheck
: public TBase
{
179 bool checked
; ///< Is item checked.
180 Dimension dim
; ///< Dimension of checkmark.
182 template <typename
... Args
>
183 explicit DropDownCheck(bool checked
, Args
&&... args
) : TBase(std::forward
<Args
>(args
)...), checked(checked
)
185 this->dim
= GetStringBoundingBox(STR_JUST_CHECKMARK
, TFs
);
188 uint
Height() const override
{ return std::max
<uint
>(this->dim
.height
, this->TBase::Height()); }
189 uint
Width() const override
{ return this->dim
.width
+ WidgetDimensions::scaled
.hsep_wide
+ this->TBase::Width(); }
191 void Draw(const Rect
&full
, const Rect
&r
, bool sel
, Colours bg_colour
) const override
193 bool rtl
= TEnd
^ (_current_text_dir
== TD_RTL
);
195 DrawStringMultiLine(r
.WithWidth(this->dim
.width
, rtl
), STR_JUST_CHECKMARK
, this->GetColour(sel
), SA_CENTER
, false, TFs
);
197 this->TBase::Draw(full
, r
.Indent(this->dim
.width
+ WidgetDimensions::scaled
.hsep_wide
, rtl
), sel
, bg_colour
);
201 /* Commonly used drop down list items. */
202 using DropDownListDividerItem
= DropDownDivider
<DropDownListItem
>;
203 using DropDownListStringItem
= DropDownString
<DropDownListItem
>;
204 using DropDownListIconItem
= DropDownIcon
<DropDownString
<DropDownListItem
>>;
205 using DropDownListCheckedItem
= DropDownCheck
<DropDownString
<DropDownListItem
>>;
208 * A drop down list is a collection of drop down list items.
210 typedef std::vector
<std::unique_ptr
<const DropDownListItem
>> DropDownList
;
212 void ShowDropDownListAt(Window
*w
, DropDownList
&&list
, int selected
, WidgetID button
, Rect wi_rect
, Colours wi_colour
, bool instant_close
= false, bool persist
= false);
214 void ShowDropDownList(Window
*w
, DropDownList
&&list
, int selected
, WidgetID button
, uint width
= 0, bool instant_close
= false, bool persist
= false);
216 Dimension
GetDropDownListDimension(const DropDownList
&list
);
218 void ReplaceDropDownList(Window
*parent
, DropDownList
&&list
);
220 #endif /* WIDGETS_DROPDOWN_TYPE_H */