340 lines
7.1 KiB
C#
340 lines
7.1 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
using UnityEngine.EventSystems;
|
|
using UnityEngine.UI;
|
|
|
|
namespace UIWidgets
|
|
{
|
|
[AddComponentMenu("UI/Combobox", 220)]
|
|
[RequireComponent(typeof(InputField))]
|
|
public class Combobox : MonoBehaviour, ISubmitHandler, IEventSystemHandler
|
|
{
|
|
[SerializeField]
|
|
private ListView listView;
|
|
|
|
[SerializeField]
|
|
private Button toggleButton;
|
|
|
|
[SerializeField]
|
|
private bool editable = true;
|
|
|
|
private InputField input;
|
|
|
|
public ListViewEvent OnSelect = new ListViewEvent();
|
|
|
|
private Transform _listCanvas;
|
|
|
|
private Transform listParent;
|
|
|
|
[NonSerialized]
|
|
private bool isStartedCombobox;
|
|
|
|
protected int? ModalKey;
|
|
|
|
protected List<SelectListener> childrenDeselect = new List<SelectListener>();
|
|
|
|
public ListView ListView
|
|
{
|
|
get
|
|
{
|
|
return listView;
|
|
}
|
|
set
|
|
{
|
|
SetListView(value);
|
|
}
|
|
}
|
|
|
|
public Button ToggleButton
|
|
{
|
|
get
|
|
{
|
|
return toggleButton;
|
|
}
|
|
set
|
|
{
|
|
SetToggleButton(value);
|
|
}
|
|
}
|
|
|
|
public bool Editable
|
|
{
|
|
get
|
|
{
|
|
return editable;
|
|
}
|
|
set
|
|
{
|
|
editable = value;
|
|
input.interactable = editable;
|
|
}
|
|
}
|
|
|
|
private Transform listCanvas
|
|
{
|
|
get
|
|
{
|
|
if (_listCanvas == null)
|
|
{
|
|
_listCanvas = Utilites.FindCanvas(listView.transform.parent);
|
|
}
|
|
return _listCanvas;
|
|
}
|
|
}
|
|
|
|
private void Awake()
|
|
{
|
|
Start();
|
|
}
|
|
|
|
public virtual void Start()
|
|
{
|
|
if (isStartedCombobox)
|
|
{
|
|
return;
|
|
}
|
|
isStartedCombobox = true;
|
|
input = GetComponent<InputField>();
|
|
input.onEndEdit.AddListener(InputItem);
|
|
Editable = editable;
|
|
SetToggleButton(toggleButton);
|
|
SetListView(listView);
|
|
if (listView != null)
|
|
{
|
|
listView.OnSelectString.RemoveListener(SelectItem);
|
|
listView.gameObject.SetActive(true);
|
|
listView.Start();
|
|
if (listView.SelectedIndex != -1)
|
|
{
|
|
input.text = listView.DataSource[listView.SelectedIndex];
|
|
}
|
|
listView.gameObject.SetActive(false);
|
|
listView.OnSelectString.AddListener(SelectItem);
|
|
}
|
|
}
|
|
|
|
protected virtual void SetListView(ListView value)
|
|
{
|
|
if (listView != null)
|
|
{
|
|
listParent = null;
|
|
listView.OnSelectString.RemoveListener(SelectItem);
|
|
listView.OnFocusOut.RemoveListener(onFocusHideList);
|
|
listView.onCancel.RemoveListener(OnListViewCancel);
|
|
listView.onItemCancel.RemoveListener(OnListViewCancel);
|
|
RemoveDeselectCallbacks();
|
|
}
|
|
listView = value;
|
|
if (listView != null)
|
|
{
|
|
listParent = listView.transform.parent;
|
|
listView.OnSelectString.AddListener(SelectItem);
|
|
listView.OnFocusOut.AddListener(onFocusHideList);
|
|
listView.onCancel.AddListener(OnListViewCancel);
|
|
listView.onItemCancel.AddListener(OnListViewCancel);
|
|
AddDeselectCallbacks();
|
|
}
|
|
}
|
|
|
|
protected virtual void SetToggleButton(Button value)
|
|
{
|
|
if (toggleButton != null)
|
|
{
|
|
toggleButton.onClick.RemoveListener(ToggleList);
|
|
}
|
|
toggleButton = value;
|
|
if (toggleButton != null)
|
|
{
|
|
toggleButton.onClick.AddListener(ToggleList);
|
|
}
|
|
}
|
|
|
|
public virtual void Clear()
|
|
{
|
|
listView.DataSource.Clear();
|
|
input.text = string.Empty;
|
|
}
|
|
|
|
public virtual void ToggleList()
|
|
{
|
|
if (!(listView == null))
|
|
{
|
|
if (listView.gameObject.activeSelf)
|
|
{
|
|
HideList();
|
|
}
|
|
else
|
|
{
|
|
ShowList();
|
|
}
|
|
}
|
|
}
|
|
|
|
public virtual void ShowList()
|
|
{
|
|
if (!(listView == null))
|
|
{
|
|
if (listCanvas != null)
|
|
{
|
|
ModalKey = ModalHelper.Open(this, null, new Color(0f, 0f, 0f, 0f), HideList);
|
|
listParent = listView.transform.parent;
|
|
listView.transform.SetParent(listCanvas);
|
|
}
|
|
listView.gameObject.SetActive(true);
|
|
if (listView.Layout != null)
|
|
{
|
|
listView.Layout.UpdateLayout();
|
|
}
|
|
if (listView.SelectComponent())
|
|
{
|
|
SetChildDeselectListener(EventSystem.current.currentSelectedGameObject);
|
|
}
|
|
else
|
|
{
|
|
EventSystem.current.SetSelectedGameObject(listView.gameObject);
|
|
}
|
|
}
|
|
}
|
|
|
|
public virtual void HideList()
|
|
{
|
|
int? modalKey = ModalKey;
|
|
if (modalKey.HasValue)
|
|
{
|
|
int? modalKey2 = ModalKey;
|
|
ModalHelper.Close(modalKey2.Value);
|
|
ModalKey = null;
|
|
}
|
|
if (!(listView == null))
|
|
{
|
|
listView.gameObject.SetActive(false);
|
|
if (listCanvas != null)
|
|
{
|
|
listView.transform.SetParent(listParent);
|
|
}
|
|
}
|
|
}
|
|
|
|
protected void onFocusHideList(BaseEventData eventData)
|
|
{
|
|
if (eventData.selectedObject == base.gameObject)
|
|
{
|
|
return;
|
|
}
|
|
ListViewItemEventData listViewItemEventData = eventData as ListViewItemEventData;
|
|
if (listViewItemEventData != null)
|
|
{
|
|
if (listViewItemEventData.NewSelectedObject != null)
|
|
{
|
|
SetChildDeselectListener(listViewItemEventData.NewSelectedObject);
|
|
}
|
|
return;
|
|
}
|
|
PointerEventData pointerEventData = eventData as PointerEventData;
|
|
if (pointerEventData == null)
|
|
{
|
|
HideList();
|
|
return;
|
|
}
|
|
GameObject gameObject = pointerEventData.pointerPressRaycast.gameObject;
|
|
if (!(gameObject == null) && !gameObject.Equals(toggleButton.gameObject))
|
|
{
|
|
if (gameObject.transform.IsChildOf(listView.transform))
|
|
{
|
|
SetChildDeselectListener(gameObject);
|
|
}
|
|
else
|
|
{
|
|
HideList();
|
|
}
|
|
}
|
|
}
|
|
|
|
protected void SetChildDeselectListener(GameObject child)
|
|
{
|
|
SelectListener deselectListener = GetDeselectListener(child);
|
|
if (!childrenDeselect.Contains(deselectListener))
|
|
{
|
|
deselectListener.onDeselect.AddListener(onFocusHideList);
|
|
childrenDeselect.Add(deselectListener);
|
|
}
|
|
}
|
|
|
|
protected SelectListener GetDeselectListener(GameObject go)
|
|
{
|
|
return go.GetComponent<SelectListener>() ?? go.AddComponent<SelectListener>();
|
|
}
|
|
|
|
protected void AddDeselectCallbacks()
|
|
{
|
|
if (!(listView.ScrollRect == null) && !(listView.ScrollRect.verticalScrollbar == null))
|
|
{
|
|
GameObject go = listView.ScrollRect.verticalScrollbar.gameObject;
|
|
SelectListener deselectListener = GetDeselectListener(go);
|
|
deselectListener.onDeselect.AddListener(onFocusHideList);
|
|
childrenDeselect.Add(deselectListener);
|
|
}
|
|
}
|
|
|
|
protected void RemoveDeselectCallbacks()
|
|
{
|
|
childrenDeselect.ForEach(RemoveDeselectCallback);
|
|
childrenDeselect.Clear();
|
|
}
|
|
|
|
protected void RemoveDeselectCallback(SelectListener listener)
|
|
{
|
|
if (listener != null)
|
|
{
|
|
listener.onDeselect.RemoveListener(onFocusHideList);
|
|
}
|
|
}
|
|
|
|
public virtual int Set(string item, bool allowDuplicate = true)
|
|
{
|
|
return listView.Set(item, allowDuplicate);
|
|
}
|
|
|
|
protected virtual void SelectItem(int index, string text)
|
|
{
|
|
input.text = text;
|
|
HideList();
|
|
if (EventSystem.current != null && !EventSystem.current.alreadySelecting)
|
|
{
|
|
EventSystem.current.SetSelectedGameObject(toggleButton.gameObject);
|
|
}
|
|
OnSelect.Invoke(index, text);
|
|
}
|
|
|
|
protected virtual void InputItem(string item)
|
|
{
|
|
if (editable && !(item == string.Empty) && !listView.DataSource.Contains(item))
|
|
{
|
|
int index = listView.Add(item);
|
|
listView.Select(index);
|
|
}
|
|
}
|
|
|
|
protected virtual void OnDestroy()
|
|
{
|
|
ListView = null;
|
|
ToggleButton = null;
|
|
if (input != null)
|
|
{
|
|
input.onEndEdit.RemoveListener(InputItem);
|
|
}
|
|
}
|
|
|
|
protected void OnListViewCancel()
|
|
{
|
|
HideList();
|
|
}
|
|
|
|
public virtual void OnSubmit(BaseEventData eventData)
|
|
{
|
|
ShowList();
|
|
}
|
|
}
|
|
}
|