Index: DuplicateEditingProvider.java
===================================================================
--- DuplicateEditingProvider.java	(revision 2870)
+++ DuplicateEditingProvider.java	(revision 2871)
@@ -25,6 +25,7 @@
 package org.gvsig.vectorediting.lib.prov.duplicate;
 
 import java.awt.geom.AffineTransform;
+import java.text.DecimalFormat;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
@@ -37,11 +38,11 @@
 import org.gvsig.fmap.geom.Geometry;
 import org.gvsig.fmap.geom.GeometryLocator;
 import org.gvsig.fmap.geom.GeometryManager;
+import org.gvsig.fmap.geom.GeometryUtils;
 import org.gvsig.fmap.geom.aggregate.Aggregate;
 import org.gvsig.fmap.geom.aggregate.MultiCurve;
 import org.gvsig.fmap.geom.aggregate.MultiPoint;
 import org.gvsig.fmap.geom.aggregate.MultiSurface;
-import org.gvsig.fmap.geom.exception.CreateGeometryException;
 import org.gvsig.fmap.geom.operation.GeometryOperationException;
 import org.gvsig.fmap.geom.operation.GeometryOperationNotSupportedException;
 import org.gvsig.fmap.geom.primitive.Curve;
@@ -49,14 +50,14 @@
 import org.gvsig.fmap.geom.primitive.Point;
 import org.gvsig.fmap.geom.primitive.Surface;
 import org.gvsig.fmap.mapcontext.rendering.symbols.ISymbol;
-import org.gvsig.tools.ToolsLocator;
+import org.gvsig.symbology.SymbologyLocator;
+import org.gvsig.symbology.SymbologyManager;
+import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.text.ISimpleTextSymbol;
 import org.gvsig.tools.dispose.DisposableIterator;
 import org.gvsig.tools.dispose.DisposeUtils;
 import org.gvsig.tools.dynobject.DynObject;
 import org.gvsig.tools.exception.BaseException;
 import org.gvsig.tools.service.spi.ProviderServices;
-import org.gvsig.tools.visitor.VisitCanceledException;
-import org.gvsig.tools.visitor.Visitor;
 import org.gvsig.vectorediting.lib.api.DrawingStatus;
 import org.gvsig.vectorediting.lib.api.EditingServiceParameter;
 import org.gvsig.vectorediting.lib.api.EditingServiceParameter.TYPE;
@@ -86,6 +87,8 @@
     private final EditingServiceParameter firstPoint;
 
     private final EditingServiceParameter secondPoint;
+    
+    private final EditingServiceParameter equidistantCopies;
 
     private final FeatureStore featureStore;
 
@@ -118,6 +121,10 @@
         this.secondPoint =
             new DefaultEditingServiceParameter("second_point", "second_point",
                 TYPE.POSITION);
+
+        this.equidistantCopies = new DefaultEditingServiceParameter("equidistant_copies", "equidistant_copies", true, TYPE.VALUE);
+        this.equidistantCopies.setDefaultValue(1);
+
     }
 
     @Override
@@ -159,52 +166,80 @@
             FeatureSelection featureSelection =
                 (FeatureSelection) values.get(selection);
             Point firstPointValue = (Point) values.get(firstPoint);
+            Number equidistantCopiesNumberValue = ((Number) values.get(this.equidistantCopies));
+            int equidistantCopiesValue = equidistantCopiesNumberValue != null ? equidistantCopiesNumberValue.intValue() : ((Number)this.equidistantCopies.getDefaultValue()).intValue();
 
             if (featureSelection != null && firstPointValue != null) {
                 drawingStatus.addStatus(firstPointValue, auxiliaryPointSymbolEditing, "");
-                Line auxLine;
-                try {
-                    auxLine = geometryManager.createLine(subtype);
-                } catch (CreateGeometryException e1) {
-                    throw new DrawServiceException(e1);
-                }
-                auxLine.setPoints(firstPointValue, mousePosition);
-                drawingStatus.addStatus(auxLine, auxiliarylineSymbolEditing, "");
 
+                Point offset = GeometryUtils.createPoint(
+                        mousePosition.getX() - firstPointValue.getX(),
+                        mousePosition.getY() - firstPointValue.getY()
+                );
+
                 DisposableIterator it = null;
                 try {
                     it = featureSelection.fastIterator();
+                    Point pos = null;
                     while (it.hasNext()) {
                         Feature feature = (Feature) it.next();
                         ISymbol previewSymbol = this.getPreviewSymbol(feature);
 
-                        Geometry geometry =
-                            feature.getDefaultGeometry().cloneGeometry();
+                        Point antPos = firstPointValue;
+                        for (int c = 1; c <= equidistantCopiesValue; c++) {
+                            
+                            pos = GeometryUtils.createPoint(
+                                    firstPointValue.getX() + (c * offset.getX()),
+                                    firstPointValue.getY() + (c * offset.getY())
+                            );
 
-                        AffineTransform at =
-                            getMoveAffineTransform(firstPointValue,
-                                mousePosition);
-                        geometry.transform(at);
-                        ISymbol symbol=null;
-                        if(geometry instanceof Curve || geometry instanceof MultiCurve){
-                            symbol = lineSymbolEditing;
-                        } else if(geometry instanceof Surface || geometry instanceof MultiSurface){
-                            symbol = polygonSymbolEditing;
-                        } else if(geometry instanceof Point || geometry instanceof MultiPoint){
-                            symbol = auxiliaryPointSymbolEditing;
-                        }
-                        if(geometry instanceof Aggregate){
-                            int primitivesNumber = ((Aggregate)geometry).getPrimitivesNumber();
-                            for (int i = 0; i < primitivesNumber; i++) {
-                                drawingStatus.addStatus(((Aggregate)geometry).getPrimitiveAt(i), symbol, "");
-                                drawingStatus.addStatus(((Aggregate)geometry).getPrimitiveAt(i), previewSymbol, "");
+                            Geometry geometry
+                                    = feature.getDefaultGeometry().cloneGeometry();
+                            AffineTransform at
+                                    = getMoveAffineTransform(firstPointValue,
+                                            pos);
+                            geometry.transform(at);
+                            ISymbol symbol = null;
+                            if (geometry instanceof Curve || geometry instanceof MultiCurve) {
+                                symbol = lineSymbolEditing;
+                            } else if (geometry instanceof Surface || geometry instanceof MultiSurface) {
+                                symbol = polygonSymbolEditing;
+                            } else if (geometry instanceof Point || geometry instanceof MultiPoint) {
+                                symbol = auxiliaryPointSymbolEditing;
                             }
-                        } else {
-                            drawingStatus.addStatus(geometry, symbol, "");
-                            drawingStatus.addStatus(geometry, previewSymbol, "");
+
+                            if (geometry instanceof Aggregate) {
+                                int primitivesNumber = ((Aggregate) geometry).getPrimitivesNumber();
+                                for (int i = 0; i < primitivesNumber; i++) {
+                                    drawingStatus.addStatus(((Aggregate) geometry).getPrimitiveAt(i), symbol, "");
+                                    drawingStatus.addStatus(((Aggregate) geometry).getPrimitiveAt(i), previewSymbol, "");
+                                }
+                            } else {
+                                drawingStatus.addStatus(geometry, symbol, "");
+                                drawingStatus.addStatus(geometry, previewSymbol, "");
+                            }
+                            antPos = pos;
                         }
-//                        drawingStatus.addGeometry(geometry);
+                        
                     }
+                    
+                    if(pos != null) {
+                        Line auxLine = GeometryUtils.createLine(firstPointValue, pos, subtype);
+                        drawingStatus.addStatus(auxLine, auxiliarylineSymbolEditing, "");
+                    }
+ 
+                    Point pointText = GeometryUtils.createPoint(
+                                firstPointValue.getX() + (0.5 * offset.getX()),
+                                firstPointValue.getY() + (0.5 * offset.getY())
+                        );
+
+                    ISimpleTextSymbol textSymbol = getTextSymbol();
+                    drawingStatus.addStatus(
+                            pointText, 
+                            textSymbol, 
+                            new DecimalFormat("#.0#").format(Math.sqrt(Math.pow(offset.getX(),2)+Math.pow(offset.getY(),2)))
+                    );
+                    
                 } catch (BaseException e) {
                     throw new DrawServiceException(e);
                 } finally {
@@ -240,6 +275,7 @@
         parameters.add(selection);
         parameters.add(firstPoint);
         parameters.add(secondPoint);
+        parameters.add(equidistantCopies);
         return parameters;
     }
 
@@ -267,6 +303,13 @@
             if (value instanceof Point) {
                 values.put(parameter, value);
             }
+        } else if (parameter == equidistantCopies) {
+            if (value instanceof Number) {
+                int intValue = ((Number) value).intValue();
+                if(intValue >= 1) {
+                    values.put(parameter, ((Number) value).intValue());
+                }
+            }
         }
     }
 
@@ -281,10 +324,12 @@
 
             final Point p1 = (Point) values.get(firstPoint);
             final Point p2 = (Point) values.get(secondPoint);
+            Number equidistantCopiesNumberValue = ((Number) values.get(this.equidistantCopies));
+            int equidistantCopiesValue = equidistantCopiesNumberValue != null ? equidistantCopiesNumberValue.intValue() : ((Number)this.equidistantCopies.getDefaultValue()).intValue();
 
             FeatureSelection featureSelection =
                 (FeatureSelection) values.get(selection);
-            ToolsLocator.getDisposableManager().bind(featureSelection);
+//            ToolsLocator.getDisposableManager().bind(featureSelection);
 
             try {
                 featureSelection.accept((Object obj) -> {
@@ -293,21 +338,36 @@
                     EditingProviderServices editingProviderServices =
                             (EditingProviderServices) getProviderServices();
                     
-                    EditableFeature editable =
-                            editingProviderServices.getFeatureCopyWithoutUniqueIndex(
-                                    featureStore, feature);
+                    Point offset = GeometryUtils.createPoint(
+                            p2.getX() - p1.getX(),
+                            p2.getY() - p1.getY()
+                    );
                     
-                    Geometry geometry =
-                            feature.getDefaultGeometry().cloneGeometry();
-                    geometry.transform(getMoveAffineTransform(p1, p2));
-                    
-                    editable.setDefaultGeometry(geometry);
-                    editingProviderServices.insertFeatureIntoFeatureStore(
-                            editable, featureStore);
+                    for(int c = 1; c <= equidistantCopiesValue; c++){
+
+                        EditableFeature editable =
+                                editingProviderServices.getFeatureCopyWithoutUniqueIndex(
+                                        featureStore, feature);
+
+                        Geometry geometry =
+                                feature.getDefaultGeometry().cloneGeometry();
+                        
+                        Point pos = GeometryUtils.createPoint(
+                                p1.getX() + (c * offset.getX()),
+                                p1.getY() + (c * offset.getY())
+                        );
+                        
+                        
+                        geometry.transform(getMoveAffineTransform(p1, pos));
+
+                        editable.setDefaultGeometry(geometry);
+                        editingProviderServices.insertFeatureIntoFeatureStore(
+                                editable, featureStore);
+                    }
                 });
 
-                featureStore.getFeatureSelection().deselectAll();
-                featureSelection.dispose();
+//                featureStore.getFeatureSelection().deselectAll();
+//                featureSelection.dispose();
 
             } catch (BaseException e) {
                 throw new FinishServiceException(e);
@@ -334,6 +394,11 @@
     }
 
     @Override
+    public void restart() throws StartServiceException, InvalidEntryException, StopServiceException {
+        values.put(secondPoint,null);
+    }
+    
+    @Override
     public String getName() {
         return DuplicateEditingProviderFactory.PROVIDER_NAME;
     }
@@ -342,5 +407,21 @@
     public Object getValue(EditingServiceParameter parameter) {
         return values!=null?values.get(parameter):null;
     }
+    
+    private ISimpleTextSymbol getTextSymbol(){
+        SymbologyManager symbologyManager = SymbologyLocator.getSymbologyManager();
+        ISimpleTextSymbol textSymbol = symbologyManager.createSimpleTextSymbol();
+        textSymbol.setFontSize(10);
+        return textSymbol;
+    }
 
+    @Override
+    public boolean isEnabled(EditingServiceParameter parameter) {
+
+        if (parameter == equidistantCopies) {
+            return true;
+        }
+        return true;
+    }
+
 }
