Index: src/Common/SharpMap/Editors/FeatureInteractor.cs =================================================================== diff -u -r8f6ae890fed8e8eae3a32f9c0498a10f82e0ddf9 -r5fc71a385897af92ccb092f2f969b5709afab85a --- src/Common/SharpMap/Editors/FeatureInteractor.cs (.../FeatureInteractor.cs) (revision 8f6ae890fed8e8eae3a32f9c0498a10f82e0ddf9) +++ src/Common/SharpMap/Editors/FeatureInteractor.cs (.../FeatureInteractor.cs) (revision 5fc71a385897af92ccb092f2f969b5709afab85a) @@ -19,12 +19,14 @@ { public abstract class FeatureInteractor : IFeatureInteractor { - private readonly List trackers = new List(); - private IFeature sourceFeature; + public event WorkerFeatureCreated WorkerFeatureCreated; protected static readonly Cursor MoveCursor = new Cursor(Assembly.GetExecutingAssembly().GetManifestResourceStream("SharpMap.Editors.Cursors.Move.cur")); + private readonly List trackers = new List(); + private IFeature sourceFeature; + protected FeatureInteractor(ILayer layer, IFeature feature, VectorStyle vectorStyle, IEditableObject editableObject) { Layer = layer; @@ -35,6 +37,10 @@ CreateTrackers(); } + public VectorStyle VectorStyle { get; protected set; } + + public virtual IList SnapRules { get; set; } + /// /// original feature (geometry in coordinate system of Layer) /// @@ -52,31 +58,26 @@ public ILayer Layer { get; protected set; } - public VectorStyle VectorStyle { get; protected set; } - public virtual IFallOffPolicy FallOffPolicy { get; set; } - - public virtual IList SnapRules { get; set; } - protected IList FeatureRelationEditors { get; set; } + public virtual IEditableObject EditableObject { get; set; } - public virtual IEditableObject EditableObject { get; set; } - - protected abstract void CreateTrackers(); - public virtual IList Trackers { - get { return trackers; } + get + { + return trackers; + } } - protected IEnumerable TrackerIndices + public virtual Cursor GetCursor(TrackerFeature trackerFeature) { - get { return Trackers.Select(t => t.Index); } + return MoveCursor; } - protected IEnumerable SelectedTrackerIndices + public virtual IEnumerable GetFeatureRelationInteractors(IFeature feature) { - get { return Trackers.Where(t => t.Selected).Select(t => t.Index); } + yield break; } public virtual bool MoveTracker(TrackerFeature trackerFeature, double deltaX, double deltaY, SnapResult snapResult = null) @@ -91,7 +92,7 @@ if (handles.Count == 0) { return false; - // Do not throw exception, can occur in special cases when moving with CTRL toggle selection + // Do not throw exception, can occur in special cases when moving with CTRL toggle selection } if (FallOffPolicy != null) @@ -146,7 +147,7 @@ Trackers.Insert(index, new TrackerFeature(this, new Point(coordinate), index, null)); TargetFeature.Geometry = GeometryHelper.InsertCurvePoint(TargetFeature.Geometry, coordinate, index); - + foreach (var topologyRule in FeatureRelationEditors) { topologyRule.UpdateRelatedFeatures(SourceFeature, TargetFeature.Geometry, SelectedTrackerIndices.ToList()); @@ -155,15 +156,8 @@ return true; } - public virtual void SetTrackerSelection(TrackerFeature trackerFeature, bool select) - { - } + public virtual void SetTrackerSelection(TrackerFeature trackerFeature, bool select) {} - public virtual Cursor GetCursor(TrackerFeature trackerFeature) - { - return MoveCursor; - } - public virtual TrackerFeature GetTrackerAtCoordinate(ICoordinate worldPos) { return trackers.FirstOrDefault(t => t.Geometry.Intersects(GetLocalExtend(t, worldPos))); @@ -172,7 +166,7 @@ public virtual void Start() { TargetFeature = (IFeature) SourceFeature.Clone(); - + foreach (var featureRelationInteractor in GetFeatureRelationInteractors(SourceFeature)) { var activeRule = featureRelationInteractor.Activate(SourceFeature, TargetFeature, AddRelatedFeature, 0, FallOffPolicy); @@ -190,16 +184,21 @@ public virtual void Stop() { - if (TargetFeature == null) + if (TargetFeature == null) + { return; + } foreach (var topologyRule in FeatureRelationEditors) { - topologyRule.StoreRelatedFeatures(SourceFeature, TargetFeature.Geometry, new List { 0 }); + topologyRule.StoreRelatedFeatures(SourceFeature, TargetFeature.Geometry, new List + { + 0 + }); } SourceFeature.Geometry = (IGeometry) TargetFeature.Geometry.Clone(); - + FeatureRelationEditors.Clear(); // refresh trackers @@ -212,70 +211,75 @@ Stop(); } - public virtual void UpdateTracker(IGeometry geometry) + public virtual void UpdateTracker(IGeometry geometry) {} + + public bool AllowMove() { + return !IsLayerReadOnly() && AllowMoveCore(); } - /// - /// Default implementation for moving feature is set to false. IFeatureProvider is not required to - /// return the same objects for each request. For example the IFeatureProvider for shape files - /// constructs them on the fly in each GetGeometriesInView call. To support deletion and moving of - /// shapes local caching and writing of shape files has to be implemented. - /// - /// - protected virtual bool AllowMoveCore() + public bool AllowDeletion() { - return false; + return !IsLayerReadOnly() && AllowDeletionCore(); } /// /// Default set to false. See AllowMove. + /// Typically set to true for IPoint based geometries where there is only 1 tracker. /// /// - protected virtual bool AllowDeletionCore() + public virtual bool AllowSingleClickAndMove() { return false; } - public bool AllowMove() + public virtual void Add(IFeature feature) { - return !IsLayerReadOnly() && AllowMoveCore(); + Start(); + Stop(); } - public bool AllowDeletion() + protected IList FeatureRelationEditors { get; set; } + + protected IEnumerable TrackerIndices { - return !IsLayerReadOnly() && AllowDeletionCore(); + get + { + return Trackers.Select(t => t.Index); + } } - private bool IsLayerReadOnly() + protected IEnumerable SelectedTrackerIndices { - var layer = Layer; - - while (layer != null) + get { - if (layer.ReadOnly) - { - return true; - } + return Trackers.Where(t => t.Selected).Select(t => t.Index); + } + } - layer = Layer.Map != null ? Layer.Map.GetGroupLayerContainingLayer(layer) : null; - } + protected abstract void CreateTrackers(); + /// + /// Default implementation for moving feature is set to false. IFeatureProvider is not required to + /// return the same objects for each request. For example the IFeatureProvider for shape files + /// constructs them on the fly in each GetGeometriesInView call. To support deletion and moving of + /// shapes local caching and writing of shape files has to be implemented. + /// + /// + protected virtual bool AllowMoveCore() + { return false; } /// /// Default set to false. See AllowMove. - /// Typically set to true for IPoint based geometries where there is only 1 tracker. /// /// - public virtual bool AllowSingleClickAndMove() + protected virtual bool AllowDeletionCore() { return false; } - public event WorkerFeatureCreated WorkerFeatureCreated; - protected virtual void OnWorkerFeatureCreated(IFeature sourceFeature, IFeature workFeature) { if (null != WorkerFeatureCreated) @@ -284,15 +288,21 @@ } } - public virtual IEnumerable GetFeatureRelationInteractors(IFeature feature) + private bool IsLayerReadOnly() { - yield break; - } + var layer = Layer; - public virtual void Add(IFeature feature) - { - Start(); - Stop(); + while (layer != null) + { + if (layer.ReadOnly) + { + return true; + } + + layer = Layer.Map != null ? Layer.Map.GetGroupLayerContainingLayer(layer) : null; + } + + return false; } private void AddRelatedFeature(IList childTopologyRules, IFeature sourceFeature, IFeature cloneFeature, int level) @@ -303,31 +313,33 @@ { var activeRule = topologyRule.Activate(sourceFeature, cloneFeature, AddRelatedFeature, ++level, FallOffPolicy); if (activeRule != null) + { childTopologyRules.Add(activeRule); + } } } private IPolygon GetLocalExtend(TrackerFeature tracker, ICoordinate worldPos) { // get world position var mapWorldPos = Layer.CoordinateTransformation != null - ? GeometryTransform.TransformPoint(new Point(worldPos), Layer.CoordinateTransformation.MathTransform).Coordinate - : worldPos; + ? GeometryTransform.TransformPoint(new Point(worldPos), Layer.CoordinateTransformation.MathTransform).Coordinate + : worldPos; var size = tracker.Bitmap != null - ? MapHelper.ImageToWorld(Layer.Map, tracker.Bitmap.Width, tracker.Bitmap.Height) - : MapHelper.ImageToWorld(Layer.Map, 6, 6); + ? MapHelper.ImageToWorld(Layer.Map, tracker.Bitmap.Width, tracker.Bitmap.Height) + : MapHelper.ImageToWorld(Layer.Map, 6, 6); var boundingBox = MapHelper.GetEnvelope(mapWorldPos, size.X, size.Y); IPolygon polygon = new Polygon(new LinearRing(new[] - { - new Coordinate(boundingBox.MinX, boundingBox.MinY), - new Coordinate(boundingBox.MinX, boundingBox.MaxY), - new Coordinate(boundingBox.MaxX, boundingBox.MaxY), - new Coordinate(boundingBox.MaxX, boundingBox.MinY), - new Coordinate(boundingBox.MinX, boundingBox.MinY) - })); + { + new Coordinate(boundingBox.MinX, boundingBox.MinY), + new Coordinate(boundingBox.MinX, boundingBox.MaxY), + new Coordinate(boundingBox.MaxX, boundingBox.MaxY), + new Coordinate(boundingBox.MaxX, boundingBox.MinY), + new Coordinate(boundingBox.MinX, boundingBox.MinY) + })); if (Layer.CoordinateTransformation != null) {