jamesmontemagno / ImageCirclePlugin

Circle Images for your Xamarin.Forms Applications
MIT License
240 stars 68 forks source link

Add support for WPF #66

Open VladislavAntonyuk opened 6 years ago

VladislavAntonyuk commented 6 years ago

I have implemented renderer on WPF. Could you please add it to use out of box

using Platform.WPF.Renderer;
using ImageCircle.Forms.Plugin.Abstractions;
using Xamarin.Forms.Platform.WPF;

[assembly: ExportRenderer(typeof(CircleImage), typeof(ImageCircleRenderer))]

namespace Platform.WPF.Renderer
{
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Windows.Media;
    using System.Windows.Shapes;
    using Xamarin.Forms;
    using Xamarin.Forms.Platform.WPF;
    using Color = Xamarin.Forms.Color;
    using ImageSource = Xamarin.Forms.ImageSource;

    public class ImageCircleRenderer : ViewRenderer<Image, Ellipse>
    {
        private ImageSource file;

        protected override void OnElementChanged(ElementChangedEventArgs<Image> e)
        {
            base.OnElementChanged(e);
            if (e.OldElement == null)
            {
                var ellipse = new Ellipse();
                SetNativeControl(ellipse);
            }
        }

        protected override async void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            base.OnElementPropertyChanged(sender, e);

            if (Control == null)
            {
                return;
            }

            var min = Math.Min(Element.Width, Element.Height);
            if (min / 2.0f <= 0)
            {
                return;
            }

            Control.Width = min;
            Control.Height = min;

            // Fill background color
            var color = ((CircleImage) Element).FillColor;
            Control.Fill = XamarinColorToBrush(color);

            // Fill stroke
            color = ((CircleImage) Element).BorderColor;
            Control.StrokeThickness = ((CircleImage) Element).BorderThickness;
            Control.Stroke = XamarinColorToBrush(color);

            var force = ForceUpdate(e.PropertyName);

            //already set
            if (file == Element.Source && !force)
            {
                return;
            }

            file = Element.Source;

            IImageSourceHandler handler;

            switch (file)
            {
                case UriImageSource _:
                    handler = new UriImageSourceHandler();
                    break;
                case FileImageSource f:
                    if(!File.Exists(f.File))
                    {
                        return;
                    }

                    handler = new FileImageSourceHandler();
                    break;
                case StreamImageSource _:
                    handler = new StreamImageSourceHandler();
                    break;
                default:
// do not need to throw Exception. Probably file is null, so just return
                    return;
            }

            var originalBitmap = await handler.LoadImageAsync(Element.Source);
            if (originalBitmap != null)
            {
                Control.Fill = new ImageBrush
                {
                    ImageSource = originalBitmap,
                    Stretch = Stretch.UniformToFill
                };
            }
        }

        private static bool ForceUpdate(string propertyName)
        {
            var forcePropertiesList = new List<string>
            {
                VisualElement.XProperty.PropertyName,
                VisualElement.YProperty.PropertyName,
                VisualElement.WidthProperty.PropertyName,
                VisualElement.HeightProperty.PropertyName,
                VisualElement.ScaleProperty.PropertyName,
                VisualElement.TranslationXProperty.PropertyName,
                VisualElement.TranslationYProperty.PropertyName,
                VisualElement.RotationYProperty.PropertyName,
                VisualElement.RotationXProperty.PropertyName,
                VisualElement.RotationProperty.PropertyName,
                CircleImage.BorderThicknessProperty.PropertyName,
                CircleImage.BorderColorProperty.PropertyName,
                CircleImage.FillColorProperty.PropertyName,
                VisualElement.AnchorXProperty.PropertyName,
                VisualElement.AnchorYProperty.PropertyName
            };

            return forcePropertiesList.Contains(propertyName);
        }

        private static Brush XamarinColorToBrush(Color color)
        {
            return new SolidColorBrush(System.Windows.Media.Color.FromArgb(
                (byte) (color.A * 255),
                (byte) (color.R * 255),
                (byte) (color.G * 255),
                (byte) (color.B * 255)));
        }
    }
}
jamesmontemagno commented 5 years ago

Pull requests are welcome.