Statistics
| Revision:

svn-gvsig-desktop / trunk / org.gvsig.desktop / org.gvsig.desktop.plugin / org.gvsig.editing.app / org.gvsig.editing.app.mainplugin / src / main / java / org / gvsig / editing / gui / cad / CADToolAdapter.java @ 40557

History | View | Annotate | Download (58.8 KB)

1
/**
2
 * gvSIG. Desktop Geographic Information System.
3
 *
4
 * Copyright (C) 2007-2013 gvSIG Association.
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 3
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
 * For any additional information, do not hesitate to contact us
22
 * at info AT gvsig.com, or visit our website www.gvsig.com.
23
 */
24
package org.gvsig.editing.gui.cad;
25

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

    
42
import org.cresques.cts.IProjection;
43
import org.slf4j.Logger;
44
import org.slf4j.LoggerFactory;
45

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

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

    
146
    private static Logger logger = LoggerFactory
147
        .getLogger(CADToolAdapter.class);
148

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

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

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

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

    
181
    /**
182
     * Equivalent to {@link CADToolAdapter#ABSOLUTE CADToolAdapter#ABSOLUTE}.
183
     */
184
    public static final int RELATIVE_SCP = 1;
185

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

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

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

    
206
    /**
207
     * Stores the 2D map coordinates of the last point added.
208
     */
209
    private double[] previousPoint = null;
210

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

    
220
    /**
221
     * X coordinate of the last dragging or moving mouse event.
222
     */
223
    private int lastX;
224

    
225
    /**
226
     * Y coordinate of the last dragging or moving mouse event.
227
     */
228
    private int lastY;
229

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

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

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

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

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

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

    
301
    /**
302
     * Last question asked to the user in the CAD console.
303
     */
304
    private Object lastQuestion;
305

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

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

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

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

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

    
385
    }
386

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

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

    
416
            // If the stack is empty, return
417
            if (cadToolStack.isEmpty()) {
418
                return;
419
            }
420

    
421
            if (((CADTool) cadToolStack.peek()).getVLE() == null) {
422
                return;
423
            }
424

    
425
            ((CADTool) cadToolStack.peek()).drawOperation(mapControlDrawer,
426
                p.getX(), p.getY());
427
        }
428
    }
429

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

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

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

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

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

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

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

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

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

    
659
        lastX = e.getX();
660
        lastY = e.getY();
661
        adjustedPoint = e.getPoint();
662
        // calculateSnapPoint(e.getPoint());
663

    
664
        showCoords(e.getPoint());
665

    
666
        getMapControl().repaint();
667
    }
668

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

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

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

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

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

    
734
        getMapControl().setCursor(transparentCursor);
735
    }
736

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

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

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

    
983
            double[] values = null;
984

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

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

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

    
1027
    }
1028

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1378
    }
1379

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

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

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

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

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

    
1464
        /*
1465
         * if (getCadTool() instanceof SelectionCADTool) { SelectionCADTool
1466
         * selTool = (SelectionCADTool) getCadTool(); selTool.clearSelection();
1467
         * }
1468
         */
1469
        refreshEditedLayer();
1470
    }
1471

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

    
1530
                    pushCadTool(selCad);
1531
                    // getVectorialAdapter().getSelection().clear();
1532

    
1533
                    refreshEditedLayer();
1534

    
1535
                    PluginServices.getMainFrame().setSelectedTool("_selection");
1536
                    // askQuestion();
1537
                } else {
1538
                    getMapControl().setPrevTool();
1539
                }
1540
            }
1541

    
1542
        PluginServices.getMainFrame().enableControls();
1543

    
1544
    }
1545

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

    
1565
    }
1566

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

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

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

    
1618
    }
1619

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

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

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

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

    
1691
    /**
1692
     * <p>
1693
     * Returns the GeometryType of the current active and vector layer being
1694
     * edited.
1695
     * </p>
1696
     * 
1697
     * @see FLyrVect#getGeom
1698
     * 
1699
     * @return type of the shape that's the current active and vector layer
1700
     *         being edited
1701
     */
1702
    public GeometryType getActiveLayerGeometryType() {
1703
        try {
1704
            return ((FLyrVect) CADExtension.getEditionManager()
1705
                .getActiveLayerEdited().getLayer()).getGeometryType();
1706
        } catch (ReadException e) {
1707
            NotificationManager.addError(e);
1708
            return null;
1709
        }
1710
    }
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#getGeometryType()
1719
     * 
1720
     * @return type of geometry that's the current active and vector layer
1721
     *         being edited
1722
     * @deprecated use {@link #getActiveLayerGeometryType()} instead. To be
1723
     *             removed in gvSIG 2.1
1724
     */
1725
    public int getActiveLayerType() {
1726
        int type = Geometry.TYPES.GEOMETRY;
1727
        try {
1728
            type =
1729
                ((FLyrVect) CADExtension.getEditionManager()
1730
                    .getActiveLayerEdited().getLayer()).getShapeType();
1731
        } catch (ReadException e) {
1732
            NotificationManager.addError(e);
1733
        }
1734
        return type;
1735
    }
1736

    
1737
}