diff --git a/resources/data/skins/dark-mode.surge-skin/skin.xml b/resources/data/skins/dark-mode.surge-skin/skin.xml index 099718ed7fe..3a6bb085487 100644 --- a/resources/data/skins/dark-mode.surge-skin/skin.xml +++ b/resources/data/skins/dark-mode.surge-skin/skin.xml @@ -348,7 +348,7 @@ - + diff --git a/src/common/ModulationSource.h b/src/common/ModulationSource.h index 12b92b4507d..21a1129bfc0 100644 --- a/src/common/ModulationSource.h +++ b/src/common/ModulationSource.h @@ -122,13 +122,47 @@ extern float samplerate_inv; extern float samplerate; const char modsource_names_button[n_modsources][32] = { - "Off", "Velocity", "Keytrack", "Poly AT", "Channel AT", "Pitch Bend", - "Modwheel", "Macro 1", "Macro 2", "Macro 3", "Macro 4", "Macro 5", - "Macro 6", "Macro 7", "Macro 8", "Amp EG", "Filter EG", "LFO 1", - "LFO 2", "LFO 3", "LFO 4", "LFO 5", "LFO 6", "S-LFO 1", - "S-LFO 2", "S-LFO 3", "S-LFO 4", "S-LFO 5", "S-LFO 6", "MPE Timbre", - "Rel Velocity", "Random", "RandUni", "Alternate", "Alternate Uni", "Breath", - "Expression", "Sustain", "Lowest Key", "Highest Key", "Latest Key", + "Off", + "Velocity", + "Keytrack", + "Poly AT", + "Channel AT", + "Pitch Bend", + "Modwheel", + "Macro 1", + "Macro 2", + "Macro 3", + "Macro 4", + "Macro 5", + "Macro 6", + "Macro 7", + "Macro 8", + "Amp EG", + "Filter EG", + "LFO 1", + "LFO 2", + "LFO 3", + "LFO 4", + "LFO 5", + "LFO 6", + "S-LFO 1", + "S-LFO 2", + "S-LFO 3", + "S-LFO 4", + "S-LFO 5", + "S-LFO 6", + "MPE Timbre", + "Release Velocity", + "Random", + "Rand Uni", + "Alternate", + "Alternate Uni", + "Breath", + "Expression", + "Sustain", + "Lowest Key", + "Highest Key", + "Latest Key", }; const char modsource_names[n_modsources][32] = { diff --git a/src/common/SkinModel.cpp b/src/common/SkinModel.cpp index d867b20aa8d..9137b2514d0 100644 --- a/src/common/SkinModel.cpp +++ b/src/common/SkinModel.cpp @@ -566,7 +566,7 @@ Connector store_patch_dialog = Connector("controls.patch.store.window", 157, 57, // modulation panel is special, so it shows up as 'CUSTOM' with no connector and is special-cased in // SurgeGUIEditor -Connector modulation_panel = Connector("controls.modulation.panel", 2, 402, Components::Custom); +Connector modulation_panel = Connector("controls.modulation.panel", 3, 402, Components::Custom); } // namespace OtherControls } // namespace Skin } // namespace Surge diff --git a/src/gui/SurgeGUIEditor.cpp b/src/gui/SurgeGUIEditor.cpp index 25fff8aa7c5..d4d6ae8fc17 100644 --- a/src/gui/SurgeGUIEditor.cpp +++ b/src/gui/SurgeGUIEditor.cpp @@ -2554,7 +2554,8 @@ juce::PopupMenu SurgeGUIEditor::makeZoomMenu(const juce::Point &where, bool auto dzf = Surge::Storage::getUserDefaultValue(&(synth->storage), Surge::Storage::DefaultZoom, zoomFactor); - std::string dss = "Zoom to Default (" + std::to_string(dzf) + "%)"; + std::string dss = + Surge::GUI::toOSCaseForMenu("Zoom to Default (") + std::to_string(dzf) + "%)"; zoomSubMenu.addItem(dss, [this, dzf]() { resizeWindow(dzf); }); } @@ -2741,6 +2742,19 @@ juce::PopupMenu SurgeGUIEditor::makeValueDisplaysMenu(const juce::Point &wh !modValues); }); + bool infowi = Surge::Storage::getUserDefaultValue(&(this->synth->storage), + Surge::Storage::InfoWindowPopupOnIdle, true); + + dispDefMenu.addItem(Surge::GUI::toOSCaseForMenu("Show Value Readout on Mouse Hover"), true, + infowi, [this, infowi]() { + Surge::Storage::updateUserDefaultValue( + &(this->synth->storage), Surge::Storage::InfoWindowPopupOnIdle, + !infowi); + this->frame->repaint(); + }); + + dispDefMenu.addSeparator(); + bool lfoone = Surge::Storage::getUserDefaultValue( &(this->synth->storage), Surge::Storage::ShowGhostedLFOWaveReference, true); @@ -2752,16 +2766,7 @@ juce::PopupMenu SurgeGUIEditor::makeValueDisplaysMenu(const juce::Point &wh this->frame->repaint(); }); - bool infowi = Surge::Storage::getUserDefaultValue(&(this->synth->storage), - Surge::Storage::InfoWindowPopupOnIdle, true); - - dispDefMenu.addItem(Surge::GUI::toOSCaseForMenu("Show Value Popup On Slider Mouseover"), true, - infowi, [this, infowi]() { - Surge::Storage::updateUserDefaultValue( - &(this->synth->storage), Surge::Storage::InfoWindowPopupOnIdle, - !infowi); - this->frame->repaint(); - }); + dispDefMenu.addSeparator(); // Middle C submenu auto middleCSubMenu = juce::PopupMenu(); @@ -3133,7 +3138,8 @@ juce::PopupMenu SurgeGUIEditor::makeSmoothMenu( auto asmt = [&smoothMenu, smoothing, setSmooth](const char *label, ControllerModulationSource::SmoothingMode md) { - smoothMenu.addItem(label, true, (smoothing == md), [setSmooth, md]() { setSmooth(md); }); + smoothMenu.addItem(Surge::GUI::toOSCaseForMenu(label), true, (smoothing == md), + [setSmooth, md]() { setSmooth(md); }); }; asmt("Legacy", ControllerModulationSource::SmoothingMode::LEGACY); @@ -4765,7 +4771,7 @@ void SurgeGUIEditor::togglePatchBrowserDialog() void SurgeGUIEditor::showModulationEditorDialog() { auto pt = std::make_unique(this, this->synth); - addJuceEditorOverlay(std::move(pt), "Modulation Overview", MODULATION_EDITOR, + addJuceEditorOverlay(std::move(pt), "Modulation List", MODULATION_EDITOR, juce::Rectangle(50, 50, 750, 450)); } @@ -5011,7 +5017,7 @@ std::string SurgeGUIEditor::modulatorIndexExtension(int scene, int ms, int index if (index == 0) return shortV ? "" : " (Uniform)"; if (index == 1) - return shortV ? " hN" : " (Half Normal)"; + return shortV ? " HN" : " (Half Normal)"; } if (shortV) return "." + std::to_string(index + 1); diff --git a/src/gui/SurgeGUIEditorValueCallbacks.cpp b/src/gui/SurgeGUIEditorValueCallbacks.cpp index 06952d498ae..68cc66113a4 100644 --- a/src/gui/SurgeGUIEditorValueCallbacks.cpp +++ b/src/gui/SurgeGUIEditorValueCallbacks.cpp @@ -350,7 +350,7 @@ int32_t SurgeGUIEditor::controlModifierClicked(Surge::GUI::IComponentTagValue *c contextMenu.addSeparator(); - contextMenu.addItem(Surge::GUI::toOSCaseForMenu("Modulation Editor"), [this]() { + contextMenu.addItem(Surge::GUI::toOSCaseForMenu("Modulation List..."), [this]() { if (!isAnyOverlayPresent(MODULATION_EDITOR)) showModulationEditorDialog(); }); @@ -1899,11 +1899,10 @@ int32_t SurgeGUIEditor::controlModifierClicked(Surge::GUI::IComponentTagValue *c } } - contextMenu.addItem(Surge::GUI::toOSCaseForMenu("Modulation Overview..."), - [this]() { - if (!isAnyOverlayPresent(MODULATION_EDITOR)) - showModulationEditorDialog(); - }); + contextMenu.addItem(Surge::GUI::toOSCaseForMenu("Modulation List..."), [this]() { + if (!isAnyOverlayPresent(MODULATION_EDITOR)) + showModulationEditorDialog(); + }); if (n_ms) { diff --git a/src/gui/overlays/MiniEdit.cpp b/src/gui/overlays/MiniEdit.cpp index f97a38325a6..9953d0b23e8 100644 --- a/src/gui/overlays/MiniEdit.cpp +++ b/src/gui/overlays/MiniEdit.cpp @@ -27,7 +27,7 @@ MiniEdit::MiniEdit() { typein = std::make_unique("minieditTypein"); typein->setJustification(juce::Justification::centred); - typein->setFont(Surge::GUI::getFontManager()->getLatoAtSize(11)); + typein->setFont(Surge::GUI::getFontManager()->getLatoAtSize(10, juce::Font::bold)); typein->setSelectAllWhenFocused(true); typein->addListener(this); addAndMakeVisible(*typein); @@ -42,12 +42,15 @@ MiniEdit::MiniEdit() cancelButton->addListener(this); addAndMakeVisible(*cancelButton); } + MiniEdit::~MiniEdit() {} + juce::Rectangle MiniEdit::getDisplayRegion() { auto fullRect = juce::Rectangle(0, 0, 160, 80).withCentre(getBounds().getCentre()); return fullRect; } + void MiniEdit::paint(juce::Graphics &g) { if (!skin || !associatedBitmapStore) @@ -56,30 +59,36 @@ void MiniEdit::paint(juce::Graphics &g) g.fillAll(juce::Colours::red); return; } + g.fillAll(skin->getColor(Colors::Overlay::Background)); auto fullRect = getDisplayRegion(); auto tbRect = fullRect.withHeight(18); + g.setColour(skin->getColor(Colors::Dialog::Titlebar::Background)); g.fillRect(tbRect); g.setColour(skin->getColor(Colors::Dialog::Titlebar::Text)); - g.setFont(Surge::GUI::getFontManager()->getLatoAtSize(11)); + g.setFont(Surge::GUI::getFontManager()->getLatoAtSize(10, juce::Font::bold)); g.drawText(title, tbRect, juce::Justification::centred); auto d = associatedBitmapStore->getImage(IDB_SURGE_ICON); + if (d) { - d->drawAt(g, fullRect.getX(), fullRect.getY(), 1.0); + d->drawAt(g, fullRect.getX(), fullRect.getY() + 2, 1.0); } auto bodyRect = fullRect.withTrimmedTop(18); + g.setColour(skin->getColor(Colors::Dialog::Background)); g.fillRect(bodyRect); g.setColour(skin->getColor(Colors::Dialog::Label::Text)); g.setFont(Surge::GUI::getFontManager()->getLatoAtSize(9)); - auto labelRect = bodyRect.withHeight(22).withTrimmedLeft(3).withTrimmedRight(3); + + auto labelRect = bodyRect.withHeight(20).reduced(4, 0); + g.drawText(label, labelRect, juce::Justification::centredLeft); g.setColour(skin->getColor(Colors::Dialog::Border)); @@ -97,10 +106,11 @@ void MiniEdit::onSkinChanged() skin->getColor(Colors::Dialog::Entry::Border)); repaint(); } + void MiniEdit::resized() { - auto fullRect = getDisplayRegion(); auto eh = 18, mg = 2, bw = 40; + auto fullRect = getDisplayRegion(); auto typeinBox = fullRect.translated(0, 2 * eh + mg * 2) .withHeight(eh) @@ -109,19 +119,22 @@ void MiniEdit::resized() typein->setBounds(typeinBox); typein->setIndents(4, (typein->getHeight() - typein->getTextHeight()) / 2); - auto buttonRow = fullRect.translated(0, 3 * eh + mg * 3) - .withHeight(eh) + auto buttonRow = fullRect.translated(0, (3 * eh) + (mg * 3) + 2) + .withHeight(eh - 4) .withTrimmedLeft(mg) .withTrimmedRight(mg); - auto okRect = buttonRow.withTrimmedLeft(40).withWidth(38); - auto canRect = buttonRow.withTrimmedLeft(80).withWidth(38); + auto okRect = buttonRow.withTrimmedLeft(40).withWidth(40); + auto canRect = buttonRow.withTrimmedLeft(80).withWidth(40); okButton->setBounds(okRect); cancelButton->setBounds(canRect); if (isVisible()) + { grabFocus(); + } } + void MiniEdit::buttonClicked(juce::Button *button) { if (button == okButton.get()) @@ -130,16 +143,19 @@ void MiniEdit::buttonClicked(juce::Button *button) } setVisible(false); } + void MiniEdit::visibilityChanged() { if (isVisible()) grabFocus(); } + void MiniEdit::textEditorReturnKeyPressed(juce::TextEditor &editor) { callback(typein->getText().toStdString()); setVisible(false); } + void MiniEdit::textEditorEscapeKeyPressed(juce::TextEditor &editor) { setVisible(false); } } // namespace Overlays } // namespace Surge \ No newline at end of file diff --git a/src/gui/overlays/OverlayWrapper.cpp b/src/gui/overlays/OverlayWrapper.cpp index aae40fa318c..fc2abe2ba7e 100644 --- a/src/gui/overlays/OverlayWrapper.cpp +++ b/src/gui/overlays/OverlayWrapper.cpp @@ -25,7 +25,7 @@ OverlayWrapper::OverlayWrapper() { closeButton = std::make_unique("closeButton"); closeButton->addListener(this); - closeButton->setButtonText("Close"); + closeButton->setButtonText("X"); addAndMakeVisible(*closeButton); } @@ -33,11 +33,15 @@ void OverlayWrapper::paint(juce::Graphics &g) { g.fillAll(skin->getColor(Colors::Dialog::Titlebar::Background)); g.setColour(skin->getColor(Colors::Dialog::Titlebar::Text)); - g.setFont(Surge::GUI::getFontManager()->getLatoAtSize(11)); + g.setFont(Surge::GUI::getFontManager()->getLatoAtSize(10, juce::Font::bold)); g.drawText(title, getLocalBounds().withHeight(titlebarSize + margin), juce::Justification::centred); + if (icon) - icon->drawAt(g, 1, 1, 1); + { + icon->drawAt(g, 2, 1, 1); + } + g.setColour(skin->getColor(Colors::Dialog::Border)); g.drawRect(getLocalBounds(), 1); } @@ -51,16 +55,19 @@ void OverlayWrapper::addAndTakeOwnership(std::unique_ptr c) primaryChild = std::move(c); primaryChild->setBounds(q); - auto buttonWidth = 50; - auto closeButtonBounds = getLocalBounds() - .withHeight(titlebarSize - 1) - .withLeft(getWidth() - buttonWidth) - .translated(-2, 2); + auto buttonSize = titlebarSize - 2; + auto closeButtonBounds = + getLocalBounds().withHeight(buttonSize).withLeft(getWidth() - buttonSize).translated(-2, 2); if (showCloseButton) + { closeButton->setBounds(closeButtonBounds); + } else + { closeButton->setVisible(false); + } + addAndMakeVisible(*primaryChild); } diff --git a/src/gui/widgets/ModulationSourceButton.cpp b/src/gui/widgets/ModulationSourceButton.cpp index 86d49704ef0..3146087577f 100644 --- a/src/gui/widgets/ModulationSourceButton.cpp +++ b/src/gui/widgets/ModulationSourceButton.cpp @@ -38,7 +38,7 @@ void ModulationSourceButton::paint(juce::Graphics &g) * 0 - nothing * 1 - selected modeditor * 2 - selected modsource (locked) - * 4 [bit 2] - selected arrowbutton [0,1,2 -> 4,5,6] + * 4 [bit 2] - selected arrow button [0, 1, 2 -> 4, 5, 6] */ bool SelectedModSource = (state & 3) == 1; @@ -136,11 +136,13 @@ void ModulationSourceButton::paint(juce::Graphics &g) g.setColour(FillCol); g.fillRect(fillRect); + auto btnFont = Surge::GUI::getFontManager()->getLatoAtSize(8, juce::Font::bold); + if (!isMeta) { // modbutton name settings g.setColour(FontCol); - g.setFont(Surge::GUI::getFontManager()->displayFont); + g.setFont(btnFont); // modbutton name g.drawText(getCurrentModLabel(), getLocalBounds(), juce::Justification::centred); @@ -153,8 +155,9 @@ void ModulationSourceButton::paint(juce::Graphics &g) { // macro name area auto topRect = getLocalBounds().withHeight(splitHeight); + g.setColour(FontCol); - g.setFont(Surge::GUI::getFontManager()->displayFont); + g.setFont(btnFont); g.drawText(getCurrentModLabel(), topRect, juce::Justification::centred); // macro slider area @@ -215,9 +218,10 @@ void ModulationSourceButton::paint(juce::Graphics &g) if (isLFO()) { auto arrSze = getLocalBounds().withLeft(getLocalBounds().getRight() - 14).withHeight(16); + float dy = (state >= 4) ? -16 : 0; + juce::Graphics::ScopedSaveState gs(g); g.reduceClipRegion(arrSze); - float dy = (state >= 4) ? -16 : 0; arrow->drawAt(g, arrSze.getX(), arrSze.getY() + dy, 1.0); } @@ -225,16 +229,17 @@ void ModulationSourceButton::paint(juce::Graphics &g) if (needsHamburger()) { g.setColour(FrameCol); + float ht = 1.5; - int nburg = 4; - float pxspace = 1.f * (hamburgerHome.getHeight() - ht) / (nburg - 1); + int nburg = 3; + float pxspace = 1.f * (hamburgerHome.getHeight() - ht) / (nburg); for (int i = 0; i < nburg; ++i) { - auto r = - juce::Rectangle(hamburgerHome.getX(), hamburgerHome.getY() + i * pxspace, - hamburgerHome.getWidth(), ht); - g.fillRoundedRectangle(r, 1); + auto r = juce::Rectangle(hamburgerHome.getX() + 1, + ht + hamburgerHome.getY() + i * pxspace, + hamburgerHome.getWidth() - 1, ht); + g.fillRect(r); } } } @@ -248,6 +253,7 @@ void ModulationSourceButton::mouseDown(const juce::MouseEvent &event) { auto menu = juce::PopupMenu(); int idx{0}; + for (auto e : modlist) { menu.addItem(std::get<3>(e), [this, idx]() { @@ -257,12 +263,16 @@ void ModulationSourceButton::mouseDown(const juce::MouseEvent &event) mouseMode = NONE; repaint(); }); + idx++; } + mouseMode = HAMBURGER; menu.showMenuAsync(juce::PopupMenu::Options()); + return; } + if (event.mods.isPopupMenu()) { mouseMode = NONE; @@ -284,6 +294,7 @@ void ModulationSourceButton::mouseDown(const juce::MouseEvent &event) notifyBeginEdit(); mouseMode = DRAG_VALUE; valAtMouseDown = value; + return; } } @@ -345,8 +356,11 @@ void ModulationSourceButton::endHover() { bool oh = isHovered; isHovered = false; + if (oh != isHovered) + { repaint(); + } } void ModulationSourceButton::onSkinChanged() @@ -365,16 +379,19 @@ void ModulationSourceButton::mouseUp(const juce::MouseEvent &event) { auto sge = firstListenerOfType(); auto q = event.position.translated(getBounds().getX(), getBounds().getY()); + sge->modSourceButtonDroppedAt(this, q.toInt()); setBounds(mouseDownBounds); } if (mouseMode == DRAG_VALUE) { - juce::Desktop::getInstance().getMainMouseSource().enableUnboundedMouseMovement(false); auto p = juce::Point(value * getWidth(), 20); + + juce::Desktop::getInstance().getMainMouseSource().enableUnboundedMouseMovement(false); p = localPointToGlobal(p); juce::Desktop::getInstance().getMainMouseSource().setScreenPosition(p); + notifyEndEdit(); } @@ -413,6 +430,7 @@ void ModulationSourceButton::mouseDrag(const juce::MouseEvent &event) getParentComponent()->toFront(false); toFront(false); + mouseMode = DRAG_COMPONENT_HAPPEN; componentDragger.dragComponent(this, event, nullptr); everDragged = true; @@ -442,24 +460,37 @@ void ModulationSourceButton::mouseWheelMove(const juce::MouseEvent &event, value = limit01(value + speed * delta); mouseMode = DRAG_VALUE; + notifyValueChanged(); + mouseMode = NONE; + repaint(); } else if (needsHamburger()) { int dir = wheelAccumulationHelper.accumulate(wheel, false, true); + if (dir != 0) { auto n = this->modlistIndex - dir; + if (n < 0) + { n = this->modlist.size() - 1; + } else if (n >= modlist.size()) + { n = 0; + } + this->modlistIndex = n; mouseMode = HAMBURGER; + notifyValueChanged(); + mouseMode = NONE; + repaint(); } } @@ -483,30 +514,38 @@ void ModulationOverviewLaunchButton::paintButton(juce::Graphics &g, auto FillCol = skin->getColor(Colors::ModSource::Unused::Background); auto FrameCol = skin->getColor(Colors::ModSource::Unused::Border); auto FontCol = skin->getColor(Colors::ModSource::Unused::Text); + if (shouldDrawButtonAsHighlighted || shouldDrawButtonAsDown) { FrameCol = skin->getColor(Colors::ModSource::Unused::BorderHover); FontCol = skin->getColor(Colors::ModSource::Unused::TextHover); } + g.fillAll(FillCol); g.setColour(FrameCol); g.drawRect(getLocalBounds(), 1); - std::string msg = "Show"; + std::string msg = "List"; + if (editor->isAnyOverlayPresent(SurgeGUIEditor::MODULATION_EDITOR)) { - msg = "Hide"; + msg = "Close"; } - auto f = Surge::GUI::getFontManager()->displayFont; + + auto f = Surge::GUI::getFontManager()->getLatoAtSize(9); auto h = f.getHeight() * 0.9f; auto sh = h * msg.length(); auto y0 = (getHeight() - sh) / 2.f; + g.setFont(f); g.setColour(FontCol); + for (auto c : msg) { auto s = std::string("") + c; + g.drawText(s, juce::Rectangle(0, y0, getWidth(), h), juce::Justification::centred); + y0 += h; } }