6 #include "sdl_input_widgets.hpp"
8 static const Uint32 vpadding = 5;
10 SdlInputWidgetList::SdlInputWidgetList(
const std::string& title,
11 const std::vector<std::string>& labels,
12 const std::vector<std::string>& initial,
13 const std::vector<Uint32>& flags)
14 : _window(nullptr), _renderer(nullptr)
16 assert(labels.size() == initial.size());
17 assert(labels.size() == flags.size());
18 const std::vector<int> buttonids = { INPUT_BUTTON_ACCEPT, INPUT_BUTTON_CANCEL };
19 const std::vector<std::string> buttonlabels = {
"accept",
"cancel" };
21 const size_t widget_width = 300;
22 const size_t widget_heigth = 50;
24 const size_t total_width = widget_width + widget_width;
25 const size_t input_height = labels.size() * (widget_heigth + vpadding) + vpadding;
26 const size_t total_height = input_height + widget_heigth;
28 assert(total_width <= INT32_MAX);
29 assert(total_height <= INT32_MAX);
30 Uint32 wflags = SDL_WINDOW_ALLOW_HIGHDPI | SDL_WINDOW_MOUSE_FOCUS | SDL_WINDOW_INPUT_FOCUS;
32 SDL_CreateWindowAndRenderer(
static_cast<int>(total_width),
static_cast<int>(total_height),
33 wflags, &_window, &_renderer);
35 widget_log_error(rc,
"SDL_CreateWindowAndRenderer");
38 SDL_SetWindowTitle(_window, title.c_str());
39 for (
size_t x = 0; x < labels.size(); x++)
40 _list.emplace_back(_renderer, labels[x], initial[x], flags[x], x, widget_width,
43 _buttons.populate(_renderer, buttonlabels, buttonids, total_width,
44 static_cast<Sint32
>(input_height),
static_cast<Sint32
>(widget_width),
45 static_cast<Sint32
>(widget_heigth));
46 _buttons.set_highlight(0);
50 ssize_t SdlInputWidgetList::next(ssize_t current)
53 auto val =
static_cast<size_t>(current);
57 if (iteration >= _list.size())
71 }
while (!valid(
static_cast<ssize_t
>(val)));
72 return static_cast<ssize_t
>(val);
75 bool SdlInputWidgetList::valid(ssize_t current)
const
79 auto s =
static_cast<size_t>(current);
80 if (s >= _list.size())
82 return !_list[s].readonly();
89 auto s =
static_cast<size_t>(index);
90 if (s >= _list.size())
95 SdlInputWidgetList::~SdlInputWidgetList()
99 SDL_DestroyRenderer(_renderer);
100 SDL_DestroyWindow(_window);
103 bool SdlInputWidgetList::update(SDL_Renderer* renderer)
105 for (
auto& btn : _list)
107 if (!btn.update_label(renderer))
109 if (!btn.update_input(renderer))
113 return _buttons.update(renderer);
116 ssize_t SdlInputWidgetList::get_index(
const SDL_MouseButtonEvent& button)
118 const Sint32 x = button.x;
119 const Sint32 y = button.y;
121 assert(_list.size() <= std::numeric_limits<ssize_t>::max());
122 for (
size_t i = 0; i < _list.size(); i++)
124 auto& cur = _list[i];
125 auto r = cur.input_rect();
127 if ((x >= r.x) && (x <= r.x + r.w) && (y >= r.y) && (y <= r.y + r.h))
128 return static_cast<ssize_t
>(i);
133 int SdlInputWidgetList::run(std::vector<std::string>& result)
136 ssize_t LastActiveTextInput = -1;
137 ssize_t CurrentActiveTextInput = next(-1);
139 if (!_window || !_renderer)
145 std::vector<SDL_Keycode> pressed;
148 if (!clear_window(_renderer))
151 if (!update(_renderer))
154 if (!_buttons.update(_renderer))
157 SDL_Event
event = {};
158 SDL_WaitEvent(&event);
163 auto it = std::remove(pressed.begin(), pressed.end(), event.key.keysym.sym);
164 pressed.erase(it, pressed.end());
166 switch (event.key.keysym.sym)
170 auto cur = get(CurrentActiveTextInput);
173 if (!cur->remove_str(_renderer, 1))
179 CurrentActiveTextInput = next(CurrentActiveTextInput);
185 res = INPUT_BUTTON_ACCEPT;
189 res = INPUT_BUTTON_CANCEL;
192 if (pressed.size() == 2)
194 if ((pressed[0] == SDLK_LCTRL) || (pressed[0] == SDLK_RCTRL))
196 auto cur = get(CurrentActiveTextInput);
199 auto text = SDL_GetClipboardText();
200 cur->set_str(_renderer, text);
211 pressed.push_back(event.key.keysym.sym);
215 auto cur = get(CurrentActiveTextInput);
218 if (!cur->append_str(_renderer, event.text.text))
223 case SDL_MOUSEMOTION:
225 auto TextInputIndex = get_index(event.button);
226 for (
auto& cur : _list)
228 if (!cur.set_mouseover(_renderer,
false))
231 if (TextInputIndex >= 0)
233 auto& cur = _list[
static_cast<size_t>(TextInputIndex)];
234 if (!cur.set_mouseover(_renderer,
true))
238 _buttons.set_mouseover(event.button.x, event.button.y);
241 case SDL_MOUSEBUTTONDOWN:
243 auto val = get_index(event.button);
245 CurrentActiveTextInput = val;
247 auto button = _buttons.get_selected(event.button);
251 if (button->id() == INPUT_BUTTON_CANCEL)
252 res = INPUT_BUTTON_CANCEL;
254 res = INPUT_BUTTON_ACCEPT;
259 res = INPUT_BUTTON_CANCEL;
266 if (LastActiveTextInput != CurrentActiveTextInput)
268 if (CurrentActiveTextInput < 0)
271 SDL_StartTextInput();
272 LastActiveTextInput = CurrentActiveTextInput;
275 for (
auto& cur : _list)
277 if (!cur.set_highlight(_renderer,
false))
280 auto cur = get(CurrentActiveTextInput);
283 if (!cur->set_highlight(_renderer,
true))
287 SDL_RenderPresent(_renderer);
290 for (
auto& cur : _list)
291 result.push_back(cur.value());