45 changed files with 914 additions and 479 deletions
@ -1,4 +1,9 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<packages> |
|||
<package id="Rx-Core" version="2.2.5" targetFramework="portable45-net45+win8" /> |
|||
<package id="Rx-Interfaces" version="2.2.5" targetFramework="portable45-net45+win8" /> |
|||
<package id="Rx-Linq" version="2.2.5" targetFramework="portable45-net45+win8" /> |
|||
<package id="Rx-Main" version="2.2.5" targetFramework="portable45-net45+win8" /> |
|||
<package id="Rx-PlatformServices" version="2.2.5" targetFramework="portable45-net45+win8" /> |
|||
<package id="Splat" version="1.6.2" targetFramework="portable45-net45+win8" /> |
|||
</packages> |
|||
@ -0,0 +1,16 @@ |
|||
// Copyright (c) The Perspex Project. All rights reserved.
|
|||
// Licensed under the MIT license. See licence.md file in the project root for full license information.
|
|||
|
|||
using System; |
|||
using System.Reactive.Subjects; |
|||
|
|||
namespace Perspex.Reactive |
|||
{ |
|||
public class AnonymousSubject<T> : AnonymousSubject<T, T>, ISubject<T> |
|||
{ |
|||
public AnonymousSubject(IObserver<T> observer, IObservable<T> observable) |
|||
: base(observer, observable) |
|||
{ |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,49 @@ |
|||
// Copyright (c) The Perspex Project. All rights reserved.
|
|||
// Licensed under the MIT license. See licence.md file in the project root for full license information.
|
|||
|
|||
using System; |
|||
using System.Reactive.Subjects; |
|||
|
|||
namespace Perspex.Reactive |
|||
{ |
|||
public class AnonymousSubject<T, U> : ISubject<T, U> |
|||
{ |
|||
private readonly IObserver<T> _observer; |
|||
private readonly IObservable<U> _observable; |
|||
|
|||
public AnonymousSubject(IObserver<T> observer, IObservable<U> observable) |
|||
{ |
|||
_observer = observer; |
|||
_observable = observable; |
|||
} |
|||
|
|||
public void OnCompleted() |
|||
{ |
|||
_observer.OnCompleted(); |
|||
} |
|||
|
|||
public void OnError(Exception error) |
|||
{ |
|||
if (error == null) |
|||
throw new ArgumentNullException("error"); |
|||
|
|||
_observer.OnError(error); |
|||
} |
|||
|
|||
public void OnNext(T value) |
|||
{ |
|||
_observer.OnNext(value); |
|||
} |
|||
|
|||
public IDisposable Subscribe(IObserver<U> observer) |
|||
{ |
|||
if (observer == null) |
|||
throw new ArgumentNullException("observer"); |
|||
|
|||
//
|
|||
// [OK] Use of unsafe Subscribe: non-pretentious wrapping of an observable sequence.
|
|||
//
|
|||
return _observable.Subscribe/*Unsafe*/(observer); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,36 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Text; |
|||
using System.Threading.Tasks; |
|||
using Perspex.Media; |
|||
|
|||
namespace Perspex.Controls.Shapes |
|||
{ |
|||
public class Line : Shape |
|||
{ |
|||
private Geometry _geometry; |
|||
|
|||
private Size _geometrySize; |
|||
|
|||
public override Geometry DefiningGeometry |
|||
{ |
|||
get |
|||
{ |
|||
if (_geometry == null || _geometrySize != Bounds.Size) |
|||
{ |
|||
var rect = new Rect(Bounds.Size).Deflate(StrokeThickness); |
|||
_geometry = new LineGeometry(rect.TopLeft, rect.BottomRight); |
|||
_geometrySize = Bounds.Size; |
|||
} |
|||
|
|||
return _geometry; |
|||
} |
|||
} |
|||
|
|||
protected override Size MeasureOverride(Size availableSize) |
|||
{ |
|||
return new Size(StrokeThickness, StrokeThickness); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,47 @@ |
|||
// Copyright (c) The Perspex Project. All rights reserved.
|
|||
// Licensed under the MIT license. See licence.md file in the project root for full license information.
|
|||
|
|||
using Perspex.Platform; |
|||
|
|||
namespace Perspex.Media |
|||
{ |
|||
/// <summary>
|
|||
/// Represents the geometry of a line.
|
|||
/// </summary>
|
|||
public class LineGeometry : Geometry |
|||
{ |
|||
private Point _startPoint; |
|||
private Point _endPoint; |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="LineGeometry"/> class.
|
|||
/// </summary>
|
|||
/// <param name="startPoint">The start point.</param>
|
|||
/// <param name="endPoint">The end point.</param>
|
|||
public LineGeometry(Point startPoint, Point endPoint) |
|||
{ |
|||
_startPoint = startPoint; |
|||
_endPoint = endPoint; |
|||
IPlatformRenderInterface factory = PerspexLocator.Current.GetService<IPlatformRenderInterface>(); |
|||
IStreamGeometryImpl impl = factory.CreateStreamGeometry(); |
|||
|
|||
using (IStreamGeometryContextImpl context = impl.Open()) |
|||
{ |
|||
context.BeginFigure(startPoint, false); |
|||
context.LineTo(endPoint); |
|||
context.EndFigure(false); |
|||
} |
|||
|
|||
PlatformImpl = impl; |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public override Rect Bounds => new Rect(_startPoint, _endPoint); |
|||
|
|||
/// <inheritdoc/>
|
|||
public override Geometry Clone() |
|||
{ |
|||
return new LineGeometry(Bounds.TopLeft, Bounds.BottomRight); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,74 @@ |
|||
// Copyright (c) The Perspex Project. All rights reserved.
|
|||
// Licensed under the MIT license. See licence.md file in the project root for full license information.
|
|||
|
|||
using System; |
|||
using System.Reactive; |
|||
using System.Reactive.Linq; |
|||
|
|||
namespace Perspex.Styling |
|||
{ |
|||
/// <summary>
|
|||
/// An observable which is switched on or off according to an activator observable.
|
|||
/// </summary>
|
|||
/// <remarks>
|
|||
/// An <see cref="ActivatedObservable"/> has two inputs: an activator observable a
|
|||
/// <see cref="Source"/> observable which produces the activated value. When the activator
|
|||
/// produces true, the <see cref="ActivatedObservable"/> will produce the current activated
|
|||
/// value. When the activator produces false it will produce
|
|||
/// <see cref="PerspexProperty.UnsetValue"/>.
|
|||
/// </remarks>
|
|||
internal class ActivatedObservable : ObservableBase<object>, IDescription |
|||
{ |
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="ActivatedObservable"/> class.
|
|||
/// </summary>
|
|||
/// <param name="activator">The activator.</param>
|
|||
/// <param name="source">An observable that produces the activated value.</param>
|
|||
/// <param name="description">The binding description.</param>
|
|||
public ActivatedObservable( |
|||
IObservable<bool> activator, |
|||
IObservable<object> source, |
|||
string description) |
|||
{ |
|||
Activator = activator; |
|||
Description = description; |
|||
Source = source; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the activator observable.
|
|||
/// </summary>
|
|||
public IObservable<bool> Activator { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets a description of the binding.
|
|||
/// </summary>
|
|||
public string Description { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets an observable which produces the <see cref="ActivatedValue"/>.
|
|||
/// </summary>
|
|||
public IObservable<object> Source { get; } |
|||
|
|||
/// <summary>
|
|||
/// Notifies the provider that an observer is to receive notifications.
|
|||
/// </summary>
|
|||
/// <param name="observer">The observer.</param>
|
|||
/// <returns>IDisposable object used to unsubscribe from the observable sequence.</returns>
|
|||
protected override IDisposable SubscribeCore(IObserver<object> observer) |
|||
{ |
|||
Contract.Requires<ArgumentNullException>(observer != null); |
|||
|
|||
var sourceCompleted = Source.TakeLast(1).Select(_ => Unit.Default); |
|||
var activatorCompleted = Activator.TakeLast(1).Select(_ => Unit.Default); |
|||
var completed = sourceCompleted.Merge(activatorCompleted); |
|||
|
|||
return Activator |
|||
.CombineLatest(Source, (x, y) => new { Active = x, Value = y }) |
|||
.Select(x => x.Active ? x.Value : PerspexProperty.UnsetValue) |
|||
.DistinctUntilChanged() |
|||
.TakeUntil(completed) |
|||
.Subscribe(observer); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,111 @@ |
|||
// Copyright (c) The Perspex Project. All rights reserved.
|
|||
// Licensed under the MIT license. See licence.md file in the project root for full license information.
|
|||
|
|||
using System; |
|||
using System.Reactive.Linq; |
|||
using System.Reactive.Subjects; |
|||
|
|||
namespace Perspex.Styling |
|||
{ |
|||
/// <summary>
|
|||
/// A subject which is switched on or off according to an activator observable.
|
|||
/// </summary>
|
|||
/// <remarks>
|
|||
/// An <see cref="ActivatedSubject"/> has two inputs: an activator observable and either an
|
|||
/// <see cref="ActivatedValue"/> or a <see cref="Source"/> observable which produces the
|
|||
/// activated value. When the activator produces true, the <see cref="ActivatedObservable"/> will
|
|||
/// produce the current activated value. When the activator produces false it will produce
|
|||
/// <see cref="PerspexProperty.UnsetValue"/>.
|
|||
/// </remarks>
|
|||
internal class ActivatedSubject : ActivatedObservable, ISubject<object>, IDescription |
|||
{ |
|||
private bool? _active; |
|||
private bool _completed; |
|||
private object _value; |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="ActivatedSubject"/> class.
|
|||
/// </summary>
|
|||
/// <param name="activator">The activator.</param>
|
|||
/// <param name="source">An observable that produces the activated value.</param>
|
|||
/// <param name="description">The binding description.</param>
|
|||
public ActivatedSubject( |
|||
IObservable<bool> activator, |
|||
ISubject<object> source, |
|||
string description) |
|||
: base(activator, source, description) |
|||
{ |
|||
Activator.Subscribe(ActivatorChanged, ActivatorError, ActivatorCompleted); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the underlying subject.
|
|||
/// </summary>
|
|||
public new ISubject<object> Source |
|||
{ |
|||
get { return (ISubject<object>)base.Source; } |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Notifies all subscribed observers about the end of the sequence.
|
|||
/// </summary>
|
|||
public void OnCompleted() |
|||
{ |
|||
if (_active.Value && !_completed) |
|||
{ |
|||
Source.OnCompleted(); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Notifies all subscribed observers with the exception.
|
|||
/// </summary>
|
|||
/// <param name="error">The exception to send to all subscribed observers.</param>
|
|||
/// <exception cref="ArgumentNullException"><paramref name="error"/> is null.</exception>
|
|||
public void OnError(Exception error) |
|||
{ |
|||
if (_active.Value && !_completed) |
|||
{ |
|||
Source.OnError(error); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Notifies all subscribed observers with the value.
|
|||
/// </summary>
|
|||
/// <param name="value">The value to send to all subscribed observers.</param>
|
|||
public void OnNext(object value) |
|||
{ |
|||
_value = value; |
|||
|
|||
if (_active.Value && !_completed) |
|||
{ |
|||
Source.OnNext(value); |
|||
} |
|||
} |
|||
|
|||
private void ActivatorChanged(bool active) |
|||
{ |
|||
bool first = !_active.HasValue; |
|||
|
|||
_active = active; |
|||
|
|||
if (!first) |
|||
{ |
|||
Source.OnNext(active ? _value : PerspexProperty.UnsetValue); |
|||
} |
|||
} |
|||
|
|||
private void ActivatorCompleted() |
|||
{ |
|||
_completed = true; |
|||
Source.OnCompleted(); |
|||
} |
|||
|
|||
private void ActivatorError(Exception e) |
|||
{ |
|||
_completed = true; |
|||
Source.OnError(e); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,72 @@ |
|||
// Copyright (c) The Perspex Project. All rights reserved.
|
|||
// Licensed under the MIT license. See licence.md file in the project root for full license information.
|
|||
|
|||
using System; |
|||
using System.Reactive; |
|||
using System.Reactive.Linq; |
|||
|
|||
namespace Perspex.Styling |
|||
{ |
|||
/// <summary>
|
|||
/// An value which is switched on or off according to an activator observable.
|
|||
/// </summary>
|
|||
/// <remarks>
|
|||
/// An <see cref="ActivatedValue"/> has two inputs: an activator observable and an
|
|||
/// <see cref="Value"/>. When the activator produces true, the
|
|||
/// <see cref="ActivatedValue"/> will produce the current value. When the activator
|
|||
/// produces false it will produce <see cref="PerspexProperty.UnsetValue"/>.
|
|||
/// </remarks>
|
|||
internal class ActivatedValue : ObservableBase<object>, IDescription |
|||
{ |
|||
/// <summary>
|
|||
/// The activator.
|
|||
/// </summary>
|
|||
private readonly IObservable<bool> _activator; |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="ActivatedObservable"/> class.
|
|||
/// </summary>
|
|||
/// <param name="activator">The activator.</param>
|
|||
/// <param name="value">The activated value.</param>
|
|||
/// <param name="description">The binding description.</param>
|
|||
public ActivatedValue( |
|||
IObservable<bool> activator, |
|||
object value, |
|||
string description) |
|||
{ |
|||
_activator = activator; |
|||
Value = value; |
|||
Description = description; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the activated value.
|
|||
/// </summary>
|
|||
public object Value |
|||
{ |
|||
get; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets a description of the binding.
|
|||
/// </summary>
|
|||
public string Description |
|||
{ |
|||
get; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Notifies the provider that an observer is to receive notifications.
|
|||
/// </summary>
|
|||
/// <param name="observer">The observer.</param>
|
|||
/// <returns>IDisposable object used to unsubscribe from the observable sequence.</returns>
|
|||
protected override IDisposable SubscribeCore(IObserver<object> observer) |
|||
{ |
|||
Contract.Requires<ArgumentNullException>(observer != null); |
|||
|
|||
return _activator |
|||
.Select(active => active ? Value : PerspexProperty.UnsetValue) |
|||
.Subscribe(observer); |
|||
} |
|||
} |
|||
} |
|||
@ -1,107 +0,0 @@ |
|||
// Copyright (c) The Perspex Project. All rights reserved.
|
|||
// Licensed under the MIT license. See licence.md file in the project root for full license information.
|
|||
|
|||
using System; |
|||
using System.Reactive; |
|||
using System.Reactive.Linq; |
|||
|
|||
namespace Perspex.Styling |
|||
{ |
|||
/// <summary>
|
|||
/// Provides an observable for a style.
|
|||
/// </summary>
|
|||
/// <remarks>
|
|||
/// A <see cref="StyleBinding"/> has two inputs: an activator observable and either an
|
|||
/// <see cref="ActivatedValue"/> or a <see cref="Source"/> observable which produces the
|
|||
/// activated value. When the activator produces true, the <see cref="StyleBinding"/> will
|
|||
/// produce the current activated value. When the activator produces false it will produce
|
|||
/// <see cref="PerspexProperty.UnsetValue"/>.
|
|||
/// </remarks>
|
|||
internal class StyleBinding : ObservableBase<object>, IDescription |
|||
{ |
|||
/// <summary>
|
|||
/// The activator.
|
|||
/// </summary>
|
|||
private readonly IObservable<bool> _activator; |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="StyleBinding"/> class.
|
|||
/// </summary>
|
|||
/// <param name="activator">The activator.</param>
|
|||
/// <param name="activatedValue">The activated value.</param>
|
|||
/// <param name="description">The binding description.</param>
|
|||
public StyleBinding( |
|||
IObservable<bool> activator, |
|||
object activatedValue, |
|||
string description) |
|||
{ |
|||
_activator = activator; |
|||
ActivatedValue = activatedValue; |
|||
Description = description; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="StyleBinding"/> class.
|
|||
/// </summary>
|
|||
/// <param name="activator">The activator.</param>
|
|||
/// <param name="source">An observable that produces the activated value.</param>
|
|||
/// <param name="description">The binding description.</param>
|
|||
public StyleBinding( |
|||
IObservable<bool> activator, |
|||
IObservable<object> source, |
|||
string description) |
|||
{ |
|||
_activator = activator; |
|||
Description = description; |
|||
Source = source; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the activated value.
|
|||
/// </summary>
|
|||
public object ActivatedValue |
|||
{ |
|||
get; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets a description of the binding.
|
|||
/// </summary>
|
|||
public string Description |
|||
{ |
|||
get; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets an observable which produces the <see cref="ActivatedValue"/>.
|
|||
/// </summary>
|
|||
public IObservable<object> Source |
|||
{ |
|||
get; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Notifies the provider that an observer is to receive notifications.
|
|||
/// </summary>
|
|||
/// <param name="observer">The observer.</param>
|
|||
/// <returns>IDisposable object used to unsubscribe from the observable sequence.</returns>
|
|||
protected override IDisposable SubscribeCore(IObserver<object> observer) |
|||
{ |
|||
Contract.Requires<ArgumentNullException>(observer != null); |
|||
|
|||
if (Source == null) |
|||
{ |
|||
return _activator |
|||
.Select(active => active ? ActivatedValue : PerspexProperty.UnsetValue) |
|||
.Subscribe(observer); |
|||
} |
|||
else |
|||
{ |
|||
return _activator |
|||
.CombineLatest(Source, (x, y) => new { Active = x, Value = y }) |
|||
.Select(x => x.Active ? x.Value : PerspexProperty.UnsetValue) |
|||
.Subscribe(observer); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,43 @@ |
|||
// Copyright (c) The Perspex Project. All rights reserved.
|
|||
// Licensed under the MIT license. See licence.md file in the project root for full license information.
|
|||
|
|||
using Perspex.Controls; |
|||
using Perspex.Controls.Shapes; |
|||
using Perspex.Media; |
|||
using Xunit; |
|||
|
|||
#if PERSPEX_CAIRO
|
|||
namespace Perspex.Cairo.RenderTests.Shapes |
|||
#elif PERSPEX_SKIA
|
|||
namespace Perspex.Skia.RenderTests |
|||
#else
|
|||
namespace Perspex.Direct2D1.RenderTests.Shapes |
|||
#endif
|
|||
{ |
|||
public class LineTests : TestBase |
|||
{ |
|||
public LineTests() |
|||
: base(@"Shapes\Line") |
|||
{ |
|||
} |
|||
|
|||
[Fact] |
|||
public void Line_1px_Stroke() |
|||
{ |
|||
Decorator target = new Decorator |
|||
{ |
|||
Padding = new Thickness(8), |
|||
Width = 200, |
|||
Height = 200, |
|||
Child = new Line |
|||
{ |
|||
Stroke = Brushes.Black, |
|||
StrokeThickness = 1, |
|||
} |
|||
}; |
|||
|
|||
RenderToFile(target); |
|||
CompareImages(); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,70 @@ |
|||
// Copyright (c) The Perspex Project. All rights reserved.
|
|||
// Licensed under the MIT license. See licence.md file in the project root for full license information.
|
|||
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Reactive.Linq; |
|||
using System.Reactive.Subjects; |
|||
using Xunit; |
|||
|
|||
namespace Perspex.Styling.UnitTests |
|||
{ |
|||
public class ActivatedObservableTests |
|||
{ |
|||
[Fact] |
|||
public void Should_Produce_Correct_Values() |
|||
{ |
|||
var activator = new BehaviorSubject<bool>(false); |
|||
var source = new BehaviorSubject<object>(1); |
|||
var target = new ActivatedObservable(activator, source, string.Empty); |
|||
var result = new List<object>(); |
|||
|
|||
target.Subscribe(x => result.Add(x)); |
|||
|
|||
activator.OnNext(true); |
|||
source.OnNext(2); |
|||
activator.OnNext(false); |
|||
source.OnNext(3); |
|||
activator.OnNext(true); |
|||
|
|||
Assert.Equal( |
|||
new[] |
|||
{ |
|||
PerspexProperty.UnsetValue, |
|||
1, |
|||
2, |
|||
PerspexProperty.UnsetValue, |
|||
3, |
|||
}, |
|||
result); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_Complete_When_Source_Completes() |
|||
{ |
|||
var activator = new BehaviorSubject<bool>(false); |
|||
var source = new BehaviorSubject<object>(1); |
|||
var target = new ActivatedObservable(activator, source, string.Empty); |
|||
var completed = false; |
|||
|
|||
target.Subscribe(_ => { }, () => completed = true); |
|||
source.OnCompleted(); |
|||
|
|||
Assert.True(completed); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_Complete_When_Activator_Completes() |
|||
{ |
|||
var activator = new BehaviorSubject<bool>(false); |
|||
var source = new BehaviorSubject<object>(1); |
|||
var target = new ActivatedObservable(activator, source, string.Empty); |
|||
var completed = false; |
|||
|
|||
target.Subscribe(_ => { }, () => completed = true); |
|||
activator.OnCompleted(); |
|||
|
|||
Assert.True(completed); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,98 @@ |
|||
// Copyright (c) The Perspex Project. All rights reserved.
|
|||
// Licensed under the MIT license. See licence.md file in the project root for full license information.
|
|||
|
|||
using System; |
|||
using System.Reactive.Disposables; |
|||
using System.Reactive.Subjects; |
|||
using Xunit; |
|||
|
|||
namespace Perspex.Styling.UnitTests |
|||
{ |
|||
public class ActivatedSubjectTests |
|||
{ |
|||
[Fact] |
|||
public void Should_Set_Values() |
|||
{ |
|||
var activator = new BehaviorSubject<bool>(false); |
|||
var source = new TestSubject(); |
|||
var target = new ActivatedSubject(activator, source, string.Empty); |
|||
|
|||
target.OnNext("bar"); |
|||
Assert.Equal(PerspexProperty.UnsetValue, source.Value); |
|||
activator.OnNext(true); |
|||
target.OnNext("baz"); |
|||
Assert.Equal("baz", source.Value); |
|||
activator.OnNext(false); |
|||
Assert.Equal(PerspexProperty.UnsetValue, source.Value); |
|||
target.OnNext("bax"); |
|||
activator.OnNext(true); |
|||
Assert.Equal("bax", source.Value); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_Invoke_OnCompleted_On_Activator_Completed() |
|||
{ |
|||
var activator = new BehaviorSubject<bool>(false); |
|||
var source = new TestSubject(); |
|||
var target = new ActivatedSubject(activator, source, string.Empty); |
|||
|
|||
activator.OnCompleted(); |
|||
|
|||
Assert.True(source.Completed); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_Invoke_OnError_On_Activator_Error() |
|||
{ |
|||
var activator = new BehaviorSubject<bool>(false); |
|||
var source = new TestSubject(); |
|||
var target = new ActivatedSubject(activator, source, string.Empty); |
|||
|
|||
activator.OnError(new Exception()); |
|||
|
|||
Assert.NotNull(source.Error); |
|||
} |
|||
|
|||
private class Class1 : PerspexObject |
|||
{ |
|||
public static readonly PerspexProperty<string> FooProperty = |
|||
PerspexProperty.Register<Class1, string>("Foo", "foodefault"); |
|||
|
|||
public string Foo |
|||
{ |
|||
get { return GetValue(FooProperty); } |
|||
set { SetValue(FooProperty, value); } |
|||
} |
|||
} |
|||
|
|||
private class TestSubject : ISubject<object> |
|||
{ |
|||
private IObserver<object> _observer; |
|||
|
|||
public bool Completed { get; set; } |
|||
public Exception Error { get; set; } |
|||
public object Value { get; set; } = PerspexProperty.UnsetValue; |
|||
|
|||
public void OnCompleted() |
|||
{ |
|||
Completed = true; |
|||
} |
|||
|
|||
public void OnError(Exception error) |
|||
{ |
|||
Error = error; |
|||
} |
|||
|
|||
public void OnNext(object value) |
|||
{ |
|||
Value = value; |
|||
} |
|||
|
|||
public IDisposable Subscribe(IObserver<object> observer) |
|||
{ |
|||
_observer = observer; |
|||
return Disposable.Empty; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,42 @@ |
|||
// Copyright (c) The Perspex Project. All rights reserved.
|
|||
// Licensed under the MIT license. See licence.md file in the project root for full license information.
|
|||
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Reactive.Linq; |
|||
using System.Reactive.Subjects; |
|||
using Xunit; |
|||
|
|||
namespace Perspex.Styling.UnitTests |
|||
{ |
|||
public class ActivatedValueTests |
|||
{ |
|||
[Fact] |
|||
public void Should_Produce_Correct_Values() |
|||
{ |
|||
var activator = new BehaviorSubject<bool>(false); |
|||
var target = new ActivatedValue(activator, 1, string.Empty); |
|||
var result = new List<object>(); |
|||
|
|||
target.Subscribe(x => result.Add(x)); |
|||
|
|||
activator.OnNext(true); |
|||
activator.OnNext(false); |
|||
|
|||
Assert.Equal(new[] { PerspexProperty.UnsetValue, 1, PerspexProperty.UnsetValue }, result); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_Complete_When_Activator_Completes() |
|||
{ |
|||
var activator = new BehaviorSubject<bool>(false); |
|||
var target = new ActivatedValue(activator, 1, string.Empty); |
|||
var completed = false; |
|||
|
|||
target.Subscribe(_ => { }, () => completed = true); |
|||
activator.OnCompleted(); |
|||
|
|||
Assert.True(completed); |
|||
} |
|||
} |
|||
} |
|||
@ -1,79 +0,0 @@ |
|||
// Copyright (c) The Perspex Project. All rights reserved.
|
|||
// Licensed under the MIT license. See licence.md file in the project root for full license information.
|
|||
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Reactive.Linq; |
|||
using System.Reactive.Subjects; |
|||
using Xunit; |
|||
|
|||
namespace Perspex.Styling.UnitTests |
|||
{ |
|||
public class StyleBindingTests |
|||
{ |
|||
[Fact] |
|||
public async void Should_Produce_UnsetValue_On_Activator_False() |
|||
{ |
|||
var activator = new BehaviorSubject<bool>(false); |
|||
var target = new StyleBinding(activator, 1, string.Empty); |
|||
var result = await target.Take(1); |
|||
|
|||
Assert.Equal(PerspexProperty.UnsetValue, result); |
|||
} |
|||
|
|||
[Fact] |
|||
public async void Should_Produce_Value_On_Activator_True() |
|||
{ |
|||
var activator = new BehaviorSubject<bool>(true); |
|||
var target = new StyleBinding(activator, 1, string.Empty); |
|||
var result = await target.Take(1); |
|||
|
|||
Assert.Equal(1, result); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_Change_Value_On_Activator_Change() |
|||
{ |
|||
var activator = new BehaviorSubject<bool>(false); |
|||
var target = new StyleBinding(activator, 1, string.Empty); |
|||
var result = new List<object>(); |
|||
|
|||
target.Subscribe(x => result.Add(x)); |
|||
|
|||
activator.OnNext(true); |
|||
activator.OnNext(false); |
|||
|
|||
Assert.Equal(new[] { PerspexProperty.UnsetValue, 1, PerspexProperty.UnsetValue }, result); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_Change_Value_With_Source_Observable() |
|||
{ |
|||
var activator = new BehaviorSubject<bool>(false); |
|||
var source = new BehaviorSubject<object>(1); |
|||
var target = new StyleBinding(activator, source, string.Empty); |
|||
var result = new List<object>(); |
|||
|
|||
target.Subscribe(x => result.Add(x)); |
|||
|
|||
activator.OnNext(true); |
|||
source.OnNext(2); |
|||
activator.OnNext(false); |
|||
|
|||
Assert.Equal(new[] { PerspexProperty.UnsetValue, 1, 2, PerspexProperty.UnsetValue }, result); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_Complete_When_Activator_Completes() |
|||
{ |
|||
var activator = new BehaviorSubject<bool>(false); |
|||
var target = new StyleBinding(activator, 1, string.Empty); |
|||
var completed = false; |
|||
|
|||
target.Subscribe(_ => { }, () => completed = true); |
|||
activator.OnCompleted(); |
|||
|
|||
Assert.True(completed); |
|||
} |
|||
} |
|||
} |
|||
|
After Width: | Height: | Size: 618 B |
|
After Width: | Height: | Size: 618 B |
|
After Width: | Height: | Size: 618 B |
Loading…
Reference in new issue