Statistics
| Revision:

root / branches / v2_0_0_prep / libraries / libFMap_mapcontext / src / org / gvsig / fmap / mapcontext / DefaultMapContextDrawer.java @ 26225

History | View | Annotate | Download (16.3 KB)

1
package org.gvsig.fmap.mapcontext;
2

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

    
11
import javax.print.attribute.PrintRequestAttributeSet;
12

    
13
import org.gvsig.fmap.dal.exception.ReadException;
14
import org.gvsig.fmap.mapcontext.layers.FLayer;
15
import org.gvsig.fmap.mapcontext.layers.FLayers;
16
import org.gvsig.fmap.mapcontext.layers.LayersIterator;
17
import org.gvsig.fmap.mapcontext.layers.operations.ComposedLayer;
18
import org.gvsig.fmap.mapcontext.layers.operations.ILabelable;
19
import org.gvsig.fmap.mapcontext.layers.operations.LayerCollection;
20
import org.gvsig.tools.task.Cancellable;
21

    
22

    
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

    
31

    
32
        public DefaultMapContextDrawer(){
33

    
34
        }
35

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

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

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

    
49
                this.checkIntilalized();
50

    
51
                boolean needToPaintAll = false;
52

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

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

    
64

    
65
                int firstLayer= 0;
66
                if (!needToPaintAll){
67
                        firstLayer = cachedImage.getListPosition()+1;
68
//                        System.out.println("=======Pintando a partir de la pos "+ 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

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

    
90
                        obj = drawList.get(pos);
91

    
92
                        // *** Gestion de eventos de pintado de grupos ***
93
                        if (obj instanceof LayersGroupEvent){
94
                                event = (LayersGroupEvent) obj;
95
                                if (event.type == LayersGroupEvent.IN_Event){
96
//                                        System.out.println("=======Empiza a pintar grupo de capas "+ ((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 "+ ((FLayers)event.group).getName() +"============");
101

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

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

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

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

    
128
                                                }
129
                                                CachedImage  newCached = new CachedImage();
130
                                                newCached.setImage(image, mapContext, viewPort, layerPos-1);
131
                                                this.cachedImage = newCached;
132
//                                                System.out.println("=======Guardando imagen de la pos "+ (layerPos-1)+" ("+ newCached.getListPosition() +")============");
133
                                        }
134
                                }
135
                                cached = true;
136
                        }
137
                        if (cancel.isCanceled()){
138
                                return;
139
                        }
140

    
141
                        if (composed == null){
142
                                composed = layer.newComposedLayer();
143
                                if (composed != null){
144
                                        try {
145
//                                                System.out.println("=== a?adiendo a composicion de pintado "+ layerPos+ " "+layer.getName());
146
                                                composed.add(layer);
147
                                                continue;
148
                                        } catch (Exception e) {
149
                                                throw new ReadException("DefalutMapContexDrawer exception",e);
150
                                        }
151
                                }
152
                        }else{
153
                                if (composed.canAdd(layer)){
154
                                        try {
155
//                                                System.out.println("=== a?adiendo a composicion de pintado "+ layerPos+ " "+layer.getName());
156
                                                composed.add(layer);
157
                                                continue;
158
                                        } catch (Exception e) {
159
                                                throw new ReadException("DefalutMapContexDrawer exception",e);
160
                                        }
161
                                } else {
162
//                                        System.out.println("=======Pintando composicion de pintado "+ (layerPos-1)+" (cambio composicion)============");
163
                                        this.draw(composed, image, g, cancel, scale);
164
//                                        composed.draw(image, g, viewPort, cancel, scale);
165
                                        composed = layer.newComposedLayer();
166
                                        if (composed != null){
167
                                                try {
168
//                                                        System.out.println("=== a?adiendo a composicion de pintado "+ layerPos+ " "+layer.getName());
169
                                                        composed.add(layer);
170
                                                        continue;
171
                                                } catch (Exception e) {
172
                                                        throw new ReadException("DefalutMapContexDrawer exception",e);
173
                                                }                                        }
174
                                }
175
                        }
176
//                        System.out.println("=== pintando "+ layerPos+ " "+layer.getName());
177
                        this.draw(layer, image, g, cancel, scale);
178
//                        layer.draw(image, g, viewPort, cancel, scale);
179

    
180
                }
181
                if (composed != null){
182
                        // si la composicion no se ha pintado la pintamos
183
//                        System.out.println("=======Pintando composicion de pintado "+ (layerPos-1)+" (ultimo)============");
184
                        this.draw(composed, image, g, cancel, scale);
185
//                        composed.draw(image, g, viewPort, cancel, scale);
186
                }
187
                if (cancel.isCanceled()){
188
                        return;
189
                }
190

    
191
                this.previousDrawList = drawList;
192

    
193
        }
194

    
195
        private void draw(Object layerOrComposed,BufferedImage image, Graphics2D g, Cancellable cancel,
196
                        double scale) throws ReadException{
197
                ILabelable labelable= null;
198
                ILabelable tmp= null;
199
                if (layerOrComposed instanceof ILabelable){
200

    
201
                        tmp =(ILabelable) layerOrComposed;
202

    
203
                        if (tmp.isLabeled()
204
                                && tmp.getLabelingStrategy() != null
205
                                && tmp.getLabelingStrategy().shouldDrawLabels(scale)) {
206
                                labelable =tmp;
207
                        }
208
                }
209
                if (layerOrComposed instanceof FLayer){
210
                        FLayer layer = (FLayer) layerOrComposed;
211
                        layer.draw(image, g, viewPort, cancel, scale);
212
                } else{
213
                        ComposedLayer composed = (ComposedLayer) layerOrComposed;
214
                        composed.draw(image, g, viewPort, cancel, scale);
215
                }
216
                if (labelable != null){
217
                        labelable.drawLabels(image, g, viewPort, cancel, scale, MapContext.getScreenDPI());
218
                }
219

    
220
        }
221

    
222
        private void print(Object layerOrComposed,Graphics2D g, Cancellable cancel,
223
                        double scale, PrintRequestAttributeSet properties) throws ReadException{
224
                ILabelable labelable= null;
225
                ILabelable tmp= null;
226
                if (layerOrComposed instanceof ILabelable){
227

    
228
                        tmp =(ILabelable) layerOrComposed;
229

    
230
                        if (tmp.isLabeled()
231
                                && tmp.getLabelingStrategy() != null
232
                                && tmp.getLabelingStrategy().shouldDrawLabels(scale)) {
233
                                labelable =tmp;
234
                        }
235
                }
236

    
237
                if (layerOrComposed instanceof FLayer){
238
                        FLayer layer = (FLayer) layerOrComposed;
239
                        layer.print(g, viewPort, cancel, scale, properties);
240
                } else{
241
                        ComposedLayer composed = (ComposedLayer) layerOrComposed;
242
                        composed.print(g, viewPort, cancel, scale, properties);
243
                }
244
                if (labelable != null){
245
                        labelable.printLabels(g, viewPort, cancel, scale, properties);
246
                }
247

    
248
        }
249

    
250
        public void setMapContext(MapContext mapContext) {
251
                if (this.mapContext == mapContext){
252
                        return;
253
                }
254
                this.clean();
255
                this.mapContext = mapContext;
256

    
257
        }
258

    
259
        public void setViewPort(ViewPort viewPort) {
260
                if (this.viewPort == viewPort){
261
                        return;
262
                }
263
                this.clean();
264
                this.viewPort = viewPort;
265

    
266
        }
267

    
268
        protected void clean(){
269
                this.cachedImage = null;
270
        }
271

    
272
        public class CachedImage{
273
                private BufferedImage image;
274
                private long mapContextVersion;
275
                private long viewPortVersion;
276
                private int listPosition;
277

    
278
                public void setImage(BufferedImage image,MapContext mapContext, ViewPort viewPort,int pos) {
279
                        this.image = new BufferedImage(image.getWidth(), image.getHeight(), image.getType());
280
                        WritableRaster w = this.image.getRaster();
281
                        image.copyData(w);
282
                        this.mapContextVersion = mapContext.getDrawVersion();
283
                        this.viewPortVersion = viewPort.getDrawVersion();
284
                        this.listPosition = pos;
285
                }
286

    
287
                public BufferedImage getImage() {
288
                        return image;
289
                }
290

    
291
                public long getMapContextVersion() {
292
                        return mapContextVersion;
293
                }
294

    
295
                public long getViewPortVersion() {
296
                        return viewPortVersion;
297
                }
298

    
299
                public int getListPosition(){
300
                        return this.listPosition;
301
                }
302

    
303
                public boolean isValid(MapContext context,ViewPort viewPort,int firstLayerToDraw){
304
                        if (viewPort.getDrawVersion() > this.viewPortVersion){
305
                                return false;
306
                        }
307
                        if (firstLayerToDraw <= this.listPosition){
308
                                return false;
309
                        }
310
                        return true;
311
                }
312
        }
313

    
314
        public class DrawList{
315
                private List layers = new ArrayList();
316
                private List all = new ArrayList();
317
                private List versions = new ArrayList();
318
                private DrawList previosList = null;
319
                private int firstLayerToDraw =-1;
320

    
321
                public DrawList(){
322
                }
323

    
324
                public DrawList(DrawList previousList){
325
                        if (previousList != null){
326
                                this.firstLayerToDraw =previousList.size();
327
                                this.previosList=previousList;
328
                        }
329
                }
330

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

    
335
                private boolean hasChanged(FLayer layer, int pos){
336
                        FLayer previous =(FLayer) this.previosList.layers.get(pos);
337
                        String previousName = previous.getName();
338
                        String layerName = layer.getName();
339
                        if (previous != layer){
340
                                return true;
341
                        }
342
                        long previousVersion = ((Long) this.previosList.versions.get(pos)).longValue();
343
                        long layerVersion = layer.getDrawVersion();
344

    
345
                        return previousVersion != layerVersion;
346
                }
347

    
348
                public void add(Object obj){
349
                        if (obj instanceof FLayer){
350
                                FLayer layer = (FLayer) obj;
351
                                int curIndex = this.layers.size();
352
                                if (this.firstLayerToDraw >= curIndex){
353
                                        if (this.previosList.getLayerCount() > curIndex){
354
                                                if (this.hasChanged(layer, curIndex)){
355
                                                        this.firstLayerToDraw = curIndex;
356
                                                }
357
                                        } else if (this.previosList.getLayerCount() == curIndex){
358
                                                this.firstLayerToDraw = curIndex;
359
                                        }
360
                                }
361
                                this.layers.add(layer);
362
                                this.versions.add(new Long(layer.getDrawVersion()));
363
                        } else if (!(obj instanceof LayersGroupEvent)){
364
                                throw new UnsupportedOperationException();
365
                        }
366

    
367
                        this.all.add(obj);
368
                }
369

    
370
                public int size(){
371
                        return this.all.size();
372
                }
373

    
374
                public int getFirstLayerToDraw(){
375
                        return this.firstLayerToDraw;
376
                }
377

    
378
                public FLayer getLayer(int pos){
379
                        return (FLayer) this.layers.get(pos);
380
                }
381

    
382
                public Object get(int pos){
383
                        return this.all.get(pos);
384
                }
385

    
386
        }
387

    
388
        private class SimpleLayerIterator extends LayersIterator{
389

    
390
                public SimpleLayerIterator(FLayer layer) {
391
                        this.appendLayer(layer);
392
                }
393

    
394
                public boolean evaluate(FLayer layer) {
395
                        if (layer instanceof FLayers) {
396
                                return false;
397
                        }
398
                        return layer.isAvailable() && layer.isVisible();
399
                }
400

    
401
        }
402

    
403
        public void dispose() {
404
                this.mapContext=null;
405
                this.viewPort=null;
406
                this.cachedImage=null;
407
                this.previousDrawList = null;
408
        }
409

    
410
        /* (non-Javadoc)
411
         * @see com.iver.cit.gvsig.fmap.MapContextDrawer#print(com.iver.cit.gvsig.fmap.layers.FLayers, java.awt.Graphics2D, com.iver.utiles.swing.threads.Cancellable, double, javax.print.attribute.PrintRequestAttributeSet)
412
         */
413
        public void print(FLayers root, Graphics2D g, Cancellable cancel,
414
                        double scale, PrintRequestAttributeSet properties)
415
                        throws ReadException {
416
                this.checkIntilalized();
417

    
418
                List printList = this.createPrintList(root, cancel);
419
                if (cancel.isCanceled()){
420
                        return;
421
                }
422

    
423

    
424
                ComposedLayer composed = null;
425
                int pos;
426
                FLayer layer;
427
                int layerPos= -1;
428
                Object obj;
429
                LayersGroupEvent event;
430
                for (pos=0; pos < printList.size(); pos++){
431
                        if (cancel.isCanceled()){
432
                                return;
433
                        }
434

    
435
                        obj = printList.get(pos);
436
                        if (obj instanceof LayersGroupEvent){
437
                                event = (LayersGroupEvent) obj;
438
                                if (event.type == LayersGroupEvent.IN_Event){
439
//                                        System.out.println("=======Empiza a pintar grupo de capas "+ ((FLayers)event.group).getName() +"============");
440
                                        event.group.beginDraw(g, viewPort);
441
                                } else{
442
                                        event.group.endDraw(g, viewPort);
443
//                                        System.out.println("=======Fin a pintar grupo de capas "+ ((FLayers)event.group).getName() +"============");
444

    
445
                                }
446
                                continue;
447
                        }
448
                        layerPos++;
449

    
450
                        layer = (FLayer) obj;
451

    
452

    
453
                        // *** Pintado de capa/composicion de capa ***
454
                        if (composed == null){
455
                                composed = layer.newComposedLayer();
456
                                if (composed != null){
457
                                        try {
458
                                                composed.add(layer);
459
//                                                System.out.println("=======Imprimiendo composicion de pintado "+ (layerPos-1)+" ============");
460
                                                continue;
461
                                        } catch (Exception e) {
462
                                                throw new ReadException("DefalutMapContexDrawer exception",e);
463
                                        }
464
                                }
465
                        }else{
466
                                if (composed.canAdd(layer)){
467
                                        try {
468
                                                composed.add(layer);
469
//                                                System.out.println("=== a?adiendo a composicion de pintado "+ layerPos+ " "+layer.getName());
470
                                                continue;
471
                                        } catch (Exception e) {
472
                                                throw new ReadException("DefalutMapContexDrawer exception",e);
473
                                        }
474
                                } else {
475
//                                        System.out.println("=======Imprimiendo composicion de pintado "+ (layerPos-1)+" ============");
476
                                        this.print(composed, g, cancel, scale, properties);
477
//                                        composed.print( g, viewPort, cancel, scale,properties);
478
                                        composed = layer.newComposedLayer();
479
                                        if (composed != null){
480
                                                try {
481
                                                        composed.add(layer);
482
//                                                        System.out.println("=== a?adiendo a composicion de pintado "+ layerPos+ " "+layer.getName());
483
                                                        continue;
484
                                                } catch (Exception e) {
485
                                                        throw new ReadException("DefalutMapContexDrawer exception",e);
486
                                                }
487
                                        }
488
                                }
489
                        }
490
//                        System.out.println("=== imprimiendo "+ layerPos+ " "+layer.getName());
491
                        this.print(layer, g, cancel, scale, properties);
492
//                        layer.print(g, viewPort, cancel, scale,properties);
493
                        // *** Pintado de capa/composicion de capa ***
494
                        if (composed != null){
495
                                // si la composicion no se ha pintado la pintamos
496
//                                System.out.println("=======Imprimiendo composicion de pintado "+ (layerPos-1)+" (ultimo) ============");
497
                                this.print(composed, g, cancel, scale, properties);
498
//                                composed.print(g, viewPort, cancel, scale, properties);
499
                                composed = null;
500
                        }
501
                }
502

    
503

    
504
        }
505

    
506
        private DrawList createDrawList(FLayers root,Cancellable cancel,double scale){
507
                DrawList result = new DrawList(this.previousDrawList);
508
                Iterator iter = new MyLayerIterator((FLayer)root,scale);
509
                while (iter.hasNext()){
510
                        if (cancel.isCanceled()){
511
                                return null;
512
                        }
513
                        result.add(iter.next());
514

    
515
                }
516

    
517
                return result;
518
        }
519

    
520
        private List createPrintList(FLayers root,Cancellable cancel){
521
                List result = new ArrayList();
522
                Iterator iter = new SimpleLayerIterator((FLayer)root);
523
                while (iter.hasNext()){
524
                        if (cancel.isCanceled()){
525
                                return null;
526
                        }
527
                        result.add(iter.next());
528
                }
529
                return result;
530
        }
531

    
532
        private class MyLayerIterator implements Iterator{
533
                ArrayList layersList  =new ArrayList();
534
                int index = 0;
535
                double scale=0;
536

    
537

    
538
                public MyLayerIterator(FLayer layer, double scale) {
539
                        this.appendLayer(layer);
540
                        this.scale=scale;
541
                }
542

    
543
                protected void appendLayer(FLayer layer) {
544
                        if (this.evaluate(layer)) {
545
                                layersList.add(layer);
546
                        }
547
                        if (layer instanceof LayerCollection) {
548
                                appendLayers((LayerCollection)layer);
549
                        }
550
                }
551

    
552
                private void appendLayers(LayerCollection layers) {
553
                        int i;
554
                        layersList.add(new LayersGroupEvent(layers,LayersGroupEvent.IN_Event));
555
                        for (i=0;i< layers.getLayersCount();i++) {
556
                                appendLayer(layers.getLayer(i));
557
                        }
558
                        layersList.add(new LayersGroupEvent(layers,LayersGroupEvent.OUT_Event));
559
                }
560

    
561
                public void remove() {
562
                        throw new UnsupportedOperationException();
563
                }
564

    
565
                public boolean hasNext() {
566
                        return  index < layersList.size();
567
                }
568

    
569
                public Object next() {
570
                        if (!this.hasNext()) {
571
                                throw new NoSuchElementException();
572
                        }
573
                        Object aux = layersList.get(index);
574
                        index++;
575
                        return aux;
576
                }
577

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

    
585
        }
586

    
587
        private class LayersGroupEvent {
588
                public static final String IN_Event = "in";
589
                public static final String OUT_Event = "Out";
590

    
591
                private LayerCollection group=null;
592
                private String type = IN_Event;
593

    
594
                public LayersGroupEvent(LayerCollection group,String type){
595
                        this.group =group;
596
                        this.type =type;
597
                }
598

    
599

    
600
                public String getType() {
601
                        return type;
602
                }
603

    
604
                public LayerCollection getGroup() {
605
                        return group;
606
                }
607
        }
608

    
609
}