Statistics
| Revision:

svn-gvsig-desktop / trunk / libraries / libFMap / src / com / iver / cit / gvsig / fmap / MapContext.java @ 12773

History | View | Annotate | Download (30.2 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.core.v02.FSymbol;
67
import com.iver.cit.gvsig.fmap.layers.CancelationException;
68
import com.iver.cit.gvsig.fmap.layers.FLayer;
69
import com.iver.cit.gvsig.fmap.layers.FLayers;
70
import com.iver.cit.gvsig.fmap.layers.GraphicLayer;
71
import com.iver.cit.gvsig.fmap.layers.LayerCollectionEvent;
72
import com.iver.cit.gvsig.fmap.layers.LayerCollectionListener;
73
import com.iver.cit.gvsig.fmap.layers.LayerDrawEvent;
74
import com.iver.cit.gvsig.fmap.layers.LayerDrawingListener;
75
import com.iver.cit.gvsig.fmap.layers.LayerPositionEvent;
76
import com.iver.cit.gvsig.fmap.layers.LegendListener;
77
import com.iver.cit.gvsig.fmap.layers.VectorialAdapter;
78
import com.iver.cit.gvsig.fmap.layers.XMLException;
79
import com.iver.cit.gvsig.fmap.layers.layerOperations.AlphanumericData;
80
import com.iver.cit.gvsig.fmap.layers.layerOperations.Classifiable;
81
import com.iver.cit.gvsig.fmap.layers.layerOperations.Selectable;
82
import com.iver.cit.gvsig.fmap.operations.selection.Record;
83
import com.iver.cit.gvsig.fmap.operations.strategies.FeatureVisitor;
84
import com.iver.cit.gvsig.fmap.operations.strategies.SelectedZoomVisitor;
85
import com.iver.utiles.XMLEntity;
86
import com.iver.utiles.swing.threads.Cancellable;
87

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

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

    
102
        public static final int EQUALS = 0;
103

    
104
        public static final int DISJOINT = 1;
105

    
106
        public static final int INTERSECTS = 2;
107

    
108
        public static final int TOUCHES = 3;
109

    
110
        public static final int CROSSES = 4;
111

    
112
        public static final int WITHIN = 5;
113

    
114
        public static final int CONTAINS = 6;
115

    
116
        public static final int OVERLAPS = 7;
117

    
118
        protected FLayers layers;
119

    
120
        private GraphicLayer tracLayer = new GraphicLayer();
121

    
122
        private ViewPort viewPort;
123

    
124
        // private ArrayList invalidationListeners = new ArrayList();
125
        private ArrayList legendListeners = new ArrayList();
126

    
127
        private ArrayList layerDrawingListeners = new ArrayList();
128

    
129
        private EventBuffer eventBuffer = new EventBuffer();
130

    
131
        private LayerEventListener layerEventListener = null;
132

    
133
        private ArrayList layersError = new ArrayList();
134

    
135
        private ArrayList errorListeners = new ArrayList();
136

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

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

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

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

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

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

    
189
                setViewPort(vp);
190

    
191
        }
192

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

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

    
200
                setViewPort(vp);
201
        }
202

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

    
216

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
371
                return ret;
372
        }
373

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

    
399
//                return createFromXML(getXMLEntity());
400

    
401
        }
402
        public MapContext cloneToDraw() {
403
                ViewPort vp = getViewPort().cloneViewPort();
404
                MapContext mapContext=new MapContext(getLayers(),vp);
405
                return mapContext;
406
        }
407

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

    
418
        /*
419
         * public void addLayer(LayerPath parent, FLayer layer) throws
420
         * ProjectionMismatchException, ChildrenNotAllowedException {
421
         * layers.addLayer(parent, layer); } public void removeLayer(LayerPath
422
         * parent)throws ChildrenNotAllowedException{ layers.removeLayer(parent); }
423
         */
424

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

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

    
444
                if (viewPort.getImageSize() == null)
445
                        return -1;
446

    
447
                if (viewPort.getAdjustedExtent() == null) {
448
                        return 0;
449
                }
450

    
451
                if (proj == null) {
452
                        double w = ((viewPort.getImageSize().getWidth() / dpi) * 2.54);
453
                        return (long) (viewPort.getAdjustedExtent().getWidth() / w * CHANGEM[getViewPort()
454
                                        .getMapUnits()]/CHANGEM[getViewPort().getDistanceUnits()]);
455
                }
456

    
457
                return Math.round(proj.getScale((viewPort.getAdjustedExtent().getMinX()*CHANGEM[getViewPort().getMapUnits()])/CHANGEM[getViewPort().getDistanceUnits()],
458
                                (viewPort.getAdjustedExtent().getMaxX()*CHANGEM[getViewPort().getMapUnits()])/CHANGEM[getViewPort().getDistanceUnits()], viewPort.getImageSize()
459
                                                .getWidth(), dpi));
460

    
461
        }
462

    
463

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

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

    
499
        /**
500
         * @see com.iver.cit.gvsig.fmap.operations.strategies.Strategy#process(com.iver.cit.gvsig.fmap.FeatureSelectorVisitor)
501
         */
502
        public void process(FeatureVisitor visitor) {
503
        }
504

    
505
        /**
506
         * @see com.iver.cit.gvsig.fmap.operations.strategies.Strategy#processSelected(com.iver.cit.gvsig.fmap.FeatureVisitor)
507
         */
508
        public void processSelected(FeatureVisitor visitor) {
509
        }
510

    
511
        /**
512
         * @see com.iver.cit.gvsig.fmap.operations.strategies.Strategy#select(com.iver.cit.gvsig.fmap.FeatureSelectorVisitor,
513
         *      VectorialSubSet)
514
         */
515
        public void select(FeatureVisitor visitor) {
516
        }
517

    
518
        /**
519
         * @see com.iver.cit.gvsig.fmap.operations.strategies.Strategy#selectFromSelection()
520
         */
521
        public void selectFromSelection() {
522
        }
523

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

    
530
        /**
531
         * @see org.cresques.geo.Projected#getProjection()
532
         */
533
        public IProjection getProjection() {
534
                return getViewPort().getProjection();
535
        }
536

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

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

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

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

    
585
        /**
586
         * @see com.iver.cit.gvsig.fmap.operations.strategies.Strategy#selectByShape(com.iver.cit.gvsig.fmap.fshape.IGeometry,
587
         *      int)
588
         */
589
        public void selectByShape(IGeometry g, int relationship) {
590
        }
591

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

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

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

    
615
        /**
616
         * @see com.iver.cit.gvsig.fmap.operations.strategies.Strategy#getSelectionBounds()
617
         */
618
        public Rectangle2D getSelectionBounds() {
619
                SelectedZoomVisitor visitor = new SelectedZoomVisitor();
620

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

    
633
                return visitor.getSelectBound();
634
        }
635

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

    
652
                prepareDrawing(image, g, scale);
653

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

    
664
                long t1 = System.currentTimeMillis();
665
                layers.draw(image, g, viewPort, cancel, scale);
666

    
667
                LayerDrawEvent beforeTracLayerEvent = new LayerDrawEvent(tracLayer,
668
                                g, viewPort, LayerDrawEvent.GRAPHICLAYER_BEFORE_DRAW);
669
                fireLayerDrawingEvent(beforeTracLayerEvent);
670
                tracLayer.draw(image, g, viewPort, cancel, scale);
671
                LayerDrawEvent afterTracLayerEvent = new LayerDrawEvent(tracLayer,
672
                                g, viewPort, LayerDrawEvent.GRAPHICLAYER_AFTER_DRAW);
673
                fireLayerDrawingEvent(afterTracLayerEvent);
674

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

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

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

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

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

    
753
                        if (lyr instanceof FLayers)
754
                        {
755
                                recursivePrepareDrawing((FLayers)lyr, 0);
756
                        }
757
                }
758

    
759
        }
760

    
761
        public void drawGraphics(BufferedImage image, Graphics2D g,
762
                        Cancellable cancel, double scale) throws ReadDriverException {
763
                if (viewPort == null)
764
                        return;
765
                tracLayer.draw(image, g, viewPort, cancel, scale);
766
        }
767

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

    
783
                        public void setCanceled(boolean canceled) {
784
                                // TODO Auto-generated method stub
785

    
786
                        }
787
                }, scale);
788
        }
789

    
790
        /**
791
         * Devuelve el ViewPort.
792
         *
793
         * @return Returns the viewPort.
794
         */
795
        public ViewPort getViewPort() {
796
                return viewPort;
797
        }
798

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

    
810
                this.viewPort = viewPort;
811
                if (viewPort != null)
812
                        viewPort.addViewPortListener(eventBuffer);
813
        }
814

    
815
        /**
816
         * Sets the given zoom extent to the viewport.
817
         *
818
         * @param extent
819
         *            The extent to zoom to.
820
         */
821
        public void zoomToExtent(Rectangle2D extent) {
822
            getViewPort().setExtent(extent);
823
        }
824

    
825
        /**
826
         * M�todo de conveniencia. Recorre las capas y te da el fullExtent
827
         *
828
         * @return fullExtent de todas las capas.
829
         *
830
         * @throws DriverException
831
         */
832
        public Rectangle2D getFullExtent() throws ReadDriverException {
833
                return layers.getFullExtent();
834
        }
835

    
836
        /**
837
         * Devuelve el XMLEntity.
838
         *
839
         * @return XMLEntity.
840
         * @throws XMLException
841
         */
842
        public XMLEntity getXMLEntity() throws XMLException {
843
                XMLEntity xml = new XMLEntity();
844
                xml.putProperty("className", this.getClass().getName());
845
                xml.addChild(viewPort.getXMLEntity());
846
                xml.addChild(layers.getXMLEntity());
847

    
848
                return xml;
849
        }
850

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

    
866
                return fmap;
867
        }
868

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

    
887
        /**
888
         * A�ade un AtomicEventListener.
889
         *
890
         * @param listener
891
         *            AtomicEventListener.
892
         *
893
         * @return True si se ha a�adido correctamente.
894
         */
895
        public boolean addAtomicEventListener(AtomicEventListener listener) {
896
                return eventBuffer.addAtomicEventListener(listener);
897
        }
898

    
899
        /**
900
         * Borra un AtomicEventListener de la lista de listeners.
901
         *
902
         * @param listener
903
         *            AtomicEventListener a borrar.
904
         *
905
         * @return True si se ha borrado correctamente.
906
         */
907
        public boolean removeAtomicEventListener(AtomicEventListener listener) {
908
                return eventBuffer.removeAtomicEventListener(listener);
909
        }
910

    
911
        /**
912
         * Inicializa los AtomicEvent.
913
         */
914
        public void beginAtomicEvent() {
915
                eventBuffer.beginAtomicEvent();
916
        }
917

    
918
        /**
919
         * Finaliza los AtomicEvent.
920
         */
921
        public void endAtomicEvent() {
922
                eventBuffer.endAtomicEvent();
923
        }
924

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

    
949
                        // Registramos al FMap como listener del legend de las capas
950
                        FLayer lyr = e.getAffectedLayer();
951
                        selectionListener(lyr);
952
                }
953
                private void selectionListener(FLayer lyr){
954
                        lyr.addLayerListener(eventBuffer);
955

    
956
                        if (lyr instanceof Classifiable) {
957
                                Classifiable c = (Classifiable) lyr;
958
                                c.addLegendListener(eventBuffer);
959
                        }
960

    
961
                        if (lyr instanceof AlphanumericData) {
962
                                Selectable s=null;
963
                                try {
964
                                        s = ((AlphanumericData) lyr).getRecordset();
965
                                        if (s!=null) {
966
                                                s.addSelectionListener(eventBuffer);
967
                                        }
968
                                } catch (ReadDriverException e1) {
969
                                        e1.printStackTrace();
970
                                }
971

    
972
                        }
973
                        if (lyr instanceof FLayers){
974
                                FLayers lyrs=(FLayers)lyr;
975
                                for(int i=0;i<lyrs.getLayersCount();i++){
976
                                        selectionListener(lyrs.getLayer(i));
977
                                }
978
                        }
979

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

    
987
                /**
988
                 * @see com.iver.cit.gvsig.fmap.layers.LayerCollectionListener#layerRemoved(com.iver.cit.gvsig.fmap.layers.LayerCollectionEvent)
989
                 */
990
                public void layerRemoved(LayerCollectionEvent e) {
991
                        FLayer lyr = e.getAffectedLayer();
992

    
993
                        lyr.removeLayerListener(eventBuffer);
994

    
995
                        if (lyr instanceof Classifiable) {
996
                                Classifiable c = (Classifiable) lyr;
997
                                c.removeLegendListener(eventBuffer);
998
                        }
999

    
1000
                        if (lyr instanceof Selectable) {
1001
                                Selectable s = (Selectable) lyr;
1002
                                s.addSelectionListener(eventBuffer);
1003
                        }
1004
                }
1005

    
1006
                /**
1007
                 * @see com.iver.cit.gvsig.fmap.layers.LayerCollectionListener#layerAdding(com.iver.cit.gvsig.fmap.layers.LayerCollectionEvent)
1008
                 */
1009
                public void layerAdding(LayerCollectionEvent e)
1010
                                throws CancelationException {
1011
                }
1012

    
1013
                /**
1014
                 * @see com.iver.cit.gvsig.fmap.layers.LayerCollectionListener#layerMoving(com.iver.cit.gvsig.fmap.layers.LayerPositionEvent)
1015
                 */
1016
                public void layerMoving(LayerPositionEvent e)
1017
                                throws CancelationException {
1018
                }
1019

    
1020
                /**
1021
                 * @see com.iver.cit.gvsig.fmap.layers.LayerCollectionListener#layerRemoving(com.iver.cit.gvsig.fmap.layers.LayerCollectionEvent)
1022
                 */
1023
                public void layerRemoving(LayerCollectionEvent e)
1024
                                throws CancelationException {
1025
                }
1026

    
1027

    
1028
                /**
1029
                 * @see com.iver.cit.gvsig.fmap.layers.LayerCollectionListener#visibilityChanged(com.iver.cit.gvsig.fmap.layers.LayerCollectionEvent)
1030
                 */
1031
                public void visibilityChanged(LayerCollectionEvent e)
1032
                                throws CancelationException {
1033
                }
1034
        }
1035

    
1036
        public void addAsCollectionListener(FLayers layers2) {
1037
                layers2.addLayerCollectionListener(layerEventListener);
1038
        }
1039

    
1040
        public GraphicLayer getGraphicsLayer() {
1041
                return tracLayer;
1042
        }
1043

    
1044
        /**
1045
         * Asigna la capa gr�fica
1046
         * @param graphicLayer
1047
         */
1048
        public void setGraphicsLayer(GraphicLayer graphicLayer) {
1049
                tracLayer = graphicLayer;
1050
        }
1051

    
1052
        public boolean equals(Object arg0) {
1053
                MapContext map = (MapContext) arg0;
1054
                if (super.equals(arg0))
1055
                        return true;
1056
                if (getLayers() == map.getLayers())
1057
                        return true;
1058
                boolean isEqual = true;
1059
                if (map.getLayers().getLayersCount() == getLayers().getLayersCount()) {
1060
                        for (int i = 0; i < getLayers().getLayersCount(); i++) {
1061

    
1062
                                if (!getLayers().getLayer(i).getName().equals(
1063
                                                map.getLayers().getLayer(i).getName())) {
1064
                                        isEqual = false;
1065
                                }
1066

    
1067
                        }
1068
                } else {
1069
                        isEqual = false;
1070
                }
1071
                return isEqual;
1072
        }
1073

    
1074
        public void addLayerError(String stringProperty) {
1075
                layersError.add(stringProperty);
1076
        }
1077

    
1078
        public ArrayList getLayersError() {
1079
                return layersError;
1080
        }
1081

    
1082
        public void clearErrors() {
1083
                layersError.clear();
1084
        }
1085

    
1086
        public void clearAllCachingImageDrawnLayers() {
1087
                clearCachingImageDrawnLayers(this.layers);
1088
        }
1089

    
1090
        private void clearCachingImageDrawnLayers(FLayers layers){
1091
                int i;
1092
                FLayer layer;
1093
                for (i=0;i< layers.getLayersCount();i++){
1094
                        layer = layers.getLayer(i);
1095
                        if (layer instanceof FLayers) {
1096
                                clearCachingImageDrawnLayers((FLayers)layer);
1097
                        } else {
1098
                                layer.setCacheImageDrawnLayers(null);
1099
                        }
1100
                }
1101
        }
1102

    
1103

    
1104

    
1105
        public FLayers getNewGroupLayer(FLayers parent) {
1106
            return new FLayers(this, parent);
1107
        }
1108
}