2 * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 using System.Collections.Generic;
19 using Tizen.Applications;
20 using System.Runtime.InteropServices;
22 namespace Tizen.Applications
25 /// The class for receiving widget events and sending data to the widget.
27 /// <since_tizen> 3 </since_tizen>
28 public class WidgetControl : IDisposable
30 private const string LogTag = "Tizen.Applications.WidgetControl";
32 /// Class for the widget instance.
34 /// <since_tizen> 3 </since_tizen>
37 private string _widgetId;
39 internal Instance(string widgetId)
47 /// <since_tizen> 3 </since_tizen>
48 public string Id { get; internal set; }
51 /// Gets the widget content.
53 /// <since_tizen> 3 </since_tizen>
54 /// <exception cref="InvalidOperationException">Thrown in case of failed conditions.</exception>
55 public Bundle GetContent()
59 Interop.WidgetService.ErrorCode err = Interop.WidgetService.GetContent(_widgetId, Id, out h);
63 case Interop.WidgetService.ErrorCode.InvalidParameter:
64 throw new InvalidOperationException("Invalid parameter at unmanaged code");
66 case Interop.WidgetService.ErrorCode.IoError:
67 throw new InvalidOperationException("Failed to access DB");
70 return new Bundle(new SafeBundleHandle(h, true));
74 /// Changes the content for the widget instance.
76 /// <since_tizen> 3 </since_tizen>
77 /// <param name="content">Content to be changed.</param>
78 /// <param name="force"> True if you want to update your widget even if the provider is paused, otherwise false.</param>
79 /// <exception cref="ArgumentException">Thrown when failed because of an invalid argument.</exception>
80 /// <exception cref="InvalidOperationException">Thrown in case of failed conditions.</exception>
81 /// <exception cref="UnauthorizedAccessException">Thrown when an application does not have the privilege to access this method.</exception>
82 public void ChangeContent(Bundle content, bool force)
84 Interop.WidgetService.ErrorCode err = Interop.WidgetService.UpdateContent(_widgetId, Id, content.SafeBundleHandle, force ? 1 : 0);
88 case Interop.WidgetService.ErrorCode.InvalidParameter:
89 throw new ArgumentException("Invalid parameter");
91 case Interop.WidgetService.ErrorCode.Canceled:
92 throw new InvalidOperationException("Provider is paused, so this update request is canceld");
94 case Interop.WidgetService.ErrorCode.OutOfMemory:
95 throw new InvalidOperationException("Out-of-memory at unmanaged code");
97 case Interop.WidgetService.ErrorCode.Fault:
98 throw new InvalidOperationException("Failed to create a request packet");
100 case Interop.WidgetService.ErrorCode.PermissionDenied:
101 throw new UnauthorizedAccessException();
106 /// Changes the update period for the widget instance.
108 /// <since_tizen> 3 </since_tizen>
109 /// <exception cref="ArgumentException">Thrown when failed because of an invalid argument.</exception>
110 /// <exception cref="InvalidOperationException">Thrown in case of failed conditions.</exception>
111 /// <exception cref="UnauthorizedAccessException">Thrown when an application does not have the privilege to access this method.</exception>
112 public void ChangePeriod(double period)
114 Interop.WidgetService.ErrorCode err = Interop.WidgetService.ChangePeriod(_widgetId, Id, period);
118 case Interop.WidgetService.ErrorCode.InvalidParameter:
119 throw new ArgumentException("Invalid parameter");
121 case Interop.WidgetService.ErrorCode.OutOfMemory:
122 throw new InvalidOperationException("Out-of-memory at unmanaged code");
124 case Interop.WidgetService.ErrorCode.Fault:
125 throw new InvalidOperationException("Failed to create a request packet");
127 case Interop.WidgetService.ErrorCode.PermissionDenied:
128 throw new UnauthorizedAccessException();
134 /// The class for the widget size information.
136 /// <since_tizen> 3 </since_tizen>
145 /// Enumeration for the types of widget size.
147 /// <since_tizen> 3 </since_tizen>
148 public enum SizeType : int
151 /// 175x175 based on 720x1280 resolution.
156 /// 354x175 based on 720x1280 resolution.
161 /// 354x354 based on 720x1280 resolution.
166 /// 712x175 based on 720x1280 resolution.
171 /// 712x354 based on 720x1280 resolution.
176 /// 712x533 based on 720x1280 resolution.
181 /// 712x712 based on 720x1280 resolution.
186 /// 712x891 based on 720x1280 resolution.
191 /// 712x1070 based on 720x1280 resolution.
197 /// 224x215 based on 720x1280 resolution.
202 /// 680x215 based on 720x1280 resolution.
207 /// 680x653 based on 720x1280 resolution.
212 /// 720x1280 based on 720x1280 resolution.
220 /// <since_tizen> 3 </since_tizen>
221 public int Width { get; internal set; }
226 /// <since_tizen> 3 </since_tizen>
227 public int Height { get; internal set; }
230 /// The path for the widget preview image file.
232 /// <since_tizen> 3 </since_tizen>
233 public string PreviewImagePath { get; internal set; }
236 /// The size type of the widget.
238 /// <since_tizen> 3 </since_tizen>
239 public SizeType Type { get; internal set; }
242 private event EventHandler<WidgetLifecycleEventArgs> _created;
243 private event EventHandler<WidgetLifecycleEventArgs> _resumed;
244 private event EventHandler<WidgetLifecycleEventArgs> _paused;
245 private event EventHandler<WidgetLifecycleEventArgs> _destroyed;
246 private bool _disposedValue = false;
247 private static IDictionary<string, int> s_lifecycleEventRefCnt = new Dictionary<string, int>();
248 private static IList<WidgetControl> s_eventObjects = new List<WidgetControl>();
251 /// Factory method for the WidgetControl.
252 /// It will create all the objects of WidgetControl based on the package ID.
254 /// <since_tizen> 3 </since_tizen>
255 /// <param name="pkgId">Package ID.</param>
256 /// <privilege>http://tizen.org/privilege/widget.viewer</privilege>
257 /// <exception cref="ArgumentException">Thrown when failed because of an invalid argument.</exception>
258 /// <exception cref="InvalidOperationException">Thrown in case of failed conditions.</exception>
259 /// <exception cref="UnauthorizedAccessException">Thrown when an application does not have the privilege to access this method.</exception>
260 public static WidgetControl[] CreateAll(string pkgId)
262 List<WidgetControl> list = new List<WidgetControl>();
264 Interop.WidgetService.ErrorCode err = Interop.WidgetService.GetWidgetListByPkgId(pkgId, (widgetId, isPrime, userData) =>
266 list.Add(new WidgetControl(widgetId));
271 case Interop.WidgetService.ErrorCode.InvalidParameter:
272 throw new ArgumentException("Invalid parameter");
274 case Interop.WidgetService.ErrorCode.IoError:
275 throw new InvalidOperationException("Failed to access DB");
277 case Interop.WidgetService.ErrorCode.PermissionDenied:
278 throw new UnauthorizedAccessException();
281 return list.ToArray();
285 /// Gets all the widget IDs by the package ID.
287 /// <since_tizen> 3 </since_tizen>
288 /// <privilege>http://tizen.org/privilege/widget.viewer</privilege>
289 /// <exception cref="ArgumentException">Thrown when failed because of an invalid argument.</exception>
290 /// <exception cref="InvalidOperationException">Thrown in case of failed conditions.</exception>
291 /// <exception cref="UnauthorizedAccessException">Thrown when an application does not have the privilege to access this method.</exception>
292 public static string[] GetWidgetIds(string pkgId)
294 List<string> list = new List<string>();
296 Interop.WidgetService.ErrorCode err = Interop.WidgetService.GetWidgetListByPkgId(pkgId, (widgetId, isPrime, userData) =>
303 case Interop.WidgetService.ErrorCode.InvalidParameter:
304 throw new ArgumentException("Invalid parameter");
306 case Interop.WidgetService.ErrorCode.IoError:
307 throw new InvalidOperationException("Failed to access DB");
309 case Interop.WidgetService.ErrorCode.PermissionDenied:
310 throw new UnauthorizedAccessException();
313 return list.ToArray();
319 /// <since_tizen> 3 </since_tizen>
320 public string Id { get; internal set; }
323 /// The flag value for "nodisplay".
325 /// <since_tizen> 3 </since_tizen>
326 /// <privilege>http://tizen.org/privilege/widget.viewer</privilege>
327 public bool IsNoDisplay
331 if (Interop.WidgetService.GetNoDisplay(Id) != 0)
339 /// The event handler for a created widget instance.
341 /// <since_tizen> 3 </since_tizen>
342 /// <exception cref="InvalidOperationException">Thrown in case of failed conditions.</exception>
343 /// <exception cref="UnauthorizedAccessException">Thrown when an application does not have the privilege to access this method.</exception>
344 public event EventHandler<WidgetLifecycleEventArgs> Created
348 RegisterLifecycleEvent();
354 UnregisterLifecycleEvent();
359 /// The event handler for a resumed widget instance.
361 /// <since_tizen> 3 </since_tizen>
362 /// <exception cref="InvalidOperationException">Thrown in case of failed conditions.</exception>
363 /// <exception cref="UnauthorizedAccessException">Thrown when an application does not have the privilege to access this method.</exception>
364 public event EventHandler<WidgetLifecycleEventArgs> Resumed
368 RegisterLifecycleEvent();
374 UnregisterLifecycleEvent();
379 /// The event handler for a paused widget instance.
381 /// <since_tizen> 3 </since_tizen>
382 /// <exception cref="InvalidOperationException">Thrown in case of failed conditions.</exception>
383 /// <exception cref="UnauthorizedAccessException">Thrown when an application does not have the privilege to access this method.</exception>
384 public event EventHandler<WidgetLifecycleEventArgs> Paused
388 RegisterLifecycleEvent();
394 UnregisterLifecycleEvent();
399 /// The event handler for a destroyed widget instance.
401 /// <since_tizen> 3 </since_tizen>
402 /// <exception cref="InvalidOperationException">Thrown in case of failed conditions.</exception>
403 /// <exception cref="UnauthorizedAccessException">Thrown when an application does not have the privilege to access this method.</exception>
404 public event EventHandler<WidgetLifecycleEventArgs> Destroyed
408 RegisterLifecycleEvent();
414 UnregisterLifecycleEvent();
419 /// The constructor of the WidgetControl object.
421 /// <since_tizen> 3 </since_tizen>
422 /// <param name="widgetId">Widget ID.</param>
423 public WidgetControl(string widgetId)
429 /// Finalizer of the WidgetControl class.
437 /// Gets the objects for widget instance information.
439 /// <since_tizen> 3 </since_tizen>
440 /// <exception cref="InvalidOperationException">Thrown in case of failed conditions.</exception>
441 /// <exception cref="NotSupportedException">Thrown when the API is not supported in this device.</exception>
442 /// <exception cref="UnauthorizedAccessException">Thrown when an application does not have the privilege to access this method.</exception>
443 public IEnumerable<Instance> GetInstances()
445 IList<Instance> instances = new List<Instance>();
446 Interop.WidgetService.ErrorCode err = Interop.WidgetService.GetInstances(Id, (widgetId, instanceId, userData) =>
448 instances.Add(new Instance(widgetId) { Id = instanceId });
453 case Interop.WidgetService.ErrorCode.InvalidParameter:
454 throw new InvalidOperationException("Invalid parameter at unmanaged code");
456 case Interop.WidgetService.ErrorCode.NotSupported:
457 throw new NotSupportedException();
459 case Interop.WidgetService.ErrorCode.PermissionDenied:
460 throw new UnauthorizedAccessException();
467 /// Gets the objects for widget scale information.
469 /// <since_tizen> 3 </since_tizen>
470 /// <privilege>http://tizen.org/privilege/widget.viewer</privilege>
471 /// <exception cref="InvalidOperationException">Thrown in case of failed conditions.</exception>
472 /// <exception cref="UnauthorizedAccessException">Thrown when an application does not have the privilege to access this method.</exception>
473 public IEnumerable<Scale> GetScales()
483 IList<Scale> scales = new List<Scale>();
484 Interop.WidgetService.ErrorCode err = Interop.WidgetService.GetSupportedSizes(Id, ref cnt1, out wPtr, out hPtr);
488 Log.Error(LogTag, "No supported size :" + Id);
494 case Interop.WidgetService.ErrorCode.InvalidParameter:
495 throw new InvalidOperationException("Invalid parameter at unmanaged code");
497 case Interop.WidgetService.ErrorCode.IoError:
498 throw new InvalidOperationException("Failed to access DB");
500 case Interop.WidgetService.ErrorCode.PermissionDenied:
501 throw new UnauthorizedAccessException();
504 Marshal.Copy(wPtr, w, 0, cnt1);
505 Interop.Libc.Free(wPtr);
508 Marshal.Copy(hPtr, h, 0, cnt1);
509 Interop.Libc.Free(hPtr);
511 err = Interop.WidgetService.GetSupportedSizeTypes(Id, ref cnt2, out typesPtr);
514 case Interop.WidgetService.ErrorCode.InvalidParameter:
515 throw new InvalidOperationException("Invalid parameter at unmanaged code");
517 case Interop.WidgetService.ErrorCode.IoError:
518 throw new InvalidOperationException("Failed to access DB");
520 case Interop.WidgetService.ErrorCode.PermissionDenied:
521 throw new UnauthorizedAccessException();
526 Log.Error(LogTag, "Count not match cnt1 :" + cnt1 + ", cnt2 :" + cnt2);
530 types = new int[cnt2];
531 Marshal.Copy(typesPtr, types, 0, cnt2);
532 Interop.Libc.Free(typesPtr);
534 for (int i = 0; i < cnt1; i++)
536 string prev = Interop.WidgetService.GetPreviewImagePath(Id, types[i]);
538 scales.Add(new Scale()
542 PreviewImagePath = prev,
543 Type = (Scale.SizeType)types[i]
550 /// Gets the widget name.
552 /// <since_tizen> 3 </since_tizen>
553 /// <param name="lang">Language.</param>
554 /// <privilege>http://tizen.org/privilege/widget.viewer</privilege>
555 /// <exception cref="ArgumentNullException">Thrown when the argument is null.</exception>
556 public string GetName(string lang)
559 throw new ArgumentNullException();
561 return Interop.WidgetService.GetName(Id, lang);
565 /// Gets the widget icon path.
567 /// <since_tizen> 3 </since_tizen>
568 /// <param name="lang">Language.</param>
569 /// <privilege>http://tizen.org/privilege/widget.viewer</privilege>
570 /// <exception cref="ArgumentNullException">Thrown when the argument is null.</exception>
571 public string GetIconPath(string lang)
574 throw new ArgumentNullException();
576 string pkgId = Interop.WidgetService.GetPkgId(Id);
578 return Interop.WidgetService.GetIcon(pkgId, lang);
582 /// Releases all the resources used by the WidgetControl class.
584 /// <since_tizen> 3 </since_tizen>
585 public void Dispose()
588 GC.SuppressFinalize(this);
591 private void Dispose(bool disposing)
603 UnregisterLifecycleEvent();
605 _disposedValue = true;
609 private void RegisterLifecycleEvent()
611 if (!s_lifecycleEventRefCnt.ContainsKey(Id))
612 s_lifecycleEventRefCnt[Id] = 0;
614 if (_created != null || _paused != null || _resumed != null || _destroyed != null)
617 if (s_lifecycleEventRefCnt[Id] == 0)
619 Interop.WidgetService.ErrorCode err = Interop.WidgetService.SetLifecycleEvent(Id, OnLifecycleEvent, IntPtr.Zero);
623 case Interop.WidgetService.ErrorCode.InvalidParameter:
624 throw new InvalidOperationException("Invalid parameter at unmanaged code");
626 case Interop.WidgetService.ErrorCode.PermissionDenied:
627 throw new UnauthorizedAccessException();
631 s_lifecycleEventRefCnt[Id]++;
632 s_eventObjects.Add(this);
635 private void UnregisterLifecycleEvent()
637 if (!s_lifecycleEventRefCnt.ContainsKey(Id))
640 if (s_lifecycleEventRefCnt[Id] <= 0)
643 if (_created != null || _paused != null || _resumed != null || _destroyed != null)
646 if (s_lifecycleEventRefCnt[Id] == 1)
648 Interop.WidgetService.ErrorCode err = Interop.WidgetService.UnsetLifecycleEvent(Id, IntPtr.Zero);
652 case Interop.WidgetService.ErrorCode.InvalidParameter:
653 throw new InvalidOperationException("Invalid parameter at unmanaged code");
655 case Interop.WidgetService.ErrorCode.PermissionDenied:
656 throw new UnauthorizedAccessException();
658 case Interop.WidgetService.ErrorCode.NotExist:
659 throw new InvalidOperationException("Event handler is not exist");
663 s_eventObjects.Remove(this);
664 s_lifecycleEventRefCnt[Id]--;
667 private static void OnLifecycleEvent(string widgetId, Interop.WidgetService.LifecycleEvent e, string instanceId, IntPtr userData)
671 case Interop.WidgetService.LifecycleEvent.Created:
672 foreach (WidgetControl c in s_eventObjects)
674 if (c.Id.CompareTo(widgetId) == 0)
676 c._created?.Invoke(null, new WidgetLifecycleEventArgs()
679 InstanceId = instanceId,
680 Type = WidgetLifecycleEventArgs.EventType.Created
686 case Interop.WidgetService.LifecycleEvent.Resumed:
687 foreach (WidgetControl c in s_eventObjects)
689 if (c.Id.CompareTo(widgetId) == 0)
691 c._resumed?.Invoke(null, new WidgetLifecycleEventArgs()
694 InstanceId = instanceId,
695 Type = WidgetLifecycleEventArgs.EventType.Resumed
701 case Interop.WidgetService.LifecycleEvent.Paused:
702 foreach (WidgetControl c in s_eventObjects)
704 if (c.Id.CompareTo(widgetId) == 0)
706 c._paused?.Invoke(null, new WidgetLifecycleEventArgs()
709 InstanceId = instanceId,
710 Type = WidgetLifecycleEventArgs.EventType.Paused
716 case Interop.WidgetService.LifecycleEvent.Destroyed:
717 foreach (WidgetControl c in s_eventObjects)
719 if (c.Id.CompareTo(widgetId) == 0)
721 c._destroyed?.Invoke(null, new WidgetLifecycleEventArgs()
724 InstanceId = instanceId,
725 Type = WidgetLifecycleEventArgs.EventType.Destroyed