Statistics
| Revision:

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

History | View | Annotate | Download (29.5 KB)

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

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

    
53
import javax.print.attribute.PrintRequestAttributeSet;
54

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

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

    
86
/**
87
 * Modelo del mapa.
88
 *
89
 * @author Fernando Gonz?lez Cort?s
90
 */
91
public class MapContext implements Projected {
92
        /* Do not alter the order and the values of this array, if you need append values.*/
93
        public static final double[] CHANGEM = { 1000, 1, 0.01, 0.001, 1609.344,
94
                        0.9144, 0.3048, 0.0254, 1/8.983152841195214E-6 };
95

    
96
        /* Do not alter the order and the values of this array, if you need append values.*/
97
        public static final double[] CHANGE = { 100000, 100, 1, 0.1, 160934.4,
98
                        91.44, 30.48, 2.54, 1/8.983152841195214E-4 };
99

    
100
        public static final int EQUALS = 0;
101

    
102
        public static final int DISJOINT = 1;
103

    
104
        public static final int INTERSECTS = 2;
105

    
106
        public static final int TOUCHES = 3;
107

    
108
        public static final int CROSSES = 4;
109

    
110
        public static final int WITHIN = 5;
111

    
112
        public static final int CONTAINS = 6;
113

    
114
        public static final int OVERLAPS = 7;
115

    
116
        protected FLayers layers;
117

    
118
        private GraphicLayer tracLayer = new GraphicLayer();
119

    
120
        private ViewPort viewPort;
121

    
122
        // private ArrayList invalidationListeners = new ArrayList();
123
        private ArrayList legendListeners = new ArrayList();
124

    
125
        private ArrayList layerDrawingListeners = new ArrayList();
126

    
127
        private EventBuffer eventBuffer = new EventBuffer();
128

    
129
        private LayerEventListener layerEventListener = null;
130

    
131
        private ArrayList layersError = new ArrayList();
132

    
133
        private ArrayList errorListeners = new ArrayList();
134

    
135
        /* Do not alter the order and the values of this array, if you need append values.*/
136
        public static final String[] NAMES= {
137
                Messages.getString("Kilometros"),
138
                Messages.getString("Metros"),
139
                Messages.getString("Centimetros"),
140
                Messages.getString("Milimetros"),
141
                Messages.getString("Millas"),
142
                Messages.getString("Yardas"),
143
                Messages.getString("Pies"),
144
                Messages.getString("Pulgadas"),
145
                Messages.getString("Grados"),
146
        };
147

    
148
        // public static ResourceBundle myResourceBundle =
149
        // ResourceBundle.getBundle("FMap");
150
        public static double ZOOMINFACTOR=2;
151
        public static double ZOOMOUTFACTOR=0.5;
152
        /**
153
         * Crea un nuevo FMap.
154
         *
155
         * @param vp
156
         *            ViewPort.
157
         */
158
        public MapContext(ViewPort vp) {
159
                this.layers = new FLayers(this, null);
160

    
161
                layerEventListener = new LayerEventListener();
162
                layers.addLayerCollectionListener(layerEventListener);
163
                layers.addLayerCollectionListener(eventBuffer);
164

    
165
                setViewPort(vp);
166

    
167
        }
168

    
169
        public MapContext(FLayers fLayers, ViewPort vp) {
170
                this.layers = fLayers;
171

    
172
                layerEventListener = new LayerEventListener();
173
                layers.addLayerCollectionListener(layerEventListener);
174
                layers.addLayerCollectionListener(eventBuffer);
175

    
176
                setViewPort(vp);
177
        }
178

    
179
        /**
180
         * Reports to all registered driver listener a group of driverexceptions
181
         * produced in the same fmap atomic transaction
182
         * @param driverExceptions
183
         */
184
        public synchronized void reportDriverExceptions(String introductoryText,
185
                                                                                                        List driverExceptions){
186
                for (int i = 0; i < errorListeners.size(); i++) {
187
                        ((ErrorListener) errorListeners.get(i)).
188
                                reportDriverExceptions(introductoryText, driverExceptions);
189
                }
190
        }
191

    
192

    
193
        /**
194
         * A?ade un LegendListener.
195
         *
196
         * @param listener
197
         *            LegendListener a a?adir.
198
         */
199
        public void addLayerListener(LegendListener listener) {
200
                if (!legendListeners.contains(listener))
201
                        legendListeners.add(listener);
202
        }
203

    
204
        public void addLayerDrawingListener(LayerDrawingListener listener) {
205
                layerDrawingListeners.add(listener);
206
        }
207

    
208
        public void removeLayerDrawListener(LayerDrawingListener listener) {
209
                layerDrawingListeners.remove(listener);
210
        }
211

    
212
        public void addErrorListener(ErrorListener listener) {
213
                errorListeners.add(listener);
214
        }
215

    
216
        public void removeErrorListener(LegendListener listener) {
217
                legendListeners.remove(listener);
218
        }
219

    
220
        /**
221
         * M?todo ejecutado cuando hay un cambio de leyenda que se quiera reflejar.
222
         *
223
         * @param e
224
         *            LegendChangedEvent.
225
         */
226
        public synchronized void callLegendChanged() {
227
                for (int i = 0; i < legendListeners.size(); i++) {
228
                        ((LegendListener) legendListeners.get(i)).legendChanged(null);
229
                }
230
                // getLayers().moveTo(0,0);
231
        }
232

    
233
        public synchronized void fireLayerDrawingEvent(LayerDrawEvent e) {
234
                for (int i = 0; i < layerDrawingListeners.size(); i++)
235
                {
236
                        LayerDrawingListener listener = (LayerDrawingListener) layerDrawingListeners.get(i);
237
                        switch (e.getEventType())
238
                        {
239
                                case LayerDrawEvent.LAYER_BEFORE_DRAW:
240
                                        listener.beforeLayerDraw(e);
241
                                        break;
242
                                case LayerDrawEvent.LAYER_AFTER_DRAW:
243
                                        listener.afterLayerDraw(e);
244
                                        break;
245
                                case LayerDrawEvent.GRAPHICLAYER_BEFORE_DRAW:
246
                                        listener.beforeGraphicLayerDraw(e);
247
                                        break;
248
                                case LayerDrawEvent.GRAPHICLAYER_AFTER_DRAW:
249
                                        listener.afterLayerGraphicDraw(e);
250
                                        break;
251
                        }
252
                }
253
                // getLayers().moveTo(0,0);
254
        }
255

    
256
        public synchronized void callNewErrorEvent(ErrorEvent e) {
257
                for (int i = 0; i < errorListeners.size(); i++) {
258
                        ((ErrorListener) errorListeners.get(i)).errorThrown(e);
259
                }
260
                // getLayers().moveTo(0,0);
261
        }
262

    
263
        /**
264
         * Borra un LegendListener.
265
         *
266
         * @param listener
267
         *            LegendListener a borrar.
268
         */
269
        public void removeLayerListener(LegendListener listener) {
270
                legendListeners.remove(listener);
271
        }
272

    
273
        /**
274
         * Devuelve las capas que contiene el mapa.
275
         *
276
         * @return Capas.
277
         */
278
        public FLayers getLayers() {
279
                return layers;
280
        }
281

    
282
        /**
283
         * Dibuja en la imagen que se pasa como par?metro el contenido de las capas
284
         * visibles del mapa y teniendo en cuenta los datos del ViewPort contenido
285
         * en este FMap
286
         *
287
         * @param b
288
         *            Imagen.
289
         */
290
        public void drawLabels(BufferedImage b) {
291
        }
292

    
293
        /**
294
         * M?todo de conveniencia que se usa provisionalmente para solicitar un
295
         * refresco de todo lo que dependa del FMap (MapContext). Esto provocar? un
296
         * evento de cambio de orden de capas que obligar? a redibujar todo lo que
297
         * depende de FMap (TOC, MapControl, FFrameView, etc).
298
         */
299
        public void invalidate() {
300
                getLayers().moveTo(0, 0);
301
        }
302

    
303
        /**
304
         * Imprime el las capas que contiene el FMap sobre el Graphics2D que se pasa
305
         * como par?metro, normalmente es el Graphics de la impresora.
306
         *
307
         * @param g
308
         *            Graphics2D
309
         * @throws ReadDriverException TODO
310
         */
311
        public void print(Graphics2D g, double scale, PrintRequestAttributeSet properties) throws ReadDriverException {
312
                RenderingHints renderHints = new RenderingHints(
313
                                RenderingHints.KEY_ANTIALIASING,
314
                                RenderingHints.VALUE_ANTIALIAS_ON);
315
                renderHints.put(RenderingHints.KEY_RENDERING,
316
                                RenderingHints.VALUE_RENDER_QUALITY);
317
                g.setRenderingHints(renderHints);
318

    
319
                Cancellable cancel = new Cancellable() {
320
                        public boolean isCanceled() {
321
                                return false;
322
                        }
323

    
324
                        public void setCanceled(boolean canceled) {
325
                                // No queremos que se pueda cancelar la impresi?n.
326

    
327
                        }
328
                };
329
                layers.print(g, viewPort, cancel, scale, properties);
330
                tracLayer.draw(null, g, viewPort, cancel, scale);
331
        }
332

    
333
        /**
334
         * Crea un nuevo FMap con la informaci?n del ViewPort que se pasa como
335
         * par?metro.
336
         *
337
         * @param vp
338
         *            ViewPort.
339
         *
340
         * @return FMap nuevo.
341
         */
342
        public MapContext createNewFMap(ViewPort vp) {
343
                MapContext ret = new MapContext(vp);
344
                ret.layers = this.layers;
345

    
346
                return ret;
347
        }
348

    
349
        /**
350
         * Crea un nuevo FMap totalmente desligado, se replican las capas y el
351
         * ViewPort
352
         *
353
         * @return FMap clonado.
354
         *
355
         * @throws XMLException
356
         */
357
        public MapContext cloneFMap() throws XMLException {
358
                ViewPort vp = getViewPort().cloneViewPort();
359
                FLayers antLayers = getLayers();
360
                MapContext ret = new MapContext(vp);
361
                FLayers aux = new FLayers(ret, null);
362
                for (int i=0; i < antLayers.getLayersCount(); i++)
363
                {
364
                        FLayer lyr = antLayers.getLayer(i);
365
                        try {
366
                                aux.addLayer(lyr.cloneLayer());
367
                        } catch (Exception e) {
368
                                // TODO Auto-generated catch block
369
                                e.printStackTrace();
370
                        }
371
                }
372
                ret.layers = aux;
373
                return ret;
374

    
375
//                return createFromXML(getXMLEntity());
376

    
377
        }
378
        public MapContext cloneToDraw() {
379
                ViewPort vp = getViewPort().cloneViewPort();
380
                MapContext mapContext=new MapContext(getLayers(),vp);
381
                return mapContext;
382
        }
383

    
384
        /**
385
         * A?ade la capa que se pasa como par?metro al nodo que se pasa como
386
         * parametro y lanza ProjectionMismatchException si no est?n todas las capas
387
         * de este FMap en la misma proyecci?n. Lanza un ChildNotAllowedException si
388
         * la capa no es un FLayers y no permite hijos
389
         *
390
         * @param vectorial
391
         *            DOCUMENT ME!
392
         */
393

    
394
        /*
395
         * public void addLayer(LayerPath parent, FLayer layer) throws
396
         * ProjectionMismatchException, ChildrenNotAllowedException {
397
         * layers.addLayer(parent, layer); } public void removeLayer(LayerPath
398
         * parent)throws ChildrenNotAllowedException{ layers.removeLayer(parent); }
399
         */
400

    
401
        /**
402
         * A?ade una capa al grupo de capas que se sit?a por encima de todas las
403
         * otras capas
404
         *
405
         * @param vectorial
406
         *            FLayer.
407
         */
408
        public void addToTrackLayer(FLayer vectorial) {
409
        }
410

    
411
        /**
412
         * Devuelve la escala de la vista en pantalla.
413
         *
414
         * @return escala de la vista.
415
         */
416
        public long getScaleView() {
417
                Preferences prefsResolution = Preferences.userRoot().node( "gvsig.configuration.screen" );
418
                Toolkit kit = Toolkit.getDefaultToolkit();
419
                double dpi = prefsResolution.getInt("dpi",kit.getScreenResolution());
420
                IProjection proj = viewPort.getProjection();
421

    
422
                if (viewPort.getImageSize() == null)
423
                        return -1;
424

    
425
                if (viewPort.getAdjustedExtent() == null) {
426
                        return 0;
427
                }
428

    
429
                if (proj == null) {
430
                        double w = ((viewPort.getImageSize().getWidth() / dpi) * 2.54);
431
                        return (long) (viewPort.getAdjustedExtent().getWidth() / w * CHANGEM[getViewPort()
432
                                        .getMapUnits()]/CHANGEM[getViewPort().getDistanceUnits()]);
433
                }
434

    
435
                return Math.round(proj.getScale((viewPort.getAdjustedExtent().getMinX()*CHANGEM[getViewPort().getMapUnits()])/CHANGEM[getViewPort().getDistanceUnits()],
436
                                (viewPort.getAdjustedExtent().getMaxX()*CHANGEM[getViewPort().getMapUnits()])/CHANGEM[getViewPort().getDistanceUnits()], viewPort.getImageSize()
437
                                                .getWidth(), dpi));
438

    
439
        }
440
        /**
441
         * Introduce un nuevo extent en la vista a partir de la escala que se pasa como par?metro.
442
         *
443
         * @return escala de la vista.
444
         */
445
        public void setScaleView(long scale) {
446
                clearAllCachingImageDrawnLayers();
447
                Preferences prefsResolution = Preferences.userRoot().node( "gvsig.configuration.screen" );
448
                Toolkit kit = Toolkit.getDefaultToolkit();
449
                double dpi = prefsResolution.getInt("dpi",kit.getScreenResolution());
450
                if (viewPort.getImageSize() == null)
451
                        return;
452
                IProjection proj = viewPort.getProjection();
453
                if (viewPort.getAdjustedExtent() == null) {
454
                        return;
455
                }
456
                Rectangle2D rec=proj.getExtent(viewPort.getAdjustedExtent(),scale,viewPort.getImageWidth(),viewPort.getImageHeight(),CHANGE[getViewPort().getMapUnits()],CHANGEM[getViewPort().getDistanceUnits()],dpi);
457
                getViewPort().setExtent(rec);
458
        }
459
        /**
460
         * @see com.iver.cit.gvsig.fmap.operations.strategies.Strategy#setVectorial(com.iver.cit.gvsig.fmap.VectorialAdapter)
461
         */
462
        public void setVectorial(VectorialAdapter v) {
463
        }
464

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

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

    
477
        /**
478
         * @see com.iver.cit.gvsig.fmap.operations.strategies.Strategy#select(com.iver.cit.gvsig.fmap.FeatureSelectorVisitor,
479
         *      VectorialSubSet)
480
         */
481
        public void select(FeatureVisitor visitor) {
482
        }
483

    
484
        /**
485
         * @see com.iver.cit.gvsig.fmap.operations.strategies.Strategy#selectFromSelection()
486
         */
487
        public void selectFromSelection() {
488
        }
489

    
490
        /**
491
         * @see com.iver.cit.gvsig.fmap.operations.strategies.Strategy#createIndex()
492
         */
493
        public void createIndex() {
494
        }
495

    
496
        /**
497
         * @see org.cresques.geo.Projected#getProjection()
498
         */
499
        public IProjection getProjection() {
500
                return getViewPort().getProjection();
501
        }
502

    
503
        /**
504
         * Inserta la proyecci?n.
505
         *
506
         * @param proj
507
         *            Proyecci?n.
508
         */
509
        public void setProjection(IProjection proj) {
510
                if (getViewPort() != null) {
511
                        getViewPort().setProjection(proj);
512
                }
513
        }
514

    
515
        /**
516
         * @see org.cresques.geo.Projected#reProject(org.cresques.cts.ICoordTrans)
517
         */
518
        public void reProject(ICoordTrans arg0) {
519
                // TODO implementar reprojecci?n (lo que sea eso)
520
        }
521

    
522
        /**
523
         * @see com.iver.cit.gvsig.fmap.operations.strategies.Strategy#selectByPoint(java.awt.geom.Point2D,
524
         *      double)
525
         */
526
        /*
527
         * public void selectByPoint(Point2D p, double tolerance) throws
528
         * DriverException { Point2D mapPoint = viewPort.toMapPoint((int) p.getX(),
529
         * (int) p.getY()); SelectByPointVisitor visitor = new
530
         * SelectByPointVisitor(); visitor.setQueriedPoint(mapPoint);
531
         * visitor.setTolerance(getViewPort().toMapDistance(3));
532
         *
533
         * try { layers.process(visitor); } catch (VisitException e) { throw new
534
         * RuntimeException("No se espera que SelectByPointVisitor lance esta
535
         * excepci?n", e); } }
536
         */
537

    
538
        /**
539
         * @see com.iver.cit.gvsig.fmap.operations.strategies.Strategy#selectByRect(java.awt.geom.Rectangle2D)
540
         */
541
        /*
542
         * public void selectByRect(Rectangle2D rect) throws DriverException {
543
         * FLayer[] actives = layers.getActives(); for (int i=0; i < actives.length;
544
         * i++) { if (actives[i] instanceof FLyrVect) { FLyrVect lyrVect =
545
         * (FLyrVect) actives[i]; FBitSet oldBitSet = lyrVect.getSelection();
546
         * FBitSet newBitSet = lyrVect.queryByRect(rect); newBitSet.xor(oldBitSet);
547
         * lyrVect.setSelection(newBitSet); } }
548
         *  }
549
         */
550

    
551
        /**
552
         * @see com.iver.cit.gvsig.fmap.operations.strategies.Strategy#selectByShape(com.iver.cit.gvsig.fmap.fshape.IGeometry,
553
         *      int)
554
         */
555
        public void selectByShape(IGeometry g, int relationship) {
556
        }
557

    
558
        /**
559
         * @see com.iver.cit.gvsig.fmap.operations.strategies.Strategy#queryByPoint(Point2D,
560
         *      double)
561
         */
562
        public Record[] queryByPoint(Point2D p, double tolerance) {
563
                return null;
564
        }
565

    
566
        /**
567
         * @see com.iver.cit.gvsig.fmap.operations.strategies.Strategy#queryByRect(java.awt.geom.Rectangle2D)
568
         */
569
        public Record[] queryByRect(Rectangle2D rect) {
570
                return null;
571
        }
572

    
573
        /**
574
         * @see com.iver.cit.gvsig.fmap.operations.strategies.Strategy#queryByShape(com.iver.cit.gvsig.fmap.fshape.IGeometry,
575
         *      int)
576
         */
577
        public Record[] queryByShape(IGeometry g, int relationship) {
578
                return null;
579
        }
580

    
581
        /**
582
         * @see com.iver.cit.gvsig.fmap.operations.strategies.Strategy#getSelectionBounds()
583
         */
584
        public Rectangle2D getSelectionBounds() {
585
                SelectedZoomVisitor visitor = new SelectedZoomVisitor();
586

    
587
                try {
588
                        layers.process(visitor);
589
                } catch (ReadDriverException e1) {
590
                        throw new RuntimeException(
591
                                        "No se espera que SelectByPointVisitor lance esta excepci?n",
592
                                        e1);
593
                } catch (VisitorException e) {
594
                        throw new RuntimeException(
595
                                        "No se espera que SelectByPointVisitor lance esta excepci?n",
596
                                        e);
597
                }
598

    
599
                return visitor.getSelectBound();
600
        }
601

    
602
        /**
603
         * @see com.iver.cit.gvsig.fmap.operations.LayerOperations#draw(java.awt.image.BufferedImage,
604
         *      ISymbol)
605
         */
606
        public void draw(BufferedImage image, Graphics2D g, Cancellable cancel,
607
                        double scale) throws ReadDriverException {
608
                if (viewPort.getExtent() == null) {
609
                        // System.err.println("viewPort.getExtent() = null");
610
                        return;
611
                }
612
                System.out.println("Viewport despues: " + viewPort.toString());
613
                /*
614
                 * if ((viewPort.getImageWidth() <=0) || (viewPort.getImageHeight() <=
615
                 * 0)) { return; }
616
                 */
617

    
618
                prepareDrawing(image, g, scale);
619

    
620
                // M?s c?lidad al texto
621
                RenderingHints renderHints = new RenderingHints(
622
                                RenderingHints.KEY_ANTIALIASING,
623
                                RenderingHints.VALUE_ANTIALIAS_ON);
624
                renderHints.put(RenderingHints.KEY_RENDERING,
625
                                RenderingHints.VALUE_RENDER_QUALITY);
626
                renderHints.put(RenderingHints.KEY_TEXT_ANTIALIASING,
627
                                RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
628
                g.setRenderingHints(renderHints);
629

    
630
                long t1 = System.currentTimeMillis();
631
                layers.draw(image, g, viewPort, cancel, scale);
632

    
633
                LayerDrawEvent beforeTracLayerEvent = new LayerDrawEvent(tracLayer,
634
                                g, viewPort, LayerDrawEvent.GRAPHICLAYER_BEFORE_DRAW);
635
                fireLayerDrawingEvent(beforeTracLayerEvent);
636
                tracLayer.draw(image, g, viewPort, cancel, scale);
637
                LayerDrawEvent afterTracLayerEvent = new LayerDrawEvent(tracLayer,
638
                                g, viewPort, LayerDrawEvent.GRAPHICLAYER_AFTER_DRAW);
639
                fireLayerDrawingEvent(afterTracLayerEvent);
640

    
641
                //layers.setDirty(false);
642
                long t2 = System.currentTimeMillis();
643
                System.err.println("Tiempo de dibujado:" + (t2 - t1) +
644
                                " mseg. Memoria libre:" + Runtime.getRuntime().freeMemory() / 1024  + " KB");
645
                /*
646
                 * g.setColor(Color.BLUE); GeneralPath shpR = new
647
                 * GeneralPath(viewPort.getExtent());
648
                 * shpR.transform(viewPort.getAffineTransform()); g.draw(shpR);
649
                 */
650
                System.gc();
651
        }
652

    
653
        /**
654
         * En esta funci?n vamos a revisar las capas que necesitan repintarse,
655
         * por si hay alguna que se haya guardado la imagen de las anteriores
656
         * y puede acelerar el dibujado.
657
         * @param image
658
         * @param g
659
         * @param scale
660
         */
661
        private void prepareDrawing(BufferedImage image, Graphics2D g, double scale) {
662

    
663
                // Primera pasada: si alguna capa necesita repintarse por debajo
664
                // de la que tiene la cache, TODAS necesitan
665
                // ser repintadas.
666
                boolean bNeedRepaint = false;
667
                boolean bMayExistAceleration = false;
668
                for (int i = 0; i < layers.getLayersCount(); i++)
669
                {
670
                        FLayer lyr = layers.getLayer(i);
671
                        if (lyr.isCachingDrawnLayers() && (lyr.getCacheImageDrawnLayers() != null))
672
                        {
673
                                bMayExistAceleration = true;
674
                        }
675
                        else
676
                        {
677
                                if (lyr.isDirty())
678
                                        bNeedRepaint = true;
679
                        }
680
                }
681
                if (bMayExistAceleration==false)
682
                        bNeedRepaint = true;
683
                if (bNeedRepaint)
684
                        layers.setDirty(true);
685
                else
686
                        recursivePrepareDrawing(layers, 0);
687
        }
688

    
689
        private void validatePreviousLayers(FLayers layers, int index)
690
        {
691
                // TODO: Aqu? quiz?s habr?a que explorar los padres de las capas
692
                // para marcar y/o asignar la imagen cacheada.
693
                for (int i = 0; i < index; i++)
694
                {
695
                        FLayer lyr = layers.getLayer(i);
696
                        lyr.setDirty(false);
697
                }
698
                // Las de arriba las marcamos como sucias
699
//                for (int i = index; i < layers.getLayersCount(); i++)
700
//                {
701
//                        FLayer lyr = layers.getLayer(i);
702
//                        lyr.setDirty(true);
703
//                }
704
        }
705

    
706
        private void recursivePrepareDrawing(FLayers parent, int indexInParent)
707
        {
708
                for (int i = indexInParent; i < parent.getLayersCount(); i++)
709
                {
710
                        FLayer lyr = layers.getLayer(i);
711
                        if (lyr.isCachingDrawnLayers() && (lyr.getCacheImageDrawnLayers() != null))
712
                        {
713
                                // les decimos a las anteriores que est?n validadas (not dirty)
714
                                // para que no se dibujen.
715
                                if (lyr.isDirty())
716
                                        validatePreviousLayers(parent, i);
717
                        }
718

    
719
                        if (lyr instanceof FLayers)
720
                        {
721
                                recursivePrepareDrawing((FLayers)lyr, 0);
722
                        }
723
                }
724

    
725
        }
726

    
727
        public void drawGraphics(BufferedImage image, Graphics2D g,
728
                        Cancellable cancel, double scale) throws ReadDriverException {
729
                if (viewPort == null)
730
                        return;
731
                tracLayer.draw(image, g, viewPort, cancel, scale);
732
        }
733

    
734
        /**
735
         * @see com.iver.cit.gvsig.fmap.operations.LayerOperations#draw(java.awt.image.BufferedImage,
736
         *      ISymbol)
737
         */
738
        public void draw(BufferedImage image, Graphics2D g, double scale)
739
                        throws ReadDriverException {
740
                layers.setDirty(true);
741
                draw(image, g, new Cancellable() {
742
                        /**
743
                         * @see com.iver.utiles.swing.threads.Cancellable#isCanceled()
744
                         */
745
                        public boolean isCanceled() {
746
                                return false;
747
                        }
748

    
749
                        public void setCanceled(boolean canceled) {
750
                                // TODO Auto-generated method stub
751

    
752
                        }
753
                }, scale);
754
        }
755

    
756
        /**
757
         * Devuelve el ViewPort.
758
         *
759
         * @return Returns the viewPort.
760
         */
761
        public ViewPort getViewPort() {
762
                return viewPort;
763
        }
764

    
765
        /**
766
         * Inserta un ViewPort.
767
         *
768
         * @param viewPort
769
         *            The viewPort to set.
770
         */
771
        public void setViewPort(ViewPort viewPort) {
772
                if (this.viewPort != null) {
773
                        this.viewPort.removeViewPortListener(eventBuffer);
774
                }
775

    
776
                this.viewPort = viewPort;
777
                if (viewPort != null)
778
                        viewPort.addViewPortListener(eventBuffer);
779
        }
780

    
781
        /**
782
         * Sets the given zoom extent to the viewport.
783
         *
784
         * @param extent
785
         *            The extent to zoom to.
786
         */
787
        public void zoomToExtent(Rectangle2D extent) {
788
            getViewPort().setExtent(extent);
789
        }
790

    
791
        /**
792
         * M?todo de conveniencia. Recorre las capas y te da el fullExtent
793
         *
794
         * @return fullExtent de todas las capas.
795
         *
796
         * @throws DriverException
797
         */
798
        public Rectangle2D getFullExtent() throws ReadDriverException {
799
                return layers.getFullExtent();
800
        }
801

    
802
        /**
803
         * Devuelve el XMLEntity.
804
         *
805
         * @return XMLEntity.
806
         * @throws XMLException
807
         */
808
        public XMLEntity getXMLEntity() throws XMLException {
809
                XMLEntity xml = new XMLEntity();
810
                xml.putProperty("className", this.getClass().getName());
811
                xml.addChild(viewPort.getXMLEntity());
812
                xml.addChild(layers.getXMLEntity());
813

    
814
                return xml;
815
        }
816

    
817
        /**
818
         * Crea un nuevo FMAp a partir del XMLEntity.
819
         *
820
         * @param xml
821
         *            XMLEntity
822
         *
823
         * @return Nuevo FMap.
824
         *
825
         * @throws XMLException
826
         */
827
        public static MapContext createFromXML03(XMLEntity xml) throws XMLException {
828
                ViewPort vp = ViewPort.createFromXML03(xml.getChild(0));
829
                MapContext fmap = new MapContext(vp);
830
                fmap.layers.setXMLEntity03(xml.getChild(1));
831

    
832
                return fmap;
833
        }
834

    
835
        /**
836
         * Crea un nuevo FMAp a partir del XMLEntity.
837
         *
838
         * @param xml
839
         *            XMLEntity
840
         *
841
         * @return Nuevo FMap.
842
         *
843
         * @throws XMLException
844
         */
845
        public static MapContext createFromXML(XMLEntity xml) throws XMLException {
846
                ViewPort vp = ViewPort.createFromXML(xml.getChild(0));
847
                MapContext fmap = new MapContext(vp);
848
                fmap.layers.setXMLEntity(xml.getChild(1));
849
                fmap.layers.setName("root layer");
850
                return fmap;
851
        }
852

    
853
        /**
854
         * A?ade un AtomicEventListener.
855
         *
856
         * @param listener
857
         *            AtomicEventListener.
858
         *
859
         * @return True si se ha a?adido correctamente.
860
         */
861
        public boolean addAtomicEventListener(AtomicEventListener listener) {
862
                return eventBuffer.addAtomicEventListener(listener);
863
        }
864

    
865
        /**
866
         * Borra un AtomicEventListener de la lista de listeners.
867
         *
868
         * @param listener
869
         *            AtomicEventListener a borrar.
870
         *
871
         * @return True si se ha borrado correctamente.
872
         */
873
        public boolean removeAtomicEventListener(AtomicEventListener listener) {
874
                return eventBuffer.removeAtomicEventListener(listener);
875
        }
876

    
877
        /**
878
         * Inicializa los AtomicEvent.
879
         */
880
        public void beginAtomicEvent() {
881
                eventBuffer.beginAtomicEvent();
882
        }
883

    
884
        /**
885
         * Finaliza los AtomicEvent.
886
         */
887
        public void endAtomicEvent() {
888
                eventBuffer.endAtomicEvent();
889
        }
890

    
891
        /**
892
         * Evento Layer.
893
         *
894
         * @author Fernando Gonz?lez Cort?s
895
         */
896
        public class LayerEventListener implements LayerCollectionListener {
897
                /**
898
                 * @see com.iver.cit.gvsig.fmap.layers.LayerCollectionListener#layerAdded(com.iver.cit.gvsig.fmap.layers.LayerCollectionEvent)
899
                 */
900
                public void layerAdded(LayerCollectionEvent e) {
901
                        // Si es la primera capa, fijamos su extent al ViewPort
902
                        // if (getLayers().getLayersCount() == 1) {
903
                        if (getViewPort().getExtent() == null) {
904
                                FLayer lyr = e.getAffectedLayer();
905
                                if (lyr.isAvailable())
906
                                        try {
907
                                                getViewPort().setExtent(lyr.getFullExtent());
908
                                        } catch (ReadDriverException e1) {
909
                                                e1.printStackTrace();
910
                                        } catch (ExpansionFileReadException e1) {
911
                                                e1.printStackTrace();
912
                                        }
913
                        }
914

    
915
                        // Registramos al FMap como listener del legend de las capas
916
                        FLayer lyr = e.getAffectedLayer();
917
                        selectionListener(lyr);
918
                }
919
                private void selectionListener(FLayer lyr){
920
                        lyr.addLayerListener(eventBuffer);
921

    
922
                        if (lyr instanceof Classifiable) {
923
                                Classifiable c = (Classifiable) lyr;
924
                                c.addLegendListener(eventBuffer);
925
                        }
926

    
927
                        if (lyr instanceof AlphanumericData) {
928
                                Selectable s=null;
929
                                try {
930
                                        s = ((AlphanumericData) lyr).getRecordset();
931
                                        if (s!=null) {
932
                                                s.addSelectionListener(eventBuffer);
933
                                        }
934
                                } catch (ReadDriverException e1) {
935
                                        e1.printStackTrace();
936
                                }
937

    
938
                        }
939
                        if (lyr instanceof FLayers){
940
                                FLayers lyrs=(FLayers)lyr;
941
                                for(int i=0;i<lyrs.getLayersCount();i++){
942
                                        selectionListener(lyrs.getLayer(i));
943
                                }
944
                        }
945

    
946
                }
947
                /**
948
                 * @see com.iver.cit.gvsig.fmap.layers.LayerCollectionListener#layerMoved(com.iver.cit.gvsig.fmap.layers.LayerPositionEvent)
949
                 */
950
                public void layerMoved(LayerPositionEvent e) {
951
                }
952

    
953
                /**
954
                 * @see com.iver.cit.gvsig.fmap.layers.LayerCollectionListener#layerRemoved(com.iver.cit.gvsig.fmap.layers.LayerCollectionEvent)
955
                 */
956
                public void layerRemoved(LayerCollectionEvent e) {
957
                        FLayer lyr = e.getAffectedLayer();
958

    
959
                        lyr.removeLayerListener(eventBuffer);
960

    
961
                        if (lyr instanceof Classifiable) {
962
                                Classifiable c = (Classifiable) lyr;
963
                                c.removeLegendListener(eventBuffer);
964
                        }
965

    
966
                        if (lyr instanceof Selectable) {
967
                                Selectable s = (Selectable) lyr;
968
                                s.addSelectionListener(eventBuffer);
969
                        }
970
                }
971

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

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

    
986
                /**
987
                 * @see com.iver.cit.gvsig.fmap.layers.LayerCollectionListener#layerRemoving(com.iver.cit.gvsig.fmap.layers.LayerCollectionEvent)
988
                 */
989
                public void layerRemoving(LayerCollectionEvent e)
990
                                throws CancelationException {
991
                }
992

    
993

    
994
                /**
995
                 * @see com.iver.cit.gvsig.fmap.layers.LayerCollectionListener#visibilityChanged(com.iver.cit.gvsig.fmap.layers.LayerCollectionEvent)
996
                 */
997
                public void visibilityChanged(LayerCollectionEvent e)
998
                                throws CancelationException {
999
                }
1000
        }
1001

    
1002
        public void addAsCollectionListener(FLayers layers2) {
1003
                layers2.addLayerCollectionListener(layerEventListener);
1004
        }
1005

    
1006
        public GraphicLayer getGraphicsLayer() {
1007
                return tracLayer;
1008
        }
1009

    
1010
        /**
1011
         * Asigna la capa gr?fica
1012
         * @param graphicLayer
1013
         */
1014
        public void setGraphicsLayer(GraphicLayer graphicLayer) {
1015
                tracLayer = graphicLayer;
1016
        }
1017

    
1018
        public boolean equals(Object arg0) {
1019
                MapContext map = (MapContext) arg0;
1020
                if (super.equals(arg0))
1021
                        return true;
1022
                if (getLayers() == map.getLayers())
1023
                        return true;
1024
                boolean isEqual = true;
1025
                if (map.getLayers().getLayersCount() == getLayers().getLayersCount()) {
1026
                        for (int i = 0; i < getLayers().getLayersCount(); i++) {
1027

    
1028
                                if (!getLayers().getLayer(i).getName().equals(
1029
                                                map.getLayers().getLayer(i).getName())) {
1030
                                        isEqual = false;
1031
                                }
1032

    
1033
                        }
1034
                } else {
1035
                        isEqual = false;
1036
                }
1037
                return isEqual;
1038
        }
1039

    
1040
        public void addLayerError(String stringProperty) {
1041
                layersError.add(stringProperty);
1042
        }
1043

    
1044
        public ArrayList getLayersError() {
1045
                return layersError;
1046
        }
1047

    
1048
        public void clearErrors() {
1049
                layersError.clear();
1050
        }
1051

    
1052
        public void clearAllCachingImageDrawnLayers() {
1053
                clearCachingImageDrawnLayers(this.layers);
1054
        }
1055

    
1056
        private void clearCachingImageDrawnLayers(FLayers layers){
1057
                int i;
1058
                FLayer layer;
1059
                for (i=0;i< layers.getLayersCount();i++){
1060
                        layer = layers.getLayer(i);
1061
                        if (layer instanceof FLayers) {
1062
                                clearCachingImageDrawnLayers((FLayers)layer);
1063
                        } else {
1064
                                layer.setCacheImageDrawnLayers(null);
1065
                        }
1066
                }
1067
        }
1068

    
1069
        public void redraw() {
1070
                // truco
1071
                if (getLayers().getLayersCount() > 0)
1072
                        getLayers().moveTo(0,0);
1073

    
1074
        }
1075

    
1076
}