File: Platform\Tizen\MauiPageControl.cs
Web Access
Project: src\src\Core\src\Core.csproj (Microsoft.Maui)
using System;
using System.Collections.Generic;
using Microsoft.Maui.Graphics;
using Microsoft.Maui.Graphics.Skia.Views;
using Tizen.UIExtensions.Common;
using Tizen.UIExtensions.NUI;
using NExtents = Tizen.NUI.Extents;
using NLayoutParamPolicies = Tizen.NUI.BaseComponents.LayoutParamPolicies;
using NLinearLayout = Tizen.NUI.LinearLayout;
using NPointStateType = Tizen.NUI.PointStateType;
using NSize = Tizen.NUI.Size;
using NView = Tizen.NUI.BaseComponents.View;
using TSize = Tizen.UIExtensions.Common.Size;
 
namespace Microsoft.Maui.Platform
{
	public class MauiPageControl : ViewGroup, IMeasurable
	{
		const double DefaultMargin = 4;
 
		IIndicatorView _indicatorView;
		IPlatformViewHandler? _templatedViewHandler;
		ILayout? _templatedView;
		NView? _contentView;
 
		List<Indicator> _indicators = new List<Indicator>();
		int _currentPoistion = -1;
 
		public MauiPageControl(IIndicatorView view)
		{
			_indicatorView = view;
			LayoutUpdated += OnLayoutUpdated;
		}
 
		bool UseDefaultIndicator { get; set; }
 
		double IndicatorSizeWithMargin => IndicatorSize + DefaultMargin * 2;
 
		double IndicatorSize => _indicatorView.IndicatorSize;
 
		public void ResetIndicators()
		{
			ClearIndicatorView();
			if ((_indicatorView as ITemplatedIndicatorView)?.IndicatorsLayoutOverride == null)
			{
				CreateDefaultView();
			}
			else
			{
				CreateTemplatedView();
			}
			this.InvalidateMeasure(_indicatorView);
		}
 
		public void UpdatePosition()
		{
			if (!UseDefaultIndicator)
				return;
 
			UpdateIndicatorColor(_currentPoistion, _indicatorView.IndicatorColor);
			_currentPoistion = _indicatorView.Position;
			UpdateIndicatorColor(_currentPoistion, _indicatorView.SelectedIndicatorColor);
		}
 
		public void UpdateCount()
		{
			if (!UseDefaultIndicator || _contentView == null)
				return;
 
			var count = Math.Min(_indicatorView.Count, _indicatorView.MaximumVisible);
			var diff = _indicators.Count - count;
			var needIncrease = diff < 0;
 
			diff = Math.Abs(diff);
			for (int i = 0; i < diff; i++)
			{
				if (needIncrease)
					IncreaseIndicator();
				else
					DecreaseIndicator();
			}
			UpdatePosition();
		}
 
		public TSize Measure(double availableWidth, double availableHeight)
		{
			if (UseDefaultIndicator)
			{
				return new TSize(IndicatorSizeWithMargin.ToScaledPixel() * _indicators.Count, IndicatorSizeWithMargin.ToScaledPixel());
			}
			else
			{
				return _templatedView?.CrossPlatformMeasure(availableWidth.ToScaledDP(), availableHeight.ToScaledDP()).ToPixel() ?? new TSize(0, 0);
			}
		}
 
		void UpdateIndicatorColor(int position, Paint? color)
		{
			if (position < 0 || position >= _indicators.Count)
				return;
 
			_indicators[position].Drawable.Background = color;
			_indicators[position].Invalidate();
		}
 
		void CreateTemplatedView()
		{
			UseDefaultIndicator = false;
			var layout = (_indicatorView as ITemplatedIndicatorView)?.IndicatorsLayoutOverride;
			if (layout == null || _indicatorView?.Handler?.MauiContext == null)
				return;
			_contentView = layout.ToPlatform(_indicatorView.Handler.MauiContext);
			_templatedView = layout;
			_templatedViewHandler = layout.Handler as IPlatformViewHandler;
 
			_contentView.WidthSpecification = NLayoutParamPolicies.MatchParent;
			_contentView.HeightSpecification = NLayoutParamPolicies.MatchParent;
			Children.Add(_contentView);
		}
 
		void CreateDefaultView()
		{
			UseDefaultIndicator = true;
			_contentView = new NView
			{
				WidthSpecification = NLayoutParamPolicies.MatchParent,
				HeightSpecification = NLayoutParamPolicies.MatchParent,
				Layout = new NLinearLayout
				{
					LinearOrientation = NLinearLayout.Orientation.Horizontal,
				}
			};
			Children.Add(_contentView);
 
			_currentPoistion = _indicatorView.Position;
 
			if (_indicatorView.Count == 1 && _indicatorView.HideSingle)
				return;
 
			var count = Math.Min(_indicatorView.Count, _indicatorView.MaximumVisible);
 
			for (int i = 0; i < count; i++)
			{
				var indicator = CreateIndicator((i == _indicatorView.Position) ? _indicatorView.SelectedIndicatorColor : _indicatorView.IndicatorColor);
				_contentView.Add(indicator);
				_indicators.Add(indicator);
			}
		}
 
		Indicator CreateIndicator(Paint? color)
		{
			var indicator = new Indicator()
			{
				Margin = new NExtents((ushort)DefaultMargin.ToScaledPixel()),
				Size = new NSize(IndicatorSize.ToScaledPixel(), IndicatorSize.ToScaledPixel())
			};
			indicator.Drawable.Shape = _indicatorView.IndicatorsShape;
			indicator.Drawable.Background = color;
			indicator.TouchEvent += OnIndicatorTouch;
 
			return indicator;
		}
 
		void ClearIndicatorView()
		{
			Children.Clear();
 
			if (_templatedViewHandler != null)
			{
				_templatedViewHandler.Dispose();
				_templatedViewHandler = null;
				_templatedView = null;
			}
			else
			{
				_contentView?.Dispose();
			}
			_contentView = null;
 
			foreach (var view in _indicators)
			{
				view.Dispose();
			}
			_indicators.Clear();
		}
 
		void DecreaseIndicator()
		{
			if (_contentView == null)
				return;
 
			var indicator = _indicators[_indicators.Count - 1];
			_contentView.Remove(indicator);
			_indicators.Remove(indicator);
			indicator.Dispose();
		}
 
		void IncreaseIndicator()
		{
			if (_contentView == null)
				return;
 
			var indicator = CreateIndicator(_indicators.Count == _indicatorView.Position ? _indicatorView.SelectedIndicatorColor : _indicatorView.IndicatorColor);
			_contentView.Add(indicator);
			_indicators.Add(indicator);
		}
 
		bool OnIndicatorTouch(object source, TouchEventArgs e)
		{
			if (e.Touch.GetState(0) == NPointStateType.Up && source is Indicator indicator)
			{
				var touchPosition = e.Touch.GetLocalPosition(0);
				if (0 < touchPosition.X && touchPosition.X < indicator.SizeWidth
					&& 0 < touchPosition.Y && touchPosition.Y < indicator.SizeHeight)
				{
					var position = _indicators.IndexOf(indicator);
					if (position != -1)
					{
						_indicatorView.Position = position;
					}
				}
			}
			return true;
		}
 
		void OnLayoutUpdated(object? sender, LayoutEventArgs e)
		{
			if (UseDefaultIndicator || _templatedView == null)
				return;
 
			var platformGeometry = this.GetBounds().ToDP();
			_templatedView.CrossPlatformMeasure(platformGeometry.Width, platformGeometry.Height);
 
			platformGeometry.X = 0;
			platformGeometry.Y = 0;
			_templatedView.CrossPlatformArrange(platformGeometry);
		}
 
		class Indicator : SkiaGraphicsView
		{
			public Indicator() : base(new MauiDrawable()) { }
 
			public new MauiDrawable Drawable => (MauiDrawable)base.Drawable!;
		}
	}
}