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

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

Parent Directory Parent Directory | Revision Log Revision Log


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