diff --git a/Perspex.Styling/IStyleable.cs b/Perspex.Styling/IStyleable.cs
index 7897606ade..8cb262c66a 100644
--- a/Perspex.Styling/IStyleable.cs
+++ b/Perspex.Styling/IStyleable.cs
@@ -43,9 +43,14 @@ namespace Perspex.Styling
///
/// A disposable which can be used to terminate the binding.
///
- IDisposable Bind(
- PerspexProperty property,
- IObservable source,
- BindingPriority priority = BindingPriority.LocalValue);
+ IDisposable Bind(PerspexProperty property, IObservable source, BindingPriority priority);
+
+ ///
+ /// Sets a value.
+ ///
+ /// The property.
+ /// The value.
+ /// The priority of the value.
+ void SetValue(PerspexProperty property, object value, BindingPriority priority);
}
}
diff --git a/Perspex.Styling/Perspex.Styling.csproj b/Perspex.Styling/Perspex.Styling.csproj
index 0fb56010c4..5050b0bd04 100644
--- a/Perspex.Styling/Perspex.Styling.csproj
+++ b/Perspex.Styling/Perspex.Styling.csproj
@@ -44,6 +44,7 @@
+
diff --git a/Perspex.Styling/Selector.cs b/Perspex.Styling/Selector.cs
index 6e8523f199..2daccc63ae 100644
--- a/Perspex.Styling/Selector.cs
+++ b/Perspex.Styling/Selector.cs
@@ -8,45 +8,35 @@ namespace Perspex.Styling
{
using System;
using System.Collections.Generic;
- using System.Reactive.Linq;
public class Selector
{
+ private Func evaluate;
+
+ private bool inTemplate;
+
private bool stopTraversal;
public Selector()
{
- this.GetObservable = _ => Observable.Return(true);
- this.Priority = BindingPriority.Style;
+ this.evaluate = _ => new SelectorMatch(true);
}
- public Selector(Selector previous, bool stopTraversal = false)
+ public Selector(
+ Selector previous,
+ Func evaluate,
+ string selectorString,
+ bool inTemplate = false,
+ bool stopTraversal = false)
: this()
{
- this.Previous = previous;
- this.Priority = previous.Priority;
- this.InTemplate = previous != null ? previous.InTemplate : false;
- this.stopTraversal = stopTraversal;
- }
+ Contract.Requires(previous != null);
- public Selector(Selector previous, BindingPriority priority)
- : this()
- {
this.Previous = previous;
- this.Priority = priority;
- this.InTemplate = previous != null ? previous.InTemplate : false;
- }
-
- public bool InTemplate
- {
- get;
- set;
- }
-
- public Func> GetObservable
- {
- get;
- set;
+ this.evaluate = evaluate;
+ this.SelectorString = selectorString;
+ this.inTemplate = inTemplate || previous.inTemplate;
+ this.stopTraversal = stopTraversal;
}
public Selector Previous
@@ -55,12 +45,6 @@ namespace Perspex.Styling
private set;
}
- public BindingPriority Priority
- {
- get;
- private set;
- }
-
public string SelectorString
{
get;
@@ -72,26 +56,40 @@ namespace Perspex.Styling
return this.stopTraversal ? null : this.Previous;
}
- public StyleActivator GetActivator(IStyleable control)
+ public SelectorMatch Match(IStyleable control)
{
List> inputs = new List>();
Selector selector = this;
while (selector != null)
{
- if (selector.InTemplate && control.TemplatedParent == null)
+ if (selector.inTemplate && control.TemplatedParent == null)
{
- inputs.Add(Observable.Return(false));
+ return SelectorMatch.False;
}
- else
+
+ var match = selector.evaluate(control);
+
+ if (match.ImmediateResult == false)
+ {
+ return match;
+ }
+ else if (match.ObservableResult != null)
{
- inputs.Add(selector.GetObservable(control));
+ inputs.Add(match.ObservableResult);
}
selector = selector.MovePrevious();
}
- return new StyleActivator(inputs);
+ if (inputs.Count > 0)
+ {
+ return new SelectorMatch(new StyleActivator(inputs));
+ }
+ else
+ {
+ return SelectorMatch.True;
+ }
}
public override string ToString()
diff --git a/Perspex.Styling/SelectorMatch.cs b/Perspex.Styling/SelectorMatch.cs
new file mode 100644
index 0000000000..f3246ea4ef
--- /dev/null
+++ b/Perspex.Styling/SelectorMatch.cs
@@ -0,0 +1,58 @@
+// -----------------------------------------------------------------------
+//
+// Copyright 2015 MIT Licence. See licence.md for more information.
+//
+// -----------------------------------------------------------------------
+
+namespace Perspex.Styling
+{
+ using System;
+
+ ///
+ /// Holds the result of a match.
+ ///
+ ///
+ /// There are two types of selectors - ones whose match can never change for a particular
+ /// control (such as ) and ones whose result can
+ /// change over time (such as . For the first
+ /// category of selectors, the value of will be set but for the
+ /// second, will be null and will
+ /// hold an observable which tracks the match.
+ ///
+ public class SelectorMatch
+ {
+ public static readonly SelectorMatch False = new SelectorMatch(false);
+
+ public static readonly SelectorMatch True = new SelectorMatch(true);
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The immediate match value.
+ public SelectorMatch(bool match)
+ {
+ this.ImmediateResult = match;
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The observable match value.
+ public SelectorMatch(IObservable match)
+ {
+ this.ObservableResult = match;
+ }
+
+ ///
+ /// Gets the immedate result of the selector match, in the case of selectors that cannot
+ /// change over time.
+ ///
+ public bool? ImmediateResult { get; }
+
+ ///
+ /// Gets an observable which tracks the selector match, in the case of selectors that can
+ /// change over time.
+ ///
+ public IObservable ObservableResult { get; }
+ }
+}
diff --git a/Perspex.Styling/Selectors.cs b/Perspex.Styling/Selectors.cs
index 65cf3cfee3..ec0f1e51ec 100644
--- a/Perspex.Styling/Selectors.cs
+++ b/Perspex.Styling/Selectors.cs
@@ -9,6 +9,7 @@ namespace Perspex.Styling
using System;
using System.Collections.Generic;
using System.Reactive.Linq;
+ using System.Reflection;
public static class Selectors
{
@@ -17,102 +18,127 @@ namespace Perspex.Styling
Contract.Requires(previous != null);
Contract.Requires(name != null);
- return new Selector(previous, BindingPriority.StyleTrigger)
- {
- GetObservable = control => Observable
- .Return(control.Classes.Contains(name))
- .Concat(control.Classes.Changed.Select(e => control.Classes.Contains(name))),
- SelectorString = (name[0] == ':') ? name : '.' + name,
- };
+ return new Selector(previous, x => MatchClass(x, name), name);
}
public static Selector Descendent(this Selector previous)
{
- return new Selector(previous, stopTraversal: true)
- {
- SelectorString = " ",
- GetObservable = control =>
- {
- ILogical c = (ILogical)control;
- List> descendentMatches = new List>();
-
- while (c != null)
- {
- c = c.LogicalParent;
-
- if (c is IStyleable)
- {
- descendentMatches.Add(previous.GetActivator((IStyleable)c));
- }
- }
+ Contract.Requires(previous != null);
- return new StyleActivator(
- descendentMatches,
- ActivatorMode.Or);
- },
- };
+ return new Selector(previous, x => MatchDescendent(x, previous), " ", stopTraversal: true);
}
- public static Selector Name(this Selector previous, string id)
+ public static Selector Is(this Selector previous, Type type)
{
Contract.Requires(previous != null);
- return new Selector(previous)
- {
- GetObservable = control => Observable.Return(control.Name == id),
- SelectorString = '#' + id,
- };
+ return new Selector(previous, x => MatchIs(x, type), type.Name);
}
- public static Selector OfType(this Selector previous) where T : IStyleable
+ public static Selector Is(this Selector previous) where T : IStyleable
{
- Contract.Requires(previous != null);
-
- return new Selector(previous)
- {
- GetObservable = control => Observable.Return(control.StyleKey == typeof(T)),
- SelectorString = typeof(T).Name,
- };
+ return previous.Is(typeof(T));
}
- public static Selector Is(this Selector previous) where T : IStyleable
+ public static Selector Name(this Selector previous, string name)
{
Contract.Requires(previous != null);
- return new Selector(previous)
- {
- GetObservable = control => Observable.Return(control is T),
- SelectorString = ":is(" + typeof(T).Name + ")",
- };
+ return new Selector(previous, x => MatchName(x, name), '#' + name);
}
public static Selector OfType(this Selector previous, Type type)
{
Contract.Requires(previous != null);
- return new Selector(previous)
- {
- GetObservable = control => Observable.Return(control.GetType() == type),
- SelectorString = type.Name,
- };
+ return new Selector(previous, x => MatchOfType(x, type), type.Name);
+ }
+
+ public static Selector OfType(this Selector previous) where T : IStyleable
+ {
+ return previous.OfType(typeof(T));
}
public static Selector Template(this Selector previous)
{
Contract.Requires(previous != null);
- return new Selector(previous, stopTraversal: true)
+ return new Selector(
+ previous,
+ x => MatchTemplate(x, previous),
+ " /deep/ ",
+ inTemplate: true,
+ stopTraversal: true);
+ }
+
+ private static SelectorMatch MatchClass(IStyleable control, string name)
+ {
+ return new SelectorMatch(
+ Observable
+ .Return(control.Classes.Contains(name))
+ .Concat(control.Classes.Changed.Select(e => control.Classes.Contains(name))));
+ }
+
+ private static SelectorMatch MatchDescendent(IStyleable control, Selector previous)
+ {
+ ILogical c = (ILogical)control;
+ List> descendentMatches = new List>();
+
+ while (c != null)
{
- GetObservable = control =>
+ c = c.LogicalParent;
+
+ if (c is IStyleable)
{
- IStyleable templatedParent = control.TemplatedParent as IStyleable;
- return templatedParent != null ?
- previous.GetActivator(templatedParent) :
- Observable.Return(true);
- },
- InTemplate = true,
- SelectorString = " $ ",
- };
+ var match = previous.Match((IStyleable)c);
+
+ if (match.ImmediateResult != null)
+ {
+ if (match.ImmediateResult == true)
+ {
+ return new SelectorMatch(true);
+ }
+ }
+ else
+ {
+ descendentMatches.Add(match.ObservableResult);
+ }
+ }
+ }
+
+ return new SelectorMatch(new StyleActivator(
+ descendentMatches,
+ ActivatorMode.Or));
+ }
+
+ private static SelectorMatch MatchIs(IStyleable control, Type type)
+ {
+ var controlType = control.StyleKey ?? control.GetType();
+ return new SelectorMatch(type.GetTypeInfo().IsAssignableFrom(controlType.GetTypeInfo()));
+ }
+
+ private static SelectorMatch MatchName(IStyleable control, string name)
+ {
+ return new SelectorMatch(control.Name == name);
+ }
+
+ private static SelectorMatch MatchOfType(IStyleable control, Type type)
+ {
+ var controlType = control.StyleKey ?? control.GetType();
+ return new SelectorMatch(controlType == type);
+ }
+
+ private static SelectorMatch MatchTemplate(IStyleable control, Selector previous)
+ {
+ IStyleable templatedParent = control.TemplatedParent as IStyleable;
+
+ if (templatedParent == null)
+ {
+ throw new InvalidOperationException(
+ "Cannot call Template selector on control with null TemplatedParent.");
+ }
+
+ return previous.Match(templatedParent);
}
}
}
diff --git a/Perspex.Styling/Style.cs b/Perspex.Styling/Style.cs
index db36f92a51..74447338e7 100644
--- a/Perspex.Styling/Style.cs
+++ b/Perspex.Styling/Style.cs
@@ -37,25 +37,25 @@ namespace Perspex.Styling
public void Attach(IStyleable control)
{
- string description = "Style " + this.Selector.ToString();
- StyleActivator activator = this.Selector.GetActivator(control);
+ var description = "Style " + this.Selector.ToString();
+ var match = this.Selector.Match(control);
- if (activator.CurrentValue || !activator.HasCompleted)
+ if (match.ImmediateResult.HasValue)
{
- IObservable observable = activator;
-
- // If the activator has completed, then we want its value to be true forever.
- // Because of this we can't pass the activator directly as it will complete
- // immediately and remove the binding.
- if (activator.HasCompleted)
+ if (match.ImmediateResult == true)
{
- observable = Observable.Never().StartWith(true);
+ foreach (Setter setter in this.Setters)
+ {
+ control.SetValue(setter.Property, setter.Value, BindingPriority.Style);
+ }
}
-
+ }
+ else
+ {
foreach (Setter setter in this.Setters)
{
- StyleBinding binding = new StyleBinding(observable, setter.Value, description);
- control.Bind(setter.Property, binding, this.Selector.Priority);
+ var binding = new StyleBinding(match.ObservableResult, setter.Value, description);
+ control.Bind(setter.Property, binding, BindingPriority.StyleTrigger);
}
}
}
diff --git a/Tests/Perspex.Styling.UnitTests/Perspex.Styling.UnitTests.csproj b/Tests/Perspex.Styling.UnitTests/Perspex.Styling.UnitTests.csproj
index b02801da2c..e9b57a6931 100644
--- a/Tests/Perspex.Styling.UnitTests/Perspex.Styling.UnitTests.csproj
+++ b/Tests/Perspex.Styling.UnitTests/Perspex.Styling.UnitTests.csproj
@@ -84,7 +84,7 @@
-
+
diff --git a/Tests/Perspex.Styling.UnitTests/SelectorTests_Class.cs b/Tests/Perspex.Styling.UnitTests/SelectorTests_Class.cs
index 0cf5c4f752..aad7792ec0 100644
--- a/Tests/Perspex.Styling.UnitTests/SelectorTests_Class.cs
+++ b/Tests/Perspex.Styling.UnitTests/SelectorTests_Class.cs
@@ -15,15 +15,6 @@ namespace Perspex.Styling.UnitTests
public class SelectorTests_Class
{
- [Fact]
- public void Class_Priority_Is_StyleTrigger()
- {
- var control = new Control1();
- var target = new Selector().Class("foo");
-
- Assert.Equal(BindingPriority.StyleTrigger, target.Priority);
- }
-
[Fact]
public async Task Class_Matches_Control_With_Class()
{
@@ -33,7 +24,7 @@ namespace Perspex.Styling.UnitTests
};
var target = new Selector().Class("foo");
- var activator = target.GetActivator(control);
+ var activator = target.Match(control).ObservableResult;
Assert.True(await activator.Take(1));
}
@@ -47,7 +38,7 @@ namespace Perspex.Styling.UnitTests
};
var target = new Selector().Class("foo");
- var activator = target.GetActivator(control);
+ var activator = target.Match(control).ObservableResult;
Assert.False(await activator.Take(1));
}
@@ -62,7 +53,7 @@ namespace Perspex.Styling.UnitTests
};
var target = new Selector().Class("foo");
- var activator = target.GetActivator(control);
+ var activator = target.Match(control).ObservableResult;
Assert.True(await activator.Take(1));
}
@@ -73,7 +64,7 @@ namespace Perspex.Styling.UnitTests
var control = new Control1();
var target = new Selector().Class("foo");
- var activator = target.GetActivator(control);
+ var activator = target.Match(control).ObservableResult;
Assert.False(await activator.Take(1));
control.Classes.Add("foo");
@@ -89,7 +80,7 @@ namespace Perspex.Styling.UnitTests
};
var target = new Selector().Class("foo");
- var activator = target.GetActivator(control);
+ var activator = target.Match(control).ObservableResult;
Assert.True(await activator.Take(1));
control.Classes.Remove("foo");
@@ -101,7 +92,7 @@ namespace Perspex.Styling.UnitTests
{
var control = new Control1();
var target = new Selector().Class("foo").Class("bar");
- var activator = target.GetActivator(control);
+ var activator = target.Match(control).ObservableResult;
Assert.False(await activator.Take(1));
control.Classes.Add("foo");
diff --git a/Tests/Perspex.Styling.UnitTests/SelectorTests_Descendent.cs b/Tests/Perspex.Styling.UnitTests/SelectorTests_Descendent.cs
index 1dad4fb9be..c31ec40199 100644
--- a/Tests/Perspex.Styling.UnitTests/SelectorTests_Descendent.cs
+++ b/Tests/Perspex.Styling.UnitTests/SelectorTests_Descendent.cs
@@ -10,7 +10,6 @@ namespace Perspex.Styling.UnitTests
using System.Linq;
using System.Reactive.Linq;
using System.Threading.Tasks;
- using Moq;
using Perspex.Collections;
using Perspex.Styling;
using Xunit;
@@ -18,50 +17,46 @@ namespace Perspex.Styling.UnitTests
public class SelectorTests_Descendent
{
[Fact]
- public async Task Descendent_Matches_Control_When_It_Is_Child_OfType()
+ public void Descendent_Matches_Control_When_It_Is_Child_OfType()
{
- var parent = new Mock();
- var child = new Mock();
- var childStyleable = child.As();
+ var parent = new TestLogical1();
+ var child = new TestLogical2();
- child.Setup(x => x.LogicalParent).Returns(parent.Object);
+ child.LogicalParent = parent;
- var selector = new Selector().OfType(parent.Object.GetType()).Descendent().OfType(child.Object.GetType());
- var activator = selector.GetActivator(childStyleable.Object);
+ var selector = new Selector().OfType().Descendent().OfType();
- Assert.True(await activator.Take(1));
+ Assert.True(selector.Match(child).ImmediateResult);
}
[Fact]
- public async Task Descendent_Matches_Control_When_It_Is_Descendent_OfType()
+ public void Descendent_Matches_Control_When_It_Is_Descendent_OfType()
{
- var grandparent = new Mock();
- var parent = new Mock();
- var child = new Mock();
+ var grandparent = new TestLogical1();
+ var parent = new TestLogical2();
+ var child = new TestLogical3();
- parent.Setup(x => x.LogicalParent).Returns(grandparent.Object);
- child.Setup(x => x.LogicalParent).Returns(parent.Object);
+ parent.LogicalParent = grandparent;
+ child.LogicalParent = parent;
- var selector = new Selector().OfType(grandparent.Object.GetType()).Descendent().OfType(child.Object.GetType());
- var activator = selector.GetActivator(child.Object);
+ var selector = new Selector().OfType().Descendent().OfType();
- Assert.True(await activator.Take(1));
+ Assert.True(selector.Match(child).ImmediateResult);
}
[Fact]
public async Task Descendent_Matches_Control_When_It_Is_Descendent_OfType_And_Class()
{
- var grandparent = new Mock();
- var parent = new Mock();
- var child = new Mock();
+ var grandparent = new TestLogical1();
+ var parent = new TestLogical2();
+ var child = new TestLogical3();
- grandparent.Setup(x => x.Classes).Returns(new Classes("foo"));
- parent.Setup(x => x.LogicalParent).Returns(grandparent.Object);
- parent.Setup(x => x.Classes).Returns(new Classes());
- child.Setup(x => x.LogicalParent).Returns(parent.Object);
+ grandparent.Classes.Add("foo");
+ parent.LogicalParent = grandparent;
+ child.LogicalParent = parent;
- var selector = new Selector().OfType(grandparent.Object.GetType()).Class("foo").Descendent().OfType(child.Object.GetType());
- var activator = selector.GetActivator(child.Object);
+ var selector = new Selector().OfType().Class("foo").Descendent().OfType();
+ var activator = selector.Match(child).ObservableResult;
Assert.True(await activator.Take(1));
}
@@ -69,41 +64,79 @@ namespace Perspex.Styling.UnitTests
[Fact]
public async Task Descendent_Doesnt_Match_Control_When_It_Is_Descendent_OfType_But_Wrong_Class()
{
- var grandparent = new Mock();
- var parent = new Mock();
- var child = new Mock();
+ var grandparent = new TestLogical1();
+ var parent = new TestLogical2();
+ var child = new TestLogical3();
+
+ grandparent.Classes.Add("bar");
+ parent.LogicalParent = grandparent;
+ parent.Classes.Add("foo");
+ child.LogicalParent = parent;
+
+ var selector = new Selector().OfType().Class("foo").Descendent().OfType();
+ var activator = selector.Match(child).ObservableResult;
+
+ Assert.False(await activator.Take(1));
+ }
+
+ [Fact]
+ public async Task Descendent_Matches_Any_Ancestor()
+ {
+ var grandparent = new TestLogical1();
+ var parent = new TestLogical1();
+ var child = new TestLogical3();
- grandparent.Setup(x => x.Classes).Returns(new Classes("bar"));
- parent.Setup(x => x.LogicalParent).Returns(grandparent.Object);
- parent.Setup(x => x.Classes).Returns(new Classes("foo"));
- child.Setup(x => x.LogicalParent).Returns(parent.Object);
+ parent.LogicalParent = grandparent;
+ child.LogicalParent = parent;
var selector = new Selector().OfType().Class("foo").Descendent().OfType();
- var activator = selector.GetActivator(child.Object);
+ var activator = selector.Match(child).ObservableResult;
Assert.False(await activator.Take(1));
+ parent.Classes.Add("foo");
+ Assert.True(await activator.Take(1));
+ grandparent.Classes.Add("foo");
+ Assert.True(await activator.Take(1));
+ parent.Classes.Remove("foo");
+ Assert.True(await activator.Take(1));
+ grandparent.Classes.Remove("foo");
+ Assert.False(await activator.Take(1));
}
public abstract class TestLogical : ILogical, IStyleable
{
- public abstract Classes Classes { get; }
- public abstract string Name { get; }
- public abstract IPerspexReadOnlyList LogicalChildren { get; }
- public abstract ILogical LogicalParent { get; }
+ public TestLogical()
+ {
+ this.Classes = new Classes();
+ }
+
+ public Classes Classes { get; }
+ public string Name { get; set; }
+ public IPerspexReadOnlyList LogicalChildren { get; set; }
+ public ILogical LogicalParent { get; set; }
public Type StyleKey { get; }
- public abstract ITemplatedControl TemplatedParent { get; }
- public abstract IDisposable Bind(PerspexProperty property, IObservable source, BindingPriority priority = BindingPriority.LocalValue);
+ public ITemplatedControl TemplatedParent { get; }
+
+ public IDisposable Bind(PerspexProperty property, IObservable source, BindingPriority priority)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void SetValue(PerspexProperty property, object value, BindingPriority priority)
+ {
+ throw new NotImplementedException();
+ }
}
- public abstract class TestLogical1 : TestLogical
+ public class TestLogical1 : TestLogical
{
}
- public abstract class TestLogical2 : TestLogical
+ public class TestLogical2 : TestLogical
{
}
- public abstract class TestLogical3 : TestLogical
+ public class TestLogical3 : TestLogical
{
}
}
diff --git a/Tests/Perspex.Styling.UnitTests/SelectorTests_Multiple.cs b/Tests/Perspex.Styling.UnitTests/SelectorTests_Multiple.cs
index 373994b36e..fc27ae6421 100644
--- a/Tests/Perspex.Styling.UnitTests/SelectorTests_Multiple.cs
+++ b/Tests/Perspex.Styling.UnitTests/SelectorTests_Multiple.cs
@@ -42,7 +42,7 @@ namespace Perspex.Styling.UnitTests
var border = (Border)((IVisual)control).VisualChildren.Single();
var values = new List();
- var activator = selector.GetActivator(border);
+ var activator = selector.Match(border).ObservableResult;
activator.Subscribe(x => values.Add(x));
diff --git a/Tests/Perspex.Styling.UnitTests/SelectorTests_Name.cs b/Tests/Perspex.Styling.UnitTests/SelectorTests_Name.cs
index 5a79307b3e..e7921863b6 100644
--- a/Tests/Perspex.Styling.UnitTests/SelectorTests_Name.cs
+++ b/Tests/Perspex.Styling.UnitTests/SelectorTests_Name.cs
@@ -16,64 +16,31 @@ namespace Perspex.Styling.UnitTests
public class SelectorTests_Name
{
[Fact]
- public void Name_Priority_Is_Style()
- {
- var control = new Control1();
- var target = new Selector().Name("foo");
-
- Assert.Equal(BindingPriority.Style, target.Priority);
- }
-
- [Fact]
- public async Task Name_Matches_Control_With_Correct_Name()
+ public void Name_Matches_Control_With_Correct_Name()
{
var control = new Control1 { Name = "foo" };
var target = new Selector().Name("foo");
- var activator = target.GetActivator(control);
- Assert.True(await activator.Take(1));
+ Assert.True(target.Match(control).ImmediateResult);
}
[Fact]
- public async Task Name_Doesnt_Match_Control_Of_Wrong_Name()
+ public void Name_Doesnt_Match_Control_Of_Wrong_Name()
{
var control = new Control1 { Name = "foo" };
var target = new Selector().Name("bar");
- var activator = target.GetActivator(control);
- Assert.False(await activator.Take(1));
+ Assert.False(target.Match(control).ImmediateResult);
}
[Fact]
- public async Task Name_Doesnt_Match_Control_With_TemplatedParent()
+ public void Name_Doesnt_Match_Control_With_TemplatedParent()
{
var control = new Control1 { TemplatedParent = new Mock().Object };
var target = new Selector().Name("foo");
- var activator = target.GetActivator(control);
-
- Assert.False(await activator.Take(1));
- }
-
- [Fact]
- public async Task When_Name_Matches_Control_Other_Selectors_Are_Subscribed()
- {
- var control = new Control1 { Name = "foo" };
- var target = new Selector().Name("foo").SubscribeCheck();
-
- var result = await target.GetActivator(control).Take(1);
-
- Assert.Equal(1, control.SubscribeCheckObservable.SubscribedCount);
- }
-
- [Fact]
- public async Task When_Name_Doesnt_Match_Control_Other_Selectors_Are_Not_Subscribed()
- {
- var control = new Control1 { Name = "foo" };
- var target = new Selector().Name("bar").SubscribeCheck();
-
- var result = await target.GetActivator(control).Take(1);
+ var activator = target.Match(control);
- Assert.Equal(0, control.SubscribeCheckObservable.SubscribedCount);
+ Assert.False(target.Match(control).ImmediateResult);
}
public class Control1 : TestControlBase
diff --git a/Tests/Perspex.Styling.UnitTests/SelectorTests_OfType.cs b/Tests/Perspex.Styling.UnitTests/SelectorTests_OfType.cs
index 733c4c3391..1940556c48 100644
--- a/Tests/Perspex.Styling.UnitTests/SelectorTests_OfType.cs
+++ b/Tests/Perspex.Styling.UnitTests/SelectorTests_OfType.cs
@@ -16,64 +16,30 @@ namespace Perspex.Styling.UnitTests
public class SelectorTests_OfType
{
[Fact]
- public void OfType_Priority_Is_Style()
+ public void OfType_Matches_Control_Of_Correct_Type()
{
var control = new Control1();
var target = new Selector().OfType();
- Assert.Equal(BindingPriority.Style, target.Priority);
+ Assert.True(target.Match(control).ImmediateResult);
}
[Fact]
- public async Task OfType_Matches_Control_Of_Correct_Type()
- {
- var control = new Control1();
- var target = new Selector().OfType();
- var activator = target.GetActivator(control);
-
- Assert.True(await activator.Take(1));
- }
-
- [Fact]
- public async Task OfType_Doesnt_Match_Control_Of_Wrong_Type()
+ public void OfType_Doesnt_Match_Control_Of_Wrong_Type()
{
var control = new Control2();
var target = new Selector().OfType();
- var activator = target.GetActivator(control);
- Assert.False(await activator.Take(1));
+ Assert.False(target.Match(control).ImmediateResult);
}
[Fact]
- public async Task OfType_Matches_Control_With_TemplatedParent()
+ public void OfType_Matches_Control_With_TemplatedParent()
{
var control = new Control1 { TemplatedParent = new Mock().Object };
var target = new Selector().OfType();
- var activator = target.GetActivator(control);
-
- Assert.True(await activator.Take(1));
- }
-
- [Fact]
- public async Task When_OfType_Matches_Control_Other_Selectors_Are_Subscribed()
- {
- var control = new Control1();
- var target = new Selector().OfType().SubscribeCheck();
-
- var result = await target.GetActivator(control).Take(1);
-
- Assert.Equal(1, control.SubscribeCheckObservable.SubscribedCount);
- }
-
- [Fact]
- public async Task When_OfType_Doesnt_Match_Control_Other_Selectors_Are_Not_Subscribed()
- {
- var control = new Control1();
- var target = new Selector().OfType().SubscribeCheck();
-
- var result = await target.GetActivator(control).Take(1);
- Assert.Equal(0, control.SubscribeCheckObservable.SubscribedCount);
+ Assert.True(target.Match(control).ImmediateResult);
}
public class Control1 : TestControlBase
diff --git a/Tests/Perspex.Styling.UnitTests/SelectorTests_Template.cs b/Tests/Perspex.Styling.UnitTests/SelectorTests_Template.cs
index 74efa48e5c..e83a538265 100644
--- a/Tests/Perspex.Styling.UnitTests/SelectorTests_Template.cs
+++ b/Tests/Perspex.Styling.UnitTests/SelectorTests_Template.cs
@@ -18,47 +18,62 @@ namespace Perspex.Styling.UnitTests
public class SelectorTests_Template
{
[Fact]
- public async Task Control_In_Template_Is_Matched_With_Template_Selector()
+ public void Control_In_Template_Is_Matched_With_Template_Selector()
{
var target = new Mock();
var templatedControl = target.As();
+ var styleable = target.As();
this.BuildVisualTree(target);
var border = (Border)target.Object.GetVisualChildren().Single();
+ var selector = new Selector().Template().OfType();
+
+ Assert.True(selector.Match(border).ImmediateResult);
+ }
+
+ [Fact]
+ public void Control_Not_In_Template_Is_Not_Matched_With_Template_Selector()
+ {
+ var target = new Mock();
+ var templatedControl = target.As();
+ var styleable = target.As();
+ this.BuildVisualTree(target);
+ var border = (Border)target.Object.GetVisualChildren().Single();
+ border.SetValue(Border.TemplatedParentProperty, null);
var selector = new Selector().Template().OfType();
- var activator = selector.GetActivator(border);
- Assert.True(await activator.Take(1));
+ Assert.False(selector.Match(border).ImmediateResult);
}
[Fact]
- public async Task Nested_Control_In_Template_Is_Matched_With_Template_Selector()
+ public void Nested_Control_In_Template_Is_Matched_With_Template_Selector()
{
var target = new Mock();
var templatedControl = target.As();
+ var styleable = target.As();
this.BuildVisualTree(target);
var textBlock = (TextBlock)target.Object.VisualChildren.Single().VisualChildren.Single();
var selector = new Selector().Template().OfType();
- var activator = selector.GetActivator(textBlock);
- Assert.True(await activator.Take(1));
+ Assert.True(selector.Match(textBlock).ImmediateResult);
}
[Fact]
- public async Task Control_In_Template_Is_Matched_With_TypeOf_TemplatedControl()
+ public void Control_In_Template_Is_Matched_With_TypeOf_TemplatedControl()
{
var target = new Mock();
var templatedControl = target.As();
+ var styleable = target.As();
+ var styleKey = templatedControl.Object.GetType();
this.BuildVisualTree(target);
var border = (Border)target.Object.VisualChildren.Single();
- var selector = new Selector().OfType(templatedControl.Object.GetType()).Template().OfType();
- var activator = selector.GetActivator(border);
+ var selector = new Selector().OfType(styleKey).Template().OfType();
- Assert.True(await activator.Take(1));
+ Assert.True(selector.Match(border).ImmediateResult);
}
[Fact]
@@ -68,14 +83,13 @@ namespace Perspex.Styling.UnitTests
var templatedControl = target.As();
var styleable = target.As();
var styleKey = templatedControl.Object.GetType();
-
this.BuildVisualTree(target);
styleable.Setup(x => x.StyleKey).Returns(styleKey);
styleable.Setup(x => x.Classes).Returns(new Classes("foo"));
var border = (Border)target.Object.VisualChildren.Single();
var selector = new Selector().OfType(styleKey).Class("foo").Template().OfType();
- var activator = selector.GetActivator(border);
+ var activator = selector.Match(border).ObservableResult;
Assert.True(await activator.Take(1));
}
@@ -91,7 +105,7 @@ namespace Perspex.Styling.UnitTests
styleable.Setup(x => x.Classes).Returns(new Classes("bar"));
var border = (Border)target.Object.VisualChildren.Single();
var selector = new Selector().OfType(templatedControl.Object.GetType()).Class("foo").Template().OfType();
- var activator = selector.GetActivator(border);
+ var activator = selector.Match(border).ObservableResult;
Assert.False(await activator.Take(1));
}
diff --git a/Tests/Perspex.Styling.UnitTests/TestControlBase.cs b/Tests/Perspex.Styling.UnitTests/TestControlBase.cs
index 6fa32919b3..b8681a3d2e 100644
--- a/Tests/Perspex.Styling.UnitTests/TestControlBase.cs
+++ b/Tests/Perspex.Styling.UnitTests/TestControlBase.cs
@@ -34,7 +34,12 @@ namespace Perspex.Styling.UnitTests
set;
}
- public IDisposable Bind(PerspexProperty property, IObservable source, BindingPriority priority = BindingPriority.LocalValue)
+ public IDisposable Bind(PerspexProperty property, IObservable source, BindingPriority priority)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void SetValue(PerspexProperty property, object value, BindingPriority priority)
{
throw new NotImplementedException();
}
diff --git a/Tests/Perspex.Styling.UnitTests/TestSelectors.cs b/Tests/Perspex.Styling.UnitTests/TestSelectors.cs
index 56e7ffc655..44542609c3 100644
--- a/Tests/Perspex.Styling.UnitTests/TestSelectors.cs
+++ b/Tests/Perspex.Styling.UnitTests/TestSelectors.cs
@@ -12,10 +12,10 @@ namespace Perspex.Styling.UnitTests
{
public static Selector SubscribeCheck(this Selector selector)
{
- return new Selector(selector)
- {
- GetObservable = control => ((TestControlBase)control).SubscribeCheckObservable,
- };
+ return new Selector(
+ selector,
+ control => new SelectorMatch(((TestControlBase)control).SubscribeCheckObservable),
+ "");
}
}
}
diff --git a/Tests/Perspex.Styling.UnitTests/TestTemplatedControl.cs b/Tests/Perspex.Styling.UnitTests/TestTemplatedControl.cs
index 0549dbd97b..24d705edc5 100644
--- a/Tests/Perspex.Styling.UnitTests/TestTemplatedControl.cs
+++ b/Tests/Perspex.Styling.UnitTests/TestTemplatedControl.cs
@@ -42,7 +42,12 @@ namespace Perspex.Styling.UnitTests
throw new NotImplementedException();
}
- public IDisposable Bind(PerspexProperty property, IObservable source, BindingPriority priority = BindingPriority.LocalValue)
+ public IDisposable Bind(PerspexProperty property, IObservable source, BindingPriority priority)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void SetValue(PerspexProperty property, object value, BindingPriority priority)
{
throw new NotImplementedException();
}