/*
* uDig - User Friendly Desktop Internet GIS client
* (C) MangoSystem - www.mangosystem.com
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* (http://www.eclipse.org/legal/epl-v10.html), and the Refractions BSD
* License v1.0 (http://udig.refractions.net/files/bsd3-v10.html).
*/
package org.locationtech.udig.processingtoolbox.internal.ui;
import java.util.Map;
import java.util.Map.Entry;
import java.util.logging.Logger;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Widget;
import org.geotools.data.FeatureSource;
import org.geotools.data.Parameter;
import org.geotools.data.simple.SimpleFeatureCollection;
import org.geotools.process.spatialstatistics.core.Params;
import org.geotools.process.spatialstatistics.transformation.ForceCRSFeatureCollection;
import org.geotools.util.logging.Logging;
import org.locationtech.udig.processingtoolbox.styler.MapUtils;
import org.locationtech.udig.processingtoolbox.styler.MapUtils.FieldType;
import org.locationtech.udig.processingtoolbox.styler.MapUtils.VectorLayerType;
import org.locationtech.udig.project.ILayer;
import org.locationtech.udig.project.IMap;
import org.opengis.feature.simple.SimpleFeatureType;
import org.opengis.feature.type.AttributeDescriptor;
import org.opengis.feature.type.GeometryDescriptor;
import com.vividsolutions.jts.geom.LineString;
import com.vividsolutions.jts.geom.MultiLineString;
import com.vividsolutions.jts.geom.MultiPoint;
import com.vividsolutions.jts.geom.MultiPolygon;
import com.vividsolutions.jts.geom.Point;
import com.vividsolutions.jts.geom.Polygon;
/**
* FeatureCollection Layer Data control
*
* @author Minpa Lee, MangoSystem
*
* @source $URL$
*/
public class FeatureCollectionDataWidget extends AbstractToolboxWidget {
protected static final Logger LOGGER = Logging.getLogger(FeatureCollectionDataWidget.class);
private IMap map;
public FeatureCollectionDataWidget(IMap map) {
this.map = map;
}
public void create(final Composite parent, final int style,
final Map<String, Object> processParams, final Parameter<?> param,
final Map<Widget, Map<String, Object>> uiParams) {
composite = new Composite(parent, style);
composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 1, 1));
GridLayout layout = new GridLayout(1, false);
layout.marginTop = 0;
layout.marginBottom = 0;
layout.marginLeft = 0;
layout.marginRight = 0;
layout.marginWidth = 0;
layout.marginHeight = 0;
layout.horizontalSpacing = 0;
layout.verticalSpacing = 0;
composite.setLayout(layout);
final Combo cboSfLayer = new Combo(composite, SWT.NONE | SWT.DROP_DOWN | SWT.READ_ONLY);
cboSfLayer.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
Map<String, Object> metadata = param.metadata;
if (metadata == null || metadata.size() == 0) {
fillLayers(map, cboSfLayer, VectorLayerType.ALL);
} else {
if (metadata.containsKey(Params.FEATURES)) {
String val = metadata.get(Params.FEATURES).toString();
if (val.equalsIgnoreCase(VectorLayerType.ALL.toString())) {
fillLayers(map, cboSfLayer, VectorLayerType.ALL);
} else if (val.equalsIgnoreCase(VectorLayerType.POINT.toString())) {
fillLayers(map, cboSfLayer, VectorLayerType.POINT);
} else if (val.equalsIgnoreCase(VectorLayerType.LINESTRING.toString())) {
fillLayers(map, cboSfLayer, VectorLayerType.LINESTRING);
} else if (val.equalsIgnoreCase(VectorLayerType.POLYGON.toString())) {
fillLayers(map, cboSfLayer, VectorLayerType.POLYGON);
} else if (val.equalsIgnoreCase(VectorLayerType.POLYLINE.toString())) {
fillLayers(map, cboSfLayer, VectorLayerType.POLYLINE);
} else if (val.equalsIgnoreCase(VectorLayerType.MULTIPART.toString())) {
fillLayers(map, cboSfLayer, VectorLayerType.MULTIPART);
}
} else {
fillLayers(map, cboSfLayer, VectorLayerType.ALL);
}
}
cboSfLayer.setData(param.key);
cboSfLayer.addModifyListener(new ModifyListener() {
@Override
public void modifyText(ModifyEvent e) {
SimpleFeatureCollection sfc = MapUtils.getFeatures(map, cboSfLayer.getText());
if (sfc.getSchema().getCoordinateReferenceSystem() == null) {
sfc = new ForceCRSFeatureCollection(sfc, map.getViewportModel().getCRS());
}
processParams.put(param.key, sfc);
// related field selection = Category, "TypeName.FieldType"
SimpleFeatureType schema = sfc.getSchema();
for (Entry<Widget, Map<String, Object>> entrySet : uiParams.entrySet()) {
for (Entry<String, Object> kvpSet : entrySet.getValue().entrySet()) {
String category = kvpSet.getKey();
String value = kvpSet.getValue().toString();
String typeName = value.split("\\.")[0]; //$NON-NLS-1$
String fieldType = value.split("\\.")[1]; //$NON-NLS-1$
if (typeName.equals(param.key)) {
if (category.endsWith(Params.FIELD)) {
// FieldType = ALL, String, Number, Integer, Double
Combo cboField = (Combo) entrySet.getKey();
fillFields(cboField, schema, fieldType);
} else if (category.endsWith(Params.FIELDS)) {
// FieldType = ALL, String, Number, Integer, Double
Combo cboField = (Combo) entrySet.getKey();
fillFields(cboField, schema, fieldType);
}
}
}
}
}
});
composite.pack();
}
private void fillLayers(IMap map, Combo combo, VectorLayerType layerType) {
combo.removeAll();
for (ILayer layer : map.getMapLayers()) {
if (layer.getName() != null && layer.hasResource(FeatureSource.class)) {
GeometryDescriptor descriptor = layer.getSchema().getGeometryDescriptor();
Class<?> geometryBinding = descriptor.getType().getBinding();
switch (layerType) {
case ALL:
combo.add(layer.getName());
break;
case POINT:
if (geometryBinding.isAssignableFrom(Point.class)
|| geometryBinding.isAssignableFrom(MultiPoint.class)) {
combo.add(layer.getName());
}
break;
case LINESTRING:
if (geometryBinding.isAssignableFrom(LineString.class)
|| geometryBinding.isAssignableFrom(MultiLineString.class)) {
combo.add(layer.getName());
}
break;
case POLYGON:
if (geometryBinding.isAssignableFrom(Polygon.class)
|| geometryBinding.isAssignableFrom(MultiPolygon.class)) {
combo.add(layer.getName());
}
break;
case POLYLINE:
if (geometryBinding.isAssignableFrom(Polygon.class)
|| geometryBinding.isAssignableFrom(MultiPolygon.class)
|| geometryBinding.isAssignableFrom(LineString.class)
|| geometryBinding.isAssignableFrom(MultiLineString.class)) {
combo.add(layer.getName());
}
break;
case MULTIPART:
if (geometryBinding.isAssignableFrom(MultiPoint.class)
|| geometryBinding.isAssignableFrom(MultiLineString.class)
|| geometryBinding.isAssignableFrom(MultiPolygon.class)) {
combo.add(layer.getName());
}
break;
default:
break;
}
}
}
}
private void fillFields(Combo combo, SimpleFeatureType schema, String fieldType) {
if (fieldType.equalsIgnoreCase(FieldType.ALL.toString())) {
fillFields(combo, schema, FieldType.ALL);
} else if (fieldType.equalsIgnoreCase(FieldType.String.toString())) {
fillFields(combo, schema, FieldType.String);
} else if (fieldType.equalsIgnoreCase(FieldType.Number.toString())) {
fillFields(combo, schema, FieldType.Number);
} else if (fieldType.equalsIgnoreCase(FieldType.Integer.toString())) {
fillFields(combo, schema, FieldType.Integer);
} else if (fieldType.equalsIgnoreCase(FieldType.Double.toString())) {
fillFields(combo, schema, FieldType.Double);
}
}
private void fillFields(Combo combo, SimpleFeatureType schema, FieldType fieldType) {
String selectedValue = combo.getText() == null ? null : combo.getText();
combo.removeAll();
for (AttributeDescriptor descriptor : schema.getAttributeDescriptors()) {
if (descriptor instanceof GeometryDescriptor) {
continue;
}
Class<?> binding = descriptor.getType().getBinding();
switch (fieldType) {
case ALL:
combo.add(descriptor.getLocalName());
break;
case Double:
if (Double.class.isAssignableFrom(binding) || Float.class.isAssignableFrom(binding)) {
combo.add(descriptor.getLocalName());
}
break;
case Integer:
if (Short.class.isAssignableFrom(binding)
|| Integer.class.isAssignableFrom(binding)
|| Long.class.isAssignableFrom(binding)) {
combo.add(descriptor.getLocalName());
}
break;
case Number:
if (Number.class.isAssignableFrom(binding)) {
combo.add(descriptor.getLocalName());
}
break;
case String:
if (String.class.isAssignableFrom(binding)) {
combo.add(descriptor.getLocalName());
}
break;
}
}
if (selectedValue != null) {
if (combo.indexOf(selectedValue) == -1) {
combo.add(selectedValue);
}
combo.setText(selectedValue);
}
}
}