From e7c9a72281223a206a0cad917aa943abeddbb00c Mon Sep 17 00:00:00 2001 From: Paul Walker Date: Wed, 28 Aug 2024 09:04:56 -0400 Subject: [PATCH] Tooltip gets a row data structure for clever stuff if you want --- include/sst/jucegui/components/ToolTip.h | 29 +++++++- src/sst/jucegui/components/ToolTip.cpp | 87 +++++++++++++++++++++--- 2 files changed, 105 insertions(+), 11 deletions(-) diff --git a/include/sst/jucegui/components/ToolTip.h b/include/sst/jucegui/components/ToolTip.h index ce1ab5e..7df6cb3 100644 --- a/include/sst/jucegui/components/ToolTip.h +++ b/include/sst/jucegui/components/ToolTip.h @@ -18,9 +18,11 @@ #ifndef INCLUDE_SST_JUCEGUI_COMPONENTS_TOOLTIP_H #define INCLUDE_SST_JUCEGUI_COMPONENTS_TOOLTIP_H +#include #include #include "sst/jucegui/style/StyleAndSettingsConsumer.h" #include "sst/jucegui/components/BaseStyles.h" +#include "GlyphPainter.h" namespace sst::jucegui::components { @@ -46,7 +48,27 @@ struct ToolTip : juce::Component, sst::jucegui::style::StyleConsumer ToolTip(); void paint(juce::Graphics &g); + struct Row + { + std::optional rowLeadingGlyph{std::nullopt}; + std::string leftAlignText{}, centerAlignText{}, rightAlignText{}; + bool leftIsMonospace{false}, centerIsMonospace{false}, rightIsMonospace{false}; + + explicit Row(const std::string s) : leftAlignText(s) {} + Row() {} + }; + void setTooltipTitleAndData(const std::string &t, const std::vector &d) + { + tooltipTitle = t; + tooltipData.clear(); + std::transform(d.begin(), d.end(), std::back_inserter(tooltipData), + [](auto &s) { return Row(s); }); + resetSizeFromData(); + repaint(); + } + + void setTooltipTitleAndData(const std::string &t, const std::vector &d) { tooltipTitle = t; tooltipData = d; @@ -55,8 +77,13 @@ struct ToolTip : juce::Component, sst::jucegui::style::StyleConsumer } void resetSizeFromData(); + + int getRowHeight(int row); + int getRowWidth(int row); + static constexpr size_t glyphSize{18}; + std::string tooltipTitle{}; - std::vector tooltipData; + std::vector tooltipData; }; } // namespace sst::jucegui::components #endif // SHORTCIRCUITXT_TOOLTIP_H diff --git a/src/sst/jucegui/components/ToolTip.cpp b/src/sst/jucegui/components/ToolTip.cpp index 62ff95e..15ae2e4 100644 --- a/src/sst/jucegui/components/ToolTip.cpp +++ b/src/sst/jucegui/components/ToolTip.cpp @@ -57,12 +57,28 @@ void ToolTip::paint(juce::Graphics &g) rowHeight = df.getHeight() + rowPad; g.setFont(df); - bx = bx.translated(0, rowTitlePad); + bx = bx.translated(0, rowHeight + rowTitlePad); g.setColour(txt); - for (const auto &d : tooltipData) + for (auto i = 0; i < tooltipData.size(); ++i) { - bx = bx.translated(0, rowHeight); - g.drawText(d, bx, juce::Justification::centredLeft); + auto &row = tooltipData[i]; + auto rh = getRowHeight(i); + bx = bx.withHeight(rh); + + auto yp = bx.getY(); + auto txtbx = bx; + if (row.rowLeadingGlyph.has_value()) + { + GlyphPainter::paintGlyph(g, bx.withWidth(glyphSize), *(row.rowLeadingGlyph), txt); + txtbx = bx.withTrimmedLeft(glyphSize + 2); + } + g.setFont(row.leftIsMonospace ? df : f); + g.drawText(row.leftAlignText, txtbx, juce::Justification::centredLeft); + g.setFont(row.centerIsMonospace ? df : f); + g.drawText(row.centerAlignText, txtbx, juce::Justification::centred); + g.setFont(row.rightIsMonospace ? df : f); + g.drawText(row.rightAlignText, txtbx, juce::Justification::centredRight); + bx = bx.translated(0, rh + rowPad); } } @@ -73,15 +89,66 @@ void ToolTip::resetSizeFromData() auto maxw = std::max(f.getStringWidthFloat(tooltipTitle), 60.f); auto df = style()->getFont(Styles::styleClass, Styles::datafont); - auto drowHeight = df.getHeight() + rowPad; - - for (const auto &d : tooltipData) - maxw = std::max(maxw, df.getStringWidthFloat(d)); + auto drowHeight = 0.f; + for (auto i = 0; i < tooltipData.size(); ++i) + { + drowHeight += getRowHeight(i) + rowPad; + maxw = std::max(maxw, (float)getRowWidth(i)); // FIX + } // round to nearest 20 to avoid jitters maxw = std::ceil(maxw / 20.f) * 20; - setSize(maxw + 2 * margin, - 2 * margin + rowHeight + drowHeight * tooltipData.size() + rowTitlePad); + setSize(maxw + 2 * margin, 2 * margin + rowHeight + drowHeight + rowTitlePad); +} + +int ToolTip::getRowHeight(int row) +{ + auto f = style()->getFont(Styles::styleClass, Styles::labelfont); + auto df = style()->getFont(Styles::styleClass, Styles::datafont); + + if (tooltipData[row].centerIsMonospace && tooltipData[row].leftIsMonospace && + tooltipData[row].rightIsMonospace) + return df.getHeight(); + + if (!tooltipData[row].centerIsMonospace && !tooltipData[row].leftIsMonospace && + !tooltipData[row].rightIsMonospace) + return f.getHeight(); + + return std::max(f.getHeight(), df.getHeight()); } + +int ToolTip::getRowWidth(int ri) +{ + auto f = style()->getFont(Styles::styleClass, Styles::labelfont); + auto df = style()->getFont(Styles::styleClass, Styles::datafont); + + auto &row = tooltipData[ri]; + // Special case -just the text + if (!row.rowLeadingGlyph.has_value() && row.centerAlignText.empty() && + row.rightAlignText.empty()) + { + if (row.leftIsMonospace) + return df.getStringWidthFloat(row.leftAlignText); + else + return f.getStringWidth(row.leftAlignText); + } + + auto blankStringWidth{4.f}; + auto res = 0.f; + if (row.rowLeadingGlyph.has_value()) + res += glyphSize; + res += + std::min(blankStringWidth, row.leftIsMonospace ? df.getStringWidthFloat(row.leftAlignText) + : f.getStringWidthFloat(row.leftAlignText)); + res += std::min(blankStringWidth, row.centerIsMonospace + ? df.getStringWidthFloat(row.centerAlignText) + : f.getStringWidthFloat(row.centerAlignText)); + res += std::min(blankStringWidth, row.rightIsMonospace + ? df.getStringWidthFloat(row.rightAlignText) + : f.getStringWidthFloat(row.rightAlignText)); + + return res + 4; +} + } // namespace sst::jucegui::components \ No newline at end of file