package com.link_intersystems.swing; import java.util.HashMap; import java.util.Map; import javax.swing.DefaultListSelectionModel; import javax.swing.ListSelectionModel; import javax.swing.event.ChangeEvent; import javax.swing.event.ListSelectionEvent; import javax.swing.event.TableColumnModelEvent; import javax.swing.event.TableColumnModelListener; import javax.swing.table.DefaultTableColumnModel; import javax.swing.table.TableCellEditor; import javax.swing.table.TableCellRenderer; import javax.swing.table.TableColumn; import javax.swing.table.TableColumnModel; import com.link_intersystems.beans.BeanPropertySync; public class SynchronizedTableColumnModel extends DefaultTableColumnModel { private static final long serialVersionUID = -6008690732758899314L; private TableColumnModelSync tableColumnModelSync = new TableColumnModelSync(); private TableColumnModel sourceModel; public void setSourceModel(TableColumnModel sourceModel) { if (this.sourceModel != null) { this.sourceModel.removeColumnModelListener(tableColumnModelSync); this.setSelectionModel(new DefaultListSelectionModel()); } this.sourceModel = sourceModel; if (this.sourceModel != null) { this.sourceModel.addColumnModelListener(tableColumnModelSync); ListSelectionModel selectionModel = this.sourceModel .getSelectionModel(); this.setSelectionModel(selectionModel); tableColumnModelSync.init(this.sourceModel); } } private class TableColumnModelSync implements TableColumnModelListener { private Map<TableColumn, TableColumnSync> propertySyncMap = new HashMap<TableColumn, TableColumnSync>(); private Map<TableColumn, TableColumn> sourceToTargetMap = new HashMap<TableColumn, TableColumn>(); @Override public void columnAdded(TableColumnModelEvent e) { TableColumnModel sourceModel = (TableColumnModel) e.getSource(); for (int i = e.getFromIndex(); i < e.getToIndex(); i++) { TableColumn sourceColumn = sourceModel.getColumn(i); handleColumnAdded(sourceColumn); } } public void init(TableColumnModel sourceModel) { int columnCount = sourceModel.getColumnCount(); for (int i = 0; i < columnCount; i++) { TableColumn sourceColumn = sourceModel.getColumn(i); handleColumnAdded(sourceColumn); } } private void handleColumnAdded(TableColumn sourceColumn) { TableColumn targetColumn = new TableColumn(); copyProperties(sourceColumn, targetColumn); BeanPropertySync<TableColumn> beanPropertySync = new BeanPropertySync<TableColumn>( targetColumn); beanPropertySync.setSynchronization(sourceColumn); propertySyncMap.put(targetColumn, new TableColumnSync(sourceColumn, beanPropertySync)); DefaultTableColumnModel targetModel = SynchronizedTableColumnModel.this; targetModel.addColumn(targetColumn); sourceToTargetMap.put(sourceColumn, targetColumn); } @Override public void columnRemoved(TableColumnModelEvent e) { TableColumnModel sourceModel = (TableColumnModel) e.getSource(); for (int i = e.getFromIndex(); i < e.getToIndex(); i++) { TableColumn sourceColumn = sourceModel.getColumn(i); handleColumnRemoved(sourceColumn); } } private void handleColumnRemoved(TableColumn sourceColumn) { TableColumn targetColumn = sourceToTargetMap.get(sourceColumn); TableColumnSync tableColumnSync = propertySyncMap.get(targetColumn); DefaultTableColumnModel targetModel = SynchronizedTableColumnModel.this; targetModel.removeColumn(targetColumn); tableColumnSync.removePropertyChangeListener(); } @Override public void columnMoved(TableColumnModelEvent e) { } private void copyProperties(TableColumn sourceColumn, TableColumn targetColumn) { int modelIndex = sourceColumn.getModelIndex(); int width = sourceColumn.getWidth(); TableCellRenderer cellRenderer = sourceColumn.getCellRenderer(); TableCellEditor cellEditor = sourceColumn.getCellEditor(); targetColumn.setModelIndex(modelIndex); targetColumn.setWidth(width); targetColumn.setCellRenderer(cellRenderer); targetColumn.setCellEditor(cellEditor); } @Override public void columnMarginChanged(ChangeEvent e) { TableColumnModel sourceModel = (TableColumnModel) e.getSource(); DefaultTableColumnModel targetModel = SynchronizedTableColumnModel.this; targetModel.setColumnMargin(sourceModel.getColumnMargin()); } @Override public void columnSelectionChanged(ListSelectionEvent e) { if (e.getValueIsAdjusting()) { return; } DefaultTableColumnModel targetModel = SynchronizedTableColumnModel.this; targetModel.setSelectionModel((ListSelectionModel) e.getSource()); } } private static class TableColumnSync { private TableColumn sourceColumn; private BeanPropertySync<TableColumn> beanPropertySync; public TableColumnSync(TableColumn sourceColumn, BeanPropertySync<TableColumn> beanPropertySync) { this.sourceColumn = sourceColumn; this.beanPropertySync = beanPropertySync; } public void removePropertyChangeListener() { this.sourceColumn.removePropertyChangeListener(beanPropertySync); } } }