2 * Copyright (c) 2018 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Flora License, Version 1.1 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://floralicense.org/license/
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
18 using ElmSharp.Wearable;
20 using System.Collections.Generic;
21 using System.ComponentModel;
23 using Xamarin.Forms.Platform.Tizen;
24 using Xamarin.Forms.Platform.Tizen.Native;
25 using XForms = Xamarin.Forms.Forms;
26 using XToolbarItem = Xamarin.Forms.ToolbarItem;
28 namespace Tizen.Wearable.CircularUI.Forms.Renderer
30 public class NativeCirclePage : ObservableBox
32 ElmSharp.Rectangle _bgColorObject;
33 ElmSharp.EvasImage _bgImageObject;
34 ElmSharp.Layout _surfaceLayout;
35 ElmSharp.Button _actionButton = null;
38 ElmSharp.Wearable.CircleSurface _surface = null;
39 IRotaryFocusable _currentRotaryFocusObject;
41 ElmSharp.Wearable.MoreOption _moreOption;
42 Dictionary<XToolbarItem, ElmSharp.Wearable.MoreOptionItem> _toolbarItemMap;
43 Dictionary<ICircleSurfaceItem, ElmSharp.Wearable.ICircleWidget> _circleSurfaceItems;
45 ActionButtonItem ActionButtonItem;
46 VisualElement _element = null;
48 public NativeCirclePage(EvasObject parent) : base(parent)
50 SetLayoutCallback(OnLayout);
52 _bgColorObject = new ElmSharp.Rectangle(this)
54 Color = ElmSharp.Color.Transparent
56 _bgImageObject = new EvasImage(this);
57 _surfaceLayout = new ElmSharp.Layout(this);
58 _surface = new ElmSharp.Wearable.CircleSurface(_surfaceLayout);
60 _toolbarItemMap = new Dictionary<XToolbarItem, ElmSharp.Wearable.MoreOptionItem>();
61 _circleSurfaceItems = new Dictionary<ICircleSurfaceItem, ICircleWidget>();
63 PackEnd(_bgColorObject);
64 PackEnd(_bgImageObject);
65 PackEnd(_surfaceLayout);
67 _bgColorObject.Show();
68 _bgImageObject.Hide();
69 _surfaceLayout.Show();
72 public ElmSharp.Wearable.CircleSurface Surface
74 get { return _surface; }
77 public void Dispose(bool disposing)
79 if (ActionButtonItem != null)
81 ActionButtonItem.PropertyChanged -= OnActionButtonItemChanged;
85 public void AddToolbarItem(XToolbarItem item)
87 var moreOptionItem = new ActionMoreOptionItem();
88 var icon = item.IconImageSource;
89 if (!icon.IsNullOrEmpty())
91 var iconSource = icon as FileImageSource;
92 var img = new ElmSharp.Image(_moreOption);
93 img.LoadAsync(ResourcePath.GetPath(iconSource));
94 moreOptionItem.Icon = img;
97 if (!string.IsNullOrEmpty(text))
99 moreOptionItem.MainText = text;
101 if (item is CircleToolbarItem)
103 var subText = ((CircleToolbarItem)item).SubText;
104 if (!string.IsNullOrEmpty(subText))
106 moreOptionItem.SubText = subText;
109 moreOptionItem.Action = () => ((IMenuItemController)item).Activate();
110 _moreOption.Items.Add(moreOptionItem);
111 _toolbarItemMap[item] = moreOptionItem;
114 public void RemoveToolbarITem(XToolbarItem item)
116 if (_toolbarItemMap.TryGetValue(item, out var moreOptionItem))
118 _moreOption?.Items.Remove(moreOptionItem);
119 _toolbarItemMap.Remove(item);
123 public void AddCircleSurfaceItem(ICircleSurfaceItem item)
125 if (item is CircleProgressBarSurfaceItem)
127 var widget = new CircleProgressBarSurfaceItemImplements(item as CircleProgressBarSurfaceItem, _surfaceLayout, _surface);
128 _circleSurfaceItems[item] = widget;
130 else if (item is CircleSliderSurfaceItem)
132 var widget = new CircleSliderSurfaceItemImplements(item as CircleSliderSurfaceItem, _surfaceLayout, _surface);
133 _circleSurfaceItems[item] = widget;
137 public void RemoveCircleSurfaceItem(ICircleSurfaceItem item)
139 if (_circleSurfaceItems.TryGetValue(item, out var widget))
141 ElmSharp.EvasObject obj = widget as ElmSharp.EvasObject;
143 _circleSurfaceItems.Remove(item);
147 public void UpdateRotaryFocusObject(IRotaryFocusable RotaryFocusObject)
149 DeactivateRotaryWidget();
150 _currentRotaryFocusObject = RotaryFocusObject;
151 ActivateRotaryWidget();
154 public void ActivateRotaryWidget()
156 if (_currentRotaryFocusObject is IRotaryEventReceiver)
158 RotaryEventManager.Rotated += OnRotaryEventChanged;
160 else if (_currentRotaryFocusObject is IRotaryFocusable)
162 GetRotaryWidget(_currentRotaryFocusObject)?.Activate();
166 public void DeactivateRotaryWidget()
168 if (_currentRotaryFocusObject is IRotaryEventReceiver)
170 RotaryEventManager.Rotated -= OnRotaryEventChanged;
172 else if (_currentRotaryFocusObject is IRotaryFocusable)
174 GetRotaryWidget(_currentRotaryFocusObject)?.Deactivate();
178 public void UpdateBackgroundColor(Xamarin.Forms.Color BackgroundColor)
180 if (BackgroundColor.A == 0)
182 _bgColorObject.Color = ElmSharp.Color.Transparent;
186 _bgColorObject.Color = BackgroundColor.ToNative();
191 public void UpdateBackground()
193 if (_bgImage.IsNullOrEmpty())
195 _bgImageObject.Hide();
199 _bgImageObject.Show();
203 public void UpdateBackgroundImage(ImageSource BackgroundImageSource)
205 var bgImageSource = BackgroundImageSource as FileImageSource;
206 if (bgImageSource.IsNullOrEmpty())
208 _bgImageObject.File = null;
213 _bgImageObject.IsFilled = true;
214 _bgImageObject.File = ResourcePath.GetPath(bgImageSource);
215 _bgImage = BackgroundImageSource;
220 public void SetVisibleMoreOption(bool visible)
222 if (_moreOption == null)
224 _moreOption = new ElmSharp.Wearable.MoreOption(this);
225 _moreOption.Clicked += OnMoreOptionClicked;
226 _moreOption.Opened += ToolbarOpened;
227 _moreOption.Closed += ToolbarClosed;
228 PackEnd(_moreOption);
230 if (visible) _moreOption.Show();
231 else _moreOption.Hide();
234 public void UpdateActionButton(ActionButtonItem ActionButton)
236 ActionButtonItem = ActionButton;
237 if (ActionButton != null)
239 if (_actionButton == null)
241 _actionButton = new ElmSharp.Button(this)
245 _actionButton.Clicked += OnActionButtonClicked;
246 PackEnd(_actionButton);
249 SetVisibleActionButton(ActionButton.IsVisible);
251 ActionButton.PropertyChanged += OnActionButtonItemChanged;
252 _actionButton.Text = ActionButton.Text?.Replace("&", "&")
253 .Replace("<", "<")
254 .Replace(">", ">")
255 .Replace(Environment.NewLine, "<br>");
256 _actionButton.IsEnabled = ActionButton.IsEnable;
257 if (!ActionButton.IconImageSource.IsNullOrEmpty())
259 var imageSource = ActionButton.IconImageSource as FileImageSource;
260 var path = ResourcePath.GetPath(imageSource);
261 var buttonImage = new ElmSharp.Image(_actionButton);
262 buttonImage.LoadAsync(path);
264 _actionButton.SetPartContent("elm.swallow.content", buttonImage);
268 _actionButton.SetPartContent("elm.swallow.content", null);
271 _actionButton.BackgroundColor = ActionButton.BackgroundColor.ToNative();
275 if (_actionButton != null)
277 _actionButton.Clicked -= OnActionButtonClicked;
278 UnPack(_actionButton);
279 _actionButton.Unrealize();
280 _actionButton = null;
285 internal void SetElement(VisualElement ve)
292 if (_element == null)
297 _element.Layout(rect.ToDP());
298 _bgColorObject.Geometry = rect;
299 _bgImageObject.Geometry = rect;
301 _bgImageObject.StackAbove(_bgColorObject);
302 EvasObject prev = _bgImageObject;
304 IContainable<EvasObject> container = this;
305 foreach (var obj in container.Children)
307 obj.StackAbove(prev);
311 if (_actionButton != null)
313 var btnRect = _actionButton.Geometry;
314 var btnW = Math.Max(_actionButton.MinimumWidth, btnRect.Width);
315 var btnH = Math.Max(_actionButton.MinimumHeight, btnRect.Height);
316 var btnX = rect.X + (rect.Width - btnW) / 2;
317 var btnY = rect.Y + rect.Height - btnH;
318 _actionButton.Geometry = new Rect(btnX, btnY, btnW, btnH);
319 _actionButton.StackAbove(prev);
320 prev = _actionButton;
323 _surfaceLayout.Geometry = rect;
324 _surfaceLayout.StackAbove(prev);
325 prev = _surfaceLayout;
327 if (_moreOption != null)
329 _moreOption.Geometry = rect;
330 _moreOption.StackAbove(prev);
334 void OnRotaryEventChanged(ElmSharp.Wearable.RotaryEventArgs e)
336 if (_currentRotaryFocusObject is IRotaryEventReceiver)
338 var receiver = _currentRotaryFocusObject as IRotaryEventReceiver;
339 receiver.Rotate(new RotaryEventArgs { IsClockwise = e.IsClockwise });
343 IRotaryActionWidget GetRotaryWidget(IRotaryFocusable focusable)
345 var consumer = focusable as BindableObject;
346 IRotaryActionWidget rotaryWidget = null;
347 if (consumer != null)
349 if (consumer is CircleSliderSurfaceItem)
351 ICircleSurfaceItem item = consumer as ICircleSurfaceItem;
352 rotaryWidget = GetCircleWidget(item) as IRotaryActionWidget;
356 var consumerRenderer = Xamarin.Forms.Platform.Tizen.Platform.GetRenderer(consumer);
357 rotaryWidget = consumerRenderer?.NativeView as IRotaryActionWidget;
363 ICircleWidget GetCircleWidget(ICircleSurfaceItem item)
365 ElmSharp.Wearable.ICircleWidget widget;
366 if (_circleSurfaceItems.TryGetValue(item, out widget))
373 void ToolbarClosed(object sender, EventArgs e)
375 ActivateRotaryWidget();
378 void ToolbarOpened(object sender, EventArgs e)
380 DeactivateRotaryWidget();
383 void OnMoreOptionClicked(object sender, ElmSharp.Wearable.MoreOptionItemEventArgs e)
385 var item = e.Item as ActionMoreOptionItem;
388 item.Action?.Invoke();
390 _moreOption.IsOpened = false;
393 void OnActionButtonItemChanged(object sender, PropertyChangedEventArgs e)
395 if (_actionButton == null)
399 if (e.PropertyName == MenuItem.TextProperty.PropertyName)
401 _actionButton.Text = ActionButtonItem.Text;
403 else if (e.PropertyName == ActionButtonItem.IsEnableProperty.PropertyName)
405 _actionButton.IsEnabled = ActionButtonItem.IsEnable;
407 else if (e.PropertyName == ActionButtonItem.IsVisibleProperty.PropertyName)
409 SetVisibleActionButton(ActionButtonItem.IsVisible);
413 void OnActionButtonClicked(object sender, EventArgs e)
415 if (ActionButtonItem != null)
417 ((IMenuItemController)ActionButtonItem).Activate();
421 void SetVisibleActionButton(bool visible)
423 if (_actionButton == null)
427 if (visible) _actionButton.Show();
428 else _actionButton.Hide();
431 class ActionMoreOptionItem : MoreOptionItem
433 public Action Action { get; set; }