//$HeadURL$ /*---------------- FILE HEADER ------------------------------------------ This file is part of deegree. Copyright (C) 2001-2008 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.modules; import static java.util.prefs.Preferences.userNodeForPackage; import static org.deegree.igeo.i18n.Messages.get; import static org.deegree.model.feature.FeatureFactory.createFeatureCollection; import static org.deegree.model.spatialschema.GeometryFactory.createPoint; import java.awt.Color; import java.awt.Component; import java.awt.Container; import java.awt.Cursor; import java.awt.Image; import java.awt.Toolkit; import java.awt.datatransfer.Clipboard; import java.awt.datatransfer.DataFlavor; import java.awt.datatransfer.Transferable; import java.awt.datatransfer.UnsupportedFlavorException; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.awt.event.MouseMotionAdapter; import java.awt.event.MouseMotionListener; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import java.net.MalformedURLException; import java.net.URI; import java.net.URISyntaxException; import java.util.ArrayList; import java.util.Arrays; import java.util.LinkedList; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.prefs.Preferences; import javax.swing.Icon; import javax.swing.ImageIcon; import javax.swing.JComponent; import javax.swing.JFrame; import javax.swing.JInternalFrame; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.TransferHandler; import org.deegree.datatypes.QualifiedName; import org.deegree.framework.log.ILogger; import org.deegree.framework.log.LoggerFactory; import org.deegree.framework.util.CollectionUtils; import org.deegree.framework.util.CollectionUtils.Mapper; import org.deegree.framework.util.ImageUtils; import org.deegree.framework.utils.MapTools; import org.deegree.graphics.transformation.GeoTransform; import org.deegree.igeo.ApplicationContainer; import org.deegree.igeo.commands.CommitDataChangesCommand; import org.deegree.igeo.commands.ExportLayerCommand; import org.deegree.igeo.commands.UnselectFeaturesCommand; import org.deegree.igeo.commands.model.RepaintCommand; import org.deegree.igeo.commands.model.ZoomCommand; import org.deegree.igeo.config.ModuleType; import org.deegree.igeo.config.QualifiedNameType; import org.deegree.igeo.config._ComponentPositionType; import org.deegree.igeo.dataadapter.DataAccessAdapter; import org.deegree.igeo.dataadapter.FeatureAdapter; import org.deegree.igeo.desktop.IGeoDesktop; import org.deegree.igeo.i18n.Messages; import org.deegree.igeo.mapmodel.Layer; import org.deegree.igeo.mapmodel.LayerGroup; import org.deegree.igeo.mapmodel.MapModel; import org.deegree.igeo.mapmodel.MapModelVisitor; import org.deegree.igeo.modules.ActionDescription.ACTIONTYPE; import org.deegree.igeo.state.mapstate.HotlinkState; import org.deegree.igeo.state.mapstate.MapTool; import org.deegree.igeo.views.DialogFactory; import org.deegree.igeo.views.swing.linkeddata.LinkedDataDialog; import org.deegree.igeo.views.swing.map.DefaultMapComponent; import org.deegree.igeo.views.swing.map.ObjectInfoPanel; import org.deegree.igeo.views.swing.map.SelectByAttributeDialog; import org.deegree.igeo.views.swing.map.SelectPanel; import org.deegree.igeo.views.swing.map.ZoomPanel; import org.deegree.igeo.views.swing.util.GenericFileChooser; import org.deegree.igeo.views.swing.util.GenericFileChooser.FILECHOOSERTYPE; import org.deegree.igeo.views.swing.util.IGeoFileFilter; import org.deegree.kernel.Command; import org.deegree.kernel.CommandProcessedEvent; import org.deegree.kernel.CommandProcessedListener; import org.deegree.model.Identifier; import org.deegree.model.feature.Feature; import org.deegree.model.feature.FeatureCollection; import org.deegree.model.feature.FeatureProperty; import org.deegree.model.filterencoding.FilterEvaluationException; import org.deegree.model.spatialschema.Envelope; import org.deegree.model.spatialschema.Point; /** * The <code>DefaultMapModule</code> is the specific module definition of a map module. It handles all generic events * belonging to a map - zoomIn, zoomOut, Pan, Center. * * @author <a href="mailto:buesching@lat-lon.de">Lyn Buesching</a> * @author last edited by: $Author$ * * @version $Revision$, $Date$ * @param <T> * */ public class DefaultMapModule<T> extends DefaultModule<T> implements CommandProcessedListener { private static final ILogger LOG = LoggerFactory.getLogger( DefaultMapModule.class ); protected MapTool<T> mapTool; private List<Envelope> history = new ArrayList<Envelope>( 100 ); private int historyIndex = 0; private List<Identifier> historyIdList = new ArrayList<Identifier>(); private Container jco; static { initCapabilities(); } private static final Mapper<QualifiedName, QualifiedNameType> toqualifiedname = new Mapper<QualifiedName, QualifiedNameType>() { public QualifiedName apply( QualifiedNameType u ) { try { return new QualifiedName( u.getPrefix(), u.getLocalName(), new URI( u.getNamespace() ) ); } catch ( URISyntaxException e ) { LOG.logError( "Unknown error", e ); return null; } } }; private static void initCapabilities() { ActionDescription ad1 = new ActionDescription( "center", "puts application into center mode; a click into current map will center map model on click point", null, "puts application into center mode", ACTIONTYPE.ToggleButton, null, null ); ActionDescription ad2 = new ActionDescription( "pan", "puts application into center mode", null, "puts application into center mode", ACTIONTYPE.ToggleButton, null, null ); ActionDescription ad3 = new ActionDescription( "zoomIn", "puts application into zoom in mode", null, "puts application into zoom in mode", ACTIONTYPE.ToggleButton, null, null ); ActionDescription ad4 = new ActionDescription( "zoomOut", "puts application into zoom out mode", null, "puts application into zoom out mode", ACTIONTYPE.ToggleButton, null, null ); ActionDescription ad5 = new ActionDescription( "zoomToFullExtent", "zoom to maximum extent as defined in current project", null, "zoom to maximum extent", ACTIONTYPE.PushButton, null, null ); ActionDescription ad6 = new ActionDescription( "zoomToSelectedFeatures", "zoom to extent of selected features", null, "zoom to extent of selected features", ACTIONTYPE.PushButton, null, null ); ActionDescription ad7 = new ActionDescription( "zoomToSelectedLayers", "zoom to extent of selected layers", null, "zoom to extent of selected layers", ACTIONTYPE.PushButton, null, null ); ActionDescription ad8 = new ActionDescription( "synchronizeMapModels", "sets extents of all map models to the extent of the selected one", null, "synchronizes extent of map models", ACTIONTYPE.PushButton, null, null ); ActionDescription ad9 = new ActionDescription( "historyForward", "set extent to next one", null, "set extent to next one", ACTIONTYPE.PushButton, null, null ); ActionDescription ad10 = new ActionDescription( "historyBackward", "set extent to previous one", null, "set extent to previous one", ACTIONTYPE.PushButton, null, null ); ActionDescription ad11 = new ActionDescription( "objectInfo", "puts application into objectInfo state", null, "puts application into objectInfo state", ACTIONTYPE.ToggleButton, null, null ); ActionDescription ad12 = new ActionDescription( "exportLayer", "exports selected layer depending on contained datatypes as file", null, "exports selected layer", ACTIONTYPE.PushButton, null, null ); ActionDescription ad13 = new ActionDescription( "commitAll", "writes changes for all layers performed to geometries and/or properties into according backend", null, "commits all changes to backends", ACTIONTYPE.PushButton, null, null ); ActionDescription ad14 = new ActionDescription( "commitSelected", "writes changes for selected layer performed to geometries and/or properties into according backend", null, "commits changes for selected layer to backend", ACTIONTYPE.PushButton, null, null ); ActionDescription ad15 = new ActionDescription( "exportAsImage", "exports current map as image into a file", null, "exports current map as image", ACTIONTYPE.PushButton, null, null ); ActionDescription ad16 = new ActionDescription( "exportToClipBoard", "copies current map as png image into clip board", null, "copies current map as image into clip board", ACTIONTYPE.PushButton, null, null ); moduleCapabilities = new ModuleCapabilities( ad1, ad2, ad3, ad4, ad5, ad6, ad7, ad8, ad9, ad10, ad11, ad12, ad13, ad14, ad15, ad16 ); } @Override public void init( ModuleType moduleType, _ComponentPositionType componentPosition, ApplicationContainer<T> appCont, IModule<T> parent, Map<String, String> initParams ) { super.init( moduleType, componentPosition, appCont, parent, initParams ); // register at CommandProcessor to be informed about changes of the maps // envelope. This is required to enable managing of the history of map // envelopes. appContainer.getCommandProcessor().addCommandProcessedListener( this ); mapTool = new MapTool<T>( appCont ); if ( getViewForm() instanceof JFrame ) { JFrame viewForm = (JFrame) getViewForm(); Component[] components = viewForm.getContentPane().getComponents(); for ( int i = 0; i < components.length; i++ ) { if ( components[i] instanceof DefaultMapComponent ) { jco = (Container) components[i]; break; } } if ( jco == null ) { LOG.logError( Messages.getMessage( Locale.getDefault(), "$DG10072" ) ); return; } } else if ( getViewForm() instanceof JInternalFrame ) { JInternalFrame viewForm = (JInternalFrame) getViewForm(); Component[] components = viewForm.getContentPane().getComponents(); for ( int i = 0; i < components.length; i++ ) { if ( components[i] instanceof DefaultMapComponent ) { jco = (Container) components[i]; break; } } if ( jco == null ) { LOG.logError( Messages.getMessage( Locale.getDefault(), "$DG10072" ) ); return; } } else { jco = (Container) getViewForm(); } } /** * * @return assigned maptool */ public MapTool<T> getMapTool() { return mapTool; } private void removeControlPanels() { try { String mmId = getInitParameter( "assignedMapModel" ); MapModel mm = appContainer.getMapModel( new Identifier( mmId ) ); Command cmd = new UnselectFeaturesCommand( mm, false ); appContainer.getCommandProcessor().executeSychronously( cmd, true ); } catch ( Exception e ) { LOG.logError( e.getMessage(), e ); } if ( jco != null ) { Component[] comps = jco.getComponents(); for ( int i = 0; i < comps.length; i++ ) { MouseListener[] ml = comps[i].getMouseListeners(); for ( MouseListener mouseListener : ml ) { if ( !( mouseListener instanceof DefaultMapComponent.DMCMouseListener ) ) { // keep mouse listener of map component comps[i].removeMouseListener( mouseListener ); } } MouseMotionListener[] mml = comps[i].getMouseMotionListeners(); for ( MouseMotionListener mouseMotionListener : mml ) { if ( !( mouseMotionListener instanceof DefaultMapComponent.DMCMouseMotionListener ) ) { // keep mouse motion listener of map component comps[i].removeMouseMotionListener( mouseMotionListener ); } } if ( comps[i] instanceof JPanel ) { jco.remove( comps[i] ); } if ( !( getViewForm() instanceof JFrame ) ) { if ( comps[i] instanceof MouseListener ) { jco.removeMouseListener( (MouseListener) comps[i] ); } if ( comps[i] instanceof MouseMotionListener ) { jco.removeMouseMotionListener( (MouseMotionListener) comps[i] ); } } } } } @Override public void clear() { removeControlPanels(); update(); } /** * sets map/module into select state * */ public void select() { mapTool.setSelectState(); removeControlPanels(); if ( getViewForm() instanceof Container ) { String mmId = getInitParameter( "assignedMapModel" ); MapModel mapModel = appContainer.getMapModel( new Identifier( mmId ) ); SelectPanel<T> sp = new SelectPanel<T>( this, mapTool, jco ); sp.setBounds( 0, 0, mapModel.getTargetDevice().getPixelWidth(), mapModel.getTargetDevice().getPixelHeight() ); sp.setBackground( new Color( 255, 255, 255, 0 ) ); sp.setVisible( true ); } } public void selectByAttributes() { String mmId = getInitParameter( "assignedMapModel" ); MapModel mapModel = appContainer.getMapModel( new Identifier( mmId ) ); if ( "application".equalsIgnoreCase( appContainer.getViewPlatform() ) ) { new SelectByAttributeDialog( mapModel ); } } /** * sets map/module into zoomin state * */ @SuppressWarnings("unchecked") public void zoomIn() { mapTool.setZoomInState( "zoomIn" ); removeControlPanels(); if ( getViewForm() instanceof Container ) { String mmId = getInitParameter( "assignedMapModel" ); MapModel mapModel = appContainer.getMapModel( new Identifier( mmId ) ); ZoomPanel sp = new ZoomPanel( (IModule<Container>) this, (MapTool<Container>) mapTool, jco ); sp.setBounds( 0, 0, mapModel.getTargetDevice().getPixelWidth(), mapModel.getTargetDevice().getPixelHeight() ); sp.setBackground( new Color( 255, 255, 255, 0 ) ); sp.setVisible( true ); } } /** * sets map/module into zoomout state * */ @SuppressWarnings("unchecked") public void zoomOut() { mapTool.setZoomOutState( "zoomOut" ); removeControlPanels(); if ( getViewForm() instanceof Container ) { String mmId = getInitParameter( "assignedMapModel" ); MapModel mapModel = appContainer.getMapModel( new Identifier( mmId ) ); ZoomPanel sp = new ZoomPanel( (IModule<Container>) this, (MapTool<Container>) mapTool, jco ); sp.setBounds( 0, 0, mapModel.getTargetDevice().getPixelWidth(), mapModel.getTargetDevice().getPixelHeight() ); sp.setBackground( new Color( 255, 255, 255, 0 ) ); sp.setVisible( true ); } } /** * sets map/module into pan state * */ @SuppressWarnings("unchecked") public void pan() { mapTool.setPanState( "pan" ); removeControlPanels(); if ( getViewForm() instanceof Container ) { String mmId = getInitParameter( "assignedMapModel" ); MapModel mapModel = appContainer.getMapModel( new Identifier( mmId ) ); ZoomPanel sp = new ZoomPanel( (IModule<Container>) this, (MapTool<Container>) mapTool, jco ); sp.setBounds( 0, 0, mapModel.getTargetDevice().getPixelWidth(), mapModel.getTargetDevice().getPixelHeight() ); sp.setBackground( new Color( 255, 255, 255, 0 ) ); sp.setVisible( true ); } } /** * sets map/module into re-center state * */ @SuppressWarnings("unchecked") public void center() { mapTool.setCenterState( "center" ); removeControlPanels(); if ( getViewForm() instanceof Container ) { String mmId = getInitParameter( "assignedMapModel" ); MapModel mapModel = appContainer.getMapModel( new Identifier( mmId ) ); ZoomPanel sp = new ZoomPanel( (IModule<Container>) this, (MapTool<Container>) mapTool, jco ); sp.setBounds( 0, 0, mapModel.getTargetDevice().getPixelWidth(), mapModel.getTargetDevice().getPixelHeight() ); sp.setBackground( new Color( 255, 255, 255, 0 ) ); sp.setVisible( true ); } } /** * sets map/module into object info state * */ @SuppressWarnings("unchecked") public void objectInfo() { mapTool.setInfoState( "objectInfo" ); removeControlPanels(); if ( getViewForm() instanceof Container ) { String mmId = getInitParameter( "assignedMapModel" ); MapModel mapModel = appContainer.getMapModel( new Identifier( mmId ) ); List<Layer> layers = mapModel.getLayersSelectedForAction( MapModel.SELECTION_ACTION ); if ( layers.size() == 0 ) { DialogFactory.openWarningDialog( mapModel.getApplicationContainer().getViewPlatform(), null, Messages.get( "$MD11402" ), Messages.get( "$MD11403" ) ); } else if ( !layers.get( 0 ).isQueryable() ) { DialogFactory.openWarningDialog( mapModel.getApplicationContainer().getViewPlatform(), null, Messages.get( "$MD11400", layers.get( 0 ).getTitle() ), Messages.get( "$MD11401" ) ); } else { ObjectInfoPanel oi = new ObjectInfoPanel( (IModule<Container>) this, (MapTool<Container>) mapTool, jco ); oi.setBounds( 0, 0, mapModel.getTargetDevice().getPixelWidth(), mapModel.getTargetDevice().getPixelHeight() ); oi.setBackground( new Color( 255, 255, 255, 0 ) ); oi.setVisible( true ); } } } public void repaint() { if ( getViewForm() instanceof Container ) { MapModel mapModel = getMapModuleIfPassive(); if ( mapModel != null ) { RepaintCommand repaintCommand = new RepaintCommand( mapModel ); try { appContainer.getCommandProcessor().executeSychronously( repaintCommand, true ); } catch ( Exception e ) { LOG.logWarning( "Repaint failed: " + e.getMessage() ); } } } } private MapModel getMapModuleIfPassive() { String mmId = getInitParameter( "assignedMapModel" ); MapModel mapModel = appContainer.getMapModel( new Identifier( mmId ) ); MapModel temp = appContainer.getMapModel( null ); // ensure that just the current model will be returned only if it is not the active one if ( mapModel != temp ) { return mapModel; } return null; } /** * zooms map to its full extent * */ public void zoomToFullExtent() { String mmId = getInitParameter( "assignedMapModel" ); MapModel mapModel = appContainer.getMapModel( new Identifier( mmId ) ); Envelope env = mapModel.getMaxExtent(); ZoomCommand command = new ZoomCommand( mapModel ); int w = mapModel.getTargetDevice().getPixelWidth(); int h = mapModel.getTargetDevice().getPixelHeight(); command.setZoomBox( env, w, h ); try { appContainer.getCommandProcessor().executeSychronously( command, true ); } catch ( Exception e ) { LOG.logError( e.getMessage(), e ); DialogFactory.openErrorDialog( appContainer.getViewPlatform(), null, Messages.get( "$MD11220" ), Messages.get( "$MD11221", env ), e ); } clearHistoryForwarding(); } /** * removes all entries from the history list that enables forward stepping. This method should be called if the * envelope of the map ahs been changed on an other way than moving back in history * */ protected void clearHistoryForwarding() { int k = history.size(); while ( k > historyIndex ) { history.remove( --k ); } } /** * commits changes of all changeable layers to their back ends * * @throws Exception * */ public void commitAll() throws Exception { String mmId = getInitParameter( "assignedMapModel" ); MapModel mapModel = appContainer.getMapModel( new Identifier( mmId ) ); MapModel temp = appContainer.getMapModel( null ); // this check must be done to ensure that just layers of current model will be committed // because this method is registered as action method to all map models if ( mapModel == temp ) { final List<Layer> layers = new ArrayList<Layer>( 50 ); mapModel.walkLayerTree( new MapModelVisitor() { public void visit( Layer layer ) throws Exception { layers.add( layer ); } public void visit( LayerGroup layerGroup ) throws Exception { } } ); CommitDataChangesCommand command = new CommitDataChangesCommand( layers ); appContainer.getCommandProcessor().executeSychronously( command, true ); } } /** * commits changes of all selected changeable layers to their back ends * */ public void commitSelected() { String mmId = getInitParameter( "assignedMapModel" ); MapModel mapModel = appContainer.getMapModel( new Identifier( mmId ) ); MapModel temp = appContainer.getMapModel( null ); // this check must be done to ensure that just the selected layer of current model will be committed // because this method is registered as action method to all map models if ( mapModel == temp ) { List<Layer> layers = mapModel.getLayersSelectedForAction( MapModel.SELECTION_ACTION ); CommitDataChangesCommand command = new CommitDataChangesCommand( layers ); try { appContainer.getCommandProcessor().executeSychronously( command, true ); } catch ( Exception e ) { LOG.logError( e.getMessage(), e ); DialogFactory.openErrorDialog( appContainer.getViewPlatform(), null, Messages.get( "$MD11222" ), Messages.get( "$MD11223" ), e ); } } } /** * exports a layer into a file. Depending on data source type (grid - feature) */ @SuppressWarnings("unchecked") public void exportLayer() { String mmId = getInitParameter( "assignedMapModel" ); MapModel mapModel = appContainer.getMapModel( new Identifier( mmId ) ); MapModel temp = appContainer.getMapModel( null ); // this check must be done to ensure that just the selected layer of current model will be exported // because this method is registered as action method to all map models if ( mapModel == temp ) { File file = null; List<Layer> layers = mapModel.getLayersSelectedForAction( MapModel.SELECTION_ACTION ); if ( "Application".equals( appContainer.getViewPlatform() ) ) { if ( layers.size() > 0 ) { List<IGeoFileFilter> cff = null; if ( layers.get( 0 ).getDataAccess().get( 0 ) instanceof FeatureAdapter ) { cff = IGeoFileFilter.createForwellKnownFormats( (ApplicationContainer<Container>) appContainer, IGeoFileFilter.FILETYPE.vector ); } else { cff = IGeoFileFilter.createForwellKnownFormats( (ApplicationContainer<Container>) appContainer, IGeoFileFilter.FILETYPE.raster ); } Preferences prefs = Preferences.userNodeForPackage( DefaultMapModule.class ); file = GenericFileChooser.showSaveDialog( FILECHOOSERTYPE.geoDataFile, appContainer, ( (IGeoDesktop) appContainer ).getMainWndow(), prefs, "layerFile", cff ); if ( file != null ) { LOG.logDebug( "export layer to file: ", file ); } } else { DialogFactory.openWarningDialog( "Application", view, Messages.get( "$MD10867" ), Messages.get( "$MD10868" ) ); } } if ( file != null ) { Command command = new ExportLayerCommand( layers.get( 0 ), file ); try { appContainer.getCommandProcessor().executeSychronously( command, true ); } catch ( Exception e ) { LOG.logError( e.getMessage(), e ); DialogFactory.openErrorDialog( appContainer.getViewPlatform(), null, Messages.get( "$MD11224" ), Messages.get( "$MD11225", layers.get( 0 ), file ), e ); } } } } /** * zooms the map to the next entry within the list of history envelopes. * */ public void historyForward() { if ( historyIndex < history.size() - 1 ) { historyIndex++; Envelope env = history.get( historyIndex ); String mmId = getInitParameter( "assignedMapModel" ); MapModel mapModel = appContainer.getMapModel( new Identifier( mmId ) ); // use id to identify zoom commands that has been performed in context of // stepping through the maps history Identifier id = new Identifier(); historyIdList.add( id ); ZoomCommand zc = new ZoomCommand( id, mapModel ); zc.setZoomBox( env, mapModel.getTargetDevice().getPixelWidth(), mapModel.getTargetDevice().getPixelHeight() ); try { appContainer.getCommandProcessor().executeSychronously( zc, true ); } catch ( Exception e ) { LOG.logError( e.getMessage(), e ); DialogFactory.openErrorDialog( appContainer.getViewPlatform(), null, Messages.get( "$MD11226" ), Messages.get( "$MD11227" ), e ); } } } /** * zooms the map to the previous entry within the list of history envelopes. * */ public void historyBackward() { if ( historyIndex > 0 ) { String mmId = getInitParameter( "assignedMapModel" ); MapModel mapModel = appContainer.getMapModel( new Identifier( mmId ) ); if ( historyIndex == history.size() ) { history.add( mapModel.getEnvelope() ); } historyIndex--; Envelope env = history.get( historyIndex ); // use id to identify zoom commands that has been performed in context of // stepping through the maps history Identifier id = new Identifier(); historyIdList.add( id ); ZoomCommand zc = new ZoomCommand( id, mapModel ); zc.setZoomBox( env, mapModel.getTargetDevice().getPixelWidth(), mapModel.getTargetDevice().getPixelHeight() ); try { appContainer.getCommandProcessor().executeSychronously( zc, true ); } catch ( Exception e ) { LOG.logError( e.getMessage(), e ); DialogFactory.openErrorDialog( appContainer.getViewPlatform(), null, Messages.get( "$MD11228" ), Messages.get( "$MD11229" ), e ); } } } /* * (non-Javadoc) * * @see org.deegree.kernel.CommandProcessedListener#commandProcessed(org.deegree.kernel.CommandProcessedEvent) */ public void commandProcessed( CommandProcessedEvent event ) { if ( event.getSource() instanceof ZoomCommand && !( historyIdList.contains( event.getSource().getIdentifier() ) ) ) { // clear forward history section because a new anchor/path has been set/opened clearHistoryForwarding(); // get Envelope of the map before zoom/pan action has been performed ZoomCommand zc = (ZoomCommand) event.getSource(); history.add( zc.getUndoExtent() ); historyIndex++; } else { historyIdList.remove( event.getSource().getIdentifier() ); } } /** * zooms map to extent of the selected layers */ public void zoomToSelectedLayers() { ZoomCommand cmd = new ZoomCommand( appContainer.getMapModel( null ) ); try { appContainer.getCommandProcessor().executeSychronously( cmd, true ); } catch ( Exception e ) { LOG.logError( e.getMessage(), e ); DialogFactory.openErrorDialog( appContainer.getViewPlatform(), null, Messages.get( "$MD11230" ), Messages.get( "$MD11231" ), e ); } } /** * */ public void zoomToSelectedFeatures() { String mmId = getInitParameter( "assignedMapModel" ); MapModel mm = appContainer.getMapModel( new Identifier( mmId ) ); try { SelectedFeaturesEnvelopeVisitor visitor = new SelectedFeaturesEnvelopeVisitor(); mm.walkLayerTree( visitor ); if ( visitor.bbox != null ) { ZoomCommand zoom = new ZoomCommand( mm ); zoom.setZoomBox( visitor.bbox, mm.getTargetDevice().getPixelWidth(), mm.getTargetDevice().getPixelHeight() ); appContainer.getCommandProcessor().executeSychronously( zoom, true ); } } catch ( Exception e ) { LOG.logError( e.getMessage(), e ); DialogFactory.openErrorDialog( appContainer.getViewPlatform(), null, Messages.get( "$MD11232" ), Messages.get( "$MD11233" ), e ); } } /** * */ public void activateHyperlink() { mapTool.setHotlinkState(); Container jco = null; if ( getViewForm() instanceof JFrame ) { JFrame viewForm = (JFrame) getViewForm(); Component[] components = viewForm.getContentPane().getComponents(); for ( int i = 0; i < components.length; i++ ) { if ( components[i] instanceof DefaultMapComponent ) { jco = (Container) components[i]; break; } } if ( jco == null ) { LOG.logError( Messages.getMessage( Locale.getDefault(), "$DG10072" ) ); return; } } else if ( getViewForm() instanceof JInternalFrame ) { JInternalFrame viewForm = (JInternalFrame) getViewForm(); Component[] components = viewForm.getContentPane().getComponents(); for ( int i = 0; i < components.length; i++ ) { if ( components[i] instanceof DefaultMapComponent ) { jco = (Container) components[i]; break; } } if ( jco == null ) { LOG.logError( Messages.getMessage( Locale.getDefault(), "$DG10072" ) ); return; } } else { jco = (Container) getViewForm(); } jco.addMouseListener( new MouseAdapter() { @Override public void mouseClicked( MouseEvent e ) { if ( mapTool.getState().getClass().equals( HotlinkState.class ) ) { LinkedList<String> urls = getURLsAtPoint( e ); if ( urls.isEmpty() ) { return; } String val = urls.getFirst(); if ( urls.size() > 1 ) { val = (String) JOptionPane.showInputDialog( null, get( "$MD10896" ), get( "$DI10019" ), JOptionPane.QUESTION_MESSAGE, null, urls.toArray(), val ); if ( val == null ) { return; } } String ext = CollectionUtils.last( val.split( "[.]" ) ); String program = appContainer.getSettings().getExternalReferencesOptions().getProgram( ext ); LinkedList<String> cmd = new LinkedList<String>(); if ( program == null ) { if ( System.getProperty( "os.name" ).equalsIgnoreCase( "linux" ) ) { cmd.add( "firefox" ); } else { cmd.add( "cmd" ); cmd.add( "/c" ); cmd.add( "start" ); } } else { cmd.add( program ); } cmd.add( val ); // leave the process alone, whatever happens ProcessBuilder pb = new ProcessBuilder( cmd ); try { pb.start(); } catch ( IOException e1 ) { LOG.logError( "Unknown error", e1 ); } } } } ); final Container jco2 = jco; final Cursor handCursor = Cursor.getPredefinedCursor( Cursor.HAND_CURSOR ); final Cursor defaultCursor = Cursor.getPredefinedCursor( Cursor.DEFAULT_CURSOR ); jco.addMouseMotionListener( new MouseMotionAdapter() { @Override public void mouseMoved( MouseEvent e ) { if ( mapTool.getState().getClass().equals( HotlinkState.class ) ) { LinkedList<String> urls = getURLsAtPoint( e ); if ( !urls.isEmpty() ) { jco2.setCursor( handCursor ); } else { jco2.setCursor( defaultCursor ); } } } } ); } LinkedList<String> getURLsAtPoint( MouseEvent e ) { String mmId = getInitParameter( "assignedMapModel" ); MapModel mm = appContainer.getMapModel( new Identifier( mmId ) ); List<Layer> layers = mm.getLayersSelectedForAction( MapModel.SELECTION_ACTION ); LinkedList<String> urls = new LinkedList<String>(); GeoTransform trans = mm.getToTargetDeviceTransformation(); Point pt = createPoint( trans.getSourceX( e.getX() ), trans.getSourceY( e.getY() ), mm.getCoordinateSystem() ); for ( Layer l : layers ) { for ( DataAccessAdapter adapter : l.getDataAccess() ) { if ( adapter instanceof FeatureAdapter ) { FeatureAdapter fa = (FeatureAdapter) adapter; List<QualifiedName> refProps = CollectionUtils.map( fa.getDatasource().getDatasourceType().getReferenceProperty(), toqualifiedname ); try { FeatureCollection col = fa.getFeatureCollection( pt ); for ( int i = 0; i < col.size(); i++ ) { Feature f = col.getFeature( i ); for ( FeatureProperty prop : f.getProperties() ) { if ( refProps.isEmpty() || refProps.contains( prop.getName() ) ) { String val = prop.getValue( "" ).toString(); if ( val.contains( "http://" ) ) { String[] vals = val.split( "[ ,]" ); urls.addAll( Arrays.asList( vals ) ); } else { File file = new File( val ); if ( file.exists() ) { urls.add( file.toURI().toURL().toExternalForm() ); } } } } } } catch ( FilterEvaluationException e1 ) { LOG.logError( "Unknown error", e1 ); } catch ( MalformedURLException e1 ) { LOG.logError( "Unknown error", e1 ); } } } } return urls; } /** * event handler method; setting extent of all map model to active one */ public void synchronizeMapModels() { MapModel current = appContainer.getMapModel( null ); Envelope env = current.getEnvelope(); List<MapModel> list = appContainer.getMapModelCollection().getMapModels(); try { for ( MapModel mapModel : list ) { if ( !mapModel.equals( current ) ) { ZoomCommand cmd = new ZoomCommand( mapModel ); cmd.setZoomBox( env, -1, -1 ); appContainer.getCommandProcessor().executeSychronously( cmd, true ); } } } catch ( Exception e ) { LOG.logError( e.getMessage(), e ); DialogFactory.openErrorDialog( appContainer.getViewPlatform(), null, Messages.get( "$MD11234" ), Messages.get( "$MD11235" ), e ); } } /** * action handler function for exporting a map as image */ public void exportAsImage() { String mmId = getInitParameter( "assignedMapModel" ); MapModel mapModel = appContainer.getMapModel( new Identifier( mmId ) ); MapModel temp = appContainer.getMapModel( null ); // this check must be done to ensure that just layers of current model will be committed // because this method is registered as action method to all map models if ( mapModel == temp ) { Preferences prefs = userNodeForPackage( DefaultMapModule.class ); File f = GenericFileChooser.showSaveDialog( FILECHOOSERTYPE.printResult, appContainer, null, prefs, "outputdir", IGeoFileFilter.JPEG, IGeoFileFilter.PNG, IGeoFileFilter.BMP ); if ( f != null ) { BufferedImage img; try { img = MapTools.getMapAsImage( mapModel, f.getAbsolutePath().toLowerCase().endsWith( ".png" ), 1.5f ); } catch ( Exception e ) { LOG.logError( e.getMessage(), e ); return; } try { ImageUtils.saveImage( img, f, 0.99f ); } catch ( IOException e ) { LOG.logError( e.getMessage(), e ); } } } } /** * action handler function for copying a map into clip board */ public void exportToClipBoard() { String mmId = getInitParameter( "assignedMapModel" ); MapModel mapModel = appContainer.getMapModel( new Identifier( mmId ) ); MapModel temp = appContainer.getMapModel( null ); // this check must be done to ensure that just layers of current model will be committed // because this method is registered as action method to all map models if ( mapModel == temp ) { BufferedImage img; try { img = MapTools.getMapAsImage( mapModel, true, 1.5f ); } catch ( Exception e ) { LOG.logError( e.getMessage(), e ); return; } final JLabel label = new JLabel( new ImageIcon( img ) ); label.setTransferHandler( new ImageSelection() ); // use both clip boards for text? Clipboard clip = Toolkit.getDefaultToolkit().getSystemSelection(); if ( clip != null ) { TransferHandler handler = label.getTransferHandler(); handler.exportToClipboard( label, clip, TransferHandler.COPY ); } clip = Toolkit.getDefaultToolkit().getSystemClipboard(); TransferHandler handler = label.getTransferHandler(); handler.exportToClipboard( label, clip, TransferHandler.COPY ); } } public void addLinkedTable() { MapModel mm = appContainer.getMapModel( null ); if ( mm.getLayersSelectedForAction( MapModel.SELECTION_ACTION ).size() == 0 ) { DialogFactory.openWarningDialog( appContainer.getViewPlatform(), null, Messages.get( "$MD11580" ), Messages.get( "$MD11581" ) ); return; } if ( appContainer.getViewPlatform().equalsIgnoreCase( "application" ) ) { try { new LinkedDataDialog( this ); } catch ( Exception e ) { DialogFactory.openErrorDialog( appContainer.getViewPlatform(), null, Messages.get( "$MD11582" ), Messages.get( "$MD11583" ), e ); } } } /** * * @return */ @SuppressWarnings("unchecked") public T getMapContainer() { return (T) jco; } // ////////////////////////////////////////////////////////////////////////////////////////// // inner classes // ////////////////////////////////////////////////////////////////////////////////////////// /** * <code>SelectedFeaturesVisitor</code> * * @author <a href="mailto:schmitz@lat-lon.de">Andreas Schmitz</a> * @author last edited by: $Author$ * * @version $Revision$, $Date$ */ public static class SelectedFeaturesVisitor implements MapModelVisitor { /** * The collection of selected features. */ public FeatureCollection col = createFeatureCollection( "col", 0 ); private int max; /** * @param max * maximum number of objects to be fetched in the feature collection */ public SelectedFeaturesVisitor( int max ) { this.max = max; } public void visit( Layer layer ) throws Exception { FeatureCollection sel = layer.getSelectedFeatures(); if ( max == -1 || sel.size() <= max ) { col.addAllUncontained( sel ); } else { for ( int i = 0; i < max; ++i ) { col.add( sel.getFeature( i ) ); } } } public void visit( LayerGroup layerGroup ) throws Exception { // unused } } /** * * The <code>DefaultMapModule</code> class TODO add class documentation here. * * @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a> * * @author last edited by: $Author$ * * @version $Revision$, $Date$ * */ class SelectedFeaturesEnvelopeVisitor implements MapModelVisitor { Envelope bbox; public void visit( Layer layer ) throws Exception { FeatureCollection selected = layer.getSelectedFeatures(); for ( int i = 0; i < selected.size(); ++i ) { Feature feature = selected.getFeature( i ); if ( bbox == null ) { if ( feature.getDefaultGeometryPropertyValue() instanceof Point ) { bbox = feature.getBoundedBy().getBuffer( 25 ); } else { bbox = feature.getBoundedBy(); } } else { bbox.expandToContain( feature.getBoundedBy() ); } } } public void visit( LayerGroup layerGroup ) throws Exception { // unused } } /** * * TODO add class documentation here * * @author <a href="mailto:name@deegree.org">Andreas Poth</a> * @author last edited by: $Author$ * * @version $Revision$, $Date$ */ private static class ImageSelection extends TransferHandler implements Transferable { private static final long serialVersionUID = 6897713712887196351L; private static final DataFlavor flavors[] = { DataFlavor.imageFlavor }; private Image image; @Override public int getSourceActions( JComponent c ) { return TransferHandler.COPY; } @Override public boolean canImport( JComponent comp, DataFlavor flavor[] ) { if ( !( comp instanceof JLabel ) ) { return false; } for ( int i = 0, n = flavor.length; i < n; i++ ) { for ( int j = 0, m = flavors.length; j < m; j++ ) { if ( flavor[i].equals( flavors[j] ) ) { return true; } } } return false; } @Override public Transferable createTransferable( JComponent comp ) { // Clear image = null; if ( comp instanceof JLabel ) { JLabel label = (JLabel) comp; Icon icon = label.getIcon(); if ( icon instanceof ImageIcon ) { image = ( (ImageIcon) icon ).getImage(); return this; } } return null; } @Override public boolean importData( JComponent comp, Transferable t ) { if ( comp instanceof JLabel ) { JLabel label = (JLabel) comp; if ( t.isDataFlavorSupported( flavors[0] ) ) { try { image = (Image) t.getTransferData( flavors[0] ); ImageIcon icon = new ImageIcon( image ); label.setIcon( icon ); return true; } catch ( UnsupportedFlavorException ignored ) { LOG.logWarning( "ignored", ignored ); } catch ( IOException ignored ) { LOG.logWarning( "ignored", ignored ); } } } return false; } // Transferable public Object getTransferData( DataFlavor flavor ) { if ( isDataFlavorSupported( flavor ) ) { return image; } return null; } // Transferable public DataFlavor[] getTransferDataFlavors() { return flavors; } // Transferable public boolean isDataFlavorSupported( DataFlavor flavor ) { return flavor.equals( DataFlavor.imageFlavor ); } } }