Skip to content

Commit

Permalink
Visual Feedback when dragging over droppable targets (#5002)
Browse files Browse the repository at this point in the history
Closes #4995
  • Loading branch information
baconpaul authored Sep 6, 2021
1 parent c21bc67 commit fc7f635
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 1 deletion.
54 changes: 54 additions & 0 deletions src/gui/SurgeGUIEditor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3811,6 +3811,53 @@ void SurgeGUIEditor::promptForMiniEdit(const std::string &value, const std::stri
miniEdit->grabFocus();
}

bool SurgeGUIEditor::modSourceButtonDraggedOver(Surge::Widgets::ModulationSourceButton *msb,
const juce::Point<int> &pt)
{
juce::Component *target = nullptr;

auto isDroppable = [msb](juce::Component *c) {
auto tMCI = dynamic_cast<Surge::Widgets::ModulatableControlInterface *>(c);
if (tMCI)
return true;
return false;
};
auto recC = [isDroppable, msb, pt](juce::Component *p, auto rec) -> juce::Component * {
for (auto kid : p->getChildren())
{
if (kid && kid->isVisible() && kid != msb && kid->getBounds().contains(pt))
{
if (isDroppable(kid))
return kid;

auto q = rec(kid, rec);
if (q)
return q;
}
}
return nullptr;
};
target = recC(frame.get(), recC);
auto tMCI = dynamic_cast<Surge::Widgets::ModulatableSlider *>(target);
if (tMCI != modSourceDragOverTarget)
{
if (modSourceDragOverTarget)
{
modSourceDragOverTarget->setModulationState(priorModulationState);
modSourceDragOverTarget->asJuceComponent()->repaint();
}
modSourceDragOverTarget = tMCI;

if (tMCI)
{
priorModulationState = tMCI->modulationState;
tMCI->setModulationState(
Surge::Widgets::ModulatableControlInterface::MODULATED_BY_ACTIVE);
tMCI->asJuceComponent()->repaint();
}
}
return tMCI != nullptr;
}
void SurgeGUIEditor::modSourceButtonDroppedAt(Surge::Widgets::ModulationSourceButton *msb,
const juce::Point<int> &pt)
{
Expand Down Expand Up @@ -3855,6 +3902,13 @@ void SurgeGUIEditor::modSourceButtonDroppedAt(Surge::Widgets::ModulationSourceBu
}
else if (tMCI)
{
if (modSourceDragOverTarget)
{
tMCI->setModulationState(priorModulationState);
tMCI->asJuceComponent()->repaint();

modSourceDragOverTarget = nullptr;
}
openModTypeinOnDrop(msb->getCurrentModSource(), tMCI,
tMCI->asControlValueInterface()->getTag(), msb->getCurrentModIndex());
}
Expand Down
4 changes: 4 additions & 0 deletions src/gui/SurgeGUIEditor.h
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,10 @@ class SurgeGUIEditor : public Surge::GUI::IComponentTagValue::Listener,
void mappingFileDropped(const std::string &fn);
std::string tuningToHtml();

Surge::Widgets::ModulatableControlInterface *modSourceDragOverTarget{nullptr};
Surge::Widgets::ModulatableControlInterface::ModulationState priorModulationState;
bool modSourceButtonDraggedOver(Surge::Widgets::ModulationSourceButton *msb,
const juce::Point<int> &); // true if over a droppable target
void modSourceButtonDroppedAt(Surge::Widgets::ModulationSourceButton *msb,
const juce::Point<int> &);
void swapControllers(int t1, int t2);
Expand Down
14 changes: 13 additions & 1 deletion src/gui/widgets/ModulationSourceButton.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ void ModulationSourceButton::paint(juce::Graphics &g)
: skin->getColor(Colors::ModSource::Unused::TextHover);
}

if (ActiveModSource)
if (ActiveModSource || transientArmed)
{
FrameCol = skin->getColor(Colors::ModSource::Armed::Border);
if (isHovered)
Expand Down Expand Up @@ -361,6 +361,7 @@ void ModulationSourceButton::mouseDown(const juce::MouseEvent &event)

mouseDownBounds = getBounds();
componentDragger.startDraggingComponent(this, event);
setMouseCursor(juce::MouseCursor::DraggingHandCursor);
}

void ModulationSourceButton::mouseDoubleClick(const juce::MouseEvent &event)
Expand Down Expand Up @@ -427,13 +428,15 @@ void ModulationSourceButton::onSkinChanged()

void ModulationSourceButton::mouseUp(const juce::MouseEvent &event)
{
transientArmed = false;
if (mouseMode == CLICK || mouseMode == CLICK_ARROW)
{
notifyValueChanged();
}

if (mouseMode == DRAG_COMPONENT_HAPPEN)
{
setMouseCursor(juce::MouseCursor::NormalCursor);
auto sge = firstListenerOfType<SurgeGUIEditor>();
auto q = event.position.translated(getBounds().getX(), getBounds().getY());

Expand Down Expand Up @@ -514,6 +517,15 @@ void ModulationSourceButton::mouseDrag(const juce::MouseEvent &event)

mouseMode = DRAG_COMPONENT_HAPPEN;
componentDragger.dragComponent(this, event, nullptr);
auto sge = firstListenerOfType<SurgeGUIEditor>();
auto q = event.position.translated(getBounds().getX(), getBounds().getY());
auto ota = transientArmed;
if (sge)
{
/* transientArmed = */ sge->modSourceButtonDraggedOver(this, q.toInt());
}
if (ota != transientArmed)
repaint();
everDragged = true;
}

Expand Down
1 change: 1 addition & 0 deletions src/gui/widgets/ModulationSourceButton.h
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ struct ModulationSourceButton : public juce::Component,

void setState(int s) { state = s; }
int getState() const { return state; }
bool transientArmed{false}; // armed in drop state

bool secondaryHoverActive{false};

Expand Down

0 comments on commit fc7f635

Please sign in to comment.