Fix #10490: Allow ships to exit depots if another is not moving at the exit point...
[openttd-github.git] / src / widgets / dropdown_type.h
blob485ce44c8b2a702f004ccd80ed70bea3f154dcc7
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 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"
22 /**
23 * Base list item class from which others are derived.
25 class DropDownListItem {
26 public:
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;
50 /**
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 {
57 public:
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);
75 /**
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.
85 public:
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.
145 public:
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.
181 public:
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);
194 if (this->checked) {
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 */