/*---------------- 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 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.net.URL; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Locale; import java.util.Map; import javax.swing.BorderFactory; import javax.swing.Icon; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTree; import javax.swing.ScrollPaneConstants; import javax.swing.ToolTipManager; import javax.swing.event.TreeModelEvent; import javax.swing.event.TreeModelListener; import javax.swing.event.TreeSelectionEvent; import javax.swing.event.TreeSelectionListener; import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.DefaultTreeModel; import javax.swing.tree.TreePath; import org.deegree.framework.utils.SwingUtils; import org.deegree.igeo.ApplicationContainer; import org.deegree.igeo.commands.model.AddWCSLayerCommand; import org.deegree.igeo.i18n.Messages; import org.deegree.igeo.mapmodel.MapModel; import org.deegree.igeo.views.swing.util.GuiUtils; import org.deegree.igeo.views.swing.util.IconRegistry; import org.deegree.ogcwebservices.wcs.CoverageOfferingBrief; import org.deegree.ogcwebservices.wcs.getcapabilities.WCSCapabilities; import org.deegree.ogcwebservices.wms.capabilities.Layer; /** * The <code>JAddWCSChooseLayerFrame</code> describes the second step to add a WCS datasource as layer. It contains the * possibility to choose the desired layers of a WCS.<br> * At the moment just selection of one coverage is possible, but this will be changed in future versions of this class * * @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a> * @author last edited by: $Author$ * * @version $Revision$, $Date$ * */ public class AddWCSWizardChooseCoverage extends WizardDialog implements TreeSelectionListener, ActionListener, TreeModelListener { private static final long serialVersionUID = 8507723159013643420L; private static final String SEL_ALL_BT = "selectAll"; private static final String SEL_SELECTED_BT = "selectSelected"; private static final String DESEL_ALL_BT = "deselectAll"; private static final String DESEL_SELECTED_BT = "deselectSelected"; private static final String UP_BT = "layerUp"; private static final String DOWN_BT = "layerDown"; private MapModel mapModel; private WCSCapabilities wcsCaps; private URL capabilitiesURL; private JTree trAvailableCoverages; private DefaultMutableTreeNode availableCoveragesRoot; private JTree trSelectedCoverages; private DefaultTreeModel selectedCoveragesModel; private DefaultMutableTreeNode selectedCoveragesRoot; private JButton btSelectSelected; private JButton btDeselectSelected; private JButton btDeselectAll; private JButton btCoverageUp; private JButton btCoverageDown; private JButton btSelectAll; private Map<CoverageOfferingBrief, Object[]> selectedNodes = new HashMap<CoverageOfferingBrief, Object[]>(); /** * @param frame * the previous dialog * @param appContainer * the application container * @param mapModel * the mapModel * @param wcsCapabilities * the capabilities of the requested WCS * @param capabilitiesURL */ public AddWCSWizardChooseCoverage( JFrame frame, MapModel mapModel, ApplicationContainer<Container> appContainer, WCSCapabilities wcsCapabilities, URL capabilitiesURL ) { super( frame ); this.mapModel = mapModel; this.appContainer = appContainer; this.wcsCaps = wcsCapabilities; this.capabilitiesURL = capabilitiesURL; this.setSize( 750, 600 ); this.setResizable( false ); this.setTitle( Messages.getMessage( Locale.getDefault(), "$MD11377" ) ); String wcsTitle = wcsCapabilities.getService().getLabel(); this.infoPanel.setInfoText( Messages.getMessage( Locale.getDefault(), "$MD11378", wcsTitle ) ); this.buttonPanel.registerActionListener( this ); this.buttonPanel.setButtonEnabled( ButtonPanel.NEXT_BT, false ); this.buttonPanel.setButtonEnabled( ButtonPanel.FINISH_BT, false ); super.init(); } // ///////////////////////////////////////////////////////////////////////////////// // WizardDialog // ///////////////////////////////////////////////////////////////////////////////// /* * (non-Javadoc) * * @see org.deegree.igeo.views.swing.WizardDialog#getMainPanel() */ @Override public JPanel getMainPanel() { CoverageOfferingBrief[] coverageOfferings = wcsCaps.getContentMetadata().getCoverageOfferingBrief(); // size of the two tree components Dimension treeDim = new Dimension( 300, 350 ); // tree, containing all available layers described in the wcs capabilities availableCoveragesRoot = createTreeNode( coverageOfferings ); trAvailableCoverages = new JTree( availableCoveragesRoot ); trAvailableCoverages.setBorder( BorderFactory.createEmptyBorder( 5, 5, 5, 5 ) ); trAvailableCoverages.addTreeSelectionListener( this ); trAvailableCoverages.setCellRenderer( new WCSCoverageRenderer() ); JScrollPane availableLayersScroll = new JScrollPane( trAvailableCoverages ); availableLayersScroll.setPreferredSize( treeDim ); availableLayersScroll.setHorizontalScrollBarPolicy( ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED ); availableLayersScroll.setVerticalScrollBarPolicy( ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED ); // the buttons to select/deselect layers Dimension selectBtDim = new Dimension( 55, 25 ); btSelectSelected = new JButton( IconRegistry.getIcon( "for_green.png" ) ); btSelectSelected.setName( SEL_SELECTED_BT ); btSelectSelected.addActionListener( this ); btSelectSelected.setEnabled( false ); btSelectSelected.setPreferredSize( selectBtDim ); btSelectAll = new JButton( IconRegistry.getIcon( "forward_green.png" ) ); btSelectAll.setName( SEL_ALL_BT ); btSelectAll.addActionListener( this ); btSelectAll.setPreferredSize( selectBtDim ); // TODO btSelectAll.setVisible( false ); btDeselectAll = new JButton( IconRegistry.getIcon( "backward_green.png" ) ); btDeselectAll.setName( DESEL_ALL_BT ); btDeselectAll.addActionListener( this ); btDeselectAll.setEnabled( false ); btDeselectAll.setPreferredSize( selectBtDim ); // TODO btDeselectAll.setVisible( false ); btDeselectSelected = new JButton( IconRegistry.getIcon( "back_green.png" ) ); btDeselectSelected.setName( DESEL_SELECTED_BT ); btDeselectSelected.addActionListener( this ); btDeselectSelected.setEnabled( false ); btDeselectSelected.setPreferredSize( selectBtDim ); // add select/deselect buttons to a panel JPanel selectBtPanel = new JPanel(); GridBagConstraints gbcBt = SwingUtils.initPanel( selectBtPanel ); selectBtPanel.add( btSelectSelected, gbcBt ); ++gbcBt.gridy; selectBtPanel.add( btSelectAll, gbcBt ); gbcBt.insets = new Insets( 10, 2, 2, 2 ); ++gbcBt.gridy; selectBtPanel.add( btDeselectAll, gbcBt ); gbcBt.insets = new Insets( 2, 2, 2, 2 ); ++gbcBt.gridy; selectBtPanel.add( btDeselectSelected, gbcBt ); // tree which contains all layers selected by the user selectedCoveragesRoot = new DefaultMutableTreeNode(); selectedCoveragesModel = new DefaultTreeModel( selectedCoveragesRoot ); selectedCoveragesModel.addTreeModelListener( this ); trSelectedCoverages = new JTree( selectedCoveragesModel ); trSelectedCoverages.setRootVisible( false ); trSelectedCoverages.setBorder( BorderFactory.createEmptyBorder( 5, 5, 5, 5 ) ); trSelectedCoverages.addTreeSelectionListener( this ); trSelectedCoverages.setCellRenderer( new WCSCoverageRenderer() ); trSelectedCoverages.setVisible( true ); JScrollPane selectedLayersScroll = new JScrollPane( trSelectedCoverages ); selectedLayersScroll.setPreferredSize( treeDim ); selectedLayersScroll.setHorizontalScrollBarPolicy( ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED ); selectedLayersScroll.setVerticalScrollBarPolicy( ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED ); // the buttons to change the order of the layers Dimension orderBtDim = new Dimension( 30, 50 ); Icon iconUp = IconRegistry.getIcon( "arrow_up.png" ); btCoverageUp = new JButton( iconUp ); btCoverageUp.setName( UP_BT ); btCoverageUp.setPreferredSize( orderBtDim ); btCoverageUp.addActionListener( this ); btCoverageUp.setEnabled( false ); // TODO btCoverageUp.setVisible( false ); Icon iconDown = IconRegistry.getIcon( "arrow_down.png" ); btCoverageDown = new JButton( iconDown ); btCoverageDown.setName( DOWN_BT ); btCoverageDown.setPreferredSize( orderBtDim ); btCoverageDown.addActionListener( this ); btCoverageDown.setEnabled( false ); // TODO btCoverageDown.setVisible( false ); // add buttons to change the order of the layers JPanel orderBtPanel = new JPanel(); GridBagConstraints gbcOrderBt = SwingUtils.initPanel( orderBtPanel ); orderBtPanel.add( btCoverageUp, gbcOrderBt ); ++gbcOrderBt.gridy; orderBtPanel.add( btCoverageDown, gbcOrderBt ); // add components of this dialog to the panel JPanel pnCoverageList = new JPanel(); GridBagConstraints gbc = SwingUtils.initPanel( pnCoverageList ); pnCoverageList.add( new JLabel( Messages.getMessage( Locale.getDefault(), "$MD11379" ) ), gbc ); gbc.gridx = gbc.gridx + 2; pnCoverageList.add( new JLabel( Messages.getMessage( Locale.getDefault(), "$MD11380" ) ), gbc ); ++gbc.gridy; gbc.gridx = 0; gbc.fill = GridBagConstraints.BOTH; gbc.weightx = 0.5; pnCoverageList.add( availableLayersScroll, gbc ); ++gbc.gridx; gbc.fill = GridBagConstraints.NONE; gbc.weightx = 0; pnCoverageList.add( selectBtPanel, gbc ); gbc.fill = GridBagConstraints.BOTH; gbc.weightx = 0.5; ++gbc.gridx; pnCoverageList.add( selectedLayersScroll, gbc ); gbc.fill = GridBagConstraints.NONE; gbc.weightx = 0; ++gbc.gridx; pnCoverageList.add( orderBtPanel, gbc ); pnCoverageList.setVisible( true ); ToolTipManager.sharedInstance().registerComponent( trAvailableCoverages ); ToolTipManager.sharedInstance().registerComponent( trSelectedCoverages ); return pnCoverageList; } /** * @param rootLayer * the wms layer to create a node */ private DefaultMutableTreeNode createTreeNode( CoverageOfferingBrief[] coverageOfferings ) { DefaultMutableTreeNode node = new DefaultMutableTreeNode( "root" ); for ( int i = 0; i < coverageOfferings.length; i++ ) { node.add( new DefaultMutableTreeNode( coverageOfferings[i] ) ); } return node; } // ///////////////////////////////////////////////////////////////////////////////// // 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 ) ) { this.dispose(); } else if ( srcButton.getName().equals( ButtonPanel.PREVIOUS_BT ) ) { if ( this.previousFrame != null ) { this.previousFrame.setVisible( true ); } this.close(); } else if ( srcButton.getName().equals( ButtonPanel.NEXT_BT ) ) { AddWCSWizardChooseFormat nextStep = new AddWCSWizardChooseFormat( this, this.mapModel, this.appContainer, this.wcsCaps, getSelectedCoverages(), capabilitiesURL ); GuiUtils.addToFrontListener( nextStep ); nextStep.setLocation( this.getX(), this.getY() ); nextStep.setVisible( true ); this.setVisible( false ); } else if ( srcButton.getName().equals( ButtonPanel.FINISH_BT ) ) { List<CoverageOfferingBrief> coverages = getSelectedCoverages(); for ( CoverageOfferingBrief coverage : coverages ) { AddWCSLayerCommand addWCSCmd = new AddWCSLayerCommand( this.mapModel, this.capabilitiesURL, this.wcsCaps, coverage ); appContainer.getCommandProcessor().executeASychronously( addWCSCmd ); } this.dispose(); } else if ( srcButton.getName().equals( SEL_SELECTED_BT ) ) { TreePath[] cos = this.trAvailableCoverages.getSelectionPaths(); for ( int i = 0; i < cos.length; i++ ) { if ( cos[i].getLastPathComponent() instanceof DefaultMutableTreeNode ) { DefaultMutableTreeNode selectedNode = (DefaultMutableTreeNode) cos[i].getLastPathComponent(); CoverageOfferingBrief coverageOffering = (CoverageOfferingBrief) selectedNode.getUserObject(); appendLayerToRoot( coverageOffering, this.selectedCoveragesModel ); this.selectedNodes.put( coverageOffering, cos[i].getPath() ); } } btSelectSelected.setEnabled( false ); btDeselectSelected.setEnabled( true ); // make changes visible! this.trSelectedCoverages.setRootVisible( true ); this.trSelectedCoverages.expandRow( 0 ); this.trSelectedCoverages.setRootVisible( false ); } else if ( srcButton.getName().equals( SEL_ALL_BT ) ) { appendChilds( this.availableCoveragesRoot, this.selectedCoveragesModel ); // make changes visible! this.trSelectedCoverages.setRootVisible( true ); this.trSelectedCoverages.expandRow( 0 ); this.trSelectedCoverages.setRootVisible( false ); } else if ( srcButton.getName().equals( DESEL_ALL_BT ) ) { int childCount = this.selectedCoveragesRoot.getChildCount(); for ( int i = 0; i < childCount; i++ ) { DefaultMutableTreeNode child = (DefaultMutableTreeNode) this.selectedCoveragesRoot.getChildAt( 0 ); this.selectedCoveragesModel.removeNodeFromParent( child ); } this.selectedNodes.clear(); } else if ( srcButton.getName().equals( DESEL_SELECTED_BT ) ) { TreePath[] layers = this.trSelectedCoverages.getSelectionPaths(); for ( int i = 0; i < layers.length; i++ ) { if ( layers[i].getLastPathComponent() instanceof DefaultMutableTreeNode ) { DefaultMutableTreeNode selectedNode = (DefaultMutableTreeNode) layers[i].getLastPathComponent(); this.selectedCoveragesModel.removeNodeFromParent( selectedNode ); if ( selectedNode.getUserObject() instanceof Layer ) { this.selectedNodes.remove( selectedNode.getUserObject() ); } } } btDeselectSelected.setEnabled( false ); btSelectSelected.setEnabled( true ); } else if ( srcButton.getName().equals( UP_BT ) ) { moveLayerUp(); } else if ( srcButton.getName().equals( DOWN_BT ) ) { moveLayerDown(); } } } /** * @return the coverages selected by the user */ private List<CoverageOfferingBrief> getSelectedCoverages() { List<CoverageOfferingBrief> coverages = new ArrayList<CoverageOfferingBrief>( this.selectedCoveragesRoot.getChildCount() ); for ( int i = 0; i < this.selectedCoveragesRoot.getChildCount(); i++ ) { DefaultMutableTreeNode child = (DefaultMutableTreeNode) this.selectedCoveragesRoot.getChildAt( i ); if ( child.getUserObject() instanceof CoverageOfferingBrief ) { coverages.add( (CoverageOfferingBrief) child.getUserObject() ); } } return coverages; } /** * append all child nodes of the source node to the model * * @param sourceNode * node to add * @param model * the model to add the node */ private void appendChilds( DefaultMutableTreeNode sourceNode, DefaultTreeModel model ) { for ( int i = 0; i < sourceNode.getChildCount(); i++ ) { DefaultMutableTreeNode child = (DefaultMutableTreeNode) sourceNode.getChildAt( i ); if ( child.isLeaf() ) { if ( child.getUserObject() instanceof Layer ) { CoverageOfferingBrief coverageOffering = (CoverageOfferingBrief) child.getUserObject(); appendLayerToRoot( coverageOffering, model ); this.selectedNodes.put( coverageOffering, child.getPath() ); } } else { appendChilds( child, model ); } } } /** * append the layer as node to the model * * @param coverageOffering * the layer to append as node * @param model * the model to add the node */ private void appendLayerToRoot( CoverageOfferingBrief coverageOffering, DefaultTreeModel model ) { DefaultMutableTreeNode targetNode = (DefaultMutableTreeNode) model.getRoot(); if ( coverageOffering.getName() != null && coverageOffering.getName().length() > 0 ) { boolean isSelected = false; for ( int i = 0; i < targetNode.getChildCount(); i++ ) { DefaultMutableTreeNode child = (DefaultMutableTreeNode) targetNode.getChildAt( i ); if ( child.getUserObject() instanceof Layer ) { Layer childLayer = (Layer) child.getUserObject(); if ( childLayer.getName().equals( coverageOffering.getName() ) || childLayer.getTitle().equals( coverageOffering.getLabel() ) ) isSelected = true; } } if ( !isSelected ) { model.insertNodeInto( new DefaultMutableTreeNode( coverageOffering ), targetNode, targetNode.getChildCount() ); } } } /** * move selected layer one entry up */ private void moveLayerUp() { TreePath selLayer = this.trSelectedCoverages.getSelectionPath(); int row = this.trSelectedCoverages.getSelectionRows()[0]; DefaultMutableTreeNode node = (DefaultMutableTreeNode) selLayer.getLastPathComponent(); if ( row > 0 ) { DefaultMutableTreeNode root = (DefaultMutableTreeNode) node.getRoot(); DefaultMutableTreeNode newNode = new DefaultMutableTreeNode( node.getUserObject() ); this.selectedCoveragesModel.insertNodeInto( newNode, root, row - 1 ); TreePath tp = this.trSelectedCoverages.getPathForRow( row - 1 ); this.trSelectedCoverages.setSelectionPath( tp ); this.selectedCoveragesModel.removeNodeFromParent( node ); } } /** * move selected layer one entry down */ private void moveLayerDown() { TreePath selLayer = this.trSelectedCoverages.getSelectionPath(); int row = this.trSelectedCoverages.getSelectionRows()[0]; DefaultMutableTreeNode node = (DefaultMutableTreeNode) selLayer.getLastPathComponent(); DefaultMutableTreeNode root = (DefaultMutableTreeNode) node.getRoot(); if ( row < root.getChildCount() - 1 ) { DefaultMutableTreeNode newNode = new DefaultMutableTreeNode( node.getUserObject() ); this.selectedCoveragesModel.insertNodeInto( newNode, root, row + 2 ); TreePath tp = this.trSelectedCoverages.getPathForRow( row + 2 ); this.trSelectedCoverages.setSelectionPath( tp ); this.selectedCoveragesModel.removeNodeFromParent( node ); } } // ///////////////////////////////////////////////////////////////////////////////// // TreeSelectionListener // ///////////////////////////////////////////////////////////////////////////////// /* * (non-Javadoc) * * @see javax.swing.event.TreeSelectionListener#valueChanged(javax.swing.event.TreeSelectionEvent) */ public void valueChanged( TreeSelectionEvent event ) { // enable/disable select-button if ( this.trAvailableCoverages.getSelectionCount() > 0 && this.trSelectedCoverages.getSelectionCount() == 0 ) { this.btSelectSelected.setEnabled( true ); } else { this.btSelectSelected.setEnabled( false ); } // enable/disable deselect-button if ( this.trSelectedCoverages.getSelectionCount() > 0 ) { this.btDeselectSelected.setEnabled( true ); if ( this.trSelectedCoverages.getSelectionCount() == 1 ) { this.btCoverageUp.setEnabled( true ); this.btCoverageDown.setEnabled( true ); } else { this.btCoverageUp.setEnabled( false ); this.btCoverageDown.setEnabled( false ); } } else { this.btDeselectSelected.setEnabled( false ); this.btCoverageUp.setEnabled( false ); this.btCoverageDown.setEnabled( false ); } } // ///////////////////////////////////////////////////////////////////////////////// // TreeModelListener // ///////////////////////////////////////////////////////////////////////////////// /* * (non-Javadoc) * * @see javax.swing.event.TreeModelListener#treeNodesChanged(javax.swing.event.TreeModelEvent) */ public void treeNodesChanged( TreeModelEvent arg0 ) { } /* * (non-Javadoc) * * @see javax.swing.event.TreeModelListener#treeNodesInserted(javax.swing.event.TreeModelEvent) */ public void treeNodesInserted( TreeModelEvent arg0 ) { // at least one layer must be selected -> enable deselectAll-button and next-button this.btDeselectAll.setEnabled( true ); this.buttonPanel.setButtonEnabled( ButtonPanel.NEXT_BT, true ); this.buttonPanel.setButtonEnabled( ButtonPanel.FINISH_BT, true ); } /* * (non-Javadoc) * * @see javax.swing.event.TreeModelListener#treeNodesRemoved(javax.swing.event.TreeModelEvent) */ public void treeNodesRemoved( TreeModelEvent arg0 ) { // disable deselectAll-button and next-button if no layers are selected if ( this.trSelectedCoverages.getRowCount() < 1 ) { this.btDeselectAll.setEnabled( false ); this.buttonPanel.setButtonEnabled( ButtonPanel.NEXT_BT, false ); this.buttonPanel.setButtonEnabled( ButtonPanel.FINISH_BT, false ); } } /* * (non-Javadoc) * * @see javax.swing.event.TreeModelListener#treeStructureChanged(javax.swing.event.TreeModelEvent) */ public void treeStructureChanged( TreeModelEvent arg0 ) { } }