5 #include "sdl_input_widgets.hpp"
7 static const Uint32 vpadding = 5;
9 SdlInputWidgetList::SdlInputWidgetList(
const std::string& title,
10 const std::vector<std::string>& labels,
11 const std::vector<std::string>& initial,
12 const std::vector<Uint32>& flags)
13 : _window(nullptr), _renderer(nullptr)
15 assert(labels.size() == initial.size());
16 assert(labels.size() == flags.size());
17 const std::vector<int> buttonids = { INPUT_BUTTON_ACCEPT, INPUT_BUTTON_CANCEL };
18 const std::vector<std::string> buttonlabels = {
"accept",
"cancel" };
20 const size_t widget_width = 300;
21 const size_t widget_heigth = 50;
23 const size_t total_width = widget_width + widget_width;
24 const size_t input_height = labels.size() * (widget_heigth + vpadding) + vpadding;
25 const size_t total_height = input_height + widget_heigth;
27 assert(total_width <= INT32_MAX);
28 assert(total_height <= INT32_MAX);
29 auto wflags = SDL_WINDOW_ALLOW_HIGHDPI | SDL_WINDOW_MOUSE_FOCUS | SDL_WINDOW_INPUT_FOCUS;
31 SDL_CreateWindowAndRenderer(
static_cast<int>(total_width),
static_cast<int>(total_height),
32 wflags, &_window, &_renderer);
34 widget_log_error(rc,
"SDL_CreateWindowAndRenderer");
37 SDL_SetWindowTitle(_window, title.c_str());
38 for (
size_t x = 0; x < labels.size(); x++)
39 _list.emplace_back(_renderer, labels[x], initial[x], flags[x], x, widget_width,
42 _buttons.populate(_renderer, buttonlabels, buttonids, total_width,
43 static_cast<Sint32
>(input_height),
static_cast<Sint32
>(widget_width),
44 static_cast<Sint32
>(widget_heigth));
45 _buttons.set_highlight(0);
49 ssize_t SdlInputWidgetList::next(ssize_t current)
52 auto val =
static_cast<size_t>(current);
56 if (iteration >= _list.size())
70 }
while (!valid(
static_cast<ssize_t
>(val)));
71 return static_cast<ssize_t
>(val);
74 bool SdlInputWidgetList::valid(ssize_t current)
const
78 auto s =
static_cast<size_t>(current);
79 if (s >= _list.size())
81 return !_list[s].readonly();
88 auto s =
static_cast<size_t>(index);
89 if (s >= _list.size())
94 SdlInputWidgetList::~SdlInputWidgetList()
98 SDL_DestroyRenderer(_renderer);
99 SDL_DestroyWindow(_window);
102 bool SdlInputWidgetList::update(SDL_Renderer* renderer)
104 for (
auto& btn : _list)
106 if (!btn.update_label(renderer))
108 if (!btn.update_input(renderer))
112 return _buttons.update(renderer);
115 ssize_t SdlInputWidgetList::get_index(
const SDL_MouseButtonEvent& button)
117 const Sint32 x = button.x;
118 const Sint32 y = button.y;
119 for (
size_t i = 0; i < _list.size(); i++)
121 auto& cur = _list[i];
122 auto r = cur.input_rect();
124 if ((x >= r.x) && (x <= r.x + r.w) && (y >= r.y) && (y <= r.y + r.h))
130 int SdlInputWidgetList::run(std::vector<std::string>& result)
133 ssize_t LastActiveTextInput = -1;
134 ssize_t CurrentActiveTextInput = next(-1);
136 if (!_window || !_renderer)
142 std::vector<SDL_Keycode> pressed;
145 if (!clear_window(_renderer))
148 if (!update(_renderer))
151 if (!_buttons.update(_renderer))
154 SDL_Event
event = {};
155 SDL_WaitEvent(&event);
160 auto it = std::remove(pressed.begin(), pressed.end(), event.key.keysym.sym);
161 pressed.erase(it, pressed.end());
163 switch (event.key.keysym.sym)
167 auto cur = get(CurrentActiveTextInput);
170 if (!cur->remove_str(_renderer, 1))
176 CurrentActiveTextInput = next(CurrentActiveTextInput);
182 res = INPUT_BUTTON_ACCEPT;
186 res = INPUT_BUTTON_CANCEL;
189 if (pressed.size() == 2)
191 if ((pressed[0] == SDLK_LCTRL) || (pressed[0] == SDLK_RCTRL))
193 auto cur = get(CurrentActiveTextInput);
196 auto text = SDL_GetClipboardText();
197 cur->set_str(_renderer, text);
208 pressed.push_back(event.key.keysym.sym);
212 auto cur = get(CurrentActiveTextInput);
215 if (!cur->append_str(_renderer, event.text.text))
220 case SDL_MOUSEMOTION:
222 auto TextInputIndex = get_index(event.button);
223 for (
auto& cur : _list)
225 if (!cur.set_mouseover(_renderer,
false))
228 if (TextInputIndex >= 0)
230 auto& cur = _list[
static_cast<size_t>(TextInputIndex)];
231 if (!cur.set_mouseover(_renderer,
true))
235 _buttons.set_mouseover(event.button.x, event.button.y);
238 case SDL_MOUSEBUTTONDOWN:
240 auto val = get_index(event.button);
242 CurrentActiveTextInput = val;
244 auto button = _buttons.get_selected(event.button);
248 if (button->id() == INPUT_BUTTON_CANCEL)
249 res = INPUT_BUTTON_CANCEL;
251 res = INPUT_BUTTON_ACCEPT;
256 res = INPUT_BUTTON_CANCEL;
263 if (LastActiveTextInput != CurrentActiveTextInput)
265 if (CurrentActiveTextInput < 0)
268 SDL_StartTextInput();
269 LastActiveTextInput = CurrentActiveTextInput;
272 for (
auto& cur : _list)
274 if (!cur.set_highlight(_renderer,
false))
277 auto cur = get(CurrentActiveTextInput);
280 if (!cur->set_highlight(_renderer,
true))
284 SDL_RenderPresent(_renderer);
287 for (
auto& cur : _list)
288 result.push_back(cur.value());