Add the NativeCirclePage and factory for native object (#144)
author유리나/Common Platform Lab(SR)/Staff Engineer/삼성전자 <rina6350.you@samsung.com>
Fri, 31 Jan 2020 05:37:10 +0000 (14:37 +0900)
committer부정균/Common Platform Lab(SR)/Staff Engineer/삼성전자 <jk.pu@samsung.com>
Fri, 31 Jan 2020 05:37:10 +0000 (14:37 +0900)
Tizen.CircularUI/Tizen.Wearable.CircularUI.Forms.Renderer/CirclePageRenderer.cs
Tizen.CircularUI/Tizen.Wearable.CircularUI.Forms.Renderer/CircularUIForms.cs [new file with mode: 0644]
Tizen.CircularUI/Tizen.Wearable.CircularUI.Forms.Renderer/NativeCirclePage.cs [new file with mode: 0644]
Tizen.CircularUI/Tizen.Wearable.CircularUI.Forms.Renderer/NativeFactory.cs [new file with mode: 0644]
Tizen.CircularUI/Tizen.Wearable.CircularUI.Forms.Renderer/ObservableBox.cs
Xamarin.Forms/Xamarin.Forms.Platform.Tizen/Forms.cs

index 15aae63..72f8429 100644 (file)
  * limitations under the License.
  */
 
-using ElmSharp;
-using ElmSharp.Wearable;
 using System;
-using System.Collections.Generic;
 using System.Collections.ObjectModel;
 using System.Collections.Specialized;
-using System.ComponentModel;
 using Tizen.Wearable.CircularUI.Forms;
 using Xamarin.Forms;
 using Xamarin.Forms.Platform.Tizen;
-using Xamarin.Forms.Platform.Tizen.Native;
 using XForms = Xamarin.Forms.Forms;
-
 using XToolbarItem = Xamarin.Forms.ToolbarItem;
 
 [assembly: ExportRenderer(typeof(CirclePage), typeof(Tizen.Wearable.CircularUI.Forms.Renderer.CirclePageRenderer))]
-
 namespace Tizen.Wearable.CircularUI.Forms.Renderer
 {
     public class CirclePageRenderer : VisualElementRenderer<CirclePage>
     {
-        ObservableBox _box;
-
-        ElmSharp.Rectangle _bgColorObject;
-        ElmSharp.EvasImage _bgImageObject;
-        ElmSharp.Layout _surfaceLayout;
-        ElmSharp.Button _actionButton;
-        ImageSource _bgImage;
-
-        ElmSharp.Wearable.CircleSurface _surface;
-        IRotaryFocusable _currentRotaryFocusObject;
-
-        ElmSharp.Wearable.MoreOption _moreOption;
-        Dictionary<XToolbarItem, ElmSharp.Wearable.MoreOptionItem> _toolbarItemMap;
-        Dictionary<ICircleSurfaceItem, ElmSharp.Wearable.ICircleWidget> _circleSurfaceItems;
+        NativeCirclePage _circlePage = null;
 
         public CirclePageRenderer()
         {
@@ -57,17 +37,34 @@ namespace Tizen.Wearable.CircularUI.Forms.Renderer
             RegisterPropertyHandler(CirclePage.RotaryFocusObjectProperty, UpdateRotaryFocusObject);
         }
 
-        public ElmSharp.Wearable.CircleSurface CircleSurface => _surface;
+        public ElmSharp.Wearable.CircleSurface CircleSurface;
 
         protected override void OnElementChanged(ElementChangedEventArgs<CirclePage> e)
         {
-            if (_box == null)
-            {
-                OnRealized();
-            }
+            if (_circlePage == null)
+            {
+                       _circlePage = NativeFactory.GetNativeControl(typeof(NativeCirclePage)) as NativeCirclePage;
+                       CircleSurface = _circlePage.Surface;
+
+                       if (Element.ToolbarItems.Count > 0)
+                       {
+                               Device.BeginInvokeOnMainThread(() =>
+                               {
+                                       _circlePage.SetVisibleMoreOption(true);
+
+                                       foreach (var item in Element.ToolbarItems)
+                                       {
+                                               _circlePage.AddToolbarItem(item);
+                                       }
+                               });
+                       }
+                       SetNativeView(_circlePage);
+               }
             if (e.NewElement != null)
             {
-                e.NewElement.Appearing += OnPageAppearing;
+                       _circlePage.SetElement(e.NewElement);
+
+                       e.NewElement.Appearing += OnPageAppearing;
                 e.NewElement.Disappearing += OnPageDisappearing;
                 var toolbarItems = e.NewElement.ToolbarItems as ObservableCollection<XToolbarItem>;
                 if (toolbarItems != null)
@@ -79,7 +76,7 @@ namespace Tizen.Wearable.CircularUI.Forms.Renderer
 
                     foreach (var item in circleSurfaceItems)
                     {
-                        AddCircleSurfaceItem(item);
+                        _circlePage.AddCircleSurfaceItem(item);
                     }
                 }
             }
@@ -98,46 +95,27 @@ namespace Tizen.Wearable.CircularUI.Forms.Renderer
         }
         protected override void UpdateBackgroundColor(bool initialize)
         {
-            if (initialize && Element.BackgroundColor.IsDefault) return;
+            if (initialize && Element.BackgroundColor.IsDefault)
+                       return;
 
-            if (Element.BackgroundColor.A == 0)
-            {
-                _bgColorObject.Color = ElmSharp.Color.Transparent;
-            }
-            else
-            {
-                _bgColorObject.Color = Element.BackgroundColor.ToNative();
-            }
-            UpdateBackground();
+               _circlePage.UpdateBackgroundColor(Element.BackgroundColor);
         }
+
         protected void UpdateBackgroundImage(bool initialize)
         {
             if (initialize && Element.BackgroundImageSource.IsNullOrEmpty())
                 return;
 
-            var bgImageSource = Element.BackgroundImageSource as FileImageSource;
-            if (bgImageSource.IsNullOrEmpty())
-            {
-                _bgImageObject.File = null;
-                _bgImage = null;
-            }
-            else
-            {
-                _bgImageObject.File = ResourcePath.GetPath(bgImageSource);
-                _bgImage = Element.BackgroundImageSource;
-            }
-            UpdateBackground();
+               _circlePage.UpdateBackgroundImage(Element.BackgroundImageSource);
         }
+
         protected override void Dispose(bool disposing)
         {
             if (Element != null)
             {
                 Element.Appearing -= OnPageAppearing;
                 Element.Disappearing -= OnPageDisappearing;
-                if (Element.ActionButton != null)
-                {
-                    Element.ActionButton.PropertyChanged -= OnActionButtonItemChanged;
-                }
+
                 var toolbarItems = Element.ToolbarItems as ObservableCollection<XToolbarItem>;
                 if (toolbarItems != null)
                     toolbarItems.CollectionChanged -= OnToolbarItemChanged;
@@ -146,289 +124,48 @@ namespace Tizen.Wearable.CircularUI.Forms.Renderer
                 if (circleSurfaceItems != null)
                     circleSurfaceItems.CollectionChanged -= OnCircleSurfaceItemsChanged;
             }
-            base.Dispose(disposing);
-        }
-        void OnRealized()
-        {
-            _box = new ObservableBox(XForms.NativeParent);
-            _box.SetLayoutCallback(OnLayout);
-
-            _bgColorObject = new ElmSharp.Rectangle(_box)
-            {
-                Color = ElmSharp.Color.Transparent
-            };
-            _bgImageObject = new EvasImage(_box);
-            _surfaceLayout = new ElmSharp.Layout(_box);
-            _surface = new ElmSharp.Wearable.CircleSurface(_surfaceLayout);
-
-
-            _toolbarItemMap = new Dictionary<XToolbarItem, ElmSharp.Wearable.MoreOptionItem>();
-            _circleSurfaceItems = new Dictionary<ICircleSurfaceItem, ICircleWidget>();
-
-            _box.PackEnd(_bgColorObject);
-            _box.PackEnd(_bgImageObject);
-            _box.PackEnd(_surfaceLayout);
-
-            _bgColorObject.Show();
-            _bgImageObject.Hide();
-            _surfaceLayout.Show();
-
-            if (Element.ToolbarItems.Count > 0)
-            {
-                Device.BeginInvokeOnMainThread(() =>
-                {
-                    SetVisibleMoreOption(true);
-
-                    foreach (var item in Element.ToolbarItems)
-                    {
-                        AddToolbarItem(item);
-                    }
-                });
-
-            }
-
-            SetNativeView(_box);
-        }
-        void OnLayout()
-        {
-            var rect = _box.Geometry;
-            Element.Layout(rect.ToDP());
-            _bgColorObject.Geometry = rect;
-            _bgImageObject.Geometry = rect;
-
-            _bgImageObject.StackAbove(_bgColorObject);
-            EvasObject prev = _bgImageObject;
-
-            IContainable<EvasObject> container = _box;
-            foreach (var obj in container.Children)
-            {
-                obj.StackAbove(prev);
-                prev = obj;
-            }
-
-            if (_actionButton != null)
-            {
-                var btnRect = _actionButton.Geometry;
-                var btnW = Math.Max(_actionButton.MinimumWidth, btnRect.Width);
-                var btnH = Math.Max(_actionButton.MinimumHeight, btnRect.Height);
-                var btnX = rect.X + (rect.Width - btnW)/2;
-                var btnY = rect.Height - btnH;
-                _actionButton.Geometry = new Rect(btnX, btnY, btnW, btnH);
-                _actionButton.StackAbove(prev);
-                prev = _actionButton;
-            }
 
-            _surfaceLayout.Geometry = rect;
-            _surfaceLayout.StackAbove(prev);
-            prev = _surfaceLayout;
+               if (_circlePage != null)
+               {
+                       _circlePage.Dispose(disposing);
+               }
 
-            if (_moreOption != null)
-            {
-                _moreOption.Geometry = rect;
-                _moreOption.StackAbove(prev);
-            }
+               base.Dispose(disposing);
         }
 
-        void UpdateBackground()
-        {
-            if (_bgImage.IsNullOrEmpty())
-            {
-                _bgImageObject.Hide();
-            }
-            else
-            {
-                _bgImageObject.Show();
-            }
-        }
         void UpdateActionButton(bool initialize)
         {
-            if (Element.ActionButton != null)
-            {
-                if (_actionButton == null)
-                {
-                    _actionButton = new ElmSharp.Button(_box)
-                    {
-                        Style = "bottom"
-                    };
-                    _actionButton.Clicked += OnActionButtonClicked;
-                    _box.PackEnd(_actionButton);
-                }
-
-                SetVisibleActionButton(Element.ActionButton.IsVisible);
-
-                Element.ActionButton.PropertyChanged += OnActionButtonItemChanged;
-                _actionButton.Text = Element.ActionButton.Text;
-                _actionButton.IsEnabled = Element.ActionButton.IsEnable;
-                if (!Element.ActionButton.IconImageSource.IsNullOrEmpty())
-                {
-                    var imageSource = Element.ActionButton.IconImageSource as FileImageSource;
-                    var path = ResourcePath.GetPath(imageSource);
-                    var buttonImage = new ElmSharp.Image(_actionButton);
-                    buttonImage.LoadAsync(path);
-                    buttonImage.Show();
-                    _actionButton.SetPartContent("elm.swallow.content", buttonImage);
-                }
-
-                if (Element.ActionButton.BackgroundColor != Xamarin.Forms.Color.Default)
-                {
-                    _actionButton.BackgroundColor = Element.ActionButton.BackgroundColor.ToNative();
-                }
-            }
-            else
-            {
-                if (_actionButton != null)
-                {
-                    _actionButton.Clicked -= OnActionButtonClicked;
-                    _box.UnPack(_actionButton);
-                    _actionButton.Unrealize();
-                    _actionButton = null;
-                }
-            }
-        }
-        void OnActionButtonItemChanged(object sender, PropertyChangedEventArgs e)
-        {
-            if (_actionButton == null)
-            {
-                return;
-            }
-            if (e.PropertyName == MenuItem.TextProperty.PropertyName)
-            {
-                _actionButton.Text = Element.ActionButton.Text;
-            }
-            else if (e.PropertyName == ActionButtonItem.IsEnableProperty.PropertyName)
-            {
-                _actionButton.IsEnabled = Element.ActionButton.IsEnable;
-            }
-            else if (e.PropertyName == ActionButtonItem.IsVisibleProperty.PropertyName)
-            {
-                SetVisibleActionButton(Element.ActionButton.IsVisible);
-            }
-        }
-        void OnActionButtonClicked(object sender, EventArgs e)
-        {
-            if (Element.ActionButton != null)
-            {
-                ((IMenuItemController)Element.ActionButton).Activate();
-            }
+               _circlePage.UpdateActionButton(Element.ActionButton);
         }
+
         void OnToolbarItemChanged(object sender, NotifyCollectionChangedEventArgs e)
         {
-            SetVisibleMoreOption(Element.ToolbarItems.Count > 0);
+            _circlePage.SetVisibleMoreOption(Element.ToolbarItems.Count > 0);
             if (e.Action == NotifyCollectionChangedAction.Add ||
                 e.Action == NotifyCollectionChangedAction.Replace)
             {
-                foreach (XToolbarItem item in e.NewItems) AddToolbarItem(item);
+                foreach (XToolbarItem item in e.NewItems) _circlePage.AddToolbarItem(item);
             }
             if (e.Action == NotifyCollectionChangedAction.Remove ||
                 e.Action == NotifyCollectionChangedAction.Replace)
             {
-                foreach (XToolbarItem item in e.OldItems) RemoveToolbarITem(item);
-            }
-        }
-        void AddToolbarItem(XToolbarItem item)
-        {
-            var moreOptionItem = new ActionMoreOptionItem();
-            var icon = item.IconImageSource;
-            if (!icon.IsNullOrEmpty())
-            {
-                var iconSource = icon as FileImageSource;
-                var img = new ElmSharp.Image(_moreOption);
-                img.LoadAsync(ResourcePath.GetPath(iconSource));
-                moreOptionItem.Icon = img;
-            }
-            var text = item.Text;
-            if (!string.IsNullOrEmpty(text))
-            {
-                moreOptionItem.MainText = text;
-            }
-            if (item is CircleToolbarItem)
-            {
-                var subText = ((CircleToolbarItem)item).SubText;
-                if (!string.IsNullOrEmpty(subText))
-                {
-                    moreOptionItem.SubText = subText;
-                }
-            }
-            moreOptionItem.Action = () => ((IMenuItemController)item).Activate();
-            _moreOption.Items.Add(moreOptionItem);
-            _toolbarItemMap[item] = moreOptionItem;
-        }
-        void RemoveToolbarITem(XToolbarItem item)
-        {
-            if (_toolbarItemMap.TryGetValue(item, out var moreOptionItem))
-            {
-                _moreOption?.Items.Remove(moreOptionItem);
-                _toolbarItemMap.Remove(item);
+                foreach (XToolbarItem item in e.OldItems) _circlePage.RemoveToolbarITem(item);
             }
         }
-        void OnMoreOptionClicked(object sender, ElmSharp.Wearable.MoreOptionItemEventArgs e)
+
+        void UpdateRotaryFocusObject()
         {
-            var item = e.Item as ActionMoreOptionItem;
-            if (item != null)
-            {
-                item.Action?.Invoke();
-            }
-            _moreOption.IsOpened = false;
-        }
-        void UpdateRotaryFocusObject(bool initialize)
-        {
-            if (initialize)
-            {
-                _currentRotaryFocusObject = Element.RotaryFocusObject;
-            }
-            else
-            {
-                DeactivateRotaryWidget();
-                _currentRotaryFocusObject = Element.RotaryFocusObject;
-                ActivateRotaryWidget();
-            }
+               _circlePage.UpdateRotaryFocusObject(Element.RotaryFocusObject);
         }
+
         void OnPageDisappearing(object sender, EventArgs e)
         {
-            DeactivateRotaryWidget();
-        }
-        void OnPageAppearing(object sender, EventArgs e)
-        {
-            ActivateRotaryWidget();
-        }
-        void ToolbarClosed(object sender, EventArgs e)
-        {
-            ActivateRotaryWidget();
-        }
-        void ToolbarOpened(object sender, EventArgs e)
-        {
-            DeactivateRotaryWidget();
+               _circlePage.DeactivateRotaryWidget();
         }
 
-        void ActivateRotaryWidget()
-        {
-            if (_currentRotaryFocusObject is IRotaryEventReceiver)
-            {
-                RotaryEventManager.Rotated += OnRotaryEventChanged;
-            }
-            else if (_currentRotaryFocusObject is IRotaryFocusable)
-            {
-                GetRotaryWidget(_currentRotaryFocusObject)?.Activate();
-            }
-        }
-        void DeactivateRotaryWidget()
-        {
-            if (_currentRotaryFocusObject is IRotaryEventReceiver)
-            {
-                RotaryEventManager.Rotated -= OnRotaryEventChanged;
-            }
-            else if (_currentRotaryFocusObject is IRotaryFocusable)
-            {
-                GetRotaryWidget(_currentRotaryFocusObject)?.Deactivate();
-            }
-        }
-        void OnRotaryEventChanged(ElmSharp.Wearable.RotaryEventArgs e)
+        void OnPageAppearing(object sender, EventArgs e)
         {
-            if (_currentRotaryFocusObject is IRotaryEventReceiver)
-            {
-                var receiver = _currentRotaryFocusObject as IRotaryEventReceiver;
-                receiver.Rotate(new RotaryEventArgs { IsClockwise = e.IsClockwise });
-            }
+               _circlePage.ActivateRotaryWidget();
         }
 
         void OnCircleSurfaceItemsChanged(object sender, NotifyCollectionChangedEventArgs e)
@@ -437,96 +174,14 @@ namespace Tizen.Wearable.CircularUI.Forms.Renderer
                 e.Action == NotifyCollectionChangedAction.Replace)
             {
                 foreach (ICircleSurfaceItem item in e.NewItems)
-                    AddCircleSurfaceItem(item);
+                    _circlePage.AddCircleSurfaceItem(item);
             }
             if (e.Action == NotifyCollectionChangedAction.Remove ||
                 e.Action == NotifyCollectionChangedAction.Replace)
             {
                 foreach (ICircleSurfaceItem item in e.OldItems)
-                    RemoveCircleSurfaceItem(item);
-            }
-        }
-
-        void AddCircleSurfaceItem(ICircleSurfaceItem item)
-        {
-            if (item is CircleProgressBarSurfaceItem)
-            {
-                var widget = new CircleProgressBarSurfaceItemImplements(item as CircleProgressBarSurfaceItem, _surfaceLayout, _surface);
-                _circleSurfaceItems[item] = widget;
-            }
-            else if (item is CircleSliderSurfaceItem)
-            {
-                var widget = new CircleSliderSurfaceItemImplements(item as CircleSliderSurfaceItem, _surfaceLayout, _surface);
-                _circleSurfaceItems[item] = widget;
+                    _circlePage.RemoveCircleSurfaceItem(item);
             }
         }
-        void RemoveCircleSurfaceItem(ICircleSurfaceItem item)
-        {
-            if (_circleSurfaceItems.TryGetValue(item, out var widget))
-            {
-                ElmSharp.EvasObject obj = widget as ElmSharp.EvasObject;
-                obj?.Unrealize();
-                _circleSurfaceItems.Remove(item);
-            }
-        }
-
-        IRotaryActionWidget GetRotaryWidget(IRotaryFocusable focusable)
-        {
-            var consumer = focusable as BindableObject;
-            IRotaryActionWidget rotaryWidget = null;
-            if (consumer != null)
-            {
-                if (consumer is CircleSliderSurfaceItem)
-                {
-                    ICircleSurfaceItem item = consumer as ICircleSurfaceItem;
-                    rotaryWidget = GetCircleWidget(item) as IRotaryActionWidget;
-                }
-                else
-                {
-                    var consumerRenderer = Xamarin.Forms.Platform.Tizen.Platform.GetRenderer(consumer);
-                    rotaryWidget = consumerRenderer?.NativeView as IRotaryActionWidget;
-                }
-            }
-            return rotaryWidget;
-        }
-
-        ICircleWidget GetCircleWidget(ICircleSurfaceItem item)
-        {
-            ElmSharp.Wearable.ICircleWidget widget;
-            if (_circleSurfaceItems.TryGetValue(item, out widget))
-            {
-                return widget;
-            }
-            return null;
-        }
-
-        void SetVisibleActionButton(bool visible)
-        {
-            if (_actionButton == null)
-            {
-                return;
-            }
-            if (visible) _actionButton.Show();
-            else _actionButton.Hide();
-        }
-
-        void SetVisibleMoreOption(bool visible)
-        {
-            if (_moreOption == null)
-            {
-                _moreOption = new ElmSharp.Wearable.MoreOption(_box);
-                _moreOption.Clicked += OnMoreOptionClicked;
-                _moreOption.Opened += ToolbarOpened;
-                _moreOption.Closed += ToolbarClosed;
-                _box.PackEnd(_moreOption);
-            }
-            if (visible) _moreOption.Show();
-            else _moreOption.Hide();
-        }
-
-        class ActionMoreOptionItem : MoreOptionItem
-        {
-            public Action Action { get; set; }
-        }
     }
 }
diff --git a/Tizen.CircularUI/Tizen.Wearable.CircularUI.Forms.Renderer/CircularUIForms.cs b/Tizen.CircularUI/Tizen.Wearable.CircularUI.Forms.Renderer/CircularUIForms.cs
new file mode 100644 (file)
index 0000000..563339a
--- /dev/null
@@ -0,0 +1,20 @@
+using System;
+using System.ComponentModel;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using ElmSharp;
+using Tizen.Wearable.CircularUI.Forms.Renderer;
+
+namespace Tizen.Wearable.CircularUI.Forms
+{
+       public static class CircularUIForms
+       {
+               [EditorBrowsable(EditorBrowsableState.Never)]
+               public static void Preload(object windows)
+               {
+                       EvasObject win = windows as EvasObject;
+                       NativeFactory.PrecreateNatives(win);
+               }
+       }
+}
diff --git a/Tizen.CircularUI/Tizen.Wearable.CircularUI.Forms.Renderer/NativeCirclePage.cs b/Tizen.CircularUI/Tizen.Wearable.CircularUI.Forms.Renderer/NativeCirclePage.cs
new file mode 100644 (file)
index 0000000..0255af2
--- /dev/null
@@ -0,0 +1,431 @@
+/*
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Flora License, Version 1.1 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://floralicense.org/license/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+using ElmSharp;
+using ElmSharp.Wearable;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using Xamarin.Forms;
+using Xamarin.Forms.Platform.Tizen;
+using Xamarin.Forms.Platform.Tizen.Native;
+using XForms = Xamarin.Forms.Forms;
+using XToolbarItem = Xamarin.Forms.ToolbarItem;
+
+namespace Tizen.Wearable.CircularUI.Forms.Renderer
+{
+       public class NativeCirclePage : ObservableBox
+       {
+               ElmSharp.Rectangle _bgColorObject;
+               ElmSharp.EvasImage _bgImageObject;
+               ElmSharp.Layout _surfaceLayout;
+               ElmSharp.Button _actionButton = null;
+               ImageSource _bgImage;
+
+               ElmSharp.Wearable.CircleSurface _surface = null;
+               IRotaryFocusable _currentRotaryFocusObject;
+
+               ElmSharp.Wearable.MoreOption _moreOption;
+               Dictionary<XToolbarItem, ElmSharp.Wearable.MoreOptionItem> _toolbarItemMap;
+               Dictionary<ICircleSurfaceItem, ElmSharp.Wearable.ICircleWidget> _circleSurfaceItems;
+
+               ActionButtonItem ActionButtonItem;
+               VisualElement _element = null;
+
+               public NativeCirclePage(EvasObject parent) : base(parent)
+               {
+                       SetLayoutCallback(OnLayout);
+
+                       _bgColorObject = new ElmSharp.Rectangle(this)
+                       {
+                               Color = ElmSharp.Color.Transparent
+                       };
+                       _bgImageObject = new EvasImage(this);
+                       _surfaceLayout = new ElmSharp.Layout(this);
+                       _surface = new ElmSharp.Wearable.CircleSurface(_surfaceLayout);
+
+                       _toolbarItemMap = new Dictionary<XToolbarItem, ElmSharp.Wearable.MoreOptionItem>();
+                       _circleSurfaceItems = new Dictionary<ICircleSurfaceItem, ICircleWidget>();
+
+                       PackEnd(_bgColorObject);
+                       PackEnd(_bgImageObject);
+                       PackEnd(_surfaceLayout);
+
+                       _bgColorObject.Show();
+                       _bgImageObject.Hide();
+                       _surfaceLayout.Show();
+               }
+
+               public ElmSharp.Wearable.CircleSurface Surface
+               {
+                       get { return _surface; }
+               }
+
+               public void Dispose(bool disposing)
+               {
+                       if (ActionButtonItem != null)
+                       {
+                               ActionButtonItem.PropertyChanged -= OnActionButtonItemChanged;
+                       }
+               }
+
+               public void AddToolbarItem(XToolbarItem item)
+               {
+                       var moreOptionItem = new ActionMoreOptionItem();
+                       var icon = item.IconImageSource;
+                       if (!icon.IsNullOrEmpty())
+                       {
+                               var iconSource = icon as FileImageSource;
+                               var img = new ElmSharp.Image(_moreOption);
+                               img.LoadAsync(ResourcePath.GetPath(iconSource));
+                               moreOptionItem.Icon = img;
+                       }
+                       var text = item.Text;
+                       if (!string.IsNullOrEmpty(text))
+                       {
+                               moreOptionItem.MainText = text;
+                       }
+                       if (item is CircleToolbarItem)
+                       {
+                               var subText = ((CircleToolbarItem)item).SubText;
+                               if (!string.IsNullOrEmpty(subText))
+                               {
+                                       moreOptionItem.SubText = subText;
+                               }
+                       }
+                       moreOptionItem.Action = () => ((IMenuItemController)item).Activate();
+                       _moreOption.Items.Add(moreOptionItem);
+                       _toolbarItemMap[item] = moreOptionItem;
+               }
+
+               public void RemoveToolbarITem(XToolbarItem item)
+               {
+                       if (_toolbarItemMap.TryGetValue(item, out var moreOptionItem))
+                       {
+                               _moreOption?.Items.Remove(moreOptionItem);
+                               _toolbarItemMap.Remove(item);
+                       }
+               }
+
+               public void AddCircleSurfaceItem(ICircleSurfaceItem item)
+               {
+                       if (item is CircleProgressBarSurfaceItem)
+                       {
+                               var widget = new CircleProgressBarSurfaceItemImplements(item as CircleProgressBarSurfaceItem, _surfaceLayout, _surface);
+                               _circleSurfaceItems[item] = widget;
+                       }
+                       else if (item is CircleSliderSurfaceItem)
+                       {
+                               var widget = new CircleSliderSurfaceItemImplements(item as CircleSliderSurfaceItem, _surfaceLayout, _surface);
+                               _circleSurfaceItems[item] = widget;
+                       }
+               }
+
+               public void RemoveCircleSurfaceItem(ICircleSurfaceItem item)
+               {
+                       if (_circleSurfaceItems.TryGetValue(item, out var widget))
+                       {
+                               ElmSharp.EvasObject obj = widget as ElmSharp.EvasObject;
+                               obj?.Unrealize();
+                               _circleSurfaceItems.Remove(item);
+                       }
+               }
+
+               public void UpdateRotaryFocusObject(IRotaryFocusable RotaryFocusObject)
+               {
+                       DeactivateRotaryWidget();
+                       _currentRotaryFocusObject = RotaryFocusObject;
+                       ActivateRotaryWidget();
+               }
+
+               public void ActivateRotaryWidget()
+               {
+                       if (_currentRotaryFocusObject is IRotaryEventReceiver)
+                       {
+                               RotaryEventManager.Rotated += OnRotaryEventChanged;
+                       }
+                       else if (_currentRotaryFocusObject is IRotaryFocusable)
+                       {
+                               GetRotaryWidget(_currentRotaryFocusObject)?.Activate();
+                       }
+               }
+
+               public void DeactivateRotaryWidget()
+               {
+                       if (_currentRotaryFocusObject is IRotaryEventReceiver)
+                       {
+                               RotaryEventManager.Rotated -= OnRotaryEventChanged;
+                       }
+                       else if (_currentRotaryFocusObject is IRotaryFocusable)
+                       {
+                               GetRotaryWidget(_currentRotaryFocusObject)?.Deactivate();
+                       }
+               }
+
+               public void UpdateBackgroundColor(Xamarin.Forms.Color BackgroundColor)
+               {
+                       if (BackgroundColor.A == 0)
+                       {
+                               _bgColorObject.Color = ElmSharp.Color.Transparent;
+                       }
+                       else
+                       {
+                               _bgColorObject.Color = BackgroundColor.ToNative();
+                       }
+                       UpdateBackground();
+               }
+
+               public void UpdateBackground()
+               {
+                       if (_bgImage.IsNullOrEmpty())
+                       {
+                               _bgImageObject.Hide();
+                       }
+                       else
+                       {
+                               _bgImageObject.Show();
+                       }
+               }
+
+               public void UpdateBackgroundImage(ImageSource BackgroundImageSource)
+               {
+                       var bgImageSource = BackgroundImageSource as FileImageSource;
+                       if (bgImageSource.IsNullOrEmpty())
+                       {
+                               _bgImageObject.File = null;
+                               _bgImage = null;
+                       }
+                       else
+                       {
+                               _bgImageObject.File = ResourcePath.GetPath(bgImageSource);
+                               _bgImage = BackgroundImageSource;
+                       }
+                       UpdateBackground();
+               }
+
+               public void SetVisibleMoreOption(bool visible)
+               {
+                       if (_moreOption == null)
+                       {
+                               _moreOption = new ElmSharp.Wearable.MoreOption(this);
+                               _moreOption.Clicked += OnMoreOptionClicked;
+                               _moreOption.Opened += ToolbarOpened;
+                               _moreOption.Closed += ToolbarClosed;
+                               PackEnd(_moreOption);
+                       }
+                       if (visible) _moreOption.Show();
+                       else _moreOption.Hide();
+               }
+
+               public void UpdateActionButton(ActionButtonItem ActionButton)
+               {
+                       ActionButtonItem = ActionButton;
+                       if (ActionButton != null)
+                       {
+                               if (_actionButton == null)
+                               {
+                                       _actionButton = new ElmSharp.Button(this)
+                                       {
+                                               Style = "bottom"
+                                       };
+                                       _actionButton.Clicked += OnActionButtonClicked;
+                                       PackEnd(_actionButton);
+                               }
+
+                               SetVisibleActionButton(ActionButton.IsVisible);
+
+                               ActionButton.PropertyChanged += OnActionButtonItemChanged;
+                               _actionButton.Text = ActionButton.Text;
+                               _actionButton.IsEnabled = ActionButton.IsEnable;
+                               if (!ActionButton.IconImageSource.IsNullOrEmpty())
+                               {
+                                       var imageSource = ActionButton.IconImageSource as FileImageSource;
+                                       var path = ResourcePath.GetPath(imageSource);
+                                       var buttonImage = new ElmSharp.Image(_actionButton);
+                                       buttonImage.LoadAsync(path);
+                                       buttonImage.Show();
+                                       _actionButton.SetPartContent("elm.swallow.content", buttonImage);
+                               }
+
+                               if (ActionButton.BackgroundColor != Xamarin.Forms.Color.Default)
+                               {
+                                       _actionButton.BackgroundColor = ActionButton.BackgroundColor.ToNative();
+                               }
+                       }
+                       else
+                       {
+                               if (_actionButton != null)
+                               {
+                                       _actionButton.Clicked -= OnActionButtonClicked;
+                                       UnPack(_actionButton);
+                                       _actionButton.Unrealize();
+                                       _actionButton = null;
+                               }
+                       }
+               }
+
+               internal void SetElement(VisualElement ve)
+               {
+                       _element = ve;
+               }
+
+               void OnLayout()
+               {
+                       if (_element == null)
+                       {
+                               return;
+                       }
+                       var rect = Geometry;
+                       _element.Layout(rect.ToDP());
+                       _bgColorObject.Geometry = rect;
+                       _bgImageObject.Geometry = rect;
+
+                       _bgImageObject.StackAbove(_bgColorObject);
+                       EvasObject prev = _bgImageObject;
+
+                       IContainable<EvasObject> container = this;
+                       foreach (var obj in container.Children)
+                       {
+                               obj.StackAbove(prev);
+                               prev = obj;
+                       }
+
+                       if (_actionButton != null)
+                       {
+                               var btnRect = _actionButton.Geometry;
+                               var btnW = Math.Max(_actionButton.MinimumWidth, btnRect.Width);
+                               var btnH = Math.Max(_actionButton.MinimumHeight, btnRect.Height);
+                               var btnX = rect.X + (rect.Width - btnW) / 2;
+                               var btnY = rect.Height - btnH;
+                               _actionButton.Geometry = new Rect(btnX, btnY, btnW, btnH);
+                               _actionButton.StackAbove(prev);
+                               prev = _actionButton;
+                       }
+
+                       _surfaceLayout.Geometry = rect;
+                       _surfaceLayout.StackAbove(prev);
+                       prev = _surfaceLayout;
+
+                       if (_moreOption != null)
+                       {
+                               _moreOption.Geometry = rect;
+                               _moreOption.StackAbove(prev);
+                       }
+               }
+
+               void OnRotaryEventChanged(ElmSharp.Wearable.RotaryEventArgs e)
+               {
+                       if (_currentRotaryFocusObject is IRotaryEventReceiver)
+                       {
+                               var receiver = _currentRotaryFocusObject as IRotaryEventReceiver;
+                               receiver.Rotate(new RotaryEventArgs { IsClockwise = e.IsClockwise });
+                       }
+               }
+
+               IRotaryActionWidget GetRotaryWidget(IRotaryFocusable focusable)
+               {
+                       var consumer = focusable as BindableObject;
+                       IRotaryActionWidget rotaryWidget = null;
+                       if (consumer != null)
+                       {
+                               if (consumer is CircleSliderSurfaceItem)
+                               {
+                                       ICircleSurfaceItem item = consumer as ICircleSurfaceItem;
+                                       rotaryWidget = GetCircleWidget(item) as IRotaryActionWidget;
+                               }
+                               else
+                               {
+                                       var consumerRenderer = Xamarin.Forms.Platform.Tizen.Platform.GetRenderer(consumer);
+                                       rotaryWidget = consumerRenderer?.NativeView as IRotaryActionWidget;
+                               }
+                       }
+                       return rotaryWidget;
+               }
+
+               ICircleWidget GetCircleWidget(ICircleSurfaceItem item)
+               {
+                       ElmSharp.Wearable.ICircleWidget widget;
+                       if (_circleSurfaceItems.TryGetValue(item, out widget))
+                       {
+                               return widget;
+                       }
+                       return null;
+               }
+
+               void ToolbarClosed(object sender, EventArgs e)
+               {
+                       ActivateRotaryWidget();
+               }
+
+               void ToolbarOpened(object sender, EventArgs e)
+               {
+                       DeactivateRotaryWidget();
+               }
+
+               void OnMoreOptionClicked(object sender, ElmSharp.Wearable.MoreOptionItemEventArgs e)
+               {
+                       var item = e.Item as ActionMoreOptionItem;
+                       if (item != null)
+                       {
+                               item.Action?.Invoke();
+                       }
+                       _moreOption.IsOpened = false;
+               }
+
+               void OnActionButtonItemChanged(object sender, PropertyChangedEventArgs e)
+               {
+                       if (_actionButton == null)
+                       {
+                               return;
+                       }
+                       if (e.PropertyName == MenuItem.TextProperty.PropertyName)
+                       {
+                               _actionButton.Text = ActionButtonItem.Text;
+                       }
+                       else if (e.PropertyName == ActionButtonItem.IsEnableProperty.PropertyName)
+                       {
+                               _actionButton.IsEnabled = ActionButtonItem.IsEnable;
+                       }
+                       else if (e.PropertyName == ActionButtonItem.IsVisibleProperty.PropertyName)
+                       {
+                               SetVisibleActionButton(ActionButtonItem.IsVisible);
+                       }
+               }
+
+               void OnActionButtonClicked(object sender, EventArgs e)
+               {
+                       if (ActionButtonItem != null)
+                       {
+                               ((IMenuItemController)ActionButtonItem).Activate();
+                       }
+               }
+
+               void SetVisibleActionButton(bool visible)
+               {
+                       if (_actionButton == null)
+                       {
+                               return;
+                       }
+                       if (visible) _actionButton.Show();
+                       else _actionButton.Hide();
+               }
+
+               class ActionMoreOptionItem : MoreOptionItem
+               {
+                       public Action Action { get; set; }
+               }
+       }
+}
diff --git a/Tizen.CircularUI/Tizen.Wearable.CircularUI.Forms.Renderer/NativeFactory.cs b/Tizen.CircularUI/Tizen.Wearable.CircularUI.Forms.Renderer/NativeFactory.cs
new file mode 100644 (file)
index 0000000..d203f01
--- /dev/null
@@ -0,0 +1,38 @@
+using System;
+using System.Collections.Generic;
+using ElmSharp;
+using XForms = Xamarin.Forms.Forms;
+
+namespace Tizen.Wearable.CircularUI.Forms.Renderer
+{
+       class NativeFactory
+       {
+               static List<NativeCirclePage> circlePages = new List<NativeCirclePage>();
+               const int lfrequency = 3;
+
+               public static void PrecreateNatives(EvasObject window)
+               {
+                       for (int i = 0; i < lfrequency; i++)
+                       {
+                               var page = new NativeCirclePage(window);
+                               page.Hide();
+                               circlePages.Add(page);
+                       }
+               }
+
+               public static EvasObject GetNativeControl(Type type)
+               {
+                       if (type == typeof(NativeCirclePage))
+                       {
+                               if (circlePages.Count >= 1)
+                               {
+                                       NativeCirclePage native = circlePages[circlePages.Count - 1];
+                                       circlePages.RemoveAt(circlePages.Count - 1);
+                                       return native;
+                               }
+                               return new NativeCirclePage(XForms.NativeParent);
+                       }
+                       return Activator.CreateInstance(type, new[] { XForms.NativeParent }) as EvasObject;
+               }
+       }
+}
index dc39d09..9a2a95c 100644 (file)
@@ -25,7 +25,7 @@ using Xamarin.Forms.Platform.Tizen.Native;
 
 namespace Tizen.Wearable.CircularUI.Forms.Renderer
 {
-    class ObservableBox : ElmSharp.Box, IContainable<EvasObject>
+    public class ObservableBox : ElmSharp.Box, IContainable<EvasObject>
     {
         ReObservableCollection<EvasObject> _children;
         public ObservableBox(EvasObject parent) : base(parent)
index d80cb38..bd12651 100755 (executable)
@@ -13,6 +13,7 @@ using TSystemSetting = Tizen.System.SystemSettings;
 using ELayout = ElmSharp.Layout;
 using DeviceOrientation = Xamarin.Forms.Internals.DeviceOrientation;
 using Xamarin.Forms.PlatformConfiguration.TizenSpecific;
+using System.Runtime.Loader;
 
 namespace Xamarin.Forms
 {
@@ -679,6 +680,11 @@ namespace Xamarin.Forms
                                System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(type.TypeHandle);
                        }
                        global::Xamarin.Forms.Platform.Tizen.Native.NativeFactory.PrecreateNatives(window);
+
+                       var asm = AssemblyLoadContext.Default.LoadFromAssemblyName(new AssemblyName("XSF.CircularUI.Forms.Renderer"));
+                       var preloadtype = asm.GetType("Tizen.Wearable.CircularUI.Forms.CircularUIForms").GetMethod("Preload", BindingFlags.Public | BindingFlags.Static).Invoke(null, new object[] { window });
+
+
                }
        }