/*
* @(#)AutoScroll.java 12/7/2006
*
* Copyright 2002 - 2006 JIDE Software Inc. All rights reserved.
*/
package com.jidesoft.swing;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
/**
* Please note: we are still polishing this class and may change the public interface in the future. Please do not use
* it for now until we remove this notice. You may choose to use it as long as you don't complain when you find your
* code won't compile after upgrading to a new JIDE release.
*/
abstract public class AutoScroll {
public static final String CLIENT_PROPERTY_AUTO_SCROLL = "AutoScroll";
protected Timer _timer;
protected boolean _autoScrolling = false;
protected int _scrollDirection = SCROLL_UP;
protected boolean _hasEntered;
public static final int SCROLL_UP = 0;
public static final int SCROLL_DOWN = 1;
public static final int SCROLL_LEFT = 2;
public static final int SCROLL_RIGHT = 4;
protected Component _component;
protected boolean _vertical = true;
protected int _autoScrollInterval = 100;
private boolean _componentSelfScrollable = true;
private boolean _enabled = true;
protected AutoScroll(Component component) {
_component = component;
updateClientProperty(component, this);
}
protected AutoScroll(Component component, boolean vertical) {
_component = component;
_vertical = vertical;
updateClientProperty(component, this);
}
public int getAutoScrollInterval() {
return _autoScrollInterval;
}
public void setAutoScrollInterval(int autoScrollInterval) {
_autoScrollInterval = autoScrollInterval;
}
/**
* Checks if the AutoScroll is enabled.
*
* @return true if enabled. Otherwise false.
*/
public boolean isEnabled() {
return _enabled;
}
/**
* Enables or disables the AutoScroll feature.
*
* @param enabled true or false.
*/
public void setEnabled(boolean enabled) {
_enabled = enabled;
}
private class AutoScrollActionHandler implements ActionListener {
private int _direction;
AutoScrollActionHandler(int direction) {
_direction = direction;
}
public void actionPerformed(ActionEvent e) {
autoScrolling(_direction);
}
}
public void startAutoScrolling(int direction) {
if (_autoScrolling) {
_timer.stop();
}
_autoScrolling = true;
_scrollDirection = direction;
autoScrollingStarted(_scrollDirection);
_timer = new Timer(_autoScrollInterval, new AutoScrollActionHandler(_scrollDirection));
_timer.start();
}
/**
* This protected method is implementation specific and should be private. do not call or override.
*/
public void stopAutoScrolling() {
_autoScrolling = false;
if (_timer != null) {
_timer.stop();
_timer = null;
}
autoScrollingEnded(_scrollDirection);
}
public boolean isAutoScrolling() {
return _autoScrolling;
}
public int getScrollDirection() {
return _scrollDirection;
}
public boolean isComponentSelfScrollable() {
return _componentSelfScrollable;
}
public void setComponentSelfScrollable(boolean scrollable) {
_componentSelfScrollable = scrollable;
}
protected MouseEvent convertMouseEvent(MouseEvent e) {
if (e.getSource() == _component) {
return e;
}
Point convertedPoint = SwingUtilities.convertPoint((Component) e.getSource(),
e.getPoint(), _component);
return new MouseEvent((Component) e.getSource(),
e.getID(),
e.getWhen(),
e.getModifiers(),
convertedPoint.x,
convertedPoint.y,
e.getClickCount(),
e.isPopupTrigger());
}
public void mouseReleased(MouseEvent e) {
if (!isEnabled()) {
return;
}
_hasEntered = false;
stopAutoScrolling();
}
public void mousePressed(MouseEvent e) {
if (!isEnabled()) {
return;
}
stopAutoScrolling();
}
public void mouseDragged(MouseEvent e) {
if (!isEnabled()) {
return;
}
if (_componentSelfScrollable && e.getSource() == _component) {
return;
}
if (_component.isVisible()) {
MouseEvent newEvent = convertMouseEvent(e);
Rectangle r = new Rectangle();
if (_component instanceof JComponent) {
((JComponent) _component).computeVisibleRect(r);
}
else {
r = _component.getBounds();
}
if (newEvent.getPoint().y >= r.y && newEvent.getPoint().y <= r.y + r.height - 1 &&
newEvent.getPoint().x >= r.x && newEvent.getPoint().x <= r.x + r.width - 1) {
_hasEntered = true;
if (_autoScrolling) {
stopAutoScrolling();
}
Point location = newEvent.getPoint();
if (r.contains(location)) {
updateSelectionForEvent(newEvent, false);
}
}
else {
if (_hasEntered) {
int directionToScroll;
if (newEvent.getPoint().y < r.y) {
directionToScroll = SCROLL_UP;
}
else if (newEvent.getPoint().x < r.x) {
directionToScroll = SCROLL_LEFT;
}
else if (newEvent.getPoint().y > r.y + r.height) {
directionToScroll = SCROLL_DOWN;
}
else /*if(e.getPoint().x > r.x + r.width)*/ {
directionToScroll = SCROLL_RIGHT;
}
if (_autoScrolling && _scrollDirection != directionToScroll) {
stopAutoScrolling();
startAutoScrolling(directionToScroll);
}
else if (!_autoScrolling) {
startAutoScrolling(directionToScroll);
}
}
}
}
}
public void mouseMoved(MouseEvent e) {
if (!isEnabled()) {
return;
}
if (e.getSource() == _component) {
Point location = e.getPoint();
Rectangle r = new Rectangle();
if (_component instanceof JComponent) {
((JComponent) _component).computeVisibleRect(r);
if (r.contains(location)) {
updateSelectionForEvent(e, false);
}
}
else {
updateSelectionForEvent(e, false);
}
}
}
public void autoScrollingStarted(int direction) {
}
public void autoScrollingEnded(int direction) {
}
abstract public void autoScrolling(int direction);
abstract public void updateSelectionForEvent(MouseEvent e, boolean shouldScroll);
/**
* Gets the AutoScroll installed on the component. Null is no AutoScroll was installed.
*
* @param component the component
* @return the AutoScroll installed. Null is no AutoScroll was installed.
*/
public static AutoScroll getAutoScroll(Component component) {
Object clientProperty = component instanceof JComponent ? ((JComponent) component).getClientProperty(CLIENT_PROPERTY_AUTO_SCROLL) : null;
if (clientProperty instanceof AutoScroll) {
return ((AutoScroll) clientProperty);
}
else {
return null;
}
}
private void updateClientProperty(Component component, AutoScroll autoScroll) {
if (component != null) {
Object clientProperty = ((JComponent) _component).getClientProperty(CLIENT_PROPERTY_AUTO_SCROLL);
if (clientProperty instanceof AutoScroll) {
((AutoScroll) clientProperty).stopAutoScrolling();
}
if (component instanceof JComponent) {
((JComponent) component).putClientProperty(CLIENT_PROPERTY_AUTO_SCROLL, autoScroll);
}
}
}
}