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 @ 76

History | View | Annotate | Download (19.9 KB)

1
/*
2
 * Copyright 2014 DiSiD Technologies S.L.L. All rights reserved.
3
 *
4
 * Project  : DiSiD org.gvsig.vectorediting.lib.impl
5
 * SVN Id   : $Id$
6
 */
7
package org.gvsig.vectorediting.swing.impl;
8

    
9
import java.awt.BorderLayout;
10
import java.awt.Color;
11
import java.awt.Graphics;
12
import java.awt.Image;
13
import java.awt.event.MouseEvent;
14
import java.awt.geom.Point2D;
15
import java.awt.image.BufferedImage;
16
import java.util.HashMap;
17
import java.util.Iterator;
18
import java.util.List;
19
import java.util.Map;
20

    
21
import org.cresques.cts.IProjection;
22
import org.gvsig.andami.PluginServices;
23
import org.gvsig.andami.ui.mdiFrame.MainFrame;
24
import org.gvsig.app.project.documents.view.toolListeners.StatusBarListener;
25
import org.gvsig.fmap.geom.Geometry;
26
import org.gvsig.fmap.geom.primitive.Point;
27
import org.gvsig.fmap.mapcontext.MapContext;
28
import org.gvsig.fmap.mapcontext.ViewPort;
29
import org.gvsig.fmap.mapcontext.layers.CancelationException;
30
import org.gvsig.fmap.mapcontext.layers.FLayer;
31
import org.gvsig.fmap.mapcontext.layers.FLayers;
32
import org.gvsig.fmap.mapcontext.layers.LayerCollectionEvent;
33
import org.gvsig.fmap.mapcontext.layers.LayerCollectionListener;
34
import org.gvsig.fmap.mapcontext.layers.LayerEvent;
35
import org.gvsig.fmap.mapcontext.layers.LayerListener;
36
import org.gvsig.fmap.mapcontext.layers.LayerPositionEvent;
37
import org.gvsig.fmap.mapcontext.layers.vectorial.FLyrVect;
38
import org.gvsig.fmap.mapcontrol.MapControl;
39
import org.gvsig.fmap.mapcontrol.MapControlDrawer;
40
import org.gvsig.fmap.mapcontrol.MapControlLocator;
41
import org.gvsig.fmap.mapcontrol.tools.BehaviorException;
42
import org.gvsig.fmap.mapcontrol.tools.Behavior.Behavior;
43
import org.gvsig.fmap.mapcontrol.tools.Listeners.ToolListener;
44
import org.gvsig.tools.ToolsLocator;
45
import org.gvsig.tools.i18n.I18nManager;
46
import org.gvsig.utils.console.JConsole;
47
import org.gvsig.utils.console.JDockPanel;
48
import org.gvsig.utils.console.ResponseListener;
49
import org.gvsig.utils.console.jedit.JEditTextArea;
50
import org.gvsig.vectorediting.lib.api.DrawingStatus;
51
import org.gvsig.vectorediting.lib.api.EditingLocator;
52
import org.gvsig.vectorediting.lib.api.EditingManager;
53
import org.gvsig.vectorediting.lib.api.EditingService;
54
import org.gvsig.vectorediting.lib.api.EditingServiceParameter;
55
import org.gvsig.vectorediting.lib.api.EditingServiceParameter.TYPE;
56
import org.gvsig.vectorediting.lib.api.exceptions.InvalidEntryException;
57
import org.gvsig.vectorediting.lib.api.exceptions.ParsePointException;
58
import org.gvsig.vectorediting.lib.api.exceptions.ParseValueException;
59
import org.gvsig.vectorediting.lib.api.exceptions.StartServiceException;
60
import org.gvsig.vectorediting.lib.api.exceptions.StopServiceException;
61
import org.gvsig.vectorediting.lib.api.exceptions.VectorEditingException;
62
import org.gvsig.vectorediting.swing.api.EditingBehavior;
63
import org.slf4j.Logger;
64
import org.slf4j.LoggerFactory;
65

    
66
public class DefaultEditingBehavior extends Behavior implements EditingBehavior {
67

    
68
  private static final Logger logger = LoggerFactory
69
      .getLogger(DefaultEditingBehavior.class);
70

    
71
  private Map<FLyrVect, EditingService> serviceRegistration;
72

    
73
  private MapControl mapControl;
74

    
75
  private FLyrVect currentLayer;
76

    
77
  private EditingService activeService;
78

    
79
  private EditingServiceParameter currentParam;
80

    
81
  private Point adjustedPoint;
82

    
83
  private StatusBarListener sbl = null;
84

    
85
  private JConsole console;
86

    
87
  private JDockPanel dockConsole = null;
88

    
89
  private boolean isShowConsole;
90

    
91
  protected ResponseAdapter consoleResponseAdapter;
92

    
93
  private I18nManager i18nManager = ToolsLocator.getI18nManager();
94

    
95
  private static final Image imageCursor = new BufferedImage(32, 32,
96
      BufferedImage.TYPE_INT_ARGB);
97
  static {
98
    Graphics g = imageCursor.getGraphics();
99
    int size1 = 15;
100
    int x = 16;
101
    int y = 16;
102
    g.setColor(Color.MAGENTA);
103
    g.drawLine((x - size1), (y), (x + size1), (y));
104
    g.drawLine((x), (y - size1), (x), (y + size1));
105
    g.drawRect((x - 6), (y - 6), 12, 12);
106
    g.drawRect((x - 3), (y - 3), 6, 6);
107
  }
108

    
109
  private LayerListener layerListener = new LayerListener() {
110

    
111
    public void activationChanged(LayerEvent e) {
112
      FLayer layer = e.getSource();
113
      if (layer instanceof FLyrVect) {
114

    
115
        if (layer.isActive() && layer.isEditing()) {
116
          showConsole();
117
          getMapControl().setTool("VectorEditing");
118
        }
119
        else if (!layer.isEditing() && layer.isActive()) {
120
          changeCurrentLayer((FLyrVect) layer);
121
          hideConsole();
122
          getMapControl().setTool("zoomIn");
123
        }
124
        changeCurrentLayer((FLyrVect) layer);
125

    
126
      }
127

    
128
    }
129

    
130
    public void drawValueChanged(LayerEvent e) {}
131

    
132
    public void editionChanged(LayerEvent e) {}
133

    
134
    public void nameChanged(LayerEvent e) {}
135

    
136
    public void visibilityChanged(LayerEvent e) {}
137
  };
138

    
139
  public void cleanBehavior() {
140
    activeService = null;
141
    currentParam = null;
142

    
143
    showConsoleMessage("\n" + i18nManager.getTranslation("select_new_tool")
144
        + "\n");
145
  }
146

    
147
  public DefaultEditingBehavior(MapControl mapControl) {
148
    if (mapControl != null) {
149
      this.mapControl = mapControl;
150
      serviceRegistration = new HashMap<FLyrVect, EditingService>();
151
      sbl = new StatusBarListener(mapControl);
152
      initMapControlListeners(mapControl);
153
      initConsolePanelListeners(getConsolePanel());
154
      FLayers layers = mapControl.getMapContext().getLayers();
155
      for (int i = 0; i < layers.getLayersCount(); i++) {
156
        if (layers.getLayer(i) instanceof FLyrVect
157
            && layers.getLayer(i).isActive())
158
          changeCurrentLayer((FLyrVect) layers.getLayer(i));
159
      }
160

    
161
    }
162
  }
163

    
164
  private void initConsolePanelListeners(JConsole jConsole) {
165
    consoleResponseAdapter = new ResponseAdapter();
166
    jConsole.addResponseListener(consoleResponseAdapter);
167
    addConsoleListener("ViewEditing", new ResponseListener() {
168

    
169
      public void acceptResponse(String response) {
170
        try {
171
          textEntered(response);
172
        }
173
        catch (InvalidEntryException e) {
174
          showConsoleMessage(i18nManager.getTranslation("invalid_option"));
175
        }
176
        catch (StopServiceException e) {
177
          logger.error("Can't stop "+ activeService.getName(), e);
178
        }
179
        finally {
180
          if (activeService != null) {
181
            getNextParameter();
182
          }
183
        }
184
      }
185
    });
186

    
187
  }
188

    
189
  public void activateService(String name) {
190

    
191
    EditingManager manager = EditingLocator.getManager();
192

    
193
    if (currentLayer != null) {
194
      EditingService service = serviceRegistration.get(currentLayer);
195
      if (service == null || !service.getName().equals(name)) {
196
        service = (EditingService) manager.getEditingService(name,
197
            currentLayer.getFeatureStore());
198
        serviceRegistration.put(currentLayer, service);
199
      }
200
      if (service != null) {
201
        this.activeService = service;
202
        try {
203
          service.start();
204
        }
205
        catch (StartServiceException e) {
206
          logger.error(
207
              String.format("Can't start the service %(s)", service.getName()),
208
              e);
209
        }
210
        getNextParameter();
211
      }
212
    }
213
  }
214

    
215
  /**
216
   * Shows description of parameter on console.
217
   */
218
  private void askQuestion(EditingServiceParameter param) {
219
    if (getConsolePanel() != null) {
220
      showConsoleMessage("\n#" + param.getDescription() + " > ");
221
    }
222
  }
223

    
224
  private void showConsoleMessage(String text) {
225
    getConsolePanel().addText(text, JConsole.MESSAGE);
226
  }
227

    
228
  @Override
229
  public ToolListener getListener() {
230
    return new ToolListener() {
231

    
232
      /**
233
       *
234
       */
235
      public boolean cancelDrawing() {
236
        return false;
237
      }
238

    
239
      /**
240
       *
241
       */
242
      public Image getImageCursor() {
243
        return imageCursor;
244
      }
245
    };
246
  }
247

    
248
  /**
249
   * Gets next parameter of {@link #activateService(String)} and sets
250
   * {@link #currentParam}. If currentParam is null means all service parameters
251
   * have value and service doesn't need more values.
252
   */
253
  private void getNextParameter() {
254
    currentParam = activeService.next();
255
    if (currentParam == null) {
256
      finishAndStartService();
257
    }
258
    else {
259
      askQuestion(currentParam);
260
      setCaretPosition();
261
    }
262

    
263
  }
264

    
265
  private void finishAndStartService() {
266
    try {
267
      activeService.finish();
268
    }
269
    catch (VectorEditingException e) {
270
      logger.error("An error ocurred when try to finish service", e);
271
    }
272
    mapControl.rePaintDirtyLayers();
273
    try {
274
      activeService.start();
275
    }
276
    catch (StartServiceException e) {
277
      logger.error(String.format("Can't start the service %(s)",
278
          activeService.getName()), e);
279
    }
280
    getNextParameter();
281
  }
282

    
283
  private void initMapControlListeners(MapControl mapControl) {
284

    
285
    MapContext context = mapControl.getMapContext();
286
    FLayers layers = context.getLayers();
287
    layers.addLayerListener(layerListener);
288

    
289
    layers.addLayerCollectionListener(new LayerCollectionListener() {
290

    
291
      public void layerAdded(LayerCollectionEvent e) {
292
        FLayers layers2 = e.getLayers();
293
        for (int i = 0; i < layers2.getLayersCount(); i++) {
294
          FLayer layer = layers2.getLayer(i);
295
          if (layer instanceof FLyrVect) {
296
            ((FLyrVect) layer).addLayerListener(layerListener);
297
          }
298
        }
299
      }
300

    
301
      public void layerAdding(LayerCollectionEvent e)
302
          throws CancelationException {}
303

    
304
      public void layerMoved(LayerPositionEvent e) {}
305

    
306
      public void layerMoving(LayerPositionEvent e) throws CancelationException {}
307

    
308
      public void layerRemoved(LayerCollectionEvent e) {
309
        FLayers layers2 = e.getLayers();
310
        for (int i = 0; i < layers2.getLayersCount(); i++) {
311
          FLayer layer = layers2.getLayer(i);
312
          if (layer instanceof FLyrVect) {
313
            ((FLyrVect) layer).removeLayerListener(layerListener);
314
          }
315
        }
316
      }
317

    
318
      public void layerRemoving(LayerCollectionEvent e)
319
          throws CancelationException {}
320

    
321
      public void visibilityChanged(LayerCollectionEvent e)
322
          throws CancelationException {}
323
    });
324
  }
325

    
326
  public void mouseClicked(MouseEvent e) {
327
    ViewPort vp = mapControl.getViewPort();
328
    if (activeService != null) {
329
      if (currentParam != null) {
330
        List<TYPE> typesOfParam = currentParam.getTypes();
331
        if (typesOfParam.contains(TYPE.LIST_POSITIONS)) {
332
          if (e.getClickCount() == 2) {
333
            finishAndStartService();
334
            return;
335
          }
336
          Point point;
337
          point = vp.convertToMapPoint(e.getX(), e.getY());
338
          try {
339
            this.activeService.value(point);
340
          }
341
          catch (VectorEditingException ex) {
342
            logger.error("Invalid value %s", new Object[] { point });
343
          }
344
        }
345
        if (typesOfParam.contains(TYPE.POSITION)) {
346
          Point point;
347
          point = vp.convertToMapPoint(e.getX(), e.getY());
348
          try {
349
            this.activeService.value(point);
350
          }
351
          catch (VectorEditingException ex) {
352
            logger.error("Invalid value %s", new Object[] { point });
353
          }
354
          // TODO: Comprobar el resto de casos:
355
          // TYPE.VALUE,
356
          // TYPE.OPTION, TYPE.SELECTION,
357
          // TYPE.GEOMETRY:
358
        }
359
        getNextParameter();
360
      }
361
    }
362
  }
363

    
364
  public void mouseEntered(MouseEvent e) throws BehaviorException {
365
    // TODO Auto-generated method stub
366
  }
367

    
368
  public void mouseMoved(MouseEvent e) throws BehaviorException {
369
    ViewPort vp = mapControl.getViewPort();
370
    adjustedPoint = vp.convertToMapPoint(e.getX(), e.getY());
371
    showCoords(e.getPoint());
372

    
373
    getMapControl().repaint();
374
  }
375

    
376
  public void mousePressed(MouseEvent e) throws BehaviorException {
377
    // TODO Auto-generated method stub
378
  }
379

    
380
  public void mouseReleased(MouseEvent e) throws BehaviorException {
381
    // TODO Auto-generated method stub
382
  }
383

    
384
  public void paintComponent(MapControlDrawer mapControlDrawer) {
385
    super.paintComponent(mapControlDrawer);
386
    if (activeService == null || adjustedPoint == null) {
387
      return;
388
    }
389

    
390
    DrawingStatus helperGeo = null;
391
    try {
392
      helperGeo = activeService.draw(adjustedPoint);
393
    }
394
    catch (VectorEditingException e) {
395
      logger.error("An error ocurred when draw service geometries", e);
396
    }
397
    if (helperGeo != null) {
398
      for (@SuppressWarnings("rawtypes")
399
      Iterator iterator = helperGeo.getGeometries().iterator(); iterator
400
          .hasNext();) {
401
        Geometry geometry = (Geometry) iterator.next();
402
        mapControl.getMapControlDrawer().draw(geometry,
403
            MapControlLocator.getMapControlManager().getAxisReferenceSymbol());
404
      }
405
    }
406
  }
407

    
408
  private void setCaretPosition() {
409

    
410
    JEditTextArea jeta = getConsolePanel().getTxt();
411
    jeta.requestFocusInWindow();
412
    jeta.setCaretPosition(jeta.getText().length());
413

    
414
  }
415

    
416
  /**
417
   * Sets the layer received as parameter as {@link #currentLayer}
418
   * 
419
   * @param layer
420
   */
421
  private void changeCurrentLayer(FLyrVect layer) {
422
    this.currentLayer = layer;
423
    this.activeService = serviceRegistration.get(layer);
424
    if (activeService != null) {
425
      getNextParameter();
426
      MainFrame main = PluginServices.getMainFrame();
427
      main.setSelectedTool(activeService.getName());
428
    }
429
  }
430

    
431
  /**
432
   * Show coordinates at status bar
433
   * 
434
   * @param point
435
   */
436
  private void showCoords(Point2D point) {
437
    String[] axisText = new String[2];
438
    axisText[0] = "X = ";
439
    axisText[1] = "Y = ";
440

    
441
    ViewPort vp = mapControl.getMapContext().getViewPort();
442
    IProjection iProj = vp.getProjection();
443
    Point p = vp.convertToMapPoint(point);
444
    Point2D p2D = new Point2D.Double(p.getX(), p.getY());
445

    
446
    sbl.setFractionDigits(p2D);
447
    axisText = sbl.setCoorDisplayText(axisText);
448
    MainFrame mF = PluginServices.getMainFrame();
449

    
450
    if (mF != null) {
451
      mF.getStatusBar().setMessage(
452
          "units",
453
          PluginServices.getText(this,
454
              MapContext.getDistanceNames()[vp.getDistanceUnits()]));
455
      mF.getStatusBar().setControlValue("scale",
456
          String.valueOf(mapControl.getMapContext().getScaleView()));
457
      mF.getStatusBar().setMessage("projection", iProj.getAbrev());
458

    
459
      String[] coords = sbl.getCoords(p2D);
460
      mF.getStatusBar().setMessage("x", axisText[0] + coords[0]);
461
      mF.getStatusBar().setMessage("y", axisText[1] + coords[1]);
462
    }
463

    
464
  }
465

    
466
  /**
467
   * Processes console entries from console. Tries to process entry in each type
468
   * of {@link #currentParam}. If there is some error, It will continue
469
   * checking. If entry has been processed, It will set value in {@link #activeService}.
470
   * 
471
   * @param response Console entry.
472
   * @throws InvalidEntryException If console entries has not been able to
473
   *           process, it will throw an exception to indicate that entry is not
474
   *           valid.
475
   * @throws StopServiceException If there are some errors stopping service.
476
   */
477
  private void textEntered(String response) throws InvalidEntryException, StopServiceException {
478
    if (response == null) {
479
      if (activeService != null) {
480
        this.activeService.stop();
481
        cleanBehavior();
482
      }
483
    }
484
    else {
485
      List<TYPE> types = currentParam.getTypes();
486
      Point point = null;
487
      Double value = null;
488

    
489
      boolean insertedValue = false;
490
      if (!insertedValue && types.contains(TYPE.POSITION)
491
          || types.contains(TYPE.LIST_POSITIONS)) {
492
        try {
493
          point = parsePoint(response);
494
          if (point != null) {
495
            this.activeService.value(point);
496
            insertedValue = true;
497
          }
498
        }
499
        catch (VectorEditingException e) {
500
          // Do nothing
501
        }
502
      }
503
      if (!insertedValue && types.contains(TYPE.VALUE)) {
504
        try {
505
          value = parseValue(response);
506
          if (value != null) {
507
            this.activeService.value(value);
508
            insertedValue = true;
509
          }
510
        }
511
        catch (VectorEditingException e) {
512
          // Do nothing
513
        }
514

    
515
      }
516
      if (!insertedValue && types.contains(TYPE.OPTION)) {
517
        try {
518
          response = response.replace("\n", "");
519
          if (response != null) {
520
            this.activeService.value(response);
521
            insertedValue = true;
522
          }
523
        }
524
        catch (VectorEditingException e) {
525
          // Do nothing
526
        }
527
      }
528
      // TODO: contemplar el resto de casos
529
      // TYPE.OPTION,
530
      // TYPE.SELECTION,
531
      // TYPE.GEOMETRY
532
      if (!insertedValue) {
533
        throw new InvalidEntryException(null);
534
      }
535
    }
536
  }
537

    
538
  /**
539
   * Parse String to value.
540
   * 
541
   * @param response String to be parsed.
542
   * @return Values of string.
543
   * @throws ParseValueException If there is error trying to parse <code>String</code>.
544
   */
545
  private Double parseValue(String response) throws ParseValueException {
546
    try {
547
      return Double.valueOf(response);
548
    }
549
    catch (Exception e) {
550
      throw new ParseValueException(e);
551
    }
552

    
553
  }
554

    
555
  /**
556
   * Parse String to point. Formats accepted: (x,y) and x,y.
557
   * 
558
   * @param response String to be parsed.
559
   * @return Point of string.
560
   * @throws ParsePointException If there is error trying to parse <code>String</code>.
561
   */
562
  private Point parsePoint(String response) throws ParsePointException {
563
    String[] numbers = new String[1];
564
    numbers[0] = response;
565
    numbers = response.split(",");
566
    if (numbers.length == 2) {
567
      if (numbers[0].startsWith("(") && numbers[1].endsWith(")\n")) { // CCS
568
        numbers[0] = numbers[0].replace("(", "");
569
        numbers[1] = numbers[1].replace(")\n", "");
570
      }
571
      double[] values;
572
      try {
573
        values = new double[] { Double.parseDouble(numbers[0]),
574
            Double.parseDouble(numbers[1]) };
575
      }
576
      catch (Exception e) {
577
        throw new ParsePointException(e);
578
      }
579

    
580
      Point point;
581
      try {
582
        point = geomManager.createPoint(values[0], values[1], currentLayer
583
            .getFeatureStore().getDefaultFeatureType()
584
            .getDefaultGeometryAttribute().getGeomType().getSubType());
585
        // TODO: Maybe do util class to get type and subtype of a featureStore
586
        // or a method in manager
587
      }
588
      catch (Exception e) {
589
        throw new ParsePointException(e);
590
      }
591
      return point;
592
    }
593
    else {
594
      throw new ParsePointException(null);
595
    }
596
  }
597

    
598
  private JDockPanel getDockConsole() {
599
    if (dockConsole == null) {
600
      dockConsole = new JDockPanel(getConsolePanel());
601
    }
602
    return dockConsole;
603
  }
604

    
605
  public void showConsole() {
606
    if (isShowConsole) {
607
      return;
608
    }
609
    isShowConsole = true;
610
    getMapControl().remove(getDockConsole());
611
    getMapControl().setLayout(new BorderLayout());
612
    getMapControl().add(getDockConsole(), BorderLayout.SOUTH);
613
    getDockConsole().setVisible(true);
614
    setCaretPosition();
615
  }
616

    
617
  public void hideConsole() {
618
    isShowConsole = false;
619
    getDockConsole().setVisible(false);
620

    
621
  }
622

    
623
  private JConsole getConsolePanel() {
624
    if (console == null) {
625
      console = new JConsole(true);
626
      // Para distinguir cuando se est? escribiendo sobre la consola y
627
      // cuando no.
628
      console.setJTextName("VectorEditingConsole");
629
    }
630
    return console;
631
  }
632

    
633
  private void addConsoleListener(String prefix, ResponseListener listener) {
634
    consoleResponseAdapter.putSpaceListener(prefix, listener);
635

    
636
  }
637

    
638
  static class ResponseAdapter implements ResponseListener {
639

    
640
    private HashMap<String, ResponseListener> spaceListener = new HashMap<String, ResponseListener>();
641

    
642
    public void putSpaceListener(String namespace, ResponseListener listener) {
643
      spaceListener.put(namespace, listener);
644
    }
645

    
646
    public void acceptResponse(String response) {
647
      boolean nameSpace = false;
648
      int n = -1;
649
      if (response != null) {
650
        if ((n = response.indexOf(':')) != -1) {
651
          nameSpace = true;
652
        }
653
      }
654

    
655
      if (nameSpace) {
656
        ResponseListener listener = spaceListener.get(response.substring(0, n));
657
        if (listener != null) {
658
          listener.acceptResponse(response.substring(n + 1));
659
        }
660
      }
661
      else {
662
        Iterator<ResponseListener> i = spaceListener.values().iterator();
663
        while (i.hasNext()) {
664
          ResponseListener listener = i.next();
665
          listener.acceptResponse(response);
666
        }
667
      }
668
    }
669
  }
670
}