Support new features of Tizen.CircularUI (#188)
[platform/core/csapi/xsf.git] / src / XSF / Tizen.Wearable.CircularUI.Forms.Renderer / TizenCircleSurfaceEffect.cs
1 /*
2  * Copyright (c) 2018 Samsung Electronics Co., Ltd All Rights Reserved
3  *
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
7  *
8  *     http://floralicense.org/license/
9  *
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.
15  */
16
17 using ElmSharp;
18 using ElmSharp.Wearable;
19 using System;
20 using System.Collections.Generic;
21 using System.Linq;
22 using System.Text;
23 using Xamarin.Forms;
24 using Xamarin.Forms.Platform.Tizen;
25 using XForms = Xamarin.Forms.Forms;
26
27 [assembly: ExportEffect(typeof(Tizen.Wearable.CircularUI.Forms.Renderer.TizenCircleSurfaceEffect), "CircleSurfaceEffect")]
28 namespace Tizen.Wearable.CircularUI.Forms.Renderer
29 {
30         public class TizenCircleSurfaceEffect : PlatformEffect
31         {
32                 ElmSharp.Layout _surfaceLayout;
33                 ElmSharp.Wearable.CircleSurface _surface;
34
35                 EvasObjectEvent _showEvent;
36                 EvasObjectEvent _hideEvent;
37                 EvasObjectEvent _restackEvent;
38                 EvasObjectEvent _moveEvent;
39                 EvasObjectEvent _resizeEvent;
40
41                 IRotaryEventReceiver _rotaryReceiver;
42
43                 protected override void OnAttached()
44                 {
45                         var rect = Control.Geometry;
46
47                         _surfaceLayout = new ElmSharp.Layout(XForms.NativeParent);
48                         _surfaceLayout.Show();
49                         _surface = new ElmSharp.Wearable.CircleSurface(_surfaceLayout);
50                         _surfaceLayout.Geometry = rect;
51                         _surfaceLayout.StackAbove(Control);
52
53                         CircleSurfaceEffectBehavior.SetSurface(Element, _surface);
54
55                         _showEvent = new EvasObjectEvent(Control, EvasObjectCallbackType.Show);
56                         _hideEvent = new EvasObjectEvent(Control, EvasObjectCallbackType.Hide);
57                         _restackEvent = new EvasObjectEvent(Control, EvasObjectCallbackType.Restack);
58                         _moveEvent = new EvasObjectEvent(Control, EvasObjectCallbackType.Move);
59                         _resizeEvent = new EvasObjectEvent(Control, EvasObjectCallbackType.Resize);
60
61                         _showEvent.On += ControlShowed;
62                         _hideEvent.On += ControlHided;
63                         _restackEvent.On += ControlRestacked;
64                         _moveEvent.On += ControlChanged;
65                         _resizeEvent.On += ControlChanged;
66
67                         Element.PropertyChanging += ElementPropertyChanging;
68                         Element.PropertyChanged += ElementPropertyChanged;
69
70                         if (Element is Page)
71                         {
72                                 (Element as Page).Appearing += (s, e) =>
73                                 {
74                                         var obj = CircleSurfaceEffectBehavior.GetRotaryFocusObject(Element);
75                                         ActivateRotaryFocusable(obj);
76                                 };
77                         }
78                         else
79                         {
80                                 EcoreMainloop.Post(() =>
81                                 {
82                                         var obj = CircleSurfaceEffectBehavior.GetRotaryFocusObject(Element);
83                                         ActivateRotaryFocusable(obj);
84                                 });
85                         }
86                 }
87
88                 protected override void OnDetached()
89                 {
90                         var obj = CircleSurfaceEffectBehavior.GetRotaryFocusObject(Element);
91                         DeativateRotaryFocusable(obj);
92
93                         _surface.Delete();
94                         _surface = null;
95                         _surfaceLayout.Unrealize();
96                         _surfaceLayout = null;
97                         CircleSurfaceEffectBehavior.SetSurface(Element, null);
98
99                         _showEvent.Dispose();
100                         _hideEvent.Dispose();
101                         _restackEvent.Dispose();
102                         _moveEvent.Dispose();
103                         _resizeEvent.Dispose();
104                 }
105
106                 void ElementPropertyChanging(object sender, PropertyChangingEventArgs e)
107                 {
108                         if (e.PropertyName == CircleSurfaceEffectBehavior.RotaryFocusObjectProperty.PropertyName)
109                         {
110                                 var obj = CircleSurfaceEffectBehavior.GetRotaryFocusObject(Element);
111                                 DeativateRotaryFocusable(obj);
112                         }
113                 }
114
115                 void ElementPropertyChanged(object sender, global::System.ComponentModel.PropertyChangedEventArgs e)
116                 {
117                         if (e.PropertyName == CircleSurfaceEffectBehavior.RotaryFocusObjectProperty.PropertyName)
118                         {
119                                 var obj = CircleSurfaceEffectBehavior.GetRotaryFocusObject(Element);
120                                 ActivateRotaryFocusable(obj);
121                         }
122                 }
123
124                 void OnRotaryEventChanged(ElmSharp.Wearable.RotaryEventArgs e)
125                 {
126                         _rotaryReceiver?.Rotate(new RotaryEventArgs { IsClockwise = e.IsClockwise });
127                 }
128
129                 void ControlShowed(object sender, EventArgs e)
130                 {
131                         _surfaceLayout.Show();
132                 }
133
134                 void ControlHided(object sender, EventArgs e)
135                 {
136                         _surfaceLayout.Hide();
137                 }
138
139                 void ControlRestacked(object sender, EventArgs e)
140                 {
141                         _surfaceLayout.StackAbove(Control);
142                 }
143
144                 void ControlChanged(object sender, EventArgs e)
145                 {
146                         _surfaceLayout.Geometry = Control.Geometry;
147                 }
148
149                 void ActivateRotaryFocusable(IRotaryFocusable focusable)
150                 {
151                         if (focusable is IRotaryEventReceiver)
152                         {
153                                 _rotaryReceiver = focusable as IRotaryEventReceiver;
154                                 RotaryEventManager.Rotated += OnRotaryEventChanged;
155                         }
156                         else if (focusable is IRotaryFocusable)
157                         {
158                                 var consumer = focusable as BindableObject;
159                                 if (consumer != null)
160                                 {
161                                         var renderer = Xamarin.Forms.Platform.Tizen.Platform.GetRenderer(consumer);
162                                         (renderer?.NativeView as IRotaryActionWidget)?.Activate();
163                                 }
164                         }
165                 }
166
167                 void DeativateRotaryFocusable(IRotaryFocusable focusable)
168                 {
169                         if (focusable is IRotaryEventReceiver)
170                         {
171                                 _rotaryReceiver = null;
172                                 RotaryEventManager.Rotated -= OnRotaryEventChanged;
173                         }
174                         else if (focusable is IRotaryFocusable)
175                         {
176                                 var consumer = focusable as BindableObject;
177                                 if (consumer != null)
178                                 {
179                                         var renderer = Xamarin.Forms.Platform.Tizen.Platform.GetRenderer(consumer);
180                                         (renderer?.NativeView as IRotaryActionWidget)?.Deactivate();
181                                 }
182                         }
183                 }
184         }
185 }