namespace UIWidgets { using System; using UIWidgets.Styles; using UnityEngine; using UnityEngine.UI; /// /// Base class for Pickers. /// /// Type of value. /// Type of picker. public abstract class Picker : MonoBehaviour, ITemplatable, IStylable where TPicker : Picker { bool isTemplate = true; /// /// Gets a value indicating whether this instance is template. /// /// true if this instance is template; otherwise, false. public bool IsTemplate { get { return isTemplate; } set { isTemplate = value; } } /// /// Gets the name of the template. /// /// The name of the template. public string TemplateName { get; set; } static Templates templates; /// /// Picker templates. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1000:DoNotDeclareStaticMembersOnGenericTypes", Justification = "Reviewed")] public static Templates Templates { get { if (templates == null) { templates = new Templates(); } return templates; } set { templates = value; } } [SerializeField] Button closeButton; /// /// Close button. /// public Button CloseButton { get { return closeButton; } set { if (isInited && (closeButton != null)) { closeButton.onClick.RemoveListener(Cancel); } closeButton = value; if (isInited && (closeButton != null)) { closeButton.onClick.AddListener(Cancel); } } } /// /// Awake is called when the script instance is being loaded. /// protected virtual void Awake() { if (IsTemplate) { gameObject.SetActive(false); } } /// /// Start this instance. /// protected virtual void Start() { Init(); } bool isInited; /// /// Init this instance. /// public virtual void Init() { if (isInited) { return; } if (closeButton != null) { closeButton.onClick.AddListener(Cancel); } isInited = true; } /// /// This function is called when the MonoBehaviour will be destroyed. /// protected virtual void OnDestroy() { if (!IsTemplate) { templates = null; return; } // if FindTemplates never called than TemplateName == null if (TemplateName != null) { Templates.Delete(TemplateName); } } /// /// Return picker instance using current instance as template. /// /// New picker instance. [Obsolete("Use Clone() instead.")] public TPicker Template() { return Clone(); } /// /// Return picker instance using current instance as template. /// /// New picker instance. public virtual TPicker Clone() { var picker = this as TPicker; if ((TemplateName != null) && Templates.Exists(TemplateName)) { // do nothing } else if (!Templates.Exists(gameObject.name)) { Templates.Add(gameObject.name, picker); } else if (Templates.Get(gameObject.name) != this) { Templates.Add(gameObject.name, picker); } var id = gameObject.GetInstanceID().ToString(); if (!Templates.Exists(id)) { Templates.Add(id, picker); } else if (Templates.Get(id) != this) { Templates.Add(id, picker); } return Templates.Instance(id); } /// /// The modal key. /// protected int? ModalKey; /// /// Callback with selected value. /// protected Action OnSelect; /// /// Callback when picker closed without any value selected. /// protected Action OnCancel; /// /// Show picker. /// /// Default value. /// Callback with selected value. /// Callback when picker closed without any value selected. /// Modal sprite. /// Modal color. /// Canvas. public virtual void Show( TValue defaultValue, Action onSelect, Action onCancel = null, Sprite modalSprite = null, Color? modalColor = null, Canvas canvas = null) { if (IsTemplate) { Debug.LogWarning("Use the template clone, not the template itself: PickerTemplate.Clone().Show(...), not PickerTemplate.Show(...)"); } OnSelect = onSelect; OnCancel = onCancel; var parent = (canvas != null) ? canvas.transform as RectTransform : UtilitiesUI.FindTopmostCanvas(gameObject.transform); if (parent != null) { transform.SetParent(parent, false); } if (modalColor == null) { modalColor = new Color(0, 0, 0, 0.8f); } ModalKey = ModalHelper.Open(this, modalSprite, modalColor, Close, parent); transform.SetAsLastSibling(); gameObject.SetActive(true); BeforeOpen(defaultValue); } /// /// Close picker with specified value. /// /// Value. public virtual void Selected(TValue value) { OnSelect(value); Close(); } /// /// Close picker without specified value. /// public virtual void Cancel() { if (OnCancel != null) { OnCancel(); } Close(); } /// /// Prepare picker to open. /// /// Default value. public abstract void BeforeOpen(TValue defaultValue); /// /// Prepare picker to close. /// public abstract void BeforeClose(); /// /// Close picker. /// protected virtual void Close() { BeforeClose(); if (ModalKey.HasValue) { ModalHelper.Close(ModalKey.Value); } Return(); } /// /// Return this instance to cache. /// protected virtual void Return() { Templates.ToCache(this as TPicker); } #region IStylable implementation /// public virtual bool SetStyle(Style style) { style.Dialog.Background.ApplyTo(GetComponent()); style.Dialog.Title.ApplyTo(transform.Find("Header/Title")); style.Dialog.ContentBackground.ApplyTo(transform.Find("Content")); style.Dialog.Delimiter.ApplyTo(transform.Find("Delimiter/Delimiter")); if (closeButton != null) { style.ButtonClose.ApplyTo(closeButton); } else { style.ButtonClose.Background.ApplyTo(transform.Find("Header/CloseButton")); style.ButtonClose.Text.ApplyTo(transform.Find("Header/CloseButton/Text")); } return true; } /// public virtual bool GetStyle(Style style) { style.Dialog.Background.GetFrom(GetComponent()); style.Dialog.Title.GetFrom(transform.Find("Header/Title")); style.Dialog.ContentBackground.GetFrom(transform.Find("Content")); style.Dialog.Delimiter.GetFrom(transform.Find("Delimiter/Delimiter")); if (closeButton != null) { style.ButtonClose.GetFrom(closeButton); } else { style.ButtonClose.Background.GetFrom(transform.Find("Header/CloseButton")); style.ButtonClose.Text.GetFrom(transform.Find("Header/CloseButton/Text")); } return true; } #endregion } }