Statistics
| Revision:

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

History | View | Annotate | Download (46.6 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.MapContext;
32
import com.iver.cit.gvsig.fmap.MapControl;
33
import com.iver.cit.gvsig.fmap.ViewPort;
34
import com.iver.cit.gvsig.fmap.core.FShape;
35
import com.iver.cit.gvsig.fmap.core.SymbologyFactory;
36
import com.iver.cit.gvsig.fmap.core.symbols.ISymbol;
37
import com.iver.cit.gvsig.fmap.core.v02.FConstant;
38
import com.iver.cit.gvsig.fmap.core.v02.FConverter;
39
import com.iver.cit.gvsig.fmap.edition.EditionEvent;
40
import com.iver.cit.gvsig.fmap.edition.UtilFunctions;
41
import com.iver.cit.gvsig.fmap.edition.VectorialEditableAdapter;
42
import com.iver.cit.gvsig.fmap.layers.FBitSet;
43
import com.iver.cit.gvsig.fmap.layers.FLyrVect;
44
import com.iver.cit.gvsig.fmap.layers.SpatialCache;
45
import com.iver.cit.gvsig.fmap.tools.BehaviorException;
46
import com.iver.cit.gvsig.fmap.tools.Behavior.Behavior;
47
import com.iver.cit.gvsig.fmap.tools.Listeners.ToolListener;
48
import com.iver.cit.gvsig.gui.cad.tools.SelectionCADTool;
49
import com.iver.cit.gvsig.gui.preferences.SnapConfigPage;
50
import com.iver.cit.gvsig.layers.ILayerEdited;
51
import com.iver.cit.gvsig.layers.VectorialLayerEdited;
52
import com.iver.cit.gvsig.project.documents.view.gui.View;
53
import com.iver.cit.gvsig.project.documents.view.snapping.GeometriesSnappingVisitor;
54
import com.iver.cit.gvsig.project.documents.view.snapping.ISnapper;
55
import com.iver.cit.gvsig.project.documents.view.snapping.ISnapperGeometriesVectorial;
56
import com.iver.cit.gvsig.project.documents.view.snapping.ISnapperRaster;
57
import com.iver.cit.gvsig.project.documents.view.snapping.ISnapperVectorial;
58
import com.iver.cit.gvsig.project.documents.view.snapping.SnappingVisitor;
59
import com.iver.cit.gvsig.project.documents.view.toolListeners.StatusBarListener;
60
import com.iver.utiles.console.JConsole;
61
import com.vividsolutions.jts.geom.Envelope;
62

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
257
        /**
258
         * Edition preferences.
259
         */
260
        private static Preferences prefs = Preferences.userRoot().node( "cadtooladapter" );
261

    
262
        /**
263
         * Listener to display the coordinates in the current application's status bar.
264
         */
265
        private StatusBarListener sbl=null;
266

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

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

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

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

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

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

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

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

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

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

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

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

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

    
398

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

    
401
                snappers=SnapConfigPage.getActivesSnappers();
402

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

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

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

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

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

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

    
457

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

    
474
        }
475

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

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

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

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

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

    
504
                calculateSnapPoint(e.getPoint());
505

    
506
                showCoords(e.getPoint());
507

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

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

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

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

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

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

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

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

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

    
596
                        return;
597
                }
598

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

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

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

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

    
634

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

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

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

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

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

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

    
691
                Point2D mapPoint = new Point2D.Double();
692
                double distance = adjustToHandler(handlerAdjustedPoint, mapPoint);
693

    
694
                if (distance < minDistance) {
695
                        bForceCoord = true;
696
                        adjustedPoint = getMapControl().getViewPort().fromMapPoint(mapPoint);
697
                        mapAdjustedPoint = mapPoint;
698
                        minDistance = distance;
699
                }
700

    
701
                // Si no hay ajuste
702
                if (minDistance == Double.MAX_VALUE) {
703
                        adjustedPoint = point;
704
                        mapAdjustedPoint = null;
705
                }
706

    
707
        }
708

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

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

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

    
790
                        double[] values = null;
791

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

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

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

    
831
        }
832

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

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

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

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

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

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

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

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

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

    
1026
        /*
1027
         * (non-Javadoc)
1028
         * @see com.iver.cit.gvsig.fmap.tools.Behavior.Behavior#getListener()
1029
         */
1030
        public ToolListener getListener() {
1031
                return new ToolListener() {
1032
                        /**
1033
                         * @see com.iver.cit.gvsig.fmap.tools.Listeners.ToolListener#getCursor()
1034
                         */
1035
                        public Cursor getCursor() {
1036
                                return null;
1037
                        }
1038

    
1039
                        /**
1040
                         * @see com.iver.cit.gvsig.fmap.tools.Listeners.ToolListener#cancelDrawing()
1041
                         */
1042
                        public boolean cancelDrawing() {
1043
                                return false;
1044
                        }
1045
                };
1046
        }
1047

    
1048
        /**
1049
         * Returns the {@link CADTool CADTool} at the top of the stack without removing it from the CAD tool stack.
1050
         *
1051
         * @return the {@link CADTool CADTool} at the top of the stack
1052
         *
1053
         * @see #pushCadTool(CADTool)
1054
         * @see #popCadTool()
1055
         * @see #setCadTool(CADTool)
1056
         */
1057
        public CADTool getCadTool() {
1058
                if (cadToolStack.isEmpty())
1059
                        return null;
1060
                return (CADTool) cadToolStack.peek();
1061
        }
1062

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

    
1095
        /**
1096
         * Removes the peek of the CAD tool stack.
1097
         *
1098
         * @see #pushCadTool(CADTool)
1099
         * @see #getCadTool()
1100
         * @see #setCadTool(CADTool)
1101
         */
1102
        public void popCadTool() {
1103
                cadToolStack.pop();
1104
        }
1105

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

    
1135
        }
1136

    
1137
        /**
1138
         * Empties the CAD tools stack and pushes <code>cadTool</code> in it.
1139
         *
1140
         * @param cadTool CAD tool to set at the peek of the stack
1141
         *
1142
         * @see #pushCadTool(CADTool)
1143
         * @see #popCadTool()
1144
         * @see #getCadTool()
1145
         */
1146
        public void setCadTool(CADTool cadTool) {
1147
                cadToolStack.clear();
1148
                pushCadTool(cadTool);
1149
                // askQuestion();
1150
        }
1151

    
1152
        /**
1153
         * <p>Removes all geometries selected in the associated <code>MapControl</code>.
1154
         */
1155
        public void delete() {
1156
                ILayerEdited aux = CADExtension.getEditionManager().getActiveLayerEdited();
1157
                if (!(aux instanceof VectorialLayerEdited))
1158
                        return;
1159
                VectorialLayerEdited vle = (VectorialLayerEdited) aux;
1160
                VectorialEditableAdapter vea = vle.getVEA();
1161

    
1162
                vea.startComplexRow();
1163
                try {
1164
                        FBitSet selection = vea.getSelection();
1165
                        int[] indexesToDel = new int[selection.cardinality()];
1166
                        int j = 0;
1167
                        for (int i = selection.nextSetBit(0); i >= 0; i = selection
1168
                                        .nextSetBit(i + 1)) {
1169
                                indexesToDel[j++] = i;
1170
                                // /vea.removeRow(i);
1171
                        }
1172

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

    
1195

    
1196
                /*
1197
                 * if (getCadTool() instanceof SelectionCADTool) { SelectionCADTool
1198
                 * selTool = (SelectionCADTool) getCadTool(); selTool.clearSelection(); }
1199
                 */
1200
                refreshEditedLayer();
1201
        }
1202

    
1203
        /**
1204
         * @see CADGrid#setAdjustGrid(boolean)
1205
         */
1206
        public void setAdjustGrid(boolean b) {
1207
                getGrid().setAdjustGrid(b);
1208
        }
1209

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

    
1253
                                pushCadTool(selCad);
1254
                                // getVectorialAdapter().getSelection().clear();
1255

    
1256
                                refreshEditedLayer();
1257

    
1258

    
1259
                                PluginServices.getMainFrame().setSelectedTool("_selection");
1260
                                // askQuestion();
1261
                        } else {
1262
                                getMapControl().setPrevTool();
1263
                        }
1264
                }
1265

    
1266
                PluginServices.getMainFrame().enableControls();
1267

    
1268
        }
1269

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

    
1286
        }
1287

    
1288
        /**
1289
         * Gets the {@link CADGrid CADGrid} that can be drawn on the <code>ViewPort</code> of the associated <code>MapControl</code>.
1290
         *
1291
         * @return reference to the <i>grid</i> that can be applied on the <code>ViewPort</code>
1292
         *
1293
         * @see #setGridVisibility(boolean)
1294
         */
1295
        public CADGrid getGrid() {
1296
                return cadgrid;
1297
        }
1298

    
1299
        /**
1300
         * Determines if is enabled or not the <i>orto</i> mode.
1301
         *
1302
         * @return <code>true</code> if is enabled the <i>orto</i> mode; otherwise <code>false</code>
1303
         *
1304
         * @see #setOrtoMode(boolean)
1305
         */
1306
        public boolean isOrtoMode() {
1307
                return bOrtoMode;
1308
        }
1309

    
1310
        /**
1311
         * Enables / disables the <i>orto</i> mode.
1312
         *
1313
         * @param b the desired value
1314
         *
1315
         * @see #isOrtoMode()
1316
         */
1317
        public void setOrtoMode(boolean b) {
1318
                bOrtoMode = b;
1319
        }
1320

    
1321
        /**
1322
         * Associates and stores the specified name with the specified {@link CADTool CADTool}.
1323
         *
1324
         * @param name name of the tool
1325
         * @param c CAD tool to interactuate editing the layers
1326
         *
1327
         * @see #getCADTools()
1328
         * @see #getCADTool(String)
1329
         */
1330
        public static void addCADTool(String name, CADTool c) {
1331
                namesCadTools.put(name, c);
1332

    
1333
        }
1334

    
1335
        /**
1336
         * Gets all CAD tools available to edit layers with this tool listener.
1337
         *
1338
         * @return CAD tools available to edit layers with this tool listener
1339
         *
1340
         * @see #addCADTool(String, CADTool)
1341
         * @see #getCADTool(String)
1342
         */
1343
        public static CADTool[] getCADTools() {
1344
                return (CADTool[]) CADToolAdapter.namesCadTools.values().toArray(new CADTool[0]);
1345
        }
1346

    
1347
        /**
1348
         * Returns the {@link CADTool CADTool} to which the specified name is mapped.
1349
         *
1350
         * @param text name of the tool
1351
         * @return the CAD tool whose associated name is to be returned
1352
         *
1353
         * @see #addCADTool(String, CADTool)
1354
         * @see #getCADTools()
1355
         */
1356
        public CADTool getCADTool(String text) {
1357
                CADTool ct = (CADTool) namesCadTools.get(text);
1358
                return ct;
1359
        }
1360

    
1361
        /**
1362
         * Gets the object used to manage the edition of the layers of the associated <code>MapControl</code>.
1363
         *
1364
         * @see EditionManager
1365
         *
1366
         * @return object used to manage the edition of the layers
1367
         */
1368
        public EditionManager getEditionManager() {
1369
                return editionManager;
1370
        }
1371

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

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

    
1409
                double dx = prefs.getDouble("grid.distancex",getGrid().getGridSizeX());
1410
                double dy = prefs.getDouble("grid.distancey",getGrid().getGridSizeY());
1411

    
1412
                setGridVisibility(showGrid);
1413
                setAdjustGrid(adjustGrid);
1414
                getGrid().setGridSizeX(dx);
1415
                getGrid().setGridSizeY(dy);
1416
        }
1417

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