/[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 414 - (show annotations)
Thu Sep 24 13:23:08 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: 12554 byte(s)
JMapPane can optionally be given an envelope. When zooming/panning it will never show anything outside this envelope.

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.HashSet;
48 import java.util.Iterator;
49 import java.util.Set;
50 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 import org.geotools.styling.FeatureTypeStyle;
58 import org.geotools.styling.Style;
59 import org.opengis.feature.simple.SimpleFeature;
60 import org.opengis.filter.identity.FeatureId;
61
62 import schmitzm.geotools.FilterUtil;
63 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 import skrueger.geotools.MapPaneToolBar;
69 import skrueger.geotools.StyledLayerInterface;
70
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 StyledLayerSelectionModelSynchronizer<StyledFeatureLayerSelectionModel>
91 implements JMapPaneListener {
92 public static final String SELECTION_STYLING = "SELECTION";
93 /**
94 * Holds the {@link MapLayer} to keep synchronized with the layer selection
95 * model.
96 */
97 protected final MapLayer mapLayer;
98 protected final StyledLayerInterface<?> styledLayer;
99 protected final JMapPane mapPane;
100 private final MapPaneToolBar toolBar;
101
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 StyledLayerInterface<?> styledLayer, MapLayer mapLayer,
115 JMapPane mapPane, MapPaneToolBar toolBar) {
116
117 super(layerSelModel);
118 this.styledLayer = styledLayer;
119
120 this.mapLayer = mapLayer;
121 this.mapPane = mapPane;
122 this.toolBar = toolBar;
123 }
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
138 if (!isEnabled())
139 return;
140
141 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 Vector<String> newSelection = layerSelModel.getSelection();
151 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 /**
164 * Changes the Style of the {@link MapLayer} to reflect changes of the
165 * selection.
166 *
167 * @param newSelection
168 * A {@link Vector} of SimpleFeature-IDs that are selected.
169 */
170 private void changeLayerStyle(final Vector<String> newSelection) {
171 try {
172 Style originalStyle = mapLayer.getStyle();
173 if (newSelection.isEmpty()) {
174
175 // Check if the Style contains a SELECTION FTS
176
177 FeatureTypeStyle[] clone = originalStyle.featureTypeStyles().toArray( new FeatureTypeStyle[] {} ).clone();
178
179 for (FeatureTypeStyle fts : clone) {
180 if (fts.getName() != null
181 && fts.getName().equals(SELECTION_STYLING)) {
182 originalStyle.featureTypeStyles().remove(fts);
183
184 mapPane.refresh();
185
186 return;
187 }
188 }
189
190 } else {
191 LOGGER.debug("SELECTION .. change style");
192
193 // We take Style from the MapLayer that is displayed at the
194 // moment. We do not use the styledLayer.getStyle, because in
195 // the atlas, this always return the default style, but
196 // additional styles might be selected.
197 // Taking the style from the mapLayer indicated, that we have to
198 // remove any selection rules first.
199
200 FeatureTypeStyle selectionFTStyle = StylingUtil
201 .createSelectionStyle(styledLayer.getGeoObject());
202
203 selectionFTStyle.setName(SELECTION_STYLING);
204
205 /**
206 *
207 * Add a Filter to the selectionMapStyle, so that it is only
208 * used on objects that are selected. <br/>
209 *
210 * Note 1:<br/>
211 * It is NEVER allowed to GeoTools extend Filter () { .. } (and
212 * write tests into the evaluate block). Especially for the
213 * ShapeFileRenderer, we may only use a geotools Filter.<br/>
214 *
215 * Note 2:<br/>
216 * The FilterUtil.FILTER_FAC2.id(fids) wants a set of
217 * FeatureId-Objects!
218 */
219
220 Set<FeatureId> fids = new HashSet<FeatureId>();
221 for (String fid : newSelection) {
222 fids.add(FilterUtil.FILTER_FAC2.featureId(fid));
223 }
224
225 selectionFTStyle.rules().get(0).setFilter(
226 FilterUtil.FILTER_FAC2.id(fids));
227
228 // Maybe there has already been another selection
229 // FeatureTypeStyle... Let's replace it...
230 boolean foundAndReplaced = false;
231 for (FeatureTypeStyle fts : originalStyle.featureTypeStyles()) {
232 if (fts.getName() != null
233 && fts.getName().equals(SELECTION_STYLING)) {
234 foundAndReplaced = true;
235 fts.rules().clear();
236 fts.rules().addAll(selectionFTStyle.rules());
237 break;
238 }
239 }
240 if (!foundAndReplaced) {
241 originalStyle.featureTypeStyles().add(selectionFTStyle);
242 }
243
244 // Refresh the map
245 mapPane.refresh();
246 }
247
248 } catch (Exception e) {
249 LOGGER.error("Error while trying to create a selection style", e);
250 }
251 }
252
253 /**
254 * Used to synchronize {@link FeatureSelectedEvent}s with the
255 * {@link StyledFeatureLayerSelectionModel}
256 */
257 @Override
258 public void performMapPaneEvent(JMapPaneEvent e) {
259
260 // Ignore event if it is caused by us or the synchronizer is disabled.
261 if (!isEnabled() || selectionChangeCausedByMe)
262 return;
263
264 if (!(e instanceof FeatureSelectedEvent)) {
265 // LOGGER.debug("Ignoring event " + e);
266 return;
267 }
268
269 /**
270 * Only listen to FeatureSelectedEvents if an appropriate tool is
271 * selected.
272 */
273 final int selectedTool = toolBar.getSelectedTool();
274 if (selectedTool != MapPaneToolBar.TOOL_SELECTION_ADD
275 && selectedTool != MapPaneToolBar.TOOL_SELECTION_REMOVE
276 && selectedTool != MapPaneToolBar.TOOL_SELECTION_SET) {
277 return;
278 }
279
280 // only listen to events directly coming from JMapPane
281 // selection (ignore selections from FilterDialog)
282 if (e.getSourceObject() != this.mapPane)
283 return;
284
285 FeatureSelectedEvent fse = (FeatureSelectedEvent) e;
286
287 /**
288 * Checking, that the FeatureSelectedEvent actually contains features
289 * from this layer
290 */
291 final String sourceID = fse.getSourceLayer().getTitle();
292 final String syncForID = mapLayer.getTitle();
293 if (sourceID != null && syncForID != null
294 && !sourceID.equals(syncForID)) {
295 LOGGER.debug("Ignoring a FeatureSelectedEvent from " + sourceID);
296 return;
297 }
298
299 LOGGER.debug("do event " + fse);
300
301 // Avoid event circles in propertyChange(..)
302 selectionChangeCausedByMe = true;
303
304 Iterator<SimpleFeature> fi = fse.getSelectionResult().iterator();
305
306 // reset the selection of the DpLayerSelectionModel
307 // layerSelModel.setValueIsAdjusting(true);
308
309 if (selectedTool == MapPaneToolBar.TOOL_SELECTION_ADD) {
310 layerSelModel.setValueIsAdjusting(true);
311
312 for (int fIdx = 0; fi.hasNext(); fIdx++) {
313 SimpleFeature f = fi.next();
314 layerSelModel.addSelection(f.getID());
315 }
316 layerSelModel.setValueIsAdjusting(false);
317 } else if (selectedTool == MapPaneToolBar.TOOL_SELECTION_SET) {
318 layerSelModel.setValueIsAdjusting(true);
319 layerSelModel.clearSelection();
320
321 for (int fIdx = 0; fi.hasNext(); fIdx++) {
322 SimpleFeature f = fi.next();
323 layerSelModel.addSelection(f.getID());
324 }
325
326 // LOGGER.debug("Setting selection to " + fi.());
327
328 layerSelModel.setValueIsAdjusting(false);
329 } else if (selectedTool == MapPaneToolBar.TOOL_SELECTION_REMOVE) {
330 layerSelModel.setValueIsAdjusting(true);
331 for (int fIdx = 0; fi.hasNext(); fIdx++) {
332 SimpleFeature f = fi.next();
333 layerSelModel.removeSelection(f.getID());
334 }
335 layerSelModel.setValueIsAdjusting(false);
336 }
337
338 // Show selected features in the map, which is not automatically done by
339 // the origin: FeatureSelectedEvent
340 changeLayerStyle(layerSelModel.getSelection());
341
342 // Danger of event circles in propertyChange(..) banned
343 selectionChangeCausedByMe = false;
344 }
345
346 }

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