/*---------------- FILE HEADER ------------------------------------------ This file is part of deegree. Copyright (C) 2001-2007 by: Department of Geography, University of Bonn http://www.giub.uni-bonn.de/deegree/ lat/lon GmbH http://www.lat-lon.de 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; either version 2.1 of the License, or (at your option) any later version. 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. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Contact: Andreas Poth lat/lon GmbH Aennchenstr. 19 53177 Bonn Germany E-Mail: poth@lat-lon.de Prof. Dr. Klaus Greve Department of Geography University of Bonn Meckenheimer Allee 166 53115 Bonn Germany E-Mail: greve@giub.uni-bonn.de ---------------------------------------------------------------------------*/ package org.deegree.igeo.views.swing.style; import static org.deegree.igeo.i18n.Messages.get; import static org.deegree.igeo.views.DialogFactory.openErrorDialog; import static org.deegree.igeo.views.swing.util.IconRegistry.getIcon; import java.awt.BorderLayout; import java.awt.Container; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.WindowEvent; import java.io.File; import java.net.MalformedURLException; import java.util.ArrayList; import java.util.List; import java.util.Set; import javax.swing.JButton; import javax.swing.JComboBox; import javax.swing.JLabel; import javax.swing.JMenu; import javax.swing.JMenuBar; import javax.swing.JMenuItem; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JTabbedPane; import org.deegree.datatypes.QualifiedName; import org.deegree.framework.log.ILogger; import org.deegree.framework.log.LoggerFactory; import org.deegree.framework.xml.XMLParsingException; import org.deegree.graphics.sld.AbstractLayer; import org.deegree.graphics.sld.AbstractStyle; import org.deegree.graphics.sld.FeatureTypeStyle; import org.deegree.graphics.sld.NamedLayer; import org.deegree.graphics.sld.SLDFactory; import org.deegree.graphics.sld.StyleFactory; import org.deegree.graphics.sld.StyledLayerDescriptor; import org.deegree.graphics.sld.UserStyle; import org.deegree.igeo.ApplicationContainer; import org.deegree.igeo.ChangeListener; import org.deegree.igeo.commands.ChangeLayerStyleCommand; import org.deegree.igeo.config.DirectStyleType; import org.deegree.igeo.config.ViewFormType; import org.deegree.igeo.i18n.Messages; import org.deegree.igeo.mapmodel.DefinedStyle; import org.deegree.igeo.mapmodel.DirectStyle; import org.deegree.igeo.mapmodel.Layer; import org.deegree.igeo.mapmodel.NamedStyle; import org.deegree.igeo.settings.Settings; import org.deegree.igeo.style.LayerCache; import org.deegree.igeo.style.LayerCache.CachedLayer; import org.deegree.igeo.style.perform.SldIO; import org.deegree.igeo.views.DialogFactory; import org.deegree.igeo.views.HelpManager; import org.deegree.igeo.views.swing.DefaultFrame; import org.deegree.igeo.views.swing.HelpFrame; import org.deegree.igeo.views.swing.util.IconRegistry; import org.deegree.igeo.views.swing.util.panels.PanelDialog; import org.deegree.kernel.Command; import org.deegree.model.filterencoding.ComplexFilter; import org.deegree.model.filterencoding.Filter; import org.deegree.model.filterencoding.Operation; import org.deegree.model.filterencoding.PropertyIsCOMPOperation; import org.deegree.model.filterencoding.PropertyName; import com.jgoodies.forms.builder.ButtonBarBuilder; import com.jgoodies.forms.builder.DefaultFormBuilder; import com.jgoodies.forms.layout.CellConstraints; import com.jgoodies.forms.layout.FormLayout; /** * The <code>RuleDialog</code> handles the definition of rules. * * @author <a href="mailto:buesching@lat-lon.de">Lyn Buesching</a> * @author last edited by: $Author$ * * @version $Revision$, $Date$ * */ public class RuleDialog extends DefaultFrame implements ActionListener { private static final long serialVersionUID = -4152608665359578717L; private static final ILogger LOG = LoggerFactory.getLogger( RuleDialog.class ); private Layer layer; private ApplicationContainer<?> appContainer; private Settings settings; private List<RuleDefinitionPanel> ruleDefinitionPanels = new ArrayList<RuleDefinitionPanel>(); private JTabbedPane rules; private JButton okBt; private JButton applyBt; private JButton cancelBt; private JButton helpBt; private JMenuBar menuBar; private JMenuItem addRuleItem; private JMenuItem removeRuleItem; private JMenuItem renameRuleItem; private JMenuItem duplicateRuleItem; private JMenuItem importStyleItem; private JMenuItem exportStyleItem; private JMenuItem settingsItem; private JMenuItem editSymbolItem; private SettingsPanel settingsPanel = new SettingsPanel(); private List<ChangeListener> uomChangedListener = new ArrayList<ChangeListener>(); private StyledLayerDescriptor importedSls = null; private boolean styleChanged = false; static { StyleDialogUtils.prepareFormConstants(); } /** * default constructor */ public RuleDialog() { } /** * Sets the layer and updates the RuleDefinitionPanels. * * @param layer * the layer */ public void setLayer( Layer layer ) { this.layer = layer; LayerCache.getInstance().addLayer( layer ); AbstractStyle abstractStyle = layer.getCurrentStyle().getStyle(); settingsPanel.setUom( getUom() ); setStyle( abstractStyle ); } private void setStyle( AbstractStyle abstractStyle ) { if ( abstractStyle instanceof UserStyle ) { FeatureTypeStyle[] featureStyles = ( (UserStyle) abstractStyle ).getFeatureTypeStyles(); for ( int i = 0; i < featureStyles.length; i++ ) { String name; if ( featureStyles[i].getTitle() != null ) { name = featureStyles[i].getTitle(); } else if ( featureStyles[i].getName() != null ) { name = featureStyles[i].getName(); } else { name = get( "$MD10591", ruleDefinitionPanels.size() ); } addRuleDefinitionPanel( name, featureStyles[i] ); } } // no ruleDefinitionPanels defined, so create a default one if ( ruleDefinitionPanels.size() == 0 ) { String name = get( "$MD10591", 1 ); addRuleDefinitionPanel( name, null ); } } /** * * @param appContainer */ public void setApplicationContainer( ApplicationContainer<?> appContainer ) { this.appContainer = appContainer; } /* * (non-Javadoc) * * @see org.deegree.igeo.views.IView#init(org.deegree.igeo.config.ViewFormType) */ @Override public void init( ViewFormType viewForm ) throws Exception { super.init( viewForm ); settings = owner.getApplicationContainer().getSettings(); initComponents(); initRuleDialog(); } /** * sets the ruleDialog in the initial state */ public void reset() { ruleDefinitionPanels.clear(); rules.removeAll(); } private void initComponents() { // TODO: mnemonics(!-i18n?)/shortcuts(?) menuBar = new JMenuBar(); JMenu menuRules = new JMenu( get( "$MD11069" ) ); addRuleItem = new JMenuItem( get( "$MD10592" ), getIcon( "rule_add.png" ) ); addRuleItem.addActionListener( this ); removeRuleItem = new JMenuItem( get( "$MD10593" ), getIcon( "rule_delete.png" ) ); removeRuleItem.addActionListener( this ); renameRuleItem = new JMenuItem( get( "$MD10594" ), getIcon( "rule_edit.png" ) ); renameRuleItem.addActionListener( this ); duplicateRuleItem = new JMenuItem( get( "$MD11605" ), getIcon( "rule_copy.png" ) ); duplicateRuleItem.addActionListener( this ); menuRules.add( addRuleItem ); menuRules.add( removeRuleItem ); menuRules.add( renameRuleItem ); menuRules.add( duplicateRuleItem ); JMenu menuStyles = new JMenu( get( "$MD11070" ) ); importStyleItem = new JMenuItem( get( "$MD11067" ), getIcon( "sld_import.png" ) ); importStyleItem.addActionListener( this ); exportStyleItem = new JMenuItem( get( "$MD11068" ), getIcon( "sld_export.png" ) ); exportStyleItem.addActionListener( this ); menuStyles.add( importStyleItem ); menuStyles.add( exportStyleItem ); JMenu menuSettings = new JMenu( get( "$MD11615" ) ); settingsItem = new JMenuItem( get( "$MD11616" ) ); settingsItem.addActionListener( this ); menuSettings.add( settingsItem ); JMenu menuEdit = new JMenu( get( "$MD11833" ) ); editSymbolItem = new JMenuItem( get( "$MD11834" ) ); editSymbolItem.addActionListener( this ); menuEdit.add( editSymbolItem ); menuBar.add( menuEdit ); menuBar.add( menuRules ); menuBar.add( menuStyles ); menuBar.add( menuSettings ); rules = new JTabbedPane(); rules.setVisible( true ); okBt = new JButton( get( "$DI10001" ), IconRegistry.getIcon( "accept.png" ) ); okBt.addActionListener( this ); cancelBt = new JButton( get( "$DI10002" ), IconRegistry.getIcon( "cancel.png" ) ); cancelBt.addActionListener( this ); helpBt = new JButton( get( "$DI10016" ), IconRegistry.getIcon( "help.png" ) ); helpBt.addActionListener( this ); applyBt = new JButton( get( "$DI10043" ), IconRegistry.getIcon( "eye.png" ) ); applyBt.addActionListener( this ); } private void initRuleDialog() { FormLayout fl = new FormLayout( "left:default:grow(0.5), right:default:grow(0.5)", "top:default, $btheight:grow(1.0), $btheight:grow(1.0)" ); DefaultFormBuilder builder = new DefaultFormBuilder( fl ); builder.setDefaultDialogBorder(); CellConstraints cc = new CellConstraints(); builder.add( rules, cc.xyw( 1, 1, 2 ) ); builder.add( helpBt, cc.xy( 1, 2 ) ); builder.add( applyBt, cc.xy( 2, 2 ) ); builder.add( buildMainButtonBar(), cc.xywh( 1, 3, 2, 1, CellConstraints.RIGHT, CellConstraints.BOTTOM ) ); setJMenuBar( menuBar ); getContentPane().add( builder.getPanel() ); } private JPanel buildMainButtonBar() { ButtonBarBuilder bbBuilder = new ButtonBarBuilder(); bbBuilder.addRelatedGap(); bbBuilder.addGlue(); bbBuilder.addGriddedButtons( new JButton[] { okBt, cancelBt } ); return bbBuilder.getPanel(); } private void closeDialog() { for ( int i = 0; i < rules.getComponentCount(); i++ ) { if ( rules.getComponent( i ) instanceof RuleDefinitionPanel ) { RuleDefinitionPanel ruleDefPanel = (RuleDefinitionPanel) rules.getComponent( i ); ruleDefPanel.closeFrames(); } } dispose(); } private NamedStyle getMergedStyle() { DirectStyleType dst = new DirectStyleType(); FeatureTypeStyle[] fts = new FeatureTypeStyle[ruleDefinitionPanels.size()]; for ( int i = 0; i < ruleDefinitionPanels.size(); i++ ) { fts[i] = ruleDefinitionPanels.get( i ).getFeatureTypeStyle(); } Filter filter = fts[0].getRules()[0].getFilter(); String s = ""; if ( filter != null ) { // find name of the property used for classification Operation op = ( (ComplexFilter) filter ).getOperation(); if ( op instanceof PropertyIsCOMPOperation ) { PropertyName pn = (PropertyName) ( (PropertyIsCOMPOperation) op ).getFirstExpression(); s = " (" + pn.getValue().getAsString() + ')'; } } UserStyle us = (UserStyle) StyleFactory.createStyle( "default1", layer.getTitle() + s, "default3", fts ); dst.setName( us.getName() ); dst.setTitle( us.getTitle() ); dst.setAbstract( us.getAbstract() ); dst.setCurrent( true ); dst.setUom( getUom().toString().toLowerCase() ); return new DirectStyle( dst, us, layer ); } private RuleDefinitionPanel addRuleDefinitionPanel( String name, FeatureTypeStyle rules ) { RuleDefinitionPanel newRuleDefPanel = new RuleDefinitionPanel( this, name, layer.getIdentifier(), settings, rules, appContainer ); ruleDefinitionPanels.add( newRuleDefPanel ); this.rules.addTab( name, newRuleDefPanel ); this.rules.setSelectedComponent( newRuleDefPanel ); return newRuleDefPanel; } private void removeAllRuleDefinitionPanels() { ruleDefinitionPanels.clear(); rules.removeAll(); } private void removeSelectedRuleDefinitionPanel() { ruleDefinitionPanels.remove( rules.getSelectedComponent() ); rules.remove( rules.getSelectedIndex() ); } // ////////////////////////////////////////////////////////////////////////////// // ACTIONLISTENER // ////////////////////////////////////////////////////////////////////////////// /* * (non-Javadoc) * * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent) */ public void actionPerformed( ActionEvent e ) { if ( e.getSource() instanceof JButton ) { JButton srcBt = (JButton) e.getSource(); if ( srcBt == cancelBt ) { closeDialog(); } else if ( srcBt == okBt ) { applyStyle(); closeDialog(); } else if ( srcBt == helpBt && appContainer != null ) { HelpFrame hf = HelpFrame.getInstance( new HelpManager( appContainer ) ); hf.setVisible( true ); hf.gotoKeyword( "rule:EditStyle" ); } else if ( srcBt == applyBt ) { applyStyle(); } } else if ( e.getSource() instanceof JMenuItem ) { JMenuItem srcItem = (JMenuItem) e.getSource(); if ( srcItem == addRuleItem ) { int noOfNewRules = rules.getComponentCount() + 1; String s = (String) JOptionPane.showInputDialog( this, get( "$MD10595" ), get( "$MD10596" ), JOptionPane.PLAIN_MESSAGE, null, null, get( "$MD10591", noOfNewRules ) ); if ( s != null ) { if ( s.length() == 0 ) { s = get( "$MD10591", noOfNewRules ); } addRuleDefinitionPanel( s, null ); } } else if ( srcItem == removeRuleItem ) { if ( rules.getSelectedIndex() > -1 && rules.getComponentCount() > 1 ) { removeSelectedRuleDefinitionPanel(); } } else if ( srcItem == renameRuleItem ) { int selectedIndex = rules.getSelectedIndex(); if ( rules.getSelectedComponent() instanceof RuleDefinitionPanel && selectedIndex > -1 ) { String tabTitle = rules.getTitleAt( selectedIndex ); String s = (String) JOptionPane.showInputDialog( this, get( "$MD10597" ), get( "$MD10598", tabTitle ), JOptionPane.PLAIN_MESSAGE, null, null, tabTitle ); if ( s != null && s.length() > 0 ) { rules.setTitleAt( selectedIndex, s ); RuleDefinitionPanel selectedPanel = (RuleDefinitionPanel) rules.getSelectedComponent(); selectedPanel.setRuleName( s ); } } } else if ( srcItem == duplicateRuleItem ) { int noOfNewRules = rules.getComponentCount() + 1; String s = (String) JOptionPane.showInputDialog( this, get( "$MD10595" ), get( "$MD10596" ), JOptionPane.PLAIN_MESSAGE, null, null, get( "$MD10591", noOfNewRules ) ); if ( s != null ) { if ( s.length() == 0 ) { s = get( "$MD10591", noOfNewRules ); } RuleDefinitionPanel selectedPanel = (RuleDefinitionPanel) this.rules.getSelectedComponent(); RuleDefinitionPanel newPanel = addRuleDefinitionPanel( s, selectedPanel.getFeatureTypeStyle() ); newPanel.setSettings( selectedPanel.getSelectedFeatureTypeIndex(), selectedPanel.getSelectedGeomPropertyIndex(), selectedPanel.getMinScale(), selectedPanel.getMaxScale(), selectedPanel.getSemanticTypeId() ); } } else if ( srcItem == importStyleItem ) { File file = SldIO.importSld( appContainer, this ); if ( file != null ) { try { importedSls = SLDFactory.createSLD( file.toURI().toURL() ); if ( importedSls != null ) { NamedLayer[] namedLayers = importedSls.getNamedLayers(); if ( namedLayers.length > 0 ) { AbstractStyle[] styles = namedLayers[0].getStyles(); for ( int i = 0; i < styles.length; i++ ) { if ( styles[i] instanceof UserStyle ) { removeAllRuleDefinitionPanels(); setStyle( styles[i] ); break; } } } } styleChanged = false; } catch ( MalformedURLException e1 ) { LOG.logError( get( "$DG10099", file.getPath(), e1.getMessage() ) ); } catch ( XMLParsingException e2 ) { LOG.logError( get( "$DG10100", file.getName(), e2.getMessage() ) ); openErrorDialog( appContainer.getViewPlatform(), this, get( "$MD11073" ), get( "$DI10017" ), e2 ); } } } else if ( srcItem == exportStyleItem ) { AbstractLayer al = new NamedLayer( getTitle(), null, new AbstractStyle[] { getMergedStyle().getStyle() } ); StyledLayerDescriptor sld = new StyledLayerDescriptor( new AbstractLayer[] { al }, "1.0.0" ); SldIO.exportSld( sld.exportAsXML(), appContainer, this ); } else if ( srcItem == settingsItem ) { String old = settingsPanel.getUom(); PanelDialog dlg = new PanelDialog( settingsPanel, true ); dlg.setLocationRelativeTo( this ); dlg.setVisible( true ); if ( dlg.clickedOk ) { NamedStyle currentStyle = layer.getCurrentStyle(); if ( currentStyle instanceof DefinedStyle && !old.equals( settingsPanel.getUom() ) ) { ( (DefinedStyle) currentStyle ).setUom( settingsPanel.getUom() ); informUomChangeListener(); } } } else if ( srcItem == editSymbolItem ) { PanelDialog dlg = new PanelDialog( new EditSymbollibraryPanel( settings.getGraphicOptions() ), false ); dlg.setLocationRelativeTo( this ); dlg.setVisible( true ); } } } private void applyStyle() { NamedStyle style = getStyleFromImportedSld(); if ( style == null ) { style = getMergedStyle(); } style.setCurrent( true ); Command cmd = new ChangeLayerStyleCommand( layer, style ); ApplicationContainer<Container> appContainer = owner.getApplicationContainer(); try { appContainer.getCommandProcessor().executeSychronously( cmd, true ); } catch ( Exception e ) { LOG.logError( e.getMessage(), e ); DialogFactory.openErrorDialog( appContainer.getViewPlatform(), this, Messages.getMessage( getLocale(), "$MD11250" ), Messages.getMessage( getLocale(), "$MD11251" ), e ); } } private NamedStyle getStyleFromImportedSld() { if ( !styleChanged && importedSls != null && importedSls.getNamedLayers().length > 0 ) { AbstractStyle[] styles = importedSls.getNamedLayers()[0].getStyles(); for ( AbstractStyle at : styles ) { if ( at instanceof UserStyle ) { UserStyle us = (UserStyle) at; DirectStyleType dst = new DirectStyleType(); dst.setName( us.getName() ); dst.setTitle( us.getTitle() ); dst.setAbstract( us.getAbstract() ); dst.setCurrent( true ); dst.setUom( getUom().toString().toLowerCase() ); setFeatureTypeName( us ); return new DirectStyle( dst, us, layer ); } } } return null; } private void setFeatureTypeName( UserStyle us ) { FeatureTypeStyle[] featureTypeStyles = us.getFeatureTypeStyles(); for ( FeatureTypeStyle featureTypeStyle : featureTypeStyles ) { String featureTypeName = getFeatureTypeName( featureTypeStyle.getFeatureTypeName() ); featureTypeStyle.setFeatureTypeName( featureTypeName ); } } private String getFeatureTypeName( String featureTypeName ) { CachedLayer cachedLayer = LayerCache.getInstance().getCachedLayer( layer.getIdentifier() ); Set<QualifiedName> featureTypes = cachedLayer.getFeatureTypes(); QualifiedName featureType = null; for ( QualifiedName availableFeatureType : featureTypes ) { if ( featureType == null ) { featureType = availableFeatureType; } if ( availableFeatureType.equals( new QualifiedName( featureTypeName ) ) ) { return availableFeatureType.getFormattedString(); } } if ( featureTypes.size() > 1 ) { return getFeatureTypeSelectedByUser( featureTypes, featureType.getFormattedString() ); } else if ( featureTypes.size() == 1 ) { return featureType.getFormattedString(); } return featureTypeName; } private String getFeatureTypeSelectedByUser( Set<QualifiedName> featureTypes, String defaultFeatureName ) { JPanel panel = new JPanel() { private static final long serialVersionUID = -8531703257413252791L; @Override public String toString() { return get( "$MD11869" ); } }; panel.setLayout( new BorderLayout() ); panel.add( new JLabel( get( "$MD11870" ) ) ); JComboBox featureTypeNames = new JComboBox(); for ( QualifiedName featureType : featureTypes ) { featureTypeNames.addItem( featureType ); } panel.add( featureTypeNames ); PanelDialog panelDialog = PanelDialog.create( this, panel, true ); if ( panelDialog.clickedOk ) { return ( (QualifiedName) featureTypeNames.getSelectedItem() ).getFormattedString(); } return defaultFeatureName; } /** * @return the uom defined for the current layer */ public String getUom() { NamedStyle currentStyle = layer.getCurrentStyle(); String uom = DefinedStyle.UOM_PIXEL; if ( currentStyle instanceof DefinedStyle ) { uom = ( (DefinedStyle) currentStyle ).getUom(); } return uom; } @Override public void windowOpened( WindowEvent e ) { // the state of this component will always be closed because it is not useful to have it // opened initially. So it a project will be stored the state will be closed even if the // Style editor is opened at this moment this.owner.getComponentStateAdapter().setClosed( true ); } /** * Register a listener to be informed when the global setting for uom changed. * * @param listener * listener to add */ public void addUomChangedListener( ChangeListener uomChangeListener ) { uomChangedListener.add( uomChangeListener ); } void informUomChangeListener() { for ( ChangeListener listener : uomChangedListener ) { listener.valueChanged( new UomChangedEvent( settingsPanel.getUom() ) ); } } void setStyleChanged() { this.styleChanged = true; } }