199 lines
		
	
	
		
			6.1 KiB
		
	
	
	
		
			C#
		
	
	
	
		
		
			
		
	
	
			199 lines
		
	
	
		
			6.1 KiB
		
	
	
	
		
			C#
		
	
	
	
|  | 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; | |||
|  |         } | |||
|  |     } | |||
|  | } |