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 _buttons.populate(_renderer, buttonlabels, buttonids, widget_width,
27 static_cast<Sint32>(total_height), static_cast<Sint32>(widget_width / 2),
28 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_WaitEvent(&event))
52 throw;
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 SDLK_ESCAPE:
96 running = false;
97 res = INPUT_BUTTON_CANCEL;
98 break;
99 default:
100 break;
101 }
102 break;
103 case SDL_EVENT_MOUSE_MOTION:
104 {
105 auto TextInputIndex = get_index(event.button);
106 reset_mouseover();
107 if (TextInputIndex >= 0)
108 {
109 auto& cur = _list[WINPR_ASSERTING_INT_CAST(size_t, TextInputIndex)];
110 if (!cur.mouseover(true))
111 throw;
112 }
113
114 _buttons.set_mouseover(event.button.x, event.button.y);
115 }
116 break;
117 case SDL_EVENT_MOUSE_BUTTON_DOWN:
118 {
119 auto button = _buttons.get_selected(event.button);
120 if (button)
121 {
122 running = false;
123 if (button->id() == INPUT_BUTTON_CANCEL)
124 res = INPUT_BUTTON_CANCEL;
125 else
126 res = static_cast<int>(CurrentActiveTextInput);
127 }
128 else
129 {
130 CurrentActiveTextInput = get_index(event.button);
131 }
132 }
133 break;
134 case SDL_EVENT_QUIT:
135 res = INPUT_BUTTON_CANCEL;
136 running = false;
137 break;
138 default:
139 break;
140 }
141 } while (SDL_PollEvent(&event));
142 reset_highlight();
143 if (CurrentActiveTextInput >= 0)
144 {
145 auto& cur = _list[WINPR_ASSERTING_INT_CAST(size_t, CurrentActiveTextInput)];
146 if (!cur.highlight(true))
147 throw;
148 }
149
150 update();
151 }
152 }
153 catch (...)
154 {
155 return -1;
156 }
157 return res;
158}
159
160bool SdlSelectList::updateInternal()
161{
162 for (auto& cur : _list)
163 {
164 if (!cur.update())
165 return false;
166 }
167 return true;
168}
169
170ssize_t SdlSelectList::get_index(const SDL_MouseButtonEvent& button)
171{
172 const auto x = button.x;
173 const auto y = button.y;
174 for (size_t i = 0; i < _list.size(); i++)
175 {
176 auto& cur = _list[i];
177 auto r = cur.rect();
178
179 if ((x >= r.x) && (x <= r.x + r.w) && (y >= r.y) && (y <= r.y + r.h))
180 return WINPR_ASSERTING_INT_CAST(ssize_t, i);
181 }
182 return -1;
183}
184
185void SdlSelectList::reset_mouseover()
186{
187 for (auto& cur : _list)
188 {
189 cur.mouseover(false);
190 }
191}
192
193void SdlSelectList::reset_highlight()
194{
195 for (auto& cur : _list)
196 {
197 cur.highlight(false);
198 }
199}