diff --git a/Perspex.UnitTests/Perspex.UnitTests.csproj b/Perspex.UnitTests/Perspex.UnitTests.csproj index a9d5b5368c..8786b08e30 100644 --- a/Perspex.UnitTests/Perspex.UnitTests.csproj +++ b/Perspex.UnitTests/Perspex.UnitTests.csproj @@ -75,7 +75,12 @@ + + + + + diff --git a/Perspex.UnitTests/StyleTests.cs b/Perspex.UnitTests/StyleTests.cs index b612b7abb4..24ec380d2a 100644 --- a/Perspex.UnitTests/StyleTests.cs +++ b/Perspex.UnitTests/StyleTests.cs @@ -18,7 +18,7 @@ namespace Perspex.UnitTests [TestMethod] public void Style_With_Only_Type_Selector_Should_Update_Value() { - Style style = new Style(x => x.Select().OfType()) + Style style = new Style(new Selector().OfType()) { Setters = new[] { @@ -36,7 +36,7 @@ namespace Perspex.UnitTests [TestMethod] public void Style_With_Class_Selector_Should_Update_And_Restore_Value() { - Style style = new Style(x => x.Select().OfType().Class("foo")) + Style style = new Style(new Selector().OfType().Class("foo")) { Setters = new[] { @@ -57,7 +57,7 @@ namespace Perspex.UnitTests [TestMethod] public void LocalValue_Should_Override_Style() { - Style style = new Style(x => x.Select().OfType()) + Style style = new Style(new Selector().OfType()) { Setters = new[] { @@ -79,7 +79,7 @@ namespace Perspex.UnitTests { Styles styles = new Styles { - new Style(x => x.Select().OfType().Class("foo")) + new Style(new Selector().OfType().Class("foo")) { Setters = new[] { @@ -87,7 +87,7 @@ namespace Perspex.UnitTests }, }, - new Style(x => x.Select().OfType().Class("foo")) + new Style(new Selector().OfType().Class("foo")) { Setters = new[] { diff --git a/Perspex.UnitTests/Styling/SelectorTests_Class.cs b/Perspex.UnitTests/Styling/SelectorTests_Class.cs index 08f1234d05..d2525bb52c 100644 --- a/Perspex.UnitTests/Styling/SelectorTests_Class.cs +++ b/Perspex.UnitTests/Styling/SelectorTests_Class.cs @@ -24,9 +24,9 @@ namespace Perspex.UnitTests.Styling Classes = new Classes { "foo" }, }; - var target = control.Select().Class("foo"); + var target = new Selector().Class("foo"); - CollectionAssert.AreEqual(new[] { true }, target.GetActivator().Take(1).ToEnumerable().ToArray()); + CollectionAssert.AreEqual(new[] { true }, target.GetActivator(control).Take(1).ToEnumerable().ToArray()); } [TestMethod] @@ -37,9 +37,9 @@ namespace Perspex.UnitTests.Styling Classes = new Classes { "bar" }, }; - var target = control.Select().Class("foo"); + var target = new Selector().Class("foo"); - CollectionAssert.AreEqual(new[] { false }, target.GetActivator().Take(1).ToEnumerable().ToArray()); + CollectionAssert.AreEqual(new[] { false }, target.GetActivator(control).Take(1).ToEnumerable().ToArray()); } [TestMethod] @@ -51,9 +51,9 @@ namespace Perspex.UnitTests.Styling TemplatedParent = new Mock().Object, }; - var target = control.Select().Class("foo"); + var target = new Selector().Class("foo"); - CollectionAssert.AreEqual(new[] { false }, target.GetActivator().Take(1).ToEnumerable().ToArray()); + CollectionAssert.AreEqual(new[] { false }, target.GetActivator(control).Take(1).ToEnumerable().ToArray()); } [TestMethod] @@ -61,8 +61,8 @@ namespace Perspex.UnitTests.Styling { var control = new Control1(); - var target = control.Select().Class("foo"); - var activator = target.GetActivator(); + var target = new Selector().Class("foo"); + var activator = target.GetActivator(control); CollectionAssert.AreEqual(new[] { false }, activator.Take(1).ToEnumerable().ToArray()); control.Classes.Add("foo"); @@ -77,8 +77,8 @@ namespace Perspex.UnitTests.Styling Classes = new Classes { "foo" }, }; - var target = control.Select().Class("foo"); - var activator = target.GetActivator(); + var target = new Selector().Class("foo"); + var activator = target.GetActivator(control); CollectionAssert.AreEqual(new[] { true }, activator.Take(1).ToEnumerable().ToArray()); control.Classes.Remove("foo"); diff --git a/Perspex.UnitTests/Styling/SelectorTests_Descendent.cs b/Perspex.UnitTests/Styling/SelectorTests_Descendent.cs new file mode 100644 index 0000000000..70cf926e31 --- /dev/null +++ b/Perspex.UnitTests/Styling/SelectorTests_Descendent.cs @@ -0,0 +1,55 @@ +// ----------------------------------------------------------------------- +// +// Copyright 2014 MIT Licence. See licence.md for more information. +// +// ----------------------------------------------------------------------- + +namespace Perspex.UnitTests.Styling +{ + using System.Linq; + using System.Reactive.Linq; + using Microsoft.VisualStudio.TestTools.UnitTesting; + using Moq; + using Perspex.Controls; + using Perspex.Styling; + using Match = Perspex.Styling.Selector; + + [TestClass] + public class SelectorTests_Descendent + { + [TestMethod] + public void Descendent_Matches_Control_When_It_Is_Child_OfType() + { + var parent = new Mock(); + var child = new Mock(); + + parent.Setup(x => x.LogicalChildren).Returns(new[] + { + child.Object, + }); + + var selector = new Selector().OfType().Descendent().OfType(); + + Assert.AreEqual(true, ActivatorValue(selector, child.Object)); + } + + [TestMethod] + public void Descendent_Matches_Control_When_It_Is_Descendent_OfType() + { + Assert.Fail(); + } + + private static bool ActivatorValue(Match selector, IStyleable control) + { + return selector.GetActivator(control).Take(1).ToEnumerable().Single(); + } + + public abstract class TestLogical1 : TestLogical + { + } + + public abstract class TestLogical2 : TestLogical + { + } + } +} diff --git a/Perspex.UnitTests/Styling/SelectorTests_Id.cs b/Perspex.UnitTests/Styling/SelectorTests_Id.cs index 194d7f5cbd..a338821e2a 100644 --- a/Perspex.UnitTests/Styling/SelectorTests_Id.cs +++ b/Perspex.UnitTests/Styling/SelectorTests_Id.cs @@ -22,36 +22,36 @@ namespace Perspex.UnitTests.Styling public void Id_Matches_Control_With_Correct_Id() { var control = new Control1 { Id = "foo" }; - var target = control.Select().Id("foo"); + var target = new Selector().Id("foo"); - CollectionAssert.AreEqual(new[] { true }, target.GetActivator().Take(1).ToEnumerable().ToArray()); + CollectionAssert.AreEqual(new[] { true }, target.GetActivator(control).Take(1).ToEnumerable().ToArray()); } [TestMethod] public void Id_Doesnt_Match_Control_Of_Wrong_Id() { var control = new Control1 { Id = "foo" }; - var target = control.Select().Id("bar"); + var target = new Selector().Id("bar"); - CollectionAssert.AreEqual(new[] { false }, target.GetActivator().Take(1).ToEnumerable().ToArray()); + CollectionAssert.AreEqual(new[] { false }, target.GetActivator(control).Take(1).ToEnumerable().ToArray()); } [TestMethod] public void Id_Doesnt_Match_Control_With_TemplatedParent() { var control = new Control1 { TemplatedParent = new Mock().Object }; - var target = control.Select().Id("foo"); + var target = new Selector().Id("foo"); - CollectionAssert.AreEqual(new[] { false }, target.GetActivator().Take(1).ToEnumerable().ToArray()); + CollectionAssert.AreEqual(new[] { false }, target.GetActivator(control).Take(1).ToEnumerable().ToArray()); } [TestMethod] public void When_Id_Matches_Control_Other_Selectors_Are_Subscribed() { var control = new Control1 { Id = "foo" }; - var target = control.Select().Id("foo").SubscribeCheck(); + var target = new Selector().Id("foo").SubscribeCheck(); - var result = target.GetActivator().ToEnumerable().Take(1).ToArray(); + var result = target.GetActivator(control).ToEnumerable().Take(1).ToArray(); Assert.AreEqual(1, control.SubscribeCheckObservable.SubscribedCount); } @@ -60,9 +60,9 @@ namespace Perspex.UnitTests.Styling public void When_Id_Doesnt_Match_Control_Other_Selectors_Are_Not_Subscribed() { var control = new Control1 { Id = "foo" }; - var target = control.Select().Id("bar").SubscribeCheck(); + var target = new Selector().Id("bar").SubscribeCheck(); - var result = target.GetActivator().ToEnumerable().Take(1).ToArray(); + var result = target.GetActivator(control).ToEnumerable().Take(1).ToArray(); Assert.AreEqual(0, control.SubscribeCheckObservable.SubscribedCount); } diff --git a/Perspex.UnitTests/Styling/SelectorTests_OfType.cs b/Perspex.UnitTests/Styling/SelectorTests_OfType.cs index 4936cd2e3f..ed98d8e612 100644 --- a/Perspex.UnitTests/Styling/SelectorTests_OfType.cs +++ b/Perspex.UnitTests/Styling/SelectorTests_OfType.cs @@ -20,36 +20,36 @@ namespace Perspex.UnitTests.Styling public void OfType_Matches_Control_Of_Correct_Type() { var control = new Control1(); - var target = control.Select().OfType(); + var target = new Selector().OfType(); - CollectionAssert.AreEqual(new[] { true }, target.GetActivator().Take(1).ToEnumerable().ToArray()); + CollectionAssert.AreEqual(new[] { true }, target.GetActivator(control).Take(1).ToEnumerable().ToArray()); } [TestMethod] public void OfType_Doesnt_Match_Control_Of_Wrong_Type() { var control = new Control2(); - var target = control.Select().OfType(); + var target = new Selector().OfType(); - CollectionAssert.AreEqual(new[] { false }, target.GetActivator().Take(1).ToEnumerable().ToArray()); + CollectionAssert.AreEqual(new[] { false }, target.GetActivator(control).Take(1).ToEnumerable().ToArray()); } [TestMethod] public void OfType_Doesnt_Match_Control_With_TemplatedParent() { var control = new Control1 { TemplatedParent = new Mock().Object }; - var target = control.Select().OfType(); + var target = new Selector().OfType(); - CollectionAssert.AreEqual(new[] { false }, target.GetActivator().Take(1).ToEnumerable().ToArray()); + CollectionAssert.AreEqual(new[] { false }, target.GetActivator(control).Take(1).ToEnumerable().ToArray()); } [TestMethod] public void When_OfType_Matches_Control_Other_Selectors_Are_Subscribed() { var control = new Control1(); - var target = control.Select().OfType().SubscribeCheck(); + var target = new Selector().OfType().SubscribeCheck(); - var result = target.GetActivator().ToEnumerable().Take(1).ToArray(); + var result = target.GetActivator(control).ToEnumerable().Take(1).ToArray(); Assert.AreEqual(1, control.SubscribeCheckObservable.SubscribedCount); } @@ -58,9 +58,9 @@ namespace Perspex.UnitTests.Styling public void When_OfType_Doesnt_Match_Control_Other_Selectors_Are_Not_Subscribed() { var control = new Control1(); - var target = control.Select().OfType().SubscribeCheck(); + var target = new Selector().OfType().SubscribeCheck(); - var result = target.GetActivator().ToEnumerable().Take(1).ToArray(); + var result = target.GetActivator(control).ToEnumerable().Take(1).ToArray(); Assert.AreEqual(0, control.SubscribeCheckObservable.SubscribedCount); } diff --git a/Perspex.UnitTests/Styling/SelectorTests_Template.cs b/Perspex.UnitTests/Styling/SelectorTests_Template.cs index cf51eb7e33..91c63c7de9 100644 --- a/Perspex.UnitTests/Styling/SelectorTests_Template.cs +++ b/Perspex.UnitTests/Styling/SelectorTests_Template.cs @@ -12,7 +12,7 @@ namespace Perspex.UnitTests.Styling using Moq; using Perspex.Controls; using Perspex.Styling; - using Match = Perspex.Styling.Match; + using Match = Perspex.Styling.Selector; [TestClass] public class SelectorTests_Template @@ -25,9 +25,10 @@ namespace Perspex.UnitTests.Styling this.BuildVisualTree(templatedControl); var border = (Border)templatedControl.Object.VisualChildren.Single(); - var selector = border.Select().OfType(); - Assert.AreEqual(false, ActivatorValue(selector)); + var selector = new Selector().OfType(); + + Assert.AreEqual(false, ActivatorValue(selector, border)); } [TestMethod] @@ -38,17 +39,45 @@ namespace Perspex.UnitTests.Styling this.BuildVisualTree(templatedControl); var border = (Border)templatedControl.Object.VisualChildren.Single(); - var selector = border.Select().Template().OfType(); - Assert.AreEqual(true, ActivatorValue(selector)); + var selector = new Selector().Template().OfType(); + + Assert.AreEqual(true, ActivatorValue(selector, border)); + } + + [TestMethod] + public void Nested_Control_In_Template_Is_Matched_With_Template_Selector() + { + var templatedControl = new Mock(); + var styleable = templatedControl.As(); + this.BuildVisualTree(templatedControl); + + var textBlock = (TextBlock)templatedControl.Object.VisualChildren.Single().VisualChildren.Single(); + + var selector = new Selector().Template().OfType(); + + Assert.AreEqual(true, ActivatorValue(selector, textBlock)); + } + + [TestMethod] + public void Control_In_Template_Is_Matched_With_TypeOf_TemplatedControl() + { + var templatedControl = new Mock(); + this.BuildVisualTree(templatedControl); + + var border = (Border)templatedControl.Object.VisualChildren.Single(); + + var selector = new Selector().OfType().Template().OfType(); + + Assert.AreEqual(true, ActivatorValue(selector,border)); } - private static bool ActivatorValue(Match selector) + private static bool ActivatorValue(Match selector, IStyleable control) { - return selector.GetActivator().Take(1).ToEnumerable().Single(); + return selector.GetActivator(control).Take(1).ToEnumerable().Single(); } - private void BuildVisualTree(Mock templatedControl) + private void BuildVisualTree(Mock templatedControl) where T : class, ITemplatedControl { templatedControl.Setup(x => x.VisualChildren).Returns(new[] { diff --git a/Perspex.UnitTests/Styling/TestControlBase.cs b/Perspex.UnitTests/Styling/TestControlBase.cs index d33427da95..8cf241ca35 100644 --- a/Perspex.UnitTests/Styling/TestControlBase.cs +++ b/Perspex.UnitTests/Styling/TestControlBase.cs @@ -7,22 +7,8 @@ namespace Perspex.UnitTests.Styling { using System; - using System.Reactive.Disposables; using Perspex.Controls; using Perspex.Styling; - using Match = Perspex.Styling.Match; - - public class TestObservable : IObservable - { - public int SubscribedCount { get; private set; } - - public IDisposable Subscribe(IObserver observer) - { - ++this.SubscribedCount; - observer.OnNext(true); - return Disposable.Create(() => --this.SubscribedCount); - } - } public class TestControlBase : IStyleable { @@ -48,15 +34,4 @@ namespace Perspex.UnitTests.Styling { } } - - public static class TestSelectors - { - public static Match SubscribeCheck(this Match match) - { - return new Match(match) - { - Observable = ((TestControlBase)match.Control).SubscribeCheckObservable, - }; - } - } } diff --git a/Perspex.UnitTests/Styling/TestLogical.cs b/Perspex.UnitTests/Styling/TestLogical.cs new file mode 100644 index 0000000000..6132bbd813 --- /dev/null +++ b/Perspex.UnitTests/Styling/TestLogical.cs @@ -0,0 +1,31 @@ +// ----------------------------------------------------------------------- +// +// Copyright 2014 MIT Licence. See licence.md for more information. +// +// ----------------------------------------------------------------------- + +namespace Perspex.UnitTests.Styling +{ + using System; + using System.Collections.Generic; + using Perspex.Controls; + using Perspex.Styling; + + public abstract class TestLogical : TestControlBase, ILogical + { + public TestLogical() + { + } + + public abstract ILogical LogicalParent + { + get; + set; + } + + public abstract IEnumerable LogicalChildren + { + get; + } + } +} diff --git a/Perspex.UnitTests/Styling/TestObservable.cs b/Perspex.UnitTests/Styling/TestObservable.cs new file mode 100644 index 0000000000..e7ff35c449 --- /dev/null +++ b/Perspex.UnitTests/Styling/TestObservable.cs @@ -0,0 +1,23 @@ +// ----------------------------------------------------------------------- +// +// Copyright 2014 MIT Licence. See licence.md for more information. +// +// ----------------------------------------------------------------------- + +namespace Perspex.UnitTests.Styling +{ + using System; + using System.Reactive.Disposables; + + public class TestObservable : IObservable + { + public int SubscribedCount { get; private set; } + + public IDisposable Subscribe(IObserver observer) + { + ++this.SubscribedCount; + observer.OnNext(true); + return Disposable.Create(() => --this.SubscribedCount); + } + } +} diff --git a/Perspex.UnitTests/Styling/TestSelectors.cs b/Perspex.UnitTests/Styling/TestSelectors.cs new file mode 100644 index 0000000000..74e626120b --- /dev/null +++ b/Perspex.UnitTests/Styling/TestSelectors.cs @@ -0,0 +1,21 @@ +// ----------------------------------------------------------------------- +// +// Copyright 2014 MIT Licence. See licence.md for more information. +// +// ----------------------------------------------------------------------- + +namespace Perspex.UnitTests.Styling +{ + using Perspex.Styling; + + public static class TestSelectors + { + public static Selector SubscribeCheck(this Selector selector) + { + return new Selector(selector) + { + Observable = control => ((TestControlBase)control).SubscribeCheckObservable, + }; + } + } +} diff --git a/Perspex.UnitTests/Styling/TestTemplatedControl.cs b/Perspex.UnitTests/Styling/TestTemplatedControl.cs new file mode 100644 index 0000000000..23bd1bda0a --- /dev/null +++ b/Perspex.UnitTests/Styling/TestTemplatedControl.cs @@ -0,0 +1,37 @@ +// ----------------------------------------------------------------------- +// +// Copyright 2014 MIT Licence. See licence.md for more information. +// +// ----------------------------------------------------------------------- + +namespace Perspex.UnitTests.Styling +{ + using System.Collections.Generic; + using Perspex.Controls; + using Perspex.Styling; + + public abstract class TestTemplatedControl : ITemplatedControl, IStyleable + { + public abstract Classes Classes + { + get; + } + + public abstract string Id + { + get; + } + + public abstract ITemplatedControl TemplatedParent + { + get; + } + + public abstract IEnumerable VisualChildren + { + get; + } + + public abstract void SetValue(PerspexProperty property, object value, System.IObservable activator); + } +} diff --git a/Perspex/Perspex.csproj b/Perspex/Perspex.csproj index 8a1839b596..1e76696427 100644 --- a/Perspex/Perspex.csproj +++ b/Perspex/Perspex.csproj @@ -107,7 +107,7 @@ - + diff --git a/Perspex/Styling/Activator.cs b/Perspex/Styling/Activator.cs index 29a7d117b5..860e682a68 100644 --- a/Perspex/Styling/Activator.cs +++ b/Perspex/Styling/Activator.cs @@ -21,7 +21,7 @@ namespace Perspex.Styling bool last = false; - public Activator(Match match) + public Activator(Selector match, IStyleable control) { int i = 0; @@ -33,7 +33,7 @@ namespace Perspex.Styling { this.values.Add(false); - IDisposable subscription = match.Observable.Subscribe( + IDisposable subscription = match.Observable(control).Subscribe( x => this.Update(iCaptured, x), x => this.Finish(iCaptured), () => this.Finish(iCaptured)); diff --git a/Perspex/Styling/Match.cs b/Perspex/Styling/Selector.cs similarity index 54% rename from Perspex/Styling/Match.cs rename to Perspex/Styling/Selector.cs index dc8304129a..8d1e8d2c04 100644 --- a/Perspex/Styling/Match.cs +++ b/Perspex/Styling/Selector.cs @@ -13,35 +13,20 @@ namespace Perspex.Styling using System.Text; using Perspex.Controls; - public class Match + public class Selector { - private IObservable observable; + private Func> observable; - public Match(IStyleable control) + public Selector() { - this.Control = control; } - public Match(Match previous) + public Selector(Selector previous) { - this.Control = previous.Control; - this.InTemplate = previous.InTemplate; this.Previous = previous; } - public IStyleable Control - { - get; - private set; - } - - public bool InTemplate - { - get; - set; - } - - public IObservable Observable + public Func> Observable { get { @@ -50,19 +35,11 @@ namespace Perspex.Styling set { - if ((!InTemplate && Control.TemplatedParent == null) || - (InTemplate && Control.TemplatedParent != null)) - { - this.observable = value; - } - else - { - this.observable = System.Reactive.Linq.Observable.Return(false); - } + this.observable = value; } } - public Match Previous + public Selector Previous { get; set; @@ -74,14 +51,14 @@ namespace Perspex.Styling set; } - public Activator GetActivator() + public Activator GetActivator(IStyleable control) { - return new Activator(this); + return new Activator(this, control); } public override string ToString() { - Match match = this; + Selector match = this; StringBuilder b = new StringBuilder(); while (match != null) diff --git a/Perspex/Styling/Selectors.cs b/Perspex/Styling/Selectors.cs index 179e4ac8ae..7841e48c62 100644 --- a/Perspex/Styling/Selectors.cs +++ b/Perspex/Styling/Selectors.cs @@ -12,56 +12,53 @@ namespace Perspex.Styling public static class Selectors { - public static Match Select(this IStyleable control) - { - Contract.Requires(control != null); - - return new Match(control); - } - - public static Match Class(this Match match, string name) + public static Selector Class(this Selector match, string name) { Contract.Requires(match != null); Contract.Requires(name != null); - return new Match(match) + return new Selector(match) { - Observable = Observable - .Return(match.Control.Classes.Contains(name)) - .Concat(match.Control.Classes.Changed.Select(e => match.Control.Classes.Contains(name))), + Observable = control => Observable + .Return(control.Classes.Contains(name)) + .Concat(control.Classes.Changed.Select(e => control.Classes.Contains(name))), SelectorString = (name[0] == ':') ? name : '.' + name, }; } - public static Match Id(this Match match, string id) + public static Selector Descendent(this Selector match) + { + throw new NotImplementedException(); + } + + public static Selector Id(this Selector match, string id) { Contract.Requires(match != null); - return new Match(match) + return new Selector(match) { - Observable = Observable.Return(match.Control.TemplatedParent == null && match.Control.Id == id), + Observable = control => Observable.Return(control.Id == id), SelectorString = '#' + id, }; } - public static Match OfType(this Match match) where T : IStyleable + public static Selector OfType(this Selector match) where T : IStyleable { Contract.Requires(match != null); - return new Match(match) + return new Selector(match) { - Observable = Observable.Return(match.Control is T), + Observable = control => Observable.Return(control is T), SelectorString = typeof(T).Name, }; } - public static Match Template(this Match match) + public static Selector Template(this Selector match) { Contract.Requires(match != null); - return new Match(match) + return new Selector(match) { - InTemplate = true, SelectorString = " $ ", }; } diff --git a/Perspex/Styling/Style.cs b/Perspex/Styling/Style.cs index 3ea458d95c..3367c171d7 100644 --- a/Perspex/Styling/Style.cs +++ b/Perspex/Styling/Style.cs @@ -20,13 +20,13 @@ namespace Perspex.Styling this.Setters = new List(); } - public Style(Func selector) + public Style(Selector selector) : this() { this.Selector = selector; } - public Func Selector + public Selector Selector { get; set; @@ -40,17 +40,12 @@ namespace Perspex.Styling public void Attach(IStyleable control) { - Match match = this.Selector(control); + string description = "Style " + this.Selector.ToString(); + IObservable activator = this.Selector.GetActivator(control); - if (match != null) + foreach (Setter setter in this.Setters) { - string description = "Style " + match.ToString(); - IObservable activator = match.GetActivator(); - - foreach (Setter setter in this.Setters) - { - control.SetValue(setter.Property, setter.Value, activator); - } + control.SetValue(setter.Property, setter.Value, activator); } } } diff --git a/Perspex/Themes/Default/ButtonStyle.cs b/Perspex/Themes/Default/ButtonStyle.cs index 33bb11f06d..45242dac7a 100644 --- a/Perspex/Themes/Default/ButtonStyle.cs +++ b/Perspex/Themes/Default/ButtonStyle.cs @@ -13,36 +13,36 @@ namespace Perspex.Themes.Default { public ButtonStyle() { - this.AddRange(new[] - { - new Style(x => x.Select().OfType