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

Contents of /branches/2.1/src/skrueger/geotools/selection/FeatureMapLayerSelectionSynchronizer.java

Parent Directory Parent Directory | Revision Log Revision Log


Revision 412 - (show annotations)
Tue Sep 22 17:46:26 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: 12710 byte(s)
* AV-Feature: Selected polygons are now marked with hatches, so that the underlying color can still be seen. But there seem to be some zoomIn-problems?!?!

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

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