/* (@)JTableSortingFun.java */
/* Copyright 2009 Sebastian Haufe
* Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
[url]http://www.apache.org/licenses/LICENSE-2.0[/url]
* Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License. */
package com.ebenius;
import java.awt.BorderLayout;
import java.util.*;
import javax.swing.*;
import javax.swing.event.RowSorterEvent;
import javax.swing.event.RowSorterListener;
import javax.swing.table.*;
/**
* Test on customized sorting.
*
* @version $Revision$ as of $Date$
* @author Sebastian Haufe
*/
public class JTableSortingFun {
static class AccumulatingIntegerTableModel extends DefaultTableModel {
private static final long serialVersionUID = 1L;
private int[] sum = { 0, 0 };
AccumulatingIntegerTableModel() {
super(new String[] { "Top Level Sorting", "A", "B" }, 0);
addRow(new Object[] { null, null, null });
}
@Override
public Class<?> getColumnClass(int columnIndex) {
return Integer.class;
}
@Override
public Object getValueAt(int row, int column) {
if (row == getRowCount() - 1) {
switch (column) {
case 0:
return Integer.valueOf(Integer.MAX_VALUE);
default:
return Integer.valueOf(sum[column - 1]);
}
}
return super.getValueAt(row, column);
}
@Override
public boolean isCellEditable(int row, int column) {
return row < getRowCount() - 1 && super.isCellEditable(row, column);
}
@Override
public void setValueAt(Object aValue, int row, int column) {
if (row < getRowCount() - 1) {
super.setValueAt(aValue, row, column);
}
if (column > 0) {
summarize(column);
}
}
private void summarize(int column) {
int acc = 0;
final int lastRow = getRowCount() - 1;
for (int row = 0; row < lastRow; row++) {
acc += ((Integer) getValueAt(row, column)).intValue();
}
if (acc != sum[column - 1]) {
sum[column - 1] = acc;
fireTableCellUpdated(lastRow, column);
}
}
@SuppressWarnings("unchecked")
@Override
public void addRow(Vector rowData) {
insertRow(Math.max(0, getRowCount() - 1), rowData);
}
@SuppressWarnings("unchecked")
@Override
public void insertRow(int row, Vector rowData) {
super.insertRow(row, rowData);
for (int column = 1; column < getColumnCount(); column++) {
summarize(column);
}
}
}
static class CustomRowSorter extends RowSorter<TableModel>
implements RowSorterListener {
private DefaultRowSorter<TableModel, Integer> sorter;
CustomRowSorter(TableModel model) {
sorter = new TableRowSorter<TableModel>(model);
sorter.addRowSorterListener(this);
sorter.setSortKeys(Collections.singletonList(new SortKey(0,
SortOrder.ASCENDING)));
sorter.setSortsOnUpdates(true);
}
@Override
public int convertRowIndexToModel(int index) {
return sorter.convertRowIndexToModel(index);
}
@Override
public int convertRowIndexToView(int index) {
return sorter.convertRowIndexToView(index);
}
@Override
public TableModel getModel() {
return sorter.getModel();
}
@Override
public int getModelRowCount() {
return sorter.getModelRowCount();
}
@Override
public int getViewRowCount() {
return sorter.getViewRowCount();
}
// -----------------------------------------------------------------------
// Sorter controlling
// -----------------------------------------------------------------------
@Override
public List<? extends SortKey> getSortKeys() {
final LinkedList<SortKey> result = new LinkedList<SortKey>();
final List<? extends SortKey> keys = sorter.getSortKeys();
for (Iterator<? extends SortKey> it = keys.iterator(); it.hasNext();) {
final SortKey sk = it.next();
if (sk.getColumn() != 0) {
result.add(sk);
}
}
return result;
}
@Override
public void setSortKeys(List<? extends SortKey> keys) {
final LinkedList<SortKey> copy = new LinkedList<SortKey>(keys);
copy.add(0, new SortKey(0, SortOrder.ASCENDING));
sorter.setSortKeys(copy);
}
@Override
public void toggleSortOrder(int column) {
if (column != 0) {
List<SortKey> keys = new ArrayList<SortKey>(sorter.getSortKeys());
int sortIndex;
for (sortIndex = keys.size() - 1; sortIndex >= 1; sortIndex--) {
if (keys.get(sortIndex).getColumn() == column) {
break;
}
}
if (sortIndex == 0) {
final SortKey sortKey = new SortKey(column, SortOrder.ASCENDING);
keys.add(1, sortKey);
} else if (sortIndex == 1) {
final SortOrder order =
keys.get(1).getSortOrder() == SortOrder.ASCENDING
? SortOrder.DESCENDING
: SortOrder.ASCENDING;
keys.set(1, new SortKey(column, order));
} else {
keys.remove(sortIndex);
keys.add(1, new SortKey(column, SortOrder.ASCENDING));
}
sorter.setSortKeys(keys);
}
}
// -----------------------------------------------------------------------
// Event delegation from our controller to the sorter
// -----------------------------------------------------------------------
@Override
public void allRowsChanged() {
sorter.allRowsChanged();
}
@Override
public void modelStructureChanged() {
sorter.modelStructureChanged();
}
@Override
public void rowsDeleted(int firstRow, int endRow) {
sorter.rowsDeleted(firstRow, endRow);
}
@Override
public void rowsInserted(int firstRow, int endRow) {
sorter.rowsInserted(firstRow, endRow);
}
@Override
public void rowsUpdated(int firstRow, int endRow) {
sorter.rowsUpdated(firstRow, endRow);
}
@Override
public void rowsUpdated(int firstRow, int endRow, int column) {
sorter.rowsUpdated(firstRow, endRow, column);
}
// -----------------------------------------------------------------------
// Event delegation from sorter to our listeners
// -----------------------------------------------------------------------
public void sorterChanged(RowSorterEvent e) {
if (e.getType() == RowSorterEvent.Type.SORT_ORDER_CHANGED) {
fireSortOrderChanged();
} else if (e.getType() == RowSorterEvent.Type.SORTED) {
final int[] indices = new int[e.getPreviousRowCount()];
for (int i = 0; i < indices.length; i++) {
indices[i] = e.convertPreviousRowIndexToModel(i);
}
fireRowSorterChanged(indices);
}
}
}
/**
* Test main method.
*
* @param args ignored
*/
public static void main(String[] args) {
final DefaultTableModel tm = new AccumulatingIntegerTableModel();
for (int i = 0, j = 2 << i; i < 10; i++, j = 2 << i) {
tm.addRow(new Object[] { Integer.valueOf(0), Integer.valueOf(i),
Integer.valueOf(j), });
}
final JTable table = new JTable(tm);
// use custom row sorter
table.setAutoCreateRowSorter(false);
table.setRowSorter(new CustomRowSorter(tm));
// hide first column
table.setAutoCreateColumnsFromModel(false);
table.createDefaultColumnsFromModel();
final TableColumnModel cm = table.getColumnModel();
cm.removeColumn(cm.getColumn(0));
final JPanel contentPane = new JPanel(new BorderLayout(6, 6));
contentPane.add(new JScrollPane(table));
final JFrame f = new JFrame("Test Frame: JTableSortingFun"); //$NON-NLS-1$
f.setContentPane(contentPane);
f.pack();
f.setLocationRelativeTo(null);
f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
f.setVisible(true);
}
}