23#include <winpr/cast.h>
25#include "sdl_widget_list.hpp"
26#include "sdl_input_widget_pair_list.hpp"
28static const Uint32 vpadding = 5;
30SdlInputWidgetPairList::SdlInputWidgetPairList(
const std::string& title,
31 const std::vector<std::string>& labels,
32 const std::vector<std::string>& initial,
33 const std::vector<Uint32>& flags, ssize_t selected)
35 assert(labels.size() == initial.size());
36 assert(labels.size() == flags.size());
37 const std::vector<int> buttonids = { INPUT_BUTTON_ACCEPT, INPUT_BUTTON_CANCEL };
38 const std::vector<std::string> buttonlabels = {
"accept",
"cancel" };
40 const size_t widget_width = 300;
41 const size_t widget_heigth = 50;
43 const size_t total_width = widget_width + widget_width;
44 const size_t input_height = labels.size() * (widget_heigth + vpadding) + vpadding;
45 const size_t total_height = input_height + widget_heigth;
46 assert(total_width <= INT32_MAX);
47 assert(total_height <= INT32_MAX);
49 if (reset(title, total_width, total_height))
51 for (
size_t x = 0; x < labels.size(); x++)
54 _renderer, labels[x], initial[x], flags[x], x, widget_width, widget_heigth));
55 m_list.emplace_back(widget);
58 _buttons.populate(_renderer, buttonlabels, buttonids, total_width,
59 static_cast<Sint32
>(input_height),
static_cast<Sint32
>(widget_width),
60 static_cast<Sint32
>(widget_heigth));
61 _buttons.set_highlight(0);
62 m_currentActiveTextInput = selected;
66ssize_t SdlInputWidgetPairList::next(ssize_t current)
69 auto val =
static_cast<size_t>(current);
73 if (iteration >= m_list.size())
87 }
while (!valid(
static_cast<ssize_t
>(val)));
88 return static_cast<ssize_t
>(val);
91bool SdlInputWidgetPairList::valid(ssize_t current)
const
95 auto s =
static_cast<size_t>(current);
96 if (s >= m_list.size())
98 return !m_list[s]->readonly();
101std::shared_ptr<SdlInputWidgetPair> SdlInputWidgetPairList::get(ssize_t index)
105 auto s =
static_cast<size_t>(index);
106 if (s >= m_list.size())
111SdlInputWidgetPairList::~SdlInputWidgetPairList()
117bool SdlInputWidgetPairList::updateInternal()
119 for (
auto& btn : m_list)
130ssize_t SdlInputWidgetPairList::get_index(
const SDL_MouseButtonEvent& button)
132 const auto x = button.x;
133 const auto y = button.y;
134 for (
size_t i = 0; i < m_list.size(); i++)
136 auto& cur = m_list[i];
137 auto r = cur->input_rect();
139 if ((x >= r.x) && (x <= r.x + r.w) && (y >= r.y) && (y <= r.y + r.h))
140 return WINPR_ASSERTING_INT_CAST(ssize_t, i);
145int SdlInputWidgetPairList::run(std::vector<std::string>& result)
148 ssize_t LastActiveTextInput = -1;
149 m_currentActiveTextInput = next(m_currentActiveTextInput);
151 if (!_window || !_renderer)
154 if (!SDL_StartTextInput(_window.get()))
165 SDL_Event
event = {};
166 if (!SDL_WaitEvent(&event))
172 case SDL_EVENT_KEY_UP:
174 switch (event.key.key)
178 auto cur = get(m_currentActiveTextInput);
181 if ((event.key.mod & SDL_KMOD_CTRL) != 0)
183 if (!cur->set_str(
""))
188 if (!cur->remove_str(1))
195 m_currentActiveTextInput = next(m_currentActiveTextInput);
201 res = INPUT_BUTTON_ACCEPT;
205 res = INPUT_BUTTON_CANCEL;
208 if ((event.key.mod & SDL_KMOD_CTRL) != 0)
210 auto cur = get(m_currentActiveTextInput);
213 auto text = SDL_GetClipboardText();
223 case SDL_EVENT_TEXT_INPUT:
225 auto cur = get(m_currentActiveTextInput);
228 if (!cur->append_str(event.text.text))
233 case SDL_EVENT_MOUSE_MOTION:
235 auto TextInputIndex = get_index(event.button);
236 for (
auto& cur : m_list)
238 if (!cur->set_mouseover(
false))
241 if (TextInputIndex >= 0)
243 auto& cur = m_list[
static_cast<size_t>(TextInputIndex)];
244 if (!cur->set_mouseover(
true))
248 _buttons.set_mouseover(event.button.x, event.button.y);
251 case SDL_EVENT_MOUSE_BUTTON_DOWN:
253 auto val = get_index(event.button);
255 m_currentActiveTextInput = val;
257 auto button = _buttons.get_selected(event.button);
261 if (button->id() == INPUT_BUTTON_CANCEL)
262 res = INPUT_BUTTON_CANCEL;
264 res = INPUT_BUTTON_ACCEPT;
269 res = INPUT_BUTTON_CANCEL;
275 }
while (SDL_PollEvent(&event));
277 if (LastActiveTextInput != m_currentActiveTextInput)
279 LastActiveTextInput = m_currentActiveTextInput;
282 for (
auto& cur : m_list)
284 if (!cur->set_highlight(
false))
287 auto cur = get(m_currentActiveTextInput);
290 if (!cur->set_highlight(
true))
294 auto rc = SDL_RenderPresent(_renderer.get());
297 SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION,
"[%s] SDL_RenderPresent failed with %s",
298 __func__, SDL_GetError());
302 for (
auto& cur : m_list)
303 result.push_back(cur->value());
309 if (!SDL_StopTextInput(_window.get()))