Statistics
| Revision:

root / trunk / libraries / libFMap / src / com / iver / cit / gvsig / fmap / DefaultMapContextDrawer.java @ 36203

History | View | Annotate | Download (16.6 KB)

1
package com.iver.cit.gvsig.fmap;
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 com.hardcode.gdbms.driver.exceptions.ReadDriverException;
14
import com.iver.cit.gvsig.fmap.core.ILabelable;
15
import com.iver.cit.gvsig.fmap.layers.FLayer;
16
import com.iver.cit.gvsig.fmap.layers.FLayers;
17
import com.iver.cit.gvsig.fmap.layers.LayersIterator;
18
import com.iver.cit.gvsig.fmap.layers.layerOperations.ComposedLayer;
19
import com.iver.cit.gvsig.fmap.layers.layerOperations.LayerCollection;
20
import com.iver.utiles.swing.threads.Cancellable;
21

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

    
28

    
29

    
30
        public DefaultMapContextDrawer(){
31

    
32
        }
33

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

    
40
        protected boolean isLayerCacheable(FLayer layer){
41
                return layer.isActive();
42
        }
43
        
44
        public void draw(FLayers root, BufferedImage image, Graphics2D g, Cancellable cancel,
45
                        double scale) throws ReadDriverException {
46

    
47
                this.checkIntilalized();
48

    
49
                boolean needToPaintAll = false;
50

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

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

    
62

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

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

    
75

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

    
88
                        obj = drawList.get(pos);
89

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

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

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

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

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

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

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

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

    
189
                this.previousDrawList = drawList;
190

    
191
        }
192
        
193
        private void draw(Object layerOrComposed,BufferedImage image, Graphics2D g, Cancellable cancel,
194
                        double scale, double _dpi) throws ReadDriverException{
195
                ILabelable labelable= null;
196
                ILabelable tmp= null;
197
                if (layerOrComposed instanceof ILabelable){
198

    
199
                        tmp =(ILabelable) layerOrComposed;
200

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

    
218
        }
219

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

    
226
                        tmp =(ILabelable) layerOrComposed;
227

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

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

    
246
        }
247

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

    
255
        }
256

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

    
264
        }
265

    
266
        public void clean(){
267
                this.cachedImage = null;
268
        }
269

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

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

    
285
                public BufferedImage getImage() {
286
                        return image;
287
                }
288

    
289
                public long getMapContextVersion() {
290
                        return mapContextVersion;
291
                }
292

    
293
                public long getViewPortVersion() {
294
                        return viewPortVersion;
295
                }
296

    
297
                public int getListPosition(){
298
                        return this.listPosition;
299
                }
300

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

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

    
319
                public DrawList(){
320
                }
321

    
322
                public DrawList(DrawList previousList){
323
                        if (previousList != null){
324
                                this.firstLayerToDraw =previousList.layersCount();
325
                                this.previosList=previousList;
326
                        }
327
                }
328

    
329
                public int layersCount() {
330
                        return this.layers.size();
331
                }
332

    
333
                public int getLayerCount(){
334
                        return this.layers.size();
335
                }
336

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

    
347
                        return previousVersion != layerVersion;
348
                }
349

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

    
369
                        this.all.add(obj);
370
                }
371

    
372
                public int size(){
373
                        return this.all.size();
374
                }
375

    
376
                public int getFirstLayerToDraw(){
377
                        if (this.firstLayerToDraw > this.layers.size()){
378
                                this.firstLayerToDraw = this.layers.size();
379
                        }
380
                        return this.firstLayerToDraw;
381
                }
382

    
383
                public FLayer getLayer(int pos){
384
                        return (FLayer) this.layers.get(pos);
385
                }
386

    
387
                public Object get(int pos){
388
                        return this.all.get(pos);
389
                }
390

    
391
        }
392

    
393
        private class SimpleLayerIterator extends LayersIterator{
394

    
395
                public SimpleLayerIterator(FLayer layer) {
396
                        this.appendLayer(layer);
397
                }
398

    
399
                public boolean evaluate(FLayer layer) {
400
                        if (layer instanceof FLayers) {
401
                                return false;
402
                        }
403
                        return layer.isAvailable() && layer.isVisible();
404
                }
405

    
406
        }
407

    
408
        public void dispose() {
409
                this.mapContext=null;
410
                this.viewPort=null;
411
                this.cachedImage=null;
412
                this.previousDrawList = null;
413
        }
414

    
415
        /* (non-Javadoc)
416
         * @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)
417
         */
418
        public void print(FLayers root, Graphics2D g, Cancellable cancel,
419
                        double scale, PrintRequestAttributeSet properties)
420
                        throws ReadDriverException {
421
                this.checkIntilalized();
422

    
423
                List printList = this.createPrintList(root, cancel);
424
                if (cancel.isCanceled()){
425
                        return;
426
                }
427

    
428

    
429
                ComposedLayer composed = null;
430
                int pos;
431
                FLayer layer;
432
                int layerPos= -1;
433
                Object obj;
434
                LayersGroupEvent event;
435
                for (pos=0; pos < printList.size(); pos++){
436
                        if (cancel.isCanceled()){
437
                                return;
438
                        }
439

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

    
450
                                }
451
                                continue;
452
                        }
453
                        layerPos++;
454

    
455
                        layer = (FLayer) obj;
456

    
457

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

    
508

    
509
        }
510

    
511
        private DrawList createDrawList(FLayers root,Cancellable cancel,double scale){
512
                DrawList result = new DrawList(this.previousDrawList);
513
                Iterator iter = new MyLayerIterator((FLayer)root,scale);
514
                while (iter.hasNext()){
515
                        if (cancel.isCanceled()){
516
                                return null;
517
                        }
518
                        result.add(iter.next());
519

    
520
                }
521

    
522
                return result;
523
        }
524

    
525
        private List createPrintList(FLayers root,Cancellable cancel){
526
                List result = new ArrayList();
527
                Iterator iter = new SimpleLayerIterator((FLayer)root);
528
                while (iter.hasNext()){
529
                        if (cancel.isCanceled()){
530
                                return null;
531
                        }
532
                        result.add(iter.next());
533
                }
534
                return result;
535
        }
536

    
537
        private class MyLayerIterator implements Iterator{
538
                ArrayList layersList  =new ArrayList();
539
                int index = 0;
540
                double scale=0;
541

    
542

    
543
                public MyLayerIterator(FLayer layer, double scale) {
544
                        this.scale=scale;
545
                        this.appendLayer(layer);
546
                }
547

    
548
                protected void appendLayer(FLayer layer) {
549
                        if (this.evaluate(layer)) {
550
                                layersList.add(layer);
551
                        }
552
                        if (layer instanceof LayerCollection) {
553
                                appendLayers((LayerCollection)layer);
554
                        }
555
                }
556

    
557
                private void appendLayers(LayerCollection layers) {
558
                        int i;
559
                        layersList.add(new LayersGroupEvent(layers,LayersGroupEvent.IN_Event));
560
                        for (i=0;i< layers.getLayersCount();i++) {
561
                                appendLayer(layers.getLayer(i));
562
                        }
563
                        layersList.add(new LayersGroupEvent(layers,LayersGroupEvent.OUT_Event));
564
                }
565

    
566
                public void remove() {
567
                        throw new UnsupportedOperationException();
568
                }
569

    
570
                public boolean hasNext() {
571
                        return  index < layersList.size();
572
                }
573

    
574
                public Object next() {
575
                        if (!this.hasNext()) {
576
                                throw new NoSuchElementException();
577
                        }
578
                        Object aux = layersList.get(index);
579
                        index++;
580
                        return aux;
581
                }
582

    
583
                public boolean evaluate(FLayer layer) {
584
                        if (layer instanceof FLayers) {
585
                                return false;
586
                        }
587
                        return layer.isAvailable() && layer.isVisible() && layer.isWithinScale(this.scale);
588
                }
589

    
590
        }
591

    
592
        private class LayersGroupEvent {
593
                public static final String IN_Event = "in";
594
                public static final String OUT_Event = "Out";
595

    
596
                private LayerCollection group=null;
597
                private String type = IN_Event;
598

    
599
                public LayersGroupEvent(LayerCollection group,String type){
600
                        this.group =group;
601
                        this.type =type;
602
                }
603

    
604

    
605
                public String getType() {
606
                        return type;
607
                }
608

    
609
                public LayerCollection getGroup() {
610
                        return group;
611
                }
612
        }
613

    
614
}