/* * $Id$ * * Copyright 2009 Sun Microsystems, Inc., 4150 Network Circle, * Santa Clara, California 95054, U.S.A. All rights reserved. * * 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; either * version 2.1 of the License, or (at your option) any later version. * * 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. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * */ package org.jdesktop.swingx.table; import static org.jdesktop.swingx.table.TableUtilities.isDataChanged; import static org.jdesktop.swingx.table.TableUtilities.isInsert; import static org.jdesktop.swingx.table.TableUtilities.isStructureChanged; import static org.jdesktop.swingx.table.TableUtilities.isUpdate; import static org.jdesktop.swingx.table.TableUtilities.setPreferredRowHeight; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.util.logging.Logger; import javax.swing.JTable; import javax.swing.SwingUtilities; import javax.swing.event.TableModelEvent; import javax.swing.event.TableModelListener; import javax.swing.table.TableModel; /** * A controller to adjust JTable rowHeight based on sizing requirements of its renderers. * * @author Jeanette Winzenburg, Berlin */ public class TableRowHeightController { private JTable table; private TableModelListener tableModelListener; private PropertyChangeListener tablePropertyListener; /** * Instantiates an unbound TableRowHeightController. */ public TableRowHeightController() { this(null); } /** * Instantiates a TableRowHeightController and installs itself to the given table. * The row heights of all visible rows are automatically adjusted on model changes. * * @param table the table to control. */ public TableRowHeightController(JTable table) { install(table); } /** * Installs this controller on the given table. Releases control from previously * installed table, if any. * @param table the table to install upon. */ public void install(JTable table) { release(); if (table != null) { this.table = table; installListeners(); updatePreferredRowHeights(); } } /** * Release this controller from its table. Does nothing if no table installed. * */ public void release() { if (table == null) return; uninstallListeners(); table = null; } /** * Sets the row heights of the rows in the range of first- to lastRow, inclusive. * The coordinates are model indices. * * @param firstRow the first row in model coordinates * @param lastRow the last row in model coordinates */ protected void updatePreferredRowHeights(int firstRow, int lastRow) { for (int row = firstRow; row <= lastRow; row++) { int viewRow = table.convertRowIndexToView(row); if (viewRow >= 0) { // int oldHeight = table.getRowHeight(viewRow); // LOG.info("in viewRow/old/new: " + viewRow + " / " + oldHeight + " / " + table.getRowHeight(viewRow)); setPreferredRowHeight(table, viewRow); } } } /** * Sets the row heights of all rows. */ protected void updatePreferredRowHeights() { if (table.getRowCount() == 0) return; updatePreferredRowHeights(0, table.getModel().getRowCount() - 1); } /** * @param oldValue */ protected void updateModel(TableModel oldValue) { if (oldValue != null) { oldValue.removeTableModelListener(getTableModelListener()); } table.getModel().addTableModelListener(getTableModelListener()); updatePreferredRowHeights(); } /** * @return */ protected PropertyChangeListener createTablePropertyListener() { PropertyChangeListener l = new PropertyChangeListener() { @Override public void propertyChange(PropertyChangeEvent evt) { invokedPropertyChanged(evt); } /** * @param evt */ private void invokedPropertyChanged(final PropertyChangeEvent evt) { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { if ("model".equals(evt.getPropertyName())) { updateModel((TableModel) evt.getOldValue()); } } }); } }; return l; } protected TableModelListener createTableModelListener() { TableModelListener l = new TableModelListener() { @Override public void tableChanged(final TableModelEvent e) { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { invokedTableChanged(e); } }); } private void invokedTableChanged(TableModelEvent e) { if (isStructureChanged(e) || isDataChanged(e)) { updatePreferredRowHeights(); } else if (isUpdate(e) || isInsert(e)) { updatePreferredRowHeights(e.getFirstRow(), e.getLastRow()); } // do nothing on delete } }; return l; } /** * */ private void uninstallListeners() { table.removePropertyChangeListener(getPropertyChangeListener()); table.getModel().removeTableModelListener(getTableModelListener()); // whatever else turns out to be needed } private void installListeners() { table.addPropertyChangeListener(getPropertyChangeListener()); table.getModel().addTableModelListener(getTableModelListener()); // whatever else turns out to be needed } /** * @return */ protected TableModelListener getTableModelListener() { if (tableModelListener == null) { tableModelListener = createTableModelListener(); } return tableModelListener; } /** * @return */ protected PropertyChangeListener getPropertyChangeListener() { if (tablePropertyListener == null) { tablePropertyListener = createTablePropertyListener(); } return tablePropertyListener; } @SuppressWarnings("unused") private static final Logger LOG = Logger .getLogger(TableRowHeightController.class.getName()); }