23#include <winpr/cast.h> 
   25#include "sdl_widget_list.hpp" 
   26#include "sdl_input_widget_pair_list.hpp" 
   28static const Uint32 vpadding = 5;
 
   30SdlInputWidgetPairList::SdlInputWidgetPairList(
const std::string& title,
 
   31                                               const std::vector<std::string>& labels,
 
   32                                               const std::vector<std::string>& initial,
 
   33                                               const std::vector<Uint32>& flags)
 
   35  assert(labels.size() == initial.size());
 
   36  assert(labels.size() == flags.size());
 
   37  const std::vector<int> buttonids = { INPUT_BUTTON_ACCEPT, INPUT_BUTTON_CANCEL };
 
   38  const std::vector<std::string> buttonlabels = { 
"accept", 
"cancel" };
 
   40  const size_t widget_width = 300;
 
   41  const size_t widget_heigth = 50;
 
   43  const size_t total_width = widget_width + widget_width;
 
   44  const size_t input_height = labels.size() * (widget_heigth + vpadding) + vpadding;
 
   45  const size_t total_height = input_height + widget_heigth;
 
   46  assert(total_width <= INT32_MAX);
 
   47  assert(total_height <= INT32_MAX);
 
   49  if (reset(title, total_width, total_height))
 
   51    for (
size_t x = 0; x < labels.size(); x++)
 
   54          _renderer, labels[x], initial[x], flags[x], x, widget_width, widget_heigth));
 
   55      _list.emplace_back(widget);
 
   58    _buttons.populate(_renderer, buttonlabels, buttonids, total_width,
 
   59                      static_cast<Sint32
>(input_height), 
static_cast<Sint32
>(widget_width),
 
   60                      static_cast<Sint32
>(widget_heigth));
 
   61    _buttons.set_highlight(0);
 
   65ssize_t SdlInputWidgetPairList::next(ssize_t current)
 
   68  auto val = 
static_cast<size_t>(current);
 
   72    if (iteration >= _list.size())
 
   86  } 
while (!valid(
static_cast<ssize_t
>(val)));
 
   87  return static_cast<ssize_t
>(val);
 
   90bool SdlInputWidgetPairList::valid(ssize_t current)
 const 
   94  auto s = 
static_cast<size_t>(current);
 
   95  if (s >= _list.size())
 
   97  return !_list[s]->readonly();
 
  100std::shared_ptr<SdlInputWidgetPair> SdlInputWidgetPairList::get(ssize_t index)
 
  104  auto s = 
static_cast<size_t>(index);
 
  105  if (s >= _list.size())
 
  110SdlInputWidgetPairList::~SdlInputWidgetPairList()
 
  116bool SdlInputWidgetPairList::updateInternal()
 
  118  for (
auto& btn : _list)
 
  129ssize_t SdlInputWidgetPairList::get_index(
const SDL_MouseButtonEvent& button)
 
  131  const auto x = button.x;
 
  132  const auto y = button.y;
 
  133  for (
size_t i = 0; i < _list.size(); i++)
 
  135    auto& cur = _list[i];
 
  136    auto r = cur->input_rect();
 
  138    if ((x >= r.x) && (x <= r.x + r.w) && (y >= r.y) && (y <= r.y + r.h))
 
  139      return WINPR_ASSERTING_INT_CAST(ssize_t, i);
 
  144int SdlInputWidgetPairList::run(std::vector<std::string>& result)
 
  147  ssize_t LastActiveTextInput = -1;
 
  148  ssize_t CurrentActiveTextInput = next(-1);
 
  150  if (!_window || !_renderer)
 
  153  if (!SDL_StartTextInput(_window.get()))
 
  164      SDL_Event 
event = {};
 
  165      if (!SDL_WaitEvent(&event))
 
  171          case SDL_EVENT_KEY_UP:
 
  173            switch (event.key.key)
 
  177                auto cur = get(CurrentActiveTextInput);
 
  180                  if ((event.key.mod & SDL_KMOD_CTRL) != 0)
 
  182                    if (!cur->set_str(
""))
 
  187                    if (!cur->remove_str(1))
 
  194                CurrentActiveTextInput = next(CurrentActiveTextInput);
 
  200                res = INPUT_BUTTON_ACCEPT;
 
  204                res = INPUT_BUTTON_CANCEL;
 
  207                if ((event.key.mod & SDL_KMOD_CTRL) != 0)
 
  209                  auto cur = get(CurrentActiveTextInput);
 
  212                    auto text = SDL_GetClipboardText();
 
  222          case SDL_EVENT_TEXT_INPUT:
 
  224            auto cur = get(CurrentActiveTextInput);
 
  227              if (!cur->append_str(event.text.text))
 
  232          case SDL_EVENT_MOUSE_MOTION:
 
  234            auto TextInputIndex = get_index(event.button);
 
  235            for (
auto& cur : _list)
 
  237              if (!cur->set_mouseover(
false))
 
  240            if (TextInputIndex >= 0)
 
  242              auto& cur = _list[
static_cast<size_t>(TextInputIndex)];
 
  243              if (!cur->set_mouseover(
true))
 
  247            _buttons.set_mouseover(event.button.x, event.button.y);
 
  250          case SDL_EVENT_MOUSE_BUTTON_DOWN:
 
  252            auto val = get_index(event.button);
 
  254              CurrentActiveTextInput = val;
 
  256            auto button = _buttons.get_selected(event.button);
 
  260              if (button->id() == INPUT_BUTTON_CANCEL)
 
  261                res = INPUT_BUTTON_CANCEL;
 
  263                res = INPUT_BUTTON_ACCEPT;
 
  268            res = INPUT_BUTTON_CANCEL;
 
  274      } 
while (SDL_PollEvent(&event));
 
  276      if (LastActiveTextInput != CurrentActiveTextInput)
 
  278        LastActiveTextInput = CurrentActiveTextInput;
 
  281      for (
auto& cur : _list)
 
  283        if (!cur->set_highlight(
false))
 
  286      auto cur = get(CurrentActiveTextInput);
 
  289        if (!cur->set_highlight(
true))
 
  293      auto rc = SDL_RenderPresent(_renderer.get());
 
  296        SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, 
"[%s] SDL_RenderPresent failed with %s",
 
  297                    __func__, SDL_GetError());
 
  301    for (
auto& cur : _list)
 
  302      result.push_back(cur->value());
 
  308  if (!SDL_StopTextInput(_window.get()))