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

History | View | Annotate | Download (30.1 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
    private boolean printGraphicsLayer;
69

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

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

    
80
        this.checkInitialized();
81

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

    
87
        AffineTransform aux_at = null;
88

    
89
        if (isValidFullCachedImage()) {
90

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

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

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

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

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

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

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

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

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

    
167
        this.previousDrawList = drawList;
168

    
169
    }
170

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

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

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

    
188
            tmp = (ILabelable) layerOrComposed;
189

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

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

    
207
    }
208

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

    
216
    }
217

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

    
225
    }
226

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

    
231
    @Override
232
    public boolean isPrintGraphicsLayer() {
233
        return this.printGraphicsLayer;
234
    }
235

    
236
    @Override
237
    public void setPrintGraphicsLayer(boolean b) {
238
        this.printGraphicsLayer = b;
239
    }
240

    
241
    public class CachedImage {
242

    
243
        private BufferedImage partialDrawnImage;
244
        private BufferedImage fullDrawnImage;
245
        private long lastMapContextVersion;
246
        private long lastViewPortVersion;
247
        private int lastDrawnLayerPosition;
248

    
249
        public void setPartialDrawnImage(BufferedImage partialDrawnImage,
250
                MapContext mapContext, ViewPort viewPort,
251
                int lastDrawnLayerPosition) {
252
            this.partialDrawnImage = CompatLocator.getGraphicsUtils()
253
                    .copyBufferedImage(partialDrawnImage);
254
            this.lastDrawnLayerPosition = lastDrawnLayerPosition;
255
            updateVersions(mapContext, viewPort);
256
        }
257

    
258
        public void updateVersions(MapContext mapContext, ViewPort viewPort) {
259
            this.lastMapContextVersion = mapContext.getDrawVersion();
260
            this.lastViewPortVersion = viewPort.getDrawVersion();
261
        }
262

    
263
        public void setFullDrawnImage(BufferedImage fullDrawnImage) {
264
            this.fullDrawnImage = CompatLocator.getGraphicsUtils()
265
                    .copyBufferedImage(fullDrawnImage);
266
        }
267

    
268
        public BufferedImage getPartialDrawnImage() {
269
            return partialDrawnImage;
270
        }
271

    
272
        public BufferedImage getFullDrawnImage() {
273
            return fullDrawnImage;
274
        }
275

    
276
        public long getMapContextVersion() {
277
            return lastMapContextVersion;
278
        }
279

    
280
        public int getLastDrawnLayerPosition() {
281
            return this.lastDrawnLayerPosition;
282
        }
283

    
284
        public boolean isValidFullDrawnImage(MapContext context) {
285
            // If the MapContext version has not changed, there are not any
286
            // changes that require redrawing any of the layers.
287
            return fullDrawnImage != null && !hasChangedMapContextDrawVersion();
288
        }
289

    
290
        public boolean hasChangedMapContextDrawVersion() {
291
            // This change detects changes in layers and the viewport also
292
            return mapContext.getDrawVersion() != this.lastMapContextVersion;
293
        }
294

    
295
        public boolean hasChangedViewPortDrawVersion() {
296
            // This change detects changes in the viewport
297
            return viewPort.getDrawVersion() != this.lastViewPortVersion;
298
        }
299

    
300
        public boolean isValidPartialDrawnImage(MapContext context,
301
                DrawList drawList) {
302
            if (!hasChangedMapContextDrawVersion()) {
303
                // Nothing has changed
304
                return true;
305
            }
306

    
307
            if (partialDrawnImage == null || hasChangedViewPortDrawVersion()) {
308
                // No image available or changes in view port
309
                return false;
310
            }
311

    
312
            if (drawList.size() < lastDrawnLayerPosition + 1) {
313
                // New list has fewer layers than before
314
                return false;
315
            }
316

    
317
            // There is any change in the layers drawn in the partial drawn
318
            // image?
319
            return drawList.getFirstChangedLayer() > lastDrawnLayerPosition;
320
        }
321
    }
322

    
323
    public class DrawList {
324

    
325
        private List layers = new ArrayList();
326
        private List all = new ArrayList();
327
        private List versions = new ArrayList();
328
        private DrawList previosList = null;
329
        private int firstLayerChanged = -1;
330

    
331
        public DrawList() {
332
        }
333

    
334
        public DrawList(DrawList previousList) {
335
            if (previousList != null) {
336
                this.firstLayerChanged = previousList.getLayerCount();
337
                this.previosList = previousList;
338
            }
339
        }
340

    
341
        public int getLayerCount() {
342
            return this.layers.size();
343
        }
344

    
345
        public int getLastLayerVisible(ViewPort viewPort) {
346
            Envelope area = viewPort.getAdjustedEnvelope();
347
            for (int n = 0; n < this.layers.size() - 1; n++) {
348
                FLayer layer = (FLayer) this.layers.get(n);
349
                if (layer instanceof FLayerHidesArea) {
350
                    if (((FLayerHidesArea) (layer)).hidesThisArea(area)) {
351
                        return n;
352
                    }
353
                }
354
            }
355
            return this.layers.size() - 1;
356
        }
357

    
358
        private boolean hasChanged(FLayer layer, int pos) {
359
            FLayer previous = (FLayer) this.previosList.layers.get(pos);
360
            // String previousName = previous.getName();
361
            // String layerName = layer.getName();
362
            if (previous != layer) {
363
                return true;
364
            }
365
            long previousVersion = ((Long) this.previosList.versions.get(pos))
366
                    .longValue();
367
            long layerVersion = layer.getDrawVersion();
368

    
369
            return previousVersion != layerVersion;
370
        }
371

    
372
        public void add(Object obj) {
373
            if (obj instanceof FLayer) {
374
                FLayer layer = (FLayer) obj;
375
                int curIndex = this.layers.size();
376
                if (this.firstLayerChanged >= curIndex) {
377
                    if (this.previosList.getLayerCount() > curIndex) {
378
                        if (this.hasChanged(layer, curIndex)) {
379
                            this.firstLayerChanged = curIndex;
380
                        }
381
                    } else if (this.previosList.getLayerCount() == curIndex) {
382
                        this.firstLayerChanged = curIndex;
383
                    }
384
                }
385
                this.layers.add(layer);
386
                this.versions.add(new Long(layer.getDrawVersion()));
387
            } else if (!(obj instanceof LayersGroupEvent)) {
388
                throw new UnsupportedOperationException();
389
            }
390

    
391
            this.all.add(obj);
392
        }
393

    
394
        public int size() {
395
            return this.all.size();
396
        }
397

    
398
        public int getFirstChangedLayer() {
399
            if (this.firstLayerChanged > this.layers.size()) {
400
                this.firstLayerChanged = this.layers.size();
401
            }
402
            return this.firstLayerChanged;
403
        }
404

    
405
        public FLayer getLayer(int pos) {
406
            return (FLayer) this.layers.get(pos);
407
        }
408

    
409
        public Object get(int pos) {
410
            return this.all.get(pos);
411
        }
412

    
413
        public void drawLayers(BufferedImage image, Graphics2D g,
414
                int firstLayerToDraw, int lastLayerToDraw, Cancellable cancel,
415
                double scale) throws ReadException {
416

    
417
            if (firstLayerToDraw > lastLayerToDraw) {
418
                LOG.debug("Nothing to draw");
419
                return;
420
            }
421

    
422
            // Find the real layer positions excluding LayersGroupEvents
423
            FLayer firstLayer = (FLayer) layers.get(firstLayerToDraw);
424
            int firstLayerPos = all.indexOf(firstLayer);
425
            // Look if it belongs to a group and start it
426
            if (firstLayerPos > 0) {
427
                for (int i = firstLayerPos - 1; i < all.size(); i++) {
428
                    // firstLayer
429
                    Object group = all.get(i);
430
                    if (group instanceof LayersGroupEvent) {
431
                        LayersGroupEvent event = (LayersGroupEvent) group;
432
                        if (event.type == LayersGroupEvent.IN_Event) {
433
                            event.group.beginDraw(g, viewPort);
434
                        }
435
                        break;
436
                    }
437
                }
438
            }
439
            FLayer lastLayer = (FLayer) layers.get(lastLayerToDraw);
440
            int lastLayerPos = all.indexOf(lastLayer);
441

    
442
            LOG.debug("Drawing from layer {} in position (layers: {}, all: {})"
443
                    + " to layer {} in position (layers: {}, all: {})",
444
                    new Object[]{firstLayer, new Integer(firstLayerToDraw),
445
                        new Integer(firstLayerPos), lastLayer,
446
                        new Integer(lastLayerToDraw),
447
                        new Integer(lastLayerPos)});
448

    
449
            ComposedLayer composed = null;
450
            for (int pos = firstLayerPos; pos <= lastLayerPos; pos++) {
451
                if (cancel.isCanceled()) {
452
                    return;
453
                }
454

    
455
                Object layerOrGroup = get(pos);
456

    
457
                // Group drawing events management
458
                if (layerOrGroup instanceof LayersGroupEvent) {
459
                    LayersGroupEvent event = (LayersGroupEvent) layerOrGroup;
460
                    if (event.type == LayersGroupEvent.IN_Event) {
461
                        event.group.beginDraw(g, viewPort);
462
                    } else {
463
                        event.group.endDraw(g, viewPort);
464
                    }
465
                } else {
466
                    FLayer layer = (FLayer) layerOrGroup;
467
                    if (composed != null && composed.canAdd(layer)) {
468
                        // Previous or current layer could be composed
469
                        // Add current layer
470
                        addToComposedLayer(composed, layer);
471
                    } else {
472
                        if (composed != null) {
473
                            // Current layer can't be composed on the previous
474
                            // composedlayer. Draw previous composed
475
                            LOG.debug("Drawing composed layer {} ", composed);
476
                            draw(composed, image, g, cancel, scale);
477
                            composed = null;
478
                        }
479

    
480
                        // Try if the current layer can be composed
481
                        // Create new composed or draw current layer
482
                        composed = layer.newComposedLayer();
483
                        if (composed == null) {
484
                            LOG.debug("Drawing layer {} ", layer);
485
                            draw(layer, image, g, cancel, scale);
486
                        } else {
487
                            addToComposedLayer(composed, layer);
488
                        }
489
                    }
490
                }
491
            }
492
            if (composed != null) {
493
                // Draw the pending composed
494
                draw(composed, image, g, cancel, scale);
495
            }
496

    
497
            // Check if the last layer is the last of a group and close it
498
            for (int i = lastLayerPos + 1; i < all.size(); i++) {
499
                Object group = all.get(i);
500
                if (group instanceof LayersGroupEvent) {
501
                    LayersGroupEvent event = (LayersGroupEvent) group;
502
                    if (event.type == LayersGroupEvent.OUT_Event) {
503
                        event.group.endDraw(g, viewPort);
504
                    }
505
                    break;
506
                }
507
            }
508
        }
509

    
510
        private void addToComposedLayer(ComposedLayer composed, FLayer layer)
511
                throws ReadException {
512
            try {
513
                LOG.debug("Adding layer {} to composed layer ", layer, composed);
514
                composed.add(layer);
515
            } catch (Exception e) {
516
                throw new ReadException("DefalutMapContexDrawer exception", e);
517
            }
518
        }
519

    
520
        private void draw(Object layerOrComposed, BufferedImage image,
521
                Graphics2D g, Cancellable cancel, double scale)
522
                throws ReadException {
523
            ILabelable labelable = null;
524
            ILabelable tmp = null;
525
            if (layerOrComposed instanceof ILabelable) {
526

    
527
                tmp = (ILabelable) layerOrComposed;
528

    
529
                if (tmp.isLabeled() && tmp.getLabelingStrategy() != null
530
                        && tmp.getLabelingStrategy().shouldDrawLabels(scale)) {
531
                    labelable = tmp;
532
                }
533
            }
534

    
535
            if (layerOrComposed instanceof FLayer) {
536
                int beforeDrawEventType;
537
                int afterDrawEventType;
538
                if (layerOrComposed instanceof GraphicLayer) {
539
                    beforeDrawEventType = LayerDrawEvent.GRAPHICLAYER_BEFORE_DRAW;
540
                    afterDrawEventType = LayerDrawEvent.GRAPHICLAYER_AFTER_DRAW;
541
                } else {
542
                    beforeDrawEventType = LayerDrawEvent.LAYER_BEFORE_DRAW;
543
                    afterDrawEventType = LayerDrawEvent.LAYER_AFTER_DRAW;
544
                }
545
                FLayer layer = (FLayer) layerOrComposed;
546
                drawLayer(layer, image, g, cancel, scale, beforeDrawEventType,
547
                        afterDrawEventType);
548
            } else {
549
                ComposedLayer composed = (ComposedLayer) layerOrComposed;
550
                composed.draw(image, g, viewPort, cancel, scale);
551
            }
552
            if (labelable != null) {
553
                labelable.drawLabels(image, g, viewPort, cancel, scale,
554
                        mapContext.getViewPort().getDPI());
555
            }
556

    
557
        }
558

    
559
        protected void drawLayer(FLayer layer, BufferedImage image,
560
                Graphics2D g, Cancellable cancel, double scale,
561
                int beforeDrawEventType, int afterDrawEventType)
562
                throws ReadException {
563
            LayerDrawEvent event = new LayerDrawEvent(layer, g, viewPort, beforeDrawEventType);
564
            mapContext.fireLayerDrawingEvent(event);
565
            layer.draw(image, g, viewPort, cancel, scale);
566
            event = new LayerDrawEvent(layer, g, viewPort, afterDrawEventType);
567
            mapContext.fireLayerDrawingEvent(event);
568
        }
569

    
570
    }
571

    
572
    private class SimpleLayerIterator extends LayersIterator {
573

    
574
        public SimpleLayerIterator(FLayer layer) {
575
            this.appendLayer(layer);
576
        }
577

    
578
        public boolean evaluate(FLayer layer) {
579
            if (layer instanceof FLayers) {
580
                return false;
581
            }
582
            return layer.isAvailable() && layer.isVisible();
583
        }
584

    
585
    }
586

    
587
    public void dispose() {
588
        this.mapContext = null;
589
        this.viewPort = null;
590
        this.cachedImage = null;
591
        this.previousDrawList = null;
592
    }
593

    
594
    public void print(FLayers root, Graphics2D g, Cancellable cancel,
595
            double scale, PrintAttributes properties) throws ReadException {
596
        this.checkInitialized();
597

    
598
        List printList = this.createPrintList(root, cancel, scale);
599
        if (cancel.isCanceled()) {
600
            return;
601
        }
602

    
603
        ComposedLayer composed = null;
604
        int pos;
605
        FLayer layer;
606
        int layerPos = -1;
607
        Object obj;
608
        LayersGroupEvent event;
609
        for (pos = 0; pos < printList.size(); pos++) {
610
            if (cancel.isCanceled()) {
611
                return;
612
            }
613

    
614
            obj = printList.get(pos);
615
            if (obj instanceof LayersGroupEvent) {
616
                event = (LayersGroupEvent) obj;
617
                if (event.type == LayersGroupEvent.IN_Event) {
618
                    // System.out.println("=======Empiza a pintar grupo de capas "+
619
                    // ((FLayers)event.group).getName() +"============");
620
                    event.group.beginDraw(g, viewPort);
621
                } else {
622
                    event.group.endDraw(g, viewPort);
623
                    // System.out.println("=======Fin a pintar grupo de capas "+
624
                    // ((FLayers)event.group).getName() +"============");
625

    
626
                }
627
                continue;
628
            }
629
            layerPos++;
630

    
631
            layer = (FLayer) obj;
632

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

    
692
    }
693

    
694
    private DrawList createDrawList(FLayers root, Cancellable cancel,
695
            double scale) {
696
        DrawList result = new DrawList(this.previousDrawList);
697
        Iterator iter = new MyLayerIterator((FLayer) root, scale);
698
        while (iter.hasNext()) {
699
            if (cancel.isCanceled()) {
700
                return null;
701
            }
702
            result.add(iter.next());
703
        }
704
        if (cancel.isCanceled()) {
705
            return null;
706
        }
707
        // Take into account also the Graphic layer
708
        for (VectorLayer graphicsLayer : mapContext.getGraphicsLayers()) {
709
            if (graphicsLayer != null && 
710
                    graphicsLayer.isAvailable() &&
711
                    graphicsLayer.isVisible() && 
712
                    graphicsLayer.isWithinScale(scale)) {
713
                result.add(graphicsLayer);
714
            }
715
        }
716
        return result;
717
    }
718

    
719
    private List createPrintList(FLayers root, Cancellable cancel, double scale) {
720
        List result = new ArrayList();
721
        Iterator iter = new SimpleLayerIterator((FLayer) root);
722
        while (iter.hasNext()) {
723
            if (cancel.isCanceled()) {
724
                return null;
725
            }
726
            result.add(iter.next());
727
        }
728
        if(this.printGraphicsLayer){
729
            // Take into account also the Graphic layer
730
            for (VectorLayer graphicsLayer : mapContext.getGraphicsLayers()) {
731
                if (graphicsLayer != null && 
732
                        graphicsLayer.isAvailable() &&
733
                        graphicsLayer.isVisible() && 
734
                        graphicsLayer.isWithinScale(scale)) {
735
                    result.add(graphicsLayer);
736
                }
737
            }
738
        }
739
        return result;
740
    }
741

    
742
    private class MyLayerIterator implements Iterator {
743

    
744
        List layersList = new ArrayList();
745
        int index = 0;
746
        double scale = 0;
747

    
748
        public MyLayerIterator(FLayer layer, double scale) {
749
            this.scale = scale;
750
            this.appendLayer(layer);
751
        }
752

    
753
        protected void appendLayer(FLayer layer) {
754
            if (layer instanceof LayerCollection) {
755
                appendLayers((LayerCollection) layer);
756
            } else if (this.evaluate(layer)) {
757
                layersList.add(layer);
758
            }
759
        }
760

    
761
        private void appendLayers(LayerCollection layers) {
762
            int i;
763
            layersList.add(new LayersGroupEvent(layers,
764
                    LayersGroupEvent.IN_Event));
765
            for (i = 0; i < layers.getLayersCount(); i++) {
766
                appendLayer(layers.getLayer(i));
767
            }
768
            layersList.add(new LayersGroupEvent(layers,
769
                    LayersGroupEvent.OUT_Event));
770
        }
771

    
772
        public void remove() {
773
            throw new UnsupportedOperationException();
774
        }
775

    
776
        public boolean hasNext() {
777
            return index < layersList.size();
778
        }
779

    
780
        public Object next() {
781
            if (!this.hasNext()) {
782
                throw new NoSuchElementException();
783
            }
784
            Object aux = layersList.get(index);
785
            index++;
786
            return aux;
787
        }
788

    
789
        public boolean evaluate(FLayer layer) {
790
            if (layer instanceof LayerCollection) {
791
                return false;
792
            }
793
            return layer.isAvailable() && layer.isVisible()
794
                    && layer.isWithinScale(this.scale);
795
        }
796

    
797
    }
798

    
799
    private class LayersGroupEvent {
800

    
801
        public static final String IN_Event = "in";
802
        public static final String OUT_Event = "Out";
803

    
804
        private LayerCollection group = null;
805
        private String type = IN_Event;
806

    
807
        public LayersGroupEvent(LayerCollection group, String type) {
808
            this.group = group;
809
            this.type = type;
810
        }
811

    
812
        public String getType() {
813
            return type;
814
        }
815

    
816
        public LayerCollection getGroup() {
817
            return group;
818
        }
819
    }
820

    
821
    public static class RegisterMapContextDrawer implements Callable {
822

    
823
        public Object call() {
824
            MapContextManager manager = MapContextLocator.getMapContextManager();
825
            try {
826
                manager.setDefaultMapContextDrawer(DefaultMapContextDrawer.class);
827
            } catch (MapContextException ex) {
828
                throw new RuntimeException("Can't register the default MapContextDrawer", ex);
829
            }
830
            return Boolean.TRUE;
831
        }
832
    }
833
}