Statistics
| Revision:

svn-gvsig-desktop / trunk / extensions / extCAD / src / com / iver / cit / gvsig / gui / cad / CADToolAdapter.java @ 20894

History | View | Annotate | Download (46.5 KB)

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

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

    
22
import org.cresques.cts.IProjection;
23

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

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

    
121
        /**
122
         * Reference to the object used to manage the edition of the layers of the associated <code>MapControl</code>.
123
         * 
124
         * @see EditionManager
125
         * @see #getEditionManager()
126
         */
127
        private EditionManager editionManager = new EditionManager();
128

    
129
        /**
130
         * Identifies that the data are absolute coordinates of the new point from the (0, 0) position.
131
         */
132
        public static final int ABSOLUTE = 0;
133

    
134
        /**
135
         * Equivalent to {@link CADToolAdapter#ABSOLUTE CADToolAdapter#ABSOLUTE}.
136
         */
137
        public static final int RELATIVE_SCP = 1;
138

    
139
        /**
140
         * Identifies that the data are relative distances of the new point from the previous introduced.
141
         */
142
        public static final int RELATIVE_SCU = 2;
143

    
144
        /**
145
         * Identifies that the data are relative polar distances (longitude of the line and angle given in degrees)
146
         *  of the new point from the previous introduced.
147
         */
148
        public static final int POLAR_SCP = 3;
149

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

    
156
        /**
157
         * Stores the 2D map coordinates of the last point added.
158
         */
159
        private double[] previousPoint = null;
160

    
161
        /**
162
         * <i>Stack with CAD tools.</i>
163
         * 
164
         * <i>For each CAD tool we use, the last item added in this stack will
165
         *  display a different icon according to the current operation and its status.</i> 
166
         */
167
        private Stack cadToolStack = new Stack();
168

    
169
        /**
170
         * X coordinate of the last dragging or moving mouse event.
171
         */
172
        private int lastX;
173

    
174
        /**
175
         * Y coordinate of the last dragging or moving mouse event.
176
         */
177
        private int lastY;
178

    
179
        /**
180
         * Unused attribute.
181
         */
182
        private ISymbol symbol = SymbologyFactory.createDefaultSymbolByShapeType(FConstant.SYMBOL_TYPE_POINT, Color.RED);
183

    
184
        /**
185
         * Represents the cursor's point selected in <i>map coordinates</i>.
186
         * 
187
         * @see MapControl#toMapPoint
188
         */
189
        private Point2D mapAdjustedPoint;
190

    
191
        /**
192
         * Kind of geometry drawn to identify the kind of control point selected by the cursor's mouse.
193
         */
194
        private ISnapper usedSnap = null;
195

    
196
        /**
197
         * Determines if has displayed at the edition console, the question for the operations that can do
198
         *  the user with the current CAD tool, in its current state.
199
         */
200
        private boolean questionAsked = false;
201

    
202
        /**
203
         * Represents the cursor's point selected in <i>screen coordinates</i>.
204
         *
205
         * @see ViewPort#fromMapPoint(Point2D)
206
         */
207
        private Point2D adjustedPoint;
208

    
209
        /**
210
         * Determines if the snap tools are enabled or disabled.
211
         * 
212
         * @see #isRefentEnabled()
213
         * @see #setRefentEnabled(boolean)
214
         */
215
        private boolean bRefent = true;
216

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

    
226
        /**
227
         * Optional grid that could be applied on the <code>MapControl</code>'s view port.
228
         * 
229
         * @see #getGrid()
230
         * @see #setAdjustGrid(boolean)
231
         */
232
        private CADGrid cadgrid = new CADGrid();
233

    
234
        /**
235
         * Determines is is enabled or not the <i>Orto</i> mode.
236
         */
237
        private boolean bOrtoMode;
238

    
239
        /**
240
         * A light yellow color for the tool tip text box associated to the point indicated by the mouse's cursor.
241
         */
242
        private Color theTipColor = new Color(255, 255, 155);
243

    
244
        /**
245
         * Last question asked to the user in the CAD console.
246
         */
247
        private Object lastQuestion;
248

    
249
        /**
250
         * Maximum tolerance in the approximation of a curved line by a polyline.
251
         * 
252
         * @see #initializeFlatness()
253
         */
254
        private static boolean flatnessInitialized=false;
255

    
256
        /**
257
         * Edition preferences.
258
         */
259
        private static Preferences prefs = Preferences.userRoot().node( "cadtooladapter" );
260
        
261
        /**
262
         * Listener to display the coordinates in the current application's status bar.
263
         */
264
        private StatusBarListener sbl=null;
265

    
266
        /*
267
         * (non-Javadoc)
268
         * @see com.iver.cit.gvsig.fmap.tools.Behavior.Behavior#setMapControl(com.iver.cit.gvsig.fmap.MapControl)
269
         */
270
        public void setMapControl(MapControl mc) {
271
                super.setMapControl(mc);
272
                sbl=new StatusBarListener(getMapControl());
273
        }
274

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

    
286
                if (adjustedPoint != null) {
287
                        Point2D p = null;
288
                        if (mapAdjustedPoint != null) {
289
                                p = mapAdjustedPoint;
290
                        } else {
291
                                p = getMapControl().getViewPort().toMapPoint(adjustedPoint);
292
                        }
293

    
294
                        ((CADTool) cadToolStack.peek())
295
                                        .drawOperation(g, p.getX(), p.getY());
296
                }
297
                drawCursor(g);
298
                getGrid().drawGrid(g);
299
        }
300

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

    
324
                                if (mapAdjustedPoint != null) {
325
                                        p = mapAdjustedPoint;
326
                                } else {
327
                                        p = vp.toMapPoint(adjustedPoint);
328
                                }
329
                                ct.endTransition(p.getX(), p.getY(), e);
330
                                previousPoint = new double[]{p.getX(),p.getY()};
331
                        }
332
                }
333
        }
334

    
335
        /*
336
         * (non-Javadoc)
337
         * @see com.iver.cit.gvsig.fmap.tools.Behavior.Behavior#mouseEntered(java.awt.event.MouseEvent)
338
         */
339
        public void mouseEntered(MouseEvent e) throws BehaviorException {
340
                clearMouseImage();
341
        }
342

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

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

    
361
                        if (mapAdjustedPoint != null) {
362
                                p = mapAdjustedPoint;
363
                        } else {
364
                                p = vp.toMapPoint(adjustedPoint);
365
                        }
366
                        transition(new double[] { p.getX(), p.getY() }, e, ABSOLUTE);
367
                }
368
        }
369

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

    
386
                if (!isRefentEnabled())
387
                        return Double.MAX_VALUE;
388

    
389
                ILayerEdited aux = CADExtension.getEditionManager().getActiveLayerEdited();
390
                if (!(aux instanceof VectorialLayerEdited))
391
                        return Double.MAX_VALUE;
392
                VectorialLayerEdited vle = (VectorialLayerEdited) aux;
393

    
394
                ArrayList snappers = vle.getSnappers();
395
                ArrayList layersToSnap = vle.getLayersToSnap();
396

    
397

    
398
                ViewPort vp = getMapControl().getViewPort();
399

    
400
                snappers=SnapConfigPage.getActivesSnappers();
401

    
402
                double mapTolerance = vp.toMapDistance(SelectionCADTool.tolerance);
403
                double minDist = mapTolerance;
404
//                double rw = getMapControl().getViewPort().toMapDistance(5);
405
                Point2D mapPoint = point;
406
                Rectangle2D r = new Rectangle2D.Double(mapPoint.getX() - mapTolerance / 2,
407
                                mapPoint.getY() - mapTolerance / 2, mapTolerance, mapTolerance);
408

    
409
                Envelope e = FConverter.convertRectangle2DtoEnvelope(r);
410

    
411
                usedSnap = null;
412
                Point2D lastPoint = null;
413
                if (previousPoint != null)
414
                {
415
                        lastPoint = new Point2D.Double(previousPoint[0], previousPoint[1]);
416
                }
417
                for (int j = 0; j < layersToSnap.size(); j++)
418
                {
419
                        FLyrVect lyrVect = (FLyrVect) layersToSnap.get(j);
420
                        SpatialCache cache = lyrVect.getSpatialCache();
421
                        if (lyrVect.isVisible())
422
                        {
423
                                // La lista de snappers est? siempre ordenada por prioridad. Los de mayor
424
                                // prioridad est?n primero.
425
                                for (int i = 0; i < snappers.size(); i++)
426
                                {
427
                                        ISnapper theSnapper = (ISnapper) snappers.get(i);
428

    
429
                                        if (usedSnap != null)
430
                                        {
431
                                                // Si ya tenemos un snap y es de alta prioridad, cogemos ese. (A no ser que en otra capa encontremos un snapper mejor)
432
                                                if (theSnapper.getPriority() < usedSnap.getPriority())
433
                                                        break;
434
                                        }
435
                                        SnappingVisitor snapVisitor = null;
436
                                        Point2D theSnappedPoint = null;
437

    
438
                                        if (theSnapper instanceof ISnapperVectorial)
439
                                        {
440
                                                if (theSnapper instanceof ISnapperGeometriesVectorial) {
441
                                                        snapVisitor=new GeometriesSnappingVisitor((ISnapperGeometriesVectorial) theSnapper,point,mapTolerance,lastPoint);
442
                                                }else {
443
                                                        snapVisitor = new SnappingVisitor((ISnapperVectorial) theSnapper, point, mapTolerance, lastPoint);
444
                                                }
445
                                                // System.out.println("Cache size = " + cache.size());
446
                                                cache.query(e, snapVisitor);
447
                                                theSnappedPoint = snapVisitor.getSnapPoint();
448

    
449
                                        }
450
                                        if (theSnapper instanceof ISnapperRaster)
451
                                        {
452
                                                ISnapperRaster snapRaster = (ISnapperRaster) theSnapper;
453
                                                theSnappedPoint = snapRaster.getSnapPoint(getMapControl(), point, mapTolerance, lastPoint);
454
                                        }
455

    
456

    
457
                                        if (theSnappedPoint != null) {
458
                                                double distAux = theSnappedPoint.distance(point);
459
                                                if (minDist > distAux)
460
                                                {
461
                                                        minDist = distAux;
462
                                                        usedSnap = theSnapper;
463
                                                        mapHandlerAdjustedPoint.setLocation(theSnappedPoint);
464
                                                }
465
                                        }
466
                                }
467
                        } // visible
468
                }
469
                if (usedSnap != null)
470
                        return minDist;
471
                return Double.MAX_VALUE;
472

    
473
        }
474

    
475
        /*
476
         * (non-Javadoc)
477
         * @see com.iver.cit.gvsig.fmap.tools.Behavior.Behavior#mouseReleased(java.awt.event.MouseEvent)
478
         */
479
        public void mouseReleased(MouseEvent e) throws BehaviorException {
480
                getMapControl().repaint();
481
        }
482

    
483
        /*
484
         * (non-Javadoc)
485
         * @see com.iver.cit.gvsig.fmap.tools.Behavior.Behavior#mouseDragged(java.awt.event.MouseEvent)
486
         */
487
        public void mouseDragged(MouseEvent e) throws BehaviorException {
488
                lastX = e.getX();
489
                lastY = e.getY();
490

    
491
                calculateSnapPoint(e.getPoint());
492
        }
493

    
494
        /*
495
         * (non-Javadoc)
496
         * @see com.iver.cit.gvsig.fmap.tools.Behavior.Behavior#mouseMoved(java.awt.event.MouseEvent)
497
         */
498
        public void mouseMoved(MouseEvent e) throws BehaviorException {
499

    
500
                lastX = e.getX();
501
                lastY = e.getY();
502

    
503
                calculateSnapPoint(e.getPoint());
504

    
505
                showCoords(e.getPoint());
506

    
507
                getMapControl().repaint();
508
        }
509

    
510
        /**
511
         * Displays the current coordinates of the mouse's cursor on the associated <code>MapControl</code>
512
         *  object, at the status bar of the application's main frame.
513
         * 
514
         * @param pPix current 2D mouse's cursor coordinates on the <code>MapControl</code>
515
         */
516
        private void showCoords(Point2D pPix)
517
        {
518
                String[] axisText = new String[2];
519
                axisText[0] = "X = ";
520
                axisText[1] = "Y = ";
521
//                NumberFormat nf = NumberFormat.getInstance();
522
                MapControl mapControl = getMapControl();
523
                ViewPort vp = mapControl.getMapContext().getViewPort();
524
                IProjection iProj = vp.getProjection();
525

    
526
//                if (iProj.getAbrev().equals("EPSG:4326") || iProj.getAbrev().equals("EPSG:4230")) {
527
//                        axisText[0] = "Lon = ";
528
//                        axisText[1] = "Lat = ";
529
//                        nf.setMaximumFractionDigits(8);
530
//                } else {
531
//                        axisText[0] = "X = ";
532
//                        axisText[1] = "Y = ";
533
//                        nf.setMaximumFractionDigits(2);
534
//                }
535
                Point2D p;
536
                if (mapAdjustedPoint == null)
537
                {
538
                        p = vp.toMapPoint(pPix);
539
                }
540
                else
541
                {
542
                        p = mapAdjustedPoint;
543
                }
544
                sbl.setFractionDigits(p);
545
                axisText = sbl.setCoorDisplayText(axisText);
546
                MainFrame mF = PluginServices.getMainFrame();
547

    
548
                if (mF != null)
549
                {
550
            mF.getStatusBar().setMessage("units",
551
                            PluginServices.getText(this, FConstant.NAMES[vp.getDistanceUnits()]));
552
            mF.getStatusBar().setControlValue("scale",String.valueOf(mapControl.getMapContext().getScaleView()));
553
                        mF.getStatusBar().setMessage("projection", iProj.getAbrev());
554

    
555
                        String[] coords=sbl.getCoords(p);
556
                        mF.getStatusBar().setMessage("x",
557
                                        axisText[0] + coords[0]);
558
                        mF.getStatusBar().setMessage("y",
559
                                        axisText[1] + coords[1]);
560
                }
561
        }
562

    
563
        /**
564
         * Hides the mouse's cursor.
565
         */
566
        private void clearMouseImage() {
567
                int[] pixels = new int[16 * 16];
568
                Image image = Toolkit.getDefaultToolkit().createImage(
569
                                new MemoryImageSource(16, 16, pixels, 0, 16));
570
                Cursor transparentCursor = Toolkit.getDefaultToolkit()
571
                                .createCustomCursor(image, new Point(0, 0), "invisiblecursor");
572

    
573
                getMapControl().setCursor(transparentCursor);
574
        }
575

    
576
        /**
577
         * <p>Draws a 31x31 pixels cross round the mouse's cursor with an small geometry centered:
578
         *  <ul>
579
         *   <li><i>an square centered</i>: if isn't over a <i>control point</i>.
580
         *   <li><i>an small geometry centered according to the kind of control point</i>: if it's over a control
581
         *    point. In this case, the small geometry is drawn by a {@link ISnapper ISnapper} type object.<br>
582
         *    On the other hand, a light-yellowed background tool tip text with the type of <i>control point</i> will
583
         *     be displayed.</li>
584
         * </p> 
585
         *
586
         * @param g <code>MapControl</code>'s graphics where the data will be drawn
587
         */
588
        private void drawCursor(Graphics g) {
589
                g.setColor(Color.black);
590
                Point2D p = adjustedPoint;
591

    
592
                if (p == null) {
593
                        getGrid().setViewPort(getMapControl().getViewPort());
594

    
595
                        return;
596
                }
597

    
598
                int size1 = 15;
599
                int size2 = 3;
600
                g.drawLine((int) (p.getX() - size1), (int) (p.getY()),
601
                                (int) (p.getX() + size1), (int) (p.getY()));
602
                g.drawLine((int) (p.getX()), (int) (p.getY() - size1),
603
                                (int) (p.getX()), (int) (p.getY() + size1));
604

    
605
                // getMapControl().setToolTipText(null);
606
                if (adjustedPoint != null) {
607
                        if (bForceCoord) {
608
                                /* g.setColor(Color.ORANGE);
609
                                g.drawRect((int) (adjustedPoint.getX() - 6),
610
                                                (int) (adjustedPoint.getY() - 6), 12, 12);
611
                                g.drawRect((int) (adjustedPoint.getX() - 3),
612
                                                (int) (adjustedPoint.getY() - 3), 6, 6);
613
                                g.setColor(Color.MAGENTA);
614
                                g.drawRect((int) (adjustedPoint.getX() - 4),
615
                                                (int) (adjustedPoint.getY() - 4), 8, 8); */
616
                                if (usedSnap != null)
617
                                {
618
                                        usedSnap.draw(g, adjustedPoint);
619

    
620
                                        Graphics2D g2 = (Graphics2D) g;
621
                                FontMetrics metrics = g2.getFontMetrics();
622
                                int w = metrics.stringWidth(usedSnap.getToolTipText()) + 5;
623
                                int h = metrics.getMaxAscent() + 5;
624
                                int x = (int)p.getX()+9;
625
                                int y = (int)p.getY()- 7;
626

    
627
                                g2.setColor(theTipColor );
628
                                g2.fillRect(x, y-h, w, h);
629
                                g2.setColor(Color.BLACK);
630
                                g2.drawRect(x, y-h, w, h);
631
                                        g2.drawString(usedSnap.getToolTipText(), x+3, y-3);
632

    
633

    
634
                                        // getMapControl().setToolTipText(usedSnap.getToolTipText());
635
                                }
636

    
637
                                bForceCoord = false;
638
                        } else {
639
                                g.drawRect((int) (p.getX() - size2), (int) (p.getY() - size2),
640
                                                (int) (size2 * 2), (int) (size2 * 2));
641
                        }
642
                }
643
        }
644

    
645
        /**
646
         * <p>Tries to find the nearest geometry or grid control point by the position of the current snap tool.</p>
647
         * 
648
         * <p>Prioritizes the grid control points than the geometries ones.</p>
649
         * 
650
         * <p>If finds any near, stores the <i>map</i> and <i>pixel</i> coordinates for the snap, and enables
651
         *  the <code>bForceCoord</code> attribute for the next draw of the mouse's cursor.</p>
652
         *
653
         * @param point current mouse 2D position
654
         */
655
        private void calculateSnapPoint(Point point) {
656
                // Se comprueba el ajuste a rejilla
657

    
658
                Point2D gridAdjustedPoint = getMapControl().getViewPort().toMapPoint(
659
                                point);
660
                double minDistance = Double.MAX_VALUE;
661
                CADTool ct = (CADTool) cadToolStack.peek();
662
                if (ct instanceof SelectionCADTool
663
                                && ((SelectionCADTool) ct).getStatus().equals(
664
                                                "Selection.FirstPoint")) {
665
                        mapAdjustedPoint = gridAdjustedPoint;
666
                        adjustedPoint = (Point2D) point.clone();
667
                } else {
668

    
669
                        minDistance = getGrid().adjustToGrid(gridAdjustedPoint);
670
                        if (minDistance < Double.MAX_VALUE) {
671
                                adjustedPoint = getMapControl().getViewPort().fromMapPoint(
672
                                                gridAdjustedPoint);
673
                                mapAdjustedPoint = gridAdjustedPoint;
674
                        } else {
675
                                mapAdjustedPoint = null;
676
                        }
677
                }
678
                Point2D handlerAdjustedPoint = null;
679

    
680
                // Se comprueba el ajuste a los handlers
681
                if (mapAdjustedPoint != null) {
682
                        handlerAdjustedPoint = (Point2D) mapAdjustedPoint.clone(); // getMapControl().getViewPort().toMapPoint(point);
683
                } else {
684
                        handlerAdjustedPoint = getMapControl().getViewPort().toMapPoint(
685
                                        point);
686
                }
687

    
688
                Point2D mapPoint = new Point2D.Double();
689
                double distance = adjustToHandler(handlerAdjustedPoint, mapPoint);
690

    
691
                if (distance < minDistance) {
692
                        bForceCoord = true;
693
                        adjustedPoint = getMapControl().getViewPort().fromMapPoint(mapPoint);
694
                        mapAdjustedPoint = mapPoint;
695
                        minDistance = distance;
696
                }
697

    
698
                // Si no hay ajuste
699
                if (minDistance == Double.MAX_VALUE) {
700
                        adjustedPoint = point;
701
                        mapAdjustedPoint = null;
702
                }
703

    
704
        }
705

    
706
        /*
707
         * (non-Javadoc)
708
         * @see com.iver.cit.gvsig.fmap.tools.Behavior.Behavior#mouseWheelMoved(java.awt.event.MouseWheelEvent)
709
         */
710
        public void mouseWheelMoved(MouseWheelEvent e) throws BehaviorException {
711
        }
712

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

    
763
                                numbers = text.split(",");
764
                                if (numbers[0].substring(0, 1).equals("@")) {
765
                                        numbers[0] = numbers[0].substring(1, numbers[0].length());
766
                                        type = RELATIVE_SCU;
767
                                        if (numbers[0].substring(0, 1).equals("*")) {
768
                                                type = RELATIVE_SCP;
769
                                                numbers[0] = numbers[0].substring(1, numbers[0]
770
                                                                .length());
771
                                        }
772
                                }
773
                        } else if (text.indexOf("<") != -1) {
774
                                type = POLAR_SCP;
775
                                numbers = text.split("<");
776
                                if (numbers[0].substring(0, 1).equals("@")) {
777
                                        numbers[0] = numbers[0].substring(1, numbers[0].length());
778
                                        type = POLAR_SCU;
779
                                        if (numbers[0].substring(0, 1).equals("*")) {
780
                                                type = POLAR_SCP;
781
                                                numbers[0] = numbers[0].substring(1, numbers[0]
782
                                                                .length());
783
                                        }
784
                                }
785
                        }
786

    
787
                        double[] values = null;
788

    
789
                        try {
790
                                if (numbers.length == 2) {
791
                                        // punto
792
                                        values = new double[] { Double.parseDouble(numbers[0]),
793
                                                        Double.parseDouble(numbers[1]) };
794
                                        transition(values, null, type);
795
                                } else if (numbers.length == 1) {
796
                                        // valor
797
                                        values = new double[] { Double.parseDouble(numbers[0]) };
798
                                        transition(values[0]);
799
                                }
800
                        } catch (NumberFormatException e) {
801
                                transition(text);
802
                        } catch (NullPointerException e) {
803
                                transition(text);
804
                        }
805
                        // }
806
                }
807
                getMapControl().repaint();
808
        }
809

    
810
        /**
811
         * If there are options related with the <code>CADTool</code> at the peek of the CAD tool stack,
812
         *  displays them as a popup.
813
         */
814
        public void configureMenu() {
815
                String[] desc = ((CADTool) cadToolStack.peek()).getDescriptions();
816
                // String[] labels = ((CADTool)
817
                // cadToolStack.peek()).getCurrentTransitions();
818
                CADExtension.clearMenu();
819

    
820
                for (int i = 0; i < desc.length; i++) {
821
                        if (desc[i] != null) {
822
                                CADExtension
823
                                                .addMenuEntry(PluginServices.getText(this, desc[i]));// ,
824
                                // labels[i]);
825
                        }
826
                }
827

    
828
        }
829

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

    
856
                        switch (type) {
857
                        case ABSOLUTE:
858
                                ct.transition(values[0], values[1], event);
859
                                previousPoint = values;
860
                                break;
861
                        case RELATIVE_SCU:
862
                                // Comprobar que tenemos almacenado el punto anterior
863
                                // y crear nuevo con coordenadas relativas a ?l.
864
                                double[] auxSCU = values;
865
                                if (previousPoint != null) {
866
                                        auxSCU[0] = previousPoint[0] + values[0];
867
                                        auxSCU[1] = previousPoint[1] + values[1];
868
                                }
869
                                ct.transition(auxSCU[0], auxSCU[1], event);
870

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

    
925
        /**
926
         * <p>One of the three kind of transaction methods of the <i>finite machine</i> of
927
         *  edition.</p>
928
         * 
929
         * <p>This one deals <code>value</code> as a single number used as a parameter for the current
930
         *    tool state. Ultimately, if isn't valid, <code>number</code> will be rewritten in the
931
         *    console notifying the user that isn't correct.</p>
932
         *    
933
         * <p>After applying the changes, updates the controls available for managing the current data.</p>
934
         * 
935
         * @param value value for the current tool state
936
         * 
937
         * @see CADTool#transition(double)
938
         * @see #transition(double[], InputEvent, int)
939
         * @see #transition(String)
940
         */
941
        private void transition(double value) {
942
                questionAsked = true;
943
                if (!cadToolStack.isEmpty()) {
944
                        CADTool ct = (CADTool) cadToolStack.peek();
945
                        ct.transition(value);
946
                        askQuestion();
947
                }
948
                configureMenu();
949
                PluginServices.getMainFrame().enableControls();
950
        }
951

    
952
        /**
953
         * <p>One of the three kind of transaction methods of the <i>finite machine</i> of
954
         *  edition.</p>
955
         * 
956
         * <p>This one deals <code>option</code> as an option of the current
957
         *    tool state. Ultimately, if isn't valid, <code>option</code> will be rewritten in the
958
         *    console notifying the user that isn't correct.</p>
959
         * 
960
         * @param option option for the current tool state
961
         * 
962
         * @see CADTool#transition(String)
963
         * @see #transition(double[], InputEvent, int)
964
         * @see #transition(double)
965
         */
966
        public void transition(String option) {
967
                questionAsked = true;
968
                if (!cadToolStack.isEmpty()) {
969
                        CADTool ct = (CADTool) cadToolStack.peek();
970
                        try {
971
                                ct.transition(option);
972
                        } catch (Exception e) {
973
                                IWindow window = PluginServices.getMDIManager().getActiveWindow();
974

    
975
                                if (window instanceof View) {
976
                                        ((View)window).getConsolePanel().addText(
977
                                                        "\n" + PluginServices.getText(this, "incorrect_option")
978
                                                        + " : " + option, JConsole.ERROR);
979
                                }
980
                        }
981
                        askQuestion();
982
                }
983
                configureMenu();
984
                PluginServices.getMainFrame().enableControls();
985
        }
986

    
987
        /**
988
         * Shows or hides a grid on the <code>ViewPort</code> of the associated <code>MapControl</code>.
989
         *
990
         * @param value <code>true</code> to make the grid visible; <code>false</code> to make it invisible
991
         */
992
        public void setGridVisibility(boolean value) {
993
                getGrid().setShowGrid(value);
994
                getGrid().setViewPort(getMapControl().getViewPort());
995
                getMapControl().repaint();
996
        }
997

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

    
1009
        /**
1010
         * Determines if snap tools are enabled or disabled.
1011
         * 
1012
         * @return <code>true</code> to enable the snap tools; <code>false</code> to disable them
1013
         * 
1014
         * @see #setRefentEnabled(boolean)
1015
         */
1016
        public boolean isRefentEnabled()
1017
        {
1018
                return bRefent;
1019
        }
1020

    
1021
        /*
1022
         * (non-Javadoc)
1023
         * @see com.iver.cit.gvsig.fmap.tools.Behavior.Behavior#getListener()
1024
         */
1025
        public ToolListener getListener() {
1026
                return new ToolListener() {
1027
                        /**
1028
                         * @see com.iver.cit.gvsig.fmap.tools.Listeners.ToolListener#getCursor()
1029
                         */
1030
                        public Cursor getCursor() {
1031
                                return null;
1032
                        }
1033

    
1034
                        /**
1035
                         * @see com.iver.cit.gvsig.fmap.tools.Listeners.ToolListener#cancelDrawing()
1036
                         */
1037
                        public boolean cancelDrawing() {
1038
                                return false;
1039
                        }
1040
                };
1041
        }
1042

    
1043
        /**
1044
         * Returns the {@link CADTool CADTool} at the top of the stack without removing it from the CAD tool stack.
1045
         * 
1046
         * @return the {@link CADTool CADTool} at the top of the stack
1047
         * 
1048
         * @see #pushCadTool(CADTool)
1049
         * @see #popCadTool()
1050
         * @see #setCadTool(CADTool)
1051
         */
1052
        public CADTool getCadTool() {
1053
                return (CADTool) cadToolStack.peek();
1054
        }
1055

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

    
1088
        /**
1089
         * Removes the peek of the CAD tool stack.
1090
         * 
1091
         * @see #pushCadTool(CADTool)
1092
         * @see #getCadTool()
1093
         * @see #setCadTool(CADTool)
1094
         */
1095
        public void popCadTool() {
1096
                cadToolStack.pop();
1097
        }
1098

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

    
1128
        }
1129

    
1130
        /**
1131
         * Empties the CAD tools stack and pushes <code>cadTool</code> in it.
1132
         * 
1133
         * @param cadTool CAD tool to set at the peek of the stack
1134
         * 
1135
         * @see #pushCadTool(CADTool)
1136
         * @see #popCadTool()
1137
         * @see #getCadTool()
1138
         */
1139
        public void setCadTool(CADTool cadTool) {
1140
                cadToolStack.clear();
1141
                pushCadTool(cadTool);
1142
                // askQuestion();
1143
        }
1144

    
1145
        /**
1146
         * <p>Removes all geometries selected in the associated <code>MapControl</code>.
1147
         */
1148
        public void delete() {
1149
                ILayerEdited aux = CADExtension.getEditionManager().getActiveLayerEdited();
1150
                if (!(aux instanceof VectorialLayerEdited))
1151
                        return;
1152
                VectorialLayerEdited vle = (VectorialLayerEdited) aux;
1153
                VectorialEditableAdapter vea = vle.getVEA();
1154

    
1155
                vea.startComplexRow();
1156
                try {
1157
                        FBitSet selection = vea.getSelection();
1158
                        int[] indexesToDel = new int[selection.cardinality()];
1159
                        int j = 0;
1160
                        for (int i = selection.nextSetBit(0); i >= 0; i = selection
1161
                                        .nextSetBit(i + 1)) {
1162
                                indexesToDel[j++] = i;
1163
                                // /vea.removeRow(i);
1164
                        }
1165

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

    
1188

    
1189
                /*
1190
                 * if (getCadTool() instanceof SelectionCADTool) { SelectionCADTool
1191
                 * selTool = (SelectionCADTool) getCadTool(); selTool.clearSelection(); }
1192
                 */
1193
                refreshEditedLayer();
1194
        }
1195

    
1196
        /**
1197
         * @see CADGrid#setAdjustGrid(boolean)
1198
         */
1199
        public void setAdjustGrid(boolean b) {
1200
                getGrid().setAdjustGrid(b);
1201
        }
1202

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

    
1246
                                pushCadTool(selCad);
1247
                                // getVectorialAdapter().getSelection().clear();
1248

    
1249
                                refreshEditedLayer();
1250

    
1251

    
1252
                                PluginServices.getMainFrame().setSelectedTool("_selection");
1253
                                // askQuestion();
1254
                        } else {
1255
                                getMapControl().setPrevTool();
1256
                        }
1257
                }
1258

    
1259
                PluginServices.getMainFrame().enableControls();
1260

    
1261
        }
1262

    
1263
        /**
1264
         * <p>Applies a lightweight repaint of the active layer being edited.</p>
1265
         * 
1266
         * <p>All layers under it won't be drawn, only the upper one and whose are over that layer in the TOC.</p>
1267
         * 
1268
         * @see MapControl#rePaintDirtyLayers()
1269
         */
1270
        public void refreshEditedLayer()
1271
        {
1272
                ILayerEdited edLayer = CADExtension.getEditionManager().getActiveLayerEdited();
1273
                if (edLayer != null)
1274
                {
1275
                        edLayer.getLayer().setDirty(true);
1276
                        getMapControl().rePaintDirtyLayers();
1277
                }
1278

    
1279
        }
1280

    
1281
        /**
1282
         * Gets the {@link CADGrid CADGrid} that can be drawn on the <code>ViewPort</code> of the associated <code>MapControl</code>.
1283
         * 
1284
         * @return reference to the <i>grid</i> that can be applied on the <code>ViewPort</code>
1285
         * 
1286
         * @see #setGridVisibility(boolean)
1287
         */
1288
        public CADGrid getGrid() {
1289
                return cadgrid;
1290
        }
1291

    
1292
        /**
1293
         * Determines if is enabled or not the <i>orto</i> mode.
1294
         * 
1295
         * @return <code>true</code> if is enabled the <i>orto</i> mode; otherwise <code>false</code> 
1296
         * 
1297
         * @see #setOrtoMode(boolean)
1298
         */
1299
        public boolean isOrtoMode() {
1300
                return bOrtoMode;
1301
        }
1302

    
1303
        /**
1304
         * Enables / disables the <i>orto</i> mode.
1305
         * 
1306
         * @param b the desired value
1307
         * 
1308
         * @see #isOrtoMode()
1309
         */
1310
        public void setOrtoMode(boolean b) {
1311
                bOrtoMode = b;
1312
        }
1313

    
1314
        /**
1315
         * Associates and stores the specified name with the specified {@link CADTool CADTool}.
1316
         * 
1317
         * @param name name of the tool
1318
         * @param c CAD tool to interactuate editing the layers
1319
         * 
1320
         * @see #getCADTools()
1321
         * @see #getCADTool(String)
1322
         */
1323
        public static void addCADTool(String name, CADTool c) {
1324
                namesCadTools.put(name, c);
1325

    
1326
        }
1327

    
1328
        /**
1329
         * Gets all CAD tools available to edit layers with this tool listener.
1330
         * 
1331
         * @return CAD tools available to edit layers with this tool listener
1332
         *
1333
         * @see #addCADTool(String, CADTool)
1334
         * @see #getCADTool(String)
1335
         */
1336
        public static CADTool[] getCADTools() {
1337
                return (CADTool[]) CADToolAdapter.namesCadTools.values().toArray(new CADTool[0]);
1338
        }
1339

    
1340
        /**
1341
         * Returns the {@link CADTool CADTool} to which the specified name is mapped.
1342
         * 
1343
         * @param text name of the tool
1344
         * @return the CAD tool whose associated name is to be returned
1345
         * 
1346
         * @see #addCADTool(String, CADTool)
1347
         * @see #getCADTools()
1348
         */
1349
        public CADTool getCADTool(String text) {
1350
                CADTool ct = (CADTool) namesCadTools.get(text);
1351
                return ct;
1352
        }
1353

    
1354
        /**
1355
         * Gets the object used to manage the edition of the layers of the associated <code>MapControl</code>.
1356
         * 
1357
         * @see EditionManager
1358
         * 
1359
         * @return object used to manage the edition of the layers
1360
         */
1361
        public EditionManager getEditionManager() {
1362
                return editionManager;
1363
        }
1364

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

    
1385
        /**
1386
         * <p>Updates the grid on the <code>ViewPort</code> of the associated <code>MapControl</code>
1387
         *  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>
1388
         * 
1389
         * <p>The preferences are:
1390
         *  <ul>
1391
         *   <li>Show/hide the grid.</li>
1392
         *   <li>Adjust or not the grid.</li>
1393
         *   <li>Horizontal ( X ) line separation.</li>
1394
         *   <li>Vertical ( Y ) line separation.</li>
1395
         *  </ul>
1396
         * </p>
1397
         */
1398
        public void initializeGrid(){
1399
                boolean showGrid = prefs.getBoolean("grid.showgrid",getGrid().isShowGrid());
1400
                boolean adjustGrid = prefs.getBoolean("grid.adjustgrid",getGrid().isAdjustGrid());
1401

    
1402
                double dx = prefs.getDouble("grid.distancex",getGrid().getGridSizeX());
1403
                double dy = prefs.getDouble("grid.distancey",getGrid().getGridSizeY());
1404

    
1405
                setGridVisibility(showGrid);
1406
                setAdjustGrid(adjustGrid);
1407
                getGrid().setGridSizeX(dx);
1408
                getGrid().setGridSizeY(dy);
1409
        }
1410

    
1411
        /**
1412
         * <p>Returns the type of the shape that's the current active and vector layer being edited.</p>
1413
         * 
1414
         * @see FLyrVect#getShapeType()
1415
         * 
1416
         * @return type of the shape that's the current active and vector layer being edited
1417
         */
1418
        public int getActiveLayerType() {
1419
                int type=FShape.MULTI;
1420
                try {
1421
                        type=((FLyrVect)CADExtension.getEditionManager().getActiveLayerEdited().getLayer()).getShapeType();
1422
                } catch (ReadDriverException e) {
1423
                        NotificationManager.addError(e);
1424
                }
1425
                return type;
1426
        }
1427
}