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 @ 44453

History | View | Annotate | Download (29.2 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
        drawList.drawLayers(image, g, firstLayerToDraw, lastLayerToDraw,
157
                cancel, scale);
158
        cachedImage.setFullDrawnImage(image);
159

    
160
        this.previousDrawList = drawList;
161
    }
162

    
163
    private boolean isValidPartialCachedImage(DrawList drawList) {
164
        return cachedImage != null
165
                && cachedImage.isValidPartialDrawnImage(mapContext, drawList);
166
    }
167

    
168
    private boolean isValidFullCachedImage() {
169
        return cachedImage != null
170
                && cachedImage.isValidFullDrawnImage(mapContext);
171
    }
172

    
173
    private void print(Object layerOrComposed, Graphics2D g,
174
            Cancellable cancel, double scale, PrintAttributes properties)
175
            throws ReadException {
176
        ILabelable labelable = null;
177
        ILabelable tmp = null;
178
        if (layerOrComposed instanceof ILabelable) {
179

    
180
            tmp = (ILabelable) layerOrComposed;
181

    
182
            if (tmp.isLabeled() && tmp.getLabelingStrategy() != null
183
                    && tmp.getLabelingStrategy().shouldDrawLabels(scale)) {
184
                labelable = tmp;
185
            }
186
        }
187

    
188
        if (layerOrComposed instanceof FLayer) {
189
            FLayer layer = (FLayer) layerOrComposed;
190
            layer.print(g, viewPort, cancel, scale, properties);
191
        } else {
192
            ComposedLayer composed = (ComposedLayer) layerOrComposed;
193
            composed.print(g, viewPort, cancel, scale, properties);
194
        }
195
        if (labelable != null) {
196
            labelable.printLabels(g, viewPort, cancel, scale, properties);
197
        }
198

    
199
    }
200

    
201
    public void setMapContext(MapContext mapContext) {
202
        if (this.mapContext == mapContext) {
203
            return;
204
        }
205
        this.clean();
206
        this.mapContext = mapContext;
207

    
208
    }
209

    
210
    public void setViewPort(ViewPort viewPort) {
211
        if (this.viewPort == viewPort) {
212
            return;
213
        }
214
        this.clean();
215
        this.viewPort = viewPort;
216

    
217
    }
218

    
219
    protected void clean() {
220
        this.cachedImage = null;
221
    }
222

    
223
    public class CachedImage {
224

    
225
        private BufferedImage partialDrawnImage;
226
        private BufferedImage fullDrawnImage;
227
        private long lastMapContextVersion;
228
        private long lastViewPortVersion;
229
        private int lastDrawnLayerPosition;
230

    
231
        public void setPartialDrawnImage(BufferedImage partialDrawnImage,
232
                MapContext mapContext, ViewPort viewPort,
233
                int lastDrawnLayerPosition) {
234
            this.partialDrawnImage = CompatLocator.getGraphicsUtils()
235
                    .copyBufferedImage(partialDrawnImage);
236
            this.lastDrawnLayerPosition = lastDrawnLayerPosition;
237
            updateVersions(mapContext, viewPort);
238
        }
239

    
240
        public void updateVersions(MapContext mapContext, ViewPort viewPort) {
241
            this.lastMapContextVersion = mapContext.getDrawVersion();
242
            this.lastViewPortVersion = viewPort.getDrawVersion();
243
        }
244

    
245
        public void setFullDrawnImage(BufferedImage fullDrawnImage) {
246
            this.fullDrawnImage = CompatLocator.getGraphicsUtils()
247
                    .copyBufferedImage(fullDrawnImage);
248
        }
249

    
250
        public BufferedImage getPartialDrawnImage() {
251
            return partialDrawnImage;
252
        }
253

    
254
        public BufferedImage getFullDrawnImage() {
255
            return fullDrawnImage;
256
        }
257

    
258
        public long getMapContextVersion() {
259
            return lastMapContextVersion;
260
        }
261

    
262
        public int getLastDrawnLayerPosition() {
263
            return this.lastDrawnLayerPosition;
264
        }
265

    
266
        public boolean isValidFullDrawnImage(MapContext context) {
267
            // If the MapContext version has not changed, there are not any
268
            // changes that require redrawing any of the layers.
269
            return fullDrawnImage != null && !hasChangedMapContextDrawVersion();
270
        }
271

    
272
        public boolean hasChangedMapContextDrawVersion() {
273
            // This change detects changes in layers and the viewport also
274
            return mapContext.getDrawVersion() != this.lastMapContextVersion;
275
        }
276

    
277
        public boolean hasChangedViewPortDrawVersion() {
278
            // This change detects changes in the viewport
279
            return viewPort.getDrawVersion() != this.lastViewPortVersion;
280
        }
281

    
282
        public boolean isValidPartialDrawnImage(MapContext context,
283
                DrawList drawList) {
284
            if (!hasChangedMapContextDrawVersion()) {
285
                // Nothing has changed
286
                return true;
287
            }
288

    
289
            if (partialDrawnImage == null || hasChangedViewPortDrawVersion()) {
290
                // No image available or changes in view port
291
                return false;
292
            }
293

    
294
            if (drawList.size() < lastDrawnLayerPosition + 1) {
295
                // New list has fewer layers than before
296
                return false;
297
            }
298

    
299
            // There is any change in the layers drawn in the partial drawn
300
            // image?
301
            return drawList.getFirstChangedLayer() > lastDrawnLayerPosition;
302
        }
303
    }
304

    
305
    public class DrawList {
306

    
307
        private List layers = new ArrayList();
308
        private List all = new ArrayList();
309
        private List versions = new ArrayList();
310
        private DrawList previosList = null;
311
        private int firstLayerChanged = -1;
312

    
313
        public DrawList() {
314
        }
315

    
316
        public DrawList(DrawList previousList) {
317
            if (previousList != null) {
318
                this.firstLayerChanged = previousList.getLayerCount();
319
                this.previosList = previousList;
320
            }
321
        }
322

    
323
        public int getLayerCount() {
324
            return this.layers.size();
325
        }
326

    
327
        public int getLastLayerVisible(ViewPort viewPort) {
328
            Envelope area = viewPort.getAdjustedEnvelope();
329
            for (int n = 0; n < this.layers.size() - 1; n++) {
330
                FLayer layer = (FLayer) this.layers.get(n);
331
                if (layer instanceof FLayerHidesArea) {
332
                    if (((FLayerHidesArea) (layer)).hidesThisArea(area)) {
333
                        return n;
334
                    }
335
                }
336
            }
337
            return this.layers.size() - 1;
338
        }
339

    
340
        private boolean hasChanged(FLayer layer, int pos) {
341
            FLayer previous = (FLayer) this.previosList.layers.get(pos);
342
            // String previousName = previous.getName();
343
            // String layerName = layer.getName();
344
            if (previous != layer) {
345
                return true;
346
            }
347
            long previousVersion = ((Long) this.previosList.versions.get(pos))
348
                    .longValue();
349
            long layerVersion = layer.getDrawVersion();
350

    
351
            return previousVersion != layerVersion;
352
        }
353

    
354
        public void add(Object obj) {
355
            if (obj instanceof FLayer) {
356
                FLayer layer = (FLayer) obj;
357
                int curIndex = this.layers.size();
358
                if (this.firstLayerChanged >= curIndex) {
359
                    if (this.previosList.getLayerCount() > curIndex) {
360
                        if (this.hasChanged(layer, curIndex)) {
361
                            this.firstLayerChanged = curIndex;
362
                        }
363
                    } else if (this.previosList.getLayerCount() == curIndex) {
364
                        this.firstLayerChanged = curIndex;
365
                    }
366
                }
367
                this.layers.add(layer);
368
                this.versions.add(new Long(layer.getDrawVersion()));
369
            } else if (!(obj instanceof LayersGroupEvent)) {
370
                throw new UnsupportedOperationException();
371
            }
372

    
373
            this.all.add(obj);
374
        }
375

    
376
        public int size() {
377
            return this.all.size();
378
        }
379

    
380
        public int getFirstChangedLayer() {
381
            if (this.firstLayerChanged > this.layers.size()) {
382
                this.firstLayerChanged = this.layers.size();
383
            }
384
            return this.firstLayerChanged;
385
        }
386

    
387
        public FLayer getLayer(int pos) {
388
            return (FLayer) this.layers.get(pos);
389
        }
390

    
391
        public Object get(int pos) {
392
            return this.all.get(pos);
393
        }
394

    
395
        public void drawLayers(BufferedImage image, Graphics2D g,
396
                int firstLayerToDraw, int lastLayerToDraw, Cancellable cancel,
397
                double scale) throws ReadException {
398

    
399
            if (firstLayerToDraw > lastLayerToDraw) {
400
                LOG.debug("Nothing to draw");
401
                return;
402
            }
403

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

    
424
            LOG.debug("Drawing from layer {} in position (layers: {}, all: {})"
425
                    + " to layer {} in position (layers: {}, all: {})",
426
                    new Object[]{firstLayer, new Integer(firstLayerToDraw),
427
                        new Integer(firstLayerPos), lastLayer,
428
                        new Integer(lastLayerToDraw),
429
                        new Integer(lastLayerPos)});
430

    
431
            ComposedLayer composed = null;
432
            for (int pos = firstLayerPos; pos <= lastLayerPos; pos++) {
433
                if (cancel.isCanceled()) {
434
                    return;
435
                }
436

    
437
                Object layerOrGroup = get(pos);
438

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

    
462
                        // Try if the current layer can be composed
463
                        // Create new composed or draw current layer
464
                        composed = layer.newComposedLayer();
465
                        if (composed == null) {
466
                            LOG.debug("Drawing layer {} ", layer);
467
                            draw(layer, image, g, cancel, scale);
468
                        } else {
469
                            addToComposedLayer(composed, layer);
470
                        }
471
                    }
472
                }
473
            }
474
            if (composed != null) {
475
                // Draw the pending composed
476
                draw(composed, image, g, cancel, scale);
477
            }
478

    
479
            // Check if the last layer is the last of a group and close it
480
            for (int i = lastLayerPos + 1; i < all.size(); i++) {
481
                Object group = all.get(i);
482
                if (group instanceof LayersGroupEvent) {
483
                    LayersGroupEvent event = (LayersGroupEvent) group;
484
                    if (event.type == LayersGroupEvent.OUT_Event) {
485
                        event.group.endDraw(g, viewPort);
486
                    }
487
                    break;
488
                }
489
            }
490
        }
491

    
492
        private void addToComposedLayer(ComposedLayer composed, FLayer layer)
493
                throws ReadException {
494
            try {
495
                LOG.debug("Adding layer {} to composed layer ", layer, composed);
496
                composed.add(layer);
497
            } catch (Exception e) {
498
                throw new ReadException("DefalutMapContexDrawer exception", e);
499
            }
500
        }
501

    
502
        private void draw(Object layerOrComposed, BufferedImage image,
503
                Graphics2D g, Cancellable cancel, double scale)
504
                throws ReadException {
505
            ILabelable labelable = null;
506
            ILabelable tmp = null;
507
            if (layerOrComposed instanceof ILabelable) {
508

    
509
                tmp = (ILabelable) layerOrComposed;
510

    
511
                if (tmp.isLabeled() && tmp.getLabelingStrategy() != null
512
                        && tmp.getLabelingStrategy().shouldDrawLabels(scale)) {
513
                    labelable = tmp;
514
                }
515
            }
516

    
517
            if (layerOrComposed instanceof FLayer) {
518
                int beforeDrawEventType;
519
                int afterDrawEventType;
520
                if (layerOrComposed instanceof GraphicLayer) {
521
                    beforeDrawEventType = LayerDrawEvent.GRAPHICLAYER_BEFORE_DRAW;
522
                    afterDrawEventType = LayerDrawEvent.GRAPHICLAYER_AFTER_DRAW;
523
                } else {
524
                    beforeDrawEventType = LayerDrawEvent.LAYER_BEFORE_DRAW;
525
                    afterDrawEventType = LayerDrawEvent.LAYER_AFTER_DRAW;
526
                }
527
                FLayer layer = (FLayer) layerOrComposed;
528
                drawLayer(layer, image, g, cancel, scale, beforeDrawEventType,
529
                        afterDrawEventType);
530
            } else {
531
                ComposedLayer composed = (ComposedLayer) layerOrComposed;
532
                composed.draw(image, g, viewPort, cancel, scale);
533
            }
534
            if (labelable != null) {
535
                labelable.drawLabels(image, g, viewPort, cancel, scale,
536
                        mapContext.getViewPort().getDPI());
537
            }
538

    
539
        }
540

    
541
        protected void drawLayer(FLayer layer, BufferedImage image,
542
                Graphics2D g, Cancellable cancel, double scale,
543
                int beforeDrawEventType, int afterDrawEventType)
544
                throws ReadException {
545
            LayerDrawEvent event = new LayerDrawEvent(layer, g, viewPort, beforeDrawEventType);
546
            mapContext.fireLayerDrawingEvent(event);
547
            layer.draw(image, g, viewPort, cancel, scale);
548
            event = new LayerDrawEvent(layer, g, viewPort, afterDrawEventType);
549
            mapContext.fireLayerDrawingEvent(event);
550
        }
551

    
552
    }
553

    
554
    private class SimpleLayerIterator extends LayersIterator {
555

    
556
        public SimpleLayerIterator(FLayer layer) {
557
            this.appendLayer(layer);
558
        }
559

    
560
        public boolean evaluate(FLayer layer) {
561
            if (layer instanceof FLayers) {
562
                return false;
563
            }
564
            return layer.isAvailable() && layer.isVisible();
565
        }
566

    
567
    }
568

    
569
    public void dispose() {
570
        this.mapContext = null;
571
        this.viewPort = null;
572
        this.cachedImage = null;
573
        this.previousDrawList = null;
574
    }
575

    
576
    public void print(FLayers root, Graphics2D g, Cancellable cancel,
577
            double scale, PrintAttributes properties) throws ReadException {
578
        this.checkInitialized();
579

    
580
        List printList = this.createPrintList(root, cancel);
581
        if (cancel.isCanceled()) {
582
            return;
583
        }
584

    
585
        ComposedLayer composed = null;
586
        int pos;
587
        FLayer layer;
588
        int layerPos = -1;
589
        Object obj;
590
        LayersGroupEvent event;
591
        for (pos = 0; pos < printList.size(); pos++) {
592
            if (cancel.isCanceled()) {
593
                return;
594
            }
595

    
596
            obj = printList.get(pos);
597
            if (obj instanceof LayersGroupEvent) {
598
                event = (LayersGroupEvent) obj;
599
                if (event.type == LayersGroupEvent.IN_Event) {
600
                    // System.out.println("=======Empiza a pintar grupo de capas "+
601
                    // ((FLayers)event.group).getName() +"============");
602
                    event.group.beginDraw(g, viewPort);
603
                } else {
604
                    event.group.endDraw(g, viewPort);
605
                    // System.out.println("=======Fin a pintar grupo de capas "+
606
                    // ((FLayers)event.group).getName() +"============");
607

    
608
                }
609
                continue;
610
            }
611
            layerPos++;
612

    
613
            layer = (FLayer) obj;
614

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

    
674
    }
675

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

    
701
    private List createPrintList(FLayers root, Cancellable cancel) {
702
        List result = new ArrayList();
703
        Iterator iter = new SimpleLayerIterator((FLayer) root);
704
        while (iter.hasNext()) {
705
            if (cancel.isCanceled()) {
706
                return null;
707
            }
708
            result.add(iter.next());
709
        }
710
        return result;
711
    }
712

    
713
    private class MyLayerIterator implements Iterator {
714

    
715
        List layersList = new ArrayList();
716
        int index = 0;
717
        double scale = 0;
718

    
719
        public MyLayerIterator(FLayer layer, double scale) {
720
            this.scale = scale;
721
            this.appendLayer(layer);
722
        }
723

    
724
        protected void appendLayer(FLayer layer) {
725
            if (layer instanceof LayerCollection) {
726
                appendLayers((LayerCollection) layer);
727
            } else if (this.evaluate(layer)) {
728
                layersList.add(layer);
729
            }
730
        }
731

    
732
        private void appendLayers(LayerCollection layers) {
733
            int i;
734
            layersList.add(new LayersGroupEvent(layers,
735
                    LayersGroupEvent.IN_Event));
736
            for (i = 0; i < layers.getLayersCount(); i++) {
737
                appendLayer(layers.getLayer(i));
738
            }
739
            layersList.add(new LayersGroupEvent(layers,
740
                    LayersGroupEvent.OUT_Event));
741
        }
742

    
743
        public void remove() {
744
            throw new UnsupportedOperationException();
745
        }
746

    
747
        public boolean hasNext() {
748
            return index < layersList.size();
749
        }
750

    
751
        public Object next() {
752
            if (!this.hasNext()) {
753
                throw new NoSuchElementException();
754
            }
755
            Object aux = layersList.get(index);
756
            index++;
757
            return aux;
758
        }
759

    
760
        public boolean evaluate(FLayer layer) {
761
            if (layer instanceof LayerCollection) {
762
                return false;
763
            }
764
            return layer.isAvailable() && layer.isVisible()
765
                    && layer.isWithinScale(this.scale);
766
        }
767

    
768
    }
769

    
770
    private class LayersGroupEvent {
771

    
772
        public static final String IN_Event = "in";
773
        public static final String OUT_Event = "Out";
774

    
775
        private LayerCollection group = null;
776
        private String type = IN_Event;
777

    
778
        public LayersGroupEvent(LayerCollection group, String type) {
779
            this.group = group;
780
            this.type = type;
781
        }
782

    
783
        public String getType() {
784
            return type;
785
        }
786

    
787
        public LayerCollection getGroup() {
788
            return group;
789
        }
790
    }
791

    
792
    public static class RegisterMapContextDrawer implements Callable {
793

    
794
        public Object call() {
795
            MapContextManager manager = MapContextLocator.getMapContextManager();
796
            try {
797
                manager.setDefaultMapContextDrawer(DefaultMapContextDrawer.class);
798
            } catch (MapContextException ex) {
799
                throw new RuntimeException("Can't register the default MapContextDrawer", ex);
800
            }
801
            return Boolean.TRUE;
802
        }
803
    }
804
}