/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
* Implementation of ScrollBarUI for the Basic Look and Feel
*
* @author Rich Schiavi
* @author David Kloba
* @author Hans Muller
*/
public class BasicScrollBarUI
{
// NOTE: DO NOT use this field directly, SynthScrollBarUI assumes you'll
// call getMinimumThumbSize to access it.
protected boolean isDragging;
protected int trackHighlight;
/** True indicates a middle click will absolutely position the
* scrollbar. */
private boolean supportsAbsolutePositioning;
/**
* Hint as to what width (when vertical) or height (when horizontal)
* should be.
*
* @since 1.7
*/
protected int scrollBarWidth;
private boolean thumbActive;
/**
* Determine whether scrollbar layout should use cached value or adjusted
* value returned by scrollbar's <code>getValue</code>.
*/
private boolean useCachedValue = false;
/**
* The scrollbar value is cached to save real value if the view is adjusted.
*/
private int scrollBarValue;
/**
* Distance between the increment button and the track. This may be a negative
* number. If negative, then an overlap between the button and track will occur,
* which is useful for shaped buttons.
*
* @since 1.7
*/
protected int incrGap;
/**
* Distance between the decrement button and the track. This may be a negative
* number. If negative, then an overlap between the button and track will occur,
* which is useful for shaped buttons.
*
* @since 1.7
*/
protected int decrGap;
}
return new BasicScrollBarUI();
}
protected void configureScrollBarColors()
{
"ScrollBar.foreground");
}
scrollbar = (JScrollBar)c;
}
scrollbar = (JScrollBar)c;
incrButton = null;
decrButton = null;
}
protected void installDefaults()
{
if (scrollBarWidth <= 0) {
scrollBarWidth = 16;
}
false;
}
// handle scaling for sizeVarients for special case components. The
// components are based on Apples LAF
"JComponent.sizeVariant");
scrollBarWidth *= 1.15;
incrGap *= 1.15;
decrGap *= 1.15;
scrollBarWidth *= 0.857;
incrGap *= 0.857;
decrGap *= 0.714;
scrollBarWidth *= 0.714;
incrGap *= 0.714;
decrGap *= 0.714;
}
}
}
protected void installComponents(){
switch (scrollbar.getOrientation()) {
case JScrollBar.VERTICAL:
break;
case JScrollBar.HORIZONTAL:
} else {
}
break;
}
// Force the children's enabled state to be updated.
}
protected void uninstallComponents(){
}
protected void installListeners(){
if (incrButton != null) {
}
if (decrButton != null) {
}
}
protected void installKeyboardActions(){
"ScrollBar.actionMap");
inputMap);
}
protected void uninstallKeyboardActions(){
null);
}
scrollbar, this, "ScrollBar.focusInputMap");
((rtlKeyMap = (InputMap)DefaultLookup.get(scrollbar, this, "ScrollBar.focusInputMap.RightToLeft")) == null)) {
return keyMap;
} else {
return rtlKeyMap;
}
}
scrollbar, this, "ScrollBar.ancestorInputMap");
((rtlKeyMap = (InputMap)DefaultLookup.get(scrollbar, this, "ScrollBar.ancestorInputMap.RightToLeft")) == null)) {
return keyMap;
} else {
return rtlKeyMap;
}
}
return null;
}
protected void uninstallListeners() {
scrollTimer.stop();
scrollTimer = null;
if (decrButton != null){
}
if (incrButton != null){
}
}
protected void uninstallDefaults(){
}
}
}
return handler;
}
return new TrackListener();
}
return new ArrowButtonListener();
}
return new ModelListener();
}
return new ScrollListener();
}
return getHandler();
}
private void updateThumbState(int x, int y) {
}
/**
* Sets whether or not the mouse is currently over the thumb.
*
* @param active True indicates the thumb is currently active.
* @since 1.5
*/
if (thumbActive != active) {
}
}
/**
* Returns true if the mouse is currently over the thumb.
*
* @return true if the thumb is currently active
* @since 1.5
*/
public boolean isThumbRollover() {
return thumbActive;
}
paintTrack(g, c, getTrackBounds());
paintThumb(g, c, thumbBounds);
}
}
/**
* A vertical scrollbar's preferred width is the maximum of
* preferred widths of the (non <code>null</code>)
* and the minimum width of the thumb. The preferred height is the
* sum of the preferred heights of the same parts. The basis for
* the preferred size of a horizontal scrollbar is similar.
* <p>
* The <code>preferredSize</code> is only computed once, subsequent
* calls to this method just return a cached size.
*
* @param c the <code>JScrollBar</code> that's delegating this method to us
* @return the preferred size of a Basic JScrollBar
* @see #getMaximumSize
* @see #getMinimumSize
*/
}
/**
* @param c The JScrollBar that's delegating this method to us.
* @return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE);
* @see #getMinimumSize
* @see #getPreferredSize
*/
}
return new BasicArrowButton(orientation,
}
return new BasicArrowButton(orientation,
}
{
//paint the distance between the start of the track and top of the thumb
int y = trackRect.y;
int h = thumbR.y - y;
g.fillRect(x, y, w, h);
} else {
//if left-to-right, fill the area between the start of the track and
//the left edge of the thumb. If right-to-left, fill the area between
//the end of the thumb and end of the track.
int x, w;
x = trackRect.x;
w = thumbR.x - x;
} else {
}
g.fillRect(x, y, w, h);
}
}
{
//fill the area between the bottom of the thumb and the end of the track.
g.fillRect(x, y, w, h);
}
else {
//if left-to-right, fill the area between the right of the thumb and the
//end of the track. If right-to-left, then fill the area to the left of
//the thumb and the start of the track.
int x, w;
} else {
x = trackRect.x;
w = thumbR.x - x;
}
g.fillRect(x, y, w, h);
}
}
{
g.setColor(trackColor);
if(trackHighlight == DECREASE_HIGHLIGHT) {
}
else if(trackHighlight == INCREASE_HIGHLIGHT) {
}
}
{
return;
}
int w = thumbBounds.width;
int h = thumbBounds.height;
g.setColor(thumbColor);
}
/**
* Returns the smallest acceptable size for the thumb. If the scrollbar
* becomes so small that this size isn't available, the thumb will be
* hidden.
* <p>
* <b>Warning </b>: the value returned by this method should not be
* be modified, it's a shared static constant.
*
* @return The smallest acceptable size for the thumb.
* @see #getMaximumThumbSize
*/
return minimumThumbSize;
}
/**
* Returns the largest acceptable size for the thumb. To create a fixed
* size thumb one make this method and <code>getMinimumThumbSize</code>
* return the same value.
* <p>
* <b>Warning </b>: the value returned by this method should not be
* be modified, it's a shared static constant.
*
* @return The largest acceptable size for the thumb.
* @see #getMinimumThumbSize
*/
return maximumThumbSize;
}
/*
* LayoutManager Implementation
*/
}
}
}
{
/*
* Width and left edge of the buttons and thumb.
*/
/* Nominal locations of the buttons, assuming their preferred
* size will fit.
*/
scrollbar, this, "ScrollBar.squareButtons", false);
/* The thumb must fit within the height left over after we
* subtract the preferredSize of the buttons and the insets
* and the gaps
*/
/* Compute the height and origin of the thumb. The case
* where the thumb is at the bottom edge is handled specially
* to avoid numerical problems in computing thumbY. Enforce
* fit in the track (trackH) we'll hide it later.
*/
}
/* If the buttons don't fit, allocate half of the available
* space to each and move the lower one (incrButton) down.
*/
if (sbAvailButtonH < sbButtonsH) {
}
/* Update the trackRect field.
*/
/* If the thumb isn't going to fit, zero it's bounds. Otherwise
* make sure it fits between the buttons. Note that setting the
* thumbs bounds will cause a repaint.
*/
// This is used primarily for GTK L&F, which expands the
// thumb to fit the track when it would otherwise be hidden.
} else {
// Other L&F's simply hide the thumb in this case.
}
}
else {
}
}
}
}
{
/* Height and top edge of the buttons and thumb.
*/
/* Nominal locations of the buttons, assuming their preferred
* size will fit.
*/
scrollbar, this, "ScrollBar.squareButtons", false);
if (!ltr) {
int temp = leftButtonW;
rightButtonW = temp;
}
/* The thumb must fit within the width left over after we
* subtract the preferredSize of the buttons and the insets
* and the gaps
*/
/* Compute the width and origin of the thumb. Enforce
* is at the right edge is handled specially to avoid numerical
* problems in computing thumbX. If the thumb doesn't
* fit in the track (trackH) we'll hide it later.
*/
if( ltr ) {
} else {
}
}
/* If the buttons don't fit, allocate half of the available
* space to each and move the right one over.
*/
if (sbAvailButtonW < sbButtonsW) {
}
/* Update the trackRect field.
*/
/* Make sure the thumb fits between the buttons. Note
* that setting the thumbs bounds causes a repaint.
*/
// This is used primarily for GTK L&F, which expands the
// thumb to fit the track when it would otherwise be hidden.
} else {
// Other L&F's simply hide the thumb in this case.
}
}
else {
}
}
}
}
{
/* If the user is dragging the value, we'll assume that the
* scrollbars layout is OK modulo the thumb which is being
* handled by the dragging code.
*/
if (isDragging) {
return;
}
switch (scrollbar.getOrientation()) {
case JScrollBar.VERTICAL:
break;
case JScrollBar.HORIZONTAL:
break;
}
}
/**
* Set the bounds of the thumb and force a repaint that includes
* the old thumbBounds and the new one.
*
* @see #getThumbBounds
*/
{
/* If the thumbs bounds haven't changed, we're done.
*/
if ((thumbRect.x == x) &&
(thumbRect.y == y) &&
return;
}
/* Update thumbRect, and repaint the union of x,y,w,h and
* the old thumbRect.
*/
// Once there is API to determine the mouse location this will need
// to be changed.
setThumbRollover(false);
}
/**
* <p>
* <b>Warning </b>: the value returned by this method should not be
* be modified, it's a reference to the actual rectangle, not a copy.
*
* @see #setThumbBounds
*/
return thumbRect;
}
/**
* Returns the current bounds of the track, i.e. the space in between
* the increment and decrement buttons, less the insets. The value
* returned by this method is updated each time the scrollbar is
* laid out (validated).
* <p>
* <b>Warning </b>: the value returned by this method should not be
* be modified, it's a reference to the actual rectangle, not a copy.
*
* @return the current bounds of the scrollbar track
* @see #layoutContainer
*/
return trackRect;
}
/*
* Method for scrolling by a block increment.
* Added for mouse wheel scrolling support, RFE 4202656.
*/
// This method is called from BasicScrollPaneUI to implement wheel
// scrolling, and also from scrollByBlock().
// Check for overflow.
}
}
}
{
}
/*
* Method for scrolling by a unit increment.
* Added for mouse wheel scrolling support, RFE 4202656.
*
* If limitByBlock is set to true, the scrollbar will scroll at least 1
* unit increment, but will not scroll farther than the block increment.
* See BasicScrollPaneUI.Handler.mouseWheelMoved().
*/
int units, boolean limitToBlock) {
// This method is called from BasicScrollPaneUI to implement wheel
// scrolling, as well as from scrollByUnit().
int delta;
int limit = -1;
if (limitToBlock) {
if (direction < 0) {
}
else {
}
}
for (int i=0; i<units; i++) {
if (direction > 0) {
}
else {
}
// Check for overflow.
}
}
break;
}
if (limitToBlock && i > 0) {
assert limit != -1;
break;
}
}
}
}
}
/**
* Indicates whether the user can absolutely position the thumb with
* a mouse gesture (usually the middle mouse button).
*
* @return true if a mouse gesture can absolutely position the thumb
* @since 1.5
*/
public boolean getSupportsAbsolutePositioning() {
return supportsAbsolutePositioning;
}
/**
* A listener to listen for model changes.
*
*/
if (!useCachedValue) {
}
useCachedValue = false;
}
}
/**
* Track mouse drags.
*/
protected class TrackListener
extends MouseAdapter implements MouseMotionListener
{
protected transient int offset;
{
if (isDragging) {
}
if (SwingUtilities.isRightMouseButton(e) ||
return;
return;
Rectangle r = getTrackBounds();
isDragging = false;
offset = 0;
scrollTimer.stop();
useCachedValue = true;
scrollbar.setValueIsAdjusting(false);
}
/**
* If the mouse is pressed above the "thumb" component
* then reduce the scrollbars value by one page ("page up"),
* otherwise increase it by one page. If there is no
* thumb then page up if the mouse is in the upper half
* of the track.
*/
{
if (SwingUtilities.isRightMouseButton(e) ||
return;
return;
}
useCachedValue = true;
scrollbar.setValueIsAdjusting(true);
currentMouseX = e.getX();
currentMouseY = e.getY();
// Clicked in the Thumb area?
switch (scrollbar.getOrientation()) {
case JScrollBar.VERTICAL:
break;
case JScrollBar.HORIZONTAL:
break;
}
isDragging = true;
return;
}
else if (getSupportsAbsolutePositioning() &&
switch (scrollbar.getOrientation()) {
case JScrollBar.VERTICAL:
break;
case JScrollBar.HORIZONTAL:
break;
}
isDragging = true;
setValueFrom(e);
return;
}
isDragging = false;
direction = +1;
switch (scrollbar.getOrientation()) {
case JScrollBar.VERTICAL:
if (getThumbBounds().isEmpty()) {
} else {
int thumbY = getThumbBounds().y;
}
break;
case JScrollBar.HORIZONTAL:
if (getThumbBounds().isEmpty()) {
} else {
int thumbX = getThumbBounds().x;
}
}
break;
}
scrollTimer.stop();
scrollListener.setScrollByBlock(true);
}
/**
* Set the models value to the position of the thumb's top of Vertical
* left-to-right/right-to-left scrollbar relative to the origin of the
* track.
*/
if (SwingUtilities.isRightMouseButton(e) ||
return;
return;
}
if (isDragging) {
setValueFrom(e);
} else {
currentMouseX = e.getX();
currentMouseY = e.getY();
}
}
boolean active = isThumbRollover();
float trackLength;
}
else {
}
/* Set the scrollbars value. If the thumb has reached the end of
* the scrollbar, then just set the value to its maximum. Otherwise
* compute the value as accurately as possible.
*/
} else {
}
}
else {
int value;
} else {
}
useCachedValue = true;
}
}
"List.lockToPositionOnScroll", false)) {
int adjustedValue = value;
adjustedValue = rect.y;
}
}
adjustedValue = rect.x;
}
}
else {
}
}
}
}
}
}
return value;
}
private void startScrollTimerIfNecessary() {
if (scrollTimer.isRunning()) {
return;
}
switch (scrollbar.getOrientation()) {
case JScrollBar.VERTICAL:
if (direction > 0) {
scrollTimer.start();
}
scrollTimer.start();
}
break;
case JScrollBar.HORIZONTAL:
scrollTimer.start();
}
break;
}
}
if (!isDragging) {
}
}
/**
* Invoked when the mouse exits the scrollbar.
*
* @param e MouseEvent further describing the event
* @since 1.5
*/
if (!isDragging) {
setThumbRollover(false);
}
}
}
/**
* Listener for cursor keys.
*/
{
// Because we are handling both mousePressed and Actions
// we need to make sure we don't fire under both conditions.
// (keyfocus on scrollbars causes action without mousePress
boolean handledEvent;
// not an unmodified left mouse button
//if(e.getModifiers() != InputEvent.BUTTON1_MASK) {return; }
if( ! SwingUtilities.isLeftMouseButton(e)) { return; }
scrollTimer.stop();
scrollListener.setScrollByBlock(false);
scrollTimer.start();
handledEvent = true;
}
}
scrollTimer.stop();
handledEvent = false;
scrollbar.setValueIsAdjusting(false);
}
}
/**
* Listener for scrolling events initiated in the
* <code>ScrollPane</code>.
*/
{
boolean useBlockIncrement;
public ScrollListener() {
direction = +1;
useBlockIncrement = false;
}
}
if(useBlockIncrement) {
// Stop scrolling if the thumb catches up with the mouse
if(direction > 0) {
}
} else {
}
}
} else {
}
if(direction > 0
>= scrollbar.getMaximum())
else if(direction < 0
}
}
private boolean isMouseLeftOfThumb() {
}
private boolean isMouseRightOfThumb() {
}
private boolean isMouseBeforeThumb() {
: isMouseRightOfThumb();
}
private boolean isMouseAfterThumb() {
: isMouseLeftOfThumb();
}
private void updateButtonDirections() {
if (incrButton instanceof BasicArrowButton) {
}
if (decrButton instanceof BasicArrowButton) {
}
}
else {
if (incrButton instanceof BasicArrowButton) {
}
if (decrButton instanceof BasicArrowButton) {
}
}
}
{
// NOTE: This class exists only for backward compatability. All
// its functionality has been moved into Handler. If you need to add
// new functionality add it to the Handler, but make sure this
// class calls into the Handler.
getHandler().propertyChange(e);
}
}
/**
* Used for scrolling the scrollbar.
*/
"positiveUnitIncrement";
"positiveBlockIncrement";
"negativeUnitIncrement";
"negativeBlockIncrement";
super(name);
}
if (key == POSITIVE_UNIT_INCREMENT) {
}
else if (key == POSITIVE_BLOCK_INCREMENT) {
}
else if (key == NEGATIVE_UNIT_INCREMENT) {
}
else if (key == NEGATIVE_BLOCK_INCREMENT) {
}
else if (key == MIN_SCROLL) {
}
else if (key == MAX_SCROLL) {
}
}
int amount;
// Don't use the BasicScrollBarUI.scrollByXXX methods as we
// don't want to use an invokeLater to reset the trackHighlight
// via an invokeLater
if (block) {
if (dir == NEGATIVE_SCROLL) {
}
else {
}
}
else {
if (dir == NEGATIVE_SCROLL) {
}
else {
}
}
}
}
}
}
}
//
// EventHandler
//
//
// FocusListener
//
}
}
//
// PropertyChangeListener
//
if ("model" == propertyName) {
} else if ("orientation" == propertyName) {
} else if ("componentOrientation" == propertyName) {
}
}
}
}