From 4cee0dd6cd1b6f444b06540309e5d4df89cb06d3 Mon Sep 17 00:00:00 2001 From: Paul Walker Date: Mon, 25 Oct 2021 10:55:51 -0400 Subject: [PATCH] Patch Comment Tooltip Add a tooltip object which shows and dismisses appropriately. Size based on comment. Skin colors for everything. Closes #5298 --- .../data/skins/dark-mode.surge-skin/skin.xml | 4 ++ src/common/SkinColors.cpp | 7 ++ src/common/SkinColors.h | 4 ++ src/surge-xt/gui/SurgeGUIEditor.cpp | 28 ++++++++ src/surge-xt/gui/SurgeGUIEditor.h | 4 ++ src/surge-xt/gui/widgets/PatchSelector.cpp | 66 ++++++++++++++++++- src/surge-xt/gui/widgets/PatchSelector.h | 17 ++++- 7 files changed, 126 insertions(+), 4 deletions(-) diff --git a/resources/data/skins/dark-mode.surge-skin/skin.xml b/resources/data/skins/dark-mode.surge-skin/skin.xml index 5fda26ff217..7caa13a40eb 100644 --- a/resources/data/skins/dark-mode.surge-skin/skin.xml +++ b/resources/data/skins/dark-mode.surge-skin/skin.xml @@ -182,6 +182,10 @@ + + + + diff --git a/src/common/SkinColors.cpp b/src/common/SkinColors.cpp index da25c641b18..bd49fcbb4d3 100644 --- a/src/common/SkinColors.cpp +++ b/src/common/SkinColors.cpp @@ -376,6 +376,13 @@ namespace PatchBrowser { const Surge::Skin::Color Text("patchbrowser.text", 0, 0, 0); +namespace CommentTooltip +{ +const Surge::Skin::Color Border("patchbrowser.commenttooltip.border", 0xFF979797), + Background("patchbrowser.commenttooltip.background", 0xFFE3E3E3), + Text("patchbrowser.commenttooltip.text", 0xFF151515); +} + namespace TypeAheadList { const Surge::Skin::Color Border("patchbrowser.typeahead.border", 100, 100, 130), diff --git a/src/common/SkinColors.h b/src/common/SkinColors.h index f660a0deb16..c57828e30a1 100644 --- a/src/common/SkinColors.h +++ b/src/common/SkinColors.h @@ -276,6 +276,10 @@ namespace PatchBrowser { extern const Surge::Skin::Color Text; +namespace CommentTooltip +{ +extern const Surge::Skin::Color Border, Background, Text; +} namespace TypeAheadList { extern const Surge::Skin::Color Border, Background, Text, HighlightBackground, HighlightText, diff --git a/src/surge-xt/gui/SurgeGUIEditor.cpp b/src/surge-xt/gui/SurgeGUIEditor.cpp index 9424156b6ea..00281953499 100644 --- a/src/surge-xt/gui/SurgeGUIEditor.cpp +++ b/src/surge-xt/gui/SurgeGUIEditor.cpp @@ -382,6 +382,9 @@ SurgeGUIEditor::SurgeGUIEditor(SurgeSynthEditor *jEd, SurgeSynthesizer *synth) paramInfowindow = std::make_unique(); paramInfowindow->setVisible(false); + patchSelectorComment = std::make_unique(); + patchSelectorComment->setVisible(false); + typeinParamEditor = std::make_unique(); typeinParamEditor->setVisible(false); typeinParamEditor->setSurgeGUIEditor(this); @@ -1534,6 +1537,7 @@ void SurgeGUIEditor::openOrRecreateEditor() "Browse"); frame->addAndMakeVisible(*patchSelector); + break; } case Surge::Skin::Connector::NonParameterConnection::FX_SELECTOR: @@ -1695,6 +1699,9 @@ void SurgeGUIEditor::openOrRecreateEditor() paramInfowindow->setVisible(false); frame->addChildComponent(*paramInfowindow); + patchSelectorComment->setVisible(false); + frame->addChildComponent(*patchSelectorComment); + // Mouse behavior if (Surge::Widgets::ModulatableSlider::sliderMoveRateState == Surge::Widgets::ModulatableSlider::kUnInitialized) @@ -3654,6 +3661,7 @@ void SurgeGUIEditor::reloadFromSkin() bitmapStore->setPhysicalZoomFactor(getZoomFactor() * dbs); paramInfowindow->setSkin(currentSkin, bitmapStore); + patchSelectorComment->setSkin(currentSkin, bitmapStore); auto bg = currentSkin->customBackgroundImage(); @@ -5912,3 +5920,23 @@ void SurgeGUIEditor::loadFromDAWExtraState(SurgeSynthesizer *synth) } } } + +void SurgeGUIEditor::showPatchCommentTooltip(const std::string &comment) +{ + if (patchSelectorComment) + { + patchSelectorComment->setVisible(true); + patchSelectorComment->getParentComponent()->toFront(true); + patchSelectorComment->toFront(true); + patchSelectorComment->positionForComment(patchSelector->getBounds().getBottomLeft(), + comment); + } +} + +void SurgeGUIEditor::hidePatchCommentTooltip() +{ + if (patchSelectorComment && patchSelectorComment->isVisible()) + { + patchSelectorComment->setVisible(false); + } +} \ No newline at end of file diff --git a/src/surge-xt/gui/SurgeGUIEditor.h b/src/surge-xt/gui/SurgeGUIEditor.h index dd9b0aa5d6c..ef08046acc0 100644 --- a/src/surge-xt/gui/SurgeGUIEditor.h +++ b/src/surge-xt/gui/SurgeGUIEditor.h @@ -56,6 +56,7 @@ struct NumberField; struct OscillatorWaveformDisplay; struct ParameterInfowindow; struct PatchSelector; +struct PatchSelectorCommentTooltip; struct Switch; struct VerticalLabel; struct VuMeter; @@ -448,6 +449,7 @@ class SurgeGUIEditor : public Surge::GUI::IComponentTagValue::Listener, private: std::array, n_fx_slots + 1> vu; std::unique_ptr patchSelector; + std::unique_ptr patchSelectorComment; std::unique_ptr oscMenu; std::unique_ptr fxMenu; std::unique_ptr waveshaperSelector; @@ -459,6 +461,8 @@ class SurgeGUIEditor : public Surge::GUI::IComponentTagValue::Listener, void setupAlternates(modsources ms); public: + void showPatchCommentTooltip(const std::string &comment); + void hidePatchCommentTooltip(); void showInfowindow(int ptag, juce::Rectangle relativeTo, bool isModulated); void showInfowindowSelfDismiss(int ptag, juce::Rectangle relativeTo, bool isModulated); void updateInfowindowContents(int ptag, bool isModulated); diff --git a/src/surge-xt/gui/widgets/PatchSelector.cpp b/src/surge-xt/gui/widgets/PatchSelector.cpp index bcf97bb9575..28df98513af 100644 --- a/src/surge-xt/gui/widgets/PatchSelector.cpp +++ b/src/surge-xt/gui/widgets/PatchSelector.cpp @@ -215,7 +215,12 @@ void PatchSelector::mouseMove(const juce::MouseEvent &e) { if (tooltipCountdown >= 0) tooltipCountdown = 5; - toggleCommentTooltip(false); + // todo : apply mouse tolerance here + if (tooltipShowing && e.position.getDistanceFrom(tooltipMouseLocation.toFloat()) > 1) + toggleCommentTooltip(false); + else + tooltipMouseLocation = e.position; + auto pfh = favoritesHover; favoritesHover = false; if (favoritesRect.contains(e.position.toInt())) @@ -306,8 +311,21 @@ void PatchSelector::shouldTooltip() void PatchSelector::toggleCommentTooltip(bool b) { - if (b && !comment.empty()) - std::cout << "-------------\n" << comment << "---------------\n" << std::endl; + auto sge = firstListenerOfType(); + + if (sge) + { + if (b && !comment.empty()) + { + tooltipShowing = true; + sge->showPatchCommentTooltip(comment); + } + else + { + tooltipShowing = false; + sge->hidePatchCommentTooltip(); + } + } } void PatchSelector::openPatchBrowser() @@ -927,5 +945,47 @@ std::unique_ptr PatchSelector::createAccessibilityHa } #endif +void PatchSelectorCommentTooltip::paint(juce::Graphics &g) +{ + namespace clr = Colors::PatchBrowser::CommentTooltip; + g.fillAll(skin->getColor(clr::Border)); + g.setColour(skin->getColor(clr::Background)); + g.fillRect(getLocalBounds().reduced(1)); + g.setColour(skin->getColor(clr::Text)); + g.setFont(Surge::GUI::getFontManager()->getLatoAtSize(9)); + g.drawMultiLineText(comment, 5, g.getCurrentFont().getHeight() + 2, getWidth(), + juce::Justification::left); +} + +void PatchSelectorCommentTooltip::positionForComment(const juce::Point &topLeft, + const std::string &c) +{ + comment = c; + + std::stringstream ss(comment); + std::string to; + + int idx = 0; + + auto ft = Surge::GUI::getFontManager()->getLatoAtSize(9); + auto width = 0; + while (std::getline(ss, to, '\n')) + { + auto w = ft.getStringWidth(to); + width = std::max(w, width); + idx++; + } + + auto height = std::max(idx * (ft.getHeight() + 2), 30.f); + + auto r = juce::Rectangle() + .withX(topLeft.x) + .withY(topLeft.y) + .withWidth(width + 12) + .withHeight(height); + setBounds(r); + repaint(); +} + } // namespace Widgets } // namespace Surge \ No newline at end of file diff --git a/src/surge-xt/gui/widgets/PatchSelector.h b/src/surge-xt/gui/widgets/PatchSelector.h index 1f30ca25cf6..41414de9bf5 100644 --- a/src/surge-xt/gui/widgets/PatchSelector.h +++ b/src/surge-xt/gui/widgets/PatchSelector.h @@ -111,7 +111,7 @@ struct PatchSelector : public juce::Component, favoritesHover = false; searchHover = false; tooltipCountdown = -1; - toggleCommentTooltip(false); + // toggleCommentTooltip(false); repaint(); } void showClassicMenu(bool singleCategory = false); @@ -150,6 +150,8 @@ struct PatchSelector : public juce::Component, int tooltipCountdown{-1}; void toggleCommentTooltip(bool b); void shouldTooltip(); + juce::Point tooltipMouseLocation; + bool tooltipShowing{false}; /** * populatePatchMenuForCategory @@ -168,6 +170,19 @@ struct PatchSelector : public juce::Component, protected: JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(PatchSelector); }; + +struct PatchSelectorCommentTooltip : public juce::Component, + public Surge::GUI::SkinConsumingComponent +{ + PatchSelectorCommentTooltip(){}; + void paint(juce::Graphics &g) override; + + std::string comment; + void positionForComment(const juce::Point &topLeft, const std::string &comment); + + protected: + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(PatchSelectorCommentTooltip); +}; } // namespace Widgets } // namespace Surge #endif // SURGE_XT_PATCHSELECTOR_H