diff --git a/Perspex.Controls/AdornerTemplate.cs b/Perspex.Controls/AdornerTemplate.cs new file mode 100644 index 0000000000..8a93de3ca5 --- /dev/null +++ b/Perspex.Controls/AdornerTemplate.cs @@ -0,0 +1,27 @@ +// ----------------------------------------------------------------------- +// +// Copyright 2014 MIT Licence. See licence.md for more information. +// +// ----------------------------------------------------------------------- + +namespace Perspex.Controls +{ + using System; + + public class AdornerTemplate + { + private Func build; + + public AdornerTemplate(Func build) + { + Contract.Requires(build != null); + + this.build = build; + } + + public Control Build() + { + return this.build(); + } + } +} diff --git a/Perspex.Controls/Control.cs b/Perspex.Controls/Control.cs index 40f50695aa..d92a2b8845 100644 --- a/Perspex.Controls/Control.cs +++ b/Perspex.Controls/Control.cs @@ -25,6 +25,9 @@ namespace Perspex.Controls public static readonly PerspexProperty DataContextProperty = PerspexProperty.Register("DataContext", inherits: true); + public static readonly PerspexProperty FocusAdornerProperty = + PerspexProperty.Register("FocusAdorner"); + public static readonly PerspexProperty ParentProperty = PerspexProperty.Register("Parent"); @@ -43,7 +46,7 @@ namespace Perspex.Controls private DataTemplates dataTemplates; - private Rectangle focusAdorner; + private Control focusAdorner; private string id; @@ -199,15 +202,21 @@ namespace Perspex.Controls if (adornerLayer != null) { - this.focusAdorner = new Rectangle + if (this.focusAdorner == null) + { + var template = this.GetValue(FocusAdornerProperty); + + if (template != null) + { + this.focusAdorner = template.Build(); + } + } + + if (this.focusAdorner != null) { - Stroke = Brushes.Black, - StrokeThickness = 1, - StrokeDashArray = new PerspexList(1, 2), - Margin = new Thickness(3), - }; - AdornerLayer.SetAdornedElement(this.focusAdorner, this); - adornerLayer.Children.Add(this.focusAdorner); + AdornerLayer.SetAdornedElement(this.focusAdorner, this); + adornerLayer.Children.Add(this.focusAdorner); + } } } } diff --git a/Perspex.Controls/Perspex.Controls.csproj b/Perspex.Controls/Perspex.Controls.csproj index da3cd831b9..5ba608adf0 100644 --- a/Perspex.Controls/Perspex.Controls.csproj +++ b/Perspex.Controls/Perspex.Controls.csproj @@ -36,6 +36,7 @@ + diff --git a/Perspex.Styling/Selectors.cs b/Perspex.Styling/Selectors.cs index 3e1e9d39e2..181eba47a0 100644 --- a/Perspex.Styling/Selectors.cs +++ b/Perspex.Styling/Selectors.cs @@ -75,6 +75,17 @@ namespace Perspex.Styling }; } + public static Selector Is(this Selector previous) where T : IStyleable + { + Contract.Requires(previous != null); + + return new Selector(previous) + { + GetObservable = control => Observable.Return(control is T), + SelectorString = ":is(" + typeof(T).Name + ")", + }; + } + public static Selector OfType(this Selector previous, Type type) { Contract.Requires(previous != null); diff --git a/Perspex.Themes.Default/DefaultTheme.cs b/Perspex.Themes.Default/DefaultTheme.cs index 5d976e9574..c2b4975104 100644 --- a/Perspex.Themes.Default/DefaultTheme.cs +++ b/Perspex.Themes.Default/DefaultTheme.cs @@ -16,6 +16,7 @@ namespace Perspex.Themes.Default this.Add(new CheckBoxStyle()); this.Add(new ContentControlStyle()); this.Add(new DropDownStyle()); + this.Add(new FocusAdornerStyle()); this.Add(new GridSplitterStyle()); this.Add(new ItemsControlStyle()); this.Add(new ListBoxStyle()); diff --git a/Perspex.Themes.Default/FocusAdornerStyle.cs b/Perspex.Themes.Default/FocusAdornerStyle.cs new file mode 100644 index 0000000000..354b2af556 --- /dev/null +++ b/Perspex.Themes.Default/FocusAdornerStyle.cs @@ -0,0 +1,42 @@ +// ----------------------------------------------------------------------- +// +// Copyright 2014 MIT Licence. See licence.md for more information. +// +// ----------------------------------------------------------------------- + +namespace Perspex.Themes.Default +{ + using Perspex.Collections; + using Perspex.Controls; + using Perspex.Controls.Shapes; + using Perspex.Media; + using Perspex.Styling; + + public class FocusAdornerStyle : Styles + { + public FocusAdornerStyle() + { + this.AddRange(new[] + { + new Style(x => x.Is()) + { + Setters = new[] + { + new Setter(Control.FocusAdornerProperty, new AdornerTemplate(this.Template)), + }, + }, + }); + } + + private Control Template() + { + return new Rectangle + { + Stroke = Brushes.Black, + StrokeThickness = 1, + StrokeDashArray = new PerspexList(1, 2), + Margin = new Thickness(3), + }; + } + } +} diff --git a/Perspex.Themes.Default/Perspex.Themes.Default.csproj b/Perspex.Themes.Default/Perspex.Themes.Default.csproj index be4ec9af91..af2f6cdb10 100644 --- a/Perspex.Themes.Default/Perspex.Themes.Default.csproj +++ b/Perspex.Themes.Default/Perspex.Themes.Default.csproj @@ -70,6 +70,7 @@ +