Merge pull request #13283 from jordan-woyak/button-indicators

DolphinQt: Replace MappingButton bold text with graphical indicators.
This commit is contained in:
Jordan Woyak 2025-01-22 13:22:33 -06:00 committed by GitHub
commit 4b4a58623b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 68 additions and 30 deletions

View File

@ -72,7 +72,7 @@ bool MappingButton::IsInput() const
return m_reference->IsInput(); return m_reference->IsInput();
} }
MappingButton::MappingButton(MappingWidget* parent, ControlReference* ref, bool indicator) MappingButton::MappingButton(MappingWidget* parent, ControlReference* ref)
: ElidedButton(RefToDisplayString(ref)), m_mapping_window(parent->GetParent()), m_reference(ref) : ElidedButton(RefToDisplayString(ref)), m_mapping_window(parent->GetParent()), m_reference(ref)
{ {
if (IsInput()) if (IsInput())
@ -87,9 +87,6 @@ MappingButton::MappingButton(MappingWidget* parent, ControlReference* ref, bool
connect(this, &MappingButton::clicked, this, &MappingButton::Clicked); connect(this, &MappingButton::clicked, this, &MappingButton::Clicked);
if (indicator)
connect(parent, &MappingWidget::Update, this, &MappingButton::UpdateIndicator);
connect(parent, &MappingWidget::ConfigChanged, this, &MappingButton::ConfigChanged); connect(parent, &MappingWidget::ConfigChanged, this, &MappingButton::ConfigChanged);
connect(this, &MappingButton::ConfigChanged, [this] { connect(this, &MappingButton::ConfigChanged, [this] {
setText(RefToDisplayString(m_reference)); setText(RefToDisplayString(m_reference));
@ -134,21 +131,6 @@ void MappingButton::Clear()
m_mapping_window->UnQueueInputDetection(this); m_mapping_window->UnQueueInputDetection(this);
} }
void MappingButton::UpdateIndicator()
{
QFont f = m_mapping_window->font();
if (isActiveWindow() && m_reference->IsInput() && m_reference->GetState<bool>() && !m_is_mapping)
f.setBold(true);
// If the expression has failed to parse, show it in italic.
// Some expressions still work even the failed to parse so don't prevent the GetState() above.
if (m_reference->GetParseStatus() == ciface::ExpressionParser::ParseStatus::SyntaxError)
f.setItalic(true);
setFont(f);
}
void MappingButton::StartMapping() void MappingButton::StartMapping()
{ {
// Focus just makes it more clear which button is currently being mapped. // Focus just makes it more clear which button is currently being mapped.

View File

@ -15,7 +15,7 @@ class MappingButton : public ElidedButton
{ {
Q_OBJECT Q_OBJECT
public: public:
MappingButton(MappingWidget* widget, ControlReference* ref, bool indicator); MappingButton(MappingWidget* widget, ControlReference* ref);
bool IsInput() const; bool IsInput() const;
ControlReference* GetControlReference(); ControlReference* GetControlReference();
@ -26,7 +26,6 @@ signals:
private: private:
void Clear(); void Clear();
void UpdateIndicator();
void AdvancedPressed(); void AdvancedPressed();
void Clicked(); void Clicked();

View File

@ -128,6 +128,37 @@ void MappingIndicator::AdjustGateColor(QColor* color)
color->setHsvF(color->hueF(), color->saturationF(), 1 - color->valueF()); color->setHsvF(color->hueF(), color->saturationF(), 1 - color->valueF());
} }
ButtonIndicator::ButtonIndicator(ControlReference* control_ref) : m_control_ref{control_ref}
{
setSizePolicy(QSizePolicy::Policy::Fixed, QSizePolicy::Policy::Fixed);
}
QSize ButtonIndicator::sizeHint() const
{
return QSize{INPUT_DOT_RADIUS + 2,
QFontMetrics(font()).boundingRect(QStringLiteral("[")).height()};
}
void ButtonIndicator::Draw()
{
QPainter p(this);
p.setBrush(GetBBoxBrush());
p.setPen(GetBBoxPen());
p.drawRect(QRect{{0, 0}, size() - QSize{1, 1}});
const auto input_value = std::clamp(m_control_ref->GetState<ControlState>(), 0.0, 1.0);
const bool is_pressed = std::lround(input_value) != 0;
QSizeF value_size = size() - QSizeF{2, 2};
value_size.setHeight(value_size.height() * input_value);
p.translate(0, height());
p.scale(1, -1);
p.setPen(Qt::NoPen);
p.setBrush(is_pressed ? GetAdjustedInputColor() : GetRawInputColor());
p.drawRect(QRectF{{1, 1}, value_size});
}
SquareIndicator::SquareIndicator() SquareIndicator::SquareIndicator()
{ {
// Additional pixel for border. // Additional pixel for border.

View File

@ -53,6 +53,17 @@ private:
Clock::time_point m_last_update = Clock::now(); Clock::time_point m_last_update = Clock::now();
}; };
class ButtonIndicator final : public MappingIndicator
{
public:
ButtonIndicator(ControlReference* control_ref);
private:
ControlReference* const m_control_ref;
QSize sizeHint() const override;
void Draw() override;
};
class SquareIndicator : public MappingIndicator class SquareIndicator : public MappingIndicator
{ {
protected: protected:

View File

@ -173,19 +173,19 @@ QGroupBox* MappingWidget::CreateGroupBox(const QString& name, ControllerEmu::Con
form_layout->insertRow(2, mouse_button); form_layout->insertRow(2, mouse_button);
using ControllerEmu::Cursor; using ControllerEmu::Cursor;
connect(mouse_button, &QCheckBox::clicked, [this, group = static_cast<Cursor*>(group)] { connect(mouse_button, &QCheckBox::clicked, [this, grp = static_cast<Cursor*>(group)] {
std::string default_device = g_controller_interface.GetDefaultDeviceString() + ":"; std::string default_device = g_controller_interface.GetDefaultDeviceString() + ":";
const std::string controller_device = GetController()->GetDefaultDevice().ToString() + ":"; const std::string controller_device = GetController()->GetDefaultDevice().ToString() + ":";
if (default_device == controller_device) if (default_device == controller_device)
{ {
default_device.clear(); default_device.clear();
} }
group->SetControlExpression(0, fmt::format("`{}Cursor Y-`", default_device)); grp->SetControlExpression(0, fmt::format("`{}Cursor Y-`", default_device));
group->SetControlExpression(1, fmt::format("`{}Cursor Y+`", default_device)); grp->SetControlExpression(1, fmt::format("`{}Cursor Y+`", default_device));
group->SetControlExpression(2, fmt::format("`{}Cursor X-`", default_device)); grp->SetControlExpression(2, fmt::format("`{}Cursor X-`", default_device));
group->SetControlExpression(3, fmt::format("`{}Cursor X+`", default_device)); grp->SetControlExpression(3, fmt::format("`{}Cursor X+`", default_device));
group->SetRelativeInput(false); grp->SetRelativeInput(false);
emit ConfigChanged(); emit ConfigChanged();
GetController()->UpdateReferences(g_controller_interface); GetController()->UpdateReferences(g_controller_interface);
@ -313,14 +313,29 @@ QGroupBox* MappingWidget::CreateControlsBox(const QString& name, ControllerEmu::
void MappingWidget::CreateControl(const ControllerEmu::Control* control, QFormLayout* layout, void MappingWidget::CreateControl(const ControllerEmu::Control* control, QFormLayout* layout,
bool indicator) bool indicator)
{ {
auto* button = new MappingButton(this, control->control_ref.get(), indicator); auto* const button = new MappingButton(this, control->control_ref.get());
button->setMinimumWidth(100); button->setMinimumWidth(100);
button->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); button->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
const bool translate = control->translate == ControllerEmu::Translatability::Translate; const bool translate = control->translate == ControllerEmu::Translatability::Translate;
const QString translated_name = const QString translated_name =
translate ? tr(control->ui_name.c_str()) : QString::fromStdString(control->ui_name); translate ? tr(control->ui_name.c_str()) : QString::fromStdString(control->ui_name);
layout->addRow(translated_name, button);
if (indicator && control->control_ref->IsInput())
{
auto* const button_indicator = new ButtonIndicator{control->control_ref.get()};
connect(this, &MappingWidget::Update, button_indicator, qOverload<>(&MappingIndicator::update));
auto* const hbox = new QHBoxLayout;
hbox->setSpacing(0);
hbox->addWidget(button_indicator);
hbox->addWidget(button);
layout->addRow(translated_name, hbox);
}
else
{
layout->addRow(translated_name, button);
}
} }
ControllerEmu::EmulatedController* MappingWidget::GetController() const ControllerEmu::EmulatedController* MappingWidget::GetController() const