package org.exist.client.xacml; import java.awt.Component; import java.awt.Container; import java.awt.Dimension; import java.awt.Point; import java.awt.Rectangle; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.JViewport; import javax.swing.Scrollable; import javax.swing.SwingConstants; import javax.swing.Timer; public class AutoScroller implements ActionListener { private static final int DELTA = 8; private static final int DEFAULT_INCREMENT = 42; private static final int DEFAULT_INITIAL_DELAY = 400; private static final int DEFAULT_REPEAT_DELAY = 50; private Component comp; private Point cursorLocation; private Timer scrollTimer; public AutoScroller() { scrollTimer = new Timer(DEFAULT_REPEAT_DELAY, this); scrollTimer.setCoalesce(true); scrollTimer.setRepeats(true); scrollTimer.setInitialDelay(DEFAULT_INITIAL_DELAY); scrollTimer.setDelay(DEFAULT_REPEAT_DELAY); } public void stop() { comp = null; cursorLocation = null; scrollTimer.stop(); } public void autoscroll(Component comp, Point cursorLocation) { this.comp = comp; this.cursorLocation = cursorLocation; scrollTimer.restart(); } public void actionPerformed(ActionEvent event) { Container parent = comp.getParent(); if(!(parent instanceof JViewport)) return; JViewport view = (JViewport)parent; Rectangle rect = view.getViewRect(); int horizontal = 0; int vertical = 0; int verticalDiffTop = cursorLocation.y - rect.y; int verticalDiffBottom = rect.height - verticalDiffTop; int horizontalDiffLeft = cursorLocation.x - rect.x; int horizontalDiffRight = rect.width - horizontalDiffLeft; if(verticalDiffTop < DELTA) vertical = -1; else if(verticalDiffBottom < DELTA) vertical = 1; if(horizontalDiffLeft < DELTA) horizontal = -1; else if(horizontalDiffRight < DELTA) horizontal = 1; if(comp instanceof Scrollable) { Scrollable scrollable = (Scrollable)comp; vertical *= scrollable.getScrollableUnitIncrement(rect, SwingConstants.VERTICAL, vertical); horizontal *= scrollable.getScrollableUnitIncrement(rect, SwingConstants.HORIZONTAL, horizontal); } else { vertical *= DEFAULT_INCREMENT; horizontal *= DEFAULT_INCREMENT; } Dimension viewSize = view.getViewSize(); Point newPosition = new Point(rect.x + horizontal, rect.y + vertical); if(newPosition.x < 0) newPosition.x = 0; else if(newPosition.x > viewSize.width - rect.width) newPosition.x = viewSize.width - rect.width; if(newPosition.y < 0) newPosition.y = 0; else if(newPosition.y > viewSize.height - rect.height) newPosition.y = viewSize.height - rect.height; if(newPosition.x != rect.x || newPosition.y != rect.y) { cursorLocation.x += (newPosition.x - rect.x); cursorLocation.y += (newPosition.y - rect.y); view.setViewPosition(newPosition); } } }