From 57d0860008a6987ff3614f61117c2107421bff2d Mon Sep 17 00:00:00 2001 From: Paul Date: Wed, 17 Jul 2024 15:36:10 -0400 Subject: [PATCH] Add initial explicit layout class. Add ruled label (#96) All part of starting to restructure the bus screens in SCXT but useful for more than just that. --- include/sst/jucegui/components/Label.h | 2 +- include/sst/jucegui/components/RuledLabel.h | 95 ++++++++++++++++ include/sst/jucegui/layouts/ExplicitLayout.h | 110 +++++++++++++++++++ src/sst/jucegui/style/StyleSheet.cpp | 2 + 4 files changed, 208 insertions(+), 1 deletion(-) create mode 100644 include/sst/jucegui/components/RuledLabel.h create mode 100644 include/sst/jucegui/layouts/ExplicitLayout.h diff --git a/include/sst/jucegui/components/Label.h b/include/sst/jucegui/components/Label.h index 9268760..c7c61d7 100644 --- a/include/sst/jucegui/components/Label.h +++ b/include/sst/jucegui/components/Label.h @@ -74,7 +74,7 @@ struct Label : public juce::Component, public style::StyleConsumer, public style JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(Label) - private: + protected: std::string text; }; } // namespace sst::jucegui::components diff --git a/include/sst/jucegui/components/RuledLabel.h b/include/sst/jucegui/components/RuledLabel.h new file mode 100644 index 0000000..794336a --- /dev/null +++ b/include/sst/jucegui/components/RuledLabel.h @@ -0,0 +1,95 @@ +/* + * sst-jucegui - an open source library of juce widgets + * built by Surge Synth Team. + * + * Copyright 2023-2024, various authors, as described in the GitHub + * transaction log. + * + * sst-jucegui is released under the MIT license, as described + * by "LICENSE.md" in this repository. This means you may use this + * in commercial software if you are a JUCE Licensee. If you use JUCE + * in the open source / GPL3 context, your combined work must be + * released under GPL3. + * + * All source in sst-jucegui available at + * https://github.com/surge-synthesizer/sst-jucegui + */ + +#ifndef INCLUDE_SST_JUCEGUI_COMPONENTS_RULEDLABEL_H +#define INCLUDE_SST_JUCEGUI_COMPONENTS_RULEDLABEL_H + +#include +#include + +#include "Label.h" + +namespace sst::jucegui::components +{ +struct RuledLabel : public juce::Component, + public style::StyleConsumer, + public style::SettingsConsumer +{ + struct Styles : base_styles::BaseLabel, base_styles::Outlined + { + using sclass = style::StyleSheet::Class; + using sprop = style::StyleSheet::Property; + static constexpr sclass styleClass{"label"}; + + static void initialize() + { + style::StyleSheet::addClass(styleClass) + .withBaseClass(base_styles::BaseLabel::styleClass) + .withBaseClass(base_styles::Outlined::styleClass); + } + }; + + RuledLabel() : style::StyleConsumer(Styles::styleClass) { setAccessible(true); }; + ~RuledLabel() = default; + + void setText(const std::string &s) + { + text = s; + setTitle(s); + repaint(); + } + std::string getText() const { return text; } + + std::unique_ptr createAccessibilityHandler() override + { + return std::make_unique(*this, juce::AccessibilityRole::label); + } + + void paint(juce::Graphics &g) override + { + g.setColour(getColour(Styles::labelcolor)); + if (!isEnabled()) + g.setColour(getColour(Styles::labelcolor).withAlpha(0.5f)); + g.setFont(getFont(Styles::labelfont)); + g.drawText(text, getLocalBounds(), juce::Justification::centred); + + auto labelWidth = g.getCurrentFont().getStringWidth(text); + + auto ht = getLocalBounds(); + g.setColour(getColour(Styles::brightoutline)); + auto q = ht.toFloat() + .withWidth((ht.getWidth() - labelWidth - 2) / 2) + .translated(0, ht.getHeight() / 2.f - 0.5) + .withHeight(1) + .withTrimmedRight(4); + g.fillRect(q); + q = ht.toFloat() + .withWidth((ht.getWidth() - labelWidth - 2) / 2) + .translated((ht.getWidth() - labelWidth - 2) / 2 + labelWidth + 2, + ht.getHeight() / 2.f - 0.5) + .withHeight(1) + .withTrimmedLeft(4); + g.fillRect(q); + } + + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(RuledLabel) + + protected: + std::string text; +}; +} // namespace sst::jucegui::components +#endif // SHORTCIRCUITXT_RULEDLABEL_H diff --git a/include/sst/jucegui/layouts/ExplicitLayout.h b/include/sst/jucegui/layouts/ExplicitLayout.h new file mode 100644 index 0000000..7f87836 --- /dev/null +++ b/include/sst/jucegui/layouts/ExplicitLayout.h @@ -0,0 +1,110 @@ +/* + * sst-jucegui - an open source library of juce widgets + * built by Surge Synth Team. + * + * Copyright 2023-2024, various authors, as described in the GitHub + * transaction log. + * + * sst-jucegui is released under the MIT license, as described + * by "LICENSE.md" in this repository. This means you may use this + * in commercial software if you are a JUCE Licensee. If you use JUCE + * in the open source / GPL3 context, your combined work must be + * released under GPL3. + * + * All source in sst-jucegui available at + * https://github.com/surge-synthesizer/sst-jucegui + */ + +#ifndef INCLUDE_SST_JUCEGUI_LAYOUTS_EXPLICITLAYOUT_H +#define INCLUDE_SST_JUCEGUI_LAYOUTS_EXPLICITLAYOUT_H + +#include +namespace sst::jucegui::layout +{ +struct ExplicitLayout +{ + static constexpr int labelHeight{18}; + static constexpr int toggleSize{14}; + + ExplicitLayout() {} + + struct NamedPosition + { + NamedPosition() {} + NamedPosition(const std::string &n) : name(n) {} + + NamedPosition at(const juce::Rectangle &t) + { + auto res = *this; + res.rect = t; + return res; + } + + // Fractionally scale the 0...1 x and 0...h/w y + NamedPosition scaled(const juce::Rectangle &into, float x, float y, float w, float h) + { + auto res = *this; + res.rect = juce::Rectangle(into.getX() + x * into.getWidth(), + into.getY() + y * into.getWidth(), + w * into.getWidth(), h * into.getWidth()); + return res; + } + NamedPosition scaled(const juce::Rectangle &into, float x, float y, float w) + { + return scaled(into, x, y, w, w); + } + + std::string name; + juce::Rectangle rect{}; + }; + void addNamedPosition(const NamedPosition &n) { positions[n.name] = n; } + void addNamedPositionAndLabel(const NamedPosition &n) + { + addNamedPosition(n); + addLabelPositionTo(n.name); + } + void addPowerButtonPositionTo(const std::string &name, int w = toggleSize, int off = -1) + { + auto op = positionFor(name); + auto oh = op.getHeight(); + op = op.withTrimmedLeft(op.getWidth() - w).withTrimmedBottom(op.getHeight() - w); + if (off < 0) + off = w / 4; + op = op.translated(off, -off); + addNamedPosition(NamedPosition(name + ".power").at(op.toFloat())); + } + void addLabelPositionTo(const std::string &name) + { + auto op = positionFor(name); + auto oh = op.getHeight(); + op = op.withBottom(op.getBottom() + 18).withTrimmedTop(oh); + addNamedPosition(NamedPosition(name + ".label").at(op.toFloat())); + } + + juce::Rectangle positionFor(const std::string &s) const + { + auto p = positions.find(s); + if (p == positions.end()) + { + std::cout << "Unable to find name " << s << std::endl; + assert(false); + return {}; + } + return p->second.rect.toNearestIntEdges(); + } + + juce::Rectangle labelPositionFor(const std::string &s) const + { + return positionFor(s + ".label"); + } + + juce::Rectangle powerButtonPositionFor(const std::string &s) const + { + return positionFor(s + ".power"); + } + + std::unordered_map positions; +}; +} // namespace sst::jucegui::layout + +#endif // SHORTCIRCUITXT_EXPLICITLAYOUT_H diff --git a/src/sst/jucegui/style/StyleSheet.cpp b/src/sst/jucegui/style/StyleSheet.cpp index 6a1c49b..67187cf 100644 --- a/src/sst/jucegui/style/StyleSheet.cpp +++ b/src/sst/jucegui/style/StyleSheet.cpp @@ -34,6 +34,7 @@ #include #include #include +#include #include #include #include @@ -584,6 +585,7 @@ void StyleSheet::initializeStyleSheets(std::function userClassInitialize n::NamedPanel::Styles::initialize(); n::NamedPanelDivider::Styles::initialize(); n::Label::Styles::initialize(); + n::RuledLabel::Styles::initialize(); n::GlyphPainter::Styles::initialize(); n::WindowPanel::Styles::initialize();