1
0
Fork 0
mirror of https://github.com/juce-framework/JUCE.git synced 2026-01-10 23:44:24 +00:00
JUCE/src/gui/components/layout/juce_Viewport.cpp

356 lines
12 KiB
C++

/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-9 by Raw Material Software Ltd.
------------------------------------------------------------------------------
JUCE can be redistributed and/or modified under the terms of the GNU General
Public License (Version 2), as published by the Free Software Foundation.
A copy of the license is included in the JUCE distribution, or can be found
online at www.gnu.org/licenses.
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.rawmaterialsoftware.com/juce for more information.
==============================================================================
*/
#include "../../../core/juce_StandardHeader.h"
BEGIN_JUCE_NAMESPACE
#include "juce_Viewport.h"
#include "../lookandfeel/juce_LookAndFeel.h"
//==============================================================================
Viewport::Viewport (const String& componentName)
: Component (componentName),
contentComp (0),
lastVX (0),
lastVY (0),
lastVW (0),
lastVH (0),
scrollBarThickness (0),
singleStepX (16),
singleStepY (16),
showHScrollbar (true),
showVScrollbar (true)
{
// content holder is used to clip the contents so they don't overlap the scrollbars
addAndMakeVisible (contentHolder = new Component());
contentHolder->setInterceptsMouseClicks (false, true);
verticalScrollBar = new ScrollBar (true);
horizontalScrollBar = new ScrollBar (false);
addChildComponent (verticalScrollBar);
addChildComponent (horizontalScrollBar);
verticalScrollBar->addListener (this);
horizontalScrollBar->addListener (this);
setInterceptsMouseClicks (false, true);
setWantsKeyboardFocus (true);
}
Viewport::~Viewport()
{
contentHolder->deleteAllChildren();
deleteAllChildren();
}
//==============================================================================
void Viewport::visibleAreaChanged (int, int, int, int)
{
}
//==============================================================================
void Viewport::setViewedComponent (Component* const newViewedComponent)
{
if (contentComp != newViewedComponent)
{
if (contentComp->isValidComponent())
{
Component* const oldComp = contentComp;
contentComp = 0;
delete oldComp;
}
contentComp = newViewedComponent;
if (contentComp != 0)
{
contentComp->setTopLeftPosition (0, 0);
contentHolder->addAndMakeVisible (contentComp);
contentComp->addComponentListener (this);
}
updateVisibleRegion();
}
}
int Viewport::getMaximumVisibleWidth() const throw()
{
return jmax (0, getWidth() - (verticalScrollBar->isVisible() ? getScrollBarThickness() : 0));
}
int Viewport::getMaximumVisibleHeight() const throw()
{
return jmax (0, getHeight() - (horizontalScrollBar->isVisible() ? getScrollBarThickness() : 0));
}
void Viewport::setViewPosition (const int xPixelsOffset,
const int yPixelsOffset)
{
if (contentComp != 0)
contentComp->setTopLeftPosition (-xPixelsOffset,
-yPixelsOffset);
}
void Viewport::setViewPositionProportionately (const double x,
const double y)
{
if (contentComp != 0)
setViewPosition (jmax (0, roundToInt (x * (contentComp->getWidth() - getWidth()))),
jmax (0, roundToInt (y * (contentComp->getHeight() - getHeight()))));
}
bool Viewport::autoScroll (int mouseX, int mouseY, int activeBorderThickness, int maximumSpeed)
{
if (contentComp != 0)
{
int dx = 0, dy = 0;
if (mouseX < activeBorderThickness)
dx = activeBorderThickness - mouseX;
else if (mouseX >= contentHolder->getWidth() - activeBorderThickness)
dx = (contentHolder->getWidth() - activeBorderThickness) - mouseX;
if (dx < 0)
dx = jmax (dx, -maximumSpeed, contentHolder->getWidth() - contentComp->getRight());
else
dx = jmin (dx, maximumSpeed, -contentComp->getX());
if (mouseY < activeBorderThickness)
dy = activeBorderThickness - mouseY;
else if (mouseY >= contentHolder->getHeight() - activeBorderThickness)
dy = (contentHolder->getHeight() - activeBorderThickness) - mouseY;
if (dy < 0)
dy = jmax (dy, -maximumSpeed, contentHolder->getHeight() - contentComp->getBottom());
else
dy = jmin (dy, maximumSpeed, -contentComp->getY());
if (dx != 0 || dy != 0)
{
contentComp->setTopLeftPosition (contentComp->getX() + dx,
contentComp->getY() + dy);
return true;
}
}
return false;
}
void Viewport::componentMovedOrResized (Component&, bool, bool)
{
updateVisibleRegion();
}
void Viewport::resized()
{
updateVisibleRegion();
}
//==============================================================================
void Viewport::updateVisibleRegion()
{
if (contentComp != 0)
{
const int newVX = -contentComp->getX();
const int newVY = -contentComp->getY();
if (newVX == 0 && newVY == 0
&& contentComp->getWidth() <= getWidth()
&& contentComp->getHeight() <= getHeight())
{
horizontalScrollBar->setVisible (false);
verticalScrollBar->setVisible (false);
}
horizontalScrollBar->setRangeLimits (0.0, contentComp->getWidth());
horizontalScrollBar->setCurrentRange (newVX, getMaximumVisibleWidth());
horizontalScrollBar->setSingleStepSize (singleStepX);
if (! (contentComp->getWidth() > 0 && showHScrollbar && getHeight() > getScrollBarThickness()))
horizontalScrollBar->setVisible (false);
verticalScrollBar->setRangeLimits (0.0, contentComp->getHeight());
verticalScrollBar->setCurrentRange (newVY, getMaximumVisibleHeight());
verticalScrollBar->setSingleStepSize (singleStepY);
if (! (contentComp->getHeight() > 0 && showVScrollbar && getWidth() > getScrollBarThickness()))
verticalScrollBar->setVisible (false);
if (verticalScrollBar->isVisible())
{
horizontalScrollBar->setCurrentRange (newVX, getMaximumVisibleWidth());
verticalScrollBar->setCurrentRange (newVY, getMaximumVisibleHeight());
verticalScrollBar
->setBounds (getMaximumVisibleWidth(), 0,
getScrollBarThickness(), getMaximumVisibleHeight());
}
if (horizontalScrollBar->isVisible())
{
horizontalScrollBar->setCurrentRange (newVX, getMaximumVisibleWidth());
horizontalScrollBar
->setBounds (0, getMaximumVisibleHeight(),
getMaximumVisibleWidth(), getScrollBarThickness());
}
contentHolder->setSize (getMaximumVisibleWidth(),
getMaximumVisibleHeight());
const int newVW = jmin (contentComp->getRight(), getMaximumVisibleWidth());
const int newVH = jmin (contentComp->getBottom(), getMaximumVisibleHeight());
if (newVX != lastVX
|| newVY != lastVY
|| newVW != lastVW
|| newVH != lastVH)
{
lastVX = newVX;
lastVY = newVY;
lastVW = newVW;
lastVH = newVH;
visibleAreaChanged (newVX, newVY, newVW, newVH);
}
horizontalScrollBar->handleUpdateNowIfNeeded();
verticalScrollBar->handleUpdateNowIfNeeded();
}
else
{
horizontalScrollBar->setVisible (false);
verticalScrollBar->setVisible (false);
}
}
//==============================================================================
void Viewport::setSingleStepSizes (const int stepX,
const int stepY)
{
singleStepX = stepX;
singleStepY = stepY;
updateVisibleRegion();
}
void Viewport::setScrollBarsShown (const bool showVerticalScrollbarIfNeeded,
const bool showHorizontalScrollbarIfNeeded)
{
showVScrollbar = showVerticalScrollbarIfNeeded;
showHScrollbar = showHorizontalScrollbarIfNeeded;
updateVisibleRegion();
}
void Viewport::setScrollBarThickness (const int thickness)
{
scrollBarThickness = thickness;
updateVisibleRegion();
}
int Viewport::getScrollBarThickness() const throw()
{
return (scrollBarThickness > 0) ? scrollBarThickness
: getLookAndFeel().getDefaultScrollbarWidth();
}
void Viewport::setScrollBarButtonVisibility (const bool buttonsVisible)
{
verticalScrollBar->setButtonVisibility (buttonsVisible);
horizontalScrollBar->setButtonVisibility (buttonsVisible);
}
void Viewport::scrollBarMoved (ScrollBar* scrollBarThatHasMoved, const double newRangeStart)
{
if (scrollBarThatHasMoved == horizontalScrollBar)
{
setViewPosition (roundToInt (newRangeStart), getViewPositionY());
}
else if (scrollBarThatHasMoved == verticalScrollBar)
{
setViewPosition (getViewPositionX(), roundToInt (newRangeStart));
}
}
void Viewport::mouseWheelMove (const MouseEvent& e, float wheelIncrementX, float wheelIncrementY)
{
if (! useMouseWheelMoveIfNeeded (e, wheelIncrementX, wheelIncrementY))
Component::mouseWheelMove (e, wheelIncrementX, wheelIncrementY);
}
bool Viewport::useMouseWheelMoveIfNeeded (const MouseEvent& e, float wheelIncrementX, float wheelIncrementY)
{
if (! (e.mods.isAltDown() || e.mods.isCtrlDown()))
{
const bool hasVertBar = verticalScrollBar->isVisible();
const bool hasHorzBar = horizontalScrollBar->isVisible();
if (hasHorzBar && (wheelIncrementX != 0 || e.mods.isShiftDown() || ! hasVertBar))
{
if (wheelIncrementX == 0 && ! hasVertBar)
wheelIncrementX = wheelIncrementY;
horizontalScrollBar->mouseWheelMove (e.getEventRelativeTo (horizontalScrollBar),
wheelIncrementX, wheelIncrementY);
return true;
}
else if (hasVertBar && wheelIncrementY != 0)
{
verticalScrollBar->mouseWheelMove (e.getEventRelativeTo (verticalScrollBar),
wheelIncrementX, wheelIncrementY);
return true;
}
}
return false;
}
bool Viewport::keyPressed (const KeyPress& key)
{
const bool isUpDownKey = key.isKeyCode (KeyPress::upKey)
|| key.isKeyCode (KeyPress::downKey)
|| key.isKeyCode (KeyPress::pageUpKey)
|| key.isKeyCode (KeyPress::pageDownKey)
|| key.isKeyCode (KeyPress::homeKey)
|| key.isKeyCode (KeyPress::endKey);
if (verticalScrollBar->isVisible() && isUpDownKey)
return verticalScrollBar->keyPressed (key);
const bool isLeftRightKey = key.isKeyCode (KeyPress::leftKey)
|| key.isKeyCode (KeyPress::rightKey);
if (horizontalScrollBar->isVisible() && (isUpDownKey || isLeftRightKey))
return horizontalScrollBar->keyPressed (key);
return false;
}
END_JUCE_NAMESPACE