Statistics
| Revision:

svn-gvsig-desktop / branches / v2_0_0_prep / libraries / libFMap_mapcontext / src / org / gvsig / fmap / mapcontext / impl / DefaultMapContextDrawer.java @ 38200

History | View | Annotate | Download (16.7 KB)

1
package org.gvsig.fmap.mapcontext.impl;
2

    
3
import java.awt.Graphics2D;
4
import java.awt.image.BufferedImage;
5
import java.util.ArrayList;
6
import java.util.Iterator;
7
import java.util.List;
8
import java.util.NoSuchElementException;
9

    
10
import org.gvsig.compat.CompatLocator;
11
import org.gvsig.compat.print.PrintAttributes;
12
import org.gvsig.fmap.dal.exception.ReadException;
13
import org.gvsig.fmap.mapcontext.MapContext;
14
import org.gvsig.fmap.mapcontext.MapContextDrawer;
15
import org.gvsig.fmap.mapcontext.ViewPort;
16
import org.gvsig.fmap.mapcontext.layers.FLayer;
17
import org.gvsig.fmap.mapcontext.layers.FLayers;
18
import org.gvsig.fmap.mapcontext.layers.LayersIterator;
19
import org.gvsig.fmap.mapcontext.layers.operations.ComposedLayer;
20
import org.gvsig.fmap.mapcontext.layers.operations.LayerCollection;
21
import org.gvsig.fmap.mapcontext.rendering.legend.styling.ILabelable;
22
import org.gvsig.tools.task.Cancellable;
23

    
24
public class DefaultMapContextDrawer implements MapContextDrawer {
25
        private MapContext mapContext = null;
26
        private ViewPort viewPort = null;
27
        private CachedImage cachedImage = null;
28
        private DrawList previousDrawList = null;
29

    
30
        public DefaultMapContextDrawer() {
31

    
32
        }
33

    
34
        protected void checkIntilalized() {
35
                if (mapContext == null || viewPort == null) {
36
                        throw new IllegalStateException(
37
                                        "MapContext and ViewPort must be set");
38
                }
39
        }
40

    
41
        protected boolean isLayerCacheable(FLayer layer) {
42
                return layer.isActive();
43
        }
44

    
45
        public void draw(FLayers root, BufferedImage image, Graphics2D g,
46
                        Cancellable cancel, double scale) throws ReadException {
47

    
48
                this.checkIntilalized();
49

    
50
                boolean needToPaintAll = false;
51

    
52
                DrawList drawList = this.createDrawList(root, cancel, scale);
53
                if (cancel.isCanceled()) {
54
                        return;
55
                }
56

    
57
                if (cachedImage == null) {
58
                        needToPaintAll = true;
59
                } else if (!cachedImage.isValid(mapContext, viewPort,
60
                                drawList.getFirstLayerToDraw())) {
61
                        needToPaintAll = true;
62
                }
63

    
64
                int firstLayer = 0;
65
                if (!needToPaintAll) {
66
                        firstLayer = cachedImage.getListPosition() + 1;
67
                        // System.out.println("=======Pintando a partir de la pos "+
68
                        // firstLayer+"============");
69
                        g.drawImage(cachedImage.getImage(), 0, 0, null);
70
                        // System.out.println("=======Pintando imagen ============");
71

    
72
                } else {
73
                        this.cachedImage = null;
74
                        // System.out.println("=======Pintando todo============");
75
                }
76

    
77
                boolean cached = false;
78
                ComposedLayer composed = null;
79
                int pos;
80
                int layerPos = -1;
81
                FLayer layer;
82
                Object obj;
83
                LayersGroupEvent event;
84
                for (pos = 0; pos < drawList.size(); pos++) {
85
                        if (cancel.isCanceled()) {
86
                                return;
87
                        }
88

    
89
                        obj = drawList.get(pos);
90

    
91
                        // *** Gestion de eventos de pintado de grupos ***
92
                        if (obj instanceof LayersGroupEvent) {
93
                                event = (LayersGroupEvent) obj;
94
                                if (event.type == LayersGroupEvent.IN_Event) {
95
                                        // System.out.println("=======Empiza a pintar grupo de capas "+
96
                                        // ((FLayers)event.group).getName() +"============");
97
                                        event.group.beginDraw(g, viewPort);
98
                                } else {
99
                                        event.group.endDraw(g, viewPort);
100
                                        // System.out.println("=======Fin a pintar grupo de capas "+
101
                                        // ((FLayers)event.group).getName() +"============");
102

    
103
                                }
104
                                continue;
105
                        }
106
                        layerPos++;
107
                        if (layerPos < firstLayer) {
108
                                continue;
109
                        }
110

    
111
                        layer = (FLayer) obj;
112
                        if (cancel.isCanceled()) {
113
                                return;
114
                        }
115

    
116
                        // *** Gestion de cache ***
117
                        if ((!cached) && this.isLayerCacheable(layer)) {
118
                                if (layerPos > 0) { // La primera capa es la activa, no
119
                                                                        // cacheamos
120
                                        if (cachedImage == null
121
                                                        || cachedImage.getListPosition() < layerPos - 1) {
122

    
123
                                                if (composed != null) {
124
                                                        // si tenemos una composicion de capas, necesitamos
125
                                                        // pintarlas
126
                                                        // antes de guardarnos la imagen
127
                                                        // System.out.println("=======Pintando composicion de pintado "+
128
                                                        // (layerPos-1)+" (antes de cache)============");
129
                                                        this.draw(composed, image, g, cancel, scale);
130
                                                        // composed.draw(image, g, viewPort, cancel, scale);
131
                                                        composed = null;
132

    
133
                                                }
134
                                                CachedImage newCached = new CachedImage();
135
                                                newCached.setImage(image, mapContext, viewPort,
136
                                                                layerPos - 1);
137
                                                this.cachedImage = newCached;
138
                                                // System.out.println("=======Guardando imagen de la pos "+
139
                                                // (layerPos-1)+" ("+ newCached.getListPosition()
140
                                                // +")============");
141
                                        }
142
                                }
143
                                cached = true;
144
                        }
145
                        if (cancel.isCanceled()) {
146
                                return;
147
                        }
148

    
149
                        if (composed == null) {
150
                                composed = layer.newComposedLayer();
151
                                if (composed != null) {
152
                                        try {
153
                                                // System.out.println("=== a?adiendo a composicion de pintado "+
154
                                                // layerPos+ " "+layer.getName());
155
                                                composed.add(layer);
156
                                                continue;
157
                                        } catch (Exception e) {
158
                                                throw new ReadException(
159
                                                                "DefalutMapContexDrawer exception", e);
160
                                        }
161
                                }
162
                        } else {
163
                                if (composed.canAdd(layer)) {
164
                                        try {
165
                                                // System.out.println("=== a?adiendo a composicion de pintado "+
166
                                                // layerPos+ " "+layer.getName());
167
                                                composed.add(layer);
168
                                                continue;
169
                                        } catch (Exception e) {
170
                                                throw new ReadException(
171
                                                                "DefalutMapContexDrawer exception", e);
172
                                        }
173
                                } else {
174
                                        // System.out.println("=======Pintando composicion de pintado "+
175
                                        // (layerPos-1)+" (cambio composicion)============");
176
                                        this.draw(composed, image, g, cancel, scale);
177
                                        // composed.draw(image, g, viewPort, cancel, scale);
178
                                        composed = layer.newComposedLayer();
179
                                        if (composed != null) {
180
                                                try {
181
                                                        // System.out.println("=== a?adiendo a composicion de pintado "+
182
                                                        // layerPos+ " "+layer.getName());
183
                                                        composed.add(layer);
184
                                                        continue;
185
                                                } catch (Exception e) {
186
                                                        throw new ReadException(
187
                                                                        "DefalutMapContexDrawer exception", e);
188
                                                }
189
                                        }
190
                                }
191
                        }
192
                        // System.out.println("=== pintando "+ layerPos+
193
                        // " "+layer.getName());
194
                        this.draw(layer, image, g, cancel, scale);
195
                        // layer.draw(image, g, viewPort, cancel, scale);
196

    
197
                }
198
                if (composed != null) {
199
                        // si la composicion no se ha pintado la pintamos
200
                        // System.out.println("=======Pintando composicion de pintado "+
201
                        // (layerPos-1)+" (ultimo)============");
202
                        this.draw(composed, image, g, cancel, scale);
203
                        // composed.draw(image, g, viewPort, cancel, scale);
204
                }
205
                if (cancel.isCanceled()) {
206
                        return;
207
                }
208

    
209
                this.previousDrawList = drawList;
210

    
211
        }
212

    
213
        private void draw(Object layerOrComposed, BufferedImage image,
214
                        Graphics2D g, Cancellable cancel, double scale)
215
                        throws ReadException {
216
                ILabelable labelable = null;
217
                ILabelable tmp = null;
218
                if (layerOrComposed instanceof ILabelable) {
219

    
220
                        tmp = (ILabelable) layerOrComposed;
221

    
222
                        if (tmp.isLabeled() && tmp.getLabelingStrategy() != null
223
                                        && tmp.getLabelingStrategy().shouldDrawLabels(scale)) {
224
                                labelable = tmp;
225
                        }
226
                }
227
                if (layerOrComposed instanceof FLayer) {
228
                        FLayer layer = (FLayer) layerOrComposed;
229
                        layer.draw(image, g, viewPort, cancel, scale);
230
                } else {
231
                        ComposedLayer composed = (ComposedLayer) layerOrComposed;
232
                        composed.draw(image, g, viewPort, cancel, scale);
233
                }
234
                if (labelable != null) {
235
                        labelable.drawLabels(image, g, viewPort, cancel, scale,
236
                                        MapContext.getScreenDPI());
237
                }
238

    
239
        }
240

    
241
        private void print(Object layerOrComposed, Graphics2D g,
242
                        Cancellable cancel, double scale, PrintAttributes properties)
243
                        throws ReadException {
244
                ILabelable labelable = null;
245
                ILabelable tmp = null;
246
                if (layerOrComposed instanceof ILabelable) {
247

    
248
                        tmp = (ILabelable) layerOrComposed;
249

    
250
                        if (tmp.isLabeled() && tmp.getLabelingStrategy() != null
251
                                        && tmp.getLabelingStrategy().shouldDrawLabels(scale)) {
252
                                labelable = tmp;
253
                        }
254
                }
255

    
256
                if (layerOrComposed instanceof FLayer) {
257
                        FLayer layer = (FLayer) layerOrComposed;
258
                        layer.print(g, viewPort, cancel, scale, properties);
259
                } else {
260
                        ComposedLayer composed = (ComposedLayer) layerOrComposed;
261
                        composed.print(g, viewPort, cancel, scale, properties);
262
                }
263
                if (labelable != null) {
264
                        labelable.printLabels(g, viewPort, cancel, scale, properties);
265
                }
266

    
267
        }
268

    
269
        public void setMapContext(MapContext mapContext) {
270
                if (this.mapContext == mapContext) {
271
                        return;
272
                }
273
                this.clean();
274
                this.mapContext = mapContext;
275

    
276
        }
277

    
278
        public void setViewPort(ViewPort viewPort) {
279
                if (this.viewPort == viewPort) {
280
                        return;
281
                }
282
                this.clean();
283
                this.viewPort = viewPort;
284

    
285
        }
286

    
287
        protected void clean() {
288
                this.cachedImage = null;
289
        }
290

    
291
        public class CachedImage {
292
                private BufferedImage image;
293
                private long mapContextVersion;
294
                private long viewPortVersion;
295
                private int listPosition;
296

    
297
                public void setImage(BufferedImage img, MapContext mapContext,
298
                                ViewPort viewPort, int pos) {
299

    
300
                        image = CompatLocator.getGraphicsUtils().copyBufferedImage(img);
301
                        this.mapContextVersion = mapContext.getDrawVersion();
302
                        this.viewPortVersion = viewPort.getDrawVersion();
303
                        this.listPosition = pos;
304
                }
305

    
306
                public BufferedImage getImage() {
307
                        return image;
308
                }
309

    
310
                public long getMapContextVersion() {
311
                        return mapContextVersion;
312
                }
313

    
314
                public long getViewPortVersion() {
315
                        return viewPortVersion;
316
                }
317

    
318
                public int getListPosition() {
319
                        return this.listPosition;
320
                }
321

    
322
                public boolean isValid(MapContext context, ViewPort viewPort,
323
                                int firstLayerToDraw) {
324
                        if (viewPort.getDrawVersion() > this.viewPortVersion) {
325
                                return false;
326
                        }
327
                        if (firstLayerToDraw <= this.listPosition) {
328
                                return false;
329
                        }
330
                        return true;
331
                }
332
        }
333

    
334
        public class DrawList {
335
                private List layers = new ArrayList();
336
                private List all = new ArrayList();
337
                private List versions = new ArrayList();
338
                private DrawList previosList = null;
339
                private int firstLayerToDraw = -1;
340

    
341
                public DrawList() {
342
                }
343

    
344
                public DrawList(DrawList previousList) {
345
                        if (previousList != null) {
346
                                this.firstLayerToDraw = previousList.getLayerCount();
347
                                this.previosList = previousList;
348
                        }
349
                }
350

    
351
                public int getLayerCount() {
352
                        return this.layers.size();
353
                }
354

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

    
366
                        return previousVersion != layerVersion;
367
                }
368

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

    
388
                        this.all.add(obj);
389
                }
390

    
391
                public int size() {
392
                        return this.all.size();
393
                }
394

    
395
                public int getFirstLayerToDraw() {
396
                        if (this.firstLayerToDraw > this.layers.size()) {
397
                                this.firstLayerToDraw = this.layers.size();
398
                        }
399
                        return this.firstLayerToDraw;
400
                }
401

    
402
                public FLayer getLayer(int pos) {
403
                        return (FLayer) this.layers.get(pos);
404
                }
405

    
406
                public Object get(int pos) {
407
                        return this.all.get(pos);
408
                }
409

    
410
        }
411

    
412
        private class SimpleLayerIterator extends LayersIterator {
413

    
414
                public SimpleLayerIterator(FLayer layer) {
415
                        this.appendLayer(layer);
416
                }
417

    
418
                public boolean evaluate(FLayer layer) {
419
                        if (layer instanceof FLayers) {
420
                                return false;
421
                        }
422
                        return layer.isAvailable() && layer.isVisible();
423
                }
424

    
425
        }
426

    
427
        public void dispose() {
428
                this.mapContext = null;
429
                this.viewPort = null;
430
                this.cachedImage = null;
431
                this.previousDrawList = null;
432
        }
433

    
434
        public void print(FLayers root, Graphics2D g, Cancellable cancel,
435
                        double scale, PrintAttributes properties) throws ReadException {
436
                this.checkIntilalized();
437

    
438
                List printList = this.createPrintList(root, cancel);
439
                if (cancel.isCanceled()) {
440
                        return;
441
                }
442

    
443
                ComposedLayer composed = null;
444
                int pos;
445
                FLayer layer;
446
                int layerPos = -1;
447
                Object obj;
448
                LayersGroupEvent event;
449
                for (pos = 0; pos < printList.size(); pos++) {
450
                        if (cancel.isCanceled()) {
451
                                return;
452
                        }
453

    
454
                        obj = printList.get(pos);
455
                        if (obj instanceof LayersGroupEvent) {
456
                                event = (LayersGroupEvent) obj;
457
                                if (event.type == LayersGroupEvent.IN_Event) {
458
                                        // System.out.println("=======Empiza a pintar grupo de capas "+
459
                                        // ((FLayers)event.group).getName() +"============");
460
                                        event.group.beginDraw(g, viewPort);
461
                                } else {
462
                                        event.group.endDraw(g, viewPort);
463
                                        // System.out.println("=======Fin a pintar grupo de capas "+
464
                                        // ((FLayers)event.group).getName() +"============");
465

    
466
                                }
467
                                continue;
468
                        }
469
                        layerPos++;
470

    
471
                        layer = (FLayer) obj;
472

    
473
                        // *** Pintado de capa/composicion de capa ***
474
                        if (composed == null) {
475
                                composed = layer.newComposedLayer();
476
                                if (composed != null) {
477
                                        try {
478
                                                composed.add(layer);
479
                                                // System.out.println("=======Imprimiendo composicion de pintado "+
480
                                                // (layerPos-1)+" ============");
481
                                                continue;
482
                                        } catch (Exception e) {
483
                                                throw new ReadException(
484
                                                                "DefaultMapContexDrawer exception", e);
485
                                        }
486
                                }
487
                        } else {
488
                                if (composed.canAdd(layer)) {
489
                                        try {
490
                                                composed.add(layer);
491
                                                // System.out.println("=== a?adiendo a composicion de pintado "+
492
                                                // layerPos+ " "+layer.getName());
493
                                                continue;
494
                                        } catch (Exception e) {
495
                                                throw new ReadException(
496
                                                                "DefaultMapContexDrawer exception", e);
497
                                        }
498
                                } else {
499
                                        // System.out.println("=======Imprimiendo composicion de pintado "+
500
                                        // (layerPos-1)+" ============");
501
                                        this.print(composed, g, cancel, scale, properties);
502
                                        // composed.print( g, viewPort, cancel, scale,properties);
503
                                        composed = layer.newComposedLayer();
504
                                        if (composed != null) {
505
                                                try {
506
                                                        composed.add(layer);
507
                                                        // System.out.println("=== a?adiendo a composicion de pintado "+
508
                                                        // layerPos+ " "+layer.getName());
509
                                                        continue;
510
                                                } catch (Exception e) {
511
                                                        throw new ReadException(
512
                                                                        "DefaultMapContexDrawer exception", e);
513
                                                }
514
                                        }
515
                                }
516
                        }
517
                        // System.out.println("=== imprimiendo "+ layerPos+
518
                        // " "+layer.getName());
519
                        this.print(layer, g, cancel, scale, properties);
520
                        // layer.print(g, viewPort, cancel, scale,properties);
521
                        // *** Pintado de capa/composicion de capa ***
522
                        if (composed != null) {
523
                                // si la composicion no se ha pintado la pintamos
524
                                // System.out.println("=======Imprimiendo composicion de pintado "+
525
                                // (layerPos-1)+" (ultimo) ============");
526
                                this.print(composed, g, cancel, scale, properties);
527
                                // composed.print(g, viewPort, cancel, scale, properties);
528
                                composed = null;
529
                        }
530
                }
531

    
532
        }
533

    
534
        private DrawList createDrawList(FLayers root, Cancellable cancel,
535
                        double scale) {
536
                DrawList result = new DrawList(this.previousDrawList);
537
                Iterator iter = new MyLayerIterator((FLayer) root, scale);
538
                while (iter.hasNext()) {
539
                        if (cancel.isCanceled()) {
540
                                return null;
541
                        }
542
                        result.add(iter.next());
543

    
544
                }
545

    
546
                return result;
547
        }
548

    
549
        private List createPrintList(FLayers root, Cancellable cancel) {
550
                List result = new ArrayList();
551
                Iterator iter = new SimpleLayerIterator((FLayer) root);
552
                while (iter.hasNext()) {
553
                        if (cancel.isCanceled()) {
554
                                return null;
555
                        }
556
                        result.add(iter.next());
557
                }
558
                return result;
559
        }
560

    
561
        private class MyLayerIterator implements Iterator {
562
                ArrayList layersList = new ArrayList();
563
                int index = 0;
564
                double scale = 0;
565

    
566
                public MyLayerIterator(FLayer layer, double scale) {
567
                        this.scale = scale;
568
                        this.appendLayer(layer);
569
                }
570

    
571
                protected void appendLayer(FLayer layer) {
572
                        if (this.evaluate(layer)) {
573
                                layersList.add(layer);
574
                        }
575
                        if (layer instanceof LayerCollection) {
576
                                appendLayers((LayerCollection) layer);
577
                        }
578
                }
579

    
580
                private void appendLayers(LayerCollection layers) {
581
                        int i;
582
                        layersList.add(new LayersGroupEvent(layers,
583
                                        LayersGroupEvent.IN_Event));
584
                        for (i = 0; i < layers.getLayersCount(); i++) {
585
                                appendLayer(layers.getLayer(i));
586
                        }
587
                        layersList.add(new LayersGroupEvent(layers,
588
                                        LayersGroupEvent.OUT_Event));
589
                }
590

    
591
                public void remove() {
592
                        throw new UnsupportedOperationException();
593
                }
594

    
595
                public boolean hasNext() {
596
                        return index < layersList.size();
597
                }
598

    
599
                public Object next() {
600
                        if (!this.hasNext()) {
601
                                throw new NoSuchElementException();
602
                        }
603
                        Object aux = layersList.get(index);
604
                        index++;
605
                        return aux;
606
                }
607

    
608
                public boolean evaluate(FLayer layer) {
609
                        if (layer instanceof FLayers) {
610
                                return false;
611
                        }
612
                        return layer.isAvailable() && layer.isVisible()
613
                                        && layer.isWithinScale(this.scale);
614
                }
615

    
616
        }
617

    
618
        private class LayersGroupEvent {
619
                public static final String IN_Event = "in";
620
                public static final String OUT_Event = "Out";
621

    
622
                private LayerCollection group = null;
623
                private String type = IN_Event;
624

    
625
                public LayersGroupEvent(LayerCollection group, String type) {
626
                        this.group = group;
627
                        this.type = type;
628
                }
629

    
630
                public String getType() {
631
                        return type;
632
                }
633

    
634
                public LayerCollection getGroup() {
635
                        return group;
636
                }
637
        }
638

    
639
}