зеркало из https://github.com/DeGsoft/maui-linux.git
236 строки
7.0 KiB
C#
236 строки
7.0 KiB
C#
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.Collections.ObjectModel;
|
|
using System.Collections.Specialized;
|
|
using System.ComponentModel;
|
|
using System.Linq;
|
|
using Xamarin.Forms.Internals;
|
|
|
|
namespace Xamarin.Forms.Maps
|
|
{
|
|
public class Map : View, IEnumerable<Pin>
|
|
{
|
|
public static readonly BindableProperty MapTypeProperty = BindableProperty.Create("MapType", typeof(MapType), typeof(Map), default(MapType));
|
|
|
|
public static readonly BindableProperty IsShowingUserProperty = BindableProperty.Create("IsShowingUser", typeof(bool), typeof(Map), default(bool));
|
|
|
|
public static readonly BindableProperty HasScrollEnabledProperty = BindableProperty.Create("HasScrollEnabled", typeof(bool), typeof(Map), true);
|
|
|
|
public static readonly BindableProperty HasZoomEnabledProperty = BindableProperty.Create("HasZoomEnabled", typeof(bool), typeof(Map), true);
|
|
|
|
public static readonly BindableProperty ItemsSourceProperty = BindableProperty.Create(nameof(ItemsSource), typeof(IEnumerable), typeof(Map), default(IEnumerable),
|
|
propertyChanged: (b, o, n) => ((Map)b).OnItemsSourcePropertyChanged((IEnumerable)o, (IEnumerable)n));
|
|
|
|
public static readonly BindableProperty ItemTemplateProperty = BindableProperty.Create(nameof(ItemTemplate), typeof(DataTemplate), typeof(Map), default(DataTemplate),
|
|
propertyChanged: (b, o, n) => ((Map)b).OnItemTemplatePropertyChanged((DataTemplate)o, (DataTemplate)n));
|
|
|
|
public static readonly BindableProperty ItemTemplateSelectorProperty = BindableProperty.Create(nameof(ItemTemplateSelector), typeof(DataTemplateSelector), typeof(Map), default(DataTemplateSelector),
|
|
propertyChanged: (b, o, n) => ((Map)b).OnItemTemplateSelectorPropertyChanged());
|
|
|
|
public static readonly BindableProperty MoveToLastRegionOnLayoutChangeProperty = BindableProperty.Create(nameof(MoveToLastRegionOnLayoutChange), typeof(bool), typeof(Map), defaultValue: true);
|
|
|
|
readonly ObservableCollection<Pin> _pins = new ObservableCollection<Pin>();
|
|
MapSpan _visibleRegion;
|
|
|
|
public Map(MapSpan region)
|
|
{
|
|
LastMoveToRegion = region;
|
|
|
|
VerticalOptions = HorizontalOptions = LayoutOptions.FillAndExpand;
|
|
|
|
_pins.CollectionChanged += PinsOnCollectionChanged;
|
|
}
|
|
|
|
// center on Rome by default
|
|
public Map() : this(new MapSpan(new Position(41.890202, 12.492049), 0.1, 0.1))
|
|
{
|
|
}
|
|
|
|
public bool HasScrollEnabled
|
|
{
|
|
get { return (bool)GetValue(HasScrollEnabledProperty); }
|
|
set { SetValue(HasScrollEnabledProperty, value); }
|
|
}
|
|
|
|
public bool HasZoomEnabled
|
|
{
|
|
get { return (bool)GetValue(HasZoomEnabledProperty); }
|
|
set { SetValue(HasZoomEnabledProperty, value); }
|
|
}
|
|
|
|
public bool IsShowingUser
|
|
{
|
|
get { return (bool)GetValue(IsShowingUserProperty); }
|
|
set { SetValue(IsShowingUserProperty, value); }
|
|
}
|
|
|
|
public MapType MapType
|
|
{
|
|
get { return (MapType)GetValue(MapTypeProperty); }
|
|
set { SetValue(MapTypeProperty, value); }
|
|
}
|
|
|
|
public IList<Pin> Pins
|
|
{
|
|
get { return _pins; }
|
|
}
|
|
|
|
public IEnumerable ItemsSource
|
|
{
|
|
get { return (IEnumerable)GetValue(ItemsSourceProperty); }
|
|
set { SetValue(ItemsSourceProperty, value); }
|
|
}
|
|
|
|
public DataTemplate ItemTemplate
|
|
{
|
|
get { return (DataTemplate)GetValue(ItemTemplateProperty); }
|
|
set { SetValue(ItemTemplateProperty, value); }
|
|
}
|
|
|
|
public DataTemplateSelector ItemTemplateSelector
|
|
{
|
|
get { return (DataTemplateSelector)GetValue(ItemTemplateSelectorProperty); }
|
|
set { SetValue(ItemTemplateSelectorProperty, value); }
|
|
}
|
|
|
|
public bool MoveToLastRegionOnLayoutChange
|
|
{
|
|
get { return (bool)GetValue(MoveToLastRegionOnLayoutChangeProperty); }
|
|
set { SetValue(MoveToLastRegionOnLayoutChangeProperty, value); }
|
|
}
|
|
|
|
public event EventHandler<MapClickedEventArgs> MapClicked;
|
|
|
|
[EditorBrowsable(EditorBrowsableState.Never)]
|
|
public void SendMapClicked(Position position) => MapClicked?.Invoke(this, new MapClickedEventArgs(position));
|
|
|
|
[EditorBrowsable(EditorBrowsableState.Never)]
|
|
public void SetVisibleRegion(MapSpan value) => VisibleRegion = value;
|
|
public MapSpan VisibleRegion
|
|
{
|
|
get { return _visibleRegion; }
|
|
internal set
|
|
{
|
|
if (_visibleRegion == value)
|
|
return;
|
|
if (value == null)
|
|
throw new ArgumentNullException(nameof(value));
|
|
OnPropertyChanging();
|
|
_visibleRegion = value;
|
|
OnPropertyChanged();
|
|
}
|
|
}
|
|
|
|
[EditorBrowsable(EditorBrowsableState.Never)]
|
|
public MapSpan LastMoveToRegion { get; private set; }
|
|
|
|
IEnumerator IEnumerable.GetEnumerator()
|
|
{
|
|
return GetEnumerator();
|
|
}
|
|
|
|
public IEnumerator<Pin> GetEnumerator()
|
|
{
|
|
return _pins.GetEnumerator();
|
|
}
|
|
|
|
public void MoveToRegion(MapSpan mapSpan)
|
|
{
|
|
if (mapSpan == null)
|
|
throw new ArgumentNullException(nameof(mapSpan));
|
|
LastMoveToRegion = mapSpan;
|
|
MessagingCenter.Send(this, "MapMoveToRegion", mapSpan);
|
|
}
|
|
|
|
void PinsOnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
|
|
{
|
|
if (e.NewItems != null && e.NewItems.Cast<Pin>().Any(pin => pin.Label == null))
|
|
throw new ArgumentException("Pin must have a Label to be added to a map");
|
|
}
|
|
|
|
void OnItemsSourcePropertyChanged(IEnumerable oldItemsSource, IEnumerable newItemsSource)
|
|
{
|
|
if (oldItemsSource is INotifyCollectionChanged ncc)
|
|
{
|
|
ncc.CollectionChanged -= OnItemsSourceCollectionChanged;
|
|
}
|
|
|
|
if (newItemsSource is INotifyCollectionChanged ncc1)
|
|
{
|
|
ncc1.CollectionChanged += OnItemsSourceCollectionChanged;
|
|
}
|
|
|
|
_pins.Clear();
|
|
CreatePinItems();
|
|
}
|
|
|
|
void OnItemTemplatePropertyChanged(DataTemplate oldItemTemplate, DataTemplate newItemTemplate)
|
|
{
|
|
if (newItemTemplate is DataTemplateSelector)
|
|
{
|
|
throw new NotSupportedException(
|
|
$"The {nameof(Map)}.{ItemTemplateProperty.PropertyName} property only supports {nameof(DataTemplate)}." +
|
|
$" Set the {nameof(Map)}.{ItemTemplateSelectorProperty.PropertyName} property instead to use a {nameof(DataTemplateSelector)}");
|
|
}
|
|
|
|
_pins.Clear();
|
|
CreatePinItems();
|
|
}
|
|
|
|
void OnItemTemplateSelectorPropertyChanged()
|
|
{
|
|
_pins.Clear();
|
|
CreatePinItems();
|
|
}
|
|
|
|
void OnItemsSourceCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
|
|
{
|
|
e.Apply(
|
|
insert: (item, _, __) => CreatePin(item),
|
|
removeAt: (item, _) => RemovePin(item),
|
|
reset: () => _pins.Clear());
|
|
}
|
|
|
|
void CreatePinItems()
|
|
{
|
|
if (ItemsSource == null || (ItemTemplate == null && ItemTemplateSelector == null))
|
|
{
|
|
return;
|
|
}
|
|
|
|
foreach (object item in ItemsSource)
|
|
{
|
|
CreatePin(item);
|
|
}
|
|
}
|
|
|
|
void CreatePin(object newItem)
|
|
{
|
|
DataTemplate itemTemplate = ItemTemplate;
|
|
if (itemTemplate == null)
|
|
itemTemplate = ItemTemplateSelector?.SelectTemplate(newItem, this);
|
|
|
|
if (itemTemplate == null)
|
|
return;
|
|
|
|
var pin = (Pin)itemTemplate.CreateContent();
|
|
pin.BindingContext = newItem;
|
|
_pins.Add(pin);
|
|
}
|
|
|
|
void RemovePin(object itemToRemove)
|
|
{
|
|
// Instead of just removing by item (i.e. _pins.Remove(pinToRemove))
|
|
// we need to remove by index because of how Pin.Equals() works
|
|
for (int i = 0; i < _pins.Count; ++i)
|
|
{
|
|
Pin pin = _pins[i];
|
|
if (pin.BindingContext?.Equals(itemToRemove) == true)
|
|
{
|
|
_pins.RemoveAt(i);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} |