5#include "sdl_selectlist.hpp"
7static const Uint32 vpadding = 5;
9SdlSelectList::SdlSelectList(
const std::string& title,
const std::vector<std::string>& labels)
10 : _window(nullptr), _renderer(nullptr)
12 const size_t widget_height = 50;
13 const size_t widget_width = 600;
15 const size_t total_height = labels.size() * (widget_height + vpadding) + vpadding;
16 const size_t height = total_height + widget_height;
17 assert(widget_width <= INT32_MAX);
18 assert(height <= INT32_MAX);
20 auto flags = WINPR_ASSERTING_INT_CAST(
21 uint32_t, SDL_WINDOW_ALLOW_HIGHDPI | SDL_WINDOW_MOUSE_FOCUS | SDL_WINDOW_INPUT_FOCUS);
22 auto rc = SDL_CreateWindowAndRenderer(
static_cast<int>(widget_width),
static_cast<int>(height),
23 flags, &_window, &_renderer);
25 widget_log_error(rc,
"SDL_CreateWindowAndRenderer");
28 SDL_SetWindowTitle(_window, title.c_str());
30 SDL_Rect rect = { 0, 0, widget_width, widget_height };
31 for (
auto& label : labels)
33 _list.emplace_back(_renderer, label, rect);
34 rect.y += widget_height + vpadding;
37 const std::vector<int> buttonids = { INPUT_BUTTON_ACCEPT, INPUT_BUTTON_CANCEL };
38 const std::vector<std::string> buttonlabels = {
"accept",
"cancel" };
39 _buttons.populate(_renderer, buttonlabels, buttonids, widget_width,
40 static_cast<Sint32
>(total_height),
static_cast<Sint32
>(widget_width / 2),
41 static_cast<Sint32
>(widget_height));
42 _buttons.set_highlight(0);
46SdlSelectList::~SdlSelectList()
50 SDL_DestroyRenderer(_renderer);
51 SDL_DestroyWindow(_window);
54int SdlSelectList::run()
57 ssize_t CurrentActiveTextInput = 0;
60 if (!_window || !_renderer)
66 if (!clear_window(_renderer))
72 if (!_buttons.update(_renderer))
76 SDL_WaitEvent(&event);
80 switch (event.key.keysym.sym)
84 if (CurrentActiveTextInput > 0)
85 CurrentActiveTextInput--;
87 CurrentActiveTextInput =
88 WINPR_ASSERTING_INT_CAST(ssize_t, _list.size() - 1);
93 if (CurrentActiveTextInput < 0)
94 CurrentActiveTextInput = 0;
96 CurrentActiveTextInput++;
98 const auto s = _list.size();
100 CurrentActiveTextInput = 0;
102 CurrentActiveTextInput =
103 CurrentActiveTextInput % WINPR_ASSERTING_INT_CAST(ssize_t, s);
110 res = WINPR_ASSERTING_INT_CAST(
int, CurrentActiveTextInput);
114 res = INPUT_BUTTON_CANCEL;
120 case SDL_MOUSEMOTION:
122 ssize_t TextInputIndex = get_index(event.button);
124 if (TextInputIndex >= 0)
126 auto& cur = _list[WINPR_ASSERTING_INT_CAST(
size_t, TextInputIndex)];
127 if (!cur.set_mouseover(_renderer,
true))
131 _buttons.set_mouseover(event.button.x, event.button.y);
134 case SDL_MOUSEBUTTONDOWN:
136 auto button = _buttons.get_selected(event.button);
140 if (button->id() == INPUT_BUTTON_CANCEL)
141 res = INPUT_BUTTON_CANCEL;
143 res =
static_cast<int>(CurrentActiveTextInput);
147 CurrentActiveTextInput = get_index(event.button);
152 res = INPUT_BUTTON_CANCEL;
160 if (CurrentActiveTextInput >= 0)
162 auto& cur = _list[WINPR_ASSERTING_INT_CAST(
size_t, CurrentActiveTextInput)];
163 if (!cur.set_highlight(_renderer,
true))
167 SDL_RenderPresent(_renderer);
177ssize_t SdlSelectList::get_index(
const SDL_MouseButtonEvent& button)
179 const Sint32 x = button.x;
180 const Sint32 y = button.y;
181 for (
size_t i = 0; i < _list.size(); i++)
183 auto& cur = _list[i];
186 if ((x >= r.x) && (x <= r.x + r.w) && (y >= r.y) && (y <= r.y + r.h))
187 return WINPR_ASSERTING_INT_CAST(ssize_t, i);
192bool SdlSelectList::update_text()
194 for (
auto& cur : _list)
196 if (!cur.update_text(_renderer))
203void SdlSelectList::reset_mouseover()
205 for (
auto& cur : _list)
207 cur.set_mouseover(_renderer,
false);
211void SdlSelectList::reset_highlight()
213 for (
auto& cur : _list)
215 cur.set_highlight(_renderer,
false);