Statistics
| Revision:

root / branches / v2_0_0_prep / extensions / extEditing / src / org / gvsig / editing / gui / cad / CADToolAdapter.java @ 38520

History | View | Annotate | Download (58.7 KB)

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

    
24
import java.awt.Color;
25
import java.awt.Cursor;
26
import java.awt.Graphics;
27
import java.awt.Image;
28
import java.awt.Point;
29
import java.awt.Toolkit;
30
import java.awt.event.InputEvent;
31
import java.awt.event.MouseEvent;
32
import java.awt.event.MouseWheelEvent;
33
import java.awt.geom.Point2D;
34
import java.awt.image.BufferedImage;
35
import java.awt.image.MemoryImageSource;
36
import java.util.HashMap;
37
import java.util.Stack;
38
import java.util.prefs.Preferences;
39

    
40
import org.cresques.cts.IProjection;
41
import org.slf4j.Logger;
42
import org.slf4j.LoggerFactory;
43

    
44
import org.gvsig.andami.PluginServices;
45
import org.gvsig.andami.messages.NotificationManager;
46
import org.gvsig.andami.ui.mdiFrame.MainFrame;
47
import org.gvsig.andami.ui.mdiManager.IWindow;
48
import org.gvsig.app.project.documents.view.gui.DefaultViewPanel;
49
import org.gvsig.app.project.documents.view.toolListeners.StatusBarListener;
50
import org.gvsig.editing.CADExtension;
51
import org.gvsig.editing.EditionManager;
52
import org.gvsig.editing.gui.cad.tools.SelectionCADTool;
53
import org.gvsig.editing.layers.ILayerEdited;
54
import org.gvsig.editing.layers.VectorialLayerEdited;
55
import org.gvsig.fmap.dal.exception.DataException;
56
import org.gvsig.fmap.dal.exception.ReadException;
57
import org.gvsig.fmap.dal.feature.Feature;
58
import org.gvsig.fmap.dal.feature.FeatureSelection;
59
import org.gvsig.fmap.dal.feature.FeatureSet;
60
import org.gvsig.fmap.dal.feature.FeatureStore;
61
import org.gvsig.fmap.dal.feature.exception.NeedEditingModeException;
62
import org.gvsig.fmap.geom.Geometry;
63
import org.gvsig.fmap.geom.type.GeometryType;
64
import org.gvsig.fmap.geom.util.UtilFunctions;
65
import org.gvsig.fmap.mapcontext.MapContext;
66
import org.gvsig.fmap.mapcontext.MapContextLocator;
67
import org.gvsig.fmap.mapcontext.MapContextManager;
68
import org.gvsig.fmap.mapcontext.ViewPort;
69
import org.gvsig.fmap.mapcontext.layers.vectorial.FLyrVect;
70
import org.gvsig.fmap.mapcontext.rendering.symbols.ISymbol;
71
import org.gvsig.fmap.mapcontrol.MapControl;
72
import org.gvsig.fmap.mapcontrol.MapControlDrawer;
73
import org.gvsig.fmap.mapcontrol.tools.BehaviorException;
74
import org.gvsig.fmap.mapcontrol.tools.Behavior.Behavior;
75
import org.gvsig.fmap.mapcontrol.tools.Listeners.ToolListener;
76
import org.gvsig.tools.dispose.DisposableIterator;
77
import org.gvsig.utils.console.JConsole;
78

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

    
143
    private static Logger logger = LoggerFactory
144
        .getLogger(CADToolAdapter.class);
145

    
146
    /**
147
     * Stores the CAD tools to edit the layers of the associated
148
     * <code>MapControl</code>.
149
     * 
150
     * @see #addCADTool(String, CADTool)
151
     * @see #getCadTool()
152
     * @see #getCADTool(String)
153
     */
154
    private static HashMap namesCadTools = new HashMap();
155

    
156
    /**
157
     * Reference to the object used to manage the edition of the layers of the
158
     * associated <code>MapControl</code>.
159
     * 
160
     * @see EditionManager
161
     * @see #getEditionManager()
162
     */
163
    private EditionManager editionManager = new EditionManager();
164

    
165
    /**
166
     * Reference to the MapContext library manager, used to create symbols
167
     * and legends.
168
     */
169
    private MapContextManager mapContextManager = MapContextLocator
170
        .getMapContextManager();
171

    
172
    /**
173
     * Identifies that the data are absolute coordinates of the new point from
174
     * the (0, 0) position.
175
     */
176
    public static final int ABSOLUTE = 0;
177

    
178
    /**
179
     * Equivalent to {@link CADToolAdapter#ABSOLUTE CADToolAdapter#ABSOLUTE}.
180
     */
181
    public static final int RELATIVE_SCP = 1;
182

    
183
    /**
184
     * Identifies that the data are relative distances of the new point from the
185
     * previous introduced.
186
     */
187
    public static final int RELATIVE_SCU = 2;
188

    
189
    /**
190
     * Identifies that the data are relative polar distances (longitude of the
191
     * line and angle given in degrees) of the new point from the previous
192
     * introduced.
193
     */
194
    public static final int POLAR_SCP = 3;
195

    
196
    /**
197
     * Identifies that the data are relative polar distances (longitude of the
198
     * line and angle given in radians) of the new point from the previous
199
     * introduced.
200
     */
201
    public static final int POLAR_SCU = 4;
202

    
203
    /**
204
     * Stores the 2D map coordinates of the last point added.
205
     */
206
    private double[] previousPoint = null;
207

    
208
    /**
209
     * <i>Stack with CAD tools.</i>
210
     * 
211
     * <i>For each CAD tool we use, the last item added in this stack will
212
     * display a different icon according to the current operation and its
213
     * status.</i>
214
     */
215
    private Stack cadToolStack = new Stack();
216

    
217
    /**
218
     * X coordinate of the last dragging or moving mouse event.
219
     */
220
    private int lastX;
221

    
222
    /**
223
     * Y coordinate of the last dragging or moving mouse event.
224
     */
225
    private int lastY;
226

    
227
    /**
228
     * Unused attribute.
229
     */
230
    private ISymbol symbol = mapContextManager.getSymbolManager().createSymbol(
231
        Geometry.TYPES.POINT, Color.RED);
232

    
233
    /**
234
     * Represents the cursor's point selected in <i>map coordinates</i>.
235
     * 
236
     * @see MapControl#toMapPoint
237
     */
238
    private Point2D mapAdjustedPoint;
239

    
240
    /**
241
     * Kind of geometry drawn to identify the kind of control point selected by
242
     * the cursor's mouse.
243
     */
244
    // private ISnapper usedSnap = null;
245
    /**
246
     * Determines if has displayed at the edition console, the question for the
247
     * operations that can do the user with the current CAD tool, in its current
248
     * state.
249
     */
250
    private boolean questionAsked = false;
251

    
252
    /**
253
     * Represents the cursor's point selected in <i>screen coordinates</i>.
254
     * 
255
     * @see ViewPort#fromMapPoint(Point2D)
256
     */
257
    private Point2D adjustedPoint;
258

    
259
    /**
260
     * Determines if the snap tools are enabled or disabled.
261
     * 
262
     * @see #isRefentEnabled()
263
     * @see #setRefentEnabled(boolean)
264
     */
265
    // private boolean bRefent = true;
266
    /**
267
     * <p>
268
     * Determines if the position of the snap of the mouse's cursor on the
269
     * <code>MapControl</code> is within the area around a control point of a
270
     * geometry.
271
     * </p>
272
     * 
273
     * <p>
274
     * The area is calculated as a circle centered at the control point and with
275
     * radius the pixels tolerance defined in the preferences.
276
     * </p>
277
     */
278
    // private boolean bForceCoord = false;
279
    /**
280
     * Optional grid that could be applied on the <code>MapControl</code>'s
281
     * view port.
282
     * 
283
     * @see #getGrid()
284
     * @see #setAdjustGrid(boolean)
285
     */
286
    // private CADGrid cadgrid = new CADGrid();
287
    /**
288
     * Determines is is enabled or not the <i>Orto</i> mode.
289
     */
290
    private boolean bOrtoMode;
291

    
292
    /**
293
     * A light yellow color for the tool tip text box associated to the point
294
     * indicated by the mouse's cursor.
295
     */
296
    private Color theTipColor = new Color(255, 255, 155);
297

    
298
    /**
299
     * Last question asked to the user in the CAD console.
300
     */
301
    private Object lastQuestion;
302

    
303
    /**
304
     * Maximum tolerance in the approximation of a curved line by a polyline.
305
     * 
306
     * @see #initializeFlatness()
307
     */
308
    private static boolean flatnessInitialized = false;
309

    
310
    /**
311
     * Listener to display the coordinates in the current application's status
312
     * bar.
313
     */
314
    private StatusBarListener sbl = null;
315

    
316
    /*
317
     * (non-Javadoc)
318
     * 
319
     * @see
320
     * com.iver.cit.gvsig.fmap.tools.Behavior.Behavior#setMapControl(com.iver
321
     * .cit.gvsig.fmap.MapControl)
322
     */
323
    public void setMapControl(MapControl mc) {
324
        super.setMapControl(mc);
325
        sbl = new StatusBarListener(getMapControl());
326
    }
327

    
328
    private static final Image imageCursor = new BufferedImage(32, 32,
329
        BufferedImage.TYPE_INT_ARGB);
330
    static {
331
        Graphics g = imageCursor.getGraphics();
332
        int size1 = 15;
333
        int size2 = 3;
334
        int x = 16;
335
        int y = 16;
336
        g.setColor(Color.MAGENTA);
337
        g.drawLine((x - size1), (y), (x + size1), (y));
338
        g.drawLine((x), (y - size1), (x), (y + size1));
339
        // g.setColor(Color.MAGENTA);
340
        g.drawRect((x - 6), (y - 6), 12, 12);
341
        g.drawRect((x - 3), (y - 3), 6, 6);
342

    
343
        // // getMapControl().setToolTipText(null);
344
        // if (adjustedPoint != null) {
345
        // if (bForceCoord) {
346
        // /* g.setColor(Color.ORANGE);
347
        // g.drawRect((int) (adjustedPoint.getX() - 6),
348
        // (int) (adjustedPoint.getY() - 6), 12, 12);
349
        // g.drawRect((int) (adjustedPoint.getX() - 3),
350
        // (int) (adjustedPoint.getY() - 3), 6, 6);
351
        // g.setColor(Color.MAGENTA);
352
        // g.drawRect((int) (adjustedPoint.getX() - 4),
353
        // (int) (adjustedPoint.getY() - 4), 8, 8); */
354
        // if (usedSnap != null)
355
        // {
356
        // usedSnap.draw(g, adjustedPoint);
357
        //
358
        // Graphics2D g2 = (Graphics2D) g;
359
        // FontMetrics metrics = g2.getFontMetrics();
360
        // int w = metrics.stringWidth(usedSnap.getToolTipText()) + 5;
361
        // int h = metrics.getMaxAscent() + 5;
362
        // int x = (int)p.getX()+9;
363
        // int y = (int)p.getY()- 7;
364
        //
365
        // g2.setColor(theTipColor );
366
        // g2.fillRect(x, y-h, w, h);
367
        // g2.setColor(Color.BLACK);
368
        // g2.drawRect(x, y-h, w, h);
369
        // g2.drawString(usedSnap.getToolTipText(), x+3, y-3);
370
        //
371
        //
372
        // // getMapControl().setToolTipText(usedSnap.getToolTipText());
373
        // }
374
        //
375
        // bForceCoord = false;
376
        // } else {
377
        // g.drawRect((int) (p.getX() - size2), (int) (p.getY() - size2),
378
        // (int) (size2 * 2), (int) (size2 * 2));
379
        // }
380
        // }
381

    
382
    }
383

    
384
    /**
385
     * <p>
386
     * Draws the selected geometries to edit. And, if the <i>snapping</i> is
387
     * enabled, draws also its effect over them.
388
     * </p>
389
     * 
390
     * @see com.iver.cit.gvsig.fmap.tools.Behavior.Behavior#paintComponent(java.awt.Graphics)
391
     */
392
    public void paintComponent(MapControlDrawer mapControlDrawer) {
393
        super.paintComponent(mapControlDrawer);
394
        if (CADExtension.getCADToolAdapter() != this) {
395
            return;
396
        }
397

    
398
        if (adjustedPoint != null) {
399
            Point2D p = null;
400
            
401
            p = getMapControl().getViewPort().toMapPoint(adjustedPoint);
402
            /*
403
             * We are going to draw.
404
             * Is mapAdjustedPoint better in any situation?
405
             * 
406
            if (mapAdjustedPoint != null) {
407
                p = mapAdjustedPoint;
408
            } else {
409
                p = getMapControl().getViewPort().toMapPoint(adjustedPoint);
410
            }
411
            */
412

    
413
            // If the stack is empty, return
414
            if (cadToolStack.isEmpty()) {
415
                return;
416
            }
417

    
418
            if (((CADTool) cadToolStack.peek()).getVLE() == null) {
419
                return;
420
            }
421

    
422
            ((CADTool) cadToolStack.peek()).drawOperation(mapControlDrawer,
423
                p.getX(), p.getY());
424
        }
425
    }
426

    
427
    /**
428
     * <p>
429
     * Responds two kind of mouse click events:
430
     * <ul>
431
     * <li><b><i>One click of the third mouse's button</i></b>: displays a popup
432
     * with edition options.</li>
433
     * <li><b><i>Two clicks of the first mouse's button</i></b>: ends the last
434
     * cad tool setting as end transition point the event's one.</li>
435
     * </ul>
436
     * </p>
437
     * 
438
     * 
439
     * @see com.iver.cit.gvsig.fmap.tools.Behavior.Behavior#mouseClicked(java.awt.event.MouseEvent)
440
     * @see CADExtension#showPopup(MouseEvent)
441
     */
442
    public void mouseClicked(MouseEvent e) throws BehaviorException {
443
        if (e.getButton() == MouseEvent.BUTTON3) {
444
            CADExtension.showPopup(e);
445
        } else
446
            if (e.getButton() == MouseEvent.BUTTON1 && e.getClickCount() == 2) {
447
                questionAsked = true;
448
                if (!cadToolStack.isEmpty()) {
449
                    CADTool ct = (CADTool) cadToolStack.peek();
450
                    ViewPort vp = getMapControl().getMapContext().getViewPort();
451
                    Point2D p;
452

    
453
                    if (mapAdjustedPoint != null) {
454
                        p = mapAdjustedPoint;
455
                    } else {
456
                        p = vp.toMapPoint(adjustedPoint);
457
                    }
458
                    ct.endTransition(p.getX(), p.getY(), e);
459
                    previousPoint = new double[] { p.getX(), p.getY() };
460
                }
461
            }
462
    }
463

    
464
    /*
465
     * (non-Javadoc)
466
     * 
467
     * @see
468
     * com.iver.cit.gvsig.fmap.tools.Behavior.Behavior#mouseEntered(java.awt
469
     * .event.MouseEvent)
470
     */
471
    public void mouseEntered(MouseEvent e) throws BehaviorException {
472
        clearMouseImage();
473
    }
474

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

    
485
    /**
486
     * Selects the vertex of a geometry at the point selected on the
487
     * <code>MapControl</code> by pressing the first mouse's button.
488
     * 
489
     * @see com.iver.cit.gvsig.fmap.tools.Behavior.Behavior#mousePressed(java.awt.event.MouseEvent)
490
     */
491
    public void mousePressed(MouseEvent e) throws BehaviorException {
492
        if (e.getButton() == MouseEvent.BUTTON1) {
493
            ViewPort vp = getMapControl().getMapContext().getViewPort();
494
            Point2D p;
495
            mapAdjustedPoint = getMapControl().getMapAdjustedPoint();
496
            if (mapAdjustedPoint != null) {
497
                p = mapAdjustedPoint;
498
            } else {
499
                p = vp.toMapPoint(adjustedPoint);
500
            }
501
            transition(new double[] { p.getX(), p.getY() }, e, ABSOLUTE);
502
        }
503
    }
504

    
505
    // /**
506
    // * <p>Adjusts the <code>point</code> to the grid if its enabled, and
507
    // * sets <code>mapHandlerAdjustedPoint</code> with that new value.</p>
508
    // *
509
    // * <p>The value returned is the distance between those points: the
510
    // original and
511
    // * the adjusted one.</p>
512
    // *
513
    // * @param point point to adjust
514
    // * @param mapHandlerAdjustedPoint <code>point</code> adjusted
515
    // *
516
    // * @return distance from <code>point</code> to the adjusted one. If there
517
    // is no
518
    // * adjustment, returns <code>Double.MAX_VALUE</code>.
519
    // */
520
    // private double adjustToHandler(Point2D point,
521
    // Point2D mapHandlerAdjustedPoint) {
522
    //
523
    // if (!isRefentEnabled())
524
    // return Double.MAX_VALUE;
525
    //
526
    // ILayerEdited aux =
527
    // CADExtension.getEditionManager().getActiveLayerEdited();
528
    // if (!(aux instanceof VectorialLayerEdited))
529
    // return Double.MAX_VALUE;
530
    // VectorialLayerEdited vle = (VectorialLayerEdited) aux;
531
    //
532
    // ArrayList snappers = vle.getSnappers();
533
    // ArrayList layersToSnap = vle.getLayersToSnap();
534
    //
535
    //
536
    // ViewPort vp = getMapControl().getViewPort();
537
    //
538
    // snappers=SnapConfigPage.getActivesSnappers();
539
    //
540
    // double mapTolerance = vp.toMapDistance(SelectionCADTool.tolerance);
541
    // double minDist = mapTolerance;
542
    // // double rw = getMapControl().getViewPort().toMapDistance(5);
543
    // Point2D mapPoint = point;
544
    // double middleTol=mapTolerance * 0.5;
545
    // org.gvsig.fmap.geom.primitive.Envelope r = new
546
    // DefaultEnvelope(mapPoint.getX() - middleTol,
547
    // mapPoint.getY() - middleTol,
548
    // mapPoint.getX() + middleTol,
549
    // mapPoint.getY() + middleTol);
550
    //
551
    // Envelope e = Converter.convertEnvelopeToJTS(r);
552
    //
553
    // usedSnap = null;
554
    // Point2D lastPoint = null;
555
    // if (previousPoint != null)
556
    // {
557
    // lastPoint = new Point2D.Double(previousPoint[0], previousPoint[1]);
558
    // }
559
    // for (int j = 0; j < layersToSnap.size(); j++)
560
    // {
561
    // FLyrVect lyrVect = (FLyrVect) layersToSnap.get(j);
562
    // SpatialCache cache = lyrVect.getSpatialCache();
563
    // if (lyrVect.isVisible())
564
    // {
565
    // // La lista de snappers est� siempre ordenada por prioridad. Los de
566
    // mayor
567
    // // prioridad est�n primero.
568
    // for (int i = 0; i < snappers.size(); i++)
569
    // {
570
    // ISnapper theSnapper = (ISnapper) snappers.get(i);
571
    //
572
    // if (usedSnap != null)
573
    // {
574
    // // Si ya tenemos un snap y es de alta prioridad, cogemos ese. (A no ser
575
    // que en otra capa encontremos un snapper mejor)
576
    // if (theSnapper.getPriority() < usedSnap.getPriority())
577
    // break;
578
    // }
579
    // SnappingVisitor snapVisitor = null;
580
    // Point2D theSnappedPoint = null;
581
    //
582
    // if (theSnapper instanceof ISnapperVectorial)
583
    // {
584
    // if (theSnapper instanceof ISnapperGeometriesVectorial) {
585
    // snapVisitor=new GeometriesSnappingVisitor((ISnapperGeometriesVectorial)
586
    // theSnapper,point,mapTolerance,lastPoint);
587
    // }else {
588
    // snapVisitor = new SnappingVisitor((ISnapperVectorial) theSnapper, point,
589
    // mapTolerance, lastPoint);
590
    // }
591
    // // System.out.println("Cache size = " + cache.size());
592
    // cache.query(e, snapVisitor);
593
    // theSnappedPoint = snapVisitor.getSnapPoint();
594
    //
595
    // }
596
    // if (theSnapper instanceof ISnapperRaster)
597
    // {
598
    // ISnapperRaster snapRaster = (ISnapperRaster) theSnapper;
599
    // theSnappedPoint = snapRaster.getSnapPoint(getMapControl(), point,
600
    // mapTolerance, lastPoint);
601
    // }
602
    //
603
    //
604
    // if (theSnappedPoint != null) {
605
    // double distAux = theSnappedPoint.distance(point);
606
    // if (minDist > distAux)
607
    // {
608
    // minDist = distAux;
609
    // usedSnap = theSnapper;
610
    // mapHandlerAdjustedPoint.setLocation(theSnappedPoint);
611
    // }
612
    // }
613
    // }
614
    // } // visible
615
    // }
616
    // if (usedSnap != null)
617
    // return minDist;
618
    // return Double.MAX_VALUE;
619
    //
620
    // }
621

    
622
    /*
623
     * (non-Javadoc)
624
     * 
625
     * @see
626
     * com.iver.cit.gvsig.fmap.tools.Behavior.Behavior#mouseReleased(java.awt
627
     * .event.MouseEvent)
628
     */
629
    public void mouseReleased(MouseEvent e) throws BehaviorException {
630
        getMapControl().repaint();
631
    }
632

    
633
    /*
634
     * (non-Javadoc)
635
     * 
636
     * @see
637
     * com.iver.cit.gvsig.fmap.tools.Behavior.Behavior#mouseDragged(java.awt
638
     * .event.MouseEvent)
639
     */
640
    public void mouseDragged(MouseEvent e) throws BehaviorException {
641
        lastX = e.getX();
642
        lastY = e.getY();
643
        adjustedPoint = e.getPoint();
644
        // calculateSnapPoint(e.getPoint());
645
    }
646

    
647
    /*
648
     * (non-Javadoc)
649
     * 
650
     * @see
651
     * com.iver.cit.gvsig.fmap.tools.Behavior.Behavior#mouseMoved(java.awt.event
652
     * .MouseEvent)
653
     */
654
    public void mouseMoved(MouseEvent e) throws BehaviorException {
655

    
656
        lastX = e.getX();
657
        lastY = e.getY();
658
        adjustedPoint = e.getPoint();
659
        // calculateSnapPoint(e.getPoint());
660

    
661
        showCoords(e.getPoint());
662

    
663
        getMapControl().repaint();
664
    }
665

    
666
    /**
667
     * Displays the current coordinates of the mouse's cursor on the associated
668
     * <code>MapControl</code> object, at the status bar of the application's
669
     * main frame.
670
     * 
671
     * @param pPix
672
     *            current 2D mouse's cursor coordinates on the
673
     *            <code>MapControl</code>
674
     */
675
    private void showCoords(Point2D pPix) {
676
        String[] axisText = new String[2];
677
        axisText[0] = "X = ";
678
        axisText[1] = "Y = ";
679
        // NumberFormat nf = NumberFormat.getInstance();
680
        MapControl mapControl = getMapControl();
681
        ViewPort vp = mapControl.getMapContext().getViewPort();
682
        IProjection iProj = vp.getProjection();
683

    
684
        // if (iProj.getAbrev().equals("EPSG:4326") ||
685
        // iProj.getAbrev().equals("EPSG:4230")) {
686
        // axisText[0] = "Lon = ";
687
        // axisText[1] = "Lat = ";
688
        // nf.setMaximumFractionDigits(8);
689
        // } else {
690
        // axisText[0] = "X = ";
691
        // axisText[1] = "Y = ";
692
        // nf.setMaximumFractionDigits(2);
693
        // }
694
        Point2D p;
695
        if (mapAdjustedPoint == null) {
696
            p = vp.toMapPoint(pPix);
697
        } else {
698
            p = mapAdjustedPoint;
699
        }
700
        sbl.setFractionDigits(p);
701
        axisText = sbl.setCoorDisplayText(axisText);
702
        MainFrame mF = PluginServices.getMainFrame();
703

    
704
        if (mF != null) {
705
            mF.getStatusBar().setMessage(
706
                "units",
707
                PluginServices.getText(this,
708
                    MapContext.getDistanceNames()[vp.getDistanceUnits()]));
709
            mF.getStatusBar().setControlValue("scale",
710
                String.valueOf(mapControl.getMapContext().getScaleView()));
711
            mF.getStatusBar().setMessage("projection", iProj.getAbrev());
712

    
713
            String[] coords = sbl.getCoords(p);
714
            mF.getStatusBar().setMessage("x", axisText[0] + coords[0]);
715
            mF.getStatusBar().setMessage("y", axisText[1] + coords[1]);
716
        }
717
    }
718

    
719
    /**
720
     * Hides the mouse's cursor.
721
     */
722
    private void clearMouseImage() {
723
        int[] pixels = new int[16 * 16];
724
        Image image =
725
            Toolkit.getDefaultToolkit().createImage(
726
                new MemoryImageSource(16, 16, pixels, 0, 16));
727
        Cursor transparentCursor =
728
            Toolkit.getDefaultToolkit().createCustomCursor(image,
729
                new Point(0, 0), "invisiblecursor");
730

    
731
        getMapControl().setCursor(transparentCursor);
732
    }
733

    
734
    /**
735
     * <p>
736
     * Draws a 31x31 pixels cross round the mouse's cursor with an small
737
     * geometry centered:
738
     * <ul>
739
     * <li><i>an square centered</i>: if isn't over a <i>control point</i>.
740
     * <li><i>an small geometry centered according to the kind of control
741
     * point</i>: if it's over a control point. In this case, the small geometry
742
     * is drawn by a {@link ISnapper ISnapper} type object.<br>
743
     * On the other hand, a light-yellowed background tool tip text with the
744
     * type of <i>control point</i> will be displayed.</li>
745
     * </p>
746
     * 
747
     * @param g
748
     *            <code>MapControl</code>'s graphics where the data will be
749
     *            drawn
750
     */
751
    // private void drawCursor(Graphics g) {
752
    // g.setColor(Color.black);
753
    // Point2D p = adjustedPoint;
754
    //
755
    // if (p == null) {
756
    // getGrid().setViewPort(getMapControl().getViewPort());
757
    //
758
    // return;
759
    // }
760
    //
761
    // int size1 = 15;
762
    // int size2 = 3;
763
    // g.drawLine((int) (p.getX() - size1), (int) (p.getY()),
764
    // (int) (p.getX() + size1), (int) (p.getY()));
765
    // g.drawLine((int) (p.getX()), (int) (p.getY() - size1),
766
    // (int) (p.getX()), (int) (p.getY() + size1));
767
    //
768
    // // getMapControl().setToolTipText(null);
769
    // if (adjustedPoint != null) {
770
    // if (bForceCoord) {
771
    // /* g.setColor(Color.ORANGE);
772
    // g.drawRect((int) (adjustedPoint.getX() - 6),
773
    // (int) (adjustedPoint.getY() - 6), 12, 12);
774
    // g.drawRect((int) (adjustedPoint.getX() - 3),
775
    // (int) (adjustedPoint.getY() - 3), 6, 6);
776
    // g.setColor(Color.MAGENTA);
777
    // g.drawRect((int) (adjustedPoint.getX() - 4),
778
    // (int) (adjustedPoint.getY() - 4), 8, 8); */
779
    // if (usedSnap != null)
780
    // {
781
    // usedSnap.draw(g, adjustedPoint);
782
    //
783
    // Graphics2D g2 = (Graphics2D) g;
784
    // FontMetrics metrics = g2.getFontMetrics();
785
    // int w = metrics.stringWidth(usedSnap.getToolTipText()) + 5;
786
    // int h = metrics.getMaxAscent() + 5;
787
    // int x = (int)p.getX()+9;
788
    // int y = (int)p.getY()- 7;
789
    //
790
    // g2.setColor(theTipColor );
791
    // g2.fillRect(x, y-h, w, h);
792
    // g2.setColor(Color.BLACK);
793
    // g2.drawRect(x, y-h, w, h);
794
    // g2.drawString(usedSnap.getToolTipText(), x+3, y-3);
795
    //
796
    //
797
    // // getMapControl().setToolTipText(usedSnap.getToolTipText());
798
    // }
799
    //
800
    // bForceCoord = false;
801
    // } else {
802
    // g.drawRect((int) (p.getX() - size2), (int) (p.getY() - size2),
803
    // (int) (size2 * 2), (int) (size2 * 2));
804
    // }
805
    // }
806
    // }
807
    /**
808
     * <p>
809
     * Tries to find the nearest geometry or grid control point by the position
810
     * of the current snap tool.
811
     * </p>
812
     * 
813
     * <p>
814
     * Prioritizes the grid control points than the geometries ones.
815
     * </p>
816
     * 
817
     * <p>
818
     * If finds any near, stores the <i>map</i> and <i>pixel</i> coordinates for
819
     * the snap, and enables the <code>bForceCoord</code> attribute for the next
820
     * draw of the mouse's cursor.
821
     * </p>
822
     * 
823
     * @param point
824
     *            current mouse 2D position
825
     */
826
    // private void calculateSnapPoint(Point point) {
827
    // // Se comprueba el ajuste a rejilla
828
    //
829
    // Point2D gridAdjustedPoint = getMapControl().getViewPort().toMapPoint(
830
    // point);
831
    // double minDistance = Double.MAX_VALUE;
832
    // CADTool ct = (CADTool) cadToolStack.peek();
833
    // if (ct instanceof SelectionCADTool
834
    // && ((SelectionCADTool) ct).getStatus().equals(
835
    // "Selection.FirstPoint")) {
836
    // mapAdjustedPoint = gridAdjustedPoint;
837
    // adjustedPoint = (Point2D) point.clone();
838
    // } else {
839
    //
840
    // minDistance = getGrid().adjustToGrid(gridAdjustedPoint);
841
    // if (minDistance < Double.MAX_VALUE) {
842
    // adjustedPoint = getMapControl().getViewPort().fromMapPoint(
843
    // gridAdjustedPoint);
844
    // mapAdjustedPoint = gridAdjustedPoint;
845
    // } else {
846
    // mapAdjustedPoint = null;
847
    // }
848
    // }
849
    // Point2D handlerAdjustedPoint = null;
850
    //
851
    // // Se comprueba el ajuste a los handlers
852
    // if (mapAdjustedPoint != null) {
853
    // handlerAdjustedPoint = (Point2D) mapAdjustedPoint.clone(); //
854
    // getMapControl().getViewPort().toMapPoint(point);
855
    // } else {
856
    // handlerAdjustedPoint = getMapControl().getViewPort().toMapPoint(
857
    // point);
858
    // }
859
    //
860
    // Point2D mapPoint = new Point2D.Double();
861
    // double distance = adjustToHandler(handlerAdjustedPoint, mapPoint);
862
    //
863
    // if (distance < minDistance) {
864
    // bForceCoord = true;
865
    // adjustedPoint = getMapControl().getViewPort().fromMapPoint(mapPoint);
866
    // mapAdjustedPoint = mapPoint;
867
    // minDistance = distance;
868
    // }
869
    //
870
    // // Si no hay ajuste
871
    // if (minDistance == Double.MAX_VALUE) {
872
    // adjustedPoint = point;
873
    // mapAdjustedPoint = null;
874
    // }
875
    //
876
    // }
877
    /*
878
     * (non-Javadoc)
879
     * 
880
     * @see
881
     * com.iver.cit.gvsig.fmap.tools.Behavior.Behavior#mouseWheelMoved(java.
882
     * awt.event.MouseWheelEvent)
883
     */
884
    public void mouseWheelMoved(MouseWheelEvent e) throws BehaviorException {
885
    }
886

    
887
    /**
888
     * <p>
889
     * Process the information written by the user about the next point
890
     * coordinate, determining the kind of <i>transition</i> according the
891
     * parameters written.
892
     * </p>
893
     * 
894
     * <p>
895
     * After, invokes one of the three possible <i>transition</i> methods of the
896
     * <i>finite machine</i> of edition:
897
     * <ul>
898
     * <li><i>First transition type: <b>Point</i></b>: if <code>text</code>
899
     * matches with any pattern of parameters needed for any kind of point
900
     * coordinates.<br>
901
     * There are eight ways of introducing point 2D coordinates:
902
     * <ul>
903
     * <li><i>X,Y</i> : absolute cardinal 2D coordinate from the center
904
     * <i>(0,0)</i> of the CCS <i>Current Coordinate System</i>.</li>
905
     * <li><i>@X,Y</i> : relative cardinal 2D distances from the last point
906
     * added of the CCS. If it's the first point of the geometry, works like
907
     * <i>X,Y</i>.</li>
908
     * <li><i>length< angle</i> : absolute polar 2D coordinate from the center
909
     * <i>(0,0)</i> of the CCS <i>Current Coordinate System</i>, using
910
     * <i>angle</i> from the <i>X</i> axis of CCS, and <i>length</i> far away.</li>
911
     * <li><i>@length< angle</i> : relative polar 2D coordinate from the last
912
     * point added of the CCS <i>Current Coordinate System</i>, using
913
     * <i>angle</i> from the <i>X</i> axis of CCS, and <i>length</i> far away.
914
     * If it's the first point of the geometry, works like <i>length< angle</i>.
915
     * </li>
916
     * <li><i>*X,Y</i> : like <i>X,Y</i> but using UCS <i>Universal Coordinate
917
     * System</i> as reference.</li>
918
     * <li><i>@*X,Y</i> : like <i>@X,Y</i> but using UCS <i>Universal Coordinate
919
     * System</i> as reference. If it's the first point of the geometry, works
920
     * like <i>*X,Y</i>.</li>
921
     * <li><i>*length< angle</i> : like <i>length< angle</i> but using UCS
922
     * <i>Universal Coordinate System</i> as reference.</li>
923
     * <li><i>@*length< angle</i> : like <i>@length< angle</i> but using UCS
924
     * <i>Universal Coordinate System</i> as reference. If it's the first point
925
     * of the geometry, works like <i>*length< angle</i>.</li>
926
     * </ul>
927
     * </li>
928
     * <li><i>Second transition type: <b>Value</i></b>: if recognizes it as a
929
     * single number.</li>
930
     * <li><i>Third transition type: <b>Option</i></b>: by default, if can't
931
     * classify the information as a single number neither as a point. This
932
     * information will be an <code>String</code> and dealt as an option of the
933
     * current tool state. Ultimately, if isn't valid, <code>text</code> will be
934
     * rewritten in the console notifying the user that isn't correct.</li>
935
     * </ul>
936
     * </p>
937
     * 
938
     * @param text
939
     *            command written by user in the edition's console
940
     */
941
    public void textEntered(String text) {
942
        if (text == null) {
943
            transition(PluginServices.getText(this, "cancel"));
944
        } else {
945
            /*
946
             * if ("".equals(text)) { transition("aceptar"); } else {
947
             */
948
            text = text.trim();
949
            int type = ABSOLUTE;
950
            String[] numbers = new String[1];
951
            numbers[0] = text;
952
            if (text.indexOf(",") != -1) {
953

    
954
                numbers = text.split(",");
955
                if (numbers[0].substring(0, 1).equals("@")) {
956
                    numbers[0] = numbers[0].substring(1, numbers[0].length());
957
                    type = RELATIVE_SCU;
958
                    if (numbers[0].substring(0, 1).equals("*")) {
959
                        type = RELATIVE_SCP;
960
                        numbers[0] =
961
                            numbers[0].substring(1, numbers[0].length());
962
                    }
963
                }
964
            } else
965
                if (text.indexOf("<") != -1) {
966
                    type = POLAR_SCP;
967
                    numbers = text.split("<");
968
                    if (numbers[0].substring(0, 1).equals("@")) {
969
                        numbers[0] =
970
                            numbers[0].substring(1, numbers[0].length());
971
                        type = POLAR_SCU;
972
                        if (numbers[0].substring(0, 1).equals("*")) {
973
                            type = POLAR_SCP;
974
                            numbers[0] =
975
                                numbers[0].substring(1, numbers[0].length());
976
                        }
977
                    }
978
                }
979

    
980
            double[] values = null;
981

    
982
            try {
983
                if (numbers.length == 2) {
984
                    // punto
985
                    values =
986
                        new double[] { Double.parseDouble(numbers[0]),
987
                            Double.parseDouble(numbers[1]) };
988
                    transition(values, null, type);
989
                } else
990
                    if (numbers.length == 1) {
991
                        // valor
992
                        values =
993
                            new double[] { Double.parseDouble(numbers[0]) };
994
                        transition(values[0]);
995
                    }
996
            } catch (NumberFormatException e) {
997
                transition(text);
998
            } catch (NullPointerException e) {
999
                transition(text);
1000
            }
1001
            // }
1002
        }
1003
        getMapControl().repaint();
1004
    }
1005

    
1006
    /**
1007
     * If there are options related with the <code>CADTool</code> at the peek
1008
     * of the CAD tool stack, displays them as a popup.
1009
     */
1010
    public void configureMenu() {
1011
        String[] desc = ((CADTool) cadToolStack.peek()).getDescriptions();
1012
        // String[] labels = ((CADTool)
1013
        // cadToolStack.peek()).getCurrentTransitions();
1014
        CADExtension.clearMenu();
1015

    
1016
        for (int i = 0; i < desc.length; i++) {
1017
            if (desc[i] != null) {
1018
                CADExtension
1019
                    .addMenuEntry(PluginServices.getText(this, desc[i]));// ,
1020
                // labels[i]);
1021
            }
1022
        }
1023

    
1024
    }
1025

    
1026
    /**
1027
     * <p>
1028
     * One of the three kind of transaction methods of the <i>finite machine</i>
1029
     * of edition.
1030
     * </p>
1031
     * 
1032
     * <p>
1033
     * This one deals <code>values</code> as two numbers that, according
1034
     * <code>type</code> calculate a new point 2D in the current layer edited in
1035
     * the associated <code>MapControl</code>.
1036
     * </p>
1037
     * 
1038
     * <p>
1039
     * There are different ways of calculating the new point 2D coordinates,
1040
     * according the value of <code>type</code>, see
1041
     * {@link #textEntered(String) #textEntered(String)}.
1042
     * </p>
1043
     * 
1044
     * <p>
1045
     * After applying the changes, updates the controls available for managing
1046
     * the current data.
1047
     * </p>
1048
     * 
1049
     * @param values
1050
     *            numbers needed to calculate the new point coordinates
1051
     *            according <code>type</code>
1052
     * @param event
1053
     *            event which generated this invocation (a
1054
     *            <code>MouseEvent</code> or a <code>KeyEvent</code>)
1055
     * @param type
1056
     *            kind of information that is <code>values</code>. According
1057
     *            this parameter, will calculate the new point in a different
1058
     *            way
1059
     * 
1060
     * @see CADTool#transition(double, double, InputEvent)
1061
     * @see #transition(double)
1062
     * @see #transition(String)
1063
     */
1064
    private void transition(double[] values, InputEvent event, int type) {
1065
        questionAsked = true;
1066
        if (!cadToolStack.isEmpty()) {
1067
            CADTool ct = (CADTool) cadToolStack.peek();
1068

    
1069
            switch (type) {
1070
            case ABSOLUTE:
1071
                ct.transition(values[0], values[1], event);
1072
                previousPoint = values;
1073
                break;
1074
            case RELATIVE_SCU:
1075
                // Comprobar que tenemos almacenado el punto anterior
1076
                // y crear nuevo con coordenadas relativas a �l.
1077
                double[] auxSCU = values;
1078
                if (previousPoint != null) {
1079
                    auxSCU[0] = previousPoint[0] + values[0];
1080
                    auxSCU[1] = previousPoint[1] + values[1];
1081
                }
1082
                ct.transition(auxSCU[0], auxSCU[1], event);
1083

    
1084
                previousPoint = auxSCU;
1085
                break;
1086
            case RELATIVE_SCP:
1087
                // TODO de momento no implementado.
1088
                ct.transition(values[0], values[1], event);
1089
                previousPoint = values;
1090
                break;
1091
            case POLAR_SCU:// Relativo
1092
                // Comprobar que tenemos almacenado el punto anterior
1093
                // y crear nuevo con coordenadas relativas a �l.
1094
                double[] auxPolarSCU = values;
1095
                if (previousPoint != null) {
1096
                    Point2D point =
1097
                        UtilFunctions.getPoint(new Point2D.Double(
1098
                            previousPoint[0], previousPoint[1]), Math
1099
                            .toRadians(values[1]), values[0]);
1100
                    auxPolarSCU[0] = point.getX();
1101
                    auxPolarSCU[1] = point.getY();
1102
                    ct.transition(auxPolarSCU[0], auxPolarSCU[1], event);
1103
                } else {
1104
                    Point2D point =
1105
                        UtilFunctions.getPoint(new Point2D.Double(0, 0),
1106
                            Math.toRadians(values[1]), values[0]);
1107
                    auxPolarSCU[0] = point.getX();
1108
                    auxPolarSCU[1] = point.getY();
1109
                    ct.transition(auxPolarSCU[0], auxPolarSCU[1], event);
1110
                }
1111
                previousPoint = auxPolarSCU;
1112
                break;
1113
            case POLAR_SCP:// Absoluto
1114
                double[] auxPolarSCP = values;
1115
                if (previousPoint != null) {
1116
                    Point2D point =
1117
                        UtilFunctions.getPoint(new Point2D.Double(0, 0),
1118
                            Math.toRadians(values[1]), values[0]);
1119
                    auxPolarSCP[0] = point.getX();
1120
                    auxPolarSCP[1] = point.getY();
1121
                    ct.transition(auxPolarSCP[0], auxPolarSCP[1], event);
1122
                } else {
1123
                    Point2D point =
1124
                        UtilFunctions.getPoint(new Point2D.Double(0, 0),
1125
                            values[1], values[0]);
1126
                    auxPolarSCP[0] = point.getX();
1127
                    auxPolarSCP[1] = point.getY();
1128
                    ct.transition(auxPolarSCP[0], auxPolarSCP[1], event);
1129
                }
1130
                previousPoint = auxPolarSCP;
1131
                break;
1132
            default:
1133
                break;
1134
            }
1135
            askQuestion();
1136
        }
1137
        configureMenu();
1138
        PluginServices.getMainFrame().enableControls();
1139
    }
1140

    
1141
    /**
1142
     * <p>
1143
     * One of the three kind of transaction methods of the <i>finite machine</i>
1144
     * of edition.
1145
     * </p>
1146
     * 
1147
     * <p>
1148
     * This one deals <code>value</code> as a single number used as a parameter
1149
     * for the current tool state. Ultimately, if isn't valid,
1150
     * <code>number</code> will be rewritten in the console notifying the user
1151
     * that isn't correct.
1152
     * </p>
1153
     * 
1154
     * <p>
1155
     * After applying the changes, updates the controls available for managing
1156
     * the current data.
1157
     * </p>
1158
     * 
1159
     * @param value
1160
     *            value for the current tool state
1161
     * 
1162
     * @see CADTool#transition(double)
1163
     * @see #transition(double[], InputEvent, int)
1164
     * @see #transition(String)
1165
     */
1166
    private void transition(double value) {
1167
        questionAsked = true;
1168
        if (!cadToolStack.isEmpty()) {
1169
            CADTool ct = (CADTool) cadToolStack.peek();
1170
            ct.transition(value);
1171
            askQuestion();
1172
        }
1173
        configureMenu();
1174
        PluginServices.getMainFrame().enableControls();
1175
    }
1176

    
1177
    /**
1178
     * <p>
1179
     * One of the three kind of transaction methods of the <i>finite machine</i>
1180
     * of edition.
1181
     * </p>
1182
     * 
1183
     * <p>
1184
     * This one deals <code>option</code> as an option of the current tool
1185
     * state. Ultimately, if isn't valid, <code>option</code> will be rewritten
1186
     * in the console notifying the user that isn't correct.
1187
     * </p>
1188
     * 
1189
     * @param option
1190
     *            option for the current tool state
1191
     * 
1192
     * @see CADTool#transition(String)
1193
     * @see #transition(double[], InputEvent, int)
1194
     * @see #transition(double)
1195
     */
1196
    public void transition(String option) {
1197
        questionAsked = true;
1198
        if (!cadToolStack.isEmpty()) {
1199
            CADTool ct = (CADTool) cadToolStack.peek();
1200
            try {
1201
                ct.transition(option);
1202
            } catch (Exception e) {
1203
                IWindow window =
1204
                    PluginServices.getMDIManager().getActiveWindow();
1205

    
1206
                if (window instanceof DefaultViewPanel) {
1207
                    ((DefaultViewPanel) window).getConsolePanel().addText(
1208
                        "\n" + PluginServices.getText(this, "incorrect_option")
1209
                            + " : " + option, JConsole.ERROR);
1210
                }
1211
            }
1212
            askQuestion();
1213
        }
1214
        configureMenu();
1215
        PluginServices.getMainFrame().enableControls();
1216
    }
1217

    
1218
    /**
1219
     * Shows or hides a grid on the <code>ViewPort</code> of the associated
1220
     * <code>MapControl</code>.
1221
     * 
1222
     * @param value
1223
     *            <code>true</code> to make the grid visible; <code>false</code>
1224
     *            to make it invisible
1225
     */
1226
    // public void setGridVisibility(boolean value) {
1227
    // getGrid().setShowGrid(value);
1228
    // getGrid().setViewPort(getMapControl().getViewPort());
1229
    // getMapControl().repaint();
1230
    // }
1231
    // /**
1232
    // * Sets the snap tools enabled or disabled.
1233
    // *
1234
    // * @param activated <code>true</code> to enable the snap tools;
1235
    // <code>false</code> to disable them
1236
    // *
1237
    // * @see #isRefentEnabled()
1238
    // */
1239
    // public void setRefentEnabled(boolean activated) {
1240
    // bRefent = activated;
1241
    // }
1242
    //
1243
    // /**
1244
    // * Determines if snap tools are enabled or disabled.
1245
    // *
1246
    // * @return <code>true</code> to enable the snap tools; <code>false</code>
1247
    // to disable them
1248
    // *
1249
    // * @see #setRefentEnabled(boolean)
1250
    // */
1251
    // public boolean isRefentEnabled()
1252
    // {
1253
    // return bRefent;
1254
    // }
1255
    /*
1256
     * (non-Javadoc)
1257
     * 
1258
     * @see com.iver.cit.gvsig.fmap.tools.Behavior.Behavior#getListener()
1259
     */
1260
    public ToolListener getListener() {
1261
        return new ToolListener() {
1262

    
1263
            /**
1264
             * @see com.iver.cit.gvsig.fmap.tools.Listeners.ToolListener#getCursor()
1265
             */
1266
            public Image getImageCursor() {
1267
                return imageCursor;
1268
            }
1269

    
1270
            /**
1271
             * @see com.iver.cit.gvsig.fmap.tools.Listeners.ToolListener#cancelDrawing()
1272
             */
1273
            public boolean cancelDrawing() {
1274
                return false;
1275
            }
1276
        };
1277
    }
1278

    
1279
    /**
1280
     * Returns the {@link CADTool CADTool} at the top of the stack without
1281
     * removing it from the CAD tool stack.
1282
     * 
1283
     * @return the {@link CADTool CADTool} at the top of the stack
1284
     * 
1285
     * @see #pushCadTool(CADTool)
1286
     * @see #popCadTool()
1287
     * @see #setCadTool(CADTool)
1288
     */
1289
    public CADTool getCadTool() {
1290
        return (CADTool) cadToolStack.peek();
1291
    }
1292

    
1293
    /**
1294
     * <p>
1295
     * Pushes a {@link CADTool CADTool} onto the top of the CAD tool stack, and
1296
     * sets it as current.
1297
     * </p>
1298
     * 
1299
     * @param cadTool
1300
     *            CAD tool to enable as current
1301
     * 
1302
     * @see #getCadTool()
1303
     * @see #popCadTool()
1304
     * @see #setCadTool(CADTool)
1305
     */
1306
    public void pushCadTool(CADTool cadTool) {
1307
        cadToolStack.push(cadTool);
1308
        cadTool.setCadToolAdapter(this);
1309
        // cadTool.initializeStatus();
1310
        // cadTool.setVectorialAdapter(vea);
1311
        /*
1312
         * int ret = cadTool.transition(null, editableFeatureSource, selection,
1313
         * new double[0]);
1314
         * 
1315
         * if ((ret & Automaton.AUTOMATON_FINISHED) ==
1316
         * Automaton.AUTOMATON_FINISHED) { popCadTool();
1317
         * 
1318
         * if (cadToolStack.isEmpty()) { pushCadTool(new
1319
         * com.iver.cit.gvsig.gui.cad.smc.gen.CADTool());//new
1320
         * SelectionCadTool());
1321
         * PluginServices.getMainFrame().setSelectedTool("selection"); }
1322
         * 
1323
         * askQuestion();
1324
         * 
1325
         * getMapControl().drawMap(false); }
1326
         */
1327
    }
1328

    
1329
    /**
1330
     * Removes the peek of the CAD tool stack.
1331
     * 
1332
     * @see #pushCadTool(CADTool)
1333
     * @see #getCadTool()
1334
     * @see #setCadTool(CADTool)
1335
     */
1336
    public void popCadTool() {
1337
        cadToolStack.pop();
1338
    }
1339

    
1340
    /**
1341
     * <p>
1342
     * Displays at the console associated to the current active view that's
1343
     * being edited, the question of the following operation that user can do
1344
     * with the current <code>CADTool</code>, only if it hasn't just answered.
1345
     * </p>
1346
     * 
1347
     * <p>
1348
     * The format of the question will be according the following pattern:<br>
1349
     * "\n#"<i>{cadtool at CAD tool stack peek}</i>.getQuestion()">"
1350
     * </p>
1351
     */
1352
    public void askQuestion() {
1353
        CADTool cadtool = (CADTool) cadToolStack.peek();
1354
        /*
1355
         * if (cadtool..getStatus()==0){
1356
         * PluginServices.getMainFrame().addTextToConsole("\n"
1357
         * +cadtool.getName()); }
1358
         */
1359
        if (PluginServices.getMDIManager().getActiveWindow() instanceof DefaultViewPanel) {
1360
            DefaultViewPanel vista =
1361
                (DefaultViewPanel) PluginServices.getMDIManager()
1362
                    .getActiveWindow();
1363
            String question = cadtool.getQuestion();
1364
            if (lastQuestion == null || !(lastQuestion.equals(question))
1365
                || questionAsked) {
1366
                vista.getConsolePanel().addText("\n" + "#" + question + " > ",
1367
                    JConsole.MESSAGE);
1368
                // ***PluginServices.getMainFrame().addTextToConsole("\n" +
1369
                // cadtool.getQuestion());
1370
                questionAsked = false;
1371
            }
1372
            lastQuestion = question;
1373
        }
1374

    
1375
    }
1376

    
1377
    /**
1378
     * Empties the CAD tools stack and pushes <code>cadTool</code> in it.
1379
     * 
1380
     * @param cadTool
1381
     *            CAD tool to set at the peek of the stack
1382
     * 
1383
     * @see #pushCadTool(CADTool)
1384
     * @see #popCadTool()
1385
     * @see #getCadTool()
1386
     */
1387
    public void setCadTool(CADTool cadTool) {
1388
        cadToolStack.clear();
1389
        pushCadTool(cadTool);
1390
        // askQuestion();
1391
    }
1392

    
1393
    /**
1394
     * <p>
1395
     * Removes all geometries selected in the associated <code>MapControl</code>.
1396
     */
1397
    public void delete() {
1398
        ILayerEdited aux =
1399
            CADExtension.getEditionManager().getActiveLayerEdited();
1400
        if (!(aux instanceof VectorialLayerEdited)) {
1401
            return;
1402
        }
1403
        VectorialLayerEdited vle = (VectorialLayerEdited) aux;
1404
        FeatureStore featureStore = null;
1405
        // try {
1406
        featureStore = ((FLyrVect) vle.getLayer()).getFeatureStore();
1407
        // } catch (ReadException e1) {
1408
        // // TODO Auto-generated catch block
1409
        // e1.printStackTrace();
1410
        // }
1411
        String description = PluginServices.getText(this, "remove_geometry");
1412
        DisposableIterator iterator = null;
1413
        try {
1414
            featureStore.beginEditingGroup(description);
1415

    
1416
            FeatureSelection selection = featureStore.createFeatureSelection();
1417
            selection.select((FeatureSet) featureStore.getSelection());
1418
            iterator = selection.iterator();
1419
            while (iterator.hasNext()) {
1420
                Feature feature = (Feature) iterator.next();
1421
                featureStore.delete(feature);
1422
            }
1423

    
1424
            // int[] indexesToDel = new int[selection.cardinality()];
1425
            // int j = 0;
1426
            // for (int i = selection.nextSetBit(0); i >= 0; i = selection
1427
            // .nextSetBit(i + 1)) {
1428
            // indexesToDel[j++] = i;
1429
            // // /vea.removeRow(i);
1430
            // }
1431

    
1432
            // ArrayList selectedRow = vle.getSelectedRow();
1433
            //
1434
            // int[] indexesToDel = new int[selectedRow.size()];
1435
            // for (int i = 0;i < selectedRow.size(); i++) {
1436
            // IRowEdited edRow = (IRowEdited) selectedRow.get(i);
1437
            // indexesToDel[i] = vea.getInversedIndex(edRow.getIndex());
1438
            // }
1439
            //
1440
            // for (int i = indexesToDel.length - 1; i >= 0; i--) {
1441
            // vea.removeRow(indexesToDel[i], PluginServices.getText(this,
1442
            // "deleted_feature"),EditionEvent.GRAPHIC);
1443
            // }
1444
            System.out.println("clear Selection");
1445
            vle.clearSelection();
1446
        } catch (ReadException e) {
1447
            NotificationManager.addError(e.getMessage(), e);
1448
        } catch (DataException e) {
1449
            NotificationManager.addError(e.getMessage(), e);
1450
        } finally {
1451
            if (iterator != null) {
1452
                iterator.dispose();
1453
            }
1454
            try {
1455
                featureStore.endEditingGroup();
1456
            } catch (NeedEditingModeException e) {
1457
                logger.error("Exception endEditingGroup", e);
1458
            }
1459
        }
1460

    
1461
        /*
1462
         * if (getCadTool() instanceof SelectionCADTool) { SelectionCADTool
1463
         * selTool = (SelectionCADTool) getCadTool(); selTool.clearSelection();
1464
         * }
1465
         */
1466
        refreshEditedLayer();
1467
    }
1468

    
1469
    /**
1470
     * @see CADGrid#setAdjustGrid(boolean)
1471
     */
1472
    // public void setAdjustGrid(boolean b) {
1473
    // getGrid().setAdjustGrid(b);
1474
    // }
1475
    /**
1476
     * <p>
1477
     * Responds to actions of writing common key commands for all kind of CAD
1478
     * operations, enabling/disabling after the controls to manage the available
1479
     * information according the tool selected:
1480
     * <ul>
1481
     * <li><i>eliminar</i>: removes the geometries that are now selected.</li>
1482
     * <li><i>escape</i>: executes different actions according to the current
1483
     * CAD tool of the associated <code>MapControl</code>:
1484
     * <ul>
1485
     * <li>If the tool enabled is identified by <i>cadtooladapter</i>: empties
1486
     * the CAD tools stack, changing the current tool by a
1487
     * {@link SelectionCADTool SelectionCADTool}, which is identified by
1488
     * <i>_selection</i> and allows select features of the active vector layer
1489
     * of the associated <code>MapControl</code> instance.</li>
1490
     * <li>Otherwise, that means current associated <code>MapControl</code>
1491
     * instance isn't identified by "<i>cadtooladapter</i>", changes the enabled
1492
     * tool by the previous.</li>
1493
     * </ul>
1494
     * </li>
1495
     * </ul>
1496
     * </p>
1497
     * 
1498
     * @param actionCommand
1499
     *            identifier of the key action command executed by the user
1500
     * 
1501
     * @see SelectionCADTool
1502
     * @see MapControl#setPrevTool()
1503
     */
1504
    public void keyPressed(String actionCommand) {
1505
        if (CADExtension.getEditionManager().getActiveLayerEdited() == null) {
1506
            return;
1507
        }
1508
        if (actionCommand.equals("eliminar")) {
1509
            delete();
1510
        } else
1511
            if (actionCommand.equals("escape")) {
1512
                if (getMapControl().getCurrentTool().equals("cadtooladapter")) {
1513
                    CADTool ct = (CADTool) cadToolStack.peek();
1514
                    ct.end();
1515
                    cadToolStack.clear();
1516
                    SelectionCADTool selCad = new SelectionCADTool();
1517
                    selCad.init();
1518
                    VectorialLayerEdited vle =
1519
                        (VectorialLayerEdited) CADExtension.getEditionManager()
1520
                            .getActiveLayerEdited();
1521
                    try {
1522
                        vle.clearSelection();
1523
                    } catch (DataException e) {
1524
                        NotificationManager.addError(e.getMessage(), e);
1525
                    }
1526

    
1527
                    pushCadTool(selCad);
1528
                    // getVectorialAdapter().getSelection().clear();
1529

    
1530
                    refreshEditedLayer();
1531

    
1532
                    PluginServices.getMainFrame().setSelectedTool("_selection");
1533
                    // askQuestion();
1534
                } else {
1535
                    getMapControl().setPrevTool();
1536
                }
1537
            }
1538

    
1539
        PluginServices.getMainFrame().enableControls();
1540

    
1541
    }
1542

    
1543
    /**
1544
     * <p>
1545
     * Applies a lightweight repaint of the active layer being edited.
1546
     * </p>
1547
     * 
1548
     * <p>
1549
     * All layers under it won't be drawn, only the upper one and whose are over
1550
     * that layer in the TOC.
1551
     * </p>
1552
     * 
1553
     * @see MapControl#rePaintDirtyLayers()
1554
     */
1555
    public void refreshEditedLayer() {
1556
        ILayerEdited edLayer =
1557
            CADExtension.getEditionManager().getActiveLayerEdited();
1558
        if (edLayer != null) {
1559
            getMapControl().rePaintDirtyLayers();
1560
        }
1561

    
1562
    }
1563

    
1564
    /**
1565
     * Gets the {@link CADGrid CADGrid} that can be drawn on the
1566
     * <code>ViewPort</code> of the associated <code>MapControl</code>.
1567
     * 
1568
     * @return reference to the <i>grid</i> that can be applied on the
1569
     *         <code>ViewPort</code>
1570
     * 
1571
     * @see #setGridVisibility(boolean)
1572
     */
1573
    // public CADGrid getGrid() {
1574
    // return cadgrid;
1575
    // }
1576
    /**
1577
     * Determines if is enabled or not the <i>orto</i> mode.
1578
     * 
1579
     * @return <code>true</code> if is enabled the <i>orto</i> mode;
1580
     *         otherwise <code>false</code>
1581
     * 
1582
     * @see #setOrtoMode(boolean)
1583
     */
1584
    public boolean isOrtoMode() {
1585
        return bOrtoMode;
1586
    }
1587

    
1588
    /**
1589
     * Enables / disables the <i>orto</i> mode.
1590
     * 
1591
     * @param b
1592
     *            the desired value
1593
     * 
1594
     * @see #isOrtoMode()
1595
     */
1596
    public void setOrtoMode(boolean b) {
1597
        bOrtoMode = b;
1598
    }
1599

    
1600
    /**
1601
     * Associates and stores the specified name with the specified
1602
     * {@link CADTool CADTool}.
1603
     * 
1604
     * @param name
1605
     *            name of the tool
1606
     * @param c
1607
     *            CAD tool to interactuate editing the layers
1608
     * 
1609
     * @see #getCADTools()
1610
     * @see #getCADTool(String)
1611
     */
1612
    public static void addCADTool(String name, CADTool c) {
1613
        namesCadTools.put(name, c);
1614

    
1615
    }
1616

    
1617
    /**
1618
     * Gets all CAD tools available to edit layers with this tool listener.
1619
     * 
1620
     * @return CAD tools available to edit layers with this tool listener
1621
     * 
1622
     * @see #addCADTool(String, CADTool)
1623
     * @see #getCADTool(String)
1624
     */
1625
    public static CADTool[] getCADTools() {
1626
        return (CADTool[]) CADToolAdapter.namesCadTools.values().toArray(
1627
            new CADTool[0]);
1628
    }
1629

    
1630
    /**
1631
     * Returns the {@link CADTool CADTool} to which the specified name is
1632
     * mapped.
1633
     * 
1634
     * @param text
1635
     *            name of the tool
1636
     * @return the CAD tool whose associated name is to be returned
1637
     * 
1638
     * @see #addCADTool(String, CADTool)
1639
     * @see #getCADTools()
1640
     */
1641
    public CADTool getCADTool(String text) {
1642
        CADTool ct = (CADTool) namesCadTools.get(text);
1643
        return ct;
1644
    }
1645

    
1646
    /**
1647
     * Gets the object used to manage the edition of the layers of the
1648
     * associated <code>MapControl</code>.
1649
     * 
1650
     * @see EditionManager
1651
     * 
1652
     * @return object used to manage the edition of the layers
1653
     */
1654
    public EditionManager getEditionManager() {
1655
        return editionManager;
1656
    }
1657

    
1658
    /**
1659
     * <p>
1660
     * Initializes the <i>flatness</i> with the defined in preferences.
1661
     * </p>
1662
     * 
1663
     * <p>
1664
     * The <i>flatness</i> is the maximum tolerance used to approximate curved
1665
     * lines in a <i>shape</i> by polylines.
1666
     * </p>
1667
     * <p>
1668
     * The shapes doesn't support primitive like arcs neither other curved lines
1669
     * to draw their geometries, then for drawing any kind of this geometries
1670
     * the curved lines are drawn approximately by a polyline. And for doing
1671
     * more realistic that curves, is used the <i>flatness</i> parameter, that
1672
     * indicates that the difference between each arc and the straight segment
1673
     * that approximates it must be in the worse case, like the <i>flatness</i>.
1674
     * </p>
1675
     * 
1676
     * @see FConverter#FLATNESS
1677
     */
1678
    public void initializeFlatness() {
1679
        if (!flatnessInitialized) {
1680
            flatnessInitialized = true;
1681
            Preferences prefs = Preferences.userRoot().node("cadtooladapter");
1682
            double flatness =
1683
                prefs.getDouble("flatness", geomManager.getFlatness());
1684
            geomManager.setFlatness(flatness);
1685
        }
1686
    }
1687

    
1688
    /**
1689
     * <p>
1690
     * Returns the GeometryType of the current active and vector layer being
1691
     * edited.
1692
     * </p>
1693
     * 
1694
     * @see FLyrVect#getGeom
1695
     * 
1696
     * @return type of the shape that's the current active and vector layer
1697
     *         being edited
1698
     */
1699
    public GeometryType getActiveLayerGeometryType() {
1700
        try {
1701
            return ((FLyrVect) CADExtension.getEditionManager()
1702
                .getActiveLayerEdited().getLayer()).getGeometryType();
1703
        } catch (ReadException e) {
1704
            NotificationManager.addError(e);
1705
            return null;
1706
        }
1707
    }
1708

    
1709
    /**
1710
     * <p>
1711
     * Returns the type of the shape that's the current active and vector layer
1712
     * being edited.
1713
     * </p>
1714
     * 
1715
     * @see FLyrVect#getGeometryType()
1716
     * 
1717
     * @return type of geometry that's the current active and vector layer
1718
     *         being edited
1719
     * @deprecated use {@link #getActiveLayerGeometryType()} instead. To be
1720
     *             removed in gvSIG 2.1
1721
     */
1722
    public int getActiveLayerType() {
1723
        int type = Geometry.TYPES.GEOMETRY;
1724
        try {
1725
            type =
1726
                ((FLyrVect) CADExtension.getEditionManager()
1727
                    .getActiveLayerEdited().getLayer()).getShapeType();
1728
        } catch (ReadException e) {
1729
            NotificationManager.addError(e);
1730
        }
1731
        return type;
1732
    }
1733

    
1734
}