package com.revolsys.swing.map.layer.record.table.model;
import java.awt.Dimension;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.Rectangle;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.lang.ref.Reference;
import java.lang.ref.WeakReference;
import java.util.List;
import java.util.Map;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;
import com.revolsys.datatype.DataType;
import com.revolsys.record.RecordState;
import com.revolsys.record.schema.FieldDefinition;
import com.revolsys.record.schema.RecordDefinition;
import com.revolsys.swing.field.ArrayListComboBoxModel;
import com.revolsys.swing.field.ComboBox;
import com.revolsys.swing.map.form.FieldNamesSetPanel;
import com.revolsys.swing.map.form.LayerRecordForm;
import com.revolsys.swing.map.layer.record.AbstractRecordLayer;
import com.revolsys.swing.map.layer.record.LayerRecord;
import com.revolsys.swing.map.layer.record.table.predicate.FormAllFieldsErrorPredicate;
import com.revolsys.swing.map.layer.record.table.predicate.FormAllFieldsModifiedPredicate;
import com.revolsys.swing.table.BaseJTable;
import com.revolsys.swing.table.TablePanel;
import com.revolsys.swing.table.record.model.AbstractSingleRecordTableModel;
import com.revolsys.swing.toolbar.ToolBar;
import com.revolsys.util.Property;
public class LayerRecordTableModel extends AbstractSingleRecordTableModel
implements PropertyChangeListener {
private static final long serialVersionUID = 1L;
public static TablePanel newTablePanel(final LayerRecordForm form) {
final LayerRecordTableModel tableModel = new LayerRecordTableModel(form);
return tableModel.newTablePanel();
}
private final Reference<LayerRecordForm> form;
private final AbstractRecordLayer layer;
private LayerRecord record;
private final ComboBox<String> fieldNamesSetNamesField;
public LayerRecordTableModel(final LayerRecordForm form) {
super(form.getRecordDefinition(), true);
this.form = new WeakReference<>(form);
this.layer = form.getLayer();
this.record = form.getRecord();
final List<String> fieldNamesSetNames = this.layer.getFieldNamesSetNames();
this.fieldNamesSetNamesField = ComboBox.newComboBox("fieldNamesSetName", fieldNamesSetNames);
int maxLength = 3;
for (final String name : fieldNamesSetNames) {
maxLength = Math.max(maxLength, name.length());
}
this.fieldNamesSetNamesField
.setMaximumSize(new Dimension(Math.max(300, maxLength * 11 + 40), 22));
final String fieldNamesSetName = this.layer.getFieldNamesSetName();
this.fieldNamesSetNamesField.setSelectedItem(fieldNamesSetName);
Property.addListener(this.fieldNamesSetNamesField, "fieldNamesSetName", this);
Property.addListener(this.layer, this);
refreshFieldNames();
}
@Override
public void dispose() {
super.dispose();
Property.removeListener(this.layer, this);
}
@Override
public int getColumnCount() {
return 4;
}
@Override
public String getColumnName(final int column) {
if (column == 3) {
return "Original Value";
} else {
return super.getColumnName(column);
}
}
@Override
public String getFieldTitle(final String fieldName) {
return this.layer.getFieldTitle(fieldName);
}
@SuppressWarnings("unchecked")
@Override
public <V extends Map<String, Object>> V getMap(final int columnIndex) {
if (columnIndex == 2) {
return (V)this.record;
} else {
return null;
}
}
@Override
public Object getObjectValue(final int rowIndex, final int columnIndex) {
if (this.record == null) {
return null;
} else {
final String fieldName = getColumnFieldName(rowIndex);
return this.record.getValue(fieldName);
}
}
public LayerRecord getRecord() {
return this.record;
}
@Override
public Object getValueAt(final int rowIndex, final int columnIndex) {
if (this.record == null) {
return null;
} else if (columnIndex == 3) {
final String fieldName = getColumnFieldName(rowIndex);
return this.record.getOriginalValue(fieldName);
} else {
return super.getValueAt(rowIndex, columnIndex);
}
}
@Override
public boolean isCellEditable(final int rowIndex, final int columnIndex) {
if (columnIndex == 2) {
if (this.form.get().isEditable()) {
final String fieldName = getColumnFieldName(rowIndex);
final RecordDefinition recordDefinition = getRecordDefinition();
final FieldDefinition idField = recordDefinition.getIdField();
if (idField != null) {
final String idFieldName = idField.getName();
if (fieldName.equals(idFieldName)) {
if (this.record != null && this.record.getState() == RecordState.NEW) {
if (!Number.class.isAssignableFrom(idField.getTypeClass())) {
return true;
}
}
return false;
}
}
if (recordDefinition.getGeometryFieldNames().contains(fieldName)) {
return false;
} else {
return this.form.get().isEditable(fieldName);
}
} else {
return false;
}
} else {
return false;
}
}
public boolean isModified(final int rowIndex) {
final String fieldName = getColumnFieldName(rowIndex);
final Object originalValue = this.record.getOriginalValue(fieldName);
final Object value = this.record.getValue(fieldName);
return !DataType.equal(originalValue, value);
}
public TablePanel newTablePanel() {
final LayerRecordForm form = this.form.get();
final BaseJTable table = AbstractSingleRecordTableModel.newTable(this);
FormAllFieldsModifiedPredicate.add(form, table);
FormAllFieldsErrorPredicate.add(form, table);
final TableColumnModel columnModel = table.getColumnModel();
for (int i = 0; i < columnModel.getColumnCount(); i++) {
final TableColumn column = columnModel.getColumn(i);
if (i == 2) {
final TableCellEditor cellEditor = column.getCellEditor();
cellEditor.addCellEditorListener(form);
}
}
final TablePanel tablePanel = new TablePanel(table);
final ToolBar toolBar = tablePanel.getToolBar();
toolBar.addComponent("default", this.fieldNamesSetNamesField);
toolBar.addButtonTitleIcon("default", "Edit Field Sets", "fields_filter_edit", () -> {
final String fieldNamesSetName = FieldNamesSetPanel.showDialog(this.layer);
if (Property.hasValue(fieldNamesSetName)) {
this.fieldNamesSetNamesField.setFieldValue(fieldNamesSetName);
}
});
int maxHeight = 500;
for (final GraphicsDevice device : GraphicsEnvironment.getLocalGraphicsEnvironment()
.getScreenDevices()) {
final GraphicsConfiguration graphicsConfiguration = device.getDefaultConfiguration();
final Rectangle bounds = graphicsConfiguration.getBounds();
maxHeight = Math.min(bounds.height, maxHeight);
}
final int preferredHeight = Math.min(maxHeight, (this.getRowCount() + 1) * 20);
tablePanel.setMinimumSize(new Dimension(100, preferredHeight));
tablePanel.setMaximumSize(new Dimension(Integer.MAX_VALUE, maxHeight));
tablePanel.setPreferredSize(new Dimension(800, preferredHeight));
return tablePanel;
}
@Override
public void propertyChange(final PropertyChangeEvent event) {
final Object source = event.getSource();
final String propertyName = event.getPropertyName();
if (source == this.record) {
final RecordDefinition recordDefinition = getRecordDefinition();
final int index = recordDefinition.getFieldIndex(propertyName);
if (index > -1) {
try {
fireTableRowsUpdated(index, index);
} catch (final Throwable t) {
}
}
} else if (source == this.layer) {
if ("fieldNamesSets".equals(propertyName)) {
refreshFieldNames();
}
} else if (source == this.fieldNamesSetNamesField) {
final String fieldNamesSetName = this.fieldNamesSetNamesField.getFieldValue();
final List<String> fieldNames = this.layer.getFieldNamesSet(fieldNamesSetName);
if (fieldNames != null) {
setFieldNames(fieldNames);
}
}
}
protected void refreshFieldNames() {
final ArrayListComboBoxModel<String> model = this.fieldNamesSetNamesField.getComboBoxModel();
final List<String> fieldNamesSetNames = this.layer.getFieldNamesSetNames();
model.setAll(fieldNamesSetNames);
setFieldNames(this.layer.getFieldNamesSet());
}
public void removeListener() {
Property.removeListener(this.layer, this);
}
@Override
protected Object setObjectValue(final String fieldName, final Object value) {
final Object oldValue = this.record.getValue(fieldName);
this.record.setValue(fieldName, value);
return oldValue;
}
public void setRecord(final LayerRecord record) {
this.record = record;
}
}