Statistics
| Revision:

svn-gvsig-desktop / trunk / libraries / libFMap / src / com / iver / cit / gvsig / fmap / layers / FLyrVect.java @ 39570

History | View | Annotate | Download (69.4 KB)

1
/* gvSIG. Sistema de Informaci?n Geogr?fica de la Generalitat Valenciana
2
 *
3
 * Copyright (C) 2004 IVER T.I. and Generalitat Valenciana.
4
 *
5
 * This program is free software; you can redistribute it and/or
6
 * modify it under the terms of the GNU General Public License
7
 * as published by the Free Software Foundation; either version 2
8
 * of the License, or (at your option) any later version.
9
 *
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 * GNU General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU General Public License
16
 * along with this program; if not, write to the Free Software
17
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,USA.
18
 *
19
 * For more information, contact:
20
 *
21
 *  Generalitat Valenciana
22
 *   Conselleria d'Infraestructures i Transport
23
 *   Av. Blasco Ib??ez, 50
24
 *   46010 VALENCIA
25
 *   SPAIN
26
 *
27
 *      +34 963862235
28
 *   gvsig@gva.es
29
 *      www.gvsig.gva.es
30
 *
31
 *    or
32
 *
33
 *   IVER T.I. S.A
34
 *   Salamanca 50
35
 *   46005 Valencia
36
 *   Spain
37
 *
38
 *   +34 963163400
39
 *   dac@iver.es
40
 */
41
package com.iver.cit.gvsig.fmap.layers;
42

    
43
import java.awt.Graphics2D;
44
import java.awt.Point;
45
import java.awt.geom.AffineTransform;
46
import java.awt.geom.Point2D;
47
import java.awt.geom.Rectangle2D;
48
import java.awt.image.BufferedImage;
49
import java.io.File;
50
import java.net.URI;
51
import java.util.ArrayList;
52

    
53
import javax.print.attribute.PrintRequestAttributeSet;
54
import javax.print.attribute.standard.PrintQuality;
55

    
56
import org.apache.log4j.Logger;
57
import org.cresques.cts.ICoordTrans;
58
import org.gvsig.tools.file.PathGenerator;
59

    
60
import com.hardcode.gdbms.driver.exceptions.ReadDriverException;
61
import com.hardcode.gdbms.engine.data.DataSourceFactory;
62
import com.hardcode.gdbms.engine.data.NoSuchTableException;
63
import com.hardcode.gdbms.engine.data.driver.DriverException;
64
import com.hardcode.gdbms.engine.instruction.FieldNotFoundException;
65
import com.iver.cit.gvsig.exceptions.expansionfile.ExpansionFileReadException;
66
import com.iver.cit.gvsig.exceptions.layers.LegendLayerException;
67
import com.iver.cit.gvsig.exceptions.layers.ReloadLayerException;
68
import com.iver.cit.gvsig.exceptions.layers.ReprojectLayerException;
69
import com.iver.cit.gvsig.exceptions.layers.StartEditionLayerException;
70
import com.iver.cit.gvsig.exceptions.visitors.StartWriterVisitorException;
71
import com.iver.cit.gvsig.exceptions.visitors.VisitorException;
72
import com.iver.cit.gvsig.fmap.MapContext;
73
import com.iver.cit.gvsig.fmap.MapControl;
74
import com.iver.cit.gvsig.fmap.ViewPort;
75
import com.iver.cit.gvsig.fmap.core.CartographicSupport;
76
import com.iver.cit.gvsig.fmap.core.FPoint2D;
77
import com.iver.cit.gvsig.fmap.core.FShape;
78
import com.iver.cit.gvsig.fmap.core.IFeature;
79
import com.iver.cit.gvsig.fmap.core.IGeometry;
80
import com.iver.cit.gvsig.fmap.core.ILabelable;
81
import com.iver.cit.gvsig.fmap.core.IRow;
82
import com.iver.cit.gvsig.fmap.core.symbols.IMultiLayerSymbol;
83
import com.iver.cit.gvsig.fmap.core.symbols.ISymbol;
84
import com.iver.cit.gvsig.fmap.core.v02.FSymbol;
85
import com.iver.cit.gvsig.fmap.drivers.BoundedShapes;
86
import com.iver.cit.gvsig.fmap.drivers.IFeatureIterator;
87
import com.iver.cit.gvsig.fmap.drivers.IVectorialDatabaseDriver;
88
import com.iver.cit.gvsig.fmap.drivers.VectorialDriver;
89
import com.iver.cit.gvsig.fmap.drivers.WithDefaultLegend;
90
import com.iver.cit.gvsig.fmap.drivers.featureiterators.JoinFeatureIterator;
91
import com.iver.cit.gvsig.fmap.edition.AfterFieldEditEvent;
92
import com.iver.cit.gvsig.fmap.edition.AfterRowEditEvent;
93
import com.iver.cit.gvsig.fmap.edition.AnnotationEditableAdapter;
94
import com.iver.cit.gvsig.fmap.edition.BeforeFieldEditEvent;
95
import com.iver.cit.gvsig.fmap.edition.BeforeRowEditEvent;
96
import com.iver.cit.gvsig.fmap.edition.EditionEvent;
97
import com.iver.cit.gvsig.fmap.edition.IEditionListener;
98
import com.iver.cit.gvsig.fmap.edition.ISpatialWriter;
99
import com.iver.cit.gvsig.fmap.edition.IWriteable;
100
import com.iver.cit.gvsig.fmap.edition.IWriter;
101
import com.iver.cit.gvsig.fmap.edition.VectorialEditableAdapter;
102
import com.iver.cit.gvsig.fmap.edition.VectorialEditableDBAdapter;
103
import com.iver.cit.gvsig.fmap.layers.layerOperations.AlphanumericData;
104
import com.iver.cit.gvsig.fmap.layers.layerOperations.ClassifiableVectorial;
105
import com.iver.cit.gvsig.fmap.layers.layerOperations.InfoByPoint;
106
import com.iver.cit.gvsig.fmap.layers.layerOperations.RandomVectorialData;
107
import com.iver.cit.gvsig.fmap.layers.layerOperations.SingleLayer;
108
import com.iver.cit.gvsig.fmap.layers.layerOperations.VectorialData;
109
import com.iver.cit.gvsig.fmap.layers.layerOperations.VectorialXMLItem;
110
import com.iver.cit.gvsig.fmap.layers.layerOperations.XMLItem;
111
import com.iver.cit.gvsig.fmap.operations.strategies.FeatureVisitor;
112
import com.iver.cit.gvsig.fmap.operations.strategies.Strategy;
113
import com.iver.cit.gvsig.fmap.operations.strategies.StrategyManager;
114
import com.iver.cit.gvsig.fmap.rendering.IClassifiedVectorLegend;
115
import com.iver.cit.gvsig.fmap.rendering.ILegend;
116
import com.iver.cit.gvsig.fmap.rendering.IVectorLegend;
117
import com.iver.cit.gvsig.fmap.rendering.LegendClearEvent;
118
import com.iver.cit.gvsig.fmap.rendering.LegendContentsChangedListener;
119
import com.iver.cit.gvsig.fmap.rendering.LegendFactory;
120
import com.iver.cit.gvsig.fmap.rendering.SingleSymbolLegend;
121
import com.iver.cit.gvsig.fmap.rendering.SymbolLegendEvent;
122
import com.iver.cit.gvsig.fmap.rendering.ZSort;
123
import com.iver.cit.gvsig.fmap.rendering.styling.labeling.AttrInTableLabelingStrategy;
124
import com.iver.cit.gvsig.fmap.rendering.styling.labeling.ILabelingStrategy;
125
import com.iver.cit.gvsig.fmap.rendering.styling.labeling.LabelingFactory;
126
import com.iver.cit.gvsig.fmap.spatialindex.IPersistentSpatialIndex;
127
import com.iver.cit.gvsig.fmap.spatialindex.ISpatialIndex;
128
import com.iver.cit.gvsig.fmap.spatialindex.QuadtreeGt2;
129
import com.iver.cit.gvsig.fmap.spatialindex.QuadtreeJts;
130
import com.iver.cit.gvsig.fmap.spatialindex.SpatialIndexException;
131
import com.iver.utiles.FileUtils;
132
import com.iver.utiles.IPersistence;
133
import com.iver.utiles.NotExistInXMLEntity;
134
import com.iver.utiles.PostProcessSupport;
135
import com.iver.utiles.StringUtilities;
136
import com.iver.utiles.XMLEntity;
137
import com.iver.utiles.swing.threads.Cancellable;
138
import com.iver.utiles.swing.threads.CancellableMonitorable;
139

    
140
/**
141
 * Capa b?sica Vectorial.
142
 *
143
 * @author Fernando Gonz?lez Cort?s
144
 */
145

    
146
public class FLyrVect extends FLyrDefault implements ILabelable,
147
        ClassifiableVectorial, SingleLayer, VectorialData, RandomVectorialData,
148
        AlphanumericData, InfoByPoint, SelectionListener, IEditionListener, LegendContentsChangedListener {
149

    
150
        private static Logger logger = Logger.getLogger(FLyrVect.class.getName());
151

    
152
    /** Leyenda de la capa vectorial */
153
    private IVectorLegend legend;
154
    private int typeShape = -1;
155
    private ReadableVectorial source;
156
    private SelectableDataSource sds;
157
    private SpatialCache spatialCache = new SpatialCache();
158
    private boolean spatialCacheEnabled = false;
159

    
160
    /**
161
     * An implementation of gvSIG spatial index
162
     */
163
    protected ISpatialIndex spatialIndex = null;
164
    private boolean bHasJoin = false;
165
    private XMLEntity orgXMLEntity = null;
166
    private XMLEntity loadSelection = null;
167
    private IVectorLegend loadLegend = null;
168

    
169
    //Lo a?ado. Caracter?sticas de HyperEnlace (LINK)
170
    private FLyrVectLinkProperties linkProperties=new FLyrVectLinkProperties();
171
    //private ArrayList linkProperties=null;
172
    private boolean waitTodraw=false;
173
    private static PathGenerator pathGenerator=PathGenerator.getInstance();
174
    
175
    public boolean isWaitTodraw() {
176
                return waitTodraw;
177
        }
178

    
179
        public void setWaitTodraw(boolean waitTodraw) {
180
                this.waitTodraw = waitTodraw;
181
        }
182
    /**
183
     * Devuelve el VectorialAdapater de la capa.
184
     *
185
     * @return VectorialAdapter.
186
     */
187
    public ReadableVectorial getSource() {
188
        if (!this.isAvailable()) return null;
189
        return source;
190
    }
191

    
192
    /**
193
     * If we use a persistent spatial index associated with this layer, and the
194
     * index is not intrisic to the layer (for example spatial databases) this
195
     * method looks for existent spatial index, and loads it.
196
     *
197
     */
198
    private void loadSpatialIndex() {
199
        //FIXME: Al abrir el indice en fichero...
200
        //?C?mo lo liberamos? un metodo Layer.shutdown()
201

    
202

    
203
        ReadableVectorial source = getSource();
204
        //REVISAR QUE PASA CON LOS DRIVERS DXF, DGN, etc.
205
        //PUES SON VECTORIALFILEADAPTER
206
        if (!(source instanceof VectorialFileAdapter)) {
207
            // we are not interested in db adapters
208
            return;
209
        }
210
        VectorialDriver driver = source.getDriver();
211
        if (!(driver instanceof BoundedShapes)) {
212
            // we dont spatially index layers that are not bounded
213
            return;
214
        }
215
        File file = ((VectorialFileAdapter) source).getFile();
216
        String fileName = file.getAbsolutePath();
217
        File sptFile = new File(fileName + ".qix");
218
        if (!sptFile.exists() || (!(sptFile.length() > 0))) {
219
            // before to exit, look for it in temp path
220
            String tempPath = System.getProperty("java.io.tmpdir");
221
            fileName = tempPath + File.separator + sptFile.getName();
222
            sptFile = new File(fileName);
223
            // it doesnt exists, must to create
224
            if (!sptFile.exists() || (!(sptFile.length() > 0))) {
225
                return;
226
            }// if
227
        }// if
228

    
229
        try {
230
            source.start();
231
            spatialIndex = new QuadtreeGt2(FileUtils.getFileWithoutExtension(sptFile),
232
                    "NM", source.getFullExtent(), source.getShapeCount(), false);
233
            source.setSpatialIndex(spatialIndex);
234
        } catch (SpatialIndexException e) {
235
            spatialIndex = null;
236
            e.printStackTrace();
237
            return;
238
        } catch (ReadDriverException e) {
239
            spatialIndex = null;
240
            e.printStackTrace();
241
            return;
242
        }
243

    
244
    }
245

    
246
    /**
247
     * Checks if it has associated an external spatial index
248
     * (an spatial index file).
249
     *
250
     * It looks for it in main file path, or in temp system path.
251
     * If main file is rivers.shp, it looks for a file called
252
     * rivers.shp.qix.
253

254
     * @return
255
     */
256
    public boolean isExternallySpatiallyIndexed() {
257
        /*
258
         * FIXME (AZABALA): Independizar del tipo de fichero de ?ndice
259
          * con el que se trabaje (ahora mismo considera la extension .qix,
260
         * pero esto depender? del tipo de ?ndice)
261
         * */
262
        ReadableVectorial source = getSource();
263
        if (!(source instanceof VectorialFileAdapter)) {
264
            // we are not interested in db adapters.
265
            // think in non spatial dbs, like HSQLDB
266
            return false;
267
        }
268
        File file = ((VectorialFileAdapter) source).getFile();
269
        String fileName = file.getAbsolutePath();
270
        File sptFile = new File(fileName + ".qix");
271
        if (!sptFile.exists() || (!(sptFile.length() > 0))) {
272
            // before to exit, look for it in temp path
273
            // it doesnt exists, must to create
274
            String tempPath = System.getProperty("java.io.tmpdir");
275
            fileName = tempPath + File.separator + sptFile.getName();
276
            sptFile = new File(fileName);
277
            if (!sptFile.exists() || (!(sptFile.length() > 0))) {
278
                return false;
279
            }// if
280
        }// if
281
        return true;
282
    }
283

    
284
    /**
285
     * Inserta el VectorialAdapter a la capa.
286
     *
287
     * @param va
288
     *            VectorialAdapter.
289
     */
290
    public void setSource(ReadableVectorial rv) {
291
        source = rv;
292
        // azabala: we check if this layer could have a file spatial index
293
        // and load it if it exists
294
        loadSpatialIndex();
295
    }
296

    
297
    public Rectangle2D getFullExtent() throws ReadDriverException, ExpansionFileReadException {
298
            Rectangle2D rAux;
299
            source.start();
300
            rAux = (Rectangle2D)source.getFullExtent().clone();
301
            source.stop();
302

    
303
            // Si existe reproyecci?n, reproyectar el extent
304
            if (!(this.getProjection()!=null &&
305
                            this.getMapContext().getProjection()!=null &&
306
                            this.getProjection().getAbrev().equals(this.getMapContext().getProjection().getAbrev()))){
307
                    ICoordTrans ct = getCoordTrans();
308
                    try{
309
                            if (ct != null) {
310
                                    Point2D pt1 = new Point2D.Double(rAux.getMinX(), rAux.getMinY());
311
                                    Point2D pt2 = new Point2D.Double(rAux.getMaxX(), rAux.getMaxY());
312
                                    pt1 = ct.convert(pt1, null);
313
                                    pt2 = ct.convert(pt2, null);
314
                                    rAux = new Rectangle2D.Double();
315
                                    rAux.setFrameFromDiagonal(pt1, pt2);
316
                            }
317
                    }catch (IllegalStateException e) {
318
                            this.setAvailable(false);
319
                            this.addError(new ReprojectLayerException(getName(), e));
320
                    }
321
            }
322
            //Esto es para cuando se crea una capa nueva con el fullExtent de ancho y alto 0.
323
            if (rAux.getWidth()==0 && rAux.getHeight()==0) {
324
                rAux=new Rectangle2D.Double(0,0,100,100);
325
            }
326

    
327
            return rAux;
328
    }
329

    
330
    /**
331
     * Draws using IFeatureIterator. This method will replace the old draw(...) one.
332
     * @autor jaume dominguez faus - jaume.dominguez@iver.es
333
     * @param image
334
     * @param g
335
     * @param viewPort
336
     * @param cancel
337
     * @param scale
338
     * @throws ReadDriverException
339
     */
340
    private void _draw(BufferedImage image, Graphics2D g, ViewPort viewPort,
341
                    Cancellable cancel, double scale) throws ReadDriverException {
342
            boolean bDrawShapes = true;
343
            if (legend instanceof SingleSymbolLegend) {
344
                    bDrawShapes = legend.getDefaultSymbol().isShapeVisible();
345
            }
346
            Point2D offset = viewPort.getOffset();
347
            double dpi = MapContext.getScreenDPI();
348

    
349

    
350

    
351
            if (bDrawShapes) {
352
                    boolean cacheFeatures = isSpatialCacheEnabled();
353
                    SpatialCache cache = null;
354
                    if (cacheFeatures) {
355
                            getSpatialCache().clearAll();
356
                            cache = getSpatialCache();
357
                    }
358

    
359
                    try {
360
                            ArrayList<String> fieldList = new ArrayList<String>();
361

    
362
                            // fields from legend
363
                            String[] aux = null;
364

    
365
                            if (legend instanceof IClassifiedVectorLegend) {
366
                                    aux = ((IClassifiedVectorLegend) legend).getClassifyingFieldNames();
367
                                    if (aux!=null) {
368
                                            for (int i = 0; i < aux.length; i++) {
369
                                                    // check fields exists
370
                                                    if (sds.getFieldIndexByName(aux[i]) == -1) {
371
                                                            logger.warn("Error en leyenda de " + getName() +
372
                                                                            ". El campo " + aux[i] + " no est?.");
373
                                                            legend = LegendFactory.createSingleSymbolLegend(getShapeType());
374
                                                            break;
375
                                                    }
376
                                                    fieldList.add(aux[i]);
377
                                            }
378
                                    }
379
                            }
380
                            // Get the iterator over the visible features
381
                            IFeatureIterator it = null;
382
                            if (isJoined()) {
383
                                    it = new JoinFeatureIterator(this, viewPort,
384
                                                    fieldList.toArray(new String[fieldList.size()]));
385
                            }
386
                            else {
387
                                    ReadableVectorial rv=getSource();
388
//                                    rv.start();
389
                                    it = rv.getFeatureIterator(
390
                                            viewPort.getAdjustedExtent(),
391
                                            fieldList.toArray(new String[fieldList.size()]),
392
                                            viewPort.getProjection(),
393
                                            true);
394
//                                    rv.stop();
395
                            }
396

    
397
                                ZSort zSort = ((IVectorLegend) getLegend()).getZSort();
398

    
399
                            boolean bSymbolLevelError = false;
400

    
401
                            // if layer has map levels it will use a ZSort
402
                            boolean useZSort = zSort != null && zSort.isUsingZSort();
403

    
404
                            // -- visual FX stuff
405
                            long time = System.currentTimeMillis();
406
                            BufferedImage virtualBim;
407
                            Graphics2D virtualGraphics;
408

    
409
                            // render temporary map each screenRefreshRate milliseconds;
410
                            int screenRefreshDelay = (int) ((1D/MapControl.getDrawFrameRate())*3*1000);
411
                            BufferedImage[] imageLevels = null;
412
                            Graphics2D[] graphics = null;
413
                            if (useZSort) {
414
                                    imageLevels = new BufferedImage[zSort.getLevelCount()];
415
                                    graphics = new Graphics2D[imageLevels.length];
416
                                    for (int i = 0; !cancel.isCanceled() && i < imageLevels.length; i++) {
417
                                            imageLevels[i] = new BufferedImage(image.getWidth(), image.getHeight(), image.getType());
418
                                            graphics[i] = imageLevels[i].createGraphics();
419
                                            graphics[i].setTransform(g.getTransform());
420
                                            graphics[i].setRenderingHints(g.getRenderingHints());
421
                                    }
422
                            }
423
                            // -- end visual FX stuff
424

    
425
                            boolean isInMemory = false;
426
                            if (getSource().getDriverAttributes() != null){
427
                                    isInMemory = getSource().getDriverAttributes().isLoadedInMemory();
428
                            }
429
                            SelectionSupport selectionSupport=getSelectionSupport();
430
                            // Iteration over each feature
431
                            while ( !cancel.isCanceled() && it.hasNext()) {
432
                                    IFeature feat = it.next();
433
                                    IGeometry geom = null;
434

    
435
                                    if (isInMemory){
436
                                            geom = feat.getGeometry().cloneGeometry();
437
                                    }else{
438
                                            geom = feat.getGeometry();
439
                                    }
440

    
441
                                    if (cacheFeatures) {
442
                                            if (cache.getMaxFeatures() >= cache.size()) {
443
                                                    // already reprojected
444
                                                    cache.insert(geom.getBounds2D(), geom);
445
                                            }
446
                                    }
447

    
448
                                    // retrieve the symbol associated to such feature
449
                                    ISymbol sym = legend.getSymbolByFeature(feat);
450

    
451
                                    if (sym == null) continue;
452

    
453
                                    //C?digo para poder acceder a los ?ndices para ver si est? seleccionado un Feature
454
                                    ReadableVectorial rv=getSource();
455
                                    int selectionIndex=-1;
456
                                    if (rv instanceof ISpatialDB){
457
                                            selectionIndex = ((ISpatialDB)rv).getRowIndexByFID(feat);
458
                                    }else{
459
                                            selectionIndex = Integer.parseInt(feat.getID());
460
                                    }
461
                                    if (selectionIndex!=-1) {
462
                                            if (selectionSupport.isSelected(selectionIndex)) {
463
                                                    sym = sym.getSymbolForSelection();
464
                                            }
465
                                    }
466

    
467
                                    // Check if this symbol is sized with CartographicSupport
468
                                    CartographicSupport csSym = null;
469
                                    int symbolType = sym.getSymbolType();
470
                                    boolean bDrawCartographicSupport = false;
471

    
472
                                    if (   symbolType == FShape.POINT
473
                                                    || symbolType == FShape.LINE
474
                                                    || sym instanceof CartographicSupport) {
475

    
476
                                            // patch
477
                                            if (!sym.getClass().equals(FSymbol.class)) {
478
                                                    csSym = (CartographicSupport) sym;
479
                                                    bDrawCartographicSupport = (csSym.getUnit() != -1);
480
                                            }
481
                                    }
482

    
483
                                    int x = -1;
484
                                    int y = -1;
485
                                    int[] xyCoords = new int[2];
486

    
487
                                    // Check if size is a pixel
488
                                    boolean onePoint = bDrawCartographicSupport ?
489
                                                    isOnePoint(g.getTransform(), viewPort, MapContext.getScreenDPI(), csSym, geom, xyCoords) :
490
                                                            isOnePoint(g.getTransform(), viewPort, geom, xyCoords);
491

    
492
                                                    // Avoid out of bounds exceptions
493
                                                    if (onePoint) {
494
                                                            x = xyCoords[0];
495
                                                            y = xyCoords[1];
496
                                                            if (x<0 || y<0 || x>= viewPort.getImageWidth() || y>=viewPort.getImageHeight()) continue;
497
                                                    }
498

    
499
                                                    if (useZSort) {
500
                                                            // Check if this symbol is a multilayer
501
                                                                int[] symLevels = zSort.getLevels(sym);
502
                                                            if (sym instanceof IMultiLayerSymbol) {
503
                                                                    // if so, treat each of its layers as a single symbol
504
                                                                    // in its corresponding map level
505
                                                                    IMultiLayerSymbol mlSym = (IMultiLayerSymbol) sym;
506
                                                                    for (int i = 0; !cancel.isCanceled() && i < mlSym.getLayerCount(); i++) {
507
                                                                            ISymbol mySym = mlSym.getLayer(i);
508
                                                                        int symbolLevel = 0;
509
                                                                        if (symLevels != null) {
510
                                                                                symbolLevel = symLevels[i];
511
                                                                        } else {
512
                                                                                    /* an error occured when managing symbol levels.
513
                                                                                     * some of the legend changed events regarding the
514
                                                                                     * symbols did not finish satisfactory and the legend
515
                                                                                     * is now inconsistent. For this drawing, it will finish
516
                                                                                     * as it was at the bottom (level 0) but, when done, the
517
                                                                                     * ZSort will be reset to avoid app crashes. This is
518
                                                                                     * a bug that has to be fixed.
519
                                                                                     */
520
                                                                                    bSymbolLevelError = true;
521
                                                                            }
522

    
523
                                                                            if (onePoint) {
524
                                                                                    if (x<0 || y<0 || x>= imageLevels[symbolLevel].getWidth() || y>=imageLevels[symbolLevel].getHeight()) continue;
525
                                                                                    imageLevels[symbolLevel].setRGB(x, y, mySym.getOnePointRgb());
526
                                                                            } else {
527
                                                                                    if (!bDrawCartographicSupport) {
528
                                                                                            geom.drawInts(graphics[symbolLevel], viewPort, mySym, cancel);
529
                                                                                    } else {
530
                                                                                            geom.drawInts(graphics[symbolLevel], viewPort, dpi, (CartographicSupport) mySym, cancel);
531
                                                                                    }
532
                                                                            }
533
                                                                    }
534
                                                            } else {
535
                                                                    // else, just draw the symbol in its level
536
                                                                    int symbolLevel = 0;
537
                                                                    if (symLevels != null) {
538

    
539
                                                                            symbolLevel=symLevels[0];
540
                                                                    } else {
541
                                                                            /* If symLevels == null
542
                                                                             * an error occured when managing symbol levels.
543
                                                                             * some of the legend changed events regarding the
544
                                                                             * symbols did not finish satisfactory and the legend
545
                                                                             * is now inconsistent. For this drawing, it will finish
546
                                                                             * as it was at the bottom (level 0). This is
547
                                                                             * a bug that has to be fixed.
548
                                                                             */
549
//                                                                            bSymbolLevelError = true;
550
                                                                    }
551

    
552
                                                                    if (!bDrawCartographicSupport) {
553
                                                                            geom.drawInts(graphics[symbolLevel], viewPort, sym, cancel);
554
                                                                    } else {
555
                                                                            geom.drawInts(graphics[symbolLevel], viewPort, dpi, (CartographicSupport) csSym, cancel);
556
                                                                    }
557
                                                            }
558

    
559
                                                            // -- visual FX stuff
560
                                                            // Cuando el offset!=0 se est? dibujando sobre el Layout y por tanto no tiene que ejecutar el siguiente c?digo.
561
                                                            if (offset.getX()==0 && offset.getY()==0)
562
                                                                    if ((System.currentTimeMillis() - time) > screenRefreshDelay) {
563
                                                                            virtualBim = new BufferedImage(image.getWidth(),image.getHeight(),BufferedImage.TYPE_INT_ARGB);
564
                                                                            virtualGraphics = virtualBim.createGraphics();
565
                                                                            virtualGraphics.drawImage(image,0,0, null);
566
                                                                            for (int i = 0; !cancel.isCanceled() && i < imageLevels.length; i++) {
567
                                                                                    virtualGraphics.drawImage(imageLevels[i],0,0, null);
568
                                                                            }
569
                                                                            g.clearRect(0, 0, image.getWidth(), image.getHeight());
570
                                                                            g.drawImage(virtualBim, 0, 0, null);
571
                                                                            time = System.currentTimeMillis();
572
                                                                    }
573
                                                            // -- end visual FX stuff
574

    
575
                                                    } else {
576
                                                            // no ZSort, so there is only a map level, symbols are
577
                                                            // just drawn.
578
                                                            if (onePoint) {
579
                                                                    if (x<0 || y<0 || x>= image.getWidth() || y>=image.getHeight()) continue;
580
                                                                    image.setRGB(x, y, sym.getOnePointRgb());
581
                                                            } else {
582
                                                                    if (!bDrawCartographicSupport) {
583
                                                                            geom.drawInts(g, viewPort, sym, cancel);
584
                                                                    } else {
585
                                                                            geom.drawInts(g, viewPort, dpi, csSym, cancel);
586
                                                                    }
587
                                                            }
588
                                                    }
589
                            }
590

    
591
                            if (useZSort) {
592
                                    g.drawImage(image, (int)offset.getX(), (int)offset.getY(), null);
593
                                    g.translate(offset.getX(), offset.getY());
594
                                    for (int i = 0; !cancel.isCanceled() && i < imageLevels.length; i++) {
595
                                            g.drawImage(imageLevels[i],0,0, null);
596
                                            imageLevels[i] = null;
597
                                            graphics[i] = null;
598
                                    }
599
                                    g.translate(-offset.getX(), -offset.getY());
600
                                    imageLevels = null;
601
                                    graphics = null;
602
                            }
603
                            it.closeIterator();
604

    
605
                            if (bSymbolLevelError) {
606
                                    ((IVectorLegend) getLegend()).setZSort(null);
607
                            }
608

    
609
                    } catch (ReadDriverException e) {
610
                            this.setVisible(false);
611
                            this.setActive(false);
612
                            throw e;
613
                    }
614

    
615

    
616
            }
617
    }
618

    
619
           public void draw(BufferedImage image, Graphics2D g, ViewPort viewPort,
620
            Cancellable cancel, double scale) throws ReadDriverException {
621
                   if (isWaitTodraw()) {
622
                        return;
623
                }
624
                   if (getStrategy() != null) {
625
                           getStrategy().draw(image, g, viewPort, cancel);
626
                   }
627
                   else {
628
                           _draw(image, g, viewPort, cancel, scale);
629
                   }
630
    }
631

    
632
    public void _print(Graphics2D g, ViewPort viewPort, Cancellable cancel,
633
                    double scale, PrintRequestAttributeSet properties) throws ReadDriverException {
634
            boolean bDrawShapes = true;
635
            if (legend instanceof SingleSymbolLegend) {
636
                    bDrawShapes = legend.getDefaultSymbol().isShapeVisible();
637
            }
638

    
639

    
640
            if (bDrawShapes) {
641

    
642
                    try {
643
                            double dpi = 72;
644

    
645
                            PrintQuality resolution=(PrintQuality)properties.get(PrintQuality.class);
646
                            if (resolution.equals(PrintQuality.NORMAL)){
647
                                    dpi = 300;
648
                            } else if (resolution.equals(PrintQuality.HIGH)){
649
                                    dpi = 600;
650
                            } else if (resolution.equals(PrintQuality.DRAFT)){
651
                                    dpi = 72;
652
                            }
653
                            ArrayList<String> fieldList = new ArrayList<String>();
654
                            String[] aux;
655

    
656
                            // fields from legend
657
                            if (legend instanceof IClassifiedVectorLegend) {
658
                                    aux = ((IClassifiedVectorLegend) legend).getClassifyingFieldNames();
659
                                    for (int i = 0; i < aux.length; i++) {
660
                                            fieldList.add(aux[i]);
661
                                    }
662
                            }
663
                            //
664
                            //                            // fields from labeling
665
                            //                            if (isLabeled()) {
666
                            //                                    aux = getLabelingStrategy().getUsedFields();
667
                            //                                    for (int i = 0; i < aux.length; i++) {
668
                            //                                            fieldList.add(aux[i]);
669
                            //                                    }
670
                            //                            }
671

    
672
                            ZSort zSort = ((IVectorLegend) getLegend()).getZSort();
673

    
674
                            // if layer has map levels it will use a ZSort
675
                            boolean useZSort = zSort != null && zSort.isUsingZSort();
676

    
677

    
678
                            int mapLevelCount = (useZSort) ? zSort.getLevelCount() : 1;
679
                            for (int mapPass = 0; mapPass < mapLevelCount; mapPass++) {
680
                                    // Get the iterator over the visible features
681
                                    //                                    IFeatureIterator it = getSource().getFeatureIterator(
682
                                    //                                                    viewPort.getAdjustedExtent(),
683
                                    //                                                    fieldList.toArray(new String[fieldList.size()]),
684
                                    //                                                    viewPort.getProjection(),
685
                                    //                                                    true);
686
                                    IFeatureIterator it = null;
687
                                    if (isJoined()) {
688
                                            it = new JoinFeatureIterator(this, viewPort,
689
                                                            fieldList.toArray(new String[fieldList.size()]));
690
                                    }
691
                                    else {
692
                                            it = getSource().getFeatureIterator(
693
                                                            viewPort.getAdjustedExtent(),
694
                                                            fieldList.toArray(new String[fieldList.size()]),
695
                                                            viewPort.getProjection(),
696
                                                            true);
697
                                    }
698

    
699
                                    // Iteration over each feature
700
                                    while ( !cancel.isCanceled() && it.hasNext()) {
701
                                            IFeature feat = it.next();
702
                                            IGeometry geom = feat.getGeometry();
703

    
704
                                            // retreive the symbol associated to such feature
705
                                            ISymbol sym = legend.getSymbolByFeature(feat);
706
                                            if (sym == null) {
707
                                                    continue;
708
                                            }
709
                                            if (useZSort) {
710
                                                    int[] symLevels = zSort.getLevels(sym);
711
                                                    if(symLevels != null){
712
                                                            // Check if this symbol is a multilayer
713
                                                            if (sym instanceof IMultiLayerSymbol) {
714
                                                                    // if so, get the layer corresponding to the current
715
                                                                    // level. If none, continue to next iteration
716
                                                                    IMultiLayerSymbol mlSym = (IMultiLayerSymbol) sym;
717
                                                                    for (int i = 0; i < mlSym.getLayerCount(); i++) {
718
                                                                            ISymbol mySym = mlSym.getLayer(i);
719
                                                                            if (symLevels[i] == mapPass) {
720
                                                                                    sym = mySym;
721
                                                                                    break;
722
                                                                            }
723
                                                                            System.out.println("avoided layer "+i+"of symbol '"+mlSym.getDescription()+"' (pass "+mapPass+")");
724
                                                                    }
725
                                                            } else {
726
                                                                    // else, just draw the symbol in its level
727
                                                                    if (symLevels[0] != mapPass) {
728
                                                                            System.out.println("avoided single layer symbol '"+sym.getDescription()+"' (pass "+mapPass+")");
729
                                                                            continue;
730
                                                                    }
731
                                                            }
732
                                                    }
733
                                            }
734

    
735
                                            // Check if this symbol is sized with CartographicSupport
736
                                            CartographicSupport csSym = null;
737
                                            int symbolType = sym.getSymbolType();
738

    
739
                                            if (   symbolType == FShape.POINT
740
                                                            || symbolType == FShape.LINE
741
                                                            || sym instanceof CartographicSupport) {
742

    
743
                                                    csSym = (CartographicSupport) sym;
744
                                            }
745

    
746
                                            //System.err.println("passada "+mapPass+" pinte s?mboll "+sym.getDescription());
747

    
748
                                            if (csSym == null) {
749
                                                    geom.drawInts(g, viewPort, sym, null);
750
                                            } else {
751
                                                    geom.drawInts(g, viewPort, dpi, (CartographicSupport) csSym, cancel);
752
                                            }
753

    
754
                                    }
755
                                    it.closeIterator();
756
                            }
757
                    } catch (ReadDriverException e) {
758
                            this.setVisible(false);
759
                            this.setActive(false);
760
                            throw e;
761
                    }
762
            }
763
    }
764

    
765

    
766
    public void print(Graphics2D g, ViewPort viewPort, Cancellable cancel,
767
            double scale, PrintRequestAttributeSet properties) throws ReadDriverException {
768
            if (isVisible() && isWithinScale(scale)) {
769
                    _print(g, viewPort, cancel, scale, properties);
770
            }
771
    }
772

    
773
    public void deleteSpatialIndex() {
774
        //must we delete possible spatial indexes files?
775
        spatialIndex = null;
776
    }
777

    
778
   /**
779
    * <p>
780
    * Creates an spatial index associated to this layer.
781
    * The spatial index will used
782
    * the native projection of the layer, so if the layer is reprojected, it will
783
    * be ignored.
784
    * </p>
785
    * @param cancelMonitor instance of CancellableMonitorable that allows
786
    * to monitor progress of spatial index creation, and cancel the process
787
    */
788
    public void createSpatialIndex(CancellableMonitorable cancelMonitor){
789
         // FJP: ESTO HABR? QUE CAMBIARLO. PARA LAS CAPAS SECUENCIALES, TENDREMOS
790
        // QUE ACCEDER CON UN WHILE NEXT. (O mejorar lo de los FeatureVisitor
791
        // para que acepten recorrer sin geometria, solo con rectangulos.
792

    
793
        //If this vectorial layer is based in a spatial database, the spatial
794
        //index is already implicit. We only will index file drivers
795
        ReadableVectorial va = getSource();
796
        //We must think in non spatial databases, like HSQLDB
797
        if(!(va instanceof VectorialFileAdapter)){
798
            return;
799
        }
800
        if (!(va.getDriver() instanceof BoundedShapes)) {
801
            return;
802
        }
803
        File file = ((VectorialFileAdapter) va).getFile();
804
        String fileName = file.getAbsolutePath();
805
        ISpatialIndex localCopy = null;
806
        try {
807
            va.start();
808
            localCopy = new QuadtreeGt2(fileName, "NM", va.getFullExtent(),
809
                    va.getShapeCount(), true);
810

    
811
        } catch (SpatialIndexException e1) {
812
            // Probably we dont have writing permissions
813
            String directoryName = System.getProperty("java.io.tmpdir");
814
            File newFile = new File(directoryName +
815
                    File.separator +
816
                    file.getName());
817
            String newFileName = newFile.getName();
818
            try {
819
                localCopy = new QuadtreeGt2(newFileName, "NM", va.getFullExtent(),
820
                        va.getShapeCount(), true);
821
            } catch (SpatialIndexException e) {
822
                // if we cant build a file based spatial index, we'll build
823
                // a pure memory spatial index
824
                localCopy = new QuadtreeJts();
825
            } catch (ReadDriverException e) {
826
                localCopy = new QuadtreeJts();
827
            }
828

    
829
        } catch(Exception e){
830
            e.printStackTrace();
831
        }//try
832
        BoundedShapes shapeBounds = (BoundedShapes) va.getDriver();
833
        try {
834
            for (int i=0; i < va.getShapeCount(); i++)
835
            {
836
                if(cancelMonitor != null){
837
                    if(cancelMonitor.isCanceled())
838
                        return;
839
                    cancelMonitor.reportStep();
840
                }
841
                Rectangle2D r = shapeBounds.getShapeBounds(i);
842
                if(r != null)
843
                    localCopy.insert(r, i);
844
            } // for
845
            va.stop();
846
            if(localCopy instanceof IPersistentSpatialIndex)
847
                ((IPersistentSpatialIndex) localCopy).flush();
848
            spatialIndex = localCopy;
849
            //vectorial adapter needs a reference to the spatial index, to solve
850
            //request for feature iteration based in spatial queries
851
            source.setSpatialIndex(spatialIndex);
852
        } catch (ReadDriverException e) {
853
            e.printStackTrace();
854
        }
855
    }
856

    
857
    public void createSpatialIndex() {
858
        createSpatialIndex(null);
859
    }
860

    
861
    public void process(FeatureVisitor visitor, FBitSet subset)
862
            throws ReadDriverException, ExpansionFileReadException, VisitorException {
863
        Strategy s = StrategyManager.getStrategy(this);
864
        s.process(visitor, subset);
865
    }
866

    
867
    public void process(FeatureVisitor visitor) throws ReadDriverException, VisitorException {
868
        Strategy s = StrategyManager.getStrategy(this);
869
        s.process(visitor);
870
    }
871

    
872
    public void process(FeatureVisitor visitor, Rectangle2D rect)
873
            throws ReadDriverException, ExpansionFileReadException, VisitorException {
874
        Strategy s = StrategyManager.getStrategy(this);
875
        s.process(visitor, rect);
876
    }
877

    
878
    public FBitSet queryByRect(Rectangle2D rect) throws ReadDriverException, VisitorException {
879
        Strategy s = StrategyManager.getStrategy(this);
880

    
881
        return s.queryByRect(rect);
882
    }
883

    
884
    public FBitSet queryByPoint(Point2D p, double tolerance)
885
            throws ReadDriverException, VisitorException {
886
        Strategy s = StrategyManager.getStrategy(this);
887
        return s.queryByPoint(p, tolerance);
888
    }
889

    
890
    public FBitSet queryByShape(IGeometry g, int relationship)
891
            throws ReadDriverException, VisitorException {
892
        Strategy s = StrategyManager.getStrategy(this);
893
        return s.queryByShape(g, relationship);
894
    }
895

    
896
    public XMLItem[] getInfo(Point p, double tolerance, Cancellable cancel) throws ReadDriverException, VisitorException {
897
        Point2D pReal = this.getMapContext().getViewPort().toMapPoint(p);
898
        FBitSet bs = queryByPoint(pReal, tolerance);
899
        VectorialXMLItem[] item = new VectorialXMLItem[1];
900
        item[0] = new VectorialXMLItem(bs, this);
901

    
902
        return item;
903
    }
904

    
905
    public void setLegend(IVectorLegend r) throws LegendLayerException {
906
            if (this.legend == r){
907
                    return;
908
            }
909
                if (this.legend != null && this.legend.equals(r)){
910
                        return;
911
                }
912
        IVectorLegend oldLegend = legend;
913

    
914
        /*
915
         * Parche para discriminar las leyendas clasificadas cuyos campos de
916
         * clasificaci?n no est?n en la fuente de la capa.
917
         *
918
         * Esto puede ocurrir porque en versiones anteriores se admit?an
919
         * leyendas clasificadas en capas que se han unido a una tabla
920
         * por campos que pertenec?an a la tabla y no s?lo a la capa.
921
         *
922
         */
923
//                if(r instanceof IClassifiedVectorLegend){
924
//                        IClassifiedVectorLegend classifiedLegend = (IClassifiedVectorLegend)r;
925
//                        String[] fieldNames = classifiedLegend.getClassifyingFieldNames();
926
//
927
//                        for (int i = 0; i < fieldNames.length; i++) {
928
//                                try {
929
//                                        if(this.getRecordset().getFieldIndexByName(fieldNames[i]) == -1){
930
////                                        if(this.getSource().getRecordset().getFieldIndexByName(fieldNames[i]) == -1){
931
//                                                logger.warn("Some fields of the classification of the legend doesn't belong with the source of the layer.");
932
//                                                if (this.legend == null){
933
//                                                        r = LegendFactory.createSingleSymbolLegend(this.getShapeType());
934
//                                                } else {
935
//                                                        return;
936
//                                                }
937
//                                        }
938
//                                } catch (ReadDriverException e1) {
939
//                                        throw new LegendLayerException(getName(),e1);
940
//                                }
941
//                        }
942
//                }
943
                /* Fin del parche */
944

    
945
                legend = r;
946
        try {
947
            legend.setDataSource(getRecordset());
948
        } catch (FieldNotFoundException e1) {
949
            throw new LegendLayerException(getName(),e1);
950
        } catch (ReadDriverException e1) {
951
            throw new LegendLayerException(getName(),e1);
952
        } finally{
953
                this.updateDrawVersion();
954
        }
955
        if (oldLegend != null){
956
                oldLegend.removeLegendListener(this);
957
        }
958
        if (legend != null){
959
                legend.addLegendListener(this);
960
        }
961
        LegendChangedEvent e = LegendChangedEvent.createLegendChangedEvent(
962
                oldLegend, legend);
963
        e.setLayer(this);
964
        callLegendChanged(e);
965
    }
966

    
967
    /**
968
     * Devuelve la Leyenda de la capa.
969
     *
970
     * @return Leyenda.
971
     */
972
    public ILegend getLegend() {
973
        return legend;
974
    }
975

    
976
    /**
977
     * Devuelve el tipo de shape que contiene la capa.
978
     *
979
     * @return tipo de shape.
980
     *
981
     * @throws DriverException
982
     */
983
    public int getShapeType() throws ReadDriverException {
984
        if (typeShape == -1) {
985
            getSource().start();
986
            typeShape = getSource().getShapeType();
987
            getSource().stop();
988
        }
989

    
990
        return typeShape;
991
    }
992

    
993
    public XMLEntity getXMLEntity() throws XMLException {
994
        if (!this.isAvailable() && this.orgXMLEntity != null) {
995
            return this.orgXMLEntity;
996
        }
997
        XMLEntity xml = super.getXMLEntity();
998
        if (getLegend()!=null)
999
            xml.addChild(getLegend().getXMLEntity());
1000
        try {
1001
            if (getRecordset()!=null)
1002
                xml.addChild(getRecordset().getSelectionSupport().getXMLEntity());
1003
        } catch (ReadDriverException e1) {
1004
            e1.printStackTrace();
1005
            throw new XMLException(e1);
1006
        }
1007
        // Repongo el mismo ReadableVectorial m?s abajo para cuando se guarda el proyecto.
1008
        ReadableVectorial rv=getSource();
1009
        xml.putProperty("type", "vectorial");
1010
        if (source instanceof VectorialEditableAdapter) {
1011
            setSource(((VectorialEditableAdapter) source).getOriginalAdapter());
1012
        }
1013
        if (source instanceof VectorialFileAdapter) {
1014
            xml.putProperty("type", "vectorial");
1015
            xml.putProperty("absolutePath",((VectorialFileAdapter) source)
1016
                    .getFile().getAbsolutePath());
1017
            xml.putProperty("file", pathGenerator.getPath(((VectorialFileAdapter) source)
1018
                    .getFile().getAbsolutePath()));
1019
            try {
1020
                xml.putProperty("recordset-name", source.getRecordset()
1021
                        .getName());
1022
            } catch (ReadDriverException e) {
1023
                throw new XMLException(e);
1024
            } catch (RuntimeException e) {
1025
                e.printStackTrace();
1026
            }
1027
        } else if (source instanceof VectorialDBAdapter) {
1028
            xml.putProperty("type", "vectorial");
1029

    
1030
            IVectorialDatabaseDriver dbDriver = (IVectorialDatabaseDriver) source
1031
                    .getDriver();
1032

    
1033
            // Guardamos el nombre del driver para poder recuperarlo
1034
            // con el DriverManager de Fernando.
1035
            xml.putProperty("db", dbDriver.getName());
1036
            try {
1037
                xml.putProperty("recordset-name", source.getRecordset()
1038
                        .getName());
1039
            } catch (ReadDriverException e) {
1040
                throw new XMLException(e);
1041
            } catch (RuntimeException e) {
1042
                e.printStackTrace();
1043
            }
1044
            xml.addChild(dbDriver.getXMLEntity()); // Tercer child. Antes hemos
1045
                                                    // metido la leyenda y el
1046
                                                    // selection support
1047
        } else if (source instanceof VectorialAdapter) {
1048
            // Se supone que hemos hecho algo gen?rico.
1049
            xml.putProperty("type", "vectorial");
1050

    
1051
            VectorialDriver driver = source.getDriver();
1052

    
1053
            // Guardamos el nombre del driver para poder recuperarlo
1054
            // con el DriverManager de Fernando.
1055
            xml.putProperty("other", driver.getName());
1056
            // try {
1057
            try {
1058
                xml.putProperty("recordset-name", source.getRecordset()
1059
                        .getName());
1060
            } catch (ReadDriverException e) {
1061
                throw new XMLException(e);
1062
            } catch (RuntimeException e) {
1063
                e.printStackTrace();
1064
            }
1065
            if (driver instanceof IPersistence) {
1066
                // xml.putProperty("className", driver.getClass().getName());
1067
                    IPersistence persist = (IPersistence) driver;
1068
                xml.addChild(persist.getXMLEntity()); // Tercer child. Antes
1069
                                                        // hemos metido la
1070
                                                        // leyenda y el
1071
                                                        // selection support
1072
            }
1073
        }
1074
        if (rv!=null)
1075
            setSource(rv);
1076
        xml.putProperty("driverName", source.getDriver().getName());
1077
        if (bHasJoin)
1078
            xml.putProperty("hasJoin", "true");
1079

    
1080
        // properties from ILabelable
1081
        xml.putProperty("isLabeled", isLabeled);
1082
        if (strategy != null) {
1083
            XMLEntity strategyXML = strategy.getXMLEntity();
1084
            strategyXML.putProperty("Strategy", strategy.getClassName());
1085
            xml.addChild(strategy.getXMLEntity());
1086
        }
1087
        xml.addChild(getLinkProperties().getXMLEntity());
1088
        return xml;
1089
    }
1090

    
1091
    /**
1092
     * @see com.iver.cit.gvsig.fmap.layers.FLyrDefault#setXMLEntity(com.iver.utiles.XMLEntity)
1093
     */
1094
    public void setXMLEntity03(XMLEntity xml) throws XMLException {
1095

    
1096
        super.setXMLEntity(xml);
1097
        legend = LegendFactory.createFromXML03(xml.getChild(0));
1098

    
1099
        try {
1100
            setLegend(legend);
1101
        } catch (LegendLayerException e) {
1102
            throw new XMLException(e);
1103
        }
1104

    
1105
        try {
1106
            getRecordset().getSelectionSupport()
1107
                    .setXMLEntity03(xml.getChild(1));
1108
        } catch (ReadDriverException e) {
1109
            e.printStackTrace();
1110
        }
1111
    }
1112

    
1113
    /*
1114
     * @see com.iver.cit.gvsig.fmap.layers.FLyrDefault#setXMLEntity(com.iver.utiles.XMLEntity)
1115
     */
1116
    public void setXMLEntity(XMLEntity xml) throws XMLException {
1117
        try {
1118
                    super.setXMLEntity(xml);
1119
                    XMLEntity legendXML = xml.getChild(0);
1120
                    IVectorLegend leg = LegendFactory.createFromXML(legendXML);
1121

    
1122
                    /*
1123
                     * Parche para detectar cuando, por algun problema de persistencia
1124
                     * respecto a versiones anteriores, la leyenda que se ha cargado
1125
                     * no se corresponde con el tipo de shape de la capa.
1126
                     */
1127
                    int legShapeType = leg.getShapeType();
1128
                    if (legShapeType != 0 && legShapeType != this.getShapeType()){
1129
                            leg = LegendFactory.createSingleSymbolLegend(this.getShapeType());
1130
                                logger.warn("Legend shape type and layer shape type does not match.");
1131
                    }
1132
                    /* Fin del parche */
1133

    
1134
                    try {
1135
                            getRecordset().getSelectionSupport().setXMLEntity(xml.getChild(1));
1136
                            // JMVIVO: Esto sirve para algo????
1137
                            /*
1138
                             *  Jaume: si, para restaurar el selectable datasource cuando se
1139
                             *  clona la capa, cuando se carga de un proyecto. Si no esta ya
1140
                             *  no se puede ni hacer consultas sql, ni hacer selecciones,
1141
                             *  ni usar la mayor parte de las herramientas.
1142
                             *
1143
                             *  Lo vuelvo a poner.
1144
                             */
1145

    
1146
                            String recordsetName = xml.getStringProperty("recordset-name");
1147

    
1148
                            LayerFactory.getDataSourceFactory().changeDataSourceName(
1149
                                            getSource().getRecordset().getName(), recordsetName);
1150
                            SelectableDataSource sds = new SelectableDataSource(LayerFactory
1151
                                            .getDataSourceFactory().createRandomDataSource(
1152
                                                            recordsetName, DataSourceFactory.AUTOMATIC_OPENING));
1153

    
1154
                    } catch (NoSuchTableException e1) {
1155
                            this.setAvailable(false);
1156
                            throw new XMLException(e1);
1157
                    } catch (ReadDriverException e1) {
1158
                            this.setAvailable(false);
1159
                            throw new XMLException(e1);
1160
                    }
1161
                    // Si tiene una uni?n, lo marcamos para que no se cree la leyenda hasta
1162
                    // el final
1163
                    // de la lectura del proyecto
1164
                    if (xml.contains("hasJoin")) {
1165
                            setIsJoined(true);
1166
                            PostProcessSupport.addToPostProcess(this, "setLegend", leg, 1);
1167
                    } else {
1168
                            try {
1169
                                    setLegend(leg);
1170
                            } catch (LegendLayerException e) {
1171
                                    throw new XMLException(e);
1172
                            }
1173
                    }
1174

    
1175
                    //Por compatibilidad con proyectos anteriores a la 1.0
1176
                    boolean containsIsLabeled = xml.contains("isLabeled");
1177
                    if (containsIsLabeled){
1178
                            isLabeled = xml.getBooleanProperty("isLabeled");
1179
                    }
1180
                    // set properties for ILabelable
1181
                    XMLEntity labelingXML = xml.firstChild("labelingStrategy", "labelingStrategy");
1182
                    if (labelingXML!= null) {
1183
                            if(!containsIsLabeled){
1184
                                    isLabeled = true;
1185
                            }
1186
                            try {
1187
                                    ILabelingStrategy labeling = LabelingFactory.createStrategyFromXML(labelingXML, this);
1188
                                    if (isJoined()) {
1189
                                            PostProcessSupport.addToPostProcess(this, "setLabelingStrategy", labeling, 1);
1190
                                    }
1191
                                    else
1192
                                            this.setLabelingStrategy(labeling);
1193

    
1194
                            } catch (NotExistInXMLEntity neXMLEX) {
1195
                                    // no strategy was set, just continue;
1196
                                    logger.warn("Reached what should be unreachable code");
1197
                            }
1198
                    } else if (legendXML.contains("labelFieldName")|| legendXML.contains("labelfield")) {
1199
                            /* (jaume) begin patch;
1200
                         * for backward compatibility purposes. Since gvSIG v1.1 labeling is
1201
                         * no longer managed by the Legend but by the ILabelingStrategy. The
1202
                         * following allows restoring older projects' labelings.
1203
                         */
1204
                            String labelTextField =        null;
1205
                            if (legendXML.contains("labelFieldName")){
1206
                                    labelTextField = legendXML.getStringProperty("labelFieldName");
1207
                                if (labelTextField != null) {
1208
                                        AttrInTableLabelingStrategy labeling = new AttrInTableLabelingStrategy();
1209
                                        labeling.setLayer(this);
1210
                                                int unit = 1;
1211
                                                boolean useFixedSize = false;
1212
                                            String labelFieldHeight = legendXML.getStringProperty("labelHeightFieldName");
1213
                                            labeling.setTextField(labelTextField);
1214
                                            if(labelFieldHeight!=null){
1215
                                                    labeling.setHeightField(labelFieldHeight);
1216
                                            } else {
1217
                                                    double size = -1;
1218
                                                    for(int i=0; i<legendXML.getChildrenCount();i++){
1219
                                                            XMLEntity xmlChild = legendXML.getChild(i);
1220
                                                            if(xmlChild.contains("m_FontSize")){
1221
                                                                    double childFontSize =  xmlChild.getDoubleProperty("m_FontSize");
1222
                                                                    if(size<0){
1223
                                                                            size = childFontSize;
1224
                                                                            useFixedSize = true;
1225
                                                                    } else {
1226
                                                                            useFixedSize = useFixedSize && (size==childFontSize);
1227
                                                                    }
1228
                                                                    if(xmlChild.contains("m_bUseFontSize")){
1229
                                                                            if(xmlChild.getBooleanProperty("m_bUseFontSize")){
1230
                                                                                    unit = -1;
1231
                                                                            } else {
1232
                                                                                    unit = 1;
1233
                                                                            }
1234
                                                                    }
1235
                                                            }
1236
                                                    }
1237
                                                    labeling.setFixedSize(size/1.4);//Factor de correcci?n que se aplicaba antes en el etiquetado
1238
                                            }
1239
                                                labeling.setUsesFixedSize(useFixedSize);
1240
                                                labeling.setUnit(unit);
1241
                                        labeling.setRotationField(legendXML.getStringProperty("labelRotationFieldName"));
1242
                                        if (legendXML.contains("haloWidth")) {
1243
                                                float haloWidth = legendXML.getFloatProperty("haloWidth");
1244
                                                labeling.setHaloColor(StringUtilities.string2Color(legendXML.getStringProperty("haloColor")));
1245
                                                labeling.setHaloWidth(haloWidth);
1246
                                                labeling.setWithHalo(true);
1247
                                        }
1248
                                        if (isJoined()) {
1249
                                                PostProcessSupport.addToPostProcess(this, "setLabelingStrategy", labeling, 1);
1250
                                        }
1251
                                        else
1252
                                                this.setLabelingStrategy(labeling);
1253
                                        this.setIsLabeled(true);
1254
                                }
1255
                            }else{
1256
                                    labelTextField = legendXML.getStringProperty("labelfield");
1257
                                    if (labelTextField != null) {
1258
                                            AttrInTableLabelingStrategy labeling = new AttrInTableLabelingStrategy();
1259
                                            labeling.setLayer(this);
1260
                                                int unit = 1;
1261
                                                boolean useFixedSize = false;
1262
                                            String labelFieldHeight = legendXML.getStringProperty("labelFieldHeight");
1263
                                            labeling.setTextField(labelTextField);
1264
                                            if(labelFieldHeight!=null){
1265
                                                    labeling.setHeightField(labelFieldHeight);
1266
                                            } else {
1267
                                                    double size = -1;
1268
                                                    for(int i=0; i<legendXML.getChildrenCount();i++){
1269
                                                            XMLEntity xmlChild = legendXML.getChild(i);
1270
                                                            if(xmlChild.contains("m_FontSize")){
1271
                                                                    double childFontSize =  xmlChild.getDoubleProperty("m_FontSize");
1272
                                                                    if(size<0){
1273
                                                                            size = childFontSize;
1274
                                                                            useFixedSize = true;
1275
                                                                    } else {
1276
                                                                            useFixedSize = useFixedSize && (size==childFontSize);
1277
                                                                    }
1278
                                                                    if(xmlChild.contains("m_bUseFontSize")){
1279
                                                                            if(xmlChild.getBooleanProperty("m_bUseFontSize")){
1280
                                                                                    unit = -1;
1281
                                                                            } else {
1282
                                                                                    unit = 1;
1283
                                                                            }
1284
                                                                    }
1285
                                                            }
1286
                                                    }
1287
                                                    labeling.setFixedSize(size/1.4);//Factor de correcci?n que se aplicaba antes en el etiquetado
1288
                                            }
1289
                                                labeling.setUsesFixedSize(useFixedSize);
1290
                                                labeling.setUnit(unit);
1291
                                            labeling.setRotationField(legendXML.getStringProperty("labelFieldRotation"));
1292
                                        if (isJoined()) {
1293
                                                PostProcessSupport.addToPostProcess(this, "setLabelingStrategy", labeling, 1);
1294
                                        }
1295
                                        else
1296
                                                this.setLabelingStrategy(labeling);
1297
                                            this.setIsLabeled(true);
1298
                                    }
1299
                            }
1300

    
1301
                }else if(!containsIsLabeled){
1302
                                    isLabeled = false;
1303
                    }
1304

    
1305
                    // compatibility with hyperlink from 1.9 alpha version... do we really need to be compatible with alpha versions??
1306
                    XMLEntity xmlLinkProperties=xml.firstChild("typeChild", "linkProperties");
1307
                    if (xmlLinkProperties != null){
1308
                            try {
1309
                                    String fieldName=xmlLinkProperties.getStringProperty("fieldName");
1310
                                    xmlLinkProperties.remove("fieldName");
1311
                                    String extName = xmlLinkProperties.getStringProperty("extName");
1312
                                    xmlLinkProperties.remove("extName");
1313
                                    int typeLink = xmlLinkProperties.getIntProperty("typeLink");
1314
                                    xmlLinkProperties.remove("typeLink");
1315
                                    if (fieldName!=null) {
1316
                                            setProperty("legacy.hyperlink.selectedField", fieldName);
1317
                                            setProperty("legacy.hyperlink.type", new Integer(typeLink));
1318
                                            if (extName!=null) {
1319
                                                    setProperty("legacy.hyperlink.extension", extName);
1320
                                            }
1321
                                    }
1322
                            }
1323
                            catch (NotExistInXMLEntity ex) {
1324
                                    logger.warn("Error getting old hyperlink configuration", ex);
1325
                            }
1326
                    }
1327

    
1328
            } catch (XMLException e) {
1329
                    this.setAvailable(false);
1330
                    this.orgXMLEntity = xml;
1331
            } catch (Exception e) {
1332
                    e.printStackTrace();
1333
                    this.setAvailable(false);
1334
                    this.orgXMLEntity = xml;
1335

    
1336
            }
1337

    
1338

    
1339
    }
1340

    
1341
    public void setXMLEntityNew(XMLEntity xml) throws XMLException {
1342
        try {
1343
            super.setXMLEntity(xml);
1344

    
1345
            XMLEntity legendXML = xml.getChild(0);
1346
            IVectorLegend leg = LegendFactory.createFromXML(legendXML);
1347
            /* (jaume) begin patch;
1348
             * for backward compatibility purposes. Since gvSIG v1.1 labeling is
1349
             * no longer managed by the Legend but by the ILabelingStrategy. The
1350
             * following allows restoring older projects' labelings.
1351
             */
1352
            if (legendXML.contains("labelFieldHeight")) {
1353
                AttrInTableLabelingStrategy labeling = new AttrInTableLabelingStrategy();
1354
                labeling.setLayer(this);
1355
                labeling.setTextField(legendXML.getStringProperty("labelFieldHeight"));
1356
                labeling.setRotationField(legendXML.getStringProperty("labelFieldRotation"));
1357
                this.setLabelingStrategy(labeling);
1358
                this.setIsLabeled(true);
1359
              }
1360
            /* end patch */
1361
            try {
1362
                getRecordset().getSelectionSupport().setXMLEntity(xml.getChild(1));
1363

    
1364
                this.setLoadSelection(xml.getChild(1));
1365
            } catch (ReadDriverException e1) {
1366
                this.setAvailable(false);
1367
                throw new XMLException(e1);
1368
            }
1369
            // Si tiene una uni?n, lo marcamos para que no se cree la leyenda hasta
1370
            // el final
1371
            // de la lectura del proyecto
1372
            if (xml.contains("hasJoin")) {
1373
                setIsJoined(true);
1374
                PostProcessSupport.addToPostProcess(this, "setLegend", leg, 1);
1375
            } else {
1376
                this.setLoadLegend(leg);
1377
            }
1378

    
1379
        } catch (XMLException e) {
1380
            this.setAvailable(false);
1381
            this.orgXMLEntity = xml;
1382
        } catch (Exception e) {
1383
            this.setAvailable(false);
1384
            this.orgXMLEntity = xml;
1385
        }
1386

    
1387

    
1388
    }
1389

    
1390

    
1391
    /**
1392
     * Sobreimplementaci?n del m?todo toString para que las bases de datos
1393
     * identifiquen la capa.
1394
     *
1395
     * @return DOCUMENT ME!
1396
     */
1397
    public String toString() {
1398
        /*
1399
         * Se usa internamente para que la parte de datos identifique de forma
1400
         * un?voca las tablas
1401
         */
1402
        String ret = super.toString();
1403

    
1404
        return "layer" + ret.substring(ret.indexOf('@') + 1);
1405
    }
1406

    
1407
    public boolean isJoined() {
1408
        return bHasJoin;
1409
    }
1410

    
1411
    /**
1412
     * Returns if a layer is spatially indexed
1413
     *
1414
     * @return if this layer has the ability to proces spatial queries without
1415
     *         secuential scans.
1416
     */
1417
    public boolean isSpatiallyIndexed() {
1418
        ReadableVectorial source = getSource();
1419
        if (source instanceof ISpatialDB)
1420
            return true;
1421

    
1422
//FIXME azabala
1423
/*
1424
 * Esto es muy dudoso, y puede cambiar.
1425
 * Estoy diciendo que las que no son fichero o no son
1426
 * BoundedShapes estan indexadas. Esto es mentira, pero
1427
 * as? quien pregunte no querr? generar el indice.
1428
 * Esta por ver si interesa generar el indice para capas
1429
 * HSQLDB, WFS, etc.
1430
 */
1431
        if(!(source instanceof VectorialFileAdapter)){
1432
            return true;
1433
        }
1434
        if (!(source.getDriver() instanceof BoundedShapes)) {
1435
            return true;
1436
        }
1437

    
1438
        if (getISpatialIndex() != null)
1439
            return true;
1440
        return false;
1441
    }
1442

    
1443
    public void setIsJoined(boolean hasJoin) {
1444
        bHasJoin = hasJoin;
1445
    }
1446

    
1447
    /**
1448
     * @return Returns the spatialIndex.
1449
     */
1450
    public ISpatialIndex getISpatialIndex() {
1451
        return spatialIndex;
1452
    }
1453
    /**
1454
     * Sets the spatial index. This could be useful if, for some
1455
     * reasons, you want to work with a distinct spatial index
1456
     * (for example, a spatial index which could makes nearest
1457
     * neighbour querys)
1458
     * @param spatialIndex
1459
     */
1460
    public void setISpatialIndex(ISpatialIndex spatialIndex){
1461
        this.spatialIndex = spatialIndex;
1462
    }
1463

    
1464
    public SelectableDataSource getRecordset() throws ReadDriverException {
1465
        if (!this.isAvailable()) return null;
1466
        if (sds == null) {
1467

    
1468
                SelectableDataSource ds = source.getRecordset();
1469

    
1470
                if (ds == null) {
1471
                    return null;
1472
                }
1473

    
1474
                sds = ds;
1475
                getSelectionSupport().addSelectionListener(this);
1476

    
1477
        }
1478
        return sds;
1479
    }
1480

    
1481
    public void setEditing(boolean b) throws StartEditionLayerException {
1482
        super.setEditing(b);
1483
        try {
1484
            if (b) {
1485
                VectorialEditableAdapter vea = null;
1486
                // TODO: Qu? pasa si hay m?s tipos de adapters?
1487
                // FJP: Se podr?a pasar como argumento el
1488
                // VectorialEditableAdapter
1489
                // que se quiera usar para evitar meter c?digo aqu? de este
1490
                // estilo.
1491
                if (getSource() instanceof VectorialDBAdapter) {
1492
                    vea = new VectorialEditableDBAdapter();
1493
                } else if (this instanceof FLyrAnnotation) {
1494
                    vea = new AnnotationEditableAdapter(
1495
                            (FLyrAnnotation) this);
1496
                } else {
1497
                    vea = new VectorialEditableAdapter();
1498
                }
1499
                vea.addEditionListener(this);
1500
                vea.setOriginalVectorialAdapter(getSource());
1501
//                                azo: implementations of readablevectorial need
1502
                //references of projection and spatial index
1503
                vea.setProjection(getProjection());
1504
                vea.setSpatialIndex(spatialIndex);
1505

    
1506

    
1507
                // /vea.setSpatialIndex(getSpatialIndex());
1508
                // /vea.setFullExtent(getFullExtent());
1509
                vea.setCoordTrans(getCoordTrans());
1510
                vea.startEdition(EditionEvent.GRAPHIC);
1511
                setSource(vea);
1512
                getRecordset().setSelectionSupport(
1513
                        vea.getOriginalAdapter().getRecordset()
1514
                                .getSelectionSupport());
1515

    
1516
            } else {
1517
                VectorialEditableAdapter vea = (VectorialEditableAdapter) getSource();
1518
                vea.removeEditionListener(this);
1519
                setSource(vea.getOriginalAdapter());
1520
            }
1521
            // Si tenemos una leyenda, hay que pegarle el cambiazo a su
1522
            // recordset
1523
            setRecordset(getSource().getRecordset());
1524
            if (getLegend() instanceof IVectorLegend) {
1525
                IVectorLegend ley = (IVectorLegend) getLegend();
1526
                ley.setDataSource(getSource().getRecordset());
1527
                // Esto lo pongo para evitar que al dibujar sobre un
1528
                // dxf, dwg, o dgn no veamos nada. Es debido al checkbox
1529
                // de la leyenda de textos "dibujar solo textos".
1530
//jaume
1531
//                                if (!(getSource().getDriver() instanceof IndexedShpDriver)){
1532
//                                        FSymbol symbol=new FSymbol(getShapeType());
1533
//                                        symbol.setFontSizeInPixels(false);
1534
//                                        symbol.setFont(new Font("SansSerif", Font.PLAIN, 9));
1535
//                                        Color color=symbol.getColor();
1536
//                                        int alpha=symbol.getColor().getAlpha();
1537
//                                        if (alpha>250) {
1538
//                                                symbol.setColor(new Color(color.getRed(),color.getGreen(),color.getBlue(),100));
1539
//                                        }
1540
//                                        ley.setDefaultSymbol(symbol);
1541
//                                }
1542
//jaume//
1543
                ley.useDefaultSymbol(true);
1544
            }
1545
        } catch (ReadDriverException e) {
1546
            throw new StartEditionLayerException(getName(),e);
1547
        } catch (FieldNotFoundException e) {
1548
            throw new StartEditionLayerException(getName(),e);
1549
        } catch (StartWriterVisitorException e) {
1550
            throw new StartEditionLayerException(getName(),e);
1551
        }
1552

    
1553
        setSpatialCacheEnabled(b);
1554
        callEditionChanged(LayerEvent
1555
                .createEditionChangedEvent(this, "edition"));
1556

    
1557
    }
1558

    
1559
    /**
1560
     * Para cuando haces una uni?n, sustituyes el recorset por el nuevo. De esta
1561
     * forma, podr?s poner leyendas basadas en el nuevo recordset
1562
     *
1563
     * @param newSds
1564
     */
1565
    public void setRecordset(SelectableDataSource newSds) {
1566
            // TODO: Deberiamos hacer comprobaciones del cambio
1567
        sds = newSds;
1568
                getSelectionSupport().addSelectionListener(this);
1569
                this.updateDrawVersion();
1570
    }
1571

    
1572
    public void clearSpatialCache()
1573
    {
1574
        spatialCache.clearAll();
1575
    }
1576

    
1577
    public boolean isSpatialCacheEnabled() {
1578
        return spatialCacheEnabled;
1579
    }
1580

    
1581
    public void setSpatialCacheEnabled(boolean spatialCacheEnabled) {
1582
        this.spatialCacheEnabled = spatialCacheEnabled;
1583
    }
1584

    
1585
    public SpatialCache getSpatialCache() {
1586
        return spatialCache;
1587
    }
1588

    
1589
    /**
1590
     * Siempre es un numero mayor de 1000
1591
     * @param maxFeatures
1592
     */
1593
    public void setMaxFeaturesInEditionCache(int maxFeatures) {
1594
        if (maxFeatures > spatialCache.maxFeatures)
1595
            spatialCache.setMaxFeatures(maxFeatures);
1596

    
1597
    }
1598

    
1599
    /**
1600
     * This method returns a boolean that is used by the FPopMenu
1601
     * to make visible the properties menu or not. It is visible by
1602
     * default, and if a later don't have to show this menu only
1603
     * has to override this method.
1604
     * @return
1605
     * If the properties menu is visible (or not)
1606
     */
1607
    public boolean isPropertiesMenuVisible(){
1608
        return true;
1609
    }
1610

    
1611
    public void reload() throws ReloadLayerException {
1612
            if(this.isEditing()){
1613
            throw new ReloadLayerException(getName());
1614
            }
1615
        this.setAvailable(true);
1616
        super.reload();
1617
        this.updateDrawVersion();
1618
        try {
1619
            this.source.getDriver().reload();
1620
            if (this.getLegend() == null) {
1621
                if (this.getRecordset().getDriver() instanceof WithDefaultLegend) {
1622
                    WithDefaultLegend aux = (WithDefaultLegend) this.getRecordset().getDriver();
1623
                    this.setLegend((IVectorLegend) aux.getDefaultLegend());
1624
                    this.setLabelingStrategy(aux.getDefaultLabelingStrategy());
1625
                } else {
1626
                    this.setLegend(LegendFactory.createSingleSymbolLegend(
1627
                            this.getShapeType()));
1628
                }
1629
            }
1630

    
1631
        } catch (LegendLayerException e) {
1632
            this.setAvailable(false);
1633
            throw new ReloadLayerException(getName(),e);
1634
        } catch (ReadDriverException e) {
1635
            this.setAvailable(false);
1636
            throw new ReloadLayerException(getName(),e);
1637
        }
1638

    
1639
    }
1640

    
1641
    protected void setLoadSelection(XMLEntity xml) {
1642
        this.loadSelection = xml;
1643
    }
1644

    
1645
    protected void setLoadLegend(IVectorLegend legend) {
1646
        this.loadLegend = legend;
1647
    }
1648

    
1649
    protected void putLoadSelection() throws XMLException {
1650
        if (this.loadSelection == null) return;
1651
        try {
1652
            this.getRecordset().getSelectionSupport().setXMLEntity(this.loadSelection);
1653
        } catch (ReadDriverException e) {
1654
            throw new XMLException(e);
1655
        }
1656
        this.loadSelection = null;
1657

    
1658
    }
1659
    protected void putLoadLegend() throws LegendLayerException {
1660
        if (this.loadLegend == null) return;
1661
        this.setLegend(this.loadLegend);
1662
        this.loadLegend = null;
1663
    }
1664

    
1665
    protected void cleanLoadOptions() {
1666
        this.loadLegend = null;
1667
        this.loadSelection = null;
1668
    }
1669

    
1670
    public boolean isWritable() {
1671
        VectorialDriver drv = getSource().getDriver();
1672
        if (!drv.isWritable())
1673
            return false;
1674
        if (drv instanceof IWriteable)
1675
        {
1676
            IWriter writer = ((IWriteable)drv).getWriter();
1677
            if (writer != null)
1678
            {
1679
                if (writer instanceof ISpatialWriter)
1680
                    return true;
1681
            }
1682
        }
1683
        return false;
1684

    
1685
    }
1686

    
1687
    public FLayer cloneLayer() throws Exception {
1688
        FLyrVect clonedLayer = new FLyrVect();
1689
        clonedLayer.setSource(getSource());
1690
        if (isJoined()) {
1691
                        clonedLayer.setIsJoined(true);
1692
                        clonedLayer.setRecordset(getRecordset());
1693
                }
1694
        clonedLayer.setVisible(isVisible());
1695
        clonedLayer.setISpatialIndex(getISpatialIndex());
1696
        clonedLayer.setName(getName());
1697
        clonedLayer.setCoordTrans(getCoordTrans());
1698

    
1699
        clonedLayer.setLegend((IVectorLegend)getLegend().cloneLegend());
1700

    
1701
        clonedLayer.setIsLabeled(isLabeled());
1702
        ILabelingStrategy labelingStrategy=getLabelingStrategy();
1703
        if (labelingStrategy!=null)
1704
                clonedLayer.setLabelingStrategy(labelingStrategy);
1705

    
1706
        return clonedLayer;
1707
    }
1708

    
1709
    public SelectionSupport getSelectionSupport() {
1710
                try {
1711
                        return getRecordset().getSelectionSupport();
1712
                } catch (ReadDriverException e) {
1713
                        e.printStackTrace();
1714
                }
1715
                return null;
1716
        }
1717

    
1718
    protected boolean isOnePoint(AffineTransform graphicsTransform, ViewPort viewPort, double dpi, CartographicSupport csSym, IGeometry geom, int[] xyCoords) {
1719
            return isOnePoint(graphicsTransform, viewPort, geom, xyCoords) && csSym.getCartographicSize(viewPort, dpi, (FShape)geom.getInternalShape()) <= 1;
1720
    }
1721

    
1722
    protected boolean isOnePoint(AffineTransform graphicsTransform, ViewPort viewPort, IGeometry geom, int[] xyCoords) {
1723
            boolean onePoint = false;
1724
            int type=geom.getGeometryType() % FShape.Z;
1725
            if (type!=FShape.POINT && type!=FShape.MULTIPOINT && type!=FShape.NULL) {
1726

    
1727
                        Rectangle2D geomBounds = geom.getBounds2D();
1728

    
1729
                //        ICoordTrans ct = getCoordTrans();
1730

    
1731
                        // Se supone que la geometria ya esta
1732
                        // repoyectada y no hay que hacer
1733
                        // ninguna transformacion
1734
//                        if (ct!=null) {
1735
////                                geomBounds = ct.getInverted().convert(geomBounds);
1736
//                                geomBounds = ct.convert(geomBounds);
1737
//                        }
1738

    
1739
                        double dist1Pixel = viewPort.getDist1pixel();
1740

    
1741
                        onePoint = (geomBounds.getWidth()  <= dist1Pixel
1742
                                         && geomBounds.getHeight() <= dist1Pixel);
1743

    
1744
                        if (onePoint) {
1745
                                // avoid out of range exceptions
1746
                                FPoint2D p = new FPoint2D(geomBounds.getMinX(), geomBounds.getMinY());
1747
                                p.transform(viewPort.getAffineTransform());
1748
                                p.transform(graphicsTransform);
1749
                                xyCoords[0] = (int) p.getX();
1750
                                xyCoords[1] = (int) p.getY();
1751

    
1752
                        }
1753

    
1754
                }
1755
            return onePoint;
1756
    }
1757
    /*
1758
     * jaume. Stuff from ILabeled.
1759
     */
1760
    private boolean isLabeled;
1761
    private ILabelingStrategy strategy;
1762

    
1763
    public boolean isLabeled() {
1764
        return isLabeled;
1765
    }
1766

    
1767
    public void setIsLabeled(boolean isLabeled) {
1768
        this.isLabeled = isLabeled;
1769
    }
1770

    
1771
    public ILabelingStrategy getLabelingStrategy() {
1772
        return strategy;
1773
    }
1774

    
1775
    public void setLabelingStrategy(ILabelingStrategy strategy) {
1776
        this.strategy = strategy;
1777
        try {
1778
                        strategy.setLayer(this);
1779
                } catch (ReadDriverException e) {
1780
                        e.printStackTrace();
1781
                }
1782
    }
1783

    
1784
    public void drawLabels(BufferedImage image, Graphics2D g, ViewPort viewPort,
1785
                    Cancellable cancel, double scale, double dpi) throws ReadDriverException {
1786
        if (strategy!=null && isWithinScale(scale)) {
1787
                strategy.draw(image, g, viewPort, cancel, dpi);
1788
        }
1789
    }
1790
    public void printLabels(Graphics2D g, ViewPort viewPort,
1791
                    Cancellable cancel, double scale, PrintRequestAttributeSet properties) throws ReadDriverException {
1792
        if (strategy!=null) {
1793
                strategy.print(g, viewPort, cancel, properties);
1794
        }
1795
    }
1796

    
1797

    
1798
    //M?todos para el uso de HyperLinks en capas FLyerVect
1799

    
1800
    /**
1801
     * Return true, because a Vectorial Layer supports HyperLink
1802
     */
1803
    public boolean allowLinks()
1804
    {
1805
            return true;
1806
    }
1807

    
1808
    /**
1809
         * Returns an instance of AbstractLinkProperties that contains the information
1810
         * of the HyperLink
1811
         * @return Abstra
1812
         */
1813
    public AbstractLinkProperties getLinkProperties()
1814
    {
1815
            return linkProperties;
1816
    }
1817

    
1818
    /**
1819
         * Provides an array with URIs. Returns one URI by geometry that includes the point
1820
         * in its own geometry limits with a allowed tolerance.
1821
         * @param layer, the layer
1822
         * @param point, the point to check that is contained or not in the geometries in the layer
1823
         * @param tolerance, the tolerance allowed. Allowed margin of error to detect if the  point
1824
         *                 is contained in some geometries of the layer
1825
         * @return
1826
         */
1827
    public URI[] getLink(Point2D point, double tolerance)
1828
    {
1829
            //return linkProperties.getLink(this)
1830
            return linkProperties.getLink(this,point,tolerance);
1831
    }
1832

    
1833
        public void selectionChanged(SelectionEvent e) {
1834
                this.updateDrawVersion();
1835
        }
1836

    
1837
        public void afterFieldEditEvent(AfterFieldEditEvent e) {
1838
                this.updateDrawVersion();
1839
        }
1840

    
1841
        public void afterRowEditEvent(IRow feat, AfterRowEditEvent e) {
1842
                this.updateDrawVersion();
1843

    
1844
        }
1845

    
1846
        public void beforeFieldEditEvent(BeforeFieldEditEvent e) {
1847

    
1848
        }
1849

    
1850
        public void beforeRowEditEvent(IRow feat, BeforeRowEditEvent e) {
1851

    
1852
        }
1853

    
1854
        public void processEvent(EditionEvent e) {
1855
                if (e.getChangeType()== e.ROW_EDITION){
1856
                        this.updateDrawVersion();
1857
                }
1858

    
1859
        }
1860

    
1861
        public void legendCleared(LegendClearEvent event) {
1862
                this.updateDrawVersion();
1863
        LegendChangedEvent e = LegendChangedEvent.createLegendChangedEvent(
1864
                legend, legend);
1865
        this.callLegendChanged(e);
1866
        }
1867

    
1868
        public boolean symbolChanged(SymbolLegendEvent e) {
1869
                this.updateDrawVersion();
1870
        LegendChangedEvent event = LegendChangedEvent.createLegendChangedEvent(
1871
                legend, legend);
1872
        this.callLegendChanged(event);
1873
        return true;
1874
        }
1875
        public String getTypeStringVectorLayer() throws ReadDriverException {
1876
                String typeString="";
1877
                int typeShape=((FLyrVect)this).getShapeType();
1878
                if (FShape.MULTI==typeShape){
1879
                        ReadableVectorial rv=((FLyrVect)this).getSource();
1880
                        int i=0;
1881
                        boolean isCorrect=false;
1882
                        while(rv.getShapeCount()>i && !isCorrect){
1883
                                IGeometry geom=rv.getShape(i);
1884
                                if (geom==null){
1885
                                        i++;
1886
                                        continue;
1887
                                }
1888
                                isCorrect=true;
1889
                                if ((geom.getGeometryType() & FShape.Z) == FShape.Z){
1890
                                        typeString="Geometries3D";
1891
                                }else{
1892
                                        typeString="Geometries2D";
1893
                                 }
1894
                         }
1895
                }else{
1896
                        ReadableVectorial rv=((FLyrVect)this).getSource();
1897
                        int i=0;
1898
                        boolean isCorrect=false;
1899
                        while(rv.getShapeCount()>i && !isCorrect){
1900
                                IGeometry geom=rv.getShape(i);
1901
                                if (geom==null){
1902
                                        i++;
1903
                                        continue;
1904
                                }
1905
                                isCorrect=true;
1906
                                int type=geom.getGeometryType();
1907
                                if (FShape.POINT == type){
1908
                                        typeString="Point2D";
1909
                                } else if (FShape.LINE == type){
1910
                                        typeString="Line2D";
1911
                                } else if (FShape.POLYGON == type){
1912
                                        typeString="Polygon2D";
1913
                                } else if (FShape.MULTIPOINT == type){
1914
                                        typeString="MultiPint2D";
1915
                                } else if ((FShape.POINT | FShape.Z)  == type ){
1916
                                        typeString="Point3D";
1917
                                } else if ((FShape.LINE | FShape.Z)  == type ){
1918
                                        typeString="Line3D";
1919
                                } else if ((FShape.POLYGON | FShape.Z)  == type ){
1920
                                        typeString="Polygon3D";
1921
                                } else if ((FShape.MULTIPOINT | FShape.Z)  == type ){
1922
                                        typeString="MultiPoint3D";
1923
                                } else if ((FShape.POINT | FShape.M)  == type ){
1924
                                        typeString="PointM";
1925
                                } else if ((FShape.LINE | FShape.M)  == type ){
1926
                                        typeString="LineM";
1927
                                } else if ((FShape.POLYGON | FShape.M)  == type ){
1928
                                        typeString="PolygonM";
1929
                                } else if ((FShape.MULTIPOINT | FShape.M)  == type ){
1930
                                        typeString="MultiPointM";
1931
                                } else if ((FShape.MULTI | FShape.M)  == type ){
1932
                                        typeString="M";
1933
                                }
1934

    
1935
                        }
1936
                        return typeString;
1937
                }
1938
                return "";
1939
        }
1940
        public int getTypeIntVectorLayer() throws ReadDriverException {
1941
                int typeInt=0;
1942
                int typeShape=((FLyrVect)this).getShapeType();
1943
                if (FShape.MULTI==typeShape){
1944
                        ReadableVectorial rv=((FLyrVect)this).getSource();
1945
                        int i=0;
1946
                        boolean isCorrect=false;
1947
                        while(rv.getShapeCount()>i && !isCorrect){
1948
                                IGeometry geom=rv.getShape(i);
1949
                                if (geom==null){
1950
                                        i++;
1951
                                        continue;
1952
                                }
1953
                                isCorrect=true;
1954
                                if ((geom.getGeometryType() & FShape.Z) == FShape.Z){
1955
                                        typeInt=FShape.MULTI | FShape.Z;
1956
                                }else{
1957
                                        typeInt=FShape.MULTI;
1958
                                }
1959
                        }
1960
                }else{
1961
                        ReadableVectorial rv=((FLyrVect)this).getSource();
1962
                        int i=0;
1963
                        boolean isCorrect=false;
1964
                        while(rv.getShapeCount()>i && !isCorrect){
1965
                                IGeometry geom=rv.getShape(i);
1966
                                if (geom==null){
1967
                                        i++;
1968
                                        continue;
1969
                                }
1970
                                isCorrect=true;
1971
                                int type=geom.getGeometryType();
1972
                                typeInt=type;
1973
                        }
1974
                        return typeInt;
1975
                }
1976
                return typeInt;
1977
        }
1978
 }