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