FreeRDP
Loading...
Searching...
No Matches
sdl_select_list.cpp
1#include <cassert>
2#include <winpr/cast.h>
3#include "sdl_select_list.hpp"
4#include "../sdl_utils.hpp"
5
6static const Uint32 vpadding = 5;
7
8SdlSelectList::SdlSelectList(const std::string& title, const std::vector<std::string>& labels)
9{
10 const size_t widget_height = 50;
11 const size_t widget_width = 600;
12
13 const size_t total_height = labels.size() * (widget_height + vpadding) + vpadding;
14 const size_t height = total_height + widget_height;
15 if (reset(title, widget_width, height))
16 {
17 SDL_FRect rect = { 0, 0, widget_width, widget_height };
18 for (auto& label : labels)
19 {
20 _list.emplace_back(_renderer, label, rect);
21 rect.y += widget_height + vpadding;
22 }
23
24 const std::vector<int> buttonids = { INPUT_BUTTON_ACCEPT, INPUT_BUTTON_CANCEL };
25 const std::vector<std::string> buttonlabels = { "accept", "cancel" };
26 std::ignore = _buttons.populate(
27 _renderer, buttonlabels, buttonids, widget_width, static_cast<Sint32>(total_height),
28 static_cast<Sint32>(widget_width / 2), static_cast<Sint32>(widget_height));
29 _buttons.set_highlight(0);
30 }
31}
32
33SdlSelectList::~SdlSelectList() = default;
34
35int SdlSelectList::run()
36{
37 int res = -2;
38 ssize_t CurrentActiveTextInput = 0;
39 bool running = true;
40
41 if (!_window || !_renderer)
42 return -2;
43 try
44 {
45 while (running)
46 {
47 if (!update())
48 throw;
49
50 SDL_Event event = {};
51 if (!SDL_WaitEventTimeout(&event, 30))
52 continue;
53 do
54 {
55 switch (event.type)
56 {
57 case SDL_EVENT_KEY_DOWN:
58 switch (event.key.key)
59 {
60 case SDLK_UP:
61 case SDLK_BACKSPACE:
62 if (CurrentActiveTextInput > 0)
63 CurrentActiveTextInput--;
64 else if (_list.empty())
65 CurrentActiveTextInput = 0;
66 else
67 {
68 auto s = _list.size();
69 CurrentActiveTextInput =
70 WINPR_ASSERTING_INT_CAST(ssize_t, s) - 1;
71 }
72 break;
73 case SDLK_DOWN:
74 case SDLK_TAB:
75 if ((CurrentActiveTextInput < 0) || _list.empty())
76 CurrentActiveTextInput = 0;
77 else
78 {
79 auto s = _list.size();
80 CurrentActiveTextInput++;
81 if (s > 0)
82 {
83 CurrentActiveTextInput =
84 CurrentActiveTextInput %
85 WINPR_ASSERTING_INT_CAST(ssize_t, s);
86 }
87 }
88 break;
89 case SDLK_RETURN:
90 case SDLK_RETURN2:
91 case SDLK_KP_ENTER:
92 running = false;
93 res = static_cast<int>(CurrentActiveTextInput);
94 break;
95 case SDL_EVENT_WINDOW_OCCLUDED:
96 case SDL_EVENT_WINDOW_MINIMIZED:
97 case SDL_EVENT_WINDOW_CLOSE_REQUESTED:
98 case SDL_EVENT_TERMINATING:
99 case SDL_EVENT_WINDOW_DESTROYED:
100 case SDLK_ESCAPE:
101 running = false;
102 res = INPUT_BUTTON_CANCEL;
103 break;
104 default:
105 break;
106 }
107 break;
108 case SDL_EVENT_MOUSE_MOTION:
109 {
110 auto TextInputIndex = get_index(event.button);
111 reset_mouseover();
112 if (TextInputIndex >= 0)
113 {
114 auto& cur = _list.at(WINPR_ASSERTING_INT_CAST(size_t, TextInputIndex));
115 if (!cur.mouseover(true))
116 throw;
117 }
118
119 _buttons.set_mouseover(event.button.x, event.button.y);
120 }
121 break;
122 case SDL_EVENT_MOUSE_BUTTON_DOWN:
123 {
124 auto button = _buttons.get_selected(event.button);
125 if (button)
126 {
127 running = false;
128 if (button->id() == INPUT_BUTTON_CANCEL)
129 res = INPUT_BUTTON_CANCEL;
130 else
131 res = static_cast<int>(CurrentActiveTextInput);
132 }
133 else
134 {
135 CurrentActiveTextInput = get_index(event.button);
136 }
137 }
138 break;
139 case SDL_EVENT_QUIT:
140 res = INPUT_BUTTON_CANCEL;
141 running = false;
142 break;
143 default:
144 break;
145 }
146 } while (running && SDL_PollEvent(&event));
147
148 reset_highlight();
149 if (CurrentActiveTextInput >= 0)
150 {
151 auto& cur = _list.at(WINPR_ASSERTING_INT_CAST(size_t, CurrentActiveTextInput));
152 if (!cur.highlight(true))
153 throw;
154 }
155 }
156
157 SDL_PumpEvents();
158 SDL_FlushEvents(SDL_EVENT_FIRST, SDL_EVENT_USER);
159 }
160 catch (...)
161 {
162 return -1;
163 }
164 return res;
165}
166
167bool SdlSelectList::updateInternal()
168{
169 for (auto& cur : _list)
170 {
171 if (!cur.update())
172 return false;
173 }
174 return true;
175}
176
177ssize_t SdlSelectList::get_index(const SDL_MouseButtonEvent& button)
178{
179 const auto x = button.x;
180 const auto y = button.y;
181 for (size_t i = 0; i < _list.size(); i++)
182 {
183 auto& cur = _list.at(i);
184 auto r = cur.rect();
185
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);
188 }
189 return -1;
190}
191
192void SdlSelectList::reset_mouseover()
193{
194 for (auto& cur : _list)
195 {
196 cur.mouseover(false);
197 }
198}
199
200void SdlSelectList::reset_highlight()
201{
202 for (auto& cur : _list)
203 {
204 cur.highlight(false);
205 }
206}