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";
31 private static Interop.WidgetService.LifecycleCallback _onLifecycleCallback;
33 /// Class for the widget instance.
35 /// <since_tizen> 3 </since_tizen>
38 private string _widgetId;
40 internal Instance(string widgetId)
48 /// <since_tizen> 3 </since_tizen>
49 public string Id { get; internal set; }
52 /// Gets the widget content.
54 /// <since_tizen> 3 </since_tizen>
55 /// <exception cref="InvalidOperationException">Thrown in case of failed conditions.</exception>
56 public Bundle GetContent()
60 Interop.WidgetService.ErrorCode err = Interop.WidgetService.GetContent(_widgetId, Id, out h);
64 case Interop.WidgetService.ErrorCode.InvalidParameter:
65 throw new InvalidOperationException("Invalid parameter at unmanaged code");
67 case Interop.WidgetService.ErrorCode.IoError:
68 throw new InvalidOperationException("Failed to access DB");
71 return new Bundle(new SafeBundleHandle(h, true));
75 /// Changes the content for the widget instance.
77 /// <since_tizen> 3 </since_tizen>
78 /// <param name="content">Content to be changed.</param>
79 /// <param name="force"> True if you want to update your widget even if the provider is paused, otherwise false.</param>
80 /// <exception cref="ArgumentException">Thrown when failed because of an invalid argument.</exception>
81 /// <exception cref="InvalidOperationException">Thrown in case of failed conditions.</exception>
82 /// <exception cref="UnauthorizedAccessException">Thrown when an application does not have the privilege to access this method.</exception>
83 public void ChangeContent(Bundle content, bool force)
85 Interop.WidgetService.ErrorCode err = Interop.WidgetService.UpdateContent(_widgetId, Id, content.SafeBundleHandle, force ? 1 : 0);
89 case Interop.WidgetService.ErrorCode.InvalidParameter:
90 throw new ArgumentException("Invalid parameter");
92 case Interop.WidgetService.ErrorCode.Canceled:
93 throw new InvalidOperationException("Provider is paused, so this update request is canceld");
95 case Interop.WidgetService.ErrorCode.OutOfMemory:
96 throw new InvalidOperationException("Out-of-memory at unmanaged code");
98 case Interop.WidgetService.ErrorCode.Fault:
99 throw new InvalidOperationException("Failed to create a request packet");
101 case Interop.WidgetService.ErrorCode.PermissionDenied:
102 throw new UnauthorizedAccessException();
107 /// Changes the update period for the widget instance.
109 /// <since_tizen> 3 </since_tizen>
110 /// <exception cref="ArgumentException">Thrown when failed because of an invalid argument.</exception>
111 /// <exception cref="InvalidOperationException">Thrown in case of failed conditions.</exception>
112 /// <exception cref="UnauthorizedAccessException">Thrown when an application does not have the privilege to access this method.</exception>
113 public void ChangePeriod(double period)
115 Interop.WidgetService.ErrorCode err = Interop.WidgetService.ChangePeriod(_widgetId, Id, period);
119 case Interop.WidgetService.ErrorCode.InvalidParameter:
120 throw new ArgumentException("Invalid parameter");
122 case Interop.WidgetService.ErrorCode.OutOfMemory:
123 throw new InvalidOperationException("Out-of-memory at unmanaged code");
125 case Interop.WidgetService.ErrorCode.Fault:
126 throw new InvalidOperationException("Failed to create a request packet");
128 case Interop.WidgetService.ErrorCode.PermissionDenied:
129 throw new UnauthorizedAccessException();
135 /// The class for the widget size information.
137 /// <since_tizen> 3 </since_tizen>
146 /// Enumeration for the types of widget size.
148 /// <since_tizen> 3 </since_tizen>
149 public enum SizeType : int
152 /// 175x175 based on 720x1280 resolution.
157 /// 354x175 based on 720x1280 resolution.
162 /// 354x354 based on 720x1280 resolution.
167 /// 712x175 based on 720x1280 resolution.
172 /// 712x354 based on 720x1280 resolution.
177 /// 712x533 based on 720x1280 resolution.
182 /// 712x712 based on 720x1280 resolution.
187 /// 712x891 based on 720x1280 resolution.
192 /// 712x1070 based on 720x1280 resolution.
198 /// 224x215 based on 720x1280 resolution.
203 /// 680x215 based on 720x1280 resolution.
208 /// 680x653 based on 720x1280 resolution.
213 /// 720x1280 based on 720x1280 resolution.
221 /// <since_tizen> 3 </since_tizen>
222 public int Width { get; internal set; }
227 /// <since_tizen> 3 </since_tizen>
228 public int Height { get; internal set; }
231 /// The path for the widget preview image file.
233 /// <since_tizen> 3 </since_tizen>
234 public string PreviewImagePath { get; internal set; }
237 /// The size type of the widget.
239 /// <since_tizen> 3 </since_tizen>
240 public SizeType Type { get; internal set; }
243 private event EventHandler<WidgetLifecycleEventArgs> _created;
244 private event EventHandler<WidgetLifecycleEventArgs> _resumed;
245 private event EventHandler<WidgetLifecycleEventArgs> _paused;
246 private event EventHandler<WidgetLifecycleEventArgs> _destroyed;
247 private bool _disposedValue = false;
248 private static IDictionary<string, int> s_lifecycleEventRefCnt = new Dictionary<string, int>();
249 private static IList<WidgetControl> s_eventObjects = new List<WidgetControl>();
252 /// Factory method for the WidgetControl.
253 /// It will create all the objects of WidgetControl based on the package ID.
255 /// <since_tizen> 3 </since_tizen>
256 /// <param name="pkgId">Package ID.</param>
257 /// <privilege>http://tizen.org/privilege/widget.viewer</privilege>
258 /// <exception cref="ArgumentException">Thrown when failed because of an invalid argument.</exception>
259 /// <exception cref="InvalidOperationException">Thrown in case of failed conditions.</exception>
260 /// <exception cref="UnauthorizedAccessException">Thrown when an application does not have the privilege to access this method.</exception>
261 public static WidgetControl[] CreateAll(string pkgId)
263 List<WidgetControl> list = new List<WidgetControl>();
265 Interop.WidgetService.ErrorCode err = Interop.WidgetService.GetWidgetListByPkgId(pkgId, (widgetId, isPrime, userData) =>
267 list.Add(new WidgetControl(widgetId));
272 case Interop.WidgetService.ErrorCode.InvalidParameter:
273 throw new ArgumentException("Invalid parameter");
275 case Interop.WidgetService.ErrorCode.IoError:
276 throw new InvalidOperationException("Failed to access DB");
278 case Interop.WidgetService.ErrorCode.PermissionDenied:
279 throw new UnauthorizedAccessException();
282 return list.ToArray();
286 /// Gets all the widget IDs by the package ID.
288 /// <since_tizen> 3 </since_tizen>
289 /// <privilege>http://tizen.org/privilege/widget.viewer</privilege>
290 /// <exception cref="ArgumentException">Thrown when failed because of an invalid argument.</exception>
291 /// <exception cref="InvalidOperationException">Thrown in case of failed conditions.</exception>
292 /// <exception cref="UnauthorizedAccessException">Thrown when an application does not have the privilege to access this method.</exception>
293 public static string[] GetWidgetIds(string pkgId)
295 List<string> list = new List<string>();
297 Interop.WidgetService.ErrorCode err = Interop.WidgetService.GetWidgetListByPkgId(pkgId, (widgetId, isPrime, userData) =>
304 case Interop.WidgetService.ErrorCode.InvalidParameter:
305 throw new ArgumentException("Invalid parameter");
307 case Interop.WidgetService.ErrorCode.IoError:
308 throw new InvalidOperationException("Failed to access DB");
310 case Interop.WidgetService.ErrorCode.PermissionDenied:
311 throw new UnauthorizedAccessException();
314 return list.ToArray();
320 /// <since_tizen> 3 </since_tizen>
321 public string Id { get; internal set; }
324 /// The flag value for "nodisplay".
326 /// <since_tizen> 3 </since_tizen>
327 /// <privilege>http://tizen.org/privilege/widget.viewer</privilege>
328 public bool IsNoDisplay
332 if (Interop.WidgetService.GetNoDisplay(Id) != 0)
340 /// The event handler for a created widget instance.
342 /// <since_tizen> 3 </since_tizen>
343 /// <exception cref="InvalidOperationException">Thrown in case of failed conditions.</exception>
344 /// <exception cref="UnauthorizedAccessException">Thrown when an application does not have the privilege to access this method.</exception>
345 public event EventHandler<WidgetLifecycleEventArgs> Created
349 RegisterLifecycleEvent();
355 UnregisterLifecycleEvent();
360 /// The event handler for a resumed widget instance.
362 /// <since_tizen> 3 </since_tizen>
363 /// <exception cref="InvalidOperationException">Thrown in case of failed conditions.</exception>
364 /// <exception cref="UnauthorizedAccessException">Thrown when an application does not have the privilege to access this method.</exception>
365 public event EventHandler<WidgetLifecycleEventArgs> Resumed
369 RegisterLifecycleEvent();
375 UnregisterLifecycleEvent();
380 /// The event handler for a paused widget instance.
382 /// <since_tizen> 3 </since_tizen>
383 /// <exception cref="InvalidOperationException">Thrown in case of failed conditions.</exception>
384 /// <exception cref="UnauthorizedAccessException">Thrown when an application does not have the privilege to access this method.</exception>
385 public event EventHandler<WidgetLifecycleEventArgs> Paused
389 RegisterLifecycleEvent();
395 UnregisterLifecycleEvent();
400 /// The event handler for a destroyed widget instance.
402 /// <since_tizen> 3 </since_tizen>
403 /// <exception cref="InvalidOperationException">Thrown in case of failed conditions.</exception>
404 /// <exception cref="UnauthorizedAccessException">Thrown when an application does not have the privilege to access this method.</exception>
405 public event EventHandler<WidgetLifecycleEventArgs> Destroyed
409 RegisterLifecycleEvent();
415 UnregisterLifecycleEvent();
420 /// The constructor of the WidgetControl object.
422 /// <since_tizen> 3 </since_tizen>
423 /// <param name="widgetId">Widget ID.</param>
424 public WidgetControl(string widgetId)
430 /// Finalizer of the WidgetControl class.
438 /// Gets the objects for widget instance information.
440 /// <since_tizen> 3 </since_tizen>
441 /// <exception cref="InvalidOperationException">Thrown in case of failed conditions.</exception>
442 /// <exception cref="NotSupportedException">Thrown when the API is not supported in this device.</exception>
443 /// <exception cref="UnauthorizedAccessException">Thrown when an application does not have the privilege to access this method.</exception>
444 public IEnumerable<Instance> GetInstances()
446 IList<Instance> instances = new List<Instance>();
447 Interop.WidgetService.ErrorCode err = Interop.WidgetService.GetInstances(Id, (widgetId, instanceId, userData) =>
449 instances.Add(new Instance(widgetId) { Id = instanceId });
454 case Interop.WidgetService.ErrorCode.InvalidParameter:
455 throw new InvalidOperationException("Invalid parameter at unmanaged code");
457 case Interop.WidgetService.ErrorCode.NotSupported:
458 throw new NotSupportedException();
460 case Interop.WidgetService.ErrorCode.PermissionDenied:
461 throw new UnauthorizedAccessException();
468 /// Gets the objects for widget scale information.
470 /// <since_tizen> 3 </since_tizen>
471 /// <privilege>http://tizen.org/privilege/widget.viewer</privilege>
472 /// <exception cref="InvalidOperationException">Thrown in case of failed conditions.</exception>
473 /// <exception cref="UnauthorizedAccessException">Thrown when an application does not have the privilege to access this method.</exception>
474 public IEnumerable<Scale> GetScales()
484 IList<Scale> scales = new List<Scale>();
485 Interop.WidgetService.ErrorCode err = Interop.WidgetService.GetSupportedSizes(Id, ref cnt1, out wPtr, out hPtr);
489 Log.Error(LogTag, "No supported size :" + Id);
495 case Interop.WidgetService.ErrorCode.InvalidParameter:
496 throw new InvalidOperationException("Invalid parameter at unmanaged code");
498 case Interop.WidgetService.ErrorCode.IoError:
499 throw new InvalidOperationException("Failed to access DB");
501 case Interop.WidgetService.ErrorCode.PermissionDenied:
502 throw new UnauthorizedAccessException();
505 Marshal.Copy(wPtr, w, 0, cnt1);
506 Interop.Libc.Free(wPtr);
509 Marshal.Copy(hPtr, h, 0, cnt1);
510 Interop.Libc.Free(hPtr);
512 err = Interop.WidgetService.GetSupportedSizeTypes(Id, ref cnt2, out typesPtr);
515 case Interop.WidgetService.ErrorCode.InvalidParameter:
516 throw new InvalidOperationException("Invalid parameter at unmanaged code");
518 case Interop.WidgetService.ErrorCode.IoError:
519 throw new InvalidOperationException("Failed to access DB");
521 case Interop.WidgetService.ErrorCode.PermissionDenied:
522 throw new UnauthorizedAccessException();
527 Log.Error(LogTag, "Count not match cnt1 :" + cnt1 + ", cnt2 :" + cnt2);
531 types = new int[cnt2];
532 Marshal.Copy(typesPtr, types, 0, cnt2);
533 Interop.Libc.Free(typesPtr);
535 for (int i = 0; i < cnt1; i++)
537 string prev = Interop.WidgetService.GetPreviewImagePath(Id, types[i]);
539 scales.Add(new Scale()
543 PreviewImagePath = prev,
544 Type = (Scale.SizeType)types[i]
551 /// Gets the widget name.
553 /// <since_tizen> 3 </since_tizen>
554 /// <param name="lang">Language.</param>
555 /// <privilege>http://tizen.org/privilege/widget.viewer</privilege>
556 /// <exception cref="ArgumentNullException">Thrown when the argument is null.</exception>
557 public string GetName(string lang)
560 throw new ArgumentNullException();
562 return Interop.WidgetService.GetName(Id, lang);
566 /// Gets the widget icon path.
568 /// <since_tizen> 3 </since_tizen>
569 /// <param name="lang">Language.</param>
570 /// <privilege>http://tizen.org/privilege/widget.viewer</privilege>
571 /// <exception cref="ArgumentNullException">Thrown when the argument is null.</exception>
572 public string GetIconPath(string lang)
575 throw new ArgumentNullException();
577 string pkgId = Interop.WidgetService.GetPkgId(Id);
579 return Interop.WidgetService.GetIcon(pkgId, lang);
583 /// Releases all the resources used by the WidgetControl class.
585 /// <since_tizen> 3 </since_tizen>
586 public void Dispose()
589 GC.SuppressFinalize(this);
592 private void Dispose(bool disposing)
604 UnregisterLifecycleEvent();
606 _disposedValue = true;
610 private void RegisterLifecycleEvent()
612 if (!s_lifecycleEventRefCnt.ContainsKey(Id))
613 s_lifecycleEventRefCnt[Id] = 0;
615 if (_created != null || _paused != null || _resumed != null || _destroyed != null)
618 if (s_lifecycleEventRefCnt[Id] == 0)
620 if (_onLifecycleCallback == null)
621 _onLifecycleCallback = new Interop.WidgetService.LifecycleCallback(OnLifecycleEvent);
623 Interop.WidgetService.ErrorCode err = Interop.WidgetService.SetLifecycleEvent(Id, _onLifecycleCallback, IntPtr.Zero);
626 case Interop.WidgetService.ErrorCode.InvalidParameter:
627 throw new InvalidOperationException("Invalid parameter at unmanaged code");
629 case Interop.WidgetService.ErrorCode.PermissionDenied:
630 throw new UnauthorizedAccessException();
634 s_lifecycleEventRefCnt[Id]++;
635 s_eventObjects.Add(this);
636 Log.Debug(LogTag, "register lifecycle cb " + Id + " [" + s_lifecycleEventRefCnt[Id] + "]");
639 private void UnregisterLifecycleEvent()
641 if (!s_lifecycleEventRefCnt.ContainsKey(Id))
644 if (s_lifecycleEventRefCnt[Id] <= 0)
647 if (_created != null || _paused != null || _resumed != null || _destroyed != null)
650 if (s_lifecycleEventRefCnt[Id] == 1)
652 Interop.WidgetService.ErrorCode err = Interop.WidgetService.UnsetLifecycleEvent(Id, IntPtr.Zero);
656 case Interop.WidgetService.ErrorCode.InvalidParameter:
657 throw new InvalidOperationException("Invalid parameter at unmanaged code");
659 case Interop.WidgetService.ErrorCode.PermissionDenied:
660 throw new UnauthorizedAccessException();
662 case Interop.WidgetService.ErrorCode.NotExist:
663 throw new InvalidOperationException("Event handler is not exist");
665 _onLifecycleCallback = null;
668 s_eventObjects.Remove(this);
669 s_lifecycleEventRefCnt[Id]--;
670 Log.Debug(LogTag, "unregister lifecycle cb " + Id + " [" + s_lifecycleEventRefCnt[Id] + "]");
673 private static int OnLifecycleEvent(string widgetId, Interop.WidgetService.LifecycleEvent e, string instanceId, IntPtr userData)
675 Log.Debug(LogTag, "Lifecycle event : " + instanceId + " [" + e + "]");
678 case Interop.WidgetService.LifecycleEvent.Created:
679 foreach (WidgetControl c in s_eventObjects)
681 if (c.Id.CompareTo(widgetId) == 0)
683 c._created?.Invoke(null, new WidgetLifecycleEventArgs()
686 InstanceId = instanceId,
687 Type = WidgetLifecycleEventArgs.EventType.Created
693 case Interop.WidgetService.LifecycleEvent.Resumed:
694 foreach (WidgetControl c in s_eventObjects)
696 if (c.Id.CompareTo(widgetId) == 0)
698 c._resumed?.Invoke(null, new WidgetLifecycleEventArgs()
701 InstanceId = instanceId,
702 Type = WidgetLifecycleEventArgs.EventType.Resumed
708 case Interop.WidgetService.LifecycleEvent.Paused:
709 foreach (WidgetControl c in s_eventObjects)
711 if (c.Id.CompareTo(widgetId) == 0)
713 c._paused?.Invoke(null, new WidgetLifecycleEventArgs()
716 InstanceId = instanceId,
717 Type = WidgetLifecycleEventArgs.EventType.Paused
723 case Interop.WidgetService.LifecycleEvent.Destroyed:
724 foreach (WidgetControl c in s_eventObjects)
726 if (c.Id.CompareTo(widgetId) == 0)
728 c._destroyed?.Invoke(null, new WidgetLifecycleEventArgs()
731 InstanceId = instanceId,
732 Type = WidgetLifecycleEventArgs.EventType.Destroyed