/[schmitzm]/trunk/src/skrueger/geotools/selection/FeatureMapLayerSelectionSynchronizer.java
ViewVC logotype

Annotation of /trunk/src/skrueger/geotools/selection/FeatureMapLayerSelectionSynchronizer.java

Parent Directory Parent Directory | Revision Log Revision Log


Revision 415 - (hide annotations)
Thu Sep 24 17:58:32 2009 UTC (15 years, 5 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: 12875 byte(s)
* GP-Feature: In the MapComposer it is now BASICALLY possible to change the CRS and format of the Grid/Ruler on the left/bottom. At the moment only two formatters are available, one for DHDN in Germany, and one for lat/lon. 
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     import java.beans.PropertyChangeEvent;
46     import java.beans.PropertyChangeListener;
47 alfonx 158 import java.util.HashSet;
48 alfonx 409 import java.util.Iterator;
49 alfonx 158 import java.util.Set;
50 alfonx 97 import java.util.Vector;
51    
52     import javax.swing.JTable;
53     import javax.swing.ListSelectionModel;
54     import javax.swing.event.ListSelectionListener;
55    
56     import org.geotools.map.MapLayer;
57 alfonx 123 import org.geotools.styling.FeatureTypeStyle;
58 alfonx 97 import org.geotools.styling.Style;
59 mojays 325 import org.opengis.feature.simple.SimpleFeature;
60 alfonx 158 import org.opengis.filter.identity.FeatureId;
61 alfonx 97
62 alfonx 158 import schmitzm.geotools.FilterUtil;
63 alfonx 97 import schmitzm.geotools.gui.JMapPane;
64     import schmitzm.geotools.map.event.FeatureSelectedEvent;
65     import schmitzm.geotools.map.event.JMapPaneEvent;
66     import schmitzm.geotools.map.event.JMapPaneListener;
67     import schmitzm.geotools.styling.StylingUtil;
68 alfonx 111 import skrueger.geotools.MapPaneToolBar;
69 alfonx 224 import skrueger.geotools.StyledLayerInterface;
70 alfonx 97
71     /**
72     * This class keeps the selection of a (feature) {@link JTable} synchronized
73     * with the {@link StyledLayerSelectionModel} of a layer. This is done by
74     * implementing:
75     * <ul>
76     * <li>a {@link PropertyChangeListener} which listens to the
77     * {@link StyledLayerSelectionModel} and accordingly changes the {@link JTable}
78     * selection</li>
79     * <li>a {@link ListSelectionListener} which listens to the {@link JTable} and
80     * accordingly changes the {@link StyledLayerSelectionModel} selection</li>
81     * </ul>
82     * After creating, the instance of this synchronizer must be added as listener
83     * to both, the {@link StyledLayerSelectionModel} and the table's
84     * {@link ListSelectionModel}.
85     *
86     * @author <a href="mailto:[email protected]">Martin Schmitz</a>
87     * (University of Bonn/Germany)
88     */
89     public class FeatureMapLayerSelectionSynchronizer extends
90 alfonx 106 StyledLayerSelectionModelSynchronizer<StyledFeatureLayerSelectionModel>
91     implements JMapPaneListener {
92 alfonx 111 public static final String SELECTION_STYLING = "SELECTION";
93 alfonx 97 /**
94     * Holds the {@link MapLayer} to keep synchronized with the layer selection
95     * model.
96     */
97     protected final MapLayer mapLayer;
98 alfonx 224 protected final StyledLayerInterface<?> styledLayer;
99 alfonx 97 protected final JMapPane mapPane;
100 alfonx 111 private final MapPaneToolBar toolBar;
101 alfonx 97
102     /**
103     * Creates a new synchronizer
104     *
105     * @param layerSelModel
106     * layer selection model to keep synchronized with the
107     * {@link MapLayer}
108     *
109     * @param mapLayer
110     * {@link MapLayer} to keep synchronized with.
111     */
112     public FeatureMapLayerSelectionSynchronizer(
113     StyledFeatureLayerSelectionModel layerSelModel,
114 alfonx 224 StyledLayerInterface<?> styledLayer, MapLayer mapLayer,
115 alfonx 111 JMapPane mapPane, MapPaneToolBar toolBar) {
116 alfonx 97
117     super(layerSelModel);
118 alfonx 224 this.styledLayer = styledLayer;
119 alfonx 97
120     this.mapLayer = mapLayer;
121     this.mapPane = mapPane;
122 alfonx 111 this.toolBar = toolBar;
123 alfonx 97 }
124    
125     /**
126     * Called by {@link StyledLayerSelectionModel} when a the selection on other
127     * selection components (map, chart, ...) has changed. When calling this
128     *
129     * method changes the {@link MapLayer} selection according to the
130     * {@link StyledLayerSelectionModel} selection.
131     *
132     * @param evt
133     * an event
134     */
135     @Override
136     public void propertyChange(PropertyChangeEvent evt) {
137 alfonx 151
138     if (!isEnabled())
139     return;
140    
141 alfonx 97 if (!(evt instanceof StyledLayerSelectionEvent))
142     return;
143     StyledLayerSelectionEvent selEvt = (StyledLayerSelectionEvent) evt;
144     // Only react on own layer and ignore events invoked by
145     // this component itself
146     if (selEvt.getEmitter() != layerSelModel || selectionChangeCausedByMe)
147     return;
148     // Apply new selection on table (except this event is one of
149     // some more events)
150 alfonx 111 Vector<String> newSelection = layerSelModel.getSelection();
151 alfonx 97 if (newSelection == null)
152     return;
153    
154     // Avoid event circles in valueChanged(..)
155     selectionChangeCausedByMe = true;
156    
157     changeLayerStyle(newSelection);
158    
159     // Danger of event circles in valueChanged(..) banned
160     selectionChangeCausedByMe = false;
161     }
162    
163 alfonx 151 /**
164     * Changes the Style of the {@link MapLayer} to reflect changes of the
165     * selection.
166     *
167     * @param newSelection
168 alfonx 318 * A {@link Vector} of SimpleFeature-IDs that are selected.
169 alfonx 151 */
170 alfonx 111 private void changeLayerStyle(final Vector<String> newSelection) {
171 alfonx 97 try {
172 alfonx 415 // GTRenderer r = mapPane.getRenderer();
173     // if (r instanceof ShapefileRenderer) {
174     // ShapefileRenderer sfr = (ShapefileRenderer)r;
175     // sfr.setCaching(false);
176     // }
177     //
178    
179 alfonx 412 Style originalStyle = mapLayer.getStyle();
180 alfonx 97 if (newSelection.isEmpty()) {
181    
182 alfonx 412 // Check if the Style contains a SELECTION FTS
183    
184     FeatureTypeStyle[] clone = originalStyle.featureTypeStyles().toArray( new FeatureTypeStyle[] {} ).clone();
185    
186     for (FeatureTypeStyle fts : clone) {
187     if (fts.getName() != null
188     && fts.getName().equals(SELECTION_STYLING)) {
189     originalStyle.featureTypeStyles().remove(fts);
190    
191     mapPane.refresh();
192 alfonx 106
193 alfonx 412 return;
194     }
195     }
196    
197 alfonx 97 } else {
198 alfonx 100 LOGGER.debug("SELECTION .. change style");
199 alfonx 106
200 alfonx 123 // We take Style from the MapLayer that is displayed at the
201 alfonx 224 // moment. We do not use the styledLayer.getStyle, because in
202 alfonx 123 // the atlas, this always return the default style, but
203 alfonx 224 // additional styles might be selected.
204 alfonx 123 // Taking the style from the mapLayer indicated, that we have to
205 alfonx 125 // remove any selection rules first.
206 alfonx 101
207 alfonx 412 FeatureTypeStyle selectionFTStyle = StylingUtil
208 alfonx 224 .createSelectionStyle(styledLayer.getGeoObject());
209 alfonx 106
210 alfonx 412 selectionFTStyle.setName(SELECTION_STYLING);
211 alfonx 123
212 alfonx 158 /**
213     *
214     * Add a Filter to the selectionMapStyle, so that it is only
215     * used on objects that are selected. <br/>
216     *
217     * Note 1:<br/>
218 alfonx 409 * It is NEVER allowed to GeoTools extend Filter () { .. } (and
219     * write tests into the evaluate block). Especially for the
220 alfonx 158 * ShapeFileRenderer, we may only use a geotools Filter.<br/>
221     *
222     * Note 2:<br/>
223 alfonx 409 * The FilterUtil.FILTER_FAC2.id(fids) wants a set of
224     * FeatureId-Objects!
225 alfonx 158 */
226 alfonx 106
227 alfonx 158 Set<FeatureId> fids = new HashSet<FeatureId>();
228     for (String fid : newSelection) {
229     fids.add(FilterUtil.FILTER_FAC2.featureId(fid));
230     }
231 alfonx 106
232 alfonx 412 selectionFTStyle.rules().get(0).setFilter(
233     FilterUtil.FILTER_FAC2.id(fids));
234 alfonx 106
235 alfonx 412 // Maybe there has already been another selection
236     // FeatureTypeStyle... Let's replace it...
237     boolean foundAndReplaced = false;
238     for (FeatureTypeStyle fts : originalStyle.featureTypeStyles()) {
239     if (fts.getName() != null
240     && fts.getName().equals(SELECTION_STYLING)) {
241     foundAndReplaced = true;
242     fts.rules().clear();
243     fts.rules().addAll(selectionFTStyle.rules());
244     break;
245     }
246 alfonx 123 }
247 alfonx 412 if (!foundAndReplaced) {
248     originalStyle.featureTypeStyles().add(selectionFTStyle);
249     }
250 alfonx 151
251 alfonx 412 // Refresh the map
252     mapPane.refresh();
253 alfonx 97 }
254 alfonx 415 //
255     // if (r instanceof ShapefileRenderer) {
256     // ShapefileRenderer sfr = (ShapefileRenderer)r;
257     // sfr.setCaching(true);
258     // }
259 alfonx 97
260 alfonx 415
261 alfonx 97 } catch (Exception e) {
262     LOGGER.error("Error while trying to create a selection style", e);
263     }
264     }
265    
266 alfonx 151 /**
267     * Used to synchronize {@link FeatureSelectedEvent}s with the
268     * {@link StyledFeatureLayerSelectionModel}
269     */
270 alfonx 97 @Override
271     public void performMapPaneEvent(JMapPaneEvent e) {
272 alfonx 106
273 alfonx 151 // Ignore event if it is caused by us or the synchronizer is disabled.
274     if (!isEnabled() || selectionChangeCausedByMe)
275     return;
276    
277     if (!(e instanceof FeatureSelectedEvent)) {
278     // LOGGER.debug("Ignoring event " + e);
279     return;
280     }
281    
282 alfonx 111 /**
283 alfonx 151 * Only listen to FeatureSelectedEvents if an appropriate tool is
284 alfonx 111 * selected.
285     */
286     final int selectedTool = toolBar.getSelectedTool();
287     if (selectedTool != MapPaneToolBar.TOOL_SELECTION_ADD
288     && selectedTool != MapPaneToolBar.TOOL_SELECTION_REMOVE
289     && selectedTool != MapPaneToolBar.TOOL_SELECTION_SET) {
290     return;
291     }
292    
293 mojays 109 // only listen to events directly coming from JMapPane
294     // selection (ignore selections from FilterDialog)
295 alfonx 111 if (e.getSourceObject() != this.mapPane)
296     return;
297    
298 alfonx 97 FeatureSelectedEvent fse = (FeatureSelectedEvent) e;
299    
300 alfonx 151 /**
301 alfonx 158 * Checking, that the FeatureSelectedEvent actually contains features
302     * from this layer
303 alfonx 151 */
304     final String sourceID = fse.getSourceLayer().getTitle();
305     final String syncForID = mapLayer.getTitle();
306     if (sourceID != null && syncForID != null
307 alfonx 158 && !sourceID.equals(syncForID)) {
308     LOGGER.debug("Ignoring a FeatureSelectedEvent from " + sourceID);
309 alfonx 97 return;
310 alfonx 151 }
311 alfonx 97
312 alfonx 151 LOGGER.debug("do event " + fse);
313 alfonx 111
314 alfonx 97 // Avoid event circles in propertyChange(..)
315     selectionChangeCausedByMe = true;
316    
317 alfonx 409 Iterator<SimpleFeature> fi = fse.getSelectionResult().iterator();
318 alfonx 97
319 alfonx 151 // reset the selection of the DpLayerSelectionModel
320     // layerSelModel.setValueIsAdjusting(true);
321 alfonx 97
322 alfonx 151 if (selectedTool == MapPaneToolBar.TOOL_SELECTION_ADD) {
323     layerSelModel.setValueIsAdjusting(true);
324 alfonx 409
325     for (int fIdx = 0; fi.hasNext(); fIdx++) {
326     SimpleFeature f = fi.next();
327 alfonx 151 layerSelModel.addSelection(f.getID());
328     }
329     layerSelModel.setValueIsAdjusting(false);
330     } else if (selectedTool == MapPaneToolBar.TOOL_SELECTION_SET) {
331     layerSelModel.setValueIsAdjusting(true);
332     layerSelModel.clearSelection();
333 alfonx 97
334 alfonx 409 for (int fIdx = 0; fi.hasNext(); fIdx++) {
335     SimpleFeature f = fi.next();
336 alfonx 151 layerSelModel.addSelection(f.getID());
337     }
338 alfonx 111
339 alfonx 409 // LOGGER.debug("Setting selection to " + fi.());
340    
341 alfonx 151 layerSelModel.setValueIsAdjusting(false);
342     } else if (selectedTool == MapPaneToolBar.TOOL_SELECTION_REMOVE) {
343     layerSelModel.setValueIsAdjusting(true);
344 alfonx 409 for (int fIdx = 0; fi.hasNext(); fIdx++) {
345     SimpleFeature f = fi.next();
346 alfonx 151 layerSelModel.removeSelection(f.getID());
347 alfonx 111 }
348 alfonx 151 layerSelModel.setValueIsAdjusting(false);
349     }
350 alfonx 111
351     // Show selected features in the map, which is not automatically done by
352     // the origin: FeatureSelectedEvent
353 alfonx 97 changeLayerStyle(layerSelModel.getSelection());
354 alfonx 106
355 alfonx 97 // Danger of event circles in propertyChange(..) banned
356     selectionChangeCausedByMe = false;
357     }
358 alfonx 151
359 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