/* * Geotoolkit - An Open Source Java GIS Toolkit * http://www.geotoolkit.org * * (C) 2014, Geomatys * * 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; * version 3 of the License. * * 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. */ package org.geotoolkit.gui.javafx.chooser; 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; import java.awt.Graphics2D; import java.awt.image.BufferedImage; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; import javafx.application.Platform; import javafx.collections.FXCollections; import javafx.embed.swing.SwingFXUtils; import javafx.scene.control.ListCell; import javafx.scene.control.ListView; import javafx.scene.control.ScrollPane; import javafx.scene.control.SelectionMode; import javafx.scene.control.Tooltip; import javafx.scene.image.ImageView; import javafx.scene.layout.BorderPane; import org.apache.sis.feature.FeatureExt; import org.apache.sis.storage.DataStoreException; import org.geotoolkit.data.FeatureCollection; import org.geotoolkit.data.FeatureStore; import org.geotoolkit.data.query.QueryBuilder; import org.geotoolkit.data.session.Session; import org.geotoolkit.factory.FactoryFinder; import org.geotoolkit.factory.Hints; import org.geotoolkit.util.NamesExt; import org.opengis.util.GenericName; import org.geotoolkit.filter.DefaultFilterFactory2; import org.geotoolkit.internal.GeotkFX; import org.geotoolkit.map.CoverageMapLayer; import org.geotoolkit.map.FeatureMapLayer; import org.geotoolkit.map.MapBuilder; import org.geotoolkit.map.MapLayer; import org.geotoolkit.storage.DataStoreFactory; import org.geotoolkit.storage.coverage.CoverageReference; import org.geotoolkit.storage.coverage.CoverageStore; import org.geotoolkit.style.MutableStyle; import org.geotoolkit.style.MutableStyleFactory; import org.geotoolkit.style.RandomStyleBuilder; import org.geotoolkit.style.StyleConstants; import org.opengis.feature.AttributeType; import org.opengis.feature.FeatureType; import org.opengis.filter.FilterFactory2; /** * * @author Johann Sorel (Geomatys) */ public class FXLayerChooser extends BorderPane{ private static final Comparator SORTER = new Comparator() { @Override public int compare(Object o1, Object o2) { final String str1; final String str2; if(o1 instanceof FeatureType){ str1 = ((FeatureType)o1).getName().tip().toString(); }else if(o1 instanceof GenericName){ str1 = ((GenericName)o1).tip().toString(); }else{ str1 = o1.toString(); } if(o2 instanceof FeatureType){ str2 = ((FeatureType)o2).getName().tip().toString(); }else if(o2 instanceof GenericName){ str2 = ((GenericName)o2).tip().toString(); }else{ str2 = o2.toString(); } return str1.compareToIgnoreCase(str2); } }; private Object source = null; public final ListView<Object> layerNames = new ListView<>(); private final ScrollPane scroll = new ScrollPane(layerNames); public FXLayerChooser() { scroll.setFitToHeight(true); scroll.setFitToWidth(true); setCenter(scroll); layerNames.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE); layerNames.setCellFactory((ListView<Object> param) -> new LayerCell()); } public List<MapLayer> getLayers() throws DataStoreException{ final MutableStyleFactory styleFactory = (MutableStyleFactory) FactoryFinder.getStyleFactory( new Hints(Hints.STYLE_FACTORY, MutableStyleFactory.class)); final FilterFactory2 FF = new DefaultFilterFactory2(); final MutableStyleFactory SF = styleFactory; final List values = layerNames.getSelectionModel().getSelectedItems(); final List<MapLayer> layers = new ArrayList<>(); if(values != null){ for(Object value : values){ final GenericName name; if(value instanceof FeatureType){ name = ((FeatureType) value).getName(); }else{ name = (GenericName) value; } if(source instanceof FeatureStore){ final FeatureStore store = (FeatureStore) source; final DataStoreFactory factory = store.getFactory(); final Session session = store.createSession(true); final FeatureCollection collection = session.getFeatureCollection(QueryBuilder.all(name.toString())); final MutableStyle style; if(factory.getMetadata().produceStyledFeature()){ //do not create a style, each feature defines it's own symbolizers style = SF.style(); }else{ style = RandomStyleBuilder.createRandomVectorStyle(collection.getFeatureType()); } final FeatureMapLayer layer = MapBuilder.createFeatureLayer(collection, style); layer.setName(name.tip().toString()); layer.setDescription(styleFactory.description(name.tip().toString(), name.toString())); layer.setUserProperty(MapLayer.USERKEY_STYLED_FEATURE, factory.getMetadata().produceStyledFeature()); layers.add(layer); }else if(source instanceof CoverageStore){ final CoverageStore store = (CoverageStore) source; final CoverageReference ref = store.getCoverageReference(name); final MutableStyle style = styleFactory.style(StyleConstants.DEFAULT_RASTER_SYMBOLIZER); final CoverageMapLayer layer = MapBuilder.createCoverageLayer(ref, style); layer.setName(name.tip().toString()); layer.setDescription(styleFactory.description(name.tip().toString(), name.toString())); layers.add(layer); } } } return layers; } public void setSource(Object source) throws DataStoreException { this.source = source; final List firstCandidates = new ArrayList<>(); final List secondCandidates = new ArrayList<>(); if(source instanceof FeatureStore){ final FeatureStore store = (FeatureStore) source; for(GenericName name : store.getNames()){ final FeatureType ft = store.getFeatureType(name.toString()); final AttributeType<?> geomAtt = FeatureExt.getDefaultGeometryAttribute(ft); if(geomAtt != null){ firstCandidates.add(ft); }else{ secondCandidates.add(ft); } } } if(source instanceof CoverageStore){ final CoverageStore store = (CoverageStore) source; firstCandidates.addAll(store.getNames()); } Collections.sort(firstCandidates, SORTER); if(!secondCandidates.isEmpty()){ Collections.sort(secondCandidates, SORTER); firstCandidates.addAll(secondCandidates); } final Runnable setList = () -> layerNames.setItems(FXCollections.observableArrayList(firstCandidates)); if (Platform.isFxApplicationThread()) { setList.run(); } else { Platform.runLater(setList); } } public Object getSource() { return source; } private final class LayerCell extends ListCell{ @Override protected void updateItem(Object item, boolean empty) { super.updateItem(item, empty); setText(""); setTooltip(null); setGraphic(null); Object value = item; if(value instanceof FeatureType){ final FeatureType ft = (FeatureType) value; final FeatureStore store = (FeatureStore) getSource(); final AttributeType<?> desc = FeatureExt.getDefaultGeometryAttribute(ft); if(desc != null){ BufferedImage icon; final Class binding = desc.getValueClass(); if(Point.class.isAssignableFrom(binding)){ icon = GeotkFX.getBufferedImage("edit_single_point"); }else if(MultiPoint.class.isAssignableFrom(binding)){ icon = GeotkFX.getBufferedImage("edit_multi_point"); }else if(LineString.class.isAssignableFrom(binding)){ icon = GeotkFX.getBufferedImage("edit_single_line"); }else if(MultiLineString.class.isAssignableFrom(binding)){ icon = GeotkFX.getBufferedImage("edit_multi_line"); }else if(Polygon.class.isAssignableFrom(binding)){ icon = GeotkFX.getBufferedImage("edit_single_polygon"); }else if(MultiPolygon.class.isAssignableFrom(binding)){ icon = GeotkFX.getBufferedImage("edit_multi_polygon"); }else{ icon = (BufferedImage) GeotkFX.EMPTY_ICON_16; } boolean editable = false; try { if(store.isWritable(ft.getName().toString())){ editable = true; } } catch (DataStoreException ex) {} if(!editable){ final BufferedImage img = new BufferedImage( icon.getWidth(), icon.getHeight(), BufferedImage.TYPE_INT_ARGB); final Graphics2D g = img.createGraphics(); g.drawImage(icon, 0, 0, null); final BufferedImage lock = GeotkFX.getBufferedImage("lock"); g.drawImage(lock, 0, 0, null); icon = img; } setGraphic(new ImageView(SwingFXUtils.toFXImage(icon, null))); } value = ft.getName(); } if(value instanceof GenericName){ final GenericName name = (GenericName) value; setText(name.tip().toString()); setTooltip(new Tooltip(NamesExt.toExpandedString(name))); } } } }