using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
using Core.Common.Utils;
using Core.Common.Utils.Editing;
using Core.GIS.GeoApi.Extensions.Feature;
using Core.GIS.GeoApi.Geometries;
using Core.GIS.SharpMap.Api.Editors;
using Core.GIS.SharpMap.CoordinateSystems.Transformations;
using Core.GIS.SharpMap.Editors.Snapping;
using Core.GIS.SharpMap.UI.Helpers;
using Core.GIS.SharpMap.UI.Properties;
using Point = Core.GIS.NetTopologySuite.Geometries.Point;
namespace Core.GIS.SharpMap.UI.Tools
{
public class CurvePointTool : MapTool
{
public enum EditMode
{
Add,
Remove
};
private static readonly Cursor AddPointCursor = MapCursors.CreateArrowOverlayCuror(Resources.CurvePointSmall);
private static readonly Cursor RemovePointCursor = MapCursors.CreateArrowOverlayCuror(Resources.CurvePointSmallRemove);
private bool isMoving;
private bool isBusy;
private EditMode mode;
public CurvePointTool()
{
Name = "CurvePoint";
}
public override Cursor Cursor
{
get
{
switch (Mode)
{
case EditMode.Add:
return AddPointCursor;
case EditMode.Remove:
return RemovePointCursor;
default:
throw new ArgumentOutOfRangeException();
}
}
}
public override bool IsBusy
{
get
{
return isBusy;
}
}
public EditMode Mode
{
get
{
return (Control.ModifierKeys & Keys.Alt) == Keys.Alt ? EditMode.Remove : mode;
}
set
{
mode = value;
}
}
public override void OnMouseUp(ICoordinate worldPosition, MouseEventArgs e)
{
if (isMoving)
{
MoveTool.OnMouseUp(worldPosition, e);
}
else
{
SelectTool.OnMouseUp(worldPosition, e);
}
isBusy = false;
isMoving = false;
}
public override void OnMouseMove(ICoordinate worldPosition, MouseEventArgs e)
{
if (e.Button != MouseButtons.None && !isMoving)
{
return;
}
if (isMoving)
{
MoveTool.OnMouseMove(worldPosition, e);
}
else if ((SelectTool.SelectedFeatureInteractors.Count == 1)
&& SupportedGeometry(SelectTool.SelectedFeatureInteractors[0].SourceFeature.Geometry))
{
SelectTool.OnMouseMove(worldPosition, e);
Snap(SelectTool.SelectedFeatureInteractors[0].SourceFeature.Geometry, worldPosition);
SetMouseCursor();
StartDrawing();
DoDrawing(true);
StopDrawing();
}
}
public override void OnMouseDown(ICoordinate worldPosition, MouseEventArgs e)
{
if (e.Button != MouseButtons.Left)
{
return;
}
isBusy = true;
if (SelectTool.SelectedFeatureInteractors.Count != 1)
{
SelectTool.OnMouseDown(worldPosition, e);
return;
}
var featureInteractor = SelectTool.SelectedFeatureInteractors[0];
if (SupportedGeometry(featureInteractor.SourceFeature.Geometry))
{
if (SnapResult == null)
{
SelectTool.OnMouseDown(worldPosition, e);
return;
}
var worldPos = SnapResult.Location;
if (featureInteractor.Layer.CoordinateTransformation != null)
{
worldPos = GeometryTransform.TransformPoint(new Point(worldPos), featureInteractor.Layer.CoordinateTransformation.MathTransform.Inverse()).Coordinate;
}
var trackerFeature = featureInteractor.GetTrackerAtCoordinate(worldPos);
// if user click visible tracker it will be handled as move, otherwise a Trackers will be added.
if (Mode == EditMode.Add && trackerFeature != null && trackerFeature.Index != -1)
{
MoveTool.OnMouseDown(worldPosition, e);
isMoving = true;
return;
}
var renderRequired = false;
if (!featureInteractor.Layer.ReadOnly)
{
featureInteractor.Start();
if (featureInteractor.EditableObject != null)
{
var featureName = featureInteractor.SourceFeature is INameable
? ((INameable) featureInteractor.SourceFeature).Name
: "";
featureInteractor.EditableObject.BeginEdit(string.Format(ActionName + " {0}", featureName));
}
renderRequired = Mode == EditMode.Add
? featureInteractor.InsertTracker(worldPos, SnapResult.SnapIndexPrevious + 1)
: featureInteractor.RemoveTracker(trackerFeature);
featureInteractor.Stop();
}
if (featureInteractor.EditableObject != null)
{
featureInteractor.EditableObject.EndEdit();
}
SelectTool.Select(featureInteractor.Layer, featureInteractor.SourceFeature);
if (renderRequired)
{
featureInteractor.Layer.RenderRequired = true;
MapControl.Refresh();
return;
}
}
// if no curve point modification, handle as normal selection
SelectTool.OnMouseDown(worldPosition, e);
}
public override void Render(Graphics graphics, Map.Map mapBox)
{
MapControl.MoveTool.Render(graphics, mapBox);
}
private SnapResult SnapResult { get; set; }
private string ActionName
{
get
{
return Mode == EditMode.Add ? "Adding coordinate to geometry of" : "Removing coordinate from geometry of";
}
}
private SelectTool SelectTool
{
get
{
return MapControl.SelectTool;
}
}
private MoveTool MoveTool
{
get
{
return MapControl.MoveTool;
}
}
///
/// snapping specific for a tool. Called before layer specific snapping is applied.
///
///
private void Snap(IGeometry snapSource, ICoordinate worldPos)
{
SnapResult = null;
var sourceFeature = SelectTool.SelectedFeatureInteractors[0].SourceFeature;
if (!Equals(sourceFeature.Geometry, snapSource))
{
return;
}
SnapRole snapRole;
if (Mode == EditMode.Add)
{
snapRole = SnapRole.FreeAtObject;
if ((Control.ModifierKeys & Keys.Control) == Keys.Control)
{
snapRole = SnapRole.Free;
}
}
else
{
snapRole = SnapRole.AllTrackers;
}
var snapRule = new SnapRule
{
Obligatory = true, SnapRole = snapRole, PixelGravity = 8
};
SnapResult = MapControl.SnapTool.ExecuteSnapRule(snapRule, sourceFeature, sourceFeature.Geometry, new List
{
sourceFeature
}, worldPos, -1);
}
private static bool SupportedGeometry(IGeometry geometry)
{
return geometry is ILineString || geometry is IPolygon || geometry is IMultiLineString || geometry is IMultiPolygon;
}
private void SetMouseCursor()
{
var cursor = SnapResult == null
? Cursor
: Mode == EditMode.Add ? MapCursors.AddPoint : MapCursors.RemovePoint;
if (!ReferenceEquals(MapControl.Cursor, cursor))
{
MapControl.Cursor = cursor;
}
}
}
}