/*
* Copyright 2004 - 2008 Christian Sprajc. All rights reserved.
*
* This file is part of PowerFolder.
*
* PowerFolder is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation.
*
* PowerFolder 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.
*
* You should have received a copy of the GNU General Public License
* along with PowerFolder. If not, see <http://www.gnu.org/licenses/>.
*
* $Id$
*/
package de.dal33t.powerfolder.ui.util;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.JEditorPane;
import javax.swing.JScrollPane;
import javax.swing.JViewport;
import javax.swing.Timer;
import java.awt.Insets;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.AdjustmentEvent;
import java.awt.event.AdjustmentListener;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* A text pane that automatic scrolls the text, starts after a delay.
*
* @author <A HREF="mailto:schaatser@powerfolder.com">Jan van Oosterom</A>
* @version $Revision: 1.5 $
*/
public class ScrollableTextPane extends JScrollPane {
private static final Logger log = Logger.getLogger(ScrollableTextPane.class.getName());
/** Timer to control the scrolling */
protected Timer timer;
/** The text pane that holds our text */
private JEditorPane textPanel;
/** delay to wait after start or scrollbar change */
private int delay;
/** text in HTML format to scroll... */
public ScrollableTextPane(String text, int delay) {
this.delay = delay;
if (text == null) {
throw new NullPointerException("null text: " + text);
}
// set mimetype and text
textPanel = new JEditorPane("text/html", text);
// smooth ;-)
textPanel.setDoubleBuffered(true);
// no editing
textPanel.setEditable(false);
// marge
textPanel.setMargin(new Insets(4, 4, 4, 4));
// add to the scrollpane
JViewport viewPort = getViewport();
viewPort.add(textPanel);
// create timer
Action scrollText = new AbstractAction() {
public void actionPerformed(ActionEvent e) {
try {
timer.setDelay(30);
scroll();
} catch (Throwable t) {
log.log(Level.SEVERE, "Throwable", t);
}
}
};
// timer will call the above action every 30 milliseconds
timer = new Timer(delay, scrollText);
}
/** start scrolling */
public void start() {
//try detect if scroll bar changed by hand
//then wait again
getVerticalScrollBar().addAdjustmentListener(new AdjustmentListener() {
int lastValue = -10;
public void adjustmentValueChanged(AdjustmentEvent adjustmentEvent) {
if (adjustmentEvent.getValueIsAdjusting()) {
// The user is dragging the knob
return;
}
//if its one more than last its our scroll code...
//else its by hand
if (lastValue + 1 != adjustmentEvent.getValue()) {
timer.stop();
timer.setDelay(delay);
timer.start();
}
lastValue = adjustmentEvent.getValue();
}
});
Rectangle rect = new Rectangle(0, 0, 0, 0);
// scroll to start position
textPanel.scrollRectToVisible(rect);
timer.start();
}
/** stop scolling */
public void stop() {
timer.stop();
}
/**
* Scroll the contents of the textPanel
*/
private void scroll() {
// get visible rectangle
Rectangle rect = textPanel.getVisibleRect();
// get x / y values
int x = rect.x;
int y = this.getVerticalScrollBar().getValue();
// no scroll if at end
if ((y + rect.height) >= textPanel.getHeight()) {
return;
}
// one pixel lower:
y += 1;
Rectangle rectNew = new Rectangle(x, y, (x + rect.width),
(y + rect.height));
// scroll to next pixel
textPanel.scrollRectToVisible(rectNew);
}
}