Release 4.0.0-preview1-00051
[platform/core/csapi/tizenfx.git] / src / Tizen.Applications.WidgetControl / Tizen.Applications / WidgetControl.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.Collections.Generic;
19 using Tizen.Applications;
20
21 namespace Tizen.Applications
22 {
23     /// <summary>
24     /// The class for receiving widget events and sending data to the widget.
25     /// </summary>
26     public class WidgetControl : IDisposable
27     {
28         /// <summary>
29         /// Class for the widget instance.
30         /// </summary>
31         public class Instance
32         {
33             private string _widgetId;
34
35             internal Instance(string widgetId)
36             {
37                 _widgetId = widgetId;
38             }
39
40             /// <summary>
41             /// The widget ID.
42             /// </summary>
43             /// <since_tizen> 3 </since_tizen>
44             public string Id { get; internal set; }
45
46             /// <summary>
47             /// Gets the widget content.
48             /// </summary>
49             /// <since_tizen> 3 </since_tizen>
50             /// <exception cref="InvalidOperationException">Thrown in case of failed conditions.</exception>
51             public Bundle GetContent()
52             {
53                 IntPtr h;
54
55                 Interop.WidgetService.ErrorCode err = Interop.WidgetService.GetContent(_widgetId, Id, out h);
56
57                 switch (err)
58                 {
59                     case Interop.WidgetService.ErrorCode.InvalidParameter:
60                         throw new InvalidOperationException("Invalid parameter at unmanaged code");
61
62                     case Interop.WidgetService.ErrorCode.IoError:
63                         throw new InvalidOperationException("Failed to access DB");
64                 }
65
66                 return new Bundle(new SafeBundleHandle(h, true));
67             }
68
69             /// <summary>
70             /// Changes the content for the widget instance.
71             /// </summary>
72             /// <since_tizen> 3 </since_tizen>
73             /// <param name="content">Content to be changed.</param>
74             /// <param name="force"> True if you want to update your widget even if the provider is paused, otherwise false.</param>
75             /// <exception cref="ArgumentException">Thrown when failed because of an invalid argument.</exception>
76             /// <exception cref="InvalidOperationException">Thrown in case of failed conditions.</exception>
77             /// <exception cref="UnauthorizedAccessException">Thrown when an application does not have the privilege to access this method.</exception>
78             public void ChangeContent(Bundle content, bool force)
79             {
80                 Interop.WidgetService.ErrorCode err = Interop.WidgetService.UpdateContent(_widgetId, Id, content.SafeBundleHandle, force ? 1 : 0);
81
82                 switch (err)
83                 {
84                     case Interop.WidgetService.ErrorCode.InvalidParameter:
85                         throw new ArgumentException("Invalid parameter");
86
87                     case Interop.WidgetService.ErrorCode.Canceled:
88                         throw new InvalidOperationException("Provider is paused, so this update request is canceld");
89
90                     case Interop.WidgetService.ErrorCode.OutOfMemory:
91                         throw new InvalidOperationException("Out-of-memory at unmanaged code");
92
93                     case Interop.WidgetService.ErrorCode.Fault:
94                         throw new InvalidOperationException("Failed to create a request packet");
95
96                     case Interop.WidgetService.ErrorCode.PermissionDenied:
97                         throw new UnauthorizedAccessException();
98                 }
99             }
100
101             /// <summary>
102             /// Changes the update period for the widget instance.
103             /// </summary>
104             /// <since_tizen> 3 </since_tizen>
105             /// <exception cref="ArgumentException">Thrown when failed because of an invalid argument.</exception>
106             /// <exception cref="InvalidOperationException">Thrown in case of failed conditions.</exception>
107             /// <exception cref="UnauthorizedAccessException">Thrown when an application does not have the privilege to access this method.</exception>
108             public void ChangePeriod(double period)
109             {
110                 Interop.WidgetService.ErrorCode err = Interop.WidgetService.ChangePeriod(_widgetId, Id, period);
111
112                 switch (err)
113                 {
114                     case Interop.WidgetService.ErrorCode.InvalidParameter:
115                         throw new ArgumentException("Invalid parameter");
116
117                     case Interop.WidgetService.ErrorCode.OutOfMemory:
118                         throw new InvalidOperationException("Out-of-memory at unmanaged code");
119
120                     case Interop.WidgetService.ErrorCode.Fault:
121                         throw new InvalidOperationException("Failed to create a request packet");
122
123                     case Interop.WidgetService.ErrorCode.PermissionDenied:
124                         throw new UnauthorizedAccessException();
125                 }
126             }
127         }
128
129         /// <summary>
130         /// The class for the widget size information.
131         /// </summary>
132         public class Scale
133         {
134
135             internal Scale()
136             {
137             }
138
139             /// <summary>
140             /// Enumeration for the types of widget size.
141             /// </summary>
142             /// <since_tizen> 3 </since_tizen>
143             public enum SizeType : int
144             {
145                 /// <summary>
146                 /// 175x175 based on 720x1280 resolution.
147                 /// </summary>
148                 Basic1x1 = 0x0001,
149
150                 /// <summary>
151                 /// 354x175 based on 720x1280 resolution.
152                 /// </summary>
153                 Basic2x1 = 0x0002,
154
155                 /// <summary>
156                 /// 354x354 based on 720x1280 resolution.
157                 /// </summary>
158                 Basic2x2 = 0x0004,
159
160                 /// <summary>
161                 /// 712x175 based on 720x1280 resolution.
162                 /// </summary>
163                 Basic4x1 = 0x0008,
164
165                 /// <summary>
166                 /// 712x354 based on 720x1280 resolution.
167                 /// </summary>
168                 Basic4x2 = 0x0010,
169
170                 /// <summary>
171                 /// 712x533 based on 720x1280 resolution.
172                 /// </summary>
173                 Basic4x3 = 0x0020,
174
175                 /// <summary>
176                 /// 712x712 based on 720x1280 resolution.
177                 /// </summary>
178                 Basic4x4 = 0x0040,
179
180                 /// <summary>
181                 /// 712x891 based on 720x1280 resolution.
182                 /// </summary>
183                 Basic4x5 = 0x0080,
184
185                 /// <summary>
186                 /// 712x1070 based on 720x1280 resolution.
187                 /// </summary>
188                 Basic4x6 = 0x0100,
189
190
191                 /// <summary>
192                 /// 224x215 based on 720x1280 resolution.
193                 /// </summary>
194                 Easy1x1 = 0x1000,
195
196                 /// <summary>
197                 /// 680x215 based on 720x1280 resolution.
198                 /// </summary>
199                 Easy1x2 = 0x2000,
200
201                 /// <summary>
202                 /// 680x653 based on 720x1280 resolution.
203                 /// </summary>
204                 Easy1x3 = 0x4000,
205
206                 /// <summary>
207                 /// 720x1280 based on 720x1280 resolution.
208                 /// </summary>
209                 Full = 0x0800,
210             }
211
212             /// <summary>
213             /// Widget width.
214             /// </summary>
215             /// <since_tizen> 3 </since_tizen>
216             public int Width { get; internal set; }
217
218             /// <summary>
219             ///Widget height.
220             /// </summary>
221             /// <since_tizen> 3 </since_tizen>
222             public int Height { get; internal set; }
223
224             /// <summary>
225             /// The path for the widget preview image file.
226             /// </summary>
227             /// <since_tizen> 3 </since_tizen>
228             public string PreviewImagePath { get; internal set; }
229
230             /// <summary>
231             /// The size type of the widget.
232             /// </summary>
233             /// <since_tizen> 3 </since_tizen>
234             public SizeType Type { get; internal set; }
235         }
236
237         private event EventHandler<WidgetLifecycleEventArgs> _created;
238         private event EventHandler<WidgetLifecycleEventArgs> _resumed;
239         private event EventHandler<WidgetLifecycleEventArgs> _paused;
240         private event EventHandler<WidgetLifecycleEventArgs> _destroyed;
241         private bool _disposedValue = false;
242         private static IDictionary<string, int> s_lifecycleEventRefCnt = new Dictionary<string, int>();
243         private static IList<WidgetControl> s_eventObjects = new List<WidgetControl>();
244
245         /// <summary>
246         /// Factory method for the WidgetControl.
247         /// It will create all the objects of WidgetControl based on the package ID.
248         /// </summary>
249         /// <since_tizen> 3 </since_tizen>
250         /// <param name="pkgId">Package ID.</param>
251         /// <privilege>http://tizen.org/privilege/widget.viewer</privilege>
252         /// <exception cref="ArgumentException">Thrown when failed because of an invalid argument.</exception>
253         /// <exception cref="InvalidOperationException">Thrown in case of failed conditions.</exception>
254         /// <exception cref="UnauthorizedAccessException">Thrown when an application does not have the privilege to access this method.</exception>
255         public static WidgetControl[] CreateAll(string pkgId)
256         {
257             List<WidgetControl> list = new List<WidgetControl>();
258
259             Interop.WidgetService.ErrorCode err = Interop.WidgetService.GetWidgetListByPkgId(pkgId, (widgetId, isPrime, userData) =>
260             {
261                 list.Add(new WidgetControl(widgetId));
262             }, IntPtr.Zero);
263
264             switch (err)
265             {
266                 case Interop.WidgetService.ErrorCode.InvalidParameter:
267                     throw new ArgumentException("Invalid parameter");
268
269                 case Interop.WidgetService.ErrorCode.IoError:
270                     throw new InvalidOperationException("Failed to access DB");
271
272                 case Interop.WidgetService.ErrorCode.PermissionDenied:
273                     throw new UnauthorizedAccessException();
274             }
275
276             return list.ToArray();
277         }
278
279         /// <summary>
280         /// Gets all the widget IDs by the package ID.
281         /// </summary>
282         /// <since_tizen> 3 </since_tizen>
283         /// <privilege>http://tizen.org/privilege/widget.viewer</privilege>
284         /// <exception cref="ArgumentException">Thrown when failed because of an invalid argument.</exception>
285         /// <exception cref="InvalidOperationException">Thrown in case of failed conditions.</exception>
286         /// <exception cref="UnauthorizedAccessException">Thrown when an application does not have the privilege to access this method.</exception>
287         public static string[] GetWidgetIds(string pkgId)
288         {
289             List<string> list = new List<string>();
290
291             Interop.WidgetService.ErrorCode err = Interop.WidgetService.GetWidgetListByPkgId(pkgId, (widgetId, isPrime, userData) =>
292             {
293                 list.Add(widgetId);
294             }, IntPtr.Zero);
295
296             switch (err)
297             {
298                 case Interop.WidgetService.ErrorCode.InvalidParameter:
299                     throw new ArgumentException("Invalid parameter");
300
301                 case Interop.WidgetService.ErrorCode.IoError:
302                     throw new InvalidOperationException("Failed to access DB");
303
304                 case Interop.WidgetService.ErrorCode.PermissionDenied:
305                     throw new UnauthorizedAccessException();
306             }
307
308             return list.ToArray();
309         }
310
311         /// <summary>
312         /// The widget ID.
313         /// </summary>
314         /// <since_tizen> 3 </since_tizen>
315         public string Id { get; internal set; }
316
317         /// <summary>
318         /// The flag value for "nodisplay".
319         /// </summary>
320         /// <since_tizen> 3 </since_tizen>
321         /// <privilege>http://tizen.org/privilege/widget.viewer</privilege>
322         public bool IsNoDisplay
323         {
324             get
325             {
326                 if (Interop.WidgetService.GetNoDisplay(Id) != 0)
327                     return true;
328
329                 return false;
330             }
331         }
332
333         /// <summary>
334         ///  The event handler for a created widget instance.
335         /// </summary>
336         /// <since_tizen> 3 </since_tizen>
337         /// <exception cref="InvalidOperationException">Thrown in case of failed conditions.</exception>
338         /// <exception cref="UnauthorizedAccessException">Thrown when an application does not have the privilege to access this method.</exception>
339         public event EventHandler<WidgetLifecycleEventArgs> Created
340         {
341             add
342             {
343                 RegisterLifecycleEvent();
344                 _created += value;
345             }
346             remove
347             {
348                 _created -= value;
349                 UnregisterLifecycleEvent();
350             }
351         }
352
353         /// <summary>
354         /// The event handler for a resumed widget instance.
355         /// </summary>
356         /// <since_tizen> 3 </since_tizen>
357         /// <exception cref="InvalidOperationException">Thrown in case of failed conditions.</exception>
358         /// <exception cref="UnauthorizedAccessException">Thrown when an application does not have the privilege to access this method.</exception>
359         public event EventHandler<WidgetLifecycleEventArgs> Resumed
360         {
361             add
362             {
363                 RegisterLifecycleEvent();
364                 _resumed += value;
365             }
366             remove
367             {
368                 _resumed -= value;
369                 UnregisterLifecycleEvent();
370             }
371         }
372
373         /// <summary>
374         /// The event handler for a paused widget instance.
375         /// </summary>
376         /// <since_tizen> 3 </since_tizen>
377         /// <exception cref="InvalidOperationException">Thrown in case of failed conditions.</exception>
378         /// <exception cref="UnauthorizedAccessException">Thrown when an application does not have the privilege to access this method.</exception>
379         public event EventHandler<WidgetLifecycleEventArgs> Paused
380         {
381             add
382             {
383                 RegisterLifecycleEvent();
384                 _paused += value;
385             }
386             remove
387             {
388                 _paused -= value;
389                 UnregisterLifecycleEvent();
390             }
391         }
392
393         /// <summary>
394         /// The event handler for a destroyed widget instance.
395         /// </summary>
396         /// <since_tizen> 3 </since_tizen>
397         /// <exception cref="InvalidOperationException">Thrown in case of failed conditions.</exception>
398         /// <exception cref="UnauthorizedAccessException">Thrown when an application does not have the privilege to access this method.</exception>
399         public event EventHandler<WidgetLifecycleEventArgs> Destroyed
400         {
401             add
402             {
403                 RegisterLifecycleEvent();
404                 _destroyed += value;
405             }
406             remove
407             {
408                 _destroyed -= value;
409                 UnregisterLifecycleEvent();
410             }
411         }
412
413         /// <summary>
414         /// The constructor of the WidgetControl object.
415         /// </summary>
416         /// <since_tizen> 3 </since_tizen>
417         /// <param name="widgetId">Widget ID.</param>
418         public WidgetControl(string widgetId)
419         {
420             Id = widgetId;
421         }
422
423         /// <summary>
424         /// Finalizer of the WidgetControl class.
425         /// </summary>
426         ~WidgetControl()
427         {
428             Dispose(false);
429         }
430
431         /// <summary>
432         /// Gets the objects for widget instance information.
433         /// </summary>
434         /// <since_tizen> 3 </since_tizen>
435         /// <exception cref="InvalidOperationException">Thrown in case of failed conditions.</exception>
436         /// <exception cref="NotSupportedException">Thrown when the API is not supported in this device.</exception>
437         /// <exception cref="UnauthorizedAccessException">Thrown when an application does not have the privilege to access this method.</exception>
438         public IEnumerable<Instance> GetInstances()
439         {
440             IList<Instance> instances = new List<Instance>();
441             Interop.WidgetService.ErrorCode err = Interop.WidgetService.GetInstances(Id, (widgetId, instanceId, userData) =>
442             {
443                 instances.Add(new Instance(widgetId) { Id = instanceId });
444             }, IntPtr.Zero);
445
446             switch (err)
447             {
448                 case Interop.WidgetService.ErrorCode.InvalidParameter:
449                     throw new InvalidOperationException("Invalid parameter at unmanaged code");
450
451                 case Interop.WidgetService.ErrorCode.NotSupported:
452                     throw new NotSupportedException();
453
454                 case Interop.WidgetService.ErrorCode.PermissionDenied:
455                     throw new UnauthorizedAccessException();
456             }
457
458             return instances;
459         }
460
461         /// <summary>
462         /// Gets the objects for widget scale information.
463         /// </summary>
464         /// <since_tizen> 3 </since_tizen>
465         /// <privilege>http://tizen.org/privilege/widget.viewer</privilege>
466         /// <exception cref="InvalidOperationException">Thrown in case of failed conditions.</exception>
467         /// <exception cref="UnauthorizedAccessException">Thrown when an application does not have the privilege to access this method.</exception>
468         public IEnumerable<Scale> GetScales()
469         {
470             int[] w = new int[100];
471             int[] h = new int[100];
472             int[] types = new int[100];
473             int cnt1 = 100;
474             int cnt2 = 100;
475             IList<Scale> scales = new List<Scale>();
476
477             Interop.WidgetService.ErrorCode err = Interop.WidgetService.GetSupportedSizes(Id, ref cnt1, out w, out h);
478
479             switch (err)
480             {
481                 case Interop.WidgetService.ErrorCode.InvalidParameter:
482                     throw new InvalidOperationException("Invalid parameter at unmanaged code");
483
484                 case Interop.WidgetService.ErrorCode.IoError:
485                     throw new InvalidOperationException("Failed to access DB");
486
487                 case Interop.WidgetService.ErrorCode.PermissionDenied:
488                     throw new UnauthorizedAccessException();
489             }
490
491             err = Interop.WidgetService.GetSupportedSizeTypes(Id, ref cnt2, out types);
492
493             switch (err)
494             {
495                 case Interop.WidgetService.ErrorCode.InvalidParameter:
496                     throw new InvalidOperationException("Invalid parameter at unmanaged code");
497
498                 case Interop.WidgetService.ErrorCode.IoError:
499                     throw new InvalidOperationException("Failed to access DB");
500
501                 case Interop.WidgetService.ErrorCode.PermissionDenied:
502                     throw new UnauthorizedAccessException();
503             }
504
505             if (cnt1 != cnt2)
506                 return null;
507
508             for (int i = 0; i < cnt1; i++)
509             {
510                 string prev = Interop.WidgetService.GetPreviewImagePath(Id, types[i]);
511
512                 scales.Add(new Scale()
513                 {
514                     Width = w[i],
515                     Height = h[i],
516                     PreviewImagePath = prev,
517                     Type = (Scale.SizeType)types[i]
518                 });
519             }
520             return scales;
521         }
522
523         /// <summary>
524         /// Gets the widget name.
525         /// </summary>
526         /// <since_tizen> 3 </since_tizen>
527         /// <param name="lang">Language.</param>
528         /// <privilege>http://tizen.org/privilege/widget.viewer</privilege>
529         /// <exception cref="ArgumentNullException">Thrown when the argument is null.</exception>
530         public string GetName(string lang)
531         {
532             if (lang == null)
533                 throw new ArgumentNullException();
534
535             return Interop.WidgetService.GetName(Id, lang);
536         }
537
538         /// <summary>
539         /// Gets the widget icon path.
540         /// </summary>
541         /// <since_tizen> 3 </since_tizen>
542         /// <param name="lang">Language.</param>
543         /// <privilege>http://tizen.org/privilege/widget.viewer</privilege>
544         /// <exception cref="ArgumentNullException">Thrown when the argument is null.</exception>
545         public string GetIconPath(string lang)
546         {
547             if (lang == null)
548                 throw new ArgumentNullException();
549
550             string pkgId = Interop.WidgetService.GetPkgId(Id);
551
552             return Interop.WidgetService.GetIcon(pkgId, lang);
553         }
554
555         /// <summary>
556         /// Releases all the resources used by the WidgetControl class.
557         /// </summary>
558         /// <since_tizen> 3 </since_tizen>
559         public void Dispose()
560         {
561             Dispose(true);
562             GC.SuppressFinalize(this);
563         }
564
565         private void Dispose(bool disposing)
566         {
567             if (!_disposedValue)
568             {
569                 if (disposing)
570                 {
571                 }
572
573                 _created = null;
574                 _resumed = null;
575                 _paused = null;
576                 _destroyed = null;
577                 UnregisterLifecycleEvent();
578
579                 _disposedValue = true;
580             }
581         }
582
583         private void RegisterLifecycleEvent()
584         {
585             if (!s_lifecycleEventRefCnt.ContainsKey(Id))
586                 s_lifecycleEventRefCnt[Id] = 0;
587
588             if (_created != null || _paused != null || _resumed != null || _destroyed != null)
589                 return;
590
591             if (s_lifecycleEventRefCnt[Id] == 0)
592             {
593                 Interop.WidgetService.ErrorCode err = Interop.WidgetService.SetLifecycleEvent(Id, OnLifecycleEvent, IntPtr.Zero);
594
595                 switch (err)
596                 {
597                     case Interop.WidgetService.ErrorCode.InvalidParameter:
598                         throw new InvalidOperationException("Invalid parameter at unmanaged code");
599
600                     case Interop.WidgetService.ErrorCode.PermissionDenied:
601                         throw new UnauthorizedAccessException();
602                 }
603             }
604
605             s_lifecycleEventRefCnt[Id]++;
606             s_eventObjects.Add(this);
607         }
608
609         private void UnregisterLifecycleEvent()
610         {
611             if (!s_lifecycleEventRefCnt.ContainsKey(Id))
612                 return;
613
614             if (s_lifecycleEventRefCnt[Id] <= 0)
615                 return;
616
617             if (_created != null || _paused != null || _resumed != null || _destroyed != null)
618                 return;
619
620             if (s_lifecycleEventRefCnt[Id] == 1)
621             {
622                 Interop.WidgetService.ErrorCode err = Interop.WidgetService.UnsetLifecycleEvent(Id, IntPtr.Zero);
623
624                 switch (err)
625                 {
626                     case Interop.WidgetService.ErrorCode.InvalidParameter:
627                         throw new InvalidOperationException("Invalid parameter at unmanaged code");
628
629                     case Interop.WidgetService.ErrorCode.PermissionDenied:
630                         throw new UnauthorizedAccessException();
631
632                     case Interop.WidgetService.ErrorCode.NotExist:
633                         throw new InvalidOperationException("Event handler is not exist");
634                 }
635             }
636
637             s_eventObjects.Remove(this);
638             s_lifecycleEventRefCnt[Id]--;
639         }
640
641         private static void OnLifecycleEvent(string widgetId, Interop.WidgetService.LifecycleEvent e, string instanceId, IntPtr userData)
642         {
643             switch (e)
644             {
645                 case Interop.WidgetService.LifecycleEvent.Created:
646                     foreach (WidgetControl c in s_eventObjects)
647                     {
648                         if (c.Id.CompareTo(widgetId) == 0)
649                         {
650                             c._created?.Invoke(null, new WidgetLifecycleEventArgs()
651                             {
652                                 WidgetId = widgetId,
653                                 InstanceId = instanceId,
654                                 Type = WidgetLifecycleEventArgs.EventType.Created
655                             });
656                         }
657                     }
658                     break;
659
660                 case Interop.WidgetService.LifecycleEvent.Resumed:
661                     foreach (WidgetControl c in s_eventObjects)
662                     {
663                         if (c.Id.CompareTo(widgetId) == 0)
664                         {
665                             c._resumed?.Invoke(null, new WidgetLifecycleEventArgs()
666                             {
667                                 WidgetId = widgetId,
668                                 InstanceId = instanceId,
669                                 Type = WidgetLifecycleEventArgs.EventType.Resumed
670                             });
671                        }
672                     }
673                     break;
674
675                 case Interop.WidgetService.LifecycleEvent.Paused:
676                     foreach (WidgetControl c in s_eventObjects)
677                     {
678                         if (c.Id.CompareTo(widgetId) == 0)
679                         {
680                             c._paused?.Invoke(null, new WidgetLifecycleEventArgs()
681                             {
682                                 WidgetId = widgetId,
683                                 InstanceId = instanceId,
684                                 Type = WidgetLifecycleEventArgs.EventType.Paused
685                             });
686                         }
687                     }
688                     break;
689
690                 case Interop.WidgetService.LifecycleEvent.Destroyed:
691                     foreach (WidgetControl c in s_eventObjects)
692                     {
693                         if (c.Id.CompareTo(widgetId) == 0)
694                         {
695                             c._destroyed?.Invoke(null, new WidgetLifecycleEventArgs()
696                             {
697                                 WidgetId = widgetId,
698                                 InstanceId = instanceId,
699                                 Type = WidgetLifecycleEventArgs.EventType.Destroyed
700                             });
701                         }
702                     }
703                     break;
704             }
705
706         }
707     }
708 }