using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using UnityEngine;
namespace Chronos.Controls.Editor
{
///
/// Utility class to display complex editor popups.
///
public static class PopupGUI
{
public delegate void PopupCallback(T value);
///
/// Render an editor popup and return the newly selected option.
///
/// The position of the control.
/// The function called when a value is selected.
/// The list of available options.
/// The selected option, or null for none.
/// The option for "no selection", or null for none.
/// Whether the content has multiple different values.
/// Whether a selected option not in range should be allowed.
public static void Render
(
Rect position,
PopupCallback callback,
IEnumerable> options,
PopupOption selectedOption,
PopupOption noneOption,
bool hasMultipleDifferentValues,
bool allowOuterOption = true
)
{
bool hasOptions = options != null && options.Any();
string label;
if (hasMultipleDifferentValues)
{
label = "\u2014"; // Em Dash
}
else if (selectedOption == null)
{
if (noneOption != null)
{
label = noneOption.label;
}
else
{
label = string.Empty;
}
}
else
{
label = selectedOption.label;
}
if (GUI.Button(position, label, EditorStyles.popup))
{
GenericMenu menu = new GenericMenu();
GenericMenu.MenuFunction2 menuCallback = (o) => callback((T)o);
if (noneOption != null)
{
bool on = !hasMultipleDifferentValues && (selectedOption == null || EqualityComparer.Default.Equals(selectedOption.value, noneOption.value));
menu.AddItem(new GUIContent(noneOption.label), on, menuCallback, noneOption.value);
}
if (noneOption != null && hasOptions)
{
menu.AddSeparator("");
}
if (hasOptions)
{
foreach (var option in options)
{
bool on = !hasMultipleDifferentValues && (selectedOption != null && EqualityComparer.Default.Equals(selectedOption.value, option.value));
menu.AddItem(new GUIContent(option.label), on, menuCallback, option.value);
}
}
Vector2 menuPosition = new Vector2(position.xMin, position.yMax);
menu.DropDown(new Rect(menuPosition, Vector2.zero));
}
else if (selectedOption != null && !options.Select(o => o.value).Contains(selectedOption.value) && !allowOuterOption)
{
// Selected option isn't in range
if (hasMultipleDifferentValues)
{
// Do nothing
}
else if (noneOption != null)
{
callback(noneOption.value);
}
else
{
callback(default(T));
}
}
}
}
}