1
0
Fork 0
mirror of https://github.com/juce-framework/JUCE.git synced 2026-01-10 23:44:24 +00:00

DragAndDropContainer: Allow custom scaling

This commit is contained in:
reuk 2021-11-25 17:57:53 +00:00
parent 6468088100
commit 34fdea0708
No known key found for this signature in database
GPG key ID: FCB43929F012EE5C
9 changed files with 195 additions and 72 deletions

View file

@ -35,14 +35,15 @@ class DragAndDropContainer::DragImageComponent : public Component,
private Timer
{
public:
DragImageComponent (const Image& im,
DragImageComponent (const ScaledImage& im,
const var& desc,
Component* const sourceComponent,
const MouseInputSource* draggingSource,
DragAndDropContainer& ddc,
Point<int> offset)
: sourceDetails (desc, sourceComponent, Point<int>()),
image (im), owner (ddc),
image (im),
owner (ddc),
mouseDragSource (draggingSource->getComponentUnderMouse()),
imageOffset (transformOffsetCoordinates (sourceComponent, offset)),
originalInputSourceIndex (draggingSource->getIndex()),
@ -83,7 +84,7 @@ public:
g.fillAll (Colours::white);
g.setOpacity (1.0f);
g.drawImageAt (image, 0, 0);
g.drawImage (image.getImage(), getLocalBounds().toFloat());
}
void mouseUp (const MouseEvent& e) override
@ -164,7 +165,7 @@ public:
forceMouseCursorUpdate();
}
void updateImage (const Image& newImage)
void updateImage (const ScaledImage& newImage)
{
image = newImage;
updateSize();
@ -218,7 +219,7 @@ public:
DragAndDropTarget::SourceDetails sourceDetails;
private:
Image image;
ScaledImage image;
DragAndDropContainer& owner;
WeakReference<Component> mouseDragSource, currentlyOverComp;
const Point<int> imageOffset;
@ -229,7 +230,8 @@ private:
void updateSize()
{
setSize (image.getWidth(), image.getHeight());
const auto bounds = image.getScaledBounds().toNearestInt();
setSize (bounds.getWidth(), bounds.getHeight());
}
void forceMouseCursorUpdate()
@ -388,17 +390,13 @@ private:
//==============================================================================
DragAndDropContainer::DragAndDropContainer()
{
}
DragAndDropContainer::DragAndDropContainer() = default;
DragAndDropContainer::~DragAndDropContainer()
{
}
DragAndDropContainer::~DragAndDropContainer() = default;
void DragAndDropContainer::startDragging (const var& sourceDescription,
Component* sourceComponent,
Image dragImage,
const ScaledImage& dragImage,
const bool allowDraggingToExternalWindows,
const Point<int>* imageOffsetFromMouse,
const MouseInputSource* inputSourceCausingDrag)
@ -414,55 +412,53 @@ void DragAndDropContainer::startDragging (const var& sourceDescription,
return;
}
auto lastMouseDown = draggingSource->getLastMouseDownPosition().roundToInt();
Point<int> imageOffset;
const auto lastMouseDown = draggingSource->getLastMouseDownPosition().roundToInt();
if (dragImage.isNull())
struct ImageAndOffset
{
dragImage = sourceComponent->createComponentSnapshot (sourceComponent->getLocalBounds())
.convertedToFormat (Image::ARGB);
ScaledImage image;
Point<double> offset;
};
dragImage.multiplyAllAlphas (0.6f);
auto lo = 150;
auto hi = 400;
auto relPos = sourceComponent->getLocalPoint (nullptr, lastMouseDown);
auto clipped = dragImage.getBounds().getConstrainedPoint (relPos);
Random random;
for (auto y = dragImage.getHeight(); --y >= 0;)
{
auto dy = (y - clipped.getY()) * (y - clipped.getY());
for (auto x = dragImage.getWidth(); --x >= 0;)
{
auto dx = x - clipped.getX();
auto distance = roundToInt (std::sqrt (dx * dx + dy));
if (distance > lo)
{
auto alpha = (distance > hi) ? 0
: (float) (hi - distance) / (float) (hi - lo)
+ random.nextFloat() * 0.008f;
dragImage.multiplyAlphaAt (x, y, alpha);
}
}
}
imageOffset = clipped;
}
else
const auto imageToUse = [&]() -> ImageAndOffset
{
if (imageOffsetFromMouse == nullptr)
imageOffset = dragImage.getBounds().getCentre();
else
imageOffset = dragImage.getBounds().getConstrainedPoint (-*imageOffsetFromMouse);
}
if (! dragImage.getImage().isNull())
return { dragImage, imageOffsetFromMouse != nullptr ? dragImage.getScaledBounds().getConstrainedPoint (-imageOffsetFromMouse->toDouble())
: dragImage.getScaledBounds().getCentre() };
auto* dragImageComponent = dragImageComponents.add (new DragImageComponent (dragImage, sourceDescription, sourceComponent,
draggingSource, *this, imageOffset));
const auto scaleFactor = 2.0;
auto image = sourceComponent->createComponentSnapshot (sourceComponent->getLocalBounds(), true, (float) scaleFactor)
.convertedToFormat (Image::ARGB);
image.multiplyAllAlphas (0.6f);
const auto relPos = sourceComponent->getLocalPoint (nullptr, lastMouseDown).toDouble();
const auto clipped = (image.getBounds().toDouble() / scaleFactor).getConstrainedPoint (relPos);
Image fade (Image::SingleChannel, image.getWidth(), image.getHeight(), true);
Graphics fadeContext (fade);
ColourGradient gradient;
gradient.isRadial = true;
gradient.point1 = clipped.toFloat() * scaleFactor;
gradient.point2 = gradient.point1 + Point<float> (0.0f, scaleFactor * 400.0f);
gradient.addColour (0.0, Colours::white);
gradient.addColour (0.375, Colours::white);
gradient.addColour (1.0, Colours::transparentWhite);
fadeContext.setGradientFill (gradient);
fadeContext.fillAll();
Image composite (Image::ARGB, image.getWidth(), image.getHeight(), true);
Graphics compositeContext (composite);
compositeContext.reduceClipRegion (fade, {});
compositeContext.drawImageAt (image, 0, 0);
return { ScaledImage (composite, scaleFactor), clipped };
}();
auto* dragImageComponent = dragImageComponents.add (new DragImageComponent (imageToUse.image, sourceDescription, sourceComponent,
draggingSource, *this, imageToUse.offset.roundToInt()));
if (allowDraggingToExternalWindows)
{
@ -527,7 +523,7 @@ var DragAndDropContainer::getDragDescriptionForIndex (int index) const
return dragImageComponents.getUnchecked (index)->sourceDetails.description;
}
void DragAndDropContainer::setCurrentDragImage (const Image& newImage)
void DragAndDropContainer::setCurrentDragImage (const ScaledImage& newImage)
{
// If you are performing drag and drop in a multi-touch environment then
// you should use the setDragImageForIndex() method instead!
@ -536,7 +532,7 @@ void DragAndDropContainer::setCurrentDragImage (const Image& newImage)
dragImageComponents[0]->updateImage (newImage);
}
void DragAndDropContainer::setDragImageForIndex (int index, const Image& newImage)
void DragAndDropContainer::setDragImageForIndex (int index, const ScaledImage& newImage)
{
if (isPositiveAndBelow (index, dragImageComponents.size()))
dragImageComponents.getUnchecked (index)->updateImage (newImage);