File: Platform\Tizen\MauiSwipeView.cs
Web Access
Project: src\src\Core\src\Core.csproj (Microsoft.Maui)
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Maui.Graphics;
using Tizen.UIExtensions.Common.Internal;
using Tizen.UIExtensions.NUI;
using GSize = Microsoft.Maui.Graphics.Size;
using NView = Tizen.NUI.BaseComponents.View;
using TPointStateType = Tizen.NUI.PointStateType;
using TRect = Tizen.UIExtensions.Common.Rect;
 
namespace Microsoft.Maui.Platform
{
	public class MauiSwipeView : ContentViewGroup, IAnimatable
	{
		const float OpenSwipeThresholdPercentage = 0.6f; // 60%
		const uint SwipeAnimationDuration = 200;
 
		IPlatformViewHandler? _contentHandler;
		NView? _contentView;
		NView? _actionView;
 
		bool _isSwiping;
		bool _isSwipeEnabled;
		bool _isResettingSwipe;
		bool _isOpen;
		double _swipeOffset;
		double _swipeThreshold;
		double _itemsWidth;
		double _itemsHeight;
		Point _initialPoint;
		SwipeDirection? _swipeDirection;
		OpenSwipeItem _previousOpenSwipeItem;
		SwipeTransitionMode _swipeTransitionMode;
		readonly Dictionary<ISwipeItem, NView> _swipeItems = new Dictionary<ISwipeItem, NView>();
 
		public MauiSwipeView(ISwipeView view) : base(view)
		{
			GrabTouchAfterLeave = true;
			ClippingMode = Tizen.NUI.ClippingModeType.ClipToBoundingBox;
			TouchEvent += OnTouchEvent;
 
			Element = view;
		}
 
		ISwipeView Element { get; }
 
		IMauiContext MauiContext => Element?.Handler?.MauiContext ?? throw new InvalidOperationException("MauiContext cannot be null here");
 
		public void UpdateSwipeTransitionMode(SwipeTransitionMode swipeTransitionMode)
		{
			_swipeTransitionMode = swipeTransitionMode;
		}
 
		public void UpdateContent()
		{
			if (_contentView != null)
			{
				Children.Remove(_contentView);
				_contentView?.Unparent();
				_contentView?.Dispose();
				_contentView = null;
			}
 
			_contentHandler?.Dispose();
			_contentHandler = null;
 
			if (Element?.PresentedContent is IView view)
			{
				_contentView = view.ToPlatform(MauiContext);
				if (view.Handler is IPlatformViewHandler thandler)
				{
					_contentHandler = thandler;
				}
			}
			else
			{
				_contentView = CreateEmptyContent();
			}
			Children.Add(_contentView);
		}
 
		public void UpdateIsSwipeEnabled(bool isEnabled)
		{
			_isSwipeEnabled = isEnabled;
		}
 
		public void UpdateIsVisibleSwipeItem(ISwipeItem item)
		{
			if (!_isOpen)
				return;
 
			_swipeItems.TryGetValue(item, out NView? view);
 
			if (view != null)
			{
				_swipeThreshold = 0;
				LayoutSwipeItems(GetNativeSwipeItems());
				SwipeToThreshold(false);
			}
		}
 
		public void OnOpenRequested(SwipeViewOpenRequest e)
		{
			if (_contentView == null)
				return;
 
			var openSwipeItem = e.OpenSwipeItem;
			var animated = e.Animated;
 
			ProgrammaticallyOpenSwipeItem(openSwipeItem, animated);
		}
 
		public void OnCloseRequested(SwipeViewCloseRequest e)
		{
			var animated = e.Animated;
 
			ResetSwipe(animated);
		}
 
		bool OnTouchEvent(object source, TouchEventArgs e)
		{
			if (!_isSwipeEnabled)
				return false;
 
			var touchPosition = e.Touch.GetLocalPosition(0);
			var point = new Point(touchPosition.X.ToScaledDP(), touchPosition.Y.ToScaledDP());
 
			switch (e.Touch.GetState(0))
			{
				case TPointStateType.Down:
					return ProcessTouchDown(point);
				case TPointStateType.Motion:
					return ProcessTouchMove(point);
				case TPointStateType.Up:
				case TPointStateType.Interrupted:
					return ProcessTouchUp();
				default:
					return false;
			}
		}
 
		bool ProcessTouchDown(Point point)
		{
			if (_isSwiping || _contentView == null)
				return false;
 
			ResetSwipe(true);
 
			_initialPoint = point;
			return true;
		}
 
		bool ProcessTouchMove(Point point)
		{
			if (_contentView == null || _initialPoint.IsEmpty)
				return false;
 
			if (!_isOpen)
			{
				ResetSwipeToInitialPosition();
				_swipeDirection = SwipeDirectionHelper.GetSwipeDirection(_initialPoint, point);
				UpdateSwipeItems();
			}
 
			if (_isResettingSwipe || !ValidateSwipeDirection())
				return false;
 
			if (!_isSwiping)
			{
				RaiseSwipeStarted();
				_isSwiping = true;
			}
 
			_swipeOffset = GetSwipeOffset(_initialPoint, point);
			UpdateIsOpen(_swipeOffset != 0);
 
			UpdateSwipeItems();
 
			if (Math.Abs(_swipeOffset) > double.Epsilon)
				Swipe();
 
			RaiseSwipeChanging();
 
			return true;
		}
 
		bool ProcessTouchUp()
		{
			if (!_isSwiping)
				return false;
 
			_isSwiping = false;
 
			RaiseSwipeEnded();
 
			if (_isResettingSwipe || !ValidateSwipeDirection())
				return false;
 
			ValidateSwipeThreshold();
 
			return false;
		}
 
		void ResetSwipeToInitialPosition()
		{
			_isResettingSwipe = false;
			_isSwiping = false;
			_swipeThreshold = 0;
			_swipeDirection = null;
			DisposeSwipeItems();
		}
 
		void DisposeSwipeItems()
		{
			foreach (var item in _swipeItems.Keys)
			{
				if (item.Handler is IPlatformViewHandler platformViewHandler)
				{
					platformViewHandler.Dispose();
				}
				else
				{
					item.Handler?.DisconnectHandler();
					_swipeItems[item].Unparent();
					_swipeItems[item].Dispose();
				}
				item.Handler = null;
			}
			_swipeItems.Clear();
 
			if (_actionView != null)
			{
				Children.Remove(_actionView);
				_actionView.Dispose();
				_actionView = null;
			}
			UpdateIsOpen(false);
		}
 
		void UpdateIsOpen(bool isOpen)
		{
			_isOpen = isOpen;
			Element.IsOpen = isOpen;
		}
 
		void UpdateOffset(double swipeOffset)
		{
			switch (_swipeDirection)
			{
				case SwipeDirection.Right:
				case SwipeDirection.Down:
					_swipeOffset = swipeOffset;
					break;
				case SwipeDirection.Left:
				case SwipeDirection.Up:
					_swipeOffset = -swipeOffset;
					break;
			}
		}
 
		static void UpdateSwipeItemViewLayout(ISwipeItemView swipeItemView)
		{
			swipeItemView?.Handler?.ToPlatform().InvalidateMeasure(swipeItemView);
		}
 
		void UpdateSwipeItems()
		{
			if (_contentView == null || _actionView != null)
				return;
 
			ISwipeItems? items = GetSwipeItemsByDirection();
 
			if (items?.Count == 0 || items == null)
				return;
 
			_actionView = new NView
			{
				Layout = new Tizen.NUI.AbsoluteLayout(),
				WidthSpecification = Tizen.NUI.BaseComponents.LayoutParamPolicies.MatchParent,
				HeightSpecification = Tizen.NUI.BaseComponents.LayoutParamPolicies.MatchParent,
			};
 
			var swipeItems = new List<NView>();
 
			foreach (var item in items)
			{
				var swipeItem = item.ToPlatform(MauiContext);
				if (swipeItem != null)
				{
					if (item is ISwipeItemView formsSwipeItemView)
					{
						UpdateSwipeItemViewLayout(formsSwipeItemView);
					}
 
					_actionView.Add(swipeItem);
					_swipeItems.Add(item, swipeItem);
					swipeItems.Add(swipeItem);
 
					swipeItem.TouchEvent += (s, e) =>
					{
						if (e.Touch.GetState(0) == TPointStateType.Up)
						{
							ExecuteSwipeItem(item);
							if (GetSwipeItemsByDirection()?.SwipeBehaviorOnInvoked != SwipeBehaviorOnInvoked.RemainOpen)
								ResetSwipe();
						}
 
						return true;
					};
				}
			}
 
			Children.Add(_actionView);
			_contentView.RaiseToTop();
 
			LayoutSwipeItems(swipeItems);
		}
 
		void LayoutSwipeItems(List<NView> children)
		{
			if (_actionView == null || children == null || _contentView == null)
				return;
 
			_itemsWidth = 0;
			_itemsHeight = 0;
 
			var items = GetSwipeItemsByDirection();
 
			if (items == null || items.Count == 0)
				return;
 
			int i = 0;
			int previousWidth = 0;
 
			foreach (var child in children)
			{
				if (child.Visibility)
				{
					var item = items[i];
					var swipeItemSize = GetSwipeItemSize(item);
 
					var swipeItemHeight = swipeItemSize.Height.ToScaledPixel();
					var swipeItemWidth = swipeItemSize.Width.ToScaledPixel();
					TRect bound = new TRect();
 
					switch (_swipeDirection)
					{
						case SwipeDirection.Left:
							bound.X = _contentView.PositionX + _contentView.SizeWidth - (swipeItemWidth + previousWidth);
							bound.Y = _contentView.PositionY;
							bound.Width = swipeItemWidth;
							bound.Height = swipeItemHeight;
							break;
						case SwipeDirection.Right:
							bound.X = _contentView.PositionX + previousWidth;
							bound.Y = _contentView.PositionY;
							bound.Width = swipeItemWidth;
							bound.Height = swipeItemHeight;
							break;
						case SwipeDirection.Down:
							bound.X = _contentView.PositionX + previousWidth;
							bound.Y = _contentView.PositionY;
							bound.Width = swipeItemWidth;
							bound.Height = swipeItemHeight;
							break;
						case SwipeDirection.Up:
							bound.X = _contentView.PositionX + previousWidth;
							bound.Y = _contentView.PositionY + _contentView.SizeHeight - swipeItemHeight;
							bound.Width = swipeItemWidth;
							bound.Height = swipeItemHeight;
							break;
					}
					child.UpdateBounds(bound);
 
					i++;
					previousWidth += swipeItemWidth;
					_itemsHeight = Math.Max(_itemsHeight, swipeItemHeight);
				}
			}
			_itemsWidth = previousWidth;
		}
 
		List<NView> GetNativeSwipeItems()
		{
			var swipeItems = new List<NView>();
 
			if (_actionView == null)
				return swipeItems;
 
			for (int i = 0; i < _actionView.ChildCount; i++)
			{
				var view = _actionView.Children[i];
				if (view == null)
					continue;
 
				swipeItems.Add(view);
			}
 
			return swipeItems;
		}
 
		void Swipe()
		{
			if (_contentView == null)
				return;
 
			var offset = AdjustSwipeOffset(_swipeOffset.ToScaledPixel());
 
			var contentPosition = _contentHandler?.VirtualView?.Frame.ToPixel() ?? new TRect();
 
			switch (_swipeDirection)
			{
				case SwipeDirection.Left:
				case SwipeDirection.Right:
					{
						var translateX = offset;
						_contentView.PositionX = (float)(contentPosition.X + translateX);
						break;
					}
				case SwipeDirection.Up:
				case SwipeDirection.Down:
					{
						var translateY = offset;
						_contentView.PositionY = (float)(contentPosition.Y + translateY);
						break;
					}
			}
		}
 
		static void ExecuteSwipeItem(ISwipeItem item)
		{
			if (item == null)
				return;
 
			bool isEnabled = true;
 
			if (item is ISwipeItemMenuItem swipeItem)
				isEnabled = swipeItem.IsEnabled;
 
			if (item is ISwipeItemView swipeItemView)
				isEnabled = swipeItemView.IsEnabled;
 
			if (isEnabled)
				item.OnInvoked();
		}
 
		void ResetSwipe(bool animated = true)
		{
			if (_contentView == null)
				return;
 
			_isResettingSwipe = true;
			_isSwiping = false;
			_swipeThreshold = 0;
 
			var contentPosition = _contentHandler?.VirtualView?.Frame.ToPixel() ?? new TRect();
 
			if (animated)
			{
				switch (_swipeDirection)
				{
					case SwipeDirection.Left:
					case SwipeDirection.Right:
						{
							_swipeDirection = null;
							var diffX = _contentView.PositionX - contentPosition.X;
							new Animation(v =>
							{
								_contentView.PositionX = (float)(contentPosition.X + diffX - diffX * v);
 
							}).Commit(this, "Swipe", (uint)SwipeAnimationDuration, finished: (v, r) =>
							{
								if (_swipeDirection == null)
									DisposeSwipeItems();
 
								_isResettingSwipe = false;
							});
 
							break;
						}
					case SwipeDirection.Up:
					case SwipeDirection.Down:
						{
							_swipeDirection = null;
							var diffY = _contentView.PositionY - contentPosition.Y;
							new Animation(v =>
							{
								_contentView.PositionY = (float)(contentPosition.Y + diffY - diffY * v);
 
							}).Commit(this, "Swipe", (uint)SwipeAnimationDuration, finished: (v, r) =>
							{
								if (_swipeDirection == null)
									DisposeSwipeItems();
 
								_isResettingSwipe = false;
							});
							break;
						}
					default:
						_isResettingSwipe = false;
						break;
				}
			}
			else
			{
				_contentView.PositionX = (float)contentPosition.X;
				_contentView.PositionY = (float)contentPosition.Y;
 
				DisposeSwipeItems();
				_isResettingSwipe = false;
			}
		}
 
		void ProgrammaticallyOpenSwipeItem(OpenSwipeItem openSwipeItem, bool animated)
		{
			if (_isOpen)
			{
				if (_previousOpenSwipeItem == openSwipeItem)
					return;
 
				ResetSwipe(false);
			}
 
			_previousOpenSwipeItem = openSwipeItem;
 
			switch (openSwipeItem)
			{
				case OpenSwipeItem.BottomItems:
					_swipeDirection = SwipeDirection.Up;
					break;
				case OpenSwipeItem.LeftItems:
					_swipeDirection = SwipeDirection.Right;
					break;
				case OpenSwipeItem.RightItems:
					_swipeDirection = SwipeDirection.Left;
					break;
				case OpenSwipeItem.TopItems:
					_swipeDirection = SwipeDirection.Down;
					break;
			}
 
			var swipeItems = GetSwipeItemsByDirection();
 
			if (swipeItems == null || swipeItems.Count == 0)
				return;
 
			UpdateSwipeItems();
			SwipeToThreshold(animated);
		}
 
		void SwipeToThreshold(bool animated = true)
		{
			var completeAnimationDuration = animated ? SwipeAnimationDuration : 0;
			UpdateOffset(GetSwipeThreshold());
			float swipeThreshold = _swipeOffset.ToScaledPixel();
 
			var contentPosition = _contentHandler?.VirtualView?.Frame.ToPixel() ?? new TRect();
 
			if (_contentView != null)
			{
				switch (_swipeDirection)
				{
					case SwipeDirection.Left:
					case SwipeDirection.Right:
						{
							var target = swipeThreshold + contentPosition.X;
							var init = _contentView.PositionX;
							var diff = init - (float)target;
							new Animation(v =>
							{
								_contentView.PositionX = init - diff * (float)v;
							}).Commit(this, "Swipe", length: completeAnimationDuration, finished: (v, r) =>
							{
								_isSwiping = false;
							});
							break;
						}
					case SwipeDirection.Up:
					case SwipeDirection.Down:
						{
							var target = swipeThreshold + contentPosition.Y;
							var init = _contentView.PositionY;
							var diff = init - (float)target;
							new Animation(v =>
							{
								_contentView.PositionY = init - diff * (float)v;
							}).Commit(this, "Swipe", length: completeAnimationDuration, finished: (v, r) =>
							{
								_isSwiping = false;
							});
							break;
						}
				}
			}
		}
 
		GSize GetSwipeItemSize(ISwipeItem swipeItem)
		{
			if (_contentView == null || Element == null)
				return GSize.Zero;
 
			bool isHorizontal = IsHorizontalSwipe();
			var items = GetSwipeItemsByDirection();
 
			if (items == null)
				return GSize.Zero;
 
			double threshold = Element.Threshold;
			double contentHeight = _contentView.SizeHeight.ToScaledDP();
			double contentWidth = _contentView.SizeWidth.ToScaledDP();
 
			if (isHorizontal)
			{
				if (swipeItem is ISwipeItemView horizontalSwipeItemView)
				{
					var swipeItemViewSizeRequest = horizontalSwipeItemView.Measure(double.PositiveInfinity, double.PositiveInfinity);
					double swipeItemWidth = swipeItemViewSizeRequest.Width > 0 ? swipeItemViewSizeRequest.Width : SwipeViewExtensions.SwipeItemWidth;
					swipeItemWidth = Math.Max(threshold, swipeItemWidth);
					return new GSize(swipeItemWidth, contentHeight);
				}
				else if (swipeItem is ISwipeItem)
				{
					return new GSize(items.Mode == SwipeMode.Execute ? (threshold > 0 ? threshold : contentWidth) / items.Count : Math.Max(threshold, SwipeViewExtensions.SwipeItemWidth), contentHeight);
				}
			}
			else
			{
				if (swipeItem is ISwipeItemView verticalSwipeItemView)
				{
					var swipeItemViewSizeRequest = verticalSwipeItemView.Measure(double.PositiveInfinity, double.PositiveInfinity);
					double swipeItemHeight = swipeItemViewSizeRequest.Height > 0 ? swipeItemViewSizeRequest.Height : contentHeight;
					swipeItemHeight = Math.Max(threshold, swipeItemHeight);
					return new GSize(contentWidth / items.Count, swipeItemHeight);
				}
				else if (swipeItem is ISwipeItem)
				{
					var swipeItemHeight = GetSwipeItemHeight();
					return new GSize(contentWidth / items.Count, (threshold > 0 && threshold < swipeItemHeight) ? threshold : swipeItemHeight);
				}
			}
 
			return GSize.Zero;
		}
 
		ISwipeItems? GetSwipeItemsByDirection()
		{
			if (_swipeDirection.HasValue)
				return GetSwipeItemsByDirection(_swipeDirection.Value);
 
			return null;
		}
 
		ISwipeItems? GetSwipeItemsByDirection(SwipeDirection swipeDirection)
		{
			ISwipeItems? swipeItems = null;
 
			switch (swipeDirection)
			{
				case SwipeDirection.Left:
					swipeItems = Element?.RightItems;
					break;
				case SwipeDirection.Right:
					swipeItems = Element?.LeftItems;
					break;
				case SwipeDirection.Up:
					swipeItems = Element?.BottomItems;
					break;
				case SwipeDirection.Down:
					swipeItems = Element?.TopItems;
					break;
			}
			return swipeItems;
		}
 
		bool IsHorizontalSwipe()
		{
			return _swipeDirection == SwipeDirection.Left || _swipeDirection == SwipeDirection.Right;
		}
 
		float GetSwipeItemHeight()
		{
			if (_contentView == null)
				return 0f;
 
			var contentHeight = _contentView.SizeHeight.ToScaledDP();
			var items = GetSwipeItemsByDirection();
 
			if (items == null)
				return 0f;
 
			if (items.Any(s => s is ISwipeItemView))
			{
				var itemsHeight = new List<float>();
 
				foreach (var swipeItem in items)
				{
					if (swipeItem is ISwipeItemView swipeItemView)
					{
						var swipeItemViewSizeRequest = swipeItemView.Measure(double.PositiveInfinity, double.PositiveInfinity);
						itemsHeight.Add((float)swipeItemViewSizeRequest.Height);
					}
				}
 
				return itemsHeight.Max();
			}
 
			return contentHeight;
		}
 
		bool ValidateSwipeDirection()
		{
			if (_swipeDirection == null)
				return false;
 
			var swipeItems = GetSwipeItemsByDirection();
			return IsValidSwipeItems(swipeItems);
		}
 
		static bool IsValidSwipeItems(ISwipeItems? swipeItems)
		{
			return swipeItems != null && swipeItems.Where(s => GetIsVisible(s)).Any();
		}
 
		static bool GetIsVisible(ISwipeItem swipeItem)
		{
			if (swipeItem is IView view)
				return view.Visibility == Maui.Visibility.Visible;
			else if (swipeItem is ISwipeItemMenuItem menuItem)
				return menuItem.Visibility == Maui.Visibility.Visible;
 
			return true;
		}
 
		double GetSwipeOffset(Point initialPoint, Point endPoint)
		{
			double swipeOffset = 0;
 
			switch (_swipeDirection)
			{
				case SwipeDirection.Left:
				case SwipeDirection.Right:
					swipeOffset = (int)endPoint.X - (int)initialPoint.X;
					break;
				case SwipeDirection.Up:
				case SwipeDirection.Down:
					swipeOffset = (int)endPoint.Y - (int)initialPoint.Y;
					break;
			}
 
			if (swipeOffset == 0)
				swipeOffset = GetSwipeContentOffset();
 
			return swipeOffset;
		}
 
		double GetSwipeContentOffset()
		{
			double swipeOffset = 0;
 
			if (_contentView != null)
			{
				switch (_swipeDirection)
				{
					case SwipeDirection.Left:
					case SwipeDirection.Right:
						swipeOffset = _contentView.PositionX.ToScaledDP();
						break;
					case SwipeDirection.Up:
					case SwipeDirection.Down:
						swipeOffset = _contentView.PositionY.ToScaledDP();
						break;
				}
			}
			return swipeOffset;
		}
 
		void RaiseSwipeStarted()
		{
			if (_swipeDirection == null || !ValidateSwipeDirection())
				return;
 
			Element?.SwipeStarted(new SwipeViewSwipeStarted(_swipeDirection.Value));
		}
 
		void RaiseSwipeChanging()
		{
			if (_swipeDirection == null)
				return;
 
			Element?.SwipeChanging(new SwipeViewSwipeChanging(_swipeDirection.Value, _swipeOffset));
		}
 
		void RaiseSwipeEnded()
		{
			if (_swipeDirection == null || !ValidateSwipeDirection())
				return;
 
			bool isOpen = false;
 
			var swipeThresholdPercent = OpenSwipeThresholdPercentage * GetSwipeThreshold();
 
			if (Math.Abs(_swipeOffset) >= swipeThresholdPercent)
				isOpen = true;
 
			Element?.SwipeEnded(new SwipeViewSwipeEnded(_swipeDirection.Value, isOpen));
		}
 
		double GetSwipeThreshold()
		{
			if (Math.Abs(_swipeThreshold) > double.Epsilon)
				return _swipeThreshold;
 
			var swipeItems = GetSwipeItemsByDirection();
 
			if (swipeItems == null)
				return 0;
 
			_swipeThreshold = GetSwipeThreshold(swipeItems);
 
			return _swipeThreshold;
		}
 
		double GetSwipeThreshold(ISwipeItems swipeItems)
		{
			if (Element == null)
				return 0f;
 
			double threshold = Element.Threshold;
 
			if (threshold > 0)
				return (float)threshold;
 
			double swipeThreshold = 0;
 
			bool isHorizontal = IsHorizontalSwipe();
 
			if (swipeItems.Mode == SwipeMode.Reveal)
			{
				if (isHorizontal)
				{
					foreach (var swipeItem in swipeItems)
					{
						if (GetIsVisible(swipeItem))
						{
							var swipeItemSize = GetSwipeItemSize(swipeItem);
							swipeThreshold += (float)swipeItemSize.Width;
						}
					}
				}
				else
					swipeThreshold = GetSwipeItemHeight();
			}
			else
				swipeThreshold = CalculateSwipeThreshold();
 
			return ValidateSwipeThreshold(swipeThreshold);
		}
 
		double CalculateSwipeThreshold()
		{
			var swipeItems = GetSwipeItemsByDirection();
			if (swipeItems == null)
				return SwipeViewExtensions.SwipeThreshold;
 
			float swipeItemsHeight = 0;
			float swipeItemsWidth = 0;
			bool useSwipeItemsSize = false;
 
			foreach (var swipeItem in swipeItems)
			{
				if (swipeItem is ISwipeItemView)
					useSwipeItemsSize = true;
 
				if (GetIsVisible(swipeItem))
				{
					var swipeItemSize = GetSwipeItemSize(swipeItem);
					swipeItemsHeight += (float)swipeItemSize.Height;
					swipeItemsWidth += (float)swipeItemSize.Width;
				}
			}
 
			if (useSwipeItemsSize)
			{
				var isHorizontalSwipe = IsHorizontalSwipe();
 
				return isHorizontalSwipe ? swipeItemsWidth : swipeItemsHeight;
			}
			else
			{
				if (_contentView != null)
				{
					var contentWidth = _contentView.SizeWidth.ToScaledDP();
					var contentWidthSwipeThreshold = contentWidth * 0.8f;
 
					return contentWidthSwipeThreshold;
				}
			}
 
			return SwipeViewExtensions.SwipeThreshold;
		}
 
		double ValidateSwipeThreshold(double swipeThreshold)
		{
			if (_contentView == null)
				return swipeThreshold;
 
			var contentHeight = _contentView.SizeHeight.ToScaledDP();
			var contentWidth = _contentView.SizeWidth.ToScaledDP();
			bool isHorizontal = IsHorizontalSwipe();
 
			if (isHorizontal)
			{
				if (swipeThreshold > contentWidth)
					swipeThreshold = contentWidth;
 
				return swipeThreshold;
			}
 
			if (swipeThreshold > contentHeight)
				swipeThreshold = contentHeight;
 
			return swipeThreshold;
		}
 
		void ValidateSwipeThreshold()
		{
			if (_swipeDirection == null)
				return;
 
			var swipeThresholdPercent = OpenSwipeThresholdPercentage * GetSwipeThreshold();
 
			if (Math.Abs(_swipeOffset) >= swipeThresholdPercent)
			{
				var swipeItems = GetSwipeItemsByDirection();
 
				if (swipeItems == null)
					return;
 
				if (swipeItems.Mode == SwipeMode.Execute)
				{
					foreach (var swipeItem in swipeItems)
					{
						if (GetIsVisible(swipeItem))
							ExecuteSwipeItem(swipeItem);
					}
 
					if (swipeItems.SwipeBehaviorOnInvoked != SwipeBehaviorOnInvoked.RemainOpen)
						ResetSwipe();
				}
				else
					SwipeToThreshold();
			}
			else
				ResetSwipe();
		}
 
		int AdjustSwipeOffset(int offset)
		{
			if (_swipeDirection == null)
				return offset;
 
			switch (_swipeDirection)
			{
				case SwipeDirection.Left:
					offset = Math.Min(offset, 0);
					offset = Math.Max(offset, (int)-_itemsWidth);
					break;
				case SwipeDirection.Right:
					offset = Math.Max(offset, 0);
					offset = Math.Min(offset, (int)_itemsWidth);
					break;
				case SwipeDirection.Up:
					offset = Math.Min(offset, 0);
					offset = Math.Max(offset, (int)-_itemsHeight);
					break;
				case SwipeDirection.Down:
					offset = Math.Max(offset, 0);
					offset = Math.Min(offset, (int)_itemsHeight);
					break;
			}
			return offset;
		}
 
		static NView CreateEmptyContent()
		{
			return new NView
			{
				BackgroundColor = Tizen.NUI.Color.Transparent
			};
		}
 
		public void BatchBegin() { }
 
		public void BatchCommit() { }
	}
}