Statistics
| Revision:

svn-gvsig-desktop / trunk / org.gvsig.desktop / org.gvsig.desktop.compat.cdc / org.gvsig.fmap.mapcontext / org.gvsig.fmap.mapcontext.api / src / main / java / org / gvsig / fmap / mapcontext / impl / DefaultMapContextDrawer.java @ 46909

History | View | Annotate | Download (29.3 KB)

1
/**
2
 * gvSIG. Desktop Geographic Information System.
3
 *
4
 * Copyright (C) 2007-2013 gvSIG Association.
5
 *
6
 * This program is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU General Public License
8
 * as published by the Free Software Foundation; either version 3
9
 * of the License, or (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19
 * MA  02110-1301, USA.
20
 *
21
 * For any additional information, do not hesitate to contact us
22
 * at info AT gvsig.com, or visit our website www.gvsig.com.
23
 */
24
package org.gvsig.fmap.mapcontext.impl;
25

    
26
import java.awt.Graphics2D;
27
import java.awt.geom.AffineTransform;
28
import java.awt.image.BufferedImage;
29
import java.util.ArrayList;
30
import java.util.Iterator;
31
import java.util.List;
32
import java.util.NoSuchElementException;
33

    
34
import org.gvsig.compat.CompatLocator;
35
import org.gvsig.compat.print.PrintAttributes;
36
import org.gvsig.fmap.dal.exception.ReadException;
37
import org.gvsig.fmap.geom.primitive.Envelope;
38
import org.gvsig.fmap.mapcontext.MapContext;
39
import org.gvsig.fmap.mapcontext.MapContextDrawer;
40
import org.gvsig.fmap.mapcontext.MapContextException;
41
import org.gvsig.fmap.mapcontext.MapContextLocator;
42
import org.gvsig.fmap.mapcontext.MapContextManager;
43
import org.gvsig.fmap.mapcontext.ViewPort;
44
import org.gvsig.fmap.mapcontext.layers.FLayer;
45
import org.gvsig.fmap.mapcontext.layers.FLayerHidesArea;
46
import org.gvsig.fmap.mapcontext.layers.FLayers;
47
import org.gvsig.fmap.mapcontext.layers.LayerDrawEvent;
48
import org.gvsig.fmap.mapcontext.layers.LayersIterator;
49
import org.gvsig.fmap.mapcontext.layers.operations.ComposedLayer;
50
import org.gvsig.fmap.mapcontext.layers.operations.LayerCollection;
51
import org.gvsig.fmap.mapcontext.layers.vectorial.GraphicLayer;
52
import org.gvsig.fmap.mapcontext.layers.vectorial.VectorLayer;
53
import org.gvsig.fmap.mapcontext.rendering.legend.styling.ILabelable;
54
import org.gvsig.tools.task.Cancellable;
55
import org.gvsig.tools.util.Callable;
56
import org.slf4j.Logger;
57
import org.slf4j.LoggerFactory;
58

    
59
public class DefaultMapContextDrawer implements MapContextDrawer {
60

    
61
    private static final Logger LOG = LoggerFactory
62
            .getLogger(DefaultMapContextDrawer.class);
63

    
64
    private MapContext mapContext = null;
65
    private ViewPort viewPort = null;
66
    private CachedImage cachedImage = null;
67
    private DrawList previousDrawList = null;
68

    
69
    protected void checkInitialized() {
70
        if (mapContext == null || viewPort == null) {
71
            throw new IllegalStateException(
72
                    "MapContext and ViewPort must be set");
73
        }
74
    }
75

    
76
    public void draw(FLayers root, BufferedImage image, Graphics2D g,
77
            Cancellable cancel, double scale) throws ReadException {
78

    
79
        this.checkInitialized();
80

    
81
        // With viewport changes all layers must be redrawn, discard cache
82
        if (cachedImage != null && cachedImage.hasChangedViewPortDrawVersion()) {
83
            cachedImage = null;
84
        }
85

    
86
        AffineTransform aux_at = null;
87

    
88
        if (isValidFullCachedImage()) {
89

    
90
            aux_at = g.getTransform();
91
            g.drawImage(
92
                    cachedImage.getFullDrawnImage(),
93
                    (int) -aux_at.getTranslateX(),
94
                    (int) -aux_at.getTranslateY(),
95
                    null);
96
            LOG.debug("Drawn full image from the cache, all layers cached");
97
            return;
98
        }
99

    
100
        DrawList drawList = this.createDrawList(root, cancel, scale);
101
        if (drawList == null || drawList.size() == 0) {
102
            return;
103
        }
104

    
105
        if (cancel.isCanceled()) {
106
            cachedImage = null;
107
            return;
108
        }
109

    
110
        int firstLayerToDraw;
111
        int lastLayerToDraw;
112
        if (isValidPartialCachedImage(drawList)) {
113
            firstLayerToDraw = 0;
114
            lastLayerToDraw = cachedImage.getLastDrawnLayerPosition();
115

    
116
            aux_at = g.getTransform();
117
            g.drawImage(
118
                    cachedImage.getPartialDrawnImage(),
119
                    (int) -aux_at.getTranslateX(),
120
                    (int) -aux_at.getTranslateY(),
121
                    null);
122

    
123
            cachedImage.updateVersions(mapContext, viewPort);
124
            LOG.debug("Reused image of cached layers from 0 to {}",
125
                    new Integer(lastLayerToDraw));
126
        } else {
127
            if (cachedImage == null) {
128
                cachedImage = new CachedImage();
129
                // Draw all layers
130
                firstLayerToDraw = 0;
131
                //lastLayerToDraw = drawList.getLayerCount() - 1;
132
                lastLayerToDraw = drawList.getLastLayerVisible(viewPort);
133
            } else {
134
                // Draw the first group of layers without changes to be cached
135
                // next time
136
                firstLayerToDraw = 0;
137
                int firstChangedLayer = drawList.getFirstChangedLayer();
138
                // If negative nothing has changed, so draw all the layers
139
                lastLayerToDraw = firstChangedLayer < 0 ? drawList
140
                        .getLayerCount() - 1 : firstChangedLayer - 1;
141
            }
142
            drawList.drawLayers(image, g, firstLayerToDraw, lastLayerToDraw,
143
                    cancel, scale);
144
            cachedImage.setPartialDrawnImage(image, mapContext, viewPort,
145
                    lastLayerToDraw);
146
        }
147

    
148
        if (cancel.isCanceled()) {
149
            cachedImage = null;
150
            return;
151
        }
152

    
153
        // Draw the second group of layers not cached
154
        firstLayerToDraw = lastLayerToDraw + 1;
155
        lastLayerToDraw = drawList.getLayerCount() - 1;
156

    
157
        drawList.drawLayers(image, g, firstLayerToDraw, lastLayerToDraw,
158
                cancel, scale);
159
        
160
        if (cancel.isCanceled()) {
161
            this.clean();
162
        } else {
163
            cachedImage.setFullDrawnImage(image);
164
        }
165

    
166
        this.previousDrawList = drawList;
167

    
168
    }
169

    
170
    private boolean isValidPartialCachedImage(DrawList drawList) {
171
        return cachedImage != null
172
                && cachedImage.isValidPartialDrawnImage(mapContext, drawList);
173
    }
174

    
175
    private boolean isValidFullCachedImage() {
176
        return cachedImage != null
177
                && cachedImage.isValidFullDrawnImage(mapContext);
178
    }
179

    
180
    private void print(Object layerOrComposed, Graphics2D g,
181
            Cancellable cancel, double scale, PrintAttributes properties)
182
            throws ReadException {
183
        ILabelable labelable = null;
184
        ILabelable tmp = null;
185
        if (layerOrComposed instanceof ILabelable) {
186

    
187
            tmp = (ILabelable) layerOrComposed;
188

    
189
            if (tmp.isLabeled() && tmp.getLabelingStrategy() != null
190
                    && tmp.getLabelingStrategy().shouldDrawLabels(scale)) {
191
                labelable = tmp;
192
            }
193
        }
194

    
195
        if (layerOrComposed instanceof FLayer) {
196
            FLayer layer = (FLayer) layerOrComposed;
197
            layer.print(g, viewPort, cancel, scale, properties);
198
        } else {
199
            ComposedLayer composed = (ComposedLayer) layerOrComposed;
200
            composed.print(g, viewPort, cancel, scale, properties);
201
        }
202
        if (labelable != null) {
203
            labelable.printLabels(g, viewPort, cancel, scale, properties);
204
        }
205

    
206
    }
207

    
208
    public void setMapContext(MapContext mapContext) {
209
        if (this.mapContext == mapContext) {
210
            return;
211
        }
212
        this.clean();
213
        this.mapContext = mapContext;
214

    
215
    }
216

    
217
    public void setViewPort(ViewPort viewPort) {
218
        if (this.viewPort == viewPort) {
219
            return;
220
        }
221
        this.clean();
222
        this.viewPort = viewPort;
223

    
224
    }
225

    
226
    protected void clean() {
227
        this.cachedImage = null;
228
    }
229

    
230
    public class CachedImage {
231

    
232
        private BufferedImage partialDrawnImage;
233
        private BufferedImage fullDrawnImage;
234
        private long lastMapContextVersion;
235
        private long lastViewPortVersion;
236
        private int lastDrawnLayerPosition;
237

    
238
        public void setPartialDrawnImage(BufferedImage partialDrawnImage,
239
                MapContext mapContext, ViewPort viewPort,
240
                int lastDrawnLayerPosition) {
241
            this.partialDrawnImage = CompatLocator.getGraphicsUtils()
242
                    .copyBufferedImage(partialDrawnImage);
243
            this.lastDrawnLayerPosition = lastDrawnLayerPosition;
244
            updateVersions(mapContext, viewPort);
245
        }
246

    
247
        public void updateVersions(MapContext mapContext, ViewPort viewPort) {
248
            this.lastMapContextVersion = mapContext.getDrawVersion();
249
            this.lastViewPortVersion = viewPort.getDrawVersion();
250
        }
251

    
252
        public void setFullDrawnImage(BufferedImage fullDrawnImage) {
253
            this.fullDrawnImage = CompatLocator.getGraphicsUtils()
254
                    .copyBufferedImage(fullDrawnImage);
255
        }
256

    
257
        public BufferedImage getPartialDrawnImage() {
258
            return partialDrawnImage;
259
        }
260

    
261
        public BufferedImage getFullDrawnImage() {
262
            return fullDrawnImage;
263
        }
264

    
265
        public long getMapContextVersion() {
266
            return lastMapContextVersion;
267
        }
268

    
269
        public int getLastDrawnLayerPosition() {
270
            return this.lastDrawnLayerPosition;
271
        }
272

    
273
        public boolean isValidFullDrawnImage(MapContext context) {
274
            // If the MapContext version has not changed, there are not any
275
            // changes that require redrawing any of the layers.
276
            return fullDrawnImage != null && !hasChangedMapContextDrawVersion();
277
        }
278

    
279
        public boolean hasChangedMapContextDrawVersion() {
280
            // This change detects changes in layers and the viewport also
281
            return mapContext.getDrawVersion() != this.lastMapContextVersion;
282
        }
283

    
284
        public boolean hasChangedViewPortDrawVersion() {
285
            // This change detects changes in the viewport
286
            return viewPort.getDrawVersion() != this.lastViewPortVersion;
287
        }
288

    
289
        public boolean isValidPartialDrawnImage(MapContext context,
290
                DrawList drawList) {
291
            if (!hasChangedMapContextDrawVersion()) {
292
                // Nothing has changed
293
                return true;
294
            }
295

    
296
            if (partialDrawnImage == null || hasChangedViewPortDrawVersion()) {
297
                // No image available or changes in view port
298
                return false;
299
            }
300

    
301
            if (drawList.size() < lastDrawnLayerPosition + 1) {
302
                // New list has fewer layers than before
303
                return false;
304
            }
305

    
306
            // There is any change in the layers drawn in the partial drawn
307
            // image?
308
            return drawList.getFirstChangedLayer() > lastDrawnLayerPosition;
309
        }
310
    }
311

    
312
    public class DrawList {
313

    
314
        private List layers = new ArrayList();
315
        private List all = new ArrayList();
316
        private List versions = new ArrayList();
317
        private DrawList previosList = null;
318
        private int firstLayerChanged = -1;
319

    
320
        public DrawList() {
321
        }
322

    
323
        public DrawList(DrawList previousList) {
324
            if (previousList != null) {
325
                this.firstLayerChanged = previousList.getLayerCount();
326
                this.previosList = previousList;
327
            }
328
        }
329

    
330
        public int getLayerCount() {
331
            return this.layers.size();
332
        }
333

    
334
        public int getLastLayerVisible(ViewPort viewPort) {
335
            Envelope area = viewPort.getAdjustedEnvelope();
336
            for (int n = 0; n < this.layers.size() - 1; n++) {
337
                FLayer layer = (FLayer) this.layers.get(n);
338
                if (layer instanceof FLayerHidesArea) {
339
                    if (((FLayerHidesArea) (layer)).hidesThisArea(area)) {
340
                        return n;
341
                    }
342
                }
343
            }
344
            return this.layers.size() - 1;
345
        }
346

    
347
        private boolean hasChanged(FLayer layer, int pos) {
348
            FLayer previous = (FLayer) this.previosList.layers.get(pos);
349
            // String previousName = previous.getName();
350
            // String layerName = layer.getName();
351
            if (previous != layer) {
352
                return true;
353
            }
354
            long previousVersion = ((Long) this.previosList.versions.get(pos))
355
                    .longValue();
356
            long layerVersion = layer.getDrawVersion();
357

    
358
            return previousVersion != layerVersion;
359
        }
360

    
361
        public void add(Object obj) {
362
            if (obj instanceof FLayer) {
363
                FLayer layer = (FLayer) obj;
364
                int curIndex = this.layers.size();
365
                if (this.firstLayerChanged >= curIndex) {
366
                    if (this.previosList.getLayerCount() > curIndex) {
367
                        if (this.hasChanged(layer, curIndex)) {
368
                            this.firstLayerChanged = curIndex;
369
                        }
370
                    } else if (this.previosList.getLayerCount() == curIndex) {
371
                        this.firstLayerChanged = curIndex;
372
                    }
373
                }
374
                this.layers.add(layer);
375
                this.versions.add(new Long(layer.getDrawVersion()));
376
            } else if (!(obj instanceof LayersGroupEvent)) {
377
                throw new UnsupportedOperationException();
378
            }
379

    
380
            this.all.add(obj);
381
        }
382

    
383
        public int size() {
384
            return this.all.size();
385
        }
386

    
387
        public int getFirstChangedLayer() {
388
            if (this.firstLayerChanged > this.layers.size()) {
389
                this.firstLayerChanged = this.layers.size();
390
            }
391
            return this.firstLayerChanged;
392
        }
393

    
394
        public FLayer getLayer(int pos) {
395
            return (FLayer) this.layers.get(pos);
396
        }
397

    
398
        public Object get(int pos) {
399
            return this.all.get(pos);
400
        }
401

    
402
        public void drawLayers(BufferedImage image, Graphics2D g,
403
                int firstLayerToDraw, int lastLayerToDraw, Cancellable cancel,
404
                double scale) throws ReadException {
405

    
406
            if (firstLayerToDraw > lastLayerToDraw) {
407
                LOG.debug("Nothing to draw");
408
                return;
409
            }
410

    
411
            // Find the real layer positions excluding LayersGroupEvents
412
            FLayer firstLayer = (FLayer) layers.get(firstLayerToDraw);
413
            int firstLayerPos = all.indexOf(firstLayer);
414
            // Look if it belongs to a group and start it
415
            if (firstLayerPos > 0) {
416
                for (int i = firstLayerPos - 1; i < all.size(); i++) {
417
                    // firstLayer
418
                    Object group = all.get(i);
419
                    if (group instanceof LayersGroupEvent) {
420
                        LayersGroupEvent event = (LayersGroupEvent) group;
421
                        if (event.type == LayersGroupEvent.IN_Event) {
422
                            event.group.beginDraw(g, viewPort);
423
                        }
424
                        break;
425
                    }
426
                }
427
            }
428
            FLayer lastLayer = (FLayer) layers.get(lastLayerToDraw);
429
            int lastLayerPos = all.indexOf(lastLayer);
430

    
431
            LOG.debug("Drawing from layer {} in position (layers: {}, all: {})"
432
                    + " to layer {} in position (layers: {}, all: {})",
433
                    new Object[]{firstLayer, new Integer(firstLayerToDraw),
434
                        new Integer(firstLayerPos), lastLayer,
435
                        new Integer(lastLayerToDraw),
436
                        new Integer(lastLayerPos)});
437

    
438
            ComposedLayer composed = null;
439
            for (int pos = firstLayerPos; pos <= lastLayerPos; pos++) {
440
                if (cancel.isCanceled()) {
441
                    return;
442
                }
443

    
444
                Object layerOrGroup = get(pos);
445

    
446
                // Group drawing events management
447
                if (layerOrGroup instanceof LayersGroupEvent) {
448
                    LayersGroupEvent event = (LayersGroupEvent) layerOrGroup;
449
                    if (event.type == LayersGroupEvent.IN_Event) {
450
                        event.group.beginDraw(g, viewPort);
451
                    } else {
452
                        event.group.endDraw(g, viewPort);
453
                    }
454
                } else {
455
                    FLayer layer = (FLayer) layerOrGroup;
456
                    if (composed != null && composed.canAdd(layer)) {
457
                        // Previous or current layer could be composed
458
                        // Add current layer
459
                        addToComposedLayer(composed, layer);
460
                    } else {
461
                        if (composed != null) {
462
                            // Current layer can't be composed on the previous
463
                            // composedlayer. Draw previous composed
464
                            LOG.debug("Drawing composed layer {} ", composed);
465
                            draw(composed, image, g, cancel, scale);
466
                            composed = null;
467
                        }
468

    
469
                        // Try if the current layer can be composed
470
                        // Create new composed or draw current layer
471
                        composed = layer.newComposedLayer();
472
                        if (composed == null) {
473
                            LOG.debug("Drawing layer {} ", layer);
474
                            draw(layer, image, g, cancel, scale);
475
                        } else {
476
                            addToComposedLayer(composed, layer);
477
                        }
478
                    }
479
                }
480
            }
481
            if (composed != null) {
482
                // Draw the pending composed
483
                draw(composed, image, g, cancel, scale);
484
            }
485

    
486
            // Check if the last layer is the last of a group and close it
487
            for (int i = lastLayerPos + 1; i < all.size(); i++) {
488
                Object group = all.get(i);
489
                if (group instanceof LayersGroupEvent) {
490
                    LayersGroupEvent event = (LayersGroupEvent) group;
491
                    if (event.type == LayersGroupEvent.OUT_Event) {
492
                        event.group.endDraw(g, viewPort);
493
                    }
494
                    break;
495
                }
496
            }
497
        }
498

    
499
        private void addToComposedLayer(ComposedLayer composed, FLayer layer)
500
                throws ReadException {
501
            try {
502
                LOG.debug("Adding layer {} to composed layer ", layer, composed);
503
                composed.add(layer);
504
            } catch (Exception e) {
505
                throw new ReadException("DefalutMapContexDrawer exception", e);
506
            }
507
        }
508

    
509
        private void draw(Object layerOrComposed, BufferedImage image,
510
                Graphics2D g, Cancellable cancel, double scale)
511
                throws ReadException {
512
            ILabelable labelable = null;
513
            ILabelable tmp = null;
514
            if (layerOrComposed instanceof ILabelable) {
515

    
516
                tmp = (ILabelable) layerOrComposed;
517

    
518
                if (tmp.isLabeled() && tmp.getLabelingStrategy() != null
519
                        && tmp.getLabelingStrategy().shouldDrawLabels(scale)) {
520
                    labelable = tmp;
521
                }
522
            }
523

    
524
            if (layerOrComposed instanceof FLayer) {
525
                int beforeDrawEventType;
526
                int afterDrawEventType;
527
                if (layerOrComposed instanceof GraphicLayer) {
528
                    beforeDrawEventType = LayerDrawEvent.GRAPHICLAYER_BEFORE_DRAW;
529
                    afterDrawEventType = LayerDrawEvent.GRAPHICLAYER_AFTER_DRAW;
530
                } else {
531
                    beforeDrawEventType = LayerDrawEvent.LAYER_BEFORE_DRAW;
532
                    afterDrawEventType = LayerDrawEvent.LAYER_AFTER_DRAW;
533
                }
534
                FLayer layer = (FLayer) layerOrComposed;
535
                drawLayer(layer, image, g, cancel, scale, beforeDrawEventType,
536
                        afterDrawEventType);
537
            } else {
538
                ComposedLayer composed = (ComposedLayer) layerOrComposed;
539
                composed.draw(image, g, viewPort, cancel, scale);
540
            }
541
            if (labelable != null) {
542
                labelable.drawLabels(image, g, viewPort, cancel, scale,
543
                        mapContext.getViewPort().getDPI());
544
            }
545

    
546
        }
547

    
548
        protected void drawLayer(FLayer layer, BufferedImage image,
549
                Graphics2D g, Cancellable cancel, double scale,
550
                int beforeDrawEventType, int afterDrawEventType)
551
                throws ReadException {
552
            LayerDrawEvent event = new LayerDrawEvent(layer, g, viewPort, beforeDrawEventType);
553
            mapContext.fireLayerDrawingEvent(event);
554
            layer.draw(image, g, viewPort, cancel, scale);
555
            event = new LayerDrawEvent(layer, g, viewPort, afterDrawEventType);
556
            mapContext.fireLayerDrawingEvent(event);
557
        }
558

    
559
    }
560

    
561
    private class SimpleLayerIterator extends LayersIterator {
562

    
563
        public SimpleLayerIterator(FLayer layer) {
564
            this.appendLayer(layer);
565
        }
566

    
567
        public boolean evaluate(FLayer layer) {
568
            if (layer instanceof FLayers) {
569
                return false;
570
            }
571
            return layer.isAvailable() && layer.isVisible();
572
        }
573

    
574
    }
575

    
576
    public void dispose() {
577
        this.mapContext = null;
578
        this.viewPort = null;
579
        this.cachedImage = null;
580
        this.previousDrawList = null;
581
    }
582

    
583
    public void print(FLayers root, Graphics2D g, Cancellable cancel,
584
            double scale, PrintAttributes properties) throws ReadException {
585
        this.checkInitialized();
586

    
587
        List printList = this.createPrintList(root, cancel);
588
        if (cancel.isCanceled()) {
589
            return;
590
        }
591

    
592
        ComposedLayer composed = null;
593
        int pos;
594
        FLayer layer;
595
        int layerPos = -1;
596
        Object obj;
597
        LayersGroupEvent event;
598
        for (pos = 0; pos < printList.size(); pos++) {
599
            if (cancel.isCanceled()) {
600
                return;
601
            }
602

    
603
            obj = printList.get(pos);
604
            if (obj instanceof LayersGroupEvent) {
605
                event = (LayersGroupEvent) obj;
606
                if (event.type == LayersGroupEvent.IN_Event) {
607
                    // System.out.println("=======Empiza a pintar grupo de capas "+
608
                    // ((FLayers)event.group).getName() +"============");
609
                    event.group.beginDraw(g, viewPort);
610
                } else {
611
                    event.group.endDraw(g, viewPort);
612
                    // System.out.println("=======Fin a pintar grupo de capas "+
613
                    // ((FLayers)event.group).getName() +"============");
614

    
615
                }
616
                continue;
617
            }
618
            layerPos++;
619

    
620
            layer = (FLayer) obj;
621

    
622
            // *** Pintado de capa/composicion de capa ***
623
            if (composed == null) {
624
                composed = layer.newComposedLayer();
625
                if (composed != null) {
626
                    try {
627
                        composed.add(layer);
628
                        // System.out.println("=======Imprimiendo composicion de pintado "+
629
                        // (layerPos-1)+" ============");
630
                        continue;
631
                    } catch (Exception e) {
632
                        throw new ReadException(
633
                                "DefaultMapContexDrawer exception", e);
634
                    }
635
                }
636
            } else {
637
                if (composed.canAdd(layer)) {
638
                    try {
639
                        composed.add(layer);
640
                        // System.out.println("=== a�adiendo a composicion de pintado "+
641
                        // layerPos+ " "+layer.getName());
642
                        continue;
643
                    } catch (Exception e) {
644
                        throw new ReadException(
645
                                "DefaultMapContexDrawer exception", e);
646
                    }
647
                } else {
648
                    // System.out.println("=======Imprimiendo composicion de pintado "+
649
                    // (layerPos-1)+" ============");
650
                    this.print(composed, g, cancel, scale, properties);
651
                    // composed.print( g, viewPort, cancel, scale,properties);
652
                    composed = layer.newComposedLayer();
653
                    if (composed != null) {
654
                        try {
655
                            composed.add(layer);
656
                            // System.out.println("=== a�adiendo a composicion de pintado "+
657
                            // layerPos+ " "+layer.getName());
658
                            continue;
659
                        } catch (Exception e) {
660
                            throw new ReadException(
661
                                    "DefaultMapContexDrawer exception", e);
662
                        }
663
                    }
664
                }
665
            }
666
            // System.out.println("=== imprimiendo "+ layerPos+
667
            // " "+layer.getName());
668
            this.print(layer, g, cancel, scale, properties);
669
            // layer.print(g, viewPort, cancel, scale,properties);
670
            // *** Pintado de capa/composicion de capa ***
671
            if (composed != null) {
672
                // si la composicion no se ha pintado la pintamos
673
                // System.out.println("=======Imprimiendo composicion de pintado "+
674
                // (layerPos-1)+" (ultimo) ============");
675
                this.print(composed, g, cancel, scale, properties);
676
                // composed.print(g, viewPort, cancel, scale, properties);
677
                composed = null;
678
            }
679
        }
680

    
681
    }
682

    
683
    private DrawList createDrawList(FLayers root, Cancellable cancel,
684
            double scale) {
685
        DrawList result = new DrawList(this.previousDrawList);
686
        Iterator iter = new MyLayerIterator((FLayer) root, scale);
687
        while (iter.hasNext()) {
688
            if (cancel.isCanceled()) {
689
                return null;
690
            }
691
            result.add(iter.next());
692
        }
693
        if (cancel.isCanceled()) {
694
            return null;
695
        }
696
        // Take into account also the Graphic layer
697
        for (VectorLayer graphicsLayer : mapContext.getGraphicsLayers()) {
698
            if (graphicsLayer != null && 
699
                    graphicsLayer.isAvailable() &&
700
                    graphicsLayer.isVisible() && 
701
                    graphicsLayer.isWithinScale(scale)) {
702
                result.add(graphicsLayer);
703
            }
704
        }
705
        return result;
706
    }
707

    
708
    private List createPrintList(FLayers root, Cancellable cancel) {
709
        List result = new ArrayList();
710
        Iterator iter = new SimpleLayerIterator((FLayer) root);
711
        while (iter.hasNext()) {
712
            if (cancel.isCanceled()) {
713
                return null;
714
            }
715
            result.add(iter.next());
716
        }
717
        return result;
718
    }
719

    
720
    private class MyLayerIterator implements Iterator {
721

    
722
        List layersList = new ArrayList();
723
        int index = 0;
724
        double scale = 0;
725

    
726
        public MyLayerIterator(FLayer layer, double scale) {
727
            this.scale = scale;
728
            this.appendLayer(layer);
729
        }
730

    
731
        protected void appendLayer(FLayer layer) {
732
            if (layer instanceof LayerCollection) {
733
                appendLayers((LayerCollection) layer);
734
            } else if (this.evaluate(layer)) {
735
                layersList.add(layer);
736
            }
737
        }
738

    
739
        private void appendLayers(LayerCollection layers) {
740
            int i;
741
            layersList.add(new LayersGroupEvent(layers,
742
                    LayersGroupEvent.IN_Event));
743
            for (i = 0; i < layers.getLayersCount(); i++) {
744
                appendLayer(layers.getLayer(i));
745
            }
746
            layersList.add(new LayersGroupEvent(layers,
747
                    LayersGroupEvent.OUT_Event));
748
        }
749

    
750
        public void remove() {
751
            throw new UnsupportedOperationException();
752
        }
753

    
754
        public boolean hasNext() {
755
            return index < layersList.size();
756
        }
757

    
758
        public Object next() {
759
            if (!this.hasNext()) {
760
                throw new NoSuchElementException();
761
            }
762
            Object aux = layersList.get(index);
763
            index++;
764
            return aux;
765
        }
766

    
767
        public boolean evaluate(FLayer layer) {
768
            if (layer instanceof LayerCollection) {
769
                return false;
770
            }
771
            return layer.isAvailable() && layer.isVisible()
772
                    && layer.isWithinScale(this.scale);
773
        }
774

    
775
    }
776

    
777
    private class LayersGroupEvent {
778

    
779
        public static final String IN_Event = "in";
780
        public static final String OUT_Event = "Out";
781

    
782
        private LayerCollection group = null;
783
        private String type = IN_Event;
784

    
785
        public LayersGroupEvent(LayerCollection group, String type) {
786
            this.group = group;
787
            this.type = type;
788
        }
789

    
790
        public String getType() {
791
            return type;
792
        }
793

    
794
        public LayerCollection getGroup() {
795
            return group;
796
        }
797
    }
798

    
799
    public static class RegisterMapContextDrawer implements Callable {
800

    
801
        public Object call() {
802
            MapContextManager manager = MapContextLocator.getMapContextManager();
803
            try {
804
                manager.setDefaultMapContextDrawer(DefaultMapContextDrawer.class);
805
            } catch (MapContextException ex) {
806
                throw new RuntimeException("Can't register the default MapContextDrawer", ex);
807
            }
808
            return Boolean.TRUE;
809
        }
810
    }
811
}