4 #include "sdl_input_widgets.hpp"
6 static const Uint32 vpadding = 5;
8 SdlInputWidgetList::SdlInputWidgetList(
const std::string& title,
9 const std::vector<std::string>& labels,
10 const std::vector<std::string>& initial,
11 const std::vector<Uint32>& flags)
12 : _window(nullptr), _renderer(nullptr)
14 assert(labels.size() == initial.size());
15 assert(labels.size() == flags.size());
16 const std::vector<int> buttonids = { INPUT_BUTTON_ACCEPT, INPUT_BUTTON_CANCEL };
17 const std::vector<std::string> buttonlabels = {
"accept",
"cancel" };
19 const size_t widget_width = 300;
20 const size_t widget_heigth = 50;
22 const size_t total_width = widget_width + widget_width;
23 const size_t input_height = labels.size() * (widget_heigth + vpadding) + vpadding;
24 const size_t total_height = input_height + widget_heigth;
25 assert(total_width <= INT32_MAX);
26 assert(total_height <= INT32_MAX);
27 auto rc = SDL_CreateWindowAndRenderer(
28 title.c_str(), total_width,
static_cast<int>(total_height),
29 SDL_WINDOW_HIGH_PIXEL_DENSITY | SDL_WINDOW_MOUSE_FOCUS | SDL_WINDOW_INPUT_FOCUS, &_window,
32 widget_log_error(rc,
"SDL_CreateWindowAndRenderer");
35 for (
size_t x = 0; x < labels.size(); x++)
36 _list.emplace_back(_renderer, labels[x], initial[x], flags[x], x, widget_width,
39 _buttons.populate(_renderer, buttonlabels, buttonids, total_width,
40 static_cast<Sint32
>(input_height),
static_cast<Sint32
>(widget_width),
41 static_cast<Sint32
>(widget_heigth));
42 _buttons.set_highlight(0);
46 ssize_t SdlInputWidgetList::next(ssize_t current)
49 auto val =
static_cast<size_t>(current);
53 if (iteration >= _list.size())
67 }
while (!valid(
static_cast<ssize_t
>(val)));
68 return static_cast<ssize_t
>(val);
71 bool SdlInputWidgetList::valid(ssize_t current)
const
75 auto s =
static_cast<size_t>(current);
76 if (s >= _list.size())
78 return !_list[s].readonly();
85 auto s =
static_cast<size_t>(index);
86 if (s >= _list.size())
91 SdlInputWidgetList::~SdlInputWidgetList()
95 SDL_DestroyRenderer(_renderer);
96 SDL_DestroyWindow(_window);
99 bool SdlInputWidgetList::update(SDL_Renderer* renderer)
101 for (
auto& btn : _list)
103 if (!btn.update_label(renderer))
105 if (!btn.update_input(renderer))
109 return _buttons.update(renderer);
112 ssize_t SdlInputWidgetList::get_index(
const SDL_MouseButtonEvent& button)
114 const auto x = button.x;
115 const auto y = button.y;
116 for (
size_t i = 0; i < _list.size(); i++)
118 auto& cur = _list[i];
119 auto r = cur.input_rect();
121 if ((x >= r.x) && (x <= r.x + r.w) && (y >= r.y) && (y <= r.y + r.h))
127 int SdlInputWidgetList::run(std::vector<std::string>& result)
130 ssize_t LastActiveTextInput = -1;
131 ssize_t CurrentActiveTextInput = next(-1);
133 if (!_window || !_renderer)
139 std::vector<SDL_Keycode> pressed;
142 if (!clear_window(_renderer))
145 if (!update(_renderer))
148 if (!_buttons.update(_renderer))
151 SDL_Event
event = {};
152 SDL_WaitEvent(&event);
155 case SDL_EVENT_KEY_UP:
157 auto it = std::remove(pressed.begin(), pressed.end(), event.key.key);
158 pressed.erase(it, pressed.end());
160 switch (event.key.key)
164 auto cur = get(CurrentActiveTextInput);
167 if (!cur->remove_str(_renderer, 1))
173 CurrentActiveTextInput = next(CurrentActiveTextInput);
179 res = INPUT_BUTTON_ACCEPT;
183 res = INPUT_BUTTON_CANCEL;
186 if (pressed.size() == 2)
188 if ((pressed[0] == SDLK_LCTRL) || (pressed[0] == SDLK_RCTRL))
190 auto cur = get(CurrentActiveTextInput);
193 auto text = SDL_GetClipboardText();
194 cur->set_str(_renderer, text);
204 case SDL_EVENT_KEY_DOWN:
205 pressed.push_back(event.key.key);
207 case SDL_EVENT_TEXT_INPUT:
209 auto cur = get(CurrentActiveTextInput);
212 if (!cur->append_str(_renderer, event.text.text))
217 case SDL_EVENT_MOUSE_MOTION:
219 auto TextInputIndex = get_index(event.button);
220 for (
auto& cur : _list)
222 if (!cur.set_mouseover(_renderer,
false))
225 if (TextInputIndex >= 0)
227 auto& cur = _list[
static_cast<size_t>(TextInputIndex)];
228 if (!cur.set_mouseover(_renderer,
true))
232 _buttons.set_mouseover(event.button.x, event.button.y);
235 case SDL_EVENT_MOUSE_BUTTON_DOWN:
237 auto val = get_index(event.button);
239 CurrentActiveTextInput = val;
241 auto button = _buttons.get_selected(event.button);
245 if (button->id() == INPUT_BUTTON_CANCEL)
246 res = INPUT_BUTTON_CANCEL;
248 res = INPUT_BUTTON_ACCEPT;
253 res = INPUT_BUTTON_CANCEL;
260 if (LastActiveTextInput != CurrentActiveTextInput)
262 if (CurrentActiveTextInput < 0)
263 SDL_StopTextInput(_window);
265 SDL_StartTextInput(_window);
266 LastActiveTextInput = CurrentActiveTextInput;
269 for (
auto& cur : _list)
271 if (!cur.set_highlight(_renderer,
false))
274 auto cur = get(CurrentActiveTextInput);
277 if (!cur->set_highlight(_renderer,
true))
281 SDL_RenderPresent(_renderer);
284 for (
auto& cur : _list)
285 result.push_back(cur.value());