9 changed files with 254 additions and 65 deletions
@ -0,0 +1,68 @@ |
|||||
|
// -----------------------------------------------------------------------
|
||||
|
// <copyright file="SelectorTests.cs" company="Steven Kirk">
|
||||
|
// Copyright 2014 MIT Licence. See licence.md for more information.
|
||||
|
// </copyright>
|
||||
|
// -----------------------------------------------------------------------
|
||||
|
|
||||
|
namespace Perspex.UnitTests.Styling |
||||
|
{ |
||||
|
using System; |
||||
|
using System.Linq; |
||||
|
using System.Reactive; |
||||
|
using System.Reactive.Linq; |
||||
|
using Microsoft.VisualStudio.TestTools.UnitTesting; |
||||
|
using Perspex.Styling; |
||||
|
using Match = Perspex.Styling.Match; |
||||
|
|
||||
|
[TestClass] |
||||
|
public class SelectorTests |
||||
|
{ |
||||
|
[TestMethod] |
||||
|
public void OfType_Matches_Control_Of_Correct_Type() |
||||
|
{ |
||||
|
var control = new Class1(); |
||||
|
var target = control.Select().OfType<Class1>(); |
||||
|
|
||||
|
CollectionAssert.AreEqual(new[] { true }, target.GetActivator().Take(1).ToEnumerable().ToArray()); |
||||
|
} |
||||
|
|
||||
|
[TestMethod] |
||||
|
public void OfType_Doesnt_Match_Control_Of_Wrong_Type() |
||||
|
{ |
||||
|
var control = new Class2(); |
||||
|
var target = control.Select().OfType<Class1>(); |
||||
|
|
||||
|
CollectionAssert.AreEqual(new[] { false }, target.GetActivator().Take(1).ToEnumerable().ToArray()); |
||||
|
} |
||||
|
|
||||
|
[TestMethod] |
||||
|
public void When_OfType_Matches_Control_Other_Selectors_Are_Subscribed() |
||||
|
{ |
||||
|
var control = new Class1(); |
||||
|
var target = control.Select().OfType<Class1>().SubscribeCheck(); |
||||
|
|
||||
|
var result = target.GetActivator().ToEnumerable().Take(1).ToArray(); |
||||
|
|
||||
|
Assert.AreEqual(1, control.SubscribeCheckObservable.SubscribedCount); |
||||
|
} |
||||
|
|
||||
|
[TestMethod] |
||||
|
public void When_OfType_Doesnt_Match_Control_Other_Selectors_Are_Not_Subscribed() |
||||
|
{ |
||||
|
var control = new Class1(); |
||||
|
var target = control.Select().OfType<Class2>().SubscribeCheck(); |
||||
|
|
||||
|
var result = target.GetActivator().ToEnumerable().Take(1).ToArray(); |
||||
|
|
||||
|
Assert.AreEqual(0, control.SubscribeCheckObservable.SubscribedCount); |
||||
|
} |
||||
|
|
||||
|
public class Class1 : SubscribeCheck |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
public class Class2 : SubscribeCheck |
||||
|
{ |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,59 @@ |
|||||
|
// -----------------------------------------------------------------------
|
||||
|
// <copyright file="SubscribeCheck.cs" company="Steven Kirk">
|
||||
|
// Copyright 2014 MIT Licence. See licence.md for more information.
|
||||
|
// </copyright>
|
||||
|
// -----------------------------------------------------------------------
|
||||
|
|
||||
|
namespace Perspex.UnitTests.Styling |
||||
|
{ |
||||
|
using System; |
||||
|
using System.Reactive.Disposables; |
||||
|
using Perspex.Styling; |
||||
|
using Match = Perspex.Styling.Match; |
||||
|
|
||||
|
public class TestObservable : IObservable<bool> |
||||
|
{ |
||||
|
public int SubscribedCount { get; private set; } |
||||
|
|
||||
|
public IDisposable Subscribe(IObserver<bool> observer) |
||||
|
{ |
||||
|
++this.SubscribedCount; |
||||
|
observer.OnNext(true); |
||||
|
return Disposable.Create(() => --this.SubscribedCount); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public class SubscribeCheck : IStyleable |
||||
|
{ |
||||
|
public SubscribeCheck() |
||||
|
{ |
||||
|
this.Classes = new PerspexList<string>(); |
||||
|
this.SubscribeCheckObservable = new TestObservable(); |
||||
|
} |
||||
|
|
||||
|
public PerspexList<string> Classes |
||||
|
{ |
||||
|
get; |
||||
|
private set; |
||||
|
} |
||||
|
|
||||
|
public TestObservable SubscribeCheckObservable |
||||
|
{ |
||||
|
get; |
||||
|
private set; |
||||
|
} |
||||
|
|
||||
|
public virtual void SetValue(PerspexProperty property, object value, IObservable<bool> activator) |
||||
|
{ |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public static class TestSelectors |
||||
|
{ |
||||
|
public static Match SubscribeCheck(this Match match) |
||||
|
{ |
||||
|
match.Observables.Add(((SubscribeCheck)match.Control).SubscribeCheckObservable); |
||||
|
return match; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,89 @@ |
|||||
|
// -----------------------------------------------------------------------
|
||||
|
// <copyright file="Activator.cs" company="Steven Kirk">
|
||||
|
// Copyright 2014 MIT Licence. See licence.md for more information.
|
||||
|
// </copyright>
|
||||
|
// -----------------------------------------------------------------------
|
||||
|
|
||||
|
namespace Perspex.Styling |
||||
|
{ |
||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Diagnostics.Contracts; |
||||
|
using System.Linq; |
||||
|
using System.Reactive.Disposables; |
||||
|
|
||||
|
public class Activator : IObservable<bool> |
||||
|
{ |
||||
|
List<bool> values = new List<bool>(); |
||||
|
|
||||
|
List<IDisposable> subscriptions = new List<IDisposable>(); |
||||
|
|
||||
|
List<IObserver<bool>> observers = new List<IObserver<bool>>(); |
||||
|
|
||||
|
bool last = false; |
||||
|
|
||||
|
public Activator(IList<IObservable<bool>> observables) |
||||
|
{ |
||||
|
int i = 0; |
||||
|
|
||||
|
foreach (IObservable<bool> o in observables.Reverse()) |
||||
|
{ |
||||
|
int iCaptured = i; |
||||
|
|
||||
|
this.values.Add(false); |
||||
|
|
||||
|
IDisposable subscription = o.Subscribe( |
||||
|
x => this.Update(iCaptured, x), |
||||
|
x => this.Finish(iCaptured), |
||||
|
() => this.Finish(iCaptured)); |
||||
|
|
||||
|
this.subscriptions.Add(subscription); |
||||
|
|
||||
|
++i; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public IDisposable Subscribe(IObserver<bool> observer) |
||||
|
{ |
||||
|
Contract.Requires<ArgumentNullException>(observer != null); |
||||
|
|
||||
|
this.observers.Add(observer); |
||||
|
observer.OnNext(last); |
||||
|
return Disposable.Create(() => this.observers.Remove(observer)); |
||||
|
} |
||||
|
|
||||
|
private void Update(int index, bool value) |
||||
|
{ |
||||
|
this.values[index] = value; |
||||
|
|
||||
|
bool current = this.values.All(x => x); |
||||
|
|
||||
|
if (current != last) |
||||
|
{ |
||||
|
this.Push(current); |
||||
|
last = current; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
private void Finish(int i) |
||||
|
{ |
||||
|
if (!this.values[i]) |
||||
|
{ |
||||
|
// If the observable has finished on 'false' then it will never go back to true
|
||||
|
// so we can unsubscribe from all the other subscriptions now.
|
||||
|
foreach (IDisposable subscription in this.subscriptions) |
||||
|
{ |
||||
|
subscription.Dispose(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
private void Push(bool value) |
||||
|
{ |
||||
|
foreach (IObserver<bool> observer in this.observers) |
||||
|
{ |
||||
|
observer.OnNext(value); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
Loading…
Reference in new issue