| @@ -22,7 +22,7 @@ | |||||
| ============================================================================== | ============================================================================== | ||||
| */ | */ | ||||
| #ifndef __JUCE_GRAPHICS_MODULE_JUCEHEADER__ | |||||
| #ifndef __JUCE_GRAPHICS_MODULE_JUCEHEADER__ // %% | |||||
| #define __JUCE_GRAPHICS_MODULE_JUCEHEADER__ | #define __JUCE_GRAPHICS_MODULE_JUCEHEADER__ | ||||
| #include "../juce_core/juce_core.h" | #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_DragAndDropContainer.cpp" | ||||
| #include "mouse/juce_MouseCursor.cpp" | #include "mouse/juce_MouseCursor.cpp" | ||||
| #include "mouse/juce_MouseEvent.cpp" | #include "mouse/juce_MouseEvent.cpp" | ||||
| #include "mouse/juce_MouseInactivityDetector.cpp" | |||||
| #include "mouse/juce_MouseInputSource.cpp" | #include "mouse/juce_MouseInputSource.cpp" | ||||
| #include "mouse/juce_MouseListener.cpp" | #include "mouse/juce_MouseListener.cpp" | ||||
| #include "keyboard/juce_CaretComponent.cpp" | #include "keyboard/juce_CaretComponent.cpp" | ||||
| @@ -111,6 +111,9 @@ namespace juce | |||||
| #ifndef __JUCE_MOUSEEVENT_JUCEHEADER__ | #ifndef __JUCE_MOUSEEVENT_JUCEHEADER__ | ||||
| #include "mouse/juce_MouseEvent.h" | #include "mouse/juce_MouseEvent.h" | ||||
| #endif | #endif | ||||
| #ifndef __JUCE_MOUSEINACTIVITYDETECTOR_JUCEHEADER__ | |||||
| #include "mouse/juce_MouseInactivityDetector.h" | |||||
| #endif | |||||
| #ifndef __JUCE_MOUSEINPUTSOURCE_JUCEHEADER__ | #ifndef __JUCE_MOUSEINPUTSOURCE_JUCEHEADER__ | ||||
| #include "mouse/juce_MouseInputSource.h" | #include "mouse/juce_MouseInputSource.h" | ||||
| #endif | #endif | ||||
| @@ -240,6 +243,12 @@ namespace juce | |||||
| #ifndef __JUCE_WILDCARDFILEFILTER_JUCEHEADER__ | #ifndef __JUCE_WILDCARDFILEFILTER_JUCEHEADER__ | ||||
| #include "filebrowser/juce_WildcardFileFilter.h" | #include "filebrowser/juce_WildcardFileFilter.h" | ||||
| #endif | #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__ | #ifndef __JUCE_COMPONENTANIMATOR_JUCEHEADER__ | ||||
| #include "layout/juce_ComponentAnimator.h" | #include "layout/juce_ComponentAnimator.h" | ||||
| #endif | #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__ | |||||