/*---------------- 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 java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;
import javax.swing.BorderFactory;
import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import org.deegree.datatypes.QualifiedName;
import org.deegree.framework.log.ILogger;
import org.deegree.framework.log.LoggerFactory;
import org.deegree.graphics.sld.FeatureTypeStyle;
import org.deegree.graphics.sld.Geometry;
import org.deegree.graphics.sld.Rule;
import org.deegree.graphics.sld.StyleFactory;
import org.deegree.graphics.sld.Symbolizer;
import org.deegree.igeo.ApplicationContainer;
import org.deegree.igeo.ChangeListener;
import org.deegree.igeo.settings.Settings;
import org.deegree.igeo.style.LayerCache;
import org.deegree.igeo.style.LayerCache.CachedLayer;
import org.deegree.igeo.views.swing.ScaleDenominatorPanel;
import org.deegree.igeo.views.swing.addlayer.QualifiedNameRenderer;
import org.deegree.igeo.views.swing.style.StyleDialog.GEOMTYPE;
import org.deegree.igeo.views.swing.style.component.SldFrame;
import org.deegree.model.Identifier;
import org.deegree.model.feature.schema.FeatureType;
import org.deegree.model.filterencoding.ComplexFilter;
import org.deegree.model.filterencoding.LogicalOperation;
import org.deegree.model.filterencoding.Operation;
import org.deegree.model.filterencoding.OperationDefines;
import org.deegree.model.filterencoding.PropertyIsInstanceOfOperation;
import org.deegree.model.filterencoding.PropertyName;
import org.deegree.ogcbase.CommonNamespaces;
import org.deegree.ogcbase.PropertyPath;
import org.deegree.ogcbase.PropertyPathFactory;
import org.deegree.ogcbase.PropertyPathStep;
import com.jgoodies.forms.builder.ButtonBarBuilder;
import com.jgoodies.forms.builder.DefaultFormBuilder;
import com.jgoodies.forms.layout.CellConstraints;
import com.jgoodies.forms.layout.FormLayout;
/**
* <code>RuleDefinitionPanel</code> represents one rule.
*
* @author <a href="mailto:buesching@lat-lon.de">Lyn Buesching</a>
* @author last edited by: $Author$
*
* @version $Revision$, $Date$
*
*/
public class RuleDefinitionPanel extends JPanel {
private static final long serialVersionUID = -1607863664136371060L;
private static final ILogger LOG = LoggerFactory.getLogger( RuleDefinitionPanel.class );
private RuleDialog ruleDialog;
private ApplicationContainer<?> appContainer;
private Settings settings;
private FeatureTypeStyle featureTypeStyle;
private SldFrame sldFrame;
private String ruleName;
private StyleDialog styleDialog;
private JComboBox featureTypeCBox;
private JComboBox geomPropertyCBox;
private ScaleDenominatorPanel scalePanel;
private List<JRadioButton> geomTypeRBs;
private JRadioButton rbAll;
private JRadioButton rbPoints;
private JRadioButton rbLines;
private JRadioButton rbPolygons;
private Identifier layerId;
/*
* @param ruleName the name of the RuleDefinitionPanel (shown in the assigned StyleDialog as FrameTitle)
*
* @param layer the layer selected for editing
*
* @param settings the settings of the project
*
* @param rules
*/
public RuleDefinitionPanel( RuleDialog ruleDialog, String ruleName, Identifier layerId, Settings settings,
FeatureTypeStyle featureTypeStyle, ApplicationContainer<?> appContainer ) {
this.ruleDialog = ruleDialog;
this.ruleName = ruleName;
this.settings = settings;
this.featureTypeStyle = featureTypeStyle;
this.appContainer = appContainer;
this.layerId = layerId;
initComponents();
init();
setLayer();
setStyle( featureTypeStyle );
}
/**
* @param featureTypeStyle
*/
private void setStyle( FeatureTypeStyle featureTypeStyle ) {
if ( featureTypeStyle != null ) {
setName( featureTypeStyle.getTitle() );
String ftsName = featureTypeStyle.getFeatureTypeName();
for ( int i = 0; i < featureTypeCBox.getItemCount(); i++ ) {
if ( ( (QualifiedName) featureTypeCBox.getItemAt( i ) ).getFormattedString().equals( ftsName ) ) {
featureTypeCBox.setSelectedIndex( i );
}
}
String typeName = null;
if ( featureTypeStyle.getRules() != null && featureTypeStyle.getRules().length > 0 ) {
Rule rule = featureTypeStyle.getRules()[0];
scalePanel.setScaleDenominator( rule.getMinScaleDenominator(), rule.getMaxScaleDenominator() );
if ( rule.getFilter() instanceof ComplexFilter
&& ( (ComplexFilter) rule.getFilter() ).getOperation().getOperatorId() == OperationDefines.PROPERTYISINSTANCEOF ) {
PropertyIsInstanceOfOperation op = (PropertyIsInstanceOfOperation) ( (ComplexFilter) rule.getFilter() ).getOperation();
typeName = op.getTypeName().getLocalName();
} else if ( rule.getFilter() instanceof ComplexFilter
&& ( (ComplexFilter) rule.getFilter() ).getOperation().getOperatorId() == OperationDefines.AND ) {
LogicalOperation lo = (LogicalOperation) ( (ComplexFilter) rule.getFilter() ).getOperation();
for ( Operation op : lo.getArguments() ) {
if ( op.getOperatorId() == OperationDefines.PROPERTYISINSTANCEOF ) {
typeName = ( (PropertyIsInstanceOfOperation) op ).getTypeName().getLocalName();
}
}
}
}
String[] semTypeIds = featureTypeStyle.getSemanticTypeIdentifier();
if ( semTypeIds != null && semTypeIds.length > 0 ) {
if ( typeName == null || "generic:any".equals( semTypeIds[0] ) ) {
rbAll.setSelected( true );
} else if ( "_Curve".equals( typeName ) || "generic:line".equals( semTypeIds[0] ) ) {
rbLines.setSelected( true );
} else if ( "Point".equals( typeName ) || "generic:point".equals( semTypeIds[0] ) ) {
rbPoints.setSelected( true );
} else if ( "_Surface".equals( typeName ) || "generic:polygon".equals( semTypeIds[0] ) ) {
rbPolygons.setSelected( true );
}
}
}
}
/**
* sets the name of the rule and updates the title of the assigned style dialog, when user changed the name of the
* rule
*
* @param ruleName
* the name of the rule
*/
public void setRuleName( String ruleName ) {
this.ruleName = ruleName;
if ( styleDialog != null ) {
styleDialog.updateTitle( ruleName );
}
}
/**
* @return the name of the rule
*/
public String getRuleName() {
return this.ruleName;
}
/**
* @return the FeatureTypeStyle of this RuleDefinitionPanel
*/
public FeatureTypeStyle getFeatureTypeStyle() {
List<Rule> rules = getRules();
double minScaleDenom = scalePanel.getMinScaleDenominator();
double maxScaleDenom = scalePanel.getMaxScaleDenominator();
ComplexFilter geomTypeFilter = getGeomTypeFilter();
Geometry geometry = null;
if ( geomPropertyCBox.getSelectedItem() != null ) {
List<PropertyPathStep> pps = new ArrayList<PropertyPathStep>();
pps.add( PropertyPathFactory.createPropertyPathStep( (QualifiedName) geomPropertyCBox.getSelectedItem() ) );
geometry = new Geometry( new PropertyPath( pps ), null );
}
for ( Rule rule : rules ) {
rule.setMaxScaleDenominator( maxScaleDenom );
rule.setMinScaleDenominator( minScaleDenom );
if ( geomTypeFilter != null ) {
if ( rule.getFilter() != null && rule.getFilter() instanceof ComplexFilter ) {
rule.setFilter( new ComplexFilter( geomTypeFilter, (ComplexFilter) rule.getFilter(),
OperationDefines.AND ) );
} else {
rule.setFilter( geomTypeFilter );
}
}
Symbolizer[] symbolizer = rule.getSymbolizers();
if ( geometry != null ) {
for ( int i = 0; i < symbolizer.length; i++ ) {
symbolizer[i].setMaxScaleDenominator( maxScaleDenom );
symbolizer[i].setMinScaleDenominator( minScaleDenom );
symbolizer[i].setGeometry( geometry );
}
}
}
Rule[] r = rules.toArray( new Rule[rules.size()] );
FeatureTypeStyle fts = StyleFactory.createFeatureTypeStyle( r );
fts.setTitle( ruleName );
if ( featureTypeCBox.getSelectedItem() != null ) {
QualifiedName qn = (QualifiedName) featureTypeCBox.getSelectedItem();
fts.setFeatureTypeName( qn.getFormattedString() );
}
String[] semanticTypeIds = new String[] { getSemanticTypeId() };
fts.setSemanticTypeIdentifier( semanticTypeIds );
return fts;
}
/**
* @return return uom
*/
public String getUom() {
return ruleDialog.getUom();
}
/**
* @return the settings
*/
public Settings getSettings() {
return settings;
}
void closeFrames() {
if ( sldFrame != null ) {
sldFrame.dispose();
}
if ( styleDialog != null ) {
styleDialog.dispose();
}
}
/**
* Sets the layer and updates the components.
*
* @param layer
* the layer
*/
private void setLayer() {
CachedLayer wl = getLayer();
if ( wl != null ) {
scalePanel.setScaleDenominator( wl.getMinScaleDenominator(), wl.getMaxScaleDenominator() );
for ( QualifiedName ft : wl.getFeatureTypes() ) {
featureTypeCBox.addItem( ft );
}
for ( QualifiedName gp : wl.getGeometryProperties().keySet() ) {
geomPropertyCBox.addItem( gp );
}
if ( featureTypeCBox.getItemCount() > 0 ) {
featureTypeCBox.setSelectedIndex( 0 );
}
}
// some elements are unneeded, if datasource is a raster
if ( wl == null || ( wl.isRaster() && !wl.isOther() ) ) {
featureTypeCBox.setEnabled( false );
geomPropertyCBox.setEnabled( false );
rbAll.setEnabled( false );
rbPoints.setEnabled( false );
rbLines.setEnabled( false );
rbPolygons.setEnabled( false );
}
}
private CachedLayer getLayer() {
return LayerCache.getInstance().getCachedLayer( layerId );
}
private void initComponents() {
featureTypeCBox = new JComboBox();
featureTypeCBox.setRenderer( new QualifiedNameRenderer() );
geomPropertyCBox = new JComboBox();
geomPropertyCBox.setRenderer( new QualifiedNameRenderer() );
scalePanel = new ScaleDenominatorPanel();
scalePanel.setBorder( BorderFactory.createTitledBorder( get( "$MD10608" ) ) );
}
private void init() {
FormLayout fl = new FormLayout( "default" );
DefaultFormBuilder builder = new DefaultFormBuilder( fl );
builder.append( getFeatureTypePanel() );
builder.nextLine();
builder.append( getGeomPropertyPanel() );
builder.nextLine();
builder.append( getGeomTypePanel() );
builder.nextLine();
builder.append( scalePanel );
builder.nextLine();
builder.append( getButtonPanel() );
add( builder.getPanel() );
}
private JPanel getButtonPanel() {
JButton openStyleDialogBt = new JButton( get( "$MD10599" ) );
openStyleDialogBt.addActionListener( new ActionListener() {
public void actionPerformed( ActionEvent e ) {
ruleDialog.setStyleChanged();
createStyleDialog();
styleDialog.setVisible( true );
}
} );
JButton showSLDBt = new JButton( get( "$MD10600" ) );
showSLDBt.addActionListener( new ActionListener() {
public void actionPerformed( ActionEvent e ) {
createStyleDialog();
updateSldFrame();
if ( !sldFrame.isVisible() ) {
sldFrame.setVisible( true );
}
}
} );
ButtonBarBuilder bbBuilder = new ButtonBarBuilder();
bbBuilder.addGriddedButtons( new JButton[] { openStyleDialogBt, showSLDBt } );
return bbBuilder.getPanel();
}
private void createSldFrame() {
sldFrame = new SldFrame( ruleName, appContainer );
sldFrame.setLocation( 100, 100 );
sldFrame.setSize( 500, 400 );
}
private void updateSldFrame() {
if ( sldFrame == null ) {
createSldFrame();
}
FeatureTypeStyle fts = getFeatureTypeStyle();
String sld = fts.exportAsXML();
sldFrame.setSld( sld );
sldFrame.repaint();
}
private void createStyleDialog() {
if ( styleDialog == null ) {
Rule[] rules = null;
if ( featureTypeStyle != null ) {
rules = featureTypeStyle.getRules();
}
long startTime = System.currentTimeMillis();
GEOMTYPE geomtype = getLayer().getGeometryType( (QualifiedName) geomPropertyCBox.getSelectedItem() );
styleDialog = new StyleDialog( this, layerId, appContainer );
ruleDialog.informUomChangeListener();
styleDialog.initValues( rules, getSelectedFeatureType(), geomtype );
if ( isShowing() ) {
styleDialog.setLocation( getLocationOnScreen().x, getLocationOnScreen().y );
}
styleDialog.pack();
if ( LOG.isDebug() ) {
long timeNow = System.currentTimeMillis();
LOG.logDebug( "Time needed to initialise StyleDialog for layer with id '"
+ layerId.getAsQualifiedString() + "': " + ( timeNow - startTime ) );
}
}
}
private FeatureType getSelectedFeatureType() {
if ( featureTypeCBox.getSelectedItem() != null ) {
CachedLayer wl = getLayer();
if ( wl != null ) {
return wl.getFeatureType( (QualifiedName) featureTypeCBox.getSelectedItem() );
}
}
return null;
}
private JPanel getFeatureTypePanel() {
FormLayout fl = new FormLayout( "left:min(70dlu;pref):grow(1.0)", "$cpheight" );
DefaultFormBuilder builder = new DefaultFormBuilder( fl );
builder.setBorder( BorderFactory.createTitledBorder( get( "$MD10601" ) ) );
CellConstraints cc = new CellConstraints();
cc.insets = new Insets( 2, 10, 2, 2 );
builder.add( featureTypeCBox, cc.xy( 1, 1 ) );
return builder.getPanel();
}
private JPanel getGeomPropertyPanel() {
FormLayout fl = new FormLayout( "left:min(70dlu;pref):grow(1.0)", "$cpheight" );
DefaultFormBuilder builder = new DefaultFormBuilder( fl );
builder.setBorder( BorderFactory.createTitledBorder( get( "$MD10602" ) ) );
CellConstraints cc = new CellConstraints();
cc.insets = new Insets( 2, 10, 2, 2 );
builder.add( geomPropertyCBox, cc.xy( 1, 1 ) );
return builder.getPanel();
}
private JPanel getGeomTypePanel() {
FormLayout fl = new FormLayout( "left:pref", "$rbheight, $rbheight, $rbheight, $rbheight" );
DefaultFormBuilder builder = new DefaultFormBuilder( fl );
builder.setBorder( BorderFactory.createTitledBorder( get( "$MD10603" ) ) );
CellConstraints cc = new CellConstraints();
cc.insets = new Insets( 2, 10, 2, 2 );
ButtonGroup bg = new ButtonGroup();
geomTypeRBs = new ArrayList<JRadioButton>( 4 );
rbAll = new JRadioButton( get( "$MD10604" ), true );
geomTypeRBs.add( rbAll );
rbPoints = new JRadioButton( get( "$MD10605" ) );
geomTypeRBs.add( rbPoints );
rbLines = new JRadioButton( get( "$MD10606" ) );
geomTypeRBs.add( rbLines );
rbPolygons = new JRadioButton( get( "$MD10607" ) );
geomTypeRBs.add( rbPolygons );
int i = 1;
for ( JRadioButton rb : geomTypeRBs ) {
builder.add( rb, cc.xy( 1, i++ ) );
bg.add( rb );
}
return builder.getPanel();
}
private ComplexFilter getGeomTypeFilter() {
QualifiedName qn = null;
if ( rbLines.isSelected() ) {
qn = new QualifiedName( "_Curve", CommonNamespaces.GMLNS );
} else if ( rbPoints.isSelected() ) {
qn = new QualifiedName( "Point", CommonNamespaces.GMLNS );
} else if ( rbPolygons.isSelected() ) {
qn = new QualifiedName( "_Surface", CommonNamespaces.GMLNS );
}
if ( qn != null && geomPropertyCBox.getSelectedItem() != null ) {
PropertyName pn = new PropertyName( (QualifiedName) geomPropertyCBox.getSelectedItem() );
PropertyIsInstanceOfOperation op = new PropertyIsInstanceOfOperation( pn, qn );
return new ComplexFilter( op );
}
return null;
}
public String getSemanticTypeId() {
String semTypeId = "generic:any";
if ( rbLines.isSelected() ) {
semTypeId = "generic:line";
} else if ( rbPoints.isSelected() ) {
semTypeId = "generic:point";
} else if ( rbPolygons.isSelected() ) {
semTypeId = "generic:polygon";
}
return semTypeId;
}
private List<Rule> getRules() {
createStyleDialog();
return styleDialog.getRules();
}
public int getSelectedFeatureTypeIndex() {
return featureTypeCBox.getSelectedIndex();
}
public int getSelectedGeomPropertyIndex() {
return geomPropertyCBox.getSelectedIndex();
}
public double getMinScale() {
return scalePanel.getMinScaleDenominator();
}
public double getMaxScale() {
return scalePanel.getMaxScaleDenominator();
}
public void setSettings( int selectedFeatureTypeIndex, int selectedGeomPropertyIndex, double minScale,
double maxScale, String semanticTypeId ) {
featureTypeCBox.setSelectedIndex( selectedFeatureTypeIndex );
geomPropertyCBox.setSelectedIndex( selectedGeomPropertyIndex );
scalePanel.setScaleDenominator( minScale, maxScale );
if ( "generic:any".equals( semanticTypeId ) ) {
rbAll.setSelected( true );
} else if ( "generic:line".equals( semanticTypeId ) ) {
rbLines.setSelected( true );
} else if ( "generic:point".equals( semanticTypeId ) ) {
rbPoints.setSelected( true );
} else if ( "generic:polygon".equals( semanticTypeId ) ) {
rbPolygons.setSelected( true );
}
}
/**
* Register a listener to be informed when the global setting for uom changed.
*
* @param listener
* listener to add
*/
public void addUomChangedListener( ChangeListener listener ) {
ruleDialog.addUomChangedListener( listener );
}
}