/* * GeoTools - The Open Source Java GIS Toolkit * http://geotools.org * * (C) 2001-2008, Open Source Geospatial Foundation (OSGeo) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License. * * This library 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 * Lesser General Public License for more details. */ package org.geotools.gui.swing; // J2SE dependencies import java.io.Serializable; import javax.swing.JScrollBar; import javax.swing.JScrollPane; import javax.swing.BoundedRangeModel; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import javax.swing.table.DefaultTableModel; // For JavaDoc only /** * Scroll down a panel when new lines are added. This helper class require only the reference * to the underlying {@link BoundedRangeModel}. If the model's value is equals to its maximal * value and this maximal value increase, then this class increase the model's value as well. * Example of use: * * <blockquote><pre> * {@link DefaultTableModel} table = new DefaultTableModel(); * {@link JScrollPane} pane = new JScrollPane(new JTable(table)); * {@link AutoScroll} autos = new AutoScrool(pane.getVerticalScrollBar().getModel()); * // etc... * * // Now, add the new item to the table. The table * // will be scrolled down automatically if needed. * table.addRow(...); * </pre></blockquote> * * @since 2.0 * @source $URL$ * @version $Id$ * @author Martin Desruisseaux (IRD) */ final class AutoScroll implements ChangeListener, Serializable { /** * Serial number for interoperability with different versions. */ private static final long serialVersionUID = 8932928616386789102L; /** * The model for the vertical scrollbar. */ private final BoundedRangeModel model; /** * Properties of the {@link BoundedRangeModel} the last time {@link #sync} has been invoked. */ private int value, extent, maximum; /** * Constructs a new {@code AutoScroll} for the specified model. */ public AutoScroll(final BoundedRangeModel model) { this.model = model; model.addChangeListener(this); sync(); } /** * Disposes any resources hold by this object. * This method deregisters any listeners. */ public void dispose() { model.removeChangeListener(this); } /** * Copies current model's state into {@link #value}, * {@link #extent} and {@link #maximum} fields. */ private void sync() { value = model.getValue(); extent = model.getExtent(); maximum = model.getMaximum(); } /** * Invoked automatically when the upper limit of {@link BoundedRangeModel} has increased. * If the last row was visible prior the addition of new rows, then this method scrolls * down the model in order to show the new rows. */ public void stateChanged(final ChangeEvent event) { final int oldValue = value; final int oldExtent = extent; final int oldMaximum = maximum; sync(); if (oldValue+oldExtent >= oldMaximum) { if (value==oldValue && extent>=oldExtent && maximum>oldMaximum) { model.setValue(oldValue + (maximum-oldMaximum)); } } } }