/* * Geotoolkit - An Open Source Java GIS Toolkit * http://www.geotoolkit.org * * (C) 2014, Geomatys * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. */ package org.geotoolkit.gui.swing.style.symbolizer; import org.apache.sis.storage.DataStoreException; import org.geotoolkit.data.FeatureStoreUtilities; import org.geotoolkit.display2d.ext.isoline.symbolizer.IsolineSymbolizer; import org.geotoolkit.factory.FactoryFinder; import org.geotoolkit.factory.Hints; import org.geotoolkit.gui.swing.propertyedit.PropertyPane; import org.geotoolkit.gui.swing.style.JColorMapPane; import org.geotoolkit.gui.swing.style.StyleElementEditor; import org.geotoolkit.map.CoverageMapLayer; import org.geotoolkit.map.FeatureMapLayer; import org.geotoolkit.map.MapBuilder; import org.geotoolkit.map.MapLayer; import org.geotoolkit.style.MutableFeatureTypeStyle; import org.geotoolkit.style.MutableRule; import org.geotoolkit.style.MutableStyleFactory; import org.opengis.feature.FeatureType; import org.opengis.style.*; import org.apache.sis.measure.Units; import javax.swing.*; import java.awt.*; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.util.logging.Level; import org.geotoolkit.gui.swing.resource.MessageBundle; import static org.geotoolkit.style.StyleConstants.*; /** * Swing editor for IsolineSymbolizer. * * @author Quentin Boileau (Geomatys) */ public class JIsolineSymbolizerPane extends StyleElementEditor<IsolineSymbolizer> implements PropertyPane { private static final MutableStyleFactory SF = (MutableStyleFactory) FactoryFinder.getStyleFactory(new Hints(Hints.STYLE_FACTORY, MutableStyleFactory.class)); private final JColorMapPane guiColorMapPane = new JColorMapPane(); private final JLineSymbolizerPane guiLineSymbolizerPane = new JLineSymbolizerPane(); private final JTextSymbolizerPane guiTextSymbolizerPane = new JTextSymbolizerPane(); private final JCheckBox guiShowTextCB = new JCheckBox(); private final JCheckBox guiIsolineOnlyCB = new JCheckBox(); private MapLayer layer = null; private RasterSymbolizer oldRS; private FeatureMapLayer isolineMockLayer; public JIsolineSymbolizerPane() { super(IsolineSymbolizer.class); guiShowTextCB.setText(MessageBundle.format("isolineEditor_showLabel")); guiShowTextCB.setSelected(false); guiIsolineOnlyCB.setText(MessageBundle.format("isolineEditor_isolineOnly")); guiIsolineOnlyCB.setSelected(false); setLayout(new BorderLayout()); JPanel topPanel = new JPanel(new FlowLayout()); topPanel.add(guiShowTextCB); topPanel.add(guiIsolineOnlyCB); JTabbedPane tabbedPane = new JTabbedPane(SwingConstants.LEFT); tabbedPane.add(MessageBundle.format("isolineEditor_colormap"), guiColorMapPane); tabbedPane.add(MessageBundle.format("isolineEditor_line"), guiLineSymbolizerPane); tabbedPane.add(MessageBundle.format("isolineEditor_text"), guiTextSymbolizerPane); add(BorderLayout.NORTH, topPanel); add(BorderLayout.CENTER, tabbedPane); final PropertyChangeListener propListener = new PropertyChangeListener() { @Override public void propertyChange(PropertyChangeEvent evt) { JIsolineSymbolizerPane.this.propertyChange(evt); } }; guiShowTextCB.addPropertyChangeListener(propListener); guiIsolineOnlyCB.addPropertyChangeListener(propListener); guiColorMapPane.addPropertyChangeListener(propListener); guiLineSymbolizerPane.addPropertyChangeListener(propListener); guiTextSymbolizerPane.addPropertyChangeListener(propListener); } @Override public void setLayer(MapLayer layer) { super.setLayer(layer); this.layer = layer; guiColorMapPane.setLayer(layer); //use isoline mock layer guiLineSymbolizerPane.setLayer(isolineMockLayer); guiTextSymbolizerPane.setLayer(isolineMockLayer); } @Override public void parse(IsolineSymbolizer target) { if (target != null) { this.oldRS = target.getRasterSymbolizer(); guiColorMapPane.parse(target.getRasterSymbolizer()); guiLineSymbolizerPane.parse(target.getLineSymbolizer()); guiTextSymbolizerPane.parse(target.getTextSymbolizer()); guiIsolineOnlyCB.setSelected(target.getIsolineOnly()); guiShowTextCB.setSelected(target.getTextSymbolizer() != null); } else { RasterSymbolizer nullRasterSymbolizer = null; guiColorMapPane.parse(nullRasterSymbolizer); guiLineSymbolizerPane.parse(null); guiTextSymbolizerPane.parse(null); guiShowTextCB.setSelected(false); guiIsolineOnlyCB.setSelected(false); } } @Override public IsolineSymbolizer create() { //rebuild RasterSymbolizer from ColorMap final ColorMap colorMap = guiColorMapPane.create(); final String name = (oldRS != null ? oldRS.getName() : "RasterSymbolizer"); final ContrastEnhancement enchance = (oldRS != null ? oldRS.getContrastEnhancement() : DEFAULT_CONTRAST_ENHANCEMENT); final ShadedRelief relief = (oldRS != null ? oldRS.getShadedRelief() : DEFAULT_SHADED_RELIEF); final Description desc = (oldRS != null ? oldRS.getDescription() : DEFAULT_DESCRIPTION); final ChannelSelection selection = SF.channelSelection( SF.selectedChannelType(guiColorMapPane.getSelectedBand(),DEFAULT_CONTRAST_ENHANCEMENT)); final RasterSymbolizer rasterSymbolizer = SF.rasterSymbolizer( name, DEFAULT_GEOM, desc, Units.POINT, LITERAL_ONE_FLOAT, selection, OverlapBehavior.LATEST_ON_TOP, colorMap, enchance, relief, null); final TextSymbolizer textSymbolizer = guiShowTextCB.isSelected() ? guiTextSymbolizerPane.create() : null; return new IsolineSymbolizer( rasterSymbolizer, guiLineSymbolizerPane.create(), textSymbolizer, guiIsolineOnlyCB.isSelected()); } @Override protected Object[] getFirstColumnComponents() { return new Object[0]; } @Override public boolean canHandle(Object candidate) { return super.canHandle(candidate) || (candidate instanceof CoverageMapLayer); } //keep track of where the symbolizer was to avoid rewriting the complete style private MutableRule parentRule = null; private int parentIndex = 0; @Override public void setTarget(Object candidate) { isolineMockLayer = null; if (candidate instanceof CoverageMapLayer) { try { final FeatureType ft = IsolineSymbolizer.buildIsolineType(); isolineMockLayer = MapBuilder.createFeatureLayer( FeatureStoreUtilities.collection("", ft), getStyleFactory().style()); } catch (DataStoreException ex) { LOGGER.log(Level.WARNING, ex.getMessage(),ex); } setLayer((CoverageMapLayer) candidate); //search for a IsolineSymbolizer parentRule = null; parentIndex = 0; for(MutableFeatureTypeStyle fts : this.layer.getStyle().featureTypeStyles()){ for(MutableRule r : fts.rules()){ for(int i=0,n=r.symbolizers().size();i<n;i++){ Symbolizer s = r.symbolizers().get(i); if(s instanceof IsolineSymbolizer){ parse((IsolineSymbolizer)s); parentRule = r; parentIndex = i; return; } } } } parse(null); }else if(candidate instanceof IsolineSymbolizer){ parse((IsolineSymbolizer)candidate); }else{ parse(null); } } @Override public void apply() { if(layer!=null){ final IsolineSymbolizer symbol = create(); if(parentRule!=null){ parentRule.symbolizers().remove(parentIndex); parentRule.symbolizers().add(parentIndex,symbol); }else{ //style did not exist, add a new feature type style for it final MutableFeatureTypeStyle fts = SF.featureTypeStyle(); final MutableRule rule = SF.rule(symbol); fts.rules().add(rule); fts.setDescription(SF.description("isoline", "isoline")); rule.setDescription(SF.description("isoline", "isoline")); layer.getStyle().featureTypeStyles().add(fts); parentRule = rule; parentIndex = 0; } } } private void propertyChange(PropertyChangeEvent evt) { if (PROPERTY_UPDATED.equalsIgnoreCase(evt.getPropertyName())) { firePropertyChange(PROPERTY_UPDATED, null, create()); } } @Override public void reset() { parse(null); } @Override public String getTitle() { return MessageBundle.format("isolineEditor_displayName"); } @Override public ImageIcon getIcon() { //TODO return null; } @Override public Image getPreview() { return null; } @Override public String getToolTip() { return MessageBundle.format("isolineEditor_displayName"); } @Override public Component getComponent() { return this; } }