Statistics
| Revision:

root / branches / v2_0_0_prep / extensions / extEditing / src / com / iver / cit / gvsig / gui / cad / CADToolAdapter.java @ 27525

History | View | Annotate | Download (49.3 KB)

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

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

    
19
import org.cresques.cts.IProjection;
20
import org.gvsig.fmap.dal.exception.DataException;
21
import org.gvsig.fmap.dal.exception.ReadException;
22
import org.gvsig.fmap.dal.feature.DisposableIterator;
23
import org.gvsig.fmap.dal.feature.Feature;
24
import org.gvsig.fmap.dal.feature.FeatureSet;
25
import org.gvsig.fmap.dal.feature.FeatureStore;
26
import org.gvsig.fmap.dal.feature.exception.NeedEditingModeException;
27
import org.gvsig.fmap.geom.Geometry;
28
import org.gvsig.fmap.geom.util.Converter;
29
import org.gvsig.fmap.geom.util.UtilFunctions;
30
import org.gvsig.fmap.mapcontext.MapContext;
31
import org.gvsig.fmap.mapcontext.ViewPort;
32
import org.gvsig.fmap.mapcontext.layers.vectorial.FLyrVect;
33
import org.gvsig.fmap.mapcontext.rendering.symbols.ISymbol;
34
import org.gvsig.fmap.mapcontext.rendering.symbols.SymbologyFactory;
35
import org.gvsig.fmap.mapcontrol.MapControl;
36
import org.gvsig.fmap.mapcontrol.tools.BehaviorException;
37
import org.gvsig.fmap.mapcontrol.tools.Behavior.Behavior;
38
import org.gvsig.fmap.mapcontrol.tools.Listeners.ToolListener;
39

    
40
import com.iver.andami.PluginServices;
41
import com.iver.andami.messages.NotificationManager;
42
import com.iver.andami.ui.mdiFrame.MainFrame;
43
import com.iver.andami.ui.mdiManager.IWindow;
44
import com.iver.cit.gvsig.CADExtension;
45
import com.iver.cit.gvsig.EditionManager;
46
import com.iver.cit.gvsig.gui.cad.tools.SelectionCADTool;
47
import com.iver.cit.gvsig.layers.ILayerEdited;
48
import com.iver.cit.gvsig.layers.VectorialLayerEdited;
49
import com.iver.cit.gvsig.project.documents.view.gui.View;
50
import com.iver.cit.gvsig.project.documents.view.toolListeners.StatusBarListener;
51
import com.iver.utiles.console.JConsole;
52

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

    
118
        /**
119
         * Stores the CAD tools to edit the layers of the associated
120
         * <code>MapControl</code>.
121
         *
122
         * @see #addCADTool(String, CADTool)
123
         * @see #getCadTool()
124
         * @see #getCADTool(String)
125
         */
126
        private static HashMap namesCadTools = new HashMap();
127

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

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

    
143
        /**
144
         * Equivalent to {@link CADToolAdapter#ABSOLUTE CADToolAdapter#ABSOLUTE}.
145
         */
146
        public static final int RELATIVE_SCP = 1;
147

    
148
        /**
149
         * Identifies that the data are relative distances of the new point from the
150
         * previous introduced.
151
         */
152
        public static final int RELATIVE_SCU = 2;
153

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

    
161
        /**
162
         * Identifies that the data are relative polar distances (longitude of the
163
         * line and angle given in radians) of the new point from the previous
164
         * introduced.
165
         */
166
        public static final int POLAR_SCU = 4;
167

    
168
        /**
169
         * Stores the 2D map coordinates of the last point added.
170
         */
171
        private double[] previousPoint = null;
172

    
173
        /**
174
         * <i>Stack with CAD tools.</i>
175
         *
176
         * <i>For each CAD tool we use, the last item added in this stack will
177
         * display a different icon according to the current operation and its
178
         * status.</i>
179
         */
180
        private Stack cadToolStack = new Stack();
181

    
182
        /**
183
         * X coordinate of the last dragging or moving mouse event.
184
         */
185
        private int lastX;
186

    
187
        /**
188
         * Y coordinate of the last dragging or moving mouse event.
189
         */
190
        private int lastY;
191

    
192
        /**
193
         * Unused attribute.
194
         */
195
        private ISymbol symbol = SymbologyFactory.createDefaultSymbolByShapeType(
196
                        Geometry.TYPES.POINT, Color.RED);
197

    
198
        /**
199
         * Represents the cursor's point selected in <i>map coordinates</i>.
200
         *
201
         * @see MapControl#toMapPoint
202
         */
203
        private Point2D mapAdjustedPoint;
204

    
205
        /**
206
         * Kind of geometry drawn to identify the kind of control point selected by
207
         * the cursor's mouse.
208
         */
209
        // private ISnapper usedSnap = null;
210
        /**
211
         * Determines if has displayed at the edition console, the question for the
212
         * operations that can do the user with the current CAD tool, in its current
213
         * state.
214
         */
215
        private boolean questionAsked = false;
216

    
217
        /**
218
         * Represents the cursor's point selected in <i>screen coordinates</i>.
219
         *
220
         * @see ViewPort#fromMapPoint(Point2D)
221
         */
222
        private Point2D adjustedPoint;
223

    
224
        /**
225
         * Determines if the snap tools are enabled or disabled.
226
         *
227
         * @see #isRefentEnabled()
228
         * @see #setRefentEnabled(boolean)
229
         */
230
        // private boolean bRefent = true;
231
        /**
232
         * <p>
233
         * Determines if the position of the snap of the mouse's cursor on the
234
         * <code>MapControl</code> is within the area around a control point of a
235
         * geometry.
236
         * </p>
237
         *
238
         * <p>
239
         * The area is calculated as a circle centered at the control point and with
240
         * radius the pixels tolerance defined in the preferences.
241
         * </p>
242
         */
243
        // private boolean bForceCoord = false;
244
        /**
245
         * Optional grid that could be applied on the <code>MapControl</code>'s
246
         * view port.
247
         *
248
         * @see #getGrid()
249
         * @see #setAdjustGrid(boolean)
250
         */
251
        // private CADGrid cadgrid = new CADGrid();
252
        /**
253
         * Determines is is enabled or not the <i>Orto</i> mode.
254
         */
255
        private boolean bOrtoMode;
256

    
257
        /**
258
         * A light yellow color for the tool tip text box associated to the point
259
         * indicated by the mouse's cursor.
260
         */
261
        private Color theTipColor = new Color(255, 255, 155);
262

    
263
        /**
264
         * Last question asked to the user in the CAD console.
265
         */
266
        private Object lastQuestion;
267

    
268
        /**
269
         * Maximum tolerance in the approximation of a curved line by a polyline.
270
         *
271
         * @see #initializeFlatness()
272
         */
273
        private static boolean flatnessInitialized = false;
274

    
275
        /**
276
         * Edition preferences.
277
         */
278
        private static Preferences prefs = Preferences.userRoot().node(
279
                        "cadtooladapter");
280

    
281
        /**
282
         * Listener to display the coordinates in the current application's status
283
         * bar.
284
         */
285
        private StatusBarListener sbl = null;
286

    
287
        /*
288
         * (non-Javadoc)
289
         *
290
         * @see com.iver.cit.gvsig.fmap.tools.Behavior.Behavior#setMapControl(com.iver.cit.gvsig.fmap.MapControl)
291
         */
292
        public void setMapControl(MapControl mc) {
293
                super.setMapControl(mc);
294
                sbl = new StatusBarListener(getMapControl());
295
        }
296

    
297
        private static final Image imageCursor = new BufferedImage(32, 32,
298
                        BufferedImage.TYPE_INT_ARGB);
299
        static {
300
                Graphics g = imageCursor.getGraphics();
301
                int size1 = 15;
302
                int size2 = 3;
303
                int x = 16;
304
                int y = 16;
305
                g.setColor(Color.MAGENTA);
306
                g.drawLine((x - size1), (y), (x + size1), (y));
307
                g.drawLine((x), (y - size1), (x), (y + size1));
308
                // g.setColor(Color.MAGENTA);
309
                g.drawRect((x - 6), (y - 6), 12, 12);
310
                g.drawRect((x - 3), (y - 3), 6, 6);
311

    
312
                // // getMapControl().setToolTipText(null);
313
                // if (adjustedPoint != null) {
314
                // if (bForceCoord) {
315
                // /* g.setColor(Color.ORANGE);
316
                // g.drawRect((int) (adjustedPoint.getX() - 6),
317
                // (int) (adjustedPoint.getY() - 6), 12, 12);
318
                // g.drawRect((int) (adjustedPoint.getX() - 3),
319
                // (int) (adjustedPoint.getY() - 3), 6, 6);
320
                // g.setColor(Color.MAGENTA);
321
                // g.drawRect((int) (adjustedPoint.getX() - 4),
322
                // (int) (adjustedPoint.getY() - 4), 8, 8); */
323
                // if (usedSnap != null)
324
                // {
325
                // usedSnap.draw(g, adjustedPoint);
326
                //
327
                // Graphics2D g2 = (Graphics2D) g;
328
                // FontMetrics metrics = g2.getFontMetrics();
329
                // int w = metrics.stringWidth(usedSnap.getToolTipText()) + 5;
330
                // int h = metrics.getMaxAscent() + 5;
331
                // int x = (int)p.getX()+9;
332
                // int y = (int)p.getY()- 7;
333
                //
334
                // g2.setColor(theTipColor );
335
                // g2.fillRect(x, y-h, w, h);
336
                // g2.setColor(Color.BLACK);
337
                // g2.drawRect(x, y-h, w, h);
338
                // g2.drawString(usedSnap.getToolTipText(), x+3, y-3);
339
                //
340
                //
341
                // // getMapControl().setToolTipText(usedSnap.getToolTipText());
342
                // }
343
                //
344
                // bForceCoord = false;
345
                // } else {
346
                // g.drawRect((int) (p.getX() - size2), (int) (p.getY() - size2),
347
                // (int) (size2 * 2), (int) (size2 * 2));
348
                // }
349
                // }
350

    
351
        }
352

    
353
        /**
354
         * <p>
355
         * Draws the selected geometries to edit. And, if the <i>snapping</i> is
356
         * enabled, draws also its effect over them.
357
         * </p>
358
         *
359
         * @see com.iver.cit.gvsig.fmap.tools.Behavior.Behavior#paintComponent(java.awt.Graphics)
360
         */
361
        public void paintComponent(Graphics g) {
362
                super.paintComponent(g);
363
                if (CADExtension.getCADToolAdapter() != this) {
364
                        return;
365
                }
366

    
367
                if (adjustedPoint != null) {
368
                        Point2D p = null;
369
                        if (mapAdjustedPoint != null) {
370
                                p = mapAdjustedPoint;
371
                        } else {
372
                                p = getMapControl().getViewPort().toMapPoint(adjustedPoint);
373
                        }
374

    
375
                        ((CADTool) cadToolStack.peek())
376
                                        .drawOperation(g, p.getX(), p.getY());
377
                }
378
                // drawCursor(g);
379
                // getGrid().drawGrid(g);
380
        }
381

    
382
        /**
383
         * <p>
384
         * Responds two kind of mouse click events:
385
         * <ul>
386
         * <li><b><i>One click of the third mouse's button</i></b>: displays a
387
         * popup with edition options.</li>
388
         * <li><b><i>Two clicks of the first mouse's button</i></b>: ends the
389
         * last cad tool setting as end transition point the event's one.</li>
390
         * </ul>
391
         * </p>
392
         *
393
         *
394
         * @see com.iver.cit.gvsig.fmap.tools.Behavior.Behavior#mouseClicked(java.awt.event.MouseEvent)
395
         * @see CADExtension#showPopup(MouseEvent)
396
         */
397
        public void mouseClicked(MouseEvent e) throws BehaviorException {
398
                if (e.getButton() == MouseEvent.BUTTON3) {
399
                        CADExtension.showPopup(e);
400
                } else if (e.getButton() == MouseEvent.BUTTON1
401
                                && e.getClickCount() == 2) {
402
                        questionAsked = true;
403
                        if (!cadToolStack.isEmpty()) {
404
                                CADTool ct = (CADTool) cadToolStack.peek();
405
                                ViewPort vp = getMapControl().getMapContext().getViewPort();
406
                                Point2D p;
407

    
408
                                if (mapAdjustedPoint != null) {
409
                                        p = mapAdjustedPoint;
410
                                } else {
411
                                        p = vp.toMapPoint(adjustedPoint);
412
                                }
413
                                ct.endTransition(p.getX(), p.getY(), e);
414
                                previousPoint = new double[] { p.getX(), p.getY() };
415
                        }
416
                }
417
        }
418

    
419
        /*
420
         * (non-Javadoc)
421
         *
422
         * @see com.iver.cit.gvsig.fmap.tools.Behavior.Behavior#mouseEntered(java.awt.event.MouseEvent)
423
         */
424
        public void mouseEntered(MouseEvent e) throws BehaviorException {
425
                clearMouseImage();
426
        }
427

    
428
        /*
429
         * (non-Javadoc)
430
         *
431
         * @see com.iver.cit.gvsig.fmap.tools.Behavior.Behavior#mouseExited(java.awt.event.MouseEvent)
432
         */
433
        public void mouseExited(MouseEvent e) throws BehaviorException {
434
        }
435

    
436
        /**
437
         * Selects the vertex of a geometry at the point selected on the
438
         * <code>MapControl</code> by pressing the first mouse's button.
439
         *
440
         * @see com.iver.cit.gvsig.fmap.tools.Behavior.Behavior#mousePressed(java.awt.event.MouseEvent)
441
         */
442
        public void mousePressed(MouseEvent e) throws BehaviorException {
443
                if (e.getButton() == MouseEvent.BUTTON1) {
444
                        ViewPort vp = getMapControl().getMapContext().getViewPort();
445
                        Point2D p;
446

    
447
                        if (mapAdjustedPoint != null) {
448
                                p = mapAdjustedPoint;
449
                        } else {
450
                                p = vp.toMapPoint(adjustedPoint);
451
                        }
452
                        transition(new double[] { p.getX(), p.getY() }, e, ABSOLUTE);
453
                }
454
        }
455

    
456
        // /**
457
        // * <p>Adjusts the <code>point</code> to the grid if its enabled, and
458
        // * sets <code>mapHandlerAdjustedPoint</code> with that new value.</p>
459
        // *
460
        // * <p>The value returned is the distance between those points: the
461
        // original and
462
        // * the adjusted one.</p>
463
        // *
464
        // * @param point point to adjust
465
        // * @param mapHandlerAdjustedPoint <code>point</code> adjusted
466
        // *
467
        // * @return distance from <code>point</code> to the adjusted one. If there
468
        // is no
469
        // * adjustment, returns <code>Double.MAX_VALUE</code>.
470
        // */
471
        // private double adjustToHandler(Point2D point,
472
        // Point2D mapHandlerAdjustedPoint) {
473
        //
474
        // if (!isRefentEnabled())
475
        // return Double.MAX_VALUE;
476
        //
477
        // ILayerEdited aux =
478
        // CADExtension.getEditionManager().getActiveLayerEdited();
479
        // if (!(aux instanceof VectorialLayerEdited))
480
        // return Double.MAX_VALUE;
481
        // VectorialLayerEdited vle = (VectorialLayerEdited) aux;
482
        //
483
        // ArrayList snappers = vle.getSnappers();
484
        // ArrayList layersToSnap = vle.getLayersToSnap();
485
        //
486
        //
487
        // ViewPort vp = getMapControl().getViewPort();
488
        //
489
        // snappers=SnapConfigPage.getActivesSnappers();
490
        //
491
        // double mapTolerance = vp.toMapDistance(SelectionCADTool.tolerance);
492
        // double minDist = mapTolerance;
493
        // // double rw = getMapControl().getViewPort().toMapDistance(5);
494
        // Point2D mapPoint = point;
495
        // double middleTol=mapTolerance * 0.5;
496
        // org.gvsig.fmap.geom.primitive.Envelope r = new
497
        // DefaultEnvelope(mapPoint.getX() - middleTol,
498
        // mapPoint.getY() - middleTol,
499
        // mapPoint.getX() + middleTol,
500
        // mapPoint.getY() + middleTol);
501
        //
502
        // Envelope e = Converter.convertEnvelopeToJTS(r);
503
        //
504
        // usedSnap = null;
505
        // Point2D lastPoint = null;
506
        // if (previousPoint != null)
507
        // {
508
        // lastPoint = new Point2D.Double(previousPoint[0], previousPoint[1]);
509
        // }
510
        // for (int j = 0; j < layersToSnap.size(); j++)
511
        // {
512
        // FLyrVect lyrVect = (FLyrVect) layersToSnap.get(j);
513
        // SpatialCache cache = lyrVect.getSpatialCache();
514
        // if (lyrVect.isVisible())
515
        // {
516
        // // La lista de snappers est? siempre ordenada por prioridad. Los de mayor
517
        // // prioridad est?n primero.
518
        // for (int i = 0; i < snappers.size(); i++)
519
        // {
520
        // ISnapper theSnapper = (ISnapper) snappers.get(i);
521
        //
522
        // if (usedSnap != null)
523
        // {
524
        // // Si ya tenemos un snap y es de alta prioridad, cogemos ese. (A no ser
525
        // que en otra capa encontremos un snapper mejor)
526
        // if (theSnapper.getPriority() < usedSnap.getPriority())
527
        // break;
528
        // }
529
        // SnappingVisitor snapVisitor = null;
530
        // Point2D theSnappedPoint = null;
531
        //
532
        // if (theSnapper instanceof ISnapperVectorial)
533
        // {
534
        // if (theSnapper instanceof ISnapperGeometriesVectorial) {
535
        // snapVisitor=new GeometriesSnappingVisitor((ISnapperGeometriesVectorial)
536
        // theSnapper,point,mapTolerance,lastPoint);
537
        // }else {
538
        // snapVisitor = new SnappingVisitor((ISnapperVectorial) theSnapper, point,
539
        // mapTolerance, lastPoint);
540
        // }
541
        // // System.out.println("Cache size = " + cache.size());
542
        // cache.query(e, snapVisitor);
543
        // theSnappedPoint = snapVisitor.getSnapPoint();
544
        //
545
        // }
546
        // if (theSnapper instanceof ISnapperRaster)
547
        // {
548
        // ISnapperRaster snapRaster = (ISnapperRaster) theSnapper;
549
        // theSnappedPoint = snapRaster.getSnapPoint(getMapControl(), point,
550
        // mapTolerance, lastPoint);
551
        // }
552
        //
553
        //
554
        // if (theSnappedPoint != null) {
555
        // double distAux = theSnappedPoint.distance(point);
556
        // if (minDist > distAux)
557
        // {
558
        // minDist = distAux;
559
        // usedSnap = theSnapper;
560
        // mapHandlerAdjustedPoint.setLocation(theSnappedPoint);
561
        // }
562
        // }
563
        // }
564
        // } // visible
565
        // }
566
        // if (usedSnap != null)
567
        // return minDist;
568
        // return Double.MAX_VALUE;
569
        //
570
        // }
571

    
572
        /*
573
         * (non-Javadoc)
574
         *
575
         * @see com.iver.cit.gvsig.fmap.tools.Behavior.Behavior#mouseReleased(java.awt.event.MouseEvent)
576
         */
577
        public void mouseReleased(MouseEvent e) throws BehaviorException {
578
                getMapControl().repaint();
579
        }
580

    
581
        /*
582
         * (non-Javadoc)
583
         *
584
         * @see com.iver.cit.gvsig.fmap.tools.Behavior.Behavior#mouseDragged(java.awt.event.MouseEvent)
585
         */
586
        public void mouseDragged(MouseEvent e) throws BehaviorException {
587
                lastX = e.getX();
588
                lastY = e.getY();
589
                adjustedPoint = e.getPoint();
590
                // calculateSnapPoint(e.getPoint());
591
        }
592

    
593
        /*
594
         * (non-Javadoc)
595
         *
596
         * @see com.iver.cit.gvsig.fmap.tools.Behavior.Behavior#mouseMoved(java.awt.event.MouseEvent)
597
         */
598
        public void mouseMoved(MouseEvent e) throws BehaviorException {
599

    
600
                lastX = e.getX();
601
                lastY = e.getY();
602
                adjustedPoint = e.getPoint();
603
                // calculateSnapPoint(e.getPoint());
604

    
605
                showCoords(e.getPoint());
606

    
607
                getMapControl().repaint();
608
        }
609

    
610
        /**
611
         * Displays the current coordinates of the mouse's cursor on the associated
612
         * <code>MapControl</code> object, at the status bar of the application's
613
         * main frame.
614
         *
615
         * @param pPix
616
         *            current 2D mouse's cursor coordinates on the
617
         *            <code>MapControl</code>
618
         */
619
        private void showCoords(Point2D pPix) {
620
                String[] axisText = new String[2];
621
                axisText[0] = "X = ";
622
                axisText[1] = "Y = ";
623
                // NumberFormat nf = NumberFormat.getInstance();
624
                MapControl mapControl = getMapControl();
625
                ViewPort vp = mapControl.getMapContext().getViewPort();
626
                IProjection iProj = vp.getProjection();
627

    
628
                // if (iProj.getAbrev().equals("EPSG:4326") ||
629
                // iProj.getAbrev().equals("EPSG:4230")) {
630
                // axisText[0] = "Lon = ";
631
                // axisText[1] = "Lat = ";
632
                // nf.setMaximumFractionDigits(8);
633
                // } else {
634
                // axisText[0] = "X = ";
635
                // axisText[1] = "Y = ";
636
                // nf.setMaximumFractionDigits(2);
637
                // }
638
                Point2D p;
639
                if (mapAdjustedPoint == null) {
640
                        p = vp.toMapPoint(pPix);
641
                } else {
642
                        p = mapAdjustedPoint;
643
                }
644
                sbl.setFractionDigits(p);
645
                axisText = sbl.setCoorDisplayText(axisText);
646
                MainFrame mF = PluginServices.getMainFrame();
647

    
648
                if (mF != null) {
649
                        mF.getStatusBar().setMessage(
650
                                        "units",
651
                                        PluginServices
652
                                                        .getText(this, MapContext.getDistanceNames()[vp
653
                                                                        .getDistanceUnits()]));
654
                        mF.getStatusBar().setControlValue("scale",
655
                                        String.valueOf(mapControl.getMapContext().getScaleView()));
656
                        mF.getStatusBar().setMessage("projection", iProj.getAbrev());
657

    
658
                        String[] coords = sbl.getCoords(p);
659
                        mF.getStatusBar().setMessage("x", axisText[0] + coords[0]);
660
                        mF.getStatusBar().setMessage("y", axisText[1] + coords[1]);
661
                }
662
        }
663

    
664
        /**
665
         * Hides the mouse's cursor.
666
         */
667
        private void clearMouseImage() {
668
                int[] pixels = new int[16 * 16];
669
                Image image = Toolkit.getDefaultToolkit().createImage(
670
                                new MemoryImageSource(16, 16, pixels, 0, 16));
671
                Cursor transparentCursor = Toolkit.getDefaultToolkit()
672
                                .createCustomCursor(image, new Point(0, 0), "invisiblecursor");
673

    
674
                getMapControl().setCursor(transparentCursor);
675
        }
676

    
677
        /**
678
         * <p>
679
         * Draws a 31x31 pixels cross round the mouse's cursor with an small
680
         * geometry centered:
681
         * <ul>
682
         * <li><i>an square centered</i>: if isn't over a <i>control point</i>.
683
         * <li><i>an small geometry centered according to the kind of control point</i>:
684
         * if it's over a control point. In this case, the small geometry is drawn
685
         * by a {@link ISnapper ISnapper} type object.<br>
686
         * On the other hand, a light-yellowed background tool tip text with the
687
         * type of <i>control point</i> will be displayed.</li>
688
         * </p>
689
         *
690
         * @param g
691
         *            <code>MapControl</code>'s graphics where the data will be
692
         *            drawn
693
         */
694
        // private void drawCursor(Graphics g) {
695
        // g.setColor(Color.black);
696
        // Point2D p = adjustedPoint;
697
        //
698
        // if (p == null) {
699
        // getGrid().setViewPort(getMapControl().getViewPort());
700
        //
701
        // return;
702
        // }
703
        //
704
        // int size1 = 15;
705
        // int size2 = 3;
706
        // g.drawLine((int) (p.getX() - size1), (int) (p.getY()),
707
        // (int) (p.getX() + size1), (int) (p.getY()));
708
        // g.drawLine((int) (p.getX()), (int) (p.getY() - size1),
709
        // (int) (p.getX()), (int) (p.getY() + size1));
710
        //
711
        // // getMapControl().setToolTipText(null);
712
        // if (adjustedPoint != null) {
713
        // if (bForceCoord) {
714
        // /* g.setColor(Color.ORANGE);
715
        // g.drawRect((int) (adjustedPoint.getX() - 6),
716
        // (int) (adjustedPoint.getY() - 6), 12, 12);
717
        // g.drawRect((int) (adjustedPoint.getX() - 3),
718
        // (int) (adjustedPoint.getY() - 3), 6, 6);
719
        // g.setColor(Color.MAGENTA);
720
        // g.drawRect((int) (adjustedPoint.getX() - 4),
721
        // (int) (adjustedPoint.getY() - 4), 8, 8); */
722
        // if (usedSnap != null)
723
        // {
724
        // usedSnap.draw(g, adjustedPoint);
725
        //
726
        // Graphics2D g2 = (Graphics2D) g;
727
        // FontMetrics metrics = g2.getFontMetrics();
728
        // int w = metrics.stringWidth(usedSnap.getToolTipText()) + 5;
729
        // int h = metrics.getMaxAscent() + 5;
730
        // int x = (int)p.getX()+9;
731
        // int y = (int)p.getY()- 7;
732
        //
733
        // g2.setColor(theTipColor );
734
        // g2.fillRect(x, y-h, w, h);
735
        // g2.setColor(Color.BLACK);
736
        // g2.drawRect(x, y-h, w, h);
737
        // g2.drawString(usedSnap.getToolTipText(), x+3, y-3);
738
        //
739
        //
740
        // // getMapControl().setToolTipText(usedSnap.getToolTipText());
741
        // }
742
        //
743
        // bForceCoord = false;
744
        // } else {
745
        // g.drawRect((int) (p.getX() - size2), (int) (p.getY() - size2),
746
        // (int) (size2 * 2), (int) (size2 * 2));
747
        // }
748
        // }
749
        // }
750
        /**
751
         * <p>
752
         * Tries to find the nearest geometry or grid control point by the position
753
         * of the current snap tool.
754
         * </p>
755
         *
756
         * <p>
757
         * Prioritizes the grid control points than the geometries ones.
758
         * </p>
759
         *
760
         * <p>
761
         * If finds any near, stores the <i>map</i> and <i>pixel</i> coordinates
762
         * for the snap, and enables the <code>bForceCoord</code> attribute for
763
         * the next draw of the mouse's cursor.
764
         * </p>
765
         *
766
         * @param point
767
         *            current mouse 2D position
768
         */
769
        // private void calculateSnapPoint(Point point) {
770
        // // Se comprueba el ajuste a rejilla
771
        //
772
        // Point2D gridAdjustedPoint = getMapControl().getViewPort().toMapPoint(
773
        // point);
774
        // double minDistance = Double.MAX_VALUE;
775
        // CADTool ct = (CADTool) cadToolStack.peek();
776
        // if (ct instanceof SelectionCADTool
777
        // && ((SelectionCADTool) ct).getStatus().equals(
778
        // "Selection.FirstPoint")) {
779
        // mapAdjustedPoint = gridAdjustedPoint;
780
        // adjustedPoint = (Point2D) point.clone();
781
        // } else {
782
        //
783
        // minDistance = getGrid().adjustToGrid(gridAdjustedPoint);
784
        // if (minDistance < Double.MAX_VALUE) {
785
        // adjustedPoint = getMapControl().getViewPort().fromMapPoint(
786
        // gridAdjustedPoint);
787
        // mapAdjustedPoint = gridAdjustedPoint;
788
        // } else {
789
        // mapAdjustedPoint = null;
790
        // }
791
        // }
792
        // Point2D handlerAdjustedPoint = null;
793
        //
794
        // // Se comprueba el ajuste a los handlers
795
        // if (mapAdjustedPoint != null) {
796
        // handlerAdjustedPoint = (Point2D) mapAdjustedPoint.clone(); //
797
        // getMapControl().getViewPort().toMapPoint(point);
798
        // } else {
799
        // handlerAdjustedPoint = getMapControl().getViewPort().toMapPoint(
800
        // point);
801
        // }
802
        //
803
        // Point2D mapPoint = new Point2D.Double();
804
        // double distance = adjustToHandler(handlerAdjustedPoint, mapPoint);
805
        //
806
        // if (distance < minDistance) {
807
        // bForceCoord = true;
808
        // adjustedPoint = getMapControl().getViewPort().fromMapPoint(mapPoint);
809
        // mapAdjustedPoint = mapPoint;
810
        // minDistance = distance;
811
        // }
812
        //
813
        // // Si no hay ajuste
814
        // if (minDistance == Double.MAX_VALUE) {
815
        // adjustedPoint = point;
816
        // mapAdjustedPoint = null;
817
        // }
818
        //
819
        // }
820
        /*
821
         * (non-Javadoc)
822
         *
823
         * @see com.iver.cit.gvsig.fmap.tools.Behavior.Behavior#mouseWheelMoved(java.awt.event.MouseWheelEvent)
824
         */
825
        public void mouseWheelMoved(MouseWheelEvent e) throws BehaviorException {
826
        }
827

    
828
        /**
829
         * <p>
830
         * Process the information written by the user about the next point
831
         * coordinate, determining the kind of <i>transition</i> according the
832
         * parameters written.
833
         * </p>
834
         *
835
         * <p>
836
         * After, invokes one of the three possible <i>transition</i> methods of
837
         * the <i>finite machine</i> of edition:
838
         * <ul>
839
         * <li><i>First transition type: <b>Point</i></b>: if <code>text</code>
840
         * matches with any pattern of parameters needed for any kind of point
841
         * coordinates.<br>
842
         * There are eight ways of introducing point 2D coordinates:
843
         * <ul>
844
         * <li><i>X,Y</i> : absolute cardinal 2D coordinate from the center
845
         * <i>(0,0)</i> of the CCS <i>Current Coordinate System</i>.</li>
846
         * <li><i>@X,Y</i> : relative cardinal 2D distances from the last point
847
         * added of the CCS. If it's the first point of the geometry, works like
848
         * <i>X,Y</i>.</li>
849
         * <li><i>length< angle</i> : absolute polar 2D coordinate from the
850
         * center <i>(0,0)</i> of the CCS <i>Current Coordinate System</i>, using
851
         * <i>angle</i> from the <i>X</i> axis of CCS, and <i>length</i> far
852
         * away.</li>
853
         * <li><i>@length< angle</i> : relative polar 2D coordinate from the last
854
         * point added of the CCS <i>Current Coordinate System</i>, using <i>angle</i>
855
         * from the <i>X</i> axis of CCS, and <i>length</i> far away. If it's the
856
         * first point of the geometry, works like <i>length< angle</i>.</li>
857
         * <li><i>*X,Y</i> : like <i>X,Y</i> but using UCS <i>Universal
858
         * Coordinate System</i> as reference.</li>
859
         * <li><i>@*X,Y</i> : like <i>@X,Y</i> but using UCS <i>Universal
860
         * Coordinate System</i> as reference. If it's the first point of the
861
         * geometry, works like <i>*X,Y</i>.</li>
862
         * <li><i>*length< angle</i> : like <i>length< angle</i> but using UCS
863
         * <i>Universal Coordinate System</i> as reference.</li>
864
         * <li><i>@*length< angle</i> : like <i>@length< angle</i> but using
865
         * UCS <i>Universal Coordinate System</i> as reference. If it's the first
866
         * point of the geometry, works like <i>*length< angle</i>.</li>
867
         * </ul>
868
         * </li>
869
         * <li><i>Second transition type: <b>Value</i></b>: if recognizes it as a
870
         * single number.</li>
871
         * <li><i>Third transition type: <b>Option</i></b>: by default, if can't
872
         * classify the information as a single number neither as a point. This
873
         * information will be an <code>String</code> and dealt as an option of
874
         * the current tool state. Ultimately, if isn't valid, <code>text</code>
875
         * will be rewritten in the console notifying the user that isn't correct.</li>
876
         * </ul>
877
         * </p>
878
         *
879
         * @param text
880
         *            command written by user in the edition's console
881
         */
882
        public void textEntered(String text) {
883
                if (text == null) {
884
                        transition(PluginServices.getText(this, "cancel"));
885
                } else {
886
                        /*
887
                         * if ("".equals(text)) { transition("aceptar"); } else {
888
                         */
889
                        text = text.trim();
890
                        int type = ABSOLUTE;
891
                        String[] numbers = new String[1];
892
                        numbers[0] = text;
893
                        if (text.indexOf(",") != -1) {
894

    
895
                                numbers = text.split(",");
896
                                if (numbers[0].substring(0, 1).equals("@")) {
897
                                        numbers[0] = numbers[0].substring(1, numbers[0].length());
898
                                        type = RELATIVE_SCU;
899
                                        if (numbers[0].substring(0, 1).equals("*")) {
900
                                                type = RELATIVE_SCP;
901
                                                numbers[0] = numbers[0].substring(1, numbers[0]
902
                                                                .length());
903
                                        }
904
                                }
905
                        } else if (text.indexOf("<") != -1) {
906
                                type = POLAR_SCP;
907
                                numbers = text.split("<");
908
                                if (numbers[0].substring(0, 1).equals("@")) {
909
                                        numbers[0] = numbers[0].substring(1, numbers[0].length());
910
                                        type = POLAR_SCU;
911
                                        if (numbers[0].substring(0, 1).equals("*")) {
912
                                                type = POLAR_SCP;
913
                                                numbers[0] = numbers[0].substring(1, numbers[0]
914
                                                                .length());
915
                                        }
916
                                }
917
                        }
918

    
919
                        double[] values = null;
920

    
921
                        try {
922
                                if (numbers.length == 2) {
923
                                        // punto
924
                                        values = new double[] { Double.parseDouble(numbers[0]),
925
                                                        Double.parseDouble(numbers[1]) };
926
                                        transition(values, null, type);
927
                                } else if (numbers.length == 1) {
928
                                        // valor
929
                                        values = new double[] { Double.parseDouble(numbers[0]) };
930
                                        transition(values[0]);
931
                                }
932
                        } catch (NumberFormatException e) {
933
                                transition(text);
934
                        } catch (NullPointerException e) {
935
                                transition(text);
936
                        }
937
                        // }
938
                }
939
                getMapControl().repaint();
940
        }
941

    
942
        /**
943
         * If there are options related with the <code>CADTool</code> at the peek
944
         * of the CAD tool stack, displays them as a popup.
945
         */
946
        public void configureMenu() {
947
                String[] desc = ((CADTool) cadToolStack.peek()).getDescriptions();
948
                // String[] labels = ((CADTool)
949
                // cadToolStack.peek()).getCurrentTransitions();
950
                CADExtension.clearMenu();
951

    
952
                for (int i = 0; i < desc.length; i++) {
953
                        if (desc[i] != null) {
954
                                CADExtension
955
                                                .addMenuEntry(PluginServices.getText(this, desc[i]));// ,
956
                                // labels[i]);
957
                        }
958
                }
959

    
960
        }
961

    
962
        /**
963
         * <p>
964
         * One of the three kind of transaction methods of the <i>finite machine</i>
965
         * of edition.
966
         * </p>
967
         *
968
         * <p>
969
         * This one deals <code>values</code> as two numbers that, according
970
         * <code>type</code> calculate a new point 2D in the current layer edited
971
         * in the associated <code>MapControl</code>.
972
         * </p>
973
         *
974
         * <p>
975
         * There are different ways of calculating the new point 2D coordinates,
976
         * according the value of <code>type</code>, see
977
         * {@link #textEntered(String) #textEntered(String)}.
978
         * </p>
979
         *
980
         * <p>
981
         * After applying the changes, updates the controls available for managing
982
         * the current data.
983
         * </p>
984
         *
985
         * @param values
986
         *            numbers needed to calculate the new point coordinates
987
         *            according <code>type</code>
988
         * @param event
989
         *            event which generated this invocation (a
990
         *            <code>MouseEvent</code> or a <code>KeyEvent</code>)
991
         * @param type
992
         *            kind of information that is <code>values</code>. According
993
         *            this parameter, will calculate the new point in a different
994
         *            way
995
         *
996
         * @see CADTool#transition(double, double, InputEvent)
997
         * @see #transition(double)
998
         * @see #transition(String)
999
         */
1000
        private void transition(double[] values, InputEvent event, int type) {
1001
                questionAsked = true;
1002
                if (!cadToolStack.isEmpty()) {
1003
                        CADTool ct = (CADTool) cadToolStack.peek();
1004

    
1005
                        switch (type) {
1006
                        case ABSOLUTE:
1007
                                ct.transition(values[0], values[1], event);
1008
                                previousPoint = values;
1009
                                break;
1010
                        case RELATIVE_SCU:
1011
                                // Comprobar que tenemos almacenado el punto anterior
1012
                                // y crear nuevo con coordenadas relativas a ?l.
1013
                                double[] auxSCU = values;
1014
                                if (previousPoint != null) {
1015
                                        auxSCU[0] = previousPoint[0] + values[0];
1016
                                        auxSCU[1] = previousPoint[1] + values[1];
1017
                                }
1018
                                ct.transition(auxSCU[0], auxSCU[1], event);
1019

    
1020
                                previousPoint = auxSCU;
1021
                                break;
1022
                        case RELATIVE_SCP:
1023
                                // TODO de momento no implementado.
1024
                                ct.transition(values[0], values[1], event);
1025
                                previousPoint = values;
1026
                                break;
1027
                        case POLAR_SCU:// Relativo
1028
                                // Comprobar que tenemos almacenado el punto anterior
1029
                                // y crear nuevo con coordenadas relativas a ?l.
1030
                                double[] auxPolarSCU = values;
1031
                                if (previousPoint != null) {
1032
                                        Point2D point = UtilFunctions.getPoint(new Point2D.Double(
1033
                                                        previousPoint[0], previousPoint[1]), Math
1034
                                                        .toRadians(values[1]), values[0]);
1035
                                        auxPolarSCU[0] = point.getX();
1036
                                        auxPolarSCU[1] = point.getY();
1037
                                        ct.transition(auxPolarSCU[0], auxPolarSCU[1], event);
1038
                                } else {
1039
                                        Point2D point = UtilFunctions.getPoint(new Point2D.Double(
1040
                                                        0, 0), Math.toRadians(values[1]), values[0]);
1041
                                        auxPolarSCU[0] = point.getX();
1042
                                        auxPolarSCU[1] = point.getY();
1043
                                        ct.transition(auxPolarSCU[0], auxPolarSCU[1], event);
1044
                                }
1045
                                previousPoint = auxPolarSCU;
1046
                                break;
1047
                        case POLAR_SCP:// Absoluto
1048
                                double[] auxPolarSCP = values;
1049
                                if (previousPoint != null) {
1050
                                        Point2D point = UtilFunctions.getPoint(new Point2D.Double(
1051
                                                        0, 0), Math.toRadians(values[1]), values[0]);
1052
                                        auxPolarSCP[0] = point.getX();
1053
                                        auxPolarSCP[1] = point.getY();
1054
                                        ct.transition(auxPolarSCP[0], auxPolarSCP[1], event);
1055
                                } else {
1056
                                        Point2D point = UtilFunctions.getPoint(new Point2D.Double(
1057
                                                        0, 0), values[1], values[0]);
1058
                                        auxPolarSCP[0] = point.getX();
1059
                                        auxPolarSCP[1] = point.getY();
1060
                                        ct.transition(auxPolarSCP[0], auxPolarSCP[1], event);
1061
                                }
1062
                                previousPoint = auxPolarSCP;
1063
                                break;
1064
                        default:
1065
                                break;
1066
                        }
1067
                        askQuestion();
1068
                }
1069
                configureMenu();
1070
                PluginServices.getMainFrame().enableControls();
1071
        }
1072

    
1073
        /**
1074
         * <p>
1075
         * One of the three kind of transaction methods of the <i>finite machine</i>
1076
         * of edition.
1077
         * </p>
1078
         *
1079
         * <p>
1080
         * This one deals <code>value</code> as a single number used as a
1081
         * parameter for the current tool state. Ultimately, if isn't valid,
1082
         * <code>number</code> will be rewritten in the console notifying the user
1083
         * that isn't correct.
1084
         * </p>
1085
         *
1086
         * <p>
1087
         * After applying the changes, updates the controls available for managing
1088
         * the current data.
1089
         * </p>
1090
         *
1091
         * @param value
1092
         *            value for the current tool state
1093
         *
1094
         * @see CADTool#transition(double)
1095
         * @see #transition(double[], InputEvent, int)
1096
         * @see #transition(String)
1097
         */
1098
        private void transition(double value) {
1099
                questionAsked = true;
1100
                if (!cadToolStack.isEmpty()) {
1101
                        CADTool ct = (CADTool) cadToolStack.peek();
1102
                        ct.transition(value);
1103
                        askQuestion();
1104
                }
1105
                configureMenu();
1106
                PluginServices.getMainFrame().enableControls();
1107
        }
1108

    
1109
        /**
1110
         * <p>
1111
         * One of the three kind of transaction methods of the <i>finite machine</i>
1112
         * of edition.
1113
         * </p>
1114
         *
1115
         * <p>
1116
         * This one deals <code>option</code> as an option of the current tool
1117
         * state. Ultimately, if isn't valid, <code>option</code> will be
1118
         * rewritten in the console notifying the user that isn't correct.
1119
         * </p>
1120
         *
1121
         * @param option
1122
         *            option for the current tool state
1123
         *
1124
         * @see CADTool#transition(String)
1125
         * @see #transition(double[], InputEvent, int)
1126
         * @see #transition(double)
1127
         */
1128
        public void transition(String option) {
1129
                questionAsked = true;
1130
                if (!cadToolStack.isEmpty()) {
1131
                        CADTool ct = (CADTool) cadToolStack.peek();
1132
                        try {
1133
                                ct.transition(option);
1134
                        } catch (Exception e) {
1135
                                IWindow window = PluginServices.getMDIManager()
1136
                                                .getActiveWindow();
1137

    
1138
                                if (window instanceof View) {
1139
                                        ((View) window).getConsolePanel().addText(
1140
                                                        "\n"
1141
                                                                        + PluginServices.getText(this,
1142
                                                                                        "incorrect_option") + " : "
1143
                                                                        + option, JConsole.ERROR);
1144
                                }
1145
                        }
1146
                        askQuestion();
1147
                }
1148
                configureMenu();
1149
                PluginServices.getMainFrame().enableControls();
1150
        }
1151

    
1152
        /**
1153
         * Shows or hides a grid on the <code>ViewPort</code> of the associated
1154
         * <code>MapControl</code>.
1155
         *
1156
         * @param value
1157
         *            <code>true</code> to make the grid visible;
1158
         *            <code>false</code> to make it invisible
1159
         */
1160
        // public void setGridVisibility(boolean value) {
1161
        // getGrid().setShowGrid(value);
1162
        // getGrid().setViewPort(getMapControl().getViewPort());
1163
        // getMapControl().repaint();
1164
        // }
1165
        // /**
1166
        // * Sets the snap tools enabled or disabled.
1167
        // *
1168
        // * @param activated <code>true</code> to enable the snap tools;
1169
        // <code>false</code> to disable them
1170
        // *
1171
        // * @see #isRefentEnabled()
1172
        // */
1173
        // public void setRefentEnabled(boolean activated) {
1174
        // bRefent = activated;
1175
        // }
1176
        //
1177
        // /**
1178
        // * Determines if snap tools are enabled or disabled.
1179
        // *
1180
        // * @return <code>true</code> to enable the snap tools; <code>false</code>
1181
        // to disable them
1182
        // *
1183
        // * @see #setRefentEnabled(boolean)
1184
        // */
1185
        // public boolean isRefentEnabled()
1186
        // {
1187
        // return bRefent;
1188
        // }
1189
        /*
1190
         * (non-Javadoc)
1191
         *
1192
         * @see com.iver.cit.gvsig.fmap.tools.Behavior.Behavior#getListener()
1193
         */
1194
        public ToolListener getListener() {
1195
                return new ToolListener() {
1196
                        /**
1197
                         * @see com.iver.cit.gvsig.fmap.tools.Listeners.ToolListener#getCursor()
1198
                         */
1199
                        public Image getImageCursor() {
1200
                                return imageCursor;
1201
                        }
1202

    
1203
                        /**
1204
                         * @see com.iver.cit.gvsig.fmap.tools.Listeners.ToolListener#cancelDrawing()
1205
                         */
1206
                        public boolean cancelDrawing() {
1207
                                return false;
1208
                        }
1209
                };
1210
        }
1211

    
1212
        /**
1213
         * Returns the {@link CADTool CADTool} at the top of the stack without
1214
         * removing it from the CAD tool stack.
1215
         *
1216
         * @return the {@link CADTool CADTool} at the top of the stack
1217
         *
1218
         * @see #pushCadTool(CADTool)
1219
         * @see #popCadTool()
1220
         * @see #setCadTool(CADTool)
1221
         */
1222
        public CADTool getCadTool() {
1223
                return (CADTool) cadToolStack.peek();
1224
        }
1225

    
1226
        /**
1227
         * <p>
1228
         * Pushes a {@link CADTool CADTool} onto the top of the CAD tool stack, and
1229
         * sets it as current.
1230
         * </p>
1231
         *
1232
         * @param cadTool
1233
         *            CAD tool to enable as current
1234
         *
1235
         * @see #getCadTool()
1236
         * @see #popCadTool()
1237
         * @see #setCadTool(CADTool)
1238
         */
1239
        public void pushCadTool(CADTool cadTool) {
1240
                cadToolStack.push(cadTool);
1241
                cadTool.setCadToolAdapter(this);
1242
                // cadTool.initializeStatus();
1243
                // cadTool.setVectorialAdapter(vea);
1244
                /*
1245
                 * int ret = cadTool.transition(null, editableFeatureSource, selection,
1246
                 * new double[0]);
1247
                 *
1248
                 * if ((ret & Automaton.AUTOMATON_FINISHED) ==
1249
                 * Automaton.AUTOMATON_FINISHED) { popCadTool();
1250
                 *
1251
                 * if (cadToolStack.isEmpty()) { pushCadTool(new
1252
                 * com.iver.cit.gvsig.gui.cad.smc.gen.CADTool());//new
1253
                 * SelectionCadTool());
1254
                 * PluginServices.getMainFrame().setSelectedTool("selection"); }
1255
                 *
1256
                 * askQuestion();
1257
                 *
1258
                 * getMapControl().drawMap(false); }
1259
                 */
1260
        }
1261

    
1262
        /**
1263
         * Removes the peek of the CAD tool stack.
1264
         *
1265
         * @see #pushCadTool(CADTool)
1266
         * @see #getCadTool()
1267
         * @see #setCadTool(CADTool)
1268
         */
1269
        public void popCadTool() {
1270
                cadToolStack.pop();
1271
        }
1272

    
1273
        /**
1274
         * <p>
1275
         * Displays at the console associated to the current active view that's
1276
         * being edited, the question of the following operation that user can do
1277
         * with the current <code>CADTool</code>, only if it hasn't just
1278
         * answered.
1279
         * </p>
1280
         *
1281
         * <p>
1282
         * The format of the question will be according the following pattern:<br>
1283
         * "\n#"<i>{cadtool at CAD tool stack peek}</i>.getQuestion()">"
1284
         * </p>
1285
         */
1286
        public void askQuestion() {
1287
                CADTool cadtool = (CADTool) cadToolStack.peek();
1288
                /*
1289
                 * if (cadtool..getStatus()==0){
1290
                 * PluginServices.getMainFrame().addTextToConsole("\n"
1291
                 * +cadtool.getName()); }
1292
                 */
1293
                if (PluginServices.getMDIManager().getActiveWindow() instanceof View) {
1294
                        View vista = (View) PluginServices.getMDIManager()
1295
                                        .getActiveWindow();
1296
                        String question = cadtool.getQuestion();
1297
                        if (lastQuestion == null || !(lastQuestion.equals(question))
1298
                                        || questionAsked) {
1299
                                vista.getConsolePanel().addText("\n" + "#" + question + " > ",
1300
                                                JConsole.MESSAGE);
1301
                                // ***PluginServices.getMainFrame().addTextToConsole("\n" +
1302
                                // cadtool.getQuestion());
1303
                                questionAsked = false;
1304
                        }
1305
                        lastQuestion = question;
1306
                }
1307

    
1308
        }
1309

    
1310
        /**
1311
         * Empties the CAD tools stack and pushes <code>cadTool</code> in it.
1312
         *
1313
         * @param cadTool
1314
         *            CAD tool to set at the peek of the stack
1315
         *
1316
         * @see #pushCadTool(CADTool)
1317
         * @see #popCadTool()
1318
         * @see #getCadTool()
1319
         */
1320
        public void setCadTool(CADTool cadTool) {
1321
                cadToolStack.clear();
1322
                pushCadTool(cadTool);
1323
                // askQuestion();
1324
        }
1325

    
1326
        /**
1327
         * <p>
1328
         * Removes all geometries selected in the associated <code>MapControl</code>.
1329
         */
1330
        public void delete() {
1331
                ILayerEdited aux = CADExtension.getEditionManager()
1332
                                .getActiveLayerEdited();
1333
                if (!(aux instanceof VectorialLayerEdited)) {
1334
                        return;
1335
                }
1336
                VectorialLayerEdited vle = (VectorialLayerEdited) aux;
1337
                FeatureStore featureStore = null;
1338
                try {
1339
                        featureStore = ((FLyrVect) vle.getLayer()).getFeatureStore();
1340
                } catch (ReadException e1) {
1341
                        // TODO Auto-generated catch block
1342
                        e1.printStackTrace();
1343
                }
1344
                String description = PluginServices.getText(this, "remove_geometry");
1345
                try {
1346
                        featureStore.beginEditingGroup(description);
1347

    
1348
                        FeatureSet selection = (FeatureSet) featureStore.getSelection();
1349
                        DisposableIterator iterator = selection.iterator();
1350
                        while (iterator.hasNext()) {
1351
                                Feature feature = (Feature) iterator.next();
1352
                                featureStore.delete(feature);
1353
                        }
1354
                        iterator.dispose();
1355
                        // int[] indexesToDel = new int[selection.cardinality()];
1356
                        // int j = 0;
1357
                        // for (int i = selection.nextSetBit(0); i >= 0; i = selection
1358
                        // .nextSetBit(i + 1)) {
1359
                        // indexesToDel[j++] = i;
1360
                        // // /vea.removeRow(i);
1361
                        // }
1362

    
1363
                        // ArrayList selectedRow = vle.getSelectedRow();
1364
                        //
1365
                        // int[] indexesToDel = new int[selectedRow.size()];
1366
                        // for (int i = 0;i < selectedRow.size(); i++) {
1367
                        // IRowEdited edRow = (IRowEdited) selectedRow.get(i);
1368
                        // indexesToDel[i] = vea.getInversedIndex(edRow.getIndex());
1369
                        // }
1370
                        //
1371
                        // for (int i = indexesToDel.length - 1; i >= 0; i--) {
1372
                        // vea.removeRow(indexesToDel[i], PluginServices.getText(this,
1373
                        // "deleted_feature"),EditionEvent.GRAPHIC);
1374
                        // }
1375
                        System.out.println("clear Selection");
1376
                        vle.clearSelection();
1377
                } catch (ReadException e) {
1378
                        NotificationManager.addError(e.getMessage(), e);
1379
                } catch (DataException e) {
1380
                        NotificationManager.addError(e.getMessage(), e);
1381
                } finally {
1382
                        try {
1383
                                featureStore.endEditingGroup();
1384
                        } catch (NeedEditingModeException e) {
1385
                                // TODO Auto-generated catch block
1386
                                e.printStackTrace();
1387
                        }
1388
                }
1389

    
1390
                /*
1391
                 * if (getCadTool() instanceof SelectionCADTool) { SelectionCADTool
1392
                 * selTool = (SelectionCADTool) getCadTool(); selTool.clearSelection(); }
1393
                 */
1394
                refreshEditedLayer();
1395
        }
1396

    
1397
        /**
1398
         * @see CADGrid#setAdjustGrid(boolean)
1399
         */
1400
        // public void setAdjustGrid(boolean b) {
1401
        // getGrid().setAdjustGrid(b);
1402
        // }
1403
        /**
1404
         * <p>
1405
         * Responds to actions of writing common key commands for all kind of CAD
1406
         * operations, enabling/disabling after the controls to manage the available
1407
         * information according the tool selected:
1408
         * <ul>
1409
         * <li><i>eliminar</i>: removes the geometries that are now selected.</li>
1410
         * <li><i>escape</i>: executes different actions according to the current
1411
         * CAD tool of the associated <code>MapControl</code>:
1412
         * <ul>
1413
         * <li>If the tool enabled is identified by <i>cadtooladapter</i>: empties
1414
         * the CAD tools stack, changing the current tool by a
1415
         * {@link SelectionCADTool SelectionCADTool}, which is identified by
1416
         * <i>_selection</i> and allows select features of the active vector layer
1417
         * of the associated <code>MapControl</code> instance. </li>
1418
         * <li>Otherwise, that means current associated <code>MapControl</code>
1419
         * instance isn't identified by "<i>cadtooladapter</i>", changes the
1420
         * enabled tool by the previous.</li>
1421
         * </ul>
1422
         * </li>
1423
         * </ul>
1424
         * </p>
1425
         *
1426
         * @param actionCommand
1427
         *            identifier of the key action command executed by the user
1428
         *
1429
         * @see SelectionCADTool
1430
         * @see MapControl#setPrevTool()
1431
         */
1432
        public void keyPressed(String actionCommand) {
1433
                if (CADExtension.getEditionManager().getActiveLayerEdited() == null) {
1434
                        return;
1435
                }
1436
                if (actionCommand.equals("eliminar")) {
1437
                        delete();
1438
                } else if (actionCommand.equals("escape")) {
1439
                        if (getMapControl().getCurrentTool().equals("cadtooladapter")) {
1440
                                CADTool ct = (CADTool) cadToolStack.peek();
1441
                                ct.end();
1442
                                cadToolStack.clear();
1443
                                SelectionCADTool selCad = new SelectionCADTool();
1444
                                selCad.init();
1445
                                VectorialLayerEdited vle = (VectorialLayerEdited) CADExtension
1446
                                                .getEditionManager().getActiveLayerEdited();
1447
                                try {
1448
                                        vle.clearSelection();
1449
                                } catch (DataException e) {
1450
                                        NotificationManager.addError(e.getMessage(), e);
1451
                                }
1452

    
1453
                                pushCadTool(selCad);
1454
                                // getVectorialAdapter().getSelection().clear();
1455

    
1456
                                refreshEditedLayer();
1457

    
1458
                                PluginServices.getMainFrame().setSelectedTool("_selection");
1459
                                // askQuestion();
1460
                        } else {
1461
                                getMapControl().setPrevTool();
1462
                        }
1463
                }
1464

    
1465
                PluginServices.getMainFrame().enableControls();
1466

    
1467
        }
1468

    
1469
        /**
1470
         * <p>
1471
         * Applies a lightweight repaint of the active layer being edited.
1472
         * </p>
1473
         *
1474
         * <p>
1475
         * All layers under it won't be drawn, only the upper one and whose are over
1476
         * that layer in the TOC.
1477
         * </p>
1478
         *
1479
         * @see MapControl#rePaintDirtyLayers()
1480
         */
1481
        public void refreshEditedLayer() {
1482
                ILayerEdited edLayer = CADExtension.getEditionManager()
1483
                                .getActiveLayerEdited();
1484
                if (edLayer != null) {
1485
                        getMapControl().rePaintDirtyLayers();
1486
                }
1487

    
1488
        }
1489

    
1490
        /**
1491
         * Gets the {@link CADGrid CADGrid} that can be drawn on the
1492
         * <code>ViewPort</code> of the associated <code>MapControl</code>.
1493
         *
1494
         * @return reference to the <i>grid</i> that can be applied on the
1495
         *         <code>ViewPort</code>
1496
         *
1497
         * @see #setGridVisibility(boolean)
1498
         */
1499
        // public CADGrid getGrid() {
1500
        // return cadgrid;
1501
        // }
1502
        /**
1503
         * Determines if is enabled or not the <i>orto</i> mode.
1504
         *
1505
         * @return <code>true</code> if is enabled the <i>orto</i> mode;
1506
         *         otherwise <code>false</code>
1507
         *
1508
         * @see #setOrtoMode(boolean)
1509
         */
1510
        public boolean isOrtoMode() {
1511
                return bOrtoMode;
1512
        }
1513

    
1514
        /**
1515
         * Enables / disables the <i>orto</i> mode.
1516
         *
1517
         * @param b
1518
         *            the desired value
1519
         *
1520
         * @see #isOrtoMode()
1521
         */
1522
        public void setOrtoMode(boolean b) {
1523
                bOrtoMode = b;
1524
        }
1525

    
1526
        /**
1527
         * Associates and stores the specified name with the specified
1528
         * {@link CADTool CADTool}.
1529
         *
1530
         * @param name
1531
         *            name of the tool
1532
         * @param c
1533
         *            CAD tool to interactuate editing the layers
1534
         *
1535
         * @see #getCADTools()
1536
         * @see #getCADTool(String)
1537
         */
1538
        public static void addCADTool(String name, CADTool c) {
1539
                namesCadTools.put(name, c);
1540

    
1541
        }
1542

    
1543
        /**
1544
         * Gets all CAD tools available to edit layers with this tool listener.
1545
         *
1546
         * @return CAD tools available to edit layers with this tool listener
1547
         *
1548
         * @see #addCADTool(String, CADTool)
1549
         * @see #getCADTool(String)
1550
         */
1551
        public static CADTool[] getCADTools() {
1552
                return (CADTool[]) CADToolAdapter.namesCadTools.values().toArray(
1553
                                new CADTool[0]);
1554
        }
1555

    
1556
        /**
1557
         * Returns the {@link CADTool CADTool} to which the specified name is
1558
         * mapped.
1559
         *
1560
         * @param text
1561
         *            name of the tool
1562
         * @return the CAD tool whose associated name is to be returned
1563
         *
1564
         * @see #addCADTool(String, CADTool)
1565
         * @see #getCADTools()
1566
         */
1567
        public CADTool getCADTool(String text) {
1568
                CADTool ct = (CADTool) namesCadTools.get(text);
1569
                return ct;
1570
        }
1571

    
1572
        /**
1573
         * Gets the object used to manage the edition of the layers of the
1574
         * associated <code>MapControl</code>.
1575
         *
1576
         * @see EditionManager
1577
         *
1578
         * @return object used to manage the edition of the layers
1579
         */
1580
        public EditionManager getEditionManager() {
1581
                return editionManager;
1582
        }
1583

    
1584
        /**
1585
         * <p>
1586
         * Initializes the <i>flatness</i> with the defined in preferences.
1587
         * </p>
1588
         *
1589
         * <p>
1590
         * The <i>flatness</i> is the maximum tolerance used to approximate curved
1591
         * lines in a <i>shape</i> by polylines.
1592
         * </p>
1593
         * <p>
1594
         * The shapes doesn't support primitive like arcs neither other curved lines
1595
         * to draw their geometries, then for drawing any kind of this geometries
1596
         * the curved lines are drawn approximately by a polyline. And for doing
1597
         * more realistic that curves, is used the <i>flatness</i> parameter, that
1598
         * indicates that the difference between each arc and the straight segment
1599
         * that approximates it must be in the worse case, like the <i>flatness</i>.
1600
         * </p>
1601
         *
1602
         * @see FConverter#FLATNESS
1603
         */
1604
        public void initializeFlatness() {
1605
                if (!flatnessInitialized) {
1606
                        flatnessInitialized = true;
1607
                        Preferences prefs = Preferences.userRoot().node("cadtooladapter");
1608
                        double flatness = prefs.getDouble("flatness", Converter.FLATNESS);
1609
                        Converter.FLATNESS = flatness;
1610
                }
1611
        }
1612

    
1613
        /**
1614
         * <p>
1615
         * Updates the grid on the <code>ViewPort</code> of the associated
1616
         * <code>MapControl</code> object according the values in the
1617
         * {@link com.iver.cit.gvsig.gui.cad.CADToolAdapter.prefs.Preferences com.iver.cit.gvsig.gui.cad.CADToolAdapter.prefs.Preferences}.
1618
         * </p>
1619
         *
1620
         * <p>
1621
         * The preferences are:
1622
         * <ul>
1623
         * <li>Show/hide the grid.</li>
1624
         * <li>Adjust or not the grid.</li>
1625
         * <li>Horizontal ( X ) line separation.</li>
1626
         * <li>Vertical ( Y ) line separation.</li>
1627
         * </ul>
1628
         * </p>
1629
         */
1630
        // public void initializeGrid(){
1631
        // boolean showGrid =
1632
        // prefs.getBoolean("grid.showgrid",getGrid().isShowGrid());
1633
        // boolean adjustGrid =
1634
        // prefs.getBoolean("grid.adjustgrid",getGrid().isAdjustGrid());
1635
        //
1636
        // double dx = prefs.getDouble("grid.distancex",getGrid().getGridSizeX());
1637
        // double dy = prefs.getDouble("grid.distancey",getGrid().getGridSizeY());
1638
        //
1639
        // setGridVisibility(showGrid);
1640
        // setAdjustGrid(adjustGrid);
1641
        // getGrid().setGridSizeX(dx);
1642
        // getGrid().setGridSizeY(dy);
1643
        // }
1644
        /**
1645
         * <p>
1646
         * Returns the type of the shape that's the current active and vector layer
1647
         * being edited.
1648
         * </p>
1649
         *
1650
         * @see FLyrVect#getShapeType()
1651
         *
1652
         * @return type of the shape that's the current active and vector layer
1653
         *         being edited
1654
         */
1655
        public int getActiveLayerType() {
1656
                int type = Geometry.TYPES.GEOMETRY;
1657
                try {
1658
                        type = ((FLyrVect) CADExtension.getEditionManager()
1659
                                        .getActiveLayerEdited().getLayer()).getShapeType();
1660
                } catch (ReadException e) {
1661
                        NotificationManager.addError(e);
1662
                }
1663
                return type;
1664
        }
1665

    
1666
}