Release 4.0.0-preview1-00286
[platform/core/csapi/tizenfx.git] / src / Tizen.Applications.Notification / Tizen.Applications.Notifications / Notification.cs
1 /*
2  * Copyright (c) 2017 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 namespace Tizen.Applications.Notifications
18 {
19     using System;
20     using System.Collections.Generic;
21     using System.ComponentModel;
22
23     /// <summary>
24     /// This class contains common properties and methods of notifications.
25     /// </summary>
26     /// <remarks>
27     /// A notification is a message that is displayed on the notification area.
28     /// It is created to notify information to the user through the application.
29     /// This class helps you to provide method and property for creating notification object.
30     /// </remarks>
31     public sealed partial class Notification : IDisposable
32     {
33         internal static readonly string LogTag = "Tizen.Applications.Notification";
34
35         private NotificationSafeHandle safeHandle;
36         private bool disposed = false;
37
38         private IDictionary<string, StyleBase> styleDictionary;
39         private IDictionary<string, Bundle> extraDataDictionary;
40         private int count = 0;
41
42         /// <summary>
43         /// Initializes a new instance of the <see cref="Notification"/> class.
44         /// </summary>
45         public Notification()
46         {
47             styleDictionary = new Dictionary<string, StyleBase>();
48             extraDataDictionary = new Dictionary<string, Bundle>();
49         }
50
51         /// <summary>
52         /// Gets or sets the tag of notification.
53         /// </summary>
54         public string Tag { get; set; } = string.Empty;
55
56         /// <summary>
57         /// Gets or sets the title of notification.
58         /// </summary>
59         public string Title { get; set; } = string.Empty;
60
61         /// <summary>
62         /// Gets or sets the icon of notification.
63         /// You should set an absolute path for an image file.
64         /// </summary>
65         public string Icon { get; set; } = string.Empty;
66
67         /// <summary>
68         /// Gets or sets the sub icon of notification.
69         /// This SubIcon is displayed in Icon you set.
70         /// You should set an absolute path for an image file.
71         /// </summary>
72         public string SubIcon { get; set; } = string.Empty;
73
74         /// <summary>
75         /// Gets or sets the content of notification.
76         /// </summary>
77         public string Content { get; set; } = string.Empty;
78
79         /// <summary>
80         /// Gets or sets a value indicating whether TimeStamp of the notification is Visible or not.
81         /// Default to true.
82         /// </summary>
83         public bool IsTimeStampVisible { get; set; } = true;
84
85         /// <summary>
86         /// Gets or sets the TimeStamp of notification.
87         /// </summary>
88         /// <remarks>
89         /// If you don't set TimeStamp, it will set the value when the notification is posted.
90         /// TimeStamp requires NotificationManager.Post() to be called.
91         /// If you set IsVisibleTimeStamp property to false, TimeStamp is not visible in notification.
92         /// </remarks>
93         public DateTime TimeStamp { get; set; }
94
95         /// <summary>
96         /// Gets or sets action, which is invoked when the notification is clicked.
97         /// </summary>
98         /// <remarks>
99         /// If you set it to null, the already set AppControl will be removed and nothing will happen when you click on notification.
100         /// </remarks>
101         /// <seealso cref="Tizen.Applications.AppControl"></seealso>
102         public AppControl Action { get; set; }
103
104         /// <summary>
105         /// Gets or sets count, which is displayed at the right side of the notification.
106         /// </summary>
107         /// <remarks>
108         /// You must set only positive number.
109         /// If you set count to negative number, this property throws exception.
110         /// </remarks>
111         /// <exception cref="ArgumentException">Thrown when argument is invalid.</exception>
112         public int Count
113         {
114             get
115             {
116                 return count;
117             }
118
119             set
120             {
121                 if (value < 0)
122                 {
123                     Log.Error(LogTag, "Count value is negative");
124                     throw NotificationErrorFactory.GetException(NotificationError.InvalidParameter, "The Count must be a positive integer.");
125                 }
126
127                 count = value;
128             }
129         }
130
131         /// <summary>
132         /// Gets or sets a value indicating whether the notification is Onging or not.
133         /// Default value is false.
134         /// </summary>
135         [EditorBrowsable(EditorBrowsableState.Never)]
136         public bool IsOngoing { get; set; } = false;
137
138         /// <summary>
139         /// Gets or sets property.
140         /// </summary>
141         /// <seealso cref="Tizen.Applications.Notifications.NotificationProperty"></seealso>
142         public NotificationProperty Property { get; set; } = NotificationProperty.None;
143
144         /// <summary>
145         /// Gets or sets <see cref="Notification.ProgressType"/> object for display at notification.
146         /// </summary>
147         /// <seealso cref="Tizen.Applications.Notifications.Notification.ProgressType"></seealso>
148         public ProgressType Progress { get; set; }
149
150         /// <summary>
151         /// Gets or sets <see cref="Notification.AccessorySet"/> which is included vibration, LED and sound option to be applied at notification.
152         /// </summary>
153         /// <remarks>
154         /// If you set it to null, the already set AccessorySet will be initialized.
155         /// </remarks>
156         /// <example>
157         /// <code>
158         /// Notification notification = new Notification
159         /// {
160         ///     Title = "Notification",
161         ///     Content = "Hello Tizen",
162         ///     Icon = "Icon path",
163         ///     Count = 3
164         /// };
165         ///
166         /// Notification.AccessorySet accessory = new Notification.AccessorySet
167         /// {
168         ///     SoundOption = AccessoryOption.Custom,
169         ///     SoundPath = "Sound File Path",
170         ///     IsVibration = true,
171         ///     LedOption = AccessoryOption.Custom,
172         ///     LedOnMs = 100;
173         ///     LedOffMs = 50;
174         ///     LedColor = Color.Lime
175         /// };
176         ///
177         /// notification.Accessory = accessory;
178         ///
179         /// NotificationManager.Post(notification);
180         /// </code>
181         /// </example>
182         public AccessorySet Accessory { get; set; }
183
184         /// <summary>
185         /// Gets or sets a value indicating whether notification is displayed on the default viewer.
186         /// If you set false and add style, you can see only style notification.
187         /// </summary>
188         public bool IsVisible { get; set; } = true;
189
190         /// <summary>
191         /// Gets or sets NotificationSafeHandle.
192         /// </summary>
193         internal NotificationSafeHandle Handle
194         {
195             get
196             {
197                 return safeHandle;
198             }
199
200             set
201             {
202                 if (value == null)
203                 {
204                     Log.Error(LogTag, "Invalid argument NotificationSafeHandle");
205                     throw NotificationErrorFactory.GetException(NotificationError.InvalidParameter, "invalid argument to set NotificationSafeHandle");
206                 }
207
208                 safeHandle = value;
209             }
210         }
211
212         /// <summary>
213         /// Gets or sets private ID.
214         /// </summary>
215         internal int PrivID { get; set; } = -1;
216
217         /// <summary>
218         /// Method for adding various styles to be applied to notification.
219         /// </summary>
220         /// <remarks>
221         /// The user always see about valid notification style. If you add a style which is not supported in platform,
222         /// this method has no effect.
223         /// </remarks>
224         /// <param name="style">The style to be applied to notification.</param>
225         /// <exception cref="ArgumentException">Thrown when argument is invalid.</exception>
226         /// <example>
227         /// <code>
228         /// Notification notification = new Notification
229         /// {
230         ///     Title = "Notification",
231         ///     Content = "Hello Tizen",
232         ///     Icon = "Icon path",
233         ///     Count = 3
234         /// };
235         ///
236         /// Notification.LockStyle lockStyle = new Notification.LockStyle
237         /// {
238         ///     IconPath = "Icon path",
239         ///     ThumbnailPath = "Thumbnail Path"
240         /// };
241         ///
242         /// notification.AddStyle(lockStyle);
243         ///
244         /// NotificationManager.Post(notification);
245         /// </code>
246         /// </example>
247         public void AddStyle(StyleBase style)
248         {
249             if (style == null)
250             {
251                 throw NotificationErrorFactory.GetException(NotificationError.InvalidParameter, "invalid parameter entered");
252             }
253
254             if (styleDictionary.ContainsKey(style.Key) == true)
255             {
256                 Log.Info(LogTag, "The Style is existed, so extender data is replaced");
257                 styleDictionary.Remove(style.Key);
258                 styleDictionary.Add(style.Key, style);
259             }
260             else
261             {
262                 styleDictionary.Add(style.Key, style);
263             }
264         }
265
266         /// <summary>
267         /// Method to remove style you already added.
268         /// </summary>
269         /// <typeparam name="T">Type of notification style to be queried.</typeparam>
270         /// <exception cref="ArgumentException">Thrown when argument is invalid.</exception>
271         public void RemoveStyle<T>() where T : Notification.StyleBase, new()
272         {
273             T type = new T();
274
275             if (styleDictionary.ContainsKey(type.Key))
276             {
277                 styleDictionary.Remove(type.Key);
278             }
279             else
280             {
281                 Log.Error(LogTag, "Sytle Can't be removed, there is no style matched input key");
282                 throw NotificationErrorFactory.GetException(NotificationError.InvalidParameter, "invalid parameter entered");
283             }
284         }
285
286         /// <summary>
287         /// Method to get style you already added.
288         /// </summary>
289         /// <typeparam name="T">Type of notification style to be queried.</typeparam>
290         /// <returns>
291         /// The Notification.Style object associated with the given style.
292         /// </returns>
293         /// <exception cref="ArgumentException">Thrown when argument is invalid.</exception>
294         public T GetStyle<T>() where T : Notification.StyleBase, new()
295         {
296             T type = new T();
297             StyleBase style = null;
298
299             styleDictionary.TryGetValue(type.Key, out style);
300
301             if (style == null)
302             {
303                 Log.Error(LogTag, "Invalid Style");
304                 throw NotificationErrorFactory.GetException(NotificationError.InvalidParameter, "invalid parameter entered");
305             }
306             else
307             {
308                 return style as T;
309             }
310         }
311
312         /// <summary>
313         /// Method to set extra data to add extra data.
314         /// </summary>
315         /// <remarks>
316         /// The type of extra data is bundle.
317         /// </remarks>
318         /// <param name="key">The key of the extra data you want to add.</param>
319         /// <param name="value">The value you want to add.</param>
320         /// <exception cref="ArgumentException">Thrown when argument is invalid.</exception>
321         /// <example>
322         /// <code>
323         /// Notification notification = new Notification
324         /// {
325         ///     Title = "Notification",
326         ///     Content = "Hello Tizen",
327         ///     Icon = "Icon path",
328         /// };
329         ///
330         /// Bundle bundle = new Bundle();
331         /// bundle.AddItem("key", "value");
332         ///
333         /// notification.SetExtraData("firstKey", bundle);
334         /// </code>
335         /// </example>
336         public void SetExtraData(string key, Bundle value)
337         {
338             if (value == null || value.SafeBundleHandle.IsInvalid || string.IsNullOrEmpty(key))
339             {
340                 throw NotificationErrorFactory.GetException(NotificationError.InvalidParameter, "invalid parameter entered");
341             }
342
343             if (extraDataDictionary.ContainsKey(key) == true)
344             {
345                 Log.Info(LogTag, "The key is existed, so extender data is replaced");
346                 extraDataDictionary.Remove(key);
347                 extraDataDictionary.Add(key, value);
348             }
349             else
350             {
351                 extraDataDictionary.Add(key, value);
352             }
353         }
354
355         /// <summary>
356         /// Method to remove extra you already added.
357         /// </summary>
358         /// <remarks>
359         /// The type of extra data is bundle.
360         /// </remarks>
361         /// <param name="key">The key of the extra data to add.</param>
362         /// <exception cref="ArgumentException">Thrown when argument is invalid.</exception>
363         public void RemoveExtraData(string key)
364         {
365             if (string.IsNullOrEmpty(key))
366             {
367                 throw NotificationErrorFactory.GetException(NotificationError.InvalidParameter, "invalid parameter entered");
368             }
369
370             if (extraDataDictionary.ContainsKey(key))
371             {
372                 extraDataDictionary.Remove(key);
373             }
374             else
375             {
376                 throw NotificationErrorFactory.GetException(NotificationError.InvalidParameter, "invalid parameter entered");
377             }
378         }
379
380         /// <summary>
381         /// Method to get extra data you already set.
382         /// </summary>
383         /// <param name="key">The key of the extra data to get.</param>
384         /// <returns>Bundle Object that include extra data</returns>
385         /// <exception cref="ArgumentException">Thrown when argument is invalid.</exception>
386         public Bundle GetExtraData(string key)
387         {
388             if (string.IsNullOrEmpty(key))
389             {
390                 throw NotificationErrorFactory.GetException(NotificationError.InvalidParameter, "invalid parameter entered");
391             }
392
393             Bundle bundle;
394             if (extraDataDictionary.TryGetValue(key, out bundle) == false)
395             {
396                 throw NotificationErrorFactory.GetException(NotificationError.InvalidParameter, "invalid parameter entered : " + key);
397             }
398
399             return bundle;
400         }
401
402         /// <summary>
403         /// Releases any unmanaged resources used by this object.
404         /// </summary>
405         public void Dispose()
406         {
407             Dispose(true);
408             GC.SuppressFinalize(this);
409         }
410
411         internal void Dispose(bool disposing)
412         {
413             if (disposed)
414             {
415                 return;
416             }
417
418             if (disposing && Handle != null && Handle.IsInvalid == false)
419             {
420                 Handle.Dispose();
421             }
422
423             disposed = true;
424         }
425
426         internal IDictionary<string, StyleBase> GetStyleDictionary()
427         {
428             return styleDictionary;
429         }
430
431         internal IDictionary<string, Bundle> GetextraDataDictionary()
432         {
433             return extraDataDictionary;
434         }
435
436         internal StyleBase GetStyle(string key)
437         {
438             if (string.IsNullOrEmpty(key))
439             {
440                 throw NotificationErrorFactory.GetException(NotificationError.InvalidParameter, "Key is null or empty");
441             }
442
443             StyleBase style = null;
444             bool ret = styleDictionary.TryGetValue(key, out style);
445             if (ret == false)
446             {
447                 throw NotificationErrorFactory.GetException(NotificationError.InvalidParameter, "The Style object matched input key is not existed");
448             }
449
450             return style;
451         }
452
453         internal void Make()
454         {
455             NotificationBinder.BindObject(this);
456
457             foreach (string key in GetextraDataDictionary().Keys)
458             {
459                 Log.Info(LogTag, "Start to bind Notification.ExtenderData to SafeHandle");
460                 Interop.Notification.SetExtentionData(Handle, key, extraDataDictionary[key].SafeBundleHandle);
461             }
462
463             foreach (Notification.StyleBase style in styleDictionary.Values)
464             {
465                 Log.Info(LogTag, "Start to bind Notification.Style to SafeHandle [" + style.Key + "]");
466                 style.Make(this);
467             }
468
469             if (Accessory != null)
470             {
471                 Log.Info(LogTag, "Start to bind Notification.AccessetSet to SafeHandle");
472                 Accessory.Make(this);
473             }
474
475             if (Progress != null)
476             {
477                 Log.Info(LogTag, "Start to bind Notification.Progress to SafeHandle");
478                 Progress.Make(this);
479             }
480         }
481
482         internal Notification Build()
483         {
484             IntPtr extention = IntPtr.Zero;
485             IntPtr extentionBundlePtr = IntPtr.Zero;
486
487             NotificationBinder.BindSafeHandle(this);
488
489             Interop.Notification.GetExtentionBundle(Handle, out extention, out extentionBundlePtr);
490
491             if (extention != IntPtr.Zero)
492             {
493                 Bundle bundle = new Bundle(new SafeBundleHandle(extention, false));
494                 foreach (string key in bundle.Keys)
495                 {
496                     if (key.StartsWith("_NOTIFICATION_EXTENSION_EVENT_"))
497                         continue;
498
499                     SafeBundleHandle sbh;
500                     Interop.Notification.GetExtentionData(Handle, key, out sbh);
501                     extraDataDictionary.Add(key, new Bundle(sbh));
502                 }
503             }
504
505             ProgressBinder.BindSafeHandle(this);
506             AccessorySetBinder.BindSafeHandle(this);
507             IndicatorBinder.BindSafeHandle(this);
508             ActiveBinder.BindSafeHandle(this);
509             LockBinder.BindSafehandle(this);
510
511             return this;
512         }
513     }
514 }