cbe2f0b89b99b7906de36257adf662fd16bd5ad3
[platform/core/csapi/xsf.git] / src / XSF / Xamarin.Forms.Platform.Tizen / FormsApplication.cs
1 using System;
2 using System.ComponentModel;
3 using System.Diagnostics;
4 using System.Threading.Tasks;
5 using System.Reflection;
6 using ElmSharp;
7 using Tizen.Applications;
8 using Xamarin.Forms.Internals;
9 using ELayout = ElmSharp.Layout;
10 using DeviceOrientation = Xamarin.Forms.Internals.DeviceOrientation;
11 using Xamarin.Forms.Platform.Tizen.Native;
12 using ElmSharp.Wearable;
13 using Specific = Xamarin.Forms.PlatformConfiguration.TizenSpecific.Application;
14 using CircularUI = Tizen.Wearable.CircularUI.Forms;
15
16 namespace Xamarin.Forms.Platform.Tizen
17 {
18
19         public class FormsApplication : CoreUIApplication
20         {
21                 ITizenPlatform _platform;
22                 Application _application;
23                 bool _isInitialStart;
24                 Window _window;
25                 bool _useBezelInteration;
26
27                 protected FormsApplication()
28                 {
29                         _isInitialStart = true;
30                 }
31
32                 /// <summary>
33                 /// Gets the main window or <c>null</c> if it's not set.
34                 /// </summary>
35                 /// <value>The main window or <c>null</c>.</value>
36                 public Window MainWindow
37                 {
38                         get
39                         {
40                                 return _window;
41                         }
42                         protected set
43                         {
44                                 _window = value;
45                                 InitializeWindow();
46                         }
47                 }
48
49                 public ELayout BaseLayout
50                 {
51                         get; protected set;
52                 }
53
54                 public CircleSurface BaseCircleSurface
55                 {
56                         get; protected set;
57                 }
58
59                 public bool UseBezelInteration => _useBezelInteration;
60
61                 protected override void OnPreCreate()
62                 {
63                         base.OnPreCreate();
64                         Application.ClearCurrent();
65                         PreloadedWindow window = PreloadedWindow.GetInstance() ?? new PreloadedWindow();
66
67                         MainWindow = window.Window;
68                         MainWindow.Show();
69                         if (window.BaseConformant != null)
70                         {
71                                 window.BaseConformant.Show();
72                         }
73
74                         BaseLayout = window.BaseLayout;
75                         BaseLayout.Show();
76
77                         BaseCircleSurface = window.BaseCircleSurface;
78                         Forms.CircleSurface = BaseCircleSurface;
79                 }
80
81                 protected override void OnTerminate()
82                 {
83                         base.OnTerminate();
84                         if (_platform != null)
85                         {
86                                 _platform.Dispose();
87                         }
88                 }
89
90                 protected override void OnAppControlReceived(AppControlReceivedEventArgs e)
91                 {
92                         base.OnAppControlReceived(e);
93
94                         if (!_isInitialStart && _application != null)
95                         {
96                                 _application.SendResume();
97                         }
98                         _isInitialStart = false;
99                 }
100
101                 protected override void OnPause()
102                 {
103                         base.OnPause();
104                         if (_application != null)
105                         {
106                                 _application.SendSleep();
107                         }
108                 }
109
110                 protected override void OnResume()
111                 {
112                         base.OnResume();
113                         if (_application != null)
114                         {
115                                 _application.SendResume();
116                         }
117                 }
118
119                 [EditorBrowsable(EditorBrowsableState.Never)]
120                 public static Func<Task> RequestingUserConsentFunc { get; set; } = null;
121
122                 public async void LoadApplication(Application application)
123                 {
124                         if (RequestingUserConsentFunc != null)
125                         {
126                                 await RequestingUserConsentFunc();
127                         }
128
129                         if (null == MainWindow)
130                         {
131                                 throw new InvalidOperationException("MainWindow is not prepared. This method should be called in OnCreated().");
132                         }
133
134                         if (null == application)
135                         {
136                                 throw new ArgumentNullException(nameof(application));
137                         }
138                         _application = application;
139                         Application.Current = application;
140                         application.SendStart();
141                         application.PropertyChanged += new PropertyChangedEventHandler(this.AppOnPropertyChanged);
142                         SetPage(_application.MainPage);
143                         if (Device.Idiom == TargetIdiom.Watch)
144                         {
145                                 _useBezelInteration = Specific.GetUseBezelInteraction(_application);
146                                 UpdateOverlayContent();
147                         }
148                 }
149
150                 void AppOnPropertyChanged(object sender, PropertyChangedEventArgs args)
151                 {
152                         if ("MainPage" == args.PropertyName)
153                         {
154                                 SetPage(_application.MainPage);
155                         }
156                         else if (Device.Idiom == TargetIdiom.Watch)
157                         {
158                                 if (Specific.UseBezelInteractionProperty.PropertyName == args.PropertyName)
159                                 {
160                                         _useBezelInteration = Specific.GetUseBezelInteraction(_application);
161                                 }
162                                 else if (Specific.OverlayContentProperty.PropertyName == args.PropertyName)
163                                 {
164                                         UpdateOverlayContent();
165                                 }
166                         }
167                 }
168
169                 void UpdateOverlayContent()
170                 {
171                         EvasObject nativeView = null;
172                         var content = Specific.GetOverlayContent(_application);
173                         if(content != null)
174                         {
175                                 var renderer = Platform.GetOrCreateRenderer(content);
176                         (renderer as LayoutRenderer)?.RegisterOnLayoutUpdated();
177                                 nativeView = renderer?.NativeView;
178                         }
179                         Forms.BaseLayout.SetPartContent("elm.swallow.overlay", nativeView);
180                 }
181
182                 void SetPage(Page page)
183                 {
184                         if (!Forms.IsInitialized)
185                         {
186                                 throw new InvalidOperationException("Call Forms.Init (UIApplication) before this");
187                         }
188
189 #pragma warning disable CS0618 // Type or member is obsolete
190                         // The Platform property is no longer necessary, but we have to set it because some third-party
191                         // library might still be retrieving it and using it
192                         if (_application != null)
193                         {
194                                 _application.Platform = _platform;
195                         }
196 #pragma warning restore CS0618 // Type or member is obsolete
197
198                         _platform.HasAlpha = MainWindow.Alpha;
199                         _platform.SetPage(page);
200
201                         Device.BeginInvokeOnMainThread(() => Native.NativeFactory.DeleteUnusedNative());
202                         Device.BeginInvokeOnMainThread(() => CircularUI.Renderer.NativeFactory.DeleteUnusedNative());
203                 }
204
205                 void InitializeWindow()
206                 {
207                         Debug.Assert(MainWindow != null, "Window cannot be null");
208
209                         MainWindow.Active();
210                         MainWindow.Show();
211
212                         // in case of no use of preloaded window
213                         if (BaseLayout == null)
214                         {
215                                 var conformant = new Conformant(MainWindow);
216                                 conformant.Show();
217
218                                 var layout = new ELayout(conformant);
219                                 layout.SetTheme("layout", "application", "default");
220                                 layout.Show();
221
222                                 BaseLayout = layout;
223
224                                 if (Device.Idiom == TargetIdiom.Watch)
225                                 {
226                                         BaseCircleSurface = new CircleSurface(conformant);
227                                         Forms.CircleSurface = BaseCircleSurface;
228                                 }
229                                 conformant.SetContent(BaseLayout);
230                         }
231
232                         MainWindow.AvailableRotations = DisplayRotation.Degree_0 | DisplayRotation.Degree_90 | DisplayRotation.Degree_180 | DisplayRotation.Degree_270;
233
234                         MainWindow.Deleted += (s, e) =>
235                         {
236                                 Exit();
237                         };
238
239                         Device.Info.CurrentOrientation = MainWindow.GetDeviceOrientation();
240
241                         MainWindow.RotationChanged += (sender, e) =>
242                         {
243                                 Device.Info.CurrentOrientation = MainWindow.GetDeviceOrientation();
244                         };
245
246                         MainWindow.BackButtonPressed += (sender, e) =>
247                         {
248                                 if (_platform != null)
249                                 {
250                                         if (!_platform.SendBackButtonPressed())
251                                         {
252                                                 Exit();
253                                         }
254                                 }
255                         };
256
257                         _platform = Platform.CreatePlatform(BaseLayout);
258                         BaseLayout.SetContent(_platform.GetRootNativeView());
259                         _platform.RootNativeViewChanged += (s, e) => BaseLayout.SetContent(e.RootNativeView);
260                 }
261
262                 public void Run()
263                 {
264                         Run(System.Environment.GetCommandLineArgs());
265                 }
266
267                 /// <summary>
268                 /// Exits the application's main loop, which initiates the process of its termination
269                 /// </summary>
270                 public override void Exit()
271                 {
272                         if (_platform == null)
273                         {
274                                 Log.Warn("Exit was already called or FormsApplication is not initialized yet.");
275                                 return;
276                         }
277                         try
278                         {
279                                 _platform.Dispose();
280                                 _platform = null;
281                         }
282                         catch (Exception e)
283                         {
284                                 Log.Error("Exception thrown from Dispose: {0}", e.Message);
285                         }
286
287                         base.Exit();
288                 }
289         }
290         static class WindowExtension
291         {
292                 public static DeviceOrientation GetDeviceOrientation(this Window window)
293                 {
294                         DeviceOrientation orientation = DeviceOrientation.Other;
295                         var isPortraitDevice = Forms.NaturalOrientation.IsPortrait();
296                         switch (window.Rotation)
297                         {
298                                 case 0:
299                                 case 180:
300                                         orientation = isPortraitDevice ? DeviceOrientation.Portrait : DeviceOrientation.Landscape;
301                                         break;
302
303                                 case 90:
304                                 case 270:
305                                         orientation = isPortraitDevice ? DeviceOrientation.Landscape : DeviceOrientation.Portrait;
306                                         break;
307                         }
308                         return orientation;
309                 }
310         }
311 }