@@ -22,7 +22,7 @@ | |||
============================================================================== | |||
*/ | |||
#ifndef __JUCE_GRAPHICS_MODULE_JUCEHEADER__ | |||
#ifndef __JUCE_GRAPHICS_MODULE_JUCEHEADER__ // %% | |||
#define __JUCE_GRAPHICS_MODULE_JUCEHEADER__ | |||
#include "../juce_core/juce_core.h" | |||
@@ -172,4 +172,4 @@ namespace juce | |||
} | |||
#endif // __JUCE_GRAPHICS_JUCEHEADER__ | |||
#endif // __JUCE_GRAPHICS_MODULE_JUCEHEADER__ |
@@ -147,6 +147,7 @@ namespace juce | |||
#include "mouse/juce_DragAndDropContainer.cpp" | |||
#include "mouse/juce_MouseCursor.cpp" | |||
#include "mouse/juce_MouseEvent.cpp" | |||
#include "mouse/juce_MouseInactivityDetector.cpp" | |||
#include "mouse/juce_MouseInputSource.cpp" | |||
#include "mouse/juce_MouseListener.cpp" | |||
#include "keyboard/juce_CaretComponent.cpp" | |||
@@ -111,6 +111,9 @@ namespace juce | |||
#ifndef __JUCE_MOUSEEVENT_JUCEHEADER__ | |||
#include "mouse/juce_MouseEvent.h" | |||
#endif | |||
#ifndef __JUCE_MOUSEINACTIVITYDETECTOR_JUCEHEADER__ | |||
#include "mouse/juce_MouseInactivityDetector.h" | |||
#endif | |||
#ifndef __JUCE_MOUSEINPUTSOURCE_JUCEHEADER__ | |||
#include "mouse/juce_MouseInputSource.h" | |||
#endif | |||
@@ -240,6 +243,12 @@ namespace juce | |||
#ifndef __JUCE_WILDCARDFILEFILTER_JUCEHEADER__ | |||
#include "filebrowser/juce_WildcardFileFilter.h" | |||
#endif | |||
#ifndef __JUCE_ANIMATEDPOSITION_JUCEHEADER__ | |||
#include "layout/juce_AnimatedPosition.h" | |||
#endif | |||
#ifndef __JUCE_ANIMATEDPOSITIONBEHAVIOURS_JUCEHEADER__ | |||
#include "layout/juce_AnimatedPositionBehaviours.h" | |||
#endif | |||
#ifndef __JUCE_COMPONENTANIMATOR_JUCEHEADER__ | |||
#include "layout/juce_ComponentAnimator.h" | |||
#endif | |||
@@ -0,0 +1,208 @@ | |||
/* | |||
============================================================================== | |||
This file is part of the JUCE library. | |||
Copyright (c) 2013 - Raw Material Software Ltd. | |||
Permission is granted to use this software under the terms of either: | |||
a) the GPL v2 (or any later version) | |||
b) the Affero GPL v3 | |||
Details of these licenses can be found at: www.gnu.org/licenses | |||
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY | |||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR | |||
A PARTICULAR PURPOSE. See the GNU General Public License for more details. | |||
------------------------------------------------------------------------------ | |||
To release a closed-source product which uses JUCE, commercial licenses are | |||
available: visit www.juce.com for more information. | |||
============================================================================== | |||
*/ | |||
#ifndef __JUCE_ANIMATEDPOSITION_JUCEHEADER__ | |||
#define __JUCE_ANIMATEDPOSITION_JUCEHEADER__ | |||
//============================================================================== | |||
/** | |||
Models a 1-dimensional position that can be dragged around by the user, and which | |||
will then continue moving with a customisable physics behaviour when released. | |||
This is useful for things like scrollable views or objects that can be dragged and | |||
thrown around with the mouse/touch, and by writing your own behaviour class, you can | |||
customise the trajectory that it follows when released. | |||
The class uses its own Timer to continuously change its value when a drag ends, and | |||
Listener objects can be registered to receive callbacks whenever the value changes. | |||
The value is stored as a double, and can be used to represent whatever units you need. | |||
The template parameter Behaviour must be a class that implements various methods to | |||
return the physics of the value's movement - you can use the classes provided for this | |||
in the AnimatedPositionBehaviours namespace, or write your own custom behaviour. | |||
@see AnimatedPositionBehaviours::ContinuousWithMomentum, | |||
AnimatedPositionBehaviours::SnapToPageBoundaries | |||
*/ | |||
template <typename Behaviour> | |||
class AnimatedPosition : private Timer | |||
{ | |||
public: | |||
AnimatedPosition() | |||
: position(), grabbedPos(), releaseVelocity(), | |||
range (-std::numeric_limits<double>::max(), | |||
std::numeric_limits<double>::max()) | |||
{ | |||
} | |||
/** Sets a range within which the value will be constrained. */ | |||
void setLimits (Range<double> newRange) | |||
{ | |||
range = newRange; | |||
} | |||
//============================================================================== | |||
/** Called to indicate that the object is now being controlled by a | |||
mouse-drag or similar operation. | |||
After calling this method, you should make calls to the drag() method | |||
each time the mouse drags the position around, and always be sure to | |||
finish with a call to endDrag() when the mouse is released, which allows | |||
the position to continue moving freely according to the specified behaviour. | |||
*/ | |||
void beginDrag() | |||
{ | |||
grabbedPos = position; | |||
releaseVelocity = 0; | |||
stopTimer(); | |||
} | |||
/** Called during a mouse-drag operation, to indicate that the mouse has moved. | |||
The delta is the difference between the position when beginDrag() was called | |||
and the new position that's required. | |||
*/ | |||
void drag (double deltaFromStartOfDrag) | |||
{ | |||
moveTo (grabbedPos + deltaFromStartOfDrag); | |||
} | |||
/** Called after beginDrag() and drag() to indicate that the drag operation has | |||
now finished. | |||
*/ | |||
void endDrag() | |||
{ | |||
startTimer (1000 / 60); | |||
} | |||
/** Called outside of a drag operation to cause a nudge in the specified direction. | |||
This is intended for use by e.g. mouse-wheel events. | |||
*/ | |||
void nudge (double deltaFromCurrentPosition) | |||
{ | |||
startTimer (100); | |||
moveTo (position + deltaFromCurrentPosition); | |||
} | |||
//============================================================================== | |||
/** Returns the current position. */ | |||
double getPosition() const noexcept | |||
{ | |||
return position; | |||
} | |||
/** Explicitly sets the position and stops any further movement. | |||
This will cause a synchronous call to any listeners if the position actually | |||
changes. | |||
*/ | |||
void setPosition (double newPosition) | |||
{ | |||
stopTimer(); | |||
setPositionAndSendChange (newPosition); | |||
} | |||
//============================================================================== | |||
/** Implement this class if you need to receive callbacks when the value of | |||
an AnimatedPosition changes. | |||
@see AnimatedPosition::addListener, AnimatedPosition::removeListener | |||
*/ | |||
class Listener | |||
{ | |||
public: | |||
virtual ~Listener() {} | |||
/** Called synchronously when an AnimatedPosition changes. */ | |||
virtual void positionChanged (AnimatedPosition&, double newPosition) = 0; | |||
}; | |||
/** Adds a listener to be called when the value changes. */ | |||
void addListener (Listener* listener) { listeners.add (listener); } | |||
/** Removes a previously-registered listener. */ | |||
void removeListener (Listener* listener) { listeners.remove (listener); } | |||
//============================================================================== | |||
/** The behaviour object. | |||
This is public to let you tweak any parameters that it provides. | |||
*/ | |||
Behaviour behaviour; | |||
private: | |||
//============================================================================== | |||
double position, grabbedPos, releaseVelocity; | |||
Range<double> range; | |||
Time lastUpdate, lastDrag; | |||
ListenerList<Listener> listeners; | |||
static double getSpeed (const Time last, double lastPos, | |||
const Time now, double newPos) | |||
{ | |||
const double elapsedSecs = jmax (0.005, (now - last).inSeconds()); | |||
const double v = (newPos - lastPos) / elapsedSecs; | |||
return std::abs (v) > 0.2 ? v : 0.0; | |||
} | |||
void moveTo (double newPos) | |||
{ | |||
const Time now (Time::getCurrentTime()); | |||
releaseVelocity = getSpeed (lastDrag, position, now, newPos); | |||
behaviour.releasedWithVelocity (newPos, releaseVelocity); | |||
lastDrag = now; | |||
setPositionAndSendChange (newPos); | |||
} | |||
void setPositionAndSendChange (double newPosition) | |||
{ | |||
newPosition = range.clipValue (newPosition); | |||
if (position != newPosition) | |||
{ | |||
position = newPosition; | |||
listeners.call (&Listener::positionChanged, *this, newPosition); | |||
} | |||
} | |||
void timerCallback() override | |||
{ | |||
const Time now = Time::getCurrentTime(); | |||
const double elapsed = jlimit (0.001, 0.020, (now - lastUpdate).inSeconds()); | |||
lastUpdate = now; | |||
const double newPos = behaviour.getNextPosition (position, elapsed); | |||
if (behaviour.isStopped (newPos)) | |||
stopTimer(); | |||
else | |||
startTimer (1000 / 60); | |||
setPositionAndSendChange (newPos); | |||
} | |||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AnimatedPosition) | |||
}; | |||
#endif // __JUCE_ANIMATEDPOSITION_JUCEHEADER__ |
@@ -0,0 +1,149 @@ | |||
/* | |||
============================================================================== | |||
This file is part of the JUCE library. | |||
Copyright (c) 2013 - Raw Material Software Ltd. | |||
Permission is granted to use this software under the terms of either: | |||
a) the GPL v2 (or any later version) | |||
b) the Affero GPL v3 | |||
Details of these licenses can be found at: www.gnu.org/licenses | |||
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY | |||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR | |||
A PARTICULAR PURPOSE. See the GNU General Public License for more details. | |||
------------------------------------------------------------------------------ | |||
To release a closed-source product which uses JUCE, commercial licenses are | |||
available: visit www.juce.com for more information. | |||
============================================================================== | |||
*/ | |||
#ifndef __JUCE_ANIMATEDPOSITIONBEHAVIOURS_JUCEHEADER__ | |||
#define __JUCE_ANIMATEDPOSITIONBEHAVIOURS_JUCEHEADER__ | |||
//============================================================================== | |||
/** Contains classes for different types of physics behaviours - these classes | |||
are used as template parameters for the AnimatedPosition class. | |||
*/ | |||
namespace AnimatedPositionBehaviours | |||
{ | |||
/** A non-snapping behaviour that allows the content to be freely flicked in | |||
either direction, with momentum based on the velocity at which it was | |||
released, and variable friction to make it come to a halt. | |||
This class is intended to be used as a template parameter to the | |||
AnimatedPosition class. | |||
@see AnimatedPosition | |||
*/ | |||
struct ContinuousWithMomentum | |||
{ | |||
ContinuousWithMomentum() noexcept | |||
: velocity (0), damping (0.92) | |||
{ | |||
} | |||
/** Sets the friction that damps the movement of the value. | |||
A typical value is 0.08; higher values indicate more friction. | |||
*/ | |||
void setFriction (double newFriction) noexcept | |||
{ | |||
damping = 1.0 - newFriction; | |||
} | |||
/** Called by the AnimatedPosition class. This tells us the position and | |||
velocity at which the user is about to release the object. | |||
The velocity is measured in units/second. | |||
*/ | |||
void releasedWithVelocity (double /*position*/, double releaseVelocity) noexcept | |||
{ | |||
velocity = releaseVelocity; | |||
} | |||
/** Called by the AnimatedPosition class to get the new position, after | |||
the given time has elapsed. | |||
*/ | |||
double getNextPosition (double oldPos, double elapsedSeconds) noexcept | |||
{ | |||
velocity *= damping; | |||
if (std::abs (velocity) < 0.05) | |||
velocity = 0; | |||
return oldPos + velocity * elapsedSeconds; | |||
} | |||
/** Called by the AnimatedPosition class to check whether the object | |||
is now stationary. | |||
*/ | |||
bool isStopped (double /*position*/) const noexcept | |||
{ | |||
return velocity == 0; | |||
} | |||
private: | |||
double velocity, damping; | |||
}; | |||
//============================================================================== | |||
/** A behaviour that gravitates an AnimatedPosition object towards the nearest | |||
integer position when released. | |||
This class is intended to be used as a template parameter to the | |||
AnimatedPosition class. It's handy when using an AnimatedPosition to show a | |||
series of pages, because it allows the pages can be scrolled smoothly, but when | |||
released, snaps back to show a whole page. | |||
@see AnimatedPosition | |||
*/ | |||
struct SnapToPageBoundaries | |||
{ | |||
SnapToPageBoundaries() noexcept : targetSnapPosition() | |||
{ | |||
} | |||
/** Called by the AnimatedPosition class. This tells us the position and | |||
velocity at which the user is about to release the object. | |||
The velocity is measured in units/second. | |||
*/ | |||
void releasedWithVelocity (double position, double releaseVelocity) noexcept | |||
{ | |||
targetSnapPosition = std::floor (position + 0.5); | |||
if (releaseVelocity > 1.0 && targetSnapPosition < position) ++targetSnapPosition; | |||
if (releaseVelocity < -1.0 && targetSnapPosition > position) --targetSnapPosition; | |||
} | |||
/** Called by the AnimatedPosition class to get the new position, after | |||
the given time has elapsed. | |||
*/ | |||
double getNextPosition (double oldPos, double elapsedSeconds) const noexcept | |||
{ | |||
if (isStopped (oldPos)) | |||
return targetSnapPosition; | |||
const double snapSpeed = 10.0; | |||
const double velocity = (targetSnapPosition - oldPos) * snapSpeed; | |||
return oldPos + velocity * elapsedSeconds; | |||
} | |||
/** Called by the AnimatedPosition class to check whether the object | |||
is now stationary. | |||
*/ | |||
bool isStopped (double position) const noexcept | |||
{ | |||
return std::abs (targetSnapPosition - position) < 0.001; | |||
} | |||
private: | |||
double targetSnapPosition; | |||
}; | |||
}; | |||
#endif // __JUCE_ANIMATEDPOSITIONBEHAVIOURS_JUCEHEADER__ |
@@ -0,0 +1,70 @@ | |||
/* | |||
============================================================================== | |||
This file is part of the JUCE library. | |||
Copyright (c) 2013 - Raw Material Software Ltd. | |||
Permission is granted to use this software under the terms of either: | |||
a) the GPL v2 (or any later version) | |||
b) the Affero GPL v3 | |||
Details of these licenses can be found at: www.gnu.org/licenses | |||
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY | |||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR | |||
A PARTICULAR PURPOSE. See the GNU General Public License for more details. | |||
------------------------------------------------------------------------------ | |||
To release a closed-source product which uses JUCE, commercial licenses are | |||
available: visit www.juce.com for more information. | |||
============================================================================== | |||
*/ | |||
MouseInactivityDetector::MouseInactivityDetector (Component& c) | |||
: targetComp (c), delayMs (1500), isActive (true) | |||
{ | |||
targetComp.addMouseListener (this, true); | |||
} | |||
MouseInactivityDetector::~MouseInactivityDetector() | |||
{ | |||
targetComp.removeMouseListener (this); | |||
} | |||
void MouseInactivityDetector::setDelay (int newDelayMilliseconds) | |||
{ | |||
delayMs = newDelayMilliseconds; | |||
} | |||
void MouseInactivityDetector::addListener (Listener* l) { listenerList.add (l); } | |||
void MouseInactivityDetector::removeListener (Listener* l) { listenerList.remove (l); } | |||
void MouseInactivityDetector::timerCallback() | |||
{ | |||
setActive (false); | |||
} | |||
void MouseInactivityDetector::wakeUp (const MouseEvent& e, bool alwaysWake) | |||
{ | |||
const Point<int> newPos (e.getEventRelativeTo (&targetComp).getPosition()); | |||
if ((! isActive) && (alwaysWake || e.source.isTouch() || newPos.getDistanceFrom (lastMousePos) > 15)) | |||
setActive (true); | |||
lastMousePos = newPos; | |||
startTimer (delayMs); | |||
} | |||
void MouseInactivityDetector::setActive (bool b) | |||
{ | |||
if (isActive != b) | |||
{ | |||
isActive = b; | |||
listenerList.call (b ? &Listener::mouseBecameActive | |||
: &Listener::mouseBecameInactive); | |||
} | |||
} |
@@ -0,0 +1,105 @@ | |||
/* | |||
============================================================================== | |||
This file is part of the JUCE library. | |||
Copyright (c) 2013 - Raw Material Software Ltd. | |||
Permission is granted to use this software under the terms of either: | |||
a) the GPL v2 (or any later version) | |||
b) the Affero GPL v3 | |||
Details of these licenses can be found at: www.gnu.org/licenses | |||
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY | |||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR | |||
A PARTICULAR PURPOSE. See the GNU General Public License for more details. | |||
------------------------------------------------------------------------------ | |||
To release a closed-source product which uses JUCE, commercial licenses are | |||
available: visit www.juce.com for more information. | |||
============================================================================== | |||
*/ | |||
#ifndef __JUCE_MOUSEINACTIVITYDETECTOR_JUCEHEADER__ | |||
#define __JUCE_MOUSEINACTIVITYDETECTOR_JUCEHEADER__ | |||
//============================================================================== | |||
/** | |||
This object watches for mouse-events happening within a component, and if | |||
the mouse remains still for long enough, triggers an event to indicate that | |||
it has become inactive. | |||
You'd use this for situations where e.g. you want to hide the mouse-cursor | |||
when the user's not actively using the mouse. | |||
After creating an instance of this, use addListener to get callbacks when | |||
the activity status changes. | |||
*/ | |||
class JUCE_API MouseInactivityDetector : private Timer, | |||
private MouseListener | |||
{ | |||
public: | |||
/** Creates an inactivity watcher, attached to the given component. | |||
The target component must not be deleted while this - it will be monitored | |||
for any mouse events in it or its child components. | |||
*/ | |||
MouseInactivityDetector (Component& target); | |||
/** Destructor. */ | |||
~MouseInactivityDetector(); | |||
/** Sets the time for which the mouse must be still before the callback | |||
is triggered. | |||
*/ | |||
void setDelay (int newDelayMilliseconds); | |||
//============================================================================== | |||
/** Classes should implement this to receive callbacks from a MouseInactivityDetector | |||
when the mouse becomes active or inactive. | |||
*/ | |||
class Listener | |||
{ | |||
public: | |||
virtual ~Listener() {} | |||
/** Called when the mouse is moved or clicked for the first time | |||
after a period of inactivity. */ | |||
virtual void mouseBecameActive() = 0; | |||
/** Called when the mouse hasn't been moved for the timeout period. */ | |||
virtual void mouseBecameInactive() = 0; | |||
}; | |||
/** Registers a listener. */ | |||
void addListener (Listener* listener); | |||
/** Removes a previously-registered listener. */ | |||
void removeListener (Listener* listener); | |||
private: | |||
//============================================================================== | |||
Component& targetComp; | |||
ListenerList<Listener> listenerList; | |||
Point<int> lastMousePos; | |||
int delayMs; | |||
bool isActive; | |||
void timerCallback() override; | |||
void wakeUp (const MouseEvent&, bool alwaysWake); | |||
void setActive (bool); | |||
void mouseMove (const MouseEvent& e) override { wakeUp (e, false); } | |||
void mouseEnter (const MouseEvent& e) override { wakeUp (e, false); } | |||
void mouseExit (const MouseEvent& e) override { wakeUp (e, false); } | |||
void mouseDown (const MouseEvent& e) override { wakeUp (e, true); } | |||
void mouseDrag (const MouseEvent& e) override { wakeUp (e, true); } | |||
void mouseUp (const MouseEvent& e) override { wakeUp (e, true); } | |||
void mouseWheelMove (const MouseEvent& e, const MouseWheelDetails&) override { wakeUp (e, true); } | |||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MouseInactivityDetector) | |||
}; | |||
#endif // __JUCE_MOUSEINACTIVITYDETECTOR_JUCEHEADER__ |