Statistics
| Revision:

svn-gvsig-desktop / trunk / libraries / libFMap / src / com / iver / cit / gvsig / fmap / DefaultMapContextDrawer.java @ 24293

History | View | Annotate | Download (16 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
        public void draw(FLayers root, BufferedImage image, Graphics2D g, Cancellable cancel,
41
                        double scale) throws ReadDriverException {
42

    
43
                this.checkIntilalized();
44

    
45
                boolean needToPaintAll = false;
46

    
47
                DrawList drawList = this.createDrawList(root, cancel);
48
                if (cancel.isCanceled()){
49
                        return;
50
                }
51

    
52
                if (cachedImage == null){
53
                        needToPaintAll=true;
54
                } else if (!cachedImage.isValid(mapContext, viewPort, drawList.getFirstLayerToDraw())){
55
                        needToPaintAll=true;
56
                }
57

    
58

    
59
                int first= 0;
60
                if (!needToPaintAll){
61
                        first = cachedImage.getListPosition()+1;
62
                        System.out.println("=======Pintando a partir de la pos "+ first+"============");
63
                        g.drawImage(cachedImage.getImage(), 0, 0, null);
64
                        System.out.println("=======Pintando imagen ============");
65

    
66
                } else{
67
                        this.cachedImage = null;
68
                        System.out.println("=======Pintando todo============");
69
                }
70

    
71

    
72
                CachedImage newCached = null;
73
                boolean cached=false;
74
                ComposedLayer composed = null;
75
                int pos;
76
                int layerPos= -1;
77
                FLayer layer;
78
                Object obj;
79
                LayersGroupEvent event;
80
                for (pos=first; pos < drawList.size(); pos++){
81
                        if (cancel.isCanceled()){
82
                                return;
83
                        }
84

    
85
                        obj = drawList.get(pos);
86

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

    
97
                                }
98
                                continue;
99
                        }
100
                        layerPos++;
101
                        if (layerPos < first){
102
                                continue;
103
                        }
104

    
105
                        layer = (FLayer) obj;
106

    
107
                        // *** Gestion de cache ***
108
                        if ((!cached) && layer.isActive()){
109
                                if (pos > 0){ //La primera capa es la activa, no cacheamos
110
                                        if (cachedImage==null || cachedImage.getListPosition() < pos-1){
111

    
112
                                                if (composed != null){
113
                                                        //si tenemos una composicion de capas, necesitamos pintarlas
114
                                                        //antes de guardarnos la imagen
115
                                                        System.out.println("=======Pintando composicion de pintado "+ (layerPos-1)+" (antes de cache)============");
116
                                                        this.draw(composed, image, g, cancel, scale);
117
//                                                        composed.draw(image, g, viewPort, cancel, scale);
118
                                                        composed = null;
119

    
120
                                                }
121
                                                newCached = new CachedImage();
122
                                                newCached.setImage(image, mapContext, viewPort, pos-1);
123
                                                System.out.println("=======Guardando imagen de la pos "+ (layerPos-1)+"============");
124
                                        }
125
                                }
126
                                cached = true;
127
                        }
128

    
129
                        if (composed == null){
130
                                composed = layer.newComposedLayer();
131
                                if (composed != null){
132
                                        try {
133
                                                System.out.println("=== a?adiendo a composicion de pintado "+ layerPos+ " "+layer.getName());
134
                                                composed.add(layer);
135
                                                continue;
136
                                        } catch (Exception e) {
137
                                                throw new ReadDriverException("DefalutMapContexDrawer exception",e);
138
                                        }
139
                                }
140
                        }else{
141
                                if (composed.canAdd(layer)){
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("DefalutMapContexDrawer exception",e);
148
                                        }
149
                                } else {
150
                                        System.out.println("=======Pintando composicion de pintado "+ (layerPos-1)+" (cambio composicion)============");
151
                                        this.draw(composed, image, g, cancel, scale);
152
//                                        composed.draw(image, g, viewPort, cancel, scale);
153
                                        composed = layer.newComposedLayer();
154
                                        if (composed != null){
155
                                                try {
156
                                                        System.out.println("=== a?adiendo a composicion de pintado "+ layerPos+ " "+layer.getName());
157
                                                        composed.add(layer);
158
                                                        continue;
159
                                                } catch (Exception e) {
160
                                                        throw new ReadDriverException("DefalutMapContexDrawer exception",e);
161
                                                }                                        }
162
                                }
163
                        }
164
                        System.out.println("=== pintando "+ layerPos+ " "+layer.getName());
165
                        this.draw(layer, image, g, cancel, scale);
166
//                        layer.draw(image, g, viewPort, cancel, scale);
167

    
168
                }
169
                if (composed != null){
170
                        // si la composicion no se ha pintado la pintamos
171
                        System.out.println("=======Pintando composicion de pintado "+ (layerPos-1)+" (ultimo)============");
172
                        this.draw(composed, image, g, cancel, scale);
173
//                        composed.draw(image, g, viewPort, cancel, scale);
174
                }
175

    
176
                this.previousDrawList = drawList;
177
                this.cachedImage= newCached;
178

    
179
        }
180

    
181
        private void draw(Object layerOrComposed,BufferedImage image, Graphics2D g, Cancellable cancel,
182
                        double scale) throws ReadDriverException{
183
                ILabelable labelable= null;
184
                ILabelable tmp= null;
185
                if (layerOrComposed instanceof ILabelable){
186

    
187
                        tmp =(ILabelable) layerOrComposed;
188

    
189
                        if (tmp.isLabeled()
190
                                && tmp.getLabelingStrategy() != null
191
                                && tmp.getLabelingStrategy().shouldDrawLabels(scale)) {
192
                                labelable =tmp;
193
                        }
194
                }
195
                if (layerOrComposed instanceof FLayer){
196
                        FLayer layer = (FLayer) layerOrComposed;
197
                        layer.draw(image, g, viewPort, cancel, scale);
198
                } else{
199
                        ComposedLayer composed = (ComposedLayer) layerOrComposed;
200
                        composed.draw(image, g, viewPort, cancel, scale);
201
                }
202
                if (labelable != null){
203
                        labelable.drawLabels(image, g, viewPort, cancel, scale, MapContext.getScreenDPI());
204
                }
205

    
206
        }
207

    
208
        private void print(Object layerOrComposed,Graphics2D g, Cancellable cancel,
209
                        double scale, PrintRequestAttributeSet properties) throws ReadDriverException{
210
                ILabelable labelable= null;
211
                ILabelable tmp= null;
212
                if (layerOrComposed instanceof ILabelable){
213

    
214
                        tmp =(ILabelable) layerOrComposed;
215

    
216
                        if (tmp.isLabeled()
217
                                && tmp.getLabelingStrategy() != null
218
                                && tmp.getLabelingStrategy().shouldDrawLabels(scale)) {
219
                                labelable =tmp;
220
                        }
221
                }
222

    
223
                if (layerOrComposed instanceof FLayer){
224
                        FLayer layer = (FLayer) layerOrComposed;
225
                        layer.print(g, viewPort, cancel, scale, properties);
226
                } else{
227
                        ComposedLayer composed = (ComposedLayer) layerOrComposed;
228
                        composed.print(g, viewPort, cancel, scale, properties);
229
                }
230
                if (labelable != null){
231
                        labelable.printLabels(g, viewPort, cancel, scale, properties);
232
                }
233

    
234
        }
235

    
236
        public void setMapContext(MapContext mapContext) {
237
                if (this.mapContext == mapContext){
238
                        return;
239
                }
240
                this.clean();
241
                this.mapContext = mapContext;
242

    
243
        }
244

    
245
        public void setViewPort(ViewPort viewPort) {
246
                if (this.viewPort == viewPort){
247
                        return;
248
                }
249
                this.clean();
250
                this.viewPort = viewPort;
251

    
252
        }
253

    
254
        protected void clean(){
255
                this.cachedImage = null;
256
        }
257

    
258
        public class CachedImage{
259
                private BufferedImage image;
260
                private long mapContextVersion;
261
                private long viewPortVersion;
262
                private int listPosition;
263

    
264
                public void setImage(BufferedImage image,MapContext mapContext, ViewPort viewPort,int pos) {
265
                        this.image = new BufferedImage(image.getWidth(), image.getHeight(), image.getType());
266
                        WritableRaster w = this.image.getRaster();
267
                        image.copyData(w);
268
                        this.mapContextVersion = mapContext.getDrawVersion();
269
                        this.viewPortVersion = viewPort.getDrawVersion();
270
                        this.listPosition = pos;
271
                }
272

    
273
                public BufferedImage getImage() {
274
                        return image;
275
                }
276

    
277
                public long getMapContextVersion() {
278
                        return mapContextVersion;
279
                }
280

    
281
                public long getViewPortVersion() {
282
                        return viewPortVersion;
283
                }
284

    
285
                public int getListPosition(){
286
                        return this.listPosition;
287
                }
288

    
289
                public boolean isValid(MapContext context,ViewPort viewPort,int firstLayerToDraw){
290
                        if (viewPort.getDrawVersion() > this.viewPortVersion){
291
                                return false;
292
                        }
293
                        if (firstLayerToDraw <= this.listPosition){
294
                                return false;
295
                        }
296
                        return true;
297
                }
298
        }
299

    
300
        public class DrawList{
301
                private List layers = new ArrayList();
302
                private List all = new ArrayList();
303
                private List versions = new ArrayList();
304
                private DrawList previosList = null;
305
                private int firstLayerToDraw =-1;
306

    
307
                public DrawList(){
308
                }
309

    
310
                public DrawList(DrawList previousList){
311
                        if (previousList != null){
312
                                this.firstLayerToDraw =previousList.size();
313
                                this.previosList=previousList;
314
                        }
315
                }
316

    
317
                public int getLayerCount(){
318
                        return this.layers.size();
319
                }
320

    
321
                private boolean hasChanged(FLayer layer, int pos){
322
                        FLayer previous =(FLayer) this.previosList.layers.get(pos);
323
                        String previousName = previous.getName();
324
                        String layerName = layer.getName();
325
                        if (previous != layer){
326
                                return true;
327
                        }
328
                        long previousVersion = ((Long) this.previosList.versions.get(pos)).longValue();
329
                        long layerVersion = layer.getDrawVersion();
330

    
331
                        return previousVersion != layerVersion;
332
                }
333

    
334
                public void add(Object obj){
335
                        if (obj instanceof FLayer){
336
                                FLayer layer = (FLayer) obj;
337
                                int curIndex = this.layers.size();
338
                                if (this.firstLayerToDraw >= curIndex){
339
                                        if (this.previosList.getLayerCount() > curIndex){
340
                                                if (this.hasChanged(layer, curIndex)){
341
                                                        this.firstLayerToDraw = curIndex;
342
                                                }
343
                                        } else if (this.previosList.getLayerCount() == curIndex){
344
                                                this.firstLayerToDraw = curIndex;
345
                                        }
346
                                }
347
                                this.layers.add(layer);
348
                                this.versions.add(new Long(layer.getDrawVersion()));
349
                        } else if (!(obj instanceof LayersGroupEvent)){
350
                                throw new UnsupportedOperationException();
351
                        }
352

    
353
                        this.all.add(obj);
354
                }
355

    
356
                public int size(){
357
                        return this.all.size();
358
                }
359

    
360
                public int getFirstLayerToDraw(){
361
                        return this.firstLayerToDraw;
362
                }
363

    
364
                public FLayer getLayer(int pos){
365
                        return (FLayer) this.layers.get(pos);
366
                }
367

    
368
                public Object get(int pos){
369
                        return this.all.get(pos);
370
                }
371

    
372
        }
373

    
374
        private class SimpleLayerIterator extends LayersIterator{
375

    
376
                public SimpleLayerIterator(FLayer layer) {
377
                        this.appendLayer(layer);
378
                }
379

    
380
                public boolean evaluate(FLayer layer) {
381
                        if (layer instanceof FLayers) {
382
                                return false;
383
                        }
384
                        return layer.isAvailable() && layer.isVisible();
385
                }
386

    
387
        }
388

    
389
        public void dispose() {
390
                this.mapContext=null;
391
                this.viewPort=null;
392
                this.cachedImage=null;
393
                this.previousDrawList = null;
394
        }
395

    
396
        /* (non-Javadoc)
397
         * @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)
398
         */
399
        public void print(FLayers root, Graphics2D g, Cancellable cancel,
400
                        double scale, PrintRequestAttributeSet properties)
401
                        throws ReadDriverException {
402
                this.checkIntilalized();
403

    
404
                List printList = this.createPrintList(root, cancel);
405
                if (cancel.isCanceled()){
406
                        return;
407
                }
408

    
409

    
410
                ComposedLayer composed = null;
411
                int pos;
412
                FLayer layer;
413
                int layerPos= -1;
414
                Object obj;
415
                LayersGroupEvent event;
416
                for (pos=0; pos < printList.size(); pos++){
417
                        if (cancel.isCanceled()){
418
                                return;
419
                        }
420

    
421
                        obj = printList.get(pos);
422
                        if (obj instanceof ReadDriverException){
423
                                event = (LayersGroupEvent) obj;
424
                                if (event.type == LayersGroupEvent.IN_Event){
425
                                        System.out.println("=======Empiza a pintar grupo de capas "+ ((FLayers)event.group).getName() +"============");
426
                                        event.group.beginDraw(g, viewPort);
427
                                } else{
428
                                        event.group.endDraw(g, viewPort);
429
                                        System.out.println("=======Fin a pintar grupo de capas "+ ((FLayers)event.group).getName() +"============");
430

    
431
                                }
432
                                continue;
433
                        }
434
                        layerPos++;
435

    
436
                        layer = (FLayer) obj;
437

    
438

    
439
                        // *** Pintado de capa/composicion de capa ***
440
                        if (composed == null){
441
                                composed = layer.newComposedLayer();
442
                                if (composed != null){
443
                                        try {
444
                                                composed.add(layer);
445
                                                System.out.println("=======Imprimiendo composicion de pintado "+ (layerPos-1)+" ============");
446
                                                continue;
447
                                        } catch (Exception e) {
448
                                                throw new ReadDriverException("DefalutMapContexDrawer exception",e);
449
                                        }
450
                                }
451
                        }else{
452
                                if (composed.canAdd(layer)){
453
                                        try {
454
                                                composed.add(layer);
455
                                                System.out.println("=== a?adiendo a composicion de pintado "+ layerPos+ " "+layer.getName());
456
                                                continue;
457
                                        } catch (Exception e) {
458
                                                throw new ReadDriverException("DefalutMapContexDrawer exception",e);
459
                                        }
460
                                } else {
461
                                        System.out.println("=======Imprimiendo composicion de pintado "+ (layerPos-1)+" ============");
462
                                        this.print(composed, g, cancel, scale, properties);
463
//                                        composed.print( g, viewPort, cancel, scale,properties);
464
                                        composed = layer.newComposedLayer();
465
                                        if (composed != null){
466
                                                try {
467
                                                        composed.add(layer);
468
                                                        System.out.println("=== a?adiendo a composicion de pintado "+ layerPos+ " "+layer.getName());
469
                                                        continue;
470
                                                } catch (Exception e) {
471
                                                        throw new ReadDriverException("DefalutMapContexDrawer exception",e);
472
                                                }
473
                                        }
474
                                }
475
                        }
476
                        System.out.println("=== imprimiendo "+ layerPos+ " "+layer.getName());
477
                        this.print(layer, g, cancel, scale, properties);
478
//                        layer.print(g, viewPort, cancel, scale,properties);
479
                        // *** Pintado de capa/composicion de capa ***
480
                        if (composed != null){
481
                                // si la composicion no se ha pintado la pintamos
482
                                System.out.println("=======Imprimiendo composicion de pintado "+ (layerPos-1)+" (ultimo) ============");
483
                                this.print(composed, g, cancel, scale, properties);
484
//                                composed.print(g, viewPort, cancel, scale, properties);
485
                                composed = null;
486
                        }
487
                }
488

    
489

    
490
        }
491

    
492
        private DrawList createDrawList(FLayers root,Cancellable cancel){
493
                DrawList result = new DrawList(this.previousDrawList);
494
                MyLayerIterator iter = new MyLayerIterator((FLayer)root);
495
                while (iter.hasNext()){
496
                        if (cancel.isCanceled()){
497
                                return null;
498
                        }
499
                        result.add(iter.next());
500

    
501
                }
502

    
503
                return result;
504
        }
505

    
506
        private List createPrintList(FLayers root,Cancellable cancel){
507
                List result = new ArrayList();
508
                MyLayerIterator iter = new MyLayerIterator((FLayer)root);
509
                while (iter.hasNext()){
510
                        if (cancel.isCanceled()){
511
                                return null;
512
                        }
513
                        result.add(iter.next());
514

    
515
                }
516
                return result;
517
        }
518

    
519
        private class MyLayerIterator implements Iterator{
520
                ArrayList layersList  =new ArrayList();
521
                int index = 0;
522

    
523
                public MyLayerIterator(FLayer layer) {
524
                        this.appendLayer(layer);
525
                }
526

    
527
                protected void appendLayer(FLayer layer) {
528
                        if (this.evaluate(layer)) {
529
                                layersList.add(layer);
530
                        }
531
                        if (layer instanceof LayerCollection) {
532
                                appendLayers((LayerCollection)layer);
533
                        }
534
                }
535

    
536
                private void appendLayers(LayerCollection layers) {
537
                        int i;
538
                        layersList.add(new LayersGroupEvent(layers,LayersGroupEvent.IN_Event));
539
                        for (i=0;i< layers.getLayersCount();i++) {
540
                                appendLayer(layers.getLayer(i));
541
                        }
542
                        layersList.add(new LayersGroupEvent(layers,LayersGroupEvent.OUT_Event));
543
                }
544

    
545
                public void remove() {
546
                        throw new UnsupportedOperationException();
547
                }
548

    
549
                public boolean hasNext() {
550
                        return  index < layersList.size();
551
                }
552

    
553
                public Object next() {
554
                        if (!this.hasNext()) {
555
                                throw new NoSuchElementException();
556
                        }
557
                        Object aux = layersList.get(index);
558
                        index++;
559
                        return aux;
560
                }
561

    
562
                public boolean evaluate(FLayer layer) {
563
                        if (layer instanceof FLayers) {
564
                                return false;
565
                        }
566
                        return layer.isAvailable() && layer.isVisible();
567
                }
568

    
569
        }
570

    
571
        private class LayersGroupEvent {
572
                public static final String IN_Event = "in";
573
                public static final String OUT_Event = "Out";
574

    
575
                private LayerCollection group=null;
576
                private String type = IN_Event;
577

    
578
                public LayersGroupEvent(LayerCollection group,String type){
579
                        this.group =group;
580
                        this.type =type;
581
                }
582

    
583

    
584
                public String getType() {
585
                        return type;
586
                }
587

    
588
                public LayerCollection getGroup() {
589
                        return group;
590
                }
591
        }
592

    
593
}