using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Security.Cryptography; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Windows.Forms; using Common.Logging; using GeoAPI.Geometries; using SharpMap; using SharpMap.Data; using SharpMap.Forms; using SharpMap.Forms.Tools; using SharpMap.Layers; namespace WinFormSamples { public class SampleTool : MapTool, IDisposable { private ILog Logger = LogManager.GetLogger(typeof(SampleTool)); public SampleTool() : base("Sample", "A sample tool that does nothing really useful") { Logger.Debug(fmh => fmh("Created \"{0}\"-Tool, {1}", Name,Description)); Enabled = true; } void IDisposable.Dispose() { HandleCancel(); } private ToolTip _toolTip; public SampleTool(MapBox mapBox1) : this() { MapControl = mapBox1; MapControl.MapChanged += (sender, args) => { HandleCancel(); }; _cts.Token.Register(HandleCancel); } public override bool DoKeyDown(Coordinate mapPosition, KeyEventArgs keyEventArgs) { Logger.Debug(fmh => fmh("KeyDown {1} at {0}", mapPosition, keyEventArgs.KeyCode)); return base.DoKeyDown(mapPosition, keyEventArgs); } public override bool DoKeyUp(Coordinate mapPosition, KeyEventArgs keyEventArgs) { Logger.Debug(fmh => fmh("KeyUp {1} at {0}", mapPosition, keyEventArgs.KeyCode)); return base.DoKeyUp(mapPosition, keyEventArgs); } public override bool DoMouseDoubleClick(Coordinate mapPosition, MouseEventArgs mouseEventArgs) { Logger.Debug(fmh => fmh("MouseDoubleClick {1} at {0}", mapPosition, mouseEventArgs.Button)); return base.DoMouseDoubleClick(mapPosition, mouseEventArgs); } public override bool DoMouseDown(Coordinate mapPosition, MouseEventArgs mouseEventArgs) { Logger.Debug(fmh => fmh("MouseDown {1} at {0}", mapPosition, mouseEventArgs.Button)); return base.DoMouseDown(mapPosition, mouseEventArgs); } public override bool DoMouseEnter() { Logger.Debug(fmh => fmh("MouseEnter")); return base.DoMouseEnter(); } protected override void OnEnabledChanged(EventArgs e) { base.OnEnabledChanged(e); if (!Enabled) { if (_toolTip != null) _toolTip.RemoveAll(); } } private CancellationTokenSource _cts = new CancellationTokenSource(); public override bool DoMouseHover(Coordinate mapPosition) { Logger.Debug(fmh => fmh("MouseHover at {0}", mapPosition)); _cts.Cancel(); _cts.Token.WaitHandle.WaitOne(); _cts.Dispose(); _cts = new CancellationTokenSource(); _cts.Token.Register(HandleCancel); var t = new Task(FindGeoNearPoint, mapPosition, _cts.Token); t.Start(); t.ContinueWith(res => ShowToolTip(res.Result)); return base.DoMouseHover(mapPosition); } BackgroundWorker _bw = new BackgroundWorker(); void HandleCancel() { if (_toolTip != null) { MapControl.Invoke(new MethodInvoker(() => { _toolTip.Hide(MapControl); _toolTip.Dispose(); })); _toolTip = null; } } private void ShowToolTip(FeatureDataRow fdr) { if (fdr != null) { MapControl.BeginInvoke(new Action(() => { var _t = new ToolTip(); _toolTip = _t; _t/*oolTip*/.ToolTipTitle = fdr.Table.TableName; _t/*oolTip*/.Show(ToText(fdr), MapControl); })); } else { //MapControl.BeginInvoke(new MethodInvoker( () => _toolTip.Hide(MapControl))); } } private string ToText(FeatureDataRow fdr) { var sb = new StringBuilder(); if (fdr.Geometry != null) { sb.AppendFormat("Geometry:\n Type: {0}\n SRID: {1}\n", fdr.Geometry.GeometryType, fdr.Geometry.SRID); switch (fdr.Geometry.Dimension) { case Dimension.Surface: sb.AppendFormat(" Area: {0}\n", fdr.Geometry.Area); break; case Dimension.Curve: sb.AppendFormat(" Length: {0}\n", fdr.Geometry.Length); break; case Dimension.Point: sb.AppendFormat(" Position: {0}\n", fdr.Geometry.AsText()); break; } } sb.Append("Data:\n"); foreach (DataColumn col in fdr.Table.Columns) sb.AppendFormat(" {0}: {1}\n", col.Caption, fdr[col] == DBNull.Value ? "NULL" : fdr[col]); Logger.Debug(fmh => fmh("\n{0}\n{1}", fdr.Table.TableName, sb.ToString(0, sb.Length-1))); return sb.ToString(0, sb.Length - 1); } private FeatureDataRow FindGeoNearPoint(object/*Coordinate*/ coord) { var mapPosition = (Coordinate) coord; var env = new Envelope(mapPosition); env.ExpandBy(5 * Map.PixelWidth); var g = NetTopologySuite.Geometries.Prepared.PreparedGeometryFactory.Prepare(Map.Factory.ToGeometry(env)); var fdrs = new List>(); var fds = new FeatureDataSet(); var tableCount = 0; var layersToQuery = GetLayersToQuery(Map); for (var i = layersToQuery.Count - 1; i >= 0; i--) { if (_cts.Token.IsCancellationRequested) { Logger.Debug("Cancellation requested"); return null; } var l = layersToQuery[i]; if (l.Enabled && l.MinVisible < Map.Zoom && l.MaxVisible >= Map.Zoom) { if (!l.IsQueryEnabled) continue; l.ExecuteIntersectionQuery(env, fds); for (var j = tableCount; j < fds.Tables.Count; j++) { var fdt = fds.Tables[j]; for (var k = 0; k < fdt.Rows.Count; k++) { var fdr = (FeatureDataRow) fdt.Rows[k]; if (g.Intersects(fdr.Geometry)) { var distance = g.Geometry.InteriorPoint.Distance(fdr.Geometry); if (fdr.Geometry.Dimension == Dimension.Surface) distance += 5* Map.PixelWidth; fdrs.Add(Tuple.Create(distance, fdr)); } } } tableCount = fds.Tables.Count; } } if (fdrs.Count > 0) { fdrs.Sort((t1, t2) => t1.Item1.CompareTo(t2.Item1)); return fdrs[0].Item2; } return null; } private static List GetLayersToQuery(Map map) { var res = new List(); for (var i = 0; i < map.BackgroundLayer.Count; i++) { if (map.BackgroundLayer[i] is ICanQueryLayer) { if (((ICanQueryLayer)map.BackgroundLayer[i]).IsQueryEnabled) res.Add((ICanQueryLayer)map.BackgroundLayer[i]); } } for (var i = 0; i < map.Layers.Count; i++) { if (map.Layers[i] is ICanQueryLayer) { if (((ICanQueryLayer)map.Layers[i]).IsQueryEnabled) res.Add((ICanQueryLayer)map.Layers[i]); } } return res; } public MapBox MapControl { get; private set; } public override bool DoMouseLeave() { Logger.Debug(fmh => fmh("MouseLeave")); //_toolTip.RemoveAll(); return base.DoMouseLeave(); } public override bool DoMouseMove(Coordinate mapPosition, MouseEventArgs mouseEventArgs) { Logger.Debug(fmh => fmh("MouseMove {1} at {0}", mapPosition, mouseEventArgs.Button)); //_toolTip.RemoveAll(); return base.DoMouseMove(mapPosition, mouseEventArgs); } public override bool DoMouseUp(Coordinate mapPosition, MouseEventArgs mouseEventArgs) { Logger.Debug(fmh => fmh("MouseUp {1} at {0}", mapPosition, mouseEventArgs.Button)); return base.DoMouseUp(mapPosition, mouseEventArgs); } public override bool DoMouseWheel(Coordinate mapPosition, MouseEventArgs mouseEventArgs) { Logger.Debug(fmh => fmh("MouseWheel {1} at {0}", mapPosition, mouseEventArgs.Button)); return base.DoMouseWheel(mapPosition, mouseEventArgs); } public override void Cancel() { Logger.Debug(fmh => fmh("Cancel")); base.Cancel(); } public override void DoPaint(PaintEventArgs e) { Logger.Debug(fmh => fmh("Paint")); base.DoPaint(e); } } }