/*
* Copyright (C) 2014 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.core.ProgressMonitor;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.io.ParseException;
import com.vividsolutions.jts.io.WKTReader;
import org.esa.snap.core.datamodel.PlainFeatureFactory;
import org.esa.snap.core.util.FeatureUtils;
import org.esa.snap.rcp.SnapApp;
import org.esa.snap.rcp.actions.interactors.InsertFigureInteractorInterceptor;
import org.esa.snap.rcp.util.Dialogs;
import org.esa.snap.ui.ModalDialog;
import org.esa.snap.ui.product.ProductSceneView;
import org.esa.snap.ui.product.VectorDataLayer;
import org.geotools.data.collection.ListFeatureCollection;
import org.geotools.feature.FeatureCollection;
import org.geotools.feature.simple.SimpleFeatureBuilder;
import org.geotools.referencing.crs.DefaultGeographicCRS;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;
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 insert a Geometry from WKT.
*
* @author MarcoZ
* @since BEAM 5
*/
@ActionID(
category = "File",
id = "org.esa.snap.rcp.actions.vector.InsertWktGeometryAction"
)
@ActionRegistration(
displayName = "#CTL_InsertWktGeometryAction_MenuText",
lazy = false
)
@ActionReferences({
@ActionReference(path = "Menu/Vector", position = 11, separatorBefore = 10),
@ActionReference(path = "Context/ProductSceneView", position = 0)
})
@NbBundle.Messages({
"CTL_InsertWktGeometryAction_DialogTitle=Geometry from WKT",
"CTL_InsertWktGeometryAction_MenuText=Geometry from WKT",
"CTL_InsertWktGeometryAction_ShortDescription=Creates a geomtry from well-known-text (WKT) representation."
})
public class InsertWktGeometryAction extends AbstractAction implements ContextAwareAction,LookupListener {
private static final String DLG_TITLE = "Geometry from WKT";
private Lookup.Result<ProductSceneView> result;
private Lookup lookup;
private long currentFeatureId = System.nanoTime();
public InsertWktGeometryAction(){
this(Utilities.actionsGlobalContext());
}
public InsertWktGeometryAction(Lookup lookup) {
super(Bundle.CTL_InsertWktGeometryAction_MenuText());
this.lookup = lookup;
result = lookup.lookupResult(ProductSceneView.class);
result.addLookupListener(WeakListeners.create(LookupListener.class,this,result));
setEnabled(false);
}
@Override
public Action createContextAwareInstance(Lookup actionContext) {
return new InsertWktGeometryAction(actionContext);
}
@Override
public void resultChanged(LookupEvent lookupEvent) {
ProductSceneView productSceneView = lookup.lookup(ProductSceneView.class);
setEnabled(productSceneView != null);
}
@Override
public void actionPerformed(ActionEvent event) {
JTextArea textArea = new JTextArea(16, 32);
textArea.setEditable(true);
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);
SnapApp snapApp = SnapApp.getDefault();
ModalDialog modalDialog = new ModalDialog(snapApp.getMainFrame(),
Bundle.CTL_InsertWktGeometryAction_DialogTitle(),
ModalDialog.ID_OK_CANCEL, null);
modalDialog.setContent(contentPanel);
modalDialog.center();
if (modalDialog.show() == ModalDialog.ID_OK) {
String wellKnownText = textArea.getText();
if (wellKnownText == null || wellKnownText.isEmpty()) {
return;
}
ProductSceneView sceneView = snapApp.getSelectedProductSceneView();
VectorDataLayer vectorDataLayer = InsertFigureInteractorInterceptor.getActiveVectorDataLayer(sceneView);
if (vectorDataLayer == null) {
return;
}
SimpleFeatureType wktFeatureType = PlainFeatureFactory.createDefaultFeatureType(DefaultGeographicCRS.WGS84);
ListFeatureCollection newCollection = new ListFeatureCollection(wktFeatureType);
SimpleFeatureBuilder featureBuilder = new SimpleFeatureBuilder(wktFeatureType);
SimpleFeature wktFeature = featureBuilder.buildFeature("ID" + Long.toHexString(currentFeatureId++));
Geometry geometry;
try {
geometry = new WKTReader().read(wellKnownText);
} catch (ParseException e) {
snapApp.handleError("Failed to convert WKT into geometry", e);
return;
}
wktFeature.setDefaultGeometry(geometry);
newCollection.add(wktFeature);
FeatureCollection<SimpleFeatureType, SimpleFeature> productFeatures = FeatureUtils.clipFeatureCollectionToProductBounds(
newCollection,
sceneView.getProduct(),
null,
ProgressMonitor.NULL);
if (productFeatures.isEmpty()) {
Dialogs.showError(Bundle.CTL_InsertWktGeometryAction_MenuText(),
"The geometry is not contained in the product.");
} else {
vectorDataLayer.getVectorDataNode().getFeatureCollection().addAll(productFeatures);
}
}
}
}