diff --git a/samples/MapsuiInteractivitySample/ViewModels/MainWindowViewModel.cs b/samples/MapsuiInteractivitySample/ViewModels/MainWindowViewModel.cs index abd4fd6..3fd9fc1 100644 --- a/samples/MapsuiInteractivitySample/ViewModels/MainWindowViewModel.cs +++ b/samples/MapsuiInteractivitySample/ViewModels/MainWindowViewModel.cs @@ -39,6 +39,8 @@ public MainWindowViewModel() radioButtonList.Register(new RadioButtonItem("Circle"), DrawingCircleCommand, Reset); radioButtonList.Register(new RadioButtonItem("Polygon"), DrawingPolygonCommand, Reset); radioButtonList.Register(new RadioButtonItem("Route"), DrawingRouteCommand, Reset); + radioButtonList.Register(new RadioButtonItem("Select|Filter"), SelectWithFilterCommand, Reset); + radioButtonList.Register(new RadioButtonItem("Translate|Filter"), TranslateWithFilterCommand, Reset); RadioButtons = new List(radioButtonList.Items); @@ -115,10 +117,11 @@ public void PointeroverLeaveImpl() private void Reset() { - _selector?.Unselected(); + Interactive?.Cancel(); + Interactive = null; + _selector = null; - Interactive = null; State = States.Default; Tip = string.Empty; @@ -126,7 +129,52 @@ private void Reset() private void SelectCommand() { - _selector = new InteractiveBuilder().SelectSelector().Build(); + _selector = new InteractiveBuilder() + .SelectSelector() + .AttachTo(Map) + .Build(); + + _selector.Select.Subscribe(s => + { + Tip = $"Select{Environment.NewLine}{s.SelectedFeature?.ToFeatureInfo()}"; + + if (IsWktInfo == true) + { + WktInfo = s.SelectedFeature?.ToWkt(); + } + }); + + _selector.Unselect.Subscribe(s => + { + Tip = string.Empty; + + if (IsWktInfo == true) + { + WktInfo = string.Empty; + } + }); + + _selector.HoverBegin.Subscribe(s => + { + Tip = $"HoveringBegin{Environment.NewLine}{s.HoveringFeature?.ToFeatureInfo()}"; + }); + + _selector.HoverEnd.Subscribe(s => + { + Tip = string.Empty; + }); + + Interactive = _selector; + State = States.Selecting; + } + + private void SelectWithFilterCommand() + { + _selector = new InteractiveBuilder() + .SelectSelector() + .AttachTo(Map) + .AvailableFor(_userLayer) + .Build(); _selector.Select.Subscribe(s => { @@ -188,6 +236,33 @@ private void TranslateCommand() State = States.Selecting; } + private void TranslateWithFilterCommand() + { + _selector = new InteractiveBuilder() + .SelectDecorator() + .AttachTo(Map) + .WithSelector() + .AvailableFor(_userLayer) + .Build(); + + ((IDecoratorSelector)_selector).DecoratorSelecting.Subscribe(s => + { + Interactive = s; + State = States.Editing; + Tip = $"Translate mode"; + }); + + _selector.Unselect.Subscribe(s => + { + Interactive = s; + State = States.Selecting; + Tip = String.Empty; + }); + + Interactive = _selector; + State = States.Selecting; + } + private void ScaleCommand() { _selector = new InteractiveBuilder() diff --git a/samples/MapsuiInteractivitySample/Views/MainView.axaml b/samples/MapsuiInteractivitySample/Views/MainView.axaml index 8259067..fbf2bfd 100644 --- a/samples/MapsuiInteractivitySample/Views/MainView.axaml +++ b/samples/MapsuiInteractivitySample/Views/MainView.axaml @@ -117,6 +117,9 @@ + diff --git a/src/Mapsui.Interactivity.UI/CustomManipulators/EditingManipulator.cs b/src/Mapsui.Interactivity.UI/CustomManipulators/EditingManipulator.cs index 908859d..25a5024 100644 --- a/src/Mapsui.Interactivity.UI/CustomManipulators/EditingManipulator.cs +++ b/src/Mapsui.Interactivity.UI/CustomManipulators/EditingManipulator.cs @@ -35,7 +35,7 @@ public override void Completed(MouseEventArgs e) && IsClick(clickPoint, _clickPoint) == true && IFeature.Equals(_clickFeature, clickFeature) == true) { - View.Interactive.Canceling.Execute().Subscribe(); + View.Interactive.Cancel(); } } diff --git a/src/Mapsui.Interactivity/BaseInteractive.cs b/src/Mapsui.Interactivity/BaseInteractive.cs index a2ededa..7e19c96 100644 --- a/src/Mapsui.Interactivity/BaseInteractive.cs +++ b/src/Mapsui.Interactivity/BaseInteractive.cs @@ -31,5 +31,10 @@ public virtual void Hovering(MapInfo? mapInfo) { } public virtual void HoveringBegin(MapInfo? mapInfo) { } public virtual void HoveringEnd() { } + + public virtual void Cancel() + { + Canceling.Execute().Subscribe(); + } } } diff --git a/src/Mapsui.Interactivity/InteractiveBuilder.cs b/src/Mapsui.Interactivity/InteractiveBuilder.cs index 1813cf4..867b4f4 100644 --- a/src/Mapsui.Interactivity/InteractiveBuilder.cs +++ b/src/Mapsui.Interactivity/InteractiveBuilder.cs @@ -8,6 +8,7 @@ namespace Mapsui.Interactivity { public class InteractiveBuilder { + // TODO: to IDictionary> _cache private static readonly IDictionary> _cache1 = new Dictionary>(); private static readonly IDictionary> _cache2 = new Dictionary>(); diff --git a/src/Mapsui.Interactivity/Interfaces/IBuilder.cs b/src/Mapsui.Interactivity/Interfaces/IBuilder.cs index 1357d2a..4e133fc 100644 --- a/src/Mapsui.Interactivity/Interfaces/IBuilder.cs +++ b/src/Mapsui.Interactivity/Interfaces/IBuilder.cs @@ -17,7 +17,14 @@ public interface IAttachable where T : IBuilder T AttachTo(IMap map); } - public interface ISelectorBuilder : IBuilder { } + public interface IFilterable where T : IBuilder + { + T AvailableFor(ILayer[] layers); + + T AvailableFor(ILayer layer); + } + + public interface ISelectorBuilder : IBuilder, IAttachable, IFilterable { } public interface IDesignerBuilder : IBuilder, IAttachable { } @@ -28,5 +35,5 @@ public interface IDecoratorBuilder : IBuilder, IAttachable, IFilterable { } } diff --git a/src/Mapsui.Interactivity/Interfaces/IInteractive.cs b/src/Mapsui.Interactivity/Interfaces/IInteractive.cs index 1797fa0..6bbf320 100644 --- a/src/Mapsui.Interactivity/Interfaces/IInteractive.cs +++ b/src/Mapsui.Interactivity/Interfaces/IInteractive.cs @@ -25,5 +25,7 @@ public interface IInteractive void HoveringBegin(MapInfo? mapInfo); void HoveringEnd(); + + void Cancel(); } } diff --git a/src/Mapsui.Interactivity/SelectorBuilder.cs b/src/Mapsui.Interactivity/SelectorBuilder.cs index e7d3de3..20cac54 100644 --- a/src/Mapsui.Interactivity/SelectorBuilder.cs +++ b/src/Mapsui.Interactivity/SelectorBuilder.cs @@ -1,19 +1,89 @@ using Mapsui.Interactivity.Interfaces; +using Mapsui.Layers; namespace Mapsui.Interactivity { internal class SelectorBuilder : ISelectorBuilder { private readonly Func _builder; + private IList? _availableLayers; + private readonly IList _dirtyLayers = new List(); public SelectorBuilder(Func builder) { _builder = builder; } + internal LayerCollection? Layers { get; set; } + + public ISelectorBuilder AvailableFor(ILayer[] layers) + { + _availableLayers = layers.Select(s => s.Name).ToList(); + + return this; + } + + public ISelectorBuilder AvailableFor(ILayer layer) + { + _availableLayers = new List() { layer.Name }; + + return this; + } + + public ISelectorBuilder AttachTo(LayerCollection layers) + { + Layers = layers; + + return this; + } + + public ISelectorBuilder AttachTo(IMap map) + { + Layers = map.Layers; + + return this; + } + public ISelector Build() { - return (ISelector)_builder.Invoke(); + var selector = (ISelector)_builder.Invoke(); + + if (_availableLayers != null && Layers != null) + { + foreach (var item in Layers) + { + if (_availableLayers.Contains(item.Name) == true) + { + if (item.IsMapInfoLayer == false) + { + item.IsMapInfoLayer = true; + + _dirtyLayers.Add(item); + } + } + else + { + if (item.IsMapInfoLayer == true) + { + item.IsMapInfoLayer = false; + + _dirtyLayers.Add(item); + } + } + } + } + + selector.Canceling.Subscribe(s => + { + foreach (var item in _dirtyLayers) + { + item.IsMapInfoLayer = !item.IsMapInfoLayer; + } + + _dirtyLayers.Clear(); + }); + + return selector; } } } diff --git a/src/Mapsui.Interactivity/SelectorWithDecoratorBuilder.cs b/src/Mapsui.Interactivity/SelectorWithDecoratorBuilder.cs index dde89fb..84bc9c8 100644 --- a/src/Mapsui.Interactivity/SelectorWithDecoratorBuilder.cs +++ b/src/Mapsui.Interactivity/SelectorWithDecoratorBuilder.cs @@ -10,6 +10,8 @@ internal class SelectorWithDecoratorBuilder : ISelectorWithDecoratorBuilder { private readonly Func _builder; private readonly LayerCollection? _layers; + private IList? _availableLayers; + private readonly IList _dirtyLayers = new List(); public SelectorWithDecoratorBuilder(LayerCollection? layers, Func builder) { @@ -17,6 +19,20 @@ public SelectorWithDecoratorBuilder(LayerCollection? layers, Func s.Name).ToList(); + + return this; + } + + public ISelectorWithDecoratorBuilder AvailableFor(ILayer layer) + { + _availableLayers = new List() { layer.Name }; + + return this; + } + public ISelector Build() { ISelector selector = new DecoratorSelector(_builder); @@ -29,6 +45,41 @@ public ISelector Build() selector.Unselect.Subscribe(_ => _layers.RemoveInteractiveLayer()); } + if (_availableLayers != null && _layers != null) + { + foreach (var item in _layers) + { + if (_availableLayers.Contains(item.Name) == true) + { + if (item.IsMapInfoLayer == false) + { + item.IsMapInfoLayer = true; + + _dirtyLayers.Add(item); + } + } + else + { + if (item.IsMapInfoLayer == true) + { + item.IsMapInfoLayer = false; + + _dirtyLayers.Add(item); + } + } + } + } + + selector.Canceling.Subscribe(s => + { + foreach (var item in _dirtyLayers) + { + item.IsMapInfoLayer = !item.IsMapInfoLayer; + } + + _dirtyLayers.Clear(); + }); + return selector; } } diff --git a/src/Mapsui.Interactivity/Selectors/DecoratorSelector.cs b/src/Mapsui.Interactivity/Selectors/DecoratorSelector.cs index eaa4260..748152d 100644 --- a/src/Mapsui.Interactivity/Selectors/DecoratorSelector.cs +++ b/src/Mapsui.Interactivity/Selectors/DecoratorSelector.cs @@ -33,8 +33,7 @@ internal DecoratorSelector(Func builder) public override void Unselected() { - _decorator?.Canceling.Execute().Subscribe(); - + _decorator?.Cancel(); _decorator = null; base.Unselected(); diff --git a/src/Mapsui.Interactivity/Selectors/Selector.cs b/src/Mapsui.Interactivity/Selectors/Selector.cs index 48b3612..8ca1305 100644 --- a/src/Mapsui.Interactivity/Selectors/Selector.cs +++ b/src/Mapsui.Interactivity/Selectors/Selector.cs @@ -164,5 +164,12 @@ public override void HoveringEnd() HoverEnd?.Execute().Subscribe(); } } + + public override void Cancel() + { + Unselected(); + + base.Cancel(); + } } }