namespace UIWidgets.Menu
{
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using UIWidgets.Styles;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
///
/// ContextMenu view.
///
[RequireComponent(typeof(LayoutGroup))]
[RequireComponent(typeof(ContentSizeFitter))]
[RequireComponent(typeof(RectTransform))]
public partial class ContextMenuView : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler, IStylable
{
[SerializeField]
MenuItemView defaultItem;
///
/// Default item.
///
public MenuItemView DefaultItem
{
get
{
return defaultItem;
}
set
{
if (defaultItem != value)
{
defaultItem = value;
DefaultItemTemplate = new MenuItemTemplate(null, DefaultItem);
UpdateEmptyTemplateReferences();
}
}
}
MenuItemTemplate defaultItemTemplate;
///
/// Default item template.
///
protected MenuItemTemplate DefaultItemTemplate
{
get
{
if (defaultItemTemplate == null)
{
defaultItemTemplate = new MenuItemTemplate(null, DefaultItem);
EmptyTemplate.defaultItemTemplate = defaultItemTemplate;
}
return defaultItemTemplate;
}
set
{
if (defaultItemTemplate != value)
{
SubscribersReset();
defaultItemTemplate = value;
UpdateEmptyTemplateReferences();
SubscribersUpdate();
}
}
}
[SerializeField]
List specialItems = new List();
///
/// Special items.
///
public ReadOnlyCollection SpecialItems
{
get
{
return specialItems.AsReadOnly();
}
set
{
if (value == null)
{
throw new ArgumentNullException("value");
}
SubscribersReset();
specialItems.Clear();
specialItems.AddRange(value);
UpdateEmptyTemplateReferences();
SubscribersUpdate();
}
}
///
/// Cache.
///
[SerializeField]
[HideInInspector]
protected List Cache = new List();
///
/// Empty template without nested items templates.
///
protected ContextMenuView EmptyTemplate;
RectTransform rectTransform;
///
/// RectTransform.
///
public RectTransform RectTransform
{
get
{
if (rectTransform == null)
{
rectTransform = transform as RectTransform;
}
return rectTransform;
}
}
///
/// Is pointer over?
///
public bool IsPointerOver
{
get;
protected set;
}
///
/// Subscribers.
///
protected readonly List Subscribers = new List();
///
/// Process the start event.
///
protected virtual void Start()
{
Init();
}
bool isInited;
///
/// Init this instance.
///
public virtual void Init()
{
if (isInited)
{
return;
}
gameObject.SetActive(false);
defaultItem.gameObject.SetActive(false);
for (int i = 0; i < specialItems.Count; i++)
{
specialItems[i].Template.gameObject.SetActive(false);
}
isInited = true;
}
///
/// Subscribe menu instance.
///
/// Menu.
public void Subscribe(IMenuSubscriber menu)
{
Subscribers.Add(menu);
}
///
/// Unsubscribe menu instance.
///
/// Menu.
public void Unsubscribe(IMenuSubscriber menu)
{
Subscribers.Remove(menu);
}
///
/// Send ResetItems event to the subscribers.
///
protected void SubscribersReset()
{
foreach (var s in Subscribers)
{
ResetItems(s);
}
}
///
/// Send ResetItems event to the subscriber.
///
/// Subscriber.
protected static void ResetItems(IMenuSubscriber subscriber)
{
subscriber.ResetItems();
}
///
/// Send UpdateItems event to the subscribers.
///
protected void SubscribersUpdate()
{
foreach (var s in Subscribers)
{
UpdateItems(s);
}
}
///
/// Send UpdateItems event to the subscriber.
///
/// Subscriber.
protected static void UpdateItems(IMenuSubscriber subscriber)
{
subscriber.UpdateItems();
}
///
/// Return menu to the cache.
///
/// Menu.
public void Return(ContextMenuView menu)
{
if (menu == null)
{
return;
}
menu.IsPointerOver = false;
menu.transform.SetParent(RectTransform, false);
menu.gameObject.SetActive(false);
Cache.Add(menu);
}
///
/// Return MenuItem view to the cache.
///
/// Item.
/// Instance.
public void Return(MenuItem item, MenuItemView view)
{
GetItemTemplate(item).Return(view);
}
///
/// Get menu.
///
/// Menu.
public virtual ContextMenuView Instance()
{
if (EmptyTemplate == null)
{
CreateEmptyTemplate();
}
ContextMenuView menu;
if (Cache.Count > 0)
{
menu = Cache[Cache.Count - 1];
Cache.RemoveAt(Cache.Count - 1);
}
else
{
menu = Instantiate(EmptyTemplate);
Utilities.FixInstantiated(EmptyTemplate, menu);
menu.Init();
}
menu.IsPointerOver = false;
menu.gameObject.SetActive(true);
return menu;
}
///
/// Create empty template.
///
protected virtual void CreateEmptyTemplate()
{
EmptyTemplate = Instantiate(this);
Utilities.FixInstantiated(this, EmptyTemplate);
EmptyTemplate.gameObject.SetActive(false);
EmptyTemplate.name = string.Format("{0}EmptyTemplate", name);
// destroy nested defaultItem
if (EmptyTemplate.defaultItem.RectTransform.IsChildOf(EmptyTemplate.RectTransform))
{
if (EmptyTemplate.defaultItemTemplate != null)
{
EmptyTemplate.defaultItemTemplate.Clear();
}
EmptyTemplate.defaultItem.transform.SetParent(null, false);
Destroy(EmptyTemplate.defaultItem.gameObject);
}
// destroy nested specialItems
for (int i = 0; i < EmptyTemplate.specialItems.Count; i++)
{
var item = EmptyTemplate.specialItems[i];
if (item.Template.RectTransform.IsChildOf(EmptyTemplate.RectTransform))
{
item.Clear();
item.Template.transform.SetParent(null, false);
Destroy(item.Template.gameObject);
}
}
EmptyTemplate.Init();
UpdateEmptyTemplateReferences();
}
///
/// Update empty template.
///
protected virtual void UpdateEmptyTemplateReferences()
{
if (EmptyTemplate == null)
{
return;
}
EmptyTemplate.defaultItem = defaultItem;
EmptyTemplate.DefaultItemTemplate = DefaultItemTemplate;
EmptyTemplate.specialItems = specialItems;
}
///
/// Get item instance.
///
/// Item.
/// Instance.
public MenuItemView GetItemView(MenuItem item)
{
return GetItemTemplate(item).Instance();
}
///
/// Get item template.
///
/// Item.
/// Template.
protected MenuItemTemplate GetItemTemplate(MenuItem item)
{
for (int i = 0; i < SpecialItems.Count; i++)
{
if (SpecialItems[i].Key == item.Template)
{
return SpecialItems[i];
}
}
return DefaultItemTemplate;
}
///
/// Process the pointer enter event.
///
/// Event data.
public void OnPointerEnter(PointerEventData eventData)
{
IsPointerOver = true;
}
///
/// Process the pointer exit event.
///
/// Event data.
public void OnPointerExit(PointerEventData eventData)
{
IsPointerOver = false;
}
#region IStyleable
///
/// Name of the delimiter template.
///
protected static readonly string DelimiterName = "-";
///
public bool SetStyle(Style style)
{
style.ContextMenu.MainBackground.ApplyTo(this);
for (int i = 0; i < SpecialItems.Count; i++)
{
if (UtilitiesCompare.StartsWith(SpecialItems[i].Key, DelimiterName))
{
SpecialItems[i].Template.SetDelimiterStyle(style.ContextMenu.DelimiterImage);
}
else
{
SpecialItems[i].Template.SetStyle(style);
}
}
DefaultItem.SetStyle(style);
return true;
}
///
public bool GetStyle(Style style)
{
style.ContextMenu.MainBackground.GetFrom(this);
for (int i = 0; i < SpecialItems.Count; i++)
{
if (UtilitiesCompare.StartsWith(SpecialItems[i].Key, DelimiterName))
{
SpecialItems[i].Template.GetDelimiterStyle(style.ContextMenu.DelimiterImage);
}
else
{
SpecialItems[i].Template.GetStyle(style);
}
}
DefaultItem.GetStyle(style);
return true;
}
#endregion
}
}