Statistics
| Revision:

svn-gvsig-desktop / trunk / org.gvsig.desktop / org.gvsig.desktop.plugin / org.gvsig.editing.app / org.gvsig.editing.app.mainplugin / src / main / java / org / gvsig / editing / gui / cad / tools / SelectionCADTool.java @ 40557

History | View | Annotate | Download (19.8 KB)

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

    
26
import java.awt.Color;
27
import java.awt.event.InputEvent;
28
import java.awt.geom.Point2D;
29
import java.util.ArrayList;
30

    
31
import org.cresques.cts.ICoordTrans;
32
import org.slf4j.Logger;
33
import org.slf4j.LoggerFactory;
34

    
35
import org.gvsig.andami.PluginServices;
36
import org.gvsig.andami.messages.NotificationManager;
37
import org.gvsig.editing.CADExtension;
38
import org.gvsig.editing.IEditionManager;
39
import org.gvsig.editing.gui.cad.CADTool;
40
import org.gvsig.editing.gui.cad.DefaultCADTool;
41
import org.gvsig.editing.gui.cad.exception.CommandException;
42
import org.gvsig.editing.gui.cad.tools.smc.SelectionCADToolContext;
43
import org.gvsig.editing.gui.cad.tools.smc.SelectionCADToolContext.SelectionCADToolState;
44
import org.gvsig.editing.layers.VectorialLayerEdited;
45
import org.gvsig.fmap.dal.exception.DataException;
46
import org.gvsig.fmap.dal.exception.ReadException;
47
import org.gvsig.fmap.dal.feature.EditableFeature;
48
import org.gvsig.fmap.dal.feature.Feature;
49
import org.gvsig.fmap.dal.feature.FeatureSet;
50
import org.gvsig.fmap.dal.feature.FeatureStore;
51
import org.gvsig.fmap.dal.feature.exception.NeedEditingModeException;
52
import org.gvsig.fmap.geom.Geometry;
53
import org.gvsig.fmap.geom.handler.Handler;
54
import org.gvsig.fmap.geom.primitive.Curve;
55
import org.gvsig.fmap.geom.type.GeometryType;
56
import org.gvsig.fmap.mapcontext.MapContext;
57
import org.gvsig.fmap.mapcontext.ViewPort;
58
import org.gvsig.fmap.mapcontext.layers.FLayer;
59
import org.gvsig.fmap.mapcontrol.MapControlDrawer;
60
import org.gvsig.tools.dispose.DisposableIterator;
61

    
62
/**
63
 * DOCUMENT ME!
64
 * 
65
 * @author Vicente Caballero Navarro
66
 */
67
public class SelectionCADTool extends DefaultCADTool {
68

    
69
    private static final Logger LOG = LoggerFactory
70
        .getLogger(SelectionCADTool.class);
71

    
72
    protected SelectionCADToolContext _fsm;
73

    
74
    protected Point2D firstPoint;
75

    
76
    protected String nextState;
77
    
78
    // These two arrays are used to save the current selected features and
79
    // geometries. The selected geometries contains an instance of the
80
    // geometry that can be reprojected.
81
    protected ArrayList selectedGeometries = new ArrayList();
82
    protected ArrayList selectedFeatures = new ArrayList(); 
83
    
84
    protected String type = PluginServices.getText(this, "simple");
85

    
86
    protected boolean multipleSelection = false;
87

    
88
    /**
89
     * M?todo de incio, para poner el c?digo de todo lo que se requiera de una
90
     * carga previa a la utilizaci?n de la herramienta.
91
     */
92
    public void init() {
93
        _fsm = new SelectionCADToolContext(this);
94
        setNextTool("selection");
95
        setType(PluginServices.getText(this, "simple"));
96
    }
97

    
98
    public void transition(double x, double y, InputEvent event) {
99
        LOG.debug("TRANSICION DESDE ESTADO {}", _fsm.getState() + " x= " + x
100
            + " y=" + y);
101
        try {
102
            _fsm.addPoint(x, y, event);
103
        } catch (Exception e) {
104
            init();
105
            PluginServices.getMDIManager().restoreCursor();
106
        }
107
        LOG.debug("ESTADO ACTUAL: ", getStatus());
108
    }
109

    
110
    public void transition(double d) {
111
        _fsm.addValue(d);
112
    }
113

    
114
    public void transition(String s) throws CommandException {
115
        if (!super.changeCommand(s)) {
116
            _fsm.addOption(s);
117
        }
118
    }
119

    
120
    public String getNextState() {
121
        return nextState;
122
    }
123

    
124
    protected void pointDoubleClick(MapContext map) throws ReadException {
125
        FLayer[] actives = map.getLayers().getActives();
126
    }
127

    
128
    /**
129
     * Equivale al transition del prototipo pero sin pasarle como par? metro el
130
     * editableFeatureSource que ya estar? creado.
131
     * 
132
     * @param selection
133
     *            Bitset con las geometr?as que est?n seleccionadas.
134
     * @param x
135
     *            par?metro x del punto que se pase en esta transici?n.
136
     * @param y
137
     *            par?metro y del punto que se pase en esta transici?n.
138
     */
139
    public void addPoint(double x, double y, InputEvent event) {
140
        SelectionCADToolState actualState =
141
            (SelectionCADToolState) _fsm.getPreviousState();
142
        String status = actualState.getName();
143
        LOG.debug("PREVIOUSSTATE = {}", status);
144
        VectorialLayerEdited vle = getVLE();
145
        try {
146
            LOG.debug("STATUS ACTUAL = {}", _fsm.getTransition());
147
            if (status.equals("Selection.FirstPoint")) {
148
                firstPoint = new Point2D.Double(x, y);
149
            } else
150
                if (status.equals("Selection.SecondPoint")) {
151
                } else
152
                    if (status.equals("Selection.WithFeatures")) {
153
                    } else
154
                        if (status.equals("Selection.WithHandlers")) {
155
                            addPointWithHandlers(x, y, vle.getFeatureStore(),
156
                                vle.getSelectedHandler());
157
                        }
158
        } catch (DataException e) {
159
            LOG.error("Error reding the store", e);
160
        }
161
    }
162

    
163
    /**
164
     * AddPoint method for the WithHandlers option
165
     * 
166
     * @param x
167
     *            selected x coordinate.
168
     * @param y
169
     *            selected y coordinate.
170
     * @param featureStore
171
     *            the selected feature store.
172
     * @param selectedHandlers
173
     *            the selected handlers
174
     */
175
    protected void addPointWithHandlers(double x, double y,
176
        FeatureStore featureStore, ArrayList selectedHandlers) {
177
        String description = PluginServices.getText(this, "move_handlers");
178
        DisposableIterator iterator = null;
179
        
180
        IEditionManager ed_man = this.getEditionManager();
181
        try {
182
            featureStore.beginEditingGroup(description);
183
            ICoordTrans coordTrans = getVLE().getLayer().getCoordTrans();
184
            for (int i=0 ; i<selectedFeatures.size() ; i++){
185
                Feature feature = (Feature) selectedFeatures.get(i);
186
                
187
                Geometry changing_geometry = (Geometry)selectedGeometries.get(i);
188
                Geometry old_geometry = changing_geometry.cloneGeometry();
189
                
190
                // Draw the moved geometry. It has been reprojected in the
191
                // select handler method
192
                for (int k = 0; k < selectedHandlers.size(); k++) {
193
                    Handler h = (Handler) selectedHandlers.get(k);
194
                    h.set(x, y);
195
                }                            
196
                             
197
                //If the layer is reprojected, It is necessary
198
                //to reproject the geometry
199
                if (coordTrans != null) {
200
                    changing_geometry = changing_geometry.cloneGeometry();
201
                    changing_geometry.reProject(coordTrans.getInverted());
202
                    // ==========================
203
                    // this is already an independent clone
204
                    old_geometry.reProject(coordTrans.getInverted());
205
                }              
206
                
207
                // restore old geometry in feature
208
                // this is because selectedGeometries and
209
                // selectedFeature point
210
                // at the same geometries at least sometimes
211
                EditableFeature eFeature = feature.getEditable();
212
                eFeature.setDefaultGeometry(old_geometry);
213
                
214
                Feature old_geom_feature = eFeature.getNotEditableCopy();
215
                
216
                // set new (old remains as source for undoing)
217
                eFeature = old_geom_feature.getEditable();
218
                eFeature.setDefaultGeometry(changing_geometry);
219
                
220
                ed_man.updateFeature(featureStore, eFeature);
221
            }
222

    
223
            firstPoint = new Point2D.Double(x, y);
224

    
225
            featureStore.endEditingGroup();
226
        } catch (DataException e1) {
227
            LOG.error("Error reading the store", e1);
228
        } finally {
229
            if (iterator != null) {
230
                iterator.dispose();
231
            }
232
        }
233
    }
234

    
235
    /**
236
     * Receives second point
237
     * 
238
     * @param x
239
     * @param y
240
     * @return numFeatures selected
241
     */
242
    public long selectWithSecondPoint(double x, double y, InputEvent event) {
243
        VectorialLayerEdited vle = getVLE();
244
        PluginServices.getMDIManager().setWaitCursor();
245
        vle.selectWithSecondPoint(x, y);
246
        FeatureSet selection = null;
247
        try {
248
            selection = (FeatureSet) vle.getFeatureStore().getSelection();
249
            PluginServices.getMDIManager().restoreCursor();
250
            long countSel = selection.getSize();
251
            if (countSel > 0) {
252
                nextState = "Selection.WithSelectedFeatures";
253
            } else {
254
                nextState = "Selection.FirstPoint";
255
            }
256
            return countSel;
257
        } catch (ReadException e) {
258
            e.printStackTrace();
259
            return 0;
260
        } catch (DataException e) {
261
            e.printStackTrace();
262
            return 0;
263
        }
264
    }
265

    
266
    /**
267
     * M?todo para dibujar la lo necesario para el estado en el que nos
268
     * encontremos.
269
     * 
270
     * @param g
271
     *            Graphics sobre el que dibujar.
272
     * @param selectedGeometries
273
     *            BitSet con las geometr?as seleccionadas.
274
     * @param x
275
     *            par?metro x del punto que se pase para dibujar.
276
     * @param y
277
     *            par?metro x del punto que se pase para dibujar.
278
     */
279
    public void drawOperation(MapControlDrawer renderer, double x, double y) {
280
        SelectionCADToolState actualState = _fsm.getState();
281
        String status = actualState.getName();
282
        VectorialLayerEdited vle = getVLE();
283
        if (vle == null) {
284
            return;
285
        }
286
        ArrayList selectedHandler = vle.getSelectedHandler();
287
        ViewPort vp = vle.getLayer().getMapContext().getViewPort();
288
        if (status.equals("Selection.SecondPoint")) {
289
            // Dibuja el rect?ngulo de selecci?n
290
            Curve curve = createCurve();
291
            curve.addMoveToVertex(createPoint(firstPoint.getX(),
292
                firstPoint.getY()));
293
            curve.addVertex(createPoint(x, firstPoint.getY()));
294
            curve.addVertex(createPoint(x, y));
295
            curve.addVertex(createPoint(firstPoint.getX(), y));
296
            curve.addVertex(createPoint(firstPoint.getX(), firstPoint.getY()));
297

    
298
            renderer
299
                .draw(curve, mapControlManager.getGeometrySelectionSymbol());
300

    
301
            return;
302
        } else
303
            //If there is a handler to move...
304
            if (status.equals("Selection.WithHandlers")) {
305
                drawWithHandlers(renderer, x, y, selectedHandler);
306
            }
307
    }
308
    
309
    /**
310
     * Draw method to draw a geometry with handlers
311
     * 
312
     * @param mapControlDrawer
313
     *            object used to draw.
314
     * @param x
315
     *            selected x coordinate.
316
     * @param y
317
     *            selected y coordinate.
318
     * @param selectedHandlers
319
     *            the selected handlers
320
     */
321
    protected void drawWithHandlers(MapControlDrawer mapControlDrawer, double x,
322
        double y, ArrayList selectedHandlers) {
323
        // Moving the handlers that have been selected
324
        // in the selectHandlers method
325
        double xPrev = 0;
326
        double yPrev = 0;
327
        for (int k = 0; k < selectedHandlers.size(); k++) {
328
            Handler h = (Handler) selectedHandlers.get(k);
329
            xPrev = h.getPoint().getX();
330
            yPrev = h.getPoint().getY();
331
            h.set(x, y);
332
        }
333
       
334
        // Draw the moved geometry. It has been reprojected in the
335
        // select handler method
336
        for (int i = 0; i < selectedGeometries.size(); i++) {
337
            Geometry geom = (Geometry) selectedGeometries.get(i);
338

    
339
            mapControlDrawer.setColor(Color.gray);
340
            mapControlDrawer.draw(geom,
341
                mapControlManager.getAxisReferenceSymbol());
342
        }
343
        for (int k = 0; k < selectedHandlers.size(); k++) {
344
            Handler h = (Handler) selectedHandlers.get(k);
345
            h.set(xPrev, yPrev);
346
        } 
347
    }
348

    
349
    /**
350
     * Add a diferent option.
351
     * 
352
     * @param sel
353
     *            DOCUMENT ME!
354
     * @param s
355
     *            Diferent option.
356
     */
357
    public void addOption(String s) {
358
        SelectionCADToolState actualState =
359
            (SelectionCADToolState) _fsm.getPreviousState();
360
        String status = actualState.getName();
361
        LOG.debug("PREVIOUSSTATE = {}", status);
362
        LOG.debug("STATUS ACTUAL = {}", _fsm.getTransition());
363
        if (s.equals(PluginServices.getText(this, "cancel"))) {
364
            init();
365
            return;
366
        }
367
        if (status.equals("Selection.FirstPoint")) {
368
            setType(s);
369
            return;
370
        }
371
        init();
372
    }
373

    
374
    /*
375
     * (non-Javadoc)
376
     * 
377
     * @see com.iver.cit.gvsig.gui.cad.CADTool#addvalue(double)
378
     */
379
    public void addValue(double d) {
380
    }
381

    
382
    public String getStatus() {
383
        try {
384
            SelectionCADToolState actualState =
385
                (SelectionCADToolState) _fsm.getPreviousState();
386
            String status = actualState.getName();
387

    
388
            return status;
389
        } catch (NullPointerException e) {
390
            return "Selection.FirstPoint";
391
        }
392
    }
393

    
394
    public void end() {
395
        if (!getNextTool().equals("selection")) {
396
            CADExtension.setCADTool(getNextTool(), false);
397
        }
398
    }
399

    
400
    public String getName() {
401
        return PluginServices.getText(this, "selection_");
402
    }
403

    
404
    public boolean selectFeatures(double x, double y, InputEvent event) {
405
        SelectionCADToolState actualState = _fsm.getState();
406

    
407
        String status = actualState.getName();
408
        VectorialLayerEdited vle = getVLE();
409
        multipleSelection = event.isControlDown();
410

    
411
        if ((status.equals("Selection.FirstPoint"))
412
            || (status.equals("Selection.WithSelectedFeatures"))) {
413
            PluginServices.getMDIManager().setWaitCursor();
414
            firstPoint = new Point2D.Double(x, y);
415
            try {
416
                vle.getFeatureStore().beginEditingGroup(getName());
417
                vle.selectWithPoint(x, y, multipleSelection);
418
                vle.getFeatureStore().endEditingGroup();
419
            } catch (NeedEditingModeException e) {
420
                NotificationManager.showMessageError(getName(), e);
421
            } catch (ReadException e) {
422
                NotificationManager.showMessageError(getName(), e);
423
            }
424
            PluginServices.getMDIManager().restoreCursor();
425
        }
426
        FeatureSet selection = null;
427
        try {
428
            selection = (FeatureSet) vle.getFeatureStore().getSelection();
429
            long countSel = selection.getSize();
430
            if (countSel > 0) {
431
                nextState = "Selection.WithSelectedFeatures";
432
                return true;
433
            } else {
434
                {
435
                    nextState = "Selection.SecondPoint";
436
                    return true;
437
                }
438
            }
439
        } catch (ReadException e) {
440
            LOG.error("Error selecting the features", e);
441
            return false;
442
        } catch (DataException e) {
443
            LOG.error("Error selecting the features", e);
444
            return false;
445
        }
446
    }
447

    
448
    public int selectHandlers(double x, double y, InputEvent event) {
449
        Point2D auxPoint = new Point2D.Double(x, y);
450

    
451
        VectorialLayerEdited vle = getVLE();
452
        
453
        //Gets the current selected handlers 
454
        ArrayList selectedHandler = vle.getSelectedHandler();
455
        FeatureSet selection = null;
456
        DisposableIterator iterator = null;
457
        try {
458
            selection = (FeatureSet) vle.getFeatureStore().getSelection();
459

    
460
            long countSel = selection.getSize();
461
            LOG.debug("DENTRO DE selectHandlers. selectedRow.size = {}",
462
                countSel);
463
            selectedHandler.clear();
464

    
465
            //Clear the previous selection
466
            clearCurrentSelection();
467
            
468
            // Se comprueba si se pincha en una gemometr?a
469
            PluginServices.getMDIManager().setWaitCursor();
470

    
471
            double tam =
472
                getCadToolAdapter().getMapControl().getViewPort()
473
                    .toMapDistance(mapControlManager.getTolerance());
474

    
475
            Handler[] handlers = null;
476
            
477
            
478
            selectedGeometries.clear();
479
            iterator = selection.fastIterator();
480
            ICoordTrans coordTrans = getVLE().getLayer().getCoordTrans();
481
            while (iterator.hasNext()) {
482
                Feature feature = (Feature) iterator.next();
483
                
484
                //If the layer is reprojected, the tolerance is not applicable. It is necessary
485
                //to reproject the geometry
486
                Geometry geometry = feature.getDefaultGeometry();
487
                if (coordTrans != null){
488
                    geometry = geometry.cloneGeometry();
489
                    geometry.reProject(coordTrans);
490
                }
491
                
492
                handlers = geometry.getHandlers(Geometry.SELECTHANDLER);
493

    
494
                // y miramos los handlers de cada entidad seleccionada
495
                double min = tam;
496

    
497
                for (int j = 0; j < handlers.length; j++) {
498
                    Point2D handlerPoint = handlers[j].getPoint();
499
                    double distance = auxPoint.distance(handlerPoint);
500
                    if (distance <= min) {
501
                        min = distance;
502
                        selectedHandler.add(handlers[j]);
503
                        selectedGeometries.add(geometry);
504
                        selectedFeatures.add(feature);
505
                    }
506
                }
507
            }
508
            PluginServices.getMDIManager().restoreCursor();
509
        } catch (DataException e) {
510
            LOG.error("Error reading the store", e);
511
        } finally {
512
            if (iterator != null) {
513
                iterator.dispose();
514
            }
515
        }
516

    
517
        return selectedHandler.size();
518
    }
519
    
520
    protected void clearCurrentSelection(){
521
        selectedFeatures.clear();
522
        selectedGeometries.clear();
523
    }
524

    
525
    public String getType() {
526
        return type;
527
    }
528

    
529
    public void setType(String type) {
530
        if (type.equals("S") || type.equals("s")) {
531
            this.type = PluginServices.getText(this, "simple");
532
        } else {
533
            this.type = type;
534
        }
535
    }
536

    
537
    public String toString() {
538
        return "_selection";
539
    }
540

    
541
    public void multipleSelection(boolean b) {
542
        multipleSelection = b;
543

    
544
    }
545

    
546
    @Override
547
    public boolean isApplicable(GeometryType geometryType) {
548
        return true;
549
    }
550

    
551
    @Override
552
    protected int[] getSupportedGeometryTypes() {
553
        return null;
554
    }
555
    
556
    /**
557
     * Tells whether the tool provided is an instance of this class
558
     * 
559
     * @param tool
560
     * @param exactly_this requires that the object is an instance of
561
     * this class and not an instance of a subclass
562
     *  
563
     * @return 
564
     */
565
    public static boolean isInstance(CADTool tool, boolean exactly_this) {
566
        
567
        if (exactly_this) {
568
            return tool.getClass() == SelectionCADTool.class;
569
        } else {
570
            return (tool instanceof SelectionCADTool);
571
        }
572
        
573
    }
574
}