public async Task CombinableEnum()
        {
            var enumObj = new EnumClass();

            var           provider = new ReflectionEditorProvider();
            IObjectEditor editor   = await provider.GetObjectEditorAsync(enumObj);

            List <int> values = new List <int> ();

            values.Add((int)FlagsTestEnum.Flag1);
            values.Add((int)FlagsTestEnum.Flag3);

            FlagsTestEnum expected = FlagsTestEnum.Flag1 | FlagsTestEnum.Flag3;

            await editor.SetValueAsync(editor.Properties.First(), new ValueInfo <IReadOnlyList <int> > {
                Value = values
            });

            ValueInfo <int> underlying = await editor.GetValueAsync <int> (editor.Properties.First());

            Assert.That((FlagsTestEnum)underlying.Value, Is.EqualTo(expected));

            ValueInfo <IReadOnlyList <int> > underlyingList = await editor.GetValueAsync <IReadOnlyList <int> > (editor.Properties.First());

            Assert.That(underlyingList.Value, Contains.Item((int)FlagsTestEnum.Flag1));
            Assert.That(underlyingList.Value, Contains.Item((int)FlagsTestEnum.Flag3));
        }
        public void ValidatorClearInvalid()
        {
            FlagsTestEnum value = FlagsTestEnum.Flag2;

            var p         = GetPropertyMock();
            var validator = p.As <IValidator <IReadOnlyList <int> > > ();

            validator.Setup(l => l.IsValid(It.IsAny <IReadOnlyList <int> > ())).Returns <IReadOnlyList <int> > (l => !(l == null || l.Count == 0));

            var target     = new object();
            var editorMock = new Mock <IObjectEditor> ();

            editorMock.SetupGet(e => e.Target).Returns(target);
            editorMock.Setup(e => e.GetValueAsync <IReadOnlyList <int> > (p.Object, null)).ReturnsAsync(
                new ValueInfo <IReadOnlyList <int> > {
                Value  = new int[] { (int)FlagsTestEnum.Flag2 },
                Source = ValueSource.Local
            });
            editorMock.Setup(e => e.GetValueAsync <int> (p.Object, null)).ReturnsAsync(new ValueInfo <int> {
                Value  = (int)value,
                Source = ValueSource.Local
            });

            ValueInfo <IReadOnlyList <int> > setValue = null;

            editorMock.Setup(oe => oe.SetValueAsync(p.Object, It.IsAny <ValueInfo <IReadOnlyList <int> > > (), null))
            .Callback <IPropertyInfo, ValueInfo <IReadOnlyList <int> >, PropertyVariation> ((pi, v, variation) => {
                setValue = v;
                editorMock.Setup(e => e.GetValueAsync <IReadOnlyList <int> > (p.Object, null)).ReturnsAsync(v);

                int rv = 0;
                for (int i = 0; i < v.Value.Count; i++)
                {
                    rv |= v.Value[i];
                }

                editorMock.Setup(e => e.GetValueAsync <int> (p.Object, null)).ReturnsAsync(new ValueInfo <int> {
                    Value  = rv,
                    Source = ValueSource.Local
                });
                editorMock.Raise(oe => oe.PropertyChanged += null, new EditorPropertyChangedEventArgs(p.Object));
            })
            .Returns(Task.FromResult(true));

            var vm = GetViewModel(p.Object, editorMock.Object);

            Assume.That(vm.Choices.Count, Is.EqualTo(7));
            Assume.That(vm.Value, Is.EqualTo((int)value));

            value = FlagsTestEnum.Flag2;
            vm.Choices.Single(c => c.Value == (int)FlagsTestEnum.Flag2).IsFlagged = false;
            Assert.That(setValue, Is.Not.Null, "Did not call setvalue");
            CollectionAssert.AreEquivalent(new[] { (int)value }, setValue.Value);
            Assert.That(vm.Value, Is.EqualTo((int)value));
        }
        public void SetFlags()
        {
            FlagsTestEnum value = FlagsTestEnum.Flag2 | FlagsTestEnum.Flag3;

            var p = GetPropertyMock();

            var target     = new object();
            var editorMock = new Mock <IObjectEditor> ();

            editorMock.SetupGet(e => e.Target).Returns(target);
            editorMock.Setup(e => e.GetValueAsync <IReadOnlyList <int> > (p.Object, null)).ReturnsAsync(
                new ValueInfo <IReadOnlyList <int> > {
                Value  = new int[] { (int)FlagsTestEnum.Flag2, (int)FlagsTestEnum.Flag3 },
                Source = ValueSource.Local
            });
            editorMock.Setup(e => e.GetValueAsync <int> (p.Object, null)).ReturnsAsync(new ValueInfo <int> {
                Value  = (int)value,
                Source = ValueSource.Local
            });

            ValueInfo <IReadOnlyList <int> > setValue = null;

            editorMock.Setup(oe => oe.SetValueAsync(p.Object, It.IsAny <ValueInfo <IReadOnlyList <int> > > (), null))
            .Callback <IPropertyInfo, ValueInfo <IReadOnlyList <int> >, PropertyVariation> ((pi, v, variation) => {
                setValue = v;
                editorMock.Setup(e => e.GetValueAsync <IReadOnlyList <int> > (p.Object, null)).ReturnsAsync(v);

                int rv = 0;
                for (int i = 0; i < v.Value.Count; i++)
                {
                    rv |= v.Value[i];
                }

                editorMock.Setup(e => e.GetValueAsync <int> (p.Object, null)).ReturnsAsync(new ValueInfo <int> {
                    Value  = rv,
                    Source = ValueSource.Local
                });
                editorMock.Raise(oe => oe.PropertyChanged += null, new EditorPropertyChangedEventArgs(p.Object));
            });

            var vm = GetViewModel(p.Object, editorMock.Object);

            Assume.That(vm.Choices.Count, Is.EqualTo(7));
            Assume.That(vm.Value, Is.EqualTo((int)value));

            value |= FlagsTestEnum.Flag1;
            vm.Choices[1].IsFlagged = true;
            Assert.That(setValue, Is.Not.Null, "Did not call setvalue");
            CollectionAssert.AreEquivalent(new[] { (int)FlagsTestEnum.Flag1, (int)FlagsTestEnum.Flag2, (int)FlagsTestEnum.Flag3 }, setValue.Value);
            Assert.That(vm.Value, Is.EqualTo((int)value));
        }
        public void GetsFlags()
        {
            FlagsTestEnum value = FlagsTestEnum.Flag2 | FlagsTestEnum.Flag3;

            var p = GetPropertyMock();

            var target     = new object();
            var editorMock = new Mock <IObjectEditor> ();

            editorMock.SetupGet(e => e.Target).Returns(target);
            editorMock.Setup(e => e.GetValueAsync <IReadOnlyList <int> > (p.Object, null)).ReturnsAsync(
                new ValueInfo <IReadOnlyList <int> > {
                Value  = new int[] { (int)FlagsTestEnum.Flag2, (int)FlagsTestEnum.Flag3 },
                Source = ValueSource.Local
            });
            editorMock.Setup(e => e.GetValueAsync <int> (p.Object, null)).ReturnsAsync(new ValueInfo <int> {
                Value  = (int)value,
                Source = ValueSource.Local
            });

            var vm = GetViewModel(p.Object, editorMock.Object);

            Assume.That(vm.Choices.Count, Is.EqualTo(7));

            var flag2Choice = vm.Choices.Single(v => v.Name == nameof(FlagsTestEnum.Flag2));

            Assume.That(flag2Choice.Value, Is.EqualTo((int)FlagsTestEnum.Flag2));
            var flag3Choice = vm.Choices.Single(v => v.Name == nameof(FlagsTestEnum.Flag3));

            Assume.That(flag3Choice.Value, Is.EqualTo((int)FlagsTestEnum.Flag3));

            Assert.That(vm.Value, Is.EqualTo((int)value));
            Assert.That(flag2Choice.IsFlagged.HasValue && flag2Choice.IsFlagged.Value, Is.True);
            Assert.That(flag3Choice.IsFlagged.HasValue && flag3Choice.IsFlagged.Value, Is.True);
            Assert.That(vm.Choices.Count(v => v.IsFlagged.HasValue && !v.IsFlagged.Value), Is.EqualTo(5), "Unselected choices not marked false");
        }
        public void GetsFlagsDisasgree()
        {
            FlagsTestEnum value  = FlagsTestEnum.Flag2 | FlagsTestEnum.Flag3;
            FlagsTestEnum value2 = FlagsTestEnum.Flag2 | FlagsTestEnum.Flag4;

            var p = GetPropertyMock();

            var target     = new object();
            var editorMock = new Mock <IObjectEditor> ();

            editorMock.SetupGet(e => e.Target).Returns(target);
            editorMock.Setup(e => e.GetValueAsync <IReadOnlyList <int> > (p.Object, null)).ReturnsAsync(
                new ValueInfo <IReadOnlyList <int> > {
                Value  = new int[] { (int)FlagsTestEnum.Flag2, (int)FlagsTestEnum.Flag3 },
                Source = ValueSource.Local
            });
            editorMock.Setup(e => e.GetValueAsync <int> (p.Object, null)).ReturnsAsync(new ValueInfo <int> {
                Value  = (int)value,
                Source = ValueSource.Local
            });

            var target2     = new object();
            var editorMock2 = new Mock <IObjectEditor> ();

            editorMock2.SetupGet(e => e.Target).Returns(target2);
            editorMock2.Setup(e => e.GetValueAsync <IReadOnlyList <int> > (p.Object, null)).ReturnsAsync(
                new ValueInfo <IReadOnlyList <int> > {
                Value  = new int[] { (int)FlagsTestEnum.Flag2, (int)FlagsTestEnum.Flag4 },
                Source = ValueSource.Local
            });
            editorMock2.Setup(e => e.GetValueAsync <int> (p.Object, null)).ReturnsAsync(new ValueInfo <int> {
                Value  = (int)value2,
                Source = ValueSource.Local
            });

            var vm = GetViewModel(p.Object, new[] { editorMock.Object, editorMock2.Object });

            Assume.That(vm.Choices.Count, Is.EqualTo(7));

            var flag2Choice = vm.Choices.Single(v => v.Name == nameof(FlagsTestEnum.Flag2));

            Assume.That(flag2Choice.Value, Is.EqualTo((int)FlagsTestEnum.Flag2));
            var flag3Choice = vm.Choices.Single(v => v.Name == nameof(FlagsTestEnum.Flag3));

            Assume.That(flag3Choice.Value, Is.EqualTo((int)FlagsTestEnum.Flag3));
            var flag4Choice = vm.Choices.Single(v => v.Name == nameof(FlagsTestEnum.Flag4));

            Assume.That(flag4Choice.Value, Is.EqualTo((int)FlagsTestEnum.Flag4));
            var flag5Choice = vm.Choices.Single(v => v.Name == nameof(FlagsTestEnum.Flag5));

            Assume.That(flag5Choice.Value, Is.EqualTo((int)FlagsTestEnum.Flag5));

            Assert.That(vm.Value, Is.EqualTo(default(int)));
            Assert.That(vm.MultipleValues, Is.True, "MultipleValues is not marked true for disagreeing values");
            Assert.That(flag2Choice.IsFlagged.HasValue && flag2Choice.IsFlagged.Value, Is.True);
            Assert.That(flag3Choice.IsFlagged.HasValue, Is.False, "Disagreed upon choice is indeterminate");
            Assert.That(flag4Choice.IsFlagged.HasValue, Is.False, "Disagreed upon choice is indeterminate");
            // We expect 5 to match 4's behavior, they should set, unset, and be indeterminate together.
            Assert.That(flag5Choice.IsFlagged.HasValue, Is.False, "Disagreed upon duplicate choice is indeterminate");
            Assert.That(vm.Choices.Count(v => v.IsFlagged.HasValue && !v.IsFlagged.Value), Is.EqualTo(3), "Unselected choices not marked false");
        }
        public async Task SetFlagsMultipleValues()
        {
            FlagsTestEnum value  = FlagsTestEnum.Flag2 | FlagsTestEnum.Flag3;
            FlagsTestEnum value2 = FlagsTestEnum.Flag2 | FlagsTestEnum.Flag4;

            var p = GetPropertyMock();

            var editor = new MockObjectEditor(p.Object);
            await editor.SetValueAsync(p.Object, new ValueInfo <int> {
                Value  = (int)value,
                Source = ValueSource.Local
            });

            var editor2 = new MockObjectEditor(p.Object);
            await editor2.SetValueAsync(p.Object, new ValueInfo <int> {
                Value  = (int)value2,
                Source = ValueSource.Local
            });

            var vm = GetViewModel(p.Object, new [] { editor, editor2 });

            Assume.That(vm.Choices.Count, Is.EqualTo(7));
            Assume.That(vm.Value, Is.EqualTo(default(int)));

            var flag1Choice = vm.Choices.Single(v => v.Name == nameof(FlagsTestEnum.Flag1));

            Assume.That(flag1Choice.Value, Is.EqualTo((int)FlagsTestEnum.Flag1));
            Assume.That(flag1Choice.IsFlagged.HasValue && !flag1Choice.IsFlagged.Value);
            var flag2Choice = vm.Choices.Single(v => v.Name == nameof(FlagsTestEnum.Flag2));

            Assume.That(flag2Choice.Value, Is.EqualTo((int)FlagsTestEnum.Flag2));
            Assume.That(flag2Choice.IsFlagged.HasValue && flag2Choice.IsFlagged.Value, Is.True);
            var flag3Choice = vm.Choices.Single(v => v.Name == nameof(FlagsTestEnum.Flag3));

            Assume.That(flag3Choice.Value, Is.EqualTo((int)FlagsTestEnum.Flag3));
            Assume.That(flag3Choice.IsFlagged.HasValue, Is.False);
            var flag4Choice = vm.Choices.Single(v => v.Name == nameof(FlagsTestEnum.Flag4));

            Assume.That(flag4Choice.Value, Is.EqualTo((int)FlagsTestEnum.Flag4));
            Assume.That(flag4Choice.IsFlagged.HasValue, Is.False);
            var flag5Choice = vm.Choices.Single(v => v.Name == nameof(FlagsTestEnum.Flag5));

            Assume.That(flag5Choice.Value, Is.EqualTo((int)FlagsTestEnum.Flag5));
            Assume.That(flag5Choice.IsFlagged.HasValue, Is.False);

            flag1Choice.IsFlagged = true;

            Assert.That(flag1Choice.IsFlagged, Is.True);
            Assert.That(flag2Choice.IsFlagged, Is.True);
            Assert.That(flag3Choice.IsFlagged, Is.Null);
            Assert.That(flag4Choice.IsFlagged, Is.Null);
            Assert.That(flag5Choice.IsFlagged, Is.Null);
            Assert.That(vm.Value, Is.EqualTo(default(int)));

            var setValue = await editor.GetValueAsync <IReadOnlyList <int> > (p.Object);

            var setValue2 = await editor2.GetValueAsync <IReadOnlyList <int> > (p.Object);

            CollectionAssert.AreEquivalent(new[] { (int)FlagsTestEnum.Flag1, (int)FlagsTestEnum.Flag2, (int)FlagsTestEnum.Flag3 }, setValue.Value);
            CollectionAssert.AreEquivalent(new[] { (int)FlagsTestEnum.Flag1, (int)FlagsTestEnum.Flag2, (int)FlagsTestEnum.Flag4, (int)FlagsTestEnum.Flag5 }, setValue2.Value);
        }