[Applications.Common] Add missing application APIs (#547)
[platform/core/csapi/tizenfx.git] / src / Tizen.Applications.Common / Tizen.Applications / CoreApplication.cs
1 /*
2  * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  * Licensed under the Apache License, Version 2.0 (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://www.apache.org/licenses/LICENSE-2.0
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 System;
18 using System.Globalization;
19 using System.Text;
20 using Tizen.Applications.CoreBackend;
21
22 namespace Tizen.Applications
23 {
24     /// <summary>
25     /// This class represents an application controlled lifecycles by the backend system.
26     /// </summary>
27     /// <since_tizen> 3 </since_tizen>
28     public class CoreApplication : Application
29     {
30         private readonly ICoreBackend _backend;
31         private bool _disposedValue = false;
32
33         /// <summary>
34         /// Initializes the CoreApplication class.
35         /// </summary>
36         /// <param name="backend">The backend instance implementing ICoreBacked interface.</param>
37         /// <since_tizen> 3 </since_tizen>
38         public CoreApplication(ICoreBackend backend)
39         {
40             _backend = backend;
41         }
42
43         /// <summary>
44         /// Occurs when the application is launched.
45         /// </summary>
46         /// <since_tizen> 3 </since_tizen>
47         public event EventHandler Created;
48
49         /// <summary>
50         /// Occurs when the application is about to shutdown.
51         /// </summary>
52         /// <since_tizen> 3 </since_tizen>
53         public event EventHandler Terminated;
54
55         /// <summary>
56         /// Occurs whenever the application receives the appcontrol message.
57         /// </summary>
58         /// <since_tizen> 3 </since_tizen>
59         public event EventHandler<AppControlReceivedEventArgs> AppControlReceived;
60
61         /// <summary>
62         /// Occurs when the system memory is low.
63         /// </summary>
64         /// <since_tizen> 3 </since_tizen>
65         public event EventHandler<LowMemoryEventArgs> LowMemory;
66
67         /// <summary>
68         /// Occurs when the system battery is low.
69         /// </summary>
70         /// <since_tizen> 3 </since_tizen>
71         public event EventHandler<LowBatteryEventArgs> LowBattery;
72
73         /// <summary>
74         /// Occurs when the system language is chagned.
75         /// </summary>
76         /// <since_tizen> 3 </since_tizen>
77         public event EventHandler<LocaleChangedEventArgs> LocaleChanged;
78
79         /// <summary>
80         /// Occurs when the region format is changed.
81         /// </summary>
82         /// <since_tizen> 3 </since_tizen>
83         public event EventHandler<RegionFormatChangedEventArgs> RegionFormatChanged;
84
85         /// <summary>
86         /// Occurs when the device orientation is changed.
87         /// </summary>
88         /// <since_tizen> 3 </since_tizen>
89         public event EventHandler<DeviceOrientationEventArgs> DeviceOrientationChanged;
90
91         /// <summary>
92         /// The backend instance.
93         /// </summary>
94         /// <since_tizen> 3 </since_tizen>
95         protected ICoreBackend Backend { get { return _backend; } }
96
97         /// <summary>
98         /// Runs the application's main loop.
99         /// </summary>
100         /// <param name="args">Arguments from commandline.</param>
101         /// <since_tizen> 3 </since_tizen>
102         public override void Run(string[] args)
103         {
104             base.Run(args);
105
106             _backend.AddEventHandler(EventType.Created, OnCreate);
107             _backend.AddEventHandler(EventType.Terminated, OnTerminate);
108             _backend.AddEventHandler<AppControlReceivedEventArgs>(EventType.AppControlReceived, OnAppControlReceived);
109             _backend.AddEventHandler<LowMemoryEventArgs>(EventType.LowMemory, OnLowMemory);
110             _backend.AddEventHandler<LowBatteryEventArgs>(EventType.LowBattery, OnLowBattery);
111             _backend.AddEventHandler<LocaleChangedEventArgs>(EventType.LocaleChanged, OnLocaleChanged);
112             _backend.AddEventHandler<RegionFormatChangedEventArgs>(EventType.RegionFormatChanged, OnRegionFormatChanged);
113             _backend.AddEventHandler<DeviceOrientationEventArgs>(EventType.DeviceOrientationChanged, OnDeviceOrientationChanged);
114
115             string[] argsClone = null;
116
117             if (args == null)
118             {
119                 argsClone = new string[1];
120             }
121             else
122             {
123                 argsClone = new string[args.Length + 1];
124                 args.CopyTo(argsClone, 1);
125             }
126             argsClone[0] = string.Empty;
127             _backend.Run(argsClone);
128         }
129
130         /// <summary>
131         /// Exits the main loop of the application.
132         /// </summary>
133         /// <since_tizen> 3 </since_tizen>
134         public override void Exit()
135         {
136             _backend.Exit();
137         }
138
139         /// <summary>
140         /// Overrides this method if want to handle behavior when the application is launched.
141         /// If base.OnCreated() is not called, the event 'Created' will not be emitted.
142         /// </summary>
143         /// <since_tizen> 3 </since_tizen>
144         protected virtual void OnCreate()
145         {
146             Created?.Invoke(this, EventArgs.Empty);
147         }
148
149         /// <summary>
150         /// Overrides this method if want to handle behavior when the application is terminated.
151         /// If base.OnTerminate() is not called, the event 'Terminated' will not be emitted.
152         /// </summary>
153         /// <since_tizen> 3 </since_tizen>
154         protected virtual void OnTerminate()
155         {
156             Terminated?.Invoke(this, EventArgs.Empty);
157         }
158
159         /// <summary>
160         /// Overrides this method if want to handle behavior when the application receives the appcontrol message.
161         /// If base.OnAppControlReceived() is not called, the event 'AppControlReceived' will not be emitted.
162         /// </summary>
163         /// <param name="e"></param>
164         /// <since_tizen> 3 </since_tizen>
165         protected virtual void OnAppControlReceived(AppControlReceivedEventArgs e)
166         {
167             AppControlReceived?.Invoke(this, e);
168         }
169
170         /// <summary>
171         /// Overrides this method if want to handle behavior when the system memory is low.
172         /// If base.OnLowMemory() is not called, the event 'LowMemory' will not be emitted.
173         /// </summary>
174         /// <param name="e">The low memory event argument</param>
175         /// <since_tizen> 3 </since_tizen>
176         protected virtual void OnLowMemory(LowMemoryEventArgs e)
177         {
178             LowMemory?.Invoke(this, e);
179             System.GC.Collect();
180         }
181
182         /// <summary>
183         /// Overrides this method if want to handle behavior when the system battery is low.
184         /// If base.OnLowBattery() is not called, the event 'LowBattery' will not be emitted.
185         /// </summary>
186         /// <param name="e">The low battery event argument</param>
187         /// <since_tizen> 3 </since_tizen>
188         protected virtual void OnLowBattery(LowBatteryEventArgs e)
189         {
190             LowBattery?.Invoke(this, e);
191         }
192
193         /// <summary>
194         /// Overrides this method if want to handle behavior when the system language is changed.
195         /// If base.OnLocaleChanged() is not called, the event 'LocaleChanged' will not be emitted.
196         /// </summary>
197         /// <param name="e">The locale changed event argument</param>
198         /// <since_tizen> 3 </since_tizen>
199         protected virtual void OnLocaleChanged(LocaleChangedEventArgs e)
200         {
201             ChangeCurrentCultureInfo(e.Locale);
202             LocaleChanged?.Invoke(this, e);
203         }
204
205         /// <summary>
206         /// Overrides this method if want to handle behavior when the region format is changed.
207         /// If base.OnRegionFormatChanged() is not called, the event 'RegionFormatChanged' will not be emitted.
208         /// </summary>
209         /// <param name="e">The region format changed event argument</param>
210         /// <since_tizen> 3 </since_tizen>
211         protected virtual void OnRegionFormatChanged(RegionFormatChangedEventArgs e)
212         {
213             RegionFormatChanged?.Invoke(this, e);
214         }
215
216         /// <summary>
217         /// Overrides this method if want to handle behavior when the device orientation is changed.
218         /// If base.OnRegionFormatChanged() is not called, the event 'RegionFormatChanged' will not be emitted.
219         /// </summary>
220         /// <param name="e">The device orientation changed event argument</param>
221         /// <since_tizen> 3 </since_tizen>
222         protected virtual void OnDeviceOrientationChanged(DeviceOrientationEventArgs e)
223         {
224             DeviceOrientationChanged?.Invoke(this, e);
225         }
226
227         /// <summary>
228         /// Releases any unmanaged resources used by this object. Can also dispose any other disposable objects.
229         /// </summary>
230         /// <param name="disposing">If true, disposes any disposable objects. If false, does not dispose disposable objects.</param>
231         /// <since_tizen> 3 </since_tizen>
232         protected override void Dispose(bool disposing)
233         {
234             if (!_disposedValue)
235             {
236                 if (disposing)
237                 {
238                     _backend.Dispose();
239                 }
240
241                 _disposedValue = true;
242             }
243             base.Dispose(disposing);
244         }
245
246         private void ChangeCurrentCultureInfo(string locale)
247         {
248             ULocale pLocale = new ULocale(locale);
249             CultureInfo currentCultureInfo = null;
250
251             try
252             {
253                 currentCultureInfo = new CultureInfo(pLocale.Locale.Replace("_", "-"));
254             }
255             catch (CultureNotFoundException)
256             {
257                 currentCultureInfo = GetFallbackCultureInfo(pLocale);
258             }
259
260             CultureInfo.CurrentCulture = currentCultureInfo;
261         }
262
263         private CultureInfo GetCultureInfo(string locale)
264         {
265             CultureInfo cultureInfo = null;
266
267             try
268             {
269                 cultureInfo = new CultureInfo(locale);
270             }
271             catch (CultureNotFoundException)
272             {
273                 return null;
274             }
275
276             return cultureInfo;
277         }
278
279         private CultureInfo GetFallbackCultureInfo(ULocale uLocale)
280         {
281             string locale = string.Empty;
282             CultureInfo fallbackCultureInfo = null;
283
284             if (uLocale.Script != null && uLocale.Country != null)
285             {
286                 locale = uLocale.Language + "-" + uLocale.Script + "-" + uLocale.Country;
287                 fallbackCultureInfo = GetCultureInfo(locale);
288             }
289
290             if (fallbackCultureInfo == null && uLocale.Script != null)
291             {
292                 locale = uLocale.Language + "-" + uLocale.Script;
293                 fallbackCultureInfo = GetCultureInfo(locale);
294             }
295
296             if (fallbackCultureInfo == null && uLocale.Country != null)
297             {
298                 locale = uLocale.Language + "-" + uLocale.Country;
299                 fallbackCultureInfo = GetCultureInfo(locale);
300             }
301
302             if (fallbackCultureInfo == null)
303             {
304                 try
305                 {
306                     fallbackCultureInfo = new CultureInfo(uLocale.Language);
307                 }
308                 catch (CultureNotFoundException)
309                 {
310                     fallbackCultureInfo = new CultureInfo("en");
311                 }
312             }
313
314             return fallbackCultureInfo;
315         }
316     }
317
318     internal class ULocale
319     {
320         private const int ICU_ULOC_FULLNAME_CAPACITY = 157;
321         private const int ICU_ULOC_LANG_CAPACITY = 12;
322         private const int ICU_ULOC_SCRIPT_CAPACITY = 6;
323         private const int ICU_ULOC_COUNTRY_CAPACITY = 4;
324         private const int ICU_ULOC_VARIANT_CAPACITY = ICU_ULOC_FULLNAME_CAPACITY;
325         private const int ICU_U_ZERO_ERROR = 0;
326
327         internal ULocale(string locale)
328         {
329             Locale = Canonicalize(locale);
330             Language = GetLanguage(Locale);
331             Script = GetScript(Locale);
332             Country = GetCountry(Locale);
333             Variant = GetVariant(Locale);
334         }
335
336         internal string Locale { get; private set; }
337         internal string Language { get; private set; }
338         internal string Script { get; private set; }
339         internal string Country { get; private set; }
340         internal string Variant { get; private set; }
341
342         private string Canonicalize(string localeName)
343         {
344             int err = ICU_U_ZERO_ERROR;
345
346             // Get the locale name from ICU
347             StringBuilder sb = new StringBuilder(ICU_ULOC_FULLNAME_CAPACITY);
348             if (Interop.Icu.Canonicalize(localeName, sb, sb.Capacity, out err) <= 0)
349             {
350                 return null;
351             }
352
353             return sb.ToString();
354         }
355
356         private string GetLanguage(string locale)
357         {
358             int err = ICU_U_ZERO_ERROR;
359
360             // Get the language name from ICU
361             StringBuilder sb = new StringBuilder(ICU_ULOC_LANG_CAPACITY);
362             if (Interop.Icu.GetLanguage(locale, sb, sb.Capacity, out err) <= 0)
363             {
364                 return null;
365             }
366
367             return sb.ToString();
368         }
369
370         private string GetScript(string locale)
371         {
372             int err = ICU_U_ZERO_ERROR;
373
374             // Get the script name from ICU
375             StringBuilder sb = new StringBuilder(ICU_ULOC_SCRIPT_CAPACITY);
376             if (Interop.Icu.GetScript(locale, sb, sb.Capacity, out err) <= 0)
377             {
378                 return null;
379             }
380
381             return sb.ToString();
382         }
383
384         private string GetCountry(string locale)
385         {
386             int err = ICU_U_ZERO_ERROR;
387
388             // Get the country name from ICU
389             StringBuilder sb = new StringBuilder(ICU_ULOC_SCRIPT_CAPACITY);
390             if (Interop.Icu.GetCountry(locale, sb, sb.Capacity, out err) <= 0)
391             {
392                 return null;
393             }
394
395             return sb.ToString();
396         }
397
398         private string GetVariant(string locale)
399         {
400             int err = ICU_U_ZERO_ERROR;
401
402             // Get the variant name from ICU
403             StringBuilder sb = new StringBuilder(ICU_ULOC_VARIANT_CAPACITY);
404             if (Interop.Icu.GetVariant(locale, sb, sb.Capacity, out err) <= 0)
405             {
406                 return null;
407             }
408
409             return sb.ToString();
410         }
411     }
412 }