package org.geopublishing.atlasStyler.swing; import java.awt.Color; import java.awt.Component; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.event.MouseWheelEvent; import java.awt.event.MouseWheelListener; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.text.NumberFormat; import javax.swing.JLabel; import javax.swing.JTable; import javax.swing.SwingConstants; import javax.swing.table.DefaultTableCellRenderer; import javax.swing.table.DefaultTableModel; import javax.swing.table.TableCellRenderer; import org.geopublishing.atlasStyler.ASUtil; import org.geopublishing.atlasStyler.AtlasStyler; import org.geopublishing.atlasStyler.AtlasStylerVector; import org.geopublishing.atlasStyler.RuleChangeListener; import org.geopublishing.atlasStyler.RuleChangedEvent; import org.geopublishing.atlasStyler.RulesListsList; import org.geopublishing.atlasStyler.rulesLists.AbstractRulesList.RulesListType; import org.geopublishing.atlasStyler.rulesLists.RulesListInterface; import org.geopublishing.atlasViewer.swing.AtlasStylerDialog; import org.opengis.filter.Filter; import de.schmitzm.geotools.gui.XMapPane; import de.schmitzm.lang.LangUtil; import de.schmitzm.swing.SwingUtil; public class RulesListTable extends JTable { public static final int COLIDX_ENABLED = 0; static final int COLIDX_TITLE = 1; static final int COLIDX_TYPE = 2; public static final int COLIDX_MINSCALE = 3; public static final int COLIDX_MAXSCALE = 4; public static final int COLIDX_FILTER = 5; private final RulesListsList rulesList; private final AtlasStyler atlasStyler; /** * Listen to changes in the rulelist that affect this table view */ protected RuleChangeListener listenForRulesListChangesWhichShowInTheTable = new RuleChangeListener() { @Override public void changed(RuleChangedEvent e) { if (RuleChangedEvent.RULE_CHANGE_EVENT_FILTER_STRING.equals(e .getReason())) { // ((DefaultTableModel) getModel()).fireTableDataChanged(); repaint(); } else if (RuleChangedEvent.RULE_CHANGE_EVENT_MINMAXSCALE_STRING .equals(e.getReason())) { // ((DefaultTableModel) getModel()).fireTableDataChanged(); repaint(); } else if (RuleChangedEvent.RULE_CHANGE_EVENT_ENABLED_STRING .equals(e.getReason())) repaint(); } }; /** * The ScaleDenominator shown in any preview {@link XMapPane} outside of * this {@link AtlasStylerDialog} */ private Double scaleDenominator; protected PropertyChangeListener listenForScaleChangesInthePreviewPaneAndRepaintTable = new PropertyChangeListener() { @Override public void propertyChange(PropertyChangeEvent evt) { setScaleInPreview((Double) evt.getNewValue()); } }; private void setScaleInPreview(Double newScale) { if (newScale == scaleDenominator) return; scaleDenominator = newScale; // ((DefaultTableModel) getModel()).fireTableDataChanged(); repaint(); } private final PropertyChangeListener updateOnRulesListsListChanges = new PropertyChangeListener() { @Override public void propertyChange(PropertyChangeEvent evt) { changeTableModel(); } }; private final StylerDialog asd; private final TableCellRenderer ruleListLabelRenderer = new DefaultTableCellRenderer() { @Override public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { JLabel proto = (JLabel) super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); if (!(Boolean) table.getModel().getValueAt(row, RulesListTable.COLIDX_ENABLED)) { proto.setForeground(Color.gray); } else proto.setForeground(Color.BLACK); return proto; } }; private void changeTableModel() { ((DefaultTableModel) getModel()).fireTableStructureChanged(); int rc = rulesList.size(); if (rc > 0) { // Default select the first one.. nice when it has just been added if (getSelectionModel().isSelectionEmpty()) // getSelectionModel().setSelectionInterval(rc - 1, rc - 1); getSelectionModel().setSelectionInterval(0, 0); } updateColumnsLook(); if (atlasStyler instanceof AtlasStylerVector) { setDefaultEditor( Filter.class, new FilterTableCellEditor(RulesListTable.this, ((AtlasStylerVector) atlasStyler) .getStyledFeatures())); } // Re-add the weak listener that listens for filter changes created // external, e.g. by popup menu insert for (RulesListInterface rl : rulesList) { rl.addListener(listenForRulesListChangesWhichShowInTheTable); } } public RulesListTable(StylerDialog asd) { this.asd = asd; asd.addScaleChangeListener(listenForScaleChangesInthePreviewPaneAndRepaintTable); if (asd.getPreviewMapPane() != null) scaleDenominator = asd.getPreviewMapPane().getScaleDenominator(); this.atlasStyler = asd.getAtlasStyler(); rulesList = atlasStyler.getRuleLists(); setModel(new RulesListTableModel()); rulesList.addListener(updateOnRulesListsListChanges); changeTableModel(); addMouseListener(new PopupListener()); addMouseWheelListener(new MouseWheelListener() { @Override public void mouseWheelMoved(MouseWheelEvent e) { int columnAtPoint = RulesListTable.this.columnAtPoint(e .getPoint()); int rowAtPoint = RulesListTable.this.rowAtPoint(e.getPoint()); int colInModel = RulesListTable.this .convertColumnIndexToModel(columnAtPoint); int rowInModel = RulesListTable.this .convertRowIndexToModel(rowAtPoint); RulesListInterface ruleList = rulesList.get(rowInModel); final int i = e.getWheelRotation() * -1; if (colInModel == COLIDX_MINSCALE) { double tenPercent = ruleList.getMinScaleDenominator() * 0.1; if (tenPercent < 5000) tenPercent = 5000; double newValue = ruleList.getMinScaleDenominator() + i * tenPercent; // Nicht größer Unendlich erlauben if (i > 0 && ruleList.getMinScaleDenominator() >= RulesListInterface.MAX_SCALEDENOMINATOR) { return; } newValue = LangUtil.round(newValue, -3); ruleList.setMinScaleDenominator(newValue); } if (colInModel == COLIDX_MAXSCALE) { double tenPercent = ruleList.getMaxScaleDenominator() * 0.1; if (tenPercent < 5000) tenPercent = 5000; double newValue = ruleList.getMaxScaleDenominator() + i * tenPercent; // Nicht größer Unendlich erlauben if (i > 0 && ruleList.getMaxScaleDenominator() >= RulesListInterface.MAX_SCALEDENOMINATOR) { return; } // newValue = LangUtil.round(newValue, -3); ruleList.setMaxScaleDenominator(newValue); } } }); } /** * Renderer for a table cell that presents a Min- or MaxScaleDenominator. */ class ScaleCellRenderer extends DefaultTableCellRenderer { private final boolean isMin; /** * @param min * if <code>true</code> this renders a minScaleDenominator, * otherwise a maxScaleDenominator */ public ScaleCellRenderer(boolean min) { this.isMin = min; } @Override public JLabel getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { JLabel proto = (JLabel) new DefaultTableCellRenderer() .getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); proto.setHorizontalAlignment(SwingConstants.RIGHT); proto.setVerticalAlignment(SwingConstants.TOP); if (value != null && ((Number) value).doubleValue() >= RulesListInterface.MAX_SCALEDENOMINATOR) proto.setText("<html>∞</html>"); else proto.setText(NumberFormat.getIntegerInstance().format(value)); if (isMin && scaleDenominator != null && scaleDenominator < (Double) value) { proto.setBackground(Color.red); } else if (!isMin && scaleDenominator != null && scaleDenominator > (Double) value) { proto.setBackground(Color.red); } // Use gray font if the rulelist is disabled if (!(Boolean) table.getModel().getValueAt(row, COLIDX_ENABLED)) { proto.setForeground(Color.GRAY); } return proto; } } class PopupListener extends MouseAdapter { @Override public void mousePressed(MouseEvent e) { if (!showPopup(e)) { } } @Override public void mouseReleased(MouseEvent e) { if (!showPopup(e)) { } } private boolean showPopup(MouseEvent e) { if (e.isPopupTrigger()) { final Component component = e.getComponent(); // int columnAtPoint = RulesListTable.this.columnAtPoint(e // .getPoint()); int rowAtPoint = RulesListTable.this.rowAtPoint(e.getPoint()); // int colInModel = RulesListTable.this // .convertColumnIndexToModel(columnAtPoint); int rowInModel = RulesListTable.this .convertRowIndexToModel(rowAtPoint); getSelectionModel() .setSelectionInterval(rowInModel, rowInModel); RulesListInterface ruleList = rulesList.get(rowInModel); RulesListPopup popup = new RulesListPopup(ruleList, asd); popup.show(component, e.getX(), e.getY()); return true; } return false; } } class RulesListTableModel extends DefaultTableModel { @Override public int getRowCount() { return rulesList.size(); } @Override public int getColumnCount() { if (atlasStyler instanceof AtlasStylerVector) { return 6; } else return 5; } @Override public String getColumnName(int column) { switch (column) { case COLIDX_TITLE: return ASUtil.R("RulesListTable.Column.Name"); case COLIDX_TYPE: return ASUtil.R("RulesListTable.Column.Type"); case COLIDX_MINSCALE: return ASUtil.R("RulesListTable.Column.MinScale"); case COLIDX_MAXSCALE: return ASUtil.R("RulesListTable.Column.MaxScale"); case COLIDX_FILTER: return ASUtil.R("RulesListTable.Column.Filter"); case COLIDX_ENABLED: return ASUtil.R("RulesListTable.Column.Enabled"); default: return super.getColumnName(column); } } @Override public Object getValueAt(int row, int column) { switch (column) { case COLIDX_TITLE: return rulesList.get(row).getTitle(); case COLIDX_TYPE: return "<html>" + rulesList.get(row).getType().getTitle() + "</html>"; case COLIDX_MINSCALE: return rulesList.get(row).getMinScaleDenominator(); case COLIDX_MAXSCALE: return rulesList.get(row).getMaxScaleDenominator(); case COLIDX_FILTER: return rulesList.get(row).getRlFilter(); case COLIDX_ENABLED: return rulesList.get(row).isEnabled(); default: return super.getValueAt(row, column); } } @Override public boolean isCellEditable(int row, int column) { switch (column) { case COLIDX_ENABLED: case COLIDX_FILTER: case COLIDX_MINSCALE: case COLIDX_MAXSCALE: case COLIDX_TITLE: return true; default: return false; } } @Override public Class<?> getColumnClass(int column) { switch (column) { case COLIDX_TITLE: return String.class; case COLIDX_TYPE: return RulesListType.class; case COLIDX_FILTER: return Filter.class; case COLIDX_MINSCALE: case COLIDX_MAXSCALE: return Double.class; case COLIDX_ENABLED: return Boolean.class; default: return super.getColumnClass(column); } } @Override public void setValueAt(Object aValue, int row, int column) { switch (column) { case COLIDX_TITLE: rulesList.get(row).setTitle(aValue.toString()); return; case COLIDX_MINSCALE: rulesList.get(row).setMinScaleDenominator((Double) aValue); return; case COLIDX_MAXSCALE: rulesList.get(row).setMaxScaleDenominator((Double) aValue); return; case COLIDX_FILTER: rulesList.get(row).setRlFilter((Filter) aValue); return; case COLIDX_ENABLED: rulesList.get(row).setEnabled(!rulesList.get(row).isEnabled()); return; default: return; } } } /** * Configures how the columns should be rendered. This method checks for the * "isEasy" flag and hides columns. */ public void updateColumnsLook() { boolean easy = asd.isEasy(); SwingUtil.setColumnLook(this, COLIDX_ENABLED, null, 17, 19, 19); SwingUtil.setColumnLook(this, COLIDX_TITLE, ruleListLabelRenderer, easy ? 0 : 10, easy ? 0 : 40, easy ? 0 : 120); SwingUtil.setColumnLook(this, COLIDX_TYPE, ruleListLabelRenderer, 40, 50, null); SwingUtil.setColumnLook(this, COLIDX_MINSCALE, new ScaleCellRenderer( true), easy ? 0 : 10, easy ? 0 : 40, easy ? 0 : 120); SwingUtil.setColumnLook(this, COLIDX_MAXSCALE, new ScaleCellRenderer( false), easy ? 0 : 10, easy ? 0 : 40, easy ? 0 : 120); if (atlasStyler instanceof AtlasStylerVector) { SwingUtil.setColumnLook(this, COLIDX_FILTER, new FilterTableCellRenderer(), easy ? 0 : 17, easy ? 0 : 19, easy ? 0 : 19); } } }