Skip to content
This repository has been archived by the owner on Dec 28, 2023. It is now read-only.

Commit

Permalink
Update CircleScrollViewRenderer (#300)
Browse files Browse the repository at this point in the history
* Update CircleScrollViewRenderer

* Obsolete BarColor property in CircleScrollView
  • Loading branch information
myroot authored May 13, 2020
1 parent f049072 commit 383f0a6
Show file tree
Hide file tree
Showing 2 changed files with 8 additions and 244 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,258 +14,19 @@
* limitations under the License.
*/

using System;
using System.ComponentModel;
using System.Threading.Tasks;
using ElmSharp;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Tizen;
using Xamarin.Forms.Platform.Tizen.Native;
using ERect = ElmSharp.Rect;
using XForms = Xamarin.Forms.Forms;
using Watch = Xamarin.Forms.Platform.Tizen.Native.Watch;

[assembly: ExportRenderer(typeof(Tizen.Wearable.CircularUI.Forms.CircleScrollView), typeof(Tizen.Wearable.CircularUI.Forms.Renderer.CircleScrollViewRenderer))]

namespace Tizen.Wearable.CircularUI.Forms.Renderer
{
public class CircleScrollViewRenderer : ViewRenderer<CircleScrollView, ElmSharp.Wearable.CircleScroller>
public class CircleScrollViewRenderer : ScrollViewRenderer
{
Xamarin.Forms.Platform.Tizen.Native.Box _scrollCanvas;
ElmSharp.SmartEvent _scrollAnimationStart, _scrollAnimationStop;
bool _isAnimation;
TaskCompletionSource<bool> _animationTaskComplateSource;

public CircleScrollViewRenderer()
{
RegisterPropertyHandler(CircleScrollView.BarColorProperty, UpdateBarColor);
RegisterPropertyHandler("Content", OnContent);
}

public override ERect GetNativeContentGeometry()
{
return _scrollCanvas.Geometry;
}

protected override void OnElementChanged(ElementChangedEventArgs<CircleScrollView> e)
{
if (Control == null)
{
var surface = this.GetSurface();
SetNativeControl(new ElmSharp.Wearable.CircleScroller(XForms.NativeParent, surface));
InitControl();
Control.Scrolled += OnScrolled;
_scrollCanvas = new Xamarin.Forms.Platform.Tizen.Native.Box(Control);
_scrollCanvas.LayoutUpdated += OnContentLayoutUpdated;
Control.SetContent(_scrollCanvas);
}
if (e.OldElement != null)
{
(e.OldElement as IScrollViewController).ScrollToRequested -= OnScrollRequestedAsync;
}
if (e.NewElement != null)
{
(e.NewElement as IScrollViewController).ScrollToRequested += OnScrollRequestedAsync;
}

UpdateAll();

base.OnElementChanged(e);
}

protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (ScrollView.OrientationProperty.PropertyName == e.PropertyName)
{
UpdateOrientation();
}
else if (ScrollView.ContentSizeProperty.PropertyName == e.PropertyName)
{
UpdateContentSize();
}
else if (ScrollView.VerticalScrollBarVisibilityProperty.PropertyName == e.PropertyName)
{
UpdateVerticalScrollBarVisibility();
}
else if (ScrollView.HorizontalScrollBarVisibilityProperty.PropertyName == e.PropertyName)
{
UpdateHorizontalScrollBarVisibility();
}

base.OnElementPropertyChanged(sender, e);
}

protected override void Dispose(bool disposing)
{
if (disposing)
{
if (null != Element)
{
(Element as IScrollViewController).ScrollToRequested -= OnScrollRequestedAsync;
}
if (Control != null)
{
Control.Scrolled -= OnScrolled;
}
if (_scrollCanvas != null)
{
_scrollCanvas.LayoutUpdated -= OnContentLayoutUpdated;
}
_scrollAnimationStart?.Dispose();
_scrollAnimationStop?.Dispose();
}
base.Dispose(disposing);
}

void UpdateAll()
{
UpdateOrientation();
UpdateVerticalScrollBarVisibility();
UpdateHorizontalScrollBarVisibility();
}

void UpdateVerticalScrollBarVisibility()
{
var orientation = Element.Orientation;
if (orientation == ScrollOrientation.Vertical || orientation == ScrollOrientation.Both)
Control.VerticalScrollBarVisiblePolicy = ScrollBarVisibilityToTizen(Element.VerticalScrollBarVisibility);
}

void UpdateHorizontalScrollBarVisibility()
{
var orientation = Element.Orientation;
if (orientation == ScrollOrientation.Horizontal || orientation == ScrollOrientation.Both)
Control.HorizontalScrollBarVisiblePolicy = ScrollBarVisibilityToTizen(Element.HorizontalScrollBarVisibility);
}

void UpdateBarColor()
{
var color = Element.BarColor;
if (color != Xamarin.Forms.Color.Default)
{
Control.VerticalScrollBarColor = color.ToNative();
Control.HorizontalScrollBarColor = color.ToNative();
}
}

ScrollBarVisiblePolicy ScrollBarVisibilityToTizen(ScrollBarVisibility visibility)
{
switch (visibility)
{
case ScrollBarVisibility.Always:
return ScrollBarVisiblePolicy.Visible;
case ScrollBarVisibility.Never:
return ScrollBarVisiblePolicy.Invisible;
default:
return ScrollBarVisiblePolicy.Auto;
}
}

async void OnScrollRequestedAsync(object sender, ScrollToRequestedEventArgs e)
{
var x = e.ScrollX;
var y = e.ScrollY;
if (e.Mode == ScrollToMode.Element)
{
var itemPosition = (Element as IScrollViewController).GetScrollPositionForElement(e.Element as VisualElement, e.Position);
x = itemPosition.X;
y = itemPosition.Y;
}
var region = new Xamarin.Forms.Rectangle(x, y, Element.Width, Element.Height).ToPixel();
await ScrollToAsync(region, e.ShouldAnimate).ConfigureAwait(false);
Element.SendScrollFinished();
}

void OnScrolled(object sender, EventArgs e)
{
var region = Control.CurrentRegion.ToDP();
((IScrollViewController)Element).SetScrolledPosition(region.X, region.Y);
}

void OnContent()
{
_scrollCanvas.UnPackAll();
if (Element.Content != null)
{
_scrollCanvas.PackEnd(Platform.GetOrCreateRenderer(Element.Content).NativeView);
UpdateContentSize();
}
}

void UpdateContentSize()
{
_scrollCanvas.MinimumWidth = XForms.ConvertToScaledPixel(Element.ContentSize.Width + Element.Padding.HorizontalThickness);
_scrollCanvas.MinimumHeight = XForms.ConvertToScaledPixel(Element.ContentSize.Height + Element.Padding.VerticalThickness);

Device.BeginInvokeOnMainThread(() =>
{
if (Control != null)
{
OnScrolled(Control, EventArgs.Empty);
}
});
}

void OnContentLayoutUpdated(object sender, LayoutEventArgs e)
{
UpdateContentSize();
}

void UpdateOrientation()
{
switch (Element.Orientation)
{
case ScrollOrientation.Horizontal:
Control.ScrollBlock = ElmSharp.ScrollBlock.Vertical;
Control.HorizontalScrollBarVisiblePolicy = ElmSharp.ScrollBarVisiblePolicy.Auto;
Control.VerticalScrollBarVisiblePolicy = ElmSharp.ScrollBarVisiblePolicy.Invisible;
break;
case ScrollOrientation.Vertical:
Control.ScrollBlock = ElmSharp.ScrollBlock.Horizontal;
Control.HorizontalScrollBarVisiblePolicy = ElmSharp.ScrollBarVisiblePolicy.Invisible;
Control.VerticalScrollBarVisiblePolicy = ElmSharp.ScrollBarVisiblePolicy.Auto;
break;
case ScrollOrientation.Both:
Control.ScrollBlock = ElmSharp.ScrollBlock.None;
Control.HorizontalScrollBarVisiblePolicy = ElmSharp.ScrollBarVisiblePolicy.Auto;
Control.VerticalScrollBarVisiblePolicy = ElmSharp.ScrollBarVisiblePolicy.Auto;
break;
default:
throw new InvalidOperationException("Not supported orientation.");
}
}

void InitControl()
{
_scrollAnimationStart = new ElmSharp.SmartEvent(Control, Control.RealHandle, "scroll,anim,start");
_scrollAnimationStop = new ElmSharp.SmartEvent(Control, Control.RealHandle, "scroll,anim,stop");
_scrollAnimationStart.On += (s, e) => _isAnimation = true;
_scrollAnimationStop.On += (s, e) =>
{
if (_animationTaskComplateSource != null)
{
_animationTaskComplateSource.TrySetResult(true);
}
_isAnimation = false;
};
}

Task ScrollToAsync(Rect region, bool shouldAnimate)
{
CheckTaskCompletionSource();
Control.ScrollTo(region, shouldAnimate);
return shouldAnimate && _isAnimation ? _animationTaskComplateSource.Task : Task.CompletedTask;
}

void CheckTaskCompletionSource()
protected override Xamarin.Forms.Platform.Tizen.Native.Scroller CreateNativeControl()
{
if (_animationTaskComplateSource != null)
{
if (_animationTaskComplateSource.Task.Status == TaskStatus.Running)
{
_animationTaskComplateSource.TrySetCanceled();
}
}
_animationTaskComplateSource = new TaskCompletionSource<bool>();
return new Watch.WatchScroller(XForms.NativeParent, this.GetSurface());
}
}
}
5 changes: 4 additions & 1 deletion src/Tizen.Wearable.CircularUI.Forms/CircleScrollView.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
* limitations under the License.
*/

using System;
using Xamarin.Forms;

namespace Tizen.Wearable.CircularUI.Forms
Expand All @@ -29,12 +30,14 @@ public class CircleScrollView : ScrollView, IRotaryFocusable, ICircleSurfaceCons
/// BindableProperty. Identifies the Header, Footer cancel the Fish Eye Effect or not.
/// </summary>
/// <since_tizen> 4 </since_tizen>
public static readonly BindableProperty BarColorProperty = BindableProperty.CreateAttached("BarColor", typeof(Color), typeof(CircleScrollView), Color.Default);
[Obsolete("BarColor is obsolete as of version 1.5.0. Please use Xamarin.Forms.PlatformConfiguration.TizenSpecific.ScrollView.BarColorProperty instead.")]
public static readonly BindableProperty BarColorProperty = Xamarin.Forms.PlatformConfiguration.TizenSpecific.ScrollView.BarColorProperty;

/// <summary>
/// Gets or sets a scroll bar color value.
/// </summary>
/// <since_tizen> 4 </since_tizen>
[Obsolete("BarColor is obsolete as of version 1.5.0. Please use Xamarin.Forms.PlatformConfiguration.TizenSpecific.ScrollView.BarColorProperty instead.")]
public Color BarColor
{
get => (Color)GetValue(BarColorProperty);
Expand Down

0 comments on commit 383f0a6

Please sign in to comment.