1
0
mirror of https://github.com/OpenRCT2/OpenRCT2 synced 2026-01-30 18:25:16 +01:00

Dropdown: allow specifying number of rows per column (#23713)

* Dropdown: allow specifying number of rows per column

* Dropdown: fix indentation for kColoursDropdownOrder

* Dropdown: minor header cleanup
This commit is contained in:
Aaron van Geffen
2025-01-27 21:49:24 +01:00
committed by GitHub
parent 4bc13f2678
commit 9a8abf2b74
2 changed files with 107 additions and 98 deletions

View File

@@ -10,9 +10,10 @@
#pragma once
#include <openrct2-ui/UiStringIds.h>
#include <openrct2-ui/interface/Window.h>
#include <openrct2/core/EnumUtils.hpp>
#include <openrct2/drawing/ImageId.hpp>
#include <openrct2/interface/Window.h>
struct ImageId;
namespace OpenRCT2::Dropdown
{
@@ -22,18 +23,6 @@ namespace OpenRCT2::Dropdown
constexpr StringId kFormatColourPicker = 0xFFFE;
constexpr StringId kFormatLandPicker = 0xFFFF;
constexpr int32_t kItemsMaxSize = 512;
enum Flag
{
CustomHeight = (1 << 6),
StayOpen = (1 << 7)
};
bool IsChecked(int32_t index);
bool IsDisabled(int32_t index);
void SetChecked(int32_t index, bool value);
void SetDisabled(int32_t index, bool value);
void SetImage(int32_t index, ImageId image);
} // namespace OpenRCT2::Dropdown
namespace OpenRCT2::Ui::Windows
@@ -46,27 +35,45 @@ namespace OpenRCT2::Ui::Windows
extern int32_t gDropdownDefaultIndex;
void WindowDropdownShowText(
const ScreenCoordsXY& screenPos, int32_t extray, ColourWithFlags colour, uint8_t flags, size_t num_items);
const ScreenCoordsXY& screenPos, int32_t extray, ColourWithFlags colour, uint8_t flags, size_t num_items,
size_t prefRowsPerColumn = 0);
void WindowDropdownShowTextCustomWidth(
const ScreenCoordsXY& screenPos, int32_t extray, ColourWithFlags colour, uint8_t custom_height, uint8_t flags,
size_t num_items, int32_t width);
size_t num_items, int32_t width, size_t prefRowsPerColumn = 0);
void WindowDropdownShowImage(
int32_t x, int32_t y, int32_t extray, ColourWithFlags colour, uint8_t flags, int32_t numItems, int32_t itemWidth,
int32_t itemHeight, int32_t numColumns);
void WindowDropdownClose();
int32_t DropdownIndexFromPoint(const ScreenCoordsXY& loc, WindowBase* w);
void WindowDropdownShowColour(
WindowBase* w, Widget* widget, ColourWithFlags dropdownColour, colour_t selectedColour,
bool alwaysHideSpecialColours = false);
void WindowDropdownShowColourAvailable(
WindowBase* w, Widget* widget, uint8_t dropdownColour, uint8_t selectedColour, uint32_t availableColours);
uint32_t DropdownGetAppropriateImageDropdownItemsPerRow(uint32_t numItems);
colour_t ColourDropDownIndexToColour(uint8_t ddidx);
uint32_t DropdownGetAppropriateImageDropdownItemsPerRow(uint32_t numItems);
} // namespace OpenRCT2::Ui::Windows
namespace OpenRCT2::Dropdown
{
bool IsChecked(int32_t index);
bool IsDisabled(int32_t index);
void SetChecked(int32_t index, bool value);
void SetDisabled(int32_t index, bool value);
void SetImage(int32_t index, ImageId image);
enum Flag
{
CustomHeight = (1 << 6), // never set?
StayOpen = (1 << 7)
};
enum class ItemFlag : uint8_t
{
IsDisabled = (1 << 0),

View File

@@ -183,23 +183,24 @@ namespace OpenRCT2::Ui::Windows
}
void SetTextItems(
const ScreenCoordsXY& screenPos, int32_t extraY, ColourWithFlags colour, uint8_t customHeight, uint8_t txtFlags,
size_t numItems, int32_t itemWidth)
const ScreenCoordsXY& screenPos, int32_t extraY, ColourWithFlags colour, uint8_t customItemHeight, uint8_t txtFlags,
size_t numItems, int32_t itemWidth, int32_t numRowsPerColumn)
{
// Set and calculate num items, rows and columns
ItemHeight = (txtFlags & Dropdown::Flag::CustomHeight) ? customHeight : GetDefaultRowHeight();
ItemHeight = (txtFlags & Dropdown::Flag::CustomHeight) ? customItemHeight : GetDefaultRowHeight();
gDropdownNumItems = static_cast<int32_t>(numItems);
// There must always be at least one column to prevent dividing by zero
if (gDropdownNumItems <= 1)
if (gDropdownNumItems > 1)
{
NumRows = 1;
NumColumns = 1;
int32_t numAvailableRows = std::max(1, getSpaceUntilBottom(screenPos, extraY) / ItemHeight);
NumRows = std::min({ gDropdownNumItems, numAvailableRows, numRowsPerColumn });
NumColumns = (gDropdownNumItems + NumRows - 1) / NumRows;
}
else
{
const int32_t numAvailableRows = std::max(1, getSpaceUntilBottom(screenPos, extraY) / ItemHeight);
NumRows = std::min(numAvailableRows, gDropdownNumItems);
NumColumns = (gDropdownNumItems + NumRows - 1) / NumRows;
// There must always be at least one column to prevent dividing by zero
NumRows = 1;
NumColumns = 1;
}
ItemWidth = itemWidth;
@@ -225,6 +226,7 @@ namespace OpenRCT2::Ui::Windows
ItemWidth = itemWidth;
ItemHeight = itemHeight;
gDropdownNumItems = numItems;
// There must always be at least one column and row to prevent dividing by zero
if (gDropdownNumItems == 0)
{
@@ -319,21 +321,22 @@ namespace OpenRCT2::Ui::Windows
* @param colour (al)
*/
void WindowDropdownShowText(
const ScreenCoordsXY& screenPos, int32_t extray, ColourWithFlags colour, uint8_t flags, size_t num_items)
const ScreenCoordsXY& screenPos, int32_t extray, ColourWithFlags colour, uint8_t flags, size_t num_items,
size_t prefRowsPerColumn)
{
int32_t string_width, max_string_width;
char buffer[256];
// Calculate the longest string width
max_string_width = 0;
int32_t max_string_width = 0;
for (size_t i = 0; i < num_items; i++)
{
FormatStringLegacy(buffer, 256, gDropdownItems[i].Format, static_cast<void*>(&gDropdownItems[i].Args));
string_width = GfxGetStringWidth(buffer, FontStyle::Medium);
int32_t string_width = GfxGetStringWidth(buffer, FontStyle::Medium);
max_string_width = std::max(string_width, max_string_width);
}
WindowDropdownShowTextCustomWidth(screenPos, extray, colour, 0, flags, num_items, max_string_width + 3);
WindowDropdownShowTextCustomWidth(
screenPos, extray, colour, 0, flags, num_items, max_string_width + 3, prefRowsPerColumn);
}
/**
@@ -346,11 +349,11 @@ namespace OpenRCT2::Ui::Windows
* @param flags (bh)
* @param num_items (bx)
* @param colour (al)
* @param custom_height (ah) requires flag set as well
* @param customItemHeight (ah) requires flag set as well
*/
void WindowDropdownShowTextCustomWidth(
const ScreenCoordsXY& screenPos, int32_t extray, ColourWithFlags colour, uint8_t custom_height, uint8_t flags,
size_t num_items, int32_t width)
const ScreenCoordsXY& screenPos, int32_t extray, ColourWithFlags colour, uint8_t customItemHeight, uint8_t flags,
size_t num_items, int32_t width, size_t prefRowsPerColumn)
{
InputSetFlag(static_cast<INPUT_FLAGS>(INPUT_FLAG_DROPDOWN_STAY_OPEN | INPUT_FLAG_DROPDOWN_MOUSE_UP), false);
if (flags & Dropdown::Flag::StayOpen || Config::Get().interface.TouchEnhancements)
@@ -360,10 +363,11 @@ namespace OpenRCT2::Ui::Windows
// Create the window (width/height position are set later)
auto* windowMgr = GetWindowManager();
auto* w = windowMgr->Create<DropdownWindow>(WindowClass::Dropdown, width, custom_height, WF_STICK_TO_FRONT);
auto* w = windowMgr->Create<DropdownWindow>(WindowClass::Dropdown, width, customItemHeight, WF_STICK_TO_FRONT);
if (w != nullptr)
{
w->SetTextItems(screenPos, extray, colour, custom_height, flags, num_items, width);
auto numRowsPerColumn = prefRowsPerColumn > 0 ? static_cast<int32_t>(prefRowsPerColumn) : Dropdown::kItemsMaxSize;
w->SetTextItems(screenPos, extray, colour, customItemHeight, flags, num_items, width, numRowsPerColumn);
}
}
@@ -421,73 +425,71 @@ namespace OpenRCT2::Ui::Windows
return -1;
}
// clang-format off
// colour_t ordered for use in color dropdown
static constexpr colour_t kColoursDropdownOrder[] = {
COLOUR_BLACK,
COLOUR_SATURATED_RED,
COLOUR_DARK_ORANGE,
COLOUR_DARK_YELLOW,
COLOUR_GRASS_GREEN_DARK,
COLOUR_SATURATED_GREEN,
COLOUR_AQUA_DARK,
COLOUR_DARK_BLUE,
COLOUR_SATURATED_PURPLE_DARK,
// colour_t ordered for use in color dropdown
static constexpr colour_t kColoursDropdownOrder[] = {
COLOUR_BLACK,
COLOUR_SATURATED_RED,
COLOUR_DARK_ORANGE,
COLOUR_DARK_YELLOW,
COLOUR_GRASS_GREEN_DARK,
COLOUR_SATURATED_GREEN,
COLOUR_AQUA_DARK,
COLOUR_DARK_BLUE,
COLOUR_SATURATED_PURPLE_DARK,
COLOUR_GREY,
COLOUR_BRIGHT_RED,
COLOUR_LIGHT_ORANGE,
COLOUR_YELLOW,
COLOUR_MOSS_GREEN,
COLOUR_BRIGHT_GREEN,
COLOUR_TEAL,
COLOUR_LIGHT_BLUE,
COLOUR_BRIGHT_PURPLE,
COLOUR_GREY,
COLOUR_BRIGHT_RED,
COLOUR_LIGHT_ORANGE,
COLOUR_YELLOW,
COLOUR_MOSS_GREEN,
COLOUR_BRIGHT_GREEN,
COLOUR_TEAL,
COLOUR_LIGHT_BLUE,
COLOUR_BRIGHT_PURPLE,
COLOUR_WHITE,
COLOUR_LIGHT_PINK,
COLOUR_ORANGE_LIGHT,
COLOUR_BRIGHT_YELLOW,
COLOUR_GRASS_GREEN_LIGHT,
COLOUR_SATURATED_GREEN_LIGHT,
COLOUR_AQUAMARINE,
COLOUR_ICY_BLUE,
COLOUR_SATURATED_PURPLE_LIGHT,
COLOUR_WHITE,
COLOUR_LIGHT_PINK,
COLOUR_ORANGE_LIGHT,
COLOUR_BRIGHT_YELLOW,
COLOUR_GRASS_GREEN_LIGHT,
COLOUR_SATURATED_GREEN_LIGHT,
COLOUR_AQUAMARINE,
COLOUR_ICY_BLUE,
COLOUR_SATURATED_PURPLE_LIGHT,
COLOUR_DULL_BROWN_DARK,
COLOUR_BORDEAUX_RED_DARK,
COLOUR_TAN_DARK,
COLOUR_SATURATED_BROWN,
COLOUR_DARK_OLIVE_DARK,
COLOUR_OLIVE_DARK,
COLOUR_DULL_GREEN_DARK,
COLOUR_DARK_PURPLE,
COLOUR_DARK_PINK,
COLOUR_DULL_BROWN_DARK,
COLOUR_BORDEAUX_RED_DARK,
COLOUR_TAN_DARK,
COLOUR_SATURATED_BROWN,
COLOUR_DARK_OLIVE_DARK,
COLOUR_OLIVE_DARK,
COLOUR_DULL_GREEN_DARK,
COLOUR_DARK_PURPLE,
COLOUR_DARK_PINK,
COLOUR_DARK_BROWN,
COLOUR_BORDEAUX_RED,
COLOUR_SALMON_PINK,
COLOUR_LIGHT_BROWN,
COLOUR_DARK_OLIVE_GREEN,
COLOUR_OLIVE_GREEN,
COLOUR_DARK_GREEN,
COLOUR_LIGHT_PURPLE,
COLOUR_BRIGHT_PINK,
COLOUR_DARK_BROWN,
COLOUR_BORDEAUX_RED,
COLOUR_SALMON_PINK,
COLOUR_LIGHT_BROWN,
COLOUR_DARK_OLIVE_GREEN,
COLOUR_OLIVE_GREEN,
COLOUR_DARK_GREEN,
COLOUR_LIGHT_PURPLE,
COLOUR_BRIGHT_PINK,
COLOUR_DULL_BROWN_LIGHT,
COLOUR_BORDEAUX_RED_LIGHT,
COLOUR_TAN_LIGHT,
COLOUR_SATURATED_BROWN_LIGHT,
COLOUR_DARK_OLIVE_LIGHT,
COLOUR_OLIVE_LIGHT,
COLOUR_DULL_GREEN_LIGHT,
COLOUR_DULL_PURPLE_LIGHT,
COLOUR_MAGENTA_LIGHT,
COLOUR_DULL_BROWN_LIGHT,
COLOUR_BORDEAUX_RED_LIGHT,
COLOUR_TAN_LIGHT,
COLOUR_SATURATED_BROWN_LIGHT,
COLOUR_DARK_OLIVE_LIGHT,
COLOUR_OLIVE_LIGHT,
COLOUR_DULL_GREEN_LIGHT,
COLOUR_DULL_PURPLE_LIGHT,
COLOUR_MAGENTA_LIGHT,
COLOUR_INVISIBLE,
COLOUR_VOID
};
// clang-format on
COLOUR_INVISIBLE,
COLOUR_VOID,
};
colour_t ColourDropDownIndexToColour(uint8_t ddidx)
{