/*
* $Id$
*
* Copyright 2004 Sun Microsystems, Inc., 4150 Network Circle,
* Santa Clara, California 95054, U.S.A. All rights reserved.
*/
package org.jdesktop.swingx;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GraphicsEnvironment;
import java.awt.event.MouseEvent;
import java.beans.PropertyChangeListener;
import java.lang.reflect.InvocationTargetException;
import java.net.MalformedURLException;
import java.net.URL;
import java.text.Collator;
import java.util.Arrays;
import java.util.Vector;
import java.util.logging.Logger;
import java.util.regex.Pattern;
import javax.swing.DefaultComboBoxModel;
import javax.swing.DefaultListCellRenderer;
import javax.swing.DefaultListModel;
import javax.swing.ListCellRenderer;
import javax.swing.ListModel;
import javax.swing.RowFilter;
import javax.swing.SortOrder;
import javax.swing.SwingUtilities;
import javax.swing.text.Position.Bias;
import org.jdesktop.swingx.JXList.DelegatingRenderer;
import org.jdesktop.swingx.decorator.ColorHighlighter;
import org.jdesktop.swingx.decorator.ComponentAdapter;
import org.jdesktop.swingx.decorator.Highlighter;
import org.jdesktop.swingx.decorator.SearchPredicate;
import org.jdesktop.swingx.decorator.ComponentAdapterTest.JXListT;
import org.jdesktop.swingx.hyperlink.LinkModel;
import org.jdesktop.swingx.renderer.DefaultListRenderer;
import org.jdesktop.swingx.renderer.StringValue;
import org.jdesktop.swingx.renderer.StringValues;
import org.jdesktop.swingx.rollover.ListRolloverController;
import org.jdesktop.swingx.rollover.RolloverProducer;
import org.jdesktop.swingx.sort.DefaultSortController;
import org.jdesktop.swingx.sort.ListSortController;
import org.jdesktop.swingx.sort.RowFilters;
import org.jdesktop.swingx.sort.StringValueRegistry;
import org.jdesktop.swingx.sort.TableSortController;
import org.jdesktop.test.AncientSwingTeam;
import org.jdesktop.test.PropertyChangeReport;
import org.jdesktop.test.TestUtils;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
/**
* Testing JXList. <p>
*
* Note: all tests related to the disabled sorting/filtering support are moved to
* JXListSortRevamp and forced to fail.
*
* @author Jeanette Winzenburg
*/
@RunWith(JUnit4.class)
public class JXListTest extends InteractiveTestCase {
@SuppressWarnings("unused")
private static final Logger LOG = Logger.getLogger(JXListTest.class
.getName());
protected ListModel listModel;
protected DefaultListModel ascendingListModel;
/** empty default list */
private JXList list;
private StringValue sv;
/**
* Issue #1563-swingx: find cell that was clicked for componentPopup
*
* Test api and event firing.
*/
@Test
public void testPopupTriggerLocationAvailable() {
JXList table = new JXList(listModel);
MouseEvent event = new MouseEvent(table, 0,
0, 0, 40, 5, 0, false);
PropertyChangeReport report = new PropertyChangeReport(table);
table.getPopupLocation(event);
assertEquals(event.getPoint(), table.getPopupTriggerLocation());
TestUtils.assertPropertyChangeEvent(report, "popupTriggerLocation",
null, event.getPoint());
}
/**
* Issue #1563-swingx: find cell that was clicked for componentPopup
*
* Test safe return value.
*/
@Test
public void testPopupTriggerCopy() {
JXList table = new JXList(listModel);
MouseEvent event = new MouseEvent(table, 0,
0, 0, 40, 5, 0, false);
table.getPopupLocation(event);
assertNotSame("trigger point must not be same",
table.getPopupTriggerLocation(), table.getPopupTriggerLocation());
}
/**
* Issue #1563-swingx: find cell that was clicked for componentPopup
*
* Test safe handle null.
*/
@Test
public void testPopupTriggerKeyboard() {
JXList table = new JXList(listModel);
MouseEvent event = new MouseEvent(table, 0,
0, 0, 40, 5, 0, false);
table.getPopupLocation(event);
PropertyChangeReport report = new PropertyChangeReport(table);
table.getPopupLocation(null);
assertNull("trigger must null",
table.getPopupTriggerLocation());
TestUtils.assertPropertyChangeEvent(report, "popupTriggerLocation",
event.getPoint(), null);
}
/**
* Issue #1263-swingx: JXList selectedValues must convert index to model.
*/
@Test
public void testGetSelectedValue() {
DefaultListModel model = new DefaultListModel();
model.addElement("One");
model.addElement("Two");
model.addElement("Three");
model.addElement("Four");
model.addElement("Five");
model.addElement("Six");
model.addElement("Seven");
JXList list = new JXList();
list.setAutoCreateRowSorter(true);
list.setModel(model);
list.setSelectedIndex(2);
assertEquals("Three", list.getSelectedValue());
list.setRowFilter(new RowFilter<ListModel, Integer>() {
@Override
public boolean include(Entry<? extends ListModel, ? extends Integer> entry) {
return entry.getStringValue(entry.getIdentifier()).contains("e");
}
});
assertEquals("Three", list.getSelectedValue());
}
/**
* Issue #1263-swingx: JXList selectedValues must convert index to model.
*/
@Test
public void testGetSelectedValues() {
DefaultListModel model = new DefaultListModel();
model.addElement("One");
model.addElement("Two");
model.addElement("Three");
model.addElement("Four");
model.addElement("Five");
model.addElement("Six");
model.addElement("Seven");
JXList list = new JXList();
list.setAutoCreateRowSorter(true);
list.setModel(model);
list.setSelectedIndex(2);
list.addSelectionInterval(0, 2);
assertTrue(Arrays.deepEquals(new Object[] {"One", "Two", "Three"}, list.getSelectedValues()));
list.setRowFilter(new RowFilter<ListModel, Integer>() {
@Override
public boolean include(Entry<? extends ListModel, ? extends Integer> entry) {
return entry.getStringValue(entry.getIdentifier()).contains("e");
}
});
assertTrue(Arrays.deepEquals(new Object[] {"One", "Three"}, list.getSelectedValues()));
list.clearSelection();
list.addSelectionInterval(0, 2);
assertTrue(Arrays.deepEquals(new Object[] {"One", "Three", "Five"}, list.getSelectedValues()));
}
/**
* Issue #1263-swingx: JXList selectedValues must convert index to model.
*/
@Test
public void testSetSelectedValue() {
DefaultListModel model = new DefaultListModel();
model.addElement("One");
model.addElement("Two");
model.addElement("Three");
model.addElement("Four");
model.addElement("Five");
model.addElement("Six");
model.addElement("Seven");
JXList list = new JXList();
list.setAutoCreateRowSorter(true);
list.setModel(model);
list.setSelectedValue("Three", false);
assertEquals(2, list.getSelectedIndex());
list.setRowFilter(new RowFilter<ListModel, Integer>() {
@Override
public boolean include(Entry<? extends ListModel, ? extends Integer> entry) {
return entry.getStringValue(entry.getIdentifier()).contains("e");
}
});
assertEquals(1, list.getSelectedIndex());
list.setSelectedValue("Five", false);
assertEquals(2, list.getSelectedIndex());
}
/**
* Issue #1232-swingx: JXList must fire property change on setCellRenderer.
*
*/
@Test
public void testRendererNotification() {
JXList list = new JXList();
assertNotNull("sanity: ", list.getCellRenderer());
// very first setting: fires twice ... a bit annoying but ... waiting for complaints ;-)
list.setCellRenderer(new DefaultListRenderer());
PropertyChangeReport report = new PropertyChangeReport(list);
list.setCellRenderer(new DefaultListRenderer());
TestUtils.assertPropertyChangeEvent(report, "cellRenderer", null, list.getCellRenderer());
}
/**
* Issue #1162-swingx: getNextMatch incorrect if sorted.
*/
@Test
public void testNextMatch() {
JXList list = new JXList(AncientSwingTeam.createNamedColorListModel(), true);
int index = list.getNextMatch("b", 0, Bias.Forward);
assertEquals(1, index);
list.toggleSortOrder();
assertEquals(0, list.getNextMatch("b", 0, Bias.Forward));
}
/**
* Issue #1162-swingx: getNextMatch incorrect for non-standard stringValue
*/
@Test
public void testNextMatchUseString() {
JXList list = new JXList(AncientSwingTeam.createNamedColorListModel(), true);
list.setCellRenderer(new DefaultListRenderer(sv));
assertEquals("must not find a match for 'b', all start with 'r'",
-1, list.getNextMatch("b", 0, Bias.Forward));
}
/**
* Issue 1161-swingx: JXList not completely updated on setRowFilter
*/
@Test
public void testRevalidateOnSetRowFilter() throws InterruptedException, InvocationTargetException {
// This test will not work in a headless configuration.
if (GraphicsEnvironment.isHeadless()) {
LOG.fine("cannot run ui test - headless environment");
return;
}
final JXList list = new JXList(AncientSwingTeam.createNamedColorListModel(), true);
showWithScrollingInFrame(list, "");
final Dimension size = list.getSize();
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
RowFilter<? super ListModel, ? super Integer> filter = RowFilters.regexFilter(Pattern.CASE_INSENSITIVE, "^b");
list.setRowFilter(filter);
}
});
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
// subtraction arbitrary number, don't want to depend on single pixels
assertTrue("height must be adjusted to reduced number of rows, " +
"but was (old/current): " + size.height + "/" + list.getSize().height,
size.height - 50 > list.getSize().height);
}
});
}
//--------------- string rep
/**
* Issue #1152-swingx: re-enable filtering with single-string-representation.
* was: Issue #767-swingx: consistent string representation.
*
* Here: test Pattern filtering uses string rep
*/
@Test
public void testListGetStringUsedInPatternFilter() {
JXList list = new JXList(AncientSwingTeam.createNamedColorListModel(), true);
list.setCellRenderer(new DefaultListRenderer(sv));
RowFilter<Object, Integer> filter = RowFilter.regexFilter("R/G/B: -2.*", 0);
list.setRowFilter(filter);
assertTrue(list.getElementCount() > 0);
assertEquals(sv.getString(list.getElementAt(0)), list.getStringAt(0));
}
/**
* Issue #1152-swingx: re-enable filtering with single-string-representation.
* was: Issue #767-swingx: consistent string representation.
*
* Here: test list has stringValueProvider and configures the sortController with it
*/
@Test
public void testStringValueRegistry() {
JXList list = new JXList(AncientSwingTeam.createNamedColorListModel(), true);
assertSame(list.getStringValueRegistry(), getSortController(list).getStringValueProvider());
}
/**
* Issue #1152-swingx: re-enable filtering with single-string-representation.
* was: Issue #767-swingx: consistent string representation.
*
* Here: test updates the sortController on renderer change.
*/
@Test
public void testStringValueRegistryFromRendererChange() {
JXList list = new JXList(AncientSwingTeam.createNamedColorListModel(), true);
StringValueRegistry provider = list.getStringValueRegistry();
list.setCellRenderer(new DefaultListRenderer(sv));
assertEquals(list.getWrappedCellRenderer(), provider.getStringValue(0, 0));
}
/**
* Issue #1152-swingx: re-enable filtering with single-string-representation.
* was: Issue #767-swingx: consistent string representation.
*
* Here: test getStringAt use provider (sanity, trying to pull the rag failed
* during re-enable)
*/
@Test
public void testStringAtUseProvider() {
JXList list = new JXList(AncientSwingTeam.createNamedColorListModel(), true);
list.setCellRenderer(new DefaultListRenderer(sv));
list.getStringValueRegistry().setStringValue(StringValues.TO_STRING, 0);
assertEquals(StringValues.TO_STRING.getString(list.getElementAt(0)),
list.getStringAt(0));
}
/**
* Issue #1152-swingx: re-enable filtering with single-string-representation.
* was: Issue #767-swingx: consistent string representation.
*
* Here: test getStringAt of ComponentAdapter use provider
* (sanity, trying to pull the rag failed during re-enable)
*/
@Test
public void testStringAtComponentAdapterUseProvider() {
JXListT list = new JXListT(AncientSwingTeam.createNamedColorListModel(), true);
list.setCellRenderer(new DefaultListRenderer(sv));
list.getStringValueRegistry().setStringValue(StringValues.TO_STRING, 0);
ComponentAdapter adapter = list.getComponentAdapter();
assertEquals(StringValues.TO_STRING.getString(list.getElementAt(0)),
adapter.getStringAt(0, 0));
}
//----------------- sorter api on JXList
/**
* JXList has responsibility to guarantee usage of
* its comparator.
*/
@Test
public void testSetComparatorToSortController() {
JXList list = new JXList(listModel, true);
list.setComparator(Collator.getInstance());
assertSame(list.getComparator(), getSortController(list).getComparator(0));
}
/**
* added xtable.setSortOrder(int, SortOrder)
*
*/
@Test
public void testSetSortOrder() {
JXList list = new JXList(ascendingListModel, true);
list.setSortOrder(SortOrder.ASCENDING);
assertSame("column must be sorted after setting sortOrder on ", SortOrder.ASCENDING, list.getSortOrder());
assertSame(SortOrder.ASCENDING, getSortController(list).getSortOrder(0));
}
/**
* testing new sorter api:
* getSortOrder(), toggleSortOrder(), resetSortOrder().
*
*/
@Test
public void testToggleSortOrder() {
JXList list = new JXList(ascendingListModel, true);
assertSame(SortOrder.UNSORTED, list.getSortOrder());
list.toggleSortOrder();
assertSame(SortOrder.ASCENDING, list.getSortOrder());
list.toggleSortOrder();
assertSame(SortOrder.DESCENDING, list.getSortOrder());
list.resetSortOrder();
assertSame(SortOrder.UNSORTED, list.getSortOrder());
}
/**
* prepare sort testing: internal probs with SortController?
*/
@Test
public void testSortController() {
JXList list = new JXList(ascendingListModel, true);
assertNotNull("sortController must be initialized", list.getRowSorter());
}
//----------------- data api on JXList
/**
* testing that rowSorter's model is updated
*/
@Test
public void testSetModel() {
JXList list = new JXList(true);
list.setModel(listModel);
assertEquals(listModel.getSize(), list.getElementCount());
assertSame(listModel, list.getRowSorter().getModel());
}
@Test(expected = IndexOutOfBoundsException.class)
public void testConvertToModelPreconditions() {
final JXList list = new JXList(ascendingListModel, true);
assertEquals(20, list.getElementCount());
RowFilter<ListModel, Integer> filter = RowFilters.regexFilter("0", 0);
list.setRowFilter(filter);
assertEquals(2, list.getElementCount());
list.convertIndexToModel(list.getElementCount());
}
@Test(expected = IndexOutOfBoundsException.class)
public void testElementAtPreconditions() {
final JXList list = new JXList(ascendingListModel, true);
assertEquals(20, list.getElementCount());
RowFilter<ListModel, Integer> filter = RowFilters.regexFilter("0", 0);
list.setRowFilter(filter);
assertEquals(2, list.getElementCount());
list.getElementAt(list.getElementCount());
}
/**
*
*/
@Test(expected = IndexOutOfBoundsException.class)
public void testConvertToViewPreconditions() {
final JXList list = new JXList(ascendingListModel);
list.setAutoCreateRowSorter(true);
assertEquals(20, list.getElementCount());
RowFilter<ListModel, Integer> filter = RowFilters.regexFilter("0", 0);
list.setRowFilter(filter);
assertEquals(2, list.getElementCount());
list.convertIndexToView(ascendingListModel.getSize());
}
@Test
public void testNoSorter() {
JXList list = new JXList(ascendingListModel);
assertEquals(ascendingListModel.getSize(), list.getElementCount());
assertEquals(ascendingListModel.getElementAt(0), list.getElementAt(0));
}
@Test
public void testSorterNotSorted() {
JXList list = new JXList(ascendingListModel, true);
assertEquals(ascendingListModel.getSize(), list.getElementCount());
assertEquals(ascendingListModel.getElementAt(0), list.getElementAt(0));
}
@Test
public void testSorterSorted() {
JXList list = new JXList(ascendingListModel, true);
list.setSortOrder(SortOrder.DESCENDING);
assertEquals(ascendingListModel.getSize(), list.getElementCount());
assertEquals(ascendingListModel.getElementAt(0), list.getElementAt(list.getElementCount() - 1));
}
//------------- sort properties
@Test
public void testPropertiesToSorterOnSetRowsorter() {
list.setAutoCreateRowSorter(true);
list.setSortsOnUpdates(false);
list.setSortable(false);
Collator comparator = Collator.getInstance();
list.setComparator(comparator);
ListSortController<?> controller = new ListSortController<ListModel>(list.getModel());
list.setRowSorter(controller);
assertEquals("sortable propagated", false, controller.isSortable(0));
assertSame("comparator propagated", comparator, controller.getComparator(0));
assertEquals("sortsOnUpdates propagated", false, controller.getSortsOnUpdates());
}
@Test
public void testSortsOnUpdate() {
PropertyChangeReport report = new PropertyChangeReport(list);
list.setSortsOnUpdates(false);
TestUtils.assertPropertyChangeEvent(report, "sortsOnUpdates", true, false);
assertFalse(list.getSortsOnUpdates());
}
@Test
public void testSortable() {
PropertyChangeReport report = new PropertyChangeReport(list);
list.setSortable(false);
TestUtils.assertPropertyChangeEvent(report, "sortable", true, false);
assertFalse(list.isSortable());
}
/**
* Setting table's sortable property updates controller.
*/
@Test
public void testTableRowFilterSynchedToController() {
JXList list = new JXList(true);
RowFilter<Object, Object> filter = RowFilters.regexFilter(".*");
list.setRowFilter(filter);
assertEquals(filter, getSortController(list).getRowFilter());
assertEquals(filter, list.getRowFilter());
}
/**
* Setting table's sortable property updates controller.
*/
@Test
public void testSortOrderCycle() {
JXList list = new JXList(true);
SortOrder[] cycle = new SortOrder[] {SortOrder.DESCENDING, SortOrder.UNSORTED};
PropertyChangeReport report = new PropertyChangeReport(list);
list.setSortOrderCycle(cycle);
TestUtils.assertPropertyChangeEvent(report, "sortOrderCycle",
DefaultSortController.getDefaultSortOrderCycle(), list.getSortOrderCycle());
}
/**
* Convenience: type cast of default rowSorter.
* @param list
* @return
*/
private ListSortController<? extends ListModel> getSortController(JXList list) {
return (ListSortController<? extends ListModel>) list.getRowSorter();
}
//------------ rowSorter api
/**
* test filterEnabled property on initialization.
*
*/
@Test
public void testConstructorAutoCreateSorter() {
assertAutoCreateRowSorter(new JXList(), false);
assertAutoCreateRowSorter(new JXList(new DefaultListModel()), false);
assertAutoCreateRowSorter(new JXList(new Vector<Object>()), false);
assertAutoCreateRowSorter(new JXList(new Object[] { }), false);
assertAutoCreateRowSorter(new JXList(false), false);
assertAutoCreateRowSorter(new JXList(new DefaultListModel(), false), false);
assertAutoCreateRowSorter(new JXList(new Vector<Object>(), false), false);
assertAutoCreateRowSorter(new JXList(new Object[] { }, false), false);
assertAutoCreateRowSorter(new JXList(true), true);
assertAutoCreateRowSorter(new JXList(new DefaultListModel(), true), true);
assertAutoCreateRowSorter(new JXList(new Vector<Object>(), true), true);
assertAutoCreateRowSorter(new JXList(new Object[] { }, true), true);
}
private void assertAutoCreateRowSorter(JXList list, boolean b) {
assertEquals(b, list.getAutoCreateRowSorter());
}
@Test
public void testRowSorterSet() {
assertNull(list.getRowSorter());
ListSortController<ListModel> controller = new ListSortController<ListModel>(list.getModel());
PropertyChangeReport report = new PropertyChangeReport(list);
list.setRowSorter(controller);
TestUtils.assertPropertyChangeEvent(report, list, "rowSorter", null, controller);
assertSame(controller, list.getRowSorter());
}
@Test
public void testAutoCreateRowSorterSet() {
PropertyChangeReport report = new PropertyChangeReport(list);
list.setAutoCreateRowSorter(true);
assertTrue(list.getAutoCreateRowSorter());
TestUtils.assertPropertyChangeEvent(report, "autoCreateRowSorter", false, true, false);
assertNotNull(list.getRowSorter());
}
/**
* Test assumptions of accessing list model/view values through
* the list's componentAdapter.
*/
@Test
public void testComponentAdapterCoordinates() {
JXList list = new JXList(ascendingListModel, true);
list.setComparator(TableSortController.COMPARABLE_COMPARATOR);
Object originalFirstRowValue = list.getElementAt(0);
Object originalLastRowValue = list.getElementAt(list.getElementCount() - 1);
assertEquals("view row coordinate equals model row coordinate",
list.getModel().getElementAt(0), originalFirstRowValue);
// sort first column - actually does not change anything order
list.toggleSortOrder();
// sanity asssert
assertEquals("view order must be unchanged ",
list.getElementAt(0), originalFirstRowValue);
// invert sort
list.toggleSortOrder();
// sanity assert
assertEquals("view order must be reversed changed ",
list.getElementAt(0), originalLastRowValue);
ComponentAdapter adapter = list.getComponentAdapter();
assertEquals("adapter filteredValue expects row view coordinates",
list.getElementAt(0), adapter.getFilteredValueAt(0, 0));
// adapter coordinates are view coordinates
adapter.row = 0;
adapter.column = 0;
assertEquals("adapter.getValue must return value at adapter coordinates",
list.getElementAt(0), adapter.getValue());
assertEquals("adapter.getValue must return value at adapter coordinates",
list.getElementAt(0), adapter.getValue(0));
}
//------------------------end of re-enable sort/filter
/**
* Issue #816-swingx: Delegating renderer must create list's default.
* Consistent api: expose wrappedRenderer the same way as wrappedModel
*/
@Test
public void testWrappedRendererDefault() {
JXList list = new JXList();
DelegatingRenderer renderer = (DelegatingRenderer) list.getCellRenderer();
assertSame("wrapping renderer must use list's default on null",
renderer.getDelegateRenderer(), list.getWrappedCellRenderer());
}
/**
* Issue #816-swingx: Delegating renderer must create list's default.
* Consistent api: expose wrappedRenderer the same way as wrappedModel
*/
@Test
public void testWrappedRendererCustom() {
JXList list = new JXList();
DelegatingRenderer renderer = (DelegatingRenderer) list.getCellRenderer();
ListCellRenderer custom = new DefaultListRenderer();
list.setCellRenderer(custom);
assertSame("wrapping renderer must use list's default on null",
renderer.getDelegateRenderer(), list.getWrappedCellRenderer());
}
/**
* Issue #816-swingx: Delegating renderer must create list's default.
* Delegating uses default on null, here: default default.
*/
@Test
public void testDelegatingRendererUseDefaultSetNull() {
JXList list = new JXList();
ListCellRenderer defaultRenderer = list.createDefaultCellRenderer();
DelegatingRenderer renderer = (DelegatingRenderer) list.getCellRenderer();
list.setCellRenderer(null);
assertEquals("wrapping renderer must use list's default on null",
defaultRenderer.getClass(), renderer.getDelegateRenderer().getClass());
}
/**
* Issue #816-swingx: Delegating renderer must create list's default.
* Delegating has default from list initially, here: default default.
*/
@Test
public void testDelegatingRendererUseDefault() {
JXList list = new JXList();
ListCellRenderer defaultRenderer = list.createDefaultCellRenderer();
assertEquals("sanity: creates default", DefaultListRenderer.class,
defaultRenderer.getClass());
DelegatingRenderer renderer = (DelegatingRenderer) list.getCellRenderer();
assertEquals(defaultRenderer.getClass(), renderer.getDelegateRenderer().getClass());
}
/**
* Issue #816-swingx: Delegating renderer must create list's default.
* Delegating has default from list initially, here: custom default.
*/
@Test
public void testDelegatingRendererUseCustomDefaultSetNull() {
JXList list = new JXList() {
@Override
protected ListCellRenderer createDefaultCellRenderer() {
return new CustomDefaultRenderer();
}
};
ListCellRenderer defaultRenderer = list.createDefaultCellRenderer();
DelegatingRenderer renderer = (DelegatingRenderer) list.getCellRenderer();
list.setCellRenderer(null);
assertEquals("wrapping renderer must use list's default on null",
defaultRenderer.getClass(), renderer.getDelegateRenderer().getClass());
}
/**
* Issue #816-swingx: Delegating renderer must create list's default.
* Delegating has default from list initially, here: custom default.
*/
@Test
public void testDelegatingRendererUseCustomDefault() {
JXList list = new JXList() {
@Override
protected ListCellRenderer createDefaultCellRenderer() {
return new CustomDefaultRenderer();
}
};
ListCellRenderer defaultRenderer = list.createDefaultCellRenderer();
assertEquals("sanity: creates custom", CustomDefaultRenderer.class,
defaultRenderer.getClass());
DelegatingRenderer renderer = (DelegatingRenderer) list.getCellRenderer();
assertEquals(defaultRenderer.getClass(), renderer.getDelegateRenderer().getClass());
}
/**
* Dummy extension for testing - does nothing more as super.
*/
public static class CustomDefaultRenderer extends DefaultListCellRenderer {
}
/**
* Issue #767-swingx: consistent string representation.
*
* Here: test api on JXTable.
*/
@Test
public void testGetString() {
JXList list = new JXList(AncientSwingTeam.createNamedColorListModel());
StringValue sv = new StringValue() {
public String getString(Object value) {
if (value instanceof Color) {
Color color = (Color) value;
return "R/G/B: " + color.getRGB();
}
return StringValues.TO_STRING.getString(value);
}
};
list.setCellRenderer(new DefaultListRenderer(sv));
String text = list.getStringAt(0);
assertEquals(sv.getString(list.getElementAt(0)), text);
}
/**
* test that swingx renderer is used by default.
*
*/
@Test
public void testDefaultListRenderer() {
JXList list = new JXList();
ListCellRenderer renderer = ((DelegatingRenderer) list.getCellRenderer()).getDelegateRenderer();
assertTrue("default renderer expected to be DefaultListRenderer " +
"\n but is " + renderer.getClass(),
renderer instanceof DefaultListRenderer);
}
/**
* Issue #473-swingx: NPE in list with highlighter. <p>
*
* Renderers are doc'ed to cope with invalid input values.
* Highlighters can rely on valid ComponentAdapter state.
* JXList delegatingRenderer is the culprit which does set
* invalid ComponentAdapter state. Negative invalid index.
*
*/
@Test
public void testIllegalNegativeListRowIndex() {
JXList list = new JXList(new Object[] {1, 2, 3});
ListCellRenderer renderer = list.getCellRenderer();
renderer.getListCellRendererComponent(list, "dummy", -1, false, false);
SearchPredicate predicate = new SearchPredicate("\\QNode\\E");
Highlighter searchHighlighter = new ColorHighlighter(predicate, null, Color.RED);
list.addHighlighter(searchHighlighter);
renderer.getListCellRendererComponent(list, "dummy", -1, false, false);
}
/**
* Issue #473-swingx: NPE in list with highlighter. <p>
*
* Renderers are doc'ed to cope with invalid input values.
* Highlighters can rely on valid ComponentAdapter state.
* JXList delegatingRenderer is the culprit which does set
* invalid ComponentAdapter state. Invalid index > valid range.
*
*/
@Test
public void testIllegalExceedingListRowIndex() {
JXList list = new JXList(new Object[] {1, 2, 3});
ListCellRenderer renderer = list.getCellRenderer();
renderer.getListCellRendererComponent(list, "dummy", list.getElementCount(), false, false);
SearchPredicate predicate = new SearchPredicate("\\QNode\\E");
Highlighter searchHighlighter = new ColorHighlighter(predicate, null, Color.RED);
list.addHighlighter(searchHighlighter);
renderer.getListCellRendererComponent(list, "dummy", list.getElementCount(), false, false);
}
/**
* test convenience method accessing the configured adapter.
*
*/
@Test
public void testConfiguredComponentAdapter() {
JXList list = new JXList(new Object[] {1, 2, 3});
ComponentAdapter adapter = list.getComponentAdapter();
assertEquals(0, adapter.column);
assertEquals(0, adapter.row);
adapter.row = 1;
// corrupt adapter
adapter.column = 1;
adapter = list.getComponentAdapter(0);
assertEquals(0, adapter.column);
assertEquals(0, adapter.row);
}
/**
* test exceptions on null data(model, vector, array).
*
*/
@Test
public void testNullData() {
try {
new JXList((ListModel) null);
fail("JXList contructor must throw on null data");
} catch (IllegalArgumentException e) {
// expected
} catch (Exception e) {
fail("unexpected exception type " + e);
}
try {
new JXList((Vector<?>) null);
fail("JXList contructor must throw on null data");
} catch (IllegalArgumentException e) {
// expected
} catch (Exception e) {
fail("unexpected exception type " + e);
}
try {
new JXList((Object[]) null);
fail("JXList contructor must throw on null data");
} catch (IllegalArgumentException e) {
// expected
} catch (Exception e) {
fail("unexpected exception type " + e);
}
}
/**
* add and test comparator property.
*
*/
@Test
public void testComparator() {
JXList list = new JXList();
assertNull(list.getComparator());
Collator comparator = Collator.getInstance();
PropertyChangeReport report = new PropertyChangeReport();
list.addPropertyChangeListener(report);
list.setComparator(comparator);
assertEquals(comparator, list.getComparator());
assertEquals(1, report.getEventCount());
assertEquals(1, report.getEventCount("comparator"));
}
/**
* test if LinkController/executeButtonAction is properly registered/unregistered on
* setRolloverEnabled.
*
*/
@Test
public void testLinkControllerListening() {
JXList table = new JXList();
table.setRolloverEnabled(true);
assertNotNull("LinkController must be listening", getLinkControllerAsPropertyChangeListener(table, RolloverProducer.CLICKED_KEY));
assertNotNull("LinkController must be listening", getLinkControllerAsPropertyChangeListener(table, RolloverProducer.ROLLOVER_KEY));
assertNotNull("execute button action must be registered", table.getActionMap().get(JXList.EXECUTE_BUTTON_ACTIONCOMMAND));
table.setRolloverEnabled(false);
assertNull("LinkController must not be listening", getLinkControllerAsPropertyChangeListener(table, RolloverProducer.CLICKED_KEY ));
assertNull("LinkController must be listening", getLinkControllerAsPropertyChangeListener(table, RolloverProducer.ROLLOVER_KEY));
assertNull("execute button action must be de-registered", table.getActionMap().get(JXList.EXECUTE_BUTTON_ACTIONCOMMAND));
}
private PropertyChangeListener getLinkControllerAsPropertyChangeListener(JXList table, String propertyName) {
PropertyChangeListener[] listeners = table.getPropertyChangeListeners(propertyName);
for (int i = 0; i < listeners.length; i++) {
if (listeners[i] instanceof ListRolloverController<?>) {
return (ListRolloverController<?>) listeners[i];
}
}
return null;
}
protected ListModel createListModel() {
JXList list = new JXList();
return new DefaultComboBoxModel(list.getActionMap().allKeys());
}
protected DefaultListModel createAscendingListModel(int startRow, int count) {
DefaultListModel l = new DefaultListModel();
for (int row = startRow; row < startRow + count; row++) {
l.addElement(new Integer(row));
}
return l;
}
protected DefaultListModel createListModelWithLinks() {
DefaultListModel model = new DefaultListModel();
for (int i = 0; i < 20; i++) {
try {
LinkModel link = new LinkModel("a link text " + i, null, new URL("http://some.dummy.url" + i));
if (i == 1) {
URL url = JXEditorPaneTest.class.getResource("resources/test.html");
link = new LinkModel("a resource", null, url);
}
model.addElement(link);
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return model;
}
/**
* Creates and returns a StringValue which maps a Color to it's R/G/B rep,
* prepending "R/G/B: "
*
* @return the StringValue for color.
*/
private StringValue createColorStringValue() {
StringValue sv = new StringValue() {
public String getString(Object value) {
if (value instanceof Color) {
Color color = (Color) value;
return "R/G/B: " + color.getRGB();
}
return StringValues.TO_STRING.getString(value);
}
};
return sv;
}
/**
* Creates and returns a number filter, passing values which are numbers and
* have int values inside or outside of the bounds (included), depending on the given
* flag.
*
* @param lowerBound
* @param upperBound
* @param inside
* @return
*/
// protected Filter createNumberFilter(final int lowerBound, final int upperBound, final boolean inside) {
// PatternFilter f = new PatternFilter() {
//
// @Override
// public boolean test(int row) {
// Object value = getInputValue(row, getColumnIndex());
// if (!(value instanceof Number)) return false;
// boolean isInside = ((Number) value).intValue() >= lowerBound
// && ((Number) value).intValue() <= upperBound;
// return inside ? isInside : !isInside;
// }
//
// };
// return f;
// }
@Override
protected void setUp() throws Exception {
super.setUp();
list = new JXList();
listModel = createListModel();
ascendingListModel = createAscendingListModel(0, 20);
sv = createColorStringValue();
}
public JXListTest() {
super("JXList Tests");
}
@Before
public void setUpJ4() throws Exception {
setUp();
}
@After
public void tearDownJ4() throws Exception {
tearDown();
}
}