Statistics
| Revision:

root / trunk / libraries / libFMap / src / com / iver / cit / gvsig / fmap / MapContext.java @ 10977

History | View | Annotate | Download (28.7 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
import java.util.List;
51
import java.util.prefs.Preferences;
52

    
53
import javax.print.attribute.PrintRequestAttributeSet;
54

    
55
import org.cresques.cts.ICoordTrans;
56
import org.cresques.cts.IProjection;
57
import org.cresques.geo.Projected;
58

    
59
import com.hardcode.gdbms.driver.exceptions.ReadDriverException;
60
import com.hardcode.gdbms.engine.data.driver.DriverException;
61
import com.iver.cit.gvsig.exceptions.expansionfile.ExpansionFileReadException;
62
import com.iver.cit.gvsig.exceptions.visitors.VisitorException;
63
import com.iver.cit.gvsig.fmap.core.IGeometry;
64
import com.iver.cit.gvsig.fmap.core.symbols.ISymbol;
65
import com.iver.cit.gvsig.fmap.layers.CancelationException;
66
import com.iver.cit.gvsig.fmap.layers.FLayer;
67
import com.iver.cit.gvsig.fmap.layers.FLayers;
68
import com.iver.cit.gvsig.fmap.layers.GraphicLayer;
69
import com.iver.cit.gvsig.fmap.layers.LayerCollectionEvent;
70
import com.iver.cit.gvsig.fmap.layers.LayerCollectionListener;
71
import com.iver.cit.gvsig.fmap.layers.LayerDrawEvent;
72
import com.iver.cit.gvsig.fmap.layers.LayerDrawingListener;
73
import com.iver.cit.gvsig.fmap.layers.LayerPositionEvent;
74
import com.iver.cit.gvsig.fmap.layers.LegendListener;
75
import com.iver.cit.gvsig.fmap.layers.VectorialAdapter;
76
import com.iver.cit.gvsig.fmap.layers.XMLException;
77
import com.iver.cit.gvsig.fmap.layers.layerOperations.AlphanumericData;
78
import com.iver.cit.gvsig.fmap.layers.layerOperations.Classifiable;
79
import com.iver.cit.gvsig.fmap.layers.layerOperations.Selectable;
80
import com.iver.cit.gvsig.fmap.operations.selection.Record;
81
import com.iver.cit.gvsig.fmap.operations.strategies.FeatureVisitor;
82
import com.iver.cit.gvsig.fmap.operations.strategies.SelectedZoomVisitor;
83
import com.iver.utiles.XMLEntity;
84
import com.iver.utiles.swing.threads.Cancellable;
85

    
86
/**
87
 * Modelo del mapa.
88
 *
89
 * @author Fernando Gonz?lez Cort?s
90
 */
91
public class MapContext implements Projected {
92
        public static final double[] CHANGEM = { 1000, 1, 0.01, 0.001, 1609.344,
93
                        0.9144, 0.3048, 0.0254, 1/8.983152841195214E-6 };
94

    
95
        public static final double[] CHANGE = { 100000, 100, 1, 0.1, 160934.4,
96
                        91.44, 30.48, 2.54, 1/8.983152841195214E-4 };
97

    
98
        public static final int EQUALS = 0;
99

    
100
        public static final int DISJOINT = 1;
101

    
102
        public static final int INTERSECTS = 2;
103

    
104
        public static final int TOUCHES = 3;
105

    
106
        public static final int CROSSES = 4;
107

    
108
        public static final int WITHIN = 5;
109

    
110
        public static final int CONTAINS = 6;
111

    
112
        public static final int OVERLAPS = 7;
113

    
114
        protected FLayers layers;
115

    
116
        private GraphicLayer tracLayer = new GraphicLayer();
117

    
118
        private ViewPort viewPort;
119

    
120
        // private ArrayList invalidationListeners = new ArrayList();
121
        private ArrayList legendListeners = new ArrayList();
122

    
123
        private ArrayList layerDrawingListeners = new ArrayList();
124

    
125
        private EventBuffer eventBuffer = new EventBuffer();
126

    
127
        private LayerEventListener layerEventListener = null;
128

    
129
        private ArrayList layersError = new ArrayList();
130

    
131
        private ArrayList errorListeners = new ArrayList();
132

    
133
        // public static ResourceBundle myResourceBundle =
134
        // ResourceBundle.getBundle("FMap");
135
        public static double ZOOMINFACTOR=2;
136
        public static double ZOOMOUTFACTOR=0.5;
137
        /**
138
         * Crea un nuevo FMap.
139
         *
140
         * @param vp
141
         *            ViewPort.
142
         */
143
        public MapContext(ViewPort vp) {
144
                this.layers = new FLayers(this, null);
145

    
146
                layerEventListener = new LayerEventListener();
147
                layers.addLayerCollectionListener(layerEventListener);
148
                layers.addLayerCollectionListener(eventBuffer);
149

    
150
                setViewPort(vp);
151

    
152
        }
153

    
154
        public MapContext(FLayers fLayers, ViewPort vp) {
155
                this.layers = fLayers;
156

    
157
                layerEventListener = new LayerEventListener();
158
                layers.addLayerCollectionListener(layerEventListener);
159
                layers.addLayerCollectionListener(eventBuffer);
160

    
161
                setViewPort(vp);
162
        }
163

    
164
        /**
165
         * Reports to all registered driver listener a group of driverexceptions
166
         * produced in the same fmap atomic transaction
167
         * @param driverExceptions
168
         */
169
        public synchronized void reportDriverExceptions(String introductoryText,
170
                                                                                                        List driverExceptions){
171
                for (int i = 0; i < errorListeners.size(); i++) {
172
                        ((ErrorListener) errorListeners.get(i)).
173
                                reportDriverExceptions(introductoryText, driverExceptions);
174
                }
175
        }
176

    
177

    
178
        /**
179
         * A?ade un LegendListener.
180
         *
181
         * @param listener
182
         *            LegendListener a a?adir.
183
         */
184
        public void addLayerListener(LegendListener listener) {
185
                if (!legendListeners.contains(listener))
186
                        legendListeners.add(listener);
187
        }
188

    
189
        public void addLayerDrawingListener(LayerDrawingListener listener) {
190
                layerDrawingListeners.add(listener);
191
        }
192

    
193
        public void removeLayerDrawListener(LayerDrawingListener listener) {
194
                layerDrawingListeners.remove(listener);
195
        }
196

    
197
        public void addErrorListener(ErrorListener listener) {
198
                errorListeners.add(listener);
199
        }
200

    
201
        public void removeErrorListener(LegendListener listener) {
202
                legendListeners.remove(listener);
203
        }
204

    
205
        /**
206
         * M?todo ejecutado cuando hay un cambio de leyenda que se quiera reflejar.
207
         *
208
         * @param e
209
         *            LegendChangedEvent.
210
         */
211
        public synchronized void callLegendChanged() {
212
                for (int i = 0; i < legendListeners.size(); i++) {
213
                        ((LegendListener) legendListeners.get(i)).legendChanged(null);
214
                }
215
                // getLayers().moveTo(0,0);
216
        }
217

    
218
        public synchronized void fireLayerDrawingEvent(LayerDrawEvent e) {
219
                for (int i = 0; i < layerDrawingListeners.size(); i++)
220
                {
221
                        LayerDrawingListener listener = (LayerDrawingListener) layerDrawingListeners.get(i);
222
                        switch (e.getEventType())
223
                        {
224
                                case LayerDrawEvent.LAYER_BEFORE_DRAW:
225
                                        listener.beforeLayerDraw(e);
226
                                        break;
227
                                case LayerDrawEvent.LAYER_AFTER_DRAW:
228
                                        listener.afterLayerDraw(e);
229
                                        break;
230
                                case LayerDrawEvent.GRAPHICLAYER_BEFORE_DRAW:
231
                                        listener.beforeGraphicLayerDraw(e);
232
                                        break;
233
                                case LayerDrawEvent.GRAPHICLAYER_AFTER_DRAW:
234
                                        listener.afterLayerGraphicDraw(e);
235
                                        break;
236
                        }
237
                }
238
                // getLayers().moveTo(0,0);
239
        }
240

    
241
        public synchronized void callNewErrorEvent(ErrorEvent e) {
242
                for (int i = 0; i < errorListeners.size(); i++) {
243
                        ((ErrorListener) errorListeners.get(i)).errorThrown(e);
244
                }
245
                // getLayers().moveTo(0,0);
246
        }
247

    
248
        /**
249
         * Borra un LegendListener.
250
         *
251
         * @param listener
252
         *            LegendListener a borrar.
253
         */
254
        public void removeLayerListener(LegendListener listener) {
255
                legendListeners.remove(listener);
256
        }
257

    
258
        /**
259
         * Devuelve las capas que contiene el mapa.
260
         *
261
         * @return Capas.
262
         */
263
        public FLayers getLayers() {
264
                return layers;
265
        }
266

    
267
        /**
268
         * Dibuja en la imagen que se pasa como par?metro el contenido de las capas
269
         * visibles del mapa y teniendo en cuenta los datos del ViewPort contenido
270
         * en este FMap
271
         *
272
         * @param b
273
         *            Imagen.
274
         */
275
        public void drawLabels(BufferedImage b) {
276
        }
277

    
278
        /**
279
         * M?todo de conveniencia que se usa provisionalmente para solicitar un
280
         * refresco de todo lo que dependa del FMap (MapContext). Esto provocar? un
281
         * evento de cambio de orden de capas que obligar? a redibujar todo lo que
282
         * depende de FMap (TOC, MapControl, FFrameView, etc).
283
         */
284
        public void invalidate() {
285
                getLayers().moveTo(0, 0);
286
        }
287

    
288
        /**
289
         * Imprime el las capas que contiene el FMap sobre el Graphics2D que se pasa
290
         * como par?metro, normalmente es el Graphics de la impresora.
291
         *
292
         * @param g
293
         *            Graphics2D
294
         * @throws ReadDriverException TODO
295
         */
296
        public void print(Graphics2D g, double scale, PrintRequestAttributeSet properties) throws ReadDriverException {
297
                RenderingHints renderHints = new RenderingHints(
298
                                RenderingHints.KEY_ANTIALIASING,
299
                                RenderingHints.VALUE_ANTIALIAS_ON);
300
                renderHints.put(RenderingHints.KEY_RENDERING,
301
                                RenderingHints.VALUE_RENDER_QUALITY);
302
                g.setRenderingHints(renderHints);
303

    
304
                Cancellable cancel = new Cancellable() {
305
                        public boolean isCanceled() {
306
                                return false;
307
                        }
308

    
309
                        public void setCanceled(boolean canceled) {
310
                                // No queremos que se pueda cancelar la impresi?n.
311

    
312
                        }
313
                };
314
                layers.print(g, viewPort, cancel, scale, properties);
315
                tracLayer.draw(null, g, viewPort, cancel, scale);
316
        }
317

    
318
        /**
319
         * Crea un nuevo FMap con la informaci?n del ViewPort que se pasa como
320
         * par?metro.
321
         *
322
         * @param vp
323
         *            ViewPort.
324
         *
325
         * @return FMap nuevo.
326
         */
327
        public MapContext createNewFMap(ViewPort vp) {
328
                MapContext ret = new MapContext(vp);
329
                ret.layers = this.layers;
330

    
331
                return ret;
332
        }
333

    
334
        /**
335
         * Crea un nuevo FMap totalmente desligado, se replican las capas y el
336
         * ViewPort
337
         *
338
         * @return FMap clonado.
339
         *
340
         * @throws XMLException
341
         */
342
        public MapContext cloneFMap() throws XMLException {
343
                ViewPort vp = getViewPort().cloneViewPort();
344
                FLayers antLayers = getLayers();
345
                MapContext ret = new MapContext(vp);
346
                FLayers aux = new FLayers(ret, null);
347
                for (int i=0; i < antLayers.getLayersCount(); i++)
348
                {
349
                        FLayer lyr = antLayers.getLayer(i);
350
                        try {
351
                                aux.addLayer(lyr.cloneLayer());
352
                        } catch (Exception e) {
353
                                // TODO Auto-generated catch block
354
                                e.printStackTrace();
355
                        }
356
                }
357
                ret.layers = aux;
358
                return ret;
359

    
360
//                return createFromXML(getXMLEntity());
361

    
362
        }
363
        public MapContext cloneToDraw() {
364
                ViewPort vp = getViewPort().cloneViewPort();
365
                MapContext mapContext=new MapContext(getLayers(),vp);
366
                return mapContext;
367
        }
368

    
369
        /**
370
         * A?ade la capa que se pasa como par?metro al nodo que se pasa como
371
         * parametro y lanza ProjectionMismatchException si no est?n todas las capas
372
         * de este FMap en la misma proyecci?n. Lanza un ChildNotAllowedException si
373
         * la capa no es un FLayers y no permite hijos
374
         *
375
         * @param vectorial
376
         *            DOCUMENT ME!
377
         */
378

    
379
        /*
380
         * public void addLayer(LayerPath parent, FLayer layer) throws
381
         * ProjectionMismatchException, ChildrenNotAllowedException {
382
         * layers.addLayer(parent, layer); } public void removeLayer(LayerPath
383
         * parent)throws ChildrenNotAllowedException{ layers.removeLayer(parent); }
384
         */
385

    
386
        /**
387
         * A?ade una capa al grupo de capas que se sit?a por encima de todas las
388
         * otras capas
389
         *
390
         * @param vectorial
391
         *            FLayer.
392
         */
393
        public void addToTrackLayer(FLayer vectorial) {
394
        }
395

    
396
        /**
397
         * Devuelve la escala de la vista en pantalla.
398
         *
399
         * @return escala de la vista.
400
         */
401
        public long getScaleView() {
402
                Preferences prefsResolution = Preferences.userRoot().node( "gvsig.configuration.screen" );
403
                Toolkit kit = Toolkit.getDefaultToolkit();
404
                double dpi = prefsResolution.getInt("dpi",kit.getScreenResolution());
405
                IProjection proj = viewPort.getProjection();
406

    
407
                if (viewPort.getImageSize() == null)
408
                        return -1;
409

    
410
                if (viewPort.getAdjustedExtent() == null) {
411
                        return 0;
412
                }
413

    
414
                if (proj == null) {
415
                        double w = ((viewPort.getImageSize().getWidth() / dpi) * 2.54);
416
                        return (long) (viewPort.getAdjustedExtent().getWidth() / w * CHANGE[getViewPort()
417
                                        .getMapUnits()]);
418
                }
419

    
420
                return Math.round(proj.getScale(viewPort.getAdjustedExtent().getMinX(),
421
                                viewPort.getAdjustedExtent().getMaxX(), viewPort.getImageSize()
422
                                                .getWidth(), dpi));
423
        }
424
        /**
425
         * Introduce un nuevo extent en la vista a partir de la escala que se pasa como par?metro.
426
         *
427
         * @return escala de la vista.
428
         */
429
        public void setScaleView(long scale) {
430
                clearAllCachingImageDrawnLayers();
431
                Preferences prefsResolution = Preferences.userRoot().node( "gvsig.configuration.screen" );
432
                Toolkit kit = Toolkit.getDefaultToolkit();
433
                double dpi = prefsResolution.getInt("dpi",kit.getScreenResolution());
434
                if (viewPort.getImageSize() == null)
435
                        return;
436
                IProjection proj = viewPort.getProjection();
437
                if (viewPort.getAdjustedExtent() == null) {
438
                        return;
439
                }
440
                Rectangle2D rec=proj.getExtent(viewPort.getExtent(),scale,viewPort.getImageWidth(),viewPort.getImageHeight(),CHANGE[getViewPort().getMapUnits()],dpi);
441
                getViewPort().setExtent(rec);
442
        }
443
        /**
444
         * @see com.iver.cit.gvsig.fmap.operations.strategies.Strategy#setVectorial(com.iver.cit.gvsig.fmap.VectorialAdapter)
445
         */
446
        public void setVectorial(VectorialAdapter v) {
447
        }
448

    
449
        /**
450
         * @see com.iver.cit.gvsig.fmap.operations.strategies.Strategy#process(com.iver.cit.gvsig.fmap.FeatureSelectorVisitor)
451
         */
452
        public void process(FeatureVisitor visitor) {
453
        }
454

    
455
        /**
456
         * @see com.iver.cit.gvsig.fmap.operations.strategies.Strategy#processSelected(com.iver.cit.gvsig.fmap.FeatureVisitor)
457
         */
458
        public void processSelected(FeatureVisitor visitor) {
459
        }
460

    
461
        /**
462
         * @see com.iver.cit.gvsig.fmap.operations.strategies.Strategy#select(com.iver.cit.gvsig.fmap.FeatureSelectorVisitor,
463
         *      VectorialSubSet)
464
         */
465
        public void select(FeatureVisitor visitor) {
466
        }
467

    
468
        /**
469
         * @see com.iver.cit.gvsig.fmap.operations.strategies.Strategy#selectFromSelection()
470
         */
471
        public void selectFromSelection() {
472
        }
473

    
474
        /**
475
         * @see com.iver.cit.gvsig.fmap.operations.strategies.Strategy#createIndex()
476
         */
477
        public void createIndex() {
478
        }
479

    
480
        /**
481
         * @see org.cresques.geo.Projected#getProjection()
482
         */
483
        public IProjection getProjection() {
484
                return getViewPort().getProjection();
485
        }
486

    
487
        /**
488
         * Inserta la proyecci?n.
489
         *
490
         * @param proj
491
         *            Proyecci?n.
492
         */
493
        public void setProjection(IProjection proj) {
494
                if (getViewPort() != null) {
495
                        getViewPort().setProjection(proj);
496
                }
497
        }
498

    
499
        /**
500
         * @see org.cresques.geo.Projected#reProject(org.cresques.cts.ICoordTrans)
501
         */
502
        public void reProject(ICoordTrans arg0) {
503
                // TODO implementar reprojecci?n (lo que sea eso)
504
        }
505

    
506
        /**
507
         * @see com.iver.cit.gvsig.fmap.operations.strategies.Strategy#selectByPoint(java.awt.geom.Point2D,
508
         *      double)
509
         */
510
        /*
511
         * public void selectByPoint(Point2D p, double tolerance) throws
512
         * DriverException { Point2D mapPoint = viewPort.toMapPoint((int) p.getX(),
513
         * (int) p.getY()); SelectByPointVisitor visitor = new
514
         * SelectByPointVisitor(); visitor.setQueriedPoint(mapPoint);
515
         * visitor.setTolerance(getViewPort().toMapDistance(3));
516
         *
517
         * try { layers.process(visitor); } catch (VisitException e) { throw new
518
         * RuntimeException("No se espera que SelectByPointVisitor lance esta
519
         * excepci?n", e); } }
520
         */
521

    
522
        /**
523
         * @see com.iver.cit.gvsig.fmap.operations.strategies.Strategy#selectByRect(java.awt.geom.Rectangle2D)
524
         */
525
        /*
526
         * public void selectByRect(Rectangle2D rect) throws DriverException {
527
         * FLayer[] actives = layers.getActives(); for (int i=0; i < actives.length;
528
         * i++) { if (actives[i] instanceof FLyrVect) { FLyrVect lyrVect =
529
         * (FLyrVect) actives[i]; FBitSet oldBitSet = lyrVect.getSelection();
530
         * FBitSet newBitSet = lyrVect.queryByRect(rect); newBitSet.xor(oldBitSet);
531
         * lyrVect.setSelection(newBitSet); } }
532
         *  }
533
         */
534

    
535
        /**
536
         * @see com.iver.cit.gvsig.fmap.operations.strategies.Strategy#selectByShape(com.iver.cit.gvsig.fmap.fshape.IGeometry,
537
         *      int)
538
         */
539
        public void selectByShape(IGeometry g, int relationship) {
540
        }
541

    
542
        /**
543
         * @see com.iver.cit.gvsig.fmap.operations.strategies.Strategy#queryByPoint(Point2D,
544
         *      double)
545
         */
546
        public Record[] queryByPoint(Point2D p, double tolerance) {
547
                return null;
548
        }
549

    
550
        /**
551
         * @see com.iver.cit.gvsig.fmap.operations.strategies.Strategy#queryByRect(java.awt.geom.Rectangle2D)
552
         */
553
        public Record[] queryByRect(Rectangle2D rect) {
554
                return null;
555
        }
556

    
557
        /**
558
         * @see com.iver.cit.gvsig.fmap.operations.strategies.Strategy#queryByShape(com.iver.cit.gvsig.fmap.fshape.IGeometry,
559
         *      int)
560
         */
561
        public Record[] queryByShape(IGeometry g, int relationship) {
562
                return null;
563
        }
564

    
565
        /**
566
         * @see com.iver.cit.gvsig.fmap.operations.strategies.Strategy#getSelectionBounds()
567
         */
568
        public Rectangle2D getSelectionBounds() {
569
                SelectedZoomVisitor visitor = new SelectedZoomVisitor();
570

    
571
                try {
572
                        layers.process(visitor);
573
                } catch (ReadDriverException e1) {
574
                        throw new RuntimeException(
575
                                        "No se espera que SelectByPointVisitor lance esta excepci?n",
576
                                        e1);
577
                } catch (VisitorException e) {
578
                        throw new RuntimeException(
579
                                        "No se espera que SelectByPointVisitor lance esta excepci?n",
580
                                        e);
581
                }
582

    
583
                return visitor.getSelectBound();
584
        }
585

    
586
        /**
587
         * @see com.iver.cit.gvsig.fmap.operations.LayerOperations#draw(java.awt.image.BufferedImage,
588
         *      ISymbol)
589
         */
590
        public void draw(BufferedImage image, Graphics2D g, Cancellable cancel,
591
                        double scale) throws ReadDriverException {
592
                if (viewPort.getExtent() == null) {
593
                        // System.err.println("viewPort.getExtent() = null");
594
                        return;
595
                }
596
                System.out.println("Viewport despues: " + viewPort.toString());
597
                /*
598
                 * if ((viewPort.getImageWidth() <=0) || (viewPort.getImageHeight() <=
599
                 * 0)) { return; }
600
                 */
601

    
602
                prepareDrawing(image, g, scale);
603

    
604
                // M?s c?lidad al texto
605
                RenderingHints renderHints = new RenderingHints(
606
                                RenderingHints.KEY_ANTIALIASING,
607
                                RenderingHints.VALUE_ANTIALIAS_ON);
608
                renderHints.put(RenderingHints.KEY_RENDERING,
609
                                RenderingHints.VALUE_RENDER_QUALITY);
610
                renderHints.put(RenderingHints.KEY_TEXT_ANTIALIASING,
611
                                RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
612
                g.setRenderingHints(renderHints);
613

    
614
                long t1 = System.currentTimeMillis();
615
                layers.draw(image, g, viewPort, cancel, scale);
616

    
617
                LayerDrawEvent beforeTracLayerEvent = new LayerDrawEvent(tracLayer,
618
                                g, viewPort, LayerDrawEvent.GRAPHICLAYER_BEFORE_DRAW);
619
                fireLayerDrawingEvent(beforeTracLayerEvent);
620
                tracLayer.draw(image, g, viewPort, cancel, scale);
621
                LayerDrawEvent afterTracLayerEvent = new LayerDrawEvent(tracLayer,
622
                                g, viewPort, LayerDrawEvent.GRAPHICLAYER_AFTER_DRAW);
623
                fireLayerDrawingEvent(afterTracLayerEvent);
624

    
625
                //layers.setDirty(false);
626
                long t2 = System.currentTimeMillis();
627
                System.err.println("Tiempo de dibujado:" + (t2 - t1) +
628
                                " mseg. Memoria libre:" + Runtime.getRuntime().freeMemory() / 1024  + " KB");
629
                /*
630
                 * g.setColor(Color.BLUE); GeneralPath shpR = new
631
                 * GeneralPath(viewPort.getExtent());
632
                 * shpR.transform(viewPort.getAffineTransform()); g.draw(shpR);
633
                 */
634
                System.gc();
635
        }
636

    
637
        /**
638
         * En esta funci?n vamos a revisar las capas que necesitan repintarse,
639
         * por si hay alguna que se haya guardado la imagen de las anteriores
640
         * y puede acelerar el dibujado.
641
         * @param image
642
         * @param g
643
         * @param scale
644
         */
645
        private void prepareDrawing(BufferedImage image, Graphics2D g, double scale) {
646

    
647
                // Primera pasada: si alguna capa necesita repintarse por debajo
648
                // de la que tiene la cache, TODAS necesitan
649
                // ser repintadas.
650
                boolean bNeedRepaint = false;
651
                boolean bMayExistAceleration = false;
652
                for (int i = 0; i < layers.getLayersCount(); i++)
653
                {
654
                        FLayer lyr = layers.getLayer(i);
655
                        if (lyr.isCachingDrawnLayers() && (lyr.getCacheImageDrawnLayers() != null))
656
                        {
657
                                bMayExistAceleration = true;
658
                        }
659
                        else
660
                        {
661
                                if (lyr.isDirty())
662
                                        bNeedRepaint = true;
663
                        }
664
                }
665
                if (bMayExistAceleration==false)
666
                        bNeedRepaint = true;
667
                if (bNeedRepaint)
668
                        layers.setDirty(true);
669
                else
670
                        recursivePrepareDrawing(layers, 0);
671
        }
672

    
673
        private void validatePreviousLayers(FLayers layers, int index)
674
        {
675
                // TODO: Aqu? quiz?s habr?a que explorar los padres de las capas
676
                // para marcar y/o asignar la imagen cacheada.
677
                for (int i = 0; i < index; i++)
678
                {
679
                        FLayer lyr = layers.getLayer(i);
680
                        lyr.setDirty(false);
681
                }
682
                // Las de arriba las marcamos como sucias
683
//                for (int i = index; i < layers.getLayersCount(); i++)
684
//                {
685
//                        FLayer lyr = layers.getLayer(i);
686
//                        lyr.setDirty(true);
687
//                }
688
        }
689

    
690
        private void recursivePrepareDrawing(FLayers parent, int indexInParent)
691
        {
692
                for (int i = indexInParent; i < parent.getLayersCount(); i++)
693
                {
694
                        FLayer lyr = layers.getLayer(i);
695
                        if (lyr.isCachingDrawnLayers() && (lyr.getCacheImageDrawnLayers() != null))
696
                        {
697
                                // les decimos a las anteriores que est?n validadas (not dirty)
698
                                // para que no se dibujen.
699
                                if (lyr.isDirty())
700
                                        validatePreviousLayers(parent, i);
701
                        }
702

    
703
                        if (lyr instanceof FLayers)
704
                        {
705
                                recursivePrepareDrawing((FLayers)lyr, 0);
706
                        }
707
                }
708

    
709
        }
710

    
711
        public void drawGraphics(BufferedImage image, Graphics2D g,
712
                        Cancellable cancel, double scale) throws ReadDriverException {
713
                if (viewPort == null)
714
                        return;
715
                tracLayer.draw(image, g, viewPort, cancel, scale);
716
        }
717

    
718
        /**
719
         * @see com.iver.cit.gvsig.fmap.operations.LayerOperations#draw(java.awt.image.BufferedImage,
720
         *      ISymbol)
721
         */
722
        public void draw(BufferedImage image, Graphics2D g, double scale)
723
                        throws ReadDriverException {
724
                layers.setDirty(true);
725
                draw(image, g, new Cancellable() {
726
                        /**
727
                         * @see com.iver.utiles.swing.threads.Cancellable#isCanceled()
728
                         */
729
                        public boolean isCanceled() {
730
                                return false;
731
                        }
732

    
733
                        public void setCanceled(boolean canceled) {
734
                                // TODO Auto-generated method stub
735

    
736
                        }
737
                }, scale);
738
        }
739

    
740
        /**
741
         * Devuelve el ViewPort.
742
         *
743
         * @return Returns the viewPort.
744
         */
745
        public ViewPort getViewPort() {
746
                return viewPort;
747
        }
748

    
749
        /**
750
         * Inserta un ViewPort.
751
         *
752
         * @param viewPort
753
         *            The viewPort to set.
754
         */
755
        public void setViewPort(ViewPort viewPort) {
756
                if (this.viewPort != null) {
757
                        this.viewPort.removeViewPortListener(eventBuffer);
758
                }
759

    
760
                this.viewPort = viewPort;
761
                if (viewPort != null)
762
                        viewPort.addViewPortListener(eventBuffer);
763
        }
764

    
765
        /**
766
         * Sets the given zoom extent to the viewport.
767
         *
768
         * @param extent
769
         *            The extent to zoom to.
770
         */
771
        public void zoomToExtent(Rectangle2D extent) {
772
            getViewPort().setExtent(extent);
773
        }
774

    
775
        /**
776
         * M?todo de conveniencia. Recorre las capas y te da el fullExtent
777
         *
778
         * @return fullExtent de todas las capas.
779
         *
780
         * @throws DriverException
781
         */
782
        public Rectangle2D getFullExtent() throws ReadDriverException {
783
                return layers.getFullExtent();
784
        }
785

    
786
        /**
787
         * Devuelve el XMLEntity.
788
         *
789
         * @return XMLEntity.
790
         * @throws XMLException
791
         */
792
        public XMLEntity getXMLEntity() throws XMLException {
793
                XMLEntity xml = new XMLEntity();
794
                xml.putProperty("className", this.getClass().getName());
795
                xml.addChild(viewPort.getXMLEntity());
796
                xml.addChild(layers.getXMLEntity());
797

    
798
                return xml;
799
        }
800

    
801
        /**
802
         * Crea un nuevo FMAp a partir del XMLEntity.
803
         *
804
         * @param xml
805
         *            XMLEntity
806
         *
807
         * @return Nuevo FMap.
808
         *
809
         * @throws XMLException
810
         */
811
        public static MapContext createFromXML03(XMLEntity xml) throws XMLException {
812
                ViewPort vp = ViewPort.createFromXML03(xml.getChild(0));
813
                MapContext fmap = new MapContext(vp);
814
                fmap.layers.setXMLEntity03(xml.getChild(1));
815

    
816
                return fmap;
817
        }
818

    
819
        /**
820
         * Crea un nuevo FMAp a partir del XMLEntity.
821
         *
822
         * @param xml
823
         *            XMLEntity
824
         *
825
         * @return Nuevo FMap.
826
         *
827
         * @throws XMLException
828
         */
829
        public static MapContext createFromXML(XMLEntity xml) throws XMLException {
830
                ViewPort vp = ViewPort.createFromXML(xml.getChild(0));
831
                MapContext fmap = new MapContext(vp);
832
                fmap.layers.setXMLEntity(xml.getChild(1));
833
                fmap.layers.setName("root layer");
834
                return fmap;
835
        }
836

    
837
        /**
838
         * A?ade un AtomicEventListener.
839
         *
840
         * @param listener
841
         *            AtomicEventListener.
842
         *
843
         * @return True si se ha a?adido correctamente.
844
         */
845
        public boolean addAtomicEventListener(AtomicEventListener listener) {
846
                return eventBuffer.addAtomicEventListener(listener);
847
        }
848

    
849
        /**
850
         * Borra un AtomicEventListener de la lista de listeners.
851
         *
852
         * @param listener
853
         *            AtomicEventListener a borrar.
854
         *
855
         * @return True si se ha borrado correctamente.
856
         */
857
        public boolean removeAtomicEventListener(AtomicEventListener listener) {
858
                return eventBuffer.removeAtomicEventListener(listener);
859
        }
860

    
861
        /**
862
         * Inicializa los AtomicEvent.
863
         */
864
        public void beginAtomicEvent() {
865
                eventBuffer.beginAtomicEvent();
866
        }
867

    
868
        /**
869
         * Finaliza los AtomicEvent.
870
         */
871
        public void endAtomicEvent() {
872
                eventBuffer.endAtomicEvent();
873
        }
874

    
875
        /**
876
         * Evento Layer.
877
         *
878
         * @author Fernando Gonz?lez Cort?s
879
         */
880
        public class LayerEventListener implements LayerCollectionListener {
881
                /**
882
                 * @see com.iver.cit.gvsig.fmap.layers.LayerCollectionListener#layerAdded(com.iver.cit.gvsig.fmap.layers.LayerCollectionEvent)
883
                 */
884
                public void layerAdded(LayerCollectionEvent e) {
885
                        // Si es la primera capa, fijamos su extent al ViewPort
886
                        // if (getLayers().getLayersCount() == 1) {
887
                        if (getViewPort().getExtent() == null) {
888
                                FLayer lyr = e.getAffectedLayer();
889
                                if (lyr.isAvailable())
890
                                        try {
891
                                                getViewPort().setExtent(lyr.getFullExtent());
892
                                        } catch (ReadDriverException e1) {
893
                                                e1.printStackTrace();
894
                                        } catch (ExpansionFileReadException e1) {
895
                                                e1.printStackTrace();
896
                                        }
897
                        }
898

    
899
                        // Registramos al FMap como listener del legend de las capas
900
                        FLayer lyr = e.getAffectedLayer();
901
                        selectionListener(lyr);
902
                }
903
                private void selectionListener(FLayer lyr){
904
                        lyr.addLayerListener(eventBuffer);
905

    
906
                        if (lyr instanceof Classifiable) {
907
                                Classifiable c = (Classifiable) lyr;
908
                                c.addLegendListener(eventBuffer);
909
                        }
910

    
911
                        if (lyr instanceof AlphanumericData) {
912
                                Selectable s=null;
913
                                try {
914
                                        s = ((AlphanumericData) lyr).getRecordset();
915
                                        if (s!=null) {
916
                                                s.addSelectionListener(eventBuffer);
917
                                        }
918
                                } catch (ReadDriverException e1) {
919
                                        e1.printStackTrace();
920
                                }
921

    
922
                        }
923
                        if (lyr instanceof FLayers){
924
                                FLayers lyrs=(FLayers)lyr;
925
                                for(int i=0;i<lyrs.getLayersCount();i++){
926
                                        selectionListener(lyrs.getLayer(i));
927
                                }
928
                        }
929

    
930
                }
931
                /**
932
                 * @see com.iver.cit.gvsig.fmap.layers.LayerCollectionListener#layerMoved(com.iver.cit.gvsig.fmap.layers.LayerPositionEvent)
933
                 */
934
                public void layerMoved(LayerPositionEvent e) {
935
                }
936

    
937
                /**
938
                 * @see com.iver.cit.gvsig.fmap.layers.LayerCollectionListener#layerRemoved(com.iver.cit.gvsig.fmap.layers.LayerCollectionEvent)
939
                 */
940
                public void layerRemoved(LayerCollectionEvent e) {
941
                        FLayer lyr = e.getAffectedLayer();
942

    
943
                        lyr.removeLayerListener(eventBuffer);
944

    
945
                        if (lyr instanceof Classifiable) {
946
                                Classifiable c = (Classifiable) lyr;
947
                                c.removeLegendListener(eventBuffer);
948
                        }
949

    
950
                        if (lyr instanceof Selectable) {
951
                                Selectable s = (Selectable) lyr;
952
                                s.addSelectionListener(eventBuffer);
953
                        }
954
                }
955

    
956
                /**
957
                 * @see com.iver.cit.gvsig.fmap.layers.LayerCollectionListener#layerAdding(com.iver.cit.gvsig.fmap.layers.LayerCollectionEvent)
958
                 */
959
                public void layerAdding(LayerCollectionEvent e)
960
                                throws CancelationException {
961
                }
962

    
963
                /**
964
                 * @see com.iver.cit.gvsig.fmap.layers.LayerCollectionListener#layerMoving(com.iver.cit.gvsig.fmap.layers.LayerPositionEvent)
965
                 */
966
                public void layerMoving(LayerPositionEvent e)
967
                                throws CancelationException {
968
                }
969

    
970
                /**
971
                 * @see com.iver.cit.gvsig.fmap.layers.LayerCollectionListener#layerRemoving(com.iver.cit.gvsig.fmap.layers.LayerCollectionEvent)
972
                 */
973
                public void layerRemoving(LayerCollectionEvent e)
974
                                throws CancelationException {
975
                }
976

    
977

    
978
                /**
979
                 * @see com.iver.cit.gvsig.fmap.layers.LayerCollectionListener#visibilityChanged(com.iver.cit.gvsig.fmap.layers.LayerCollectionEvent)
980
                 */
981
                public void visibilityChanged(LayerCollectionEvent e)
982
                                throws CancelationException {
983
                }
984
        }
985

    
986
        public void addAsCollectionListener(FLayers layers2) {
987
                layers2.addLayerCollectionListener(layerEventListener);
988
        }
989

    
990
        public GraphicLayer getGraphicsLayer() {
991
                return tracLayer;
992
        }
993

    
994
        /**
995
         * Asigna la capa gr?fica
996
         * @param graphicLayer
997
         */
998
        public void setGraphicsLayer(GraphicLayer graphicLayer) {
999
                tracLayer = graphicLayer;
1000
        }
1001

    
1002
        public boolean equals(Object arg0) {
1003
                MapContext map = (MapContext) arg0;
1004
                if (super.equals(arg0))
1005
                        return true;
1006
                if (getLayers() == map.getLayers())
1007
                        return true;
1008
                boolean isEqual = true;
1009
                if (map.getLayers().getLayersCount() == getLayers().getLayersCount()) {
1010
                        for (int i = 0; i < getLayers().getLayersCount(); i++) {
1011

    
1012
                                if (!getLayers().getLayer(i).getName().equals(
1013
                                                map.getLayers().getLayer(i).getName())) {
1014
                                        isEqual = false;
1015
                                }
1016

    
1017
                        }
1018
                } else {
1019
                        isEqual = false;
1020
                }
1021
                return isEqual;
1022
        }
1023

    
1024
        public void addLayerError(String stringProperty) {
1025
                layersError.add(stringProperty);
1026
        }
1027

    
1028
        public ArrayList getLayersError() {
1029
                return layersError;
1030
        }
1031

    
1032
        public void clearErrors() {
1033
                layersError.clear();
1034
        }
1035

    
1036
        public void clearAllCachingImageDrawnLayers() {
1037
                clearCachingImageDrawnLayers(this.layers);
1038
}
1039
        private void clearCachingImageDrawnLayers(FLayers layers){
1040
                int i;
1041
                FLayer layer;
1042
                for (i=0;i< layers.getLayersCount();i++){
1043
                        layer = layers.getLayer(i);
1044
                        if (layer instanceof FLayers) {
1045
                                clearCachingImageDrawnLayers((FLayers)layer);
1046
                        } else {
1047
                                layer.setCacheImageDrawnLayers(null);
1048
                        }
1049
                }
1050
        }
1051

    
1052
        public void redraw() {
1053
                // truco
1054
                if (getLayers().getLayersCount() > 0)
1055
                        getLayers().moveTo(0,0);
1056

    
1057
        }
1058

    
1059
}