JUCE-7.0.12-0-g4f43011b96 JUCE-7.0.12-0-g4f43011b96
JUCE — C++ application framework with suport for VST, VST3, LV2 audio plug-ins

« « « Anklang Documentation
Loading...
Searching...
No Matches
juce_ComponentAnimator.cpp
Go to the documentation of this file.
1 /*
2 ==============================================================================
3
4 This file is part of the JUCE library.
5 Copyright (c) 2022 - Raw Material Software Limited
6
7 JUCE is an open source library subject to commercial or open-source
8 licensing.
9
10 By using JUCE, you agree to the terms of both the JUCE 7 End-User License
11 Agreement and JUCE Privacy Policy.
12
13 End User License Agreement: www.juce.com/juce-7-licence
14 Privacy Policy: www.juce.com/juce-privacy-policy
15
16 Or: You may also use this code under the terms of the GPL v3 (see
17 www.gnu.org/licenses).
18
19 JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
20 EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
21 DISCLAIMED.
22
23 ==============================================================================
24*/
25
26namespace juce
27{
28
30{
31public:
32 AnimationTask (Component* c) noexcept : component (c) {}
33
35 {
36 proxy.deleteAndZero();
37 }
38
39 void reset (const Rectangle<int>& finalBounds,
40 float finalAlpha,
43 double startSpd, double endSpd)
44 {
45 msElapsed = 0;
46 msTotal = jmax (1, millisecondsToSpendMoving);
47 lastProgress = 0;
48 destination = finalBounds;
49 destAlpha = finalAlpha;
50
51 isMoving = (finalBounds != component->getBounds());
52 isChangingAlpha = ! approximatelyEqual (finalAlpha, component->getAlpha());
53
54 left = component->getX();
55 top = component->getY();
56 right = component->getRight();
57 bottom = component->getBottom();
58 alpha = component->getAlpha();
59
60 const double invTotalDistance = 4.0 / (startSpd + endSpd + 2.0);
61 startSpeed = jmax (0.0, startSpd * invTotalDistance);
62 midSpeed = invTotalDistance;
63 endSpeed = jmax (0.0, endSpd * invTotalDistance);
64
65 proxy.deleteAndZero();
66
68 proxy = new ProxyComponent (*component);
69
70 component->setVisible (! useProxyComponent);
71 }
72
73 bool useTimeslice (const int elapsed)
74 {
75 if (auto* c = proxy != nullptr ? proxy.getComponent()
76 : component.get())
77 {
78 msElapsed += elapsed;
79 double newProgress = msElapsed / (double) msTotal;
80
81 if (newProgress >= 0 && newProgress < 1.0)
82 {
83 const WeakReference<AnimationTask> weakRef (this);
84 newProgress = timeToDistance (newProgress);
85 const double delta = (newProgress - lastProgress) / (1.0 - lastProgress);
86 jassert (newProgress >= lastProgress);
87 lastProgress = newProgress;
88
89 if (delta < 1.0)
90 {
91 bool stillBusy = false;
92
93 if (isMoving)
94 {
95 left += (destination.getX() - left) * delta;
96 top += (destination.getY() - top) * delta;
97 right += (destination.getRight() - right) * delta;
98 bottom += (destination.getBottom() - bottom) * delta;
99
100 const Rectangle<int> newBounds (roundToInt (left),
101 roundToInt (top),
102 roundToInt (right - left),
103 roundToInt (bottom - top));
104
105 if (newBounds != destination)
106 {
107 c->setBounds (newBounds);
108 stillBusy = true;
109 }
110 }
111
112 // Check whether the animation was cancelled/deleted during
113 // a callback during the setBounds method
114 if (weakRef.wasObjectDeleted())
115 return false;
116
117 if (isChangingAlpha)
118 {
119 alpha += (destAlpha - alpha) * delta;
120 c->setAlpha ((float) alpha);
121 stillBusy = true;
122 }
123
124 if (stillBusy)
125 return true;
126 }
127 }
128 }
129
130 moveToFinalDestination();
131 return false;
132 }
133
134 void moveToFinalDestination()
135 {
136 if (component != nullptr)
137 {
138 const WeakReference<AnimationTask> weakRef (this);
139 component->setAlpha ((float) destAlpha);
140 component->setBounds (destination);
141
142 if (! weakRef.wasObjectDeleted())
143 if (proxy != nullptr)
144 component->setVisible (destAlpha > 0);
145 }
146 }
147
148 //==============================================================================
150 {
152 {
153 setWantsKeyboardFocus (false);
154 setBounds (c.getBounds());
156 setAlpha (c.getAlpha());
157 setInterceptsMouseClicks (false, false);
158
159 if (auto* parent = c.getParentComponent())
160 parent->addAndMakeVisible (this);
161 else if (c.isOnDesktop() && c.getPeer() != nullptr)
163 else
164 jassertfalse; // seem to be trying to animate a component that's not visible..
165
168
169 image = c.createComponentSnapshot (c.getLocalBounds(), false, scale);
170
171 setVisible (true);
172 toBehind (&c);
173 }
174
175 void paint (Graphics& g) override
176 {
177 g.setOpacity (1.0f);
178 g.drawImageTransformed (image, AffineTransform::scale ((float) getWidth() / (float) jmax (1, image.getWidth()),
179 (float) getHeight() / (float) jmax (1, image.getHeight())), false);
180 }
181
182 private:
183 std::unique_ptr<AccessibilityHandler> createAccessibilityHandler() override
184 {
186 }
187
188 Image image;
189
191 };
192
193 WeakReference<Component> component;
195
196 Rectangle<int> destination;
197 double destAlpha;
198
199 int msElapsed, msTotal;
200 double startSpeed, midSpeed, endSpeed, lastProgress;
201 double left, top, right, bottom, alpha;
202 bool isMoving, isChangingAlpha;
203
204private:
205 double timeToDistance (const double time) const noexcept
206 {
207 return (time < 0.5) ? time * (startSpeed + time * (midSpeed - startSpeed))
208 : 0.5 * (startSpeed + 0.5 * (midSpeed - startSpeed))
209 + (time - 0.5) * (midSpeed + (time - 0.5) * (endSpeed - midSpeed));
210 }
211
212 JUCE_DECLARE_WEAK_REFERENCEABLE (AnimationTask)
214};
215
216//==============================================================================
219
220//==============================================================================
221ComponentAnimator::AnimationTask* ComponentAnimator::findTaskFor (Component* const component) const noexcept
222{
223 for (int i = tasks.size(); --i >= 0;)
224 if (component == tasks.getUnchecked (i)->component.get())
225 return tasks.getUnchecked (i);
226
227 return nullptr;
228}
229
232 const float finalAlpha,
234 const bool useProxyComponent,
235 const double startSpeed,
236 const double endSpeed)
237{
238 // the speeds must be 0 or greater!
239 jassert (startSpeed >= 0 && endSpeed >= 0);
240
241 if (component != nullptr)
242 {
243 auto* at = findTaskFor (component);
244
245 if (at == nullptr)
246 {
247 at = new AnimationTask (component);
248 tasks.add (at);
250 }
251
253 useProxyComponent, startSpeed, endSpeed);
254
255 if (! isTimerRunning())
256 {
257 lastTime = Time::getMillisecondCounter();
258 startTimerHz (50);
259 }
260 }
261}
262
264{
265 if (component != nullptr)
266 {
267 if (component->isShowing() && millisecondsToTake > 0)
268 animateComponent (component, component->getBounds(), 0.0f, millisecondsToTake, true, 1.0, 1.0);
269
270 component->setVisible (false);
271 }
272}
273
275{
276 if (component != nullptr && ! (component->isVisible() && approximatelyEqual (component->getAlpha(), 1.0f)))
277 {
278 component->setAlpha (0.0f);
279 component->setVisible (true);
280 animateComponent (component, component->getBounds(), 1.0f, millisecondsToTake, false, 1.0, 1.0);
281 }
282}
283
285{
286 if (tasks.size() > 0)
287 {
289 for (int i = tasks.size(); --i >= 0;)
290 tasks.getUnchecked (i)->moveToFinalDestination();
291
292 tasks.clear();
294 }
295}
296
299{
300 if (auto* at = findTaskFor (component))
301 {
303 at->moveToFinalDestination();
304
305 tasks.removeObject (at);
307 }
308}
309
311{
312 jassert (component != nullptr);
313
314 if (auto* at = findTaskFor (component))
315 return at->destination;
316
317 return component->getBounds();
318}
319
320bool ComponentAnimator::isAnimating (Component* component) const noexcept
321{
322 return findTaskFor (component) != nullptr;
323}
324
326{
327 return tasks.size() != 0;
328}
329
330void ComponentAnimator::timerCallback()
331{
333
334 if (lastTime == 0)
335 lastTime = timeNow;
336
337 auto elapsed = (int) (timeNow - lastTime);
338
339 for (auto* task : Array<AnimationTask*> (tasks.begin(), tasks.size()))
340 {
341 if (tasks.contains (task) && ! task->useTimeslice (elapsed))
342 {
343 tasks.removeObject (task);
345 }
346 }
347
348 lastTime = timeNow;
349
350 if (tasks.size() == 0)
351 stopTimer();
352}
353
354} // namespace juce
static AffineTransform scale(float factorX, float factorY) noexcept
Returns a new transform which is a re-scale about the origin.
Holds a resizable array of primitive or copy-by-value objects.
Definition juce_Array.h:56
void sendChangeMessage()
Causes an asynchronous change message to be sent to all the registered listeners.
void animateComponent(Component *component, const Rectangle< int > &finalBounds, float finalAlpha, int animationDurationMilliseconds, bool useProxyComponent, double startSpeed, double endSpeed)
Starts a component moving from its current position to a specified position.
void cancelAllAnimations(bool moveComponentsToTheirFinalPositions)
Clears all of the active animations.
Rectangle< int > getComponentDestination(Component *component)
Returns the destination position for a component.
void fadeOut(Component *component, int millisecondsToTake)
Begins a fade-out of this components alpha level.
bool isAnimating() const noexcept
Returns true if any components are currently being animated.
~ComponentAnimator() override
Destructor.
void cancelAnimation(Component *component, bool moveComponentToItsFinalPosition)
Stops a component if it's currently being animated.
void fadeIn(Component *component, int millisecondsToTake)
Begins a fade-in of a component.
ComponentAnimator()
Creates a ComponentAnimator.
int getStyleFlags() const noexcept
Returns the set of style flags that were set when the window was created.
@ windowIgnoresKeyPresses
Tells the window not to catch any keypresses.
Holds a pointer to some type of Component, which automatically becomes null if the component is delet...
The base class for all JUCE user-interface objects.
AffineTransform getTransform() const
Returns the transform that is currently being applied to this component.
void setTransform(const AffineTransform &transform)
Sets a transform matrix to be applied to this component.
void toBehind(Component *other)
Changes this component's z-order so that it's just behind another component.
void setInterceptsMouseClicks(bool allowClicksOnThisComponent, bool allowClicksOnChildComponents) noexcept
Changes the default return value for the hitTest() method.
bool isVisible() const noexcept
Tests whether the component is visible or not.
Component * getParentComponent() const noexcept
Returns the component which this component is inside.
Image createComponentSnapshot(Rectangle< int > areaToGrab, bool clipImageToComponentBounds=true, float scaleFactor=1.0f)
Generates a snapshot of part of this component.
int getHeight() const noexcept
Returns the component's height in pixels.
bool isShowing() const
Tests whether this component and all its parents are visible.
static float JUCE_CALLTYPE getApproximateScaleFactorForComponent(const Component *targetComponent)
Returns the approximate scale factor for a given component by traversing its parent hierarchy and app...
void setAlpha(float newAlpha)
Changes the transparency of this component.
float getAlpha() const noexcept
Returns the component's current transparency level.
Rectangle< int > getBounds() const noexcept
Returns this component's bounding box.
Rectangle< int > getScreenBounds() const
Returns the bounds of this component, relative to the screen's top-left.
bool isOnDesktop() const noexcept
Returns true if this component is currently showing on the desktop.
virtual void addToDesktop(int windowStyleFlags, void *nativeWindowToAttachTo=nullptr)
Makes this component appear as a window on the desktop.
void setBounds(int x, int y, int width, int height)
Changes the component's position and size.
void setWantsKeyboardFocus(bool wantsFocus) noexcept
Sets a flag to indicate whether this component wants keyboard focus or not.
int getWidth() const noexcept
Returns the component's width in pixels.
ComponentPeer * getPeer() const
Returns the heavyweight window that contains this component.
Rectangle< int > getLocalBounds() const noexcept
Returns the component's bounds, relative to its own origin.
virtual void setVisible(bool shouldBeVisible)
Makes the component visible or invisible.
const Displays & getDisplays() const noexcept
Returns the Displays object representing the connected displays.
static Desktop &JUCE_CALLTYPE getInstance()
There's only one desktop object, and this method will return it.
const Display * getDisplayForRect(Rectangle< int > rect, bool isPhysical=false) const noexcept
Returns the Display object representing the display containing a given Rectangle (either in logical o...
A graphics context, used for drawing a component or image.
void setOpacity(float newOpacity)
Changes the opacity to use with the current colour.
void drawImageTransformed(const Image &imageToDraw, const AffineTransform &transform, bool fillAlphaChannelWithCurrentBrush=false) const
Draws an image, having applied an affine transform to it.
Holds a fixed-size bitmap.
Definition juce_Image.h:58
int getWidth() const noexcept
Returns the image's width (in pixels).
int getHeight() const noexcept
Returns the image's height (in pixels).
Manages a rectangle and allows geometric operations to be performed on it.
ValueType getRight() const noexcept
Returns the x coordinate of the rectangle's right-hand-side.
ValueType getX() const noexcept
Returns the x coordinate of the rectangle's left-hand-side.
ValueType getBottom() const noexcept
Returns the y coordinate of the rectangle's bottom edge.
ValueType getY() const noexcept
Returns the y coordinate of the rectangle's top edge.
static uint32 getMillisecondCounter() noexcept
Returns the number of millisecs since a fixed event (usually system startup).
void stopTimer() noexcept
Stops the timer.
void startTimerHz(int timerFrequencyHz) noexcept
Starts the timer with an interval specified in Hertz.
bool isTimerRunning() const noexcept
Returns true if the timer is currently running.
Definition juce_Timer.h:111
This class acts as a pointer which will automatically become null if the object to which it points is...
bool wasObjectDeleted() const noexcept
This returns true if this reference has been pointing at an object, but that object has since been de...
#define jassert(expression)
Platform-independent assertion macro.
#define JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(className)
This is a shorthand way of writing both a JUCE_DECLARE_NON_COPYABLE and JUCE_LEAK_DETECTOR macro for ...
#define jassertfalse
This will always cause an assertion failure.
#define JUCE_DECLARE_WEAK_REFERENCEABLE(Class)
Macro to easily allow a class to be made weak-referenceable.
typedef int
typedef double
JUCE Namespace.
constexpr bool approximatelyEqual(Type a, Type b, Tolerance< Type > tolerance=Tolerance< Type >{} .withAbsolute(std::numeric_limits< Type >::min()) .withRelative(std::numeric_limits< Type >::epsilon()))
Returns true if the two floating-point numbers are approximately equal.
constexpr Type jmax(Type a, Type b)
Returns the larger of two values.
Type unalignedPointerCast(void *ptr) noexcept
Casts a pointer to another type via void*, which suppresses the cast-align warning which sometimes ar...
Definition juce_Memory.h:88
int roundToInt(const FloatType value) noexcept
Fast floating-point-to-integer conversion.
RangedDirectoryIterator begin(const RangedDirectoryIterator &it)
Returns the iterator that was passed in.
void paint(Graphics &g) override
Components can override this method to draw their content.
time