namespace UIWidgets
{
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using UIWidgets.Styles;
using UnityEngine;
using UnityEngine.UI;
///
/// Base generic class for the custom notifications.
///
/// Notification type.
public abstract class NotificationCustom : NotificationBase, IStylable, IUpgradeable, IHideable
where TNotification : NotificationCustom
{
[SerializeField]
Button hideButton;
///
/// Gets or sets the button that close current notification.
///
/// The hide button.
public Button HideButton
{
get
{
return hideButton;
}
set
{
if (hideButton != null)
{
hideButton.onClick.RemoveListener(Hide);
}
hideButton = value;
if (hideButton != null)
{
hideButton.onClick.AddListener(Hide);
}
}
}
[SerializeField]
[HideInInspector]
[Obsolete("Replaced with NotifyInfo component.")]
Text text;
///
/// Gets or sets the text component.
///
/// The text.
[HideInInspector]
[Obsolete("Replaced with NotifyInfo component.")]
public Text Text
{
get
{
return text;
}
set
{
text = value;
}
}
///
/// Hide delay.
///
[SerializeField]
public float HideDelay = 10f;
static Templates templates;
///
/// Notifications templates.
///
public static Templates Templates
{
get
{
if (templates == null)
{
templates = new Templates(AddCloseCallback);
}
return templates;
}
set
{
templates = value;
}
}
///
/// Function used to run show animation.
///
public Func ShowAnimation;
///
/// Function used to run hide animation.
///
public Func HideAnimation;
Func oldShowAnimation;
Func oldHideAnimation;
Vector2 oldSize;
Quaternion oldRotation;
IEnumerator showCoroutine;
IEnumerator hideCoroutine;
///
/// Start slide up animations after hide current notification. Turn it off if its managed with HideAnimation.
///
public bool SlideUpOnHide = true;
[SerializeField]
NotifyInfoBase notifyInfo;
///
/// Gets the notification info.
///
/// The notification info.
public NotifyInfoBase NotifyInfo
{
get
{
if (notifyInfo == null)
{
notifyInfo = GetComponent();
}
return notifyInfo;
}
}
#region buttons
///
/// Button instance.
///
public class ButtonInstance : DialogButtonCustom
{
///
/// Initializes a new instance of the class.
///
/// Owner.
/// Index.
/// Info.
/// Template.
/// Button container.
public ButtonInstance(TNotification owner, int index, NotificationButton info, Button template, RectTransform container)
: base(owner, index, info, template, container)
{
}
}
///
/// Class for the buttons instances.
///
protected class ButtonsPool : DialogButtonsPoolCustom
{
///
/// Initializes a new instance of the class.
///
/// Dialog.
/// Templates.
/// Container.
/// List for the active buttons.
/// List for the cached buttons.
public ButtonsPool(TNotification owner, ReadOnlyCollection templates, RectTransform container, List active, List> cache)
: base(owner, templates, container, active, cache)
{
}
///
/// Create the button.
///
/// Index of the button.
/// Button info.
/// Button.
protected override ButtonInstance CreateButtonInstance(int buttonIndex, NotificationButton info)
{
return new ButtonInstance(Owner, buttonIndex, info, Templates[info.TemplateIndex], Container);
}
}
ButtonsPool buttonsPool;
///
/// Buttons pool.
///
protected ButtonsPool Buttons
{
get
{
if (buttonsPool == null)
{
buttonsPool = new ButtonsPool(this as TNotification, ButtonsTemplates, ButtonsContainer, ButtonsActive, ButtonsCached);
}
return buttonsPool;
}
}
///
/// The buttons in use.
///
[SerializeField]
[HideInInspector]
protected List ButtonsActive = new List();
///
/// Current buttons.
///
public ReadOnlyCollection CurrentButtons
{
get
{
return ButtonsActive.AsReadOnly();
}
}
///
/// The cached buttons.
///
[SerializeField]
[HideInInspector]
protected List> ButtonsCached = new List>();
///
/// Buttons container.
///
[SerializeField]
protected RectTransform ButtonsContainer;
[SerializeField]
List buttonsTemplates = new List();
///
/// Gets or sets the default buttons.
///
/// The default buttons.
public ReadOnlyCollection ButtonsTemplates
{
get
{
Upgrade();
return buttonsTemplates.AsReadOnly();
}
set
{
if (IsTemplate && (buttonsTemplates.Count > value.Count))
{
throw new ArgumentOutOfRangeException("value", string.Format("Buttons count cannot be decreased. Current is {0}; New is {1}", buttonsTemplates.Count.ToString(), value.Count.ToString()));
}
Buttons.Replace(value);
buttonsTemplates.Clear();
buttonsTemplates.AddRange(value);
if (buttonsTemplates.Count > 0)
{
Upgrade();
}
}
}
///
/// Creates the buttons.
///
/// Buttons.
[Obsolete("Notifications now use NotificationButton instead of the DialogButton.")]
public virtual void SetButtons(IList buttons)
{
Buttons.Disable();
if (buttons == null)
{
return;
}
for (int index = 0; index < buttons.Count; index++)
{
var old_info = buttons[index];
#pragma warning disable 0618
var info = new NotificationButton(old_info.Label, old_info.Action, old_info.TemplateIndex);
#pragma warning restore 0618
info.TemplateIndex = GetTemplateIndex(info);
Buttons.Get(index, info);
}
}
///
/// Creates the buttons.
///
/// Buttons.
public virtual void SetButtons(IList buttons)
{
Buttons.Disable();
if (buttons == null)
{
return;
}
for (int index = 0; index < buttons.Count; index++)
{
var info = buttons[index];
info.TemplateIndex = GetTemplateIndex(info);
Buttons.Get(index, info);
}
}
///
/// Get button template index.
///
/// Button.
/// Template index,
protected int GetTemplateIndex(NotificationButton button)
{
var template = button.TemplateIndex;
if (template < 0)
{
Debug.LogWarning(string.Format("Negative button index not supported. Button: {0}. Index: {1}.", button.Label, template.ToString()));
template = 0;
}
if (template >= Buttons.Count)
{
Debug.LogWarning(string.Format(
"Not found button template with index {0} for the button: {1}. Available indices: 0..{2}",
template.ToString(),
button.Label,
(Buttons.Count - 1).ToString()));
template = 0;
}
return template;
}
#endregion
///
/// Gets the name of the template.
///
/// The name of the template.
public override string TemplateName
{
get
{
if (NotificationTemplateName == null)
{
Templates.FindTemplates();
}
return NotificationTemplateName;
}
set
{
NotificationTemplateName = value;
}
}
///
/// Callback on dialog close.
///
public Action OnReturn;
///
/// Finds the templates.
///
protected static void FindTemplates()
{
Templates.FindTemplates();
}
///
/// Awake this instance.
///
protected virtual void Awake()
{
if (IsTemplate)
{
gameObject.SetActive(false);
}
}
///
/// Remove listeners and template.
///
protected virtual void OnDestroy()
{
Buttons.Disable();
HideButton = null;
if (!IsTemplate)
{
templates = null;
return;
}
// if FindTemplates never called than TemplateName == null
if (TemplateName != null)
{
DeleteTemplate(TemplateName);
}
}
///
/// Clears the cached instance of templates.
///
public static void ClearCache()
{
Templates.ClearCache();
}
///
/// Clears the cached instance of specified template.
///
/// Template name.
public static void ClearCache(string templateName)
{
Templates.ClearCache(templateName);
}
///
/// Gets the template by name.
///
/// The template.
/// Template name.
public static TNotification GetTemplate(string template)
{
return Templates.Get(template);
}
///
/// Deletes the template by name.
///
/// Template.
public static void DeleteTemplate(string template)
{
Templates.Delete(template);
}
///
/// Adds the template.
///
/// Template name.
/// Notification template object.
/// If set to true replace.
public static void AddTemplate(string template, TNotification notificationTemplate, bool replace = true)
{
Templates.Add(template, notificationTemplate, replace);
}
///
/// Return notification instance by the specified template name.
///
/// Template name.
/// New notification instance.
[Obsolete("Use Clone(templateName) instead.")]
public static TNotification Template(string templateName)
{
return Clone(templateName);
}
///
/// Return notification instance using current instance as template.
///
/// New notification instance.
[Obsolete("Use Clone() instead.")]
public TNotification Template()
{
return Clone();
}
///
/// Return notification by the specified template name.
///
/// Template name.
/// Returns new notification instance.
public static TNotification Clone(string templateName)
{
return Templates.Instance(templateName);
}
///
/// Return notification instance using current instance as template.
///
/// Returns new notification instance.
public TNotification Clone()
{
var notification = this as TNotification;
if ((TemplateName != null) && Templates.Exists(TemplateName))
{
// do nothing
}
else if (!Templates.Exists(gameObject.name))
{
Templates.Add(gameObject.name, notification);
}
else if (Templates.Get(gameObject.name) != notification)
{
Templates.Add(gameObject.name, notification);
}
var id = gameObject.GetInstanceID().ToString();
if (!Templates.Exists(id))
{
Templates.Add(id, notification);
}
else if (Templates.Get(id) != notification)
{
Templates.Add(id, notification);
}
return Templates.Instance(id);
}
///
/// Adds the close callback.
///
/// Notification.
protected static void AddCloseCallback(TNotification notification)
{
if (notification.hideButton == null)
{
return;
}
notification.hideButton.onClick.AddListener(notification.Hide);
}
///
/// Show the notification.
///
/// Message. Also can be changed with SetMessage().
/// Custom hide delay. Also can be changed with HideDelay field.
/// Container. Parent object for the current notification. Also can be changed with SetContainer().
/// Function used to run show animation. Also can be changed with ShowAnimation field.
/// Function used to run hide animation. Also can be changed with HideAnimation field.
/// Start slide up animations after hide current notification. Also can be changed with SlideUpOnHide field.
/// Add notification to sequence and display in order according specified sequenceType.
/// Time between previous notification was hidden and next will be showed. Also can be changed with SequenceDelay field.
/// Clear notifications sequence.
/// Use unscaled time.
/// Content. Also can be changed with SetContent().
/// Action called when instance return to the cache. Also can be changed with OnReturn field.
public virtual void Show(
string message = null,
float? customHideDelay = null,
Transform container = null,
Func showAnimation = null,
Func hideAnimation = null,
bool? slideUpOnHide = null,
NotifySequence sequenceType = NotifySequence.None,
float sequenceDelay = 0.3f,
bool clearSequence = false,
bool? newUnscaledTime = null,
RectTransform content = null,
Action onReturn = null)
{
if (IsTemplate)
{
Debug.LogWarning("Use the template clone, not the template itself: NotificationTemplate.Clone().Show(...), not NotificationTemplate.Show(...)");
}
if (clearSequence)
{
ClearSequence();
}
OnReturn = onReturn;
SequenceDelay = sequenceDelay;
oldShowAnimation = ShowAnimation;
oldHideAnimation = HideAnimation;
var rt = transform as RectTransform;
oldSize = rt.rect.size;
oldRotation = rt.localRotation;
SetMessage(message, null);
SetContent(content);
SetContainer(container);
if (newUnscaledTime != null)
{
UnscaledTime = (bool)newUnscaledTime;
}
if (customHideDelay != null)
{
HideDelay = (float)customHideDelay;
}
if (slideUpOnHide != null)
{
SlideUpOnHide = (bool)slideUpOnHide;
}
if (showAnimation != null)
{
ShowAnimation = showAnimation;
}
if (hideAnimation != null)
{
HideAnimation = hideAnimation;
}
if (sequenceType != NotifySequence.None)
{
NotifyManager.Add(this, sequenceType);
}
else
{
Display();
}
}
///
/// Set message text.
///
/// Message text.
public virtual void SetMessage(string message)
{
NotifyInfo.SetInfo(message, null);
}
///
/// Set message text.
///
/// Message text.
/// An object array that contains zero or more objects to message format.
public virtual void SetMessage(string message, params object[] args)
{
NotifyInfo.SetInfo(message, args);
}
///
/// Sets the content.
///
/// Content.
public virtual void SetContent(RectTransform content)
{
if (content == null)
{
return;
}
NotifyInfo.SetContent(content);
}
Action OnHideCallback;
///
/// Display notification.
///
/// On hide callback.
public override void Display(Action onHideCallback = null)
{
transform.SetAsLastSibling();
gameObject.SetActive(true);
OnHideCallback = onHideCallback;
if (ShowAnimation != null)
{
showCoroutine = ShowAnimation(this as TNotification);
StartCoroutine(showCoroutine);
}
else
{
showCoroutine = null;
}
if (HideDelay > 0.0f)
{
hideCoroutine = HideCoroutine();
StartCoroutine(hideCoroutine);
}
else
{
hideCoroutine = null;
}
}
[System.Diagnostics.CodeAnalysis.SuppressMessage("Performance", "HAA0401:Possible allocation of reference type enumerator", Justification = "Enumerator is reusable.")]
IEnumerator HideCoroutine()
{
yield return UtilitiesTime.Wait(HideDelay, UnscaledTime);
if (HideAnimation != null)
{
yield return StartCoroutine(HideAnimation(this as TNotification));
}
Hide();
}
///
/// Hide notification.
///
public override void Hide()
{
if (SlideUpOnHide)
{
var replacement = GetReplacement(this as TNotification);
var slide = Utilities.GetOrAddComponent(replacement);
slide.UnscaledTime = UnscaledTime;
slide.Run();
}
if (OnHideCallback != null)
{
OnHideCallback();
}
Return();
}
///
/// Return this instance to cache.
///
public override void Return()
{
if (OnReturn != null)
{
OnReturn();
}
Buttons.Disable();
Templates.ToCache(this as TNotification);
ShowAnimation = oldShowAnimation;
HideAnimation = oldHideAnimation;
var rt = transform as RectTransform;
rt.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, oldSize.x);
rt.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, oldSize.y);
rt.localRotation = oldRotation;
var le = GetComponent();
if (le != null)
{
le.ignoreLayout = false;
}
OnReturn = null;
NotifyInfo.RestoreDefaultValues();
}
///
/// Upgrade fields data to the latest version.
///
public virtual void Upgrade()
{
#pragma warning disable 0618
if (notifyInfo == null)
{
notifyInfo = gameObject.AddComponent();
Utilities.GetOrAddComponent(text, ref notifyInfo.MessageAdapter);
}
#pragma warning restore 0618
}
#if UNITY_EDITOR
///
/// Update layout when parameters changed.
///
protected virtual void OnValidate()
{
Compatibility.Upgrade(this);
}
#endif
#region IStylable implementation
///
public virtual bool SetStyle(Style style)
{
style.Notify.Background.ApplyTo(transform.Find("Background"));
if (NotifyInfo != null)
{
NotifyInfo.SetStyle(style);
}
if (HideButton != null)
{
style.ButtonClose.Background.ApplyTo(HideButton);
style.ButtonClose.Text.ApplyTo(HideButton.transform.Find("Text"));
}
if (buttonsPool != null)
{
buttonsPool.SetStyle(style.Dialog.Button);
}
else
{
for (int template_index = 0; template_index < ButtonsTemplates.Count; template_index++)
{
style.Dialog.Button.ApplyTo(ButtonsTemplates[template_index].gameObject);
}
}
return true;
}
///
public virtual bool GetStyle(Style style)
{
style.Notify.Background.GetFrom(transform.Find("Background"));
if (NotifyInfo != null)
{
NotifyInfo.GetStyle(style);
}
if (HideButton != null)
{
style.ButtonClose.Background.GetFrom(HideButton);
style.ButtonClose.Text.GetFrom(HideButton.transform.Find("Text"));
}
for (int template_index = 0; template_index < ButtonsTemplates.Count; template_index++)
{
style.Dialog.Button.GetFrom(ButtonsTemplates[template_index].gameObject);
}
return true;
}
#endregion
}
}