Statistics
| Revision:

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

History | View | Annotate | Download (27.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 org.cresques.cts.ICoordTrans;
54
import org.cresques.cts.IProjection;
55
import org.cresques.geo.Projected;
56

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

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

    
92
        public static final double[] CHANGE = { 100000, 100, 1, 0.1, 160934.4,
93
                        91.44, 30.48, 2.54 };
94

    
95
        public static final int EQUALS = 0;
96

    
97
        public static final int DISJOINT = 1;
98

    
99
        public static final int INTERSECTS = 2;
100

    
101
        public static final int TOUCHES = 3;
102

    
103
        public static final int CROSSES = 4;
104

    
105
        public static final int WITHIN = 5;
106

    
107
        public static final int CONTAINS = 6;
108

    
109
        public static final int OVERLAPS = 7;
110

    
111
        protected FLayers layers;
112

    
113
        private GraphicLayer tracLayer = new GraphicLayer();
114

    
115
        private ViewPort viewPort;
116

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

    
120
        private ArrayList layerDrawingListeners = new ArrayList();
121

    
122
        private EventBuffer eventBuffer = new EventBuffer();
123

    
124
        private LayerEventListener layerEventListener = null;
125

    
126
        private ArrayList layersError = new ArrayList();
127

    
128
        private ArrayList errorListeners = new ArrayList();
129

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

    
143
                layerEventListener = new LayerEventListener();
144
                layers.addLayerCollectionListener(layerEventListener);
145
                layers.addLayerCollectionListener(eventBuffer);
146

    
147
                setViewPort(vp);
148

    
149
        }
150

    
151
        public MapContext(FLayers fLayers, ViewPort vp) {
152
                this.layers = fLayers;
153

    
154
                layerEventListener = new LayerEventListener();
155
                layers.addLayerCollectionListener(layerEventListener);
156
                layers.addLayerCollectionListener(eventBuffer);
157

    
158
                setViewPort(vp);
159
        }
160

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

    
174

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

    
186
        public void addLayerDrawingListener(LayerDrawingListener listener) {
187
                layerDrawingListeners.add(listener);
188
        }
189

    
190
        public void removeLayerDrawListener(LayerDrawingListener listener) {
191
                layerDrawingListeners.remove(listener);
192
        }
193

    
194
        public void addErrorListener(ErrorListener listener) {
195
                errorListeners.add(listener);
196
        }
197

    
198
        public void removeErrorListener(LegendListener listener) {
199
                legendListeners.remove(listener);
200
        }
201

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

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

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

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

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

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

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

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

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

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

    
310
                        }
311
                };
312
                layers.print(g, viewPort, cancel, scale);
313
                tracLayer.draw(null, g, viewPort, cancel, scale);
314
        }
315

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

    
329
                return ret;
330
        }
331

    
332
        /**
333
         * Crea un nuevo FMap totalmente desligado, se replican las capas y el
334
         * ViewPort
335
         *
336
         * @return FMap clonado.
337
         *
338
         * @throws XMLException
339
         */
340
        public MapContext cloneFMap() throws XMLException {
341
                return createFromXML(getXMLEntity());
342
        }
343
        public MapContext cloneToDraw() {
344
                ViewPort vp = getViewPort().cloneViewPort();
345
                MapContext mapContext=new MapContext(getLayers(),vp);
346
                return mapContext;
347
        }
348

    
349
        /**
350
         * A?ade la capa que se pasa como par?metro al nodo que se pasa como
351
         * parametro y lanza ProjectionMismatchException si no est?n todas las capas
352
         * de este FMap en la misma proyecci?n. Lanza un ChildNotAllowedException si
353
         * la capa no es un FLayers y no permite hijos
354
         *
355
         * @param vectorial
356
         *            DOCUMENT ME!
357
         */
358

    
359
        /*
360
         * public void addLayer(LayerPath parent, FLayer layer) throws
361
         * ProjectionMismatchException, ChildrenNotAllowedException {
362
         * layers.addLayer(parent, layer); } public void removeLayer(LayerPath
363
         * parent)throws ChildrenNotAllowedException{ layers.removeLayer(parent); }
364
         */
365

    
366
        /**
367
         * A?ade una capa al grupo de capas que se sit?a por encima de todas las
368
         * otras capas
369
         *
370
         * @param vectorial
371
         *            FLayer.
372
         */
373
        public void addToTrackLayer(FLayer vectorial) {
374
        }
375

    
376
        /**
377
         * Devuelve la escala de la vista en pantalla.
378
         *
379
         * @return escala de la vista.
380
         */
381
        public long getScaleView() {
382
                Preferences prefsResolution = Preferences.userRoot().node( "gvsig.configuration.screen" );
383
                Toolkit kit = Toolkit.getDefaultToolkit();
384
                double dpi = prefsResolution.getInt("dpi",kit.getScreenResolution());
385
                IProjection proj = viewPort.getProjection();
386

    
387
                if (viewPort.getImageSize() == null)
388
                        return -1;
389

    
390
                double w = ((viewPort.getImageSize().getWidth() / dpi) * 2.54);
391

    
392
                if (viewPort.getAdjustedExtent() == null) {
393
                        return 0;
394
                }
395

    
396
                if (proj == null) {
397
                        return (long) (viewPort.getAdjustedExtent().getWidth() / w * CHANGE[getViewPort()
398
                                        .getMapUnits()]);
399
                }
400

    
401
                return Math.round(proj.getScale(viewPort.getAdjustedExtent().getMinX(),
402
                                viewPort.getAdjustedExtent().getMaxX(), viewPort.getImageSize()
403
                                                .getWidth(), dpi));
404
        }
405
        /**
406
         * Introduce un nuevo extent en la vista a partir de la escala que se pasa como par?metro.
407
         *
408
         * @return escala de la vista.
409
         */
410
        public void setScaleView(long scale) {
411
                // TODO falta implementar un di?logo para poder especificar el usuario
412
                // los pixels exactos de su pantalla.
413
                Toolkit kit = Toolkit.getDefaultToolkit();
414
                double dpi = kit.getScreenResolution();
415
                if (viewPort.getImageSize() == null)
416
                        return;
417
                IProjection proj = viewPort.getProjection();
418
                if (viewPort.getAdjustedExtent() == null) {
419
                        return;
420
                }
421
                Rectangle2D rec=proj.getExtent(viewPort.getAdjustedExtent(),scale,viewPort.getImageWidth(),viewPort.getImageHeight(),CHANGE[getViewPort().getMapUnits()],dpi);
422
                getViewPort().setExtent(rec);
423
        }
424
        /**
425
         * @see com.iver.cit.gvsig.fmap.operations.strategies.Strategy#setVectorial(com.iver.cit.gvsig.fmap.VectorialAdapter)
426
         */
427
        public void setVectorial(VectorialAdapter v) {
428
        }
429

    
430
        /**
431
         * @see com.iver.cit.gvsig.fmap.operations.strategies.Strategy#process(com.iver.cit.gvsig.fmap.FeatureSelectorVisitor)
432
         */
433
        public void process(FeatureVisitor visitor) {
434
        }
435

    
436
        /**
437
         * @see com.iver.cit.gvsig.fmap.operations.strategies.Strategy#processSelected(com.iver.cit.gvsig.fmap.FeatureVisitor)
438
         */
439
        public void processSelected(FeatureVisitor visitor) {
440
        }
441

    
442
        /**
443
         * @see com.iver.cit.gvsig.fmap.operations.strategies.Strategy#select(com.iver.cit.gvsig.fmap.FeatureSelectorVisitor,
444
         *      VectorialSubSet)
445
         */
446
        public void select(FeatureVisitor visitor) {
447
        }
448

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

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

    
461
        /**
462
         * @see org.cresques.geo.Projected#getProjection()
463
         */
464
        public IProjection getProjection() {
465
                return getViewPort().getProjection();
466
        }
467

    
468
        /**
469
         * Inserta la proyecci?n.
470
         *
471
         * @param proj
472
         *            Proyecci?n.
473
         */
474
        public void setProjection(IProjection proj) {
475
                if (getViewPort() != null) {
476
                        getViewPort().setProjection(proj);
477
                }
478
        }
479

    
480
        /**
481
         * @see org.cresques.geo.Projected#reProject(org.cresques.cts.ICoordTrans)
482
         */
483
        public void reProject(ICoordTrans arg0) {
484
                // TODO implementar reprojecci?n (lo que sea eso)
485
        }
486

    
487
        /**
488
         * @see com.iver.cit.gvsig.fmap.operations.strategies.Strategy#selectByPoint(java.awt.geom.Point2D,
489
         *      double)
490
         */
491
        /*
492
         * public void selectByPoint(Point2D p, double tolerance) throws
493
         * DriverException { Point2D mapPoint = viewPort.toMapPoint((int) p.getX(),
494
         * (int) p.getY()); SelectByPointVisitor visitor = new
495
         * SelectByPointVisitor(); visitor.setQueriedPoint(mapPoint);
496
         * visitor.setTolerance(getViewPort().toMapDistance(3));
497
         *
498
         * try { layers.process(visitor); } catch (VisitException e) { throw new
499
         * RuntimeException("No se espera que SelectByPointVisitor lance esta
500
         * excepci?n", e); } }
501
         */
502

    
503
        /**
504
         * @see com.iver.cit.gvsig.fmap.operations.strategies.Strategy#selectByRect(java.awt.geom.Rectangle2D)
505
         */
506
        /*
507
         * public void selectByRect(Rectangle2D rect) throws DriverException {
508
         * FLayer[] actives = layers.getActives(); for (int i=0; i < actives.length;
509
         * i++) { if (actives[i] instanceof FLyrVect) { FLyrVect lyrVect =
510
         * (FLyrVect) actives[i]; FBitSet oldBitSet = lyrVect.getSelection();
511
         * FBitSet newBitSet = lyrVect.queryByRect(rect); newBitSet.xor(oldBitSet);
512
         * lyrVect.setSelection(newBitSet); } }
513
         *  }
514
         */
515

    
516
        /**
517
         * @see com.iver.cit.gvsig.fmap.operations.strategies.Strategy#selectByShape(com.iver.cit.gvsig.fmap.fshape.IGeometry,
518
         *      int)
519
         */
520
        public void selectByShape(IGeometry g, int relationship) {
521
        }
522

    
523
        /**
524
         * @see com.iver.cit.gvsig.fmap.operations.strategies.Strategy#queryByPoint(Point2D,
525
         *      double)
526
         */
527
        public Record[] queryByPoint(Point2D p, double tolerance) {
528
                return null;
529
        }
530

    
531
        /**
532
         * @see com.iver.cit.gvsig.fmap.operations.strategies.Strategy#queryByRect(java.awt.geom.Rectangle2D)
533
         */
534
        public Record[] queryByRect(Rectangle2D rect) {
535
                return null;
536
        }
537

    
538
        /**
539
         * @see com.iver.cit.gvsig.fmap.operations.strategies.Strategy#queryByShape(com.iver.cit.gvsig.fmap.fshape.IGeometry,
540
         *      int)
541
         */
542
        public Record[] queryByShape(IGeometry g, int relationship) {
543
                return null;
544
        }
545

    
546
        /**
547
         * @see com.iver.cit.gvsig.fmap.operations.strategies.Strategy#getSelectionBounds()
548
         */
549
        public Rectangle2D getSelectionBounds() {
550
                SelectedZoomVisitor visitor = new SelectedZoomVisitor();
551

    
552
                try {
553
                        layers.process(visitor);
554
                } catch (DriverException e1) {
555
                        throw new RuntimeException(
556
                                        "No se espera que SelectByPointVisitor lance esta excepci?n",
557
                                        e1);
558
                } catch (VisitException e) {
559
                        throw new RuntimeException(
560
                                        "No se espera que SelectByPointVisitor lance esta excepci?n",
561
                                        e);
562
                }
563

    
564
                return visitor.getSelectBound();
565
        }
566

    
567
        /**
568
         * @see com.iver.cit.gvsig.fmap.operations.LayerOperations#draw(java.awt.image.BufferedImage,
569
         *      java.awt.Graphics2D, ISymbol)
570
         */
571
        public void draw(BufferedImage image, Graphics2D g, Cancellable cancel,
572
                        double scale) throws DriverException {
573
                if (viewPort.getExtent() == null) {
574
                        // System.err.println("viewPort.getExtent() = null");
575
                        return;
576
                }
577
                System.out.println("Viewport despues: " + viewPort.toString());
578
                /*
579
                 * if ((viewPort.getImageWidth() <=0) || (viewPort.getImageHeight() <=
580
                 * 0)) { return; }
581
                 */
582

    
583
                prepareDrawing(image, g, scale);
584

    
585
                // M?s c?lidad al texto
586
                RenderingHints renderHints = new RenderingHints(
587
                                RenderingHints.KEY_ANTIALIASING,
588
                                RenderingHints.VALUE_ANTIALIAS_ON);
589
                renderHints.put(RenderingHints.KEY_RENDERING,
590
                                RenderingHints.VALUE_RENDER_QUALITY);
591
                renderHints.put(RenderingHints.KEY_TEXT_ANTIALIASING,
592
                                RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
593
                g.setRenderingHints(renderHints);
594

    
595
                long t1 = System.currentTimeMillis();
596
                layers.draw(image, g, viewPort, cancel, scale);
597

    
598
                LayerDrawEvent beforeTracLayerEvent = new LayerDrawEvent(tracLayer,
599
                                g, viewPort, LayerDrawEvent.GRAPHICLAYER_BEFORE_DRAW);
600
                fireLayerDrawingEvent(beforeTracLayerEvent);
601
                tracLayer.draw(image, g, viewPort, cancel, scale);
602
                LayerDrawEvent afterTracLayerEvent = new LayerDrawEvent(tracLayer,
603
                                g, viewPort, LayerDrawEvent.GRAPHICLAYER_AFTER_DRAW);
604
                fireLayerDrawingEvent(afterTracLayerEvent);
605

    
606
                long t2 = System.currentTimeMillis();
607
                System.err.println("Tiempo de dibujado:" + (t2 - t1) +
608
                                " mseg. Memoria libre:" + Runtime.getRuntime().freeMemory() / 1024  + " KB");
609
                /*
610
                 * g.setColor(Color.BLUE); GeneralPath shpR = new
611
                 * GeneralPath(viewPort.getExtent());
612
                 * shpR.transform(viewPort.getAffineTransform()); g.draw(shpR);
613
                 */
614
                System.gc();
615
        }
616

    
617
        /**
618
         * En esta funci?n vamos a revisar las capas que necesitan repintarse,
619
         * por si hay alguna que se haya guardado la imagen de las anteriores
620
         * y puede acelerar el dibujado.
621
         * @param image
622
         * @param g
623
         * @param scale
624
         */
625
        private void prepareDrawing(BufferedImage image, Graphics2D g, double scale) {
626

    
627
                // Primera pasada: si alguna capa necesita repintarse por debajo
628
                // de la que tiene la cache, TODAS necesitan
629
                // ser repintadas.
630
                boolean bNeedRepaint = false;
631
                boolean bMayExistAceleration = false;
632
                for (int i = 0; i < layers.getLayersCount(); i++)
633
                {
634
                        FLayer lyr = layers.getLayer(i);
635
                        if (lyr.isCachingDrawnLayers() && (lyr.getCacheImageDrawnLayers() != null))
636
                        {
637
                                bMayExistAceleration = true;
638
                        }
639
                        else
640
                        {
641
                                if (lyr.isDirty())
642
                                        bNeedRepaint = true;
643
                        }
644
                }
645
                if (bMayExistAceleration==false)
646
                        bNeedRepaint = true;
647
                if (bNeedRepaint)
648
                        layers.setDirty(true);
649
                else
650
                        recursivePrepareDrawing(layers, 0);
651
        }
652

    
653
        private void validatePreviousLayers(FLayers layers, int index)
654
        {
655
                // TODO: Aqu? quiz?s habr?a que explorar los padres de las capas
656
                // para marcar y/o asignar la imagen cacheada.
657
                for (int i = 0; i < index; i++)
658
                {
659
                        FLayer lyr = layers.getLayer(i);
660
                        lyr.setDirty(false);
661
                }
662
                // Las de arriba las marcamos como sucias
663
//                for (int i = index; i < layers.getLayersCount(); i++)
664
//                {
665
//                        FLayer lyr = layers.getLayer(i);
666
//                        lyr.setDirty(true);
667
//                }
668
        }
669

    
670
        private void recursivePrepareDrawing(FLayers parent, int indexInParent)
671
        {
672
                for (int i = indexInParent; i < parent.getLayersCount(); i++)
673
                {
674
                        FLayer lyr = layers.getLayer(i);
675
                        if (lyr.isCachingDrawnLayers() && (lyr.getCacheImageDrawnLayers() != null))
676
                        {
677
                                // les decimos a las anteriores que est?n validadas (not dirty)
678
                                // para que no se dibujen.
679
                                if (lyr.isDirty())
680
                                        validatePreviousLayers(parent, i);
681
                        }
682

    
683
                        if (lyr instanceof FLayers)
684
                        {
685
                                recursivePrepareDrawing((FLayers)lyr, 0);
686
                        }
687
                }
688

    
689
        }
690

    
691
        public void drawGraphics(BufferedImage image, Graphics2D g,
692
                        Cancellable cancel, double scale) throws DriverException {
693
                if (viewPort == null)
694
                        return;
695
                tracLayer.draw(image, g, viewPort, cancel, scale);
696
        }
697

    
698
        /**
699
         * @see com.iver.cit.gvsig.fmap.operations.LayerOperations#draw(java.awt.image.BufferedImage,
700
         *      java.awt.Graphics2D, ISymbol)
701
         */
702
        public void draw(BufferedImage image, Graphics2D g, double scale)
703
                        throws DriverException {
704
                layers.setDirty(true);
705
                draw(image, g, new Cancellable() {
706
                        /**
707
                         * @see com.iver.utiles.swing.threads.Cancellable#isCanceled()
708
                         */
709
                        public boolean isCanceled() {
710
                                return false;
711
                        }
712

    
713
                        public void setCanceled(boolean canceled) {
714
                                // TODO Auto-generated method stub
715

    
716
                        }
717
                }, scale);
718
        }
719

    
720
        /**
721
         * Devuelve el ViewPort.
722
         *
723
         * @return Returns the viewPort.
724
         */
725
        public ViewPort getViewPort() {
726
                return viewPort;
727
        }
728

    
729
        /**
730
         * Inserta un ViewPort.
731
         *
732
         * @param viewPort
733
         *            The viewPort to set.
734
         */
735
        public void setViewPort(ViewPort viewPort) {
736
                if (this.viewPort != null) {
737
                        this.viewPort.removeViewPortListener(eventBuffer);
738
                }
739

    
740
                this.viewPort = viewPort;
741
                if (viewPort != null)
742
                        viewPort.addViewPortListener(eventBuffer);
743
        }
744
        
745
        /**
746
         * Sets the given zoom extent to the viewport.
747
         *
748
         * @param extent
749
         *            The extent to zoom to.
750
         */
751
        public void zoomToExtent(Rectangle2D extent) {
752
            getViewPort().setExtent(extent);
753
        }
754

    
755
        /**
756
         * M?todo de conveniencia. Recorre las capas y te da el fullExtent
757
         *
758
         * @return fullExtent de todas las capas.
759
         *
760
         * @throws DriverException
761
         */
762
        public Rectangle2D getFullExtent() throws DriverException {
763
                return layers.getFullExtent();
764
        }
765

    
766
        /**
767
         * Devuelve el XMLEntity.
768
         *
769
         * @return XMLEntity.
770
         * @throws XMLException
771
         */
772
        public XMLEntity getXMLEntity() throws XMLException {
773
                XMLEntity xml = new XMLEntity();
774
                xml.putProperty("className", this.getClass().getName());
775
                xml.addChild(viewPort.getXMLEntity());
776
                xml.addChild(layers.getXMLEntity());
777

    
778
                return xml;
779
        }
780

    
781
        /**
782
         * Crea un nuevo FMAp a partir del XMLEntity.
783
         *
784
         * @param xml
785
         *            XMLEntity
786
         *
787
         * @return Nuevo FMap.
788
         *
789
         * @throws XMLException
790
         */
791
        public static MapContext createFromXML03(XMLEntity xml) throws XMLException {
792
                ViewPort vp = ViewPort.createFromXML03(xml.getChild(0));
793
                MapContext fmap = new MapContext(vp);
794
                fmap.layers.setXMLEntity03(xml.getChild(1));
795

    
796
                return fmap;
797
        }
798

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

    
814
                return fmap;
815
        }
816

    
817
        /**
818
         * A?ade un AtomicEventListener.
819
         *
820
         * @param listener
821
         *            AtomicEventListener.
822
         *
823
         * @return True si se ha a?adido correctamente.
824
         */
825
        public boolean addAtomicEventListener(AtomicEventListener listener) {
826
                return eventBuffer.addAtomicEventListener(listener);
827
        }
828

    
829
        /**
830
         * Borra un AtomicEventListener de la lista de listeners.
831
         *
832
         * @param listener
833
         *            AtomicEventListener a borrar.
834
         *
835
         * @return True si se ha borrado correctamente.
836
         */
837
        public boolean removeAtomicEventListener(AtomicEventListener listener) {
838
                return eventBuffer.removeAtomicEventListener(listener);
839
        }
840

    
841
        /**
842
         * Inicializa los AtomicEvent.
843
         */
844
        public void beginAtomicEvent() {
845
                eventBuffer.beginAtomicEvent();
846
        }
847

    
848
        /**
849
         * Finaliza los AtomicEvent.
850
         */
851
        public void endAtomicEvent() {
852
                eventBuffer.endAtomicEvent();
853
        }
854

    
855
        /**
856
         * Evento Layer.
857
         *
858
         * @author Fernando Gonz?lez Cort?s
859
         */
860
        public class LayerEventListener implements LayerCollectionListener {
861
                /**
862
                 * @see com.iver.cit.gvsig.fmap.layers.LayerCollectionListener#layerAdded(com.iver.cit.gvsig.fmap.layers.LayerCollectionEvent)
863
                 */
864
                public void layerAdded(LayerCollectionEvent e) {
865
                        // Si es la primera capa, fijamos su extent al ViewPort
866
                        // if (getLayers().getLayersCount() == 1) {
867
                        if (getViewPort().getExtent() == null) {
868
                                FLayer lyr = e.getAffectedLayer();
869

    
870
                                try {
871
                                        getViewPort().setExtent(lyr.getFullExtent());
872
                                } catch (DriverException e1) {
873
                                }
874
                        }
875

    
876
                        // Registramos al FMap como listener del legend de las capas
877
                        FLayer lyr = e.getAffectedLayer();
878

    
879
                        lyr.addLayerListener(eventBuffer);
880

    
881
                        if (lyr instanceof Classifiable) {
882
                                Classifiable c = (Classifiable) lyr;
883
                                c.addLegendListener(eventBuffer);
884
                        }
885

    
886
                        if (lyr instanceof AlphanumericData) {
887
                                Selectable s=null;
888
                                try {
889
                                        s = ((AlphanumericData) lyr).getRecordset();
890
                                        if (s!=null) {
891
                                                s.addSelectionListener(eventBuffer);
892
                                        }
893
                                } catch (DriverException e1) {
894
                                        // TODO Auto-generated catch block
895
                                        e1.printStackTrace();
896
                                }
897

    
898
                        }
899
                }
900

    
901
                /**
902
                 * @see com.iver.cit.gvsig.fmap.layers.LayerCollectionListener#layerMoved(com.iver.cit.gvsig.fmap.layers.LayerPositionEvent)
903
                 */
904
                public void layerMoved(LayerPositionEvent e) {
905
                }
906

    
907
                /**
908
                 * @see com.iver.cit.gvsig.fmap.layers.LayerCollectionListener#layerRemoved(com.iver.cit.gvsig.fmap.layers.LayerCollectionEvent)
909
                 */
910
                public void layerRemoved(LayerCollectionEvent e) {
911
                        FLayer lyr = e.getAffectedLayer();
912

    
913
                        lyr.removeLayerListener(eventBuffer);
914

    
915
                        if (lyr instanceof Classifiable) {
916
                                Classifiable c = (Classifiable) lyr;
917
                                c.removeLegendListener(eventBuffer);
918
                        }
919

    
920
                        if (lyr instanceof Selectable) {
921
                                Selectable s = (Selectable) lyr;
922
                                s.addSelectionListener(eventBuffer);
923
                        }
924
                }
925

    
926
                /**
927
                 * @see com.iver.cit.gvsig.fmap.layers.LayerCollectionListener#layerAdding(com.iver.cit.gvsig.fmap.layers.LayerCollectionEvent)
928
                 */
929
                public void layerAdding(LayerCollectionEvent e)
930
                                throws CancelationException {
931
                }
932

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

    
940
                /**
941
                 * @see com.iver.cit.gvsig.fmap.layers.LayerCollectionListener#layerRemoving(com.iver.cit.gvsig.fmap.layers.LayerCollectionEvent)
942
                 */
943
                public void layerRemoving(LayerCollectionEvent e)
944
                                throws CancelationException {
945
                }
946

    
947

    
948
                /**
949
                 * @see com.iver.cit.gvsig.fmap.layers.LayerCollectionListener#visibilityChanged(com.iver.cit.gvsig.fmap.layers.LayerCollectionEvent)
950
                 */
951
                public void visibilityChanged(LayerCollectionEvent e)
952
                                throws CancelationException {
953
                }
954
        }
955

    
956
        public void addAsCollectionListener(FLayers layers2) {
957
                layers2.addLayerCollectionListener(layerEventListener);
958
        }
959

    
960
        public GraphicLayer getGraphicsLayer() {
961
                return tracLayer;
962
        }
963

    
964
        /**
965
         * Asigna la capa gr?fica
966
         * @param graphicLayer
967
         */
968
        public void setGraphicsLayer(GraphicLayer graphicLayer) {
969
                tracLayer = graphicLayer;
970
        }
971

    
972
        public boolean equals(Object arg0) {
973
                MapContext map = (MapContext) arg0;
974
                if (super.equals(arg0))
975
                        return true;
976
                if (getLayers() == map.getLayers())
977
                        return true;
978
                boolean isEqual = true;
979
                if (map.getLayers().getLayersCount() == getLayers().getLayersCount()) {
980
                        for (int i = 0; i < getLayers().getLayersCount(); i++) {
981

    
982
                                if (!getLayers().getLayer(i).getName().equals(
983
                                                map.getLayers().getLayer(i).getName())) {
984
                                        isEqual = false;
985
                                }
986

    
987
                        }
988
                } else {
989
                        isEqual = false;
990
                }
991
                return isEqual;
992
        }
993

    
994
        public void addLayerError(String stringProperty) {
995
                layersError.add(stringProperty);
996
        }
997

    
998
        public ArrayList getLayersError() {
999
                return layersError;
1000
        }
1001

    
1002
        public void clearErrors() {
1003
                layersError.clear();
1004
        }
1005

    
1006
        public void clearAllCachingImageDrawnLayers() {
1007
                clearCachingImageDrawnLayers(this.layers);
1008
}
1009
        private void clearCachingImageDrawnLayers(FLayers layers){
1010
                int i;
1011
                FLayer layer;
1012
                for (i=0;i< layers.getLayersCount();i++){
1013
                        layer = layers.getLayer(i);
1014
                        if (layer instanceof FLayers) {
1015
                                clearCachingImageDrawnLayers((FLayers)layer);
1016
                        } else {
1017
                                layer.setCacheImageDrawnLayers(null);
1018
                        }
1019
                }
1020
        }
1021

    
1022
        public void redraw() {
1023
                // truco
1024
                if (getLayers().getLayersCount() > 0)
1025
                        getLayers().moveTo(0,0);
1026
                
1027
        }
1028

    
1029
}