Statistics
| Revision:

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

History | View | Annotate | Download (28.6 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.engine.instruction.FieldNotFoundException;
60
import com.iver.cit.gvsig.fmap.core.IGeometry;
61
import com.iver.cit.gvsig.fmap.core.ISymbol;
62
import com.iver.cit.gvsig.fmap.layers.CancelationException;
63
import com.iver.cit.gvsig.fmap.layers.FLayer;
64
import com.iver.cit.gvsig.fmap.layers.FLayers;
65
import com.iver.cit.gvsig.fmap.layers.FLyrVect;
66
import com.iver.cit.gvsig.fmap.layers.GraphicLayer;
67
import com.iver.cit.gvsig.fmap.layers.LayerCollectionEvent;
68
import com.iver.cit.gvsig.fmap.layers.LayerCollectionListener;
69
import com.iver.cit.gvsig.fmap.layers.LayerDrawEvent;
70
import com.iver.cit.gvsig.fmap.layers.LayerDrawingListener;
71
import com.iver.cit.gvsig.fmap.layers.LayerPositionEvent;
72
import com.iver.cit.gvsig.fmap.layers.LegendListener;
73
import com.iver.cit.gvsig.fmap.layers.VectorialAdapter;
74
import com.iver.cit.gvsig.fmap.layers.XMLException;
75
import com.iver.cit.gvsig.fmap.layers.layerOperations.AlphanumericData;
76
import com.iver.cit.gvsig.fmap.layers.layerOperations.Classifiable;
77
import com.iver.cit.gvsig.fmap.layers.layerOperations.Selectable;
78
import com.iver.cit.gvsig.fmap.operations.selection.Record;
79
import com.iver.cit.gvsig.fmap.operations.strategies.FeatureVisitor;
80
import com.iver.cit.gvsig.fmap.operations.strategies.SelectedZoomVisitor;
81
import com.iver.cit.gvsig.fmap.operations.strategies.VisitException;
82
import com.iver.cit.gvsig.fmap.rendering.VectorialLegend;
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 };
94

    
95
        public static final double[] CHANGE = { 100000, 100, 1, 0.1, 160934.4,
96
                        91.44, 30.48, 2.54 };
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
         *
295
         * @throws DriverException
296
         */
297
        public void print(Graphics2D g, double scale, PrintRequestAttributeSet properties) throws DriverException {
298
                RenderingHints renderHints = new RenderingHints(
299
                                RenderingHints.KEY_ANTIALIASING,
300
                                RenderingHints.VALUE_ANTIALIAS_ON);
301
                renderHints.put(RenderingHints.KEY_RENDERING,
302
                                RenderingHints.VALUE_RENDER_QUALITY);
303
                g.setRenderingHints(renderHints);
304

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

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

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

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

    
332
                return ret;
333
        }
334

    
335
        /**
336
         * Crea un nuevo FMap totalmente desligado, se replican las capas y el
337
         * ViewPort
338
         * Se crean unas nuevas capas, pero clonadas para usar
339
         * como fuentes de datos los drivers ya existentes. As? 
340
         * evitamos consumir m?s memoria, a la vez que ganamos 
341
         * rapidez.
342
         *
343
         * @return FMap clonado.
344
         *
345
         * @throws XMLException
346
         */
347
        public MapContext cloneFMap() throws XMLException {
348
                ViewPort vp = getViewPort().cloneViewPort();
349
                FLayers antLayers = getLayers();
350
                MapContext ret = new MapContext(vp);
351
                FLayers aux = new FLayers(ret, null);
352
                for (int i=0; i < antLayers.getLayersCount(); i++)
353
                {
354
                        FLayer lyr = antLayers.getLayer(i);
355
                        try {
356
                                aux.addLayer(lyr.cloneLayer());
357
                        } catch (Exception e) {
358
                                // TODO Auto-generated catch block
359
                                e.printStackTrace();
360
                        }                        
361
                }
362
                ret.layers = aux;
363
                return ret;
364

    
365
//                return createFromXML(getXMLEntity());
366
        }
367
        public MapContext cloneToDraw() {
368
                ViewPort vp = getViewPort().cloneViewPort();
369
                MapContext mapContext=new MapContext(getLayers(),vp);
370
                return mapContext;
371
        }
372

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

    
383
        /*
384
         * public void addLayer(LayerPath parent, FLayer layer) throws
385
         * ProjectionMismatchException, ChildrenNotAllowedException {
386
         * layers.addLayer(parent, layer); } public void removeLayer(LayerPath
387
         * parent)throws ChildrenNotAllowedException{ layers.removeLayer(parent); }
388
         */
389

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

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

    
411
                if (viewPort.getImageSize() == null)
412
                        return -1;
413

    
414
                if (viewPort.getAdjustedExtent() == null) {
415
                        return 0;
416
                }
417

    
418
                if (proj == null) {
419
                        double w = ((viewPort.getImageSize().getWidth() / dpi) * 2.54);
420
                        return (long) (viewPort.getAdjustedExtent().getWidth() / w * CHANGE[getViewPort()
421
                                        .getMapUnits()]);
422
                }
423

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
574
                try {
575
                        layers.process(visitor);
576
                } catch (DriverException e1) {
577
                        throw new RuntimeException(
578
                                        "No se espera que SelectByPointVisitor lance esta excepci?n",
579
                                        e1);
580
                } catch (VisitException e) {
581
                        throw new RuntimeException(
582
                                        "No se espera que SelectByPointVisitor lance esta excepci?n",
583
                                        e);
584
                }
585

    
586
                return visitor.getSelectBound();
587
        }
588

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

    
605
                prepareDrawing(image, g, scale);
606

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

    
617
                long t1 = System.currentTimeMillis();
618
                layers.draw(image, g, viewPort, cancel, scale);
619

    
620
                LayerDrawEvent beforeTracLayerEvent = new LayerDrawEvent(tracLayer,
621
                                g, viewPort, LayerDrawEvent.GRAPHICLAYER_BEFORE_DRAW);
622
                fireLayerDrawingEvent(beforeTracLayerEvent);
623
                tracLayer.draw(image, g, viewPort, cancel, scale);
624
                LayerDrawEvent afterTracLayerEvent = new LayerDrawEvent(tracLayer,
625
                                g, viewPort, LayerDrawEvent.GRAPHICLAYER_AFTER_DRAW);
626
                fireLayerDrawingEvent(afterTracLayerEvent);
627
                
628
                layers.setDirty(false);
629

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

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

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

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

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

    
707
                        if (lyr instanceof FLayers)
708
                        {
709
                                recursivePrepareDrawing((FLayers)lyr, 0);
710
                        }
711
                }
712

    
713
        }
714

    
715
        public void drawGraphics(BufferedImage image, Graphics2D g,
716
                        Cancellable cancel, double scale) throws DriverException {
717
                if (viewPort == null)
718
                        return;
719
                tracLayer.draw(image, g, viewPort, cancel, scale);
720
        }
721

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

    
737
                        public void setCanceled(boolean canceled) {
738
                                // TODO Auto-generated method stub
739

    
740
                        }
741
                }, scale);
742
        }
743

    
744
        /**
745
         * Devuelve el ViewPort.
746
         *
747
         * @return Returns the viewPort.
748
         */
749
        public ViewPort getViewPort() {
750
                return viewPort;
751
        }
752

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

    
764
                this.viewPort = viewPort;
765
                if (viewPort != null)
766
                        viewPort.addViewPortListener(eventBuffer);
767
        }
768

    
769
        /**
770
         * Sets the given zoom extent to the viewport.
771
         *
772
         * @param extent
773
         *            The extent to zoom to.
774
         */
775
        public void zoomToExtent(Rectangle2D extent) {
776
            getViewPort().setExtent(extent);
777
        }
778

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

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

    
802
                return xml;
803
        }
804

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

    
820
                return fmap;
821
        }
822

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

    
838
                return fmap;
839
        }
840

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

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

    
865
        /**
866
         * Inicializa los AtomicEvent.
867
         */
868
        public void beginAtomicEvent() {
869
                eventBuffer.beginAtomicEvent();
870
        }
871

    
872
        /**
873
         * Finaliza los AtomicEvent.
874
         */
875
        public void endAtomicEvent() {
876
                eventBuffer.endAtomicEvent();
877
        }
878

    
879
        /**
880
         * Evento Layer.
881
         *
882
         * @author Fernando Gonz?lez Cort?s
883
         */
884
        public class LayerEventListener implements LayerCollectionListener {
885
                /**
886
                 * @see com.iver.cit.gvsig.fmap.layers.LayerCollectionListener#layerAdded(com.iver.cit.gvsig.fmap.layers.LayerCollectionEvent)
887
                 */
888
                public void layerAdded(LayerCollectionEvent e) {
889
                        // Si es la primera capa, fijamos su extent al ViewPort
890
                        // if (getLayers().getLayersCount() == 1) {
891
                        if (getViewPort().getExtent() == null) {
892
                                FLayer lyr = e.getAffectedLayer();
893

    
894
                                try {
895
                                        getViewPort().setExtent(lyr.getFullExtent());
896
                                } catch (DriverException e1) {
897
                                }
898
                        }
899

    
900
                        // Registramos al FMap como listener del legend de las capas
901
                        FLayer lyr = e.getAffectedLayer();
902
                        selectionListener(lyr);
903
                }
904

    
905
                private void selectionListener(FLayer lyr){
906
                        lyr.addLayerListener(eventBuffer);
907

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

    
913
                        if (lyr instanceof AlphanumericData) {
914
                                Selectable s=null;
915
                                try {
916
                                        s = ((AlphanumericData) lyr).getRecordset();
917
                                        if (s!=null) {
918
                                                s.addSelectionListener(eventBuffer);
919
                                        }
920
                                } catch (DriverException e1) {
921
                                        // TODO Auto-generated catch block
922
                                        e1.printStackTrace();
923
                                }
924

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

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

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

    
946
                        lyr.removeLayerListener(eventBuffer);
947

    
948
                        if (lyr instanceof Classifiable) {
949
                                Classifiable c = (Classifiable) lyr;
950
                                c.removeLegendListener(eventBuffer);
951
                        }
952

    
953
                        if (lyr instanceof Selectable) {
954
                                Selectable s = (Selectable) lyr;
955
                                s.addSelectionListener(eventBuffer);
956
                        }
957
                }
958

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

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

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

    
980

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

    
989
        public void addAsCollectionListener(FLayers layers2) {
990
                layers2.addLayerCollectionListener(layerEventListener);
991
        }
992

    
993
        public GraphicLayer getGraphicsLayer() {
994
                return tracLayer;
995
        }
996

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

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

    
1015
                                if (!getLayers().getLayer(i).getName().equals(
1016
                                                map.getLayers().getLayer(i).getName())) {
1017
                                        isEqual = false;
1018
                                }
1019

    
1020
                        }
1021
                } else {
1022
                        isEqual = false;
1023
                }
1024
                return isEqual;
1025
        }
1026

    
1027
        public void addLayerError(String stringProperty) {
1028
                layersError.add(stringProperty);
1029
        }
1030

    
1031
        public ArrayList getLayersError() {
1032
                return layersError;
1033
        }
1034

    
1035
        public void clearErrors() {
1036
                layersError.clear();
1037
        }
1038

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

    
1055
        public void redraw() {
1056
                // truco
1057
                if (getLayers().getLayersCount() > 0)
1058
                        getLayers().moveTo(0,0);
1059

    
1060
        }
1061

    
1062
}