Statistics
| Revision:

root / trunk / extensions / extCAD / src / com / iver / cit / gvsig / gui / cad / CADToolAdapter.java @ 30100

History | View | Annotate | Download (47.5 KB)

1
package com.iver.cit.gvsig.gui.cad;
2

    
3
import java.awt.BasicStroke;
4
import java.awt.Color;
5
import java.awt.Cursor;
6
import java.awt.FontMetrics;
7
import java.awt.Graphics;
8
import java.awt.Graphics2D;
9
import java.awt.Image;
10
import java.awt.Point;
11
import java.awt.Toolkit;
12
import java.awt.event.InputEvent;
13
import java.awt.event.MouseEvent;
14
import java.awt.event.MouseWheelEvent;
15
import java.awt.geom.Point2D;
16
import java.awt.geom.Rectangle2D;
17
import java.awt.image.MemoryImageSource;
18
import java.util.ArrayList;
19
import java.util.HashMap;
20
import java.util.List;
21
import java.util.Stack;
22
import java.util.prefs.Preferences;
23

    
24
import org.cresques.cts.IProjection;
25

    
26
import com.hardcode.gdbms.driver.exceptions.ReadDriverException;
27
import com.iver.andami.PluginServices;
28
import com.iver.andami.messages.NotificationManager;
29
import com.iver.andami.ui.mdiFrame.MainFrame;
30
import com.iver.andami.ui.mdiManager.IWindow;
31
import com.iver.cit.gvsig.CADExtension;
32
import com.iver.cit.gvsig.EditionManager;
33
import com.iver.cit.gvsig.fmap.MapContext;
34
import com.iver.cit.gvsig.fmap.MapControl;
35
import com.iver.cit.gvsig.fmap.ViewPort;
36
import com.iver.cit.gvsig.fmap.core.FShape;
37
import com.iver.cit.gvsig.fmap.core.IGeometry;
38
import com.iver.cit.gvsig.fmap.core.SymbologyFactory;
39
import com.iver.cit.gvsig.fmap.core.symbols.ISymbol;
40
import com.iver.cit.gvsig.fmap.core.v02.FConstant;
41
import com.iver.cit.gvsig.fmap.core.v02.FConverter;
42
import com.iver.cit.gvsig.fmap.edition.EditionEvent;
43
import com.iver.cit.gvsig.fmap.edition.UtilFunctions;
44
import com.iver.cit.gvsig.fmap.edition.VectorialEditableAdapter;
45
import com.iver.cit.gvsig.fmap.layers.FBitSet;
46
import com.iver.cit.gvsig.fmap.layers.FLyrVect;
47
import com.iver.cit.gvsig.fmap.layers.SpatialCache;
48
import com.iver.cit.gvsig.fmap.tools.BehaviorException;
49
import com.iver.cit.gvsig.fmap.tools.Behavior.Behavior;
50
import com.iver.cit.gvsig.fmap.tools.Listeners.ToolListener;
51
import com.iver.cit.gvsig.gui.cad.tools.SelectionCADTool;
52
import com.iver.cit.gvsig.gui.preferences.SnapConfigPage;
53
import com.iver.cit.gvsig.layers.ILayerEdited;
54
import com.iver.cit.gvsig.layers.VectorialLayerEdited;
55
import com.iver.cit.gvsig.project.documents.view.gui.View;
56
import com.iver.cit.gvsig.project.documents.view.snapping.ISnapper;
57
import com.iver.cit.gvsig.project.documents.view.snapping.ISnapperGeometriesVectorial;
58
import com.iver.cit.gvsig.project.documents.view.snapping.ISnapperRaster;
59
import com.iver.cit.gvsig.project.documents.view.snapping.ISnapperVectorial;
60
import com.iver.cit.gvsig.project.documents.view.snapping.SnappingVisitor;
61
import com.iver.cit.gvsig.project.documents.view.snapping.snappers.FinalPointSnapper;
62
import com.iver.cit.gvsig.project.documents.view.snapping.snappers.NearestPointSnapper;
63
import com.iver.cit.gvsig.project.documents.view.toolListeners.StatusBarListener;
64
import com.iver.utiles.console.JConsole;
65
import com.iver.utiles.swing.threads.Cancellable;
66
import com.vividsolutions.jts.geom.Envelope;
67

    
68
/**
69
 * <p>Allows user interact with different CAD tools, on a layer being edited.</p>
70
 *
71
 * <p>There are two ways of interacting:
72
 *  <ul>
73
 *   <li><b>With the mouse</b> : user selects any {@link CADTool CADTool} that produces mouse events as consequence
74
 *    of the actions working with the layer being edited.
75
 *   </li>
76
 *   <li><b>Writing commands in the edition console</b> : most of the {@link CADTool CADTool} mouse actions can also
77
 *    be called writing a command or a command's parameter in the associated edition console, and pressing the key <code>Enter</code>.
78
 *    If the command isn't valid, will notify it.
79
 *   </li>
80
 *  </ul>
81
 * </p>
82
 *
83
 * <p>The edition has been implemented as a <i>finite machine</i>, with three kind of transitions between states according
84
 *  the parameters introduced:
85
 *  <ul>
86
 *   <li><i>First transition type: <b>Point</i></b>: if <code>text</code> matches with any pattern of
87
 *    parameters needed for any kind of point coordinates.<br>
88
 *    There are eight ways of introducing point 2D coordinates:
89
 *    <ul>
90
 *    <li><i>X,Y</i> : absolute cardinal 2D coordinate from the center <i>(0,0)</i> of the CCS <i>Current Coordinate System</i>.</li>
91
 *    <li><i>@X,Y</i> : relative cardinal 2D distances from the last point added of the CCS. If it's the first point of the geometry,
92
 *     works like <i>X,Y</i>.</li>
93
 *    <li><i>length< angle</i> : absolute polar 2D coordinate from the center <i>(0,0)</i> of the CCS <i>Current Coordinate System</i>, using
94
 *     <i>angle</i> from the <i>X</i> axis of CCS, and <i>length</i> far away.</li>
95
 *    <li><i>@length< angle</i> : relative polar 2D coordinate from the last point added of the CCS <i>Current Coordinate System</i>, using
96
 *     <i>angle</i> from the <i>X</i> axis of CCS, and <i>length</i> far away. If it's the first point of the geometry,
97
 *     works like <i>length< angle</i>.</li>
98
 *    <li><i>*X,Y</i> : like <i>X,Y</i> but using UCS <i>Universal Coordinate System</i> as reference.</li>
99
 *    <li><i>@*X,Y</i> : like <i>@X,Y</i> but using UCS <i>Universal Coordinate System</i> as reference.
100
 *      If it's the first point of the geometry, works like <i>*X,Y</i>.</li>
101
 *    <li><i>*length< angle</i> : like <i>length< angle</i> but using UCS <i>Universal Coordinate System</i> as reference.</li>
102
 *    <li><i>@*length< angle</i> : like <i>@length< angle</i> but using UCS <i>Universal Coordinate System</i> as reference.
103
 *      If it's the first point of the geometry, works like <i>*length< angle</i>.</li>
104
 *    </ul>
105
 *   </li>
106
 *   <li><i>Second transition type: <b>Value</i></b>: if recognizes it as a single number.</li>
107
 *   <li><i>Third transition type: <b>Option</i></b>: by default, if can't classify the information as a single number
108
 *    neither as a point. This information will be an <code>String</code> and dealt as an option of the current
109
 *    tool state. Ultimately, if isn't valid, <code>text</code> will be rewritten in the console notifying the user
110
 *    that isn't correct.</li>
111
 *  </ul>
112
 * </p>
113
 *
114
 * @see Behavior
115
 * @see MapControl
116
 */
117
public class CADToolAdapter extends Behavior {
118
        /**
119
         * Stores the CAD tools to edit the layers of the associated <code>MapControl</code>.
120
         *
121
         * @see #addCADTool(String, CADTool)
122
         * @see #getCadTool()
123
         * @see #getCADTool(String)
124
         */
125
        private static HashMap namesCadTools = new HashMap();
126

    
127
        /**
128
         * Reference to the object used to manage the edition of the layers of the associated <code>MapControl</code>.
129
         *
130
         * @see EditionManager
131
         * @see #getEditionManager()
132
         */
133
        private EditionManager editionManager = new EditionManager();
134

    
135
        /**
136
         * Identifies that the data are absolute coordinates of the new point from the (0, 0) position.
137
         */
138
        public static final int ABSOLUTE = 0;
139

    
140
        /**
141
         * Equivalent to {@link CADToolAdapter#ABSOLUTE CADToolAdapter#ABSOLUTE}.
142
         */
143
        public static final int RELATIVE_SCP = 1;
144

    
145
        /**
146
         * Identifies that the data are relative distances of the new point from the previous introduced.
147
         */
148
        public static final int RELATIVE_SCU = 2;
149

    
150
        /**
151
         * Identifies that the data are relative polar distances (longitude of the line and angle given in degrees)
152
         *  of the new point from the previous introduced.
153
         */
154
        public static final int POLAR_SCP = 3;
155

    
156
        /**
157
         * Identifies that the data are relative polar distances (longitude of the line and angle given in radians)
158
         *  of the new point from the previous introduced.
159
         */
160
        public static final int POLAR_SCU = 4;
161

    
162
        /**
163
         * Stores the 2D map coordinates of the last point added.
164
         */
165
        private double[] previousPoint = null;
166

    
167
        /**
168
         * <i>Stack with CAD tools.</i>
169
         *
170
         * <i>For each CAD tool we use, the last item added in this stack will
171
         *  display a different icon according to the current operation and its status.</i>
172
         */
173
        private Stack cadToolStack = new Stack();
174

    
175
        /**
176
         * X coordinate of the last dragging or moving mouse event.
177
         */
178
        private int lastX;
179

    
180
        /**
181
         * Y coordinate of the last dragging or moving mouse event.
182
         */
183
        private int lastY;
184

    
185
        /**
186
         * Unused attribute.
187
         */
188
        private ISymbol symbol = SymbologyFactory.createDefaultSymbolByShapeType(FConstant.SYMBOL_TYPE_POINT, Color.RED);
189

    
190
        /**
191
         * Represents the cursor's point selected in <i>map coordinates</i>.
192
         *
193
         * @see MapControl#toMapPoint
194
         */
195
        private Point2D mapAdjustedPoint;
196

    
197
        /**
198
         * Kind of geometry drawn to identify the kind of control point selected by the cursor's mouse.
199
         */
200
        private ISnapper usedSnap = null;
201

    
202
        /**
203
         * Determines if has displayed at the edition console, the question for the operations that can do
204
         *  the user with the current CAD tool, in its current state.
205
         */
206
        private boolean questionAsked = false;
207

    
208
        /**
209
         * Represents the cursor's point selected in <i>screen coordinates</i>.
210
         *
211
         * @see ViewPort#fromMapPoint(Point2D)
212
         */
213
        private Point2D adjustedPoint;
214

    
215
        /**
216
         * Determines if the snap tools are enabled or disabled.
217
         *
218
         * @see #isRefentEnabled()
219
         * @see #setRefentEnabled(boolean)
220
         */
221
        private boolean bRefent = true;
222

    
223
        /**
224
         * <p>Determines if the position of the snap of the mouse's cursor on the <code>MapControl</code>
225
         * is within the area around a control point of a geometry.</p>
226
         *
227
         * <p>The area is calculated as a circle centered at the control point and with radius the pixels tolerance
228
         *  defined in the preferences.</p>
229
         */
230
        private boolean bForceCoord = false;
231

    
232
        /**
233
         * Optional grid that could be applied on the <code>MapControl</code>'s view port.
234
         *
235
         * @see #getGrid()
236
         * @see #setAdjustGrid(boolean)
237
         */
238
        private CADGrid cadgrid = new CADGrid();
239

    
240
        /**
241
         * Determines is is enabled or not the <i>Orto</i> mode.
242
         */
243
        private boolean bOrtoMode;
244

    
245
        /**
246
         * A light yellow color for the tool tip text box associated to the point indicated by the mouse's cursor.
247
         */
248
        private Color theTipColor = new Color(255, 255, 155);
249

    
250
        /**
251
         * Last question asked to the user in the CAD console.
252
         */
253
        private Object lastQuestion;
254

    
255
        /**
256
         * Maximum tolerance in the approximation of a curved line by a polyline.
257
         *
258
         * @see #initializeFlatness()
259
         */
260
        private static boolean flatnessInitialized=false;
261

    
262
        /**
263
         * Edition preferences.
264
         */
265
        private static Preferences prefs = Preferences.userRoot().node( "cadtooladapter" );
266

    
267
        /**
268
         * Listener to display the coordinates in the current application's status bar.
269
         */
270
        private StatusBarListener sbl=null;
271

    
272
        /*
273
         * (non-Javadoc)
274
         * @see com.iver.cit.gvsig.fmap.tools.Behavior.Behavior#setMapControl(com.iver.cit.gvsig.fmap.MapControl)
275
         */
276
        public void setMapControl(MapControl mc) {
277
                super.setMapControl(mc);
278
                sbl=new StatusBarListener(getMapControl());
279
        }
280

    
281
        /**
282
         * <p>Draws the selected geometries to edit. And, if the <i>snapping</i> is enabled,
283
         *  draws also its effect over them.</p>
284
         *
285
         * @see com.iver.cit.gvsig.fmap.tools.Behavior.Behavior#paintComponent(java.awt.Graphics)
286
         */
287
        public void paintComponent(Graphics g) {
288
                super.paintComponent(g);
289
                if (CADExtension.getCADToolAdapter()!=this)
290
                        return;
291

    
292
                if (adjustedPoint != null) {
293
                        Point2D p = null;
294
                        if (mapAdjustedPoint != null) {
295
                                p = mapAdjustedPoint;
296
                        } else {
297
                                p = getMapControl().getViewPort().toMapPoint(adjustedPoint);
298
                        }
299
                        if (!cadToolStack.isEmpty())
300
                        ((CADTool) cadToolStack.peek())
301
                                        .drawOperation(g, p.getX(), p.getY());
302
                }
303
                drawCursor(g);
304
                getGrid().drawGrid(g);
305
        }
306

    
307
        /**
308
         * <p>Responds two kind of mouse click events:
309
         *  <ul>
310
         *   <li><b><i>One click of the third mouse's button</i></b>: displays a popup with edition options.</li>
311
         *   <li><b><i>Two clicks of the first mouse's button</i></b>: ends the last cad tool setting as end transition
312
         *    point the event's one.</li>
313
         *  </ul>
314
         * </p>
315
         *
316
         *
317
         * @see com.iver.cit.gvsig.fmap.tools.Behavior.Behavior#mouseClicked(java.awt.event.MouseEvent)
318
         * @see CADExtension#showPopup(MouseEvent)
319
         */
320
        public void mouseClicked(MouseEvent e) throws BehaviorException {
321
                if (e.getButton() == MouseEvent.BUTTON3) {
322
                        CADExtension.showPopup(e);
323
                }else if (e.getButton() == MouseEvent.BUTTON1 && e.getClickCount()==2){
324
                        questionAsked = true;
325
                        if (!cadToolStack.isEmpty()) {
326
                                CADTool ct = (CADTool) cadToolStack.peek();
327
                                ViewPort vp = getMapControl().getMapContext().getViewPort();
328
                                Point2D p;
329

    
330
                                if (mapAdjustedPoint != null) {
331
                                        p = mapAdjustedPoint;
332
                                } else {
333
                                        p = vp.toMapPoint(adjustedPoint);
334
                                }
335
                                ct.endTransition(p.getX(), p.getY(), e);
336
                                previousPoint = new double[]{p.getX(),p.getY()};
337
                        }
338
                }
339
        }
340

    
341
        /*
342
         * (non-Javadoc)
343
         * @see com.iver.cit.gvsig.fmap.tools.Behavior.Behavior#mouseEntered(java.awt.event.MouseEvent)
344
         */
345
        public void mouseEntered(MouseEvent e) throws BehaviorException {
346
                clearMouseImage();
347
        }
348

    
349
        /*
350
         * (non-Javadoc)
351
         * @see com.iver.cit.gvsig.fmap.tools.Behavior.Behavior#mouseExited(java.awt.event.MouseEvent)
352
         */
353
        public void mouseExited(MouseEvent e) throws BehaviorException {
354
        }
355

    
356
        /**
357
         * Selects the vertex of a geometry at the point selected on the <code>MapControl</code>
358
         * by pressing the first mouse's button.
359
         *
360
         * @see com.iver.cit.gvsig.fmap.tools.Behavior.Behavior#mousePressed(java.awt.event.MouseEvent)
361
         */
362
        public void mousePressed(MouseEvent e) throws BehaviorException {
363
                if (e.getButton() == MouseEvent.BUTTON1) {
364
                        ViewPort vp = getMapControl().getMapContext().getViewPort();
365
                        Point2D p;
366

    
367
                        if (mapAdjustedPoint != null) {
368
                                p = mapAdjustedPoint;
369
                        } else {
370
                                p = vp.toMapPoint(adjustedPoint);
371
                        }
372
                        transition(new double[] { p.getX(), p.getY() }, e, ABSOLUTE);
373
                }
374
        }
375

    
376
        /**
377
         * <p>Adjusts the <code>point</code> to the grid if its enabled, and
378
         *  sets <code>mapHandlerAdjustedPoint</code> with that new value.</p>
379
         *
380
         * <p>The value returned is the distance between those points: the original and
381
         *  the adjusted one.</p>
382
         *
383
         * @param point point to adjust
384
         * @param mapHandlerAdjustedPoint <code>point</code> adjusted
385
         *
386
         * @return distance from <code>point</code> to the adjusted one. If there is no
387
         *  adjustment, returns <code>Double.MAX_VALUE</code>.
388
         */
389
        private double adjustToHandler(Point2D point,
390
            Point2D mapHandlerAdjustedPoint) {
391

    
392
        if (!isRefentEnabled())
393
            return Double.MAX_VALUE;
394

    
395
        ILayerEdited aux = CADExtension.getEditionManager().getActiveLayerEdited();
396
        if (!(aux instanceof VectorialLayerEdited))
397
            return Double.MAX_VALUE;
398
        VectorialLayerEdited vle = (VectorialLayerEdited) aux;
399

    
400
        ArrayList snappers = SnapConfigPage.getActivesSnappers();
401
        ArrayList layersToSnap = vle.getLayersToSnap();
402

    
403

    
404
        ViewPort vp = getMapControl().getViewPort();
405

    
406
//        // TODO: PROVISIONAL. PONER ALGO COMO ESTO EN UN CUADRO DE DIALOGO
407
//        // DE CONFIGURACI?N DEL SNAPPING
408
//        FinalPointSnapper defaultSnap = new FinalPointSnapper();
409
//        NearestPointSnapper nearestSnap = new NearestPointSnapper();
410
//        // PixelSnapper pixSnap = new PixelSnapper();
411
//        snappers.clear();
412
//        snappers.add(defaultSnap);
413
//        snappers.add(nearestSnap);
414
//        // snappers.add(pixSnap);
415

    
416
        double mapTolerance = vp.toMapDistance(SelectionCADTool.tolerance);
417
        double minDist = mapTolerance;
418
//        double rw = getMapControl().getViewPort().toMapDistance(5);
419
        Point2D mapPoint = point;
420
        Rectangle2D r = new Rectangle2D.Double(mapPoint.getX() - mapTolerance / 2,
421
                mapPoint.getY() - mapTolerance / 2, mapTolerance, mapTolerance);
422

    
423
        Envelope e = FConverter.convertRectangle2DtoEnvelope(r);
424

    
425
        usedSnap = null;
426
        Point2D lastPoint = null;
427
        if (previousPoint != null)
428
        {
429
            lastPoint = new Point2D.Double(previousPoint[0], previousPoint[1]);
430
        }
431
        for (int j = 0; j < layersToSnap.size(); j++)
432
        {
433
            FLyrVect lyrVect = (FLyrVect) layersToSnap.get(j);
434
            SpatialCache cache = lyrVect.getSpatialCache();
435
            if (lyrVect.isVisible())
436
            {
437
                // La lista de snappers est? siempre ordenada por prioridad. Los de mayor
438
                // prioridad est?n primero.
439
                List geoms = cache.query(e);
440
                for (int n=0; n < geoms.size(); n++) {
441
                    IGeometry geom = (IGeometry) geoms.get(n);
442
                    for (int i = 0; i < snappers.size(); i++)
443
                    {
444
//                        if (cancel.isCanceled())
445
//                            return Double.MAX_VALUE;
446
                        ISnapper theSnapper = (ISnapper) snappers.get(i);
447

    
448
                        if (usedSnap != null)
449
                        {
450
                            // Si ya tenemos un snap y es de alta prioridad, cogemos ese. (A no ser que en otra capa encontremos un snapper mejor)
451
                            if (theSnapper.getPriority() > usedSnap.getPriority())
452
                                break;
453
                        }
454
//                        SnappingVisitor snapVisitor = null;
455
                        Point2D theSnappedPoint = null;
456
                        if (theSnapper instanceof ISnapperVectorial)
457
                        {
458
//                                if (theSnapper instanceof ISnapperGeometriesVectorial){
459
//                                        ((ISnapperGeometriesVectorial)theSnapper).setGeometries(geoms);
460
//                                }
461
//                            snapVisitor = new SnappingVisitor((ISnapperVectorial) theSnapper, point, mapTolerance, lastPoint);
462
//                            // System.out.println("Cache size = " + cache.size());
463
//                            cache.query(e, snapVisitor);
464
//                            theSnappedPoint = snapVisitor.getSnapPoint();
465
                            theSnappedPoint = ((ISnapperVectorial) theSnapper).getSnapPoint(point, geom, mapTolerance, lastPoint);
466
                        }
467
                        if (theSnapper instanceof ISnapperRaster)
468
                        {
469
                            ISnapperRaster snapRaster = (ISnapperRaster) theSnapper;
470
                            theSnappedPoint = snapRaster.getSnapPoint(getMapControl(), point, mapTolerance, lastPoint);
471
                        }
472

    
473

    
474
                        if (theSnappedPoint != null) {
475
                            double distAux = theSnappedPoint.distance(point);
476
                            if (minDist > distAux)
477
                            {
478
                                minDist = distAux;
479
                                usedSnap = theSnapper;
480
                                mapHandlerAdjustedPoint.setLocation(theSnappedPoint);
481
                            }
482
                        }
483
                    }
484
                } // for n
485
            } // visible
486
        }
487
        if (usedSnap != null)
488
            return minDist;
489
        return Double.MAX_VALUE;
490

    
491
    }
492
        /*
493
         * (non-Javadoc)
494
         * @see com.iver.cit.gvsig.fmap.tools.Behavior.Behavior#mouseReleased(java.awt.event.MouseEvent)
495
         */
496
        public void mouseReleased(MouseEvent e) throws BehaviorException {
497
                getMapControl().repaint();
498
        }
499

    
500
        /*
501
         * (non-Javadoc)
502
         * @see com.iver.cit.gvsig.fmap.tools.Behavior.Behavior#mouseDragged(java.awt.event.MouseEvent)
503
         */
504
        public void mouseDragged(MouseEvent e) throws BehaviorException {
505
                lastX = e.getX();
506
                lastY = e.getY();
507

    
508
                calculateSnapPoint(e.getPoint());
509
        }
510

    
511
        /*
512
         * (non-Javadoc)
513
         * @see com.iver.cit.gvsig.fmap.tools.Behavior.Behavior#mouseMoved(java.awt.event.MouseEvent)
514
         */
515
        public void mouseMoved(MouseEvent e) throws BehaviorException {
516

    
517
                lastX = e.getX();
518
                lastY = e.getY();
519

    
520
                calculateSnapPoint(e.getPoint());
521

    
522
                showCoords(e.getPoint());
523

    
524
                getMapControl().repaint();
525
        }
526

    
527
        /**
528
         * Displays the current coordinates of the mouse's cursor on the associated <code>MapControl</code>
529
         *  object, at the status bar of the application's main frame.
530
         *
531
         * @param pPix current 2D mouse's cursor coordinates on the <code>MapControl</code>
532
         */
533
        private void showCoords(Point2D pPix)
534
        {
535
                String[] axisText = new String[2];
536
                axisText[0] = "X = ";
537
                axisText[1] = "Y = ";
538
//                NumberFormat nf = NumberFormat.getInstance();
539
                MapControl mapControl = getMapControl();
540
                ViewPort vp = mapControl.getMapContext().getViewPort();
541
                IProjection iProj = vp.getProjection();
542

    
543
//                if (iProj.getAbrev().equals("EPSG:4326") || iProj.getAbrev().equals("EPSG:4230")) {
544
//                        axisText[0] = "Lon = ";
545
//                        axisText[1] = "Lat = ";
546
//                        nf.setMaximumFractionDigits(8);
547
//                } else {
548
//                        axisText[0] = "X = ";
549
//                        axisText[1] = "Y = ";
550
//                        nf.setMaximumFractionDigits(2);
551
//                }
552
                Point2D p;
553
                if (mapAdjustedPoint == null)
554
                {
555
                        p = vp.toMapPoint(pPix);
556
                }
557
                else
558
                {
559
                        p = mapAdjustedPoint;
560
                }
561
                sbl.setFractionDigits(p);
562
                axisText = sbl.setCoorDisplayText(axisText);
563
                MainFrame mF = PluginServices.getMainFrame();
564

    
565
                if (mF != null)
566
                {
567
            mF.getStatusBar().setMessage("units",
568
                            PluginServices.getText(this, MapContext.getDistanceNames()[vp.getDistanceUnits()]));
569
            mF.getStatusBar().setControlValue("scale",String.valueOf(mapControl.getMapContext().getScaleView()));
570
                        mF.getStatusBar().setMessage("projection", iProj.getAbrev());
571

    
572
                        String[] coords=sbl.getCoords(p);
573
                        mF.getStatusBar().setMessage("x",
574
                                        axisText[0] + coords[0]);
575
                        mF.getStatusBar().setMessage("y",
576
                                        axisText[1] + coords[1]);
577
                }
578
        }
579

    
580
        /**
581
         * Hides the mouse's cursor.
582
         */
583
        private void clearMouseImage() {
584
                int[] pixels = new int[16 * 16];
585
                Image image = Toolkit.getDefaultToolkit().createImage(
586
                                new MemoryImageSource(16, 16, pixels, 0, 16));
587
                Cursor transparentCursor = Toolkit.getDefaultToolkit()
588
                                .createCustomCursor(image, new Point(0, 0), "invisiblecursor");
589

    
590
                getMapControl().setCursor(transparentCursor);
591
        }
592
        
593
        /**
594
         * Uses like a mouse pointer the image that provides the
595
         * selected tool.
596
         */
597
        private void setToolMouse(){
598
                Image cursor = PluginServices.getIconTheme().get("cad-selection-icon").getImage();
599
                Toolkit toolkit = Toolkit.getDefaultToolkit();
600
                Cursor c = toolkit.createCustomCursor(cursor , 
601
                                new Point(16, 16), "img");
602
                getMapControl().setCursor (c);
603
        }
604

    
605
        /**
606
         * <p>Draws a 31x31 pixels cross round the mouse's cursor with an small geometry centered:
607
         *  <ul>
608
         *   <li><i>an square centered</i>: if isn't over a <i>control point</i>.
609
         *   <li><i>an small geometry centered according to the kind of control point</i>: if it's over a control
610
         *    point. In this case, the small geometry is drawn by a {@link ISnapper ISnapper} type object.<br>
611
         *    On the other hand, a light-yellowed background tool tip text with the type of <i>control point</i> will
612
         *     be displayed.</li>
613
         * </p>
614
         *
615
         * @param g <code>MapControl</code>'s graphics where the data will be drawn
616
         */
617
        private void drawCursor(Graphics g) {
618
                if (adjustedPoint == null){
619
                        return;
620
                }
621
                
622
                if (usedSnap != null){
623
                        usedSnap.draw(g, adjustedPoint);
624
                        clearMouseImage();                        
625
                }else{
626
                        setToolMouse();
627
                }
628
        }
629

    
630
        /**
631
         * <p>Tries to find the nearest geometry or grid control point by the position of the current snap tool.</p>
632
         *
633
         * <p>Prioritizes the grid control points than the geometries ones.</p>
634
         *
635
         * <p>If finds any near, stores the <i>map</i> and <i>pixel</i> coordinates for the snap, and enables
636
         *  the <code>bForceCoord</code> attribute for the next draw of the mouse's cursor.</p>
637
         *
638
         * @param point current mouse 2D position
639
         */
640
        private void calculateSnapPoint(Point point) {
641
                // Se comprueba el ajuste a rejilla
642

    
643
                Point2D gridAdjustedPoint = getMapControl().getViewPort().toMapPoint(
644
                                point);
645
                double minDistance = Double.MAX_VALUE;
646
                if (!cadToolStack.isEmpty()){
647
                CADTool ct = (CADTool) cadToolStack.peek();
648
                if (ct instanceof SelectionCADTool
649
                                && ((SelectionCADTool) ct).getStatus().equals(
650
                                                "Selection.FirstPoint")) {
651
                        mapAdjustedPoint = gridAdjustedPoint;
652
                        adjustedPoint = (Point2D) point.clone();
653
                } else {
654

    
655
                        minDistance = getGrid().adjustToGrid(gridAdjustedPoint);
656
                        if (minDistance < Double.MAX_VALUE) {
657
                                adjustedPoint = getMapControl().getViewPort().fromMapPoint(
658
                                                gridAdjustedPoint);
659
                                mapAdjustedPoint = gridAdjustedPoint;
660
                        } else {
661
                                mapAdjustedPoint = null;
662
                        }
663
                }
664
                }
665
                Point2D handlerAdjustedPoint = null;
666

    
667
                // Se comprueba el ajuste a los handlers
668
                if (mapAdjustedPoint != null) {
669
                        handlerAdjustedPoint = (Point2D) mapAdjustedPoint.clone(); // getMapControl().getViewPort().toMapPoint(point);
670
                } else {
671
                        handlerAdjustedPoint = getMapControl().getViewPort().toMapPoint(
672
                                        point);
673
                }
674

    
675
                Point2D mapPoint = new Point2D.Double();
676
                double distance = adjustToHandler(handlerAdjustedPoint, mapPoint);
677

    
678
                if (distance < minDistance) {
679
                        bForceCoord = true;
680
                        adjustedPoint = getMapControl().getViewPort().fromMapPoint(mapPoint);
681
                        mapAdjustedPoint = mapPoint;
682
                        minDistance = distance;
683
                }
684

    
685
                // Si no hay ajuste
686
                if (minDistance == Double.MAX_VALUE) {
687
                        adjustedPoint = point;
688
                        mapAdjustedPoint = null;
689
                }
690

    
691
        }
692

    
693
        /*
694
         * (non-Javadoc)
695
         * @see com.iver.cit.gvsig.fmap.tools.Behavior.Behavior#mouseWheelMoved(java.awt.event.MouseWheelEvent)
696
         */
697
        public void mouseWheelMoved(MouseWheelEvent e) throws BehaviorException {
698
        }
699

    
700
        /**
701
         * <p>Process the information written by the user about the next point coordinate, determining
702
         *  the kind of <i>transition</i> according the parameters written.</p>
703
         *
704
         * <p>After, invokes one of the three possible <i>transition</i> methods of the <i>finite machine</i> of
705
         *  edition:
706
         *  <ul>
707
         *   <li><i>First transition type: <b>Point</i></b>: if <code>text</code> matches with any pattern of
708
         *    parameters needed for any kind of point coordinates.<br>
709
         *    There are eight ways of introducing point 2D coordinates:
710
         *    <ul>
711
         *    <li><i>X,Y</i> : absolute cardinal 2D coordinate from the center <i>(0,0)</i> of the CCS <i>Current Coordinate System</i>.</li>
712
         *    <li><i>@X,Y</i> : relative cardinal 2D distances from the last point added of the CCS. If it's the first point of the geometry,
713
         *     works like <i>X,Y</i>.</li>
714
         *    <li><i>length< angle</i> : absolute polar 2D coordinate from the center <i>(0,0)</i> of the CCS <i>Current Coordinate System</i>, using
715
         *     <i>angle</i> from the <i>X</i> axis of CCS, and <i>length</i> far away.</li>
716
         *    <li><i>@length< angle</i> : relative polar 2D coordinate from the last point added of the CCS <i>Current Coordinate System</i>, using
717
         *     <i>angle</i> from the <i>X</i> axis of CCS, and <i>length</i> far away. If it's the first point of the geometry,
718
         *     works like <i>length< angle</i>.</li>
719
         *    <li><i>*X,Y</i> : like <i>X,Y</i> but using UCS <i>Universal Coordinate System</i> as reference.</li>
720
         *    <li><i>@*X,Y</i> : like <i>@X,Y</i> but using UCS <i>Universal Coordinate System</i> as reference.
721
         *      If it's the first point of the geometry, works like <i>*X,Y</i>.</li>
722
         *    <li><i>*length< angle</i> : like <i>length< angle</i> but using UCS <i>Universal Coordinate System</i> as reference.</li>
723
         *    <li><i>@*length< angle</i> : like <i>@length< angle</i> but using UCS <i>Universal Coordinate System</i> as reference.
724
         *      If it's the first point of the geometry, works like <i>*length< angle</i>.</li>
725
         *    </ul>
726
         *   </li>
727
         *   <li><i>Second transition type: <b>Value</i></b>: if recognizes it as a single number.</li>
728
         *   <li><i>Third transition type: <b>Option</i></b>: by default, if can't classify the information as a single number
729
         *    neither as a point. This information will be an <code>String</code> and dealt as an option of the current
730
         *    tool state. Ultimately, if isn't valid, <code>text</code> will be rewritten in the console notifying the user
731
         *    that isn't correct.</li>
732
         *  </ul>
733
         * </p>
734
         *
735
         * @param text command written by user in the edition's console
736
         */
737
        public void textEntered(String text) {
738
                if (text == null) {
739
                        transition(PluginServices.getText(this,"cancel"));
740
                } else {
741
                        /*
742
                         * if ("".equals(text)) { transition("aceptar"); } else {
743
                         */
744
                        text = text.trim();
745
                        int type = ABSOLUTE;
746
                        String[] numbers = new String[1];
747
                        numbers[0] = text;
748
                        if (text.indexOf(",") != -1) {
749

    
750
                                numbers = text.split(",");
751
                                if (numbers[0].substring(0, 1).equals("@")) {
752
                                        numbers[0] = numbers[0].substring(1, numbers[0].length());
753
                                        type = RELATIVE_SCU;
754
                                        if (numbers[0].substring(0, 1).equals("*")) {
755
                                                type = RELATIVE_SCP;
756
                                                numbers[0] = numbers[0].substring(1, numbers[0]
757
                                                                .length());
758
                                        }
759
                                }
760
                        } else if (text.indexOf("<") != -1) {
761
                                type = POLAR_SCP;
762
                                numbers = text.split("<");
763
                                if (numbers[0].substring(0, 1).equals("@")) {
764
                                        numbers[0] = numbers[0].substring(1, numbers[0].length());
765
                                        type = POLAR_SCU;
766
                                        if (numbers[0].substring(0, 1).equals("*")) {
767
                                                type = POLAR_SCP;
768
                                                numbers[0] = numbers[0].substring(1, numbers[0]
769
                                                                .length());
770
                                        }
771
                                }
772
                        }
773

    
774
                        double[] values = null;
775

    
776
                        try {
777
                                if (numbers.length == 2) {
778
                                        // punto
779
                                        values = new double[] { Double.parseDouble(numbers[0]),
780
                                                        Double.parseDouble(numbers[1]) };
781
                                        transition(values, null, type);
782
                                } else if (numbers.length == 1) {
783
                                        // valor
784
                                        values = new double[] { Double.parseDouble(numbers[0]) };
785
                                        transition(values[0]);
786
                                }
787
                        } catch (NumberFormatException e) {
788
                                transition(text);
789
                        } catch (NullPointerException e) {
790
                                transition(text);
791
                        }
792
                        // }
793
                }
794
                getMapControl().repaint();
795
        }
796

    
797
        /**
798
         * If there are options related with the <code>CADTool</code> at the peek of the CAD tool stack,
799
         *  displays them as a popup.
800
         */
801
        public void configureMenu() {
802
                String[] desc = ((CADTool) cadToolStack.peek()).getDescriptions();
803
                // String[] labels = ((CADTool)
804
                // cadToolStack.peek()).getCurrentTransitions();
805
                CADExtension.clearMenu();
806

    
807
                for (int i = 0; i < desc.length; i++) {
808
                        if (desc[i] != null) {
809
                                CADExtension
810
                                                .addMenuEntry(PluginServices.getText(this, desc[i]));// ,
811
                                // labels[i]);
812
                        }
813
                }
814

    
815
        }
816

    
817
        /**
818
         * <p>One of the three kind of transaction methods of the <i>finite machine</i> of
819
         *  edition.</p>
820
         *
821
         * <p>This one deals <code>values</code> as two numbers that, according <code>type</code>
822
         *  calculate a new point 2D in the current layer edited in the associated <code>MapControl</code>.</p>
823
         *
824
         * <p>There are different ways of calculating the new point 2D coordinates, according the value of <code>type</code>, see
825
         *  {@link #textEntered(String) #textEntered(String)}.</p>
826
         *
827
         * <p>After applying the changes, updates the controls available for managing the current data.</p>
828
         *
829
         * @param values numbers needed to calculate the new point coordinates according <code>type</code>
830
         * @param event event which generated this invocation (a <code>MouseEvent</code> or a <code>KeyEvent</code>)
831
         * @param type kind of information that is <code>values</code>. According this parameter, will calculate the
832
         *  new point in a different way
833
         *
834
         * @see CADTool#transition(double, double, InputEvent)
835
         * @see #transition(double)
836
         * @see #transition(String)
837
         */
838
        private void transition(double[] values, InputEvent event, int type) {
839
                questionAsked = true;
840
                if (!cadToolStack.isEmpty()) {
841
                        CADTool ct = (CADTool) cadToolStack.peek();
842

    
843
                        switch (type) {
844
                        case ABSOLUTE:
845
                                ct.transition(values[0], values[1], event);
846
                                previousPoint = values;
847
                                break;
848
                        case RELATIVE_SCU:
849
                                // Comprobar que tenemos almacenado el punto anterior
850
                                // y crear nuevo con coordenadas relativas a ?l.
851
                                double[] auxSCU = values;
852
                                if (previousPoint != null) {
853
                                        auxSCU[0] = previousPoint[0] + values[0];
854
                                        auxSCU[1] = previousPoint[1] + values[1];
855
                                }
856
                                ct.transition(auxSCU[0], auxSCU[1], event);
857

    
858
                                previousPoint = auxSCU;
859
                                break;
860
                        case RELATIVE_SCP:
861
                                // TODO de momento no implementado.
862
                                ct.transition(values[0], values[1], event);
863
                                previousPoint = values;
864
                                break;
865
                        case POLAR_SCU://Relativo
866
                                // Comprobar que tenemos almacenado el punto anterior
867
                                // y crear nuevo con coordenadas relativas a ?l.
868
                                double[] auxPolarSCU = values;
869
                                if (previousPoint != null) {
870
                                        Point2D point = UtilFunctions.getPoint(new Point2D.Double(
871
                                                        previousPoint[0], previousPoint[1]), Math
872
                                                        .toRadians(values[1]), values[0]);
873
                                        auxPolarSCU[0] = point.getX();
874
                                        auxPolarSCU[1] = point.getY();
875
                                        ct.transition(auxPolarSCU[0], auxPolarSCU[1], event);
876
                                } else {
877
                                        Point2D point = UtilFunctions.getPoint(new Point2D.Double(
878
                                                        0, 0), Math.toRadians(values[1]), values[0]);
879
                                        auxPolarSCU[0] = point.getX();
880
                                        auxPolarSCU[1] = point.getY();
881
                                        ct.transition(auxPolarSCU[0], auxPolarSCU[1], event);
882
                                }
883
                                previousPoint = auxPolarSCU;
884
                                break;
885
                        case POLAR_SCP://Absoluto
886
                                double[] auxPolarSCP = values;
887
                                if (previousPoint != null) {
888
                                        Point2D point = UtilFunctions.getPoint(new Point2D.Double(
889
                                                        0, 0),  Math
890
                                                        .toRadians(values[1]), values[0]);
891
                                        auxPolarSCP[0] = point.getX();
892
                                        auxPolarSCP[1] = point.getY();
893
                                        ct.transition(auxPolarSCP[0], auxPolarSCP[1], event);
894
                                } else {
895
                                        Point2D point = UtilFunctions.getPoint(new Point2D.Double(
896
                                                        0, 0), values[1], values[0]);
897
                                        auxPolarSCP[0] = point.getX();
898
                                        auxPolarSCP[1] = point.getY();
899
                                        ct.transition(auxPolarSCP[0], auxPolarSCP[1], event);
900
                                }
901
                                previousPoint = auxPolarSCP;
902
                                break;
903
                        default:
904
                                break;
905
                        }
906
                        askQuestion();
907
                }
908
                configureMenu();
909
                PluginServices.getMainFrame().enableControls();
910
        }
911

    
912
        /**
913
         * <p>One of the three kind of transaction methods of the <i>finite machine</i> of
914
         *  edition.</p>
915
         *
916
         * <p>This one deals <code>value</code> as a single number used as a parameter for the current
917
         *    tool state. Ultimately, if isn't valid, <code>number</code> will be rewritten in the
918
         *    console notifying the user that isn't correct.</p>
919
         *
920
         * <p>After applying the changes, updates the controls available for managing the current data.</p>
921
         *
922
         * @param value value for the current tool state
923
         *
924
         * @see CADTool#transition(double)
925
         * @see #transition(double[], InputEvent, int)
926
         * @see #transition(String)
927
         */
928
        private void transition(double value) {
929
                questionAsked = true;
930
                if (!cadToolStack.isEmpty()) {
931
                        CADTool ct = (CADTool) cadToolStack.peek();
932
                        ct.transition(value);
933
                        askQuestion();
934
                }
935
                configureMenu();
936
                PluginServices.getMainFrame().enableControls();
937
        }
938

    
939
        /**
940
         * <p>One of the three kind of transaction methods of the <i>finite machine</i> of
941
         *  edition.</p>
942
         *
943
         * <p>This one deals <code>option</code> as an option of the current
944
         *    tool state. Ultimately, if isn't valid, <code>option</code> will be rewritten in the
945
         *    console notifying the user that isn't correct.</p>
946
         *
947
         * @param option option for the current tool state
948
         *
949
         * @see CADTool#transition(String)
950
         * @see #transition(double[], InputEvent, int)
951
         * @see #transition(double)
952
         */
953
        public void transition(String option) {
954
                questionAsked = true;
955
                if (!cadToolStack.isEmpty()) {
956
                        CADTool ct = (CADTool) cadToolStack.peek();
957
                        try {
958
                                ct.transition(option);
959
                        } catch (Exception e) {
960
                                IWindow window = PluginServices.getMDIManager().getActiveWindow();
961

    
962
                                if (window instanceof View) {
963
                                        ((View)window).getConsolePanel().addText(
964
                                                        "\n" + PluginServices.getText(this, "incorrect_option")
965
                                                        + " : " + option, JConsole.ERROR);
966
                                }
967
                        }
968
                        askQuestion();
969
                }
970
                configureMenu();
971
                PluginServices.getMainFrame().enableControls();
972
        }
973

    
974
        /**
975
         * Shows or hides a grid on the <code>ViewPort</code> of the associated <code>MapControl</code>.
976
         *
977
         * @param value <code>true</code> to make the grid visible; <code>false</code> to make it invisible
978
         */
979
        public void setGridVisibility(boolean value) {
980
                getGrid().setShowGrid(value);
981
                if (getMapControl()!=null){
982
                        getGrid().setViewPort(getMapControl().getViewPort());
983
                        getMapControl().repaint();
984
                }
985
        }
986

    
987
        /**
988
         * Sets the snap tools enabled or disabled.
989
         *
990
         * @param activated <code>true</code> to enable the snap tools; <code>false</code> to disable them
991
         *
992
         * @see #isRefentEnabled()
993
         */
994
        public void setRefentEnabled(boolean activated) {
995
                bRefent = activated;
996
        }
997

    
998
        /**
999
         * Determines if snap tools are enabled or disabled.
1000
         *
1001
         * @return <code>true</code> to enable the snap tools; <code>false</code> to disable them
1002
         *
1003
         * @see #setRefentEnabled(boolean)
1004
         */
1005
        public boolean isRefentEnabled()
1006
        {
1007
                return bRefent;
1008
        }
1009

    
1010
        /*
1011
         * (non-Javadoc)
1012
         * @see com.iver.cit.gvsig.fmap.tools.Behavior.Behavior#getListener()
1013
         */
1014
        public ToolListener getListener() {
1015
                return new ToolListener() {
1016
                        /**
1017
                         * @see com.iver.cit.gvsig.fmap.tools.Listeners.ToolListener#getCursor()
1018
                         */
1019
                        public Cursor getCursor() {
1020
                                return null;
1021
                        }
1022

    
1023
                        /**
1024
                         * @see com.iver.cit.gvsig.fmap.tools.Listeners.ToolListener#cancelDrawing()
1025
                         */
1026
                        public boolean cancelDrawing() {
1027
                                return false;
1028
                        }
1029
                };
1030
        }
1031

    
1032
        /**
1033
         * Returns the {@link CADTool CADTool} at the top of the stack without removing it from the CAD tool stack.
1034
         *
1035
         * @return the {@link CADTool CADTool} at the top of the stack
1036
         *
1037
         * @see #pushCadTool(CADTool)
1038
         * @see #popCadTool()
1039
         * @see #setCadTool(CADTool)
1040
         */
1041
        public CADTool getCadTool() {
1042
                if (cadToolStack.isEmpty())
1043
                        return null;
1044
                return (CADTool) cadToolStack.peek();
1045
        }
1046

    
1047
        /**
1048
         * <p>Pushes a {@link CADTool CADTool} onto the top of the CAD tool stack, and sets it as current.</p>
1049
         *
1050
         * @param cadTool CAD tool to enable as current
1051
         *
1052
         * @see #getCadTool()
1053
         * @see #popCadTool()
1054
         * @see #setCadTool(CADTool)
1055
         */
1056
        public void pushCadTool(CADTool cadTool) {
1057
                cadToolStack.push(cadTool);
1058
                cadTool.setCadToolAdapter(this);
1059
                // cadTool.initializeStatus();
1060
                // cadTool.setVectorialAdapter(vea);
1061
                /*
1062
                 * int ret = cadTool.transition(null, editableFeatureSource, selection,
1063
                 * new double[0]);
1064
                 *
1065
                 * if ((ret & Automaton.AUTOMATON_FINISHED) ==
1066
                 * Automaton.AUTOMATON_FINISHED) { popCadTool();
1067
                 *
1068
                 * if (cadToolStack.isEmpty()) { pushCadTool(new
1069
                 * com.iver.cit.gvsig.gui.cad.smc.gen.CADTool());//new
1070
                 * SelectionCadTool());
1071
                 * PluginServices.getMainFrame().setSelectedTool("selection"); }
1072
                 *
1073
                 * askQuestion();
1074
                 *
1075
                 * getMapControl().drawMap(false); }
1076
                 */
1077
        }
1078

    
1079
        /**
1080
         * Removes the peek of the CAD tool stack.
1081
         *
1082
         * @see #pushCadTool(CADTool)
1083
         * @see #getCadTool()
1084
         * @see #setCadTool(CADTool)
1085
         */
1086
        public void popCadTool() {
1087
                cadToolStack.pop();
1088
        }
1089

    
1090
        /**
1091
         * <p>Displays at the console associated to the current active view that's being edited, the question of the following
1092
         *  operation that user can do with the current <code>CADTool</code>, only if it hasn't just answered.</p>
1093
         *
1094
         * <p>The format of the question will be according the following pattern:<br>
1095
         *   "\n#"<i>{cadtool at CAD tool stack peek}</i>.getQuestion()">"
1096
         * </p>
1097
         */
1098
        public void askQuestion() {
1099
                CADTool cadtool = (CADTool) cadToolStack.peek();
1100
                /*
1101
                 * if (cadtool..getStatus()==0){
1102
                 * PluginServices.getMainFrame().addTextToConsole("\n"
1103
                 * +cadtool.getName()); }
1104
                 */
1105
                if (PluginServices.getMDIManager().getActiveWindow() instanceof View)
1106
                {
1107
                        View vista = (View) PluginServices.getMDIManager().getActiveWindow();
1108
                        String question=cadtool.getQuestion();
1109
                        if (lastQuestion==null || !(lastQuestion.equals(question)) || questionAsked) {
1110
                        vista.getConsolePanel().addText(
1111
                                        "\n" + "#" + question + " > ", JConsole.MESSAGE);
1112
                        // ***PluginServices.getMainFrame().addTextToConsole("\n" +
1113
                        // cadtool.getQuestion());
1114
                        questionAsked = false;
1115
                        }
1116
                        lastQuestion=question;
1117
                }
1118

    
1119
        }
1120

    
1121
        /**
1122
         * Empties the CAD tools stack and pushes <code>cadTool</code> in it.
1123
         *
1124
         * @param cadTool CAD tool to set at the peek of the stack
1125
         *
1126
         * @see #pushCadTool(CADTool)
1127
         * @see #popCadTool()
1128
         * @see #getCadTool()
1129
         */
1130
        public void setCadTool(CADTool cadTool) {
1131
                cadToolStack.clear();
1132
                pushCadTool(cadTool);
1133
                // askQuestion();
1134
        }
1135

    
1136
        /**
1137
         * <p>Removes all geometries selected in the associated <code>MapControl</code>.
1138
         */
1139
        public void delete() {
1140
                ILayerEdited aux = CADExtension.getEditionManager().getActiveLayerEdited();
1141
                if (!(aux instanceof VectorialLayerEdited))
1142
                        return;
1143
                VectorialLayerEdited vle = (VectorialLayerEdited) aux;
1144
                VectorialEditableAdapter vea = vle.getVEA();
1145

    
1146
                vea.startComplexRow();
1147
                try {
1148
                        FBitSet selection = vea.getSelection();
1149
                        int[] indexesToDel = new int[selection.cardinality()];
1150
                        int j = 0;
1151
                        for (int i = selection.nextSetBit(0); i >= 0; i = selection
1152
                                        .nextSetBit(i + 1)) {
1153
                                indexesToDel[j++] = i;
1154
                                // /vea.removeRow(i);
1155
                        }
1156

    
1157
//                          ArrayList selectedRow = vle.getSelectedRow();
1158
//
1159
//                          int[] indexesToDel = new int[selectedRow.size()];
1160
//                          for (int i = 0;i < selectedRow.size(); i++) {
1161
//                                  IRowEdited edRow = (IRowEdited) selectedRow.get(i);
1162
//                                  indexesToDel[i] = vea.getInversedIndex(edRow.getIndex());
1163
//                                  }
1164
//
1165
                        for (int i = indexesToDel.length - 1; i >= 0; i--) {
1166
                                vea.removeRow(indexesToDel[i], PluginServices.getText(this,
1167
                                                "deleted_feature"),EditionEvent.GRAPHIC);
1168
                        }
1169
                        System.out.println("clear Selection");
1170
                        selection.clear();
1171
                        vle.clearSelection(VectorialLayerEdited.NOTSAVEPREVIOUS);
1172
                } catch (ReadDriverException e) {
1173
                        NotificationManager.addError(e.getMessage(),e);
1174
                } finally {
1175
                        String description=PluginServices.getText(this,"remove_geometry");
1176
                        vea.endComplexRow(description);
1177
                }
1178

    
1179

    
1180
                /*
1181
                 * if (getCadTool() instanceof SelectionCADTool) { SelectionCADTool
1182
                 * selTool = (SelectionCADTool) getCadTool(); selTool.clearSelection(); }
1183
                 */
1184
                refreshEditedLayer();
1185
        }
1186

    
1187
        /**
1188
         * @see CADGrid#setAdjustGrid(boolean)
1189
         */
1190
        public void setAdjustGrid(boolean b) {
1191
                getGrid().setAdjustGrid(b);
1192
        }
1193

    
1194
        /**
1195
         * <p>Responds to actions of writing common key commands for all kind of CAD operations, enabling/disabling after
1196
         *  the controls to manage the available information according the tool selected:
1197
         *  <ul>
1198
         *   <li><i>eliminar</i>: removes the geometries that are now selected.</li>
1199
         *   <li><i>escape</i>: executes different actions according to the current CAD tool of the associated <code>MapControl</code>:
1200
         *    <ul>
1201
         *     <li>If the tool enabled is identified by <i>cadtooladapter</i>: empties the CAD tools stack, changing the current tool by
1202
         *      a {@link SelectionCADTool SelectionCADTool}, which is identified by <i>_selection</i> and allows select features of the
1203
         *      active vector layer of the associated <code>MapControl</code> instance. </li>
1204
         *     <li>Otherwise, that means current associated <code>MapControl</code> instance isn't identified by "<i>cadtooladapter</i>",
1205
         *      changes the enabled tool by the previous.</li>
1206
         *    </ul>
1207
         *   </li>
1208
         *  </ul>
1209
         * </p>
1210
         *
1211
         * @param actionCommand identifier of the key action command executed by the user
1212
         *
1213
         * @see SelectionCADTool
1214
         * @see MapControl#setPrevTool()
1215
         */
1216
        public void keyPressed(String actionCommand) {
1217
                if (CADExtension.getEditionManager().getActiveLayerEdited()== null) {
1218
                        return;
1219
                }
1220
                if (actionCommand.equals("eliminar")) {
1221
                        delete();
1222
                } else if (actionCommand.equals("escape")) {
1223
                        if (getMapControl().getCurrentTool().equals("cadtooladapter")) {
1224
                                CADTool ct = (CADTool) cadToolStack.peek();
1225
                                ct.end();
1226
                                cadToolStack.clear();
1227
                                SelectionCADTool selCad = new SelectionCADTool();
1228
                                selCad.init();
1229
                                VectorialLayerEdited vle = (VectorialLayerEdited) CADExtension
1230
                                                .getEditionManager().getActiveLayerEdited();
1231
                                try {
1232
                                        vle.clearSelection(VectorialLayerEdited.NOTSAVEPREVIOUS);
1233
                                } catch (ReadDriverException e) {
1234
                                        NotificationManager.addError(e.getMessage(),e);
1235
                                }
1236

    
1237
                                pushCadTool(selCad);
1238
                                // getVectorialAdapter().getSelection().clear();
1239

    
1240
                                refreshEditedLayer();
1241

    
1242

    
1243
                                PluginServices.getMainFrame().setSelectedTool("_selection");
1244
                                // askQuestion();
1245
                        } else {
1246
                                getMapControl().setPrevTool();
1247
                        }
1248
                }
1249

    
1250
                PluginServices.getMainFrame().enableControls();
1251

    
1252
        }
1253

    
1254
        /**
1255
         * <p>Applies a lightweight repaint of the active layer being edited.</p>
1256
         *
1257
         * <p>All layers under it won't be drawn, only the upper one and whose are over that layer in the TOC.</p>
1258
         *
1259
         * @see MapControl#rePaintDirtyLayers()
1260
         */
1261
        public void refreshEditedLayer()
1262
        {
1263
                ILayerEdited edLayer = CADExtension.getEditionManager().getActiveLayerEdited();
1264
                if (edLayer != null)
1265
                {
1266
//                        edLayer.getLayer().setDirty(true);
1267
                        getMapControl().rePaintDirtyLayers();
1268
                }
1269

    
1270
        }
1271

    
1272
        /**
1273
         * Gets the {@link CADGrid CADGrid} that can be drawn on the <code>ViewPort</code> of the associated <code>MapControl</code>.
1274
         *
1275
         * @return reference to the <i>grid</i> that can be applied on the <code>ViewPort</code>
1276
         *
1277
         * @see #setGridVisibility(boolean)
1278
         */
1279
        public CADGrid getGrid() {
1280
                return cadgrid;
1281
        }
1282

    
1283
        /**
1284
         * Determines if is enabled or not the <i>orto</i> mode.
1285
         *
1286
         * @return <code>true</code> if is enabled the <i>orto</i> mode; otherwise <code>false</code>
1287
         *
1288
         * @see #setOrtoMode(boolean)
1289
         */
1290
        public boolean isOrtoMode() {
1291
                return bOrtoMode;
1292
        }
1293

    
1294
        /**
1295
         * Enables / disables the <i>orto</i> mode.
1296
         *
1297
         * @param b the desired value
1298
         *
1299
         * @see #isOrtoMode()
1300
         */
1301
        public void setOrtoMode(boolean b) {
1302
                bOrtoMode = b;
1303
        }
1304

    
1305
        /**
1306
         * Associates and stores the specified name with the specified {@link CADTool CADTool}.
1307
         *
1308
         * @param name name of the tool
1309
         * @param c CAD tool to interactuate editing the layers
1310
         *
1311
         * @see #getCADTools()
1312
         * @see #getCADTool(String)
1313
         */
1314
        public static void addCADTool(String name, CADTool c) {
1315
                namesCadTools.put(name, c);
1316

    
1317
        }
1318

    
1319
        /**
1320
         * Gets all CAD tools available to edit layers with this tool listener.
1321
         *
1322
         * @return CAD tools available to edit layers with this tool listener
1323
         *
1324
         * @see #addCADTool(String, CADTool)
1325
         * @see #getCADTool(String)
1326
         */
1327
        public static CADTool[] getCADTools() {
1328
                return (CADTool[]) CADToolAdapter.namesCadTools.values().toArray(new CADTool[0]);
1329
        }
1330

    
1331
        /**
1332
         * Returns the {@link CADTool CADTool} to which the specified name is mapped.
1333
         *
1334
         * @param text name of the tool
1335
         * @return the CAD tool whose associated name is to be returned
1336
         *
1337
         * @see #addCADTool(String, CADTool)
1338
         * @see #getCADTools()
1339
         */
1340
        public CADTool getCADTool(String text) {
1341
                CADTool ct = (CADTool) namesCadTools.get(text);
1342
                return ct;
1343
        }
1344

    
1345
        /**
1346
         * Gets the object used to manage the edition of the layers of the associated <code>MapControl</code>.
1347
         *
1348
         * @see EditionManager
1349
         *
1350
         * @return object used to manage the edition of the layers
1351
         */
1352
        public EditionManager getEditionManager() {
1353
                return editionManager;
1354
        }
1355

    
1356
        /**
1357
         * <p>Initializes the <i>flatness</i> with the defined in preferences.</p>
1358
         *
1359
         * <p>The <i>flatness</i> is the maximum tolerance used to approximate curved lines in a <i>shape</i> by polylines.</p>
1360
         * <p>The shapes doesn't support primitive like arcs neither other curved lines to draw their geometries, then for drawing any
1361
         *  kind of this geometries the curved lines are drawn approximately by a polyline. And for doing more realistic that curves,
1362
         *  is used the <i>flatness</i> parameter, that indicates that the difference between each arc and the straight segment that
1363
         *  approximates it must be in the worse case, like the <i>flatness</i>.</p>
1364
         *
1365
         * @see FConverter#FLATNESS
1366
         */
1367
        public void initializeFlatness() {
1368
                if (!flatnessInitialized){
1369
                        flatnessInitialized=true;
1370
                        Preferences prefs = Preferences.userRoot().node( "cadtooladapter" );
1371
                        double flatness = prefs.getDouble("flatness",FConverter.FLATNESS);
1372
                        FConverter.FLATNESS=flatness;
1373
                }
1374
        }
1375

    
1376
        /**
1377
         * <p>Updates the grid on the <code>ViewPort</code> of the associated <code>MapControl</code>
1378
         *  object according the values in the {@link com.iver.cit.gvsig.gui.cad.CADToolAdapter.prefs.Preferences com.iver.cit.gvsig.gui.cad.CADToolAdapter.prefs.Preferences}.</p>
1379
         *
1380
         * <p>The preferences are:
1381
         *  <ul>
1382
         *   <li>Show/hide the grid.</li>
1383
         *   <li>Adjust or not the grid.</li>
1384
         *   <li>Horizontal ( X ) line separation.</li>
1385
         *   <li>Vertical ( Y ) line separation.</li>
1386
         *  </ul>
1387
         * </p>
1388
         */
1389
        public void initializeGrid(){
1390
                boolean showGrid = prefs.getBoolean("grid.showgrid",getGrid().isShowGrid());
1391
                boolean adjustGrid = prefs.getBoolean("grid.adjustgrid",getGrid().isAdjustGrid());
1392

    
1393
                double dx = prefs.getDouble("grid.distancex",getGrid().getGridSizeX());
1394
                double dy = prefs.getDouble("grid.distancey",getGrid().getGridSizeY());
1395

    
1396
                setGridVisibility(showGrid);
1397
                setAdjustGrid(adjustGrid);
1398
                getGrid().setGridSizeX(dx);
1399
                getGrid().setGridSizeY(dy);
1400
        }
1401

    
1402
        /**
1403
         * <p>Returns the type of the shape that's the current active and vector layer being edited.</p>
1404
         *
1405
         * @see FLyrVect#getShapeType()
1406
         *
1407
         * @return type of the shape that's the current active and vector layer being edited
1408
         */
1409
        public int getActiveLayerType() {
1410
                int type=FShape.MULTI;
1411
                try {
1412
                        type=((FLyrVect)CADExtension.getEditionManager().getActiveLayerEdited().getLayer()).getShapeType();
1413
                } catch (ReadDriverException e) {
1414
                        NotificationManager.addError(e);
1415
                }
1416
                return type;
1417
        }
1418
}