Skip to content

Commit

Permalink
Implement Controls.Compatibility for tizen (dotnet#493)
Browse files Browse the repository at this point in the history
  • Loading branch information
myroot committed Aug 25, 2022
1 parent 627347c commit aae8b5b
Show file tree
Hide file tree
Showing 10 changed files with 545 additions and 56 deletions.
277 changes: 277 additions & 0 deletions src/Controls/src/Core/Compatibility/Handlers/Tizen/FrameRenderer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,277 @@
#nullable enable

using System.ComponentModel;
using Microsoft.Maui.Controls.Platform;
using Microsoft.Maui.Graphics;
using SkiaSharp;
using Tizen.UIExtensions.NUI;
using IMeasurable = Tizen.UIExtensions.Common.IMeasurable;
using TColor = Tizen.UIExtensions.Common.Color;
using NColor = Tizen.NUI.Color;
using TShadow = Tizen.NUI.Shadow;
using TLayoutParamPolicies = Tizen.NUI.BaseComponents.LayoutParamPolicies;

namespace Microsoft.Maui.Controls.Handlers.Compatibility
{
public class FrameRenderer : ContentViewGroup, IPlatformViewHandler, IMeasurable
{
public static IPropertyMapper<Frame, FrameRenderer> Mapper
= new PropertyMapper<Frame, FrameRenderer>(ViewRenderer.VisualElementRendererMapper)
{
[Frame.HasShadowProperty.PropertyName] = (h, _) => h.UpdateShadow(),
[VisualElement.BackgroundColorProperty.PropertyName] = (h, _) => h.UpdateBackgroundColor(),
[VisualElement.BackgroundProperty.PropertyName] = (h, _) => h.UpdateBackground(),
[Frame.CornerRadiusProperty.PropertyName] = (h, _) => h.UpdateCornerRadius(),
[Frame.BorderColorProperty.PropertyName] = (h, _) => h.UpdateBorderColor(),
[Microsoft.Maui.Controls.Compatibility.Layout.IsClippedToBoundsProperty.PropertyName] = (h, _) => h.UpdateClippedToBounds(),
[Frame.ContentProperty.PropertyName] = (h, _) => h.UpdateContent()
};

public static CommandMapper<Frame, FrameRenderer> CommandMapper
= new CommandMapper<Frame, FrameRenderer>(ViewRenderer.VisualElementRendererCommandMapper);

bool _disposed;

SKClipperView _clipperView;

IMauiContext? _mauiContext;
ViewHandlerDelegator<Frame> _viewHandlerWrapper;
IPlatformViewHandler? _contentHandler;


public FrameRenderer() : base(null)
{
_clipperView = new SKClipperView()
{
WidthSpecification = TLayoutParamPolicies.MatchParent,
HeightSpecification = TLayoutParamPolicies.MatchParent
};
_clipperView.DrawClippingArea += OnDrawClippingArea;

Children.Add(_clipperView);

BorderlineColor = NColor.Black;
BorderlineWidth = 1.0.ToScaledPixel();
_viewHandlerWrapper = new ViewHandlerDelegator<Frame>(Mapper, CommandMapper, this);
}

protected Frame? Element
{
get { return _viewHandlerWrapper.Element; }
set
{
if (value != null)
(this as IPlatformViewHandler).SetVirtualView(value);
}
}

protected override void Dispose(bool disposing)
{
if (_disposed)
return;

_disposed = true;

if (disposing)
{
if (Element != null)
{
Element.PropertyChanged -= OnElementPropertyChanged;
}

Element?.Handler?.DisconnectHandler();
}

base.Dispose(disposing);
}

protected virtual void OnElementChanged(ElementChangedEventArgs<Frame> e)
{
if (e.NewElement != null)
{
CrossPlatformArrange = e.NewElement.CrossPlatformArrange;
CrossPlatformMeasure = e.NewElement.CrossPlatformMeasure;
}
}

protected virtual void OnElementPropertyChanged(object? sender, PropertyChangedEventArgs e)
{
if (_disposed)
{
return;
}

if (Element != null && e.PropertyName != null)
_viewHandlerWrapper.UpdateProperty(e.PropertyName);
}

void OnDrawClippingArea(object? sender, SkiaSharp.Views.Tizen.SKPaintSurfaceEventArgs e)
{
if (Element == null || _disposed)
return;

var canvas = e.Surface.Canvas;
var directRect = e.Info.Rect;
canvas.Clear();

if (!Element.IsClippedToBounds)
{
canvas.Clear(SKColors.White);
return;
}
var radius = ((double)Element.CornerRadius).ToScaledPixel();
using var paint = new SKPaint
{
Color = SKColors.White,
};
canvas.DrawRoundRect(directRect, new SKSize(radius, radius), paint);
}

void UpdateClippedToBounds()
{
if (Element == null || _disposed)
return;

_clipperView.Invalidate();
}

void UpdateBackgroundColor()
{
if (Element == null || _disposed)
return;

BackgroundColor = Element.BackgroundColor.ToNUIColor();
}

void UpdateBackground()
{
if (Element == null || _disposed)
return;

var color = ((Paint)Element.Background)?.ToColor();
if (color != null)
BackgroundColor = color.ToNUIColor();
}

void UpdateBorderColor()
{
if (Element == null || _disposed)
return;

if (Element.BorderColor.IsNotDefault())
BorderlineColor = Element.BorderColor.ToNUIColor();
else
BorderlineColor = Tizen.NUI.Color.Black;
}

void UpdateShadow()
{
if (Element == null || _disposed)
return;

if (Element.HasShadow)
{
BoxShadow = new TShadow(6.0.ToScaledPixel(), TColor.FromHex("#111111").ToNative());
}
else
{
BoxShadow = null;
}
}

void UpdateCornerRadius()
{
if (Element == null || _disposed)
return;

CornerRadius = ((double)Element.CornerRadius).ToScaledPixel();
}

void UpdateContent()
{
var content = Element?.Content;

if (_contentHandler != null)
{
if (_contentHandler.PlatformView != null)
{
_clipperView.Remove(_contentHandler.PlatformView);
}
_contentHandler?.Dispose();
_contentHandler = null;
}


if (content == null || _mauiContext == null || _disposed)
{
return;
}

var platformView = content.ToPlatform(_mauiContext);
platformView.WidthSpecification = TLayoutParamPolicies.MatchParent;
platformView.HeightSpecification = TLayoutParamPolicies.MatchParent;
_clipperView.Add(platformView);
if (content.Handler is IPlatformViewHandler thandler)
{
_contentHandler = thandler;
}
}

#region IPlatformViewHandler
Size IViewHandler.GetDesiredSize(double widthConstraint, double heightConstraint)
{
if (Element?.Handler is IPlatformViewHandler pvh && Element is IContentView cv)
{
return pvh.MeasureVirtualView(widthConstraint, heightConstraint, cv.CrossPlatformMeasure);
}
else
{
return Graphics.Size.Zero;
}
}

bool IViewHandler.HasContainer { get => false; set { } }

object? IViewHandler.ContainerView => null;

IView? IViewHandler.VirtualView => Element;

object IElementHandler.PlatformView => this;

Maui.IElement? IElementHandler.VirtualView => Element;

IMauiContext? IElementHandler.MauiContext => _mauiContext;

Tizen.NUI.BaseComponents.View? IPlatformViewHandler.PlatformView => this;

Tizen.NUI.BaseComponents.View? IPlatformViewHandler.ContainerView => this;

void IViewHandler.PlatformArrange(Graphics.Rect rect) =>
this.PlatformArrangeHandler(rect);

void IElementHandler.SetMauiContext(IMauiContext mauiContext) =>
_mauiContext = mauiContext;

void IElementHandler.SetVirtualView(Maui.IElement view) =>
_viewHandlerWrapper.SetVirtualView(view, OnElementChanged, false);

void IElementHandler.UpdateValue(string property)
{
if (Element != null)
{
OnElementPropertyChanged(Element, new PropertyChangedEventArgs(property));
}
}

void IElementHandler.Invoke(string command, object? args)
{
_viewHandlerWrapper.Invoke(command, args);
}

void IElementHandler.DisconnectHandler()
{
_viewHandlerWrapper.DisconnectHandler();
}
#endregion
}
}
77 changes: 77 additions & 0 deletions src/Controls/src/Core/Compatibility/Handlers/Tizen/ViewRenderer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
#nullable enable
using Tizen.UIExtensions.NUI;
using PlatformView = Tizen.NUI.BaseComponents.View;

namespace Microsoft.Maui.Controls.Handlers.Compatibility
{
public abstract partial class ViewRenderer : ViewRenderer<View, PlatformView>
{
}

public abstract partial class ViewRenderer<TElement, TPlatformView> : VisualElementRenderer<TElement>, IPlatformViewHandler
where TElement : View, IView
where TPlatformView : PlatformView
{
TPlatformView? _platformView;
ViewGroup? _container;

public TPlatformView? Control => ((IElementHandler)this).PlatformView as TPlatformView ?? _platformView;
object? IElementHandler.PlatformView => _platformView;

public ViewRenderer() : this(VisualElementRendererMapper, VisualElementRendererCommandMapper)
{
}

internal ViewRenderer(IPropertyMapper mapper, CommandMapper? commandMapper = null)
: base(mapper, commandMapper)
{
}

protected virtual TPlatformView CreateNativeControl()
{
return default(TPlatformView)!;
}

protected void SetNativeControl(TPlatformView control)
{
SetNativeControl(control, this);
}

internal void SetNativeControl(TPlatformView control, ViewGroup container)
{
if (Control != null)
{
Children.Remove(Control);
}

_container = container;
_platformView = control;

var toAdd = container == this ? control : (PlatformView)container;
toAdd.WidthSpecification = Tizen.NUI.BaseComponents.LayoutParamPolicies.MatchParent;
toAdd.HeightSpecification = Tizen.NUI.BaseComponents.LayoutParamPolicies.MatchParent;
Children.Add(toAdd);
}

private protected override void DisconnectHandlerCore()
{
if (_platformView != null && Element != null)
{
// We set the PlatformView to null so no one outside of this handler tries to access
// PlatformView. PlatformView access should be isolated to the instance passed into
// DisconnectHandler
var oldPlatformView = _platformView;
_platformView = null;
DisconnectHandler(oldPlatformView);
}

base.DisconnectHandlerCore();
}

protected virtual void DisconnectHandler(TPlatformView oldPlatformView)
{
}

PlatformView? IPlatformViewHandler.ContainerView => _container;
}
}
Loading

0 comments on commit aae8b5b

Please sign in to comment.