mirror of
https://github.com/BanjoRecomp/BanjoRecomp
synced 2026-06-11 04:37:59 -04:00
207 lines
7.2 KiB
C++
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 });
|
|
}
|
|
};
|