text:
/*
  ==============================================================================

   This file is part of the JUCE library.
   Copyright (c) 2017 - ROLI Ltd.

   JUCE is an open source library subject to commercial or open-source
   licensing.

   By using JUCE, you agree to the terms of both the JUCE 5 End-User License
   Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
   27th April 2017).

   End User License Agreement: www.juce.com/juce-5-licence
   Privacy Policy: www.juce.com/juce-5-privacy-policy

   Or: You may also use this code under the terms of the GPL v3 (see
   www.gnu.org/licenses).

   JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
   EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
   DISCLAIMED.

  ==============================================================================
*/

namespace juce
{

//==============================================================================
/**
    A class used by the LassoComponent to manage the things that it selects.

    This allows the LassoComponent to find out which items are within the lasso,
    and to change the list of selected items.

    @see LassoComponent, SelectedItemSet
*/
template <class SelectableItemType>
class LassoSource
{
public:
    /** Destructor. */
    virtual ~LassoSource() {}

    /** Returns the set of items that lie within a given lassoable region.

        Your implementation of this method must find all the relevant items that lie
        within the given rectangle. and add them to the itemsFound array.

        The coordinates are relative to the top-left of the lasso component's parent
        component. (i.e. they are the same as the size and position of the lasso
        component itself).
    */
    virtual void findLassoItemsInArea (Array<SelectableItemType>& itemsFound,
                                       const Rectangle<int>& area) = 0;

    /** Returns the SelectedItemSet that the lasso should update.

        This set will be continuously updated by the LassoComponent as it gets
        dragged around, so make sure that you've got a ChangeListener attached to
        the set so that your UI objects will know when the selection changes and
        be able to update themselves appropriately.
    */
    virtual SelectedItemSet<SelectableItemType>& getLassoSelection() = 0;
};

//==============================================================================
/**
    A component that acts as a rectangular selection region, which you drag with
    the mouse to select groups of objects (in conjunction with a SelectedItemSet).

    To use one of these:

    - In your mouseDown or mouseDrag event, add the LassoComponent to your parent
      component, and call its beginLasso() method, giving it a
      suitable LassoSource object that it can use to find out which items are in
      the active area.

    - Each time your parent component gets a mouseDrag event, call dragLasso()
      to update the lasso's position - it will use its LassoSource to calculate and
      update the current selection.

    - After the drag has finished and you get a mouseUp callback, you should call
      endLasso() to clean up. This will make the lasso component invisible, and you
      can remove it from the parent component, or delete it.

    The class takes into account the modifier keys that are being held down while
    the lasso is being dragged, so if shift is pressed, then any lassoed items will
    be added to the original selection; if ctrl or command is pressed, they will be
    xor'ed with any previously selected items.

    @see LassoSource, SelectedItemSet
*/
template <class SelectableItemType>
class LassoComponent  : public Component
{
public:
    //==============================================================================
    /** Creates a Lasso component. */
    LassoComponent() {}

    //==============================================================================
    /** Call this in your mouseDown event, to initialise a drag.

        Pass in a suitable LassoSource object which the lasso will use to find
        the items and change the selection.

        After using this method to initialise the lasso, repeatedly call dragLasso()
        in your component's mouseDrag callback.

        @see dragLasso, endLasso, LassoSource
    */
    void beginLasso (const MouseEvent& e, LassoSource<SelectableItemType>* lassoSource)
    {
        jassert (source == nullptr);  // this suggests that you didn't call endLasso() after the last drag...
        jassert (lassoSource != nullptr); // the source can't be null!
        jassert (getParentComponent() != nullptr);  // you need to add this to a parent component for it to work!

        source = lassoSource;

        if (lassoSource != nullptr)
            originalSelection = lassoSource->getLassoSelection().getItemArray();

        setSize (0, 0);
        dragStartPos = e.getMouseDownPosition();
    }

    /** Call this in your mouseDrag event, to update the lasso's position.

        This must be repeatedly calling when the mouse is dragged, after you've
        first initialised the lasso with beginLasso().

        This method takes into account the modifier keys that are being held down, so
        if shift is pressed, then the lassoed items will be added to any that were
        previously selected; if ctrl or command is pressed, then they will be xor'ed
        with previously selected items.

        @see beginLasso, endLasso
    */
    void dragLasso (const MouseEvent& e)
    {
        if (source != nullptr)
        {
            setBounds (Rectangle<int> (dragStartPos, e.getPosition()));
            setVisible (true);

            Array<SelectableItemType> itemsInLasso;
            source->findLassoItemsInArea (itemsInLasso, getBounds());

            if (e.mods.isShiftDown())
            {
                itemsInLasso.removeValuesIn (originalSelection); //  to avoid duplicates
                itemsInLasso.addArray (originalSelection);
            }
            else if (e.mods.isCommandDown() || e.mods.isAltDown())
            {
                auto originalMinusNew = originalSelection;
                originalMinusNew.removeValuesIn (itemsInLasso);

                itemsInLasso.removeValuesIn (originalSelection);
                itemsInLasso.addArray (originalMinusNew);
            }

            source->getLassoSelection() = SelectedItemSet<SelectableItemType> (itemsInLasso);
        }
    }

    /** Call this in your mouseUp event, after the lasso has been dragged.
        @see beginLasso, dragLasso
    */
    void endLasso()
    {
        source = nullptr;
        originalSelection.clear();
        setVisible (false);
    }

    //==============================================================================
    /** A set of colour IDs to use to change the colour of various aspects of the label.

        These constants can be used either via the Component::setColour(), or LookAndFeel::setColour()
        methods.

        Note that you can also use the constants from TextEditor::ColourIds to change the
        colour of the text editor that is opened when a label is editable.

        @see Component::setColour, Component::findColour, LookAndFeel::setColour, LookAndFeel::findColour
    */
    enum ColourIds
    {
        lassoFillColourId       = 0x1000440, /**< The colour to fill the lasso rectangle with. */
        lassoOutlineColourId    = 0x1000441, /**< The colour to draw the outline with. */
    };

    //==============================================================================
    /** @internal */
    void paint (Graphics& g) override
    {
        getLookAndFeel().drawLasso (g, *this);

        // this suggests that you've left a lasso comp lying around after the
        // mouse drag has finished.. Be careful to call endLasso() when you get a
        // mouse-up event.
        jassert (isMouseButtonDownAnywhere());
    }

    /** @internal */
    bool hitTest (int, int) override        { return false; }

private:
    //==============================================================================
    Array<SelectableItemType> originalSelection;
    LassoSource<SelectableItemType>* source = nullptr;
    Point<int> dragStartPos;

    JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (LassoComponent)
};

} // namespace juce


text:
/*
  ==============================================================================

   This file is part of the JUCE library.
   Copyright (c) 2017 - ROLI Ltd.

   JUCE is an open source library subject to commercial or open-source
   licensing.

   By using JUCE, you agree to the terms of both the JUCE 5 End-User License
   Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
   27th April 2017).

   End User License Agreement: www.juce.com/juce-5-licence
   Privacy Policy: www.juce.com/juce-5-privacy-policy

   Or: You may also use this code under the terms of the GPL v3 (see
   www.gnu.org/licenses).

   JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
   EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
   DISCLAIMED.

  ==============================================================================
*/

namespace juce
{

MouseEvent::MouseEvent (MouseInputSource inputSource,
                        Point<float> pos,
                        ModifierKeys modKeys,
                        float force,
                        float o, float r,
                        float tX, float tY,
                        Component* const eventComp,
                        Component* const originator,
                        Time time,
                        Point<float> downPos,
                        Time downTime,
                        const int numClicks,
                        const bool mouseWasDragged) noexcept
    : position (pos),
      x (roundToInt (pos.x)),
      y (roundToInt (pos.y)),
      mods (modKeys),
      pressure (force),
      orientation (o), rotation (r),
      tiltX (tX), tiltY (tY),
      eventComponent (eventComp),
      originalComponent (originator),
      eventTime (time),
      mouseDownTime (downTime),
      source (inputSource),
      mouseDownPos (downPos),
      numberOfClicks ((uint8) numClicks),
      wasMovedSinceMouseDown ((uint8) (mouseWasDragged ? 1 : 0))
{
}

MouseEvent::~MouseEvent() noexcept
{
}

//==============================================================================
MouseEvent MouseEvent::getEventRelativeTo (Component* const otherComponent) const noexcept
{
    jassert (otherComponent != nullptr);

    return MouseEvent (source, otherComponent->getLocalPoint (eventComponent, position),
                       mods, pressure, orientation, rotation, tiltX, tiltY,
                       otherComponent, originalComponent, eventTime,
                       otherComponent->getLocalPoint (eventComponent, mouseDownPos),
                       mouseDownTime, numberOfClicks, wasMovedSinceMouseDown != 0);
}

MouseEvent MouseEvent::withNewPosition (Point<float> newPosition) const noexcept
{
    return MouseEvent (source, newPosition, mods, pressure, orientation, rotation, tiltX, tiltY,
                       eventComponent, originalComponent, eventTime, mouseDownPos, mouseDownTime,
                       numberOfClicks, wasMovedSinceMouseDown != 0);
}

MouseEvent MouseEvent::withNewPosition (Point<int> newPosition) const noexcept
{
    return MouseEvent (source, newPosition.toFloat(), mods, pressure, orientation, rotation,
                       tiltX, tiltY, eventComponent,  originalComponent, eventTime, mouseDownPos,
                       mouseDownTime, numberOfClicks, wasMovedSinceMouseDown != 0);
}

//==============================================================================
bool MouseEvent::mouseWasDraggedSinceMouseDown() const noexcept
{
    return wasMovedSinceMouseDown != 0;
}

bool MouseEvent::mouseWasClicked() const noexcept
{
    return ! mouseWasDraggedSinceMouseDown();
}

int MouseEvent::getLengthOfMousePress() const noexcept
{
    if (mouseDownTime.toMilliseconds() > 0)
        return jmax (0, (int) (eventTime - mouseDownTime).inMilliseconds());

    return 0;
}

//==============================================================================
Point<int> MouseEvent::getPosition() const noexcept             { return Point<int> (x, y); }
Point<int> MouseEvent::getScreenPosition() const                { return eventComponent->localPointToGlobal (getPosition()); }

Point<int> MouseEvent::getMouseDownPosition() const noexcept    { return mouseDownPos.roundToInt(); }
Point<int> MouseEvent::getMouseDownScreenPosition() const       { return eventComponent->localPointToGlobal (mouseDownPos).roundToInt(); }

Point<int> MouseEvent::getOffsetFromDragStart() const noexcept  { return (position - mouseDownPos).roundToInt(); }
int MouseEvent::getDistanceFromDragStart() const noexcept       { return roundToInt (mouseDownPos.getDistanceFrom (position)); }

int MouseEvent::getMouseDownX() const noexcept                  { return roundToInt (mouseDownPos.x); }
int MouseEvent::getMouseDownY() const noexcept                  { return roundToInt (mouseDownPos.y); }

int MouseEvent::getDistanceFromDragStartX() const noexcept      { return getOffsetFromDragStart().x; }
int MouseEvent::getDistanceFromDragStartY() const noexcept      { return getOffsetFromDragStart().y; }

int MouseEvent::getScreenX() const                              { return getScreenPosition().x; }
int MouseEvent::getScreenY() const                              { return getScreenPosition().y; }

int MouseEvent::getMouseDownScreenX() const                     { return getMouseDownScreenPosition().x; }
int MouseEvent::getMouseDownScreenY() const                     { return getMouseDownScreenPosition().y; }

bool MouseEvent::isPressureValid() const noexcept               { return pressure > 0.0f && pressure < 1.0f; }
bool MouseEvent::isOrientationValid() const noexcept            { return orientation >= 0.0f && orientation <= 2.0f * float_Pi; }
bool MouseEvent::isRotationValid() const noexcept               { return rotation >= 0 && rotation <= 2.0f * float_Pi; }
bool MouseEvent::isTiltValid (bool isX) const noexcept          { return isX ? (tiltX >= -1.0f && tiltX <= 1.0f) : (tiltY >= -1.0f && tiltY <= 1.0f); }

//==============================================================================
static int doubleClickTimeOutMs = 400;

int MouseEvent::getDoubleClickTimeout() noexcept                        { return doubleClickTimeOutMs; }
void MouseEvent::setDoubleClickTimeout (const int newTime) noexcept     { doubleClickTimeOutMs = newTime; }

} // namespace juce

repo_name: fedden/RenderMan

mime_type: text/x-c++


text:
/*
  ==============================================================================

   This file is part of the JUCE library.
   Copyright (c) 2017 - ROLI Ltd.

   JUCE is an open source library subject to commercial or open-source
   licensing.

   By using JUCE, you agree to the terms of both the JUCE 5 End-User License
   Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
   27th April 2017).

   End User License Agreement: www.juce.com/juce-5-licence
   Privacy Policy: www.juce.com/juce-5-privacy-policy

   Or: You may also use this code under the terms of the GPL v3 (see
   www.gnu.org/licenses).

   JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
   EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
   DISCLAIMED.

  ==============================================================================
*/

namespace juce
{

//==============================================================================
/** Manages a list of selectable items.

    Use one of these to keep a track of things that the user has highlighted, like
    icons or things in a list.

    The class is templated so that you can use it to hold either a set of pointers
    to objects, or a set of ID numbers or handles, for cases where each item may
    not always have a corresponding object.

    To be informed when items are selected/deselected, register a ChangeListener with
    this object.
*/
template <class SelectableItemType>
class SelectedItemSet   : public ChangeBroadcaster
{
public:
    //==============================================================================
    typedef SelectableItemType ItemType;
    typedef Array<SelectableItemType> ItemArray;
    typedef typename TypeHelpers::ParameterType<SelectableItemType>::type ParameterType;

    //==============================================================================
    /** Creates an empty set. */
    SelectedItemSet()
    {
    }

    /** Creates a set based on an array of items. */
    explicit SelectedItemSet (const ItemArray& items)
        : selectedItems (items)
    {
    }

    /** Creates a copy of another set. */
    SelectedItemSet (const SelectedItemSet& other)
        : selectedItems (other.selectedItems)
    {
    }

    /** Creates a copy of another set. */
    SelectedItemSet& operator= (const SelectedItemSet& other)
    {
        if (selectedItems != other.selectedItems)
        {
            changed();

            for (int i = selectedItems.size(); --i >= 0;)
                if (! other.isSelected (selectedItems.getReference (i)))
                    itemDeselected (selectedItems.removeAndReturn (i));

            for (SelectableItemType* i = other.selectedItems.begin(), *e = other.selectedItems.end(); i != e; ++i)
            {
                if (! isSelected (*i))
                {
                    selectedItems.add (*i);
                    itemSelected (*i);
                }
            }
        }

        return *this;
    }

    //==============================================================================
    /** Clears any other currently selected items, and selects this item.

        If this item is already the only thing selected, no change notification
        will be sent out.

        @see addToSelection, addToSelectionBasedOnModifiers
    */
    void selectOnly (ParameterType item)
    {
        if (isSelected (item))
        {
            for (int i = selectedItems.size(); --i >= 0;)
            {
                if (selectedItems.getUnchecked(i) != item)
                {
                    deselect (selectedItems.getUnchecked(i));
                    i = jmin (i, selectedItems.size());
                }
            }
        }
        else
        {
            changed();
            deselectAll();

            selectedItems.add (item);
            itemSelected (item);
        }
    }

    /** Selects an item.
        If the item is already selected, no change notification will be sent out.
        @see selectOnly, addToSelectionBasedOnModifiers
    */
    void addToSelection (ParameterType item)
    {
        if (! isSelected (item))
        {
            changed();

            selectedItems.add (item);
            itemSelected (item);
        }
    }

    /** Selects or deselects an item.

        This will use the modifier keys to decide whether to deselect other items
        first.

        So if the shift key is held down, the item will be added without deselecting
        anything (same as calling addToSelection() )

        If no modifiers are down, the current selection will be cleared first (same
        as calling selectOnly() )

        If the ctrl (or command on the Mac) key is held down, the item will be toggled -
        so it'll be added to the set unless it's already there, in which case it'll be
        deselected.

        If the items that you're selecting can also be dragged, you may need to use the
        addToSelectionOnMouseDown() and addToSelectionOnMouseUp() calls to handle the
        subtleties of this kind of usage.

        @see selectOnly, addToSelection, addToSelectionOnMouseDown, addToSelectionOnMouseUp
    */
    void addToSelectionBasedOnModifiers (ParameterType item,
                                         ModifierKeys modifiers)
    {
        if (modifiers.isShiftDown())
        {
            addToSelection (item);
        }
        else if (modifiers.isCommandDown())
        {
            if (isSelected (item))
                deselect (item);
            else
                addToSelection (item);
        }
        else
        {
            selectOnly (item);
        }
    }

    /** Selects or deselects items that can also be dragged, based on a mouse-down event.

        If you call addToSelectionOnMouseDown() at the start of your mouseDown event,
        and then call addToSelectionOnMouseUp() at the end of your mouseUp event, this
        makes it easy to handle multiple-selection of sets of objects that can also
        be dragged.

        For example, if you have several items already selected, and you click on
        one of them (without dragging), then you'd expect this to deselect the other, and
        just select the item you clicked on. But if you had clicked on this item and
        dragged it, you'd have expected them all to stay selected.

        When you call this method, you'll need to store the boolean result, because the
        addToSelectionOnMouseUp() method will need to be know this value.

        @see addToSelectionOnMouseUp, addToSelectionBasedOnModifiers
    */
    bool addToSelectionOnMouseDown (ParameterType item,
                                    ModifierKeys modifiers)
    {
        if (isSelected (item))
            return ! modifiers.isPopupMenu();

        addToSelectionBasedOnModifiers (item, modifiers);
        return false;
    }

    /** Selects or deselects items that can also be dragged, based on a mouse-up event.

        Call this during a mouseUp callback, when you have previously called the
        addToSelectionOnMouseDown() method during your mouseDown event.

        See addToSelectionOnMouseDown() for more info

        @param item             the item to select (or deselect)
        @param modifiers        the modifiers from the mouse-up event
        @param wasItemDragged   true if your item was dragged during the mouse click
        @param resultOfMouseDownSelectMethod    this is the boolean return value that came
                                back from the addToSelectionOnMouseDown() call that you
                                should have made during the matching mouseDown event
    */
    void addToSelectionOnMouseUp (ParameterType item,
                                  ModifierKeys modifiers,
                                  const bool wasItemDragged,
                                  const bool resultOfMouseDownSelectMethod)
    {
        if (resultOfMouseDownSelectMethod && ! wasItemDragged)
            addToSelectionBasedOnModifiers (item, modifiers);
    }

    /** Deselects an item. */
    void deselect (ParameterType item)
    {
        const int i = selectedItems.indexOf (item);

        if (i >= 0)
        {
            changed();
            itemDeselected (selectedItems.removeAndReturn (i));
        }
    }

    /** Deselects all items. */
    void deselectAll()
    {
        if (selectedItems.size() > 0)
        {
            changed();

            for (int i = selectedItems.size(); --i >= 0;)
            {
                itemDeselected (selectedItems.removeAndReturn (i));
                i = jmin (i, selectedItems.size());
            }
        }
    }

    //==============================================================================
    /** Returns the number of currently selected items.
        @see getSelectedItem
    */
    int getNumSelected() const noexcept                         { return selectedItems.size(); }

    /** Returns one of the currently selected items.
        If the index is out-of-range, this returns a default-constructed SelectableItemType.
        @see getNumSelected
    */
    SelectableItemType getSelectedItem (const int index) const  { return selectedItems [index]; }

    /** True if this item is currently selected. */
    bool isSelected (ParameterType item) const noexcept         { return selectedItems.contains (item); }

    /** Provides access to the array of items. */
    const ItemArray& getItemArray() const noexcept              { return selectedItems; }

    /** Provides iterator access to the array of items. */
    SelectableItemType* begin() const noexcept                  { return selectedItems.begin(); }

    /** Provides iterator access to the array of items. */
    SelectableItemType* end() const noexcept                    { return selectedItems.end(); }

    //==============================================================================
    /** Can be overridden to do special handling when an item is selected.

        For example, if the item is an object, you might want to call it and tell
        it that it's being selected.
    */
    virtual void itemSelected (SelectableItemType)              {}

    /** Can be overridden to do special handling when an item is deselected.

        For example, if the item is an object, you might want to call it and tell
        it that it's being deselected.
    */
    virtual void itemDeselected (SelectableItemType)            {}

    /** Used internally, but can be called to force a change message to be sent
        to the ChangeListeners.
    */
    void changed()
    {
        sendChangeMessage();
    }

    /** Used internally, but can be called to force a change message to be sent
        to the ChangeListeners.
    */
    void changed (const bool synchronous)
    {
        if (synchronous)
            sendSynchronousChangeMessage();
        else
            sendChangeMessage();
    }

private:
    //==============================================================================
    ItemArray selectedItems;

    JUCE_LEAK_DETECTOR (SelectedItemSet<SelectableItemType>)
};

} // namespace juce


text:
/*
  ==============================================================================

   This file is part of the JUCE library.
   Copyright (c) 2017 - ROLI Ltd.

   JUCE is an open source library subject to commercial or open-source
   licensing.

   By using JUCE, you agree to the terms of both the JUCE 5 End-User License
   Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
   27th April 2017).

   End User License Agreement: www.juce.com/juce-5-licence
   Privacy Policy: www.juce.com/juce-5-privacy-policy

   Or: You may also use this code under the terms of the GPL v3 (see
   www.gnu.org/licenses).

   JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
   EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
   DISCLAIMED.

  ==============================================================================
*/

namespace juce
{

//==============================================================================
/**
    Contains position and status information about a mouse event.

    @see MouseListener, Component::mouseMove, Component::mouseEnter, Component::mouseExit,
         Component::mouseDown, Component::mouseUp, Component::mouseDrag
*/
class JUCE_API  MouseEvent  final
{
public:
    //==============================================================================
    /** Creates a MouseEvent.

        Normally an application will never need to use this.

        @param source           the source that's invoking the event
        @param position         the position of the mouse, relative to the component that is passed-in
        @param modifiers        the key modifiers at the time of the event
        @param pressure         the pressure of the touch or stylus, in the range 0 to 1. Devices that
                                do not support force information may return 0.0, 1.0, or a negative value,
                                depending on the platform
        @param orientation      the orientation of the touch input for this event in radians. The default is 0
        @param rotation         the rotation of the pen device for this event in radians. The default is 0
        @param tiltX            the tilt of the pen device along the x-axis between -1.0 and 1.0. The default is 0
        @param tiltY            the tilt of the pen device along the y-axis between -1.0 and 1.0. The default is 0
        @param eventComponent   the component that the mouse event applies to
        @param originator       the component that originally received the event
        @param eventTime        the time the event happened
        @param mouseDownPos     the position of the corresponding mouse-down event (relative to the component that is passed-in).
                                If there isn't a corresponding mouse-down (e.g. for a mouse-move), this will just be
                                the same as the current mouse-x position.
        @param mouseDownTime    the time at which the corresponding mouse-down event happened
                                If there isn't a corresponding mouse-down (e.g. for a mouse-move), this will just be
                                the same as the current mouse-event time.
        @param numberOfClicks   how many clicks, e.g. a double-click event will be 2, a triple-click will be 3, etc
        @param mouseWasDragged  whether the mouse has been dragged significantly since the previous mouse-down
    */
    MouseEvent (MouseInputSource source,
                Point<float> position,
                ModifierKeys modifiers,
                float pressure,
                float orientation, float rotation,
                float tiltX, float tiltY,
                Component* eventComponent,
                Component* originator,
                Time eventTime,
                Point<float> mouseDownPos,
                Time mouseDownTime,
                int numberOfClicks,
                bool mouseWasDragged) noexcept;

    /** Destructor. */
    ~MouseEvent() noexcept;

    //==============================================================================
    /** The position of the mouse when the event occurred.

        This value is relative to the top-left of the component to which the
        event applies (as indicated by the MouseEvent::eventComponent field).

        This is a more accurate floating-point version of the position returned by
        getPosition() and the integer x and y member variables.
    */
    const Point<float> position;

    /** The x-position of the mouse when the event occurred.

        This value is relative to the top-left of the component to which the
        event applies (as indicated by the MouseEvent::eventComponent field).

        For a floating-point coordinate, see MouseEvent::position
    */
    const int x;

    /** The y-position of the mouse when the event occurred.

        This value is relative to the top-left of the component to which the
        event applies (as indicated by the MouseEvent::eventComponent field).

        For a floating-point coordinate, see MouseEvent::position
    */
    const int y;

    /** The key modifiers associated with the event.

        This will let you find out which mouse buttons were down, as well as which
        modifier keys were held down.

        When used for mouse-up events, this will indicate the state of the mouse buttons
        just before they were released, so that you can tell which button they let go of.
    */
    const ModifierKeys mods;

    /** The pressure of the touch or stylus for this event.
        The range is 0 (soft) to 1 (hard).
        If the input device doesn't provide any pressure data, it may return a negative
        value here, or 0.0 or 1.0, depending on the platform.
    */
    const float pressure;

    /** The orientation of the touch input for this event in radians where 0 indicates a touch aligned with the x-axis
        and pointing from left to right; increasing values indicate rotation in the clockwise direction. The default is 0.
    */
    const float orientation;

    /** The rotation of the pen device for this event in radians. Indicates the clockwise
        rotation, or twist, of the pen. The default is 0.
    */
    const float rotation;

    /** The tilt of the pen device along the x-axis between -1.0 and 1.0. A positive value indicates
        a tilt to the right. The default is 0.
    */
    const float tiltX;

    /** The tilt of the pen device along the y-axis between -1.0 and 1.0. A positive value indicates
        a tilt toward the user. The default is 0.
    */
    const float tiltY;

    /** The component that this event applies to.

        This is usually the component that the mouse was over at the time, but for mouse-drag
        events the mouse could actually be over a different component and the events are
        still sent to the component that the button was originally pressed on.

        The x and y member variables are relative to this component's position.

        If you use getEventRelativeTo() to retarget this object to be relative to a different
        component, this pointer will be updated, but originalComponent remains unchanged.

        @see originalComponent
    */
    Component* const eventComponent;

    /** The component that the event first occurred on.

        If you use getEventRelativeTo() to retarget this object to be relative to a different
        component, this value remains unchanged to indicate the first component that received it.

        @see eventComponent
    */
    Component* const originalComponent;

    /** The time that this mouse-event occurred. */
    const Time eventTime;

    /** The time that the corresponding mouse-down event occurred. */
    const Time mouseDownTime;

    /** The source device that generated this event. */
    MouseInputSource source;

    //==============================================================================
    /** Returns the x coordinate of the last place that a mouse was pressed.
        The coordinate is relative to the component specified in MouseEvent::component.
        @see getDistanceFromDragStart, getDistanceFromDragStartX, mouseWasDraggedSinceMouseDown
    */
    int getMouseDownX() const noexcept;

    /** Returns the y coordinate of the last place that a mouse was pressed.
        The coordinate is relative to the component specified in MouseEvent::component.
        @see getDistanceFromDragStart, getDistanceFromDragStartX, mouseWasDraggedSinceMouseDown
    */
    int getMouseDownY() const noexcept;

    /** Returns the coordinates of the last place that a mouse was pressed.
        The coordinates are relative to the component specified in MouseEvent::component.
        @see getDistanceFromDragStart, getDistanceFromDragStartX, mouseWasDraggedSinceMouseDown
    */
    Point<int> getMouseDownPosition() const noexcept;

    /** Returns the straight-line distance between where the mouse is now and where it
        was the last time the button was pressed.

        This is quite handy for things like deciding whether the user has moved far enough
        for it to be considered a drag operation.

        @see getDistanceFromDragStartX
    */
    int getDistanceFromDragStart() const noexcept;

    /** Returns the difference between the mouse's current x position and where it was
        when the button was last pressed.

        @see getDistanceFromDragStart
    */
    int getDistanceFromDragStartX() const noexcept;

    /** Returns the difference between the mouse's current y position and where it was
        when the button was last pressed.

        @see getDistanceFromDragStart
    */
    int getDistanceFromDragStartY() const noexcept;

    /** Returns the difference between the mouse's current position and where it was
        when the button was last pressed.

        @see getDistanceFromDragStart
    */
    Point<int> getOffsetFromDragStart() const noexcept;

    /** Returns true if the user seems to be performing a drag gesture.

        This is only meaningful if called in either a mouseUp() or mouseDrag() method.

        It will return true if the user has dragged the mouse more than a few pixels
        from the place where the mouse-down occurred.

        Once they have dragged it far enough for this method to return true, it will continue
        to return true until the mouse-up, even if they move the mouse back to the same
        location at which the mouse-down happened. This means that it's very handy for
        objects that can either be clicked on or dragged, as you can use it in the mouseDrag()
        callback to ignore small movements they might make while trying to click.
    */
    bool mouseWasDraggedSinceMouseDown() const noexcept;

    /** Returns true if the mouse event is part of a click gesture rather than a drag.
        This is effectively the opposite of mouseWasDraggedSinceMouseDown()
    */
    bool mouseWasClicked() const noexcept;

    /** For a click event, the number of times the mouse was clicked in succession.
        So for example a double-click event will return 2, a triple-click 3, etc.
    */
    int getNumberOfClicks() const noexcept                              { return numberOfClicks; }

    /** Returns the time that the mouse button has been held down for.

        If called from a mouseDrag or mouseUp callback, this will return the
        number of milliseconds since the corresponding mouseDown event occurred.
        If called in other contexts, e.g. a mouseMove, then the returned value
        may be 0 or an undefined value.
    */
    int getLengthOfMousePress() const noexcept;

    /** Returns true if the pressure value for this event is meaningful. */
    bool isPressureValid() const noexcept;

    /** Returns true if the orientation value for this event is meaningful. */
    bool isOrientationValid() const noexcept;

    /** Returns true if the rotation value for this event is meaningful. */
    bool isRotationValid() const noexcept;

    /** Returns true if the current tilt value (either x- or y-axis) is meaningful. */
    bool isTiltValid (bool tiltX) const noexcept;

    //==============================================================================
    /** The position of the mouse when the event occurred.

        This position is relative to the top-left of the component to which the
        event applies (as indicated by the MouseEvent::eventComponent field).

        For a floating-point position, see MouseEvent::position
    */
    Point<int> getPosition() const noexcept;

    /** Returns the mouse x position of this event, in global screen coordinates.
        The coordinates are relative to the top-left of the main monitor.
        @see getScreenPosition
    */
    int getScreenX() const;

    /** Returns the mouse y position of this event, in global screen coordinates.
        The coordinates are relative to the top-left of the main monitor.
        @see getScreenPosition
    */
    int getScreenY() const;

    /** Returns the mouse position of this event, in global screen coordinates.
        The coordinates are relative to the top-left of the main monitor.
        @see getMouseDownScreenPosition
    */
    Point<int> getScreenPosition() const;

    /** Returns the x coordinate at which the mouse button was last pressed.
        The coordinates are relative to the top-left of the main monitor.
        @see getMouseDownScreenPosition
    */
    int getMouseDownScreenX() const;

    /** Returns the y coordinate at which the mouse button was last pressed.
        The coordinates are relative to the top-left of the main monitor.
        @see getMouseDownScreenPosition
    */
    int getMouseDownScreenY() const;

    /** Returns the coordinates at which the mouse button was last pressed.
        The coordinates are relative to the top-left of the main monitor.
        @see getScreenPosition
    */
    Point<int> getMouseDownScreenPosition() const;

    //==============================================================================
    /** Creates a version of this event that is relative to a different component.

        The x and y positions of the event that is returned will have been
        adjusted to be relative to the new component.
        The component pointer that is passed-in must not be null.
    */
    MouseEvent getEventRelativeTo (Component* newComponent) const noexcept;

    /** Creates a copy of this event with a different position.
        All other members of the event object are the same, but the x and y are
        replaced with these new values.
    */
    MouseEvent withNewPosition (Point<float> newPosition) const noexcept;

    /** Creates a copy of this event with a different position.
        All other members of the event object are the same, but the x and y are
        replaced with these new values.
    */
    MouseEvent withNewPosition (Point<int> newPosition) const noexcept;

    //==============================================================================
    /** Changes the application-wide setting for the double-click time limit.

        This is the maximum length of time between mouse-clicks for it to be
        considered a double-click. It's used by the Component class.

        @see getDoubleClickTimeout, MouseListener::mouseDoubleClick
    */
    static void setDoubleClickTimeout (int timeOutMilliseconds) noexcept;

    /** Returns the application-wide setting for the double-click time limit.

        This is the maximum length of time between mouse-clicks for it to be
        considered a double-click. It's used by the Component class.

        @see setDoubleClickTimeout, MouseListener::mouseDoubleClick
    */
    static int getDoubleClickTimeout() noexcept;

private:
    //==============================================================================
    const Point<float> mouseDownPos;
    const uint8 numberOfClicks, wasMovedSinceMouseDown;

    MouseEvent& operator= (const MouseEvent&);
};

//==============================================================================
/**
    Contains status information about a mouse wheel event.

    @see MouseListener, MouseEvent
*/
struct MouseWheelDetails  final
{
    //==============================================================================
    /** The amount that the wheel has been moved in the X axis.

        If isReversed is true, then a negative deltaX means that the wheel has been
        pushed physically to the left.
        If isReversed is false, then a negative deltaX means that the wheel has been
        pushed physically to the right.
    */
    float deltaX;

    /** The amount that the wheel has been moved in the Y axis.

        If isReversed is true, then a negative deltaY means that the wheel has been
        pushed physically upwards.
        If isReversed is false, then a negative deltaY means that the wheel has been
        pushed physically downwards.
    */
    float deltaY;

    /** Indicates whether the user has reversed the direction of the wheel.
        See deltaX and deltaY for an explanation of the effects of this value.
    */
    bool isReversed;

    /** If true, then the wheel has continuous, un-stepped motion. */
    bool isSmooth;

    /** If true, then this event is part of the intertial momentum phase that follows
        the wheel being released. */
    bool isInertial;
};

//==============================================================================
/**
    Contains status information about a pen event.

    @see MouseListener, MouseEvent
*/
struct PenDetails  final
{
    /**
        The rotation of the pen device in radians. Indicates the clockwise rotation, or twist,
        of the pen. The default is 0.
    */
    float rotation;

    /**
        Indicates the angle of tilt of the pointer in a range of -1.0 to 1.0 along the x-axis where
        a positive value indicates a tilt to the right. The default is 0.
    */
    float tiltX;

    /**
        Indicates the angle of tilt of the pointer in a range of -1.0 to 1.0 along the y-axis where
        a positive value indicates a tilt toward the user. The default is 0.
    */
    float tiltY;
};

} // namespace juce


text:
/*
  ==============================================================================

   This file is part of the JUCE library.
   Copyright (c) 2017 - ROLI Ltd.

   JUCE is an open source library subject to commercial or open-source
   licensing.

   By using JUCE, you agree to the terms of both the JUCE 5 End-User License
   Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
   27th April 2017).

   End User License Agreement: www.juce.com/juce-5-licence
   Privacy Policy: www.juce.com/juce-5-privacy-policy

   Or: You may also use this code under the terms of the GPL v3 (see
   www.gnu.org/licenses).

   JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
   EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
   DISCLAIMED.

  ==============================================================================
*/

namespace juce
{

//==============================================================================
/**
    Enables drag-and-drop behaviour for a component and all its sub-components.

    For a component to be able to make or receive drag-and-drop events, one of its parent
    components must derive from this class. It's probably best for the top-level
    component to implement it.

    Then to start a drag operation, any sub-component can just call the startDragging()
    method, and this object will take over, tracking the mouse and sending appropriate
    callbacks to any child components derived from DragAndDropTarget which the mouse
    moves over.

    Note: If all that you need to do is to respond to files being drag-and-dropped from
    the operating system onto your component, you don't need any of these classes: you can do this
    simply by overriding FileDragAndDropTarget::filesDropped().

    @see DragAndDropTarget
*/
class JUCE_API  DragAndDropContainer
{
public:
    //==============================================================================
    /** Creates a DragAndDropContainer.

        The object that derives from this class must also be a Component.
    */
    DragAndDropContainer();

    /** Destructor. */
    virtual ~DragAndDropContainer();

    //==============================================================================
    /** Begins a drag-and-drop operation.

        This starts a drag-and-drop operation - call it when the user drags the
        mouse in your drag-source component, and this object will track mouse
        movements until the user lets go of the mouse button, and will send
        appropriate messages to DragAndDropTarget objects that the mouse moves
        over.

        findParentDragContainerFor() is a handy method to call to find the
        drag container to use for a component.

        @param sourceDescription                 a string or value to use as the description of the thing being dragged -
                                                 this will be passed to the objects that might be dropped-onto so they can
                                                 decide whether they want to handle it
        @param sourceComponent                   the component that is being dragged
        @param dragImage                         the image to drag around underneath the mouse. If this is a null image,
                                                 a snapshot of the sourceComponent will be used instead.
        @param allowDraggingToOtherJuceWindows   if true, the dragged component will appear as a desktop
                                                 window, and can be dragged to DragAndDropTargets that are the
                                                 children of components other than this one.
        @param imageOffsetFromMouse              if an image has been passed-in, this specifies the offset
                                                 at which the image should be drawn from the mouse. If it isn't
                                                 specified, then the image will be centred around the mouse. If
                                                 an image hasn't been passed-in, this will be ignored.
        @param inputSourceCausingDrag            the mouse input source which started the drag. When calling
                                                 from within a mouseDown or mouseDrag event, you can pass
                                                 MouseEvent::source to this method. If this param is nullptr then JUCE
                                                 will use the mouse input source which is currently dragging. If there
                                                 are several dragging mouse input sources (which can often occur on mobile)
                                                 then JUCE will use the mouseInputSource which is closest to the sourceComponent.
    */
    void startDragging (const var& sourceDescription,
                        Component* sourceComponent,
                        Image dragImage = Image(),
                        bool allowDraggingToOtherJuceWindows = false,
                        const Point<int>* imageOffsetFromMouse = nullptr,
                        const MouseInputSource* inputSourceCausingDrag = nullptr);

    /** Returns true if something is currently being dragged. */
    bool isDragAndDropActive() const;

    /** Returns the number of things currently being dragged. */
    int getNumCurrentDrags() const;

    /** Returns the description of the thing that's currently being dragged.

        If nothing's being dragged, this will return a null var, otherwise it'll return
        the var that was passed into startDragging().

        If you are using drag and drop in a multi-touch environment then you should use the
        getDragDescriptionForIndex() method instead which takes a touch index parameter.

        @see startDragging, getDragDescriptionForIndex
    */
    var getCurrentDragDescription() const;

    /** Same as the getCurrentDragDescription() method but takes a touch index parameter.

        @see getCurrentDragDescription
    */
    var getDragDescriptionForIndex (int index) const;

    /** If a drag is in progress, this allows the image being shown to be dynamically updated.

        If you are using drag and drop in a multi-touch environment then you should use the
        setDragImageForIndex() method instead which takes a touch index parameter.

        @see setDragImageForIndex
    */
    void setCurrentDragImage (const Image& newImage);

    /** Same as the setCurrentDragImage() method but takes a touch index parameter.

        @see setCurrentDragImage
     */
    void setDragImageForIndex (int index, const Image& newImage);

    /** Utility to find the DragAndDropContainer for a given Component.

        This will search up this component's parent hierarchy looking for the first
        parent component which is a DragAndDropContainer.

        It's useful when a component wants to call startDragging but doesn't know
        the DragAndDropContainer it should to use.

        Obviously this may return nullptr if it doesn't find a suitable component.
    */
    static DragAndDropContainer* findParentDragContainerFor (Component* childComponent);

    //==============================================================================
    /** This performs a synchronous drag-and-drop of a set of files to some external
        application.

        You can call this function in response to a mouseDrag callback, and it will
        block, running its own internal message loop and tracking the mouse, while it
        uses a native operating system drag-and-drop operation to move or copy some
        files to another application.

        @param files            a list of filenames to drag
        @param canMoveFiles     if true, the app that receives the files is allowed to move the files to a new location
                                (if this is appropriate). If false, the receiver is expected to make a copy of them.
        @param sourceComponent  Normally, JUCE will assume that the component under the mouse is the source component
                                of the drag, but you can use this parameter to override this.
        @returns                true if the files were successfully dropped somewhere, or false if it
                                was interrupted
        @see performExternalDragDropOfText
    */
    static bool performExternalDragDropOfFiles (const StringArray& files, bool canMoveFiles,
                                                Component* sourceComponent = nullptr);

    /** This performs a synchronous drag-and-drop of a block of text to some external
        application.

        You can call this function in response to a mouseDrag callback, and it will
        block, running its own internal message loop and tracking the mouse, while it
        uses a native operating system drag-and-drop operation to move or copy some
        text to another application.

        @param text             the text to copy
        @param sourceComponent  Normally, JUCE will assume that the component under the mouse is the source component
                                of the drag, but you can use this parameter to override this.
        @returns                true if the text was successfully dropped somewhere, or false if it
                                was interrupted
        @see performExternalDragDropOfFiles
    */
    static bool performExternalDragDropOfText (const String& text, Component* sourceComponent = nullptr);

protected:
    /** Override this if you want to be able to perform an external drag of a set of files
        when the user drags outside of this container component.

        This method will be called when a drag operation moves outside the JUCE window,
        and if you want it to then perform a file drag-and-drop, add the filenames you want
        to the array passed in, and return true.

        @param sourceDetails    information about the source of the drag operation
        @param files            on return, the filenames you want to drag
        @param canMoveFiles     on return, true if it's ok for the receiver to move the files; false if
                                it must make a copy of them (see the performExternalDragDropOfFiles() method)
        @see performExternalDragDropOfFiles, shouldDropTextWhenDraggedExternally
    */
    virtual bool shouldDropFilesWhenDraggedExternally (const DragAndDropTarget::SourceDetails& sourceDetails,
                                                       StringArray& files, bool& canMoveFiles);

    /** Override this if you want to be able to perform an external drag of text
        when the user drags outside of this container component.

        This method will be called when a drag operation moves outside the JUCE window,
        and if you want it to then perform a text drag-and-drop, copy the text you want to
        be dragged into the argument provided and return true.

        @param sourceDetails    information about the source of the drag operation
        @param text             on return, the text you want to drag
        @see shouldDropFilesWhenDraggedExternally
    */
    virtual bool shouldDropTextWhenDraggedExternally (const DragAndDropTarget::SourceDetails& sourceDetails,
                                                      String& text);

    /** Subclasses can override this to be told when a drag starts. */
    virtual void dragOperationStarted (const DragAndDropTarget::SourceDetails&);

    /** Subclasses can override this to be told when a drag finishes. */
    virtual void dragOperationEnded (const DragAndDropTarget::SourceDetails&);

private:
    //==============================================================================
    class DragImageComponent;
    friend class DragImageComponent;
    friend struct ContainerDeletePolicy<DragImageComponent>;
    OwnedArray<DragImageComponent> dragImageComponents;

    const MouseInputSource* getMouseInputSourceForDrag (Component* sourceComponent, const MouseInputSource* inputSourceCausingDrag);

   #if JUCE_CATCH_DEPRECATED_CODE_MISUSE
    // This is just here to cause a compile error in old code that hasn't been changed to use the new
    // version of this method.
    virtual int dragOperationStarted()              { return 0; }
    virtual int dragOperationEnded()                { return 0; }
   #endif

    JUCE_DEPRECATED_WITH_BODY (virtual bool shouldDropFilesWhenDraggedExternally (const String&, Component*, StringArray&, bool&), { return false; })

    JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (DragAndDropContainer)
};

} // namespace juce


text:
/*
  ==============================================================================

   This file is part of the JUCE library.
   Copyright (c) 2017 - ROLI Ltd.

   JUCE is an open source library subject to commercial or open-source
   licensing.

   By using JUCE, you agree to the terms of both the JUCE 5 End-User License
   Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
   27th April 2017).

   End User License Agreement: www.juce.com/juce-5-licence
   Privacy Policy: www.juce.com/juce-5-privacy-policy

   Or: You may also use this code under the terms of the GPL v3 (see
   www.gnu.org/licenses).

   JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
   EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
   DISCLAIMED.

  ==============================================================================
*/

namespace juce
{

//==============================================================================
/**
    Represents a mouse cursor image.

    This object can either be used to represent one of the standard mouse
    cursor shapes, or a custom one generated from an image.
*/
class JUCE_API  MouseCursor  final
{
public:
    //==============================================================================
    /** The set of available standard mouse cursors. */
    enum StandardCursorType
    {
        ParentCursor = 0,               /**< Indicates that the component's parent's cursor should be used. */

        NoCursor,                       /**< An invisible cursor. */
        NormalCursor,                   /**< The stardard arrow cursor. */

        WaitCursor,                     /**< The normal hourglass or spinning-beachball 'busy' cursor. */
        IBeamCursor,                    /**< A vertical I-beam for positioning within text. */
        CrosshairCursor,                /**< A pair of crosshairs. */
        CopyingCursor,                  /**< The normal arrow cursor, but with a "+" on it to indicate
                                             that you're dragging a copy of something. */

        PointingHandCursor,             /**< A hand with a pointing finger, for clicking on web-links. */
        DraggingHandCursor,             /**< An open flat hand for dragging heavy objects around. */

        LeftRightResizeCursor,          /**< An arrow pointing left and right. */
        UpDownResizeCursor,             /**< an arrow pointing up and down. */
        UpDownLeftRightResizeCursor,    /**< An arrow pointing up, down, left and right. */

        TopEdgeResizeCursor,            /**< A platform-specific cursor for resizing the top-edge of a window. */
        BottomEdgeResizeCursor,         /**< A platform-specific cursor for resizing the bottom-edge of a window. */
        LeftEdgeResizeCursor,           /**< A platform-specific cursor for resizing the left-edge of a window. */
        RightEdgeResizeCursor,          /**< A platform-specific cursor for resizing the right-edge of a window. */
        TopLeftCornerResizeCursor,      /**< A platform-specific cursor for resizing the top-left-corner of a window. */
        TopRightCornerResizeCursor,     /**< A platform-specific cursor for resizing the top-right-corner of a window. */
        BottomLeftCornerResizeCursor,   /**< A platform-specific cursor for resizing the bottom-left-corner of a window. */
        BottomRightCornerResizeCursor,  /**< A platform-specific cursor for resizing the bottom-right-corner of a window. */

        NumStandardCursorTypes
    };

    //==============================================================================
    /** Creates the standard arrow cursor. */
    MouseCursor() noexcept;

    /** Creates one of the standard mouse cursor */
    MouseCursor (StandardCursorType);

    /** Creates a custom cursor from an image.

        @param image    the image to use for the cursor - if this is bigger than the
                        system can manage, it might get scaled down first, and might
                        also have to be turned to black-and-white if it can't do colour
                        cursors.
        @param hotSpotX the x position of the cursor's hotspot within the image
        @param hotSpotY the y position of the cursor's hotspot within the image
    */
    MouseCursor (const Image& image, int hotSpotX, int hotSpotY);

    /** Creates a custom cursor from an image.

        @param image    the image to use for the cursor - if this is bigger than the
                        system can manage, it might get scaled down first, and might
                        also have to be turned to black-and-white if it can't do colour
                        cursors.
        @param hotSpotX the x position of the cursor's hotspot within the image
        @param hotSpotY the y position of the cursor's hotspot within the image
        @param scaleFactor the factor by which this image is larger than the target
                           screen size of the cursor.
    */
    MouseCursor (const Image& image, int hotSpotX, int hotSpotY, float scaleFactor);

    //==============================================================================
    /** Creates a copy of another cursor object. */
    MouseCursor (const MouseCursor&);

    /** Copies this cursor from another object. */
    MouseCursor& operator= (const MouseCursor&);

    /** Destructor. */
    ~MouseCursor();

    /** Move constructor */
    MouseCursor (MouseCursor&&) noexcept;

    /** Move assignment operator */
    MouseCursor& operator= (MouseCursor&&) noexcept;

    /** Checks whether two mouse cursors are the same.

        For custom cursors, two cursors created from the same image won't be
        recognised as the same, only MouseCursor objects that have been
        copied from the same object.
    */
    bool operator== (const MouseCursor&) const noexcept;

    /** Checks whether two mouse cursors are the same.

        For custom cursors, two cursors created from the same image won't be
        recognised as the same, only MouseCursor objects that have been
        copied from the same object.
    */
    bool operator!= (const MouseCursor&) const noexcept;

    /** Checks whether this cursor is of the standard type mentioned. */
    bool operator== (StandardCursorType type) const noexcept;

    /** Checks whether this cursor is of the standard type mentioned. */
    bool operator!= (StandardCursorType type) const noexcept;

    //==============================================================================
    /** Makes the system show its default 'busy' cursor.

        This will turn the system cursor to an hourglass or spinning beachball
        until the next time the mouse is moved, or hideWaitCursor() is called.

        This is handy if the message loop is about to block for a couple of
        seconds while busy and you want to give the user feedback about this.
    */
    static void showWaitCursor();

    /** If showWaitCursor has been called, this will return the mouse to its
        normal state.

        This will look at what component is under the mouse, and update the
        cursor to be the correct one for that component.

        @see showWaitCursor
    */
    static void hideWaitCursor();

private:
    //==============================================================================
    class SharedCursorHandle;
    friend class SharedCursorHandle;
    SharedCursorHandle* cursorHandle;

    friend class MouseInputSourceInternal;
    void showInWindow (ComponentPeer* window) const;
    void showInAllWindows() const;
    void* getHandle() const noexcept;

    static void* createStandardMouseCursor (MouseCursor::StandardCursorType type);
    static void deleteMouseCursor (void* cursorHandle, bool isStandard);

    JUCE_LEAK_DETECTOR (MouseCursor)
};

} // namespace juce


text:
/*
  ==============================================================================

   This file is part of the JUCE library.
   Copyright (c) 2017 - ROLI Ltd.

   JUCE is an open source library subject to commercial or open-source
   licensing.

   By using JUCE, you agree to the terms of both the JUCE 5 End-User License
   Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
   27th April 2017).

   End User License Agreement: www.juce.com/juce-5-licence
   Privacy Policy: www.juce.com/juce-5-privacy-policy

   Or: You may also use this code under the terms of the GPL v3 (see
   www.gnu.org/licenses).

   JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
   EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
   DISCLAIMED.

  ==============================================================================
*/

namespace juce
{

void MouseListener::mouseEnter (const MouseEvent&) {}
void MouseListener::mouseExit (const MouseEvent&)  {}
void MouseListener::mouseDown (const MouseEvent&)  {}
void MouseListener::mouseUp (const MouseEvent&)    {}
void MouseListener::mouseDrag (const MouseEvent&)  {}
void MouseListener::mouseMove (const MouseEvent&)  {}
void MouseListener::mouseDoubleClick (const MouseEvent&) {}
void MouseListener::mouseWheelMove (const MouseEvent&, const MouseWheelDetails&) {}

} // namespace juce


text:
/*
  ==============================================================================

   This file is part of the JUCE library.
   Copyright (c) 2017 - ROLI Ltd.

   JUCE is an open source library subject to commercial or open-source
   licensing.

   By using JUCE, you agree to the terms of both the JUCE 5 End-User License
   Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
   27th April 2017).

   End User License Agreement: www.juce.com/juce-5-licence
   Privacy Policy: www.juce.com/juce-5-privacy-policy

   Or: You may also use this code under the terms of the GPL v3 (see
   www.gnu.org/licenses).

   JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
   EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
   DISCLAIMED.

  ==============================================================================
*/

namespace juce
{

//==============================================================================
/**
    An object to take care of the logic for dragging components around with the mouse.

    Very easy to use - in your mouseDown() callback, call startDraggingComponent(),
    then in your mouseDrag() callback, call dragComponent().

    When starting a drag, you can give it a ComponentBoundsConstrainer to use
    to limit the component's position and keep it on-screen.

    e.g. @code
    class MyDraggableComp
    {
        ComponentDragger myDragger;

        void mouseDown (const MouseEvent& e)
        {
            myDragger.startDraggingComponent (this, e);
        }

        void mouseDrag (const MouseEvent& e)
        {
            myDragger.dragComponent (this, e, nullptr);
        }
    };
    @endcode
*/
class JUCE_API  ComponentDragger
{
public:
    //==============================================================================
    /** Creates a ComponentDragger. */
    ComponentDragger();

    /** Destructor. */
    virtual ~ComponentDragger();

    //==============================================================================
    /** Call this from your component's mouseDown() method, to prepare for dragging.

        @param componentToDrag      the component that you want to drag
        @param e                    the mouse event that is triggering the drag
        @see dragComponent
    */
    void startDraggingComponent (Component* componentToDrag,
                                 const MouseEvent& e);

    /** Call this from your mouseDrag() callback to move the component.

        This will move the component, using the given constrainer object to check
        the new position.

        @param componentToDrag      the component that you want to drag
        @param e                    the current mouse-drag event
        @param constrainer          an optional constrainer object that should be used
                                    to apply limits to the component's position. Pass
                                    null if you don't want to contrain the movement.
        @see startDraggingComponent
    */
    void dragComponent (Component* componentToDrag,
                        const MouseEvent& e,
                        ComponentBoundsConstrainer* constrainer);

private:
    //==============================================================================
    Point<int> mouseDownWithinTarget;

    JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ComponentDragger)
};

} // namespace juce


text:
/*
  ==============================================================================

   This file is part of the JUCE library.
   Copyright (c) 2017 - ROLI Ltd.

   JUCE is an open source library subject to commercial or open-source
   licensing.

   By using JUCE, you agree to the terms of both the JUCE 5 End-User License
   Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
   27th April 2017).

   End User License Agreement: www.juce.com/juce-5-licence
   Privacy Policy: www.juce.com/juce-5-privacy-policy

   Or: You may also use this code under the terms of the GPL v3 (see
   www.gnu.org/licenses).

   JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
   EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
   DISCLAIMED.

  ==============================================================================
*/

namespace juce
{

//==============================================================================
/**
    Components that want to use pop-up tooltips should implement this interface.

    A TooltipWindow will wait for the mouse to hover over a component that
    implements the TooltipClient interface, and when it finds one, it will display
    the tooltip returned by its getTooltip() method.

    @see TooltipWindow, SettableTooltipClient
*/
class JUCE_API  TooltipClient
{
public:
    /** Destructor. */
    virtual ~TooltipClient()  {}

    /** Returns the string that this object wants to show as its tooltip. */
    virtual String getTooltip() = 0;
};

//==============================================================================
/**
    An implementation of TooltipClient that stores the tooltip string and a method
    for changing it.

    This makes it easy to add a tooltip to a custom component, by simply adding this
    as a base class and calling setTooltip().

    Many of the Juce widgets already use this as a base class to implement their
    tooltips.

    @see TooltipClient, TooltipWindow
*/
class JUCE_API  SettableTooltipClient   : public TooltipClient
{
public:
    //==============================================================================
    /** Destructor. */
    ~SettableTooltipClient() {}

    //==============================================================================
    /** Assigns a new tooltip to this object. */
    virtual void setTooltip (const String& newTooltip)              { tooltipString = newTooltip; }

    /** Returns the tooltip assigned to this object. */
    String getTooltip() override                                    { return tooltipString; }

protected:
    SettableTooltipClient() {}

private:
    String tooltipString;
};

} // namespace juce


text:
/*
  ==============================================================================

   This file is part of the JUCE library.
   Copyright (c) 2017 - ROLI Ltd.

   JUCE is an open source library subject to commercial or open-source
   licensing.

   By using JUCE, you agree to the terms of both the JUCE 5 End-User License
   Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
   27th April 2017).

   End User License Agreement: www.juce.com/juce-5-licence
   Privacy Policy: www.juce.com/juce-5-privacy-policy

   Or: You may also use this code under the terms of the GPL v3 (see
   www.gnu.org/licenses).

   JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
   EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
   DISCLAIMED.

  ==============================================================================
*/

namespace juce
{

//==============================================================================
/**
    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) noexcept;

    /** Sets the number of pixels by which the cursor is allowed to drift before it is
        considered to be actively moved.
    */
    void setMouseMoveTolerance (int pixelsNeededToTrigger) noexcept;

    //==============================================================================
    /** 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, toleranceDistance;
    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)
};

} // namespace juce