Skip to content

Setting Value

A layer setting can be of different types, however changes of these settings are propagated via a single method OnSettingChanged. The definition of setting value massively simplifies the task of supporting and propagating multiple value types.

The setting value is defined like this.

internal enum SettingValueType
{
    Integer,
    Float,
    String,
    Color,
}

public struct SettingValue
{
    private SettingValueType Type { get; }

    private readonly int _intValue;
    private readonly float _singleValue;
    private readonly string _stringValue;
    private readonly SKColor _colorValue;

    // Constructors
    public SettingValue(int value)
    {
        Type = SettingValueType.Integer;
        _intValue = value;

        _singleValue = 0;
        _stringValue = null;
        _colorValue = new SKColor();
    }

    public SettingValue(float value)
    {
        Type = SettingValueType.Float;
        _singleValue = value;

        _intValue = 0;
        _stringValue = null;
        _colorValue = new SKColor();
    }

    public SettingValue(string value)
    {
        Type = SettingValueType.String;
        _stringValue = value;

        _intValue = 0;
        _singleValue = 0;
        _colorValue = new SKColor();
    }

    public SettingValue(SKColor value)
    {
        Type = SettingValueType.Color;
        _colorValue = value;

        _intValue = 0;
        _stringValue = null;
        _singleValue = 0;
    }

    // Value Retrieval
    public int ToInt()
    {
        switch (Type)
        {
            case SettingValueType.Integer:
                return _intValue;

            case SettingValueType.Float:
                return (int)Math.Round(_singleValue);

            default:
                throw new InvalidCastException($"Cannot cast setting value type '{Type}' to int.");
        }
    }

    public float ToSingle()
    {
        switch (Type)
        {
            case SettingValueType.Integer:
                return _intValue;

            case SettingValueType.Float:
                return _singleValue;

            default:
                throw new InvalidCastException($"Cannot cast setting value type '{Type}' to float.");
        }
    }

    public override string ToString()
    {
        switch (Type)
        {
            case SettingValueType.String:
                return _stringValue;

            default:
                throw new InvalidCastException($"Cannot cast setting value type '{Type}' to string.");
        }
    }

    public SKColor ToColor()
    {
        switch (Type)
        {
            case SettingValueType.Color:
                return _colorValue;

            default:
                throw new InvalidCastException($"Cannot cast setting value type '{Type}' to color.");
        }
    }

    // Conversions to other types
    public static implicit operator int(SettingValue settingValue)
    {
        return settingValue.ToInt();
    }

    public static implicit operator float(SettingValue settingValue)
    {
        return settingValue.ToSingle();
    }

    public static implicit operator string(SettingValue settingValue)
    {
        return settingValue.ToString();
    }

    public static implicit operator SKColor(SettingValue settingValue)
    {
        return settingValue.ToColor();
    }

    public static implicit operator Range<float>(SettingValue settingValue)
    {
        return settingValue.ToSingle();
    }

    // Conversions from other types
    public static implicit operator SettingValue(int value)
    {
        return new SettingValue(value);
    }

    public static implicit operator SettingValue(float value)
    {
        return new SettingValue(value);
    }

    public static implicit operator SettingValue(string value)
    {
        return new SettingValue(value);
    }

    public static implicit operator SettingValue(SKColor value)
    {
        return new SettingValue(value);
    }
}

Read more: