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