Statistics
| Revision:

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

History | View | Annotate | Download (58.8 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.util.UtilFunctions;
64
import org.gvsig.fmap.mapcontext.MapContext;
65
import org.gvsig.fmap.mapcontext.MapContextLocator;
66
import org.gvsig.fmap.mapcontext.MapContextManager;
67
import org.gvsig.fmap.mapcontext.ViewPort;
68
import org.gvsig.fmap.mapcontext.layers.vectorial.FLyrVect;
69
import org.gvsig.fmap.mapcontext.rendering.symbols.ISymbol;
70
import org.gvsig.fmap.mapcontrol.MapControl;
71
import org.gvsig.fmap.mapcontrol.MapControlDrawer;
72
import org.gvsig.fmap.mapcontrol.tools.BehaviorException;
73
import org.gvsig.fmap.mapcontrol.tools.Behavior.Behavior;
74
import org.gvsig.fmap.mapcontrol.tools.Listeners.ToolListener;
75
import org.gvsig.tools.dispose.DisposableIterator;
76
import org.gvsig.utils.console.JConsole;
77

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
381
    }
382

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

    
397
        if (adjustedPoint != null) {
398
            Point2D p = null;
399
            if (mapAdjustedPoint != null) {
400
                p = mapAdjustedPoint;
401
            } else {
402
                p = getMapControl().getViewPort().toMapPoint(adjustedPoint);
403
            }
404

    
405
            // If the stack is empty, return
406
            if (cadToolStack.isEmpty()) {
407
                return;
408
            }
409

    
410
            if (((CADTool) cadToolStack.peek()).getVLE() == null) {
411
                return;
412
            }
413

    
414
            ((CADTool) cadToolStack.peek()).drawOperation(mapControlDrawer,
415
                p.getX(), p.getY());
416
        }
417
    }
418

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

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

    
456
    /*
457
     * (non-Javadoc)
458
     * 
459
     * @see
460
     * com.iver.cit.gvsig.fmap.tools.Behavior.Behavior#mouseEntered(java.awt
461
     * .event.MouseEvent)
462
     */
463
    public void mouseEntered(MouseEvent e) throws BehaviorException {
464
        clearMouseImage();
465
    }
466

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

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

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

    
614
    /*
615
     * (non-Javadoc)
616
     * 
617
     * @see
618
     * com.iver.cit.gvsig.fmap.tools.Behavior.Behavior#mouseReleased(java.awt
619
     * .event.MouseEvent)
620
     */
621
    public void mouseReleased(MouseEvent e) throws BehaviorException {
622
        getMapControl().repaint();
623
    }
624

    
625
    /*
626
     * (non-Javadoc)
627
     * 
628
     * @see
629
     * com.iver.cit.gvsig.fmap.tools.Behavior.Behavior#mouseDragged(java.awt
630
     * .event.MouseEvent)
631
     */
632
    public void mouseDragged(MouseEvent e) throws BehaviorException {
633
        lastX = e.getX();
634
        lastY = e.getY();
635
        adjustedPoint = e.getPoint();
636
        // calculateSnapPoint(e.getPoint());
637
    }
638

    
639
    /*
640
     * (non-Javadoc)
641
     * 
642
     * @see
643
     * com.iver.cit.gvsig.fmap.tools.Behavior.Behavior#mouseMoved(java.awt.event
644
     * .MouseEvent)
645
     */
646
    public void mouseMoved(MouseEvent e) throws BehaviorException {
647

    
648
        lastX = e.getX();
649
        lastY = e.getY();
650
        adjustedPoint = e.getPoint();
651
        // calculateSnapPoint(e.getPoint());
652

    
653
        showCoords(e.getPoint());
654

    
655
        getMapControl().repaint();
656
    }
657

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

    
676
        // if (iProj.getAbrev().equals("EPSG:4326") ||
677
        // iProj.getAbrev().equals("EPSG:4230")) {
678
        // axisText[0] = "Lon = ";
679
        // axisText[1] = "Lat = ";
680
        // nf.setMaximumFractionDigits(8);
681
        // } else {
682
        // axisText[0] = "X = ";
683
        // axisText[1] = "Y = ";
684
        // nf.setMaximumFractionDigits(2);
685
        // }
686
        Point2D p;
687
        if (mapAdjustedPoint == null) {
688
            p = vp.toMapPoint(pPix);
689
        } else {
690
            p = mapAdjustedPoint;
691
        }
692
        sbl.setFractionDigits(p);
693
        axisText = sbl.setCoorDisplayText(axisText);
694
        MainFrame mF = PluginServices.getMainFrame();
695

    
696
        if (mF != null) {
697
            mF.getStatusBar().setMessage(
698
                "units",
699
                PluginServices.getText(this,
700
                    MapContext.getDistanceNames()[vp.getDistanceUnits()]));
701
            mF.getStatusBar().setControlValue("scale",
702
                String.valueOf(mapControl.getMapContext().getScaleView()));
703
            mF.getStatusBar().setMessage("projection", iProj.getAbrev());
704

    
705
            String[] coords = sbl.getCoords(p);
706
            mF.getStatusBar().setMessage("x", axisText[0] + coords[0]);
707
            mF.getStatusBar().setMessage("y", axisText[1] + coords[1]);
708
        }
709
    }
710

    
711
    /**
712
     * Hides the mouse's cursor.
713
     */
714
    private void clearMouseImage() {
715
        int[] pixels = new int[16 * 16];
716
        Image image =
717
            Toolkit.getDefaultToolkit().createImage(
718
                new MemoryImageSource(16, 16, pixels, 0, 16));
719
        Cursor transparentCursor =
720
            Toolkit.getDefaultToolkit().createCustomCursor(image,
721
                new Point(0, 0), "invisiblecursor");
722

    
723
        getMapControl().setCursor(transparentCursor);
724
    }
725

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

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

    
946
                numbers = text.split(",");
947
                if (numbers[0].substring(0, 1).equals("@")) {
948
                    numbers[0] = numbers[0].substring(1, numbers[0].length());
949
                    type = RELATIVE_SCU;
950
                    if (numbers[0].substring(0, 1).equals("*")) {
951
                        type = RELATIVE_SCP;
952
                        numbers[0] =
953
                            numbers[0].substring(1, numbers[0].length());
954
                    }
955
                }
956
            } else
957
                if (text.indexOf("<") != -1) {
958
                    type = POLAR_SCP;
959
                    numbers = text.split("<");
960
                    if (numbers[0].substring(0, 1).equals("@")) {
961
                        numbers[0] =
962
                            numbers[0].substring(1, numbers[0].length());
963
                        type = POLAR_SCU;
964
                        if (numbers[0].substring(0, 1).equals("*")) {
965
                            type = POLAR_SCP;
966
                            numbers[0] =
967
                                numbers[0].substring(1, numbers[0].length());
968
                        }
969
                    }
970
                }
971

    
972
            double[] values = null;
973

    
974
            try {
975
                if (numbers.length == 2) {
976
                    // punto
977
                    values =
978
                        new double[] { Double.parseDouble(numbers[0]),
979
                            Double.parseDouble(numbers[1]) };
980
                    transition(values, null, type);
981
                } else
982
                    if (numbers.length == 1) {
983
                        // valor
984
                        values =
985
                            new double[] { Double.parseDouble(numbers[0]) };
986
                        transition(values[0]);
987
                    }
988
            } catch (NumberFormatException e) {
989
                transition(text);
990
            } catch (NullPointerException e) {
991
                transition(text);
992
            }
993
            // }
994
        }
995
        getMapControl().repaint();
996
    }
997

    
998
    /**
999
     * If there are options related with the <code>CADTool</code> at the peek
1000
     * of the CAD tool stack, displays them as a popup.
1001
     */
1002
    public void configureMenu() {
1003
        String[] desc = ((CADTool) cadToolStack.peek()).getDescriptions();
1004
        // String[] labels = ((CADTool)
1005
        // cadToolStack.peek()).getCurrentTransitions();
1006
        CADExtension.clearMenu();
1007

    
1008
        for (int i = 0; i < desc.length; i++) {
1009
            if (desc[i] != null) {
1010
                CADExtension
1011
                    .addMenuEntry(PluginServices.getText(this, desc[i]));// ,
1012
                // labels[i]);
1013
            }
1014
        }
1015

    
1016
    }
1017

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

    
1061
            switch (type) {
1062
            case ABSOLUTE:
1063
                ct.transition(values[0], values[1], event);
1064
                previousPoint = values;
1065
                break;
1066
            case RELATIVE_SCU:
1067
                // Comprobar que tenemos almacenado el punto anterior
1068
                // y crear nuevo con coordenadas relativas a �l.
1069
                double[] auxSCU = values;
1070
                if (previousPoint != null) {
1071
                    auxSCU[0] = previousPoint[0] + values[0];
1072
                    auxSCU[1] = previousPoint[1] + values[1];
1073
                }
1074
                ct.transition(auxSCU[0], auxSCU[1], event);
1075

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

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

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

    
1198
                if (window instanceof DefaultViewPanel) {
1199
                    ((DefaultViewPanel) window).getConsolePanel().addText(
1200
                        "\n" + PluginServices.getText(this, "incorrect_option")
1201
                            + " : " + option, JConsole.ERROR);
1202
                }
1203
            }
1204
            askQuestion();
1205
        }
1206
        configureMenu();
1207
        PluginServices.getMainFrame().enableControls();
1208
    }
1209

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

    
1255
            /**
1256
             * @see com.iver.cit.gvsig.fmap.tools.Listeners.ToolListener#getCursor()
1257
             */
1258
            public Image getImageCursor() {
1259
                return imageCursor;
1260
            }
1261

    
1262
            /**
1263
             * @see com.iver.cit.gvsig.fmap.tools.Listeners.ToolListener#cancelDrawing()
1264
             */
1265
            public boolean cancelDrawing() {
1266
                return false;
1267
            }
1268
        };
1269
    }
1270

    
1271
    /**
1272
     * Returns the {@link CADTool CADTool} at the top of the stack without
1273
     * removing it from the CAD tool stack.
1274
     * 
1275
     * @return the {@link CADTool CADTool} at the top of the stack
1276
     * 
1277
     * @see #pushCadTool(CADTool)
1278
     * @see #popCadTool()
1279
     * @see #setCadTool(CADTool)
1280
     */
1281
    public CADTool getCadTool() {
1282
        return (CADTool) cadToolStack.peek();
1283
    }
1284

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

    
1321
    /**
1322
     * Removes the peek of the CAD tool stack.
1323
     * 
1324
     * @see #pushCadTool(CADTool)
1325
     * @see #getCadTool()
1326
     * @see #setCadTool(CADTool)
1327
     */
1328
    public void popCadTool() {
1329
        cadToolStack.pop();
1330
    }
1331

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

    
1367
    }
1368

    
1369
    /**
1370
     * Empties the CAD tools stack and pushes <code>cadTool</code> in it.
1371
     * 
1372
     * @param cadTool
1373
     *            CAD tool to set at the peek of the stack
1374
     * 
1375
     * @see #pushCadTool(CADTool)
1376
     * @see #popCadTool()
1377
     * @see #getCadTool()
1378
     */
1379
    public void setCadTool(CADTool cadTool) {
1380
        cadToolStack.clear();
1381
        pushCadTool(cadTool);
1382
        // askQuestion();
1383
    }
1384

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

    
1408
            FeatureSelection selection = featureStore.createFeatureSelection();
1409
            selection.select((FeatureSet) featureStore.getSelection());
1410
            iterator = selection.iterator();
1411
            while (iterator.hasNext()) {
1412
                Feature feature = (Feature) iterator.next();
1413
                featureStore.delete(feature);
1414
            }
1415

    
1416
            // int[] indexesToDel = new int[selection.cardinality()];
1417
            // int j = 0;
1418
            // for (int i = selection.nextSetBit(0); i >= 0; i = selection
1419
            // .nextSetBit(i + 1)) {
1420
            // indexesToDel[j++] = i;
1421
            // // /vea.removeRow(i);
1422
            // }
1423

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

    
1453
        /*
1454
         * if (getCadTool() instanceof SelectionCADTool) { SelectionCADTool
1455
         * selTool = (SelectionCADTool) getCadTool(); selTool.clearSelection();
1456
         * }
1457
         */
1458
        refreshEditedLayer();
1459
    }
1460

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

    
1519
                    pushCadTool(selCad);
1520
                    // getVectorialAdapter().getSelection().clear();
1521

    
1522
                    refreshEditedLayer();
1523

    
1524
                    PluginServices.getMainFrame().setSelectedTool("_selection");
1525
                    // askQuestion();
1526
                } else {
1527
                    getMapControl().setPrevTool();
1528
                }
1529
            }
1530

    
1531
        PluginServices.getMainFrame().enableControls();
1532

    
1533
    }
1534

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

    
1554
    }
1555

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

    
1580
    /**
1581
     * Enables / disables the <i>orto</i> mode.
1582
     * 
1583
     * @param b
1584
     *            the desired value
1585
     * 
1586
     * @see #isOrtoMode()
1587
     */
1588
    public void setOrtoMode(boolean b) {
1589
        bOrtoMode = b;
1590
    }
1591

    
1592
    /**
1593
     * Associates and stores the specified name with the specified
1594
     * {@link CADTool CADTool}.
1595
     * 
1596
     * @param name
1597
     *            name of the tool
1598
     * @param c
1599
     *            CAD tool to interactuate editing the layers
1600
     * 
1601
     * @see #getCADTools()
1602
     * @see #getCADTool(String)
1603
     */
1604
    public static void addCADTool(String name, CADTool c) {
1605
        namesCadTools.put(name, c);
1606

    
1607
    }
1608

    
1609
    /**
1610
     * Gets all CAD tools available to edit layers with this tool listener.
1611
     * 
1612
     * @return CAD tools available to edit layers with this tool listener
1613
     * 
1614
     * @see #addCADTool(String, CADTool)
1615
     * @see #getCADTool(String)
1616
     */
1617
    public static CADTool[] getCADTools() {
1618
        return (CADTool[]) CADToolAdapter.namesCadTools.values().toArray(
1619
            new CADTool[0]);
1620
    }
1621

    
1622
    /**
1623
     * Returns the {@link CADTool CADTool} to which the specified name is
1624
     * mapped.
1625
     * 
1626
     * @param text
1627
     *            name of the tool
1628
     * @return the CAD tool whose associated name is to be returned
1629
     * 
1630
     * @see #addCADTool(String, CADTool)
1631
     * @see #getCADTools()
1632
     */
1633
    public CADTool getCADTool(String text) {
1634
        CADTool ct = (CADTool) namesCadTools.get(text);
1635
        return ct;
1636
    }
1637

    
1638
    /**
1639
     * Gets the object used to manage the edition of the layers of the
1640
     * associated <code>MapControl</code>.
1641
     * 
1642
     * @see EditionManager
1643
     * 
1644
     * @return object used to manage the edition of the layers
1645
     */
1646
    public EditionManager getEditionManager() {
1647
        return editionManager;
1648
    }
1649

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

    
1680
    /**
1681
     * <p>
1682
     * Updates the grid on the <code>ViewPort</code> of the associated
1683
     * <code>MapControl</code> object according the values in the
1684
     * {@link com.iver.cit.gvsig.gui.cad.CADToolAdapter.prefs.Preferences
1685
     * com.iver.cit.gvsig.gui.cad.CADToolAdapter.prefs.Preferences}.
1686
     * </p>
1687
     * 
1688
     * <p>
1689
     * The preferences are:
1690
     * <ul>
1691
     * <li>Show/hide the grid.</li>
1692
     * <li>Adjust or not the grid.</li>
1693
     * <li>Horizontal ( X ) line separation.</li>
1694
     * <li>Vertical ( Y ) line separation.</li>
1695
     * </ul>
1696
     * </p>
1697
     */
1698
    // public void initializeGrid(){
1699
    // boolean showGrid =
1700
    // prefs.getBoolean("grid.showgrid",getGrid().isShowGrid());
1701
    // boolean adjustGrid =
1702
    // prefs.getBoolean("grid.adjustgrid",getGrid().isAdjustGrid());
1703
    //
1704
    // double dx = prefs.getDouble("grid.distancex",getGrid().getGridSizeX());
1705
    // double dy = prefs.getDouble("grid.distancey",getGrid().getGridSizeY());
1706
    //
1707
    // setGridVisibility(showGrid);
1708
    // setAdjustGrid(adjustGrid);
1709
    // getGrid().setGridSizeX(dx);
1710
    // getGrid().setGridSizeY(dy);
1711
    // }
1712
    /**
1713
     * <p>
1714
     * Returns the type of the shape that's the current active and vector layer
1715
     * being edited.
1716
     * </p>
1717
     * 
1718
     * @see FLyrVect#getShapeType()
1719
     * 
1720
     * @return type of the shape that's the current active and vector layer
1721
     *         being edited
1722
     */
1723
    public int getActiveLayerType() {
1724
        int type = Geometry.TYPES.GEOMETRY;
1725
        try {
1726
            type =
1727
                ((FLyrVect) CADExtension.getEditionManager()
1728
                    .getActiveLayerEdited().getLayer()).getShapeType();
1729
        } catch (ReadException e) {
1730
            NotificationManager.addError(e);
1731
        }
1732
        return type;
1733
    }
1734

    
1735
}