svn-gvsig-desktop / trunk / org.gvsig.desktop / org.gvsig.desktop.library / org.gvsig.symbology / org.gvsig.symbology.lib / org.gvsig.symbology.lib.impl / src / main / java / org / gvsig / symbology / fmap / mapcontext / rendering / legend / impl / AbstractVectorialLegend.java @ 47790
History | View | Annotate | Download (37.2 KB)
1 | 40560 | jjdelcerro | /**
|
---|---|---|---|
2 | * gvSIG. Desktop Geographic Information System.
|
||
3 | 40435 | jjdelcerro | *
|
4 | 40560 | jjdelcerro | * Copyright (C) 2007-2013 gvSIG Association.
|
5 | *
|
||
6 | 40435 | jjdelcerro | * This program is free software; you can redistribute it and/or
|
7 | * modify it under the terms of the GNU General Public License
|
||
8 | 40560 | jjdelcerro | * as published by the Free Software Foundation; either version 3
|
9 | 40435 | jjdelcerro | * of the License, or (at your option) any later version.
|
10 | 40560 | jjdelcerro | *
|
11 | 40435 | jjdelcerro | * This program is distributed in the hope that it will be useful,
|
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
14 | * GNU General Public License for more details.
|
||
15 | 40560 | jjdelcerro | *
|
16 | 40435 | jjdelcerro | * You should have received a copy of the GNU General Public License
|
17 | * along with this program; if not, write to the Free Software
|
||
18 | 40560 | jjdelcerro | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
19 | 40435 | jjdelcerro | * MA 02110-1301, USA.
|
20 | 40560 | jjdelcerro | *
|
21 | * For any additional information, do not hesitate to contact us
|
||
22 | * at info AT gvsig.com, or visit our website www.gvsig.com.
|
||
23 | 40435 | jjdelcerro | */
|
24 | /*
|
||
25 | * AUTHORS (In addition to CIT):
|
||
26 | * 2009 {DiSiD Technologies} {{Task}}
|
||
27 | */
|
||
28 | package org.gvsig.symbology.fmap.mapcontext.rendering.legend.impl; |
||
29 | |||
30 | 47790 | fdiaz | import java.awt.Color; |
31 | 40435 | jjdelcerro | import java.awt.Graphics2D; |
32 | import java.awt.geom.Point2D; |
||
33 | import java.awt.image.BufferedImage; |
||
34 | import java.util.Iterator; |
||
35 | import java.util.Map; |
||
36 | import java.util.Map.Entry; |
||
37 | 45887 | jjdelcerro | import org.apache.commons.lang3.StringUtils; |
38 | 40435 | jjdelcerro | import org.cresques.cts.ICoordTrans; |
39 | import org.cresques.cts.IProjection; |
||
40 | import org.gvsig.compat.CompatLocator; |
||
41 | import org.gvsig.compat.print.PrintAttributes; |
||
42 | 44361 | jjdelcerro | import org.gvsig.expressionevaluator.ExpressionBuilder; |
43 | import org.gvsig.expressionevaluator.ExpressionUtils; |
||
44 | 40435 | jjdelcerro | import org.gvsig.fmap.dal.exception.DataException; |
45 | import org.gvsig.fmap.dal.feature.Feature; |
||
46 | import org.gvsig.fmap.dal.feature.FeatureQuery; |
||
47 | 43206 | jjdelcerro | import org.gvsig.fmap.dal.feature.FeatureReference; |
48 | 40435 | jjdelcerro | import org.gvsig.fmap.dal.feature.FeatureSelection; |
49 | import org.gvsig.fmap.dal.feature.FeatureSet; |
||
50 | import org.gvsig.fmap.dal.feature.FeatureStore; |
||
51 | 44361 | jjdelcerro | import org.gvsig.fmap.dal.feature.FeatureType; |
52 | 40435 | jjdelcerro | import org.gvsig.fmap.dal.feature.exception.ConcurrentDataModificationException; |
53 | import org.gvsig.fmap.geom.Geometry; |
||
54 | import org.gvsig.fmap.geom.GeometryLocator; |
||
55 | import org.gvsig.fmap.geom.GeometryManager; |
||
56 | import org.gvsig.fmap.geom.aggregate.Aggregate; |
||
57 | import org.gvsig.fmap.geom.exception.CreateGeometryException; |
||
58 | import org.gvsig.fmap.geom.exception.ReprojectionRuntimeException; |
||
59 | import org.gvsig.fmap.geom.primitive.Envelope; |
||
60 | import org.gvsig.fmap.mapcontext.MapContext; |
||
61 | import org.gvsig.fmap.mapcontext.MapContextException; |
||
62 | import org.gvsig.fmap.mapcontext.ViewPort; |
||
63 | 43020 | jjdelcerro | import org.gvsig.fmap.mapcontext.layers.vectorial.SpatialEvaluatorsFactory; |
64 | 40435 | jjdelcerro | import org.gvsig.fmap.mapcontext.rendering.legend.ILegend; |
65 | import org.gvsig.fmap.mapcontext.rendering.legend.IVectorLegend; |
||
66 | import org.gvsig.fmap.mapcontext.rendering.legend.LegendException; |
||
67 | import org.gvsig.fmap.mapcontext.rendering.legend.ZSort; |
||
68 | import org.gvsig.fmap.mapcontext.rendering.symbols.CartographicSupport; |
||
69 | import org.gvsig.fmap.mapcontext.rendering.symbols.IMultiLayerSymbol; |
||
70 | import org.gvsig.fmap.mapcontext.rendering.symbols.ISymbol; |
||
71 | import org.gvsig.tools.ToolsLocator; |
||
72 | import org.gvsig.tools.dispose.DisposableIterator; |
||
73 | 43326 | jjdelcerro | import org.gvsig.tools.dispose.DisposeUtils; |
74 | 40435 | jjdelcerro | import org.gvsig.tools.dynobject.DynStruct; |
75 | 43020 | jjdelcerro | import org.gvsig.tools.evaluator.Evaluator; |
76 | 40435 | jjdelcerro | import org.gvsig.tools.exception.BaseException; |
77 | 43206 | jjdelcerro | import org.gvsig.tools.logger.FilteredLogger; |
78 | 40435 | jjdelcerro | import org.gvsig.tools.persistence.PersistenceManager; |
79 | import org.gvsig.tools.persistence.PersistentState; |
||
80 | import org.gvsig.tools.persistence.exception.PersistenceException; |
||
81 | import org.gvsig.tools.task.Cancellable; |
||
82 | import org.gvsig.tools.task.SimpleTaskStatus; |
||
83 | import org.gvsig.tools.util.Callable; |
||
84 | import org.gvsig.tools.visitor.VisitCanceledException; |
||
85 | 47476 | fdiaz | import org.slf4j.Logger; |
86 | import org.slf4j.LoggerFactory; |
||
87 | 40435 | jjdelcerro | |
88 | /**
|
||
89 | * Base implementation for Vectorial data Legends.
|
||
90 | 42464 | fdiaz | *
|
91 | 40435 | jjdelcerro | * Provides a draw method implementation which loads the {@link Feature}s and
|
92 | * uses the {@link ISymbol} objects to draw the {@link Geometry} objects.
|
||
93 | 42464 | fdiaz | *
|
94 | 40435 | jjdelcerro | */
|
95 | public abstract class AbstractVectorialLegend extends AbstractLegend implements |
||
96 | IVectorLegend { |
||
97 | 42464 | fdiaz | |
98 | 43437 | jjdelcerro | protected static final Logger LOG = LoggerFactory |
99 | 40435 | jjdelcerro | .getLogger(AbstractVectorialLegend.class); |
100 | |||
101 | private static final int DRAW_MAX_ATTEMPTS = 5; |
||
102 | |||
103 | public static final String VECTORIAL_LEGEND_PERSISTENCE_DEFINITION_NAME = "VectorialLegend"; |
||
104 | |||
105 | private static final String FIELD_HAS_ZSORT = "hasZSort"; |
||
106 | private static final String FIELD_SHAPETYPE = "shapeType"; |
||
107 | private static final String FIELD_DEFAULT_SYMBOL = "defaultSymbol"; |
||
108 | |||
109 | 46451 | fdiaz | private boolean drawSymbolInEeachPrimitive; |
110 | 40435 | jjdelcerro | |
111 | protected ZSort zSort;
|
||
112 | |||
113 | 46451 | fdiaz | protected AbstractVectorialLegend() {
|
114 | this.drawSymbolInEeachPrimitive = true; |
||
115 | } |
||
116 | |||
117 | |||
118 | 40435 | jjdelcerro | public ZSort getZSort() {
|
119 | return zSort;
|
||
120 | } |
||
121 | |||
122 | public void setZSort(ZSort zSort) { |
||
123 | if (zSort == null) { |
||
124 | removeLegendListener(this.zSort);
|
||
125 | } |
||
126 | this.zSort = zSort;
|
||
127 | addLegendListener(zSort); |
||
128 | } |
||
129 | 42464 | fdiaz | |
130 | 40435 | jjdelcerro | @SuppressWarnings("unchecked") |
131 | 43326 | jjdelcerro | @Override
|
132 | 40435 | jjdelcerro | public void draw(BufferedImage image, Graphics2D g, ViewPort viewPort, |
133 | Cancellable cancel, double scale, Map queryParameters, |
||
134 | ICoordTrans coordTrans, FeatureStore featureStore) |
||
135 | throws LegendException {
|
||
136 | 41416 | jjdelcerro | double dpi = viewPort.getDPI();
|
137 | 40435 | jjdelcerro | draw(image, g, viewPort, cancel, scale, queryParameters, coordTrans, |
138 | featureStore, null, dpi);
|
||
139 | } |
||
140 | 42464 | fdiaz | |
141 | 40435 | jjdelcerro | @SuppressWarnings("unchecked") |
142 | 43326 | jjdelcerro | @Override
|
143 | 40435 | jjdelcerro | public void draw(BufferedImage image, Graphics2D g, ViewPort viewPort, |
144 | Cancellable cancel, double scale, Map queryParameters, |
||
145 | ICoordTrans coordTrans, FeatureStore featureStore, FeatureQuery featureQuery) |
||
146 | throws LegendException {
|
||
147 | 41416 | jjdelcerro | double dpi = viewPort.getDPI();
|
148 | 40435 | jjdelcerro | draw(image, g, viewPort, cancel, scale, queryParameters, coordTrans, |
149 | featureStore, featureQuery, dpi); |
||
150 | } |
||
151 | 43326 | jjdelcerro | |
152 | 40435 | jjdelcerro | @SuppressWarnings("unchecked") |
153 | 43326 | jjdelcerro | @Override
|
154 | 40435 | jjdelcerro | public void print(Graphics2D g, ViewPort viewPort, Cancellable cancel, |
155 | double scale, Map queryParameters, ICoordTrans coordTrans, |
||
156 | FeatureStore featureStore, PrintAttributes properties) |
||
157 | throws LegendException {
|
||
158 | print(g, viewPort, cancel, scale, queryParameters, coordTrans, |
||
159 | featureStore, null, properties);
|
||
160 | } |
||
161 | 42464 | fdiaz | |
162 | 40435 | jjdelcerro | @SuppressWarnings("unchecked") |
163 | 43326 | jjdelcerro | @Override
|
164 | 40435 | jjdelcerro | public void print(Graphics2D g, ViewPort viewPort, Cancellable cancel, |
165 | double scale, Map queryParameters, ICoordTrans coordTrans, |
||
166 | 40491 | jldominguez | FeatureStore featureStore, FeatureQuery fquery, PrintAttributes properties) |
167 | 40435 | jjdelcerro | throws LegendException {
|
168 | 44249 | omartinez | |
169 | 40435 | jjdelcerro | double dpi = 72; |
170 | |||
171 | int resolution = properties.getPrintQuality();
|
||
172 | |||
173 | if (resolution == PrintAttributes.PRINT_QUALITY_DRAFT
|
||
174 | || resolution == PrintAttributes.PRINT_QUALITY_NORMAL |
||
175 | || resolution == PrintAttributes.PRINT_QUALITY_HIGH) { |
||
176 | dpi = PrintAttributes.PRINT_QUALITY_DPI[resolution]; |
||
177 | } |
||
178 | |||
179 | FeatureSet featureSet = null;
|
||
180 | DisposableIterator it = null;
|
||
181 | try {
|
||
182 | 43510 | jjdelcerro | GeometryManager geomManager = GeometryLocator.getGeometryManager(); |
183 | 47476 | fdiaz | ZSort theZSort = getZSort(); |
184 | 43326 | jjdelcerro | boolean useZSort = false; |
185 | int mapLevelCount = 1; |
||
186 | |||
187 | 47476 | fdiaz | if( theZSort != null ) { |
188 | useZSort = theZSort.isUsingZSort(); |
||
189 | 43326 | jjdelcerro | if( useZSort ) {
|
190 | 47476 | fdiaz | mapLevelCount = theZSort.getLevelCount(); |
191 | 43326 | jjdelcerro | } |
192 | } |
||
193 | 40435 | jjdelcerro | for (int mapPass = 0; mapPass < mapLevelCount; mapPass++) { |
194 | 42464 | fdiaz | |
195 | 43326 | jjdelcerro | Envelope vp_env_in_store_crs; |
196 | IProjection store_crs; |
||
197 | 40491 | jldominguez | if (coordTrans != null) { |
198 | // 'coordTrans' is from store crs to vp crs
|
||
199 | ICoordTrans inv = coordTrans.getInverted(); |
||
200 | Envelope aux = viewPort.getAdjustedEnvelope(); |
||
201 | vp_env_in_store_crs = aux.convert(inv); |
||
202 | store_crs = coordTrans.getPOrig(); |
||
203 | } else {
|
||
204 | vp_env_in_store_crs = viewPort.getAdjustedEnvelope(); |
||
205 | store_crs = viewPort.getProjection(); |
||
206 | 40435 | jjdelcerro | } |
207 | 42464 | fdiaz | |
208 | 40491 | jldominguez | FeatureQuery feat_query = fquery; |
209 | Envelope store_env = featureStore.getEnvelope(); |
||
210 | 43326 | jjdelcerro | boolean use_intersection_cond;
|
211 | 40491 | jldominguez | if (store_env == null) { |
212 | // Store does not know its envelope, so we must:
|
||
213 | use_intersection_cond = true;
|
||
214 | } else {
|
||
215 | if (vp_env_in_store_crs.contains(store_env)) {
|
||
216 | use_intersection_cond = false;
|
||
217 | } else {
|
||
218 | use_intersection_cond = true;
|
||
219 | } |
||
220 | } |
||
221 | 42464 | fdiaz | |
222 | 40491 | jldominguez | if (use_intersection_cond) {
|
223 | 43020 | jjdelcerro | Evaluator iee = SpatialEvaluatorsFactory.getInstance().intersects( |
224 | 43295 | fdiaz | vp_env_in_store_crs, |
225 | store_crs, |
||
226 | 43020 | jjdelcerro | featureStore |
227 | ); |
||
228 | 40491 | jldominguez | if (feat_query == null) { |
229 | feat_query = featureStore.createFeatureQuery(); |
||
230 | } |
||
231 | 43003 | fdiaz | String[] fns = getRequiredFeatureAttributeNames(featureStore); |
232 | 47476 | fdiaz | for (String fn : fns) { |
233 | feat_query.addAttributeName(fn); |
||
234 | 43003 | fdiaz | } |
235 | 40491 | jldominguez | feat_query.addFilter(iee); |
236 | } |
||
237 | 42464 | fdiaz | |
238 | 40491 | jldominguez | // 'feat_query' can still be NULL here, so we only filter
|
239 | // the featureStore if it's not null
|
||
240 | if (feat_query == null) { |
||
241 | featureSet = featureStore.getFeatureSet(); |
||
242 | } else {
|
||
243 | featureSet = featureStore.getFeatureSet(feat_query); |
||
244 | } |
||
245 | 40435 | jjdelcerro | it = featureSet.fastIterator(); |
246 | // Iteration over each feature
|
||
247 | 43206 | jjdelcerro | FilteredLogger logger = new FilteredLogger(LOG,"Drawing "+featureStore.getName(), 10); |
248 | 40435 | jjdelcerro | while (!cancel.isCanceled() && it.hasNext()) {
|
249 | Feature feat = (Feature) it.next(); |
||
250 | 43206 | jjdelcerro | try {
|
251 | Geometry geom = feat.getDefaultGeometry(); |
||
252 | if (geom==null) { |
||
253 | continue;
|
||
254 | } |
||
255 | // Reprojection if needed
|
||
256 | if (coordTrans != null) { |
||
257 | geom = geom.cloneGeometry(); |
||
258 | geom.reProject(coordTrans); |
||
259 | } |
||
260 | 40435 | jjdelcerro | |
261 | 43206 | jjdelcerro | // retrieve the symbol associated to such feature
|
262 | ISymbol sym = getSymbolByFeature(feat); |
||
263 | if (sym == null) { |
||
264 | continue;
|
||
265 | } |
||
266 | 47476 | fdiaz | if (useZSort && theZSort != null) { |
267 | int[] symLevels = theZSort.getLevels(sym); |
||
268 | 43206 | jjdelcerro | if (symLevels != null) { |
269 | 40435 | jjdelcerro | |
270 | 43206 | jjdelcerro | // Check if this symbol is a multilayer
|
271 | if (sym instanceof IMultiLayerSymbol) { |
||
272 | // if so, get the layer corresponding to the
|
||
273 | // current level. If none, continue to next
|
||
274 | // iteration
|
||
275 | IMultiLayerSymbol mlSym = (IMultiLayerSymbol) sym; |
||
276 | for (int i = 0; i < mlSym.getLayerCount(); i++) { |
||
277 | ISymbol mySym = mlSym.getLayer(i); |
||
278 | if (symLevels[i] == mapPass) {
|
||
279 | sym = mySym; |
||
280 | break;
|
||
281 | } |
||
282 | 40435 | jjdelcerro | } |
283 | |||
284 | 43206 | jjdelcerro | } else {
|
285 | // else, just draw the symbol in its level
|
||
286 | if (symLevels[0] != mapPass) { |
||
287 | continue;
|
||
288 | } |
||
289 | 40435 | jjdelcerro | } |
290 | } |
||
291 | } |
||
292 | |||
293 | 43206 | jjdelcerro | // Check if this symbol is sized with CartographicSupport
|
294 | CartographicSupport csSym = null;
|
||
295 | int symbolType = sym.getSymbolType();
|
||
296 | 40435 | jjdelcerro | |
297 | 43206 | jjdelcerro | if (symbolType == Geometry.TYPES.POINT
|
298 | 43510 | jjdelcerro | || geomManager.isSubtype(symbolType, Geometry.TYPES.CURVE) |
299 | 43206 | jjdelcerro | || sym instanceof CartographicSupport) {
|
300 | 40435 | jjdelcerro | |
301 | 43206 | jjdelcerro | csSym = (CartographicSupport) sym; |
302 | } |
||
303 | 40435 | jjdelcerro | |
304 | 43206 | jjdelcerro | if (csSym == null) { |
305 | 43510 | jjdelcerro | DrawUtils.drawInts(g, viewPort, sym, feat, geom); |
306 | 43206 | jjdelcerro | } else {
|
307 | 43510 | jjdelcerro | DrawUtils.drawInts(g, viewPort, cancel, dpi, sym, feat, geom); |
308 | 43206 | jjdelcerro | } |
309 | 43510 | jjdelcerro | |
310 | 43206 | jjdelcerro | } catch(Exception ex) { |
311 | FeatureReference ref = null;
|
||
312 | if( feat!=null ) { |
||
313 | ref = feat.getReference(); |
||
314 | } |
||
315 | logger.warn("Can't draw feature ("+ref+").", ex); |
||
316 | 40435 | jjdelcerro | } |
317 | } |
||
318 | } |
||
319 | } catch (DataException e) {
|
||
320 | throw new LegendDrawingException(e); |
||
321 | } finally {
|
||
322 | if (it != null) { |
||
323 | it.dispose(); |
||
324 | } |
||
325 | if (featureSet != null) { |
||
326 | featureSet.dispose(); |
||
327 | } |
||
328 | } |
||
329 | } |
||
330 | |||
331 | /**
|
||
332 | * Draws the features from the {@link FeatureStore}, filtered with the scale
|
||
333 | * and the query parameters, with the symbols of the legend.
|
||
334 | 43326 | jjdelcerro | * @param image
|
335 | * @param g
|
||
336 | * @param viewPort
|
||
337 | * @param cancel
|
||
338 | * @param scale
|
||
339 | * @param queryParameters
|
||
340 | * @param coordTrans
|
||
341 | * @param featureStore
|
||
342 | * @param featureQuery
|
||
343 | * @param dpi
|
||
344 | * @throws org.gvsig.fmap.mapcontext.rendering.legend.LegendException
|
||
345 | 40435 | jjdelcerro | */
|
346 | @SuppressWarnings("unchecked") |
||
347 | protected void draw(BufferedImage image, Graphics2D g, ViewPort viewPort, |
||
348 | Cancellable cancel, double scale, Map queryParameters, |
||
349 | ICoordTrans coordTrans, FeatureStore featureStore, |
||
350 | FeatureQuery featureQuery, double dpi) throws LegendException { |
||
351 | |||
352 | SimpleTaskStatus taskStatus = ToolsLocator.getTaskStatusManager() |
||
353 | .createDefaultSimpleTaskStatus(featureStore.getName()); |
||
354 | taskStatus.add(); |
||
355 | try {
|
||
356 | // Avoid ConcurrentModificationException errors if
|
||
357 | // while drawing another thread edits the store data.
|
||
358 | synchronized (featureStore) {
|
||
359 | internalDraw(image, g, viewPort, cancel, scale, |
||
360 | queryParameters, coordTrans, featureStore, |
||
361 | featureQuery, dpi, taskStatus); |
||
362 | } |
||
363 | } finally {
|
||
364 | 43326 | jjdelcerro | taskStatus.terminate(); |
365 | taskStatus.remove(); |
||
366 | 40435 | jjdelcerro | } |
367 | } |
||
368 | |||
369 | protected void internalDraw(BufferedImage image, Graphics2D g, |
||
370 | ViewPort viewPort, Cancellable cancel, double scale,
|
||
371 | Map queryParameters, ICoordTrans coordTrans,
|
||
372 | FeatureStore featureStore, FeatureQuery featureQuery, double dpi,
|
||
373 | SimpleTaskStatus taskStatus) throws LegendDrawingException {
|
||
374 | |||
375 | if (!getDefaultSymbol().isShapeVisible()) {
|
||
376 | return;
|
||
377 | } |
||
378 | |||
379 | if (cancel.isCanceled()) {
|
||
380 | return;
|
||
381 | } |
||
382 | |||
383 | IProjection dataProjection; |
||
384 | 42464 | fdiaz | Envelope dataEnvelope; |
385 | Envelope reprojectedDataEnvelope; |
||
386 | // Gets the view envelope
|
||
387 | Envelope viewPortEnvelope = viewPort.getAdjustedEnvelope(); |
||
388 | Envelope reprojectedViewPortEnvelope; |
||
389 | 40435 | jjdelcerro | try {
|
390 | 42464 | fdiaz | dataEnvelope = featureStore.getEnvelope(); |
391 | 40435 | jjdelcerro | if (coordTrans == null) { |
392 | dataProjection = featureStore.getDefaultFeatureType() |
||
393 | .getDefaultSRS(); |
||
394 | |||
395 | // If the data does not provide a projection, use the
|
||
396 | // current view one
|
||
397 | if (dataProjection == null) { |
||
398 | dataProjection = viewPort.getProjection(); |
||
399 | } |
||
400 | |||
401 | 42464 | fdiaz | reprojectedDataEnvelope = dataEnvelope; |
402 | reprojectedViewPortEnvelope = viewPortEnvelope; |
||
403 | 40435 | jjdelcerro | } else {
|
404 | dataProjection = coordTrans.getPOrig(); |
||
405 | |||
406 | 42464 | fdiaz | if ( dataEnvelope!=null && !dataEnvelope.isEmpty()) { |
407 | reprojectedDataEnvelope = dataEnvelope.convert(coordTrans); |
||
408 | 40435 | jjdelcerro | } else {
|
409 | 42464 | fdiaz | reprojectedDataEnvelope = dataEnvelope; |
410 | 40435 | jjdelcerro | } |
411 | 42464 | fdiaz | if ( viewPortEnvelope!=null && !viewPortEnvelope.isEmpty()) { |
412 | reprojectedViewPortEnvelope = viewPortEnvelope.convert(coordTrans.getInverted()); |
||
413 | } else {
|
||
414 | reprojectedViewPortEnvelope = viewPortEnvelope; |
||
415 | } |
||
416 | 40435 | jjdelcerro | } |
417 | } catch (DataException e) {
|
||
418 | throw new LegendDrawingException(e); |
||
419 | } |
||
420 | |||
421 | |||
422 | // Gets the data envelope with the viewport SRS
|
||
423 | 42464 | fdiaz | // Envelope myEnvelope = reprojectedDataEnvelope;
|
424 | 40435 | jjdelcerro | |
425 | // TODO: in some cases, the legend may need a different check to
|
||
426 | // decide if the data must be drawn or not
|
||
427 | // Checks if the viewport envelope intersects with the data envelope
|
||
428 | 42464 | fdiaz | // This condition may seem redundant, but sometimes the transformations may fail and cause false negatives.
|
429 | 43295 | fdiaz | if ((viewPortEnvelope==null || !viewPortEnvelope.intersects(reprojectedDataEnvelope)) && !(reprojectedViewPortEnvelope!=null && reprojectedViewPortEnvelope.intersects(dataEnvelope))) { |
430 | 40435 | jjdelcerro | // The data is not visible in the current viewport, do nothing.
|
431 | return;
|
||
432 | } |
||
433 | |||
434 | // Check if all the data is contained into the viewport envelope
|
||
435 | 42464 | fdiaz | // This condition may seem redundant, but sometimes the transformations may fail and cause false negatives.
|
436 | 47476 | fdiaz | //The Envelope.contains method checks that the parameter is null or not
|
437 | boolean containsAll = viewPortEnvelope.contains(reprojectedDataEnvelope)
|
||
438 | || (reprojectedViewPortEnvelope!=null && reprojectedViewPortEnvelope.contains(dataEnvelope));
|
||
439 | 40435 | jjdelcerro | |
440 | // Create the drawing notification to be reused on each iteration
|
||
441 | DefaultFeatureDrawnNotification drawnNotification = new DefaultFeatureDrawnNotification();
|
||
442 | |||
443 | if (cancel.isCanceled()) {
|
||
444 | return;
|
||
445 | } |
||
446 | |||
447 | FeatureSet featureSet = null;
|
||
448 | 46504 | fdiaz | FeatureSelection selection = null;
|
449 | boolean mustDisposeSelection = false; |
||
450 | 40435 | jjdelcerro | try {
|
451 | taskStatus.message("Retrieve selection");
|
||
452 | 46277 | jjdelcerro | if( featureStore.isFeatureSelectionEmpty() ) {
|
453 | // No hay seleccion, asi que creamos una vacia que consuma pocos recursos.
|
||
454 | selection = featureStore.createMemoryFeatureSelection(); |
||
455 | 46504 | fdiaz | mustDisposeSelection = true;
|
456 | 46277 | jjdelcerro | } else {
|
457 | // Ojo, que esta seleccion puede acabar haciendo un count(*) sobre la tabla.
|
||
458 | selection = featureStore.getFeatureSelection(); |
||
459 | 46504 | fdiaz | mustDisposeSelection = false;
|
460 | 46277 | jjdelcerro | } |
461 | 40435 | jjdelcerro | |
462 | if (featureQuery == null) { |
||
463 | featureQuery = featureStore.createFeatureQuery(); |
||
464 | } |
||
465 | |||
466 | completeQuery(featureStore, featureQuery, scale, queryParameters, |
||
467 | coordTrans, dataProjection, viewPortEnvelope, containsAll); |
||
468 | |||
469 | taskStatus.message("Retrieve data");
|
||
470 | featureSet = featureStore.getFeatureSet(featureQuery); |
||
471 | |||
472 | if (cancel.isCanceled()) {
|
||
473 | return;
|
||
474 | } |
||
475 | |||
476 | taskStatus.message("Drawing");
|
||
477 | drawFeatures(image, g, viewPort, cancel, coordTrans, dpi, |
||
478 | drawnNotification, featureSet, selection); |
||
479 | |||
480 | 43326 | jjdelcerro | } catch (Throwable e) { |
481 | 40435 | jjdelcerro | /*
|
482 | * Probably a reprojection exception (for example,
|
||
483 | * trying to reproject Canada to EPSG:23030)
|
||
484 | */
|
||
485 | throw new LegendDrawingException(e); |
||
486 | 46504 | fdiaz | } finally {
|
487 | if (featureSet != null) { |
||
488 | featureSet.dispose(); |
||
489 | } |
||
490 | if(mustDisposeSelection) {
|
||
491 | DisposeUtils.disposeQuietly(selection); |
||
492 | } |
||
493 | } |
||
494 | } |
||
495 | 40435 | jjdelcerro | |
496 | /**
|
||
497 | * Complete a {@link FeatureQuery} to load the {@link Feature}s to draw.
|
||
498 | */
|
||
499 | @SuppressWarnings("unchecked") |
||
500 | private FeatureQuery completeQuery(FeatureStore featureStore, FeatureQuery featureQuery, double scale, |
||
501 | Map queryParameters, ICoordTrans coordTrans,
|
||
502 | IProjection dataProjection, Envelope viewPortEnvelope, |
||
503 | boolean containsAll) throws DataException { |
||
504 | 47505 | fdiaz | boolean retrievesAllAttributes = ((featureQuery.hasFilter() && !featureQuery.hasAttributeNames()));
|
505 | 40435 | jjdelcerro | |
506 | featureQuery.setScale(scale); |
||
507 | 42464 | fdiaz | |
508 | 40435 | jjdelcerro | //Adds the attributes
|
509 | String[] fieldNames = getRequiredFeatureAttributeNames(featureStore); |
||
510 | 47476 | fdiaz | for (String fieldName : fieldNames) { |
511 | if( StringUtils.isNotBlank(fieldName) ) {
|
||
512 | featureQuery.addAttributeName(fieldName); |
||
513 | } |
||
514 | 45887 | jjdelcerro | } |
515 | 42464 | fdiaz | |
516 | 40435 | jjdelcerro | if (!containsAll) {
|
517 | // Gets the viewport envelope with the data SRS
|
||
518 | Envelope viewPortEnvelopeInMyProj = viewPortEnvelope; |
||
519 | if (coordTrans != null) { |
||
520 | viewPortEnvelopeInMyProj = viewPortEnvelope.convert(coordTrans |
||
521 | .getInverted()); |
||
522 | } |
||
523 | |||
524 | if (dataProjection == null) { |
||
525 | throw new IllegalArgumentException( |
||
526 | "Error, the projection parameter value is null");
|
||
527 | } |
||
528 | |||
529 | 43020 | jjdelcerro | Evaluator iee = SpatialEvaluatorsFactory.getInstance().intersects( |
530 | 43295 | fdiaz | viewPortEnvelopeInMyProj, |
531 | dataProjection, |
||
532 | 43020 | jjdelcerro | featureStore |
533 | ); |
||
534 | 42464 | fdiaz | featureQuery.addFilter(iee); |
535 | 44361 | jjdelcerro | } else {
|
536 | FeatureType ft = featureStore.getDefaultFeatureType(); |
||
537 | ExpressionBuilder expbuilder = ExpressionUtils.createExpressionBuilder(); |
||
538 | featureQuery.addFilter( |
||
539 | expbuilder.not_is_null( |
||
540 | expbuilder.column( |
||
541 | ft.getDefaultGeometryAttributeName() |
||
542 | ) |
||
543 | ).toString() |
||
544 | ); |
||
545 | 40435 | jjdelcerro | } |
546 | 44361 | jjdelcerro | |
547 | 40435 | jjdelcerro | if (queryParameters != null) { |
548 | Iterator iterEntry = queryParameters.entrySet().iterator();
|
||
549 | Entry entry; |
||
550 | while (iterEntry.hasNext()) {
|
||
551 | entry = (Entry) iterEntry.next(); |
||
552 | featureQuery.setQueryParameter((String) entry.getKey(),
|
||
553 | entry.getValue()); |
||
554 | } |
||
555 | 42464 | fdiaz | } |
556 | 47505 | fdiaz | // featureStore.addRequiredAttributes(featureQuery);
|
557 | 45355 | omartinez | if( retrievesAllAttributes ) {
|
558 | featureQuery.retrievesAllAttributes(); |
||
559 | } |
||
560 | 40435 | jjdelcerro | return featureQuery;
|
561 | } |
||
562 | |||
563 | /**
|
||
564 | * Draws the features from the {@link FeatureSet}, with the symbols of the
|
||
565 | * legend.
|
||
566 | */
|
||
567 | 43436 | jjdelcerro | protected void drawFeatures(BufferedImage image, Graphics2D g, |
568 | 40435 | jjdelcerro | ViewPort viewPort, Cancellable cancel, ICoordTrans coordTrans, |
569 | double dpi, DefaultFeatureDrawnNotification drawnNotification,
|
||
570 | FeatureSet featureSet, FeatureSelection selection) |
||
571 | throws BaseException {
|
||
572 | if (isUseZSort()) {
|
||
573 | drawFeaturesMultiLayer(image, g, viewPort, cancel, coordTrans, dpi, |
||
574 | drawnNotification, featureSet, selection); |
||
575 | } else {
|
||
576 | drawFeaturesSingleLayer(image, g, viewPort, cancel, coordTrans, |
||
577 | dpi, drawnNotification, featureSet, selection); |
||
578 | } |
||
579 | } |
||
580 | |||
581 | /**
|
||
582 | * Draws the features from the {@link FeatureSet}, with the symbols of the
|
||
583 | * legend, using a single drawing layer.
|
||
584 | */
|
||
585 | private void drawFeaturesSingleLayer(final BufferedImage image, |
||
586 | final Graphics2D g, final ViewPort viewPort, |
||
587 | final Cancellable cancel, final ICoordTrans coordTrans, |
||
588 | final double dpi, |
||
589 | final DefaultFeatureDrawnNotification drawnNotification,
|
||
590 | FeatureSet featureSet, final FeatureSelection selection)
|
||
591 | throws BaseException {
|
||
592 | |||
593 | try {
|
||
594 | 47476 | fdiaz | featureSet.accept((Object obj) -> {
|
595 | if( cancel.isCanceled() ) {
|
||
596 | throw new VisitCanceledException(); |
||
597 | 40435 | jjdelcerro | } |
598 | 47476 | fdiaz | Feature feat = (Feature) obj; |
599 | drawFeatureSingleLayer(image, g, viewPort, cancel, |
||
600 | coordTrans, dpi, drawnNotification, feat, selection); |
||
601 | 40435 | jjdelcerro | }); |
602 | |||
603 | } catch (ConcurrentDataModificationException e) {
|
||
604 | cancel.setCanceled(true);
|
||
605 | } |
||
606 | } |
||
607 | |||
608 | /**
|
||
609 | * Draws a Feature with the symbols of the legend, using a single drawing
|
||
610 | * layer.
|
||
611 | */
|
||
612 | private void drawFeatureSingleLayer(BufferedImage image, Graphics2D g, |
||
613 | ViewPort viewPort, Cancellable cancel, ICoordTrans coordTrans, |
||
614 | double dpi, DefaultFeatureDrawnNotification drawnNotification,
|
||
615 | Feature feat, FeatureSelection selection) |
||
616 | throws MapContextException, CreateGeometryException {
|
||
617 | |||
618 | Geometry geom = feat.getDefaultGeometry(); |
||
619 | if (geom == null) { |
||
620 | return;
|
||
621 | } |
||
622 | |||
623 | if (geom.getType() == Geometry.TYPES.NULL) {
|
||
624 | return;
|
||
625 | } |
||
626 | |||
627 | 47790 | fdiaz | ISymbol sym = getSymbol(feat, selection, viewPort.getSelectionColor()); |
628 | 40435 | jjdelcerro | if (sym == null) { |
629 | return;
|
||
630 | } |
||
631 | |||
632 | if (coordTrans != null) { |
||
633 | geom = geom.cloneGeometry(); |
||
634 | try {
|
||
635 | geom.reProject(coordTrans); |
||
636 | } catch (ReprojectionRuntimeException re) {
|
||
637 | 42464 | fdiaz | LOG.warn("Can't reproject geometry "+geom.toString(), re);
|
638 | return;
|
||
639 | 40435 | jjdelcerro | } |
640 | } |
||
641 | |||
642 | if (cancel.isCanceled()) {
|
||
643 | return;
|
||
644 | } |
||
645 | |||
646 | drawGeometry(geom, image, feat, sym, viewPort, g, dpi, cancel); |
||
647 | |||
648 | // Notify the drawing observers
|
||
649 | drawnNotification.setFeature(feat); |
||
650 | drawnNotification.setDrawnGeometry(geom); |
||
651 | notifyObservers(drawnNotification); |
||
652 | } |
||
653 | |||
654 | /**
|
||
655 | * Draws the features from the {@link FeatureSet}, with the symbols of the
|
||
656 | * legend, using a multiple drawing layer.
|
||
657 | */
|
||
658 | private void drawFeaturesMultiLayer(BufferedImage image, Graphics2D g, |
||
659 | ViewPort viewPort, Cancellable cancel, ICoordTrans coordTrans, |
||
660 | double dpi, DefaultFeatureDrawnNotification drawnNotification,
|
||
661 | FeatureSet featureSet, FeatureSelection selection) |
||
662 | throws MapContextException, CreateGeometryException, DataException {
|
||
663 | |||
664 | // -- visual FX stuff
|
||
665 | long time = System.currentTimeMillis(); |
||
666 | |||
667 | boolean bSymbolLevelError = false; |
||
668 | int screenRefreshDelay = (int) ((1D / MapContext.getDrawFrameRate()) * 3 * 1000); |
||
669 | 43326 | jjdelcerro | BufferedImage[] imageLevels; |
670 | Graphics2D[] graphics; |
||
671 | 40435 | jjdelcerro | |
672 | imageLevels = new BufferedImage[getZSort().getLevelCount()]; |
||
673 | graphics = new Graphics2D[imageLevels.length]; |
||
674 | for (int i = 0; !cancel.isCanceled() && i < imageLevels.length; i++) { |
||
675 | |||
676 | imageLevels[i] = CompatLocator.getGraphicsUtils() |
||
677 | .createBufferedImage(image.getWidth(), image.getHeight(), |
||
678 | image.getType()); |
||
679 | |||
680 | graphics[i] = imageLevels[i].createGraphics(); |
||
681 | graphics[i].setTransform(g.getTransform()); |
||
682 | graphics[i].setRenderingHints(g.getRenderingHints()); |
||
683 | } |
||
684 | |||
685 | DisposableIterator it = null;
|
||
686 | try {
|
||
687 | it = featureSet.fastIterator(); |
||
688 | // Iteration over each feature
|
||
689 | while (it.hasNext()) {
|
||
690 | if (cancel.isCanceled()) {
|
||
691 | return;
|
||
692 | } |
||
693 | Feature feat = (Feature) it.next(); |
||
694 | |||
695 | bSymbolLevelError |= drawFeatureMultiLayer(image, g, viewPort, |
||
696 | cancel, coordTrans, dpi, drawnNotification, selection, |
||
697 | time, screenRefreshDelay, imageLevels, graphics, feat); |
||
698 | |||
699 | } |
||
700 | } catch (ConcurrentDataModificationException e) {
|
||
701 | cancel.setCanceled(true);
|
||
702 | return;
|
||
703 | } finally {
|
||
704 | 43326 | jjdelcerro | DisposeUtils.dispose(it); |
705 | 40435 | jjdelcerro | } |
706 | |||
707 | g.drawImage(image, 0, 0, null); |
||
708 | |||
709 | Point2D offset = viewPort.getOffset();
|
||
710 | CompatLocator.getGraphicsUtils().translate(g, offset.getX(), |
||
711 | offset.getY()); |
||
712 | |||
713 | for (int i = 0; !cancel.isCanceled() && i < imageLevels.length; i++) { |
||
714 | g.drawImage(imageLevels[i], 0, 0, null); |
||
715 | imageLevels[i] = null;
|
||
716 | graphics[i] = null;
|
||
717 | } |
||
718 | |||
719 | CompatLocator.getGraphicsUtils().translate(g, -offset.getX(), |
||
720 | -offset.getY()); |
||
721 | |||
722 | if (bSymbolLevelError) {
|
||
723 | setZSort(null);
|
||
724 | } |
||
725 | } |
||
726 | |||
727 | /**
|
||
728 | * Draws a Feature with the symbols of the legend, using a multiple drawing
|
||
729 | * layer.
|
||
730 | */
|
||
731 | private boolean drawFeatureMultiLayer(BufferedImage image, Graphics2D g, |
||
732 | ViewPort viewPort, Cancellable cancel, ICoordTrans coordTrans, |
||
733 | double dpi, DefaultFeatureDrawnNotification drawnNotification,
|
||
734 | FeatureSelection selection, long time, int screenRefreshDelay, |
||
735 | BufferedImage[] imageLevels, Graphics2D[] graphics, Feature feat) |
||
736 | throws MapContextException, CreateGeometryException {
|
||
737 | |||
738 | Geometry geom = feat.getDefaultGeometry(); |
||
739 | boolean bSymbolLevelError = false; |
||
740 | long drawingTime = time;
|
||
741 | |||
742 | 43326 | jjdelcerro | if (geom==null || geom.getType() == Geometry.TYPES.NULL) { |
743 | 40435 | jjdelcerro | return false; |
744 | } |
||
745 | |||
746 | 47790 | fdiaz | ISymbol sym = getSymbol(feat, selection, viewPort.getSelectionColor()); |
747 | 40435 | jjdelcerro | |
748 | if (sym == null) { |
||
749 | return false; |
||
750 | } |
||
751 | |||
752 | if (coordTrans != null) { |
||
753 | geom = geom.cloneGeometry(); |
||
754 | geom.reProject(coordTrans); |
||
755 | } |
||
756 | |||
757 | if (cancel.isCanceled()) {
|
||
758 | return false; |
||
759 | } |
||
760 | |||
761 | // Check if this symbol is a multilayer
|
||
762 | int[] symLevels = getZSort().getLevels(sym); |
||
763 | if (sym instanceof IMultiLayerSymbol) { |
||
764 | // if so, treat each of its layers as a single
|
||
765 | // symbol
|
||
766 | // in its corresponding map level
|
||
767 | IMultiLayerSymbol mlSym = (IMultiLayerSymbol) sym; |
||
768 | for (int i = 0; !cancel.isCanceled() && i < mlSym.getLayerCount(); i++) { |
||
769 | ISymbol mySym = mlSym.getLayer(i); |
||
770 | int symbolLevel = 0; |
||
771 | if (symLevels != null) { |
||
772 | symbolLevel = symLevels[i]; |
||
773 | } else {
|
||
774 | /*
|
||
775 | * an error occured when managing symbol levels some of the
|
||
776 | * legend changed events regarding the symbols did not
|
||
777 | * finish satisfactory and the legend is now inconsistent.
|
||
778 | * For this drawing, it will finish as it was at the bottom
|
||
779 | * (level 0) but, when done, the ZSort will be reset to
|
||
780 | * avoid app crashes. This is a bug that has to be fixed.
|
||
781 | */
|
||
782 | bSymbolLevelError = true;
|
||
783 | } |
||
784 | drawGeometry(geom, imageLevels[symbolLevel], feat, mySym, |
||
785 | viewPort, graphics[symbolLevel], dpi, cancel); |
||
786 | } |
||
787 | } else {
|
||
788 | // else, just draw the symbol in its level
|
||
789 | int symbolLevel = 0; |
||
790 | if (symLevels != null) { |
||
791 | symbolLevel = symLevels[0];
|
||
792 | } |
||
793 | drawGeometry(geom, imageLevels[symbolLevel], feat, sym, viewPort, |
||
794 | graphics[symbolLevel], dpi, cancel); |
||
795 | } |
||
796 | |||
797 | // -- visual FX stuff
|
||
798 | // Cuando el offset!=0 se est? dibujando sobre el
|
||
799 | // Layout y por tanto no tiene que ejecutar el
|
||
800 | // siguiente c?digo.
|
||
801 | Point2D offset = viewPort.getOffset();
|
||
802 | if (offset.getX() == 0 && offset.getY() == 0) { |
||
803 | if ((System.currentTimeMillis() - drawingTime) > screenRefreshDelay) { |
||
804 | |||
805 | BufferedImage virtualBim = CompatLocator.getGraphicsUtils()
|
||
806 | .createBufferedImage(image.getWidth(), |
||
807 | image.getHeight(), BufferedImage.TYPE_INT_ARGB);
|
||
808 | |||
809 | Graphics2D virtualGraphics = virtualBim.createGraphics();
|
||
810 | virtualGraphics.drawImage(image, 0, 0, null); |
||
811 | for (int i = 0; !cancel.isCanceled() && i < imageLevels.length; i++) { |
||
812 | virtualGraphics.drawImage(imageLevels[i], 0, 0, null); |
||
813 | } |
||
814 | g.clearRect(0, 0, image.getWidth(), image.getHeight()); |
||
815 | g.drawImage(virtualBim, 0, 0, null); |
||
816 | drawingTime = System.currentTimeMillis();
|
||
817 | } |
||
818 | // -- end visual FX stuff
|
||
819 | |||
820 | } |
||
821 | // Notify the drawing observers
|
||
822 | drawnNotification.setFeature(feat); |
||
823 | drawnNotification.setDrawnGeometry(geom); |
||
824 | notifyObservers(drawnNotification); |
||
825 | return bSymbolLevelError;
|
||
826 | } |
||
827 | |||
828 | /**
|
||
829 | * Returns the symbol to use to draw a {@link Feature} taking into account
|
||
830 | * if it is selected.
|
||
831 | */
|
||
832 | 47790 | fdiaz | private ISymbol getSymbol(Feature feat, FeatureSelection selection, Color selectionColor) |
833 | 40435 | jjdelcerro | throws MapContextException {
|
834 | // retrieve the symbol associated to such feature
|
||
835 | ISymbol sym = getSymbolByFeature(feat); |
||
836 | |||
837 | if (sym != null && selection.isSelected(feat)) { |
||
838 | 47790 | fdiaz | sym = sym.getSymbolForSelection(selectionColor); |
839 | 40435 | jjdelcerro | } |
840 | return sym;
|
||
841 | } |
||
842 | |||
843 | /**
|
||
844 | * Returns if the legend is using a ZSort.
|
||
845 | */
|
||
846 | private boolean isUseZSort() { |
||
847 | return getZSort() != null && getZSort().isUsingZSort(); |
||
848 | } |
||
849 | |||
850 | /**
|
||
851 | * Draws a {@link Geometry} using the given {@link ISymbol}, over the
|
||
852 | * {@link Graphics2D} object.
|
||
853 | */
|
||
854 | private void drawGeometry(Geometry geom, BufferedImage image, |
||
855 | Feature feature, ISymbol symbol, ViewPort viewPort, |
||
856 | Graphics2D graphics, double dpi, Cancellable cancellable) |
||
857 | throws CreateGeometryException {
|
||
858 | |||
859 | 46451 | fdiaz | if (geom instanceof Aggregate && this.isDrawSymbolInEeachPrimitive()) { |
860 | 40435 | jjdelcerro | drawAggregate((Aggregate) geom, image, feature, symbol, viewPort, |
861 | graphics, dpi, cancellable); |
||
862 | } else {
|
||
863 | if (symbol instanceof CartographicSupport) { |
||
864 | 47476 | fdiaz | // if(((CartographicSupport) symbol).getUnit() == -1){
|
865 | // ((CartographicSupport) symbol).setCartographicContext((CartographicContext)null);
|
||
866 | // } else {
|
||
867 | ((CartographicSupport) symbol).setCartographicContext(viewPort, dpi, geom); |
||
868 | // }
|
||
869 | 40435 | jjdelcerro | } |
870 | 47476 | fdiaz | symbol.draw(graphics, viewPort.getAffineTransform(), geom, feature, cancellable); |
871 | 40435 | jjdelcerro | } |
872 | } |
||
873 | |||
874 | /**
|
||
875 | * Draws an {@link Aggregate} using the given {@link ISymbol}, over the
|
||
876 | * {@link Graphics2D} object.
|
||
877 | */
|
||
878 | private void drawAggregate(Aggregate aggregate, BufferedImage image, |
||
879 | Feature feature, ISymbol symbol, ViewPort viewPort, |
||
880 | Graphics2D graphics, double dpi, Cancellable cancellable) |
||
881 | throws CreateGeometryException {
|
||
882 | for (int i = 0; i < aggregate.getPrimitivesNumber(); i++) { |
||
883 | Geometry prim = aggregate.getPrimitiveAt(i); |
||
884 | drawGeometry(prim, image, feature, symbol, viewPort, graphics, dpi, |
||
885 | cancellable); |
||
886 | } |
||
887 | } |
||
888 | |||
889 | 43326 | jjdelcerro | @Override
|
890 | 40435 | jjdelcerro | public Object clone() throws CloneNotSupportedException { |
891 | AbstractVectorialLegend clone = (AbstractVectorialLegend) super.clone();
|
||
892 | |||
893 | // Clone zSort
|
||
894 | 47476 | fdiaz | ZSort theZSort = getZSort(); |
895 | if (theZSort != null) { |
||
896 | 40435 | jjdelcerro | clone.setZSort(new ZSort(clone));
|
897 | } |
||
898 | return clone;
|
||
899 | } |
||
900 | |||
901 | 43326 | jjdelcerro | @Override
|
902 | 40435 | jjdelcerro | public void loadFromState(PersistentState state) |
903 | throws PersistenceException {
|
||
904 | // Set parent properties
|
||
905 | super.loadFromState(state);
|
||
906 | // Set own properties
|
||
907 | |||
908 | setShapeType(state.getInt(FIELD_SHAPETYPE)); |
||
909 | if (state.getBoolean(FIELD_HAS_ZSORT)) {
|
||
910 | setZSort(new ZSort(this)); |
||
911 | } |
||
912 | setDefaultSymbol((ISymbol) state.get(FIELD_DEFAULT_SYMBOL)); |
||
913 | } |
||
914 | |||
915 | 43326 | jjdelcerro | @Override
|
916 | 40435 | jjdelcerro | public void saveToState(PersistentState state) throws PersistenceException { |
917 | // Save parent properties
|
||
918 | super.saveToState(state);
|
||
919 | // Save own properties
|
||
920 | state.set(FIELD_SHAPETYPE, getShapeType()); |
||
921 | state.set(FIELD_HAS_ZSORT, this.zSort != null); |
||
922 | state.set(FIELD_DEFAULT_SYMBOL, getDefaultSymbol()); |
||
923 | } |
||
924 | |||
925 | public static class RegisterPersistence implements Callable { |
||
926 | |||
927 | 43326 | jjdelcerro | @Override
|
928 | 40435 | jjdelcerro | public Object call() throws Exception { |
929 | PersistenceManager manager = ToolsLocator.getPersistenceManager(); |
||
930 | if (manager
|
||
931 | .getDefinition(VECTORIAL_LEGEND_PERSISTENCE_DEFINITION_NAME) == null) {
|
||
932 | DynStruct definition = manager.addDefinition( |
||
933 | AbstractVectorialLegend.class, |
||
934 | VECTORIAL_LEGEND_PERSISTENCE_DEFINITION_NAME, |
||
935 | VECTORIAL_LEGEND_PERSISTENCE_DEFINITION_NAME |
||
936 | + " persistence definition", null, null); |
||
937 | // Extend the Legend base definition
|
||
938 | 43326 | jjdelcerro | definition.extend(manager.getDefinition(LEGEND_PERSISTENCE_DEFINITION_NAME)); |
939 | 40435 | jjdelcerro | |
940 | // Shapetype
|
||
941 | definition.addDynFieldInt(FIELD_SHAPETYPE).setMandatory(true);
|
||
942 | // ZSort
|
||
943 | 43326 | jjdelcerro | definition.addDynFieldBoolean(FIELD_HAS_ZSORT).setMandatory(true);
|
944 | 40435 | jjdelcerro | // Default symbol
|
945 | definition.addDynFieldObject(FIELD_DEFAULT_SYMBOL) |
||
946 | 43326 | jjdelcerro | .setClassOfValue(ISymbol.class).setMandatory(true);
|
947 | 40435 | jjdelcerro | } |
948 | return Boolean.TRUE; |
||
949 | } |
||
950 | |||
951 | } |
||
952 | |||
953 | /**
|
||
954 | * Returns the names of the {@link Feature} attributes required for the
|
||
955 | * {@link ILegend} to operate.
|
||
956 | 42464 | fdiaz | *
|
957 | 40435 | jjdelcerro | * @param featureStore
|
958 | * the store where the {@link Feature}s belong to
|
||
959 | * @return the names of required {@link Feature} attribute names
|
||
960 | * @throws DataException
|
||
961 | * if there is an error getting the attribute names
|
||
962 | */
|
||
963 | protected abstract String[] getRequiredFeatureAttributeNames( |
||
964 | FeatureStore featureStore) throws DataException;
|
||
965 | 46451 | fdiaz | |
966 | /**
|
||
967 | * @return the drawSymbolInEeachPrimitive
|
||
968 | */
|
||
969 | public boolean isDrawSymbolInEeachPrimitive() { |
||
970 | return drawSymbolInEeachPrimitive;
|
||
971 | } |
||
972 | |||
973 | /**
|
||
974 | * @param drawSymbolInEeachPrimitive the drawSymbolInEeachPrimitive to set
|
||
975 | */
|
||
976 | public void setDrawSymbolInEeachPrimitive(boolean drawSymbolInEeachPrimitive) { |
||
977 | this.drawSymbolInEeachPrimitive = drawSymbolInEeachPrimitive;
|
||
978 | } |
||
979 | 40435 | jjdelcerro | } |