<commit_before>﻿// Copyright (c) 2007-2017 ppy Pty Ltd <<EMAIL>>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu-framework/master/LICENCE

using System;
using System.Collections.Generic;
using osu.Framework.Lists;

namespace osu.Framework.Configuration
{
    public class Bindable<T> : IBindable
    {
        private T value;

        public T Default;

        private bool disabled;

        public bool Disabled
        {
            get { return disabled; }
            set
            {
                if (disabled == value) return;

                disabled = value;

                TriggerDisabledChange();
            }
        }

        public delegate void BindableValueChanged<in TValue>(TValue newValue);

        public delegate void BindableDisabledChanged(bool isDisabled);

        public virtual bool IsDefault => Equals(value, Default);

        public event BindableValueChanged<T> ValueChanged;

        public event BindableDisabledChanged DisabledChanged;

        public virtual T Value
        {
            get { return value; }
            set
            {
                if (EqualityComparer<T>.Default.Equals(this.value, value)) return;

                if (Disabled)
                    throw new InvalidOperationException($"Can not set value to \"{value.ToString()}\" as bindable is disabled.");

                this.value = value;

                TriggerValueChange();
            }
        }

        public Bindable(T value = default(T))
        {
            this.value = value;
        }

        public static implicit operator T(Bindable<T> value)
        {
            return value.Value;
        }

        private WeakList<Bindable<T>> bindings = new WeakList<Bindable<T>>();

        private WeakReference<Bindable<T>> weakReference;
        //be lazy and reuse because WeakReference is kind of "heavy"
        public WeakReference<Bindable<T>> WeakReference => weakReference ?? (weakReference = new WeakReference<Bindable<T>>(this));

        /// <summary>
        /// Binds outselves to another bindable such that they receive bi-directional updates.
        /// We will take on any value limitations of the bindable we bind width.
        /// </summary>
        /// <param name="them">The foreign bindable. This should always be the most permanent end of the bind (ie. a ConfigManager)</param>
        public virtual void BindTo(Bindable<T> them)
        {
            Value = them.Value;
            Disabled = them.Disabled;

            AddWeakReference(them.WeakReference);
            them.AddWeakReference(WeakReference);
        }

        protected void AddWeakReference(WeakReference<Bindable<T>> weakReference) => bindings.Add(weakReference);

        public virtual void Parse(object s)
        {
            if (s is T)
                Value = (T)s;
            else if (typeof(T).IsEnum && s is string)
                Value = (T)Enum.Parse(typeof(T), (string)s);
            else
                throw new ArgumentException($@"Could not parse provided {s.GetType()} ({s}) to {typeof(T)}.");
        }

        public void TriggerChange()
        {
            TriggerValueChange();<commit_msg>Be lazy on WeakList. We are creating too many, much more than WeakReference itself.<commit_after>﻿// Copyright (c) 2007-2017 ppy Pty Ltd <<EMAIL>>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu-framework/master/LICENCE

using System;
using System.Collections.Generic;
using osu.Framework.Lists;

namespace osu.Framework.Configuration
{
    public class Bindable<T> : IBindable
    {
        private T value;

        public T Default;

        private bool disabled;

        public bool Disabled
        {
            get { return disabled; }
            set
            {
                if (disabled == value) return;

                disabled = value;

                TriggerDisabledChange();
            }
        }

        public delegate void BindableValueChanged<in TValue>(TValue newValue);

        public delegate void BindableDisabledChanged(bool isDisabled);

        public virtual bool IsDefault => Equals(value, Default);

        public event BindableValueChanged<T> ValueChanged;

        public event BindableDisabledChanged DisabledChanged;

        public virtual T Value
        {
            get { return value; }
            set
            {
                if (EqualityComparer<T>.Default.Equals(this.value, value)) return;

                if (Disabled)
                    throw new InvalidOperationException($"Can not set value to \"{value.ToString()}\" as bindable is disabled.");

                this.value = value;

                TriggerValueChange();
            }
        }

        public Bindable(T value = default(T))
        {
            this.value = value;
        }

        public static implicit operator T(Bindable<T> value)
        {
            return value.Value;
        }

        private WeakList<Bindable<T>> bindings;

        private WeakReference<Bindable<T>> weakReference;
        //be lazy and reuse because WeakReference is kind of "heavy"
        public WeakReference<Bindable<T>> WeakReference => weakReference ?? (weakReference = new WeakReference<Bindable<T>>(this));

        /// <summary>
        /// Binds outselves to another bindable such that they receive bi-directional updates.
        /// We will take on any value limitations of the bindable we bind width.
        /// </summary>
        /// <param name="them">The foreign bindable. This should always be the most permanent end of the bind (ie. a ConfigManager)</param>
        public virtual void BindTo(Bindable<T> them)
        {
            Value = them.Value;
            Disabled = them.Disabled;

            AddWeakReference(them.WeakReference);
            them.AddWeakReference(WeakReference);
        }

        protected void AddWeakReference(WeakReference<Bindable<T>> weakReference)
        {
            if (bindings == null)
                bindings = new WeakList<Bindable<T>>();

            bindings.Add(weakReference);
        }

        public virtual void Parse(object s)
        {
            if (s is T)
                Value = (T)s;
            else if (typeof(T).IsEnum && s is string)
                Value = (T)Enum.Parse(typeof(T), (string)s);
            else
                throw new ArgumentException($@"Could not parse provided {s.GetType()} ({s}) to {typeof(T)}.");
        }

        public void TriggerChange()
        {
            TriggerValueChange();
{'fraction_non_alphanumeric': 0.09327217125382263, 'fraction_numerical': 0.0024464831804281344, 'mean_word_length': 1.9187862561356537, 'pattern_counts': {'":': 0, '<': 51, '<?xml version=': 0, '>': 56, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7645651', 'n_tokens_mistral': 1749, 'n_tokens_neox': 1615, 'n_words': 490}