4#include "sdl_select_list.hpp"
5#include "../sdl_utils.hpp"
7static const Uint32 vpadding = 5;
9SdlSelectList::SdlSelectList(
const std::string& title,
const std::vector<std::string>& labels)
11 const size_t widget_height = 50;
12 const size_t widget_width = 600;
14 const size_t total_height = labels.size() * (widget_height + vpadding) + vpadding;
15 const size_t height = total_height + widget_height;
16 if (reset(title, widget_width, height))
18 SDL_FRect rect = { 0, 0, widget_width, widget_height };
19 for (
auto& label : labels)
21 _list.emplace_back(_renderer, label, rect);
22 rect.y += widget_height + vpadding;
25 const std::vector<int> buttonids = { INPUT_BUTTON_ACCEPT, INPUT_BUTTON_CANCEL };
26 const std::vector<std::string> buttonlabels = {
"accept",
"cancel" };
27 std::ignore = _buttons.populate(
28 _renderer, buttonlabels, buttonids, widget_width,
static_cast<Sint32
>(total_height),
29 static_cast<Sint32
>(widget_width / 2),
static_cast<Sint32
>(widget_height));
30 _buttons.set_highlight(0);
34SdlSelectList::~SdlSelectList() =
default;
36int SdlSelectList::run()
39 ssize_t CurrentActiveTextInput = 0;
41 std::optional<SDL_Event> forward;
43 if (!_window || !_renderer)
50 throw std::exception();
53 if (!SDL_WaitEventTimeout(&event, 30))
59 case SDL_EVENT_KEY_DOWN:
60 switch (event.key.key)
64 if (CurrentActiveTextInput > 0)
65 CurrentActiveTextInput--;
66 else if (_list.empty())
67 CurrentActiveTextInput = 0;
70 auto s = _list.size();
71 CurrentActiveTextInput =
72 WINPR_ASSERTING_INT_CAST(ssize_t, s) - 1;
77 if ((CurrentActiveTextInput < 0) || _list.empty())
78 CurrentActiveTextInput = 0;
81 auto s = _list.size();
82 CurrentActiveTextInput++;
85 CurrentActiveTextInput =
86 CurrentActiveTextInput %
87 WINPR_ASSERTING_INT_CAST(ssize_t, s);
95 res =
static_cast<int>(CurrentActiveTextInput);
99 res = INPUT_BUTTON_CANCEL;
105 case SDL_EVENT_MOUSE_MOTION:
107 auto TextInputIndex = get_index(event.button);
109 if (TextInputIndex >= 0)
111 auto& cur = _list.at(WINPR_ASSERTING_INT_CAST(
size_t, TextInputIndex));
112 if (!cur.mouseover(
true))
113 throw std::exception();
116 _buttons.set_mouseover(event.button.x, event.button.y);
119 case SDL_EVENT_MOUSE_BUTTON_DOWN:
121 auto button = _buttons.get_selected(event.button);
125 if (button->id() == INPUT_BUTTON_CANCEL)
126 res = INPUT_BUTTON_CANCEL;
128 res =
static_cast<int>(CurrentActiveTextInput);
132 CurrentActiveTextInput = get_index(event.button);
136 case SDL_EVENT_WINDOW_CLOSE_REQUESTED:
138 if (event.window.windowID != SDL_GetWindowID(_window.get()))
140 res = INPUT_BUTTON_CANCEL;
143 case SDL_EVENT_WINDOW_OCCLUDED:
144 case SDL_EVENT_WINDOW_MINIMIZED:
145 case SDL_EVENT_WINDOW_DESTROYED:
148 if (event.window.windowID != SDL_GetWindowID(_window.get()))
150 res = INPUT_BUTTON_CANCEL;
153 case SDL_EVENT_TERMINATING:
155 res = INPUT_BUTTON_CANCEL;
161 }
while (running && SDL_PollEvent(&event));
164 if (CurrentActiveTextInput >= 0)
166 auto& cur = _list.at(WINPR_ASSERTING_INT_CAST(
size_t, CurrentActiveTextInput));
167 if (!cur.highlight(
true))
168 throw std::exception();
175 SDL_FlushEvents(SDL_EVENT_KEY_DOWN, SDL_EVENT_MOUSE_REMOVED);
176 SDL_FlushEvents(SDL_EVENT_FINGER_DOWN, SDL_EVENT_FINGER_CANCELED);
177 SDL_FlushEvents(SDL_EVENT_PEN_PROXIMITY_IN, SDL_EVENT_PEN_AXIS);
179 std::ignore = SDL_PushEvent(&*forward);
188bool SdlSelectList::updateInternal()
190 for (
auto& cur : _list)
198ssize_t SdlSelectList::get_index(
const SDL_MouseButtonEvent& button)
200 const auto x = button.x;
201 const auto y = button.y;
202 for (
size_t i = 0; i < _list.size(); i++)
204 auto& cur = _list.at(i);
207 if ((x >= r.x) && (x <= r.x + r.w) && (y >= r.y) && (y <= r.y + r.h))
208 return WINPR_ASSERTING_INT_CAST(ssize_t, i);
213void SdlSelectList::reset_mouseover()
215 for (
auto& cur : _list)
217 cur.mouseover(
false);
221void SdlSelectList::reset_highlight()
223 for (
auto& cur : _list)
225 cur.highlight(
false);