208 lines
6.7 KiB
C#
208 lines
6.7 KiB
C#
using Prism.Mvvm;
|
||
using System;
|
||
using System.Globalization;
|
||
using System.Linq;
|
||
using XP.ImageProcessing.Core;
|
||
|
||
namespace XplorePlane.ViewModels
|
||
{
|
||
public class ProcessorParameterVM : BindableBase
|
||
{
|
||
private object _value;
|
||
private bool _isValueValid = true;
|
||
|
||
public ProcessorParameterVM(ProcessorParameter parameter)
|
||
{
|
||
Name = parameter.Name;
|
||
DisplayName = parameter.DisplayName;
|
||
_value = parameter.Value;
|
||
MinValue = parameter.MinValue;
|
||
MaxValue = parameter.MaxValue;
|
||
Options = parameter.Options;
|
||
ParameterType = parameter.ValueType?.Name?.ToLowerInvariant() switch
|
||
{
|
||
"int32" or "int" => "int",
|
||
"double" => "double",
|
||
"boolean" or "bool" => "bool",
|
||
_ => "enum"
|
||
};
|
||
ValidateValue(_value);
|
||
}
|
||
|
||
public string Name { get; }
|
||
public string DisplayName { get; }
|
||
public object MinValue { get; }
|
||
public object MaxValue { get; }
|
||
public string[]? Options { get; }
|
||
public string ParameterType { get; }
|
||
|
||
public bool IsValueValid
|
||
{
|
||
get => _isValueValid;
|
||
private set => SetProperty(ref _isValueValid, value);
|
||
}
|
||
|
||
public object Value
|
||
{
|
||
get => _value;
|
||
set
|
||
{
|
||
var normalizedValue = NormalizeValue(value);
|
||
if (SetProperty(ref _value, normalizedValue))
|
||
ValidateValue(normalizedValue);
|
||
}
|
||
}
|
||
|
||
private void ValidateValue(object value)
|
||
{
|
||
if (value == null)
|
||
{
|
||
IsValueValid = false;
|
||
return;
|
||
}
|
||
|
||
if (ParameterType == "int")
|
||
{
|
||
IsValueValid = TryConvertToInt(value, out var intValue) && IsWithinRange(intValue);
|
||
return;
|
||
}
|
||
|
||
if (ParameterType == "double")
|
||
{
|
||
IsValueValid = TryConvertToDouble(value, out var doubleValue) && IsWithinRange(doubleValue);
|
||
return;
|
||
}
|
||
|
||
if (ParameterType == "bool")
|
||
{
|
||
IsValueValid = TryConvertToBool(value, out _);
|
||
return;
|
||
}
|
||
|
||
if (Options is { Length: > 0 })
|
||
{
|
||
var stringValue = Convert.ToString(value, CultureInfo.InvariantCulture) ?? string.Empty;
|
||
IsValueValid = Options.Contains(stringValue, StringComparer.OrdinalIgnoreCase);
|
||
return;
|
||
}
|
||
|
||
IsValueValid = true;
|
||
}
|
||
|
||
private object NormalizeValue(object value)
|
||
{
|
||
if (value == null)
|
||
return value;
|
||
|
||
if (ParameterType == "int" && TryConvertToInt(value, out var intValue))
|
||
return intValue;
|
||
|
||
if (ParameterType == "double" && TryConvertToDouble(value, out var doubleValue))
|
||
return doubleValue;
|
||
|
||
if (ParameterType == "bool" && TryConvertToBool(value, out var boolValue))
|
||
return boolValue;
|
||
|
||
return value;
|
||
}
|
||
|
||
private bool IsWithinRange(double value)
|
||
{
|
||
if (MinValue != null && TryConvertToDouble(MinValue, out var minValue) && value < minValue)
|
||
return false;
|
||
|
||
if (MaxValue != null && TryConvertToDouble(MaxValue, out var maxValue) && value > maxValue)
|
||
return false;
|
||
|
||
return true;
|
||
}
|
||
|
||
private static string NormalizeNumericText(string value)
|
||
{
|
||
return value.Trim().TrimEnd('、', ',', ',', '。', '.', ';', ';', ':', ':');
|
||
}
|
||
|
||
private static bool TryConvertToInt(object value, out int result)
|
||
{
|
||
switch (value)
|
||
{
|
||
case int intValue:
|
||
result = intValue;
|
||
return true;
|
||
case string stringValue:
|
||
stringValue = NormalizeNumericText(stringValue);
|
||
return int.TryParse(stringValue, NumberStyles.Integer, CultureInfo.InvariantCulture, out result)
|
||
|| int.TryParse(stringValue, NumberStyles.Integer, CultureInfo.CurrentCulture, out result);
|
||
default:
|
||
try
|
||
{
|
||
result = Convert.ToInt32(value, CultureInfo.InvariantCulture);
|
||
return true;
|
||
}
|
||
catch
|
||
{
|
||
result = default;
|
||
return false;
|
||
}
|
||
}
|
||
}
|
||
|
||
private static bool TryConvertToDouble(object value, out double result)
|
||
{
|
||
switch (value)
|
||
{
|
||
case double doubleValue:
|
||
result = doubleValue;
|
||
return true;
|
||
case float floatValue:
|
||
result = floatValue;
|
||
return true;
|
||
case int intValue:
|
||
result = intValue;
|
||
return true;
|
||
case long longValue:
|
||
result = longValue;
|
||
return true;
|
||
case string stringValue:
|
||
stringValue = NormalizeNumericText(stringValue);
|
||
return double.TryParse(stringValue, NumberStyles.Float | NumberStyles.AllowThousands, CultureInfo.InvariantCulture, out result)
|
||
|| double.TryParse(stringValue, NumberStyles.Float | NumberStyles.AllowThousands, CultureInfo.CurrentCulture, out result);
|
||
default:
|
||
try
|
||
{
|
||
result = Convert.ToDouble(value, CultureInfo.InvariantCulture);
|
||
return true;
|
||
}
|
||
catch
|
||
{
|
||
result = default;
|
||
return false;
|
||
}
|
||
}
|
||
}
|
||
|
||
private static bool TryConvertToBool(object value, out bool result)
|
||
{
|
||
switch (value)
|
||
{
|
||
case bool boolValue:
|
||
result = boolValue;
|
||
return true;
|
||
case string stringValue:
|
||
return bool.TryParse(stringValue.Trim(), out result);
|
||
default:
|
||
try
|
||
{
|
||
result = Convert.ToBoolean(value, CultureInfo.InvariantCulture);
|
||
return true;
|
||
}
|
||
catch
|
||
{
|
||
result = default;
|
||
return false;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|