[client,sdl] improve dialog button highlighting

move state to buttons or button list
This commit is contained in:
Armin Novak 2023-12-16 17:53:35 +01:00 committed by akallabeth
parent e6384c06c2
commit a8eaf2a38d
6 changed files with 90 additions and 25 deletions

View File

@ -24,6 +24,7 @@
static const SDL_Color buttonbackgroundcolor = { 0x69, 0x66, 0x63, 0xff }; static const SDL_Color buttonbackgroundcolor = { 0x69, 0x66, 0x63, 0xff };
static const SDL_Color buttonhighlightcolor = { 0xcd, 0xca, 0x35, 0x60 }; static const SDL_Color buttonhighlightcolor = { 0xcd, 0xca, 0x35, 0x60 };
static const SDL_Color buttonmouseovercolor = { 0x66, 0xff, 0x66, 0x60 };
static const SDL_Color buttonfontcolor = { 0xd1, 0xcf, 0xcd, 0xff }; static const SDL_Color buttonfontcolor = { 0xd1, 0xcf, 0xcd, 0xff };
SdlButton::SdlButton(SDL_Renderer* renderer, const std::string& label, int id, const SDL_Rect& rect) SdlButton::SdlButton(SDL_Renderer* renderer, const std::string& label, int id, const SDL_Rect& rect)
@ -53,6 +54,14 @@ bool SdlButton::highlight(SDL_Renderer* renderer)
return update_text(renderer, _name, buttonfontcolor); return update_text(renderer, _name, buttonfontcolor);
} }
bool SdlButton::mouseover(SDL_Renderer* renderer)
{
std::vector<SDL_Color> colors = { buttonbackgroundcolor, buttonmouseovercolor };
if (!fill(renderer, colors))
return false;
return update_text(renderer, _name, buttonfontcolor);
}
bool SdlButton::update(SDL_Renderer* renderer) bool SdlButton::update(SDL_Renderer* renderer)
{ {
assert(renderer); assert(renderer);

View File

@ -12,6 +12,7 @@ class SdlButton : public SdlWidget
virtual ~SdlButton() override; virtual ~SdlButton() override;
bool highlight(SDL_Renderer* renderer); bool highlight(SDL_Renderer* renderer);
bool mouseover(SDL_Renderer* renderer);
bool update(SDL_Renderer* renderer); bool update(SDL_Renderer* renderer);
int id() const; int id() const;

View File

@ -1,4 +1,5 @@
#include <assert.h> #include <assert.h>
#include <algorithm>
#include "sdl_buttons.hpp" #include "sdl_buttons.hpp"
@ -9,8 +10,8 @@ SdlButtonList::SdlButtonList()
} }
bool SdlButtonList::populate(SDL_Renderer* renderer, const std::vector<std::string>& labels, bool SdlButtonList::populate(SDL_Renderer* renderer, const std::vector<std::string>& labels,
const std::vector<int>& ids, Sint32 offsetY, Sint32 width, const std::vector<int>& ids, Sint32 total_width, Sint32 offsetY,
Sint32 height) Sint32 width, Sint32 height)
{ {
assert(renderer); assert(renderer);
assert(width >= 0); assert(width >= 0);
@ -18,10 +19,12 @@ bool SdlButtonList::populate(SDL_Renderer* renderer, const std::vector<std::stri
assert(labels.size() == ids.size()); assert(labels.size() == ids.size());
_list.clear(); _list.clear();
size_t button_width = ids.size() * (width + hpadding) + hpadding;
size_t offsetX = total_width - std::min<size_t>(total_width, button_width);
for (size_t x = 0; x < ids.size(); x++) for (size_t x = 0; x < ids.size(); x++)
{ {
const size_t offsetX = x * (static_cast<size_t>(width) + hpadding); const size_t curOffsetX = offsetX + x * (static_cast<size_t>(width) + hpadding);
const SDL_Rect rect = { static_cast<int>(offsetX), offsetY, width, height }; const SDL_Rect rect = { static_cast<int>(curOffsetX), offsetY, width, height };
_list.push_back({ renderer, labels[x], ids[x], rect }); _list.push_back({ renderer, labels[x], ids[x], rect });
} }
return true; return true;
@ -36,6 +39,11 @@ SdlButton* SdlButtonList::get_selected(const SDL_MouseButtonEvent& button)
const Sint32 x = button.x; const Sint32 x = button.x;
const Sint32 y = button.y; const Sint32 y = button.y;
return get_selected(x, y);
}
SdlButton* SdlButtonList::get_selected(Sint32 x, Sint32 y)
{
for (auto& btn : _list) for (auto& btn : _list)
{ {
auto r = btn.rect(); auto r = btn.rect();
@ -45,9 +53,45 @@ SdlButton* SdlButtonList::get_selected(const SDL_MouseButtonEvent& button)
return nullptr; return nullptr;
} }
bool SdlButtonList::set_highlight_next(bool reset)
{
if (reset)
_highlighted = nullptr;
else
{
auto next = _highlight_index++;
_highlight_index %= _list.size();
auto& element = _list[next];
_highlighted = &element;
}
return true;
}
bool SdlButtonList::set_highlight(size_t index)
{
if (index >= _list.size())
{
_highlighted = nullptr;
return false;
}
auto& element = _list[index];
_highlighted = &element;
_highlight_index = ++index % _list.size();
return true;
}
bool SdlButtonList::set_mouseover(Sint32 x, Sint32 y)
{
_mouseover = get_selected(x, y);
return _mouseover != nullptr;
}
void SdlButtonList::clear() void SdlButtonList::clear()
{ {
_list.clear(); _list.clear();
_mouseover = nullptr;
_highlighted = nullptr;
_highlight_index = 0;
} }
bool SdlButtonList::update(SDL_Renderer* renderer) bool SdlButtonList::update(SDL_Renderer* renderer)
@ -59,5 +103,11 @@ bool SdlButtonList::update(SDL_Renderer* renderer)
if (!btn.update(renderer)) if (!btn.update(renderer))
return false; return false;
} }
if (_highlighted)
_highlighted->highlight(renderer);
if (_mouseover)
_mouseover->mouseover(renderer);
return true; return true;
} }

View File

@ -1,6 +1,7 @@
#pragma once #pragma once
#include <vector> #include <vector>
#include <stdint.h>
#include "sdl_button.hpp" #include "sdl_button.hpp"
@ -11,10 +12,16 @@ class SdlButtonList
virtual ~SdlButtonList(); virtual ~SdlButtonList();
bool populate(SDL_Renderer* renderer, const std::vector<std::string>& labels, bool populate(SDL_Renderer* renderer, const std::vector<std::string>& labels,
const std::vector<int>& ids, Sint32 offsetY, Sint32 width, Sint32 heigth); const std::vector<int>& ids, Sint32 total_width, Sint32 offsetY, Sint32 width,
Sint32 heigth);
bool update(SDL_Renderer* renderer); bool update(SDL_Renderer* renderer);
SdlButton* get_selected(const SDL_MouseButtonEvent& button); SdlButton* get_selected(const SDL_MouseButtonEvent& button);
SdlButton* get_selected(Sint32 x, Sint32 y);
bool set_highlight_next(bool reset = false);
bool set_highlight(size_t index);
bool set_mouseover(Sint32 x, Sint32 y);
void clear(); void clear();
@ -24,4 +31,7 @@ class SdlButtonList
private: private:
std::vector<SdlButton> _list; std::vector<SdlButton> _list;
SdlButton* _highlighted = nullptr;
size_t _highlight_index = 0;
SdlButton* _mouseover = nullptr;
}; };

View File

@ -22,8 +22,9 @@ SdlInputWidgetList::SdlInputWidgetList(const std::string& title,
const size_t total_width = widget_width + widget_width; const size_t total_width = widget_width + widget_width;
const size_t input_height = labels.size() * (widget_heigth + vpadding) + vpadding; const size_t input_height = labels.size() * (widget_heigth + vpadding) + vpadding;
const size_t total_height = input_height + widget_heigth; const size_t total_height = input_height + widget_heigth;
_window = SDL_CreateWindow(title.c_str(), SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, _window = SDL_CreateWindow(
total_width, total_height, 0); title.c_str(), SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, total_width, total_height,
SDL_WINDOW_ALLOW_HIGHDPI | SDL_WINDOW_MOUSE_FOCUS | SDL_WINDOW_INPUT_FOCUS);
if (_window == nullptr) if (_window == nullptr)
{ {
widget_log_error(-1, "SDL_CreateWindow"); widget_log_error(-1, "SDL_CreateWindow");
@ -42,9 +43,10 @@ SdlInputWidgetList::SdlInputWidgetList(const std::string& title,
_list.push_back( _list.push_back(
{ _renderer, labels[x], initial[x], flags[x], x, widget_width, widget_heigth }); { _renderer, labels[x], initial[x], flags[x], x, widget_width, widget_heigth });
_buttons.populate(_renderer, buttonlabels, buttonids, static_cast<Sint32>(input_height), _buttons.populate(_renderer, buttonlabels, buttonids, total_width,
static_cast<Sint32>(widget_width), static_cast<Sint32>(input_height), static_cast<Sint32>(widget_width),
static_cast<Sint32>(widget_heigth)); static_cast<Sint32>(widget_heigth));
_buttons.set_highlight(0);
} }
} }
} }
@ -234,12 +236,7 @@ int SdlInputWidgetList::run(std::vector<std::string>& result)
throw; throw;
} }
auto button = _buttons.get_selected(event.button); _buttons.set_mouseover(event.button.x, event.button.y);
if (button)
{
if (!button->highlight(_renderer))
throw;
}
} }
break; break;
case SDL_MOUSEBUTTONDOWN: case SDL_MOUSEBUTTONDOWN:

View File

@ -10,7 +10,9 @@ SdlSelectList::SdlSelectList(const std::string& title, const std::vector<std::st
const size_t total_height = labels.size() * (widget_height + vpadding) + vpadding; const size_t total_height = labels.size() * (widget_height + vpadding) + vpadding;
_window = SDL_CreateWindow(title.c_str(), SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, _window = SDL_CreateWindow(title.c_str(), SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
widget_width, total_height + widget_height, 0); widget_width, total_height + widget_height,
SDL_WINDOW_ALLOW_HIGHDPI | SDL_WINDOW_MOUSE_FOCUS |
SDL_WINDOW_INPUT_FOCUS);
if (_window == nullptr) if (_window == nullptr)
{ {
widget_log_error(-1, "SDL_CreateWindow"); widget_log_error(-1, "SDL_CreateWindow");
@ -33,9 +35,10 @@ SdlSelectList::SdlSelectList(const std::string& title, const std::vector<std::st
const std::vector<int> buttonids = { INPUT_BUTTON_ACCEPT, INPUT_BUTTON_CANCEL }; const std::vector<int> buttonids = { INPUT_BUTTON_ACCEPT, INPUT_BUTTON_CANCEL };
const std::vector<std::string> buttonlabels = { "accept", "cancel" }; const std::vector<std::string> buttonlabels = { "accept", "cancel" };
_buttons.populate(_renderer, buttonlabels, buttonids, static_cast<Sint32>(total_height), _buttons.populate(
static_cast<Sint32>(widget_width / 2), _renderer, buttonlabels, buttonids, widget_width, static_cast<Sint32>(total_height),
static_cast<Sint32>(widget_height)); static_cast<Sint32>(widget_width / 2), static_cast<Sint32>(widget_height));
_buttons.set_highlight(0);
} }
} }
} }
@ -116,12 +119,7 @@ int SdlSelectList::run()
throw; throw;
} }
auto button = _buttons.get_selected(event.button); _buttons.set_mouseover(event.button.x, event.button.y);
if (button)
{
if (!button->highlight(_renderer))
throw;
}
} }
break; break;
case SDL_MOUSEBUTTONDOWN: case SDL_MOUSEBUTTONDOWN: