FastLED 3.9.15
Loading...
Searching...
No Matches
dropdown.h
Go to the documentation of this file.
1#pragma once
2
3#include "fl/stl/function.h"
5#include "fl/stl/shared_ptr.h"
6#include "fl/stl/span.h"
7#include "fl/stl/string.h"
8#include "fl/stl/vector.h"
9#include "fl/stl/compiler_control.h" // IWYU pragma: keep
10#include "fl/stl/noexcept.h"
12#include "fl/ui/element.h"
13#include "platforms/ui_defs.h"
14
15#ifndef FASTLED_HAS_UI_DROPDOWN
16#define FASTLED_HAS_UI_DROPDOWN 0
17#endif
18
19namespace fl {
20
21#if !FASTLED_HAS_UI_DROPDOWN
23 public:
24 template<fl::size N>
25 UIDropdownImpl(const fl::string &name, const fl::string (&options)[N])
26 : UIDropdownImpl(name, options, N) {}
27
29 : mSelectedIndex(0) {
30 FASTLED_UNUSED(name);
31 for (fl::size i = 0; i < options.size(); ++i) {
32 mOptions.push_back(options[i]);
33 }
34 if (mOptions.empty()) {
35 mOptions.push_back(fl::string("No options"));
36 }
37 }
38
39 template<typename Iterator>
40 UIDropdownImpl(const fl::string &name, Iterator begin, Iterator end)
41 : mSelectedIndex(0) {
42 FASTLED_UNUSED(name);
43 for (Iterator it = begin; it != end; ++it) {
44 mOptions.push_back(*it);
45 }
46 if (mOptions.empty()) {
47 mOptions.push_back(fl::string("No options"));
48 }
49 }
50
52 : mSelectedIndex(0) {
53 FASTLED_UNUSED(name);
54 for (fl::size i = 0; i < options.size(); ++i) {
55 mOptions.push_back(options[i]);
56 }
57 if (mOptions.empty()) {
58 mOptions.push_back(fl::string("No options"));
59 }
60 }
61
62 UIDropdownImpl(const fl::string &name, fl::initializer_list<fl::string> options)
63 : mSelectedIndex(0) {
64 FASTLED_UNUSED(name);
65 for (const auto& option : options) {
66 mOptions.push_back(option);
67 }
68 if (mOptions.empty()) {
69 mOptions.push_back(fl::string("No options"));
70 }
71 }
72
74
75 fl::string value() const {
76 if (mSelectedIndex < mOptions.size()) {
78 }
79 return fl::string("Invalid");
80 }
81
82 int value_int() const { return static_cast<int>(mSelectedIndex); }
83
84 void setSelectedIndex(int index) {
85 if (index >= 0 && index < static_cast<int>(mOptions.size())) {
86 mSelectedIndex = static_cast<fl::size>(index);
87 }
88 }
89
90 fl::size getOptionCount() const { return mOptions.size(); }
91 fl::string getOption(fl::size index) const {
92 if (index < mOptions.size()) {
93 return mOptions[index];
94 }
95 return fl::string("Invalid");
96 }
97
98 // Stub method for group setting (does nothing on non-WASM platforms)
99 void setGroup(const fl::string& groupName) { FASTLED_UNUSED(groupName); }
100
101 private:
102 UIDropdownImpl(const fl::string &name, const fl::string* options, fl::size count)
103 : mSelectedIndex(0) {
104 FASTLED_UNUSED(name);
105 for (fl::size i = 0; i < count; ++i) {
106 mOptions.push_back(options[i]);
107 }
108 if (mOptions.empty()) {
109 mOptions.push_back(fl::string("No options"));
110 }
111 }
112
115};
116#endif
117
118class UIDropdown : public UIElement {
119 public:
121
122 UIDropdown(const char *name, fl::span<fl::string> options) FL_NOEXCEPT;
123 UIDropdown(const char *name, fl::initializer_list<fl::string> options) FL_NOEXCEPT;
125
126 fl::string value() const FL_NOEXCEPT { return mImpl.value(); }
127 int as_int() const FL_NOEXCEPT { return mImpl.value_int(); }
128 fl::string as_string() const FL_NOEXCEPT { return value(); }
129
131 mImpl.setSelectedIndex(index);
132 }
133
134 fl::size getOptionCount() const FL_NOEXCEPT { return mImpl.getOptionCount(); }
135 fl::string getOption(fl::size index) const FL_NOEXCEPT { return mImpl.getOption(index); }
136
137 operator fl::string() const FL_NOEXCEPT { return value(); }
138 operator int() const FL_NOEXCEPT { return as_int(); }
139
141 setSelectedIndex(index);
142 return *this;
143 }
144
145 // Add a physical button that will advance to the next option when pressed.
146 // Concrete implementation lives in fl/sensors/ui_button_integration.cpp.hpp
147 // to keep the Button dependency out of the fl.cpp link chain.
148 void addNextButton(int pin) FL_NOEXCEPT;
149
151 int currentIndex = as_int();
152 int nextIndex = (currentIndex + 1) % static_cast<int>(getOptionCount());
153 setSelectedIndex(nextIndex);
154 }
155
156 void setGroup(const fl::string& groupName) FL_NOEXCEPT override {
157 UIElement::setGroup(groupName);
158 mImpl.setGroup(groupName);
159 }
160
161 int onChanged(function<void(UIDropdown &)> callback) FL_NOEXCEPT {
162 int out = mCallbacks.add(callback);
163 mListener.addToEngineEventsOnce();
164 return out;
165 }
167
168 protected:
170
174 if (added) {
176 }
177 }
179 if (added) {
180 return;
181 }
183 added = true;
184 }
185 void onBeginFrame() FL_NOEXCEPT override;
186
187 private:
189 bool added = false;
190 };
191
192 private:
193 function_list<void(UIDropdown &)> mCallbacks;
196 fl::shared_ptr<IButtonInput> mNextButton; // Must be before mListener for init order
198};
199
201
202} // namespace fl
static void removeListener(Listener *listener) FL_NOEXCEPT
static void addListener(Listener *listener, int priority=0) FL_NOEXCEPT
UIDropdown(const char *name, fl::initializer_list< fl::string > options) FL_NOEXCEPT
fl::string as_string() const FL_NOEXCEPT
Definition dropdown.h:128
fl::string getOption(fl::size index) const FL_NOEXCEPT
Definition dropdown.h:135
FL_NO_COPY(UIDropdown) UIDropdown(const char *name
Listener mListener
Definition dropdown.h:197
function_list< void(UIDropdown &)> mCallbacks
Definition dropdown.h:193
fl::shared_ptr< IButtonInput > mNextButton
Definition dropdown.h:196
bool mLastFrameValueValid
Definition dropdown.h:195
fl::string value() const FL_NOEXCEPT
Definition dropdown.h:126
void setSelectedIndex(int index) FL_NOEXCEPT
Definition dropdown.h:130
void setGroup(const fl::string &groupName) FL_NOEXCEPT override
Definition dropdown.h:156
UIDropdownImpl mImpl
Definition dropdown.h:169
void addNextButton(int pin) FL_NOEXCEPT
fl::size getOptionCount() const FL_NOEXCEPT
Definition dropdown.h:134
int mLastFrameValue
Definition dropdown.h:194
int as_int() const FL_NOEXCEPT
Definition dropdown.h:127
fl::span< fl::string > options FL_NOEXCEPT
Definition dropdown.h:122
void clearCallbacks() FL_NOEXCEPT
Definition dropdown.h:166
UIDropdown & operator=(int index) FL_NOEXCEPT
Definition dropdown.h:140
void nextOption() FL_NOEXCEPT
Definition dropdown.h:150
int onChanged(function< void(UIDropdown &)> callback) FL_NOEXCEPT
Definition dropdown.h:161
UIDropdownImpl(const fl::string &name, const fl::string *options, fl::size count)
Definition dropdown.h:102
UIDropdownImpl(const fl::string &name, fl::initializer_list< fl::string > options)
Definition dropdown.h:62
void setSelectedIndex(int index)
Definition dropdown.h:84
UIDropdownImpl(const fl::string &name, const fl::vector< fl::string > &options)
Definition dropdown.h:28
int value_int() const
Definition dropdown.h:82
UIDropdownImpl(const fl::string &name, fl::span< fl::string > options)
Definition dropdown.h:51
fl::size mSelectedIndex
Definition dropdown.h:114
~UIDropdownImpl() FL_NOEXCEPT
Definition dropdown.h:73
void setGroup(const fl::string &groupName)
Definition dropdown.h:99
fl::size getOptionCount() const
Definition dropdown.h:90
UIDropdownImpl(const fl::string &name, Iterator begin, Iterator end)
Definition dropdown.h:40
fl::string value() const
Definition dropdown.h:75
fl::vector< fl::string > mOptions
Definition dropdown.h:113
UIDropdownImpl(const fl::string &name, const fl::string(&options)[N])
Definition dropdown.h:25
fl::string getOption(fl::size index) const
Definition dropdown.h:91
virtual void setGroup(const fl::string &groupName) FL_NOEXCEPT
Definition element.h:31
UIElement() FL_NOEXCEPT
constexpr fl::size size() const FL_NOEXCEPT
Definition span.h:458
fl::size size() const FL_NOEXCEPT
#define FASTLED_UI_DEFINE_OPERATORS(UI_CLASS)
Definition element.h:40
constexpr T * begin(T(&array)[N]) FL_NOEXCEPT
constexpr T * end(T(&array)[N]) FL_NOEXCEPT
Base definition for an LED controller.
Definition crgb.hpp:179
#define FASTLED_UNUSED(x)
#define FL_NOEXCEPT
Listener(UIDropdown *owner) FL_NOEXCEPT
Definition dropdown.h:172
~Listener() FL_NOEXCEPT
Definition dropdown.h:173
void addToEngineEventsOnce() FL_NOEXCEPT
Definition dropdown.h:178
void onBeginFrame() FL_NOEXCEPT override