package com.revolsys.swing.table.record.model;
import java.util.List;
import java.util.Map;
import javax.swing.JTable;
import org.jdesktop.swingx.table.TableColumnExt;
import com.revolsys.comparator.NumericComparator;
import com.revolsys.datatype.DataTypes;
import com.revolsys.geometry.model.Geometry;
import com.revolsys.identifier.Identifier;
import com.revolsys.record.code.CodeTable;
import com.revolsys.record.schema.RecordDefinition;
import com.revolsys.swing.menu.BaseJPopupMenu;
import com.revolsys.swing.table.BaseJTable;
import com.revolsys.swing.table.record.editor.RecordTableCellEditor;
import com.revolsys.swing.table.record.renderer.SingleRecordTableCellRenderer;
import com.revolsys.util.Strings;
public abstract class AbstractSingleRecordTableModel extends AbstractRecordTableModel {
private static final String[] COLUMN_NAMES = {
"#", "Name", "Value"
};
private static final long serialVersionUID = 1L;
public static BaseJTable newTable(final AbstractSingleRecordTableModel model) {
final BaseJTable table = new BaseJTable(model);
table.setModel(model);
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
table.setAutoCreateColumnsFromModel(false);
table.putClientProperty("terminateEditOnFocusLost", Boolean.TRUE);
final SingleRecordTableCellRenderer cellRenderer = new SingleRecordTableCellRenderer();
final RecordTableCellEditor cellEditor = new RecordTableCellEditor(table);
cellEditor.setPopupMenu(model.getMenu()::newJPopupMenu);
final RecordDefinition recordDefinition = model.getRecordDefinition();
final List<String> allFieldNames = recordDefinition.getFieldNames();
int maxTitleWidth = 100;
for (final String fieldName : allFieldNames) {
final String title = model.getFieldTitle(fieldName);
final int titleWidth = Math.max(title.length(), fieldName.length()) * 8;
if (titleWidth > maxTitleWidth) {
maxTitleWidth = titleWidth;
}
}
final int columnCount = model.getColumnCount();
int columnWidth;
if (columnCount > 3) {
columnWidth = (740 - maxTitleWidth) / 2;
} else {
columnWidth = (740 - maxTitleWidth) / 2;
}
for (int i = 0; i < columnCount; i++) {
final TableColumnExt column = table.getColumnExt(i);
column.setCellRenderer(cellRenderer);
if (i == 0) {
column.setMinWidth(40);
column.setPreferredWidth(40);
column.setMaxWidth(40);
column.setComparator(new NumericComparator());
} else if (i == 1) {
column.setMinWidth(maxTitleWidth);
column.setPreferredWidth(maxTitleWidth);
column.setMaxWidth(maxTitleWidth);
} else {
column.setPreferredWidth(columnWidth);
if (i == 2) {
column.setCellEditor(cellEditor);
}
}
}
return table;
}
private List<String> fieldNames;
public AbstractSingleRecordTableModel(final RecordDefinition recordDefinition,
final boolean editable) {
super(recordDefinition);
setEditable(editable);
setFieldNames(recordDefinition.getFieldNames());
}
@Override
public int getColumnCount() {
return 3;
}
@Override
public String getColumnFieldName(final int attributeIndex) {
return this.fieldNames.get(attributeIndex);
}
@Override
public String getColumnFieldName(final int row, final int column) {
return getColumnFieldName(row);
}
@Override
public String getColumnName(final int column) {
return COLUMN_NAMES[column];
}
public List<String> getFieldNames() {
return this.fieldNames;
}
public String getFieldTitle(final String fieldName) {
final RecordDefinition recordDefinition = getRecordDefinition();
return recordDefinition.getFieldTitle(fieldName);
}
public abstract <V extends Map<String, Object>> V getMap(int columnIndex);
@Override
public BaseJPopupMenu getMenu(final int rowIndex, final int columnIndex) {
if (columnIndex == 2) {
return getMenu().newJPopupMenu();
} else {
return null;
}
}
public abstract Object getObjectValue(final int attributeIndex, int columnIndex);
@Override
public int getRowCount() {
return this.fieldNames.size();
}
@Override
public Object getValueAt(final int rowIndex, final int columnIndex) {
switch (columnIndex) {
case 0:
return rowIndex;
case 1:
final String fieldName = getColumnFieldName(rowIndex);
final String title = getFieldTitle(fieldName);
return title;
case 2:
return getObjectValue(rowIndex, columnIndex);
default:
return null;
}
}
@Override
public boolean isCellEditable(final int rowIndex, final int columnIndex) {
if (columnIndex == 2) {
if (isEditable()) {
final RecordDefinition recordDefinition = getRecordDefinition();
if (rowIndex == recordDefinition.getIdFieldIndex()) {
return false;
} else {
final String fieldName = getColumnFieldName(rowIndex);
if (recordDefinition.getIdFieldNames().contains(fieldName)) {
return false;
} else if (recordDefinition.getGeometryFieldNames().contains(fieldName)) {
return false;
} else {
return !isReadOnly(fieldName);
}
}
} else {
return false;
}
} else {
return false;
}
}
@Override
public boolean isSelected(final boolean selected, final int rowIndex, final int columnIndex) {
return selected;
}
protected Object setDisplayValue(final String fieldName, final Object displayValue) {
final Object objectValue = toObjectValue(fieldName, displayValue);
return setObjectValue(fieldName, objectValue);
}
public void setFieldNames(final List<String> fieldNames) {
if (fieldNames != null && (this.fieldNames == null || !this.fieldNames.equals(fieldNames))) {
this.fieldNames = fieldNames;
fireTableDataChanged();
}
}
protected abstract Object setObjectValue(final String fieldName, final Object value);
@Override
public void setRecordDefinition(final RecordDefinition recordDefinition) {
super.setRecordDefinition(recordDefinition);
}
@Override
public void setValueAt(final Object value, final int rowIndex, final int columnIndex) {
if (isCellEditable(rowIndex, columnIndex)) {
final String fieldName = getColumnFieldName(rowIndex);
final Object oldValue = setDisplayValue(fieldName, value);
firePropertyChange(fieldName, oldValue, value);
}
}
@Override
public String toCopyValue(final int rowIndex, final int columnIndex, final Object objectValue) {
if (objectValue == null) {
return null;
} else if (columnIndex < 2) {
return DataTypes.toString(objectValue);
} else {
String text;
final RecordDefinition recordDefinition = getRecordDefinition();
final String idFieldName = recordDefinition.getIdFieldName();
final String name = getColumnFieldName(rowIndex);
if (objectValue instanceof Geometry) {
final Geometry geometry = (Geometry)objectValue;
return geometry.toString();
}
CodeTable codeTable = null;
if (!name.equals(idFieldName)) {
codeTable = recordDefinition.getCodeTableByFieldName(name);
}
if (codeTable == null) {
text = DataTypes.toString(objectValue);
} else {
final List<Object> values = codeTable.getValues(Identifier.newIdentifier(objectValue));
if (values == null || values.isEmpty()) {
return null;
} else {
text = Strings.toString(values);
}
}
if (text.length() == 0) {
return null;
}
return text;
}
}
}