Files
rpcs3/rpcs3/Emu/RSX/Overlays/overlay_select.cpp
T

226 lines
5.6 KiB
C++

#include "stdafx.h"
#include "overlay_select.h"
namespace rsx::overlays
{
constexpr u16 max_dropdown_arrow_dimension = 12;
constexpr u16 dropdown_arrow_spacing = 4;
constexpr u16 dropdown_pack_padding = 6;
select_popup::select_popup(u16 w, u16 h)
: list_view(w, h, false)
{
hide_prompt_buttons();
hide_scroll_indicator();
pack_padding = dropdown_pack_padding;
}
select::select(u16 w, u16 h, const std::vector<std::string>& options)
{
std::vector<std::unique_ptr<overlay_element>> labels;
for (const auto& option : options)
{
std::unique_ptr<overlay_element> element = std::make_unique<overlays::label>();
labels.push_back(std::move(element));
auto label = dynamic_cast<overlays::label*>(labels.back().get());
label->set_padding(8, 0, 0, 0);
label->set_text(option);
label->set_font("Arial", 14);
label->set_padding(4);
label->back_color.a = 0.f;
label->auto_resize();
}
create_popup(labels);
set_padding(8, 10, 6, 12);
set_size(w, h);
select_item(0);
}
select::select(u16 w, u16 h, const std::vector<std::u32string>& options)
{
std::vector<std::unique_ptr<overlay_element>> labels;
for (const auto& option : options)
{
std::unique_ptr<overlay_element> element = std::make_unique<overlays::label>();
labels.push_back(std::move(element));
auto label = dynamic_cast<overlays::label*>(labels.back().get());
label->set_padding(8, 0, 0, 0);
label->set_unicode_text(option);
label->set_padding(4);
label->set_font("Arial", 14);
label->back_color.a = 0.f;
label->auto_resize();
}
create_popup(labels);
set_padding(8, 10, 6, 12);
set_size(w, h);
select_item(0);
}
select::select(u16 w, u16 h, std::vector<std::unique_ptr<overlay_element>>& options)
{
create_popup(options);
set_padding(8, 10, 6, 12);
set_size(w, h);
select_item(0);
}
void select::create_popup(std::vector<std::unique_ptr<overlay_element>>& options)
{
u16 max_w = 0;
u16 max_h = 0;
for (const auto& option : options)
{
max_w = std::max(max_w, option->w);
max_h += option->h + dropdown_pack_padding;
}
m_popup = std::make_unique<select_popup>(max_w, max_h + dropdown_pack_padding + 4);
m_popup->back_color = color4f(0.3f, 0.3f, 0.3f, 1.0f);
for (auto& option : options)
{
m_popup->add_entry(option);
}
}
void select::auto_resize()
{
u16 _h = max_dropdown_arrow_dimension; // Minimum arrow dimension
if (m_label)
{
_h = std::max(_h, m_label->h);
}
// Compute length of longest entry
u16 text_w = 0, text_h = 0;
for (auto& option : m_popup->m_items)
{
if (option->text.empty())
{
continue;
}
u16 tw = 0, th = 0;
option->measure_text(tw, th, true);
text_w = std::max<u16>(text_w, tw);
text_h = std::max<u16>(text_h, th);
}
_h = std::max<u16>(_h, text_h);
_h += padding_top + padding_bottom;
if (text_w == 0)
{
// Avoid using auto_resize with manually generated options list
text_w = m_popup->w;
}
u16 _w = text_w + dropdown_arrow_spacing + std::max<u16>(_h / 2, max_dropdown_arrow_dimension); // Enough to fit longest string + space for the arrow and padding
_w += padding_left + padding_right;
set_size(_w, _h);
}
void select::set_size(u16 w, u16 h)
{
clear_items();
if (const u16 min_x = (padding_left + padding_right + max_dropdown_arrow_dimension + (2 * dropdown_arrow_spacing)); w < min_x)
{
w = min_x;
}
if (const u16 min_y = (padding_top + padding_bottom + 16); h < min_y)
{
h = min_y;
}
box_layout::set_size(w, h);
auto background = std::make_unique<rounded_rect>();
background->set_size(w, h);
background->radius = std::min(h / 4, 5);
background->back_color = color4f(0.3f, 0.3f, 0.3f, 1.0f);
const u16 arrow_size = std::min<u16>(h / 2, max_dropdown_arrow_dimension);
auto arrow = std::make_unique<arrow_down>();
arrow->set_size(arrow_size, arrow_size);
arrow->back_color = color4f(0.8f, 0.8f, 0.8f, 1.f);
auto textfield = std::make_unique<label>();
textfield->set_font("Arial", 14);
textfield->align_text(text_align::left);
textfield->back_color.a = 0.f;
// Stretch the textfield
textfield->set_size(w - arrow->w - padding_left - padding_right - dropdown_arrow_spacing, h);
// Center align the arrow vertically to align with the text
if (textfield->h > arrow->h)
{
arrow->set_pos(0, textfield->compute_vertically_centered(arrow.get()));
arrow->y = std::max<u16>(arrow->y, padding_top) - padding_top;
}
// Align items using a container
auto packer = std::make_unique<horizontal_layout>();
packer->set_pos(padding_left, padding_top);
m_label = packer->add_element(textfield);
packer->add_spacer(dropdown_arrow_spacing);
packer->add_element(arrow);
// Pack
add_element(background);
add_element(packer);
// Extend the popup's width
m_popup->set_size(w, m_popup->h);
update_text();
}
void select::select_item(int selection)
{
m_popup->select_entry(selection);
update_text();
}
void select::update_text()
{
if (m_popup->get_selected_index() < 0)
{
return;
}
auto element = m_popup->get_selected_entry();
m_label->set_unicode_text(element->text);
m_label->auto_resize();
m_is_compiled = false;
}
compiled_resource& select::get_compiled()
{
if (is_compiled())
{
return compiled_resources;
}
compiled_resources.clear();
if (!is_visible())
{
m_is_compiled = true;
return compiled_resources;
}
box_layout::get_compiled();
m_is_compiled = true;
return compiled_resources;
}
}