Statistics
| Revision:

svn-gvsig-desktop / trunk / org.gvsig.desktop / org.gvsig.desktop.compat.cdc / org.gvsig.fmap.mapcontext / org.gvsig.fmap.mapcontext.api / src / main / java / org / gvsig / fmap / mapcontext / layers / FLayers.java @ 45535

History | View | Annotate | Download (45.5 KB)

1
/**
2
 * gvSIG. Desktop Geographic Information System.
3
 *
4
 * Copyright (C) 2007-2013 gvSIG Association.
5
 *
6
 * This program is free software; you can redistribute it and/or modify it under
7
 * the terms of the GNU General Public License as published by the Free Software
8
 * Foundation; either version 3 of the License, or (at your option) any later
9
 * version.
10
 *
11
 * This program is distributed in the hope that it will be useful, but WITHOUT
12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
14
 * details.
15
 *
16
 * You should have received a copy of the GNU General Public License along with
17
 * this program; if not, write to the Free Software Foundation, Inc., 51
18
 * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19
 *
20
 * For any additional information, do not hesitate to contact us at info AT
21
 * gvsig.com, or visit our website www.gvsig.com.
22
 */
23
package org.gvsig.fmap.mapcontext.layers;
24

    
25
import java.awt.Graphics2D;
26
import java.awt.Point;
27
import java.awt.image.BufferedImage;
28
import java.util.ArrayList;
29
import java.util.Collection;
30
import java.util.Collections;
31
import java.util.Iterator;
32
import java.util.List;
33
import java.util.ListIterator;
34
import java.util.Set;
35
import java.util.TreeSet;
36
import java.util.function.Predicate;
37
import org.apache.commons.lang3.StringUtils;
38
import org.cresques.cts.ICoordTrans;
39
import org.cresques.cts.IProjection;
40
import org.gvsig.compat.print.PrintAttributes;
41
import org.gvsig.fmap.dal.DataStore;
42
import org.gvsig.fmap.dal.exception.DataException;
43
import org.gvsig.fmap.dal.exception.ReadException;
44
import org.gvsig.fmap.dal.feature.FeatureSelection;
45
import org.gvsig.fmap.dal.feature.FeatureStore;
46
import org.gvsig.fmap.geom.primitive.Envelope;
47
import org.gvsig.fmap.mapcontext.MapContext;
48
import org.gvsig.fmap.mapcontext.MapContextLocator;
49
import org.gvsig.fmap.mapcontext.MapContextRuntimeException;
50
import org.gvsig.fmap.mapcontext.Messages;
51
import org.gvsig.fmap.mapcontext.ViewPort;
52
import org.gvsig.fmap.mapcontext.exceptions.LoadLayerException;
53
import org.gvsig.fmap.mapcontext.layers.operations.ComposedLayer;
54
import org.gvsig.fmap.mapcontext.layers.operations.InfoByPoint;
55
import org.gvsig.fmap.mapcontext.layers.operations.LayerCollection;
56
import org.gvsig.fmap.mapcontext.layers.operations.LayerNotFoundInCollectionException;
57
import org.gvsig.fmap.mapcontext.layers.operations.LayersVisitable;
58
import org.gvsig.fmap.mapcontext.layers.operations.LayersVisitor;
59
import org.gvsig.fmap.mapcontext.layers.operations.SingleLayer;
60
import org.gvsig.fmap.mapcontext.layers.vectorial.FLyrVect;
61
import org.gvsig.fmap.mapcontext.rendering.legend.styling.ILabelable;
62
import org.gvsig.metadata.exceptions.MetadataException;
63
import org.gvsig.tools.ToolsLocator;
64
import org.gvsig.tools.dynobject.DynObjectSet;
65
import org.gvsig.tools.dynobject.DynStruct;
66
import org.gvsig.tools.dynobject.impl.MultiDynObjectSet;
67
import org.gvsig.tools.exception.BaseException;
68
import org.gvsig.tools.persistence.PersistenceManager;
69
import org.gvsig.tools.persistence.PersistentState;
70
import org.gvsig.tools.persistence.exception.PersistenceException;
71
import org.gvsig.tools.task.Cancellable;
72
import org.gvsig.tools.util.Callable;
73
import org.gvsig.tools.visitor.Visitor;
74
import org.slf4j.Logger;
75
import org.slf4j.LoggerFactory;
76

    
77
/**
78
 * <p>
79
 * Represents a generic collection of layers, that can be represented as a node
80
 * in a tree of nodes of layers.</p>
81
 *
82
 * <p>
83
 * Adapts the basic functionality implemented for a layer in the abstract class
84
 * <code>FLyrDefault</code>, to a collection of layers, implementing, as well,
85
 * specific methods for this kind of object, defined in the interfaces
86
 * <code>VectorialData</code>, <code>LayerCollection</code>, and
87
 * <code>InfoByPoint</code>.</p>
88
 *
89
 * @see FLyrDefault
90
 */
91
public class FLayers extends FLyrDefault implements LayerCollection,
92
        InfoByPoint, List<FLayer> {
93

    
94
    /**
95
     * List with all listeners registered for this kind of node.
96
     */
97
    protected ArrayList<LayerCollectionListener> layerCollectionListeners = null;
98

    
99
    /**
100
     * A synchronized list with the layers.
101
     */
102
    protected List<FLayer> layers = null;
103

    
104
    protected MapContext fmap;
105

    
106
    /**
107
     * Useful for debug the problems during the implementation.
108
     */
109
    private static final Logger LOGGER = LoggerFactory.getLogger(FLayers.class);
110
    
111
    public static final Predicate<FLayer> LAYER_ACTIVE = new Predicate<FLayer>() {
112
        @Override
113
        public boolean test(FLayer layer) {
114
            return layer.isActive();
115
        }
116
    };
117

    
118
    public static final Predicate<FLayer> LAYER_AVALAIBLE = new Predicate<FLayer>() {
119
        @Override
120
        public boolean test(FLayer layer) {
121
            return layer.isAvailable();
122
        }
123
    };
124

    
125
    public static Predicate<FLayer> LAYER_FLYRVECT = new Predicate<FLayer>() {
126
        @Override
127
        public boolean test(FLayer layer) {
128
            return layer instanceof FLyrVect;
129
        }
130
    };
131
    public static Predicate<FLayer> LAYER_SELECTION_AVAILABLE = new Predicate<FLayer>() {
132
        @Override
133
        public boolean test(FLayer layer) {
134
            if (layer instanceof FLyrVect) {
135
                try {
136
                    FeatureStore store = ((FLyrVect) layer).getFeatureStore();
137
                    if (store.getFeatureSelection().isAvailable()) {
138
                        return true;
139
                    }
140
                } catch (Exception ex) {
141
                    return false;
142
                }
143
            }
144
            return false;
145
        }
146
    };
147
    
148
    public static Predicate<FLayer> LAYER_SELECTION_EMPTY = new Predicate<FLayer>() {
149
        @Override
150
        public boolean test(FLayer layer) {
151
            if (layer instanceof FLyrVect) {
152
                try {
153
                    FeatureStore store = ((FLyrVect) layer).getFeatureStore();
154
                    FeatureSelection selection = store.getFeatureSelection();
155
                    if (!selection.isAvailable() || selection.isEmpty()) {
156
                        return true;
157
                    }
158
                    return false;
159
                } catch (Exception ex) {
160
                    return true;
161
                }
162
            } else {
163
                return true;
164
            }
165
        }
166
    };
167

    
168
    public FLayers() {
169
        super();
170
        layerCollectionListeners = new ArrayList();
171
        layers = Collections.synchronizedList(new ArrayList());
172
    }
173

    
174
    @Override
175
    public void addLayerCollectionListener(LayerCollectionListener listener) {
176
        if (!layerCollectionListeners.contains(listener)) {
177
            layerCollectionListeners.add(listener);
178
        }
179
    }
180

    
181
    /*
182
     * (non-Javadoc)
183
     * @see com.iver.cit.gvsig.fmap.layers.layerOperations.LayerCollection#setAllVisibles(boolean)
184
     */
185
    @Override
186
    public void setAllVisibles(boolean visible) {
187
        FLayer lyr;
188

    
189
        for (int i = 0; i < layers.size(); i++) {
190
            lyr = ((FLayer) layers.get(i));
191
            lyr.setVisible(visible);
192

    
193
            if (lyr instanceof LayerCollection) {
194
                ((LayerCollection) lyr).setAllVisibles(visible);
195
            }
196
        }
197
    }
198

    
199
    @Override
200
    public void removeLayerCollectionListener(LayerCollectionListener listener) {
201
        layerCollectionListeners.remove(listener);
202
    }
203

    
204
    /**
205
     * Adds a layer on an specified position in this node.
206
     *
207
     * @param pos position in the inner list where the layer will be added
208
     * @param layer a layer
209
     */
210
    private void doAddLayer(int pos, FLayer layer) {
211
        layers.add(pos, layer);
212
        ToolsLocator.getDisposableManager().bind(layer);
213
        layer.setParentLayer(this);
214
        IProjection layerProj = layer.getProjection();
215
        if (layerProj != null && fmap != null) {
216
            IProjection mapContextProj = fmap.getProjection();
217
            // TODO REVISAR ESTO !!!!
218
            // Esta condici?n puede que no fuese exacta para todos los casos
219
            if (!layerProj.getAbrev().equals(mapContextProj.getAbrev())) {
220
                ICoordTrans ct = layerProj.getCT(mapContextProj);
221
                layer.setCoordTrans(ct);
222
            } else {
223
                layer.setCoordTrans(null);
224
            }
225
        }
226
        this.updateDrawVersion();
227
    }
228

    
229
    @Override
230
    public void addLayer(FLayer layer) {
231

    
232
        MapContext mco = this.getMapContext();
233

    
234
        if (mco != null) {
235
            /*
236
             * Get order manager from map context
237
             */
238
            int position = mco.getOrderManager().getPosition(this, layer);
239
            addLayer(position, layer);
240
        } else {
241
            /*
242
             * This happens when FLayers object is not in a
243
             * map context, so no order manager is available.
244
             */
245
            addLayer(layers.size(), layer);
246
        }
247
    }
248
    
249
    public void addLayer(DataStore store) {
250
        FLayer layer;
251
        try {
252
            layer = MapContextLocator.getMapContextManager().createLayer(
253
                    store.getName(),
254
                    store
255
            );
256
            
257
        } catch (LoadLayerException ex) {
258
            throw new RuntimeException("Can't create layer from store.", ex);
259
        }
260
        this.addLayer(layer);
261
    }
262

    
263
    /**
264
     * Adds a layer in an specified position in this node.
265
     *
266
     * @param pos
267
     * @param layer a layer
268
     */
269
    public void addLayer(int pos, FLayer layer) {
270
        try {
271
            if (layer instanceof FLayers) {
272
                FLayers layersToAdd = (FLayers) layer;
273
                if( fmap != null ) {
274
                    fmap.addAsCollectionListener(layersToAdd);
275
                }
276
            }
277
            callLayerAdding(LayerCollectionEvent.createLayerAddingEvent(layer));
278

    
279
            doAddLayer(pos, layer);
280

    
281
            callLayerAdded(LayerCollectionEvent.createLayerAddedEvent(layer));
282
        } catch (CancelationException e) {
283
            LOGGER.warn(e.getMessage());
284
        }
285
    }
286

    
287
    @Override
288
    public void moveTo(int from, int to) throws CancelationException {
289
        int newfrom = layers.size() - from - 1;
290
        int newto = layers.size() - to - 1;
291
        if (newfrom < 0 || newfrom >= layers.size() || newto < 0 || newto >= layers.size()) {
292
            return;
293
        }
294
        FLayer aux = (FLayer) layers.get(newfrom);
295
        callLayerMoving(LayerPositionEvent.createLayerMovingEvent(aux, newfrom, newto));
296
        layers.remove(newfrom);
297
        layers.add(newto, aux);
298
        this.updateDrawVersion();
299
        callLayerMoved(LayerPositionEvent.createLayerMovedEvent(aux, newfrom, newto));
300
    }
301

    
302
    /**
303
     * Removes an inner layer.
304
     *
305
     * @param lyr a layer
306
     */
307
    private void doRemoveLayer(FLayer lyr) {
308
        layers.remove(lyr);
309
        lyr.dispose();
310
        this.updateDrawVersion();
311
    }
312

    
313
    @Override
314
    public void removeLayer(FLayer lyr) throws CancelationException {
315
        callLayerRemoving(LayerCollectionEvent.createLayerRemovingEvent(lyr));
316
        doRemoveLayer(lyr);
317
        callLayerRemoved(LayerCollectionEvent.createLayerRemovedEvent(lyr));
318
    }
319

    
320
    @Override
321
    public void removeLayer(int idLayer) {
322
        FLayer lyr = (FLayer) layers.get(idLayer);
323
        callLayerRemoving(LayerCollectionEvent.createLayerRemovingEvent(lyr));
324
        this.doRemoveLayer(lyr);
325
//                layers.remove(idLayer);
326
//                this.updateDrawVersion();
327
        callLayerRemoved(LayerCollectionEvent.createLayerRemovedEvent(lyr));
328
    }
329

    
330
    @Override
331
    public void removeLayer(String layerName) {
332
        FLayer lyr;
333

    
334
        for (int i = 0; i < layers.size(); i++) {
335
            lyr = ((FLayer) layers.get(i));
336

    
337
            if (lyr.getName().compareToIgnoreCase(layerName) == 0) {
338
                removeLayer(i);
339

    
340
                break;
341
            }
342
        }
343
    }
344

    
345
    /**
346
     * Replace a layer identified by its name, by another.
347
     *
348
     * @param layerName the name of the layer to be replaced
349
     * @param layer the new layer
350
     * @throws org.gvsig.fmap.mapcontext.exceptions.LoadLayerException
351
     * @deprecated use {@link FLayers#replaceLayer(FLayer, FLayer)}
352
     */
353
    public void replaceLayer(String layerName, FLayer layer) throws LoadLayerException {
354
        replaceLayer(getLayer(layerName), layer);
355
    }
356

    
357
    /**
358
     * Replace a layer by another layer. It search recursively by all the
359
     * ILayerCollection nodes
360
     *
361
     * @param layer the layer to be replaced
362
     * @param newLayer the new layer
363
     * @throws org.gvsig.fmap.mapcontext.exceptions.LoadLayerException
364
     */
365
    public void replaceLayer(FLayer layer, FLayer newLayer) throws LoadLayerException {
366
        replaceLayer(this, layer, newLayer);
367
    }
368

    
369
    /**
370
     * Replace a layer by other layer. It search recursively by all the
371
     * ILayerCollection nodes
372
     *
373
     * @param parentLayer the parent layer
374
     * @param layer the layer to be replaced
375
     * @param newLayer the new layer
376
     * @throws LoadLayerException
377
     */
378
    private void replaceLayer(FLayers parentLayer, FLayer layer, FLayer newLayer) throws LoadLayerException {
379
        FLayer lyr;
380
        for (int i = 0; i < parentLayer.getLayersCount(); i++) {
381
            lyr = ((FLayer) parentLayer.getLayer(i));
382
            if (lyr.equals(layer)) {
383
                parentLayer.removeLayer(i);
384
                parentLayer.addLayer(i, newLayer);
385
                break;
386
            }
387
            if (lyr instanceof LayerCollection) {
388
                replaceLayer((FLayers) lyr, layer, newLayer);
389
            }
390
        }
391
    }
392

    
393
    @Override
394
    public FLayer[] getVisibles() {
395
        ArrayList array = new ArrayList();
396
        LayersIterator iter = new LayersIterator(this) {
397
            @Override
398
            public boolean evaluate(FLayer layer) {
399
                return layer.isVisible();
400
            }
401

    
402
        };
403

    
404
        while (iter.hasNext()) {
405
            array.add(iter.nextLayer());
406
        }
407

    
408
        return (FLayer[]) array.toArray(new FLayer[0]);
409
    }
410

    
411
    @Override
412
    public FLayer getLayer(int index) {
413
        return (FLayer) layers.get(index);
414
    }
415

    
416
    @Override
417
    public FLayer getLayer(final String layerName) {
418
        if( StringUtils.isBlank(layerName) ) {
419
            return null;
420
        }
421
        for (FLayer layer : this.layers) {
422
            if( layer!=null && StringUtils.equalsIgnoreCase(layer.getName(), layerName) ) {
423
                return layer;
424
            }
425
            if( layer instanceof FLayers ) {
426
                List<FLayer> theLayers = this.getLayers(new Predicate<FLayer>() {
427
                    @Override
428
                    public boolean test(FLayer layer) {
429
                        return StringUtils.equalsIgnoreCase(layer.getName(), layerName);                        
430
                    }
431
                });
432
                if( theLayers.isEmpty() ) {
433
                    return null;
434
                }
435
                return theLayers.get(0);
436
            }
437
        }
438
        return null;
439
    }
440

    
441
    @Override
442
    public FLayer getLayer(final DataStore store) {
443
        List<FLayer> theLayers = this.getLayers(new Predicate<FLayer>() {
444
            @Override
445
            public boolean test(FLayer layer) {
446
                return  layer instanceof SingleLayer && store == ((SingleLayer) layer).getDataStore();
447
            }
448
        });
449
        if( theLayers.isEmpty() ) {
450
            return null;
451
        }
452
        return theLayers.get(0);
453
    }
454
    
455
    private List<FLayer> toPlainList(FLayer layer) {
456
        return toPlainList(layer, new ArrayList<FLayer>(), null);
457
    }
458

    
459
    private List<FLayer> toPlainList(FLayer layer, Predicate<FLayer> filter) {
460
        return toPlainList(layer, new ArrayList<FLayer>(), filter);
461
    }
462

    
463
    private List<FLayer> toPlainList(FLayer layer, List<FLayer> result, Predicate<FLayer> filter) {
464
        if (layer instanceof FLayers) {
465
            FLayers layerGroup = (FLayers) layer;
466
            if (filter == null || filter.test(layer)) {
467
                result.add(layer);
468
            }
469
            for (int i = 0; i < layerGroup.getLayersCount(); i++) {
470
                toPlainList(layerGroup.getLayer(i), result, filter);
471
            }
472
        } else if( filter==null || filter.test(layer) ) {
473
            result.add(layer);
474
        }
475
        return result;
476
    }
477

    
478
    @Override
479
    public int getLayersCount() {
480
        return layers.size();
481
    }
482

    
483
    @Override
484
    public void draw(BufferedImage image, Graphics2D g, ViewPort viewPort,
485
            Cancellable cancel, double scale) throws ReadException {
486
        // FIXME Arreglar este error
487
        throw new RuntimeException("Esto no deberia de llamarse");
488
    }
489

    
490
    /*
491
     * (non-Javadoc)
492
     *
493
     * @see com.iver.cit.gvsig.fmap.layers.FLayer#print(java.awt.Graphics2D,
494
     * com.iver.cit.gvsig.fmap.ViewPort,
495
     * com.iver.utiles.swing.threads.Cancellable, double,
496
     * javax.print.attribute.PrintAttributes)
497
     */
498
    @Override
499
    public void print(Graphics2D g, ViewPort viewPort, Cancellable cancel,
500
            double scale, PrintAttributes properties)
501
            throws ReadException {
502
        throw new RuntimeException("No deberia pasar por aqui");
503
    }
504

    
505
    public void print_old(Graphics2D g, ViewPort viewPort, Cancellable cancel,
506
            double scale, PrintAttributes properties)
507
            throws ReadException {
508
        this.print_old(g, viewPort, cancel, scale, properties, null);
509
    }
510

    
511
    /**
512
     * <p>
513
     * Checks all layers (each one as a sub-node of this node <i>collection of
514
     * layers</i>) of this collection and draws their requested properties. If a
515
     * node is a group of layers (<code>ComposedLayer</code>), executes it's
516
     * drawn.</p>
517
     *
518
     * <p>
519
     * All nodes which could group with the composed layer <code>group</code>,
520
     * will be drawn together. And once the <code>
521
     * group</code> is drawn, will be set to <code>null</code> if hasn't a
522
     * parent layer.</p>
523
     *
524
     * <p>
525
     * The particular implementation depends on the kind of each layer and
526
     * composed layer. And this process can be cancelled at any time by the
527
     * shared object <code>cancel</code>.</p>
528
     *
529
     * <p>
530
     * According the print quality, labels will be printed in different
531
     * resolution:
532
     * <ul>
533
     * <li><b>PrintQuality.DRAFT</b>: 72 dpi (dots per inch).</li>
534
     * <li><b>PrintQuality.NORMAL</b>: 300 dpi (dots per inch).</li>
535
     * <li><b>PrintQuality.HIGH</b>: 600 dpi (dots per inch).</li>
536
     * </ul>
537
     * </p>
538
     *
539
     * @param g for rendering 2-dimensional shapes, text and images on the
540
     * Java(tm) platform
541
     * @param viewPort the information for drawing the layers
542
     * @param cancel shared object that determines if this layer can continue
543
     * being drawn
544
     * @param scale the scale of the view. Must be between
545
     * {@linkplain FLayer#getMinScale()} and {@linkplain FLayer#getMaxScale()}.
546
     * @param properties properties that will be print
547
     * @param group a composed layer pending to paint; if this parameter is
548
     * <code>null</code>, the composed layer
549
     *
550
     * @return <code>null</code> if the layers in <code>group</code> had been
551
     * drawn or were <code>null</code>; otherwise, the <code>group</code>
552
     * @throws org.gvsig.fmap.dal.exception.ReadException
553
     *
554
     * @see FLayer#print(Graphics2D, ViewPort, Cancellable, double,
555
     * PrintAttributes)
556
     */
557
    public ComposedLayer print_old(Graphics2D g, ViewPort viewPort, Cancellable cancel, double scale, PrintAttributes properties, ComposedLayer group)
558
            throws ReadException {
559
        double dpi = 72;
560

    
561
        int resolution = properties.getPrintQuality();
562
        switch (resolution) {
563
            case PrintAttributes.PRINT_QUALITY_NORMAL:
564
                dpi = 300;
565
                break;
566
            case PrintAttributes.PRINT_QUALITY_HIGH:
567
                dpi = 600;
568
                break;
569
            case PrintAttributes.PRINT_QUALITY_DRAFT:
570
                dpi = 72;
571
                break;
572
            default:
573
                break;
574
        }
575

    
576
        // TODO: A la hora de imprimir, isWithinScale falla, porque est?
577
        // calculando la escala en pantalla, no para el layout.
578
        // Revisar esto.
579
        // TODO: We have to check when we have to call the drawLabels method when exists a ComposedLayer group.
580
        for (int i = 0; i < layers.size(); i++) {
581
            FLayer lyr = (FLayer) layers.get(i);
582
            if (!lyr.isVisible() || !lyr.isWithinScale(scale)) {
583
                continue;
584
            }
585

    
586
            try {
587

    
588
                // Checks for draw group (ComposedLayer)
589
                if (group != null) {
590
                    if (lyr instanceof FLayers) {
591
                        group = ((FLayers) lyr).print_old(g, viewPort, cancel, scale, properties, group);
592
                    } else {
593
                        // If layer can be added to the group, does it
594
                        if (lyr instanceof ILabelable
595
                                && ((ILabelable) lyr).isLabeled()
596
                                && ((ILabelable) lyr).getLabelingStrategy() != null
597
                                && ((ILabelable) lyr).getLabelingStrategy().shouldDrawLabels(scale)) {
598
                            group.add(lyr);
599
                        } else {
600
                            // draw the 'pending to draw' layer group
601
                            group.print(g, viewPort, cancel, scale, properties);
602

    
603
                            // gets a new group instance
604
                            if (lyr instanceof ILabelable
605
                                    && ((ILabelable) lyr).isLabeled()
606
                                    && ((ILabelable) lyr).getLabelingStrategy() != null
607
                                    && ((ILabelable) lyr).getLabelingStrategy().shouldDrawLabels(scale)) {
608
                                group = lyr.newComposedLayer();
609
                            } else {
610
                                group = null;
611
                            }
612
                            // if layer hasn't group, draws it inmediately
613
                            if (group == null) {
614
                                if (lyr instanceof FLayers) {
615
                                    group = ((FLayers) lyr).print_old(g, viewPort, cancel, scale, properties, group);
616
                                } else {
617
                                    lyr.print(g, viewPort, cancel, scale, properties);
618
                                    if (lyr instanceof ILabelable
619
                                            && ((ILabelable) lyr).isLabeled()
620
                                            && ((ILabelable) lyr).getLabelingStrategy() != null
621
                                            && ((ILabelable) lyr).getLabelingStrategy().shouldDrawLabels(scale)) {
622
                                        ILabelable lLayer = (ILabelable) lyr;
623
                                        lLayer.drawLabels(null, g, viewPort, cancel, scale, dpi);
624
                                    }
625
                                }
626
                            } else {
627
                                // add the layer to the group
628
                                group.setMapContext(fmap);
629
                                group.add(lyr);
630

    
631
                            }
632

    
633
                        }
634
                    }
635
                } else {
636
                    // gets a new group instance
637
                    group = lyr.newComposedLayer();
638
                    // if layer hasn't group, draws it inmediately
639
                    if (group == null) {
640
                        if (lyr instanceof FLayers) {
641
                            group = ((FLayers) lyr).print_old(g, viewPort, cancel, scale, properties, group);
642
                        } else {
643
                            lyr.print(g, viewPort, cancel, scale, properties);
644
                            if (lyr instanceof ILabelable && ((ILabelable) lyr).isLabeled()) {
645
                                ILabelable lLayer = (ILabelable) lyr;
646

    
647
                                lLayer.drawLabels(null, g, viewPort, cancel, scale, dpi);
648
                            }
649
                        }
650
                    } else {
651
                        // add the layer to the group
652
                        group.setMapContext(fmap);
653
                        group.add(lyr);
654

    
655
                    }
656
                }
657

    
658
            } catch (Exception e) {
659
                String mesg = Messages.getString("error_printing_layer") + " " + lyr.getName() + ": " + e.getMessage();
660
                if( fmap!=null ) {
661
                    fmap.addLayerError(mesg);
662
                }
663
                LOGGER.error(mesg, e);
664
            }
665

    
666
        }
667

    
668
        if (group != null && this.getParentLayer() == null) {
669
            //si tenemos un grupo pendiente de pintar, pintamos
670
            group.print(g, viewPort, cancel, scale, properties);
671
            group = null;
672

    
673
        }
674
        return group;
675
    }
676

    
677
    @Override
678
    @SuppressWarnings("UseSpecificCatch")
679
    public Envelope getFullEnvelope() {
680
        Envelope rAux = null;
681
        boolean first = true;
682

    
683
        for (FLayer capa : layers) {
684
            try {
685
                if (first) {
686
                    rAux = (Envelope) capa.getFullEnvelope().clone();
687
                    first = false;
688
                } else {
689
                    rAux.add(capa.getFullEnvelope());
690
                }
691
            } catch (Exception e) {
692
                LOGGER.warn("Can't calculate the envelope of the layer group '"+this.getName()+"'.",e);
693
            }
694
        }
695

    
696
        return rAux;
697
    }
698

    
699
    /**
700
     * Notifies all listeners associated to this collection of layers, that
701
     * another layer is going to be added or replaced in the internal list of
702
     * layers.
703
     *
704
     * @param event a layer collection event with the new layer
705
     */
706
    protected void callLayerAdding(LayerCollectionEvent event)
707
            throws CancelationException {
708
        ArrayList aux = (ArrayList) layerCollectionListeners.clone();
709
        for (Iterator iter = aux.iterator(); iter.hasNext();) {
710
            ((LayerCollectionListener) iter.next()).layerAdding(event);
711
        }
712
    }
713

    
714
    /**
715
     * Notifies all listeners associated to this collection of layers, that a
716
     * layer is going to be removed from the internal list of layers.
717
     *
718
     * @param event a layer collection event with the layer being removed
719
     *
720
     * @throws CancelationException any exception produced during the
721
     * cancellation of the driver.
722
     */
723
    protected void callLayerRemoving(LayerCollectionEvent event)
724
            throws CancelationException {
725
        ArrayList aux = (ArrayList) layerCollectionListeners.clone();
726
        for (Iterator iter = aux.iterator(); iter.hasNext();) {
727
            ((LayerCollectionListener) iter.next()).layerRemoving(event);
728
        }
729
    }
730

    
731
    /**
732
     * Notifies all listeners associated to this collection of layers, that a
733
     * layer is going to be moved in the internal list of layers.
734
     *
735
     * @param event a layer collection event with the layer being moved, and the
736
     * initial and final positions
737
     *
738
     * @throws CancelationException any exception produced during the
739
     * cancellation of the driver.
740
     */
741
    protected void callLayerMoving(LayerPositionEvent event)
742
            throws CancelationException {
743
        ArrayList aux = (ArrayList) layerCollectionListeners.clone();
744
        for (Iterator iter = aux.iterator(); iter.hasNext();) {
745
            ((LayerCollectionListener) iter.next()).layerMoving(event);
746
        }
747
    }
748

    
749
    /**
750
     * Notifies all listeners associated to this collection of layers, that
751
     * another layer has been added or replaced in the internal list of layers.
752
     *
753
     * @param event a layer collection event with the new layer
754
     */
755
    protected void callLayerAdded(LayerCollectionEvent event) {
756
        ArrayList aux = (ArrayList) layerCollectionListeners.clone();
757
        for (Iterator iter = aux.iterator(); iter.hasNext();) {
758
            ((LayerCollectionListener) iter.next()).layerAdded(event);
759
        }
760
    }
761

    
762
    /**
763
     * Notifies all listeners associated to this collection of layers, that
764
     * another layer has been removed from the internal list of layers.
765
     *
766
     * @param event a layer collection event with the layer removed
767
     */
768
    protected void callLayerRemoved(LayerCollectionEvent event) {
769
        ArrayList aux = (ArrayList) layerCollectionListeners.clone();
770
        for (Iterator iter = aux.iterator(); iter.hasNext();) {
771
            ((LayerCollectionListener) iter.next()).layerRemoved(event);
772
        }
773
    }
774

    
775
    /**
776
     * Notifies all listeners associated to this collection of layers, that
777
     * another layer has been moved in the internal list of layers.
778
     *
779
     * @param event a layer collection event with the layer moved, and the initial
780
     * and final positions
781
     */
782
    protected void callLayerMoved(LayerPositionEvent event) {
783
        ArrayList aux = (ArrayList) layerCollectionListeners.clone();
784
        for (Iterator iter = aux.iterator(); iter.hasNext();) {
785
            ((LayerCollectionListener) iter.next()).layerMoved(event);
786
        }
787
    }
788

    
789
    @Override
790
    public void saveToState(PersistentState state) throws PersistenceException {
791

    
792
        super.saveToState(state);
793

    
794
        state.set("mapContext", fmap);
795

    
796
        List layersToSave = new ArrayList();
797
        for (FLayer layer : this.layers) {
798
            if (!layer.isTemporary()) {
799
                layersToSave.add(layer);
800
            }
801
        }
802
        state.set("layers", layersToSave);
803
    }
804

    
805
    @Override
806
    public void loadFromState(PersistentState state) throws PersistenceException {
807

    
808
        super.loadFromState(state);
809

    
810
        setMapContext((MapContext) state.get("mapContext"));
811
        Iterator iter = state.getIterator("layers");
812
        while (iter.hasNext()) {
813
            FLayer item = (FLayer) iter.next();
814
            // Cuando falla la carga de la capa desde la persistencia, puede
815
            // haberse perdido quien es el parent. Asi que lo asignamos aqui
816
            // por si acaso.
817
            item.setParentLayer(this);
818
            layers.add(item);
819
        }
820
    }
821

    
822
    @Override
823
    public MapContext getMapContext() {
824
        return fmap;
825
    }
826

    
827
    @Override
828
    public void setAllActives(boolean active) {
829
        FLayer lyr;
830

    
831
        for (int i = 0; i < layers.size(); i++) {
832
            lyr = ((FLayer) layers.get(i));
833
            lyr.setActive(active);
834

    
835
            if (lyr instanceof LayerCollection) {
836
                ((LayerCollection) lyr).setAllActives(active);
837
            }
838
        }
839
    }
840

    
841
    @Override
842
    public List<FLayer> getLayers(Predicate<FLayer> filter) {
843
        List<FLayer> theLayers = this.toPlainList(this, filter);
844
        return theLayers;
845
    }
846
    
847
    @Override
848
    public FLayer[] getActives() {
849
        List<FLayer> activeLayers = this.getLayers(new Predicate<FLayer>() {
850
            @Override
851
            public boolean test(FLayer layer) {
852
                return layer.isActive();
853
            }
854
        });
855
        return (FLayer[]) activeLayers.toArray(new FLayer[activeLayers.size()]);
856
    }
857
                   
858
    @Override
859
    public double getMinScale() {
860
        return -1; // La visibilidad o no la controla cada capa
861
        // dentro de una colecci?n
862
    }
863

    
864
    @Override
865
    public double getMaxScale() {
866
        return -1;
867
    }
868

    
869
    @Override
870
    public void setMinScale(double minScale) {
871
        for (FLayer lyr : layers) {
872
            lyr.setMinScale(minScale);
873
        }
874
    }
875

    
876
    @Override
877
    public void setMaxScale(double maxScale) {
878
        for (FLayer lyr : layers) {
879
            lyr.setMinScale(maxScale);
880
        }
881
    }
882

    
883
    @Override
884
    public void setActive(boolean b) {
885
        super.setActive(b);
886
        for (FLayer layer : this.layers) {
887
            layer.setActive(b);
888
        }
889
    }
890

    
891
    @Override
892
    public boolean addLayerListener(LayerListener o) {
893
        for (FLayer layer : this.layers) {
894
            layer.addLayerListener(o);
895
        }
896
        return true;
897
    }
898

    
899
    @Override
900
    public DynObjectSet getInfo(Point p, double tolerance,
901
            Cancellable cancel) throws LoadLayerException, DataException {
902
        return getInfo(this.getMapContext().getViewPort().convertToMapPoint(p), tolerance);
903
    }
904

    
905
    @Override
906
    public DynObjectSet getInfo(Point p, double tolerance, Cancellable cancel,
907
            boolean fast) throws LoadLayerException, DataException {
908
        return getInfo(this.getMapContext().getViewPort().convertToMapPoint(p), tolerance);
909
    }
910

    
911
    @Override
912
    public DynObjectSet getInfo(org.gvsig.fmap.geom.primitive.Point p,
913
            double tolerance) throws LoadLayerException, DataException {
914
        int i;
915
        FLayer layer;
916
        List res = new ArrayList();
917
        for (i = 0; i < this.layers.size(); i++) {
918
            layer = (FLayer) layers.get(i);
919
            if (layer instanceof InfoByPoint) {
920
                InfoByPoint queryable_layer = (InfoByPoint) layer;
921
                res.add(queryable_layer.getInfo(p, tolerance));
922
            }
923
        }
924
        DynObjectSet[] innerSets
925
                = (DynObjectSet[]) res.toArray(new DynObjectSet[res.size()]);
926
        return new MultiDynObjectSet(innerSets);
927
    }
928

    
929
    @Override
930
    public String getTocImageIcon() {
931
        return "layer-icon-group";
932
    }
933

    
934
    /**
935
     * <p>
936
     * Sets the <code>MapContext</code> that contains this layer node.</p>
937
     *
938
     * @param mapContext the <code>MapContext</code> that contains this layer
939
     * node
940
     */
941
    public void setMapContext(MapContext mapContext) {
942
        this.fmap = mapContext;
943
        for (FLayer lyr : this.layers) {
944
            if(lyr instanceof FLayers){
945
                ((FLayers)lyr).setMapContext(mapContext);
946
            }
947
        }
948
    }
949

    
950
    @Override
951
    public void accept(Visitor visitor) throws BaseException {
952
        for (int i = 0; i < this.getLayersCount(); i++) {
953
            FLayer layer = this.getLayer(i);
954
//            try {
955
                if (layer instanceof LayersVisitable) {
956
                    ((LayersVisitable) layer).accept(visitor);
957
                } else {
958
                    visitor.visit(layer);
959
                }
960
//            } catch (VisitCanceledException ex) {
961
//                break;
962
//            }
963
        }
964
    }
965

    
966
    @Override
967
    public void accept(LayersVisitor visitor) throws BaseException {
968
        for (int i = 0; i < this.getLayersCount(); i++) {
969
            FLayer layer = this.getLayer(i);
970
            if (layer instanceof LayersVisitable) {
971
                ((LayersVisitable) layer).accept(visitor);
972
            } else {
973
                visitor.visit(layer);
974
            }
975
        }
976
    }
977

    
978
    @Override
979
    public Object getMetadataID() throws MetadataException {
980
        StringBuilder strb = new StringBuilder();
981
        strb.append("Layers(");
982
        strb.append(this.getName());
983
        strb.append("):{");
984
        Iterator iter = this.layers.iterator();
985
        while (iter.hasNext()) {
986
            strb.append(((FLayer) iter.next()).getMetadataID());
987
            strb.append(",");
988
        }
989
        strb.append("}");
990
        return strb.toString();
991

    
992
    }
993

    
994
    @Override
995
    public Set getMetadataChildren() {
996
        Set ret = new TreeSet();
997
        Iterator iter = this.layers.iterator();
998
        while (iter.hasNext()) {
999
            ret.add(iter.next());
1000
        }
1001
        return ret;
1002
    }
1003

    
1004
    @Override
1005
    public String getMetadataName() throws MetadataException {
1006
        StringBuilder strb = new StringBuilder();
1007
        strb.append("Layer Group '");
1008
        strb.append(this.getName());
1009
        strb.append("': {");
1010
        Iterator iter = this.layers.iterator();
1011
        while (iter.hasNext()) {
1012
            strb.append(((FLayer) iter.next()).getMetadataName());
1013
            strb.append(",");
1014
        }
1015
        strb.append("}");
1016
        return strb.toString();
1017
    }
1018

    
1019
    @Override
1020
    public void beginDraw(Graphics2D g, ViewPort viewPort) {
1021
        if( fmap == null ) {
1022
            return;
1023
        }
1024
        LayerDrawEvent beforeEvent = new LayerDrawEvent(this, g, viewPort, LayerDrawEvent.LAYER_BEFORE_DRAW);
1025
        fmap.fireLayerDrawingEvent(beforeEvent);
1026
    }
1027

    
1028
    @Override
1029
    public void endDraw(Graphics2D g, ViewPort viewPort) {
1030
        if( fmap == null ) {
1031
            return;
1032
        }
1033
        LayerDrawEvent afterEvent = new LayerDrawEvent(this, g, viewPort, LayerDrawEvent.LAYER_AFTER_DRAW);
1034
        fmap.fireLayerDrawingEvent(afterEvent);
1035
    }
1036

    
1037
    public static class RegisterPersistence implements Callable {
1038

    
1039
        @Override
1040
        public Object call() {
1041

    
1042
            PersistenceManager manager = ToolsLocator.getPersistenceManager();
1043
            DynStruct definition = manager.addDefinition(
1044
                    FLayers.class,
1045
                    "FLayers",
1046
                    "FLayers Persistence definition",
1047
                    null,
1048
                    null
1049
            );
1050
            definition.extend(PersistenceManager.PERSISTENCE_NAMESPACE, "FLyrDefault");
1051

    
1052
            definition.addDynFieldObject("mapContext").setClassOfValue(MapContext.class).setMandatory(true);
1053
            definition.addDynFieldList("layers").setClassOfItems(FLayer.class).setMandatory(true);
1054

    
1055
            return Boolean.TRUE;
1056
        }
1057
    }
1058

    
1059
    @Override
1060
    protected void doDispose() throws BaseException {
1061
        if (layers != null) {
1062
            for (FLayer layer : this.layers) {
1063
                dispose(layer);
1064
            }
1065
        }
1066
    }
1067

    
1068
    @Override
1069
    public void move(FLayer layer, LayerCollection group, int where, FLayer adjoiningLayer) throws LayerNotFoundInCollectionException {
1070

    
1071
        callLayerRemoving(LayerCollectionEvent.createLayerRemovingEvent(layer));
1072
        group.addLayer(layer, where, adjoiningLayer);
1073
        removeLayer(layer);
1074
        this.updateDrawVersion();
1075
        callLayerRemoved(LayerCollectionEvent.createLayerRemovedEvent(layer));
1076

    
1077
    }
1078

    
1079
    public void join(FLayer layer, LayerCollection group) {
1080
        try {
1081
            layers.remove(layer);
1082
            group.addLayer(layer, END, null);
1083
            this.updateDrawVersion();
1084
        } catch (LayerNotFoundInCollectionException e) {
1085
            throw new MapContextRuntimeException(e);
1086
        }
1087
    }
1088

    
1089
    @Override
1090
    public void move(FLayer layer, LayerCollection group) {
1091
        try {
1092
            move(layer, group, END, null);
1093
        } catch (LayerNotFoundInCollectionException e) {
1094
            throw new MapContextRuntimeException(e);
1095
        }
1096
    }
1097

    
1098
    @Override
1099
    public void addLayer(FLayer layer, int where, FLayer adjoiningLayer)
1100
            throws LayerNotFoundInCollectionException {
1101

    
1102
        switch (where) {
1103
            case BEGIN:
1104
                addLayer(0, layer);
1105
                break;
1106
            case BEFORE:
1107
                if (adjoiningLayer != null) {
1108
                    if (this.layers.contains(adjoiningLayer)) {
1109
                        for (int i = 0; i < this.getLayersCount(); i++) {
1110
                            if (adjoiningLayer == this.getLayer(i)) {
1111
                                addLayer(i, layer);
1112
                                break;
1113
                            }
1114
                        }
1115
                    } else {
1116
                        throw new LayerNotFoundInCollectionException(adjoiningLayer, this);
1117
                    }
1118
                } else {
1119
                    addLayer(0, layer);
1120
                }
1121
                break;
1122
            case AFTER:
1123
                if (adjoiningLayer != null) {
1124
                    if (this.layers.contains(adjoiningLayer)) {
1125
                        for (int i = 0; i < this.getLayersCount(); i++) {
1126
                            if (adjoiningLayer == this.getLayer(i)) {
1127
                                addLayer(i + 1, layer);
1128
                                break;
1129
                            }
1130
                        }
1131
                    } else {
1132
                        throw new LayerNotFoundInCollectionException(adjoiningLayer, this);
1133
                    }
1134
                } else {
1135
                    this.addLayer(layer);
1136
                }
1137
                break;
1138
            default: // By default add layer an the end of the collection
1139
                this.addLayer(layer);
1140
                break;
1141
        }
1142

    
1143
    }
1144

    
1145
    public FLayer getFirstActiveLayer() {
1146
        List<FLayer> theLayers = this.getLayers(LAYER_ACTIVE);
1147
        if( theLayers.isEmpty() ) {
1148
            return null;
1149
        }
1150
        return theLayers.get(0);
1151
    }
1152

    
1153
    public FLyrVect getFirstActiveVectorLayer() {
1154
        List<FLayer> theLayers = this.getLayers(LAYER_ACTIVE.and(LAYER_FLYRVECT));
1155
        if( theLayers.isEmpty() ) {
1156
            return null;
1157
        }
1158
        return (FLyrVect) theLayers.get(0);
1159
    }
1160
    
1161
    @Override
1162
    public Iterator<FLayer> iterator() {
1163
        return this.layers.iterator();
1164
    }
1165

    
1166
    public Iterator<FLayer> deepiterator() {
1167
        List theLayers = toPlainList(this);
1168
        return theLayers.iterator();
1169
    }
1170
    
1171
    @Override
1172
    public int size() {
1173
        return this.layers.size();
1174
    }
1175
    
1176
    @Override
1177
    public FLayer get(int index) {
1178
        return this.layers.get(index);
1179
    }
1180
    
1181
    @Override
1182
    public boolean isEmpty() {
1183
        return this.layers.isEmpty();
1184
    }
1185

    
1186
    @Override
1187
    public boolean contains(Object o) {
1188
        return this.layers.contains(o);
1189
    }
1190

    
1191
    @Override
1192
    public Object[] toArray() {
1193
        return this.layers.toArray();
1194
    }
1195

    
1196
    @Override
1197
    public Object[] toArray(Object[] ts) {
1198
        return this.layers.toArray(ts);
1199
    }
1200

    
1201
    @Override
1202
    public boolean add(FLayer e) {
1203
        this.addLayer(e);
1204
        return true;
1205
    }
1206

    
1207
    @Override
1208
    public boolean remove(Object o) {
1209
        this.removeLayer((FLayer) o);
1210
        return true;
1211
    }
1212

    
1213
    @Override
1214
    public boolean containsAll(Collection clctn) {
1215
        return this.layers.containsAll(clctn);
1216
    }
1217

    
1218
    @Override
1219
    public void add(int i, FLayer e) {
1220
        this.addLayer(i, (FLayer) e);
1221
    }
1222

    
1223
    @Override
1224
    public FLayer remove(int i) {
1225
        FLayer o = this.getLayer(i);
1226
        this.removeLayer(i);
1227
        return o;
1228
    }
1229

    
1230
    @Override
1231
    public int indexOf(Object o) {
1232
        return this.layers.indexOf(o);
1233
    }
1234

    
1235
    @Override
1236
    public int lastIndexOf(Object o) {
1237
        return this.layers.lastIndexOf(o);
1238
    }
1239

    
1240
    @Override
1241
    public ListIterator listIterator() {
1242
        return this.layers.listIterator();
1243
    }
1244

    
1245
    @Override
1246
    public ListIterator listIterator(int i) {
1247
        return this.layers.listIterator(i);
1248
    }
1249

    
1250
    @Override
1251
    public List subList(int i, int i1) {
1252
        return this.layers.subList(i, i1);
1253
    }
1254
    
1255
    @Override
1256
    public boolean addAll(Collection clctn) {
1257
        Iterator it = clctn.iterator();
1258
        while( it.hasNext() ) {
1259
            this.add((FLayer) it.next());
1260
        }
1261
        return true;
1262
    }
1263

    
1264
    @Override
1265
    public boolean addAll(int i, Collection clctn) {
1266
        Iterator it = clctn.iterator();
1267
        while( it.hasNext() ) {
1268
            this.add(i, (FLayer) it.next());
1269
        }
1270
        return true;
1271
    }
1272

    
1273
    @Override
1274
    public boolean removeAll(Collection clctn) {
1275
        Iterator it = clctn.iterator();
1276
        while( it.hasNext() ) {
1277
            this.remove((FLayer) it.next());
1278
        }
1279
        return true;
1280
    }
1281

    
1282
    @Override
1283
    public boolean retainAll(Collection clctn) {
1284
        Iterator it = this.layers.iterator();
1285
        while( it.hasNext() ) {
1286
            Object o = it.next();
1287
            if( !clctn.contains(o) ) {
1288
                this.remove((FLayer) o);
1289
            }
1290
        }
1291
        return true;
1292
    }
1293

    
1294
    @Override
1295
    public FLayer set(int i, FLayer e) {
1296
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
1297
    }
1298

    
1299
    public FLayers createFLayerGroup(String name) {            
1300
        FLayers group = new FLayers();
1301
        group.setMapContext(this.getMapContext());
1302
        group.setParentLayer(this);
1303
        group.setName(name);
1304
        return group;
1305
    }
1306

    
1307
    @Override
1308
    public FLayers cloneLayer() throws Exception {
1309
        FLayers cloned = new FLayers();
1310
        
1311
        cloned.fmap = this.fmap;
1312
        for (FLayer layer : this.layers) {
1313
            FLayer l = layer.cloneLayer();
1314
            l.setParentLayer(cloned);
1315
            cloned.add(l);
1316
        }
1317
        for (LayerCollectionListener layerCollectionListener : this.layerCollectionListeners) {
1318
            cloned.addLayerCollectionListener(layerCollectionListener);
1319
        }
1320
        for (LayerListener layerListener : this.layerListeners) {
1321
            cloned.addLayerListener(layerListener);
1322
        }
1323
        cloned.setTransparency(this.getTransparency());
1324
        cloned.setMaxScale(this.getMaxScale());
1325
        cloned.setMinScale(this.getMinScale());
1326
        cloned.setCoordTrans(this.getCoordTrans());
1327
        cloned.setFLayerStatus(this.getFLayerStatus());
1328
        cloned.setTemporary(this.isTemporary());
1329
        cloned.setTocStatusImage(this.getTocStatusImage());
1330
        cloned.metadataContainer = this.metadataContainer;
1331
        cloned.setParentLayer(this.getParentLayer());
1332
        cloned.properties = this.properties;
1333
        
1334
        return cloned;
1335
    }
1336
    
1337
    
1338
}