/*
* $Id$
*
* Copyright 2006 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.renderer;
import java.awt.Color;
import java.awt.Component;
import java.io.Serializable;
import java.text.DateFormat;
import java.util.Date;
import java.util.logging.Logger;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JTable;
import javax.swing.UIManager;
import javax.swing.border.Border;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableModel;
import org.jdesktop.swingx.InteractiveTestCase;
import org.jdesktop.swingx.JXTable;
import org.jdesktop.swingx.test.XTestUtils;
import org.jdesktop.test.SerializableSupport;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
/**
* Tests behaviour of SwingX renderers. Currently: mostly characterization to
* guarantee that they behave similar to the standard.
*
* @author Jeanette Winzenburg
*/
@RunWith(JUnit4.class)
public class TableRendererTest extends InteractiveTestCase {
private static final Logger LOG = Logger.getLogger(TableRendererTest.class
.getName());
private JTable table;
private int coreColumn;
private DefaultTableCellRenderer coreTableRenderer;
private int xColumn;
private DefaultTableRenderer xTableRenderer;
@Before
public void setUpJ4() throws Exception {
setUp();
}
@After
public void tearDownJ4() throws Exception {
tearDown();
}
/**
* Issue #1345-swingx: TableCellContext optional handling of LAF provided alternateRowColor
*/
@Test
public void testNotHandleAlternateColor() {
TableCellRenderer renderer = new DefaultTableRenderer();
Color oldColor = UIManager.getColor("Table.alternateRowColor");
Object oldHandle = UIManager.get(TableCellContext.HANDLE_ALTERNATE_ROW_BACKGROUND);
try {
// alternate color
UIManager.put("Table.alternateRowColor", Color.MAGENTA);
// remove handle flag
UIManager.put(TableCellContext.HANDLE_ALTERNATE_ROW_BACKGROUND, null);
JTable table = new JTable(10, 2);
Component comp = renderer.getTableCellRendererComponent(table, null, false, false, 0, -1);
// even row has table background
assertEquals(table.getBackground(), comp.getBackground());
// odd row has alternate background if handle active - here it is not, so expect
// stable background
renderer.getTableCellRendererComponent(table, null, false, false, 1, -1);
assertEquals(table.getBackground(), comp.getBackground());
} finally {
UIManager.put("Table.alternateRowColor", oldColor);
UIManager.put(TableCellContext.HANDLE_ALTERNATE_ROW_BACKGROUND, oldHandle);
}
}
/**
* Issue #1345-swingx: TableCellContext optional handling of LAF provided alternateRowColor
*/
@Test
public void testAlternateColor() {
TableCellRenderer renderer = new DefaultTableRenderer();
Color oldColor = UIManager.getColor("Table.alternateRowColor");
Object oldHandle = UIManager.get(TableCellContext.HANDLE_ALTERNATE_ROW_BACKGROUND);
try {
UIManager.put("Table.alternateRowColor", Color.MAGENTA);
UIManager.put(TableCellContext.HANDLE_ALTERNATE_ROW_BACKGROUND, Boolean.TRUE);
JTable table = new JTable(10, 2);
Component comp = renderer.getTableCellRendererComponent(table, null, false, false, 0, -1);
// even row has table background
assertEquals(table.getBackground(), comp.getBackground());
// odd row has alternate background
renderer.getTableCellRendererComponent(table, null, false, false, 1, -1);
assertEquals(Color.MAGENTA, comp.getBackground());
} finally {
UIManager.put("Table.alternateRowColor", oldColor);
UIManager.put(TableCellContext.HANDLE_ALTERNATE_ROW_BACKGROUND, oldHandle);
}
}
@Test
public void testUIPropertyHandleAlternateRowColor() {
assertNull(UIManager.get(TableCellContext.HANDLE_ALTERNATE_ROW_BACKGROUND));
}
@Override
protected void setUp() throws Exception {
// setup table
table = new JTable(10, 2);
coreColumn = 0;
coreTableRenderer = new DefaultTableCellRenderer();
table.getColumnModel().getColumn(coreColumn).setCellRenderer(coreTableRenderer);
xColumn = 1;
xTableRenderer = new DefaultTableRenderer();
table.getColumnModel().getColumn(xColumn).setCellRenderer(xTableRenderer);
}
/**
* Issue #484-swingx: dnd on color not showing.
* Can't really test - can't mock a drop-on only bare context methods.
*/
@Test
public void testCellContextDropOn() {
TableCellContext cellContext = new TableCellContext();
cellContext.installContext(null, "whatever", 0, 0, false, true, false, false);
assertFalse("context must cope with null component", cellContext.isDropOn());
// fake ... and test internals
cellContext.dropOn = true;
assertTrue("context must use dropOn flag ... dooh", cellContext.isDropOn());
}
/**
* Issue #484-swingx: dnd on color not showing.
* Can't really test - can't mock a drop-on only bare context methods.
*/
@Test
public void testCellContextDropOnColors() {
TableCellContext cellContext = new TableCellContext();
Color dropBackground = UIManager.getColor("Table.dropCellBackground");
LOG.info("background " + dropBackground);
if (dropBackground != null) {
assertEquals(dropBackground, cellContext.getDropCellBackground());
}
Color dropForeground = UIManager.getColor("Table.dropCellForeground");
LOG.info("foreground " + dropForeground);
if (dropForeground != null) {
assertEquals(dropForeground, cellContext.getDropCellForeground());
}
}
/**
* Issue ??-swingx: getEditable throws if cell coordinates invalid
*/
@Test
public void testCellContextEditable() {
TableCellContext cellContext = new TableCellContext();
cellContext.installContext(null, "whatever", 0, 0, false, true, false, false);
assertFalse("context must cope with null component", cellContext.isEditable());
JXTable table = new JXTable();
cellContext.installContext(table, "whatever", 0, 0, false, true, false, false);
// KEEP commented lines is real-world example that'll blow
// DefaultVisuals visuals = new DefaultVisuals();
// visuals.configureVisuals(new JLabel(), cellContext);
assertFalse("context must cope with invalid coordinates", cellContext.isEditable());
}
/**
* Test constructors: here convenience with alignment and converter
*
*/
@Test
public void testConstructor() {
FormatStringValue sv = new FormatStringValue(DateFormat.getTimeInstance());
int align = JLabel.RIGHT;
DefaultTableRenderer renderer = new DefaultTableRenderer(sv, align);
assertEquals(sv, renderer.componentController.getStringValue());
assertEquals(align, renderer.componentController.getHorizontalAlignment());
}
/**
* test if icon handling is the same for core default and
* swingx.
*
*/
@Test
public void testIcon() {
TableModel model = createTableModelWithDefaultTypes();
int iconColumn = 4;
// sanity
assertTrue(Icon.class.isAssignableFrom(model.getColumnClass(iconColumn)));
Icon icon = (Icon) model.getValueAt(0, iconColumn);
// default uses a different class for icon rendering
DefaultTableCellRenderer coreIconRenderer = (DefaultTableCellRenderer) table.getDefaultRenderer(Icon.class);
// core default can't cope with null component - can't really compare behaviour
coreIconRenderer.getTableCellRendererComponent(table, icon, false, false, -1, -1);
assertEquals(icon, coreIconRenderer.getIcon());
assertEquals("", coreIconRenderer.getText());
JXTable xTable = new JXTable();
TableCellRenderer xIconRenderer = xTable.getDefaultRenderer(Icon.class);
JLabel label = (JLabel) xIconRenderer.getTableCellRendererComponent(null, icon, false, false, -1, -1);
assertEquals(icon, label.getIcon());
assertEquals("", label.getText());
// wrong assumption after fix of #591-swingx - default icon renderer
// no longer tries to be clever
// label = (JLabel) xIconRenderer.getTableCellRendererComponent(null, "dummy", false, false, -1, -1);
// assertNull(label.getIcon());
// assertEquals("dummy", label.getText());
}
/**
* @return
*/
private TableModel createTableModelWithDefaultTypes() {
String[] names = {"Object", "Number", "Double", "Date", "ImageIcon", "Boolean"};
final Class<?>[] types = {Object.class, Number.class, Double.class, Date.class, ImageIcon.class, Boolean.class};
DefaultTableModel model = new DefaultTableModel(names, 0) {
@Override
public Class<?> getColumnClass(int columnIndex) {
return types[columnIndex];
}
};
Date today = new Date();
Icon icon = XTestUtils.loadDefaultIcon();
for (int i = 0; i < 10; i++) {
Object[] values = new Object[] {"row " + i, i, Math.random() * 100,
new Date(today.getTime() + i * 1000000), icon, i % 2 == 0};
model.addRow(values);
}
return model;
}
/**
* test serializable of default renderer.
*
*/
@Test
public void testSerializeTableRenderer() {
TableCellRenderer xListRenderer = new DefaultTableRenderer();
try {
SerializableSupport.serialize(xListRenderer);
} catch (Exception e) {
fail("not serializable " + e);
}
}
/**
* base interaction with table: focused, selected uses UI border.
*/
@Test
public void testTableFocusSelectedBorder() {
// sanity to see test test validity
// UIManager.put("Table.focusSelectedCellHighlightBorder", new LineBorder(Color.red));
// access ui colors
Border selectedFocusBorder = getFocusBorder(true);
// sanity
if (selectedFocusBorder == null) {
LOG.info("cannot run focusSelectedBorder - UI has no selected focus border");
return;
}
// need to prepare directly - focus is true only if table is focusowner
JComponent coreComponent = (JComponent) coreTableRenderer.getTableCellRendererComponent(table,
null, true, true, 0, coreColumn);
// sanity: known standard behaviour
assertEquals(selectedFocusBorder, coreComponent.getBorder());
// prepare extended
JComponent xComponent = (JComponent) xTableRenderer.getTableCellRendererComponent(table,
null, true, true, 0, xColumn);
// assert behaviour same as standard
assertEquals(coreComponent.getBorder(), xComponent.getBorder());
}
private Border getFocusBorder(boolean lookup) {
Border selectedFocusBorder = UIManager.getBorder("Table.focusSelectedCellHighlightBorder");
if (lookup && (selectedFocusBorder == null)) {
selectedFocusBorder = UIManager.getBorder("Table.focusCellHighlightBorder");
}
return selectedFocusBorder;
}
/**
* base interaction with table: focused, not-selected uses UI border.
*
*
*/
@Test
public void testTableFocusBorder() {
// access ui colors
Border focusBorder = UIManager.getBorder("Table.focusCellHighlightBorder");
// Border selectedFocusBorder = UIManager.getBorder("Table.focusSelectedCellHighlightBorder");
// sanity
assertNotNull(focusBorder);
// need to prepare directly - focus is true only if table is focusowner
JComponent coreComponent = (JComponent) coreTableRenderer.getTableCellRendererComponent(table,
null, false, true, 0, coreColumn);
// sanity: known standard behaviour
assertEquals(focusBorder, coreComponent.getBorder());
// prepare extended
JComponent xComponent = (JComponent) xTableRenderer.getTableCellRendererComponent(table,
null, false, true, 0, xColumn);
// assert behaviour same as standard
assertEquals(coreComponent.getBorder(), xComponent.getBorder());
}
/**
* base interaction with table: focused, not-selected and editable
* uses UI colors.
*
*/
@Test
public void testTableRendererExtFocusedNotSelectedEditable() {
// sanity
assertTrue(table.isCellEditable(0, coreColumn));
// access ui colors
Color uiForeground = UIManager.getColor("Table.focusCellForeground");
Color uiBackground = UIManager.getColor("Table.focusCellBackground");
// sanity
assertNotNull(uiForeground);
assertNotNull(uiBackground);
Color background = Color.MAGENTA;
Color foreground = Color.YELLOW;
// prepare standard
coreTableRenderer.setBackground(background);
coreTableRenderer.setForeground(foreground);
// need to prepare directly - focus is true only if table is focusowner
Component coreComponent = coreTableRenderer.getTableCellRendererComponent(table,
null, false, true, 0, coreColumn);
// sanity: known standard behaviour
assertEquals(uiBackground, coreComponent.getBackground());
assertEquals(uiForeground, coreComponent.getForeground());
// prepare extended
xTableRenderer.setBackground(background);
xTableRenderer.setForeground(foreground);
Component xComponent = xTableRenderer.getTableCellRendererComponent(table,
null, false, true, 0, xColumn);
// assert behaviour same as standard
assertEquals(coreComponent.getBackground(), xComponent.getBackground());
assertEquals(coreComponent.getForeground(), xComponent.getForeground());
}
/**
* base interaction with table: custom color of renderer precedes
* table color.
*
*/
@Test
public void testTableRendererExtCustomColor() {
Color background = Color.MAGENTA;
Color foreground = Color.YELLOW;
// prepare standard
coreTableRenderer.setBackground(background);
coreTableRenderer.setForeground(foreground);
Component coreComponent = table.prepareRenderer(coreTableRenderer, 0, coreColumn);
// sanity: known standard behaviour
assertEquals(background, coreComponent.getBackground());
assertEquals(foreground, coreComponent.getForeground());
// prepare extended
xTableRenderer.setBackground(background);
xTableRenderer.setForeground(foreground);
Component xComponent = table.prepareRenderer(xTableRenderer, 0, xColumn);
// assert behaviour same as standard
assertEquals(coreComponent.getBackground(), xComponent.getBackground());
assertEquals(coreComponent.getForeground(), xComponent.getForeground());
}
/**
* base interaction with table: renderer uses table's selection color.
*
*/
@Test
public void testTableRendererExtSelectedColors() {
// select first row
table.setRowSelectionInterval(0, 0);
// prepare standard
Component coreComponent = table.prepareRenderer(coreTableRenderer, 0, coreColumn);
// sanity: known standard behaviour
assertEquals(table.getSelectionBackground(), coreComponent.getBackground());
assertEquals(table.getSelectionForeground(), coreComponent.getForeground());
// prepare extended
Component xComponent = table.prepareRenderer(xTableRenderer, 0, xColumn);
// assert behaviour same as standard
assertEquals(coreComponent.getBackground(), xComponent.getBackground());
assertEquals(coreComponent.getForeground(), xComponent.getForeground());
}
/**
* base interaction with table: renderer uses table's custom selection color.
*
*/
@Test
public void testTableRendererExtTableSelectedColors() {
Color background = Color.MAGENTA;
Color foreground = Color.YELLOW;
table.setSelectionBackground(background);
table.setSelectionForeground(foreground);
// select first row
table.setRowSelectionInterval(0, 0);
// prepare standard
Component coreComponent = table.prepareRenderer(coreTableRenderer, 0, coreColumn);
// sanity: known standard behaviour
assertEquals(table.getSelectionBackground(), coreComponent.getBackground());
assertEquals(table.getSelectionForeground(), coreComponent.getForeground());
// prepare extended
Component xComponent = table.prepareRenderer(xTableRenderer, 0, xColumn);
// assert behaviour same as standard
assertEquals(coreComponent.getBackground(), xComponent.getBackground());
assertEquals(coreComponent.getForeground(), xComponent.getForeground());
}
/**
* base interaction with table: renderer uses table's unselected colors.
*
*/
@Test
public void testTableRendererExtColors() {
// prepare standard
Component coreComponent = table.prepareRenderer(coreTableRenderer, 0, coreColumn);
// sanity: known standard behaviour
assertEquals(table.getBackground(), coreComponent.getBackground());
assertEquals(table.getForeground(), coreComponent.getForeground());
// prepare extended
Component xComponent = table.prepareRenderer(xTableRenderer, 0, xColumn);
// assert behaviour same as standard
assertEquals(coreComponent.getBackground(), xComponent.getBackground());
assertEquals(coreComponent.getForeground(), xComponent.getForeground());
}
/**
* base interaction with table: renderer uses table's unselected custom colors
*
*
*/
@Test
public void testTableRendererExtTableColors() {
Color background = Color.MAGENTA;
Color foreground = Color.YELLOW;
table.setBackground(background);
table.setForeground(foreground);
// prepare standard
Component coreComponent = table.prepareRenderer(coreTableRenderer, 0, coreColumn);
// sanity: known standard behaviour
assertEquals(table.getBackground(), coreComponent.getBackground());
assertEquals(table.getForeground(), coreComponent.getForeground());
// prepare extended
Component xComponent = table.prepareRenderer(xTableRenderer, 0, xColumn);
// assert behaviour same as standard
assertEquals(coreComponent.getBackground(), xComponent.getBackground());
assertEquals(coreComponent.getForeground(), xComponent.getForeground());
}
/**
* characterize opaqueness of rendering components.
*
*/
@Test
public void testTableOpaqueRenderer() {
// sanity
assertFalse(new JLabel().isOpaque());
assertTrue(coreTableRenderer.isOpaque());
// assertTrue(xTableRenderer.getRendererComponent().isOpaque());
}
/**
* characterize opaqueness of rendering components.
*
* that's useless: the opaque magic only applies if parent != null
*/
@Test
public void testTableOpaqueRendererComponent() {
// sanity
assertFalse(new JLabel().isOpaque());
Component coreComponent = table.prepareRenderer(coreTableRenderer, 0, coreColumn);
// prepare extended
assertTrue(coreComponent.isOpaque());
Component xComponent = table.prepareRenderer(xTableRenderer, 0, xColumn);
assertTrue(xComponent.isOpaque());
}
/**
* base existence/type tests while adding DefaultTableCellRendererExt.
*
*/
@Test
public void testTableRendererExt() {
DefaultTableRenderer renderer = new DefaultTableRenderer();
assertTrue(renderer instanceof TableCellRenderer);
assertTrue(renderer instanceof Serializable);
}
}