/*
* Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the License);
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
namespace Tizen.Applications.Notifications
{
using System;
using System.Collections.Generic;
using System.ComponentModel;
///
/// This class contains common properties and methods of notifications.
///
///
/// A notification is a message that is displayed on the notification area.
/// It is created to notify information to the user through the application.
/// This class helps you to provide method and property for creating notification object.
///
public sealed partial class Notification : IDisposable
{
internal static readonly string LogTag = "Tizen.Applications.Notification";
private NotificationSafeHandle safeHandle;
private bool disposed = false;
private IDictionary styleDictionary;
private IDictionary extraDataDictionary;
private int count = 0;
///
/// Initializes a new instance of the class.
///
public Notification()
{
styleDictionary = new Dictionary();
extraDataDictionary = new Dictionary();
}
///
/// Gets or sets the tag of notification.
///
public string Tag { get; set; } = string.Empty;
///
/// Gets or sets the title of notification.
///
public string Title { get; set; } = string.Empty;
///
/// Gets or sets the icon of notification.
/// You should set an absolute path for an image file.
///
public string Icon { get; set; } = string.Empty;
///
/// Gets or sets the sub icon of notification.
/// This SubIcon is displayed in Icon you set.
/// You should set an absolute path for an image file.
///
public string SubIcon { get; set; } = string.Empty;
///
/// Gets or sets the content of notification.
///
public string Content { get; set; } = string.Empty;
///
/// Gets or sets a value indicating whether TimeStamp of the notification is Visible or not.
/// Default to true.
///
public bool IsTimeStampVisible { get; set; } = true;
///
/// Gets or sets the TimeStamp of notification.
///
///
/// If you don't set TimeStamp, it will set the value when the notification is posted.
/// TimeStamp requires NotificationManager.Post() to be called.
/// If you set IsVisibleTimeStamp property to false, TimeStamp is not visible in notification.
///
public DateTime TimeStamp { get; set; }
///
/// Gets or sets action, which is invoked when the notification is clicked.
///
///
/// If you set it to null, the already set AppControl will be removed and nothing will happen when you click on notification.
///
///
public AppControl Action { get; set; }
///
/// Gets or sets count, which is displayed at the right side of the notification.
///
///
/// You must set only positive number.
/// If you set count to negative number, this property throws exception.
///
/// Thrown when argument is invalid.
public int Count
{
get
{
return count;
}
set
{
if (value < 0)
{
Log.Error(LogTag, "Count value is negative");
throw NotificationErrorFactory.GetException(NotificationError.InvalidParameter, "The Count must be a positive integer.");
}
count = value;
}
}
[EditorBrowsable(EditorBrowsableState.Never)]
public bool IsOngoing { get; set; } = false;
///
/// Gets or sets property.
///
///
public NotificationProperty Property { get; set; } = NotificationProperty.None;
///
/// Gets or sets object for display at notification.
///
///
public ProgressType Progress { get; set; }
///
/// Gets or sets which is included vibration, LED and sound option to be applied at notification.
///
///
/// If you set it to null, the already set AccessorySet will be initialized.
///
///
///
/// Notification notification = new Notification
/// {
/// Title = "Notification",
/// Content = "Hello Tizen",
/// Icon = "Icon path",
/// Count = 3
/// };
///
/// Notification.AccessorySet accessory = new Notification.AccessorySet
/// {
/// SoundOption = AccessoryOption.Custom,
/// SoundPath = "Sound File Path",
/// IsVibration = true,
/// LedOption = AccessoryOption.Custom,
/// LedOnMs = 100;
/// LedOffMs = 50;
/// LedColor = Color.Lime
/// };
///
/// notification.Accessory = accessory;
///
/// NotificationManager.Post(notification);
///
///
public AccessorySet Accessory { get; set; }
///
/// Gets or sets a value indicating whether notification is displayed on the default viewer.
/// If you set false and add style, you can see only style notification.
///
public bool IsVisible { get; set; } = true;
///
/// Gets or sets NotificationSafeHandle.
///
internal NotificationSafeHandle Handle
{
get
{
return safeHandle;
}
set
{
if (value == null)
{
Log.Error(LogTag, "Invalid argument NotificationSafeHandle");
throw NotificationErrorFactory.GetException(NotificationError.InvalidParameter, "invalid argument to set NotificationSafeHandle");
}
safeHandle = value;
}
}
///
/// Gets or sets private ID.
///
internal int PrivID { get; set; } = -1;
///
/// Method for adding various styles to be applied to notification.
///
///
/// The user always see about valid notification style. If you add a style which is not supported in platform,
/// this method has no effect.
///
/// The style to be applied to notification.
/// Thrown when argument is invalid.
///
///
/// Notification notification = new Notification
/// {
/// Title = "Notification",
/// Content = "Hello Tizen",
/// Icon = "Icon path",
/// Count = 3
/// };
///
/// Notification.LockStyle lockStyle = new Notification.LockStyle
/// {
/// IconPath = "Icon path",
/// ThumbnailPath = "Thumbnail Path"
/// };
///
/// notification.AddStyle(lockStyle);
///
/// NotificationManager.Post(notification);
///
///
public void AddStyle(StyleBase style)
{
if (style == null)
{
throw NotificationErrorFactory.GetException(NotificationError.InvalidParameter, "invalid parameter entered");
}
if (styleDictionary.ContainsKey(style.Key) == true)
{
Log.Info(LogTag, "The Style is existed, so extender data is replaced");
styleDictionary.Remove(style.Key);
styleDictionary.Add(style.Key, style);
}
else
{
styleDictionary.Add(style.Key, style);
}
}
///
/// Method to remove style you already added.
///
/// Type of notification style to be queried.
/// Thrown when argument is invalid.
public void RemoveStyle() where T : Notification.StyleBase, new()
{
T type = new T();
if (styleDictionary.ContainsKey(type.Key))
{
styleDictionary.Remove(type.Key);
}
else
{
Log.Error(LogTag, "Sytle Can't be removed, there is no style matched input key");
throw NotificationErrorFactory.GetException(NotificationError.InvalidParameter, "invalid parameter entered");
}
}
///
/// Method to get style you already added.
///
/// Type of notification style to be queried.
///
/// The Notification.Style object associated with the given style.
///
/// Thrown when argument is invalid.
public T GetStyle() where T : Notification.StyleBase, new()
{
T type = new T();
StyleBase style = null;
styleDictionary.TryGetValue(type.Key, out style);
if (style == null)
{
Log.Error(LogTag, "Invalid Style");
throw NotificationErrorFactory.GetException(NotificationError.InvalidParameter, "invalid parameter entered");
}
else
{
return style as T;
}
}
///
/// Method to set extra data to add extra data.
///
///
/// The type of extra data is bundle.
///
/// The key of the extra data you want to add.
/// The value you want to add.
/// Thrown when argument is invalid.
///
///
/// Notification notification = new Notification
/// {
/// Title = "Notification",
/// Content = "Hello Tizen",
/// Icon = "Icon path",
/// };
///
/// Bundle bundle = new Bundle();
/// bundle.AddItem("key", "value");
///
/// notification.SetExtraData("firstKey", bundle);
///
///
public void SetExtraData(string key, Bundle value)
{
if (value == null || value.SafeBundleHandle.IsInvalid || string.IsNullOrEmpty(key))
{
throw NotificationErrorFactory.GetException(NotificationError.InvalidParameter, "invalid parameter entered");
}
if (extraDataDictionary.ContainsKey(key) == true)
{
Log.Info(LogTag, "The key is existed, so extender data is replaced");
extraDataDictionary.Remove(key);
extraDataDictionary.Add(key, value);
}
else
{
extraDataDictionary.Add(key, value);
}
}
///
/// Method to remove extra you already added.
///
///
/// The type of extra data is bundle.
///
/// The key of the extra data to add.
/// Thrown when argument is invalid.
public void RemoveExtraData(string key)
{
if (string.IsNullOrEmpty(key))
{
throw NotificationErrorFactory.GetException(NotificationError.InvalidParameter, "invalid parameter entered");
}
if (extraDataDictionary.ContainsKey(key))
{
extraDataDictionary.Remove(key);
}
else
{
throw NotificationErrorFactory.GetException(NotificationError.InvalidParameter, "invalid parameter entered");
}
}
///
/// Method to get extra data you already set.
///
/// The key of the extra data to get.
/// Bundle Object that include extra data
/// Thrown when argument is invalid.
public Bundle GetExtraData(string key)
{
if (string.IsNullOrEmpty(key))
{
throw NotificationErrorFactory.GetException(NotificationError.InvalidParameter, "invalid parameter entered");
}
Bundle bundle;
if (extraDataDictionary.TryGetValue(key, out bundle) == false)
{
throw NotificationErrorFactory.GetException(NotificationError.InvalidParameter, "invalid parameter entered : " + key);
}
return bundle;
}
///
/// Releases any unmanaged resources used by this object.
///
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
internal void Dispose(bool disposing)
{
if (disposed)
{
return;
}
if (disposing && Handle != null && Handle.IsInvalid == false)
{
Handle.Dispose();
}
disposed = true;
}
internal IDictionary GetStyleDictionary()
{
return styleDictionary;
}
internal IDictionary GetextraDataDictionary()
{
return extraDataDictionary;
}
internal StyleBase GetStyle(string key)
{
if (string.IsNullOrEmpty(key))
{
throw NotificationErrorFactory.GetException(NotificationError.InvalidParameter, "Key is null or empty");
}
StyleBase style = null;
bool ret = styleDictionary.TryGetValue(key, out style);
if (ret == false)
{
throw NotificationErrorFactory.GetException(NotificationError.InvalidParameter, "The Style object matched input key is not existed");
}
return style;
}
internal void Make()
{
NotificationBinder.BindObject(this);
foreach (string key in GetextraDataDictionary().Keys)
{
Log.Info(LogTag, "Start to bind Notification.ExtenderData to SafeHandle");
Interop.Notification.SetExtentionData(Handle, key, extraDataDictionary[key].SafeBundleHandle);
}
foreach (Notification.StyleBase style in styleDictionary.Values)
{
Log.Info(LogTag, "Start to bind Notification.Style to SafeHandle [" + style.Key + "]");
style.Make(this);
}
if (Accessory != null)
{
Log.Info(LogTag, "Start to bind Notification.AccessetSet to SafeHandle");
Accessory.Make(this);
}
if (Progress != null)
{
Log.Info(LogTag, "Start to bind Notification.Progress to SafeHandle");
Progress.Make(this);
}
}
internal Notification Build()
{
IntPtr extention = IntPtr.Zero;
IntPtr extentionBundlePtr = IntPtr.Zero;
NotificationBinder.BindSafeHandle(this);
Interop.Notification.GetExtentionBundle(Handle, out extention, out extentionBundlePtr);
if (extention != IntPtr.Zero)
{
Bundle bundle = new Bundle(new SafeBundleHandle(extention, false));
foreach (string key in bundle.Keys)
{
if (key.StartsWith("_NOTIFICATION_EXTENSION_EVENT_"))
continue;
SafeBundleHandle sbh;
Interop.Notification.GetExtentionData(Handle, key, out sbh);
extraDataDictionary.Add(key, new Bundle(sbh));
}
}
ProgressBinder.BindSafeHandle(this);
AccessorySetBinder.BindSafeHandle(this);
IndicatorBinder.BindSafeHandle(this);
ActiveBinder.BindSafeHandle(this);
LockBinder.BindSafehandle(this);
return this;
}
}
}