diff --git a/modules/juce_gui_basics/menus/juce_PopupMenu.cpp b/modules/juce_gui_basics/menus/juce_PopupMenu.cpp index b0e96ffc03..e0dc00d2d5 100644 --- a/modules/juce_gui_basics/menus/juce_PopupMenu.cpp +++ b/modules/juce_gui_basics/menus/juce_PopupMenu.cpp @@ -1093,7 +1093,7 @@ private: if (! isMovingTowardsMenu) { - Component* c = getComponentAt (localMousePos.getX(), localMousePos.getY()); + Component* c = getComponentAt (localMousePos); if (c == this) c = nullptr; diff --git a/modules/juce_gui_basics/mouse/juce_DragAndDropContainer.cpp b/modules/juce_gui_basics/mouse/juce_DragAndDropContainer.cpp index d20aedd24c..e04f3c13e2 100644 --- a/modules/juce_gui_basics/mouse/juce_DragAndDropContainer.cpp +++ b/modules/juce_gui_basics/mouse/juce_DragAndDropContainer.cpp @@ -38,15 +38,15 @@ public: const var& desc, Component* const sourceComponent, Component* const mouseDragSource_, - DragAndDropContainer* const o, + DragAndDropContainer& owner_, const Point& imageOffset_) : sourceDetails (desc, sourceComponent, Point()), image (im), + owner (owner_), mouseDragSource (mouseDragSource_), - owner (o), imageOffset (imageOffset_), hasCheckedForExternalDrag (false), - drawImage (true) + isDoingExternalDrag (false) { setSize (im.getWidth(), im.getHeight()); @@ -63,8 +63,8 @@ public: ~DragImageComponent() { - if (owner->dragImageComponent == this) - owner->dragImageComponent.release(); + if (owner.dragImageComponent == this) + owner.dragImageComponent.release(); if (mouseDragSource != nullptr) { @@ -82,45 +82,8 @@ public: if (isOpaque()) g.fillAll (Colours::white); - if (drawImage) - { - g.setOpacity (1.0f); - g.drawImageAt (image, 0, 0); - } - } - - DragAndDropTarget* findTarget (const Point& screenPos, Point& relativePos) - { - Component* hit = getParentComponent(); - - if (hit == nullptr) - { - hit = Desktop::getInstance().findComponentAt (screenPos); - } - else - { - const Point relPos (hit->getLocalPoint (nullptr, screenPos)); - hit = hit->getComponentAt (relPos.getX(), relPos.getY()); - } - - // (note: use a local copy of this in case the callback runs - // a modal loop and deletes this object before the method completes) - const DragAndDropTarget::SourceDetails details (sourceDetails); - - while (hit != nullptr) - { - DragAndDropTarget* const ddt = dynamic_cast (hit); - - if (ddt != nullptr && ddt->isInterestedInDragSource (details)) - { - relativePos = hit->getLocalPoint (nullptr, screenPos); - return ddt; - } - - hit = hit->getParentComponent(); - } - - return nullptr; + g.setOpacity (1.0f); + g.drawImageAt (image, 0, 0); } void mouseUp (const MouseEvent& e) @@ -130,136 +93,70 @@ public: if (mouseDragSource != nullptr) mouseDragSource->removeMouseListener (this); - bool dropAccepted = false; - DragAndDropTarget* ddt = nullptr; - Point relPos; + // (note: use a local copy of this in case the callback runs + // a modal loop and deletes this object before the method completes) + DragAndDropTarget::SourceDetails details (sourceDetails); + DragAndDropTarget* finalTarget = nullptr; - if (isVisible()) + if (! isDoingExternalDrag) { + const bool wasVisible = isVisible(); setVisible (false); - ddt = findTarget (e.getScreenPosition(), relPos); - - // fade this component and remove it - it'll be deleted later by the timer callback - - dropAccepted = ddt != nullptr; - - setVisible (true); + finalTarget = findTarget (e.getScreenPosition(), details.localPosition); - if (dropAccepted || sourceDetails.sourceComponent == nullptr) - { - Desktop::getInstance().getAnimator().fadeOut (this, 120); - } - else - { - const Point target (sourceDetails.sourceComponent->localPointToGlobal (sourceDetails.sourceComponent->getLocalBounds().getCentre())); - const Point ourCentre (localPointToGlobal (getLocalBounds().getCentre())); - - Desktop::getInstance().getAnimator().animateComponent (this, - getBounds() + (target - ourCentre), - 0.0f, 120, - true, 1.0, 1.0); - } + if (wasVisible) // fade the component and remove it - it'll be deleted later by the timer callback + dismissWithAnimation (finalTarget == nullptr); } if (getParentComponent() != nullptr) getParentComponent()->removeChildComponent (this); - if (dropAccepted && ddt != nullptr) + if (finalTarget != nullptr) { - // (note: use a local copy of this in case the callback runs - // a modal loop and deletes this object before the method completes) - DragAndDropTarget::SourceDetails details (sourceDetails); - details.localPosition = relPos; - currentlyOverComp = nullptr; - - ddt->itemDropped (details); + finalTarget->itemDropped (details); } // careful - this object could now be deleted.. } } + void mouseDrag (const MouseEvent& e) + { + if (e.originalComponent != this) + updateLocation (true, e.getScreenPosition()); + } + void updateLocation (const bool canDoExternalDrag, const Point& screenPos) { - // (note: use a local copy of this in case a callback runs a modal loop and deletes - // this object before it returns) DragAndDropTarget::SourceDetails details (sourceDetails); - Point newPos (screenPos + imageOffset); - - if (getParentComponent() != nullptr) - newPos = getParentComponent()->getLocalPoint (nullptr, newPos); - - //if (newX != getX() || newY != getY()) - { - setTopLeftPosition (newPos); - - Point relPos; - DragAndDropTarget* const newTarget = findTarget (screenPos, relPos); - Component* newTargetComp = dynamic_cast (newTarget); - - drawImage = (newTarget == nullptr) || newTarget->shouldDrawDragImageWhenOver(); - - if (newTargetComp != currentlyOverComp) - { - DragAndDropTarget* const lastTarget = getCurrentlyOver(); - - if (lastTarget != nullptr && details.sourceComponent != nullptr - && lastTarget->isInterestedInDragSource (details)) - lastTarget->itemDragExit (details); + setNewScreenPos (screenPos); - currentlyOverComp = newTargetComp; - - if (newTarget != nullptr) - { - details.localPosition = relPos; - - if (newTarget->isInterestedInDragSource (details)) - newTarget->itemDragEnter (details); - } - } + DragAndDropTarget* const newTarget = findTarget (screenPos, details.localPosition); + Component* newTargetComp = dynamic_cast (newTarget); - { - DragAndDropTarget* const target = getCurrentlyOver(); - if (target != nullptr) - { - details.localPosition = relPos; + setVisible (newTarget == nullptr || newTarget->shouldDrawDragImageWhenOver()); - if (target->isInterestedInDragSource (details)) - target->itemDragMove (details); - } - } + if (newTargetComp != currentlyOverComp) + { + DragAndDropTarget* const lastTarget = getCurrentlyOver(); - if (getCurrentlyOver() == nullptr && canDoExternalDrag && ! hasCheckedForExternalDrag) - { - if (Desktop::getInstance().findComponentAt (screenPos) == nullptr) - { - hasCheckedForExternalDrag = true; - StringArray files; - bool canMoveFiles = false; + if (lastTarget != nullptr && details.sourceComponent != nullptr + && lastTarget->isInterestedInDragSource (details)) + lastTarget->itemDragExit (details); - if (owner->shouldDropFilesWhenDraggedExternally (details, files, canMoveFiles) - && files.size() > 0) - { - WeakReference thisWeakRef (this); - setVisible (false); + currentlyOverComp = newTargetComp; - if (ModifierKeys::getCurrentModifiersRealtime().isAnyMouseButtonDown()) - DragAndDropContainer::performExternalDragDropOfFiles (files, canMoveFiles); - - delete thisWeakRef.get(); - return; - } - } - } + if (newTarget != nullptr + && newTarget->isInterestedInDragSource (details)) + newTarget->itemDragEnter (details); } - } - void mouseDrag (const MouseEvent& e) - { - if (e.originalComponent != this) - updateLocation (true, e.getScreenPosition()); + sendDragMove (details); + + if (canDoExternalDrag && getCurrentlyOver() == nullptr) + checkForExternalDrag (details, screenPos); } void timerCallback() @@ -280,17 +177,110 @@ public: private: DragAndDropTarget::SourceDetails sourceDetails; Image image; - WeakReference mouseDragSource; - DragAndDropContainer* const owner; + DragAndDropContainer& owner; + WeakReference mouseDragSource, currentlyOverComp; + const Point imageOffset; + bool hasCheckedForExternalDrag, isDoingExternalDrag; - WeakReference currentlyOverComp; - DragAndDropTarget* getCurrentlyOver() + DragAndDropTarget* getCurrentlyOver() const noexcept { return dynamic_cast (currentlyOverComp.get()); } - const Point imageOffset; - bool hasCheckedForExternalDrag, drawImage; + DragAndDropTarget* findTarget (const Point& screenPos, Point& relativePos) const + { + Component* hit = getParentComponent(); + + if (hit == nullptr) + hit = Desktop::getInstance().findComponentAt (screenPos); + else + hit = hit->getComponentAt (hit->getLocalPoint (nullptr, screenPos)); + + // (note: use a local copy of this in case the callback runs + // a modal loop and deletes this object before the method completes) + const DragAndDropTarget::SourceDetails details (sourceDetails); + + while (hit != nullptr) + { + DragAndDropTarget* const ddt = dynamic_cast (hit); + + if (ddt != nullptr && ddt->isInterestedInDragSource (details)) + { + relativePos = hit->getLocalPoint (nullptr, screenPos); + return ddt; + } + + hit = hit->getParentComponent(); + } + + return nullptr; + } + + void setNewScreenPos (const Point& screenPos) + { + Point newPos (screenPos - imageOffset); + + if (getParentComponent() != nullptr) + newPos = getParentComponent()->getLocalPoint (nullptr, newPos); + + setTopLeftPosition (newPos); + } + + void sendDragMove (DragAndDropTarget::SourceDetails& details) const + { + DragAndDropTarget* const target = getCurrentlyOver(); + + if (target != nullptr && target->isInterestedInDragSource (details)) + target->itemDragMove (details); + } + + void checkForExternalDrag (DragAndDropTarget::SourceDetails& details, const Point& screenPos) + { + if (! hasCheckedForExternalDrag) + { + if (Desktop::getInstance().findComponentAt (screenPos) == nullptr) + { + hasCheckedForExternalDrag = true; + StringArray files; + bool canMoveFiles = false; + + if (owner.shouldDropFilesWhenDraggedExternally (details, files, canMoveFiles) + && files.size() > 0) + { + WeakReference thisWeakRef (this); + setVisible (false); + isDoingExternalDrag = true; + + if (ModifierKeys::getCurrentModifiersRealtime().isAnyMouseButtonDown()) + DragAndDropContainer::performExternalDragDropOfFiles (files, canMoveFiles); + + delete thisWeakRef.get(); + return; + } + } + } + } + + void dismissWithAnimation (const bool shouldSnapBack) + { + setVisible (true); + ComponentAnimator& animator = Desktop::getInstance().getAnimator(); + + if (shouldSnapBack && sourceDetails.sourceComponent != nullptr) + { + const Point target (sourceDetails.sourceComponent->localPointToGlobal (sourceDetails.sourceComponent->getLocalBounds().getCentre())); + const Point ourCentre (localPointToGlobal (getLocalBounds().getCentre())); + + animator.animateComponent (this, + getBounds() + (target - ourCentre), + 0.0f, 120, + true, 1.0, 1.0); + } + else + { + animator.fadeOut (this, 120); + } + } JUCE_DECLARE_NON_COPYABLE (DragImageComponent); }; @@ -369,18 +359,18 @@ void DragAndDropContainer::startDragging (const var& sourceDescription, } } - imageOffset = -clipped; + imageOffset = clipped; } else { if (imageOffsetFromMouse == nullptr) - imageOffset = -dragImage.getBounds().getCentre(); + imageOffset = dragImage.getBounds().getCentre(); else - imageOffset = -(dragImage.getBounds().getConstrainedPoint (-*imageOffsetFromMouse)); + imageOffset = dragImage.getBounds().getConstrainedPoint (-*imageOffsetFromMouse); } dragImageComponent = new DragImageComponent (dragImage, sourceDescription, sourceComponent, - draggingSource->getComponentUnderMouse(), this, imageOffset); + draggingSource->getComponentUnderMouse(), *this, imageOffset); currentDragDesc = sourceDescription; @@ -396,7 +386,7 @@ void DragAndDropContainer::startDragging (const var& sourceDescription, else thisComp->addChildComponent (dragImageComponent); - static_cast (static_cast (dragImageComponent))->updateLocation (false, lastMouseDown); + static_cast (dragImageComponent.get())->updateLocation (false, lastMouseDown); dragImageComponent->setVisible (true); #if JUCE_WINDOWS