2 #include <winpr/cast.h>
3 #include "sdl_selectlist.hpp"
5 static const Uint32 vpadding = 5;
7 SdlSelectList::SdlSelectList(
const std::string& title,
const std::vector<std::string>& labels)
8 : _window(nullptr), _renderer(nullptr)
10 const size_t widget_height = 50;
11 const size_t widget_width = 600;
13 const size_t total_height = labels.size() * (widget_height + vpadding) + vpadding;
14 const size_t height = total_height + widget_height;
15 assert(widget_width <= INT32_MAX);
16 assert(height <= INT32_MAX);
17 auto rc = SDL_CreateWindowAndRenderer(
18 title.c_str(),
static_cast<int>(widget_width),
static_cast<int>(height),
19 SDL_WINDOW_HIGH_PIXEL_DENSITY | SDL_WINDOW_MOUSE_FOCUS | SDL_WINDOW_INPUT_FOCUS, &_window,
22 widget_log_error(rc,
"SDL_CreateWindowAndRenderer");
25 SDL_FRect rect = { 0, 0, widget_width, widget_height };
26 for (
auto& label : labels)
28 _list.emplace_back(_renderer, label, rect);
29 rect.y += widget_height + vpadding;
32 const std::vector<int> buttonids = { INPUT_BUTTON_ACCEPT, INPUT_BUTTON_CANCEL };
33 const std::vector<std::string> buttonlabels = {
"accept",
"cancel" };
34 _buttons.populate(_renderer, buttonlabels, buttonids, widget_width,
35 static_cast<Sint32
>(total_height),
static_cast<Sint32
>(widget_width / 2),
36 static_cast<Sint32
>(widget_height));
37 _buttons.set_highlight(0);
41 SdlSelectList::~SdlSelectList()
45 SDL_DestroyRenderer(_renderer);
46 SDL_DestroyWindow(_window);
49 int SdlSelectList::run()
52 ssize_t CurrentActiveTextInput = 0;
55 if (!_window || !_renderer)
61 if (!clear_window(_renderer))
67 if (!_buttons.update(_renderer))
71 SDL_WaitEvent(&event);
74 case SDL_EVENT_KEY_DOWN:
75 switch (event.key.key)
79 if (CurrentActiveTextInput > 0)
80 CurrentActiveTextInput--;
81 else if (_list.empty())
82 CurrentActiveTextInput = 0;
84 CurrentActiveTextInput =
85 WINPR_ASSERTING_INT_CAST(ssize_t, _list.size()) - 1;
89 if ((CurrentActiveTextInput < 0) || _list.empty())
90 CurrentActiveTextInput = 0;
92 CurrentActiveTextInput++;
93 CurrentActiveTextInput =
94 CurrentActiveTextInput %
95 WINPR_ASSERTING_INT_CAST(ssize_t, _list.size());
101 res =
static_cast<int>(CurrentActiveTextInput);
105 res = INPUT_BUTTON_CANCEL;
111 case SDL_EVENT_MOUSE_MOTION:
113 ssize_t TextInputIndex = get_index(event.button);
115 if (TextInputIndex >= 0)
117 auto& cur = _list[WINPR_ASSERTING_INT_CAST(
size_t, TextInputIndex)];
118 if (!cur.set_mouseover(_renderer,
true))
122 _buttons.set_mouseover(event.button.x, event.button.y);
125 case SDL_EVENT_MOUSE_BUTTON_DOWN:
127 auto button = _buttons.get_selected(event.button);
131 if (button->id() == INPUT_BUTTON_CANCEL)
132 res = INPUT_BUTTON_CANCEL;
134 res =
static_cast<int>(CurrentActiveTextInput);
138 CurrentActiveTextInput = get_index(event.button);
143 res = INPUT_BUTTON_CANCEL;
151 if (CurrentActiveTextInput >= 0)
153 auto& cur = _list[WINPR_ASSERTING_INT_CAST(
size_t, CurrentActiveTextInput)];
154 if (!cur.set_highlight(_renderer,
true))
158 SDL_RenderPresent(_renderer);
168 ssize_t SdlSelectList::get_index(
const SDL_MouseButtonEvent& button)
170 const auto x = button.x;
171 const auto y = button.y;
172 for (
size_t i = 0; i < _list.size(); i++)
174 auto& cur = _list[i];
177 if ((x >= r.x) && (x <= r.x + r.w) && (y >= r.y) && (y <= r.y + r.h))
178 return WINPR_ASSERTING_INT_CAST(ssize_t, i);
183 bool SdlSelectList::update_text()
185 for (
auto& cur : _list)
187 if (!cur.update_text(_renderer))
194 void SdlSelectList::reset_mouseover()
196 for (
auto& cur : _list)
198 cur.set_mouseover(_renderer,
false);
202 void SdlSelectList::reset_highlight()
204 for (
auto& cur : _list)
206 cur.set_highlight(_renderer,
false);