Statistics
| Revision:

svn-gvsig-desktop / tags / v10_RC2c / libraries / libFMap / src / com / iver / cit / gvsig / fmap / MapContext.java @ 8745

History | View | Annotate | Download (26.5 KB)

1
/* gvSIG. Sistema de Informaci?n Geogr?fica de la Generalitat Valenciana
2
 *
3
 * Copyright (C) 2004 IVER T.I. and Generalitat Valenciana.
4
 *
5
 * This program is free software; you can redistribute it and/or
6
 * modify it under the terms of the GNU General Public License
7
 * as published by the Free Software Foundation; either version 2
8
 * of the License, or (at your option) any later version.
9
 *
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 * GNU General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU General Public License
16
 * along with this program; if not, write to the Free Software
17
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,USA.
18
 *
19
 * For more information, contact:
20
 *
21
 *  Generalitat Valenciana
22
 *   Conselleria d'Infraestructures i Transport
23
 *   Av. Blasco Ib??ez, 50
24
 *   46010 VALENCIA
25
 *   SPAIN
26
 *
27
 *      +34 963862235
28
 *   gvsig@gva.es
29
 *      www.gvsig.gva.es
30
 *
31
 *    or
32
 *
33
 *   IVER T.I. S.A
34
 *   Salamanca 50
35
 *   46005 Valencia
36
 *   Spain
37
 *
38
 *   +34 963163400
39
 *   dac@iver.es
40
 */
41
package com.iver.cit.gvsig.fmap;
42

    
43
import java.awt.Graphics2D;
44
import java.awt.RenderingHints;
45
import java.awt.Toolkit;
46
import java.awt.geom.Point2D;
47
import java.awt.geom.Rectangle2D;
48
import java.awt.image.BufferedImage;
49
import java.util.ArrayList;
50

    
51
import org.cresques.cts.ICoordTrans;
52
import org.cresques.cts.IProjection;
53
import org.cresques.geo.Projected;
54

    
55
import com.iver.cit.gvsig.fmap.core.IGeometry;
56
import com.iver.cit.gvsig.fmap.layers.CancelationException;
57
import com.iver.cit.gvsig.fmap.layers.FLayer;
58
import com.iver.cit.gvsig.fmap.layers.FLayers;
59
import com.iver.cit.gvsig.fmap.layers.GraphicLayer;
60
import com.iver.cit.gvsig.fmap.layers.LayerCollectionEvent;
61
import com.iver.cit.gvsig.fmap.layers.LayerCollectionListener;
62
import com.iver.cit.gvsig.fmap.layers.LayerDrawEvent;
63
import com.iver.cit.gvsig.fmap.layers.LayerDrawingListener;
64
import com.iver.cit.gvsig.fmap.layers.LayerPositionEvent;
65
import com.iver.cit.gvsig.fmap.layers.LegendListener;
66
import com.iver.cit.gvsig.fmap.layers.VectorialAdapter;
67
import com.iver.cit.gvsig.fmap.layers.XMLException;
68
import com.iver.cit.gvsig.fmap.layers.layerOperations.AlphanumericData;
69
import com.iver.cit.gvsig.fmap.layers.layerOperations.Classifiable;
70
import com.iver.cit.gvsig.fmap.layers.layerOperations.Selectable;
71
import com.iver.cit.gvsig.fmap.operations.selection.Record;
72
import com.iver.cit.gvsig.fmap.operations.strategies.FeatureVisitor;
73
import com.iver.cit.gvsig.fmap.operations.strategies.SelectedZoomVisitor;
74
import com.iver.cit.gvsig.fmap.operations.strategies.VisitException;
75
import com.iver.cit.gvsig.fmap.rendering.styling.FStyle2D;
76
import com.iver.utiles.XMLEntity;
77
import com.iver.utiles.swing.threads.Cancellable;
78

    
79
/**
80
 * Modelo del mapa.
81
 *
82
 * @author Fernando Gonz?lez Cort?s
83
 */
84
public class MapContext implements Projected {
85
        public static final double[] CHANGEM = { 1000, 1, 0.01, 0.001, 1609.344,
86
                        0.9144, 0.3048, 0.0254 };
87

    
88
        public static final double[] CHANGE = { 100000, 100, 1, 0.1, 160934.4,
89
                        91.44, 30.48, 2.54 };
90

    
91
        public static final int EQUALS = 0;
92

    
93
        public static final int DISJOINT = 1;
94

    
95
        public static final int INTERSECTS = 2;
96

    
97
        public static final int TOUCHES = 3;
98

    
99
        public static final int CROSSES = 4;
100

    
101
        public static final int WITHIN = 5;
102

    
103
        public static final int CONTAINS = 6;
104

    
105
        public static final int OVERLAPS = 7;
106

    
107
        private FLayers layers = new FLayers(this, null);
108

    
109
        private GraphicLayer tracLayer = new GraphicLayer();
110

    
111
        private ViewPort viewPort;
112

    
113
        // private ArrayList invalidationListeners = new ArrayList();
114
        private ArrayList legendListeners = new ArrayList();
115

    
116
        private ArrayList layerDrawingListeners = new ArrayList();
117

    
118
        private EventBuffer eventBuffer = new EventBuffer();
119

    
120
        private LayerEventListener layerEventListener = null;
121

    
122
        private ArrayList layersError = new ArrayList();
123

    
124
        private ArrayList errorListeners = new ArrayList();
125

    
126
        // public static ResourceBundle myResourceBundle =
127
        // ResourceBundle.getBundle("FMap");
128
        public static double ZOOMINFACTOR=2;
129
        public static double ZOOMOUTFACTOR=0.5;
130
        /**
131
         * Crea un nuevo FMap.
132
         *
133
         * @param vp
134
         *            ViewPort.
135
         */
136
        public MapContext(ViewPort vp) {
137
                this.viewPort = vp;
138
                layerEventListener = new LayerEventListener();
139
                layers.addLayerCollectionListener(layerEventListener);
140
                layers.addLayerCollectionListener(eventBuffer);
141

    
142
                if (viewPort != null) {
143
                        viewPort.addViewPortListener(eventBuffer);
144
                }
145
        }
146

    
147
        /**
148
         * A?ade un LegendListener.
149
         *
150
         * @param listener
151
         *            LegendListener a a?adir.
152
         */
153
        public void addLayerListener(LegendListener listener) {
154
                legendListeners.add(listener);
155
        }
156

    
157
        public void addLayerDrawingListener(LayerDrawingListener listener) {
158
                layerDrawingListeners.add(listener);
159
        }
160

    
161
        public void removeLayerDrawListener(LayerDrawingListener listener) {
162
                layerDrawingListeners.remove(listener);
163
        }
164

    
165
        public void addErrorListener(ErrorListener listener) {
166
                errorListeners.add(listener);
167
        }
168

    
169
        public void removeErrorListener(LegendListener listener) {
170
                legendListeners.remove(listener);
171
        }
172

    
173
        /**
174
         * M?todo ejecutado cuando hay un cambio de leyenda que se quiera reflejar.
175
         *
176
         * @param e
177
         *            LegendChangedEvent.
178
         */
179
        public synchronized void callLegendChanged() {
180
                for (int i = 0; i < legendListeners.size(); i++) {
181
                        ((LegendListener) legendListeners.get(i)).legendChanged(null);
182
                }
183
                // getLayers().moveTo(0,0);
184
        }
185

    
186
        public synchronized void fireLayerDrawingEvent(LayerDrawEvent e) {
187
                for (int i = 0; i < layerDrawingListeners.size(); i++)
188
                {
189
                        LayerDrawingListener listener = (LayerDrawingListener) layerDrawingListeners.get(i);
190
                        switch (e.getEventType())
191
                        {
192
                                case LayerDrawEvent.LAYER_BEFORE_DRAW:
193
                                        listener.beforeLayerDraw(e);
194
                                        break;
195
                                case LayerDrawEvent.LAYER_AFTER_DRAW:
196
                                        listener.afterLayerDraw(e);
197
                                        break;
198
                                case LayerDrawEvent.GRAPHICLAYER_BEFORE_DRAW:
199
                                        listener.beforeGraphicLayerDraw(e);
200
                                        break;
201
                                case LayerDrawEvent.GRAPHICLAYER_AFTER_DRAW:
202
                                        listener.afterLayerGraphicDraw(e);
203
                                        break;
204
                        }
205
                }
206
                // getLayers().moveTo(0,0);
207
        }
208

    
209
        public synchronized void callNewErrorEvent(ErrorEvent e) {
210
                for (int i = 0; i < errorListeners.size(); i++) {
211
                        ((ErrorListener) errorListeners.get(i)).errorThrown(e);
212
                }
213
                // getLayers().moveTo(0,0);
214
        }
215

    
216
        /**
217
         * Borra un LegendListener.
218
         *
219
         * @param listener
220
         *            LegendListener a borrar.
221
         */
222
        public void removeLayerListener(LegendListener listener) {
223
                legendListeners.remove(listener);
224
        }
225

    
226
        /**
227
         * Devuelve las capas que contiene el mapa.
228
         *
229
         * @return Capas.
230
         */
231
        public FLayers getLayers() {
232
                return layers;
233
        }
234

    
235
        /**
236
         * Dibuja en la imagen que se pasa como par?metro el contenido de las capas
237
         * visibles del mapa y teniendo en cuenta los datos del ViewPort contenido
238
         * en este FMap
239
         *
240
         * @param b
241
         *            Imagen.
242
         */
243
        public void drawLabels(BufferedImage b) {
244
        }
245

    
246
        /**
247
         * M?todo de conveniencia que se usa provisionalmente para solicitar un
248
         * refresco de todo lo que dependa del FMap (MapContext). Esto provocar? un
249
         * evento de cambio de orden de capas que obligar? a redibujar todo lo que
250
         * depende de FMap (TOC, MapControl, FFrameView, etc).
251
         */
252
        public void invalidate() {
253
                getLayers().moveTo(0, 0);
254
        }
255

    
256
        /**
257
         * Imprime el las capas que contiene el FMap sobre el Graphics2D que se pasa
258
         * como par?metro, normalmente es el Graphics de la impresora.
259
         *
260
         * @param g
261
         *            Graphics2D
262
         *
263
         * @throws DriverException
264
         */
265
        public void print(Graphics2D g, double scale) throws DriverException {
266
                RenderingHints renderHints = new RenderingHints(
267
                                RenderingHints.KEY_ANTIALIASING,
268
                                RenderingHints.VALUE_ANTIALIAS_ON);
269
                renderHints.put(RenderingHints.KEY_RENDERING,
270
                                RenderingHints.VALUE_RENDER_QUALITY);
271
                g.setRenderingHints(renderHints);
272

    
273
                Cancellable cancel = new Cancellable() {
274
                        public boolean isCanceled() {
275
                                return false;
276
                        }
277

    
278
                        public void setCanceled(boolean canceled) {
279
                                // No queremos que se pueda cancelar la impresi?n.
280

    
281
                        }
282
                };
283
                layers.print(g, viewPort, cancel, scale);
284
                tracLayer.draw(null, g, viewPort, cancel, scale);
285
        }
286

    
287
        /**
288
         * Crea un nuevo FMap con la informaci?n del ViewPort que se pasa como
289
         * par?metro.
290
         *
291
         * @param vp
292
         *            ViewPort.
293
         *
294
         * @return FMap nuevo.
295
         */
296
        public MapContext createNewFMap(ViewPort vp) {
297
                MapContext ret = new MapContext(vp);
298
                ret.layers = this.layers;
299

    
300
                return ret;
301
        }
302

    
303
        /**
304
         * Crea un nuevo FMap totalmente desligado, se replican las capas y el
305
         * ViewPort
306
         *
307
         * @return FMap clonado.
308
         *
309
         * @throws XMLException
310
         */
311
        public MapContext cloneFMap() throws XMLException {
312
                return createFromXML(getXMLEntity());
313
        }
314

    
315
        /**
316
         * A?ade la capa que se pasa como par?metro al nodo que se pasa como
317
         * parametro y lanza ProjectionMismatchException si no est?n todas las capas
318
         * de este FMap en la misma proyecci?n. Lanza un ChildNotAllowedException si
319
         * la capa no es un FLayers y no permite hijos
320
         *
321
         * @param vectorial
322
         *            DOCUMENT ME!
323
         */
324

    
325
        /*
326
         * public void addLayer(LayerPath parent, FLayer layer) throws
327
         * ProjectionMismatchException, ChildrenNotAllowedException {
328
         * layers.addLayer(parent, layer); } public void removeLayer(LayerPath
329
         * parent)throws ChildrenNotAllowedException{ layers.removeLayer(parent); }
330
         */
331

    
332
        /**
333
         * A?ade una capa al grupo de capas que se sit?a por encima de todas las
334
         * otras capas
335
         *
336
         * @param vectorial
337
         *            FLayer.
338
         */
339
        public void addToTrackLayer(FLayer vectorial) {
340
        }
341

    
342
        /**
343
         * Devuelve la escala de la vista en pantalla.
344
         *
345
         * @return escala de la vista.
346
         */
347
        public long getScaleView() {
348
                // TODO falta implementar un di?logo para poder especificar el usuario
349
                // los pixels exactos de su pantalla.
350
                Toolkit kit = Toolkit.getDefaultToolkit();
351
                double dpi = kit.getScreenResolution();
352
                IProjection proj = viewPort.getProjection();
353

    
354
                if (viewPort.getImageSize() == null)
355
                        return -1;
356

    
357
                double w = ((viewPort.getImageSize().getWidth() / dpi) * 2.54);
358

    
359
                if (viewPort.getAdjustedExtent() == null) {
360
                        return 0;
361
                }
362

    
363
                if (proj == null) {
364
                        return (long) (viewPort.getAdjustedExtent().getWidth() / w * CHANGE[getViewPort()
365
                                        .getMapUnits()]);
366
                }
367

    
368
                return Math.round(proj.getScale(viewPort.getAdjustedExtent().getMinX(),
369
                                viewPort.getAdjustedExtent().getMaxX(), viewPort.getImageSize()
370
                                                .getWidth(), dpi));
371
        }
372
        /**
373
         * Introduce un nuevo extent en la vista a partir de la escala que se pasa como par?metro.
374
         *
375
         * @return escala de la vista.
376
         */
377
        public void setScaleView(long scale) {
378
                // TODO falta implementar un di?logo para poder especificar el usuario
379
                // los pixels exactos de su pantalla.
380
                Toolkit kit = Toolkit.getDefaultToolkit();
381
                double dpi = kit.getScreenResolution();
382
                if (viewPort.getImageSize() == null)
383
                        return;
384
                IProjection proj = viewPort.getProjection();
385
                if (viewPort.getAdjustedExtent() == null) {
386
                        return;
387
                }
388
                Rectangle2D rec=proj.getExtent(viewPort.getAdjustedExtent(),scale,viewPort.getImageWidth(),viewPort.getImageHeight(),CHANGE[getViewPort().getMapUnits()],dpi);
389
                getViewPort().setExtent(rec);
390
        }
391
        /**
392
         * @see com.iver.cit.gvsig.fmap.operations.strategies.Strategy#setVectorial(com.iver.cit.gvsig.fmap.VectorialAdapter)
393
         */
394
        public void setVectorial(VectorialAdapter v) {
395
        }
396

    
397
        /**
398
         * @see com.iver.cit.gvsig.fmap.operations.strategies.Strategy#process(com.iver.cit.gvsig.fmap.FeatureSelectorVisitor)
399
         */
400
        public void process(FeatureVisitor visitor) {
401
        }
402

    
403
        /**
404
         * @see com.iver.cit.gvsig.fmap.operations.strategies.Strategy#processSelected(com.iver.cit.gvsig.fmap.FeatureVisitor)
405
         */
406
        public void processSelected(FeatureVisitor visitor) {
407
        }
408

    
409
        /**
410
         * @see com.iver.cit.gvsig.fmap.operations.strategies.Strategy#select(com.iver.cit.gvsig.fmap.FeatureSelectorVisitor,
411
         *      VectorialSubSet)
412
         */
413
        public void select(FeatureVisitor visitor) {
414
        }
415

    
416
        /**
417
         * @see com.iver.cit.gvsig.fmap.operations.strategies.Strategy#selectFromSelection()
418
         */
419
        public void selectFromSelection() {
420
        }
421

    
422
        /**
423
         * @see com.iver.cit.gvsig.fmap.operations.strategies.Strategy#createIndex()
424
         */
425
        public void createIndex() {
426
        }
427

    
428
        /**
429
         * @see org.cresques.geo.Projected#getProjection()
430
         */
431
        public IProjection getProjection() {
432
                return getViewPort().getProjection();
433
        }
434

    
435
        /**
436
         * Inserta la proyecci?n.
437
         *
438
         * @param proj
439
         *            Proyecci?n.
440
         */
441
        public void setProjection(IProjection proj) {
442
                if (getViewPort() != null) {
443
                        getViewPort().setProjection(proj);
444
                }
445
        }
446

    
447
        /**
448
         * @see org.cresques.geo.Projected#reProject(org.cresques.cts.ICoordTrans)
449
         */
450
        public void reProject(ICoordTrans arg0) {
451
                // TODO implementar reprojecci?n (lo que sea eso)
452
        }
453

    
454
        /**
455
         * @see com.iver.cit.gvsig.fmap.operations.strategies.Strategy#selectByPoint(java.awt.geom.Point2D,
456
         *      double)
457
         */
458
        /*
459
         * public void selectByPoint(Point2D p, double tolerance) throws
460
         * DriverException { Point2D mapPoint = viewPort.toMapPoint((int) p.getX(),
461
         * (int) p.getY()); SelectByPointVisitor visitor = new
462
         * SelectByPointVisitor(); visitor.setQueriedPoint(mapPoint);
463
         * visitor.setTolerance(getViewPort().toMapDistance(3));
464
         *
465
         * try { layers.process(visitor); } catch (VisitException e) { throw new
466
         * RuntimeException("No se espera que SelectByPointVisitor lance esta
467
         * excepci?n", e); } }
468
         */
469

    
470
        /**
471
         * @see com.iver.cit.gvsig.fmap.operations.strategies.Strategy#selectByRect(java.awt.geom.Rectangle2D)
472
         */
473
        /*
474
         * public void selectByRect(Rectangle2D rect) throws DriverException {
475
         * FLayer[] actives = layers.getActives(); for (int i=0; i < actives.length;
476
         * i++) { if (actives[i] instanceof FLyrVect) { FLyrVect lyrVect =
477
         * (FLyrVect) actives[i]; FBitSet oldBitSet = lyrVect.getSelection();
478
         * FBitSet newBitSet = lyrVect.queryByRect(rect); newBitSet.xor(oldBitSet);
479
         * lyrVect.setSelection(newBitSet); } }
480
         *  }
481
         */
482

    
483
        /**
484
         * @see com.iver.cit.gvsig.fmap.operations.strategies.Strategy#selectByShape(com.iver.cit.gvsig.fmap.fshape.IGeometry,
485
         *      int)
486
         */
487
        public void selectByShape(IGeometry g, int relationship) {
488
        }
489

    
490
        /**
491
         * @see com.iver.cit.gvsig.fmap.operations.strategies.Strategy#queryByPoint(Point2D,
492
         *      double)
493
         */
494
        public Record[] queryByPoint(Point2D p, double tolerance) {
495
                return null;
496
        }
497

    
498
        /**
499
         * @see com.iver.cit.gvsig.fmap.operations.strategies.Strategy#queryByRect(java.awt.geom.Rectangle2D)
500
         */
501
        public Record[] queryByRect(Rectangle2D rect) {
502
                return null;
503
        }
504

    
505
        /**
506
         * @see com.iver.cit.gvsig.fmap.operations.strategies.Strategy#queryByShape(com.iver.cit.gvsig.fmap.fshape.IGeometry,
507
         *      int)
508
         */
509
        public Record[] queryByShape(IGeometry g, int relationship) {
510
                return null;
511
        }
512

    
513
        /**
514
         * @see com.iver.cit.gvsig.fmap.operations.strategies.Strategy#getSelectionBounds()
515
         */
516
        public Rectangle2D getSelectionBounds() {
517
                SelectedZoomVisitor visitor = new SelectedZoomVisitor();
518

    
519
                try {
520
                        layers.process(visitor);
521
                } catch (DriverException e1) {
522
                        throw new RuntimeException(
523
                                        "No se espera que SelectByPointVisitor lance esta excepci?n",
524
                                        e1);
525
                } catch (VisitException e) {
526
                        throw new RuntimeException(
527
                                        "No se espera que SelectByPointVisitor lance esta excepci?n",
528
                                        e);
529
                }
530

    
531
                return visitor.getSelectBound();
532
        }
533

    
534
        /**
535
         * @see com.iver.cit.gvsig.fmap.operations.LayerOperations#draw(java.awt.image.BufferedImage,
536
         *      java.awt.Graphics2D, FStyle2D)
537
         */
538
        public void draw(BufferedImage image, Graphics2D g, Cancellable cancel,
539
                        double scale) throws DriverException {
540
                if (viewPort.getExtent() == null) {
541
                        // System.err.println("viewPort.getExtent() = null");
542
                        return;
543
                }
544
                System.out.println("Viewport despues: " + viewPort.toString());
545
                /*
546
                 * if ((viewPort.getImageWidth() <=0) || (viewPort.getImageHeight() <=
547
                 * 0)) { return; }
548
                 */
549

    
550
                prepareDrawing(image, g, scale);
551

    
552
                // M?s c?lidad al texto
553
                RenderingHints renderHints = new RenderingHints(
554
                                RenderingHints.KEY_ANTIALIASING,
555
                                RenderingHints.VALUE_ANTIALIAS_ON);
556
                renderHints.put(RenderingHints.KEY_RENDERING,
557
                                RenderingHints.VALUE_RENDER_QUALITY);
558
                renderHints.put(RenderingHints.KEY_TEXT_ANTIALIASING,
559
                                RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
560
                g.setRenderingHints(renderHints);
561

    
562
                long t1 = System.currentTimeMillis();
563
                layers.draw(image, g, viewPort, cancel, scale);
564

    
565
                LayerDrawEvent beforeTracLayerEvent = new LayerDrawEvent(tracLayer,
566
                                g, viewPort, LayerDrawEvent.GRAPHICLAYER_BEFORE_DRAW);
567
                fireLayerDrawingEvent(beforeTracLayerEvent);
568
                tracLayer.draw(image, g, viewPort, cancel, scale);
569
                LayerDrawEvent afterTracLayerEvent = new LayerDrawEvent(tracLayer,
570
                                g, viewPort, LayerDrawEvent.GRAPHICLAYER_AFTER_DRAW);
571
                fireLayerDrawingEvent(afterTracLayerEvent);
572

    
573
                long t2 = System.currentTimeMillis();
574
                System.err.println("Tiempo de dibujado:" + (t2 - t1) +
575
                                " mseg. Memoria libre:" + Runtime.getRuntime().freeMemory() / 1024  + " KB");
576
                /*
577
                 * g.setColor(Color.BLUE); GeneralPath shpR = new
578
                 * GeneralPath(viewPort.getExtent());
579
                 * shpR.transform(viewPort.getAffineTransform()); g.draw(shpR);
580
                 */
581
                System.gc();
582
        }
583

    
584
        /**
585
         * En esta funci?n vamos a revisar las capas que necesitan repintarse,
586
         * por si hay alguna que se haya guardado la imagen de las anteriores
587
         * y puede acelerar el dibujado.
588
         * @param image
589
         * @param g
590
         * @param scale
591
         */
592
        private void prepareDrawing(BufferedImage image, Graphics2D g, double scale) {
593

    
594
                // Primera pasada: si alguna capa necesita repintarse por debajo
595
                // de la que tiene la cache, TODAS necesitan
596
                // ser repintadas.
597
                boolean bNeedRepaint = false;
598
                boolean bMayExistAceleration = false;
599
                for (int i = 0; i < layers.getLayersCount(); i++)
600
                {
601
                        FLayer lyr = layers.getLayer(i);
602
                        if (lyr.isCachingDrawnLayers() && (lyr.getCacheImageDrawnLayers() != null))
603
                        {
604
                                bMayExistAceleration = true;
605
                        }
606
                        else
607
                        {
608
                                if (lyr.isDirty())
609
                                        bNeedRepaint = true;
610
                        }
611
                }
612
                if (bMayExistAceleration==false)
613
                        bNeedRepaint = true;
614
                if (bNeedRepaint)
615
                        layers.setDirty(true);
616
                else
617
                        recursivePrepareDrawing(layers, 0);
618
        }
619

    
620
        private void validatePreviousLayers(FLayers layers, int index)
621
        {
622
                // TODO: Aqu? quiz?s habr?a que explorar los padres de las capas
623
                // para marcar y/o asignar la imagen cacheada.
624
                for (int i = 0; i < index; i++)
625
                {
626
                        FLayer lyr = layers.getLayer(i);
627
                        lyr.setDirty(false);
628
                }
629
                // Las de arriba las marcamos como sucias
630
//                for (int i = index; i < layers.getLayersCount(); i++)
631
//                {
632
//                        FLayer lyr = layers.getLayer(i);
633
//                        lyr.setDirty(true);
634
//                }
635
        }
636

    
637
        private void recursivePrepareDrawing(FLayers parent, int indexInParent)
638
        {
639
                for (int i = indexInParent; i < parent.getLayersCount(); i++)
640
                {
641
                        FLayer lyr = layers.getLayer(i);
642
                        if (lyr.isCachingDrawnLayers() && (lyr.getCacheImageDrawnLayers() != null))
643
                        {
644
                                // les decimos a las anteriores que est?n validadas (not dirty)
645
                                // para que no se dibujen.
646
                                if (lyr.isDirty())
647
                                        validatePreviousLayers(parent, i);
648
                        }
649

    
650
                        if (lyr instanceof FLayers)
651
                        {
652
                                recursivePrepareDrawing((FLayers)lyr, 0);
653
                        }
654
                }
655

    
656
        }
657

    
658
        public void drawGraphics(BufferedImage image, Graphics2D g,
659
                        Cancellable cancel, double scale) throws DriverException {
660
                if (viewPort == null)
661
                        return;
662
                tracLayer.draw(image, g, viewPort, cancel, scale);
663
        }
664

    
665
        /**
666
         * @see com.iver.cit.gvsig.fmap.operations.LayerOperations#draw(java.awt.image.BufferedImage,
667
         *      java.awt.Graphics2D, FStyle2D)
668
         */
669
        public void draw(BufferedImage image, Graphics2D g, double scale)
670
                        throws DriverException {
671
                layers.setDirty(true);
672
                draw(image, g, new Cancellable() {
673
                        /**
674
                         * @see com.iver.utiles.swing.threads.Cancellable#isCanceled()
675
                         */
676
                        public boolean isCanceled() {
677
                                return false;
678
                        }
679

    
680
                        public void setCanceled(boolean canceled) {
681
                                // TODO Auto-generated method stub
682

    
683
                        }
684
                }, scale);
685
        }
686

    
687
        /**
688
         * Devuelve el ViewPort.
689
         *
690
         * @return Returns the viewPort.
691
         */
692
        public ViewPort getViewPort() {
693
                return viewPort;
694
        }
695

    
696
        /**
697
         * Inserta un ViewPort.
698
         *
699
         * @param viewPort
700
         *            The viewPort to set.
701
         */
702
        public void setViewPort(ViewPort viewPort) {
703
                if (this.viewPort != null) {
704
                        this.viewPort.removeViewPortListener(eventBuffer);
705
                }
706

    
707
                this.viewPort = viewPort;
708
                viewPort.addViewPortListener(eventBuffer);
709
        }
710

    
711
        /**
712
         * M?todo de conveniencia. Recorre las capas y te da el fullExtent
713
         *
714
         * @return fullExtent de todas las capas.
715
         *
716
         * @throws DriverException
717
         */
718
        public Rectangle2D getFullExtent() throws DriverException {
719
                return layers.getFullExtent();
720
        }
721

    
722
        /**
723
         * Devuelve el XMLEntity.
724
         *
725
         * @return XMLEntity.
726
         * @throws XMLException
727
         */
728
        public XMLEntity getXMLEntity() throws XMLException {
729
                XMLEntity xml = new XMLEntity();
730
                xml.putProperty("className", this.getClass().getName());
731
                xml.addChild(viewPort.getXMLEntity());
732
                xml.addChild(layers.getXMLEntity());
733

    
734
                return xml;
735
        }
736

    
737
        /**
738
         * Crea un nuevo FMAp a partir del XMLEntity.
739
         *
740
         * @param xml
741
         *            XMLEntity
742
         *
743
         * @return Nuevo FMap.
744
         *
745
         * @throws XMLException
746
         */
747
        public static MapContext createFromXML03(XMLEntity xml) throws XMLException {
748
                ViewPort vp = ViewPort.createFromXML03(xml.getChild(0));
749
                MapContext fmap = new MapContext(vp);
750
                fmap.layers.setXMLEntity03(xml.getChild(1));
751

    
752
                return fmap;
753
        }
754

    
755
        /**
756
         * Crea un nuevo FMAp a partir del XMLEntity.
757
         *
758
         * @param xml
759
         *            XMLEntity
760
         *
761
         * @return Nuevo FMap.
762
         *
763
         * @throws XMLException
764
         */
765
        public static MapContext createFromXML(XMLEntity xml) throws XMLException {
766
                ViewPort vp = ViewPort.createFromXML(xml.getChild(0));
767
                MapContext fmap = new MapContext(vp);
768
                fmap.layers.setXMLEntity(xml.getChild(1));
769

    
770
                return fmap;
771
        }
772

    
773
        /**
774
         * A?ade un AtomicEventListener.
775
         *
776
         * @param listener
777
         *            AtomicEventListener.
778
         *
779
         * @return True si se ha a?adido correctamente.
780
         */
781
        public boolean addAtomicEventListener(AtomicEventListener listener) {
782
                return eventBuffer.addAtomicEventListener(listener);
783
        }
784

    
785
        /**
786
         * Borra un AtomicEventListener de la lista de listeners.
787
         *
788
         * @param listener
789
         *            AtomicEventListener a borrar.
790
         *
791
         * @return True si se ha borrado correctamente.
792
         */
793
        public boolean removeAtomicEventListener(AtomicEventListener listener) {
794
                return eventBuffer.removeAtomicEventListener(listener);
795
        }
796

    
797
        /**
798
         * Inicializa los AtomicEvent.
799
         */
800
        public void beginAtomicEvent() {
801
                eventBuffer.beginAtomicEvent();
802
        }
803

    
804
        /**
805
         * Finaliza los AtomicEvent.
806
         */
807
        public void endAtomicEvent() {
808
                eventBuffer.endAtomicEvent();
809
        }
810

    
811
        /**
812
         * Evento Layer.
813
         *
814
         * @author Fernando Gonz?lez Cort?s
815
         */
816
        public class LayerEventListener implements LayerCollectionListener {
817
                /**
818
                 * @see com.iver.cit.gvsig.fmap.layers.LayerCollectionListener#layerAdded(com.iver.cit.gvsig.fmap.layers.LayerCollectionEvent)
819
                 */
820
                public void layerAdded(LayerCollectionEvent e) {
821
                        // Si es la primera capa, fijamos su extent al ViewPort
822
                        // if (getLayers().getLayersCount() == 1) {
823
                        if (getViewPort().getExtent() == null) {
824
                                FLayer lyr = e.getAffectedLayer();
825

    
826
                                try {
827
                                        getViewPort().setExtent(lyr.getFullExtent());
828
                                } catch (DriverException e1) {
829
                                }
830
                        }
831

    
832
                        // Registramos al FMap como listener del legend de las capas
833
                        FLayer lyr = e.getAffectedLayer();
834

    
835
                        lyr.addLayerListener(eventBuffer);
836

    
837
                        if (lyr instanceof Classifiable) {
838
                                Classifiable c = (Classifiable) lyr;
839
                                c.addLegendListener(eventBuffer);
840
                        }
841

    
842
                        if (lyr instanceof AlphanumericData) {
843
                                Selectable s=null;
844
                                try {
845
                                        s = ((AlphanumericData) lyr).getRecordset();
846
                                        if (s!=null) {
847
                                                s.addSelectionListener(eventBuffer);
848
                                        }
849
                                } catch (DriverException e1) {
850
                                        // TODO Auto-generated catch block
851
                                        e1.printStackTrace();
852
                                }
853

    
854
                        }
855
                }
856

    
857
                /**
858
                 * @see com.iver.cit.gvsig.fmap.layers.LayerCollectionListener#layerMoved(com.iver.cit.gvsig.fmap.layers.LayerPositionEvent)
859
                 */
860
                public void layerMoved(LayerPositionEvent e) {
861
                }
862

    
863
                /**
864
                 * @see com.iver.cit.gvsig.fmap.layers.LayerCollectionListener#layerRemoved(com.iver.cit.gvsig.fmap.layers.LayerCollectionEvent)
865
                 */
866
                public void layerRemoved(LayerCollectionEvent e) {
867
                        FLayer lyr = e.getAffectedLayer();
868

    
869
                        lyr.removeLayerListener(eventBuffer);
870

    
871
                        if (lyr instanceof Classifiable) {
872
                                Classifiable c = (Classifiable) lyr;
873
                                c.removeLegendListener(eventBuffer);
874
                        }
875

    
876
                        if (lyr instanceof Selectable) {
877
                                Selectable s = (Selectable) lyr;
878
                                s.addSelectionListener(eventBuffer);
879
                        }
880
                }
881

    
882
                /**
883
                 * @see com.iver.cit.gvsig.fmap.layers.LayerCollectionListener#layerAdding(com.iver.cit.gvsig.fmap.layers.LayerCollectionEvent)
884
                 */
885
                public void layerAdding(LayerCollectionEvent e)
886
                                throws CancelationException {
887
                }
888

    
889
                /**
890
                 * @see com.iver.cit.gvsig.fmap.layers.LayerCollectionListener#layerMoving(com.iver.cit.gvsig.fmap.layers.LayerPositionEvent)
891
                 */
892
                public void layerMoving(LayerPositionEvent e)
893
                                throws CancelationException {
894
                }
895

    
896
                /**
897
                 * @see com.iver.cit.gvsig.fmap.layers.LayerCollectionListener#layerRemoving(com.iver.cit.gvsig.fmap.layers.LayerCollectionEvent)
898
                 */
899
                public void layerRemoving(LayerCollectionEvent e)
900
                                throws CancelationException {
901
                }
902

    
903
                /**
904
                 * @see com.iver.cit.gvsig.fmap.layers.LayerCollectionListener#activationChanged(com.iver.cit.gvsig.fmap.layers.LayerCollectionEvent)
905
                 */
906
                public void activationChanged(LayerCollectionEvent e)
907
                                throws CancelationException {
908
                }
909

    
910
                /**
911
                 * @see com.iver.cit.gvsig.fmap.layers.LayerCollectionListener#visibilityChanged(com.iver.cit.gvsig.fmap.layers.LayerCollectionEvent)
912
                 */
913
                public void visibilityChanged(LayerCollectionEvent e)
914
                                throws CancelationException {
915
                }
916
        }
917

    
918
        public void addAsCollectionListener(FLayers layers2) {
919
                layers2.addLayerCollectionListener(layerEventListener);
920
        }
921

    
922
        public GraphicLayer getGraphicsLayer() {
923
                return tracLayer;
924
        }
925

    
926
        /**
927
         * Asigna la capa gr?fica
928
         * @param graphicLayer
929
         */
930
        public void setGraphicsLayer(GraphicLayer graphicLayer) {
931
                tracLayer = graphicLayer;
932
        }
933

    
934
        public boolean equals(Object arg0) {
935
                MapContext map = (MapContext) arg0;
936
                if (super.equals(arg0))
937
                        return true;
938
                if (getLayers() == map.getLayers())
939
                        return true;
940
                boolean isEqual = true;
941
                if (map.getLayers().getLayersCount() == getLayers().getLayersCount()) {
942
                        for (int i = 0; i < getLayers().getLayersCount(); i++) {
943

    
944
                                if (!getLayers().getLayer(i).getName().equals(
945
                                                map.getLayers().getLayer(i).getName())) {
946
                                        isEqual = false;
947
                                }
948

    
949
                        }
950
                } else {
951
                        isEqual = false;
952
                }
953
                return isEqual;
954
        }
955

    
956
        public void addLayerError(String stringProperty) {
957
                layersError.add(stringProperty);
958
        }
959

    
960
        public ArrayList getLayersError() {
961
                return layersError;
962
        }
963

    
964
        public void clearErrors() {
965
                layersError.clear();
966
        }
967
        
968
        public void clearAllCachingImageDrawnLayers() {
969
                clearCachingImageDrawnLayers(this.layers);
970
        }
971
        
972
        private void clearCachingImageDrawnLayers(FLayers layers){
973
                int i;
974
                FLayer layer;
975
                for (i=0;i< layers.getLayersCount();i++){
976
                        layer = layers.getLayer(i);
977
                        if (layer instanceof FLayers) {
978
                                clearCachingImageDrawnLayers((FLayers)layer);
979
                        } else {
980
                                layer.setCacheImageDrawnLayers(null);
981
                        }
982
                }                
983
        }
984
        
985
}