Merge "[SystemInfo] Remove build warnings"
[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         [EditorBrowsable(EditorBrowsableState.Never)]
132         public bool IsOngoing { get; set; } = false;
133
134         /// <summary>
135         /// Gets or sets property.
136         /// </summary>
137         /// <seealso cref="Tizen.Applications.Notifications.NotificationProperty"></seealso>
138         public NotificationProperty Property { get; set; } = NotificationProperty.None;
139
140         /// <summary>
141         /// Gets or sets <see cref="Notification.ProgressType"/> object for display at notification.
142         /// </summary>
143         /// <seealso cref="Tizen.Applications.Notifications.Notification.ProgressType"></seealso>
144         public ProgressType Progress { get; set; }
145
146         /// <summary>
147         /// Gets or sets <see cref="Notification.AccessorySet"/> which is included vibration, LED and sound option to be applied at notification.
148         /// </summary>
149         /// <remarks>
150         /// If you set it to null, the already set AccessorySet will be initialized.
151         /// </remarks>
152         /// <example>
153         /// <code>
154         /// Notification notification = new Notification
155         /// {
156         ///     Title = "Notification",
157         ///     Content = "Hello Tizen",
158         ///     Icon = "Icon path",
159         ///     Count = 3
160         /// };
161         ///
162         /// Notification.AccessorySet accessory = new Notification.AccessorySet
163         /// {
164         ///     SoundOption = AccessoryOption.Custom,
165         ///     SoundPath = "Sound File Path",
166         ///     IsVibration = true,
167         ///     LedOption = AccessoryOption.Custom,
168         ///     LedOnMs = 100;
169         ///     LedOffMs = 50;
170         ///     LedColor = Color.Lime
171         /// };
172         ///
173         /// notification.Accessory = accessory;
174         ///
175         /// NotificationManager.Post(notification);
176         /// </code>
177         /// </example>
178         public AccessorySet Accessory { get; set; }
179
180         /// <summary>
181         /// Gets or sets a value indicating whether notification is displayed on the default viewer.
182         /// If you set false and add style, you can see only style notification.
183         /// </summary>
184         public bool IsVisible { get; set; } = true;
185
186         /// <summary>
187         /// Gets or sets NotificationSafeHandle.
188         /// </summary>
189         internal NotificationSafeHandle Handle
190         {
191             get
192             {
193                 return safeHandle;
194             }
195
196             set
197             {
198                 if (value == null)
199                 {
200                     Log.Error(LogTag, "Invalid argument NotificationSafeHandle");
201                     throw NotificationErrorFactory.GetException(NotificationError.InvalidParameter, "invalid argument to set NotificationSafeHandle");
202                 }
203
204                 safeHandle = value;
205             }
206         }
207
208         /// <summary>
209         /// Gets or sets private ID.
210         /// </summary>
211         internal int PrivID { get; set; } = -1;
212
213         /// <summary>
214         /// Method for adding various styles to be applied to notification.
215         /// </summary>
216         /// <remarks>
217         /// The user always see about valid notification style. If you add a style which is not supported in platform,
218         /// this method has no effect.
219         /// </remarks>
220         /// <param name="style">The style to be applied to notification.</param>
221         /// <exception cref="ArgumentException">Thrown when argument is invalid.</exception>
222         /// <example>
223         /// <code>
224         /// Notification notification = new Notification
225         /// {
226         ///     Title = "Notification",
227         ///     Content = "Hello Tizen",
228         ///     Icon = "Icon path",
229         ///     Count = 3
230         /// };
231         ///
232         /// Notification.LockStyle lockStyle = new Notification.LockStyle
233         /// {
234         ///     IconPath = "Icon path",
235         ///     ThumbnailPath = "Thumbnail Path"
236         /// };
237         ///
238         /// notification.AddStyle(lockStyle);
239         ///
240         /// NotificationManager.Post(notification);
241         /// </code>
242         /// </example>
243         public void AddStyle(StyleBase style)
244         {
245             if (style == null)
246             {
247                 throw NotificationErrorFactory.GetException(NotificationError.InvalidParameter, "invalid parameter entered");
248             }
249
250             if (styleDictionary.ContainsKey(style.Key) == true)
251             {
252                 Log.Info(LogTag, "The Style is existed, so extender data is replaced");
253                 styleDictionary.Remove(style.Key);
254                 styleDictionary.Add(style.Key, style);
255             }
256             else
257             {
258                 styleDictionary.Add(style.Key, style);
259             }
260         }
261
262         /// <summary>
263         /// Method to remove style you already added.
264         /// </summary>
265         /// <typeparam name="T">Type of notification style to be queried.</typeparam>
266         /// <exception cref="ArgumentException">Thrown when argument is invalid.</exception>
267         public void RemoveStyle<T>() where T : Notification.StyleBase, new()
268         {
269             T type = new T();
270
271             if (styleDictionary.ContainsKey(type.Key))
272             {
273                 styleDictionary.Remove(type.Key);
274             }
275             else
276             {
277                 Log.Error(LogTag, "Sytle Can't be removed, there is no style matched input key");
278                 throw NotificationErrorFactory.GetException(NotificationError.InvalidParameter, "invalid parameter entered");
279             }
280         }
281
282         /// <summary>
283         /// Method to get style you already added.
284         /// </summary>
285         /// <typeparam name="T">Type of notification style to be queried.</typeparam>
286         /// <returns>
287         /// The Notification.Style object associated with the given style.
288         /// </returns>
289         /// <exception cref="ArgumentException">Thrown when argument is invalid.</exception>
290         public T GetStyle<T>() where T : Notification.StyleBase, new()
291         {
292             T type = new T();
293             StyleBase style = null;
294
295             styleDictionary.TryGetValue(type.Key, out style);
296
297             if (style == null)
298             {
299                 Log.Error(LogTag, "Invalid Style");
300                 throw NotificationErrorFactory.GetException(NotificationError.InvalidParameter, "invalid parameter entered");
301             }
302             else
303             {
304                 return style as T;
305             }
306         }
307
308         /// <summary>
309         /// Method to set extra data to add extra data.
310         /// </summary>
311         /// <remarks>
312         /// The type of extra data is bundle.
313         /// </remarks>
314         /// <param name="key">The key of the extra data you want to add.</param>
315         /// <param name="value">The value you want to add.</param>
316         /// <exception cref="ArgumentException">Thrown when argument is invalid.</exception>
317         /// <example>
318         /// <code>
319         /// Notification notification = new Notification
320         /// {
321         ///     Title = "Notification",
322         ///     Content = "Hello Tizen",
323         ///     Icon = "Icon path",
324         /// };
325         ///
326         /// Bundle bundle = new Bundle();
327         /// bundle.AddItem("key", "value");
328         ///
329         /// notification.SetExtraData("firstKey", bundle);
330         /// </code>
331         /// </example>
332         public void SetExtraData(string key, Bundle value)
333         {
334             if (value == null || value.SafeBundleHandle.IsInvalid || string.IsNullOrEmpty(key))
335             {
336                 throw NotificationErrorFactory.GetException(NotificationError.InvalidParameter, "invalid parameter entered");
337             }
338
339             if (extraDataDictionary.ContainsKey(key) == true)
340             {
341                 Log.Info(LogTag, "The key is existed, so extender data is replaced");
342                 extraDataDictionary.Remove(key);
343                 extraDataDictionary.Add(key, value);
344             }
345             else
346             {
347                 extraDataDictionary.Add(key, value);
348             }
349         }
350
351         /// <summary>
352         /// Method to remove extra you already added.
353         /// </summary>
354         /// <remarks>
355         /// The type of extra data is bundle.
356         /// </remarks>
357         /// <param name="key">The key of the extra data to add.</param>
358         /// <exception cref="ArgumentException">Thrown when argument is invalid.</exception>
359         public void RemoveExtraData(string key)
360         {
361             if (string.IsNullOrEmpty(key))
362             {
363                 throw NotificationErrorFactory.GetException(NotificationError.InvalidParameter, "invalid parameter entered");
364             }
365
366             if (extraDataDictionary.ContainsKey(key))
367             {
368                 extraDataDictionary.Remove(key);
369             }
370             else
371             {
372                 throw NotificationErrorFactory.GetException(NotificationError.InvalidParameter, "invalid parameter entered");
373             }
374         }
375
376         /// <summary>
377         /// Method to get extra data you already set.
378         /// </summary>
379         /// <param name="key">The key of the extra data to get.</param>
380         /// <returns>Bundle Object that include extra data</returns>
381         /// <exception cref="ArgumentException">Thrown when argument is invalid.</exception>
382         public Bundle GetExtraData(string key)
383         {
384             if (string.IsNullOrEmpty(key))
385             {
386                 throw NotificationErrorFactory.GetException(NotificationError.InvalidParameter, "invalid parameter entered");
387             }
388
389             Bundle bundle;
390             if (extraDataDictionary.TryGetValue(key, out bundle) == false)
391             {
392                 throw NotificationErrorFactory.GetException(NotificationError.InvalidParameter, "invalid parameter entered : " + key);
393             }
394
395             return bundle;
396         }
397
398         /// <summary>
399         /// Releases any unmanaged resources used by this object.
400         /// </summary>
401         public void Dispose()
402         {
403             Dispose(true);
404             GC.SuppressFinalize(this);
405         }
406
407         internal void Dispose(bool disposing)
408         {
409             if (disposed)
410             {
411                 return;
412             }
413
414             if (disposing && Handle != null && Handle.IsInvalid == false)
415             {
416                 Handle.Dispose();
417             }
418
419             disposed = true;
420         }
421
422         internal IDictionary<string, StyleBase> GetStyleDictionary()
423         {
424             return styleDictionary;
425         }
426
427         internal IDictionary<string, Bundle> GetextraDataDictionary()
428         {
429             return extraDataDictionary;
430         }
431
432         internal StyleBase GetStyle(string key)
433         {
434             if (string.IsNullOrEmpty(key))
435             {
436                 throw NotificationErrorFactory.GetException(NotificationError.InvalidParameter, "Key is null or empty");
437             }
438
439             StyleBase style = null;
440             bool ret = styleDictionary.TryGetValue(key, out style);
441             if (ret == false)
442             {
443                 throw NotificationErrorFactory.GetException(NotificationError.InvalidParameter, "The Style object matched input key is not existed");
444             }
445
446             return style;
447         }
448
449         internal void Make()
450         {
451             NotificationBinder.BindObject(this);
452
453             foreach (string key in GetextraDataDictionary().Keys)
454             {
455                 Log.Info(LogTag, "Start to bind Notification.ExtenderData to SafeHandle");
456                 Interop.Notification.SetExtentionData(Handle, key, extraDataDictionary[key].SafeBundleHandle);
457             }
458
459             foreach (Notification.StyleBase style in styleDictionary.Values)
460             {
461                 Log.Info(LogTag, "Start to bind Notification.Style to SafeHandle [" + style.Key + "]");
462                 style.Make(this);
463             }
464
465             if (Accessory != null)
466             {
467                 Log.Info(LogTag, "Start to bind Notification.AccessetSet to SafeHandle");
468                 Accessory.Make(this);
469             }
470
471             if (Progress != null)
472             {
473                 Log.Info(LogTag, "Start to bind Notification.Progress to SafeHandle");
474                 Progress.Make(this);
475             }
476         }
477
478         internal Notification Build()
479         {
480             IntPtr extention = IntPtr.Zero;
481             IntPtr extentionBundlePtr = IntPtr.Zero;
482
483             NotificationBinder.BindSafeHandle(this);
484
485             Interop.Notification.GetExtentionBundle(Handle, out extention, out extentionBundlePtr);
486
487             if (extention != IntPtr.Zero)
488             {
489                 Bundle bundle = new Bundle(new SafeBundleHandle(extention, false));
490                 foreach (string key in bundle.Keys)
491                 {
492                     if (key.StartsWith("_NOTIFICATION_EXTENSION_EVENT_"))
493                         continue;
494
495                     SafeBundleHandle sbh;
496                     Interop.Notification.GetExtentionData(Handle, key, out sbh);
497                     extraDataDictionary.Add(key, new Bundle(sbh));
498                 }
499             }
500
501             ProgressBinder.BindSafeHandle(this);
502             AccessorySetBinder.BindSafeHandle(this);
503             IndicatorBinder.BindSafeHandle(this);
504             ActiveBinder.BindSafeHandle(this);
505             LockBinder.BindSafehandle(this);
506
507             return this;
508         }
509     }
510 }