|
|
|
|
using System.Globalization;
|
|
|
|
|
|
|
|
|
|
namespace SRDebugger.UI.Controls.Data
|
|
|
|
|
{
|
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using SRF;
|
|
|
|
|
using SRF.UI;
|
|
|
|
|
using UnityEngine;
|
|
|
|
|
using UnityEngine.UI;
|
|
|
|
|
|
|
|
|
|
public class NumberControl : DataBoundControl
|
|
|
|
|
{
|
|
|
|
|
private static readonly Type[] IntegerTypes =
|
|
|
|
|
{
|
|
|
|
|
typeof (int), typeof (short), typeof (byte), typeof (sbyte), typeof (uint), typeof (ushort)
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
private static readonly Type[] DecimalTypes =
|
|
|
|
|
{
|
|
|
|
|
typeof (float), typeof (double)
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
public static readonly Dictionary<Type, ValueRange> ValueRanges = new Dictionary<Type, ValueRange>
|
|
|
|
|
{
|
|
|
|
|
{typeof (int), new ValueRange {MaxValue = int.MaxValue, MinValue = int.MinValue}},
|
|
|
|
|
{typeof (short), new ValueRange {MaxValue = short.MaxValue, MinValue = short.MinValue}},
|
|
|
|
|
{typeof (byte), new ValueRange {MaxValue = byte.MaxValue, MinValue = byte.MinValue}},
|
|
|
|
|
{typeof (sbyte), new ValueRange {MaxValue = sbyte.MaxValue, MinValue = sbyte.MinValue}},
|
|
|
|
|
{typeof (uint), new ValueRange {MaxValue = uint.MaxValue, MinValue = uint.MinValue}},
|
|
|
|
|
{typeof (ushort), new ValueRange {MaxValue = ushort.MaxValue, MinValue = ushort.MinValue}},
|
|
|
|
|
{typeof (float), new ValueRange {MaxValue = float.MaxValue, MinValue = float.MinValue}},
|
|
|
|
|
{typeof (double), new ValueRange {MaxValue = double.MaxValue, MinValue = double.MinValue}}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
private string _lastValue;
|
|
|
|
|
private Type _type;
|
|
|
|
|
public GameObject[] DisableOnReadOnly;
|
|
|
|
|
public SRNumberButton DownNumberButton;
|
|
|
|
|
|
|
|
|
|
[RequiredField] public SRNumberSpinner NumberSpinner;
|
|
|
|
|
|
|
|
|
|
[RequiredField] public Text Title;
|
|
|
|
|
|
|
|
|
|
public SRNumberButton UpNumberButton;
|
|
|
|
|
|
|
|
|
|
protected override void Start()
|
|
|
|
|
{
|
|
|
|
|
base.Start();
|
|
|
|
|
NumberSpinner.onEndEdit.AddListener(OnValueChanged);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void OnValueChanged(string newValue)
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
var num = Convert.ChangeType(newValue, _type, CultureInfo.InvariantCulture);
|
|
|
|
|
UpdateValue(num);
|
|
|
|
|
}
|
|
|
|
|
catch (Exception)
|
|
|
|
|
{
|
|
|
|
|
NumberSpinner.text = _lastValue;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected override void OnBind(string propertyName, Type t)
|
|
|
|
|
{
|
|
|
|
|
base.OnBind(propertyName, t);
|
|
|
|
|
Title.text = propertyName;
|
|
|
|
|
|
|
|
|
|
if (IsIntegerType(t))
|
|
|
|
|
{
|
|
|
|
|
NumberSpinner.contentType = InputField.ContentType.IntegerNumber;
|
|
|
|
|
}
|
|
|
|
|
else if (IsDecimalType(t))
|
|
|
|
|
{
|
|
|
|
|
NumberSpinner.contentType = InputField.ContentType.DecimalNumber;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
throw new ArgumentException("Type must be one of expected types", "t");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var rangeAttrib = Property.GetAttribute<NumberRangeAttribute>();
|
|
|
|
|
|
|
|
|
|
NumberSpinner.MaxValue = GetMaxValue(t);
|
|
|
|
|
NumberSpinner.MinValue = GetMinValue(t);
|
|
|
|
|
|
|
|
|
|
if (rangeAttrib != null)
|
|
|
|
|
{
|
|
|
|
|
NumberSpinner.MaxValue = Math.Min(rangeAttrib.Max, NumberSpinner.MaxValue);
|
|
|
|
|
NumberSpinner.MinValue = Math.Max(rangeAttrib.Min, NumberSpinner.MinValue);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var incrementAttribute = Property.GetAttribute<IncrementAttribute>();
|
|
|
|
|
|
|
|
|
|
if (incrementAttribute != null)
|
|
|
|
|
{
|
|
|
|
|
if (UpNumberButton != null)
|
|
|
|
|
{
|
|
|
|
|
UpNumberButton.Amount = incrementAttribute.Increment;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (DownNumberButton != null)
|
|
|
|
|
{
|
|
|
|
|
DownNumberButton.Amount = -incrementAttribute.Increment;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_type = t;
|
|
|
|
|
|
|
|
|
|
NumberSpinner.interactable = !IsReadOnly;
|
|
|
|
|
|
|
|
|
|
if (DisableOnReadOnly != null)
|
|
|
|
|
{
|
|
|
|
|
foreach (var childControl in DisableOnReadOnly)
|
|
|
|
|
{
|
|
|
|
|
childControl.SetActive(!IsReadOnly);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected override void OnValueUpdated(object newValue)
|
|
|
|
|
{
|
|
|
|
|
var value = Convert.ToDecimal(newValue, CultureInfo.InvariantCulture).ToString(CultureInfo.InvariantCulture);
|
|
|
|
|
|
|
|
|
|
if (value != _lastValue)
|
|
|
|
|
{
|
|
|
|
|
NumberSpinner.text = value;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_lastValue = value;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override bool CanBind(Type type, bool isReadOnly)
|
|
|
|
|
{
|
|
|
|
|
return IsDecimalType(type) || IsIntegerType(type);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected static bool IsIntegerType(Type t)
|
|
|
|
|
{
|
|
|
|
|
for (var i = 0; i < IntegerTypes.Length; i++)
|
|
|
|
|
{
|
|
|
|
|
if (IntegerTypes[i] == t)
|
|
|
|
|
{
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected static bool IsDecimalType(Type t)
|
|
|
|
|
{
|
|
|
|
|
for (var i = 0; i < DecimalTypes.Length; i++)
|
|
|
|
|
{
|
|
|
|
|
if (DecimalTypes[i] == t)
|
|
|
|
|
{
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected double GetMaxValue(Type t)
|
|
|
|
|
{
|
|
|
|
|
ValueRange value;
|
|
|
|
|
if (ValueRanges.TryGetValue(t, out value))
|
|
|
|
|
{
|
|
|
|
|
return value.MaxValue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Debug.LogWarning("[NumberControl] No MaxValue stored for type {0}".Fmt(t));
|
|
|
|
|
|
|
|
|
|
return double.MaxValue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected double GetMinValue(Type t)
|
|
|
|
|
{
|
|
|
|
|
ValueRange value;
|
|
|
|
|
if (ValueRanges.TryGetValue(t, out value))
|
|
|
|
|
{
|
|
|
|
|
return value.MinValue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Debug.LogWarning("[NumberControl] No MinValue stored for type {0}".Fmt(t));
|
|
|
|
|
|
|
|
|
|
return double.MinValue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public struct ValueRange
|
|
|
|
|
{
|
|
|
|
|
public double MaxValue;
|
|
|
|
|
public double MinValue;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|