/*
* Beanfabrics Framework Copyright (C) by Michael Karneim, beanfabrics.org
* Use is subject to license terms. See license.txt.
*/
// TODO javadoc - remove this comment only when the class and all non-public
// methods and fields are documented
package org.beanfabrics.swing.table;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableModel;
import org.beanfabrics.Path;
import org.beanfabrics.PathEvaluation;
import org.beanfabrics.event.ElementChangedEvent;
import org.beanfabrics.event.ElementsAddedEvent;
import org.beanfabrics.event.ElementsDeselectedEvent;
import org.beanfabrics.event.ElementsRemovedEvent;
import org.beanfabrics.event.ElementsReplacedEvent;
import org.beanfabrics.event.ElementsSelectedEvent;
import org.beanfabrics.event.ListListener;
import org.beanfabrics.event.WeakListListener;
import org.beanfabrics.model.IListPM;
import org.beanfabrics.model.IOperationPM;
import org.beanfabrics.model.IValuePM;
import org.beanfabrics.model.PresentationModel;
import org.beanfabrics.model.SortKey;
/**
* The <code>BnTableModel</code> is a {@link TableModel} that decorates a {@link IListPM}.
* <p>
* To reduce work we decided to extend the {@link AbstractTableModel} in order to get the event listener handling. All
* other methods are overridden.
* </p>
*
* @author Michael Karneim
*/
@SuppressWarnings("serial")
public class BnTableModel extends AbstractTableModel {
@SuppressWarnings("rawtypes")
private IListPM list;
private boolean cellEditingAllowed;
private List<BnColumn> colDefs = new ArrayList<BnColumn>();
private final ListListener listener = new MyWeakListListener();
private class MyWeakListListener implements WeakListListener, Serializable {
public void elementsSelected(ElementsSelectedEvent evt) {
// ignore
}
public void elementsDeselected(ElementsDeselectedEvent evt) {
// ignore
}
public void elementChanged(ElementChangedEvent evt) {
fireTableRowsUpdated(evt.getIndex(), evt.getIndex());
}
public void elementsReplaced(ElementsReplacedEvent evt) {
fireTableRowsUpdated(evt.getBeginIndex(), evt.getBeginIndex() + evt.getLength() - 1);
}
public void elementsAdded(ElementsAddedEvent evt) {
fireTableRowsInserted(evt.getBeginIndex(), evt.getBeginIndex() + evt.getLength() - 1);
}
public void elementsRemoved(ElementsRemovedEvent evt) {
fireTableRowsDeleted(evt.getBeginIndex(), evt.getBeginIndex() + evt.getLength() - 1);
}
};
public BnTableModel(@SuppressWarnings("rawtypes") IListPM aListModel, List<BnColumn> colDefs, boolean editingAllowed) {
if (aListModel == null) {
throw new IllegalArgumentException("aListModel must not be null");
}
if (colDefs == null) {
throw new IllegalArgumentException("colDefs must not be null");
}
this.list = aListModel;
this.cellEditingAllowed = editingAllowed;
this.colDefs.addAll(colDefs);
this.list.addListListener(this.listener);
}
/**
* Disconnect <code>this</code> object from the underlying IListPM.
*/
public void dismiss() {
this.list.removeListListener(this.listener);
}
public void setCellEditingAllowed(boolean editingAllowed) {
boolean oldValue = this.cellEditingAllowed;
this.cellEditingAllowed = editingAllowed;
if (oldValue != this.cellEditingAllowed) {
this.fireTableStructureChanged();
}
}
public boolean isCellEditingAllowed() {
return cellEditingAllowed;
}
public List<BnColumn> getColDefs() {
return Collections.unmodifiableList(colDefs);
}
public void setColDefs(List<BnColumn> colDefs) {
if (colDefs == null) {
throw new IllegalArgumentException("colDefs==null");
}
this.colDefs.clear();
this.colDefs.addAll(colDefs);
this.fireTableStructureChanged();
}
@Override
public int getColumnCount() {
return this.colDefs.size();
}
@Override
public int getRowCount() {
return this.list.size();
}
@Override
public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
// we don't support changing a value with this method
}
@Override
public Object getValueAt(int rowIndex, int columnIndex) {
final Path path = this.colDefs.get(columnIndex).getPath();
PresentationModel rowMdl = this.list.getAt(rowIndex);
return PathEvaluation.evaluateOrNull(rowMdl, path);
}
@Override
public String getColumnName(int column) {
final BnColumn def = this.colDefs.get(column);
if (def == null)
return null;
return def.getColumnName();
}
public Path getColumnPath(int column) {
final BnColumn def = this.colDefs.get(column);
if (def == null)
return null;
return def.getPath();
}
@Override
public int findColumn(String columnName) {
for (int i = 0; i < getColumnCount(); i++) {
if (columnName.equals(getColumnName(i))) {
return i;
}
}
return -1;
}
@Override
public Class<?> getColumnClass(int columnIndex) {
return PresentationModel.class;
}
@Override
public boolean isCellEditable(int rowIndex, int columnIndex) {
if (!cellEditingAllowed) {
return false;
} else {
final Object value = this.getValueAt(rowIndex, columnIndex);
if (value instanceof IValuePM) {
return ((IValuePM) value).isEditable();
} else if (value instanceof IOperationPM) {
return ((IOperationPM) value).isEnabled();
} else {
return false;
}
}
}
/**
* Returns the underlying presentation model of this {@link TableModel}.
*
* @return the underlying presentation model
*/
@SuppressWarnings("rawtypes")
public IListPM getPresentationModel() {
return this.list;
}
/**
* Returns the {@link SortKey} of the specified column or <code>null</code> if that column is not sorted.
*
* @param col
* @return the {@link SortKey} of the specified column
*/
public SortKey getSortKey(int col) {
Path colPath = getColumnPath(col);
if (colPath == null) {
return null;
}
Collection<SortKey> sortKeys = getSortKeys();
for (SortKey sortKey : sortKeys) {
if (colPath.equals(sortKey.getSortPath())) {
return sortKey;
}
}
return null;
}
/**
* Returns the {@link SortKey}s for this table. The order of these keys reflects the order of sorting precedence.
* The entry at the top of the collection has the highest precedence when sorting.
*
* @return Returns the {@link SortKey}s for this table
*/
public Collection<SortKey> getSortKeys() {
@SuppressWarnings("unchecked")
Collection<SortKey> sortKeys = list.getSortKeys();
return sortKeys;
}
}