29using ViewportDragPosition = AnimatedPosition<AnimatedPositionBehaviours::ContinuousWithMomentum>;
32 private ViewportDragPosition::Listener
36 viewport.contentHolder.addMouseListener (
this,
true);
45 viewport.contentHolder.removeMouseListener (
this);
49 void stopOngoingAnimation()
63 if (! isGlobalMouseListener && detail::ViewportHelpers::wouldScrollOnEvent (&viewport, e.
source))
70 viewport.contentHolder.removeMouseListener (
this);
73 isGlobalMouseListener =
true;
81 if (e.
source == scrollSource
86 if (! isDragging && totalOffset.getDistanceFromOrigin() > 8.0f && detail::ViewportHelpers::wouldScrollOnEvent (&viewport, e.
source))
99 offsetX.
drag (totalOffset.x);
100 offsetY.
drag (totalOffset.y);
107 if (isGlobalMouseListener && e.
source == scrollSource)
108 endDragAndClearGlobalMouseListener();
111 void endDragAndClearGlobalMouseListener()
119 viewport.contentHolder.addMouseListener (
this,
true);
122 isGlobalMouseListener =
false;
125 bool doesMouseEventComponentBlockViewportDrag (
const Component* eventComp)
128 if (c->getViewportIgnoreDragFlag())
135 ViewportDragPosition offsetX, offsetY;
136 Point<int> originalViewPos;
138 bool isDragging =
false;
139 bool isGlobalMouseListener =
false;
151 contentHolder.setInterceptsMouseClicks (
false,
true);
163 deleteOrRemoveContentComp();
171void Viewport::deleteOrRemoveContentComp()
173 if (contentComp !=
nullptr)
175 contentComp->removeComponentListener (
this);
182 contentComp =
nullptr;
186 contentHolder.removeChildComponent (contentComp);
187 contentComp =
nullptr;
194 if (contentComp.get() != newViewedComponent)
196 deleteOrRemoveContentComp();
197 contentComp = newViewedComponent;
198 deleteContent = deleteComponentWhenNoLongerNeeded;
200 if (contentComp !=
nullptr)
202 contentHolder.addAndMakeVisible (contentComp);
204 contentComp->addComponentListener (
this);
214 verticalScrollBar.reset();
215 horizontalScrollBar.reset();
239 jassert (contentComp !=
nullptr);
241 auto contentBounds = contentHolder.getLocalArea (contentComp.get(), contentComp->getLocalBounds());
244 jmax (
jmin (0, contentHolder.getHeight() - contentBounds.getHeight()),
jmin (0, -(pos.
y))));
246 return p.transformedBy (contentComp->getTransform().inverted());
256 if (contentComp !=
nullptr)
257 contentComp->setTopLeftPosition (viewportPosToCompPos (newPosition));
262 if (contentComp !=
nullptr)
267bool Viewport::autoScroll (
const int mouseX,
const int mouseY,
const int activeBorderThickness,
const int maximumSpeed)
269 if (contentComp !=
nullptr)
275 if (mouseX < activeBorderThickness)
276 dx = activeBorderThickness - mouseX;
277 else if (mouseX >= contentHolder.getWidth() - activeBorderThickness)
278 dx = (contentHolder.getWidth() - activeBorderThickness) - mouseX;
281 dx =
jmax (dx, -maximumSpeed, contentHolder.getWidth() - contentComp->getRight());
283 dx =
jmin (dx, maximumSpeed, -contentComp->getX());
288 if (mouseY < activeBorderThickness)
289 dy = activeBorderThickness - mouseY;
290 else if (mouseY >= contentHolder.getHeight() - activeBorderThickness)
291 dy = (contentHolder.getHeight() - activeBorderThickness) - mouseY;
294 dy =
jmax (dy, -maximumSpeed, contentHolder.getHeight() - contentComp->getBottom());
296 dy =
jmin (dy, maximumSpeed, -contentComp->getY());
299 if (dx != 0 || dy != 0)
301 contentComp->setTopLeftPosition (contentComp->getX() + dx,
302 contentComp->getY() + dy);
319 scrollOnDragMode = mode;
324 return dragToScrollListener->isDragging;
330 if (! customScrollBarThickness)
343void Viewport::updateVisibleArea()
346 const bool canShowAnyBars =
getWidth() > scrollbarWidth &&
getHeight() > scrollbarWidth;
347 const bool canShowHBar = showHScrollbar && canShowAnyBars;
348 const bool canShowVBar = showVScrollbar && canShowAnyBars;
350 bool hBarVisible =
false, vBarVisible =
false;
353 for (
int i = 3; --i >= 0;)
359 if (contentComp !=
nullptr && ! contentArea.
contains (contentComp->getBounds()))
361 hBarVisible = canShowHBar && (hBarVisible || contentComp->getX() < 0 || contentComp->getRight() > contentArea.
getWidth());
362 vBarVisible = canShowVBar && (vBarVisible || contentComp->getY() < 0 || contentComp->getBottom() > contentArea.
getHeight());
370 if (! contentArea.
contains (contentComp->getBounds()))
372 hBarVisible = canShowHBar && (hBarVisible || contentComp->getRight() > contentArea.
getWidth());
373 vBarVisible = canShowVBar && (vBarVisible || contentComp->getBottom() > contentArea.
getHeight());
380 if (! vScrollbarRight && vBarVisible)
381 contentArea.
setX (scrollbarWidth);
383 if (! hScrollbarBottom && hBarVisible)
384 contentArea.
setY (scrollbarWidth);
386 if (contentComp ==
nullptr)
388 contentHolder.setBounds (contentArea);
392 auto oldContentBounds = contentComp->getBounds();
393 contentHolder.setBounds (contentArea);
396 if (oldContentBounds == contentComp->getBounds())
400 Rectangle<int> contentBounds;
402 if (
auto cc = contentComp.get())
403 contentBounds = contentHolder.getLocalArea (cc, cc->getLocalBounds());
405 auto visibleOrigin = -contentBounds.getPosition();
410 hbar.setBounds (contentArea.
getX(), hScrollbarBottom ? contentArea.
getHeight() : 0, contentArea.
getWidth(), scrollbarWidth);
411 hbar.setRangeLimits (0.0, contentBounds.getWidth());
412 hbar.setCurrentRange (visibleOrigin.x, contentArea.
getWidth());
413 hbar.setSingleStepSize (singleStepX);
415 if (canShowHBar && ! hBarVisible)
416 visibleOrigin.setX (0);
418 vbar.setBounds (vScrollbarRight ? contentArea.
getWidth() : 0, contentArea.
getY(), scrollbarWidth, contentArea.
getHeight());
419 vbar.setRangeLimits (0.0, contentBounds.getHeight());
420 vbar.setCurrentRange (visibleOrigin.y, contentArea.
getHeight());
421 vbar.setSingleStepSize (singleStepY);
423 if (canShowVBar && ! vBarVisible)
424 visibleOrigin.setY (0);
427 hbar.setVisible (hBarVisible);
428 vbar.setVisible (vBarVisible);
430 if (contentComp !=
nullptr)
432 auto newContentCompPos = viewportPosToCompPos (visibleOrigin);
434 if (contentComp->getBounds().getPosition() != newContentCompPos)
436 contentComp->setTopLeftPosition (newContentCompPos);
441 const Rectangle<int> visibleArea (visibleOrigin.x, visibleOrigin.y,
442 jmin (contentBounds.getWidth() - visibleOrigin.x, contentArea.
getWidth()),
443 jmin (contentBounds.getHeight() - visibleOrigin.y, contentArea.
getHeight()));
445 if (lastVisibleArea != visibleArea)
447 lastVisibleArea = visibleArea;
451 hbar.handleUpdateNowIfNeeded();
452 vbar.handleUpdateNowIfNeeded();
458 if (singleStepX != stepX || singleStepY != stepY)
467 const bool showHorizontalScrollbarIfNeeded,
468 const bool allowVerticalScrollingWithoutScrollbar,
469 const bool allowHorizontalScrollingWithoutScrollbar)
471 allowScrollingWithoutScrollbarV = allowVerticalScrollingWithoutScrollbar;
472 allowScrollingWithoutScrollbarH = allowHorizontalScrollingWithoutScrollbar;
474 if (showVScrollbar != showVerticalScrollbarIfNeeded
475 || showHScrollbar != showHorizontalScrollbarIfNeeded)
477 showVScrollbar = showVerticalScrollbarIfNeeded;
478 showHScrollbar = showHorizontalScrollbarIfNeeded;
492 customScrollBarThickness =
false;
497 customScrollBarThickness =
true;
498 newThickness = thickness;
501 if (scrollBarThickness != newThickness)
503 scrollBarThickness = newThickness;
510 return scrollBarThickness;
515 auto newRangeStartInt =
roundToInt (newRangeStart);
517 if (scrollBarThatHasMoved == horizontalScrollBar.get())
521 else if (scrollBarThatHasMoved == verticalScrollBar.get())
530 if (! useMouseWheelMoveIfNeeded (e, wheel))
537 dragToScrollListener->stopOngoingAnimation();
540static int rescaleMouseWheelDistance (
float distance,
int singleStepSize)
noexcept
545 distance *= 14.0f * (
float) singleStepSize;
548 :
jmax (distance, 1.0f));
551bool Viewport::useMouseWheelMoveIfNeeded (
const MouseEvent& e,
const MouseWheelDetails& wheel)
553 if (! (e.mods.isAltDown() || e.mods.isCtrlDown() || e.mods.isCommandDown()))
558 if (canScrollHorz || canScrollVert)
560 auto deltaX = rescaleMouseWheelDistance (wheel.deltaX, singleStepX);
561 auto deltaY = rescaleMouseWheelDistance (wheel.deltaY, singleStepY);
565 if (deltaX != 0 && deltaY != 0 && canScrollHorz && canScrollVert)
570 else if (canScrollHorz && (deltaX != 0 || e.mods.isShiftDown() || ! canScrollVert))
572 pos.
x -= deltaX != 0 ? deltaX : deltaY;
574 else if (canScrollVert && deltaY != 0)
590static bool isUpDownKeyPress (
const KeyPress& key)
600static bool isLeftRightKeyPress (
const KeyPress& key)
608 const bool isUpDownKey = isUpDownKeyPress (key);
613 const bool isLeftRightKey = isLeftRightKeyPress (key);
621bool Viewport::respondsToKey (
const KeyPress& key)
623 return isUpDownKeyPress (key) || isLeftRightKeyPress (key);
633 return createIgnoredAccessibilityHandler (*
this);
637 bool horizontalScrollbarAtBottom)
639 vScrollbarRight = verticalScrollbarOnRight;
640 hScrollbarBottom = horizontalScrollbarAtBottom;
Behaviour behaviour
The behaviour object.
void addListener(Listener *listener)
Adds a listener to be called when the value changes.
void endDrag()
Called after beginDrag() and drag() to indicate that the drag operation has now finished.
void setPosition(double newPosition)
Explicitly sets the position and stops any further movement.
double getPosition() const noexcept
Returns the current position.
void beginDrag()
Called to indicate that the object is now being controlled by a mouse-drag or similar operation.
void drag(double deltaFromStartOfDrag)
Called during a mouse-drag operation, to indicate that the mouse has moved.
The base class for all JUCE user-interface objects.
void setInterceptsMouseClicks(bool allowClicksOnThisComponent, bool allowClicksOnChildComponents) noexcept
Changes the default return value for the hitTest() method.
bool isVisible() const noexcept
Tests whether the component is visible or not.
Component * getParentComponent() const noexcept
Returns the component which this component is inside.
int getHeight() const noexcept
Returns the component's height in pixels.
void addAndMakeVisible(Component *child, int zOrder=-1)
Adds a child component to this one, and also makes the child visible if it isn't already.
void addMouseListener(MouseListener *newListener, bool wantsEventsForAllNestedChildComponents)
Registers a listener to be told when mouse events occur in this component.
Component() noexcept
Creates a component.
int getY() const noexcept
Returns the y coordinate of the top of this component.
void setWantsKeyboardFocus(bool wantsFocus) noexcept
Sets a flag to indicate whether this component wants keyboard focus or not.
int getWidth() const noexcept
Returns the component's width in pixels.
void mouseWheelMove(const MouseEvent &event, const MouseWheelDetails &wheel) override
Called when the mouse-wheel is moved.
LookAndFeel & getLookAndFeel() const noexcept
Finds the appropriate look-and-feel to use for this component.
Rectangle< int > getLocalBounds() const noexcept
Returns the component's bounds, relative to its own origin.
void addChildComponent(Component *child, int zOrder=-1)
Adds a child component to this one.
void addGlobalMouseListener(MouseListener *listener)
Registers a MouseListener that will receive all mouse events that occur on any component.
MouseInputSource getMainMouseSource() const noexcept
Returns the main mouse input device that the system is using.
static Desktop &JUCE_CALLTYPE getInstance()
There's only one desktop object, and this method will return it.
void removeGlobalMouseListener(MouseListener *listener)
Unregisters a MouseListener that was added with addGlobalMouseListener().
Represents a key press, including any modifier keys that are needed.
static const int homeKey
key-code for the home key
static const int upKey
key-code for the cursor-up key
static const int endKey
key-code for the end key
static const int rightKey
key-code for the cursor-right key
static const int downKey
key-code for the cursor-down key
static const int leftKey
key-code for the cursor-left key
static const int pageUpKey
key-code for the page-up key
static const int pageDownKey
key-code for the page-down key
Contains position and status information about a mouse event.
MouseInputSource source
The source device that generated this event.
Point< int > getOffsetFromDragStart() const noexcept
Returns the difference between the mouse's current position and where it was when the button was last...
MouseEvent getEventRelativeTo(Component *newComponent) const noexcept
Creates a version of this event that is relative to a different component.
Component *const eventComponent
The component that this event applies to.
A MouseListener can be registered with a component to receive callbacks about mouse events that happe...
A pair of (x, y) coordinates.
constexpr Point< float > toFloat() const noexcept
Casts this point to a Point<float> object.
ValueType y
The point's Y coordinate.
ValueType x
The point's X coordinate.
Manages a rectangle and allows geometric operations to be performed on it.
void setY(ValueType newY) noexcept
Changes the rectangle's Y coordinate.
bool contains(ValueType xCoord, ValueType yCoord) const noexcept
Returns true if this coordinate is inside the rectangle.
ValueType getX() const noexcept
Returns the x coordinate of the rectangle's left-hand-side.
void setHeight(ValueType newHeight) noexcept
Changes the rectangle's height.
ValueType getWidth() const noexcept
Returns the width of the rectangle.
void setX(ValueType newX) noexcept
Changes the rectangle's X coordinate.
void setWidth(ValueType newWidth) noexcept
Changes the rectangle's width.
ValueType getHeight() const noexcept
Returns the height of the rectangle.
A Viewport is used to contain a larger child component, and allows the child to be automatically scro...
void mouseDown(const MouseEvent &e) override
Called when a mouse button is pressed.
void setViewPositionProportionately(double proportionX, double proportionY)
Changes the view position as a proportion of the distance it can move.
void setScrollBarPosition(bool verticalScrollbarOnRight, bool horizontalScrollbarAtBottom)
Changes where the scroll bars are positioned.
virtual void viewedComponentChanged(Component *newComponent)
Callback method that is called when the viewed component is added, removed or swapped.
bool isCurrentlyScrollingOnDrag() const noexcept
Returns true if the user is currently dragging-to-scroll.
int getViewPositionX() const noexcept
Returns the position within the child component of the top-left of its visible area.
int getScrollBarThickness() const
Returns the thickness of the scrollbars.
ScrollBar & getVerticalScrollBar() noexcept
Returns a reference to the scrollbar component being used.
void setScrollOnDragMode(ScrollOnDragMode scrollOnDragMode)
Sets the current scroll-on-drag mode.
bool canScrollVertically() const noexcept
True if there's any off-screen content that could be scrolled vertically, or false if everything is c...
int getMaximumVisibleHeight() const
Returns the height available within this component for the contents.
void componentMovedOrResized(Component &, bool wasMoved, bool wasResized) override
Called when the component's position or size changes.
Point< int > getViewPosition() const noexcept
Returns the position within the child component of the top-left of its visible area.
ScrollBar & getHorizontalScrollBar() noexcept
Returns a reference to the scrollbar component being used.
virtual void visibleAreaChanged(const Rectangle< int > &newVisibleArea)
Callback method that is called when the visible area changes.
bool autoScroll(int mouseX, int mouseY, int distanceFromEdge, int maximumSpeed)
If the specified position is at the edges of the viewport, this method scrolls the viewport to bring ...
bool canScrollHorizontally() const noexcept
True if there's any off-screen content that could be scrolled horizontally, or false if everything is...
~Viewport() override
Destructor.
void scrollBarMoved(ScrollBar *, double newRangeStart) override
Called when a ScrollBar is moved.
bool keyPressed(const KeyPress &) override
Called when a key is pressed.
void resized() override
Called when this component's size has been changed.
void setViewPosition(int xPixelsOffset, int yPixelsOffset)
Changes the position of the viewed component.
void setScrollBarsShown(bool showVerticalScrollbarIfNeeded, bool showHorizontalScrollbarIfNeeded, bool allowVerticalScrollingWithoutScrollbar=false, bool allowHorizontalScrollingWithoutScrollbar=false)
Turns scrollbars on or off.
int getViewPositionY() const noexcept
Returns the position within the child component of the top-left of its visible area.
void lookAndFeelChanged() override
Called to let the component react to a change in the look-and-feel setting.
void recreateScrollbars()
Re-instantiates the scrollbars, which is only really useful if you've overridden createScrollBarCompo...
int getMaximumVisibleWidth() const
Returns the width available within this component for the contents.
virtual ScrollBar * createScrollBarComponent(bool isVertical)
Creates the Scrollbar components that will be added to the Viewport.
Viewport(const String &componentName=String())
Creates a Viewport.
void setViewedComponent(Component *newViewedComponent, bool deleteComponentWhenNoLongerNeeded=true)
Sets the component that this viewport will contain and scroll around.
void setSingleStepSizes(int stepX, int stepY)
Changes the distance that a single-step click on a scrollbar button will move the viewport.
void mouseWheelMove(const MouseEvent &, const MouseWheelDetails &) override
Called when the mouse-wheel is moved.
void setScrollBarThickness(int thickness)
Changes the width of the scrollbars.
constexpr bool approximatelyEqual(Type a, Type b, Tolerance< Type > tolerance=Tolerance< Type >{} .withAbsolute(std::numeric_limits< Type >::min()) .withRelative(std::numeric_limits< Type >::epsilon()))
Returns true if the two floating-point numbers are approximately equal.
constexpr Type jmin(Type a, Type b)
Returns the smaller of two values.
constexpr Type jmax(Type a, Type b)
Returns the larger of two values.
int roundToInt(const FloatType value) noexcept
Fast floating-point-to-integer conversion.
Contains status information about a mouse wheel event.
void setMinimumVelocity(double newMinimumVelocityToUse) noexcept
Sets the minimum velocity of the movement.