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