/*
* Copyright (C) 2010 Brockmann Consult GmbH (info@brockmann-consult.de)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 3 of the License, or (at your option)
* any later version.
* This program 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 General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, see http://www.gnu.org/licenses/
*/
package org.esa.snap.rcp.actions.vector;
import com.bc.ceres.swing.figure.Figure;
import com.bc.ceres.swing.figure.FigureSelection;
import com.bc.ceres.swing.figure.support.DefaultFigureSelection;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.io.WKTWriter;
import org.esa.snap.rcp.SnapApp;
import org.esa.snap.rcp.util.Dialogs;
import org.esa.snap.ui.ModalDialog;
import org.esa.snap.ui.product.SimpleFeatureFigure;
import org.geotools.geometry.jts.GeometryCoordinateSequenceTransformer;
import org.geotools.referencing.CRS;
import org.geotools.referencing.crs.DefaultGeographicCRS;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.referencing.FactoryException;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.opengis.referencing.operation.MathTransform;
import org.opengis.referencing.operation.TransformException;
import org.openide.awt.ActionID;
import org.openide.awt.ActionReference;
import org.openide.awt.ActionReferences;
import org.openide.awt.ActionRegistration;
import org.openide.util.ContextAwareAction;
import org.openide.util.Lookup;
import org.openide.util.LookupEvent;
import org.openide.util.LookupListener;
import org.openide.util.NbBundle;
import org.openide.util.Utilities;
import org.openide.util.WeakListeners;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
/**
* An action that allows users to copy WKT from selected Geometries.
*
* @author Norman
* @since BEAM 5
*/
@ActionID(category = "File", id = "org.esa.snap.rcp.actions.vector.ShowGeometryWktAction")
@ActionRegistration(displayName = "#CTL_ShowGeometryWktAction_MenuText", lazy = false)
@ActionReferences({
@ActionReference(path = "Menu/Vector", position = 19, separatorAfter = 20),
@ActionReference(path = "Context/ProductSceneView", position = 10)
})
@NbBundle.Messages({
"CTL_ShowGeometryWktAction_MenuText=WKT from Geometry",
"CTL_ShowGeometryWktAction_ShortDescription=Get the well-known-text (WKT) representation of a selected geometry."
})
public class ShowGeometryWktAction extends AbstractAction implements LookupListener, ContextAwareAction {
private static final String DLG_TITLE = "WKT from Geometry";
private Lookup.Result<FigureSelection> result;
private Lookup lookup;
public ShowGeometryWktAction() {
this(Utilities.actionsGlobalContext());
}
public ShowGeometryWktAction(Lookup lookup) {
super(Bundle.CTL_ShowGeometryWktAction_MenuText());
this.lookup = lookup;
result = lookup.lookupResult(FigureSelection.class);
result.addLookupListener(WeakListeners.create(LookupListener.class, this, result));
setEnabled(false);
}
@Override
public void actionPerformed(ActionEvent event) {
exportToWkt();
}
@Override
public Action createContextAwareInstance(Lookup actionContext) {
return new ShowGeometryWktAction(actionContext);
}
@Override
public void resultChanged(LookupEvent lookupEvent) {
FigureSelection selection = this.lookup.lookup(FigureSelection.class);
setEnabled(selection != null);
}
private void exportToWkt() {
SimpleFeatureFigure selectedFeatureFigure = getSimpleFeatureFigure();
if (selectedFeatureFigure == null) {
Dialogs.showInformation(DLG_TITLE, "Please select a geometry.", null);
return;
}
SimpleFeature simpleFeature = selectedFeatureFigure.getSimpleFeature();
CoordinateReferenceSystem sourceCrs = simpleFeature.getDefaultGeometryProperty().getDescriptor().getCoordinateReferenceSystem();
CoordinateReferenceSystem targetCrs = DefaultGeographicCRS.WGS84;
Geometry sourceGeom = selectedFeatureFigure.getGeometry();
Geometry targetGeom;
try {
targetGeom = transformGeometry(sourceGeom, sourceCrs, targetCrs);
} catch (Exception e) {
Dialogs.showWarning(DLG_TITLE, "Failed to transform geometry to " + targetCrs.getName() + ".\n" +
"Using " + sourceCrs.getName() + " instead.", null);
targetGeom = sourceGeom;
targetCrs = sourceCrs;
}
WKTWriter wktWriter = new WKTWriter();
wktWriter.setFormatted(true);
wktWriter.setMaxCoordinatesPerLine(2);
wktWriter.setTab(3);
String wkt = wktWriter.writeFormatted(targetGeom);
JTextArea textArea = new JTextArea(16, 32);
textArea.setEditable(false);
textArea.setText(wkt);
textArea.selectAll();
JPanel contentPanel = new JPanel(new BorderLayout(4, 4));
contentPanel.add(new JLabel("Geometry Well-Known-Text (WKT):"), BorderLayout.NORTH);
contentPanel.add(new JScrollPane(textArea), BorderLayout.CENTER);
contentPanel.add(new JLabel("Geometry CRS: " + targetCrs.getName().toString()), BorderLayout.SOUTH);
ModalDialog modalDialog = new ModalDialog(SnapApp.getDefault().getMainFrame(), DLG_TITLE, ModalDialog.ID_OK, null);
modalDialog.setContent(contentPanel);
modalDialog.center();
modalDialog.show();
}
private SimpleFeatureFigure getSimpleFeatureFigure() {
DefaultFigureSelection selection = this.lookup.lookup(DefaultFigureSelection.class);
SimpleFeatureFigure selectedFeatureFigure = null;
Figure[] figures = selection.getFigures();
for (Figure figure : figures) {
if (figure instanceof SimpleFeatureFigure) {
selectedFeatureFigure = (SimpleFeatureFigure) figure;
}
}
return selectedFeatureFigure;
}
private Geometry transformGeometry(Geometry sourceGeom,
CoordinateReferenceSystem sourceCrs,
CoordinateReferenceSystem targetCrs) throws FactoryException, TransformException {
MathTransform mt = CRS.findMathTransform(sourceCrs, targetCrs, true);
GeometryCoordinateSequenceTransformer gcst = new GeometryCoordinateSequenceTransformer();
gcst.setMathTransform(mt);
return gcst.transform(sourceGeom);
}
}