Statistics
| Revision:

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

History | View | Annotate | Download (16.4 KB)

1 24160 jmvivo
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 24279 jmvivo
import java.util.Iterator;
8 24160 jmvivo
import java.util.List;
9 24279 jmvivo
import java.util.NoSuchElementException;
10 24160 jmvivo
11
import javax.print.attribute.PrintRequestAttributeSet;
12
13
import com.hardcode.gdbms.driver.exceptions.ReadDriverException;
14 24279 jmvivo
import com.iver.cit.gvsig.fmap.core.ILabelable;
15 24160 jmvivo
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 24279 jmvivo
import com.iver.cit.gvsig.fmap.layers.layerOperations.LayerCollection;
20 24160 jmvivo
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 24653 jmvivo
        protected boolean isLayerCacheable(FLayer layer){
41
                return layer.isActive();
42
        }
43
44 24160 jmvivo
        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 25108 jmvivo
                DrawList drawList = this.createDrawList(root, cancel,scale);
52 24160 jmvivo
                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 24404 jmvivo
                int firstLayer= 0;
64 24160 jmvivo
                if (!needToPaintAll){
65 24404 jmvivo
                        firstLayer = cachedImage.getListPosition()+1;
66 24969 jmvivo
//                        System.out.println("=======Pintando a partir de la pos "+ firstLayer+"============");
67 24160 jmvivo
                        g.drawImage(cachedImage.getImage(), 0, 0, null);
68 24969 jmvivo
//                        System.out.println("=======Pintando imagen ============");
69 24160 jmvivo
70
                } else{
71
                        this.cachedImage = null;
72 24969 jmvivo
//                        System.out.println("=======Pintando todo============");
73 24160 jmvivo
                }
74
75
76
                boolean cached=false;
77
                ComposedLayer composed = null;
78
                int pos;
79 24279 jmvivo
                int layerPos= -1;
80
                FLayer layer;
81
                Object obj;
82
                LayersGroupEvent event;
83 24404 jmvivo
                for (pos=0; pos < drawList.size(); pos++){
84 24279 jmvivo
                        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 24969 jmvivo
//                                        System.out.println("=======Empiza a pintar grupo de capas "+ ((FLayers)event.group).getName() +"============");
95 24279 jmvivo
                                        event.group.beginDraw(g, viewPort);
96
                                } else{
97
                                        event.group.endDraw(g, viewPort);
98 24969 jmvivo
//                                        System.out.println("=======Fin a pintar grupo de capas "+ ((FLayers)event.group).getName() +"============");
99 24279 jmvivo
100
                                }
101
                                continue;
102
                        }
103
                        layerPos++;
104 24404 jmvivo
                        if (layerPos < firstLayer){
105 24279 jmvivo
                                continue;
106
                        }
107
108
                        layer = (FLayer) obj;
109 24404 jmvivo
                        if (cancel.isCanceled()){
110
                                return;
111
                        }
112 24279 jmvivo
113
                        // *** Gestion de cache ***
114 24653 jmvivo
                        if ((!cached) && this.isLayerCacheable(layer)){
115 24404 jmvivo
                                if (layerPos > 0){ //La primera capa es la activa, no cacheamos
116
                                        if (cachedImage==null || cachedImage.getListPosition() < layerPos-1){
117 24160 jmvivo
118
                                                if (composed != null){
119
                                                        //si tenemos una composicion de capas, necesitamos pintarlas
120
                                                        //antes de guardarnos la imagen
121 24969 jmvivo
//                                                        System.out.println("=======Pintando composicion de pintado "+ (layerPos-1)+" (antes de cache)============");
122 24279 jmvivo
                                                        this.draw(composed, image, g, cancel, scale);
123
//                                                        composed.draw(image, g, viewPort, cancel, scale);
124 24160 jmvivo
                                                        composed = null;
125
126
                                                }
127 24404 jmvivo
                                                CachedImage  newCached = new CachedImage();
128
                                                newCached.setImage(image, mapContext, viewPort, layerPos-1);
129
                                                this.cachedImage = newCached;
130 24969 jmvivo
//                                                System.out.println("=======Guardando imagen de la pos "+ (layerPos-1)+" ("+ newCached.getListPosition() +")============");
131 24160 jmvivo
                                        }
132
                                }
133
                                cached = true;
134
                        }
135 24404 jmvivo
                        if (cancel.isCanceled()){
136
                                return;
137
                        }
138 24160 jmvivo
139
                        if (composed == null){
140
                                composed = layer.newComposedLayer();
141
                                if (composed != null){
142
                                        try {
143 24969 jmvivo
//                                                System.out.println("=== a?adiendo a composicion de pintado "+ layerPos+ " "+layer.getName());
144 24160 jmvivo
                                                composed.add(layer);
145
                                                continue;
146
                                        } catch (Exception e) {
147
                                                throw new ReadDriverException("DefalutMapContexDrawer exception",e);
148
                                        }
149
                                }
150
                        }else{
151
                                if (composed.canAdd(layer)){
152
                                        try {
153 24969 jmvivo
//                                                System.out.println("=== a?adiendo a composicion de pintado "+ layerPos+ " "+layer.getName());
154 24160 jmvivo
                                                composed.add(layer);
155
                                                continue;
156
                                        } catch (Exception e) {
157
                                                throw new ReadDriverException("DefalutMapContexDrawer exception",e);
158
                                        }
159
                                } else {
160 24969 jmvivo
//                                        System.out.println("=======Pintando composicion de pintado "+ (layerPos-1)+" (cambio composicion)============");
161 24279 jmvivo
                                        this.draw(composed, image, g, cancel, scale);
162
//                                        composed.draw(image, g, viewPort, cancel, scale);
163 24160 jmvivo
                                        composed = layer.newComposedLayer();
164
                                        if (composed != null){
165
                                                try {
166 24969 jmvivo
//                                                        System.out.println("=== a?adiendo a composicion de pintado "+ layerPos+ " "+layer.getName());
167 24160 jmvivo
                                                        composed.add(layer);
168
                                                        continue;
169
                                                } catch (Exception e) {
170
                                                        throw new ReadDriverException("DefalutMapContexDrawer exception",e);
171
                                                }                                        }
172
                                }
173
                        }
174 24969 jmvivo
//                        System.out.println("=== pintando "+ layerPos+ " "+layer.getName());
175 24279 jmvivo
                        this.draw(layer, image, g, cancel, scale);
176
//                        layer.draw(image, g, viewPort, cancel, scale);
177 24160 jmvivo
178
                }
179
                if (composed != null){
180
                        // si la composicion no se ha pintado la pintamos
181 24969 jmvivo
//                        System.out.println("=======Pintando composicion de pintado "+ (layerPos-1)+" (ultimo)============");
182 24279 jmvivo
                        this.draw(composed, image, g, cancel, scale);
183
//                        composed.draw(image, g, viewPort, cancel, scale);
184 24160 jmvivo
                }
185 24404 jmvivo
                if (cancel.isCanceled()){
186
                        return;
187
                }
188 24160 jmvivo
189
                this.previousDrawList = drawList;
190
191
        }
192
193 24279 jmvivo
        private void draw(Object layerOrComposed,BufferedImage image, Graphics2D g, Cancellable cancel,
194
                        double scale) throws ReadDriverException{
195
                ILabelable labelable= null;
196 24293 jmvivo
                ILabelable tmp= null;
197 24279 jmvivo
                if (layerOrComposed instanceof ILabelable){
198
199 24293 jmvivo
                        tmp =(ILabelable) layerOrComposed;
200
201
                        if (tmp.isLabeled()
202
                                && tmp.getLabelingStrategy() != null
203
                                && tmp.getLabelingStrategy().shouldDrawLabels(scale)) {
204
                                labelable =tmp;
205 24160 jmvivo
                        }
206 24279 jmvivo
                }
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, MapContext.getScreenDPI());
216
                }
217 24160 jmvivo
218 24279 jmvivo
        }
219
220
        private void print(Object layerOrComposed,Graphics2D g, Cancellable cancel,
221
                        double scale, PrintRequestAttributeSet properties) throws ReadDriverException{
222
                ILabelable labelable= null;
223 24293 jmvivo
                ILabelable tmp= null;
224 24279 jmvivo
                if (layerOrComposed instanceof ILabelable){
225
226 24293 jmvivo
                        tmp =(ILabelable) layerOrComposed;
227
228
                        if (tmp.isLabeled()
229
                                && tmp.getLabelingStrategy() != null
230
                                && tmp.getLabelingStrategy().shouldDrawLabels(scale)) {
231
                                labelable =tmp;
232 24279 jmvivo
                        }
233 24160 jmvivo
                }
234 24293 jmvivo
235 24279 jmvivo
                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 24160 jmvivo
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
        protected 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 24279 jmvivo
                private List all = new ArrayList();
315 24160 jmvivo
                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.size();
325
                                this.previosList=previousList;
326
                        }
327
                }
328
329 24279 jmvivo
                public int getLayerCount(){
330
                        return this.layers.size();
331
                }
332
333 24160 jmvivo
                private boolean hasChanged(FLayer layer, int pos){
334
                        FLayer previous =(FLayer) this.previosList.layers.get(pos);
335 24279 jmvivo
                        String previousName = previous.getName();
336
                        String layerName = layer.getName();
337 24160 jmvivo
                        if (previous != layer){
338
                                return true;
339
                        }
340 24279 jmvivo
                        long previousVersion = ((Long) this.previosList.versions.get(pos)).longValue();
341
                        long layerVersion = layer.getDrawVersion();
342 24160 jmvivo
343 24279 jmvivo
                        return previousVersion != layerVersion;
344 24160 jmvivo
                }
345
346 24279 jmvivo
                public void add(Object obj){
347
                        if (obj instanceof FLayer){
348
                                FLayer layer = (FLayer) obj;
349
                                int curIndex = this.layers.size();
350
                                if (this.firstLayerToDraw >= curIndex){
351
                                        if (this.previosList.getLayerCount() > curIndex){
352
                                                if (this.hasChanged(layer, curIndex)){
353
                                                        this.firstLayerToDraw = curIndex;
354
                                                }
355
                                        } else if (this.previosList.getLayerCount() == curIndex){
356 24160 jmvivo
                                                this.firstLayerToDraw = curIndex;
357
                                        }
358
                                }
359 24279 jmvivo
                                this.layers.add(layer);
360
                                this.versions.add(new Long(layer.getDrawVersion()));
361
                        } else if (!(obj instanceof LayersGroupEvent)){
362
                                throw new UnsupportedOperationException();
363 24160 jmvivo
                        }
364 24279 jmvivo
365
                        this.all.add(obj);
366 24160 jmvivo
                }
367
368
                public int size(){
369 24279 jmvivo
                        return this.all.size();
370 24160 jmvivo
                }
371
372
                public int getFirstLayerToDraw(){
373
                        return this.firstLayerToDraw;
374
                }
375
376
                public FLayer getLayer(int pos){
377
                        return (FLayer) this.layers.get(pos);
378
                }
379 24279 jmvivo
380
                public Object get(int pos){
381
                        return this.all.get(pos);
382
                }
383
384 24160 jmvivo
        }
385
386
        private class SimpleLayerIterator extends LayersIterator{
387
388
                public SimpleLayerIterator(FLayer layer) {
389
                        this.appendLayer(layer);
390
                }
391
392
                public boolean evaluate(FLayer layer) {
393
                        if (layer instanceof FLayers) {
394
                                return false;
395
                        }
396
                        return layer.isAvailable() && layer.isVisible();
397
                }
398
399
        }
400
401
        public void dispose() {
402
                this.mapContext=null;
403
                this.viewPort=null;
404
                this.cachedImage=null;
405
                this.previousDrawList = null;
406
        }
407
408
        /* (non-Javadoc)
409
         * @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)
410
         */
411
        public void print(FLayers root, Graphics2D g, Cancellable cancel,
412
                        double scale, PrintRequestAttributeSet properties)
413
                        throws ReadDriverException {
414 24279 jmvivo
                this.checkIntilalized();
415 24160 jmvivo
416 24279 jmvivo
                List printList = this.createPrintList(root, cancel);
417
                if (cancel.isCanceled()){
418
                        return;
419
                }
420
421
422
                ComposedLayer composed = null;
423
                int pos;
424
                FLayer layer;
425
                int layerPos= -1;
426
                Object obj;
427
                LayersGroupEvent event;
428
                for (pos=0; pos < printList.size(); pos++){
429
                        if (cancel.isCanceled()){
430
                                return;
431
                        }
432
433
                        obj = printList.get(pos);
434 25108 jmvivo
                        if (obj instanceof LayersGroupEvent){
435 24279 jmvivo
                                event = (LayersGroupEvent) obj;
436
                                if (event.type == LayersGroupEvent.IN_Event){
437 24969 jmvivo
//                                        System.out.println("=======Empiza a pintar grupo de capas "+ ((FLayers)event.group).getName() +"============");
438 24279 jmvivo
                                        event.group.beginDraw(g, viewPort);
439
                                } else{
440
                                        event.group.endDraw(g, viewPort);
441 24969 jmvivo
//                                        System.out.println("=======Fin a pintar grupo de capas "+ ((FLayers)event.group).getName() +"============");
442 24279 jmvivo
443
                                }
444
                                continue;
445
                        }
446
                        layerPos++;
447
448
                        layer = (FLayer) obj;
449
450
451
                        // *** Pintado de capa/composicion de capa ***
452
                        if (composed == null){
453
                                composed = layer.newComposedLayer();
454
                                if (composed != null){
455
                                        try {
456
                                                composed.add(layer);
457 24969 jmvivo
//                                                System.out.println("=======Imprimiendo composicion de pintado "+ (layerPos-1)+" ============");
458 24279 jmvivo
                                                continue;
459
                                        } catch (Exception e) {
460
                                                throw new ReadDriverException("DefalutMapContexDrawer exception",e);
461
                                        }
462
                                }
463
                        }else{
464
                                if (composed.canAdd(layer)){
465
                                        try {
466
                                                composed.add(layer);
467 24969 jmvivo
//                                                System.out.println("=== a?adiendo a composicion de pintado "+ layerPos+ " "+layer.getName());
468 24279 jmvivo
                                                continue;
469
                                        } catch (Exception e) {
470
                                                throw new ReadDriverException("DefalutMapContexDrawer exception",e);
471
                                        }
472
                                } else {
473 24969 jmvivo
//                                        System.out.println("=======Imprimiendo composicion de pintado "+ (layerPos-1)+" ============");
474 24279 jmvivo
                                        this.print(composed, g, cancel, scale, properties);
475
//                                        composed.print( g, viewPort, cancel, scale,properties);
476
                                        composed = layer.newComposedLayer();
477
                                        if (composed != null){
478
                                                try {
479
                                                        composed.add(layer);
480 24969 jmvivo
//                                                        System.out.println("=== a?adiendo a composicion de pintado "+ layerPos+ " "+layer.getName());
481 24279 jmvivo
                                                        continue;
482
                                                } catch (Exception e) {
483
                                                        throw new ReadDriverException("DefalutMapContexDrawer exception",e);
484
                                                }
485
                                        }
486
                                }
487
                        }
488 24969 jmvivo
//                        System.out.println("=== imprimiendo "+ layerPos+ " "+layer.getName());
489 24279 jmvivo
                        this.print(layer, g, cancel, scale, properties);
490
//                        layer.print(g, viewPort, cancel, scale,properties);
491
                        // *** Pintado de capa/composicion de capa ***
492
                        if (composed != null){
493
                                // si la composicion no se ha pintado la pintamos
494 24969 jmvivo
//                                System.out.println("=======Imprimiendo composicion de pintado "+ (layerPos-1)+" (ultimo) ============");
495 24279 jmvivo
                                this.print(composed, g, cancel, scale, properties);
496
//                                composed.print(g, viewPort, cancel, scale, properties);
497
                                composed = null;
498
                        }
499
                }
500
501
502 24160 jmvivo
        }
503 24279 jmvivo
504 25108 jmvivo
        private DrawList createDrawList(FLayers root,Cancellable cancel,double scale){
505 24279 jmvivo
                DrawList result = new DrawList(this.previousDrawList);
506 25108 jmvivo
                Iterator iter = new MyLayerIterator((FLayer)root,scale);
507 24279 jmvivo
                while (iter.hasNext()){
508
                        if (cancel.isCanceled()){
509
                                return null;
510
                        }
511
                        result.add(iter.next());
512
513
                }
514
515
                return result;
516
        }
517
518
        private List createPrintList(FLayers root,Cancellable cancel){
519
                List result = new ArrayList();
520 25108 jmvivo
                Iterator iter = new SimpleLayerIterator((FLayer)root);
521 24279 jmvivo
                while (iter.hasNext()){
522
                        if (cancel.isCanceled()){
523
                                return null;
524
                        }
525
                        result.add(iter.next());
526
                }
527
                return result;
528
        }
529
530
        private class MyLayerIterator implements Iterator{
531
                ArrayList layersList  =new ArrayList();
532
                int index = 0;
533 25108 jmvivo
                double scale=0;
534 24279 jmvivo
535 25108 jmvivo
536
                public MyLayerIterator(FLayer layer, double scale) {
537 24279 jmvivo
                        this.appendLayer(layer);
538 25108 jmvivo
                        this.scale=scale;
539 24279 jmvivo
                }
540
541
                protected void appendLayer(FLayer layer) {
542
                        if (this.evaluate(layer)) {
543
                                layersList.add(layer);
544
                        }
545
                        if (layer instanceof LayerCollection) {
546
                                appendLayers((LayerCollection)layer);
547
                        }
548
                }
549
550
                private void appendLayers(LayerCollection layers) {
551
                        int i;
552
                        layersList.add(new LayersGroupEvent(layers,LayersGroupEvent.IN_Event));
553
                        for (i=0;i< layers.getLayersCount();i++) {
554
                                appendLayer(layers.getLayer(i));
555
                        }
556
                        layersList.add(new LayersGroupEvent(layers,LayersGroupEvent.OUT_Event));
557
                }
558
559
                public void remove() {
560
                        throw new UnsupportedOperationException();
561
                }
562
563
                public boolean hasNext() {
564
                        return  index < layersList.size();
565
                }
566
567
                public Object next() {
568
                        if (!this.hasNext()) {
569
                                throw new NoSuchElementException();
570
                        }
571
                        Object aux = layersList.get(index);
572
                        index++;
573
                        return aux;
574
                }
575
576
                public boolean evaluate(FLayer layer) {
577
                        if (layer instanceof FLayers) {
578
                                return false;
579
                        }
580 25108 jmvivo
                        return layer.isAvailable() && layer.isVisible() && layer.isWithinScale(this.scale);
581 24279 jmvivo
                }
582
583
        }
584
585
        private class LayersGroupEvent {
586
                public static final String IN_Event = "in";
587
                public static final String OUT_Event = "Out";
588
589
                private LayerCollection group=null;
590
                private String type = IN_Event;
591
592
                public LayersGroupEvent(LayerCollection group,String type){
593
                        this.group =group;
594
                        this.type =type;
595
                }
596
597
598
                public String getType() {
599
                        return type;
600
                }
601
602
                public LayerCollection getGroup() {
603
                        return group;
604
                }
605
        }
606
607 24160 jmvivo
}