3#include "Constraint.hpp"
4#include "RootDisplay.hpp"
11 std::vector<std::pair<std::string, std::string>> choices,
12 std::function<
void(std::string)> onSelect,
14 std::string defaultChoice,
16) : Button(defaultChoice.empty() ?
"Select..." : ([&choices, &defaultChoice]() {
17 for (
const auto& choice : choices) {
18 if (choice.first == defaultChoice)
return choice.second;
21 })(), physicalButton, isDarkMode, textSize, 0)
23 this->choices = choices;
24 this->onSelect = onSelect;
25 this->selectedChoice = defaultChoice;
29 callback = this->onSelect,
32 RootDisplay::pushScreen(std::make_unique<DropDownChoices>(
41 return Button::process(event);
45DropDownChoices::DropDownChoices(
46 std::vector<std::pair<std::string, std::string>> choices,
47 std::function<
void(std::string)> onSelect,
51 onSelectCallback(onSelect),
52 isDarkMode(isDarkMode),
58 for (
const auto& choice : this->choices) {
59 std::string displayText = choice.second.empty() ?
"(empty)" : choice.second;
61 auto choiceElement = std::make_unique<Button>(displayText, 0, isDarkMode, 20, 0);
62 widestWidth = std::max(widestWidth, choiceElement->width);
64 choiceElement->setAction([
66 choiceKey = choice.first
69 std::string choiceKeyCopy = choiceKey;
72 auto callbackCopy = this->onSelectCallback;
75 RootDisplay::popScreen();
79 callbackCopy(choiceKeyCopy);
82 container->add(std::move(choiceElement));
86 for (
const auto& child : container->elements) {
87 if (
auto buttonChild =
dynamic_cast<Button*
>(child.get())) {
88 buttonChild->fixedWidth = widestWidth;
89 buttonChild->updateBounds();
94void DropDownChoices::rebuildUI() {
99 auto scrollContainer = std::make_unique<ListElement>();
100 scrollContainer->width = SCREEN_WIDTH;
101 scrollContainer->height = SCREEN_HEIGHT;
102 scrollList = scrollContainer.get();
106 auto overlay = createNode<Element>();
107 overlay->width = SCREEN_WIDTH;
108 overlay->height = SCREEN_HEIGHT;
109 overlay->backgroundColor = fromRGB(0, 0, 0);
110 overlay->backgroundOpacity = 0x70;
111 overlay->cornerRadius = 1;
112 overlay->hasBackground =
true;
115 if (!header.empty()) {
116 auto headerText = std::make_unique<TextElement>(header.c_str(), 28);
117 headerText->constrain(ALIGN_CENTER_HORIZONTAL);
118 headerText->position(0, SCREEN_HEIGHT / 5 - 60);
119 scrollContainer->addNode(std::move(headerText));
123 auto containerPtr = std::make_unique<Container>(COL_LAYOUT, 20);
124 container = containerPtr.get();
128 container->backgroundColor = fromRGB(0x2d, 0x2c, 0x31);
130 container->backgroundColor = fromRGB(0xf5, 0xf5, 0xf5);
132 container->hasBackground =
true;
135 container->constrain(ALIGN_CENTER_HORIZONTAL);
137 container->y = SCREEN_HEIGHT / 5;
139 scrollContainer->addNode(std::move(containerPtr));
142 auto backBtn = createNode<Button>(i18n(
"dropdown.back"), B_BUTTON, isDarkMode, 15);
143 backBtn->constrain(ALIGN_BOTTOM | ALIGN_LEFT, 10);
144 backBtn->setAction([]() {
146 RootDisplay::popScreen();
149 addNode(std::move(scrollContainer));
152void DropDownChoices::render(
Element* parent) {
153 super::render(parent);
158 if (event->
held(A_BUTTON) && this->curHighlighted >= 0 && this->curHighlighted < (
int)container->elements.size()) {
159 this->container->elements[this->curHighlighted]->action();
163 if (event->
held(B_BUTTON)) {
165 RootDisplay::popScreen();
169 if (event->isTouch()) {
171 this->curHighlighted = -1;
173 if (event->isKeyDown() && event->
held(UP_BUTTON | DOWN_BUTTON | LEFT_BUTTON | RIGHT_BUTTON)) {
178 if (curHighlighted >= 0 && curHighlighted < (
int)container->elements.size() && container->elements[curHighlighted])
179 container->elements[curHighlighted]->elasticCounter = NO_HIGHLIGHT;
182 this->curHighlighted += -1 * (
event->held(UP_BUTTON)) + (event->
held(DOWN_BUTTON));
185 if (curHighlighted >= (
int)container->elements.size()) curHighlighted = container->elements.size() - 1;
186 if (curHighlighted < 0) curHighlighted = 0;
189 if (curHighlighted < (
int)container->elements.size() && container->elements[curHighlighted])
190 container->elements[curHighlighted]->elasticCounter = THICK_HIGHLIGHT;
193 if (curHighlighted >= 0 && curHighlighted < (
int)container->elements.size() && container->elements[curHighlighted] && scrollList) {
198 int normalizedY = container->y + curElement->y + scrollList->y;
201 if (normalizedY < 50) {
202 event->wheelScroll = 1;
205 else if (normalizedY + curElement->height > SCREEN_HEIGHT - 50) {
206 event->wheelScroll = -1;
214 return Screen::process(event);
std::vector< std::unique_ptr< Element, std::function< void(Element *)> > > elements
visible GUI child elements of this element