OpenTTD Source 20260311-master-g511d3794ce
newgrf_badge_gui.cpp
Go to the documentation of this file.
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 <https://www.gnu.org/licenses/old-licenses/gpl-2.0>.
6 */
7
9
10#include "stdafx.h"
11
12#include "core/flatset_type.hpp"
13#include "dropdown_type.h"
14#include "dropdown_func.h"
15#include "newgrf.h"
16#include "newgrf_badge.h"
17#include "newgrf_badge_config.h"
18#include "newgrf_badge_gui.h"
19#include "newgrf_badge_type.h"
20#include "settings_gui.h"
21#include "strings_func.h"
23#include "window_gui.h"
24#include "window_type.h"
25#include "zoom_func.h"
26
27#include "table/strings.h"
28
30
31#include "safeguards.h"
32
33static constexpr uint MAX_BADGE_HEIGHT = 12;
34static constexpr uint MAX_BADGE_WIDTH = MAX_BADGE_HEIGHT * 2;
35
42static Dimension GetBadgeMaximalDimension(BadgeClassID class_index, GrfSpecFeature feature)
43{
45
46 for (const auto &badge : GetBadges()) {
47 if (badge.class_index != class_index) continue;
48
49 PalSpriteID ps = GetBadgeSprite(badge, feature, std::nullopt, PAL_NONE);
50 if (ps.sprite == 0) continue;
51
52 d.width = std::max(d.width, GetSpriteSize(ps.sprite, nullptr, ZoomLevel::Normal).width);
53 if (d.width > MAX_BADGE_WIDTH) break;
54 }
55
56 d.width = std::min(d.width, MAX_BADGE_WIDTH);
57 return d;
58}
59
60static bool operator<(const GUIBadgeClasses::Element &a, const GUIBadgeClasses::Element &b)
61{
62 if (a.column_group != b.column_group) return a.column_group < b.column_group;
63 if (a.sort_order != b.sort_order) return a.sort_order < b.sort_order;
64 return a.label < b.label;
65}
66
71GUIBadgeClasses::GUIBadgeClasses(GrfSpecFeature feature) : UsedBadgeClasses(feature)
72{
73 /* Get list of classes used by feature. */
74 uint max_column = 0;
75 for (BadgeClassID class_index : this->Classes()) {
76 const Badge *class_badge = GetClassBadge(class_index);
77 if (class_badge->name == STR_NULL) continue;
78
79 Dimension size = GetBadgeMaximalDimension(class_index, feature);
80 if (size.width == 0) continue;
81
82 const auto [config, sort_order] = GetBadgeClassConfigItem(feature, class_badge->label);
83
84 this->gui_classes.emplace_back(class_index, config.column, config.show_icon, sort_order, size, class_badge->label);
85 if (size.width != 0 && config.show_icon) max_column = std::max(max_column, config.column);
86 }
87
88 std::sort(std::begin(this->gui_classes), std::end(this->gui_classes));
89
90 /* Determine total width of visible badge columns. */
91 this->column_widths.resize(max_column + 1);
92 for (const auto &el : this->gui_classes) {
93 if (!el.visible || el.size.width == 0) continue;
94 this->column_widths[el.column_group] += ScaleGUITrad(el.size.width) + WidgetDimensions::scaled.hsep_normal;
95 }
96
97 /* Replace trailing `hsep_normal` spacer with wider `hsep_wide` spacer. */
98 for (uint &badge_width : this->column_widths) {
99 if (badge_width == 0) continue;
100 badge_width = badge_width - WidgetDimensions::scaled.hsep_normal + WidgetDimensions::scaled.hsep_wide;
101 }
102}
103
109{
110 return std::accumulate(std::begin(this->column_widths), std::end(this->column_widths), 0U);
111}
112
120int DrawBadgeNameList(Rect r, std::span<const BadgeID> badges, GrfSpecFeature)
121{
122 if (badges.empty()) return r.top;
123
124 FlatSet<BadgeClassID> class_indexes;
125 for (const BadgeID &index : badges) class_indexes.insert(GetBadge(index)->class_index);
126
127 std::string_view list_separator = GetListSeparator();
128 for (const BadgeClassID &class_index : class_indexes) {
129 const Badge *class_badge = GetClassBadge(class_index);
130 if (class_badge == nullptr || class_badge->name == STR_NULL) continue;
131
132 std::string s;
133 for (const BadgeID &index : badges) {
134 const Badge *badge = GetBadge(index);
135 if (badge == nullptr || badge->name == STR_NULL) continue;
136 if (badge->class_index != class_index) continue;
137 if (badge->flags.Test(BadgeFlag::NameListSkip)) continue;
138
139 if (!s.empty()) {
140 if (badge->flags.Test(BadgeFlag::NameListFirstOnly)) continue;
141 s += list_separator;
142 }
143 AppendStringInPlace(s, badge->name);
144 if (badge->flags.Test(BadgeFlag::NameListStop)) break;
145 }
146
147 if (s.empty()) continue;
148
149 r.top = DrawStringMultiLine(r, GetString(STR_BADGE_NAME_LIST, class_badge->name, std::move(s)), TC_BLACK);
150 }
151
152 return r.top;
153}
154
165void DrawBadgeColumn(Rect r, int column_group, const GUIBadgeClasses &gui_classes, std::span<const BadgeID> badges, GrfSpecFeature feature, std::optional<TimerGameCalendar::Date> introduction_date, PaletteID remap)
166{
167 bool rtl = _current_text_dir == TD_RTL;
168 for (const auto &gc : gui_classes.GetClasses()) {
169 if (gc.column_group != column_group) continue;
170 if (!gc.visible) continue;
171
172 int width = ScaleGUITrad(gc.size.width);
173 for (const BadgeID &index : badges) {
174 const Badge &badge = *GetBadge(index);
175 if (badge.class_index != gc.class_index) continue;
176
177 PalSpriteID ps = GetBadgeSprite(badge, feature, introduction_date, remap);
178 if (ps.sprite == 0) continue;
179
180 DrawSpriteIgnorePadding(ps.sprite, ps.pal, r.WithWidth(width, rtl), SA_CENTER);
181 break;
182 }
183
184 r = r.Indent(width + WidgetDimensions::scaled.hsep_normal, rtl);
185 }
186}
187
189template <class TBase, bool TEnd = true, FontSize TFs = FS_NORMAL>
190class DropDownBadges : public TBase {
191public:
192 template <typename... Args>
193 explicit DropDownBadges(const std::shared_ptr<GUIBadgeClasses> &gui_classes, std::span<const BadgeID> badges, GrfSpecFeature feature, std::optional<TimerGameCalendar::Date> introduction_date, Args &&...args) :
194 TBase(std::forward<Args>(args)...), gui_classes(gui_classes), badges(badges), feature(feature), introduction_date(introduction_date)
195 {
196 for (const auto &gc : gui_classes->GetClasses()) {
197 if (gc.column_group != 0) continue;
198 dim.width += ScaleGUITrad(gc.size.width) + WidgetDimensions::scaled.hsep_normal;
199 dim.height = std::max<uint>(dim.height, ScaleGUITrad(gc.size.height));
200 }
201
202 /* Remove trailing `hsep_normal` spacer. */
203 if (dim.width > 0) dim.width -= WidgetDimensions::scaled.hsep_normal;
204 }
205
207 void FilterText(StringFilter &string_filter) const override
208 {
209 for (const BadgeID &badge_index : this->badges) {
210 const Badge *badge = GetBadge(badge_index);
211 if (badge->name == STR_NULL) continue;
212 string_filter.AddLine(GetString(badge->name));
213 }
214 this->TBase::FilterText(string_filter);
215 }
216
217 uint Height() const override
218 {
219 return std::max<uint>(this->dim.height, this->TBase::Height());
220 }
221
222 uint Width() const override
223 {
224 if (this->dim.width == 0) return this->TBase::Width();
225 return this->dim.width + WidgetDimensions::scaled.hsep_normal + this->TBase::Width();
226 }
227
228 int OnClick(const Rect &r, const Point &pt) const override
229 {
230 if (this->dim.width == 0) {
231 return this->TBase::OnClick(r, pt);
232 } else {
233 bool rtl = TEnd ^ (_current_text_dir == TD_RTL);
234 return this->TBase::OnClick(r.Indent(this->dim.width + WidgetDimensions::scaled.hsep_normal, rtl), pt);
235 }
236 }
237
238 void Draw(const Rect &full, const Rect &r, bool sel, int click_result, Colours bg_colour) const override
239 {
240 if (this->dim.width == 0) {
241 this->TBase::Draw(full, r, sel, click_result, bg_colour);
242 } else {
243 bool rtl = TEnd ^ (_current_text_dir == TD_RTL);
244 DrawBadgeColumn(r.WithWidth(this->dim.width, rtl), 0, *this->gui_classes, this->badges, this->feature, this->introduction_date, PAL_NONE);
245 this->TBase::Draw(full, r.Indent(this->dim.width + WidgetDimensions::scaled.hsep_normal, rtl), sel, click_result, bg_colour);
246 }
247 }
248
249private:
250 std::shared_ptr<GUIBadgeClasses> gui_classes;
251
252 const std::span<const BadgeID> badges;
253 const GrfSpecFeature feature;
254 const std::optional<TimerGameCalendar::Date> introduction_date;
255
256 Dimension dim{};
257};
258
261
262std::unique_ptr<DropDownListItem> MakeDropDownListBadgeItem(const std::shared_ptr<GUIBadgeClasses> &gui_classes, std::span<const BadgeID> badges, GrfSpecFeature feature, std::optional<TimerGameCalendar::Date> introduction_date, std::string &&str, int value, bool masked, bool shaded)
263{
264 return std::make_unique<DropDownListBadgeItem>(gui_classes, badges, feature, introduction_date, "", std::move(str), value, masked, shaded);
265}
266
267std::unique_ptr<DropDownListItem> MakeDropDownListBadgeItem(const std::shared_ptr<GUIBadgeClasses> &gui_classes, std::span<const BadgeID> badges, GrfSpecFeature feature, std::optional<TimerGameCalendar::Date> introduction_date, Money cost, std::string &&str, int value, bool masked, bool shaded)
268{
269 return std::make_unique<DropDownListBadgeItem>(gui_classes, badges, feature, introduction_date, GetString(STR_JUST_CURRENCY_SHORT, cost), std::move(str), value, masked, shaded);
270}
271
272std::unique_ptr<DropDownListItem> MakeDropDownListBadgeIconItem(const std::shared_ptr<GUIBadgeClasses> &gui_classes, std::span<const BadgeID> badges, GrfSpecFeature feature, std::optional<TimerGameCalendar::Date> introduction_date, Money cost, const Dimension &dim, SpriteID sprite, PaletteID palette, std::string &&str, int value, bool masked, bool shaded)
273{
274 return std::make_unique<DropDownListBadgeIconItem>(gui_classes, badges, feature, introduction_date, GetString(STR_JUST_CURRENCY_SHORT, cost), dim, sprite, palette, std::move(str), value, masked, shaded);
275}
276
280template <class TBase, bool TEnd = true, FontSize TFs = FS_NORMAL>
281class DropDownMover : public TBase {
282public:
283 template <typename... Args>
284 explicit DropDownMover(int click_up, int click_down, Colours button_colour, Args &&...args)
285 : TBase(std::forward<Args>(args)...), click_up(click_up), click_down(click_down), button_colour(button_colour)
286 {
287 }
288
289 uint Height() const override
290 {
291 return std::max<uint>(SETTING_BUTTON_HEIGHT, this->TBase::Height());
292 }
293
294 uint Width() const override
295 {
296 return SETTING_BUTTON_WIDTH + WidgetDimensions::scaled.hsep_wide + this->TBase::Width();
297 }
298
299 int OnClick(const Rect &r, const Point &pt) const override
300 {
301 bool rtl = (_current_text_dir == TD_RTL);
302 int w = SETTING_BUTTON_WIDTH;
303
304 Rect br = r.WithWidth(w, TEnd ^ rtl).CentreToHeight(SETTING_BUTTON_HEIGHT);
305 if (br.WithWidth(w / 2, rtl).Contains(pt)) return this->click_up;
306 if (br.WithWidth(w / 2, !rtl).Contains(pt)) return this->click_down;
307
308 return this->TBase::OnClick(r.Indent(w + WidgetDimensions::scaled.hsep_wide, TEnd ^ rtl), pt);
309 }
310
311 void Draw(const Rect &full, const Rect &r, bool sel, int click_result, Colours bg_colour) const override
312 {
313 bool rtl = (_current_text_dir == TD_RTL);
314 int w = SETTING_BUTTON_WIDTH;
315
316 int state = 0;
317 if (sel && click_result != 0) {
318 if (click_result == this->click_up) state = 1;
319 if (click_result == this->click_down) state = 2;
320 }
321
322 Rect br = r.WithWidth(w, TEnd ^ rtl).CentreToHeight(SETTING_BUTTON_HEIGHT);
323 DrawUpDownButtons(br.left, br.top, this->button_colour, state, this->click_up != 0, this->click_down != 0);
324
325 this->TBase::Draw(full, r.Indent(w + WidgetDimensions::scaled.hsep_wide, TEnd ^ rtl), sel, click_result, bg_colour);
326 }
327
328private:
332};
333
334using DropDownListToggleMoverItem = DropDownMover<DropDownToggle<DropDownString<DropDownListItem>>>;
335using DropDownListToggleItem = DropDownToggle<DropDownString<DropDownListItem>>;
336
337enum BadgeClick : int {
338 BADGE_CLICK_NONE,
339 BADGE_CLICK_MOVE_UP,
340 BADGE_CLICK_MOVE_DOWN,
341 BADGE_CLICK_TOGGLE_ICON,
342 BADGE_CLICK_TOGGLE_FILTER,
343};
344
345DropDownList BuildBadgeClassConfigurationList(const GUIBadgeClasses &gui_classes, uint columns, std::span<const StringID> column_separators, Colours bg_colour)
346{
347 DropDownList list;
348
349 list.push_back(MakeDropDownListStringItem(STR_BADGE_CONFIG_RESET, INT_MAX));
350 if (gui_classes.GetClasses().empty()) return list;
351 list.push_back(MakeDropDownListDividerItem());
352 list.push_back(std::make_unique<DropDownUnselectable<DropDownListStringItem>>(GetString(STR_BADGE_CONFIG_ICONS), -1));
353
354 const BadgeClassID front = gui_classes.GetClasses().front().class_index;
355 const BadgeClassID back = gui_classes.GetClasses().back().class_index;
356
357 for (uint i = 0; i < columns; ++i) {
358 for (const auto &gc : gui_classes.GetClasses()) {
359 if (gc.column_group != i) continue;
360 if (gc.size.width == 0) continue;
361
362 bool first = (i == 0 && gc.class_index == front);
363 bool last = (i == columns - 1 && gc.class_index == back);
364 list.push_back(std::make_unique<DropDownListToggleMoverItem>(first ? 0 : BADGE_CLICK_MOVE_UP, last ? 0 : BADGE_CLICK_MOVE_DOWN, COLOUR_YELLOW, gc.visible, BADGE_CLICK_TOGGLE_ICON, COLOUR_YELLOW, bg_colour, GetString(GetClassBadge(gc.class_index)->name), gc.class_index.base()));
365 }
366
367 if (i >= column_separators.size()) continue;
368
369 if (column_separators[i] == STR_NULL) {
370 list.push_back(MakeDropDownListDividerItem());
371 } else {
372 list.push_back(MakeDropDownListStringItem(column_separators[i], INT_MIN + i, false, true));
373 }
374 }
375
376 list.push_back(MakeDropDownListDividerItem());
377 list.push_back(std::make_unique<DropDownUnselectable<DropDownListStringItem>>(GetString(STR_BADGE_CONFIG_FILTERS), -1));
378
379 for (const BadgeClassID &badge_class_index : gui_classes.Classes()) {
380 const Badge *badge = GetClassBadge(badge_class_index);
381 if (!badge->flags.Test(BadgeFlag::HasText)) continue;
382
383 const auto [config, _] = GetBadgeClassConfigItem(gui_classes.GetFeature(), badge->label);
384 list.push_back(std::make_unique<DropDownListToggleItem>(config.show_filter, BADGE_CLICK_TOGGLE_FILTER, COLOUR_YELLOW, bg_colour, GetString(badge->name), badge_class_index.base()));
385 }
386
387 return list;
388}
389
397static void BadgeClassToggleVisibility(GrfSpecFeature feature, Badge &class_badge, int click_result, BadgeFilterChoices &choices)
398{
399 auto config = GetBadgeClassConfiguration(feature);
400 auto it = std::ranges::find(config, class_badge.label, &BadgeClassConfigItem::label);
401 if (it == std::end(config)) return;
402
403 if (click_result == BADGE_CLICK_TOGGLE_ICON) it->show_icon = !it->show_icon;
404 if (click_result == BADGE_CLICK_TOGGLE_FILTER) {
405 it->show_filter = !it->show_filter;
406 if (!it->show_filter) ResetBadgeFilter(choices, class_badge.class_index);
407 }
408}
409
415static void BadgeClassMovePrevious(GrfSpecFeature feature, Badge &class_badge)
416{
417 GUIBadgeClasses gui_classes(feature);
418 if (gui_classes.GetClasses().empty()) return;
419
420 auto config = GetBadgeClassConfiguration(feature);
421 auto it = std::ranges::find(config, class_badge.label, &BadgeClassConfigItem::label);
422 if (it == std::end(config)) return;
423
424 auto pos_cur = std::ranges::find(gui_classes.GetClasses(), class_badge.class_index, &GUIBadgeClasses::Element::class_index);
425 if (pos_cur == std::begin(gui_classes.GetClasses())) {
426 if (it->column > 0) --it->column;
427 return;
428 }
429
430 auto pos_prev = std::ranges::find(config, std::prev(pos_cur)->label, &BadgeClassConfigItem::label);
431 if (it->column > pos_prev->column) {
432 --it->column;
433 } else {
434 /* Rotate elements right so that it is placed before pos_prev, maintaining order of non-visible elements. */
435 std::rotate(pos_prev, it, std::next(it));
436 }
437}
438
445static void BadgeClassMoveNext(GrfSpecFeature feature, Badge &class_badge, uint columns)
446{
447 GUIBadgeClasses gui_classes(feature);
448 if (gui_classes.GetClasses().empty()) return;
449
450 auto config = GetBadgeClassConfiguration(feature);
451 auto it = std::ranges::find(config, class_badge.label, &BadgeClassConfigItem::label);
452 if (it == std::end(config)) return;
453
454 auto pos_cur = std::ranges::find(gui_classes.GetClasses(), class_badge.class_index, &GUIBadgeClasses::Element::class_index);
455 if (std::next(pos_cur) == std::end(gui_classes.GetClasses())) {
456 if (it->column < columns - 1) ++it->column;
457 return;
458 }
459
460 auto pos_next = std::ranges::find(config, std::next(pos_cur)->label, &BadgeClassConfigItem::label);
461 if (it->column < pos_next->column) {
462 ++it->column;
463 } else {
464 /* Rotate elements left so that it is placed after pos_next, maintaining order of non-visible elements. */
465 std::rotate(it, std::next(it), std::next(pos_next));
466 }
467}
468
478bool HandleBadgeConfigurationDropDownClick(GrfSpecFeature feature, uint columns, int result, int click_result, BadgeFilterChoices &choices)
479{
480 if (result == INT_MAX) {
482 return true;
483 }
484
485 Badge *class_badge = GetClassBadge(static_cast<BadgeClassID>(result));
486 if (class_badge == nullptr) return false;
487
488 switch (click_result) {
489 case BADGE_CLICK_MOVE_DOWN: // Move down button.
490 BadgeClassMoveNext(feature, *class_badge, columns);
491 break;
492 case BADGE_CLICK_MOVE_UP: // Move up button.
493 BadgeClassMovePrevious(feature, *class_badge);
494 break;
495 case BADGE_CLICK_TOGGLE_ICON:
496 case BADGE_CLICK_TOGGLE_FILTER:
497 BadgeClassToggleVisibility(feature, *class_badge, click_result, choices);
498 break;
499 default:
500 break;
501 }
502
503 return true;
504}
505
506NWidgetBadgeFilter::NWidgetBadgeFilter(Colours colour, WidgetID index, GrfSpecFeature feature, BadgeClassID badge_class)
507 : NWidgetLeaf(WWT_DROPDOWN, colour, index, WidgetData{ .string = STR_JUST_STRING }, STR_NULL)
508 , feature(feature), badge_class(badge_class)
509{
510 this->SetFill(1, 0);
511 this->SetResize(1, 0);
512}
513
514std::string NWidgetBadgeFilter::GetStringParameter(const BadgeFilterChoices &choices) const
515{
516 auto it = choices.find(this->badge_class);
517 if (it == std::end(choices)) {
518 return ::GetString(STR_BADGE_FILTER_ANY_LABEL, GetClassBadge(this->badge_class)->name);
519 }
520
521 return ::GetString(GetBadge(it->second)->name);
522}
523
530{
531 DropDownList list;
532
533 /* Add item for disabling filtering. */
534 list.push_back(MakeDropDownListStringItem(::GetString(STR_BADGE_FILTER_ANY_LABEL, GetClassBadge(this->badge_class)->name), -1));
535 list.push_back(MakeDropDownListDividerItem());
536
537 /* Add badges */
538 Dimension d = GetBadgeMaximalDimension(this->badge_class, this->feature);
539 d.width = ScaleGUITrad(d.width);
540 d.height = ScaleGUITrad(d.height);
541
542 auto start = list.size();
543
544 const auto *bc = GetClassBadge(this->badge_class);
545
546 for (const Badge &badge : GetBadges()) {
547 if (badge.class_index != this->badge_class) continue;
548 if (badge.index == bc->index) continue;
549 if (badge.name == STR_NULL) continue;
550 if (!badge.features.Test(this->feature)) continue;
551
552 PalSpriteID ps = GetBadgeSprite(badge, this->feature, std::nullopt, palette);
553 if (ps.sprite == 0) {
554 list.push_back(MakeDropDownListStringItem(badge.name, badge.index.base()));
555 } else {
556 list.push_back(MakeDropDownListIconItem(d, ps.sprite, ps.pal, badge.name, badge.index.base()));
557 }
558 }
559
560 std::sort(std::begin(list) + start, std::end(list), DropDownListStringItem::NatSortFunc);
561
562 return list;
563}
564
574std::pair<WidgetID, WidgetID> AddBadgeDropdownFilters(Window *window, WidgetID container_id, WidgetID widget, Colours colour, GrfSpecFeature feature)
575{
576 auto container = window->GetWidget<NWidgetContainer>(container_id);
577 container->Clear(window);
578 WidgetID first = ++widget;
579
580 /* Get list of classes used by feature. */
581 UsedBadgeClasses used(feature);
582
583 for (BadgeClassID class_index : used.Classes()) {
584 const auto [config, _] = GetBadgeClassConfigItem(feature, GetClassBadge(class_index)->label);
585 if (!config.show_filter) continue;
586
587 container->Add(std::make_unique<NWidgetBadgeFilter>(colour, widget, feature, class_index));
588 ++widget;
589 }
590
591 return {first, widget};
592}
593
599void ResetBadgeFilter(BadgeFilterChoices &choices, BadgeClassID badge_class_index)
600{
601 choices.erase(badge_class_index);
602}
603
610void SetBadgeFilter(BadgeFilterChoices &choices, BadgeID badge_index)
611{
612 const Badge *badge = GetBadge(badge_index);
613 assert(badge != nullptr);
614
615 choices[badge->class_index] = badge_index;
616}
std::string label
Class label.
BadgeClassID class_index
Index of class this badge belongs to.
std::string label
Label of badge.
BadgeID index
Index assigned to badge.
BadgeFlags flags
Display flags.
GrfSpecFeatures features
Bitmask of which features use this badge.
StringID name
Short name.
constexpr bool Test(Tvalue_type value) const
Test if the value-th bit is set.
Drop down element that draws a list of badges.
void FilterText(StringFilter &string_filter) const override
Add text from this dropdown item to a string filter.
Drop down component that shows extra buttons to indicate that the item can be moved up or down.
int click_down
Click result for down button. Button is inactive if 0.
Colours button_colour
Colour of buttons.
int click_up
Click result for up button. Button is inactive if 0.
static bool NatSortFunc(std::unique_ptr< const DropDownListItem > const &first, std::unique_ptr< const DropDownListItem > const &second)
Drop down boolean toggle component.
Drop down component that makes the item unselectable.
Flat set implementation that uses a sorted vector for storage.
std::pair< const_iterator, bool > insert(const Tkey &key)
Insert a key into the set, if it does not already exist.
uint GetTotalColumnsWidth() const
Get total width of all columns.
BadgeClassID badge_class
Badge class of this dropdown.
DropDownList GetDropDownList(PaletteID palette=PAL_NONE) const
Get the drop down list of badges for this filter.
Baseclass for container widgets.
void Clear(Window *parent_window)
Clears the container, deleting all widgets that were contained.
StringID GetString() const
Get the string that has been set for this nested widget.
Definition widget.cpp:1254
Leaf widget.
Utility class to create a list of badge classes used by a feature.
static WidgetDimensions scaled
Widget dimensions scaled for current zoom level.
Definition window_gui.h:30
int hsep_normal
Normal horizontal spacing.
Definition window_gui.h:61
std::unique_ptr< DropDownListItem > MakeDropDownListDividerItem()
Creates new DropDownListDividerItem.
Definition dropdown.cpp:36
std::unique_ptr< DropDownListItem > MakeDropDownListIconItem(SpriteID sprite, PaletteID palette, StringID str, int value, bool masked, bool shaded)
Creates new DropDownListIconItem.
Definition dropdown.cpp:70
std::unique_ptr< DropDownListItem > MakeDropDownListStringItem(StringID str, int value, bool masked, bool shaded)
Creates new DropDownListStringItem.
Definition dropdown.cpp:49
Common drop down list components.
Functions related to the drop down widget.
Types related to the drop down widget.
std::vector< std::unique_ptr< const DropDownListItem > > DropDownList
A drop down list is a collection of drop down list items.
Flat set container implementation.
Dimension GetSpriteSize(SpriteID sprid, Point *offset, ZoomLevel zoom)
Get the size of a sprite.
Definition gfx.cpp:972
int DrawStringMultiLine(int left, int right, int top, int bottom, std::string_view str, TextColour colour, StringAlignment align, bool underline, FontSize fontsize)
Draw string, possibly over multiple lines.
Definition gfx.cpp:788
uint32_t SpriteID
The number of a sprite, without mapping bits and colourtables.
Definition gfx_type.h:17
@ FS_SMALL
Index of the small font in the font tables.
Definition gfx_type.h:250
@ SA_CENTER
Center both horizontally and vertically.
Definition gfx_type.h:398
uint32_t PaletteID
The number of the palette.
Definition gfx_type.h:18
constexpr NWidgetPart SetFill(uint16_t fill_x, uint16_t fill_y)
Widget part function for setting filling.
constexpr NWidgetPart SetResize(int16_t dx, int16_t dy)
Widget part function for setting the resize step.
#define Rect
Macro that prevents name conflicts between included headers.
#define Point
Macro that prevents name conflicts between included headers.
Base for the NewGRF implementation.
GrfSpecFeature
Definition newgrf.h:71
Badge * GetBadge(BadgeID index)
Get a badge if it exists.
std::span< const Badge > GetBadges()
Get a read-only view of badges.
PalSpriteID GetBadgeSprite(const Badge &badge, GrfSpecFeature feature, std::optional< TimerGameCalendar::Date > introduction_date, PaletteID remap)
Get sprite for the given badge.
Badge * GetClassBadge(BadgeClassID class_index)
Get the badge for a badge class index.
Functions related to NewGRF badges.
void ResetBadgeClassConfiguration(GrfSpecFeature feature)
Reset badge class configuration for a feature.
std::pair< const BadgeClassConfigItem &, int > GetBadgeClassConfigItem(GrfSpecFeature feature, std::string_view label)
Get configuration for a badge class.
std::span< BadgeClassConfigItem > GetBadgeClassConfiguration(GrfSpecFeature feature)
Get the badge user configuration for a feature.
Functions related to NewGRF badge configuration.
int DrawBadgeNameList(Rect r, std::span< const BadgeID > badges, GrfSpecFeature)
Draw names for a list of badge labels.
static void BadgeClassMoveNext(GrfSpecFeature feature, Badge &class_badge, uint columns)
Move the badge class to the next position.
void DrawBadgeColumn(Rect r, int column_group, const GUIBadgeClasses &gui_classes, std::span< const BadgeID > badges, GrfSpecFeature feature, std::optional< TimerGameCalendar::Date > introduction_date, PaletteID remap)
Draw a badge column group.
static void BadgeClassToggleVisibility(GrfSpecFeature feature, Badge &class_badge, int click_result, BadgeFilterChoices &choices)
Toggle badge class visibility.
static constexpr uint MAX_BADGE_HEIGHT
Maximal height of a badge sprite.
static constexpr uint MAX_BADGE_WIDTH
Maximal width.
std::pair< WidgetID, WidgetID > AddBadgeDropdownFilters(Window *window, WidgetID container_id, WidgetID widget, Colours colour, GrfSpecFeature feature)
Add badge drop down filter widgets.
bool HandleBadgeConfigurationDropDownClick(GrfSpecFeature feature, uint columns, int result, int click_result, BadgeFilterChoices &choices)
Handle the badge configuration drop down selection.
static Dimension GetBadgeMaximalDimension(BadgeClassID class_index, GrfSpecFeature feature)
Get the largest badge size (within limits) for a badge class.
void SetBadgeFilter(BadgeFilterChoices &choices, BadgeID badge_index)
Set badge filter choice for a class.
static void BadgeClassMovePrevious(GrfSpecFeature feature, Badge &class_badge)
Move the badge class to the previous position.
void ResetBadgeFilter(BadgeFilterChoices &choices, BadgeClassID badge_class_index)
Reset badge filter choice for a class.
GUI functions related to NewGRF badges.
Types related to NewGRF badges.
@ NameListStop
Stop adding names to the name list after this badge.
@ NameListFirstOnly
Don't add this name to the name list if not first.
@ HasText
Internal flag set if the badge has text.
@ NameListSkip
Don't show name in name list at all.
A number of safeguards to prevent using unsafe methods.
void DrawUpDownButtons(int x, int y, Colours button_colour, uint8_t state, bool clickable_up, bool clickable_down)
Draw [^][v] buttons.
Functions for setting GUIs.
#define SETTING_BUTTON_WIDTH
Width of setting buttons.
#define SETTING_BUTTON_HEIGHT
Height of setting buttons.
Definition of base types and functions in a cross-platform compatible way.
std::string_view GetListSeparator()
Get the list separator string for the current language.
Definition strings.cpp:299
void AppendStringInPlace(std::string &result, StringID string)
Resolve the given StringID and append in place into an existing std::string with formatting but no pa...
Definition strings.cpp:434
std::string GetString(StringID string)
Resolve the given StringID into a std::string with formatting but no parameters.
Definition strings.cpp:424
TextDirection _current_text_dir
Text direction of the currently selected language.
Definition strings.cpp:56
Functions related to OTTD's strings.
@ TD_RTL
Text is written right-to-left by default.
Dimensions (a width and height) of a rectangle in 2D.
uint sort_order
Order of element.
std::string_view label
Class label (string owned by the class badge).
BadgeClassID class_index
Badge class index.
uint8_t column_group
Column group in UI. 0 = left, 1 = centre, 2 = right.
Combination of a palette sprite and a 'real' sprite.
Definition gfx_type.h:22
SpriteID sprite
The 'real' sprite.
Definition gfx_type.h:23
PaletteID pal
The palette (use PAL_NONE) if not needed).
Definition gfx_type.h:24
Specification of a rectangle with absolute coordinates of all edges.
Rect WithWidth(int width, bool end) const
Copy Rect and set its width.
Rect Indent(int indent, bool end) const
Copy Rect and indent it from its position.
Rect CentreToHeight(int height) const
Centre a vertical dimension within this Rect.
bool Contains(const Point &pt) const
Test if a point falls inside this Rect.
String filter and state.
Container with the data associated to a single widget.
Data structure for an opened window.
Definition window_gui.h:274
const NWID * GetWidget(WidgetID widnum) const
Get the nested widget with number widnum from the nested widget tree.
Definition window_gui.h:990
int16_t Height
Fixed point type for heights.
Definition tgp.cpp:152
Definition of the game-calendar-timer.
static RectPadding ScaleGUITrad(const RectPadding &r)
Scale a RectPadding to GUI zoom level.
Definition widget.cpp:49
@ WWT_DROPDOWN
Drop down list.
Definition widget_type.h:61
Functions, definitions and such used only by the GUI.
Types related to windows.
int WidgetID
Widget ID.
Definition window_type.h:20
Functions related to zooming.
@ Normal
The normal zoom level.
Definition zoom_type.h:26