Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve layout management of the info bubble to display more text when necessary #82

Merged
merged 1 commit into from
Feb 13, 2025
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 73 additions & 12 deletions Dependencies/Misc/Source/MiscTooltip.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -85,22 +85,44 @@ Tooltip::BubbleWindow::~BubbleWindow()
void Tooltip::BubbleWindow::paint(juce::Graphics& g)
{
auto constexpr cornerSize = 5.0f;
auto const bounds = getLocalBounds().toFloat();
auto const font = juce::Font(juce::FontOptions(13.0f)).withHorizontalScale(1.0f);

auto bounds = getLocalBounds().toFloat();
g.setColour(findColour(juce::TooltipWindow::ColourIds::backgroundColourId));
g.fillRoundedRectangle(bounds, cornerSize);

g.setColour(findColour(juce::TooltipWindow::ColourIds::outlineColourId));
g.drawRoundedRectangle(bounds.reduced(0.5f, 0.5f), cornerSize, 1.0f);

juce::AttributedString attributedString;
attributedString.setJustification(juce::Justification::centredLeft);
attributedString.append(mTooltip, font, findColour(juce::TooltipWindow::ColourIds::textColourId));
static auto constexpr offset = 8.0f;
auto const font = juce::Font(juce::FontOptions(13.0f)).withHorizontalScale(1.0f);
auto const fontHeight = font.getHeight();

auto const lines = juce::StringArray::fromLines(mTooltip);
auto const textColour = findColour(juce::TooltipWindow::ColourIds::textColourId);
auto const maxWidth = 480.0f - offset * 2;
auto const maxHeight = std::min(bounds.getHeight() - offset * 2.0f, static_cast<float>(620 - offset * 2));
auto const maxLines = static_cast<int>(std::floor(maxHeight / fontHeight));
bounds.reduce(offset, offset);

auto lineIndex = 0;
juce::AttributedString attributedString;
attributedString.setJustification(juce::Justification::topLeft);
juce::TextLayout tl;
tl.createLayoutWithBalancedLineLengths(attributedString, 500.0f);
tl.draw(g, bounds.reduced(4.0f, 4.0f));
while(lineIndex < lines.size())
{
auto subIndex = 0;
while(lineIndex < lines.size() && subIndex <= maxLines)
{
auto const br = lineIndex <= lines.size() && subIndex <= maxLines - 1;
attributedString.append(lines.getReference(lineIndex) + (br ? "\n" : ""), font, textColour);
++lineIndex;
++subIndex;
}
tl.createLayout(attributedString, std::min(bounds.getWidth(), maxWidth), maxHeight);
tl.draw(g, bounds.removeFromLeft(std::ceil(tl.getWidth())).withHeight(tl.getHeight()));
bounds.removeFromLeft(offset);
attributedString.clear();
attributedString.setJustification(juce::Justification::topLeft);
}
}

void Tooltip::BubbleWindow::timerCallback()
Expand Down Expand Up @@ -140,17 +162,56 @@ void Tooltip::BubbleWindow::timerCallback()
}
else
{
auto const mousePosition = mouseSource.getScreenPosition().toInt();
static auto constexpr offset = 8;
auto const font = juce::Font(juce::FontOptions(13.0f)).withHorizontalScale(1.0f);
auto const fontHeight = font.getHeight();
auto const lines = juce::StringArray::fromLines(mTooltip);
auto const screenPosition = mouseSource.getScreenPosition().toInt();
auto const mousePosition = owner == nullptr ? screenPosition : owner->getLocalPoint(nullptr, screenPosition);
auto const targetArea = owner == nullptr ? desktop.getDisplays().getDisplayForPoint(mousePosition)->userArea : owner->getLocalBounds();
auto const maxHeight = std::min(static_cast<float>(targetArea.getHeight() - offset * 2), static_cast<float>(620 - offset * 2));
auto const maxLines = static_cast<int>(std::floor(maxHeight / fontHeight));
auto maxWidth = std::min(static_cast<float>(targetArea.getWidth() - offset * 2), static_cast<float>(480 - offset * 2));

auto width = 0;
auto height = 0;
auto lineIndex = 0;
juce::AttributedString attributedString;
attributedString.setJustification(juce::Justification::topLeft);
juce::TextLayout tl;
while(lineIndex < lines.size())
{
auto subIndex = 0;
while(lineIndex < lines.size() && subIndex <= maxLines)
{
auto const br = lineIndex <= lines.size() && subIndex <= maxLines - 1;
attributedString.append(lines.getReference(lineIndex) + (br ? "\n" : ""), font);
++lineIndex;
++subIndex;
}
tl.createLayout(attributedString, maxWidth, maxHeight);
auto const w = static_cast<int>(std::ceil(tl.getWidth()));
auto const h = static_cast<int>(std::ceil(tl.getHeight()));
width += (w + offset);
height = std::max(height, h);
maxWidth -= static_cast<float>(w);
attributedString.clear();
attributedString.setJustification(juce::Justification::topLeft);
}
width += offset * 2;
height += offset * 2;

auto const x = mousePosition.x > targetArea.getCentreX() ? mousePosition.x - (width + offset) : mousePosition.x + offset;
auto const y = mousePosition.y > targetArea.getCentreY() ? mousePosition.y - (height + offset) : mousePosition.y + offset + 1;
auto const bounds = juce::Rectangle<int>(x, y, width, height).constrainedWithin(targetArea);
setBounds(bounds);
if(owner == nullptr)
{
auto const parentArea = desktop.getDisplays().getDisplayForPoint(mousePosition)->userArea;
setBounds(getLookAndFeel().getTooltipBounds(mTooltip, mousePosition, parentArea));
addToDesktop(juce::ComponentPeer::windowHasDropShadow | juce::ComponentPeer::windowIsTemporary | juce::ComponentPeer::windowIgnoresKeyPresses | juce::ComponentPeer::windowIgnoresMouseClicks);
}
else
{
toFront(false);
setBounds(getLookAndFeel().getTooltipBounds(mTooltip, owner->getLocalPoint(nullptr, mousePosition), owner->getLocalBounds()));
}
setVisible(true);
repaint();
Expand Down