Statistics
| Revision:

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

History | View | Annotate | Download (30.3 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.Color;
44
import java.awt.Graphics2D;
45
import java.awt.RenderingHints;
46
import java.awt.Toolkit;
47
import java.awt.geom.Point2D;
48
import java.awt.geom.Rectangle2D;
49
import java.awt.image.BufferedImage;
50
import java.util.ArrayList;
51
import java.util.List;
52
import java.util.prefs.Preferences;
53

    
54
import javax.print.attribute.PrintRequestAttributeSet;
55

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

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

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

    
97
        /* Do not alter the order and the values of this array, if you need append values.*/
98
        public static final double[] CHANGE = { 100000, 100, 1, 0.1, 160934.4,
99
                        91.44, 30.48, 2.54, 1/8.983152841195214E-4 };
100
        
101
        /* Do not alter the order and the values of this array, if you need append values.*/
102
        public static final String[] NAMES= {
103
                Messages.getString("Kilometros"),
104
                Messages.getString("Metros"),
105
                Messages.getString("Centimetros"),
106
                Messages.getString("Milimetros"),
107
                Messages.getString("Millas"),
108
                Messages.getString("Yardas"),
109
                Messages.getString("Pies"),
110
                Messages.getString("Pulgadas"),
111
                Messages.getString("Grados"),
112
        };
113
        
114
        public static final int EQUALS = 0;
115

    
116
        public static final int DISJOINT = 1;
117

    
118
        public static final int INTERSECTS = 2;
119

    
120
        public static final int TOUCHES = 3;
121

    
122
        public static final int CROSSES = 4;
123

    
124
        public static final int WITHIN = 5;
125

    
126
        public static final int CONTAINS = 6;
127

    
128
        public static final int OVERLAPS = 7;
129

    
130
        protected FLayers layers;
131

    
132
        private GraphicLayer tracLayer = new GraphicLayer();
133

    
134
        private ViewPort viewPort;
135

    
136
        // private ArrayList invalidationListeners = new ArrayList();
137
        private ArrayList legendListeners = new ArrayList();
138

    
139
        private ArrayList layerDrawingListeners = new ArrayList();
140

    
141
        private EventBuffer eventBuffer = new EventBuffer();
142

    
143
        private LayerEventListener layerEventListener = null;
144

    
145
        private ArrayList layersError = new ArrayList();
146

    
147
        private ArrayList errorListeners = new ArrayList();
148

    
149
        
150

    
151
        // public static ResourceBundle myResourceBundle =
152
        // ResourceBundle.getBundle("FMap");
153
        public static double ZOOMINFACTOR=2;
154
        public static double ZOOMOUTFACTOR=0.5;
155

    
156
        private static Color selectionColor = Color.YELLOW;
157
        
158
        
159
        /**
160
         * Devuelve el color que se aplica a los shapes seleccionados.
161
         *
162
         * @return DOCUMENT ME!
163
         */
164
        public static Color getSelectionColor() {
165
                return selectionColor;
166
        }
167

    
168
        /**
169
         * Introduce el color que se aplica a los shapes seleccionados.
170
         *
171
         * @param selectionColor DOCUMENT ME!
172
         */
173
        public static void setSelectionColor(Color selectionColor) {
174
                MapContext.selectionColor = selectionColor;
175
        }
176

    
177
        /**
178
         * Crea un nuevo FMap.
179
         *
180
         * @param vp
181
         *            ViewPort.
182
         */
183
        public MapContext(ViewPort vp) {
184
                this.layers = new FLayers(this, null);
185

    
186
                layerEventListener = new LayerEventListener();
187
                layers.addLayerCollectionListener(layerEventListener);
188
                layers.addLayerCollectionListener(eventBuffer);
189

    
190
                setViewPort(vp);
191

    
192
        }
193

    
194
        public MapContext(FLayers fLayers, ViewPort vp) {
195
                this.layers = fLayers;
196

    
197
                layerEventListener = new LayerEventListener();
198
                layers.addLayerCollectionListener(layerEventListener);
199
                layers.addLayerCollectionListener(eventBuffer);
200

    
201
                setViewPort(vp);
202
        }
203

    
204
        /**
205
         * Reports to all registered driver listener a group of driverexceptions
206
         * produced in the same fmap atomic transaction
207
         * @param driverExceptions
208
         */
209
        public synchronized void reportDriverExceptions(String introductoryText,
210
                                                                                                        List driverExceptions){
211
                for (int i = 0; i < errorListeners.size(); i++) {
212
                        ((ErrorListener) errorListeners.get(i)).
213
                                reportDriverExceptions(introductoryText, driverExceptions);
214
                }
215
        }
216

    
217

    
218
        /**
219
         * A�ade un LegendListener.
220
         *
221
         * @param listener
222
         *            LegendListener a a�adir.
223
         */
224
        public void addLayerListener(LegendListener listener) {
225
                if (!legendListeners.contains(listener))
226
                        legendListeners.add(listener);
227
        }
228

    
229
        public void addLayerDrawingListener(LayerDrawingListener listener) {
230
                layerDrawingListeners.add(listener);
231
        }
232

    
233
        public void removeLayerDrawListener(LayerDrawingListener listener) {
234
                layerDrawingListeners.remove(listener);
235
        }
236

    
237
        public void addErrorListener(ErrorListener listener) {
238
                errorListeners.add(listener);
239
        }
240

    
241
        public void removeErrorListener(LegendListener listener) {
242
                legendListeners.remove(listener);
243
        }
244

    
245
        /**
246
         * M�todo ejecutado cuando hay un cambio de leyenda que se quiera reflejar.
247
         *
248
         * @param e
249
         *            LegendChangedEvent.
250
         */
251
        public synchronized void callLegendChanged() {
252
                for (int i = 0; i < legendListeners.size(); i++) {
253
                        ((LegendListener) legendListeners.get(i)).legendChanged(null);
254
                }
255
                // getLayers().moveTo(0,0);
256
        }
257

    
258
        public synchronized void fireLayerDrawingEvent(LayerDrawEvent e) {
259
                for (int i = 0; i < layerDrawingListeners.size(); i++)
260
                {
261
                        LayerDrawingListener listener = (LayerDrawingListener) layerDrawingListeners.get(i);
262
                        switch (e.getEventType())
263
                        {
264
                                case LayerDrawEvent.LAYER_BEFORE_DRAW:
265
                                        listener.beforeLayerDraw(e);
266
                                        break;
267
                                case LayerDrawEvent.LAYER_AFTER_DRAW:
268
                                        listener.afterLayerDraw(e);
269
                                        break;
270
                                case LayerDrawEvent.GRAPHICLAYER_BEFORE_DRAW:
271
                                        listener.beforeGraphicLayerDraw(e);
272
                                        break;
273
                                case LayerDrawEvent.GRAPHICLAYER_AFTER_DRAW:
274
                                        listener.afterLayerGraphicDraw(e);
275
                                        break;
276
                        }
277
                }
278
                // getLayers().moveTo(0,0);
279
        }
280

    
281
        public synchronized void callNewErrorEvent(ErrorEvent e) {
282
                for (int i = 0; i < errorListeners.size(); i++) {
283
                        ((ErrorListener) errorListeners.get(i)).errorThrown(e);
284
                }
285
                // getLayers().moveTo(0,0);
286
        }
287

    
288
        /**
289
         * Borra un LegendListener.
290
         *
291
         * @param listener
292
         *            LegendListener a borrar.
293
         */
294
        public void removeLayerListener(LegendListener listener) {
295
                legendListeners.remove(listener);
296
        }
297

    
298
        /**
299
         * Devuelve las capas que contiene el mapa.
300
         *
301
         * @return Capas.
302
         */
303
        public FLayers getLayers() {
304
                return layers;
305
        }
306

    
307
        /**
308
         * Dibuja en la imagen que se pasa como par�metro el contenido de las capas
309
         * visibles del mapa y teniendo en cuenta los datos del ViewPort contenido
310
         * en este FMap
311
         *
312
         * @param b
313
         *            Imagen.
314
         */
315
        public void drawLabels(BufferedImage b) {
316
        }
317

    
318
        /**
319
         * M�todo de conveniencia que se usa provisionalmente para solicitar un
320
         * refresco de todo lo que dependa del FMap (MapContext). Esto provocar� un
321
         * evento de cambio de orden de capas que obligar� a redibujar todo lo que
322
         * depende de FMap (TOC, MapControl, FFrameView, etc).
323
         */
324
        public void invalidate() {
325
                if (getLayers().getLayersCount() > 0)
326
                        getLayers().moveTo(0, 0);
327
        }
328

    
329
        /**
330
         * Imprime el las capas que contiene el FMap sobre el Graphics2D que se pasa
331
         * como par�metro, normalmente es el Graphics de la impresora.
332
         *
333
         * @param g
334
         *            Graphics2D
335
         * @throws ReadDriverException TODO
336
         */
337
        public void print(Graphics2D g, double scale, PrintRequestAttributeSet properties) throws ReadDriverException {
338
                RenderingHints renderHints = new RenderingHints(
339
                                RenderingHints.KEY_ANTIALIASING,
340
                                RenderingHints.VALUE_ANTIALIAS_ON);
341
                renderHints.put(RenderingHints.KEY_RENDERING,
342
                                RenderingHints.VALUE_RENDER_QUALITY);
343
                g.setRenderingHints(renderHints);
344

    
345
                Cancellable cancel = new Cancellable() {
346
                        public boolean isCanceled() {
347
                                return false;
348
                        }
349

    
350
                        public void setCanceled(boolean canceled) {
351
                                // No queremos que se pueda cancelar la impresi�n.
352

    
353
                        }
354
                };
355
                layers.print(g, viewPort, cancel, scale, properties);
356
                tracLayer.draw(null, g, viewPort, cancel, scale);
357
        }
358

    
359
        /**
360
         * Crea un nuevo FMap con la informaci�n del ViewPort que se pasa como
361
         * par�metro.
362
         *
363
         * @param vp
364
         *            ViewPort.
365
         *
366
         * @return FMap nuevo.
367
         */
368
        public MapContext createNewFMap(ViewPort vp) {
369
                MapContext ret = new MapContext(vp);
370
                ret.layers = this.layers;
371

    
372
                return ret;
373
        }
374

    
375
        /**
376
         * Crea un nuevo FMap totalmente desligado, se replican las capas y el
377
         * ViewPort
378
         *
379
         * @return FMap clonado.
380
         *
381
         * @throws XMLException
382
         */
383
        public MapContext cloneFMap() throws XMLException {
384
                ViewPort vp = getViewPort().cloneViewPort();
385
                FLayers antLayers = getLayers();
386
                MapContext ret = new MapContext(vp);
387
                FLayers aux = new FLayers(ret, null);
388
                for (int i=0; i < antLayers.getLayersCount(); i++)
389
                {
390
                        FLayer lyr = antLayers.getLayer(i);
391
                        try {
392
                                aux.addLayer(lyr.cloneLayer());
393
                        } catch (Exception e) {
394
                        
395
                                // TODO Auto-generated catch block
396
                                e.printStackTrace();
397
                                throw new XMLException(e);
398
                        }
399
                }
400
                ret.layers = aux;
401
                return ret;
402

    
403
//                return createFromXML(getXMLEntity());
404

    
405
        }
406
        public MapContext cloneToDraw() {
407
                ViewPort vp = getViewPort().cloneViewPort();
408
                MapContext mapContext=new MapContext(getLayers(),vp);
409
                return mapContext;
410
        }
411

    
412
        /**
413
         * A�ade la capa que se pasa como par�metro al nodo que se pasa como
414
         * parametro y lanza ProjectionMismatchException si no est�n todas las capas
415
         * de este FMap en la misma proyecci�n. Lanza un ChildNotAllowedException si
416
         * la capa no es un FLayers y no permite hijos
417
         *
418
         * @param vectorial
419
         *            DOCUMENT ME!
420
         */
421

    
422
        /*
423
         * public void addLayer(LayerPath parent, FLayer layer) throws
424
         * ProjectionMismatchException, ChildrenNotAllowedException {
425
         * layers.addLayer(parent, layer); } public void removeLayer(LayerPath
426
         * parent)throws ChildrenNotAllowedException{ layers.removeLayer(parent); }
427
         */
428

    
429
        /**
430
         * A�ade una capa al grupo de capas que se sit�a por encima de todas las
431
         * otras capas
432
         *
433
         * @param vectorial
434
         *            FLayer.
435
         */
436
        public void addToTrackLayer(FLayer vectorial) {
437
        }
438

    
439
        /**
440
         * Devuelve la escala de la vista en pantalla.
441
         *
442
         * @return escala de la vista.
443
         */
444
        public long getScaleView() {
445
                double dpi = getScreenDPI();
446
                IProjection proj = viewPort.getProjection();
447

    
448
                if (viewPort.getImageSize() == null)
449
                        return -1;
450

    
451
                if (viewPort.getAdjustedExtent() == null) {
452
                        return 0;
453
                }
454

    
455
                if (proj == null) {
456
                        double w = ((viewPort.getImageSize().getWidth() / dpi) * 2.54);
457
                        return (long) (viewPort.getAdjustedExtent().getWidth() / w * CHANGEM[getViewPort()
458
                                        .getMapUnits()]/CHANGEM[getViewPort().getDistanceUnits()]);
459
                }
460

    
461
                return Math.round(proj.getScale((viewPort.getAdjustedExtent().getMinX()*CHANGEM[getViewPort().getMapUnits()])/CHANGEM[getViewPort().getDistanceUnits()],
462
                                (viewPort.getAdjustedExtent().getMaxX()*CHANGEM[getViewPort().getMapUnits()])/CHANGEM[getViewPort().getDistanceUnits()], viewPort.getImageSize()
463
                                                .getWidth(), dpi));
464

    
465
        }
466

    
467

    
468
        /**
469
         * Introduce un nuevo extent en la vista a partir de la escala que se pasa como par�metro.
470
         *
471
         * @return escala de la vista.
472
         */
473
        public void setScaleView(long scale) {
474
                clearAllCachingImageDrawnLayers();
475
                double dpi = getScreenDPI();
476
                if (viewPort.getImageSize() == null)
477
                        return;
478
                IProjection proj = viewPort.getProjection();
479
                if (viewPort.getAdjustedExtent() == null) {
480
                        return;
481
                }
482
                Rectangle2D rec=proj.getExtent(viewPort.getAdjustedExtent(),scale,viewPort.getImageWidth(),viewPort.getImageHeight(),CHANGE[getViewPort().getMapUnits()],CHANGEM[getViewPort().getDistanceUnits()],dpi);
483
                getViewPort().setExtent(rec);
484
        }
485

    
486
        /**
487
         * Returns the screen resolution (Dots Per Inch) as it was defined by the user's preference, or
488
         * by default as it is defined in the default Toolkit.
489
         * @return double with the screen's dpi
490
         */
491
        public static double getScreenDPI() {
492
                Preferences prefsResolution = Preferences.userRoot().node( "gvsig.configuration.screen" );
493
                Toolkit kit = Toolkit.getDefaultToolkit();
494
                double dpi = prefsResolution.getInt("dpi",kit.getScreenResolution());
495
                return dpi;
496
        }
497
        /**
498
         * @see com.iver.cit.gvsig.fmap.operations.strategies.Strategy#setVectorial(com.iver.cit.gvsig.fmap.VectorialAdapter)
499
         */
500
        public void setVectorial(VectorialAdapter v) {
501
        }
502

    
503
        /**
504
         * @see com.iver.cit.gvsig.fmap.operations.strategies.Strategy#process(com.iver.cit.gvsig.fmap.FeatureSelectorVisitor)
505
         */
506
        public void process(FeatureVisitor visitor) {
507
        }
508

    
509
        /**
510
         * @see com.iver.cit.gvsig.fmap.operations.strategies.Strategy#processSelected(com.iver.cit.gvsig.fmap.FeatureVisitor)
511
         */
512
        public void processSelected(FeatureVisitor visitor) {
513
        }
514

    
515
        /**
516
         * @see com.iver.cit.gvsig.fmap.operations.strategies.Strategy#select(com.iver.cit.gvsig.fmap.FeatureSelectorVisitor,
517
         *      VectorialSubSet)
518
         */
519
        public void select(FeatureVisitor visitor) {
520
        }
521

    
522
        /**
523
         * @see com.iver.cit.gvsig.fmap.operations.strategies.Strategy#selectFromSelection()
524
         */
525
        public void selectFromSelection() {
526
        }
527

    
528
        /**
529
         * @see com.iver.cit.gvsig.fmap.operations.strategies.Strategy#createIndex()
530
         */
531
        public void createIndex() {
532
        }
533

    
534
        /**
535
         * @see org.cresques.geo.Projected#getProjection()
536
         */
537
        public IProjection getProjection() {
538
                return getViewPort().getProjection();
539
        }
540

    
541
        /**
542
         * Inserta la proyecci�n.
543
         *
544
         * @param proj
545
         *            Proyecci�n.
546
         */
547
        public void setProjection(IProjection proj) {
548
                if (getViewPort() != null) {
549
                        getViewPort().setProjection(proj);
550
                }
551
        }
552

    
553
        /**
554
         * @see org.cresques.geo.Projected#reProject(org.cresques.cts.ICoordTrans)
555
         */
556
        public void reProject(ICoordTrans arg0) {
557
                // TODO implementar reprojecci�n (lo que sea eso)
558
        }
559

    
560
        /**
561
         * @see com.iver.cit.gvsig.fmap.operations.strategies.Strategy#selectByPoint(java.awt.geom.Point2D,
562
         *      double)
563
         */
564
        /*
565
         * public void selectByPoint(Point2D p, double tolerance) throws
566
         * DriverException { Point2D mapPoint = viewPort.toMapPoint((int) p.getX(),
567
         * (int) p.getY()); SelectByPointVisitor visitor = new
568
         * SelectByPointVisitor(); visitor.setQueriedPoint(mapPoint);
569
         * visitor.setTolerance(getViewPort().toMapDistance(3));
570
         *
571
         * try { layers.process(visitor); } catch (VisitException e) { throw new
572
         * RuntimeException("No se espera que SelectByPointVisitor lance esta
573
         * excepci�n", e); } }
574
         */
575

    
576
        /**
577
         * @see com.iver.cit.gvsig.fmap.operations.strategies.Strategy#selectByRect(java.awt.geom.Rectangle2D)
578
         */
579
        /*
580
         * public void selectByRect(Rectangle2D rect) throws DriverException {
581
         * FLayer[] actives = layers.getActives(); for (int i=0; i < actives.length;
582
         * i++) { if (actives[i] instanceof FLyrVect) { FLyrVect lyrVect =
583
         * (FLyrVect) actives[i]; FBitSet oldBitSet = lyrVect.getSelection();
584
         * FBitSet newBitSet = lyrVect.queryByRect(rect); newBitSet.xor(oldBitSet);
585
         * lyrVect.setSelection(newBitSet); } }
586
         *  }
587
         */
588

    
589
        /**
590
         * @see com.iver.cit.gvsig.fmap.operations.strategies.Strategy#selectByShape(com.iver.cit.gvsig.fmap.fshape.IGeometry,
591
         *      int)
592
         */
593
        public void selectByShape(IGeometry g, int relationship) {
594
        }
595

    
596
        /**
597
         * @see com.iver.cit.gvsig.fmap.operations.strategies.Strategy#queryByPoint(Point2D,
598
         *      double)
599
         */
600
        public Record[] queryByPoint(Point2D p, double tolerance) {
601
                return null;
602
        }
603

    
604
        /**
605
         * @see com.iver.cit.gvsig.fmap.operations.strategies.Strategy#queryByRect(java.awt.geom.Rectangle2D)
606
         */
607
        public Record[] queryByRect(Rectangle2D rect) {
608
                return null;
609
        }
610

    
611
        /**
612
         * @see com.iver.cit.gvsig.fmap.operations.strategies.Strategy#queryByShape(com.iver.cit.gvsig.fmap.fshape.IGeometry,
613
         *      int)
614
         */
615
        public Record[] queryByShape(IGeometry g, int relationship) {
616
                return null;
617
        }
618

    
619
        /**
620
         * @see com.iver.cit.gvsig.fmap.operations.strategies.Strategy#getSelectionBounds()
621
         */
622
        public Rectangle2D getSelectionBounds() {
623
                SelectedZoomVisitor visitor = new SelectedZoomVisitor();
624

    
625
                try {
626
                        layers.process(visitor);
627
                } catch (ReadDriverException e1) {
628
                        throw new RuntimeException(
629
                                        "No se espera que SelectByPointVisitor lance esta excepci�n",
630
                                        e1);
631
                } catch (VisitorException e) {
632
                        throw new RuntimeException(
633
                                        "No se espera que SelectByPointVisitor lance esta excepci�n",
634
                                        e);
635
                }
636

    
637
                return visitor.getSelectBound();
638
        }
639

    
640
        /**
641
         * @see com.iver.cit.gvsig.fmap.operations.LayerOperations#draw(java.awt.image.BufferedImage,
642
         *      ISymbol)
643
         */
644
        public void draw(BufferedImage image, Graphics2D g, Cancellable cancel,
645
                        double scale) throws ReadDriverException {
646
                if (viewPort.getExtent() == null) {
647
                        // System.err.println("viewPort.getExtent() = null");
648
                        return;
649
                }
650
                System.out.println("Viewport despues: " + viewPort.toString());
651
                /*
652
                 * if ((viewPort.getImageWidth() <=0) || (viewPort.getImageHeight() <=
653
                 * 0)) { return; }
654
                 */
655

    
656
                prepareDrawing(image, g, scale);
657

    
658
                // M�s c�lidad al texto
659
                RenderingHints renderHints = new RenderingHints(
660
                                RenderingHints.KEY_ANTIALIASING,
661
                                RenderingHints.VALUE_ANTIALIAS_ON);
662
                renderHints.put(RenderingHints.KEY_RENDERING,
663
                                RenderingHints.VALUE_RENDER_QUALITY);
664
                renderHints.put(RenderingHints.KEY_TEXT_ANTIALIASING,
665
                                RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
666
                g.setRenderingHints(renderHints);
667

    
668
                long t1 = System.currentTimeMillis();
669
                layers.draw(image, g, viewPort, cancel, scale);
670

    
671
                LayerDrawEvent beforeTracLayerEvent = new LayerDrawEvent(tracLayer,
672
                                g, viewPort, LayerDrawEvent.GRAPHICLAYER_BEFORE_DRAW);
673
                fireLayerDrawingEvent(beforeTracLayerEvent);
674
                tracLayer.draw(image, g, viewPort, cancel, scale);
675
                LayerDrawEvent afterTracLayerEvent = new LayerDrawEvent(tracLayer,
676
                                g, viewPort, LayerDrawEvent.GRAPHICLAYER_AFTER_DRAW);
677
                fireLayerDrawingEvent(afterTracLayerEvent);
678

    
679
                //layers.setDirty(false);
680
                long t2 = System.currentTimeMillis();
681
                System.err.println("Tiempo de dibujado:" + (t2 - t1) +
682
                                " mseg. Memoria libre:" + Runtime.getRuntime().freeMemory() / 1024  + " KB");
683
                /*
684
                 * g.setColor(Color.BLUE); GeneralPath shpR = new
685
                 * GeneralPath(viewPort.getExtent());
686
                 * shpR.transform(viewPort.getAffineTransform()); g.draw(shpR);
687
                 */
688
                System.gc();
689
        }
690

    
691
        /**
692
         * En esta funci�n vamos a revisar las capas que necesitan repintarse,
693
         * por si hay alguna que se haya guardado la imagen de las anteriores
694
         * y puede acelerar el dibujado.
695
         * @param image
696
         * @param g
697
         * @param scale
698
         */
699
        private void prepareDrawing(BufferedImage image, Graphics2D g, double scale) {
700

    
701
                // Primera pasada: si alguna capa necesita repintarse por debajo
702
                // de la que tiene la cache, TODAS necesitan
703
                // ser repintadas.
704
                boolean bNeedRepaint = false;
705
                boolean bMayExistAceleration = false;
706
                for (int i = 0; i < layers.getLayersCount(); i++)
707
                {
708
                        FLayer lyr = layers.getLayer(i);
709
                        if (lyr.isCachingDrawnLayers() && (lyr.getCacheImageDrawnLayers() != null))
710
                        {
711
                                bMayExistAceleration = true;
712
                        }
713
                        else
714
                        {
715
                                if (lyr.isDirty())
716
                                        bNeedRepaint = true;
717
                        }
718
                }
719
                if (bMayExistAceleration==false)
720
                        bNeedRepaint = true;
721
                if (bNeedRepaint)
722
                        layers.setDirty(true);
723
                else
724
                        recursivePrepareDrawing(layers, 0);
725
        }
726

    
727
        private void validatePreviousLayers(FLayers layers, int index)
728
        {
729
                // TODO: Aqu� quiz�s habr�a que explorar los padres de las capas
730
                // para marcar y/o asignar la imagen cacheada.
731
                for (int i = 0; i < index; i++)
732
                {
733
                        FLayer lyr = layers.getLayer(i);
734
                        lyr.setDirty(false);
735
                }
736
                // Las de arriba las marcamos como sucias
737
//                for (int i = index; i < layers.getLayersCount(); i++)
738
//                {
739
//                        FLayer lyr = layers.getLayer(i);
740
//                        lyr.setDirty(true);
741
//                }
742
        }
743

    
744
        private void recursivePrepareDrawing(FLayers parent, int indexInParent)
745
        {
746
                for (int i = indexInParent; i < parent.getLayersCount(); i++)
747
                {
748
                        FLayer lyr = layers.getLayer(i);
749
                        if (lyr.isCachingDrawnLayers() && (lyr.getCacheImageDrawnLayers() != null))
750
                        {
751
                                // les decimos a las anteriores que est�n validadas (not dirty)
752
                                // para que no se dibujen.
753
                                if (lyr.isDirty())
754
                                        validatePreviousLayers(parent, i);
755
                        }
756

    
757
                        if (lyr instanceof FLayers)
758
                        {
759
                                recursivePrepareDrawing((FLayers)lyr, 0);
760
                        }
761
                }
762

    
763
        }
764

    
765
        public void drawGraphics(BufferedImage image, Graphics2D g,
766
                        Cancellable cancel, double scale) throws ReadDriverException {
767
                if (viewPort == null)
768
                        return;
769
                tracLayer.draw(image, g, viewPort, cancel, scale);
770
        }
771

    
772
        /**
773
         * @see com.iver.cit.gvsig.fmap.operations.LayerOperations#draw(java.awt.image.BufferedImage,
774
         *      ISymbol)
775
         */
776
        public void draw(BufferedImage image, Graphics2D g, double scale)
777
                        throws ReadDriverException {
778
                layers.setDirty(true);
779
                draw(image, g, new Cancellable() {
780
                        /**
781
                         * @see com.iver.utiles.swing.threads.Cancellable#isCanceled()
782
                         */
783
                        public boolean isCanceled() {
784
                                return false;
785
                        }
786

    
787
                        public void setCanceled(boolean canceled) {
788
                                // TODO Auto-generated method stub
789

    
790
                        }
791
                }, scale);
792
        }
793

    
794
        /**
795
         * Devuelve el ViewPort.
796
         *
797
         * @return Returns the viewPort.
798
         */
799
        public ViewPort getViewPort() {
800
                return viewPort;
801
        }
802

    
803
        /**
804
         * Inserta un ViewPort.
805
         *
806
         * @param viewPort
807
         *            The viewPort to set.
808
         */
809
        public void setViewPort(ViewPort viewPort) {
810
                if (this.viewPort != null) {
811
                        this.viewPort.removeViewPortListener(eventBuffer);
812
                }
813

    
814
                this.viewPort = viewPort;
815
                if (viewPort != null)
816
                        viewPort.addViewPortListener(eventBuffer);
817
        }
818

    
819
        /**
820
         * Sets the given zoom extent to the viewport.
821
         *
822
         * @param extent
823
         *            The extent to zoom to.
824
         */
825
        public void zoomToExtent(Rectangle2D extent) {
826
                if (extent!=null)
827
                        getViewPort().setExtent(extent);
828
        }
829

    
830
        /**
831
         * M�todo de conveniencia. Recorre las capas y te da el fullExtent
832
         *
833
         * @return fullExtent de todas las capas.
834
         *
835
         * @throws DriverException
836
         */
837
        public Rectangle2D getFullExtent() throws ReadDriverException {
838
                return layers.getFullExtent();
839
        }
840

    
841
        /**
842
         * Devuelve el XMLEntity.
843
         *
844
         * @return XMLEntity.
845
         * @throws XMLException
846
         */
847
        public XMLEntity getXMLEntity() throws XMLException {
848
                XMLEntity xml = new XMLEntity();
849
                xml.putProperty("className", this.getClass().getName());
850
                xml.addChild(viewPort.getXMLEntity());
851
                xml.addChild(layers.getXMLEntity());
852

    
853
                return xml;
854
        }
855

    
856
        /**
857
         * Crea un nuevo FMAp a partir del XMLEntity.
858
         *
859
         * @param xml
860
         *            XMLEntity
861
         *
862
         * @return Nuevo FMap.
863
         *
864
         * @throws XMLException
865
         */
866
        public static MapContext createFromXML03(XMLEntity xml) throws XMLException {
867
                ViewPort vp = ViewPort.createFromXML03(xml.getChild(0));
868
                MapContext fmap = new MapContext(vp);
869
                fmap.layers.setXMLEntity03(xml.getChild(1));
870

    
871
                return fmap;
872
        }
873

    
874
        /**
875
         * Crea un nuevo FMAp a partir del XMLEntity.
876
         *
877
         * @param xml
878
         *            XMLEntity
879
         *
880
         * @return Nuevo FMap.
881
         *
882
         * @throws XMLException
883
         */
884
        public static MapContext createFromXML(XMLEntity xml) throws XMLException {
885
                ViewPort vp = ViewPort.createFromXML(xml.getChild(0));
886
                MapContext fmap = new MapContext(vp);
887
                fmap.layers.setXMLEntity(xml.getChild(1));
888
                fmap.layers.setName("root layer");
889
                return fmap;
890
        }
891

    
892
        /**
893
         * A�ade un AtomicEventListener.
894
         *
895
         * @param listener
896
         *            AtomicEventListener.
897
         *
898
         * @return True si se ha a�adido correctamente.
899
         */
900
        public boolean addAtomicEventListener(AtomicEventListener listener) {
901
                return eventBuffer.addAtomicEventListener(listener);
902
        }
903

    
904
        /**
905
         * Borra un AtomicEventListener de la lista de listeners.
906
         *
907
         * @param listener
908
         *            AtomicEventListener a borrar.
909
         *
910
         * @return True si se ha borrado correctamente.
911
         */
912
        public boolean removeAtomicEventListener(AtomicEventListener listener) {
913
                return eventBuffer.removeAtomicEventListener(listener);
914
        }
915

    
916
        /**
917
         * Inicializa los AtomicEvent.
918
         */
919
        public void beginAtomicEvent() {
920
                eventBuffer.beginAtomicEvent();
921
        }
922

    
923
        /**
924
         * Finaliza los AtomicEvent.
925
         */
926
        public void endAtomicEvent() {
927
                eventBuffer.endAtomicEvent();
928
        }
929

    
930
        /**
931
         * Evento Layer.
932
         *
933
         * @author Fernando Gonz�lez Cort�s
934
         */
935
        public class LayerEventListener implements LayerCollectionListener {
936
                /**
937
                 * @see com.iver.cit.gvsig.fmap.layers.LayerCollectionListener#layerAdded(com.iver.cit.gvsig.fmap.layers.LayerCollectionEvent)
938
                 */
939
                public void layerAdded(LayerCollectionEvent e) {
940
                        // Si es la primera capa, fijamos su extent al ViewPort
941
                        // if (getLayers().getLayersCount() == 1) {
942
                        if (getViewPort().getExtent() == null) {
943
                                FLayer lyr = e.getAffectedLayer();
944
                                if (lyr.isAvailable())
945
                                        try {
946
                                                getViewPort().setExtent(lyr.getFullExtent());
947
                                        } catch (ReadDriverException e1) {
948
                                                e1.printStackTrace();
949
                                        } catch (ExpansionFileReadException e1) {
950
                                                e1.printStackTrace();
951
                                        }
952
                        }
953

    
954
                        // Registramos al FMap como listener del legend de las capas
955
                        FLayer lyr = e.getAffectedLayer();
956
                        selectionListener(lyr);
957
                }
958
                private void selectionListener(FLayer lyr){
959
                        lyr.addLayerListener(eventBuffer);
960

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

    
966
                        if (lyr instanceof AlphanumericData) {
967
                                Selectable s=null;
968
                                try {
969
                                        s = ((AlphanumericData) lyr).getRecordset();
970
                                        if (s!=null) {
971
                                                s.addSelectionListener(eventBuffer);
972
                                        }
973
                                } catch (ReadDriverException e1) {
974
                                        e1.printStackTrace();
975
                                }
976

    
977
                        }
978
                        if (lyr instanceof FLayers){
979
                                FLayers lyrs=(FLayers)lyr;
980
                                for(int i=0;i<lyrs.getLayersCount();i++){
981
                                        selectionListener(lyrs.getLayer(i));
982
                                }
983
                        }
984

    
985
                }
986
                /**
987
                 * @see com.iver.cit.gvsig.fmap.layers.LayerCollectionListener#layerMoved(com.iver.cit.gvsig.fmap.layers.LayerPositionEvent)
988
                 */
989
                public void layerMoved(LayerPositionEvent e) {
990
                }
991

    
992
                /**
993
                 * @see com.iver.cit.gvsig.fmap.layers.LayerCollectionListener#layerRemoved(com.iver.cit.gvsig.fmap.layers.LayerCollectionEvent)
994
                 */
995
                public void layerRemoved(LayerCollectionEvent e) {
996
                        FLayer lyr = e.getAffectedLayer();
997

    
998
                        lyr.removeLayerListener(eventBuffer);
999

    
1000
                        if (lyr instanceof Classifiable) {
1001
                                Classifiable c = (Classifiable) lyr;
1002
                                c.removeLegendListener(eventBuffer);
1003
                        }
1004

    
1005
                        if (lyr instanceof Selectable) {
1006
                                Selectable s = (Selectable) lyr;
1007
                                s.addSelectionListener(eventBuffer);
1008
                        }
1009
                }
1010

    
1011
                /**
1012
                 * @see com.iver.cit.gvsig.fmap.layers.LayerCollectionListener#layerAdding(com.iver.cit.gvsig.fmap.layers.LayerCollectionEvent)
1013
                 */
1014
                public void layerAdding(LayerCollectionEvent e)
1015
                                throws CancelationException {
1016
                }
1017

    
1018
                /**
1019
                 * @see com.iver.cit.gvsig.fmap.layers.LayerCollectionListener#layerMoving(com.iver.cit.gvsig.fmap.layers.LayerPositionEvent)
1020
                 */
1021
                public void layerMoving(LayerPositionEvent e)
1022
                                throws CancelationException {
1023
                }
1024

    
1025
                /**
1026
                 * @see com.iver.cit.gvsig.fmap.layers.LayerCollectionListener#layerRemoving(com.iver.cit.gvsig.fmap.layers.LayerCollectionEvent)
1027
                 */
1028
                public void layerRemoving(LayerCollectionEvent e)
1029
                                throws CancelationException {
1030
                }
1031

    
1032

    
1033
                /**
1034
                 * @see com.iver.cit.gvsig.fmap.layers.LayerCollectionListener#visibilityChanged(com.iver.cit.gvsig.fmap.layers.LayerCollectionEvent)
1035
                 */
1036
                public void visibilityChanged(LayerCollectionEvent e)
1037
                                throws CancelationException {
1038
                }
1039
        }
1040

    
1041
        public void addAsCollectionListener(FLayers layers2) {
1042
                layers2.addLayerCollectionListener(layerEventListener);
1043
        }
1044

    
1045
        public GraphicLayer getGraphicsLayer() {
1046
                return tracLayer;
1047
        }
1048

    
1049
        /**
1050
         * Asigna la capa gr�fica
1051
         * @param graphicLayer
1052
         */
1053
        public void setGraphicsLayer(GraphicLayer graphicLayer) {
1054
                tracLayer = graphicLayer;
1055
        }
1056

    
1057
        public boolean equals(Object arg0) {
1058
                MapContext map = (MapContext) arg0;
1059
                if (super.equals(arg0))
1060
                        return true;
1061
                if (getLayers() == map.getLayers())
1062
                        return true;
1063
                boolean isEqual = true;
1064
                if (map.getLayers().getLayersCount() == getLayers().getLayersCount()) {
1065
                        for (int i = 0; i < getLayers().getLayersCount(); i++) {
1066

    
1067
                                if (!getLayers().getLayer(i).getName().equals(
1068
                                                map.getLayers().getLayer(i).getName())) {
1069
                                        isEqual = false;
1070
                                }
1071

    
1072
                        }
1073
                } else {
1074
                        isEqual = false;
1075
                }
1076
                return isEqual;
1077
        }
1078

    
1079
        public void addLayerError(String stringProperty) {
1080
                layersError.add(stringProperty);
1081
        }
1082

    
1083
        public ArrayList getLayersError() {
1084
                return layersError;
1085
        }
1086

    
1087
        public void clearErrors() {
1088
                layersError.clear();
1089
        }
1090

    
1091
        public void clearAllCachingImageDrawnLayers() {
1092
                clearCachingImageDrawnLayers(this.layers);
1093
        }
1094

    
1095
        private void clearCachingImageDrawnLayers(FLayers layers){
1096
                int i;
1097
                FLayer layer;
1098
                for (i=0;i< layers.getLayersCount();i++){
1099
                        layer = layers.getLayer(i);
1100
                        if (layer instanceof FLayers) {
1101
                                clearCachingImageDrawnLayers((FLayers)layer);
1102
                        } else {
1103
                                layer.setCacheImageDrawnLayers(null);
1104
                        }
1105
                }
1106
        }
1107

    
1108

    
1109

    
1110
        public FLayers getNewGroupLayer(FLayers parent) {
1111
            return new FLayers(this, parent);
1112
        }
1113
}