Statistics
| Revision:

svn-gvsig-desktop / trunk / org.gvsig.desktop / org.gvsig.desktop.compat.cdc / org.gvsig.fmap.mapcontext / org.gvsig.fmap.mapcontext.api / src / main / java / org / gvsig / fmap / mapcontext / MapContext.java @ 43147

History | View | Annotate | Download (63.2 KB)

1 40559 jjdelcerro
/**
2
 * gvSIG. Desktop Geographic Information System.
3 40435 jjdelcerro
 *
4 40559 jjdelcerro
 * Copyright (C) 2007-2013 gvSIG Association.
5 40435 jjdelcerro
 *
6 42286 jjdelcerro
 * This program is free software; you can redistribute it and/or modify it under
7
 * the terms of the GNU General Public License as published by the Free Software
8
 * Foundation; either version 3 of the License, or (at your option) any later
9
 * version.
10 40435 jjdelcerro
 *
11 42286 jjdelcerro
 * This program is distributed in the hope that it will be useful, but WITHOUT
12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
14
 * details.
15 40435 jjdelcerro
 *
16 42286 jjdelcerro
 * You should have received a copy of the GNU General Public License along with
17
 * this program; if not, write to the Free Software Foundation, Inc., 51
18
 * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 40435 jjdelcerro
 *
20 42286 jjdelcerro
 * For any additional information, do not hesitate to contact us at info AT
21
 * gvsig.com, or visit our website www.gvsig.com.
22 40435 jjdelcerro
 */
23
package org.gvsig.fmap.mapcontext;
24
25
import java.awt.Color;
26
import java.awt.Graphics;
27
import java.awt.Graphics2D;
28
import java.awt.geom.Rectangle2D;
29
import java.awt.image.BufferedImage;
30
import java.text.MessageFormat;
31
import java.util.ArrayList;
32 42293 jjdelcerro
import java.util.Iterator;
33 40435 jjdelcerro
import java.util.List;
34 43147 jjdelcerro
import org.apache.commons.lang3.ArrayUtils;
35 40435 jjdelcerro
36
import org.cresques.cts.ICoordTrans;
37
import org.cresques.cts.IProjection;
38
import org.cresques.geo.Projected;
39
import org.slf4j.Logger;
40
import org.slf4j.LoggerFactory;
41
42
import org.gvsig.compat.CompatLocator;
43
import org.gvsig.compat.print.PrintAttributes;
44
import org.gvsig.fmap.dal.exception.ReadException;
45
import org.gvsig.fmap.dal.feature.FeatureStoreNotification;
46
import org.gvsig.fmap.geom.Geometry.SUBTYPES;
47
import org.gvsig.fmap.geom.GeometryLocator;
48
import org.gvsig.fmap.geom.GeometryManager;
49
import org.gvsig.fmap.geom.exception.CreateEnvelopeException;
50
import org.gvsig.fmap.geom.primitive.Envelope;
51
import org.gvsig.fmap.mapcontext.events.ErrorEvent;
52
import org.gvsig.fmap.mapcontext.events.listeners.AtomicEventListener;
53
import org.gvsig.fmap.mapcontext.events.listeners.ErrorListener;
54
import org.gvsig.fmap.mapcontext.events.listeners.EventBuffer;
55
import org.gvsig.fmap.mapcontext.exceptions.LoadLayerException;
56 41302 jjdelcerro
import org.gvsig.fmap.mapcontext.impl.DefaultMapContextManager;
57 40435 jjdelcerro
import org.gvsig.fmap.mapcontext.layers.CancelationException;
58
import org.gvsig.fmap.mapcontext.layers.FLayer;
59
import org.gvsig.fmap.mapcontext.layers.FLayers;
60
import org.gvsig.fmap.mapcontext.layers.LayerCollectionEvent;
61
import org.gvsig.fmap.mapcontext.layers.LayerCollectionListener;
62
import org.gvsig.fmap.mapcontext.layers.LayerDrawEvent;
63
import org.gvsig.fmap.mapcontext.layers.LayerDrawingListener;
64
import org.gvsig.fmap.mapcontext.layers.LayerPositionEvent;
65
import org.gvsig.fmap.mapcontext.layers.operations.Classifiable;
66
import org.gvsig.fmap.mapcontext.layers.operations.SingleLayer;
67 40713 jldominguez
import org.gvsig.fmap.mapcontext.layers.order.LayerOrderManager;
68 41245 jjdelcerro
import org.gvsig.fmap.mapcontext.layers.vectorial.FLyrVect;
69 40435 jjdelcerro
import org.gvsig.fmap.mapcontext.layers.vectorial.GraphicLayer;
70
import org.gvsig.fmap.mapcontext.rendering.legend.events.listeners.LegendListener;
71
import org.gvsig.fmap.mapcontext.rendering.strategies.SelectedEnvelopeVisitor;
72
import org.gvsig.tools.ToolsLocator;
73
import org.gvsig.tools.dispose.impl.AbstractDisposable;
74
import org.gvsig.tools.dynobject.DynStruct;
75
import org.gvsig.tools.exception.BaseException;
76
import org.gvsig.tools.observer.Observable;
77
import org.gvsig.tools.observer.Observer;
78
import org.gvsig.tools.persistence.PersistenceManager;
79
import org.gvsig.tools.persistence.Persistent;
80
import org.gvsig.tools.persistence.PersistentState;
81
import org.gvsig.tools.persistence.exception.PersistenceException;
82
import org.gvsig.tools.task.Cancellable;
83 41840 jjdelcerro
import org.gvsig.tools.util.Callable;
84 40435 jjdelcerro
import org.gvsig.tools.visitor.Visitor;
85
86
/**
87 42286 jjdelcerro
 * <p>
88
 * The <code>MapContext</code> class represents the model and a part of the
89
 * control and view around graphical layers used by
90
 * {@link MapControl MapControl}.</p>
91 40435 jjdelcerro
 *
92 42286 jjdelcerro
 * <p>
93
 * An instance of <code>MapContext</code> is made up with:
94 40435 jjdelcerro
 * <ul>
95
 * <li>a hierarchy of {@link FLayers FLayers} nodes
96
 * <li>a {@link GraphicLayer GraphicLayer} layer
97
 * <li>a {@link ViewPort ViewPort}
98
 * <li>an {@link EventBuffer EventButter}
99 42286 jjdelcerro
 * <li>some
100
 * {@link com.iver.cit.gvsig.fmap.layers.LegendListener LegendListener}s
101 40435 jjdelcerro
 * <li>some {@link LayerDrawingListener LayerDrawingListener}s
102
 * <li>some {@link ErrorListener ErrorListener}s
103
 * </ul>
104
 * </p>
105
 *
106
 * @author Fernando Gonz?lez Cort?s
107
 */
108
public class MapContext extends AbstractDisposable implements Projected,
109 42513 jjdelcerro
        Persistent, Observer, Iterable<FLayer> {
110 40435 jjdelcerro
111 42286 jjdelcerro
    /**
112
     * <p>
113
     * Defines the value which a unit of a distance measurement must be divided
114
     * to obtain its equivalent <b>in meters</b>.</p>
115
     *
116
     * <p>
117
     * <b><i>Conversion values of distance measurements:</i></b>
118
     * <ul>
119
     * <li><code>MapContext.CHANGEM[0]</code>: kilometer
120
     * <li><code>MapContext.CHANGEM[1]</code>: meter
121
     * <li><code>MapContext.CHANGEM[2]</code>: centimeter
122
     * <li><code>MapContext.CHANGEM[3]</code>: millimeter
123
     * <li><code>MapContext.CHANGEM[4]</code>: international statute mile
124
     * <li><code>MapContext.CHANGEM[5]</code>: yard
125
     * <li><code>MapContext.CHANGEM[6]</code>: foot
126
     * <li><code>MapContext.CHANGEM[7]</code>: inch
127
     * <li><code>MapContext.CHANGEM[8]</code>: grade
128
     * </ul>
129
     *
130
     * <p>
131
     * <h3>Examples:</h3>
132
     * <pre>1 international statute mile / MapContext.CHANGEM[4] = X meters</pre>
133
     * <pre>1 kilometer / MapContext.CHANGEM[0] = X meters</pre>
134
     * <pre>1 grade / MapContext.CHANGEM[8] = X meters</pre>
135
     * </p>
136
     *
137
     * <p>
138
     * <h3>Grade conversion value: <code>MapContext.CHANGEM[8]</code></h3>
139
     * The value of <code>MapContext.CHANGEM[8]</code> represents the meters of
140
     * a straight line between two points on the Earth surface that are 1 grade
141
     * far each other of the center of the Earth. This value has been calculated
142
     * using a radius approximated of R<sub>Earth</sub>=6.37846082678100774672e6
143
     * meters, according these equations:
144
     * <pre>D = 2 * (sin (1)) * R<sub>Earth</sub></pre>
145
     * <pre>MapContext.CHANGEM[8] = 1 / D</pre>
146
     * <h4>Explanation:</h4>
147
     * We get an isosceles triangle with the center of the Earth and the 2
148
     * points on the surface. This triangle can be divided into two rectangle
149
     * triangles. We know two values, the angle of 1 grade, that will be 0.50
150
     * grades in each triangle, and the Earth radius that is the hypotenuse.
151
     * Then we apply trigonometry and get the distance <i>D</i> between both
152
     * points on the Earth surface.</p>
153
     * <p>
154
     * Now we only must invert that value to obtain
155
     * <code>MapContext.CHANGEM[8]</code>.</p>
156
     *
157
     * @deprecated use getDistanceTrans2Meter()
158
     */
159
    public static final double[] CHANGEM = {1000, 1, 0.01, 0.001, 1609.344,
160
        0.9144, 0.3048, 0.0254, 1 / 8.983152841195214E-6};
161 40435 jjdelcerro
162 42286 jjdelcerro
    public static ArrayList AREANAMES = new ArrayList();
163
    public static ArrayList AREAABBR = new ArrayList();
164
    public static ArrayList AREATRANS2METER = new ArrayList();
165 40435 jjdelcerro
166 42286 jjdelcerro
    public static ArrayList DISTANCENAMES = new ArrayList();
167
    public static ArrayList DISTANCEABBR = new ArrayList();
168
    public static ArrayList DISTANCETRANS2METER = new ArrayList();
169 40435 jjdelcerro
170 42286 jjdelcerro
    static {
171
        MapContext.addDistanceUnit("Kilometros", "Km", 1000);
172
        MapContext.addDistanceUnit("Metros", "m", 1);
173
        MapContext.addDistanceUnit("Centimetros", "cm", 0.01);
174
        MapContext.addDistanceUnit("Milimetros", "mm", 0.001);
175
        MapContext.addDistanceUnit("Millas", "mi", 1609.344);
176
        MapContext.addDistanceUnit("Yardas", "Ya", 0.9144);
177
        MapContext.addDistanceUnit("Pies", "ft", 0.3048);
178
        MapContext.addDistanceUnit("Pulgadas", "inche", 0.0254);
179
        MapContext.addDistanceUnit("Grados", "?", 1 / 8.983152841195214E-6);
180 40435 jjdelcerro
181 42286 jjdelcerro
        MapContext.addAreaUnit("Kilometros", "Km", true, 1000);
182
        MapContext.addAreaUnit("Metros", "m", true, 1);
183
        MapContext.addAreaUnit("Centimetros", "cm", true, 0.01);
184
        MapContext.addAreaUnit("Milimetros", "mm", true, 0.001);
185
        MapContext.addAreaUnit("Millas", "mi", true, 1609.344);
186
        MapContext.addAreaUnit("Yardas", "Ya", true, 0.9144);
187
        MapContext.addAreaUnit("Pies", "ft", true, 0.3048);
188
        MapContext.addAreaUnit("Pulgadas", "inche", true, 0.0254);
189
        MapContext.addAreaUnit("Grados", "?", true, 1 / 8.983152841195214E-6);
190 40435 jjdelcerro
191
    }
192
193 42286 jjdelcerro
    private static final GeometryManager geomManager = GeometryLocator.getGeometryManager();
194
195
    private static final MapContextManager mapContextManager = MapContextLocator
196
            .getMapContextManager();
197
198
    private static final Logger logger = LoggerFactory.getLogger(MapContext.class);
199
200
    /**
201
     * <p>
202
     * Determines the number of frames.</p>
203
     *
204
     * <p>
205
     * Number of updates per second that the timer will invoke repaint this
206
     * component.</p>
207
     */
208 40435 jjdelcerro
    private static int drawFrameRate = 3;
209 42286 jjdelcerro
210 40435 jjdelcerro
    /**
211 42286 jjdelcerro
     * <p>
212
     * Returns the draw frame rate.</p>
213
     *
214
     * <p>
215
     * Draw frame rate is the number of repaints of this <code>MapControl</code>
216
     * instance that timer invokes per second.</p>
217
     *
218
     * @return number of repaints of this <code>MapControl</code> instance that
219
     * timer invokes per second
220
     *
221
     * @see #applyFrameRate()
222
     * @see #setDrawFrameRate(int)
223
     */
224
    public static int getDrawFrameRate() {
225
        return drawFrameRate;
226
    }
227 40435 jjdelcerro
228 42286 jjdelcerro
    /**
229
     * <p>
230
     * Sets the draw frame rate.</p>
231
     *
232
     * <p>
233
     * Draw frame rate is the number of repaints of this <code>MapControl</code>
234
     * instance that timer invokes per second.</p>
235
     *
236
     * @param drawFrameRate number of repaints of this <code>MapControl</code>
237
     * instance that timer invokes per second
238
     *
239
     * @see #applyFrameRate()
240
     * @see #getDrawFrameRate()
241
     */
242
    public static void setDrawFrameRate(int dFR) {
243
        drawFrameRate = dFR;
244
    }
245 40435 jjdelcerro
246 42286 jjdelcerro
    public static void addAreaUnit(String name, String abbr, boolean isLinear, double trans2meter) {
247
        if (!AREANAMES.contains(name)) {
248
            AREANAMES.add(name);
249
            String pow = "";
250
            if (isLinear) {
251
                pow = String.valueOf((char) 178);
252
            }
253
            AREAABBR.add(abbr + pow);
254
            AREATRANS2METER.add(new Double(trans2meter));
255
        }
256
    }
257 40435 jjdelcerro
258 42286 jjdelcerro
    public static String[] getAreaNames() {
259
        return (String[]) AREANAMES.toArray(new String[0]);
260
    }
261
262
    public static String[] getAreaAbbr() {
263
        return (String[]) AREAABBR.toArray(new String[0]);
264
    }
265
266
    public static double[] getAreaTrans2Meter() {
267
        int size = AREATRANS2METER.size();
268
        double[] trans2meters = new double[size];
269
        for (int i = 0; i < size; i++) {
270
            trans2meters[i] = ((Double) AREATRANS2METER.get(i)).doubleValue();
271
        }
272
        return trans2meters;
273
    }
274
275
    public static String getOfLinear(int i) {
276
        if (((String) AREAABBR.get(i)).toLowerCase().endsWith(String.valueOf((char) 178))) {
277
            return String.valueOf((char) 178);
278
        }
279
        return "";
280
    }
281
282
    public static void addDistanceUnit(String name, String abbr, double trans2meter) {
283
        if (!DISTANCENAMES.contains(name)) {
284
            DISTANCENAMES.add(name);
285
            DISTANCEABBR.add(abbr);
286
            DISTANCETRANS2METER.add(new Double(trans2meter));
287
        }
288
    }
289
290
    public static String[] getDistanceNames() {
291
        return (String[]) DISTANCENAMES.toArray(new String[0]);
292
    }
293
294
    public String getDistanceName() {
295
        return (String) DISTANCENAMES.get(this.getViewPort().getDistanceUnits());
296
    }
297
298
    public static String[] getDistanceAbbr() {
299
        return (String[]) DISTANCEABBR.toArray(new String[0]);
300
    }
301
302
    public static double[] getDistanceTrans2Meter() {
303
        int size = DISTANCETRANS2METER.size();
304
        double[] trans2meters = new double[size];
305
        for (int i = 0; i < size; i++) {
306
            trans2meters[i] = ((Double) DISTANCETRANS2METER.get(i)).doubleValue();
307
        }
308
        return trans2meters;
309
    }
310
311
    public static int getDistancePosition(String s) {
312
        for (int i = 0; i < DISTANCENAMES.size(); i++) {
313
            if (DISTANCENAMES.get(i).equals(s)) {
314
                return i;
315
            }
316
        }
317
        return 0;
318
    }
319
320
    /**
321
     * <p>
322
     * Defines the value which a unit of a distance measurement must be divided
323
     * to obtain its equivalent <b>in centimeters</b>.</p>
324
     *
325
     * <p>
326
     * <b><i>Conversion values of distance measurements:</i></b>
327
     * <ul>
328
     * <li><code>MapContext.CHANGE[0]</code>: kilometer
329
     * <li><code>MapContext.CHANGE[1]</code>: meter
330
     * <li><code>MapContext.CHANGE[2]</code>: centimeter
331
     * <li><code>MapContext.CHANGE[3]</code>: millimeter
332
     * <li><code>MapContext.CHANGE[4]</code>: international statute mile
333
     * <li><code>MapContext.CHANGE[5]</code>: yard
334
     * <li><code>MapContext.CHANGE[6]</code>: foot
335
     * <li><code>MapContext.CHANGE[7]</code>: inch
336
     * <li><code>MapContext.CHANGE[8]</code>: grade
337
     * </ul>
338
     *
339
     * <p>
340
     * <h3>Examples:</h3>
341
     * <pre>1 international statute mile / MapContext.CHANGE[4] = X centimeters</pre>
342
     * <pre>1 kilometer / MapContext.CHANGE[0] = X centimeters</pre>
343
     * <pre>1 grade / MapContext.CHANGE[8] = X centimeters</pre>
344
     * </p>
345
     *
346
     * <p>
347
     * <h3>Grade conversion value: <code>MapContext.CHANGE[8]</code></h3>
348
     * The value of <code>MapContext.CHANGE[8]</code> represents the centimeters
349
     * of a straight line between two points on the Earth surface that are 1
350
     * grade far each other of the center of the Earth. This value has been
351
     * calculated using a radius approximated of
352
     * R<sub>Earth</sub>=6.37846082678100774672e6 meters, according these
353
     * equations:
354
     * <pre>D = 2 * (sin (1)) * R<sub>Earth</sub></pre>
355
     * <pre>MapContext.CHANGE[8] = 1 / D</pre>
356
     * <h4>Explanation:</h4>
357
     * We get an isosceles triangle with the center of the Earth and the 2
358
     * points on the surface. This triangle can be divided into two rectangle
359
     * triangles. We know two values, the angle of 1 grade, that will be 0.50
360
     * grades in each triangle, and the Earth radius that is the hypotenuse.
361
     * Then we apply trigonometry and get the distance <i>D</i> between both
362
     * points on the Earth surface.</p>
363
     * <p>
364
     * Now we only must invert that value to obtain
365
     * <code>MapContext.CHANGE[8]</code>.</p>
366
     *
367
     * @deprecated use getDistanceTrans2Meter() * 100
368
     */
369
    public static final double[] CHANGE = {100000, 100, 1, 0.1, 160934.4,
370
        91.44, 30.48, 2.54, 1 / 8.983152841195214E-4};
371
372
    /* Do not alter the order and the values of this array, if you need append values.*/
373
    /**
374
     * <p>
375
     * Gets the name of all distance measurements supported by
376
     * <code>MapContext</code>.</p>
377
     */
378 40435 jjdelcerro
//        public static final String[] NAMES= {
379
//                Messages.getString("Kilometros"),
380
//                Messages.getString("Metros"),
381
//                Messages.getString("Centimetros"),
382
//                Messages.getString("Milimetros"),
383
//                Messages.getString("Millas"),
384
//                Messages.getString("Yardas"),
385
//                Messages.getString("Pies"),
386
//                Messages.getString("Pulgadas"),
387
//                Messages.getString("Grados"),
388
//        };
389 42286 jjdelcerro
    public static final int EQUALS = 0;
390 40435 jjdelcerro
391 42286 jjdelcerro
    public static final int DISJOINT = 1;
392 40435 jjdelcerro
393 42286 jjdelcerro
    public static final int INTERSECTS = 2;
394 40435 jjdelcerro
395 42286 jjdelcerro
    public static final int TOUCHES = 3;
396 40435 jjdelcerro
397 42286 jjdelcerro
    public static final int CROSSES = 4;
398 40435 jjdelcerro
399 42286 jjdelcerro
    public static final int WITHIN = 5;
400 40435 jjdelcerro
401 42286 jjdelcerro
    public static final int CONTAINS = 6;
402 40435 jjdelcerro
403 42286 jjdelcerro
    public static final int OVERLAPS = 7;
404 40435 jjdelcerro
405 42286 jjdelcerro
    /**
406
     * A hierarchy of {@link FLayers FLayers} nodes.
407
     *
408
     * @see #getLayers()
409
     * @see #print(Graphics2D, double, PrintAttributes)
410
     */
411
    protected FLayers layers;
412 40435 jjdelcerro
413 42286 jjdelcerro
    /**
414
     * A layer with graphical items: geometries and symbols.
415
     *
416
     * @see #getGraphicsLayer()
417
     * @see #setGraphicsLayer(GraphicLayer)
418
     * @see #print(Graphics2D, double, PrintAttributes)
419
     */
420
    private GraphicLayer tracLayer = null;
421
    //MapContextLocator.getMapContextManager().createGraphicsLayer(getProjection());
422 40435 jjdelcerro
423 42286 jjdelcerro
    /**
424
     * Information for draw layers in a view.
425
     *
426
     * @see #getViewPort()
427
     * @see #setViewPort(ViewPort)
428
     */
429
    private ViewPort viewPort;
430 40435 jjdelcerro
431
        // private ArrayList invalidationListeners = new ArrayList();
432 42286 jjdelcerro
    /**
433
     * Array list with all {@link LegendListener LegendListener} registered to
434
     * this map.
435
     *
436
     * @see #addLayerListener(LegendListener)
437
     * @see #removeLayerListener(LegendListener)
438
     * @see #callLegendChanged()
439
     */
440
    private ArrayList legendListeners = new ArrayList();
441 40435 jjdelcerro
442 42286 jjdelcerro
    /**
443
     * Array list with all {@link LayerDrawingListener LayerDrawingListener}
444
     * registered to this map.
445
     *
446
     * @see #addLayerDrawingListener(LayerDrawingListener)
447
     * @see #removeLayerDrawListener(LayerDrawingListener)
448
     * @see #fireLayerDrawingEvent(LayerDrawEvent)
449
     */
450
    private ArrayList layerDrawingListeners = new ArrayList();
451 40435 jjdelcerro
452 42286 jjdelcerro
    /**
453
     * <p>
454
     * Buffer that is used to store and eject events produced on this map:
455
     * <ul>
456
     * <li>Layer collection events.
457
     * <li>View port events.
458
     * <li>Atomic events.
459
     * <li>Layer events.
460
     * <li>Legend events on a {@link Classificable Classificable} layer.
461
     * <li>Selection events on an {@link AlphanumericData AlphanumericData} data
462
     * layer.
463
     * </ul>
464
     * </p>
465
     *
466
     * @see #addAtomicEventListener(AtomicEventListener)
467
     * @see #removeAtomicEventListener(AtomicEventListener)
468
     * @see #beginAtomicEvent()
469
     * @see #endAtomicEvent()
470
     */
471
    private EventBuffer eventBuffer = new EventBuffer();
472 40435 jjdelcerro
473 42286 jjdelcerro
    /**
474
     * Event listener for the collection of layers of this map.
475
     */
476
    private LayerEventListener layerEventListener = null;
477 40435 jjdelcerro
478 42286 jjdelcerro
    /**
479
     * List with information of all errors produced on all layers.
480
     *
481
     * @see #addLayerError(String)
482
     * @see #getLayersError()
483
     * @see #clearErrors()
484
     */
485
    private ArrayList layersError = new ArrayList();
486 40435 jjdelcerro
487 42286 jjdelcerro
    /**
488
     * Array list with all {@link ErrorListener ErrorListener} registered to
489
     * this map.
490
     *
491
     * @see #addErrorListener(ErrorListener)
492
     * @see #removeErrorListener(LegendListener)
493
     * @see #reportDriverExceptions(String, List)
494
     */
495
    private ArrayList errorListeners = new ArrayList();
496 40435 jjdelcerro
497 42286 jjdelcerro
    /**
498
     * Layer order manager decides position of layers added to this map context.
499
     */
500 40713 jldominguez
    private LayerOrderManager orderManager = null;
501 40435 jjdelcerro
502
        // public static ResourceBundle myResourceBundle =
503 42286 jjdelcerro
    // ResourceBundle.getBundle("FMap");
504
    /**
505
     * <p>
506
     * Default <i>zoom in</i> factor.</p>
507
     * <p>
508
     * Doing a <i>zoom in</i> operation, decreases the focal distance and
509
     * increases the eyesight angle to the surface. This allows view an smaller
510
     * area but with the items bigger.</p>
511
     */
512
    public static double ZOOMINFACTOR = 2;
513 40435 jjdelcerro
514 42286 jjdelcerro
    /**
515
     * <p>
516
     * Default <i>zoom out</i> factor.</p>
517
     * <p>
518
     * Doing a <i>zoom out</i> operation, increases the focal distance and
519
     * decreases the eyesight angle to the surface. This allows view a bigger
520
     * area but with the items smaller.</p>
521
     */
522
    public static double ZOOMOUTFACTOR = 0.5;
523 40435 jjdelcerro
524 42286 jjdelcerro
    /**
525
     *          * Draw version of the context. It's used for know when de componend has
526
     * changed any visualization property
527
     *
528
     * @see getDrawVersion
529
     * @see updateDrawVersion
530
     */
531
    private long drawVersion = 0L;
532 40435 jjdelcerro
533 42286 jjdelcerro
    private long layersVersion = 0L;
534
    private long viewPortVersion = 0L;
535
    private long graphicsLayerVersion = 0L;
536 41245 jjdelcerro
537 42286 jjdelcerro
    /**
538
     * Object to Manage Draw of MapContext
539
     */
540
    private MapContextDrawer mapContextDrawer = null;
541 41245 jjdelcerro
542 42286 jjdelcerro
    /**
543
     * Object to Manage Draw of MapContext
544
     */
545
    private Class mapContextDrawerClass = null;
546 41245 jjdelcerro
547 42286 jjdelcerro
    /**
548
     * <p>
549
     * Color used to represent the selections.</p>
550
     */
551
    private static Color selectionColor = Color.YELLOW;
552
    private ArrayList layersToSnap = new ArrayList();
553 40435 jjdelcerro
554 42286 jjdelcerro
    /**
555
     * <p>
556
     * Gets the color used to represent the selections.</p>
557
     *
558
     * @return color used to represent the selections
559
     */
560
    public static Color getSelectionColor() {
561
        return selectionColor;
562
    }
563 40435 jjdelcerro
564 42286 jjdelcerro
    /**
565
     * <p>
566
     * Sets the color used to represent the selections.</p>
567
     *
568
     * @param selectionColor color used to represent the selections
569
     */
570
    public static void setSelectionColor(Color selectionColor) {
571
        MapContext.selectionColor = selectionColor;
572
    }
573 40435 jjdelcerro
574 42286 jjdelcerro
    /**
575
     * <p>
576
     * Creates a new map context with the drawing information defined in the
577
     * view port argument, and without layers.</p>
578
     *
579
     * @param vp information for drawing the layers of this map in the available
580
     * rectangular area according a projection
581
     */
582
    public MapContext(ViewPort vp) {
583 40435 jjdelcerro
        this(new FLayers(), vp);
584 42286 jjdelcerro
    }
585 40435 jjdelcerro
586 42286 jjdelcerro
    public MapContext() {
587
    }
588 40435 jjdelcerro
589 42286 jjdelcerro
    /**
590
     * <p>
591
     * Creates a new map context with the layers and the drawing information
592
     * defined in the view port arguments.</p>
593
     *
594
     * @param fLayers the initial hierarchy of nodes of layers that this map
595
     * will have
596
     * @param vp information for drawing the layers of this map in the available
597
     * rectangular area according a projection
598
     */
599
    public MapContext(FLayers fLayers, ViewPort vp) {
600
        this.layers = fLayers;
601 40435 jjdelcerro
602 42286 jjdelcerro
        layerEventListener = new LayerEventListener();
603 40435 jjdelcerro
604 42286 jjdelcerro
        if (layers != null) {
605
            layers.setMapContext(this);
606
            layers.addLayerCollectionListener(layerEventListener);
607
            layers.addLayerCollectionListener(eventBuffer);
608
        }
609 40435 jjdelcerro
610 42286 jjdelcerro
        setViewPort(vp);
611
    }
612 40435 jjdelcerro
613 42286 jjdelcerro
    /**
614
     * <p>
615
     * Reports to all driver error listeners registered of a bundle of driver
616
     * exceptions caused in the same map atomic transaction.</p>
617
     *
618
     * @param introductoryText introductory text specified by developer. If
619
     * <code>null</code>, use ""
620
     * @param driverExceptions list with a bundle of driver exceptions caught
621
     * during an atomic event
622
     *
623
     * @see #addErrorListener(ErrorListener)
624
     * @see #removeErrorListener(LegendListener)
625
     */
626
    public synchronized void reportDriverExceptions(String introductoryText,
627
            List driverExceptions) {
628
        for (int i = 0; i < errorListeners.size(); i++) {
629
            ((ErrorListener) errorListeners.get(i)).
630
                    reportDriverExceptions(introductoryText, driverExceptions);
631
        }
632
    }
633
634
    /**
635
     * <p>
636
     * Adds the specified legend listener (if didn't exist) to receive legend
637
     * events from this map.</p>
638
     *
639
     * @param listener the legend listener
640
     *
641
     * @see #removeLayerListener(LegendListener)
642
     * @see #callLegendChanged()
643
     */
644
    public void addLayerListener(LegendListener listener) {
645
        if (!legendListeners.contains(listener)) {
646
            legendListeners.add(listener);
647
        }
648
    }
649 40435 jjdelcerro
        // SUGERENCIA DE PABLO
650 42286 jjdelcerro
    //        public void addLegendListener(LegendListener listener) {
651
    //                if (!legendListeners.contains(listener))
652
    //                        legendListeners.add(listener);
653
    //        }
654 40435 jjdelcerro
655 42286 jjdelcerro
    /**
656
     * <p>
657
     * Adds the specified layer drawing listener to catch and handle drawing
658
     * events from layers of this map.</p>
659
     *
660
     * @param listener the listener to add
661
     *
662
     * @see #removeLayerDrawListener(LayerDrawingListener)
663
     * @see #fireLayerDrawingEvent(LayerDrawEvent)
664
     */
665
    public void addLayerDrawingListener(LayerDrawingListener listener) {
666
        layerDrawingListeners.add(listener);
667
    }
668 40435 jjdelcerro
669 42286 jjdelcerro
    /**
670
     * <p>
671
     * Removes the specified layer drawing listener from this map.</p>
672
     *
673
     * @param listener the listener to remove
674
     *
675
     * @see #addLayerDrawingListener(LayerDrawingListener)
676
     * @see #fireLayerDrawingEvent(LayerDrawEvent)
677
     */
678
    public void removeLayerDrawListener(LayerDrawingListener listener) {
679
        layerDrawingListeners.remove(listener);
680
    }
681 40435 jjdelcerro
682 42286 jjdelcerro
    /**
683
     * <p>
684
     * Adds the specified error listener to receive error events from this
685
     * map.</p>
686
     *
687
     * @param listener the listener to add
688
     *
689
     * @see #removeErrorListener(LegendListener)
690
     * @see #reportDriverExceptions(String, List)
691
     */
692
    public void addErrorListener(ErrorListener listener) {
693
        errorListeners.add(listener);
694
    }
695 40435 jjdelcerro
696 42286 jjdelcerro
    /**
697
     * <p>
698
     * Removes the specified error listener from this map.</p>
699
     *
700
     * @param listener the listener to remove
701
     *
702
     * @see #addErrorListener(ErrorListener)
703
     * @see #reportDriverExceptions(String, List)
704
     */
705
    public void removeErrorListener(LegendListener listener) {
706
        legendListeners.remove(listener);
707
    }
708 40435 jjdelcerro
709
        // SUGERENCIA DE PABLO:
710 42286 jjdelcerro
    //public void removeErrorListener(ErrorListener listener) {
711
    //        errorListeners.remove(listener);
712
    //}
713
    /**
714
     * <p>
715
     * Notifies to all legend listeners registered, that one legend has
716
     * changed.</p>
717
     * <p>
718
     * This method must be called only if it's wanted to reflect a legend
719
     * change.</p>
720
     *
721
     * @see #addLayerListener(LegendListener)
722
     * @see #removeLayerListener(LegendListener)
723
     */
724
    public synchronized void callLegendChanged() {
725
        for (int i = 0; i < legendListeners.size(); i++) {
726
            ((LegendListener) legendListeners.get(i)).legendChanged(null);
727
        }
728
        // getLayers().moveTo(0,0);
729
    }
730 40435 jjdelcerro
731 42286 jjdelcerro
    /**
732
     * <p>
733
     * Fires a layer drawing event to all
734
     * {@link LayerDrawingListener LayerDrawingListener} listeners registered,
735
     * distinguishing the kind of event.</p>
736
     *
737
     * @param e the event
738
     *
739
     * @see #addLayerDrawingListener(LayerDrawingListener)
740
     * @see #removeLayerDrawListener(LayerDrawingListener)
741
     */
742
    public synchronized void fireLayerDrawingEvent(LayerDrawEvent e) {
743
        for (int i = 0; i < layerDrawingListeners.size(); i++) {
744
            LayerDrawingListener listener = (LayerDrawingListener) layerDrawingListeners.get(i);
745
            switch (e.getEventType()) {
746
                case LayerDrawEvent.LAYER_BEFORE_DRAW:
747
                    listener.beforeLayerDraw(e);
748
                    break;
749
                case LayerDrawEvent.LAYER_AFTER_DRAW:
750
                    listener.afterLayerDraw(e);
751
                    break;
752
                case LayerDrawEvent.GRAPHICLAYER_BEFORE_DRAW:
753
                    listener.beforeGraphicLayerDraw(e);
754
                    break;
755
                case LayerDrawEvent.GRAPHICLAYER_AFTER_DRAW:
756
                    listener.afterLayerGraphicDraw(e);
757
                    break;
758
            }
759
        }
760
        // getLayers().moveTo(0,0);
761
    }
762 40435 jjdelcerro
763 42286 jjdelcerro
    /**
764
     * <p>
765
     * Notifies to all error listeners registered, that one error has been
766
     * produced.</p>
767
     *
768
     * @param e the event with information of the error
769
     *
770
     * @see #addErrorListener(ErrorListener)
771
     * @see #removeErrorListener(LegendListener)
772
     * @see #reportDriverExceptions(String, List)
773
     */
774
    public synchronized void callNewErrorEvent(ErrorEvent e) {
775
        for (int i = 0; i < errorListeners.size(); i++) {
776
            ((ErrorListener) errorListeners.get(i)).errorThrown(e);
777
        }
778
        errorListeners.clear();
779
        // getLayers().moveTo(0,0);
780
    }
781 40435 jjdelcerro
782 42286 jjdelcerro
    /**
783
     * <p>
784
     * Removes the specified layer listener from this map.</p>
785
     *
786
     * @param listener the listener to remove
787
     *
788
     * @see #addLayerListener(LegendListener)
789
     * @see #callLegendChanged()
790
     */
791
    public void removeLayerListener(LegendListener listener) {
792
        legendListeners.remove(listener);
793
    }
794 40435 jjdelcerro
795
        // SUGERENCIA DE PABLO:
796 42286 jjdelcerro
    // public void removeLegendListener(LegendListener listener) {
797
    //         legendListeners.remove(listener);
798
    // }
799
    /**
800
     * <p>
801
     * Returns the hierarchy of {@link FLayers FLayers} nodes stored in this
802
     * map.</p>
803
     *
804
     * @return the hierarchy of nodes of layers stored in this map
805
     */
806
    public FLayers getLayers() {
807
        return layers;
808
    }
809 40435 jjdelcerro
810 42286 jjdelcerro
    /**
811
     * <p>
812
     * Draws the visible layers of this map according its view port, on the
813
     * image parameter.</p>
814
     *
815
     * @param b image with an accessible buffer of image data
816
     */
817
    public void drawLabels(BufferedImage b) {
818
    }
819 40435 jjdelcerro
820 42286 jjdelcerro
    /**
821
     * @see #redraw()
822
     */
823
    public void invalidate() {
824
        updateDrawVersion();
825
        // Small hack to let the MapControl receive an event and repaint
826
        FLayer layer;
827
        if (layers.getLayersCount() > 0) {
828
            layer = layers.getLayer(layers.getLayersCount() - 1);
829
        } else {
830
            layer = getGraphicsLayer();
831
        }
832
        LayerPositionEvent layerMovedEvent = LayerPositionEvent
833
                .createLayerMovedEvent(
834
                        layer, 0, 0);
835
        eventBuffer.layerMoved(layerMovedEvent);
836
    }
837 40435 jjdelcerro
838
    /**
839
     * <p>
840
     * Prints the layers of this map using the {@link Graphics2D Graphics2D}
841
     * argument, that usually is the {@link Graphics Graphics} of the printer.
842
     * </p>
843 42286 jjdelcerro
     *
844
     * @param g for rendering 2-dimensional shapes, text and images on the
845
     * Java(tm) platform
846
     * @param scale the scale of the view. Must be between
847
     * {@linkplain FLayer#getMinScale()} and {@linkplain FLayer#getMaxScale()}.
848
     * @param properties a set with the settings to be applied to a whole print
849
     * job and to all the documents in the print job
850
     * @throws MapContextException if there is an error getting the instance of
851
     * MapContextDrawer
852
     *
853
     * @throws ReadDriverException if fails reading with driver.
854
     *
855 40435 jjdelcerro
     * @see GraphicLayer#draw(BufferedImage, Graphics2D, ViewPort, Cancellable,
856 42286 jjdelcerro
     * double)
857 40435 jjdelcerro
     */
858 42286 jjdelcerro
    public void print(Graphics2D g, double scale,
859
            PrintAttributes properties) throws ReadException,
860 40435 jjdelcerro
            MapContextException {
861
862 42286 jjdelcerro
        CompatLocator.getGraphicsUtils().setRenderingHintsForPrinting(g);
863 40435 jjdelcerro
864 42286 jjdelcerro
        Cancellable cancel = new Cancellable() {
865
            public boolean isCanceled() {
866
                return false;
867
            }
868 40435 jjdelcerro
869 42286 jjdelcerro
            public void setCanceled(boolean canceled) {
870
                // No queremos que se pueda cancelar la impresi?n.
871 40435 jjdelcerro
872 42286 jjdelcerro
            }
873
        };
874
        this.getMapContextDrawer().print(this.layers, g, cancel, scale, properties);
875
        if (tracLayer != null) {
876
            tracLayer.draw(null, g, viewPort, cancel, scale);
877
        }
878
    }
879 40435 jjdelcerro
880 42286 jjdelcerro
    /**
881
     * <p>
882
     * Returns a new <code>MapContext</code> instance with the information of
883
     * the <code>vp</code> argument, and the layers of this map.</p>
884
     *
885
     * @param vp information for drawing the layers of this map in the available
886
     * rectangular area according a projection
887
     *
888
     * @return a new <code>MapContext</code> instance projected by
889
     * <code>vp</code>
890
     */
891
    public MapContext createNewFMap(ViewPort vp) {
892
        MapContext ret = new MapContext(vp);
893
        ret.layers = this.layers;
894 40435 jjdelcerro
895 42286 jjdelcerro
        return ret;
896
    }
897
898
    /**
899
     * <p>
900
     * Creates a new independent <code>MapContext</code> instance, that has a
901
     * clone of the layers and the view port of this one.</p>
902
     * <p>
903
     * The new map will have the same data source drivers to avoid waste memory,
904
     * and work faster.</p>
905
     *
906
     * @return the new <code>MapContext</code> instance
907
     *
908
     * @throws XMLException if fails cloning the view port or a layer
909
     *
910
     * @see FLayer#cloneLayer()
911
     * @see ViewPort#cloneViewPort()
912
     */
913
    public MapContext cloneFMap() {
914
        ViewPort vp;
915 40435 jjdelcerro
        try {
916
            vp = (ViewPort) getViewPort().clone();
917
        } catch (CloneNotSupportedException e) {
918
            throw new RuntimeException(e);
919
        }
920 42286 jjdelcerro
        FLayers antLayers = getLayers();
921
        MapContext ret = new MapContext(vp);
922 40713 jldominguez
923 42286 jjdelcerro
        /*
924
         * Cloning order manager
925
         */
926
        LayerOrderManager lom = this.getOrderManager();
927
        try {
928
            lom = (LayerOrderManager) lom.clone();
929
            ret.setOrderManager(lom);
930
        } catch (CloneNotSupportedException e1) {
931
            logger.error("While cloning order manager", e1);
932
        }
933 40435 jjdelcerro
934 42286 jjdelcerro
        FLayers aux = new FLayers();//(ret,null);
935
        aux.setMapContext(ret);
936
        for (int i = 0; i < antLayers.getLayersCount(); i++) {
937
            FLayer lyr = antLayers.getLayer(i);
938
            try {
939
                FLayer auxLayer = lyr.cloneLayer();
940
                aux.addLayer(auxLayer);
941
                auxLayer.dispose();
942
            } catch (Exception e) {
943
                throw new RuntimeException(e);
944
            }
945
        }
946
        ret.layers = aux;
947
        return ret;
948 40435 jjdelcerro
949 42286 jjdelcerro
    }
950 40435 jjdelcerro
951 42286 jjdelcerro
    /**
952
     * Like {@linkplain #cloneFMap()}, but now doesn't clone the layers, rather
953
     * copies them.
954
     *
955
     * @return the new map
956
     */
957
    public MapContext cloneToDraw() {
958
        ViewPort vp;
959 40435 jjdelcerro
        try {
960
            vp = (ViewPort) getViewPort().clone();
961 42286 jjdelcerro
            MapContext mapContext = new MapContext(getLayers(), vp);
962 40435 jjdelcerro
            return mapContext;
963
        } catch (CloneNotSupportedException e) {
964
            throw new RuntimeException(e);
965
        }
966 42286 jjdelcerro
    }
967 40435 jjdelcerro
968 42286 jjdelcerro
    /**
969
     * <p>
970
     * Adds a layer to the group of layers that are at a upper level in the
971
     * tree.</p>
972
     *
973
     * @param vectorial the layer to add
974
     */
975
    public void addToTrackLayer(FLayer vectorial) {
976
    }
977 40435 jjdelcerro
978 42286 jjdelcerro
    /**
979
     * <p>
980
     * Returns the scale of the view in the screen.</p>
981
     *
982
     * @return one of this values:
983
     * <ul>
984
     * <li>the scale of the adjusted extent scale of the view in the screen
985
     * <li><code>-1</code> if there is no image
986
     * <li><code>0</code> if there is no extent defined for the image
987
     * </ul>
988
     *
989
     * @see #setScaleView(long)
990
     * @see ViewPort#getAdjustedExtent()
991
     * @see IProjection#getScale(double, double, double, double)
992
     */
993
    public long getScaleView() {
994
        double dpi = this.getViewPort().getDPI();
995
        IProjection proj = viewPort.getProjection();
996 40435 jjdelcerro
997 42286 jjdelcerro
        if (viewPort.getImageSize() == null) {
998
            return -1;
999
        }
1000 40435 jjdelcerro
1001 42286 jjdelcerro
        if (viewPort.getAdjustedEnvelope() == null) {
1002
            return 0;
1003
        }
1004
        double[] trans2Meter = getDistanceTrans2Meter();
1005
        int mUnits = getViewPort().getMapUnits();
1006 40435 jjdelcerro
1007 42286 jjdelcerro
        if (proj == null) {
1008
            double w = ((viewPort.getImageSize().width / dpi) * 0.0254);
1009
            return (long) (viewPort.getAdjustedEnvelope().getLength(0)
1010
                    / w * trans2Meter[mUnits]);
1011
        }
1012 40435 jjdelcerro
1013 42286 jjdelcerro
        return Math.round(proj.getScale(
1014
                viewPort.getAdjustedEnvelope().getMinimum(0) * trans2Meter[mUnits],
1015
                viewPort.getAdjustedEnvelope().getMaximum(0) * trans2Meter[mUnits],
1016
                viewPort.getImageSize().width,
1017
                dpi));
1018 40435 jjdelcerro
1019 42286 jjdelcerro
    }
1020 40435 jjdelcerro
1021 42286 jjdelcerro
    /**
1022
     * <p>
1023
     * Sets the new extent of the view, calculated using the scale argument.</p>
1024
     * <p>
1025
     * Doesn't updates the scale if there isn't information about the dimension
1026
     * of the image or the adjusted extent.</p>
1027
     *
1028
     * @param scale the new scale for the view
1029
     *
1030
     * @see ViewPort#setProjection(IProjection)
1031
     * @see #getScaleView()
1032
     */
1033
    public void setScaleView(long scale) {
1034
        double dpi = this.getViewPort().getDPI();
1035
        if (viewPort.getImageSize() == null) {
1036
            return;
1037
        }
1038
        IProjection proj = viewPort.getProjection();
1039
        if (viewPort.getAdjustedExtent() == null) {
1040
            return;
1041
        }
1042
        double[] trans2Meter = getDistanceTrans2Meter();
1043
        Envelope env = viewPort.getAdjustedExtent();
1044
        Rectangle2D r = new Rectangle2D.Double(env.getMinimum(0), env.getMinimum(1), env.getLength(0), env.getLength(1));
1045
        Rectangle2D rec = proj.getExtent(r, scale, viewPort.getImageWidth(), viewPort.getImageHeight(), 100 * getDistanceTrans2Meter()[getViewPort().getMapUnits()], trans2Meter[getViewPort().getDistanceUnits()], dpi);
1046
        try {
1047
            getViewPort().setEnvelope(geomManager.createEnvelope(rec.getX(), rec.getY(), rec.getMaxX(), rec.getMaxY(), SUBTYPES.GEOM2D));
1048
        } catch (CreateEnvelopeException e) {
1049
            logger.error("Error seting the bounding box");
1050
        }
1051
    }
1052 40435 jjdelcerro
1053 42286 jjdelcerro
    /**
1054
     * <p>
1055
     * Returns the screen resolution (Dots Per Inch) as it was defined by the
1056
     * user's preference, or by default as it is defined in the default
1057
     * Toolkit.</p>
1058
     *
1059
     * Be care, use ViewPort#getDPI to ensure are using the corrects DPI.
1060
     *
1061
     * @return double with the screen's dpi
1062
     */
1063
    public static double getScreenDPI() {
1064
        return CompatLocator.getGraphicsUtils().getScreenDPI();
1065
    }
1066 40435 jjdelcerro
1067 42286 jjdelcerro
    /**
1068
     * @see
1069
     * org.gvsig.fmap.mapcontext.rendering.strategies.Strategy#process(com.iver.cit.gvsig.fmap.FeatureSelectorVisitor)
1070
     */
1071
    public void process(Visitor visitor) {
1072
    }
1073 40435 jjdelcerro
1074 42286 jjdelcerro
    /**
1075
     * @see
1076
     * org.gvsig.fmap.mapcontext.rendering.strategies.Strategy#processSelected(com.iver.cit.gvsig.fmap.FeatureVisitor)
1077
     */
1078
    public void processSelected(Visitor visitor) {
1079
    }
1080 40435 jjdelcerro
1081 42286 jjdelcerro
    /**
1082
     * @see
1083
     * org.gvsig.fmap.mapcontext.rendering.strategies.Strategy#select(com.iver.cit.gvsig.fmap.FeatureSelectorVisitor,
1084
     * VectorialSubSet)
1085
     */
1086
    public void select(Visitor visitor) {
1087
    }
1088 40435 jjdelcerro
1089 42286 jjdelcerro
    /**
1090
     * @see
1091
     * org.gvsig.fmap.mapcontext.rendering.strategies.Strategy#selectFromSelection()
1092
     */
1093
    public void selectFromSelection() {
1094
    }
1095 40435 jjdelcerro
1096 42286 jjdelcerro
    /**
1097
     * @see
1098
     * org.gvsig.fmap.mapcontext.rendering.strategies.Strategy#createIndex()
1099
     */
1100
    public void createIndex() {
1101
    }
1102 40435 jjdelcerro
1103 42286 jjdelcerro
    /**
1104
     * @see org.cresques.geo.Projected#getProjection()
1105
     *
1106
     * @see ViewPort#getProjection()
1107
     * @see #setProjection(IProjection)
1108
     * @see #reProject(ICoordTrans)
1109
     */
1110
    public IProjection getProjection() {
1111
        return getViewPort().getProjection();
1112
    }
1113 40435 jjdelcerro
1114 42286 jjdelcerro
    /**
1115
     * <p>
1116
     * Sets the new projection.</p>
1117
     *
1118
     * @param proj the new projection
1119
     *
1120
     * @see #getProjection()
1121
     * @see ViewPort#setProjection(IProjection)
1122
     * @see #reProject(ICoordTrans)
1123
     */
1124
    public void setProjection(IProjection proj) {
1125
        if (getViewPort() != null) {
1126
            getViewPort().setProjection(proj);
1127
        }
1128
    }
1129 40435 jjdelcerro
1130 42286 jjdelcerro
    /**
1131
     * @see org.cresques.geo.Projected#reProject(org.cresques.cts.ICoordTrans)
1132
     */
1133
    public void reProject(ICoordTrans arg0) {
1134
        // TODO implementar reprojecci?n (lo que sea eso)
1135
    }
1136 40435 jjdelcerro
1137 42286 jjdelcerro
    public Envelope getSelectionBounds() throws BaseException {
1138 40435 jjdelcerro
1139 42286 jjdelcerro
        SelectedEnvelopeVisitor visitor = new SelectedEnvelopeVisitor();
1140 40435 jjdelcerro
1141 42286 jjdelcerro
        layers.accept(visitor);
1142
        Envelope env_in_data_crs = visitor.getSelectioEnvelope();
1143
        return env_in_data_crs;
1144
    }
1145
1146 40435 jjdelcerro
    /**
1147
     * <p>
1148 42286 jjdelcerro
     * Draws this map if its {@link ViewPort ViewPort} has an extent
1149
     * defined:<br>
1150 40435 jjdelcerro
     * <ol>
1151
     * <li>Selects only the layers that have to be drawn:
1152
     * {@linkplain #prepareDrawing(BufferedImage, Graphics2D, double)}.
1153
     * <li>Sets quality: antialiasing by text and images, and quality rendering.
1154
     * <li>Draws the layers.
1155
     * <li>Fires a <code>LayerDrawEvent.GRAPHICLAYER_BEFORE_DRAW</code>.
1156
     * <li>Draws the graphic layer.
1157
     * <li>Fires a <code>LayerDrawEvent.GRAPHICLAYER_AFTER_DRAW</code>.
1158
     * <li>Invokes the garbage collector and memory clean.
1159
     * </ol>
1160
     * </p>
1161 42286 jjdelcerro
     *
1162
     * @param image buffer used sometimes instead <code>g</code> to accelerate
1163
     * the draw. For example, if two points are as closed that can't be
1164
     * distinguished, draws only one.
1165
     * @param g for rendering 2-dimensional shapes, text and images on the
1166
     * Java(tm) platform
1167
     * @param cancel shared object that determines if this layer can continue
1168
     * being drawn
1169
     * @param scale the scale of the view. Must be between
1170
     * {@linkplain FLayer#getMinScale()} and {@linkplain FLayer#getMaxScale()}.
1171
     * @throws MapContextException if there is an error getting the instance of
1172
     * MapContextDrawer
1173
     * @throws ReadDriverException if fails reading with the driver.
1174 40435 jjdelcerro
     */
1175 42286 jjdelcerro
    public void draw(BufferedImage image, Graphics2D g, Cancellable cancel,
1176
            double scale) throws ReadException, MapContextException {
1177
        if (viewPort.getEnvelope() == null) {
1178
            return;
1179
        }
1180 40435 jjdelcerro
1181 42286 jjdelcerro
        CompatLocator.getGraphicsUtils().setRenderingHintsForDrawing(g);
1182 40435 jjdelcerro
1183 42286 jjdelcerro
        this.getMapContextDrawer().draw(this.layers, image, g, cancel, scale);
1184
    }
1185 40435 jjdelcerro
1186 42286 jjdelcerro
    /**
1187
     * <p>
1188
     * Draws only the internal graphic layer using the information of the
1189
     * {@link ViewPort ViewPort} of this map.</p>
1190
     *
1191
     * @param image image used to accelerate the screen draw
1192
     * @param g for rendering 2-dimensional shapes, text and images on the
1193
     * Java(tm) platform
1194
     * @param cancel shared object that determines if this layer can continue
1195
     * being drawn
1196
     * @param scale value that represents the scale
1197
     * @throws ReadDriverException if fails reading with the driver.
1198
     * @deprecated use
1199
     * {@link #draw(BufferedImage, Graphics2D, Cancellable, double)} instead
1200
     * @see GraphicLayer#draw(BufferedImage, Graphics2D, ViewPort, Cancellable,
1201
     * double)
1202
     */
1203
    public void drawGraphics(BufferedImage image, Graphics2D g,
1204
            Cancellable cancel, double scale) throws ReadException {
1205 40435 jjdelcerro
1206
                // From now on the graphics layer is handled by the MapContextDrawer,
1207 42286 jjdelcerro
        // so call the draw method instead.
1208
        try {
1209
            draw(image, g, cancel, scale);
1210
        } catch (MapContextException e) {
1211
            throw new RuntimeException(e);
1212
        }
1213
    }
1214 40435 jjdelcerro
1215
    /**
1216
     * <p>
1217
     * Like
1218
     * {@linkplain MapContext#draw(BufferedImage, Graphics2D, Cancellable, double)}
1219
     * , but creating the task as cancellable.
1220
     * </p>
1221 42286 jjdelcerro
     *
1222
     * @param image buffer used sometimes instead <code>g</code> to accelerate
1223
     * the draw. For example, if two points are as closed that can't be
1224
     * distinguished, draws only one.
1225
     * @param g for rendering 2-dimensional shapes, text and images on the
1226
     * Java(tm) platform
1227
     * @param scale the scale of the view. Must be between
1228
     * {@linkplain FLayer#getMinScale()} and {@linkplain FLayer#getMaxScale()}.
1229
     * @throws MapContextException if there is an error getting the instance of
1230
     * MapContextDrawer
1231
     *
1232
     * @throws ReadDriverException if the driver fails reading.
1233
     *
1234 40435 jjdelcerro
     * @see #draw(BufferedImage, Graphics2D, Cancellable, double)
1235
     */
1236 42286 jjdelcerro
    public void draw(BufferedImage image, Graphics2D g, double scale)
1237
            throws ReadException, MapContextException {
1238
        draw(image, g, new Cancellable() {
1239
            /**
1240
             * @see org.gvsig.utils.swing.threads.Cancellable#isCanceled()
1241
             */
1242
            public boolean isCanceled() {
1243
                return false;
1244
            }
1245 40435 jjdelcerro
1246 42286 jjdelcerro
            public void setCanceled(boolean canceled) {
1247
                // Do nothing
1248
            }
1249
        }, scale);
1250
    }
1251 40435 jjdelcerro
1252 42286 jjdelcerro
    /**
1253
     * <p>
1254
     * Gets the {@link ViewPort ViewPort} associated to this map.</p>
1255
     *
1256
     * @return the view port
1257
     *
1258
     * @see #setViewPort(ViewPort)
1259
     */
1260
    public ViewPort getViewPort() {
1261
        return viewPort;
1262
    }
1263 40435 jjdelcerro
1264 42286 jjdelcerro
    /**
1265
     * <p>
1266
     * Sets a {@link ViewPort ViewPort} with the drawing information of this
1267
     * map.</p>
1268
     * <p>
1269
     * If there was a previous view port, removes its
1270
     * {@link EventBuffer EventBuffer} and adds the new one.</p>
1271
     *
1272
     * @param viewPort the viewPort
1273
     *
1274
     * @see #getViewPort()
1275
     */
1276
    public void setViewPort(ViewPort viewPort) {
1277
        if (this.viewPort != null) {
1278
            this.viewPort.removeViewPortListener(eventBuffer);
1279
        }
1280 40435 jjdelcerro
1281 42286 jjdelcerro
        if (this.mapContextDrawer != null) {
1282
            this.mapContextDrawer.setViewPort(viewPort);
1283
        }
1284 41245 jjdelcerro
1285 42286 jjdelcerro
        this.viewPort = viewPort;
1286
        if (viewPort != null) {
1287
            viewPort.addViewPortListener(eventBuffer);
1288
        }
1289
    }
1290 40435 jjdelcerro
1291 42286 jjdelcerro
    /**
1292
     * <p>
1293
     * Sets the given extent to the {@link ViewPort ViewPort} and updates the
1294
     * view with the new zoom.</p>
1295
     *
1296
     * @param extent the extent of the new zoom
1297
     */
1298
    public void zoomToEnvelope(Envelope extent) {
1299
        if (extent != null && !extent.isEmpty()) {
1300
            getViewPort().setEnvelope(extent);
1301
        }
1302
    }
1303 40435 jjdelcerro
1304 42286 jjdelcerro
    /**
1305
     * <p>
1306
     * Returns the union of all extents of all layers of this map.</p>
1307
     *
1308
     * @return full extent of layers of this map
1309
     * @throws ReadDriverException if the driver fails reading.
1310
     *
1311
     * @see FLayers#getFullEnvelope()
1312
     */
1313
    public Envelope getFullEnvelope() throws ReadException {
1314
        Envelope envelope = layers.getFullEnvelope();
1315 40435 jjdelcerro
1316 42286 jjdelcerro
        if (tracLayer != null) {
1317
            Envelope graphicsEnvelope = tracLayer.getFullEnvelope();
1318
            if (envelope == null) {
1319
                return graphicsEnvelope;
1320
            } else if (graphicsEnvelope != null) {
1321
                envelope.add(graphicsEnvelope);
1322
            }
1323
        }
1324 40435 jjdelcerro
1325 42286 jjdelcerro
        return envelope;
1326
    }
1327 40435 jjdelcerro
1328 42286 jjdelcerro
    /**
1329
     * <p>
1330
     * Adds a listener of atomic events to the internal
1331
     * {@link EventBuffer EventBuffer}.</p>
1332
     *
1333
     * @param listener the new listener
1334
     *
1335
     * @return <code>true</code> if has added the listener successfully
1336
     *
1337
     * @see #removeAtomicEventListener(AtomicEventListener)
1338
     * @see EventBuffer#addAtomicEventListener(AtomicEventListener)
1339
     */
1340
    public boolean addAtomicEventListener(AtomicEventListener listener) {
1341
        return eventBuffer.addAtomicEventListener(listener);
1342
    }
1343 40435 jjdelcerro
1344 42286 jjdelcerro
    /**
1345
     * <p>
1346
     * Removes a listener of atomic events from the internal
1347
     * {@link EventBuffer EventBuffer}.</p>
1348
     *
1349
     * @param listener the listener to remove
1350
     *
1351 40435 jjdelcerro
     * @return <tt>true</tt> if the list contained the specified element
1352 42286 jjdelcerro
     *
1353
     * @see #addAtomicEventListener(AtomicEventListener)
1354
     * @see EventBuffer#removeAtomicEventListener(AtomicEventListener)
1355
     */
1356
    public boolean removeAtomicEventListener(AtomicEventListener listener) {
1357
        return eventBuffer.removeAtomicEventListener(listener);
1358
    }
1359 40435 jjdelcerro
1360 42286 jjdelcerro
    /**
1361
     * @see EventBuffer#beginAtomicEvent()
1362
     *
1363
     * @see #endAtomicEvent()
1364
     */
1365
    public void beginAtomicEvent() {
1366
        eventBuffer.beginAtomicEvent();
1367
    }
1368 40435 jjdelcerro
1369 42286 jjdelcerro
    /**
1370
     * @see EventBuffer#endAtomicEvent()
1371
     *
1372
     * @see #beginAtomicEvent()
1373
     */
1374
    public void endAtomicEvent() {
1375
        eventBuffer.endAtomicEvent();
1376
    }
1377 40435 jjdelcerro
1378 42286 jjdelcerro
    /**
1379
     * <p>
1380
     * The class <code>LayerEventListener</code> implements the methods of
1381
     * {@link LayerCollectionListener LayerCollectionListener} that handles the
1382
     * "layer added" or "layer removed" events in a map.</p>
1383
     * <p>
1384
     * Is designed as a listener for all layers in a
1385
     * {@link MapContext MapContext}.</p>
1386
     *
1387
     * @author Fernando Gonz?lez Cort?s
1388
     */
1389
    public class LayerEventListener implements LayerCollectionListener {
1390
        /*
1391
         * @see com.iver.cit.gvsig.fmap.layers.LayerCollectionListener#layerAdded(com.iver.cit.gvsig.fmap.layers.LayerCollectionEvent)
1392
         */
1393
1394
        public void layerAdded(LayerCollectionEvent e) {
1395 40435 jjdelcerro
                        // Si es la primera capa, fijamos su extent al ViewPort
1396 42286 jjdelcerro
            // if (getLayers().getLayersCount() == 1) {
1397
            if (getViewPort().getEnvelope() == null) {
1398
                FLayer lyr = e.getAffectedLayer();
1399
                if (lyr.isAvailable()) {
1400
                    try {
1401
                        getViewPort().setEnvelope(lyr.getFullEnvelope());
1402
                    } catch (ReadException ex) {
1403
                        logger.error(
1404
                                MessageFormat.format(
1405
                                        "Can't set envelope to view port from layer {0}",
1406
                                        new Object[]{lyr.getName()}
1407
                                ),
1408
                                ex
1409
                        );
1410
                    }
1411
                }
1412
            }
1413 40435 jjdelcerro
1414 42286 jjdelcerro
            // Registramos al FMap como listener del legend de las capas
1415
            FLayer lyr = e.getAffectedLayer();
1416
            addSelectionListener(lyr);
1417
        }
1418 40435 jjdelcerro
1419 42286 jjdelcerro
        /*
1420
         * @see com.iver.cit.gvsig.fmap.layers.LayerCollectionListener#layerMoved(com.iver.cit.gvsig.fmap.layers.LayerPositionEvent)
1421
         */
1422
        public void layerMoved(LayerPositionEvent e) {
1423
        }
1424 40435 jjdelcerro
1425 42286 jjdelcerro
        /*
1426
         * @see com.iver.cit.gvsig.fmap.layers.LayerCollectionListener#layerRemoved(com.iver.cit.gvsig.fmap.layers.LayerCollectionEvent)
1427
         */
1428
        public void layerRemoved(LayerCollectionEvent e) {
1429
            FLayer lyr = e.getAffectedLayer();
1430 40435 jjdelcerro
1431 42286 jjdelcerro
            lyr.removeLayerListener(eventBuffer);
1432 40435 jjdelcerro
1433 42286 jjdelcerro
            if (lyr instanceof Classifiable) {
1434
                Classifiable c = (Classifiable) lyr;
1435
                c.removeLegendListener(eventBuffer);
1436
            }
1437 40435 jjdelcerro
1438 42286 jjdelcerro
            if (lyr instanceof SingleLayer && ((SingleLayer) lyr).getDataStore() != null) {
1439
                ((SingleLayer) lyr).getDataStore().deleteObserver(
1440
                        MapContext.this);
1441
            }
1442 40435 jjdelcerro
1443 42286 jjdelcerro
        }
1444 40435 jjdelcerro
1445 42286 jjdelcerro
        /*
1446
         * @see com.iver.cit.gvsig.fmap.layers.LayerCollectionListener#layerAdding(com.iver.cit.gvsig.fmap.layers.LayerCollectionEvent)
1447
         */
1448
        public void layerAdding(LayerCollectionEvent e)
1449
                throws CancelationException {
1450
        }
1451 40435 jjdelcerro
1452 42286 jjdelcerro
        /*
1453
         * @see com.iver.cit.gvsig.fmap.layers.LayerCollectionListener#layerMoving(com.iver.cit.gvsig.fmap.layers.LayerPositionEvent)
1454
         */
1455
        public void layerMoving(LayerPositionEvent e)
1456
                throws CancelationException {
1457
        }
1458 40435 jjdelcerro
1459 42286 jjdelcerro
        /*
1460
         * @see com.iver.cit.gvsig.fmap.layers.LayerCollectionListener#layerRemoving(com.iver.cit.gvsig.fmap.layers.LayerCollectionEvent)
1461
         */
1462
        public void layerRemoving(LayerCollectionEvent e)
1463
                throws CancelationException {
1464
        }
1465 40435 jjdelcerro
1466
1467 42286 jjdelcerro
        /*
1468
         * @see com.iver.cit.gvsig.fmap.layers.LayerCollectionListener#visibilityChanged(com.iver.cit.gvsig.fmap.layers.LayerCollectionEvent)
1469
         */
1470
        public void visibilityChanged(LayerCollectionEvent e)
1471
                throws CancelationException {
1472
        }
1473
    }
1474 40435 jjdelcerro
1475 42286 jjdelcerro
    /**
1476
     * <p>
1477
     * Adds the {@link LayerEventListener LayerEventListener} of this map to the
1478
     * collection of layers argument.</p>
1479
     *
1480
     * @param a collection of layers
1481
     */
1482
    public void addAsCollectionListener(FLayers layers2) {
1483
        layers2.addLayerCollectionListener(layerEventListener);
1484
    }
1485 40435 jjdelcerro
1486 42286 jjdelcerro
    /**
1487
     * <p>
1488
     * Returns the internal {@link GraphicLayer GraphicLayer}.</p>
1489
     *
1490
     * @return the graphic layer of this map
1491
     *
1492
     * @see #setGraphicsLayer(GraphicLayer)
1493
     */
1494
    public GraphicLayer getGraphicsLayer() {
1495
        if (tracLayer == null) {
1496
            if (getViewPort() != null) {
1497
                this.tracLayer
1498
                        = MapContextLocator.getMapContextManager()
1499
                        .createGraphicsLayer(
1500
                                getViewPort().getProjection());
1501
            } else {
1502
                this.tracLayer
1503
                        = MapContextLocator.getMapContextManager()
1504
                        .createGraphicsLayer(null);
1505
            }
1506
        }
1507
        return tracLayer;
1508
    }
1509 40435 jjdelcerro
1510 42286 jjdelcerro
    /**
1511
     * <p>
1512
     * Sets a new {@link GraphicLayer GraphicLayer} to this map.</p>
1513
     *
1514
     * @param graphicLayer the new graphic layer
1515
     *
1516
     * @see #getGraphicsLayer()
1517
     */
1518
    public void setGraphicsLayer(GraphicLayer graphicLayer) {
1519
        tracLayer = graphicLayer;
1520
    }
1521 40435 jjdelcerro
1522 42286 jjdelcerro
    /**
1523
     * <p>
1524
     * Indicates whether some other object is "equal to" this map.</p>
1525
     * <p>
1526
     * Returns <code>true</code> if success one of this options:
1527
     * <ul>
1528
     * <li>Both objects are equal according to
1529
     * {@linkplain Object#equals(Object)}.
1530
     * <li>Both maps have the same layers.
1531
     * <li>Both maps have the same number of layers and with the same name.
1532
     * </ul>
1533
     * </p>
1534
     *
1535
     * @param obj the reference object with which to compare.
1536
     * @return <code>true</code> if this object is the same as the
1537
     * <code>arg0</code> argument; otherwise <code>false</code>.
1538
     *
1539
     * @see Object#equals(Object)
1540
     */
1541
    public boolean equals(Object arg0) {
1542
        if (!(arg0 instanceof MapContext)) {
1543
            return false;
1544
        }
1545
        MapContext map = (MapContext) arg0;
1546
        if (super.equals(arg0)) {
1547
            return true;
1548
        }
1549
        if (getLayers() == map.getLayers()) {
1550
            return true;
1551
        }
1552
        boolean isEqual = true;
1553
        if (map.getLayers().getLayersCount() == getLayers().getLayersCount()) {
1554
            for (int i = 0; i < getLayers().getLayersCount(); i++) {
1555 40435 jjdelcerro
1556 42286 jjdelcerro
                if (!getLayers().getLayer(i).getName().equals(
1557
                        map.getLayers().getLayer(i).getName())) {
1558
                    isEqual = false;
1559
                }
1560 40435 jjdelcerro
1561 42286 jjdelcerro
            }
1562
        } else {
1563
            isEqual = false;
1564
        }
1565
        return isEqual;
1566
    }
1567 40435 jjdelcerro
1568 42286 jjdelcerro
    /**
1569
     * <p>
1570
     * Registers the message of an error associated to this map.</p>
1571
     *
1572
     * @param stringProperty the error message
1573
     *
1574
     * @see #getLayersError()
1575
     * @see #clearErrors()
1576
     */
1577
    public void addLayerError(String stringProperty) {
1578
        layersError.add(stringProperty);
1579
    }
1580 40435 jjdelcerro
1581 42286 jjdelcerro
    /**
1582
     * <p>
1583
     * Gets the list with all error messages registered to this map.</p>
1584
     *
1585
     * @return the list of errors registered to this map
1586
     *
1587
     * @see #addLayerError(String)
1588
     * @see #clearErrors()
1589
     */
1590
    public ArrayList getLayersError() {
1591
        return layersError;
1592
    }
1593 40435 jjdelcerro
1594 42286 jjdelcerro
    /**
1595
     * <p>
1596
     * Removes all error messages associated to this map.</p>
1597
     *
1598
     * @see #addLayerError(String)
1599
     * @see #getLayersError()
1600
     */
1601
    public void clearErrors() {
1602
        layersError.clear();
1603
    }
1604 40435 jjdelcerro
1605 42286 jjdelcerro
    /**
1606
     * <p>
1607
     * Creates and returns a new group of layers that belongs to this
1608
     * <code>MapContext</code>.</p>
1609
     *
1610
     * @param parent layer node in this <code>MapContexte</code> that will be
1611
     * the parent of the new node
1612
     * @return the new layer node
1613
     */
1614
    public FLayers getNewGroupLayer(FLayers parent) {
1615
        FLayers group1 = new FLayers();//(this,parent);
1616
        group1.setMapContext(this);
1617
        group1.setParentLayer(parent);
1618
        return group1;
1619
    }
1620 40435 jjdelcerro
1621 42286 jjdelcerro
    public String getClassName() {
1622
        return null;
1623
    }
1624 40435 jjdelcerro
1625 42286 jjdelcerro
    public ArrayList getLayersToSnap() {
1626
        return layersToSnap;
1627
    }
1628 40435 jjdelcerro
1629 42286 jjdelcerro
    public void setLayersToSnap(ArrayList layersToSnap) {
1630
        this.layersToSnap = layersToSnap;
1631 40435 jjdelcerro
1632 42286 jjdelcerro
    }
1633 40435 jjdelcerro
1634 42286 jjdelcerro
    public void update(Observable observable, Object notification) {
1635
        // TODO REVISAR ESTO!!!
1636
        String ntype = null;
1637
        if (notification instanceof FeatureStoreNotification) {
1638
            FeatureStoreNotification fsNotification = (FeatureStoreNotification) notification;
1639
            ntype = fsNotification.getType();
1640
            if (ntype.equals(FeatureStoreNotification.LOAD_FINISHED)
1641
                    || ntype.equals(FeatureStoreNotification.SELECTION_CHANGE)) {
1642
                getLayers().moveTo(0, 0);
1643
            }
1644
        }
1645
    }
1646 40435 jjdelcerro
1647 42286 jjdelcerro
    public long getDrawVersion() {
1648
        if (getViewPort().getDrawVersion() > this.viewPortVersion
1649
                || getLayers().getDrawVersion() > this.layersVersion
1650
                || getGraphicsLayer().getDrawVersion() > graphicsLayerVersion) {
1651
            updateDrawVersion();
1652
        }
1653
        return this.drawVersion;
1654
    }
1655 40435 jjdelcerro
1656 42286 jjdelcerro
    protected void updateDrawVersion() {
1657
        this.layersVersion = getLayers().getDrawVersion();
1658
        this.viewPortVersion = getViewPort().getDrawVersion();
1659
        this.graphicsLayerVersion = getGraphicsLayer().getDrawVersion();
1660
        this.drawVersion++;
1661
    }
1662 40435 jjdelcerro
1663 42286 jjdelcerro
    public MapContextDrawer getMapContextDrawer() throws ReadException,
1664 40435 jjdelcerro
            MapContextException {
1665 42286 jjdelcerro
        if (this.mapContextDrawer == null) {
1666
            if (mapContextDrawerClass == null) {
1667 40435 jjdelcerro
                this.mapContextDrawer = mapContextManager
1668
                        .createDefaultMapContextDrawerInstance();
1669
            } else {
1670
                this.mapContextDrawer = mapContextManager
1671
                        .createMapContextDrawerInstance(mapContextDrawerClass);
1672
            }
1673 42286 jjdelcerro
            this.mapContextDrawer.setMapContext(this);
1674 40435 jjdelcerro
            this.mapContextDrawer.setViewPort(viewPort);
1675 42286 jjdelcerro
        }
1676 40435 jjdelcerro
1677 42286 jjdelcerro
        return this.mapContextDrawer;
1678
    }
1679
1680
    public void setMapContextDrawerClass(Class mapContextDrawerClass)
1681 40435 jjdelcerro
            throws MapContextException {
1682 42286 jjdelcerro
        mapContextManager.validateMapContextDrawer(mapContextDrawerClass);
1683
        this.mapContextDrawerClass = mapContextDrawerClass;
1684
        if (this.mapContextDrawer != null) {
1685
            this.mapContextDrawer.dispose();
1686
            this.mapContextDrawer = null;
1687
        }
1688
    }
1689 40435 jjdelcerro
1690 42286 jjdelcerro
    public void setMapContextDrawer(MapContextDrawer drawer) {
1691
        if (this.mapContextDrawer != null) {
1692
            this.mapContextDrawer.dispose();
1693
            this.mapContextDrawer = null;
1694
        }
1695
        this.mapContextDrawer = drawer;
1696
        if (this.mapContextDrawer != null) {
1697
            this.mapContextDrawer.setMapContext(this);
1698
            this.mapContextDrawer.setViewPort(viewPort);
1699
        }
1700
    }
1701 40435 jjdelcerro
1702 42286 jjdelcerro
    public void loadFromState(PersistentState state)
1703
            throws PersistenceException {
1704 40435 jjdelcerro
1705 42286 jjdelcerro
        ViewPort vp = (ViewPort) state.get("ViewPort");
1706
        setViewPort(vp);
1707
1708
        layers = (FLayers) state.get("layers");
1709
        layers.setName("root layer");
1710
        loadLayers(layers);
1711
        layers.setMapContext(this);
1712
1713
        layerEventListener = new LayerEventListener();
1714
        layers.addLayerCollectionListener(layerEventListener);
1715
1716
        layers.addLayerCollectionListener(eventBuffer);
1717
        layers.setProjection(vp.getProjection());
1718
1719
        //Add the listener for the selection
1720
        addSelectionListener(layers);
1721
1722
        // ======================
1723
        if (state.hasValue("orderManager")) {
1724
            LayerOrderManager lom = (LayerOrderManager) state.get("orderManager");
1725
            this.setOrderManager(lom);
1726
        }
1727
        DefaultMapContextManager manager = (DefaultMapContextManager) MapContextLocator.getMapContextManager();
1728
        manager.notifyLoadMapContext(this);
1729
    }
1730
1731
    private void loadLayers(FLayers lyrs) {
1732
1733
        int sz = lyrs.getLayersCount();
1734
        for (int i = 0; i < sz; i++) {
1735
            try {
1736
                lyrs.getLayer(i).load();
1737
            } catch (LoadLayerException e) {
1738
                logger.error("While loading layer: " + lyrs.getLayer(i).getName());
1739
            }
1740
        }
1741
    }
1742
1743
    public void saveToState(PersistentState state) throws PersistenceException {
1744
        state.set("ViewPort", viewPort);
1745 42293 jjdelcerro
        state.set("layers", (Persistent)layers);
1746 42286 jjdelcerro
        state.set("orderManager", this.getOrderManager());
1747
    }
1748
1749 41840 jjdelcerro
    public static class RegisterPersistence implements Callable {
1750 40435 jjdelcerro
1751 41840 jjdelcerro
        public Object call() {
1752 42286 jjdelcerro
            PersistenceManager manager = ToolsLocator.getPersistenceManager();
1753
            DynStruct definition = manager.addDefinition(
1754
                    MapContext.class,
1755
                    "MapContext",
1756
                    "MapContext Persistence definition",
1757
                    null,
1758
                    null
1759
            );
1760
            definition.addDynFieldObject("ViewPort")
1761
                    .setClassOfValue(ViewPort.class)
1762
                    .setMandatory(true);
1763 40713 jldominguez
1764 42286 jjdelcerro
            definition.addDynFieldObject("layers")
1765
                    .setClassOfValue(FLayers.class)
1766
                    .setMandatory(true);
1767 40713 jldominguez
1768 42286 jjdelcerro
            definition.addDynFieldObject("orderManager")
1769
                    .setClassOfValue(LayerOrderManager.class)
1770
                    .setMandatory(false);
1771
1772 41840 jjdelcerro
            return Boolean.TRUE;
1773
        }
1774
    }
1775 40435 jjdelcerro
1776 42286 jjdelcerro
    protected void doDispose() throws BaseException {
1777
        dispose(layers);
1778
        dispose(tracLayer);
1779
    }
1780
1781 40435 jjdelcerro
    /**
1782 42286 jjdelcerro
     * <p>
1783
     * Registers an event buffer as a listener for all layers as argument.</p>
1784 40435 jjdelcerro
     *
1785 42286 jjdelcerro
     * <p>
1786
     * Each {@link FLayer FLayer} of this map must have an event buffer for all
1787
     * kind of specific listeners of that layer. This method distinguish between {@link Classifiable Classifiable},
1788
     * {@link AlphanumericData AlphanumericData}, and {@link FLayers FLayers}
1789
     * layers, and for each one, registers, for their specific listeners, the
1790
     * <code>eventBuffer</code> as a listener.</p>
1791 40435 jjdelcerro
     *
1792
     * @param the layer or layers
1793
     */
1794 42286 jjdelcerro
    private void addSelectionListener(FLayer lyr) {
1795 40435 jjdelcerro
        lyr.addLayerListener(eventBuffer);
1796
1797
        if (lyr instanceof Classifiable) {
1798
            Classifiable c = (Classifiable) lyr;
1799
            c.addLegendListener(eventBuffer);
1800
        }
1801
1802 42286 jjdelcerro
        if (lyr instanceof FLayers) {
1803
            FLayers lyrs = (FLayers) lyr;
1804
            for (int i = 0; i < lyrs.getLayersCount(); i++) {
1805 40435 jjdelcerro
                addSelectionListener(lyrs.getLayer(i));
1806
            }
1807
        }
1808 42286 jjdelcerro
        if (lyr instanceof SingleLayer) {
1809 40435 jjdelcerro
            if (((SingleLayer) lyr).getDataStore() != null) {
1810
                ((SingleLayer) lyr).getDataStore().addObserver(
1811
                        MapContext.this);
1812
            }
1813
        }
1814
    }
1815 40713 jldominguez
1816
    public void setOrderManager(LayerOrderManager lom) {
1817 42286 jjdelcerro
        orderManager = lom;
1818 40713 jldominguez
    }
1819 42286 jjdelcerro
1820 40713 jldominguez
    public LayerOrderManager getOrderManager() {
1821 42286 jjdelcerro
1822
        if (orderManager == null) {
1823
            orderManager = MapContextLocator.getDefaultOrderManager();
1824
        }
1825
        return orderManager;
1826 40713 jldominguez
    }
1827 42286 jjdelcerro
1828 41245 jjdelcerro
    public boolean hasVectorLayers() {
1829
        return this.hasVectorLayers(this.getLayers());
1830
    }
1831 42286 jjdelcerro
1832 41245 jjdelcerro
    public boolean hasActiveVectorLayers() {
1833
        FLayer[] layers = this.getLayers().getActives();
1834 42286 jjdelcerro
        for (int i = 0; i < layers.length; i++) {
1835 41245 jjdelcerro
            FLayer layer = layers[i];
1836
            if (layer.isAvailable() && layer instanceof FLyrVect) {
1837
                return true;
1838
            }
1839
        }
1840
        return false;
1841
    }
1842 42286 jjdelcerro
1843 43147 jjdelcerro
    public boolean hasActiveLayers() {
1844
        FLayer[] layers = this.getLayers().getActives();
1845
        return !ArrayUtils.isEmpty(layers);
1846
    }
1847
1848
    public boolean hasLayers() {
1849
        return !this.getLayers().isEmpty();
1850
    }
1851
1852 41245 jjdelcerro
    private boolean hasVectorLayers(FLayers layers) {
1853 42286 jjdelcerro
        for (int i = 0; i < layers.getLayersCount(); i++) {
1854
            FLayer lyr = layers.getLayer(i);
1855
            if (lyr instanceof FLayers) {
1856
                if (hasVectorLayers((FLayers) lyr)) {
1857
                    return true;
1858
                }
1859
            } else if (lyr instanceof FLyrVect) {
1860
                return true;
1861 41245 jjdelcerro
            }
1862 42286 jjdelcerro
        }
1863
        return false;
1864 41245 jjdelcerro
    }
1865 42293 jjdelcerro
1866 42513 jjdelcerro
    @Override
1867
    public Iterator<FLayer> iterator() {
1868 42293 jjdelcerro
        return this.layers.iterator();
1869
    }
1870
1871
    public Iterator deepiterator() {
1872
        return this.layers.deepiterator();
1873
    }
1874
1875 40435 jjdelcerro
}