Statistics
| Revision:

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

History | View | Annotate | Download (28.4 KB)

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

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

    
53
import javax.print.attribute.PrintRequestAttributeSet;
54

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

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

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

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

    
97
        public static final int EQUALS = 0;
98

    
99
        public static final int DISJOINT = 1;
100

    
101
        public static final int INTERSECTS = 2;
102

    
103
        public static final int TOUCHES = 3;
104

    
105
        public static final int CROSSES = 4;
106

    
107
        public static final int WITHIN = 5;
108

    
109
        public static final int CONTAINS = 6;
110

    
111
        public static final int OVERLAPS = 7;
112

    
113
        protected FLayers layers;
114

    
115
        private GraphicLayer tracLayer = new GraphicLayer();
116

    
117
        private ViewPort viewPort;
118

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

    
122
        private ArrayList layerDrawingListeners = new ArrayList();
123

    
124
        private EventBuffer eventBuffer = new EventBuffer();
125

    
126
        private LayerEventListener layerEventListener = null;
127

    
128
        private ArrayList layersError = new ArrayList();
129

    
130
        private ArrayList errorListeners = new ArrayList();
131

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

    
145
                layerEventListener = new LayerEventListener();
146
                layers.addLayerCollectionListener(layerEventListener);
147
                layers.addLayerCollectionListener(eventBuffer);
148

    
149
                setViewPort(vp);
150

    
151
        }
152

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

    
156
                layerEventListener = new LayerEventListener();
157
                layers.addLayerCollectionListener(layerEventListener);
158
                layers.addLayerCollectionListener(eventBuffer);
159

    
160
                setViewPort(vp);
161
        }
162

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

    
176

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

    
188
        public void addLayerDrawingListener(LayerDrawingListener listener) {
189
                layerDrawingListeners.add(listener);
190
        }
191

    
192
        public void removeLayerDrawListener(LayerDrawingListener listener) {
193
                layerDrawingListeners.remove(listener);
194
        }
195

    
196
        public void addErrorListener(ErrorListener listener) {
197
                errorListeners.add(listener);
198
        }
199

    
200
        public void removeErrorListener(LegendListener listener) {
201
                legendListeners.remove(listener);
202
        }
203

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

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

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

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

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

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

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

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

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

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

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

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

    
331
                return ret;
332
        }
333

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

    
360
//                return createFromXML(getXMLEntity());
361

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

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

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

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

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

    
407
                if (viewPort.getImageSize() == null)
408
                        return -1;
409

    
410
                if (viewPort.getAdjustedExtent() == null) {
411
                        return 0;
412
                }
413

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
582
                return visitor.getSelectBound();
583
        }
584

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

    
601
                prepareDrawing(image, g, scale);
602

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

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

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

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

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

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

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

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

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

    
708
        }
709

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

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

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

    
735
                        }
736
                }, scale);
737
        }
738

    
739
        /**
740
         * Devuelve el ViewPort.
741
         *
742
         * @return Returns the viewPort.
743
         */
744
        public ViewPort getViewPort() {
745
                return viewPort;
746
        }
747

    
748
        /**
749
         * Inserta un ViewPort.
750
         *
751
         * @param viewPort
752
         *            The viewPort to set.
753
         */
754
        public void setViewPort(ViewPort viewPort) {
755
                if (this.viewPort != null) {
756
                        this.viewPort.removeViewPortListener(eventBuffer);
757
                }
758

    
759
                this.viewPort = viewPort;
760
                if (viewPort != null)
761
                        viewPort.addViewPortListener(eventBuffer);
762
        }
763

    
764
        /**
765
         * Sets the given zoom extent to the viewport.
766
         *
767
         * @param extent
768
         *            The extent to zoom to.
769
         */
770
        public void zoomToExtent(Rectangle2D extent) {
771
            getViewPort().setExtent(extent);
772
        }
773

    
774
        /**
775
         * M?todo de conveniencia. Recorre las capas y te da el fullExtent
776
         *
777
         * @return fullExtent de todas las capas.
778
         *
779
         * @throws DriverException
780
         */
781
        public Rectangle2D getFullExtent() throws DriverException {
782
                return layers.getFullExtent();
783
        }
784

    
785
        /**
786
         * Devuelve el XMLEntity.
787
         *
788
         * @return XMLEntity.
789
         * @throws XMLException
790
         */
791
        public XMLEntity getXMLEntity() throws XMLException {
792
                XMLEntity xml = new XMLEntity();
793
                xml.putProperty("className", this.getClass().getName());
794
                xml.addChild(viewPort.getXMLEntity());
795
                xml.addChild(layers.getXMLEntity());
796

    
797
                return xml;
798
        }
799

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

    
815
                return fmap;
816
        }
817

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

    
833
                return fmap;
834
        }
835

    
836
        /**
837
         * A?ade un AtomicEventListener.
838
         *
839
         * @param listener
840
         *            AtomicEventListener.
841
         *
842
         * @return True si se ha a?adido correctamente.
843
         */
844
        public boolean addAtomicEventListener(AtomicEventListener listener) {
845
                return eventBuffer.addAtomicEventListener(listener);
846
        }
847

    
848
        /**
849
         * Borra un AtomicEventListener de la lista de listeners.
850
         *
851
         * @param listener
852
         *            AtomicEventListener a borrar.
853
         *
854
         * @return True si se ha borrado correctamente.
855
         */
856
        public boolean removeAtomicEventListener(AtomicEventListener listener) {
857
                return eventBuffer.removeAtomicEventListener(listener);
858
        }
859

    
860
        /**
861
         * Inicializa los AtomicEvent.
862
         */
863
        public void beginAtomicEvent() {
864
                eventBuffer.beginAtomicEvent();
865
        }
866

    
867
        /**
868
         * Finaliza los AtomicEvent.
869
         */
870
        public void endAtomicEvent() {
871
                eventBuffer.endAtomicEvent();
872
        }
873

    
874
        /**
875
         * Evento Layer.
876
         *
877
         * @author Fernando Gonz?lez Cort?s
878
         */
879
        public class LayerEventListener implements LayerCollectionListener {
880
                /**
881
                 * @see com.iver.cit.gvsig.fmap.layers.LayerCollectionListener#layerAdded(com.iver.cit.gvsig.fmap.layers.LayerCollectionEvent)
882
                 */
883
                public void layerAdded(LayerCollectionEvent e) {
884
                        // Si es la primera capa, fijamos su extent al ViewPort
885
                        // if (getLayers().getLayersCount() == 1) {
886
                        if (getViewPort().getExtent() == null) {
887
                                FLayer lyr = e.getAffectedLayer();
888

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

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

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

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

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

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

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

    
940
                        lyr.removeLayerListener(eventBuffer);
941

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

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

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

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

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

    
974

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

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

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

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

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

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

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

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

    
1025
        public ArrayList getLayersError() {
1026
                return layersError;
1027
        }
1028

    
1029
        public void clearErrors() {
1030
                layersError.clear();
1031
        }
1032

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

    
1049
        public void redraw() {
1050
                // truco
1051
                if (getLayers().getLayersCount() > 0)
1052
                        getLayers().moveTo(0,0);
1053

    
1054
        }
1055

    
1056
}