[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 buttonhighlightcolor = { 0xcd, 0xca, 0x35, 0x60 };
static const SDL_Color buttonmouseovercolor = { 0x66, 0xff, 0x66, 0x60 };
static const SDL_Color buttonfontcolor = { 0xd1, 0xcf, 0xcd, 0xff };
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);
}
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)
{
assert(renderer);

View File

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

View File

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

View File

@ -1,6 +1,7 @@
#pragma once
#include <vector>
#include <stdint.h>
#include "sdl_button.hpp"
@ -11,10 +12,16 @@ class SdlButtonList
virtual ~SdlButtonList();
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);
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();
@ -24,4 +31,7 @@ class SdlButtonList
private:
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 input_height = labels.size() * (widget_heigth + vpadding) + vpadding;
const size_t total_height = input_height + widget_heigth;
_window = SDL_CreateWindow(title.c_str(), SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
total_width, total_height, 0);
_window = SDL_CreateWindow(
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)
{
widget_log_error(-1, "SDL_CreateWindow");
@ -42,9 +43,10 @@ SdlInputWidgetList::SdlInputWidgetList(const std::string& title,
_list.push_back(
{ _renderer, labels[x], initial[x], flags[x], x, widget_width, widget_heigth });
_buttons.populate(_renderer, buttonlabels, buttonids, static_cast<Sint32>(input_height),
static_cast<Sint32>(widget_width),
_buttons.populate(_renderer, buttonlabels, buttonids, total_width,
static_cast<Sint32>(input_height), static_cast<Sint32>(widget_width),
static_cast<Sint32>(widget_heigth));
_buttons.set_highlight(0);
}
}
}
@ -234,12 +236,7 @@ int SdlInputWidgetList::run(std::vector<std::string>& result)
throw;
}
auto button = _buttons.get_selected(event.button);
if (button)
{
if (!button->highlight(_renderer))
throw;
}
_buttons.set_mouseover(event.button.x, event.button.y);
}
break;
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;
_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)
{
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<std::string> buttonlabels = { "accept", "cancel" };
_buttons.populate(_renderer, buttonlabels, buttonids, static_cast<Sint32>(total_height),
static_cast<Sint32>(widget_width / 2),
static_cast<Sint32>(widget_height));
_buttons.populate(
_renderer, buttonlabels, buttonids, widget_width, static_cast<Sint32>(total_height),
static_cast<Sint32>(widget_width / 2), static_cast<Sint32>(widget_height));
_buttons.set_highlight(0);
}
}
}
@ -116,12 +119,7 @@ int SdlSelectList::run()
throw;
}
auto button = _buttons.get_selected(event.button);
if (button)
{
if (!button->highlight(_renderer))
throw;
}
_buttons.set_mouseover(event.button.x, event.button.y);
}
break;
case SDL_MOUSEBUTTONDOWN: