package com.revolsys.swing.map.layer.record.table;
import java.awt.Color;
import java.awt.Font;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.StringSelection;
import java.awt.datatransfer.Transferable;
import java.awt.font.TextAttribute;
import java.beans.PropertyChangeEvent;
import java.util.EventObject;
import java.util.Map;
import javax.swing.JComponent;
import javax.swing.ListSelectionModel;
import javax.swing.RowFilter;
import javax.swing.RowSorter;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.TableColumnModelEvent;
import javax.swing.event.TableModelEvent;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableColumn;
import javax.swing.table.TableModel;
import org.jdesktop.swingx.decorator.FontHighlighter;
import org.jdesktop.swingx.decorator.HighlightPredicate;
import org.jdesktop.swingx.decorator.HighlightPredicate.AndHighlightPredicate;
import org.jdesktop.swingx.event.TableColumnModelExtListener;
import org.jdesktop.swingx.table.TableColumnExt;
import org.jdesktop.swingx.table.TableColumnModelExt;
import com.revolsys.awt.WebColors;
import com.revolsys.geometry.model.Geometry;
import com.revolsys.swing.SwingUtil;
import com.revolsys.swing.dnd.ClipboardUtil;
import com.revolsys.swing.map.layer.record.AbstractRecordLayer;
import com.revolsys.swing.map.layer.record.LayerRecord;
import com.revolsys.swing.map.layer.record.LayerRecordMenu;
import com.revolsys.swing.map.layer.record.table.model.RecordLayerTableModel;
import com.revolsys.swing.table.TablePanel;
import com.revolsys.swing.table.highlighter.ColorHighlighter;
import com.revolsys.swing.table.record.RecordRowTable;
import com.revolsys.swing.table.record.editor.RecordTableCellEditor;
import com.revolsys.swing.table.record.model.RecordRowTableModel;
public class RecordLayerTable extends RecordRowTable {
private final class ColumnWidthListener implements TableColumnModelExtListener {
@Override
public void columnAdded(final TableColumnModelEvent e) {
}
@Override
public void columnMarginChanged(final ChangeEvent e) {
}
@Override
public void columnMoved(final TableColumnModelEvent e) {
}
@Override
public void columnPropertyChange(final PropertyChangeEvent event) {
final Object source = event.getSource();
if (source instanceof TableColumnExt) {
if ("width".equals(event.getPropertyName())) {
final AbstractRecordLayer layer = getLayer();
if (layer != null) {
if (!isInitializingColumnWidths()) {
final TableColumnExt column = (TableColumnExt)source;
final int columnIndex = column.getModelIndex();
final String fieldName = getColumnFieldName(columnIndex);
final int width = column.getWidth();
layer.setFieldColumnWidth(fieldName, width);
}
}
}
}
}
@Override
public void columnRemoved(final TableColumnModelEvent e) {
}
@Override
public void columnSelectionChanged(final ListSelectionEvent e) {
}
}
private static final long serialVersionUID = 1L;
public RecordLayerTable(final RecordLayerTableModel model) {
super(model);
final JTableHeader tableHeader = getTableHeader();
tableHeader.setReorderingAllowed(false);
final TableColumnModelExt columnModel = (TableColumnModelExt)getColumnModel();
columnModel.addColumnModelListener(new ColumnWidthListener());
}
@Override
@SuppressWarnings({
"unchecked", "rawtypes"
})
protected void addDeletedRecordHighlighter() {
final RecordLayerTableModel model = getModel();
final HighlightPredicate predicate = (renderer, adapter) -> {
try {
final int rowIndex = adapter.convertRowIndexToModel(adapter.row);
return model.isDeleted(rowIndex);
} catch (final Throwable e) {
}
return false;
};
addHighlighter(
new ColorHighlighter(new AndHighlightPredicate(predicate, HighlightPredicate.EVEN),
WebColors.newAlpha(WebColors.Pink, 127), WebColors.FireBrick, WebColors.LightCoral,
WebColors.FireBrick));
addHighlighter(
new ColorHighlighter(new AndHighlightPredicate(predicate, HighlightPredicate.ODD),
WebColors.Pink, WebColors.FireBrick, WebColors.Crimson, WebColors.White));
final Font tableFont = getFont();
final Map<TextAttribute, Object> fontAttributes = (Map)tableFont.getAttributes();
fontAttributes.put(TextAttribute.STRIKETHROUGH, TextAttribute.STRIKETHROUGH_ON);
final Font font = new Font(fontAttributes);
final FontHighlighter fontHighlighter = new FontHighlighter(predicate, font);
addHighlighter(fontHighlighter);
}
@Override
protected void addModifiedRecordHighlighter() {
final RecordLayerTableModel model = getModel();
final HighlightPredicate predicate = (renderer, adapter) -> {
try {
final int rowIndex = adapter.convertRowIndexToModel(adapter.row);
final LayerRecord record = model.getRecord(rowIndex);
final AbstractRecordLayer layer = model.getLayer();
return layer.isModified(record);
} catch (final Throwable e) {
return false;
}
};
addHighlighter(
new ColorHighlighter(new AndHighlightPredicate(predicate, HighlightPredicate.EVEN),
WebColors.newAlpha(WebColors.LimeGreen, 127), WebColors.Black,
WebColors.newAlpha(WebColors.DarkGreen, 191), Color.WHITE));
addHighlighter(
new ColorHighlighter(new AndHighlightPredicate(predicate, HighlightPredicate.ODD),
WebColors.LimeGreen, WebColors.Black, WebColors.DarkGreen, Color.WHITE));
}
@Override
protected void addNewRecordHighlighter() {
final RecordLayerTableModel model = getModel();
final HighlightPredicate predicate = (renderer, adapter) -> {
try {
final int rowIndex = adapter.convertRowIndexToModel(adapter.row);
final LayerRecord record = model.getRecord(rowIndex);
final AbstractRecordLayer layer = model.getLayer();
return layer.isNew(record);
} catch (final Throwable e) {
return false;
}
};
addHighlighter(
new ColorHighlighter(new AndHighlightPredicate(predicate, HighlightPredicate.EVEN),
WebColors.newAlpha(WebColors.LightSkyBlue, 127), WebColors.Black,
WebColors.newAlpha(WebColors.RoyalBlue, 191), Color.WHITE));
addHighlighter(
new ColorHighlighter(new AndHighlightPredicate(predicate, HighlightPredicate.ODD),
WebColors.LightSkyBlue, WebColors.Black, WebColors.RoyalBlue, Color.WHITE));
}
public void copyFieldValue() {
if (isEditingCurrentCell()) {
final RecordTableCellEditor tableCellEditor = getTableCellEditor();
final JComponent editorComponent = tableCellEditor.getEditorComponent();
SwingUtil.dndCopy(editorComponent);
} else {
final RecordRowTableModel model = getTableModel();
final int row = TablePanel.getEventRow();
final int column = TablePanel.getEventColumn();
final Object value = model.getValueAt(row, column);
if (value != null) {
final String copyValue;
if (value instanceof Geometry) {
final Geometry geometry = (Geometry)value;
copyValue = geometry.toEwkt();
} else {
copyValue = model.toDisplayValue(row, column, value);
}
final StringSelection transferable = new StringSelection(copyValue);
ClipboardUtil.setContents(transferable);
}
}
}
@Override
protected RowSorter<? extends TableModel> createDefaultRowSorter() {
final AbstractRecordLayer layer = getLayer();
if (layer != null) {
final RecordLayerTableModel model = (RecordLayerTableModel)getTableModel();
return new RecordLayerTableRowSorter(layer, model);
}
return null;
}
public void cutFieldValue() {
if (isEditingCurrentCell()) {
final RecordTableCellEditor tableCellEditor = getTableCellEditor();
final JComponent editorComponent = tableCellEditor.getEditorComponent();
SwingUtil.dndCut(editorComponent);
} else {
copyFieldValue();
final RecordRowTableModel model = getTableModel();
final int row = TablePanel.getEventRow();
final int column = TablePanel.getEventColumn();
model.setValueAt(null, row, column);
}
}
@Override
public boolean editCellAt(final int row, final int column, final EventObject e) {
final LayerRecord record = getRecord(row);
LayerRecordMenu.setEventRecord(record);
return super.editCellAt(row, column, e);
}
@SuppressWarnings("unchecked")
public <V extends AbstractRecordLayer> V getLayer() {
final RecordLayerTableModel model = (RecordLayerTableModel)getTableModel();
if (model == null) {
return null;
} else {
return (V)model.getLayer();
}
}
@Override
public RecordLayerTableModel getModel() {
return (RecordLayerTableModel)super.getModel();
}
@Override
public ListSelectionModel getSelectionModel() {
final RecordLayerTableModel model = getModel();
final ListSelectionModel selectionModel = model.getSelectionModel();
if (selectionModel == null) {
return super.getSelectionModel();
} else {
return selectionModel;
}
}
@Override
protected void initializeColumnPreferredWidth(final TableColumn column) {
final int columnIndex = column.getModelIndex();
final String fieldName = getColumnFieldName(columnIndex);
if (fieldName != null) {
final AbstractRecordLayer layer = getLayer();
final int width = layer.getFieldColumnWidth(fieldName);
if (width >= 0) {
column.setWidth(width);
column.setPreferredWidth(width);
} else {
super.initializeColumnPreferredWidth(column);
}
}
}
@Override
protected RecordTableCellEditor newTableCellEditor() {
return new RecordLayerTableCellEditor(this);
}
public void pasteFieldValue() {
if (isEditingCurrentCell()) {
final RecordTableCellEditor tableCellEditor = getTableCellEditor();
final JComponent editorComponent = tableCellEditor.getEditorComponent();
SwingUtil.dndPaste(editorComponent);
} else {
try {
final Transferable clipboard = ClipboardUtil.getContents();
final Object value = clipboard.getTransferData(DataFlavor.stringFlavor);
final RecordRowTableModel model = getTableModel();
final int row = TablePanel.getEventRow();
final int column = TablePanel.getEventColumn();
model.setValueAt(value, row, column);
} catch (final Throwable e) {
}
}
}
@Override
public void setSelectionModel(ListSelectionModel newModel) {
if (newModel == null) {
newModel = createDefaultSelectionModel();
}
super.setSelectionModel(newModel);
}
@Override
protected void tableChangedDo(final TableModelEvent event) {
final RecordLayerTableModel model = getModel();
if (model.isSortable()) {
setSortable(true);
} else {
setSortable(false);
}
final RowFilter<RecordRowTableModel, Integer> rowFilter = model.getRowFilter();
final boolean filterChanged = getRowFilter() != rowFilter;
if (filterChanged) {
setRowFilter(null);
}
super.tableChangedDo(event);
if (filterChanged) {
setRowFilter(rowFilter);
}
repaint();
}
}