/*
* $Id: JXListTest.java 3199 2009-01-21 18:37:28Z kschaefe $
*
* 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.event.ActionEvent;
import java.net.MalformedURLException;
import java.net.URL;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.DefaultComboBoxModel;
import javax.swing.DefaultListModel;
import javax.swing.DefaultListSelectionModel;
import javax.swing.JList;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.ListModel;
import javax.swing.RowFilter;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableModel;
import javax.swing.table.TableRowSorter;
import org.jdesktop.swingx.hyperlink.LinkModel;
import org.jdesktop.swingx.sort.ListSortController;
import org.jdesktop.swingx.sort.RowFilters;
import org.jdesktop.swingx.sort.RowSorterWrapper;
import org.jdesktop.swingx.sort.TableSortController;
import org.jdesktop.test.ListSelectionReport;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
/**
* Subset of tests for currently disabled sorting. Obviously, they are failing.
* Once re-added support, we'll need analogous tests.
*
* @author Jeanette Winzenburg
*/
@RunWith(JUnit4.class)
public class JXListSortRevamp extends InteractiveTestCase {
protected ListModel listModel;
protected DefaultListModelF ascendingListModel;
private ListSortController<ListModel> controller;
private JXList list;
public static void main(String[] args) {
JXListSortRevamp test = new JXListSortRevamp();
try {
// test.runInteractiveTests();
test.runInteractiveTests("interactive.*RowSorter.*");
} catch (Exception e) {
e.printStackTrace();
}
}
@Test
public void testSelectionEventListX() {
JXList list = new JXList(ascendingListModel);
list.setSelectedIndex(0);
ListSelectionReport report = new ListSelectionReport();
list.addListSelectionListener(report);
list.addSelectionInterval(1, 1);
assertEquals(1, report.getEventCount(true));
assertEquals(1, report.getLastEvent(true).getLastIndex());
assertEquals(1, report.getLastEvent(true).getFirstIndex());
}
@Test
public void testSelectionEventList() {
JList list = new JList(ascendingListModel);
list.setSelectedIndex(0);
ListSelectionReport report = new ListSelectionReport();
list.addListSelectionListener(report);
list.addSelectionInterval(1, 1);
assertEquals(1, report.getEventCount(true));
assertEquals(1, report.getLastEvent(true).getLastIndex());
assertEquals(1, report.getLastEvent(true).getFirstIndex());
}
@Test
public void testSelectionEvent() {
DefaultListSelectionModel list = new DefaultListSelectionModel();
list.setLeadAnchorNotificationEnabled(false);
list.setSelectionInterval(0, 0);
ListSelectionReport report = new ListSelectionReport();
list.addListSelectionListener(report);
list.addSelectionInterval(1, 1);
assertEquals(1, report.getEventCount(true));
assertEquals(1, report.getLastEvent(true).getLastIndex());
assertEquals(1, report.getLastEvent(true).getFirstIndex());
}
//------------------ re-enable
public void interactiveRowSorter() {
final JXList list = new JXList(ascendingListModel);
final DefaultTableModel tableModel = new DefaultTableModel(list.getElementCount(), 1) {
@Override
public Class<?> getColumnClass(int columnIndex) {
return Integer.class;
}
};
for (int i = 0; i < tableModel.getRowCount(); i++) {
tableModel.setValueAt(i, i, 0);
}
final JXTable table = new JXTable(tableModel);
final ListSortController<ListModel> controller = new ListSortController<ListModel>(list.getModel());
list.setRowSorter(controller);
controller.setComparator(0, TableSortController.COMPARABLE_COMPARATOR);
Action sort = new AbstractAction("toggle sort") {
@Override
public void actionPerformed(ActionEvent e) {
list.toggleSortOrder();
table.toggleSortOrder(0);
}
};
Action reset = new AbstractAction("reset") {
@Override
public void actionPerformed(ActionEvent e) {
controller.resetSortOrders();
table.resetSortOrder();
}
};
Action toggleFilter = new AbstractAction("toggle filter") {
boolean hasFilter;
@Override
public void actionPerformed(ActionEvent e) {
if (hasFilter) {
RowFilter<Object, Integer> filter = RowFilters.regexFilter("0", 0);
list.setRowFilter(filter);
table.setRowFilter(filter);
} else {
list.setRowFilter(null);
table.setRowFilter(null);
}
hasFilter = !hasFilter;
}
};
Action removeFirst = new AbstractAction("remove firstM") {
@Override
public void actionPerformed(ActionEvent e) {
ascendingListModel.remove(0);
tableModel.removeRow(0);
}
};
Action addFirst = new AbstractAction("add firstM") {
int counter;
@Override
public void actionPerformed(ActionEvent e) {
ascendingListModel.add(0, 10 * ++counter);
tableModel.insertRow(0, new Object[] {ascendingListModel.getElementAt(0)});
}
};
Action fireAllChanged = new AbstractAction("fireDataChanged") {
@Override
public void actionPerformed(ActionEvent e) {
ascendingListModel.fireContentsChanged();
tableModel.fireTableDataChanged();
}
};
JXFrame frame = showWithScrollingInFrame(list, table, "sort in rowSorter");
addAction(frame, sort);
addAction(frame, reset);
addAction(frame, toggleFilter);
addAction(frame, removeFirst);
addAction(frame, addFirst);
addAction(frame, fireAllChanged);
show(frame);
}
/**
* Compare behaviour of selection in xtable with RowSorterWrapper after
* 1. model changes
* 2. filter changes
* 3. shared selectionModel (starts with shared)
*/
@SuppressWarnings("unchecked")
public void interactiveRowSorterWrapperSharedXTable() {
final DefaultTableModel tableModel = new DefaultTableModel(list.getElementCount(), 2) {
@Override
public Class<?> getColumnClass(int columnIndex) {
return Integer.class;
}
};
for (int i = 0; i < tableModel.getRowCount(); i++) {
tableModel.setValueAt(i, i, 0);
tableModel.setValueAt(tableModel.getRowCount() - i, i, 1);
}
final JXTable master = new JXTable(tableModel);
final TableSortController<TableModel> rowSorter = (TableSortController<TableModel>) master.getRowSorter();
master.removeColumn(master.getColumn(0));
final JXTable rowHeader = new JXTable(master.getModel());
rowHeader.setAutoCreateRowSorter(false);
rowHeader.removeColumn(rowHeader.getColumn(1));
rowHeader.setRowSorter(new RowSorterWrapper<TableModel>(rowSorter));
rowHeader.setSelectionModel(master.getSelectionModel());
// need to disable selection update on one of the table's
// otherwise the selection is not kept in model coordinates
rowHeader.setUpdateSelectionOnSort(false);
JScrollPane scrollPane = new JScrollPane(master);
scrollPane.setRowHeaderView(rowHeader);
JXFrame frame = showInFrame(scrollPane, "xtables (wrapped sortController): shared model/selection");
Action fireAllChanged = new AbstractAction("fireDataChanged") {
@Override
public void actionPerformed(ActionEvent e) {
tableModel.fireTableDataChanged();
}
};
addAction(frame, fireAllChanged);
Action removeFirst = new AbstractAction("remove firstM") {
@Override
public void actionPerformed(ActionEvent e) {
tableModel.removeRow(0);
}
};
addAction(frame, removeFirst);
Action removeLast = new AbstractAction("remove lastM") {
@Override
public void actionPerformed(ActionEvent e) {
tableModel.removeRow(tableModel.getRowCount() - 1);
}
};
addAction(frame, removeLast);
Action filter = new AbstractAction("toggle filter") {
@Override
public void actionPerformed(ActionEvent e) {
RowFilter filter = rowSorter.getRowFilter();
if (filter == null) {
rowSorter.setRowFilter(RowFilter.regexFilter("^1", 1));
} else {
rowSorter.setRowFilter(null);
}
}
};
addAction(frame, filter);
addStatusMessage(frame, "row header example with RowSorterWrapper");
show(frame);
}
/**
* Compare behaviour of selection in xtable with shared TableSortController after
* 1. model changes
* 2. filter changes
* 3. shared selectionModel (starts with shared)
*/
@SuppressWarnings("unchecked")
public void interactiveXRowSorterSharedXTable() {
final DefaultTableModel tableModel = new DefaultTableModel(list.getElementCount(), 1) {
@Override
public Class<?> getColumnClass(int columnIndex) {
return Integer.class;
}
};
for (int i = 0; i < tableModel.getRowCount(); i++) {
tableModel.setValueAt(i, i, 0);
}
final JTable table = new JXTable(tableModel);
table.setAutoCreateRowSorter(false);
final JTable core = new JXTable(table.getModel());
core.setAutoCreateRowSorter(false);
final TableSortController<TableModel> rowSorter = new TableSortController<TableModel>(table.getModel());
table.setRowSorter(rowSorter);
core.setRowSorter(rowSorter);
core.setSelectionModel(table.getSelectionModel());
// need to disable selection update on one of the table's
// otherwise the selection is not kept in model coordinates
core.setUpdateSelectionOnSort(false);
JXFrame frame = showWithScrollingInFrame(table, core, "xtables (shared sortController): shared model/sorter/selection");
Action fireAllChanged = new AbstractAction("fireDataChanged") {
@Override
public void actionPerformed(ActionEvent e) {
tableModel.fireTableDataChanged();
}
};
addAction(frame, fireAllChanged);
Action removeFirst = new AbstractAction("remove firstM") {
@Override
public void actionPerformed(ActionEvent e) {
tableModel.removeRow(0);
}
};
addAction(frame, removeFirst);
Action removeLast = new AbstractAction("remove lastM") {
@Override
public void actionPerformed(ActionEvent e) {
tableModel.removeRow(tableModel.getRowCount() - 1);
}
};
addAction(frame, removeLast);
Action filter = new AbstractAction("toggle filter") {
@Override
public void actionPerformed(ActionEvent e) {
RowFilter filter = rowSorter.getRowFilter();
if (filter == null) {
rowSorter.setRowFilter(RowFilter.regexFilter("^1", 0));
} else {
rowSorter.setRowFilter(null);
}
}
};
addAction(frame, filter);
Action shareSelection = new AbstractAction("toggle selection share") {
@Override
public void actionPerformed(ActionEvent e) {
boolean oldSelectionShared = table.getSelectionModel() == core.getSelectionModel();
if (oldSelectionShared) {
core.setSelectionModel(new DefaultListSelectionModel());
} else {
core.setSelectionModel(table.getSelectionModel());
}
core.setUpdateSelectionOnSort(!oldSelectionShared);
}
};
addAction(frame, shareSelection);
addStatusMessage(frame, "here: updateSelectionOnSort is false if selection shared!");
show(frame);
}
/**
* Compare behaviour of selection in core table with shared TableSortController after
* 1. model changes
* 2. filter changes
* 3. shared selectionModel (starts with shared)
*/
@SuppressWarnings("unchecked")
public void interactiveXRowSorterShared() {
final DefaultTableModel tableModel = new DefaultTableModel(list.getElementCount(), 1) {
@Override
public Class<?> getColumnClass(int columnIndex) {
return Integer.class;
}
};
for (int i = 0; i < tableModel.getRowCount(); i++) {
tableModel.setValueAt(i, i, 0);
}
final JTable table = new JTable(tableModel);
final JTable core = new JTable(table.getModel());
final TableSortController<TableModel> rowSorter = new TableSortController<TableModel>(table.getModel());
table.setRowSorter(rowSorter);
core.setRowSorter(rowSorter);
core.setSelectionModel(table.getSelectionModel());
JXFrame frame = showWithScrollingInFrame(table, core, "core tables (shared sortController): shared model/sorter/selection");
Action fireAllChanged = new AbstractAction("fireDataChanged") {
@Override
public void actionPerformed(ActionEvent e) {
tableModel.fireTableDataChanged();
}
};
addAction(frame, fireAllChanged);
Action removeFirst = new AbstractAction("remove firstM") {
@Override
public void actionPerformed(ActionEvent e) {
tableModel.removeRow(0);
}
};
addAction(frame, removeFirst);
Action removeLast = new AbstractAction("remove lastM") {
@Override
public void actionPerformed(ActionEvent e) {
tableModel.removeRow(tableModel.getRowCount() - 1);
}
};
addAction(frame, removeLast);
Action filter = new AbstractAction("toggle filter") {
@Override
public void actionPerformed(ActionEvent e) {
RowFilter filter = rowSorter.getRowFilter();
if (filter == null) {
rowSorter.setRowFilter(RowFilter.regexFilter("^1", 0));
} else {
rowSorter.setRowFilter(null);
}
}
};
addAction(frame, filter);
Action shareSelection = new AbstractAction("toggle selection share") {
@Override
public void actionPerformed(ActionEvent e) {
if (table.getSelectionModel() == core.getSelectionModel()) {
core.setSelectionModel(new DefaultListSelectionModel());
} else {
core.setSelectionModel(table.getSelectionModel());
}
}
};
addAction(frame, shareSelection);
show(frame);
}
/**
* Compare behaviour of selection in core table with shared TableRowSorter after
* 1. model changes
* 2. filter changes
* 3. shared selectionModel (starts with not shared)
*/
@SuppressWarnings("unchecked")
public void interactiveRowSorterShared() {
final DefaultTableModel tableModel = new DefaultTableModel(list.getElementCount(), 1) {
@Override
public Class<?> getColumnClass(int columnIndex) {
return Integer.class;
}
};
for (int i = 0; i < tableModel.getRowCount(); i++) {
tableModel.setValueAt(i, i, 0);
}
final JTable table = new JTable(tableModel);
final JTable core = new JTable(table.getModel());
final TableRowSorter<TableModel> rowSorter = new TableRowSorter<TableModel>(table.getModel());
table.setRowSorter(rowSorter);
core.setRowSorter(rowSorter);
core.setSelectionModel(table.getSelectionModel());
JXFrame frame = showWithScrollingInFrame(table, core, "core tables: shared model/sorter/selection");
Action fireAllChanged = new AbstractAction("fireDataChanged") {
@Override
public void actionPerformed(ActionEvent e) {
tableModel.fireTableDataChanged();
}
};
addAction(frame, fireAllChanged);
Action removeFirst = new AbstractAction("remove firstM") {
@Override
public void actionPerformed(ActionEvent e) {
tableModel.removeRow(0);
}
};
addAction(frame, removeFirst);
Action removeLast = new AbstractAction("remove lastM") {
@Override
public void actionPerformed(ActionEvent e) {
tableModel.removeRow(tableModel.getRowCount() - 1);
}
};
addAction(frame, removeLast);
Action filter = new AbstractAction("toggle filter") {
@Override
public void actionPerformed(ActionEvent e) {
RowFilter filter = rowSorter.getRowFilter();
if (filter == null) {
rowSorter.setRowFilter(RowFilter.regexFilter("^1", 0));
} else {
rowSorter.setRowFilter(null);
}
}
};
addAction(frame, filter);
Action shareSelection = new AbstractAction("toggle selection share") {
@Override
public void actionPerformed(ActionEvent e) {
if (table.getSelectionModel() == core.getSelectionModel()) {
core.setSelectionModel(new DefaultListSelectionModel());
} else {
core.setSelectionModel(table.getSelectionModel());
}
}
};
addAction(frame, shareSelection);
show(frame);
}
/**
* Compare behaviour of selection with (unrelated) TableRowSorter after
* 1. model changes
* 2. filter changes
* 3. shared selectionModel (starts with not shared)
*/
@SuppressWarnings("unchecked")
public void interactiveRowSorterCore() {
final DefaultTableModel tableModel = new DefaultTableModel(list.getElementCount(), 1) {
@Override
public Class<?> getColumnClass(int columnIndex) {
return Integer.class;
}
};
for (int i = 0; i < tableModel.getRowCount(); i++) {
tableModel.setValueAt(i, i, 0);
}
final JXTable table = new JXTable(tableModel);
final JTable core = new JTable(table.getModel());
final TableRowSorter<TableModel> rowSorter = new TableRowSorter<TableModel>(table.getModel());
core.setRowSorter(rowSorter);
JXFrame frame = showWithScrollingInFrame(table, core, "xTable <> core");
Action fireAllChanged = new AbstractAction("fireDataChanged") {
@Override
public void actionPerformed(ActionEvent e) {
tableModel.fireTableDataChanged();
}
};
addAction(frame, fireAllChanged);
Action removeFirst = new AbstractAction("remove firstM") {
@Override
public void actionPerformed(ActionEvent e) {
tableModel.removeRow(0);
}
};
addAction(frame, removeFirst);
Action removeLast = new AbstractAction("remove lastM") {
@Override
public void actionPerformed(ActionEvent e) {
tableModel.removeRow(tableModel.getRowCount() - 1);
}
};
addAction(frame, removeLast);
Action filter = new AbstractAction("toggle filter") {
RowFilter regex = RowFilter.regexFilter("^1", 0);
@Override
public void actionPerformed(ActionEvent e) {
RowFilter filter = rowSorter.getRowFilter();
if (filter == null) {
rowSorter.setRowFilter(regex);
table.setRowFilter(regex);
} else {
rowSorter.setRowFilter(null);
table.setRowFilter(null);
}
}
};
addAction(frame, filter);
Action shareSelection = new AbstractAction("toggle selection share") {
@Override
public void actionPerformed(ActionEvent e) {
if (table.getSelectionModel() == core.getSelectionModel()) {
core.setSelectionModel(new DefaultListSelectionModel());
} else {
core.setSelectionModel(table.getSelectionModel());
}
}
};
addAction(frame, shareSelection);
show(frame);
}
//----------------- re-enabled functionality
//--------------------- interactive
/**
* Issue #377-swingx: JXList (it's wrapping model) fires incorrect events.
*
*
*/
public void interactiveFilterMutateModel() {
final DefaultListModel model = createAscendingListModel(0, 5);
// PENDING: currently not useful, sort disabled
final JXList list = new JXList(model, true);
// list.setFilters(new FilterPipeline(new PatternFilter()));
JXFrame frame = wrapWithScrollingInFrame(list, "Mutate model with filter");
Action addItem = new AbstractAction("add item") {
public void actionPerformed(ActionEvent e) {
int selected = list.getSelectedIndex();
if (selected >= 0) {
selected = list.convertIndexToModel(selected);
}
if (selected > 0) {
model.add(selected - 1, model.getSize());
} else {
model.addElement(model.getSize());
}
}
};
addAction(frame, addItem);
Action removeItem = new AbstractAction("remove item") {
public void actionPerformed(ActionEvent e) {
int selected = list.getSelectedIndex();
if (selected >= 0) {
selected = list.convertIndexToModel(selected);
}
if (selected > 0) {
model.remove(selected - 1);
}
}
};
addAction(frame, removeItem);
Action changeItem = new AbstractAction("change item") {
public void actionPerformed(ActionEvent e) {
int selected = list.getSelectedIndex();
if (selected >= 0) {
selected = list.convertIndexToModel(selected);
}
if (selected > 0) {
int newValue = ((Integer) model.getElementAt(selected - 1)).intValue() + 10;
model.set(selected - 1, newValue);
}
}
};
addAction(frame, changeItem);
Action flush = new AbstractAction("toggle sort") {
public void actionPerformed(ActionEvent e) {
list.toggleSortOrder();
}
};
addAction(frame, flush);
show(frame);
}
public void interactiveTestSort() {
// PENDING: currently not useful, sort disabled
final JXList list = new JXList(listModel, true);
JXFrame frame = wrapWithScrollingInFrame(list, "Toggle sorter");
Action toggleSortOrder = new AbstractAction("Toggle Sort Order") {
public void actionPerformed(ActionEvent e) {
list.toggleSortOrder();
}
};
addAction(frame, toggleSortOrder);
Action resetSortOrder = new AbstractAction("Reset Sort Order") {
public void actionPerformed(ActionEvent e) {
list.resetSortOrder();
}
};
addAction(frame, resetSortOrder);
frame.setVisible(true);
}
//-------------------- factory methods, setup
protected ListModel createListModel() {
JXList list = new JXList();
return new DefaultComboBoxModel(list.getActionMap().allKeys());
}
public static class DefaultListModelF extends DefaultListModel {
/**
* Fires a contentsChanged with -1, -1.
*/
public void fireContentsChanged() {
fireContentsChanged(this, -1, -1);
}
};
protected DefaultListModelF createAscendingListModel(int startRow, int count) {
DefaultListModelF l = new DefaultListModelF();
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 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();
listModel = createListModel();
ascendingListModel = createAscendingListModel(0, 22);
list = new JXList(ascendingListModel);
controller = new ListSortController<ListModel>(list.getModel());
controller.setComparator(0, TableSortController.COMPARABLE_COMPARATOR);
list.setRowSorter(controller);
}
public JXListSortRevamp() {
super("JXList Tests");
}
@Before
public void setUpJ4() throws Exception {
setUp();
}
@After
public void tearDownJ4() throws Exception {
tearDown();
}
}