Statistics
| Revision:

gvsig-vectorediting / org.gvsig.vectorediting / trunk / org.gvsig.vectorediting / org.gvsig.vectorediting.swing / org.gvsig.vectorediting.swing.impl / src / main / java / org / gvsig / vectorediting / swing / impl / DefaultEditingBehavior.java @ 159

History | View | Annotate | Download (19.6 KB)

1
/**
2
 * gvSIG. Desktop Geographic Information System.
3
 *
4
 * Copyright ? 2007-2014 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 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
 * 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

    
25
package org.gvsig.vectorediting.swing.impl;
26

    
27
import java.awt.Color;
28
import java.awt.Graphics;
29
import java.awt.Image;
30
import java.awt.event.MouseEvent;
31
import java.awt.image.BufferedImage;
32
import java.util.Iterator;
33
import java.util.Set;
34
import java.util.Stack;
35

    
36
import org.slf4j.Logger;
37
import org.slf4j.LoggerFactory;
38

    
39
import org.gvsig.fmap.dal.exception.DataException;
40
import org.gvsig.fmap.geom.Geometry;
41
import org.gvsig.fmap.geom.primitive.Point;
42
import org.gvsig.fmap.geom.type.GeometryType;
43
import org.gvsig.fmap.mapcontext.ViewPort;
44
import org.gvsig.fmap.mapcontext.layers.vectorial.FLyrVect;
45
import org.gvsig.fmap.mapcontrol.MapControlDrawer;
46
import org.gvsig.fmap.mapcontrol.MapControlLocator;
47
import org.gvsig.fmap.mapcontrol.tools.BehaviorException;
48
import org.gvsig.fmap.mapcontrol.tools.Behavior.Behavior;
49
import org.gvsig.fmap.mapcontrol.tools.Listeners.ToolListener;
50
import org.gvsig.tools.ToolsLocator;
51
import org.gvsig.tools.i18n.I18nManager;
52
import org.gvsig.vectorediting.lib.api.DrawingStatus;
53
import org.gvsig.vectorediting.lib.api.EditingLocator;
54
import org.gvsig.vectorediting.lib.api.EditingManager;
55
import org.gvsig.vectorediting.lib.api.EditingService;
56
import org.gvsig.vectorediting.lib.api.EditingServiceInfo;
57
import org.gvsig.vectorediting.lib.api.EditingServiceParameter;
58
import org.gvsig.vectorediting.lib.api.EditingServiceParameter.TYPE;
59
import org.gvsig.vectorediting.lib.api.exceptions.CreateEditingBehaviorException;
60
import org.gvsig.vectorediting.lib.api.exceptions.InvalidEntryException;
61
import org.gvsig.vectorediting.lib.api.exceptions.ParsePointException;
62
import org.gvsig.vectorediting.lib.api.exceptions.ParseValueException;
63
import org.gvsig.vectorediting.lib.api.exceptions.ServiceInformationException;
64
import org.gvsig.vectorediting.lib.api.exceptions.StartServiceException;
65
import org.gvsig.vectorediting.lib.api.exceptions.StopServiceException;
66
import org.gvsig.vectorediting.lib.api.exceptions.VectorEditingException;
67
import org.gvsig.vectorediting.swing.api.EditingBehavior;
68
import org.gvsig.vectorediting.swing.api.EditingContext;
69

    
70
public class DefaultEditingBehavior extends Behavior implements EditingBehavior {
71

    
72
    private static final Logger logger = LoggerFactory
73
        .getLogger(DefaultEditingBehavior.class);
74

    
75
    private Stack<EditingService> serviceStack;
76

    
77
    private EditingContext editingContext;
78

    
79
    private FLyrVect currentLayer;
80

    
81
    private EditingServiceParameter currentParam;
82

    
83
    private Point adjustedPoint;
84

    
85
    private static final Image imageCursor = new BufferedImage(32, 32,
86
        BufferedImage.TYPE_INT_ARGB);
87
    static {
88
        Graphics g = imageCursor.getGraphics();
89
        int size1 = 15;
90
        int x = 16;
91
        int y = 16;
92
        g.setColor(Color.MAGENTA);
93
        g.drawLine((x - size1), (y), (x + size1), (y));
94
        g.drawLine((x), (y - size1), (x), (y + size1));
95
        g.drawRect((x - 6), (y - 6), 12, 12);
96
        g.drawRect((x - 3), (y - 3), 6, 6);
97
    }
98

    
99
    public DefaultEditingBehavior(EditingContext editingContext)
100
        throws CreateEditingBehaviorException {
101

    
102
        if (editingContext.getMapControl() != null) {
103

    
104
            this.editingContext = editingContext;
105
            serviceStack = new Stack<EditingService>();
106

    
107
        }
108
    }
109

    
110
    public void activateService(String name) {
111

    
112
        EditingManager manager = EditingLocator.getManager();
113

    
114
        if (currentLayer != null) {
115

    
116
            EditingService service =
117
                (EditingService) manager.getEditingService(name,
118
                    currentLayer.getFeatureStore());
119

    
120
            if (service != null) {
121

    
122
                this.enableSelection(false);
123

    
124
                try {
125
                    service.start();
126
                } catch (StartServiceException e) {
127
                    logger.info(
128
                        String.format("Can't start the service %1$s",
129
                            service.getName()), e);
130
                    cleanBehavior();
131
                    return;
132
                }
133

    
134
                if (!serviceStack.isEmpty()
135
                    && !getActiveService().next().getTypes()
136
                        .contains(EditingServiceParameter.TYPE.GEOMETRY)) {
137
                    serviceStack.clear();
138
                }
139

    
140
                setActiveService(service);
141
                getNextParameter();
142
            }
143
        }
144
    }
145

    
146
    /**
147
     * Shows description of parameter on console.
148
     */
149
    private void askQuestion(EditingServiceParameter param) {
150
        showConsoleMessage("\n#" + param.getDescription() + " > ");
151
    }
152

    
153
    public void cleanBehavior() {
154
        serviceStack.clear();
155
        currentParam = null;
156
        this.enableSelection(false);
157
        editingContext.refreshMenusAndToolBars();
158

    
159
        I18nManager i18nManager = ToolsLocator.getI18nManager();
160
        showConsoleMessage("\n" + i18nManager.getTranslation("select_new_tool")
161
            + "\n");
162
    }
163

    
164
    private void showConsoleMessage(String text) {
165
        editingContext.showConsoleMessage(text);
166
    }
167

    
168
    @Override
169
    public ToolListener getListener() {
170
        return new ToolListener() {
171

    
172
            public boolean cancelDrawing() {
173
                return false;
174
            }
175

    
176
            public Image getImageCursor() {
177
                return imageCursor;
178
            }
179
        };
180
    }
181

    
182
    /**
183
     * Gets next parameter of {@link #activateService(String)} and sets
184
     * {@link #currentParam}. If currentParam is null means all service
185
     * parameters
186
     * have value and service doesn't need more values.
187
     */
188
    private void getNextParameter() {
189

    
190
        currentParam = getActiveService().next();
191

    
192
        if (currentParam == null) {
193
            finishService();
194
        } else {
195
            askQuestion(currentParam);
196
            if (currentParam.getTypes().contains(
197
                EditingServiceParameter.TYPE.SELECTION)) {
198
                enableSelection(true);
199
            } else if (currentParam.getTypes().contains(
200
                EditingServiceParameter.TYPE.GEOMETRY)) {
201

    
202
                editingContext.refreshMenusAndToolBars();
203
            }
204
        }
205
    }
206

    
207
    private EditingService getActiveService() {
208
        if (!serviceStack.isEmpty()) {
209
            return serviceStack.peek();
210
        }
211
        return null;
212
    }
213

    
214
    private void setActiveService(EditingService service) {
215
        serviceStack.add(service);
216
    }
217

    
218
    private void finishService() {
219
        EditingService lastService = serviceStack.pop();
220
        try {
221

    
222
            if (!serviceStack.isEmpty()
223
                && getActiveService().next().getTypes()
224
                    .contains(EditingServiceParameter.TYPE.GEOMETRY)) {
225

    
226
                Geometry geometry = lastService.finish();
227

    
228
                if (geometry != null) {
229

    
230
                    getActiveService().setValue(geometry);
231

    
232
                }
233

    
234
            } else {
235

    
236
                lastService.finishAndStore();
237
                editingContext.getMapControl().rePaintDirtyLayers();
238
                setActiveService(lastService);
239

    
240
            }
241

    
242
            lastService.stop();
243
            lastService.start();
244

    
245
        } catch (InvalidEntryException ex) {
246
            I18nManager i18nManager = ToolsLocator.getI18nManager();
247
            showConsoleMessage(i18nManager.getTranslation("invalid_option"));
248
        } catch (VectorEditingException ex) {
249
            logger.info("Can't finish " + lastService.getName(), ex);
250
            cleanBehavior();
251
            return;
252
        }
253

    
254
        getNextParameter();
255
    }
256

    
257
    public void mouseClicked(MouseEvent e) {
258
        ViewPort vp = editingContext.getMapControl().getViewPort();
259
        if (getActiveService() != null) {
260
            if (currentParam != null) {
261

    
262
                Set<TYPE> typesOfParam = currentParam.getTypes();
263

    
264
                if (typesOfParam.contains(TYPE.LIST_POSITIONS)
265
                    || typesOfParam.contains(TYPE.POSITION)) {
266

    
267
                    if (typesOfParam.contains(TYPE.LIST_POSITIONS)) {
268
                        if (e.getClickCount() == 2) {
269
                            finishService();
270
                            return;
271
                        }
272
                    }
273

    
274
                    Point point;
275
                    point = vp.convertToMapPoint(e.getX(), e.getY());
276

    
277
                    try {
278
                        getActiveService().setValue(point);
279
                    } catch (VectorEditingException ex) {
280
                        I18nManager i18nManager = ToolsLocator.getI18nManager();
281
                        showConsoleMessage(i18nManager
282
                            .getTranslation("invalid_option"));
283
                    }
284

    
285
                }
286

    
287
                getNextParameter();
288
            }
289
        }
290
    }
291

    
292
    public void mouseEntered(MouseEvent e) throws BehaviorException {
293
    }
294

    
295
    public void mouseMoved(MouseEvent e) throws BehaviorException {
296
        ViewPort vp = editingContext.getMapControl().getViewPort();
297
        adjustedPoint = vp.convertToMapPoint(e.getX(), e.getY());
298
    }
299

    
300
    public void mousePressed(MouseEvent e) throws BehaviorException {
301
    }
302

    
303
    public void mouseReleased(MouseEvent e) throws BehaviorException {
304
    }
305

    
306
    @SuppressWarnings("rawtypes")
307
    public void paintComponent(MapControlDrawer mapControlDrawer) {
308
        super.paintComponent(mapControlDrawer);
309

    
310
        if (getActiveService() == null || adjustedPoint == null) {
311
            return;
312
        }
313

    
314
        DrawingStatus helperGeo = null;
315

    
316
        try {
317
            helperGeo = getActiveService().getDrawingStatus(adjustedPoint);
318
        } catch (VectorEditingException e) {
319
            logger.info("An error ocurred when draw service geometries", e);
320
        }
321

    
322
        if (helperGeo != null) {
323
            for (Iterator iterator = helperGeo.getGeometries().iterator(); iterator
324
                .hasNext();) {
325
                Geometry geometry = (Geometry) iterator.next();
326
                editingContext
327
                    .getMapControl()
328
                    .getMapControlDrawer()
329
                    .draw(
330
                        geometry,
331
                        MapControlLocator.getMapControlManager()
332
                            .getAxisReferenceSymbol());
333
            }
334
        }
335
    }
336

    
337
    /**
338
     * Sets the layer received as parameter as {@link #currentLayer}
339
     * 
340
     * @param layer
341
     */
342
    public void setCurrentLayer(FLyrVect layer) {
343

    
344
        if (this.currentLayer != layer) {
345
            cleanBehavior();
346
            this.currentLayer = layer;
347
        }
348

    
349
    }
350

    
351
    /**
352
     * Processes console entries from console. Tries to process entry in each
353
     * type
354
     * of {@link #currentParam}. If there is some error, It will continue
355
     * checking. If entry has been processed, It will set value in
356
     * {@link #activeService}.
357
     * 
358
     * @param response
359
     *            Console entry.
360
     * @throws InvalidEntryException
361
     *             If console entries has not been able to
362
     *             process, it will throw an exception to indicate that entry is
363
     *             not
364
     *             valid.
365
     * @throws StopServiceException
366
     *             If there are some errors stopping service.
367
     */
368
    public void textEntered(String response) {
369
        if (response == null) {
370
            if (getActiveService() != null) {
371

    
372
                try {
373

    
374
                    getActiveService().stop();
375
                    serviceStack.pop();
376

    
377
                    if (getActiveService() != null) {
378
                        getNextParameter();
379
                    } else {
380
                        cleanBehavior();
381
                    }
382

    
383
                } catch (StopServiceException e) {
384
                    logger
385
                        .info("Can't stop " + getActiveService().getName(), e);
386
                    return;
387
                }
388
            }
389
        } else {
390

    
391
            if (currentParam != null) {
392
                Set<TYPE> types = currentParam.getTypes();
393
                Point point = null;
394
                Double value = null;
395

    
396
                boolean insertedValue = false;
397
                if (!insertedValue && types.contains(TYPE.POSITION)
398
                    || types.contains(TYPE.LIST_POSITIONS)) {
399

    
400
                    try {
401

    
402
                        point = parsePoint(response);
403
                        if (point != null) {
404
                            getActiveService().setValue(point);
405
                            insertedValue = true;
406
                        }
407

    
408
                    } catch (VectorEditingException e) {
409
                        // Do nothing to try other types
410
                    }
411
                }
412
                if (!insertedValue && types.contains(TYPE.VALUE)) {
413

    
414
                    try {
415

    
416
                        value = parseValue(response);
417
                        if (value != null) {
418
                            getActiveService().setValue(value);
419
                            insertedValue = true;
420
                        }
421

    
422
                    } catch (VectorEditingException e) {
423
                        // Do nothing to try other types
424
                    }
425

    
426
                }
427
                if (!insertedValue && types.contains(TYPE.OPTION)) {
428

    
429
                    try {
430

    
431
                        response = response.replace("\n", "");
432
                        if (response != null) {
433
                            getActiveService().setValue(response);
434
                            insertedValue = true;
435
                        }
436

    
437
                    } catch (VectorEditingException e) {
438
                        // Do nothing to try other types
439
                    }
440
                }
441
                if (!insertedValue && types.contains(TYPE.SELECTION)) {
442
                    if (response.equalsIgnoreCase("\n")) {
443
                        enableSelection(false);
444
                        insertedValue = true;
445

    
446
                        try {
447

    
448
                            getActiveService().setValue(
449
                                currentLayer.getFeatureStore()
450
                                    .getFeatureSelection().clone());
451

    
452
                        } catch (InvalidEntryException e) {
453
                            I18nManager i18nManager =
454
                                ToolsLocator.getI18nManager();
455
                            showConsoleMessage(i18nManager
456
                                .getTranslation("invalid_option"));
457
                        } catch (Exception e) {
458
                            logger.info("Can't access to selecction.", e);
459
                            cleanBehavior();
460
                            return;
461
                        }
462
                    }
463
                }
464
                if (!insertedValue) {
465
                    I18nManager i18nManager = ToolsLocator.getI18nManager();
466
                    showConsoleMessage(i18nManager
467
                        .getTranslation("invalid_option"));
468
                }
469
                getNextParameter();
470
            }
471
        }
472
    }
473

    
474
    /**
475
     * Parse String to value.
476
     * 
477
     * @param response
478
     *            String to be parsed.
479
     * @return Values of string.
480
     * @throws ParseValueException
481
     *             If there is error trying to parse <code>String</code>.
482
     */
483
    private Double parseValue(String response) throws ParseValueException {
484
        try {
485
            return Double.valueOf(response);
486
        } catch (Exception e) {
487
            throw new ParseValueException(e);
488
        }
489

    
490
    }
491

    
492
    /**
493
     * Parse String to point. Formats accepted: (x,y) and x,y.
494
     * 
495
     * @param response
496
     *            String to be parsed.
497
     * @return Point of string.
498
     * @throws ParsePointException
499
     *             If there is error trying to parse <code>String</code>.
500
     */
501
    private Point parsePoint(String response) throws ParsePointException {
502
        String[] numbers = new String[1];
503
        numbers[0] = response;
504
        numbers = response.split(",");
505
        if (numbers.length == 2) {
506
            if (numbers[0].startsWith("(") && numbers[1].endsWith(")\n")) { // CCS
507
                numbers[0] = numbers[0].replace("(", "");
508
                numbers[1] = numbers[1].replace(")\n", "");
509
            }
510
            double[] values;
511
            try {
512
                values =
513
                    new double[] { Double.parseDouble(numbers[0]),
514
                        Double.parseDouble(numbers[1]) };
515
            } catch (Exception e) {
516
                throw new ParsePointException(e);
517
            }
518

    
519
            Point point;
520
            try {
521
                point =
522
                    geomManager.createPoint(values[0], values[1], currentLayer
523
                        .getFeatureStore().getDefaultFeatureType()
524
                        .getDefaultGeometryAttribute().getGeomType()
525
                        .getSubType());
526

    
527
            } catch (Exception e) {
528
                throw new ParsePointException(e);
529
            }
530
            return point;
531
        } else {
532
            throw new ParsePointException(null);
533
        }
534
    }
535

    
536
    private void enableSelection(boolean enableSelection) {
537
        editingContext.enableSelection(enableSelection);
538
    }
539

    
540
    public boolean isServiceCompatible(String name)
541
        throws ServiceInformationException {
542
        EditingManager manager = EditingLocator.getManager();
543
        EditingServiceInfo serviceInfo = manager.getServiceInfo(name);
544
        GeometryType geoType = null;
545

    
546
        for (EditingService editingService : serviceStack) {
547
            if (editingService.next().getTypes()
548
                .contains(EditingServiceParameter.TYPE.GEOMETRY)) {
549

    
550
                int geometryType = editingService.next().getGeometryType();
551
                int subType = -1;
552
                try {
553
                    subType =
554
                        currentLayer.getFeatureStore().getDefaultFeatureType()
555
                            .getDefaultGeometryAttribute().getGeomType()
556
                            .getSubType();
557
                    geoType =
558
                        geomManager.getGeometryType(geometryType, subType);
559
                } catch (Exception e) {
560

    
561
                    String msg =
562
                        String
563
                            .format(
564
                                "Problems getting default feature"
565
                                    + " type of %1$s or getting geometry type of %2$s %3$s",
566
                                currentLayer.getName(), geometryType, subType);
567

    
568
                    throw new ServiceInformationException(msg, e);
569
                }
570

    
571
                return serviceInfo.isCompatibleWith(geoType)
572
                    && serviceInfo.createsNewGeometries();
573
            }
574
        }
575

    
576
        try {
577
            geoType =
578
                currentLayer.getFeatureStore().getDefaultFeatureType()
579
                    .getDefaultGeometryAttribute().getGeomType();
580
        } catch (DataException e) {
581
            String msg =
582
                String.format("Problems getting default "
583
                    + "feature type of %1$s", currentLayer.getName());
584
            throw new ServiceInformationException(msg, e);
585
        }
586

    
587
        return serviceInfo.isCompatibleWith(geoType);
588
    }
589
}