Files
BanjoRecomp/src/ui/elements/ui_pill_button.cpp
T

207 lines
7.2 KiB
C++

#include "ui_pill_button.h"
#include "ui_label.h"
#include <cassert>
namespace recompui {
static constexpr float pill_padding = 16.0f;
PillButton::PillButton(Element *parent, const std::string &text, const std::string &svg_src, ButtonStyle style, PillButtonSize size) : Element(parent, Events(EventType::Click, EventType::Hover, EventType::Enable, EventType::Focus), "button") {
this->style = style;
this->size = size;
// Borders add width to the button, so this subtracts from the base size to bring it back to the expected size.
float float_size_internal = static_cast<float>(size) - (theme::border::width * 2.0f);
enable_focus();
set_display(Display::Flex);
set_align_items(AlignItems::Center);
set_justify_content(JustifyContent::Center);
set_min_width(float_size_internal);
set_width_auto();
set_padding_right(pill_padding);
set_padding_left(pill_padding);
set_height(float_size_internal);
set_min_height(float_size_internal);
set_max_height(float_size_internal);
set_border_width(theme::border::width);
set_border_radius(float_size_internal * 0.5f);
set_border_color(theme::color::Transparent);
set_cursor(Cursor::Pointer);
set_color(theme::color::TextDim);
set_tab_index(TabIndex::Auto);
set_opacity(1.0f);
hover_style.set_color(theme::color::Text);
focus_style.set_color(theme::color::Text);
disabled_style.set_color(theme::color::TextDim);
disabled_style.set_cursor(Cursor::None);
disabled_style.set_opacity(0.5f);
hover_disabled_style.set_color(theme::color::TextDim);
ContextId context = get_current_context();
bool has_svg = !svg_src.empty();
bool has_text = !text.empty();
if (has_svg) {
float icon_size = 0;
switch (size) {
case PillButtonSize::Mini:
icon_size = 16.0f;
break;
case PillButtonSize::Small:
icon_size = 24.0f;
break;
case PillButtonSize::Medium:
icon_size = 32.0f;
break;
case PillButtonSize::Large:
default:
icon_size = 32.0f;
break;
case PillButtonSize::XLarge:
icon_size = 40.0f;
break;
}
svg = context.create_element<Svg>(this, svg_src);
svg->set_width(icon_size);
svg->set_image_color(theme::color::TextDim);
}
if (has_text) {
auto label = context.create_element<Label>(this, text, LabelStyle::Normal);
if (has_svg) {
label->set_margin_left(8.0f);
}
}
apply_button_style(style);
}
void PillButton::process_event(const Event &e) {
switch (e.type) {
case EventType::Click:
if (is_enabled()) {
for (const auto &function : pressed_callbacks) {
function();
}
}
break;
case EventType::Hover:
{
bool hover_active = std::get<EventHover>(e.variant).active && is_enabled();
set_style_enabled(hover_state, hover_active);
if (svg != nullptr && !has_override_text_color) {
svg->set_image_color(hover_active ? theme::color::Text : theme::color::TextDim);
}
}
break;
case EventType::Enable:
{
bool enable_active = std::get<EventEnable>(e.variant).active;
set_style_enabled(disabled_state, !enable_active);
if (enable_active) {
set_cursor(Cursor::Pointer);
set_focusable(true);
if (svg != nullptr && !has_override_text_color) {
svg->set_image_color(theme::color::TextDim);
}
}
else {
set_cursor(Cursor::None);
set_focusable(false);
if (svg != nullptr && !has_override_text_color) {
svg->set_image_color(theme::color::TextDim);
}
}
}
break;
case EventType::Focus:
{
bool focus_active = std::get<EventFocus>(e.variant).active;
set_style_enabled(focus_state, focus_active);
if (svg != nullptr && !has_override_text_color) {
svg->set_image_color(focus_active ? theme::color::Text : theme::color::TextDim);
}
}
break;
case EventType::Update:
break;
default:
assert(false && "Unknown event type.");
break;
}
}
void PillButton::add_pressed_callback(std::function<void()> callback) {
pressed_callbacks.emplace_back(callback);
}
void PillButton::apply_button_style(ButtonStyle new_style) {
style = new_style;
switch (style) {
case ButtonStyle::Primary: {
apply_theme_style(theme::color::Primary);
break;
}
case ButtonStyle::Secondary: {
apply_theme_style(theme::color::Secondary);
break;
}
case ButtonStyle::Tertiary: {
apply_theme_style(theme::color::Text);
break;
}
case ButtonStyle::Success: {
apply_theme_style(theme::color::Success);
break;
}
case ButtonStyle::Warning: {
apply_theme_style(theme::color::Warning);
break;
}
case ButtonStyle::Danger: {
apply_theme_style(theme::color::Danger);
break;
}
case ButtonStyle::Basic: {
apply_theme_style(theme::color::Text, true);
break;
}
default:
assert(false && "Unknown button style.");
break;
}
}
void PillButton::apply_theme_style(recompui::theme::color color, bool is_basic, bool with_text) {
const uint8_t background_opacity = is_basic ? 0 : 13;
const uint8_t border_opacity = is_basic ? 0 : 204;
const uint8_t background_hover_opacity = 77;
const uint8_t border_hover_opacity = is_basic ? background_hover_opacity : 255;
has_override_text_color = with_text;
set_border_color(color, border_opacity);
set_background_color(color, background_opacity);
hover_style.set_border_color(color, border_hover_opacity);
hover_style.set_background_color(color, background_hover_opacity);
focus_style.set_border_color(color, border_hover_opacity);
focus_style.set_background_color(color, background_hover_opacity);
if (with_text) {
set_color(color);
if (svg != nullptr) {
svg->set_image_color(color);
}
}
add_style(&hover_style, hover_state);
add_style(&focus_style, focus_state);
add_style(&disabled_style, disabled_state);
add_style(&hover_disabled_style, { hover_state, disabled_state });
}
};