OpenTTD Source 20251116-master-g21329071df
newgrf_badge_gui.cpp
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 */
7
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 "zoom_func.h"
25
26#include "table/strings.h"
27
29
30#include "safeguards.h"
31
32static constexpr uint MAX_BADGE_HEIGHT = 12;
33static constexpr uint MAX_BADGE_WIDTH = MAX_BADGE_HEIGHT * 2;
34
41static Dimension GetBadgeMaximalDimension(BadgeClassID class_index, GrfSpecFeature feature)
42{
43 Dimension d = {0, MAX_BADGE_HEIGHT};
44
45 for (const auto &badge : GetBadges()) {
46 if (badge.class_index != class_index) continue;
47
48 PalSpriteID ps = GetBadgeSprite(badge, feature, std::nullopt, PAL_NONE);
49 if (ps.sprite == 0) continue;
50
51 d.width = std::max(d.width, GetSpriteSize(ps.sprite, nullptr, ZoomLevel::Normal).width);
52 if (d.width > MAX_BADGE_WIDTH) break;
53 }
54
55 d.width = std::min(d.width, MAX_BADGE_WIDTH);
56 return d;
57}
58
59static bool operator<(const GUIBadgeClasses::Element &a, const GUIBadgeClasses::Element &b)
60{
61 if (a.column_group != b.column_group) return a.column_group < b.column_group;
62 if (a.sort_order != b.sort_order) return a.sort_order < b.sort_order;
63 return a.label < b.label;
64}
65
70GUIBadgeClasses::GUIBadgeClasses(GrfSpecFeature feature) : UsedBadgeClasses(feature)
71{
72 /* Get list of classes used by feature. */
73 uint max_column = 0;
74 for (BadgeClassID class_index : this->Classes()) {
75 const Badge *class_badge = GetClassBadge(class_index);
76 if (class_badge->name == STR_NULL) continue;
77
78 Dimension size = GetBadgeMaximalDimension(class_index, feature);
79 if (size.width == 0) continue;
80
81 const auto [config, sort_order] = GetBadgeClassConfigItem(feature, class_badge->label);
82
83 this->gui_classes.emplace_back(class_index, config.column, config.show_icon, sort_order, size, class_badge->label);
84 if (size.width != 0 && config.show_icon) max_column = std::max(max_column, config.column);
85 }
86
87 std::sort(std::begin(this->gui_classes), std::end(this->gui_classes));
88
89 /* Determine total width of visible badge columns. */
90 this->column_widths.resize(max_column + 1);
91 for (const auto &el : this->gui_classes) {
92 if (!el.visible || el.size.width == 0) continue;
93 this->column_widths[el.column_group] += ScaleGUITrad(el.size.width) + WidgetDimensions::scaled.hsep_normal;
94 }
95
96 /* Replace trailing `hsep_normal` spacer with wider `hsep_wide` spacer. */
97 for (uint &badge_width : this->column_widths) {
98 if (badge_width == 0) continue;
100 }
101}
102
108{
109 return std::accumulate(std::begin(this->column_widths), std::end(this->column_widths), 0U);
110}
111
119int DrawBadgeNameList(Rect r, std::span<const BadgeID> badges, GrfSpecFeature)
120{
121 if (badges.empty()) return r.top;
122
123 FlatSet<BadgeClassID> class_indexes;
124 for (const BadgeID &index : badges) class_indexes.insert(GetBadge(index)->class_index);
125
126 std::string_view list_separator = GetListSeparator();
127 for (const BadgeClassID &class_index : class_indexes) {
128 const Badge *class_badge = GetClassBadge(class_index);
129 if (class_badge == nullptr || class_badge->name == STR_NULL) continue;
130
131 std::string s;
132 for (const BadgeID &index : badges) {
133 const Badge *badge = GetBadge(index);
134 if (badge == nullptr || badge->name == STR_NULL) continue;
135 if (badge->class_index != class_index) continue;
136
137 if (!s.empty()) {
138 if (badge->flags.Test(BadgeFlag::NameListFirstOnly)) continue;
139 s += list_separator;
140 }
141 AppendStringInPlace(s, badge->name);
142 if (badge->flags.Test(BadgeFlag::NameListStop)) break;
143 }
144
145 if (s.empty()) continue;
146
147 r.top = DrawStringMultiLine(r, GetString(STR_BADGE_NAME_LIST, class_badge->name, std::move(s)), TC_BLACK);
148 }
149
150 return r.top;
151}
152
163void 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)
164{
165 bool rtl = _current_text_dir == TD_RTL;
166 for (const auto &gc : gui_classes.GetClasses()) {
167 if (gc.column_group != column_group) continue;
168 if (!gc.visible) continue;
169
170 int width = ScaleGUITrad(gc.size.width);
171 for (const BadgeID &index : badges) {
172 const Badge &badge = *GetBadge(index);
173 if (badge.class_index != gc.class_index) continue;
174
175 PalSpriteID ps = GetBadgeSprite(badge, feature, introduction_date, remap);
176 if (ps.sprite == 0) continue;
177
178 DrawSpriteIgnorePadding(ps.sprite, ps.pal, r.WithWidth(width, rtl), SA_CENTER);
179 break;
180 }
181
182 r = r.Indent(width + WidgetDimensions::scaled.hsep_normal, rtl);
183 }
184}
185
187template <class TBase, bool TEnd = true, FontSize TFs = FS_NORMAL>
188class DropDownBadges : public TBase {
189public:
190 template <typename... Args>
191 explicit DropDownBadges(const std::shared_ptr<GUIBadgeClasses> &gui_classes, std::span<const BadgeID> badges, GrfSpecFeature feature, std::optional<TimerGameCalendar::Date> introduction_date, Args &&...args) :
192 TBase(std::forward<Args>(args)...), gui_classes(gui_classes), badges(badges), feature(feature), introduction_date(introduction_date)
193 {
194 for (const auto &gc : gui_classes->GetClasses()) {
195 if (gc.column_group != 0) continue;
196 dim.width += ScaleGUITrad(gc.size.width) + WidgetDimensions::scaled.hsep_normal;
197 dim.height = std::max<uint>(dim.height, ScaleGUITrad(gc.size.height));
198 }
199
200 /* Remove trailing `hsep_normal` spacer. */
201 if (dim.width > 0) dim.width -= WidgetDimensions::scaled.hsep_normal;
202 }
203
204 uint Height() const override
205 {
206 return std::max<uint>(this->dim.height, this->TBase::Height());
207 }
208
209 uint Width() const override
210 {
211 if (this->dim.width == 0) return this->TBase::Width();
212 return this->dim.width + WidgetDimensions::scaled.hsep_normal + this->TBase::Width();
213 }
214
215 int OnClick(const Rect &r, const Point &pt) const override
216 {
217 if (this->dim.width == 0) {
218 return this->TBase::OnClick(r, pt);
219 } else {
220 bool rtl = TEnd ^ (_current_text_dir == TD_RTL);
221 return this->TBase::OnClick(r.Indent(this->dim.width + WidgetDimensions::scaled.hsep_normal, rtl), pt);
222 }
223 }
224
225 void Draw(const Rect &full, const Rect &r, bool sel, int click_result, Colours bg_colour) const override
226 {
227 if (this->dim.width == 0) {
228 this->TBase::Draw(full, r, sel, click_result, bg_colour);
229 } else {
230 bool rtl = TEnd ^ (_current_text_dir == TD_RTL);
231 DrawBadgeColumn(r.WithWidth(this->dim.width, rtl), 0, *this->gui_classes, this->badges, this->feature, this->introduction_date, PAL_NONE);
232 this->TBase::Draw(full, r.Indent(this->dim.width + WidgetDimensions::scaled.hsep_normal, rtl), sel, click_result, bg_colour);
233 }
234 }
235
236private:
237 std::shared_ptr<GUIBadgeClasses> gui_classes;
238
239 const std::span<const BadgeID> badges;
240 const GrfSpecFeature feature;
241 const std::optional<TimerGameCalendar::Date> introduction_date;
242
243 Dimension dim{};
244};
245
248
249std::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)
250{
251 return std::make_unique<DropDownListBadgeItem>(gui_classes, badges, feature, introduction_date, "", std::move(str), value, masked, shaded);
252}
253
254std::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)
255{
256 return std::make_unique<DropDownListBadgeItem>(gui_classes, badges, feature, introduction_date, GetString(STR_JUST_CURRENCY_SHORT, cost), std::move(str), value, masked, shaded);
257}
258
259std::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)
260{
261 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);
262}
263
267template <class TBase, bool TEnd = true, FontSize TFs = FS_NORMAL>
268class DropDownMover : public TBase {
269public:
270 template <typename... Args>
271 explicit DropDownMover(int click_up, int click_down, Colours button_colour, Args &&...args)
272 : TBase(std::forward<Args>(args)...), click_up(click_up), click_down(click_down), button_colour(button_colour)
273 {
274 }
275
276 uint Height() const override
277 {
278 return std::max<uint>(SETTING_BUTTON_HEIGHT, this->TBase::Height());
279 }
280
281 uint Width() const override
282 {
283 return SETTING_BUTTON_WIDTH + WidgetDimensions::scaled.hsep_wide + this->TBase::Width();
284 }
285
286 int OnClick(const Rect &r, const Point &pt) const override
287 {
288 bool rtl = (_current_text_dir == TD_RTL);
289 int w = SETTING_BUTTON_WIDTH;
290
291 Rect br = r.WithWidth(w, TEnd ^ rtl).CentreToHeight(SETTING_BUTTON_HEIGHT);
292 if (br.WithWidth(w / 2, rtl).Contains(pt)) return this->click_up;
293 if (br.WithWidth(w / 2, !rtl).Contains(pt)) return this->click_down;
294
295 return this->TBase::OnClick(r.Indent(w + WidgetDimensions::scaled.hsep_wide, TEnd ^ rtl), pt);
296 }
297
298 void Draw(const Rect &full, const Rect &r, bool sel, int click_result, Colours bg_colour) const override
299 {
300 bool rtl = (_current_text_dir == TD_RTL);
301 int w = SETTING_BUTTON_WIDTH;
302
303 int state = 0;
304 if (sel && click_result != 0) {
305 if (click_result == this->click_up) state = 1;
306 if (click_result == this->click_down) state = 2;
307 }
308
309 Rect br = r.WithWidth(w, TEnd ^ rtl).CentreToHeight(SETTING_BUTTON_HEIGHT);
310 DrawUpDownButtons(br.left, br.top, this->button_colour, state, this->click_up != 0, this->click_down != 0);
311
312 this->TBase::Draw(full, r.Indent(w + WidgetDimensions::scaled.hsep_wide, TEnd ^ rtl), sel, click_result, bg_colour);
313 }
314
315private:
319};
320
323
324enum BadgeClick : int {
325 BADGE_CLICK_NONE,
326 BADGE_CLICK_MOVE_UP,
327 BADGE_CLICK_MOVE_DOWN,
328 BADGE_CLICK_TOGGLE_ICON,
329 BADGE_CLICK_TOGGLE_FILTER,
330};
331
332DropDownList BuildBadgeClassConfigurationList(const GUIBadgeClasses &gui_classes, uint columns, std::span<const StringID> column_separators)
333{
334 DropDownList list;
335
336 list.push_back(MakeDropDownListStringItem(STR_BADGE_CONFIG_RESET, INT_MAX));
337 if (gui_classes.GetClasses().empty()) return list;
338 list.push_back(MakeDropDownListDividerItem());
339 list.push_back(std::make_unique<DropDownUnselectable<DropDownListStringItem>>(GetString(STR_BADGE_CONFIG_ICONS), -1));
340
341 const BadgeClassID front = gui_classes.GetClasses().front().class_index;
342 const BadgeClassID back = gui_classes.GetClasses().back().class_index;
343
344 for (uint i = 0; i < columns; ++i) {
345 for (const auto &gc : gui_classes.GetClasses()) {
346 if (gc.column_group != i) continue;
347 if (gc.size.width == 0) continue;
348
349 bool first = (i == 0 && gc.class_index == front);
350 bool last = (i == columns - 1 && gc.class_index == back);
351 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, COLOUR_GREY, GetString(GetClassBadge(gc.class_index)->name), gc.class_index.base()));
352 }
353
354 if (i >= column_separators.size()) continue;
355
356 if (column_separators[i] == STR_NULL) {
357 list.push_back(MakeDropDownListDividerItem());
358 } else {
359 list.push_back(MakeDropDownListStringItem(column_separators[i], INT_MIN + i, false, true));
360 }
361 }
362
363 list.push_back(MakeDropDownListDividerItem());
364 list.push_back(std::make_unique<DropDownUnselectable<DropDownListStringItem>>(GetString(STR_BADGE_CONFIG_FILTERS), -1));
365
366 for (const BadgeClassID &badge_class_index : gui_classes.Classes()) {
367 const Badge *badge = GetClassBadge(badge_class_index);
368 if (!badge->flags.Test(BadgeFlag::HasText)) continue;
369
370 const auto [config, _] = GetBadgeClassConfigItem(gui_classes.GetFeature(), badge->label);
371 list.push_back(std::make_unique<DropDownListToggleItem>(config.show_filter, BADGE_CLICK_TOGGLE_FILTER, COLOUR_YELLOW, COLOUR_GREY, GetString(badge->name), (1U << 16) | badge_class_index.base()));
372 }
373
374 return list;
375}
376
383static void BadgeClassToggleVisibility(GrfSpecFeature feature, Badge &class_badge, int click_result, BadgeFilterChoices &choices)
384{
385 auto config = GetBadgeClassConfiguration(feature);
386 auto it = std::ranges::find(config, class_badge.label, &BadgeClassConfigItem::label);
387 if (it == std::end(config)) return;
388
389 if (click_result == BADGE_CLICK_TOGGLE_ICON) it->show_icon = !it->show_icon;
390 if (click_result == BADGE_CLICK_TOGGLE_FILTER) {
391 it->show_filter = !it->show_filter;
392 if (!it->show_filter) ResetBadgeFilter(choices, class_badge.class_index);
393 }
394}
395
401static void BadgeClassMovePrevious(GrfSpecFeature feature, Badge &class_badge)
402{
403 GUIBadgeClasses gui_classes(feature);
404 if (gui_classes.GetClasses().empty()) return;
405
406 auto config = GetBadgeClassConfiguration(feature);
407 auto it = std::ranges::find(config, class_badge.label, &BadgeClassConfigItem::label);
408 if (it == std::end(config)) return;
409
410 auto pos_cur = std::ranges::find(gui_classes.GetClasses(), class_badge.class_index, &GUIBadgeClasses::Element::class_index);
411 if (pos_cur == std::begin(gui_classes.GetClasses())) {
412 if (it->column > 0) --it->column;
413 return;
414 }
415
416 auto pos_prev = std::ranges::find(config, std::prev(pos_cur)->label, &BadgeClassConfigItem::label);
417 if (it->column > pos_prev->column) {
418 --it->column;
419 } else {
420 /* Rotate elements right so that it is placed before pos_prev, maintaining order of non-visible elements. */
421 std::rotate(pos_prev, it, std::next(it));
422 }
423}
424
431static void BadgeClassMoveNext(GrfSpecFeature feature, Badge &class_badge, uint columns)
432{
433 GUIBadgeClasses gui_classes(feature);
434 if (gui_classes.GetClasses().empty()) return;
435
436 auto config = GetBadgeClassConfiguration(feature);
437 auto it = std::ranges::find(config, class_badge.label, &BadgeClassConfigItem::label);
438 if (it == std::end(config)) return;
439
440 auto pos_cur = std::ranges::find(gui_classes.GetClasses(), class_badge.class_index, &GUIBadgeClasses::Element::class_index);
441 if (std::next(pos_cur) == std::end(gui_classes.GetClasses())) {
442 if (it->column < columns - 1) ++it->column;
443 return;
444 }
445
446 auto pos_next = std::ranges::find(config, std::next(pos_cur)->label, &BadgeClassConfigItem::label);
447 if (it->column < pos_next->column) {
448 ++it->column;
449 } else {
450 /* Rotate elements left so that it is placed after pos_next, maintaining order of non-visible elements. */
451 std::rotate(it, std::next(it), std::next(pos_next));
452 }
453}
454
463bool HandleBadgeConfigurationDropDownClick(GrfSpecFeature feature, uint columns, int result, int click_result, BadgeFilterChoices &choices)
464{
465 if (result == INT_MAX) {
467 return true;
468 }
469
470 Badge *class_badge = GetClassBadge(static_cast<BadgeClassID>(result));
471 if (class_badge == nullptr) return false;
472
473 switch (click_result) {
474 case BADGE_CLICK_MOVE_DOWN: // Move down button.
475 BadgeClassMoveNext(feature, *class_badge, columns);
476 break;
477 case BADGE_CLICK_MOVE_UP: // Move up button.
478 BadgeClassMovePrevious(feature, *class_badge);
479 break;
480 case BADGE_CLICK_TOGGLE_ICON:
481 case BADGE_CLICK_TOGGLE_FILTER:
482 BadgeClassToggleVisibility(feature, *class_badge, click_result, choices);
483 break;
484 default:
485 break;
486 }
487
488 return true;
489}
490
491NWidgetBadgeFilter::NWidgetBadgeFilter(Colours colour, WidgetID index, GrfSpecFeature feature, BadgeClassID badge_class)
492 : NWidgetLeaf(WWT_DROPDOWN, colour, index, WidgetData{ .string = STR_JUST_STRING }, STR_NULL)
493 , feature(feature), badge_class(badge_class)
494{
495 this->SetFill(1, 0);
496 this->SetResize(1, 0);
497}
498
499std::string NWidgetBadgeFilter::GetStringParameter(const BadgeFilterChoices &choices) const
500{
501 auto it = choices.find(this->badge_class);
502 if (it == std::end(choices)) {
503 return ::GetString(STR_BADGE_FILTER_ANY_LABEL, GetClassBadge(this->badge_class)->name);
504 }
505
506 return ::GetString(STR_BADGE_FILTER_IS_LABEL, GetClassBadge(it->first)->name, GetBadge(it->second)->name);
507}
508
515{
516 DropDownList list;
517
518 /* Add item for disabling filtering. */
519 list.push_back(MakeDropDownListStringItem(::GetString(STR_BADGE_FILTER_ANY_LABEL, GetClassBadge(this->badge_class)->name), -1));
520 list.push_back(MakeDropDownListDividerItem());
521
522 /* Add badges */
523 Dimension d = GetBadgeMaximalDimension(this->badge_class, this->feature);
524 d.width = ScaleGUITrad(d.width);
525 d.height = ScaleGUITrad(d.height);
526
527 auto start = list.size();
528
529 const auto *bc = GetClassBadge(this->badge_class);
530
531 for (const Badge &badge : GetBadges()) {
532 if (badge.class_index != this->badge_class) continue;
533 if (badge.index == bc->index) continue;
534 if (badge.name == STR_NULL) continue;
535 if (!badge.features.Test(this->feature)) continue;
536
537 PalSpriteID ps = GetBadgeSprite(badge, this->feature, std::nullopt, palette);
538 if (ps.sprite == 0) {
539 list.push_back(MakeDropDownListStringItem(badge.name, badge.index.base()));
540 } else {
541 list.push_back(MakeDropDownListIconItem(d, ps.sprite, ps.pal, badge.name, badge.index.base()));
542 }
543 }
544
545 std::sort(std::begin(list) + start, std::end(list), DropDownListStringItem::NatSortFunc);
546
547 return list;
548}
549
558std::pair<WidgetID, WidgetID> AddBadgeDropdownFilters(NWidgetContainer &container, WidgetID widget, Colours colour, GrfSpecFeature feature)
559{
560 container.Clear();
561 WidgetID first = ++widget;
562
563 /* Get list of classes used by feature. */
564 UsedBadgeClasses used(feature);
565
566 for (BadgeClassID class_index : used.Classes()) {
567 const auto [config, _] = GetBadgeClassConfigItem(feature, GetClassBadge(class_index)->label);
568 if (!config.show_filter) continue;
569
570 container.Add(std::make_unique<NWidgetBadgeFilter>(colour, widget, feature, class_index));
571 ++widget;
572 }
573
574 return {first, widget};
575}
576
582void ResetBadgeFilter(BadgeFilterChoices &choices, BadgeClassID badge_class_index)
583{
584 choices.erase(badge_class_index);
585}
586
593void SetBadgeFilter(BadgeFilterChoices &choices, BadgeID badge_index)
594{
595 const Badge *badge = GetBadge(badge_index);
596 assert(badge != nullptr);
597
598 choices[badge->class_index] = badge_index;
599}
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.
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)
Natural sorting comparator function for DropDownList::sort().
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 Add(std::unique_ptr< NWidgetBase > &&wid)
Append widget wid to container.
Definition widget.cpp:1292
StringID GetString() const
Get the string that has been set for this nested widget.
Definition widget.cpp:1251
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_wide
Wide horizontal spacing.
Definition window_gui.h:62
int hsep_normal
Normal horizontal spacing.
Definition window_gui.h:61
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:966
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:783
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.
Base for the NewGRF implementation.
GrfSpecFeature
Definition newgrf.h:69
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.
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.
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.
Container with the data associated to a single widget.
int16_t Height
Fixed point type for heights.
Definition tgp.cpp:153
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:62
Functions, definitions and such used only by the GUI.
int WidgetID
Widget ID.
Definition window_type.h:20
Functions related to zooming.
@ Normal
The normal zoom level.