/* * $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 java.awt.Component; import java.awt.Font; import java.awt.event.ActionEvent; import java.lang.reflect.InvocationTargetException; import java.util.logging.Logger; import javax.swing.AbstractAction; import javax.swing.Action; import javax.swing.JTable; import javax.swing.SwingUtilities; import javax.swing.event.TableModelListener; import javax.swing.table.AbstractTableModel; import javax.swing.table.DefaultTableCellRenderer; import javax.swing.table.DefaultTableModel; import javax.swing.table.TableCellRenderer; import org.jdesktop.swingx.InteractiveTestCase; import org.jdesktop.swingx.JXFrame; import org.jdesktop.swingx.JXTable; import org.jdesktop.swingx.decorator.ComponentAdapter; import org.jdesktop.swingx.decorator.HighlightPredicate; import org.jdesktop.swingx.renderer.HighlighterClientVisualCheck.FontHighlighter; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; /** * Tests for TableRowHeightController. * * @author Jeanette Winzenburg */ @RunWith(JUnit4.class) public class TableRowHeightControllerTest extends InteractiveTestCase { @SuppressWarnings("unused") private static final Logger LOG = Logger .getLogger(TableRowHeightControllerTest.class.getName()); private static final String BIG = "BIG"; private static final String SMALL = "small"; private TableRowHeightController controller; private JXTable table; public static void main(String[] args) { TableRowHeightControllerTest test = new TableRowHeightControllerTest(); try { test.runInteractiveTests(); } catch (Exception e) { e.printStackTrace(); } } public void interactiveCoreTableRowHeights() { final JTable table = createCoreTableWithIndyRowHeights(); table.setAutoCreateRowSorter(true); new TableRowHeightController().install(table); JXFrame frame = wrapWithScrollingInFrame(table, "core: row heights"); Action toggleBig = new AbstractAction("toggleSize") { @Override public void actionPerformed(ActionEvent e) { if (table.getSelectionModel().isSelectionEmpty()) return; int selected = table.getSelectedRow(); Object value = BIG.equals(table.getValueAt(selected, 0)) ? SMALL : BIG; table.setValueAt(value, selected, 0); } }; addAction(frame, toggleBig); Action toggleModel = new AbstractAction("toggleModel") { boolean evenBig; @Override public void actionPerformed(ActionEvent e) { table.setModel(createTableModel(evenBig)); evenBig = !evenBig; } }; addAction(frame, toggleModel); show(frame); } public void interactiveRowHeights() { final JXTable table = createXTableWithIndyRowHeights(); new TableRowHeightController().install(table); table.packAll(); JXFrame frame = wrapWithScrollingInFrame(table, "x: row heights"); Action toggleBig = new AbstractAction("toggleSize") { @Override public void actionPerformed(ActionEvent e) { if (table.getSelectionModel().isSelectionEmpty()) return; int selected = table.getSelectedRow(); Object value = BIG.equals(table.getValueAt(selected, 0)) ? SMALL : BIG; table.setValueAt(value, selected, 0); } }; addAction(frame, toggleBig); Action toggleModel = new AbstractAction("toggleModel") { boolean evenBig; @Override public void actionPerformed(ActionEvent e) { table.setModel(createTableModel(evenBig)); evenBig = !evenBig; } }; addAction(frame, toggleModel); show(frame); } /** * @return */ private JTable createCoreTableWithIndyRowHeights() { DefaultTableModel model = createTableModel(false); JTable table = new JTable(model); final Font derivedFont = table.getFont().deriveFont(50f); TableCellRenderer renderer = new DefaultTableCellRenderer() { @Override public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { Component comp = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); if (BIG.equals(value)) { setFont(derivedFont); } return comp; } }; table.setDefaultRenderer(Object.class, renderer); return table; } /** * Creates and returns a JXTable with model as returned by createTableModel with * eventBig == false. * Has a FontHighlighter which decorates the renderer with a big font if * the cell value is BIG. * * @return a JXTable configured */ private JXTable createXTableWithIndyRowHeights() { DefaultTableModel model = createTableModel(false); JXTable table = new JXTable(model); HighlightPredicate predicate = new HighlightPredicate() { @Override public boolean isHighlighted(Component renderer, ComponentAdapter adapter) { return BIG.equals(adapter.getValue()); } }; FontHighlighter highlighter = new FontHighlighter(predicate, table.getFont().deriveFont(50f)); table.addHighlighter(highlighter); return table; } /** * Creates and returns a table model with value in first column alternating between * SMALL and BIG. * * @param evenBig starts with BIG if true, starts with SMALL otherwise * @return a DefaultTableModel with alternating SMALL/BIG values in first column. */ private DefaultTableModel createTableModel(boolean evenBig) { int compare = evenBig ? 0 : 1; DefaultTableModel model = new DefaultTableModel(10, 2) { @Override public Class<?> getColumnClass(int columnIndex) { if (columnIndex == getColumnCount() - 1) { return Boolean.class; } return super.getColumnClass(columnIndex); } }; for (int i = 0; i < model.getRowCount(); i++) { if (i % 2 == compare) { model.setValueAt(BIG, i, 0); } else { model.setValueAt(SMALL, i, 0); } } return model; } @Test public void testSetModelRewiresModelListeners() throws InterruptedException, InvocationTargetException { final int smallRowHeight = table.getRowHeight(1); final AbstractTableModel oldModel = (AbstractTableModel) table.getModel(); assertEquals("sanity: model listener installed", true, containsModelListener(oldModel)); final DefaultTableModel model = createTableModel(true); table.setModel(model); SwingUtilities.invokeAndWait(new Runnable() { @Override public void run() { assertEquals("new model must be installed", true, containsModelListener(model)); assertEquals("oldModel must be released", false, containsModelListener(oldModel)); assertEquals(smallRowHeight, table.getRowHeight(0)); } }); } /** * @param model * @return */ private boolean containsModelListener(AbstractTableModel model) { TableModelListener[] listeners = model.getListeners(TableModelListener.class); for (TableModelListener l : listeners) { if (l == controller.getTableModelListener()) return true; } return false; } @Test public void testRowHeightAdjustedOnInsert() throws InterruptedException, InvocationTargetException { final int bigRowHeight = table.getRowHeight(1); SwingUtilities.invokeAndWait(new Runnable() { @Override public void run() { ((DefaultTableModel) table.getModel()).insertRow(0, new Object[] {BIG}); } }); SwingUtilities.invokeAndWait(new Runnable() { @Override public void run() { assertEquals(bigRowHeight, table.getRowHeight(0)); } }); } @Test public void testRowHeightAdjustedOnUpdate() throws InterruptedException, InvocationTargetException { final int smallRowHeight = table.getRowHeight(0); table.setValueAt(table.getValueAt(0, 0), 1, 0); SwingUtilities.invokeAndWait(new Runnable() { @Override public void run() { assertEquals(smallRowHeight, table.getRowHeight(1)); } }); } @Test public void testRowHeightAdjustedWithPrepare() { int rowHeight = table.getRowHeight(0); int bigRowHeight = table.getRowHeight(1); assertEquals(getRendererRowHeight(0, 0), table.getRowHeight(0)); assertEquals(getRendererRowHeight(1, 0), table.getRowHeight(1)); assertTrue(" ", 2 * rowHeight < bigRowHeight); } /** * @param i * @return */ private int getRendererRowHeight(int row, int column) { TableCellRenderer renderer = table.getCellRenderer(row, column); Component comp = table.prepareRenderer(renderer, row, column); return comp.getPreferredSize().height; } @Override @Before public void setUp() throws Exception { table = createXTableWithIndyRowHeights(); controller = new TableRowHeightController(table); // controller.install(table); } }