Chesto 0.9
A declarative and element-based library for creating GUIs on homebrew'd consoles
Public Member Functions | Public Attributes | List of all members
Chesto::DropDownChoices Class Reference
Inheritance diagram for Chesto::DropDownChoices:
Inheritance graph
[legend]
Collaboration diagram for Chesto::DropDownChoices:
Collaboration graph
[legend]

Public Member Functions

 DropDownChoices (std::vector< std::pair< std::string, std::string > > choices, std::function< void(std::string)> onSelect, bool isDarkMode, std::string header="")
 
bool process (InputEvents *event) override
 process any input that is received for this element More...
 
void render (Element *parent) override
 display the current state of the display More...
 
void rebuildUI () override
 
virtual void rebuildUI ()=0
 
- Public Member Functions inherited from Chesto::Element
virtual bool process (InputEvents *event)
 process any input that is received for this element More...
 
virtual void render (Element *parent)
 display the current state of the display More...
 
bool onTouchDown (InputEvents *event)
 
bool onTouchDrag (InputEvents *event)
 
bool onTouchUp (InputEvents *event)
 
void hide ()
 
void unhide ()
 
void renderBackground (bool fill=true)
 
void addNode (std::unique_ptr< Element > node)
 
void remove (Element *element)
 
void removeAll ()
 
void position (int x, int y)
 position the element More...
 
void recalcPosition (Element *parent)
 
float getEffectiveScale () const
 
CST_Rect getBounds ()
 
CST_Renderer * getRenderer ()
 
ElementsetPosition (int x, int y)
 
ElementsetAction (std::function< void()> func)
 
ElementsetAbsolute (bool isAbs)
 
template<typename T , typename... Args>
T * createNode (Args &&... args)
 
Elementconstrain (int flags, int padding=0)
 
ElementconstrainToTarget (Element *target, int flags, int padding=0)
 
Elementanimate (int durationIn, std::function< void(float)> onStep, std::function< void()> onFinish)
 
ElementmoveToFront ()
 
ElementsetTouchable (bool touchable)
 
void screenshot (std::string path)
 Take a screenshot of this element and its children, and save it to the given path. More...
 

Public Attributes

int curHighlighted = -1
 
Containercontainer = nullptr
 
ListElementscrollList = nullptr
 
- Public Attributes inherited from Chesto::Element
std::function< void()> action = NULL
 the action to call (from binded callback) on touch or button selection https://stackoverflow.com/questions/14189440/c-class-member-callback-simple-examples More...
 
std::function< void(InputEvents *event)> actionWithEvents = NULL
 
std::vector< std::unique_ptr< Element, std::function< void(Element *)> > > elements
 visible GUI child elements of this element More...
 
float scale = 1.0f
 
bool touchable = false
 whether or not this element can be touched (highlights bounds) More...
 
bool dragging = false
 whether or not this element is currently being dragged More...
 
bool needsRedraw = false
 whether or not this element needs the screen redrawn next time it's processed More...
 
int futureRedrawCounter = 0
 whether this element needs a redraw for the next X redraws (decreases each time) (0 is no redraws) More...
 
int lastMouseY = 0
 the last Y, X coordinate of the mouse (from a drag probably) More...
 
int lastMouseX = 0
 
bool hasBackground = false
 
rgb backgroundColor = {0, 0, 0}
 
int backgroundOpacity = 0xff
 
bool isAbsolute = false
 
Elementparent = nullptr
 the parent element (reference only, not owned) More...
 
bool hidden = false
 whether this element should skip rendering or not More...
 
bool isProtected = false
 
int elasticCounter = 0
 how much time is left in an elastic-type flick/scroll set by the last distance traveled in a scroll, and counts down every frame More...
 
int width = 0
 width and height of this element (must be manually set, isn't usually calculated (but is in some cases, like text or images)) More...
 
int height = 0
 
int x = 0
 
int y = 0
 
int xAbs = 0
 
int yAbs = 0
 
double angle = 0
 rotation angle in degrees More...
 
int cornerRadius = 0
 
int tag = 0
 
std::vector< std::unique_ptr< Constraint > > constraints
 
std::vector< std::unique_ptr< Animation > > animations
 
bool useColorMask = false
 whether or not to overlay a color mask on top of this element More...
 
CST_Color maskColor = {0,0,0,0}
 The color to overlay on top. More...
 

Additional Inherited Members

- Public Types inherited from Chesto::Element
typedef Element super
 
- Protected Member Functions inherited from Chesto::Screen
int getScreenWidth () const
 
int getScreenHeight () const
 
- Protected Member Functions inherited from Chesto::Element
void addStackMember (Element *element)
 

Detailed Description

Definition at line 43 of file DropDown.hpp.

Constructor & Destructor Documentation

◆ DropDownChoices()

Chesto::DropDownChoices::DropDownChoices ( std::vector< std::pair< std::string, std::string > >  choices,
std::function< void(std::string)>  onSelect,
bool  isDarkMode,
std::string  header = "" 
)

Definition at line 45 of file DropDown.cpp.

50 : choices(choices),
51 onSelectCallback(onSelect),
52 isDarkMode(isDarkMode),
53 header(header)
54{
55 rebuildUI();
56
57 int widestWidth = 0;
58 for (const auto& choice : this->choices) {
59 std::string displayText = choice.second.empty() ? "(empty)" : choice.second;
60
61 auto choiceElement = std::make_unique<Button>(displayText, 0, isDarkMode, 20, 0);
62 widestWidth = std::max(widestWidth, choiceElement->width);
63
64 choiceElement->setAction([
65 this, // Capture this to access onSelectCallback member
66 choiceKey = choice.first
67 ]() {
68 // local copy is needed here to avoid it being destroyed after popScreen
69 std::string choiceKeyCopy = choiceKey;
70
71 // same as above?
72 auto callbackCopy = this->onSelectCallback;
73
74 // pop the dropdown screen (deletes 'this'!)
75 RootDisplay::popScreen();
76
77 // use local copies now
78 if (callbackCopy) {
79 callbackCopy(choiceKeyCopy);
80 }
81 });
82 container->add(std::move(choiceElement));
83 }
84
85 // make each choice the same width (widest)
86 for (const auto& child : container->elements) {
87 if (auto buttonChild = dynamic_cast<Button*>(child.get())) {
88 buttonChild->fixedWidth = widestWidth;
89 buttonChild->updateBounds();
90 }
91 }
92}
void rebuildUI() override
Definition: DropDown.cpp:94
std::vector< std::unique_ptr< Element, std::function< void(Element *)> > > elements
visible GUI child elements of this element
Definition: Element.hpp:59

Member Function Documentation

◆ process()

bool Chesto::DropDownChoices::process ( InputEvents event)
overridevirtual

process any input that is received for this element

Reimplemented from Chesto::Element.

Definition at line 156 of file DropDown.cpp.

156 {
157 // if we have an up or down button event, instead of scrolling the list element, move cursor selection within the container
158 if (event->held(A_BUTTON) && this->curHighlighted >= 0 && this->curHighlighted < (int)container->elements.size()) {
159 this->container->elements[this->curHighlighted]->action(); // fire that button's action
160 return true;
161 }
162
163 if (event->held(B_BUTTON)) {
164 // dismiss without a selection - pop this screen
165 RootDisplay::popScreen();
166 return true;
167 }
168
169 if (event->isTouch()) {
170 // unhighlight whatever may be highlighted
171 this->curHighlighted = -1;
172 } else {
173 if (event->isKeyDown() && event->held(UP_BUTTON | DOWN_BUTTON | LEFT_BUTTON | RIGHT_BUTTON)) {
174 // Similar to HBAS's AppList navigation logic
175
176 // look up whatever is currently chosen as the highlighted position
177 // and remove its highlight
178 if (curHighlighted >= 0 && curHighlighted < (int)container->elements.size() && container->elements[curHighlighted])
179 container->elements[curHighlighted]->elasticCounter = NO_HIGHLIGHT;
180
181 // adjust it by R for up and down
182 this->curHighlighted += -1 * (event->held(UP_BUTTON)) + (event->held(DOWN_BUTTON));
183
184 // don't let the cursor go out of bounds
185 if (curHighlighted >= (int)container->elements.size()) curHighlighted = container->elements.size() - 1;
186 if (curHighlighted < 0) curHighlighted = 0;
187
188 // highlight the new element
189 if (curHighlighted < (int)container->elements.size() && container->elements[curHighlighted])
190 container->elements[curHighlighted]->elasticCounter = THICK_HIGHLIGHT;
191
192 // Auto-scroll to keep highlighted element on screen (similar to AppList logic)
193 if (curHighlighted >= 0 && curHighlighted < (int)container->elements.size() && container->elements[curHighlighted] && scrollList) {
194 Element* curElement = container->elements[curHighlighted].get();
195
196 // Calculate the y-position of the currently highlighted element on screen (accounting for scroll)
197 // scrollList->y is the scroll offset, container->y is the initial position, curElement->y is relative to container
198 int normalizedY = container->y + curElement->y + scrollList->y;
199
200 // If element is going off the top of the screen, scroll down to keep it visible
201 if (normalizedY < 50) {
202 event->wheelScroll = 1;
203 }
204 // If element is going off the bottom of the screen, scroll up to keep it visible
205 else if (normalizedY + curElement->height > SCREEN_HEIGHT - 50) {
206 event->wheelScroll = -1;
207 }
208 }
209
210 return true;
211 }
212 }
213
214 return Screen::process(event);
215}
virtual bool process(InputEvents *event)
process any input that is received for this element
Definition: Element.cpp:29

References Chesto::Element::elements, and Chesto::InputEvents::held().

◆ rebuildUI()

void Chesto::DropDownChoices::rebuildUI ( )
overridevirtual

Rebuild the entire UI for this screen. Called on initialization and whenever the screen needs to be reconstructed (e.g., theme changes, language changes).

Implementations should:

  1. Call removeAll() to clear existing UI
  2. Create all UI elements with std::make_unique
  3. Configure elements (position, actions, etc.)
  4. Transfer ownership via append(std::move(...))

Implements Chesto::Screen.

Definition at line 94 of file DropDown.cpp.

94 {
95 removeAll();
96
97 // Create a full-screen scrollable list to hold everything
98 // TODO: a common way for Screen's to have all their content be scrollable without making a new element each time
99 auto scrollContainer = std::make_unique<ListElement>();
100 scrollContainer->width = SCREEN_WIDTH;
101 scrollContainer->height = SCREEN_HEIGHT;
102 scrollList = scrollContainer.get(); // Keep pointer for scrolling
103
104 // overlay and shade bg color
105 // also TODO: a common way to have the dim background exist and fade in
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; // needed to force transparency
112 overlay->hasBackground = true;
113
114 // header text if specified
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));
120 }
121
122 // vertical container for the choices
123 auto containerPtr = std::make_unique<Container>(COL_LAYOUT, 20);
124 container = containerPtr.get();
125
126 // TODO: Chesto doesn't know about light/dark themes, these are hardcoded to match HBAS themes
127 if (isDarkMode) {
128 container->backgroundColor = fromRGB(0x2d, 0x2c, 0x31); // match theme dark background
129 } else {
130 container->backgroundColor = fromRGB(0xf5, 0xf5, 0xf5); // light gray for light mode
131 }
132 container->hasBackground = true;
133
134 // center the container horizontally within our full screen overlay
135 container->constrain(ALIGN_CENTER_HORIZONTAL);
136 // position the start of the dropdown in the upper fifth of the screen
137 container->y = SCREEN_HEIGHT / 5;
138
139 scrollContainer->addNode(std::move(containerPtr));
140
141 // not a part of the scrollable area
142 auto backBtn = createNode<Button>(i18n("dropdown.back"), B_BUTTON, isDarkMode, 15);
143 backBtn->constrain(ALIGN_BOTTOM | ALIGN_LEFT, 10);
144 backBtn->setAction([]() {
145 // hides the dropdown without any callback
146 RootDisplay::popScreen();
147 });
148
149 addNode(std::move(scrollContainer));
150}

◆ render()

void Chesto::DropDownChoices::render ( Element parent)
overridevirtual

display the current state of the display

Reimplemented from Chesto::Element.

Definition at line 152 of file DropDown.cpp.

152 {
154}
virtual void render(Element *parent)
display the current state of the display
Definition: Element.cpp:89
Element * parent
the parent element (reference only, not owned)
Definition: Element.hpp:116

Member Data Documentation

◆ container

Container* Chesto::DropDownChoices::container = nullptr

Definition at line 57 of file DropDown.hpp.

◆ curHighlighted

int Chesto::DropDownChoices::curHighlighted = -1

Definition at line 56 of file DropDown.hpp.

◆ scrollList

ListElement* Chesto::DropDownChoices::scrollList = nullptr

Definition at line 58 of file DropDown.hpp.


The documentation for this class was generated from the following files: