diff --git a/Utilities/BindingConverters/BoolConverter.cs b/Utilities/BindingConverters/BoolConverter.cs index 6294d2f..678aea7 100644 --- a/Utilities/BindingConverters/BoolConverter.cs +++ b/Utilities/BindingConverters/BoolConverter.cs @@ -11,11 +11,19 @@ namespace Connected public BoolConverter() { - SetFunc = OnSet; - GetFunc = OnGet; } - private T OnGet(bool? value) + protected override bool? ConvertValue(T? value) + { + return OnSet(value); + } + + protected override T? ConvertValueBack(bool? value) + { + return OnGet(value); + } + + private T OnGet(bool? value) { try { @@ -31,12 +39,12 @@ namespace Connected return (T)(object)(value == true ? 1 : (value == false ? (int?)0 : null)); else { - UpdateGetError($"Conversion to type {typeof(T)} not implemented"); + TriggerError($"Conversion to type {typeof(T)} not implemented"); } } catch (Exception e) { - UpdateGetError("Conversion error: " + e.Message); + TriggerError("Conversion error: " + e.Message); return default(T); } return default(T); @@ -69,13 +77,13 @@ namespace Connected } else { - UpdateSetError("Unable to convert to bool? from type " + typeof(T).Name); + TriggerError("Unable to convert to bool? from type " + typeof(T).Name); return null; } } catch (FormatException e) { - UpdateSetError("Conversion error: " + e.Message); + TriggerError("Conversion error: " + e.Message); return null; } } diff --git a/Utilities/BindingConverters/Converter.cs b/Utilities/BindingConverters/Converter.cs index 6610817..2f97eab 100644 --- a/Utilities/BindingConverters/Converter.cs +++ b/Utilities/BindingConverters/Converter.cs @@ -1,88 +1,111 @@ -using System; -using System.Globalization; +using System.Globalization; -namespace Connected -{ - public class Converter - { - public Func SetFunc { get; set; } - public Func GetFunc { get; set; } +namespace Connected; - /// - /// The culture info being used for decimal points, date and time format, etc. - /// - public CultureInfo Culture { get; set; } = Converters.DefaultCulture; +public class Converter +{ + public event EventHandler? ErrorOccured; - public Action OnError { get; set; } - public bool SetError { get; set; } - public bool GetError { get; set; } - public string SetErrorMessage { get; set; } - public string GetErrorMessage { get; set; } + /// + /// The culture info being used for decimal points, date and time format, etc. + /// + public CultureInfo Culture { get; set; } = Converters.DefaultCulture; - public U Set(T value) + public TDestinationType? Convert(TSourceType value) + { + try { - SetError = false; - SetErrorMessage = null; - if (SetFunc == null) - return default(U); - try - { - return SetFunc(value); - } - catch (Exception e) - { - SetError = true; - SetErrorMessage = $"Conversion from {typeof(T).Name} to {typeof(U).Name} failed: {e.Message}"; - } - return default(U); + return ConvertValue(value); } - - public T Get(U value) + catch (Exception e) { - GetError = false; - GetErrorMessage = null; - if (GetFunc == null) - return default(T); - try - { - return GetFunc(value); - } - catch (Exception e) - { - GetError = true; - GetErrorMessage = $"Conversion from {typeof(U).Name} to {typeof(T).Name} failed: {e.Message}"; - } - return default(T); + TriggerError($"Conversion from {typeof(TSourceType).Name} to {typeof(TDestinationType).Name} failed: {e.Message}", e); } - protected void UpdateSetError(string msg) + return default; + } + + protected virtual TDestinationType? ConvertValue(TSourceType? value) + { + return default; + } + + public TSourceType? ConvertBack(TDestinationType value) + { + try { - SetError = true; - SetErrorMessage = msg; - OnError?.Invoke(msg); + return ConvertValueBack(value); } - - protected void UpdateGetError(string msg) + catch (Exception e) { - GetError = true; - GetErrorMessage = msg; - OnError?.Invoke(msg); + TriggerError($"Conversion from {typeof(TDestinationType).Name} to {typeof(TSourceType).Name} failed: {e.Message}", e); } + + return default; } - /// - /// Converter from T to string - /// - /// Set converts to string - /// Get converts from string - /// - public class Converter : Converter + protected virtual TSourceType? ConvertValueBack(TDestinationType? value) { + return default; + } - /// - /// Custom Format to be applied on bidirectional way. - /// - public string Format { get; set; } = null; + protected void TriggerError(string? msg, Exception? e = null) + { + ErrorOccured?.Invoke(this, msg); + OnErrorOccured(msg, e); } + + protected virtual void OnErrorOccured(string? msg, Exception? e) + { + + } +} + +/// +/// Converts values using the supplied lambda functions. +/// +/// The source type +/// The destination type +public class LambdaConverter :Converter +{ + private readonly Func? _convertFunction; + private readonly Func? _convertBackFunction; + + public LambdaConverter(Func? convertFunction = null, Func? convertBackFunction = null) + { + _convertFunction = convertFunction; + _convertBackFunction = convertBackFunction; + } + + protected override TDestinationType? ConvertValue(TSourceType? value) + { + if (_convertFunction is null) + return base.ConvertValue(value); + + return _convertFunction.Invoke(value); + } + + protected override TSourceType? ConvertValueBack(TDestinationType? value) + { + if (_convertFunction is null) + return base.ConvertValueBack(value); + + return _convertBackFunction.Invoke(value); + } +} + +/// +/// Converter from T to string +/// +/// Set converts to string +/// Get converts from string +/// +public class ToStringConverter : Converter +{ + + /// + /// Custom Format to be applied on bidirectional way. + /// + public string? Format { get; set; } = null; } diff --git a/Utilities/BindingConverters/Converters.cs b/Utilities/BindingConverters/Converters.cs index 505e242..3bff428 100644 --- a/Utilities/BindingConverters/Converters.cs +++ b/Utilities/BindingConverters/Converters.cs @@ -1,4 +1,5 @@ -using System.Globalization; +using Connected.Extensions; +using System.Globalization; namespace Connected { @@ -7,9 +8,8 @@ namespace Connected public static CultureInfo DefaultCulture = CultureInfo.CurrentUICulture; #region --> Date converters - public static Converter IsoDate - => new() - { SetFunc = SetIsoDate, GetFunc = GetIsoDate }; + public static LambdaConverter IsoDate + => new(SetIsoDate, GetIsoDate); private static DateTime GetIsoDate(string value) { @@ -23,11 +23,10 @@ namespace Connected return value.ToIsoDateString(); } - public static Converter NullableIsoDate - => new() - { SetFunc = SetNullableIsoDate, GetFunc = GetNullableIsoDate }; + public static LambdaConverter NullableIsoDate + => new(SetNullableIsoDate, GetNullableIsoDate); - private static DateTime? GetNullableIsoDate(string value) + private static DateTime? GetNullableIsoDate(string? value) { if (DateTime.TryParse(value, out var dateTime)) return dateTime; diff --git a/Utilities/BindingConverters/DateConverter.cs b/Utilities/BindingConverters/DateConverter.cs index 5712ba1..789c8ab 100644 --- a/Utilities/BindingConverters/DateConverter.cs +++ b/Utilities/BindingConverters/DateConverter.cs @@ -6,18 +6,26 @@ namespace Connected /// /// A ready made DateTime? to string binding converter with configurable date format and culture /// - public class NullableDateConverter : Converter + public class NullableDateConverter : ToStringConverter { public string DateFormat { get; set; } public NullableDateConverter(string format = "yyyy-MM-dd") { DateFormat = format; - SetFunc = OnSet; - GetFunc = OnGet; } - private DateTime? OnGet(string arg) + protected override string? ConvertValue(DateTime? value) + { + return OnSet(value); + } + + protected override DateTime? ConvertValueBack(string? value) + { + return OnGet(value); + } + + private DateTime? OnGet(string arg) { try { @@ -25,7 +33,7 @@ namespace Connected } catch (FormatException e) { - UpdateGetError(e.Message); + TriggerError(e.Message); return null; } } @@ -40,7 +48,7 @@ namespace Connected } catch (FormatException e) { - UpdateSetError(e.Message); + TriggerError(e.Message); return null; } } @@ -49,18 +57,26 @@ namespace Connected /// /// A ready made DateTime to string binding converter with configurable date format and culture /// - public class DateConverter : Converter + public class DateConverter : ToStringConverter { public string DateFormat { get; set; } = "yyyy-MM-dd"; public DateConverter(string format) { DateFormat = format; - SetFunc = OnSet; - GetFunc = OnGet; } - private DateTime OnGet(string arg) + protected override string? ConvertValue(DateTime value) + { + return OnSet(value); + } + + protected override DateTime ConvertValueBack(string value) + { + return OnGet(value); + } + + private DateTime OnGet(string arg) { try { @@ -68,7 +84,7 @@ namespace Connected } catch (FormatException e) { - UpdateGetError(e.Message); + TriggerError(e.Message); return default; } } @@ -81,7 +97,7 @@ namespace Connected } catch (FormatException e) { - UpdateSetError(e.Message); + TriggerError(e.Message); return null; } } diff --git a/Utilities/BindingConverters/DefaultConverter.cs b/Utilities/BindingConverters/DefaultConverter.cs index 09f7173..38bd620 100644 --- a/Utilities/BindingConverters/DefaultConverter.cs +++ b/Utilities/BindingConverters/DefaultConverter.cs @@ -7,16 +7,24 @@ namespace Connected /// /// A universal T to string binding converter /// - public class DefaultConverter : Converter + public class DefaultConverter : ToStringConverter { public DefaultConverter() { - SetFunc = ConvertToString; - GetFunc = ConvertFromString; } - public string DefaultTimeSpanFormat { get; set; } = "c"; + protected override string? ConvertValue(T? value) + { + return ConvertToString(value); + } + + protected override T? ConvertValueBack(string? value) + { + return ConvertFromString(value); + } + + public string DefaultTimeSpanFormat { get; set; } = "c"; protected virtual T ConvertFromString(string value) { @@ -42,91 +50,91 @@ namespace Connected return (T)(object)true; if (lowerValue is "false" or "off") return (T)(object)false; - UpdateGetError("Not a valid boolean"); + TriggerError("Not a valid boolean"); } // sbyte else if (typeof(T) == typeof(sbyte) || typeof(T) == typeof(sbyte?)) { if (sbyte.TryParse(value, NumberStyles.Integer | NumberStyles.AllowThousands, Culture, out var parsedValue)) return (T)(object)parsedValue; - UpdateGetError("Not a valid number"); + TriggerError("Not a valid number"); } // byte else if (typeof(T) == typeof(byte) || typeof(T) == typeof(byte?)) { if (byte.TryParse(value, NumberStyles.Integer | NumberStyles.AllowThousands, Culture, out var parsedValue)) return (T)(object)parsedValue; - UpdateGetError("Not a valid number"); + TriggerError("Not a valid number"); } // short else if (typeof(T) == typeof(short) || typeof(T) == typeof(short?)) { if (short.TryParse(value, NumberStyles.Integer | NumberStyles.AllowThousands, Culture, out var parsedValue)) return (T)(object)parsedValue; - UpdateGetError("Not a valid number"); + TriggerError("Not a valid number"); } // ushort else if (typeof(T) == typeof(ushort) || typeof(T) == typeof(ushort?)) { if (ushort.TryParse(value, NumberStyles.Integer | NumberStyles.AllowThousands, Culture, out var parsedValue)) return (T)(object)parsedValue; - UpdateGetError("Not a valid number"); + TriggerError("Not a valid number"); } // int else if (typeof(T) == typeof(int) || typeof(T) == typeof(int?)) { if (int.TryParse(value, NumberStyles.Integer | NumberStyles.AllowThousands, Culture, out var parsedValue)) return (T)(object)parsedValue; - UpdateGetError("Not a valid number"); + TriggerError("Not a valid number"); } // uint else if (typeof(T) == typeof(uint) || typeof(T) == typeof(uint?)) { if (uint.TryParse(value, NumberStyles.Integer | NumberStyles.AllowThousands, Culture, out var parsedValue)) return (T)(object)parsedValue; - UpdateGetError("Not a valid number"); + TriggerError("Not a valid number"); } // long else if (typeof(T) == typeof(long) || typeof(T) == typeof(long?)) { if (long.TryParse(value, NumberStyles.Integer | NumberStyles.AllowThousands, Culture, out var parsedValue)) return (T)(object)parsedValue; - UpdateGetError("Not a valid number"); + TriggerError("Not a valid number"); } // ulong else if (typeof(T) == typeof(ulong) || typeof(T) == typeof(ulong?)) { if (ulong.TryParse(value, NumberStyles.Integer | NumberStyles.AllowThousands, Culture, out var parsedValue)) return (T)(object)parsedValue; - UpdateGetError("Not a valid number"); + TriggerError("Not a valid number"); } // float else if (typeof(T) == typeof(float) || typeof(T) == typeof(float?)) { if (float.TryParse(value, NumberStyles.Any, Culture, out var parsedValue)) return (T)(object)parsedValue; - UpdateGetError("Not a valid number"); + TriggerError("Not a valid number"); } // double else if (typeof(T) == typeof(double) || typeof(T) == typeof(double?)) { if (double.TryParse(value, NumberStyles.Any, Culture, out var parsedValue)) return (T)(object)parsedValue; - UpdateGetError("Not a valid number"); + TriggerError("Not a valid number"); } // decimal else if (typeof(T) == typeof(decimal) || typeof(T) == typeof(decimal?)) { if (decimal.TryParse(value, NumberStyles.Any, Culture, out var parsedValue)) return (T)(object)parsedValue; - UpdateGetError("Not a valid number"); + TriggerError("Not a valid number"); } // guid else if (typeof(T) == typeof(Guid) || typeof(T) == typeof(Guid?)) { if (Guid.TryParse(value, out var parsedValue)) return (T)(object)parsedValue; - UpdateGetError("Not a valid GUID"); + TriggerError("Not a valid GUID"); } // enum else if (IsNullableEnum(typeof(T))) @@ -134,13 +142,13 @@ namespace Connected var enum_type = Nullable.GetUnderlyingType(typeof(T)); if (Enum.TryParse(enum_type, value, out var parsedValue)) return (T)parsedValue; - UpdateGetError("Not a value of " + enum_type.Name); + TriggerError("Not a value of " + enum_type.Name); } else if (typeof(T).IsEnum) { if (Enum.TryParse(typeof(T), value, out var parsedValue)) return (T)parsedValue; - UpdateGetError("Not a value of " + typeof(T).Name); + TriggerError("Not a value of " + typeof(T).Name); } // datetime else if (typeof(T) == typeof(DateTime) || typeof(T) == typeof(DateTime?)) @@ -151,7 +159,7 @@ namespace Connected } catch (FormatException) { - UpdateGetError("Not a valid date time"); + TriggerError("Not a valid date time"); } } // timespan @@ -163,17 +171,17 @@ namespace Connected } catch (FormatException) { - UpdateGetError("Not a valid time span"); + TriggerError("Not a valid time span"); } } else { - UpdateGetError($"Conversion to type {typeof(T)} not implemented"); + TriggerError($"Conversion to type {typeof(T)} not implemented"); } } catch (Exception e) { - UpdateGetError("Conversion error: " + e.Message); + TriggerError("Conversion error: " + e.Message); } return default(T); @@ -301,7 +309,7 @@ namespace Connected } catch (FormatException e) { - UpdateSetError("Conversion error: " + e.Message); + TriggerError("Conversion error: " + e.Message); return null; } } diff --git a/Utilities/BindingConverters/NumericConverter.cs b/Utilities/BindingConverters/NumericConverter.cs index 9db5016..bc6cafb 100644 --- a/Utilities/BindingConverters/NumericConverter.cs +++ b/Utilities/BindingConverters/NumericConverter.cs @@ -17,11 +17,19 @@ namespace Connected public NumericConverter() { - SetFunc = OnSet; - GetFunc = OnGet; } - private T OnGet(double value) + protected override double ConvertValue(T? value) + { + return OnSet(value); + } + + protected override T? ConvertValueBack(double value) + { + return OnGet(value); + } + + private T OnGet(double value) { try { @@ -33,42 +41,42 @@ namespace Connected return (T)(object)value.ToString(Culture); // sbyte else if (typeof(T) == typeof(sbyte) || typeof(T) == typeof(sbyte?)) - return (T)(object)Convert.ToSByte(value); + return (T)(object)System.Convert.ToSByte(value); // byte else if (typeof(T) == typeof(byte) || typeof(T) == typeof(byte?)) - return (T)(object)Convert.ToByte(value); + return (T)(object)System.Convert.ToByte(value); // short else if (typeof(T) == typeof(short) || typeof(T) == typeof(short?)) - return (T)(object)Convert.ToInt16(value); + return (T)(object)System.Convert.ToInt16(value); // ushort else if (typeof(T) == typeof(ushort) || typeof(T) == typeof(ushort?)) - return (T)(object)Convert.ToUInt16(value); + return (T)(object)System.Convert.ToUInt16(value); // int else if (typeof(T) == typeof(int) || typeof(T) == typeof(int?)) - return (T)(object)Convert.ToInt32(value); + return (T)(object)System.Convert.ToInt32(value); // uint else if (typeof(T) == typeof(uint) || typeof(T) == typeof(uint?)) - return (T)(object)Convert.ToUInt32(value); + return (T)(object)System.Convert.ToUInt32(value); // long else if (typeof(T) == typeof(long) || typeof(T) == typeof(long?)) - return (T)(object)Convert.ToInt64(value); + return (T)(object)System.Convert.ToInt64(value); // ulong else if (typeof(T) == typeof(ulong) || typeof(T) == typeof(ulong?)) - return (T)(object)Convert.ToUInt64(value); + return (T)(object)System.Convert.ToUInt64(value); // float else if (typeof(T) == typeof(float) || typeof(T) == typeof(float?)) - return (T)(object)Convert.ToSingle(value); + return (T)(object)System.Convert.ToSingle(value); // decimal else if (typeof(T) == typeof(decimal) || typeof(T) == typeof(decimal?)) - return (T)(object)Convert.ToDecimal(value); + return (T)(object)System.Convert.ToDecimal(value); else { - UpdateGetError($"Conversion to type {typeof(T)} not implemented"); + TriggerError($"Conversion to type {typeof(T)} not implemented"); } } catch (Exception e) { - UpdateGetError("Conversion error: " + e.Message); + TriggerError("Conversion error: " + e.Message); return default(T); } return default(T); @@ -90,63 +98,63 @@ namespace Connected return double.Parse((string)(object)arg, NumberStyles.Any, Culture); // sbyte if (typeof(T) == typeof(sbyte)) - return Convert.ToDouble((sbyte)(object)arg); + return System.Convert.ToDouble((sbyte)(object)arg); if (typeof(T) == typeof(sbyte?)) - return Convert.ToDouble(((sbyte?)(object)arg).Value); + return System.Convert.ToDouble(((sbyte?)(object)arg).Value); // byte if (typeof(T) == typeof(byte)) - return Convert.ToDouble((byte)(object)arg); + return System.Convert.ToDouble((byte)(object)arg); if (typeof(T) == typeof(byte?)) - return Convert.ToDouble(((byte?)(object)arg).Value); + return System.Convert.ToDouble(((byte?)(object)arg).Value); // short if (typeof(T) == typeof(short)) - return Convert.ToDouble((short)(object)arg); + return System.Convert.ToDouble((short)(object)arg); if (typeof(T) == typeof(short?)) - return Convert.ToDouble(((short?)(object)arg).Value); + return System.Convert.ToDouble(((short?)(object)arg).Value); // ushort if (typeof(T) == typeof(ushort)) - return Convert.ToDouble((ushort)(object)arg); + return System.Convert.ToDouble((ushort)(object)arg); if (typeof(T) == typeof(ushort?)) - return Convert.ToDouble(((ushort?)(object)arg).Value); + return System.Convert.ToDouble(((ushort?)(object)arg).Value); // int else if (typeof(T) == typeof(int)) - return Convert.ToDouble((int)(object)arg); + return System.Convert.ToDouble((int)(object)arg); else if (typeof(T) == typeof(int?)) - return Convert.ToDouble(((int?)(object)arg).Value); + return System.Convert.ToDouble(((int?)(object)arg).Value); // uint else if (typeof(T) == typeof(uint)) - return Convert.ToDouble((uint)(object)arg); + return System.Convert.ToDouble((uint)(object)arg); else if (typeof(T) == typeof(uint?)) - return Convert.ToDouble(((uint?)(object)arg).Value); + return System.Convert.ToDouble(((uint?)(object)arg).Value); // long else if (typeof(T) == typeof(long)) - return Convert.ToDouble((long)(object)arg); + return System.Convert.ToDouble((long)(object)arg); else if (typeof(T) == typeof(long?)) - return Convert.ToDouble(((long?)(object)arg).Value); + return System.Convert.ToDouble(((long?)(object)arg).Value); // ulong else if (typeof(T) == typeof(ulong)) - return Convert.ToDouble((ulong)(object)arg); + return System.Convert.ToDouble((ulong)(object)arg); else if (typeof(T) == typeof(ulong?)) - return Convert.ToDouble(((ulong?)(object)arg).Value); + return System.Convert.ToDouble(((ulong?)(object)arg).Value); // float else if (typeof(T) == typeof(float)) - return Convert.ToDouble((float)(object)arg); + return System.Convert.ToDouble((float)(object)arg); else if (typeof(T) == typeof(float?)) - return Convert.ToDouble(((float?)(object)arg).Value); + return System.Convert.ToDouble(((float?)(object)arg).Value); // decimal else if (typeof(T) == typeof(decimal)) - return Convert.ToDouble((decimal)(object)arg); + return System.Convert.ToDouble((decimal)(object)arg); else if (typeof(T) == typeof(decimal?)) - return Convert.ToDouble(((decimal?)(object)arg).Value); + return System.Convert.ToDouble(((decimal?)(object)arg).Value); else { - UpdateSetError("Unable to convert to double from type " + typeof(T).Name); + TriggerError("Unable to convert to double from type " + typeof(T).Name); return double.NaN; } } catch (FormatException e) { - UpdateSetError("Conversion error: " + e.Message); + TriggerError("Conversion error: " + e.Message); return double.NaN; } } diff --git a/Utilities/BindingConverters/RangeConverter.cs b/Utilities/BindingConverters/RangeConverter.cs index 5fd067b..a0aa6a5 100644 --- a/Utilities/BindingConverters/RangeConverter.cs +++ b/Utilities/BindingConverters/RangeConverter.cs @@ -1,61 +1,69 @@ -namespace Connected +using Connected.Components; + +namespace Connected; + +public class RangeConverter : ToStringConverter> { - public class RangeConverter : Converter> - { - readonly DefaultConverter _converter; + readonly DefaultConverter _converter; + + public RangeConverter() + { + _converter = new DefaultConverter(); + } - public RangeConverter() - { - _converter = new DefaultConverter(); + protected override string? ConvertValue(Range? value) + { + return OnSet(value); + } - SetFunc = OnSet; - GetFunc = OnGet; - } + protected override Range? ConvertValueBack(string? value) + { + return OnGet(value); + } - private Components.Range OnGet(string value) - { - if (!Split(value, out var valueStart, out var valueEnd)) - return null; + private Range OnGet(string value) + { + if (!Split(value, out var valueStart, out var valueEnd)) + return null; - return new Components.Range(_converter.Get(valueStart), _converter.Get(valueEnd)); - } + return new Range(_converter.ConvertBack(valueStart), _converter.ConvertBack(valueEnd)); + } - private string OnSet(Components.Range arg) - { - if (arg == null) - return string.Empty; + private string OnSet(Range arg) + { + if (arg == null) + return string.Empty; - return Join(_converter.Set(arg.Start), _converter.Set(arg.End)); - } + return Join(_converter.Convert(arg.Start), _converter.Convert(arg.End)); + } - public static string Join(string valueStart, string valueEnd) - { - if (string.IsNullOrEmpty(valueStart) && string.IsNullOrEmpty(valueEnd)) - return string.Empty; + public static string Join(string valueStart, string valueEnd) + { + if (string.IsNullOrEmpty(valueStart) && string.IsNullOrEmpty(valueEnd)) + return string.Empty; - return $"[{valueStart};{valueEnd}]"; - } + return $"[{valueStart};{valueEnd}]"; + } - public static bool Split(string value, out string valueStart, out string valueEnd) - { - valueStart = valueEnd = string.Empty; + public static bool Split(string value, out string valueStart, out string valueEnd) + { + valueStart = valueEnd = string.Empty; - if (string.IsNullOrEmpty(value) || value[0] != '[' || value[^1] != ']') - { - return false; - } + if (string.IsNullOrEmpty(value) || value[0] != '[' || value[^1] != ']') + { + return false; + } - var idx = value.IndexOf(';'); + var idx = value.IndexOf(';'); - if (idx < 1) - { - return false; - } + if (idx < 1) + { + return false; + } - valueStart = value[1..idx]; - valueEnd = value[(idx + 1)..^1]; + valueStart = value[1..idx]; + valueEnd = value[(idx + 1)..^1]; - return true; - } - } + return true; + } }