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