File: SwipeView\SwipeItems.cs
Web Access
Project: src\src\Controls\src\Core\Controls.Core.csproj (Microsoft.Maui.Controls)
#nullable disable
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.Linq;
using Microsoft.Extensions.Logging;
 
namespace Microsoft.Maui.Controls
{
	/// <include file="../../docs/Microsoft.Maui.Controls/SwipeItems.xml" path="Type[@FullName='Microsoft.Maui.Controls.SwipeItems']/Docs/*" />
	public class SwipeItems : Element, IList<ISwipeItem>, INotifyCollectionChanged
	{
		readonly ObservableCollection<Maui.ISwipeItem> _swipeItems;
 
		/// <include file="../../docs/Microsoft.Maui.Controls/SwipeItems.xml" path="//Member[@MemberName='.ctor']/Docs/*" />
		public SwipeItems(IEnumerable<ISwipeItem> swipeItems)
		{
			foreach (var item in swipeItems)
				if (item is Element e)
				{
					CheckParent(e);
					AddLogicalChild(e);
				}
 
			_swipeItems = new ObservableCollection<Maui.ISwipeItem>(swipeItems) ?? throw new ArgumentNullException(nameof(swipeItems));
			_swipeItems.CollectionChanged += OnSwipeItemsChanged;
		}
 
		/// <include file="../../docs/Microsoft.Maui.Controls/SwipeItems.xml" path="//Member[@MemberName='.ctor'][1]/Docs/*" />
		public SwipeItems() : this(Enumerable.Empty<ISwipeItem>())
		{
 
		}
 
		/// <summary>Bindable property for <see cref="Mode"/>.</summary>
		public static readonly BindableProperty ModeProperty = BindableProperty.Create(nameof(Mode), typeof(SwipeMode), typeof(SwipeItems), SwipeMode.Reveal);
		/// <summary>Bindable property for <see cref="SwipeBehaviorOnInvoked"/>.</summary>
		public static readonly BindableProperty SwipeBehaviorOnInvokedProperty = BindableProperty.Create(nameof(SwipeBehaviorOnInvoked), typeof(SwipeBehaviorOnInvoked), typeof(SwipeItems), SwipeBehaviorOnInvoked.Auto);
 
		/// <include file="../../docs/Microsoft.Maui.Controls/SwipeItems.xml" path="//Member[@MemberName='Mode']/Docs/*" />
		public SwipeMode Mode
		{
			get { return (SwipeMode)GetValue(ModeProperty); }
			set { SetValue(ModeProperty, value); }
		}
 
		/// <include file="../../docs/Microsoft.Maui.Controls/SwipeItems.xml" path="//Member[@MemberName='SwipeBehaviorOnInvoked']/Docs/*" />
		public SwipeBehaviorOnInvoked SwipeBehaviorOnInvoked
		{
			get { return (SwipeBehaviorOnInvoked)GetValue(SwipeBehaviorOnInvokedProperty); }
			set { SetValue(SwipeBehaviorOnInvokedProperty, value); }
		}
 
		public event NotifyCollectionChangedEventHandler CollectionChanged;
 
		public ISwipeItem this[int index]
		{
			get => _swipeItems.Count > index ? (ISwipeItem)_swipeItems[index] : null;
			set => _swipeItems[index] = value;
		}
 
		/// <include file="../../docs/Microsoft.Maui.Controls/SwipeItems.xml" path="//Member[@MemberName='Count']/Docs/*" />
		public int Count => _swipeItems.Count;
 
		/// <include file="../../docs/Microsoft.Maui.Controls/SwipeItems.xml" path="//Member[@MemberName='IsReadOnly']/Docs/*" />
		public bool IsReadOnly => false;
 
		/// <include file="../../docs/Microsoft.Maui.Controls/SwipeItems.xml" path="//Member[@MemberName='Add']/Docs/*" />
		public void Add(ISwipeItem item)
		{
			_swipeItems.Add(item);
		}
 
		/// <include file="../../docs/Microsoft.Maui.Controls/SwipeItems.xml" path="//Member[@MemberName='Clear']/Docs/*" />
		public void Clear()
		{
			foreach (var item in _swipeItems)
				if (item is Element e)
					RemoveLogicalChild(e);
 
			_swipeItems.Clear();
		}
 
		/// <include file="../../docs/Microsoft.Maui.Controls/SwipeItems.xml" path="//Member[@MemberName='Contains']/Docs/*" />
		public bool Contains(ISwipeItem item)
		{
			return _swipeItems.Contains(item);
		}
 
		/// <include file="../../docs/Microsoft.Maui.Controls/SwipeItems.xml" path="//Member[@MemberName='CopyTo']/Docs/*" />
		public void CopyTo(ISwipeItem[] array, int arrayIndex)
		{
			_swipeItems.CopyTo(array, arrayIndex);
		}
 
		/// <include file="../../docs/Microsoft.Maui.Controls/SwipeItems.xml" path="//Member[@MemberName='GetEnumerator']/Docs/*" />
		public IEnumerator<ISwipeItem> GetEnumerator()
		{
			foreach (ISwipeItem item in _swipeItems)
				yield return item;
		}
 
		/// <include file="../../docs/Microsoft.Maui.Controls/SwipeItems.xml" path="//Member[@MemberName='IndexOf']/Docs/*" />
		public int IndexOf(ISwipeItem item)
		{
			return _swipeItems.IndexOf(item);
		}
 
		/// <include file="../../docs/Microsoft.Maui.Controls/SwipeItems.xml" path="//Member[@MemberName='Insert']/Docs/*" />
		public void Insert(int index, ISwipeItem item)
		{
			_swipeItems.Insert(index, item);
		}
 
		/// <include file="../../docs/Microsoft.Maui.Controls/SwipeItems.xml" path="//Member[@MemberName='Remove']/Docs/*" />
		public bool Remove(ISwipeItem item)
		{
			return _swipeItems.Remove(item);
		}
 
		/// <include file="../../docs/Microsoft.Maui.Controls/SwipeItems.xml" path="//Member[@MemberName='RemoveAt']/Docs/*" />
		public void RemoveAt(int index)
		{
			_swipeItems.RemoveAt(index);
		}
 
		void OnSwipeItemsChanged(object sender, NotifyCollectionChangedEventArgs notifyCollectionChangedEventArgs)
		{
			if (notifyCollectionChangedEventArgs.NewItems is not null)
			{
				foreach (var item in notifyCollectionChangedEventArgs.NewItems)
					if (item is Element e)
					{
						CheckParent(e);
						AddLogicalChild(e);
					}
			}
 
			if (notifyCollectionChangedEventArgs.OldItems is not null)
			{
				foreach (var item in notifyCollectionChangedEventArgs.OldItems)
					if (item is Element e)
						RemoveLogicalChild(e);
			}
 
			CollectionChanged?.Invoke(this, notifyCollectionChangedEventArgs);
		}
 
		IEnumerator IEnumerable.GetEnumerator()
		{
			return _swipeItems.GetEnumerator();
		}
 
		// If a SwipeItem occupies multiple SwipeItems, we only want the logical hierarchy
		// to wire up to the SwipeItems that are currently part of a SwipeView.
		// We could throw an exception here but that would be too hostile of a breaking behavior.
		// TODO NET9 This warning should probably be elevated to `Element` for NET9
		void CheckParent(Element e)
		{
			if (e.Parent is not null && e.Parent != this)
			{
				this.CreateLogger<SwipeItems>()
					?.LogWarning($"{e} is already part of {e.Parent}. Remove from {e.Parent} to avoid inconsistent behavior.");
			}
		}
	}
}