/[schmitzm]/branches/2.0-GP14/src/skrueger/geotools/selection/FeatureMapLayerSelectionSynchronizer.java
ViewVC logotype

Annotation of /branches/2.0-GP14/src/skrueger/geotools/selection/FeatureMapLayerSelectionSynchronizer.java

Parent Directory Parent Directory | Revision Log Revision Log


Revision 476 - (hide annotations)
Fri Oct 16 14:40:47 2009 UTC (15 years, 4 months ago) by alfonx
Original Path: branches/1.0-gt2-2.6/src/skrueger/geotools/selection/FeatureMapLayerSelectionSynchronizer.java
File MIME type: text/plain
File size: 14933 byte(s)
* Improved GUI for UniqueValuesGUI
1 alfonx 244 /*******************************************************************************
2     * Copyright (c) 2009 Martin O. J. Schmitz.
3     *
4     * This file is part of the SCHMITZM library - a collection of utility
5 alfonx 256 * classes based on Java 1.6, focusing (not only) on Java Swing
6 alfonx 244 * and the Geotools library.
7     *
8     * The SCHMITZM project is hosted at:
9     * http://wald.intevation.org/projects/schmitzm/
10     *
11     * This program is free software; you can redistribute it and/or
12     * modify it under the terms of the GNU Lesser General Public License
13     * as published by the Free Software Foundation; either version 3
14     * of the License, or (at your option) any later version.
15     *
16     * This program is distributed in the hope that it will be useful,
17     * but WITHOUT ANY WARRANTY; without even the implied warranty of
18     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19     * GNU General Public License for more details.
20     *
21     * You should have received a copy of the GNU Lesser General Public License (license.txt)
22     * along with this program; if not, write to the Free Software
23     * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
24     * or try this link: http://www.gnu.org/licenses/lgpl.html
25     *
26     * Contributors:
27     * Martin O. J. Schmitz - initial API and implementation
28     * Stefan A. Krüger - additional utility classes
29     ******************************************************************************/
30 alfonx 97 /**
31     Copyright 2008 Stefan Alfons Krüger
32 alfonx 409
33 alfonx 97 atlas-framework - This file is part of the Atlas Framework
34    
35     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; either version 2.1 of the License, or (at your option) any later version.
36     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.
37     You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
38    
39     Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
40     Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Mehr Details finden Sie in der GNU Lesser General Public License.
41     Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
42     **/
43     package skrueger.geotools.selection;
44    
45 alfonx 419 import java.awt.RenderingHints;
46 alfonx 97 import java.beans.PropertyChangeEvent;
47     import java.beans.PropertyChangeListener;
48 alfonx 419 import java.util.HashMap;
49 alfonx 158 import java.util.HashSet;
50 alfonx 409 import java.util.Iterator;
51 alfonx 158 import java.util.Set;
52 alfonx 97 import java.util.Vector;
53    
54     import javax.swing.JTable;
55     import javax.swing.ListSelectionModel;
56     import javax.swing.event.ListSelectionListener;
57    
58 alfonx 455 import org.geotools.feature.FeatureCollection;
59 alfonx 97 import org.geotools.map.MapLayer;
60 alfonx 419 import org.geotools.renderer.GTRenderer;
61     import org.geotools.renderer.label.LabelCacheImpl;
62     import org.geotools.renderer.lite.StreamingRenderer;
63 alfonx 123 import org.geotools.styling.FeatureTypeStyle;
64 alfonx 97 import org.geotools.styling.Style;
65 alfonx 419 import org.geotools.styling.visitor.DuplicatingStyleVisitor;
66 mojays 325 import org.opengis.feature.simple.SimpleFeature;
67 alfonx 455 import org.opengis.feature.simple.SimpleFeatureType;
68 alfonx 158 import org.opengis.filter.identity.FeatureId;
69 alfonx 97
70 alfonx 158 import schmitzm.geotools.FilterUtil;
71 alfonx 438 import schmitzm.geotools.GTUtil;
72 alfonx 97 import schmitzm.geotools.gui.JMapPane;
73     import schmitzm.geotools.map.event.FeatureSelectedEvent;
74     import schmitzm.geotools.map.event.JMapPaneEvent;
75     import schmitzm.geotools.map.event.JMapPaneListener;
76     import schmitzm.geotools.styling.StylingUtil;
77 alfonx 111 import skrueger.geotools.MapPaneToolBar;
78 alfonx 224 import skrueger.geotools.StyledLayerInterface;
79 alfonx 97
80     /**
81     * This class keeps the selection of a (feature) {@link JTable} synchronized
82     * with the {@link StyledLayerSelectionModel} of a layer. This is done by
83     * implementing:
84     * <ul>
85     * <li>a {@link PropertyChangeListener} which listens to the
86     * {@link StyledLayerSelectionModel} and accordingly changes the {@link JTable}
87     * selection</li>
88     * <li>a {@link ListSelectionListener} which listens to the {@link JTable} and
89     * accordingly changes the {@link StyledLayerSelectionModel} selection</li>
90     * </ul>
91     * After creating, the instance of this synchronizer must be added as listener
92     * to both, the {@link StyledLayerSelectionModel} and the table's
93     * {@link ListSelectionModel}.
94     *
95     * @author <a href="mailto:[email protected]">Martin Schmitz</a>
96     * (University of Bonn/Germany)
97     */
98     public class FeatureMapLayerSelectionSynchronizer extends
99 alfonx 106 StyledLayerSelectionModelSynchronizer<StyledFeatureLayerSelectionModel>
100     implements JMapPaneListener {
101 alfonx 111 public static final String SELECTION_STYLING = "SELECTION";
102 alfonx 97 /**
103     * Holds the {@link MapLayer} to keep synchronized with the layer selection
104     * model.
105     */
106     protected final MapLayer mapLayer;
107 alfonx 224 protected final StyledLayerInterface<?> styledLayer;
108 alfonx 97 protected final JMapPane mapPane;
109 alfonx 111 private final MapPaneToolBar toolBar;
110 alfonx 419 private final HashMap<Object, Object> defaultGTRenderingHints;
111 alfonx 97
112     /**
113     * Creates a new synchronizer
114     *
115     * @param layerSelModel
116     * layer selection model to keep synchronized with the
117     * {@link MapLayer}
118     *
119     * @param mapLayer
120     * {@link MapLayer} to keep synchronized with.
121     */
122     public FeatureMapLayerSelectionSynchronizer(
123     StyledFeatureLayerSelectionModel layerSelModel,
124 alfonx 224 StyledLayerInterface<?> styledLayer, MapLayer mapLayer,
125 alfonx 455 JMapPane mapPane, MapPaneToolBar toolBar,
126     HashMap<Object, Object> defaultGTRenderingHints) {
127 alfonx 97
128     super(layerSelModel);
129 alfonx 224 this.styledLayer = styledLayer;
130 alfonx 97
131     this.mapLayer = mapLayer;
132     this.mapPane = mapPane;
133 alfonx 111 this.toolBar = toolBar;
134 alfonx 419 if (defaultGTRenderingHints != null)
135     this.defaultGTRenderingHints = defaultGTRenderingHints;
136 alfonx 455 else
137 alfonx 419 this.defaultGTRenderingHints = new HashMap<Object, Object>();
138 alfonx 97 }
139    
140     /**
141     * Called by {@link StyledLayerSelectionModel} when a the selection on other
142     * selection components (map, chart, ...) has changed. When calling this
143     *
144     * method changes the {@link MapLayer} selection according to the
145     * {@link StyledLayerSelectionModel} selection.
146     *
147     * @param evt
148     * an event
149     */
150     @Override
151     public void propertyChange(PropertyChangeEvent evt) {
152 alfonx 151
153     if (!isEnabled())
154     return;
155    
156 alfonx 97 if (!(evt instanceof StyledLayerSelectionEvent))
157     return;
158     StyledLayerSelectionEvent selEvt = (StyledLayerSelectionEvent) evt;
159     // Only react on own layer and ignore events invoked by
160     // this component itself
161     if (selEvt.getEmitter() != layerSelModel || selectionChangeCausedByMe)
162     return;
163     // Apply new selection on table (except this event is one of
164     // some more events)
165 alfonx 111 Vector<String> newSelection = layerSelModel.getSelection();
166 alfonx 97 if (newSelection == null)
167     return;
168    
169     // Avoid event circles in valueChanged(..)
170     selectionChangeCausedByMe = true;
171    
172     changeLayerStyle(newSelection);
173    
174     // Danger of event circles in valueChanged(..) banned
175     selectionChangeCausedByMe = false;
176     }
177    
178 alfonx 151 /**
179     * Changes the Style of the {@link MapLayer} to reflect changes of the
180     * selection.
181     *
182     * @param newSelection
183 alfonx 318 * A {@link Vector} of SimpleFeature-IDs that are selected.
184 alfonx 151 */
185 alfonx 111 private void changeLayerStyle(final Vector<String> newSelection) {
186 alfonx 97 try {
187 alfonx 455
188 alfonx 412 Style originalStyle = mapLayer.getStyle();
189 alfonx 97 if (newSelection.isEmpty()) {
190    
191 alfonx 412 // Check if the Style contains a SELECTION FTS
192 alfonx 455
193     FeatureTypeStyle[] clone = originalStyle.featureTypeStyles()
194     .toArray(new FeatureTypeStyle[] {}).clone();
195    
196 alfonx 412 for (FeatureTypeStyle fts : clone) {
197     if (fts.getName() != null
198     && fts.getName().equals(SELECTION_STYLING)) {
199     originalStyle.featureTypeStyles().remove(fts);
200 alfonx 455
201 alfonx 419 replaceRenderer();
202 alfonx 455 // mapPane.refresh();
203 alfonx 106
204 alfonx 412 return;
205     }
206     }
207    
208 alfonx 97 } else {
209 alfonx 100 LOGGER.debug("SELECTION .. change style");
210 alfonx 106
211 alfonx 123 // We take Style from the MapLayer that is displayed at the
212 alfonx 224 // moment. We do not use the styledLayer.getStyle, because in
213 alfonx 123 // the atlas, this always return the default style, but
214 alfonx 224 // additional styles might be selected.
215 alfonx 123 // Taking the style from the mapLayer indicated, that we have to
216 alfonx 125 // remove any selection rules first.
217 alfonx 101
218 alfonx 412 FeatureTypeStyle selectionFTStyle = StylingUtil
219 alfonx 224 .createSelectionStyle(styledLayer.getGeoObject());
220 alfonx 106
221 alfonx 412 selectionFTStyle.setName(SELECTION_STYLING);
222 alfonx 123
223 alfonx 158 /**
224     *
225     * Add a Filter to the selectionMapStyle, so that it is only
226     * used on objects that are selected. <br/>
227     *
228     * Note 1:<br/>
229 alfonx 409 * It is NEVER allowed to GeoTools extend Filter () { .. } (and
230     * write tests into the evaluate block). Especially for the
231 alfonx 158 * ShapeFileRenderer, we may only use a geotools Filter.<br/>
232     *
233     * Note 2:<br/>
234 alfonx 409 * The FilterUtil.FILTER_FAC2.id(fids) wants a set of
235     * FeatureId-Objects!
236 alfonx 158 */
237 alfonx 106
238 alfonx 158 Set<FeatureId> fids = new HashSet<FeatureId>();
239     for (String fid : newSelection) {
240     fids.add(FilterUtil.FILTER_FAC2.featureId(fid));
241     }
242 alfonx 476
243     LOGGER.debug("The selection filter:"+fids);
244 alfonx 106
245 alfonx 412 selectionFTStyle.rules().get(0).setFilter(
246     FilterUtil.FILTER_FAC2.id(fids));
247 alfonx 106
248 alfonx 412 // Maybe there has already been another selection
249     // FeatureTypeStyle... Let's replace it...
250     boolean foundAndReplaced = false;
251     for (FeatureTypeStyle fts : originalStyle.featureTypeStyles()) {
252     if (fts.getName() != null
253     && fts.getName().equals(SELECTION_STYLING)) {
254     foundAndReplaced = true;
255     fts.rules().clear();
256     fts.rules().addAll(selectionFTStyle.rules());
257     break;
258     }
259 alfonx 123 }
260 alfonx 412 if (!foundAndReplaced) {
261     originalStyle.featureTypeStyles().add(selectionFTStyle);
262     }
263 alfonx 151
264 alfonx 412 // Refresh the map
265 alfonx 455 // mapPane.refresh();
266    
267 alfonx 419 DuplicatingStyleVisitor dsv = new DuplicatingStyleVisitor();
268     dsv.visit(originalStyle);
269 alfonx 455 Style newStyle = (Style) dsv.getCopy();
270    
271     // Style newStyle = StylingUtil.STYLE_BUILDER.createStyle();
272     // newStyle.featureTypeStyles().addAll(originalStyle.featureTypeStyles());
273 alfonx 419 mapLayer.setStyle(newStyle);
274 alfonx 455
275 alfonx 419 replaceRenderer();
276 alfonx 97 }
277    
278     } catch (Exception e) {
279     LOGGER.error("Error while trying to create a selection style", e);
280     }
281     }
282    
283 alfonx 419 private void replaceRenderer() {
284 alfonx 455 //
285     // // Has to be done before we apply the new Renderer
286     // mapLayer.setStyle(style);
287 alfonx 419
288     GTRenderer oldRenderer = mapPane.getRenderer();
289    
290     /**
291     * Explicitly putting a new instance of LabelCacheDefault into the
292     * renderer instance, so JMapPane doesn't reuse the old one. This is
293     * very useful when changing the TextSymbolizer with AtlasStyler<br/>
294     * SK 9.7.09: It's not enought to user LabelCache.clear(). We can not
295     * reuse the old Renderer - better to create a new one!
296     */
297 alfonx 440 final GTRenderer newRenderer = GTUtil.createGTRenderer();
298 alfonx 419
299     final HashMap<Object, Object> rendererHints = defaultGTRenderingHints;
300     rendererHints.put(StreamingRenderer.LABEL_CACHE_KEY,
301     new LabelCacheImpl());
302    
303     newRenderer.setRendererHints(rendererHints);
304     mapPane.setRenderer(newRenderer);
305    
306     if (oldRenderer != null) {
307 alfonx 455
308 alfonx 419 RenderingHints java2DHints = oldRenderer.getJava2DHints();
309     if (java2DHints != null) {
310 alfonx 427 newRenderer.setJava2DHints(java2DHints);
311 alfonx 419 }
312 alfonx 455
313 alfonx 419 oldRenderer.setContext(null);
314     oldRenderer = null;
315     }
316 alfonx 455
317 alfonx 419 mapPane.refresh();
318    
319     }
320    
321 alfonx 151 /**
322     * Used to synchronize {@link FeatureSelectedEvent}s with the
323     * {@link StyledFeatureLayerSelectionModel}
324     */
325 alfonx 97 @Override
326     public void performMapPaneEvent(JMapPaneEvent e) {
327 alfonx 106
328 alfonx 151 // Ignore event if it is caused by us or the synchronizer is disabled.
329     if (!isEnabled() || selectionChangeCausedByMe)
330     return;
331    
332     if (!(e instanceof FeatureSelectedEvent)) {
333     // LOGGER.debug("Ignoring event " + e);
334     return;
335     }
336    
337 alfonx 111 /**
338 alfonx 151 * Only listen to FeatureSelectedEvents if an appropriate tool is
339 alfonx 111 * selected.
340     */
341     final int selectedTool = toolBar.getSelectedTool();
342     if (selectedTool != MapPaneToolBar.TOOL_SELECTION_ADD
343     && selectedTool != MapPaneToolBar.TOOL_SELECTION_REMOVE
344     && selectedTool != MapPaneToolBar.TOOL_SELECTION_SET) {
345     return;
346     }
347    
348 mojays 109 // only listen to events directly coming from JMapPane
349     // selection (ignore selections from FilterDialog)
350 alfonx 111 if (e.getSourceObject() != this.mapPane)
351     return;
352    
353 alfonx 97 FeatureSelectedEvent fse = (FeatureSelectedEvent) e;
354    
355 alfonx 151 /**
356 alfonx 158 * Checking, that the FeatureSelectedEvent actually contains features
357     * from this layer
358 alfonx 151 */
359     final String sourceID = fse.getSourceLayer().getTitle();
360     final String syncForID = mapLayer.getTitle();
361     if (sourceID != null && syncForID != null
362 alfonx 158 && !sourceID.equals(syncForID)) {
363     LOGGER.debug("Ignoring a FeatureSelectedEvent from " + sourceID);
364 alfonx 97 return;
365 alfonx 151 }
366 alfonx 97
367 alfonx 476 // LOGGER.debug("do event " + fse);
368 alfonx 111
369 alfonx 97 // Avoid event circles in propertyChange(..)
370     selectionChangeCausedByMe = true;
371    
372 alfonx 455 final FeatureCollection<SimpleFeatureType, SimpleFeature> selectionResult = fse
373     .getSelectionResult();
374     Iterator<SimpleFeature> fi = selectionResult.iterator();
375     try {
376 alfonx 97
377 alfonx 455 // reset the selection of the DpLayerSelectionModel
378     // layerSelModel.setValueIsAdjusting(true);
379 alfonx 97
380 alfonx 455 if (selectedTool == MapPaneToolBar.TOOL_SELECTION_ADD) {
381     layerSelModel.setValueIsAdjusting(true);
382 alfonx 409
383 alfonx 455 for (int fIdx = 0; fi.hasNext(); fIdx++) {
384     SimpleFeature f = fi.next();
385     layerSelModel.addSelection(f.getID());
386     }
387     layerSelModel.setValueIsAdjusting(false);
388     } else if (selectedTool == MapPaneToolBar.TOOL_SELECTION_SET) {
389     layerSelModel.setValueIsAdjusting(true);
390     layerSelModel.clearSelection();
391 alfonx 97
392 alfonx 455 for (int fIdx = 0; fi.hasNext(); fIdx++) {
393     SimpleFeature f = fi.next();
394     layerSelModel.addSelection(f.getID());
395     }
396 alfonx 111
397 alfonx 455 // LOGGER.debug("Setting selection to " + fi.());
398 alfonx 409
399 alfonx 455 layerSelModel.setValueIsAdjusting(false);
400     } else if (selectedTool == MapPaneToolBar.TOOL_SELECTION_REMOVE) {
401     layerSelModel.setValueIsAdjusting(true);
402     for (int fIdx = 0; fi.hasNext(); fIdx++) {
403     SimpleFeature f = fi.next();
404     layerSelModel.removeSelection(f.getID());
405     }
406     layerSelModel.setValueIsAdjusting(false);
407 alfonx 111 }
408 alfonx 455
409     } finally {
410     selectionResult.close(fi);
411 alfonx 151 }
412 alfonx 111
413     // Show selected features in the map, which is not automatically done by
414     // the origin: FeatureSelectedEvent
415 alfonx 97 changeLayerStyle(layerSelModel.getSelection());
416 alfonx 106
417 alfonx 97 // Danger of event circles in propertyChange(..) banned
418     selectionChangeCausedByMe = false;
419     }
420 alfonx 151
421 alfonx 97 }

Properties

Name Value
svn:eol-style native
svn:keywords Id
svn:mime-type text/plain

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26