/*---------------- 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.addlayer; import static org.deegree.igeo.i18n.Messages.get; import static org.deegree.igeo.views.swing.util.GuiUtils.addToFrontListener; import java.awt.Color; import java.awt.Container; import java.awt.Dimension; import java.awt.GridBagConstraints; import java.awt.Insets; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.FocusEvent; import java.awt.event.FocusListener; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import javax.swing.BorderFactory; import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JComboBox; import javax.swing.JComponent; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.ScrollPaneConstants; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import org.deegree.datatypes.QualifiedName; import org.deegree.datatypes.values.TypedLiteral; import org.deegree.framework.log.ILogger; import org.deegree.framework.log.LoggerFactory; import org.deegree.framework.util.ImageUtils; import org.deegree.framework.utils.SwingUtils; import org.deegree.igeo.ApplicationContainer; import org.deegree.igeo.commands.model.AddWMSLayerCommand; import org.deegree.igeo.dataadapter.Adapter; import org.deegree.igeo.mapmodel.MapModel; import org.deegree.igeo.views.DialogFactory; import org.deegree.ogcwebservices.wms.capabilities.Layer; import org.deegree.ogcwebservices.wms.capabilities.LegendURL; import org.deegree.ogcwebservices.wms.capabilities.Style; import org.deegree.ogcwebservices.wms.capabilities.WMSCapabilities; import org.deegree.owscommon_new.DCP; import org.deegree.owscommon_new.DomainType; import org.deegree.owscommon_new.HTTP; import org.deegree.owscommon_new.Operation; import org.deegree.owscommon_new.OperationsMetadata; /** * <code>JAddWMSWizardChooseStyles</code> * * @author <a href="mailto:buesching@lat-lon.de">Lyn Buesching</a> * @author last edited by: $Author$ * * @version $Revision$, $Date$ * */ public class AddWMSWizardChooseStyles extends WizardDialog implements ActionListener, FocusListener, MouseListener, ChangeListener { private static final long serialVersionUID = -2799571066510285487L; private static final ILogger LOG = LoggerFactory.getLogger( AddWMSWizardChooseStyles.class ); private MapModel mapModel; private WMSCapabilities wmsCaps; private Map<Layer, String> selectedLayers; private JLabel previewImage = new JLabel(); private JCheckBox preview = new JCheckBox(); private JComboBox lastSelected = null; private String layerTitle; private boolean allowSwapAxis; /** * @param frame * the dialog which was visible before * @param mapModel * the map model to add the new layer * @param appContainer * the application container * @param wmsCapabilities * the capablilties of the service to add as wms-datasource * @param selectedLayers * the wms-layers selected to add * @param layerTitle * the title of the layer * @param capabilitiesURL * the capabilities url of the service to add as wms-datasource * @param allowSwapAxsisOrder * if <code>true</code> axis order of bounding box will be swapped if a WMS 1.3 GetMap request shall be * created */ public AddWMSWizardChooseStyles( JFrame frame, MapModel mapModel, ApplicationContainer<Container> appContainer, WMSCapabilities wmsCapabilities, List<Layer> selectedLayers, String layerTitle, boolean allowSwapAxis ) { super( frame ); this.mapModel = mapModel; this.appContainer = appContainer; this.wmsCaps = wmsCapabilities; this.layerTitle = layerTitle; this.allowSwapAxis = allowSwapAxis; this.setSize( 750, 600 ); this.setResizable( false ); // initialise a new assoziated array containing all selected layers and assigned styles this.selectedLayers = new LinkedHashMap<Layer, String>( selectedLayers.size() ); for ( Layer layer : selectedLayers ) { this.selectedLayers.put( layer, "" ); } this.setTitle( get( "$MD10055" ) ); infoPanel.setInfoText( get( "$MD10056" ) ); buttonPanel.registerActionListener( this ); super.init(); } /** * update the entry in the map containing the map with assigned styles and show preview of the style * * @param srcComboBox * the comboBox whose style selection changed */ private void setSelected( JComboBox srcComboBox ) { String styleName = (String) srcComboBox.getSelectedItem(); Container p = srcComboBox.getParent(); String layerName = null; for ( int i = 0; i < p.getComponentCount(); i++ ) { p.setBackground( Color.LIGHT_GRAY ); if ( p.getComponent( i ) instanceof JLabel ) { layerName = ( (JLabel) p.getComponent( i ) ).getName(); } } Layer selectedLayer = wmsCaps.getLayer( layerName ); if ( styleName.equals( "default" ) ) { this.selectedLayers.put( selectedLayer, "" ); } else { this.selectedLayers.put( selectedLayer, styleName ); } if ( this.preview.isSelected() ) { showStyle( selectedLayer, styleName ); } else { this.previewImage.setIcon( null ); } } /** * update preview of the styles assigned to the selected style of the layer * * @param selectedLayer * the selected layer * @param styleName * the selected style */ private void showStyle( Layer selectedLayer, String styleName ) { Style style = selectedLayer.getStyleResource( styleName ); ImageIcon ii = null; // get legend out of the legendurl of the style if ( style != null ) { LegendURL[] legendURLs = style.getLegendURL(); ii = getLegendImage( legendURLs[0].getOnlineResource() ); } if ( ii == null ) { // request legend from the wms, if the layer does not define a style ii = getLegendFromWMS( selectedLayer.getName(), styleName ); if ( ii == null ) { // if no legend is available show missing legend image URL missingLegendURL = Adapter.class.getResource( "missingLegend.png" ); try { LOG.logDebug( "No legend available, show missing legend image" ); ii = new ImageIcon( ImageUtils.loadImage( missingLegendURL.openStream() ) ); } catch ( IOException e ) { LOG.logError( get( "$DG10062", missingLegendURL, e.getMessage() ) ); DialogFactory.openErrorDialog( appContainer.getViewPlatform(), this, e.getMessage(), getClass().getSimpleName(), e ); this.dispose(); } } } if ( ii != null ) { this.previewImage.setIcon( ii ); } } /** * @param layer * the layer name * @param style * the style name * @param format * the format * @param version * the version * @param url * the wms url * @return the GetLegendRequest as string */ private String createGetLegendRequest( String layer, String style, String format, String version, String url ) { StringBuffer sb = new StringBuffer( 500 ); sb.append( url ).append( '?' ); sb.append( "&VERSION=" ).append( version ); sb.append( "&REQUEST=GetLegendGraphic" ); sb.append( "&FORMAT=" ).append( format ); sb.append( "&WIDTH=15&HEIGHT=15&EXCEPTIONS=application/vnd.ogc.se_inimage" ); sb.append( "&LAYER=" ).append( layer ); sb.append( "&STYLE=" ).append( style ); return sb.toString(); } /** * @param url * the url to load the image * @return theIimageIcon of the url; returns null, if an exception is thrown */ private ImageIcon getLegendImage( URL url ) { try { LOG.logDebug( "Try to get legend from URL: " + url.toExternalForm() ); ImageIcon ii = new ImageIcon( ImageUtils.loadImage( url.openStream() ) ); return ii; } catch ( Exception e ) { LOG.logError( get( "$DG10038", url, e.getMessage() ) ); return null; } } /** * @param layer * the name of the layer * @param styleName * the name of the style * @return the legend out of a wms GetLegendRequest */ private ImageIcon getLegendFromWMS( String layer, String styleName ) { OperationsMetadata om = wmsCaps.getOperationMetadata(); Operation op = om.getOperation( new QualifiedName( "GetLegendGraphic" ) ); if ( op != null ) { URL legendGraphicURL = null; List<DCP> dcps = op.getDCP(); for ( DCP dcp : dcps ) { if ( dcp instanceof HTTP ) { List<URL> getOnlineResources = ( (HTTP) dcp ).getGetOnlineResources(); legendGraphicURL = getOnlineResources.get( 0 ); } } if ( legendGraphicURL != null ) { DomainType parameter = (DomainType) op.getParameter( new QualifiedName( "Format" ) ); List<TypedLiteral> values = parameter.getValues(); String format = values.get( 0 ).getValue(); String s = createGetLegendRequest( layer, styleName, format, wmsCaps.getVersion(), legendGraphicURL.toString() ); URL legendFromWMS = null; try { LOG.logDebug( "Try to get legend from WMS: " + s ); legendFromWMS = new URL( s ); } catch ( MalformedURLException e ) { LOG.logError( get( "$DG10049" ) ); return null; } try { return new ImageIcon( ImageUtils.loadImage( legendFromWMS ) ); } catch ( IOException e ) { LOG.logError( get( "$DG10049" ) ); } } } return null; } /** * @param layer * the layer to display informations on the panel * @return a panel containing the title of the layer and assigned styƶles in a combo box */ private JPanel getLayerStylePanel( Layer layer ) { JPanel layerStylePanel = new JPanel(); layerStylePanel.setLayout( null ); layerStylePanel.setVisible( true ); layerStylePanel.setSize( new Dimension( 500, 26 ) ); layerStylePanel.setBackground( Color.WHITE ); JLabel layerTitle = new JLabel( layer.getTitle() ); layerTitle.setBounds( 2, 0, 248, 26 ); layerTitle.setToolTipText( layer.getAbstract() ); layerTitle.setName( layer.getName() ); layerTitle.addMouseListener( this ); JComboBox styleComboBox = new JComboBox(); styleComboBox.setBounds( 250, 0, 150, 26 ); styleComboBox.addItem( "default" ); Style[] styles = layer.getStyles(); for ( int i = 0; i < styles.length; i++ ) { if ( !styles[i].getName().equals( "default" ) ) { styleComboBox.addItem( styles[i].getName() ); } } layerStylePanel.add( layerTitle ); layerStylePanel.add( styleComboBox ); styleComboBox.addActionListener( this ); styleComboBox.addFocusListener( this ); return layerStylePanel; } // ///////////////////////////////////////////////////////////////////////////////// // WizardDialog // ////////////////////////////////////////////////////////////////////////////// /* * (non-Javadoc) * * @see org.deegree.igeo.views.swing.WizardDialog#getMainPanel() */ @Override public JPanel getMainPanel() { JPanel stylePanel = new JPanel(); GridBagConstraints gbc = SwingUtils.initPanel( stylePanel ); JPanel layerStylesPanel = new JPanel(); int entryHeight = 30; layerStylesPanel.setBackground( Color.WHITE ); Dimension lsDim = new Dimension( 400, ( entryHeight * selectedLayers.size() ) + 2 ); layerStylesPanel.setSize( lsDim ); layerStylesPanel.setPreferredSize( lsDim ); layerStylesPanel.setMinimumSize( lsDim ); layerStylesPanel.setMaximumSize( lsDim ); Dimension scrollDim = new Dimension( 420, 320 ); JScrollPane layerStylesScroll = new JScrollPane( layerStylesPanel ); layerStylesScroll.setSize( scrollDim ); layerStylesScroll.setPreferredSize( scrollDim ); layerStylesScroll.setMinimumSize( scrollDim ); layerStylesScroll.setMaximumSize( scrollDim ); layerStylesScroll.setVerticalScrollBarPolicy( ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED ); layerStylesScroll.setHorizontalScrollBarPolicy( ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED ); // add selected layers with styles to the scrollPane int y = 2; layerStylesPanel.setLayout( null ); for ( Layer layer : this.selectedLayers.keySet() ) { JPanel layerStylesEntry = getLayerStylePanel( layer ); layerStylesEntry.setBorder( BorderFactory.createEmptyBorder( 2, 2, 2, 2 ) ); layerStylesEntry.setLocation( 0, y ); layerStylesPanel.add( layerStylesEntry ); y = y + entryHeight; } // area to show styles JPanel p = new JPanel(); GridBagConstraints pgbc = SwingUtils.initPanel( p ); p.add( this.previewImage, pgbc ); Dimension previewDim = new Dimension( 200, 320 ); JScrollPane previewScroll = new JScrollPane( p ); previewScroll.setSize( previewDim ); previewScroll.setPreferredSize( previewDim ); previewScroll.setMinimumSize( previewDim ); previewScroll.setMaximumSize( previewDim ); previewScroll.setHorizontalScrollBarPolicy( ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED ); previewScroll.setVerticalScrollBarPolicy( ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED ); this.preview.setText( get( "$MD10101" ) ); this.preview.setSelected( false ); this.preview.addChangeListener( this ); gbc.anchor = GridBagConstraints.LINE_START; stylePanel.add( new JLabel( get( "$MD10057" ) ), gbc ); ++gbc.gridx; gbc.insets = new Insets( 2, 20, 2, 2 ); stylePanel.add( this.preview, gbc ); gbc.insets = new Insets( 2, 2, 2, 2 ); gbc.gridx = 0; ++gbc.gridy; stylePanel.add( layerStylesScroll, gbc ); ++gbc.gridx; gbc.insets = new Insets( 2, 20, 2, 2 ); stylePanel.add( previewScroll, gbc ); return stylePanel; } // ///////////////////////////////////////////////////////////////////////////////// // ActionListener // ///////////////////////////////////////////////////////////////////////////////// /* * (non-Javadoc) * * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent) */ public void actionPerformed( ActionEvent event ) { if ( event.getSource() instanceof JButton ) { JButton srcButton = (JButton) event.getSource(); if ( srcButton.getName().equals( ButtonPanel.CANCEL_BT ) ) { // close this and the previous frame this.dispose(); } else if ( srcButton.getName().equals( ButtonPanel.PREVIOUS_BT ) ) { // set the previousframe visible and close this frame if ( this.previousFrame != null ) { this.previousFrame.setVisible( true ); } this.close(); } else if ( srcButton.getName().equals( ButtonPanel.NEXT_BT ) ) { AddWMSWizardChooseFormat nextStep = new AddWMSWizardChooseFormat( this, this.mapModel, this.appContainer, this.wmsCaps, this.selectedLayers, this.layerTitle, allowSwapAxis ); addToFrontListener( nextStep ); nextStep.setLocation( this.getX(), this.getY() ); nextStep.setVisible( true ); this.setVisible( false ); } else if ( srcButton.getName().equals( ButtonPanel.FINISH_BT ) ) { AddWMSLayerCommand addWMSCmd = new AddWMSLayerCommand( this.mapModel, this.wmsCaps, this.selectedLayers, this.layerTitle, allowSwapAxis ); appContainer.getCommandProcessor().executeASychronously( addWMSCmd ); this.dispose(); } } else if ( event.getSource() instanceof JComboBox ) { JComboBox srcComboBox = (JComboBox) event.getSource(); setSelected( srcComboBox ); } } // ///////////////////////////////////////////////////////////////////////////////// // FocusListener // ////////////////////////////////////////////////////////////////////////////// /* * (non-Javadoc) * * @see java.awt.event.FocusListener#focusGained(java.awt.event.FocusEvent) */ public void focusGained( FocusEvent event ) { // select the line of the combobox JComboBox srcComboBox = (JComboBox) event.getSource(); // deselect all other entries Container c = srcComboBox.getParent().getParent(); for ( int i = 0; i < c.getComponentCount(); i++ ) { c.getComponent( i ).setBackground( Color.WHITE ); } // and select the current setSelected( srcComboBox ); lastSelected = srcComboBox; } /* * (non-Javadoc) * * @see java.awt.event.FocusListener#focusLost(java.awt.event.FocusEvent) */ public void focusLost( FocusEvent event ) { } // ///////////////////////////////////////////////////////////////////////////////// // MouseListener // ////////////////////////////////////////////////////////////////////////////// /* * (non-Javadoc) * * @see java.awt.event.MouseListener#mouseClicked(java.awt.event.MouseEvent) */ public void mouseClicked( MouseEvent event ) { // set focus to style combo box of the selected layer JComponent srcComponent = (JComponent) event.getSource(); Container p = srcComponent.getParent(); if ( srcComponent instanceof JLabel ) { for ( int i = 0; i < p.getComponentCount(); i++ ) { if ( p.getComponent( i ) instanceof JComboBox ) { p.getComponent( i ).requestFocus(); } } } } /* * (non-Javadoc) * * @see java.awt.event.MouseListener#mouseEntered(java.awt.event.MouseEvent) */ public void mouseEntered( MouseEvent event ) { } /* * (non-Javadoc) * * @see java.awt.event.MouseListener#mouseExited(java.awt.event.MouseEvent) */ public void mouseExited( MouseEvent event ) { } /* * (non-Javadoc) * * @see java.awt.event.MouseListener#mousePressed(java.awt.event.MouseEvent) */ public void mousePressed( MouseEvent event ) { } /* * (non-Javadoc) * * @see java.awt.event.MouseListener#mouseReleased(java.awt.event.MouseEvent) */ public void mouseReleased( MouseEvent event ) { } // ///////////////////////////////////////////////////////////////////////////////// // ChangeListener // ////////////////////////////////////////////////////////////////////////////// /* * (non-Javadoc) * * @see javax.swing.event.ChangeListener#stateChanged(javax.swing.event.ChangeEvent) */ public void stateChanged( ChangeEvent event ) { // set focus to last selected layer/style if user changed status of preview if ( lastSelected != null ) { lastSelected.requestFocus(); } } }