|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427 |
- /*
- ==============================================================================
-
- This file is part of the JUCE 6 technical preview.
- Copyright (c) 2017 - ROLI Ltd.
-
- You may use this code under the terms of the GPL v3
- (see www.gnu.org/licenses).
-
- For this technical preview, this file is not subject to commercial licensing.
-
- 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 scrollbar component.
-
- To use a scrollbar, set up its total range using the setRangeLimits() method - this
- sets the range of values it can represent. Then you can use setCurrentRange() to
- change the position and size of the scrollbar's 'thumb'.
-
- Registering a ScrollBar::Listener with the scrollbar will allow you to find out when
- the user moves it, and you can use the getCurrentRangeStart() to find out where
- they moved it to.
-
- The scrollbar will adjust its own visibility according to whether its thumb size
- allows it to actually be scrolled.
-
- For most purposes, it's probably easier to use a Viewport or ListBox
- instead of handling a scrollbar directly.
-
- @see ScrollBar::Listener
-
- @tags{GUI}
- */
- class JUCE_API ScrollBar : public Component,
- public AsyncUpdater,
- private Timer
- {
- public:
- //==============================================================================
- /** Creates a Scrollbar.
- @param isVertical specifies whether the bar should be a vertical or horizontal
- */
- ScrollBar (bool isVertical);
-
- /** Destructor. */
- ~ScrollBar() override;
-
- //==============================================================================
- /** Returns true if the scrollbar is vertical, false if it's horizontal. */
- bool isVertical() const noexcept { return vertical; }
-
- /** Changes the scrollbar's direction.
-
- You'll also need to resize the bar appropriately - this just changes its internal
- layout.
-
- @param shouldBeVertical true makes it vertical; false makes it horizontal.
- */
- void setOrientation (bool shouldBeVertical);
-
- /** Tells the scrollbar whether to make itself invisible when not needed.
-
- The default behaviour is for a scrollbar to become invisible when the thumb
- fills the whole of its range (i.e. when it can't be moved). Setting this
- value to false forces the bar to always be visible.
- @see autoHides()
- */
- void setAutoHide (bool shouldHideWhenFullRange);
-
- /** Returns true if this scrollbar is set to auto-hide when its thumb is as big
- as its maximum range.
- @see setAutoHide
- */
- bool autoHides() const noexcept;
-
- //==============================================================================
- /** Sets the minimum and maximum values that the bar will move between.
-
- The bar's thumb will always be constrained so that the entire thumb lies
- within this range.
-
- @param newRangeLimit the new range.
- @param notification whether to send a notification of the change to listeners.
- A notification will only be sent if the range has changed.
-
- @see setCurrentRange
- */
- void setRangeLimits (Range<double> newRangeLimit,
- NotificationType notification = sendNotificationAsync);
-
- /** Sets the minimum and maximum values that the bar will move between.
-
- The bar's thumb will always be constrained so that the entire thumb lies
- within this range.
-
- @param minimum the new range minimum.
- @param maximum the new range maximum.
- @param notification whether to send a notification of the change to listeners.
- A notification will only be sent if the range has changed.
-
- @see setCurrentRange
- */
- void setRangeLimits (double minimum, double maximum,
- NotificationType notification = sendNotificationAsync);
-
- /** Returns the current limits on the thumb position.
- @see setRangeLimits
- */
- Range<double> getRangeLimit() const noexcept { return totalRange; }
-
- /** Returns the lower value that the thumb can be set to.
-
- This is the value set by setRangeLimits().
- */
- double getMinimumRangeLimit() const noexcept { return totalRange.getStart(); }
-
- /** Returns the upper value that the thumb can be set to.
-
- This is the value set by setRangeLimits().
- */
- double getMaximumRangeLimit() const noexcept { return totalRange.getEnd(); }
-
- //==============================================================================
- /** Changes the position of the scrollbar's 'thumb'.
-
- This sets both the position and size of the thumb - to just set the position without
- changing the size, you can use setCurrentRangeStart().
-
- If this method call actually changes the scrollbar's position, it will trigger an
- asynchronous call to ScrollBar::Listener::scrollBarMoved() for all the listeners that
- are registered.
-
- The notification parameter can be used to optionally send or inhibit a callback to
- any scrollbar listeners.
-
- @returns true if the range was changed, or false if nothing was changed.
- @see getCurrentRange. setCurrentRangeStart
- */
- bool setCurrentRange (Range<double> newRange,
- NotificationType notification = sendNotificationAsync);
-
- /** Changes the position of the scrollbar's 'thumb'.
-
- This sets both the position and size of the thumb - to just set the position without
- changing the size, you can use setCurrentRangeStart().
-
- @param newStart the top (or left) of the thumb, in the range
- getMinimumRangeLimit() <= newStart <= getMaximumRangeLimit(). If the
- value is beyond these limits, it will be clipped.
- @param newSize the size of the thumb, such that
- getMinimumRangeLimit() <= newStart + newSize <= getMaximumRangeLimit(). If the
- size is beyond these limits, it will be clipped.
- @param notification specifies if and how a callback should be made to any listeners
- if the range actually changes
- @see setCurrentRangeStart, getCurrentRangeStart, getCurrentRangeSize
- */
- void setCurrentRange (double newStart, double newSize,
- NotificationType notification = sendNotificationAsync);
-
- /** Moves the bar's thumb position.
-
- This will move the thumb position without changing the thumb size. Note
- that the maximum thumb start position is (getMaximumRangeLimit() - getCurrentRangeSize()).
-
- If this method call actually changes the scrollbar's position, it will trigger an
- asynchronous call to ScrollBar::Listener::scrollBarMoved() for all the listeners that
- are registered.
-
- @see setCurrentRange
- */
- void setCurrentRangeStart (double newStart,
- NotificationType notification = sendNotificationAsync);
-
- /** Returns the current thumb range.
- @see getCurrentRange, setCurrentRange
- */
- Range<double> getCurrentRange() const noexcept { return visibleRange; }
-
- /** Returns the position of the top of the thumb.
- @see getCurrentRange, setCurrentRangeStart
- */
- double getCurrentRangeStart() const noexcept { return visibleRange.getStart(); }
-
- /** Returns the current size of the thumb.
- @see getCurrentRange, setCurrentRange
- */
- double getCurrentRangeSize() const noexcept { return visibleRange.getLength(); }
-
- //==============================================================================
- /** Sets the amount by which the up and down buttons will move the bar.
-
- The value here is in terms of the total range, and is added or subtracted
- from the thumb position when the user clicks an up/down (or left/right) button.
- */
- void setSingleStepSize (double newSingleStepSize) noexcept;
-
- /** Moves the scrollbar by a number of single-steps.
-
- This will move the bar by a multiple of its single-step interval (as
- specified using the setSingleStepSize() method).
-
- A positive value here will move the bar down or to the right, a negative
- value moves it up or to the left.
-
- @param howManySteps the number of steps to move the scrollbar
- @param notification whether to send a notification of the change to listeners.
- A notification will only be sent if the position has changed.
-
- @returns true if the scrollbar's position actually changed.
- */
- bool moveScrollbarInSteps (int howManySteps,
- NotificationType notification = sendNotificationAsync);
-
- /** Moves the scroll bar up or down in pages.
-
- This will move the bar by a multiple of its current thumb size, effectively
- doing a page-up or down.
-
- A positive value here will move the bar down or to the right, a negative
- value moves it up or to the left.
-
- @param howManyPages the number of pages to move the scrollbar
- @param notification whether to send a notification of the change to listeners.
- A notification will only be sent if the position has changed.
-
- @returns true if the scrollbar's position actually changed.
- */
- bool moveScrollbarInPages (int howManyPages,
- NotificationType notification = sendNotificationAsync);
-
- /** Scrolls to the top (or left).
- This is the same as calling setCurrentRangeStart (getMinimumRangeLimit());
-
- @param notification whether to send a notification of the change to listeners.
- A notification will only be sent if the position has changed.
-
- @returns true if the scrollbar's position actually changed.
- */
- bool scrollToTop (NotificationType notification = sendNotificationAsync);
-
- /** Scrolls to the bottom (or right).
- This is the same as calling setCurrentRangeStart (getMaximumRangeLimit() - getCurrentRangeSize());
-
- @param notification whether to send a notification of the change to listeners.
- A notification will only be sent if the position has changed.
-
- @returns true if the scrollbar's position actually changed.
- */
- bool scrollToBottom (NotificationType notification = sendNotificationAsync);
-
- /** Changes the delay before the up and down buttons autorepeat when they are held
- down.
-
- For an explanation of what the parameters are for, see Button::setRepeatSpeed().
-
- @see Button::setRepeatSpeed
- */
- void setButtonRepeatSpeed (int initialDelayInMillisecs,
- int repeatDelayInMillisecs,
- int minimumDelayInMillisecs = -1);
-
- //==============================================================================
- /** A set of colour IDs to use to change the colour of various aspects of the component.
-
- These constants can be used either via the Component::setColour(), or LookAndFeel::setColour()
- methods.
-
- @see Component::setColour, Component::findColour, LookAndFeel::setColour, LookAndFeel::findColour
- */
- enum ColourIds
- {
- backgroundColourId = 0x1000300, /**< The background colour of the scrollbar. */
- thumbColourId = 0x1000400, /**< A base colour to use for the thumb. The look and feel will probably use variations on this colour. */
- trackColourId = 0x1000401 /**< A base colour to use for the slot area of the bar. The look and feel will probably use variations on this colour. */
- };
-
- //==============================================================================
- /**
- A class for receiving events from a ScrollBar.
-
- You can register a ScrollBar::Listener with a ScrollBar using the ScrollBar::addListener()
- method, and it will be called when the bar's position changes.
-
- @see ScrollBar::addListener, ScrollBar::removeListener
- */
- class JUCE_API Listener
- {
- public:
- /** Destructor. */
- virtual ~Listener() = default;
-
- /** Called when a ScrollBar is moved.
-
- @param scrollBarThatHasMoved the bar that has moved
- @param newRangeStart the new range start of this bar
- */
- virtual void scrollBarMoved (ScrollBar* scrollBarThatHasMoved,
- double newRangeStart) = 0;
- };
-
- /** Registers a listener that will be called when the scrollbar is moved. */
- void addListener (Listener* listener);
-
- /** Deregisters a previously-registered listener. */
- void removeListener (Listener* listener);
-
- //==============================================================================
- /** This abstract base class is implemented by LookAndFeel classes to provide
- scrollbar-drawing functionality.
- */
- struct JUCE_API LookAndFeelMethods
- {
- virtual ~LookAndFeelMethods() = default;
-
- virtual bool areScrollbarButtonsVisible() = 0;
-
- /** Draws one of the buttons on a scrollbar.
-
- @param g the context to draw into
- @param scrollbar the bar itself
- @param width the width of the button
- @param height the height of the button
- @param buttonDirection the direction of the button, where 0 = up, 1 = right, 2 = down, 3 = left
- @param isScrollbarVertical true if it's a vertical bar, false if horizontal
- @param isMouseOverButton whether the mouse is currently over the button (also true if it's held down)
- @param isButtonDown whether the mouse button's held down
- */
- virtual void drawScrollbarButton (Graphics& g,
- ScrollBar& scrollbar,
- int width, int height,
- int buttonDirection,
- bool isScrollbarVertical,
- bool isMouseOverButton,
- bool isButtonDown) = 0;
-
- /** Draws the thumb area of a scrollbar.
-
- @param g the context to draw into
- @param scrollbar the bar itself
- @param x the x position of the left edge of the thumb area to draw in
- @param y the y position of the top edge of the thumb area to draw in
- @param width the width of the thumb area to draw in
- @param height the height of the thumb area to draw in
- @param isScrollbarVertical true if it's a vertical bar, false if horizontal
- @param thumbStartPosition for vertical bars, the y coordinate of the top of the
- thumb, or its x position for horizontal bars
- @param thumbSize for vertical bars, the height of the thumb, or its width for
- horizontal bars. This may be 0 if the thumb shouldn't be drawn.
- @param isMouseOver whether the mouse is over the thumb area, also true if the mouse is
- currently dragging the thumb
- @param isMouseDown whether the mouse is currently dragging the scrollbar
- */
- virtual void drawScrollbar (Graphics& g, ScrollBar& scrollbar,
- int x, int y, int width, int height,
- bool isScrollbarVertical,
- int thumbStartPosition,
- int thumbSize,
- bool isMouseOver,
- bool isMouseDown) = 0;
-
- /** Returns the component effect to use for a scrollbar */
- virtual ImageEffectFilter* getScrollbarEffect() = 0;
-
- /** Returns the minimum length in pixels to use for a scrollbar thumb. */
- virtual int getMinimumScrollbarThumbSize (ScrollBar&) = 0;
-
- /** Returns the default thickness to use for a scrollbar. */
- virtual int getDefaultScrollbarWidth() = 0;
-
- /** Returns the length in pixels to use for a scrollbar button. */
- virtual int getScrollbarButtonSize (ScrollBar&) = 0;
- };
-
- //==============================================================================
- /** @internal */
- bool keyPressed (const KeyPress&) override;
- /** @internal */
- void mouseWheelMove (const MouseEvent&, const MouseWheelDetails&) override;
- /** @internal */
- void lookAndFeelChanged() override;
- /** @internal */
- void mouseDown (const MouseEvent&) override;
- /** @internal */
- void mouseDrag (const MouseEvent&) override;
- /** @internal */
- void mouseUp (const MouseEvent&) override;
- /** @internal */
- void paint (Graphics&) override;
- /** @internal */
- void resized() override;
- /** @internal */
- void parentHierarchyChanged() override;
- /** @internal */
- void setVisible (bool) override;
-
- private:
- //==============================================================================
- Range<double> totalRange { 0.0, 1.0 }, visibleRange { 0.0, 1.0 };
- double singleStepSize = 0.1, dragStartRange = 0;
- int thumbAreaStart = 0, thumbAreaSize = 0, thumbStart = 0, thumbSize = 0;
- int dragStartMousePos = 0, lastMousePos = 0;
- int initialDelayInMillisecs = 100, repeatDelayInMillisecs = 50, minimumDelayInMillisecs = 10;
- bool vertical, isDraggingThumb = false, autohides = true, userVisibilityFlag = false;
- class ScrollbarButton;
- std::unique_ptr<ScrollbarButton> upButton, downButton;
- ListenerList<Listener> listeners;
-
- void handleAsyncUpdate() override;
- void updateThumbPosition();
- void timerCallback() override;
- bool getVisibility() const noexcept;
-
- JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ScrollBar)
- };
-
-
- } // namespace juce
|