Statistics
| Revision:

svn-gvsig-desktop / branches / simbologia / libraries / libFMap / src / com / iver / cit / gvsig / fmap / MapContext.java @ 10450

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.iver.cit.gvsig.fmap.core.IGeometry;
60
import com.iver.cit.gvsig.fmap.core.symbols.ISymbol;
61
import com.iver.cit.gvsig.fmap.core.v02.FConstant;
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.GraphicLayer;
66
import com.iver.cit.gvsig.fmap.layers.LayerCollectionEvent;
67
import com.iver.cit.gvsig.fmap.layers.LayerCollectionListener;
68
import com.iver.cit.gvsig.fmap.layers.LayerDrawEvent;
69
import com.iver.cit.gvsig.fmap.layers.LayerDrawingListener;
70
import com.iver.cit.gvsig.fmap.layers.LayerPositionEvent;
71
import com.iver.cit.gvsig.fmap.layers.LegendListener;
72
import com.iver.cit.gvsig.fmap.layers.VectorialAdapter;
73
import com.iver.cit.gvsig.fmap.layers.XMLException;
74
import com.iver.cit.gvsig.fmap.layers.layerOperations.AlphanumericData;
75
import com.iver.cit.gvsig.fmap.layers.layerOperations.Classifiable;
76
import com.iver.cit.gvsig.fmap.layers.layerOperations.Selectable;
77
import com.iver.cit.gvsig.fmap.operations.selection.Record;
78
import com.iver.cit.gvsig.fmap.operations.strategies.FeatureVisitor;
79
import com.iver.cit.gvsig.fmap.operations.strategies.SelectedZoomVisitor;
80
import com.iver.cit.gvsig.fmap.operations.strategies.VisitException;
81
import com.iver.cit.gvsig.fmap.rendering.styling.FStyle2D;
82
import com.iver.utiles.XMLEntity;
83
import com.iver.utiles.swing.threads.Cancellable;
84

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

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

    
96
        public static final int EQUALS = 0;
97

    
98
        public static final int DISJOINT = 1;
99

    
100
        public static final int INTERSECTS = 2;
101

    
102
        public static final int TOUCHES = 3;
103

    
104
        public static final int CROSSES = 4;
105

    
106
        public static final int WITHIN = 5;
107

    
108
        public static final int CONTAINS = 6;
109

    
110
        public static final int OVERLAPS = 7;
111

    
112
        protected FLayers layers;
113

    
114
        private GraphicLayer tracLayer = new GraphicLayer();
115

    
116
        private ViewPort viewPort;
117

    
118
        // private ArrayList invalidationListeners = new ArrayList();
119
        private ArrayList legendListeners = new ArrayList();
120

    
121
        private ArrayList layerDrawingListeners = new ArrayList();
122

    
123
        private EventBuffer eventBuffer = new EventBuffer();
124

    
125
        private LayerEventListener layerEventListener = null;
126

    
127
        /**
128
         * @uml.property  name="layersError"
129
         */
130
        private ArrayList layersError = new ArrayList();
131

    
132
        private ArrayList errorListeners = new ArrayList();
133

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

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

    
151
                setViewPort(vp);
152

    
153
        }
154

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

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

    
162
                setViewPort(vp);
163
        }
164

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

    
178

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
333
                return ret;
334
        }
335

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

    
362
//                return createFromXML(getXMLEntity());
363

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

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

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

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

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

    
409
                if (viewPort.getImageSize() == null)
410
                        return -1;
411

    
412
                if (viewPort.getAdjustedExtent() == null) {
413
                        return 0;
414
                }
415

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
584
                return visitor.getSelectBound();
585
        }
586

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

    
603
                prepareDrawing(image, g, scale);
604

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

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

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

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

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

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

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

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

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

    
710
        }
711

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

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

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

    
737
                        }
738
                }, scale);
739
        }
740

    
741
        /**
742
         * Devuelve el ViewPort.
743
         * @return  Returns the viewPort.
744
         * @uml.property  name="viewPort"
745
         */
746
        public ViewPort getViewPort() {
747
                return viewPort;
748
        }
749

    
750
        /**
751
         * Inserta un ViewPort.
752
         * @param viewPort  The viewPort to set.
753
         * @uml.property  name="viewPort"
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 DriverException {
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

    
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

    
890
                                try {
891
                                        getViewPort().setExtent(lyr.getFullExtent());
892
                                } catch (DriverException e1) {
893
                                }
894
                        }
895

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

    
903
                        if (lyr instanceof Classifiable) {
904
                                Classifiable c = (Classifiable) lyr;
905
                                c.addLegendListener(eventBuffer);
906
                        }
907

    
908
                        if (lyr instanceof AlphanumericData) {
909
                                Selectable s=null;
910
                                try {
911
                                        s = ((AlphanumericData) lyr).getRecordset();
912
                                        if (s!=null) {
913
                                                s.addSelectionListener(eventBuffer);
914
                                        }
915
                                } catch (DriverException e1) {
916
                                        // TODO Auto-generated catch block
917
                                        e1.printStackTrace();
918
                                }
919

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

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

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

    
941
                        lyr.removeLayerListener(eventBuffer);
942

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

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

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

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

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

    
975

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

    
984
        public void addAsCollectionListener(FLayers layers2) {
985
                layers2.addLayerCollectionListener(layerEventListener);
986
        }
987

    
988
        public GraphicLayer getGraphicsLayer() {
989
                return tracLayer;
990
        }
991

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

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

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

    
1015
                        }
1016
                } else {
1017
                        isEqual = false;
1018
                }
1019
                return isEqual;
1020
        }
1021

    
1022
        public void addLayerError(String stringProperty) {
1023
                layersError.add(stringProperty);
1024
        }
1025

    
1026
        /**
1027
         * @return
1028
         * @uml.property  name="layersError"
1029
         */
1030
        public ArrayList getLayersError() {
1031
                return layersError;
1032
        }
1033

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

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

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

    
1059
        }
1060

    
1061
}