From 7725ae1388fb3b0ff5721566bf2e9e6c4b957675 Mon Sep 17 00:00:00 2001 From: Mathieu Baudier Date: Sat, 28 May 2011 13:31:33 +0000 Subject: [PATCH] Improve GIS NEW - bug 31: Add Swing based map viewer in RCP https://bugzilla.argeo.org/show_bug.cgi?id=31 git-svn-id: https://svn.argeo.org/commons/trunk@4542 4cfe0d0a-d680-48aa-b62c-e0a02a3f76cc --- .../META-INF/MANIFEST.MF | 1 + .../rap/openlayers/OpenLayersMapViewer.java | 5 +- .../META-INF/MANIFEST.MF | 2 + .../gis/ui/rcp/swing/SwingMapViewer.java | 47 +++++++- .../org.argeo.gis.ui/META-INF/MANIFEST.MF | 2 + .../org/argeo/gis/ui/AbstractMapViewer.java | 16 ++- .../main/java/org/argeo/gis/ui/MapViewer.java | 14 ++- .../gis/ui/views/FeatureSourcesView.java | 7 +- .../argeo/geotools/styling/StylingUtils.java | 103 ++++++++++++++++++ 9 files changed, 180 insertions(+), 17 deletions(-) create mode 100644 gis/runtime/org.argeo.gis.geotools/src/main/java/org/argeo/geotools/styling/StylingUtils.java diff --git a/gis/plugins/org.argeo.gis.ui.rap.openlayers/META-INF/MANIFEST.MF b/gis/plugins/org.argeo.gis.ui.rap.openlayers/META-INF/MANIFEST.MF index 2c9e38191..da51ec2ba 100644 --- a/gis/plugins/org.argeo.gis.ui.rap.openlayers/META-INF/MANIFEST.MF +++ b/gis/plugins/org.argeo.gis.ui.rap.openlayers/META-INF/MANIFEST.MF @@ -22,6 +22,7 @@ Import-Package: com.vividsolutions.jts.geom;version="1.10.0", org.geotools.feature, org.geotools.map, org.geotools.map.event, + org.geotools.styling, org.opengis.feature, org.opengis.feature.simple, org.opengis.feature.type, diff --git a/gis/plugins/org.argeo.gis.ui.rap.openlayers/src/main/java/org/argeo/gis/ui/rap/openlayers/OpenLayersMapViewer.java b/gis/plugins/org.argeo.gis.ui.rap.openlayers/src/main/java/org/argeo/gis/ui/rap/openlayers/OpenLayersMapViewer.java index 59d99a41e..d542ab104 100644 --- a/gis/plugins/org.argeo.gis.ui.rap.openlayers/src/main/java/org/argeo/gis/ui/rap/openlayers/OpenLayersMapViewer.java +++ b/gis/plugins/org.argeo.gis.ui.rap.openlayers/src/main/java/org/argeo/gis/ui/rap/openlayers/OpenLayersMapViewer.java @@ -164,11 +164,10 @@ public class OpenLayersMapViewer extends AbstractMapViewer implements } @Override - protected void addFeatureSource(String path, - FeatureSource featureSource) { + protected void addFeatureSource(String layerId, + FeatureSource featureSource, Object style) { FeatureIterator featureIterator = null; try { - String layerId = path; VectorLayer vectorLayer = new VectorLayer(featureSource.getName() .toString()); vectorLayer.setObjAttr("id", layerId); diff --git a/gis/plugins/org.argeo.gis.ui.rcp.swing/META-INF/MANIFEST.MF b/gis/plugins/org.argeo.gis.ui.rcp.swing/META-INF/MANIFEST.MF index 4a2380d14..ec2f58143 100644 --- a/gis/plugins/org.argeo.gis.ui.rcp.swing/META-INF/MANIFEST.MF +++ b/gis/plugins/org.argeo.gis.ui.rcp.swing/META-INF/MANIFEST.MF @@ -7,6 +7,7 @@ Bundle-RequiredExecutionEnvironment: J2SE-1.5 Import-Package: com.vividsolutions.jts.geom;version="1.10.0", javax.jcr;version="2.0.0", org.argeo.geotools.jcr, + org.argeo.geotools.styling, org.argeo.gis.ui, org.eclipse.swt, org.eclipse.swt.awt, @@ -17,6 +18,7 @@ Import-Package: com.vividsolutions.jts.geom;version="1.10.0", org.geotools.map, org.geotools.renderer, org.geotools.renderer.lite, + org.geotools.styling, org.geotools.swing, org.geotools.swing.event, org.geotools.swing.tool, diff --git a/gis/plugins/org.argeo.gis.ui.rcp.swing/src/main/java/org/argeo/gis/ui/rcp/swing/SwingMapViewer.java b/gis/plugins/org.argeo.gis.ui.rcp.swing/src/main/java/org/argeo/gis/ui/rcp/swing/SwingMapViewer.java index dd272b45a..41c03ab21 100644 --- a/gis/plugins/org.argeo.gis.ui.rcp.swing/src/main/java/org/argeo/gis/ui/rcp/swing/SwingMapViewer.java +++ b/gis/plugins/org.argeo.gis.ui.rcp.swing/src/main/java/org/argeo/gis/ui/rcp/swing/SwingMapViewer.java @@ -2,26 +2,39 @@ package org.argeo.gis.ui.rcp.swing; import java.awt.Color; import java.awt.Frame; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; import javax.jcr.Node; import org.argeo.geotools.jcr.GeoJcrMapper; +import org.argeo.geotools.styling.StylingUtils; import org.argeo.gis.ui.AbstractMapViewer; import org.eclipse.swt.SWT; import org.eclipse.swt.awt.SWT_AWT; import org.eclipse.swt.widgets.Composite; import org.geotools.data.FeatureSource; +import org.geotools.geometry.jts.ReferencedEnvelope; import org.geotools.map.DefaultMapContext; +import org.geotools.map.DefaultMapLayer; +import org.geotools.map.MapLayer; import org.geotools.renderer.lite.StreamingRenderer; +import org.geotools.styling.Style; import org.geotools.swing.JMapPane; import org.opengis.feature.simple.SimpleFeature; import org.opengis.feature.simple.SimpleFeatureType; +/** Map viewer implementation based on GeoTools Swing components. */ public class SwingMapViewer extends AbstractMapViewer { private Composite embedded; private JMapPane mapPane; private VersatileZoomTool versatileZoomTool; + private Map mapLayers = Collections + .synchronizedMap(new HashMap()); + public SwingMapViewer(Node context, GeoJcrMapper geoJcrMapper, Composite parent) { super(context, geoJcrMapper); @@ -40,11 +53,35 @@ public class SwingMapViewer extends AbstractMapViewer { } @Override - protected void addFeatureSource(String path, - FeatureSource featureSource) { - // TODO: deal with style and rasters - mapPane.getMapContext().addLayer(featureSource, null); - mapPane.reset(); + protected void addFeatureSource(String layerId, + FeatureSource featureSource, + Object style) { + if (style == null) + style = StylingUtils.createLineStyle("BLACK", 1); + + MapLayer mapLayer = new DefaultMapLayer(featureSource, (Style) style); + addMapLayer(layerId, mapLayer); + } + + protected void addMapLayer(String layerId, MapLayer mapLayer) { + mapLayers.put(layerId, mapLayer); + mapPane.getMapContext().addLayer(mapLayer); + } + + public void addLayer(String layerId, Collection collection, Object style) { + if (style == null) + style = StylingUtils.createLineStyle("BLACK", 1); + MapLayer mapLayer = new DefaultMapLayer(collection, (Style) style); + addMapLayer(layerId, mapLayer); + } + + public void setStyle(String layerId, Object style) { + mapLayers.get(layerId).setStyle((Style) style); + } + + public void setAreaOfInterest(ReferencedEnvelope areaOfInterest) { + // mapPane.getMapContext().setAreaOfInterest(areaOfInterest); + mapPane.setDisplayArea(areaOfInterest); } } diff --git a/gis/plugins/org.argeo.gis.ui/META-INF/MANIFEST.MF b/gis/plugins/org.argeo.gis.ui/META-INF/MANIFEST.MF index 3b8758230..04cf35700 100644 --- a/gis/plugins/org.argeo.gis.ui/META-INF/MANIFEST.MF +++ b/gis/plugins/org.argeo.gis.ui/META-INF/MANIFEST.MF @@ -25,8 +25,10 @@ Import-Package: javax.jcr;version="2.0.0", org.eclipse.ui.forms.editor, org.eclipse.ui.forms.widgets, org.geotools.data, + org.geotools.geometry.jts, org.geotools.map, org.geotools.map.event, + org.geotools.styling, org.opengis.feature.simple, org.opengis.feature.type, org.postgresql;resolution:=optional diff --git a/gis/plugins/org.argeo.gis.ui/src/main/java/org/argeo/gis/ui/AbstractMapViewer.java b/gis/plugins/org.argeo.gis.ui/src/main/java/org/argeo/gis/ui/AbstractMapViewer.java index d767f2277..eeb9a2183 100644 --- a/gis/plugins/org.argeo.gis.ui/src/main/java/org/argeo/gis/ui/AbstractMapViewer.java +++ b/gis/plugins/org.argeo.gis.ui/src/main/java/org/argeo/gis/ui/AbstractMapViewer.java @@ -18,6 +18,7 @@ import org.argeo.jcr.CollectionNodeIterator; import org.argeo.jcr.gis.GisTypes; import org.eclipse.swt.widgets.Composite; import org.geotools.data.FeatureSource; +import org.geotools.geometry.jts.ReferencedEnvelope; import org.opengis.feature.simple.SimpleFeature; import org.opengis.feature.simple.SimpleFeatureType; @@ -35,8 +36,9 @@ public abstract class AbstractMapViewer implements MapViewer { private Set listeners = Collections .synchronizedSet(new HashSet()); - protected abstract void addFeatureSource(String path, - FeatureSource featureSource); + protected abstract void addFeatureSource(String layerId, + FeatureSource featureSource, + Object style); public AbstractMapViewer(Node context, GeoJcrMapper geoJcrMapper) { super(); @@ -44,11 +46,13 @@ public abstract class AbstractMapViewer implements MapViewer { this.geoJcrMapper = geoJcrMapper; } - public void addLayer(Node layer) { + public void addLayer(Node layer, Object style) { try { if (layer.isNodeType(GisTypes.GIS_FEATURE_SOURCE)) { addFeatureSource(layer.getPath(), - geoJcrMapper.getFeatureSource(layer)); + geoJcrMapper.getFeatureSource(layer), style); + } else { + throw new ArgeoException("Unsupported layer " + layer); } } catch (Exception e) { throw new ArgeoException("Cannot add layer " + layer, e); @@ -103,4 +107,8 @@ public abstract class AbstractMapViewer implements MapViewer { return control; } + public GeoJcrMapper getGeoJcrMapper() { + return geoJcrMapper; + } + } diff --git a/gis/plugins/org.argeo.gis.ui/src/main/java/org/argeo/gis/ui/MapViewer.java b/gis/plugins/org.argeo.gis.ui/src/main/java/org/argeo/gis/ui/MapViewer.java index 701ef59a2..8a56e93c3 100644 --- a/gis/plugins/org.argeo.gis.ui/src/main/java/org/argeo/gis/ui/MapViewer.java +++ b/gis/plugins/org.argeo.gis.ui/src/main/java/org/argeo/gis/ui/MapViewer.java @@ -1,12 +1,19 @@ package org.argeo.gis.ui; +import java.util.Collection; + import javax.jcr.Node; import javax.jcr.NodeIterator; +import org.argeo.geotools.jcr.GeoJcrMapper; import org.eclipse.swt.widgets.Composite; +import org.geotools.geometry.jts.ReferencedEnvelope; +/** Viewer for a map, relying on JCR. */ public interface MapViewer { - public void addLayer(Node layer); + public void addLayer(Node layer, Object style); + + public void addLayer(String layerId, Collection collection, Object style); public NodeIterator getSelectedFeatures(); @@ -16,4 +23,9 @@ public interface MapViewer { public void removeMapViewerListener(MapViewerListener listener); + public void setAreaOfInterest(ReferencedEnvelope areaOfInterest); + + public void setStyle(String layerId, Object style); + + public GeoJcrMapper getGeoJcrMapper(); } diff --git a/gis/plugins/org.argeo.gis.ui/src/main/java/org/argeo/gis/ui/views/FeatureSourcesView.java b/gis/plugins/org.argeo.gis.ui/src/main/java/org/argeo/gis/ui/views/FeatureSourcesView.java index b13daaf83..5a22e27e6 100644 --- a/gis/plugins/org.argeo.gis.ui/src/main/java/org/argeo/gis/ui/views/FeatureSourcesView.java +++ b/gis/plugins/org.argeo.gis.ui/src/main/java/org/argeo/gis/ui/views/FeatureSourcesView.java @@ -14,7 +14,6 @@ import org.eclipse.jface.viewers.ColumnLabelProvider; import org.eclipse.jface.viewers.DoubleClickEvent; import org.eclipse.jface.viewers.IDoubleClickListener; import org.eclipse.jface.viewers.IStructuredSelection; -import org.eclipse.jface.viewers.LabelProvider; import org.eclipse.jface.viewers.TreeViewer; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Image; @@ -60,13 +59,13 @@ public class FeatureSourcesView extends ViewPart implements IEditorPart ed = getSite().getWorkbenchWindow().getActivePage() .getActiveEditor(); if (ed instanceof DefaultMapEditor) { - ((DefaultMapEditor) ed).getMapViewer().addLayer(node); + ((DefaultMapEditor) ed).getMapViewer().addLayer(node, null); } else if (ed instanceof FormEditor) { IFormPage activePage = ((FormEditor) ed) .getActivePageInstance(); if (activePage instanceof MapFormPage) { - ((MapFormPage) activePage).getMapViewer() - .addLayer(node); + ((MapFormPage) activePage).getMapViewer().addLayer( + node, null); } } } diff --git a/gis/runtime/org.argeo.gis.geotools/src/main/java/org/argeo/geotools/styling/StylingUtils.java b/gis/runtime/org.argeo.gis.geotools/src/main/java/org/argeo/geotools/styling/StylingUtils.java new file mode 100644 index 000000000..a4811ac87 --- /dev/null +++ b/gis/runtime/org.argeo.gis.geotools/src/main/java/org/argeo/geotools/styling/StylingUtils.java @@ -0,0 +1,103 @@ +package org.argeo.geotools.styling; + +import java.awt.Color; + +import org.argeo.ArgeoException; +import org.geotools.factory.CommonFactoryFinder; +import org.geotools.filter.text.cql2.CQL; +import org.geotools.filter.text.cql2.CQLException; +import org.geotools.styling.FeatureTypeStyle; +import org.geotools.styling.LineSymbolizer; +import org.geotools.styling.Rule; +import org.geotools.styling.Stroke; +import org.geotools.styling.Style; +import org.geotools.styling.StyleFactory; +import org.opengis.filter.Filter; +import org.opengis.filter.FilterFactory; + +/** Utilities related to GeoTools styling */ +public class StylingUtils { + static StyleFactory styleFactory = CommonFactoryFinder + .getStyleFactory(null); + static FilterFactory filterFactory = CommonFactoryFinder + .getFilterFactory(null); + + /** + * Style for a line + * + * @param color + * the AWT color in upper case + * @param width + * the width of the line + * @param cqlFilter + * filter in CQL formqt restricting the feqture upon which the + * style will apply + */ + public static Style createLineStyle(String color, Integer width) { + Rule rule = styleFactory.createRule(); + rule.symbolizers().add(createLineSymbolizer(color, width)); + FeatureTypeStyle fts = styleFactory + .createFeatureTypeStyle(new Rule[] { rule }); + Style style = styleFactory.createStyle(); + style.featureTypeStyles().add(fts); + return style; + } + + public static Style createFilteredLineStyle(String cqlFilter, + String matchedColor, Integer matchedWidth, String unmatchedColor, + Integer unmatchedWidth) { + // selection filter + Filter filter; + try { + filter = CQL.toFilter(cqlFilter); + } catch (CQLException e) { + throw new ArgeoException("Cannot parse CQL filter: " + cqlFilter, e); + } + + Rule[] rules; + // matched + Rule ruleMatched = styleFactory.createRule(); + ruleMatched.symbolizers().add( + createLineSymbolizer(matchedColor, matchedWidth)); + ruleMatched.setFilter(filter); + + // unmatched + if (unmatchedColor != null) { + Rule ruleUnMatched = styleFactory.createRule(); + ruleUnMatched.symbolizers().add( + createLineSymbolizer(unmatchedColor, + unmatchedWidth != null ? unmatchedWidth + : matchedWidth)); + ruleUnMatched.setFilter(filterFactory.not(filter)); + rules = new Rule[] { ruleMatched, ruleUnMatched }; + } else { + rules = new Rule[] { ruleMatched }; + } + + FeatureTypeStyle fts = styleFactory.createFeatureTypeStyle(rules); + Style style = styleFactory.createStyle(); + style.featureTypeStyles().add(fts); + return style; + } + + public static LineSymbolizer createLineSymbolizer(String color, + Integer width) { + Stroke stroke = styleFactory.createStroke( + filterFactory.literal(stringToColor(color)), + filterFactory.literal(width)); + return styleFactory.createLineSymbolizer(stroke, null); + } + + /** + * Converts a string to a color, using reflection, so that other methods + * don't need AWT dependencies in their signature. Package protected and not + * public so that it has less impact on the overall signature. + */ + static Color stringToColor(String color) { + try { + return (Color) Color.class.getField(color).get(null); + } catch (Exception e) { + throw new ArgeoException("Color " + color + " not found", e); + } + } +} -- 2.30.2