mirror of
https://github.com/RPCS3/rpcs3.git
synced 2026-04-07 23:45:04 +00:00
182 lines
5.6 KiB
C++
182 lines
5.6 KiB
C++
#include "stdafx.h"
|
|
#include "overlay_slider.h"
|
|
|
|
namespace rsx::overlays
|
|
{
|
|
constexpr u16 slider_rail_thickness = 5;
|
|
constexpr u16 slider_cover_thickness = 6;
|
|
constexpr u16 slider_indicator_radius = 8;
|
|
constexpr u16 slider_indicator_dia = slider_indicator_radius * 2;
|
|
constexpr const char* slider_label_font_family = "Arial";
|
|
constexpr int slider_label_font_size = 10;
|
|
|
|
void slider::init()
|
|
{
|
|
back_color = color4f(0.3f, 0.3f, 0.3f, 0.f);
|
|
fore_color = color4f(0.5647f, 0.7922f, 0.9765f, 1.f);
|
|
auto_resize = false;
|
|
m_current_value = m_min_value;
|
|
}
|
|
|
|
void slider::set_size(u16 w, u16 h)
|
|
{
|
|
horizontal_layout::set_size(w, h);
|
|
clear_items();
|
|
|
|
// Clamp the height
|
|
h = std::max<u16>(h, 8);
|
|
|
|
// Base components
|
|
auto background = std::make_unique<rounded_rect>();
|
|
auto foreground = std::make_unique<rounded_rect>();
|
|
auto indicator = std::make_unique<ellipse>();
|
|
auto value_label = std::make_unique<label>();
|
|
auto min_label = std::make_unique<label>();
|
|
auto max_label = std::make_unique<label>();
|
|
|
|
indicator->radius = slider_indicator_radius;
|
|
indicator->set_size(slider_indicator_dia + 2, slider_indicator_dia + 2);
|
|
indicator->set_padding(2);
|
|
indicator->set_pos(0, -2);
|
|
indicator->back_color = color4f(1.f);
|
|
|
|
background->radius = slider_rail_thickness / 2;
|
|
background->back_color = this->back_color;
|
|
background->back_color.a = 1.f;
|
|
background->set_size(w, slider_rail_thickness);
|
|
background->set_pos(0, (slider_indicator_dia / 2) - background->radius);
|
|
|
|
foreground->radius = slider_cover_thickness / 2;
|
|
foreground->back_color = this->fore_color;
|
|
foreground->set_size(0, slider_cover_thickness);
|
|
foreground->set_pos(0, (slider_indicator_dia / 2) - foreground->radius);
|
|
|
|
value_label->set_padding(2);
|
|
value_label->set_font(slider_label_font_family, slider_label_font_size);
|
|
value_label->set_text(m_formatter(m_current_value));
|
|
value_label->auto_resize();
|
|
value_label->back_color.a = 0.f;
|
|
value_label->fore_color = color4f(1.f);
|
|
|
|
min_label->fore_color = color4f(0.75f, 0.75f, 0.75f, 1.f);
|
|
min_label->back_color.a = 0.f;
|
|
min_label->set_font(slider_label_font_family, slider_label_font_size);
|
|
min_label->set_text(m_formatter(m_min_value));
|
|
min_label->set_pos(0, (value_label->h / 2) + slider_indicator_radius + 8); // Margin = Text Height + Indicator Rad (gets to half point) - Text Height / 2 (Offset back to box origin)
|
|
min_label->auto_resize();
|
|
|
|
max_label->fore_color = color4f(0.75f, 0.75f, 0.75f, 1.f);
|
|
max_label->back_color.a = 0.f;
|
|
max_label->set_font(slider_label_font_family, slider_label_font_size);
|
|
max_label->set_text(m_formatter(m_max_value));
|
|
max_label->set_pos(0, (value_label->h / 2) + slider_indicator_radius + 8); // Margin
|
|
max_label->auto_resize();
|
|
|
|
const u16 horizontal_padding = slider_indicator_radius + 4;
|
|
|
|
if (m_show_labels)
|
|
{
|
|
const u16 unusable_space = max_label->w + min_label->w + (2 * horizontal_padding);
|
|
if (unusable_space < w)
|
|
{
|
|
background->w -= unusable_space;
|
|
foreground->w = unusable_space;
|
|
}
|
|
}
|
|
|
|
// Pack the slider part
|
|
auto slider_part = std::make_unique<box_layout>();
|
|
slider_part->set_size(background->w, 8);
|
|
m_rail_component = slider_part->add_element(background);
|
|
m_slider_component = slider_part->add_element(foreground);
|
|
m_indicator_component = slider_part->add_element(indicator);
|
|
|
|
// Middle part of the sandwich
|
|
auto stack_part = std::make_unique<vertical_layout>();
|
|
m_value_component = stack_part->add_element(value_label);
|
|
stack_part->add_spacer(8);
|
|
stack_part->add_element(slider_part);
|
|
|
|
if (m_show_labels)
|
|
{
|
|
// Assemble the sandwich
|
|
add_element(min_label);
|
|
add_spacer(horizontal_padding);
|
|
add_element(stack_part);
|
|
add_spacer(horizontal_padding);
|
|
add_element(max_label);
|
|
}
|
|
else
|
|
{
|
|
add_element(stack_part);
|
|
}
|
|
|
|
update_elements();
|
|
}
|
|
|
|
void slider::set_value(f64 value)
|
|
{
|
|
value = std::clamp(value, m_min_value, m_max_value);
|
|
if (value == m_current_value)
|
|
{
|
|
return;
|
|
}
|
|
|
|
m_current_value = value;
|
|
update_elements();
|
|
}
|
|
|
|
void slider::set_show_labels(bool show)
|
|
{
|
|
if (m_show_labels == show)
|
|
{
|
|
return;
|
|
}
|
|
|
|
m_show_labels = show;
|
|
set_size(w, h);
|
|
}
|
|
|
|
void slider::update_elements()
|
|
{
|
|
if (!m_slider_component || !m_value_component || !m_rail_component)
|
|
{
|
|
return;
|
|
}
|
|
|
|
const auto slider_w = (std::abs(m_current_value - m_min_value) * m_rail_component->w) / std::abs(m_max_value - m_min_value);
|
|
const auto slider_w16 = static_cast<u16>(std::floor(slider_w));
|
|
|
|
m_slider_component->set_size(slider_w16, m_slider_component->h);
|
|
m_indicator_component->set_pos(m_slider_component->x + slider_w16 - slider_indicator_radius, m_indicator_component->y);
|
|
|
|
m_value_component->set_text(m_formatter(m_current_value));
|
|
m_value_component->auto_resize();
|
|
|
|
// If the label would touch the end, flip it
|
|
u16 offset = (slider_w16 + m_value_component->w) >= m_rail_component->w ? m_value_component->w : 0;
|
|
m_value_component->set_pos(m_slider_component->x + slider_w16 - offset, m_value_component->y);
|
|
|
|
// Hide indicator when slider is completely empty or completely full
|
|
m_value_component->visible = (m_current_value != m_min_value) && (m_current_value != m_max_value);
|
|
}
|
|
|
|
void slider::set_value_format(std::function<std::string(f64)> formatter)
|
|
{
|
|
m_formatter = formatter;
|
|
set_size(w, h);
|
|
}
|
|
|
|
compiled_resource& slider::get_compiled()
|
|
{
|
|
if (is_compiled())
|
|
{
|
|
return compiled_resources;
|
|
}
|
|
|
|
horizontal_layout::get_compiled();
|
|
|
|
m_is_compiled = true;
|
|
return compiled_resources;
|
|
}
|
|
}
|