/******************************************************************************* * Breakout Cave Survey Visualizer * * Copyright (C) 2014 James Edwards * * jedwards8 at fastmail dot fm * * This program is free software; you can redistribute it and/or modify it under * the terms of the GNU General Public License as published by the Free Software * Foundation; either version 2 of the License, or (at your option) any later * version. * * This program 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 General Public License for more * details. * * You should have received a copy of the GNU General Public License along with * this program; if not, write to the Free Software Foundation, Inc., 51 * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *******************************************************************************/ package org.andork.swing.table; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; import javax.swing.JTable; import javax.swing.table.AbstractTableModel; import javax.swing.table.TableColumn; @SuppressWarnings("serial") public class NiceTableModel<R> extends AbstractTableModel { /** * */ private static final long serialVersionUID = -2454625431840324267L; public static interface Column<R> { public abstract Class<?> getColumnClass(); public abstract String getColumnName(); public abstract Object getValueAt(R row); public abstract boolean isCellEditable(R row); /** * @param aValue * @param row * @return if {@code true}, this {@code NiceTableModel} should fire a * table cell updated event. */ public abstract boolean setValueAt(Object aValue, R row); } public static <R> TableColumn getTableColumn(JTable table, Column<R> column) { NiceTableModel<R> model = (NiceTableModel<R>) table.getModel(); int index = model.indexOfColumn(column); if (index >= 0) { index = table.convertColumnIndexToView(index); } if (index < 0) { return null; } return table.getColumnModel().getColumn(index); } private final List<Column<R>> columns = new ArrayList<>(); private final List<Column<R>> unmodifiableColumns = Collections.unmodifiableList(columns); private final List<R> rows = new ArrayList<>(); private final List<R> unmodifiableRows = Collections.unmodifiableList(rows); protected void addColumn(Column<R> column) { columns.add(column); fireTableStructureChanged(); } protected void addRow(int index, R row) { rows.add(index, row); fireTableRowsInserted(index, index); } protected void addRow(R row) { addRow(rows.size(), row); } protected void addRows(Collection<? extends R> rows) { addRows(this.rows.size(), rows); } protected void addRows(int index, Collection<? extends R> rows) { if (!rows.isEmpty()) { this.rows.addAll(index, rows); fireTableRowsInserted(index, index + rows.size() - 1); } } protected void clearRows() { rows.clear(); fireTableDataChanged(); } protected Column<R> getColumn(int columnIndex) { return columns.get(columnIndex); } @Override public Class<?> getColumnClass(int columnIndex) { return columns.get(columnIndex).getColumnClass(); } @Override public int getColumnCount() { return columns.size(); } @Override public String getColumnName(int column) { return columns.get(column).getColumnName(); } protected List<Column<R>> getColumns() { return unmodifiableColumns; } protected R getRow(int rowIndex) { return rows.get(rowIndex); } @Override public int getRowCount() { return rows.size(); } protected List<R> getRows() { return unmodifiableRows; } @Override public Object getValueAt(int rowIndex, int columnIndex) { return columns.get(columnIndex).getValueAt(rows.get(rowIndex)); } protected int indexOfColumn(Column<R> column) { return columns.indexOf(column); } @Override public boolean isCellEditable(int rowIndex, int columnIndex) { return columns.get(columnIndex).isCellEditable(rows.get(rowIndex)); } protected void removeColumn(Column<R> column) { columns.remove(column); fireTableStructureChanged(); } protected void removeRow(int index) { rows.remove(index); fireTableRowsDeleted(index, index); } protected void removeRows(int... rows) { for (int i = rows.length - 1; i >= 0; i--) { this.rows.remove(rows[i]); } fireTableDataChanged(); } protected void removeRows(int firstIndex, int lastIndex) { rows.subList(firstIndex, lastIndex + 1).clear(); fireTableRowsDeleted(firstIndex, lastIndex); } protected void setColumns(Collection<? extends Column<R>> columns) { this.columns.clear(); this.columns.addAll(columns); fireTableStructureChanged(); } protected void setRow(int index, R row) { rows.set(index, row); fireTableRowsUpdated(index, index); } protected void setRows(Collection<? extends R> rows) { this.rows.clear(); this.rows.addAll(rows); fireTableDataChanged(); } protected void setRows(int index, Collection<? extends R> rows) { if (!rows.isEmpty()) { List<R> sublist = this.rows.subList(index, index + rows.size()); sublist.clear(); sublist.addAll(index, rows); fireTableRowsUpdated(index, index + rows.size() - 1); } } @Override public void setValueAt(Object aValue, int rowIndex, int columnIndex) { if (columns.get(columnIndex).setValueAt(aValue, rows.get(rowIndex))) { fireTableCellUpdated(rowIndex, columnIndex); } } }