18#include "newgrf_badge_gui.h"
26#include "table/strings.h"
32static constexpr uint MAX_BADGE_HEIGHT = 12;
33static constexpr uint MAX_BADGE_WIDTH = MAX_BADGE_HEIGHT * 2;
46 if (badge.class_index != class_index)
continue;
49 if (ps.
sprite == 0)
continue;
52 if (d.width > MAX_BADGE_WIDTH)
break;
55 d.width = std::min(d.width, MAX_BADGE_WIDTH);
76 if (class_badge->
name == STR_NULL)
continue;
78 Dimension size = GetBadgeMaximalDimension(class_index, feature);
79 if (size.width == 0)
continue;
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<uint>(max_column, config.column);
87 std::sort(std::begin(this->gui_classes), std::end(this->gui_classes));
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;
97 for (uint &badge_width : this->column_widths) {
98 if (badge_width == 0)
continue;
109 return std::accumulate(std::begin(this->column_widths), std::end(this->column_widths), 0U);
121 if (badges.empty())
return r.top;
124 for (
const BadgeID &index : badges) class_indexes.insert(
GetBadge(index)->class_index);
129 if (class_badge ==
nullptr || class_badge->
name == STR_NULL)
continue;
132 for (
const BadgeID &index : badges) {
134 if (badge ==
nullptr || badge->
name == STR_NULL)
continue;
145 if (s.empty())
continue;
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)
166 for (
const auto &gc : gui_classes.GetClasses()) {
167 if (gc.column_group != column_group)
continue;
168 if (!gc.visible)
continue;
171 for (
const BadgeID &index : badges) {
176 if (ps.
sprite == 0)
continue;
187template <
class TBase,
bool TEnd = true, FontSize TFs = FS_NORMAL>
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)
194 for (
const auto &gc : gui_classes->GetClasses()) {
195 if (gc.column_group != 0)
continue;
197 dim.height = std::max(dim.height, gc.size.height);
201 uint
Height()
const override
203 return std::max<uint>(this->dim.height, this->TBase::Height());
206 uint Width()
const override
211 int OnClick(
const Rect &r,
const Point &pt)
const override
217 void Draw(
const Rect &full,
const Rect &r,
bool sel,
int click_result, Colours bg_colour)
const override
221 DrawBadgeColumn(r.
WithWidth(this->dim.width, rtl), 0, *this->gui_classes, this->badges, this->feature, this->introduction_date, PAL_NONE);
227 std::shared_ptr<GUIBadgeClasses> gui_classes;
229 const std::span<const BadgeID> badges;
231 const std::optional<TimerGameCalendar::Date> introduction_date;
239std::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)
241 return std::make_unique<DropDownListBadgeItem>(gui_classes, badges, feature, introduction_date, std::move(str), value, masked, shaded);
244std::unique_ptr<DropDownListItem> MakeDropDownListBadgeIconItem(
const std::shared_ptr<GUIBadgeClasses> &gui_classes, std::span<const BadgeID> badges,
GrfSpecFeature feature, std::optional<TimerGameCalendar::Date> introduction_date,
const Dimension &dim,
SpriteID sprite,
PaletteID palette, std::string &&str,
int value,
bool masked,
bool shaded)
246 return std::make_unique<DropDownListBadgeIconItem>(gui_classes, badges, feature, introduction_date, dim, sprite, palette, std::move(str), value, masked, shaded);
252template <
class TBase,
bool TEnd = true, FontSize TFs = FS_NORMAL>
255 template <
typename... Args>
261 uint
Height()
const override
266 uint Width()
const override
271 int OnClick(
const Rect &r,
const Point &pt)
const override
283 void Draw(
const Rect &full,
const Rect &r,
bool sel,
int click_result, Colours bg_colour)
const override
289 if (sel && click_result != 0) {
290 if (click_result == this->click_up) state = 1;
291 if (click_result == this->click_down) state = 2;
295 DrawUpDownButtons(br.left, br.top, this->button_colour, state, this->click_up != 0, this->click_down != 0);
309enum BadgeClick :
int {
312 BADGE_CLICK_MOVE_DOWN,
313 BADGE_CLICK_TOGGLE_ICON,
314 BADGE_CLICK_TOGGLE_FILTER,
317DropDownList BuildBadgeClassConfigurationList(
const GUIBadgeClasses &gui_classes, uint columns, std::span<const StringID> column_separators)
321 list.push_back(MakeDropDownListStringItem(STR_BADGE_CONFIG_RESET, INT_MAX));
322 if (gui_classes.GetClasses().empty())
return list;
323 list.push_back(MakeDropDownListDividerItem());
326 const BadgeClassID front = gui_classes.GetClasses().front().class_index;
327 const BadgeClassID back = gui_classes.GetClasses().back().class_index;
329 for (uint i = 0; i < columns; ++i) {
330 for (
const auto &gc : gui_classes.GetClasses()) {
331 if (gc.column_group != i)
continue;
332 if (gc.size.width == 0)
continue;
334 bool first = (i == 0 && gc.class_index == front);
335 bool last = (i == columns - 1 && gc.class_index == back);
336 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()));
339 if (i >= column_separators.size())
continue;
341 if (column_separators[i] == STR_NULL) {
342 list.push_back(MakeDropDownListDividerItem());
344 list.push_back(MakeDropDownListStringItem(column_separators[i], INT_MIN + i,
false,
true));
348 list.push_back(MakeDropDownListDividerItem());
351 for (
const BadgeClassID &badge_class_index : gui_classes.Classes()) {
356 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()));
368static void BadgeClassToggleVisibility(
GrfSpecFeature feature,
Badge &class_badge,
int click_result)
372 if (it == std::end(config))
return;
374 if (click_result == BADGE_CLICK_TOGGLE_ICON) it->show_icon = !it->show_icon;
375 if (click_result == BADGE_CLICK_TOGGLE_FILTER) it->show_filter = !it->show_filter;
386 if (gui_classes.GetClasses().empty())
return;
390 if (it == std::end(config))
return;
393 if (pos_cur == std::begin(gui_classes.GetClasses())) {
394 if (it->column > 0) --it->column;
399 if (it->column > pos_prev->column) {
403 std::rotate(pos_prev, it, std::next(it));
416 if (gui_classes.GetClasses().empty())
return;
420 if (it == std::end(config))
return;
423 if (std::next(pos_cur) == std::end(gui_classes.GetClasses())) {
424 if (it->column <
static_cast<int>(columns - 1)) ++it->column;
429 if (it->column < pos_next->column) {
433 std::rotate(it, std::next(it), std::next(pos_next));
445bool HandleBadgeConfigurationDropDownClick(
GrfSpecFeature feature, uint columns,
int result,
int click_result)
447 if (result == INT_MAX) {
453 if (class_badge ==
nullptr)
return false;
455 switch (click_result) {
456 case BADGE_CLICK_MOVE_DOWN:
457 BadgeClassMoveNext(feature, *class_badge, columns);
459 case BADGE_CLICK_MOVE_UP:
460 BadgeClassMovePrevious(feature, *class_badge);
462 case BADGE_CLICK_TOGGLE_ICON:
463 case BADGE_CLICK_TOGGLE_FILTER:
464 BadgeClassToggleVisibility(feature, *class_badge, click_result);
475 , feature(feature), badge_class(badge_class)
481std::string NWidgetBadgeFilter::GetStringParameter(
const BadgeFilterChoices &choices)
const
484 if (it == std::end(choices)) {
501 list.push_back(MakeDropDownListDividerItem());
508 auto start = list.size();
513 if (badge.
class_index != this->badge_class)
continue;
514 if (badge.
index == bc->index)
continue;
515 if (badge.
name == STR_NULL)
continue;
520 list.push_back(MakeDropDownListStringItem(badge.
name, badge.
index.base()));
522 list.push_back(MakeDropDownListIconItem(d, ps.
sprite, ps.
pal, badge.
name, badge.
index.base()));
549 if (!config.show_filter)
continue;
551 container.
Add(std::make_unique<NWidgetBadgeFilter>(colour, widget, feature, class_index));
555 return {first, widget};
563void ResetBadgeFilter(BadgeFilterChoices &choices,
BadgeClassID badge_class_index)
565 choices.erase(badge_class_index);
574void SetBadgeFilter(BadgeFilterChoices &choices,
BadgeID badge_index)
577 assert(badge !=
nullptr);
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.
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.
uint GetTotalColumnsWidth() const
Get total width of all columns.
Utility class to create a list of badge classes used by a feature.
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.
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.
uint32_t SpriteID
The number of a sprite, without mapping bits and colourtables.
@ SA_CENTER
Center both horizontally and vertically.
uint32_t PaletteID
The number of the palette.
Base for the NewGRF implementation.
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 class of a badge label.
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.
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.
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...
std::string GetString(StringID string)
Resolve the given StringID into a std::string with formatting but no parameters.
TextDirection _current_text_dir
Text direction of the currently selected language.
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.
SpriteID sprite
The 'real' sprite.
PaletteID pal
The palette (use PAL_NONE) if not needed)
Coordinates of a point in 2D.
Specification of a rectangle with absolute coordinates of all edges.
Rect WithWidth(int width, bool end) const
Copy Rect and set its width.
Rect CentreTo(int width, int height) const
Centre a dimension within this Rect.
Rect Indent(int indent, bool end) const
Copy Rect and indent it from its position.
bool Contains(const Point &pt) const
Test if a point falls inside this Rect.
int16_t Height
Fixed point type for heights.
Definition of the game-calendar-timer.
Functions, definitions and such used only by the GUI.
Functions related to zooming.
@ Normal
The normal zoom level.