// ----------------------------------------------------------------------- // // Copyright 2014 MIT Licence. See licence.md for more information. // // ----------------------------------------------------------------------- namespace Perspex.Controls.Primitives { using System; using System.Linq; using Perspex.Controls.Presenters; using Perspex.Controls.Templates; using Perspex.Media; using Perspex.Styling; using Perspex.VisualTree; using Serilog; using Serilog.Core.Enrichers; public class TemplatedControl : Control, ITemplatedControl { public static readonly PerspexProperty BackgroundProperty = Border.BackgroundProperty.AddOwner(); public static readonly PerspexProperty BorderBrushProperty = Border.BorderBrushProperty.AddOwner(); public static readonly PerspexProperty BorderThicknessProperty = Border.BorderThicknessProperty.AddOwner(); public static readonly PerspexProperty FontFamilyProperty = TextBlock.FontFamilyProperty.AddOwner(); public static readonly PerspexProperty FontSizeProperty = TextBlock.FontSizeProperty.AddOwner(); public static readonly PerspexProperty FontStyleProperty = TextBlock.FontStyleProperty.AddOwner(); public static readonly PerspexProperty ForegroundProperty = TextBlock.ForegroundProperty.AddOwner(); public static readonly PerspexProperty PaddingProperty = Decorator.PaddingProperty.AddOwner(); public static readonly PerspexProperty TemplateProperty = PerspexProperty.Register("Template"); private bool templateApplied; private ILogger templateLog; static TemplatedControl() { TemplateProperty.Changed.Subscribe(e => { var templatedControl = (TemplatedControl)e.Sender; templatedControl.templateApplied = false; templatedControl.InvalidateMeasure(); }); } public TemplatedControl() { this.templateLog = Log.ForContext(new[] { new PropertyEnricher("Area", "Template"), new PropertyEnricher("SourceContext", this.GetType()), new PropertyEnricher("Id", this.GetHashCode()), }); } public Brush Background { get { return this.GetValue(BackgroundProperty); } set { this.SetValue(BackgroundProperty, value); } } public Brush BorderBrush { get { return this.GetValue(BorderBrushProperty); } set { this.SetValue(BorderBrushProperty, value); } } public double BorderThickness { get { return this.GetValue(BorderThicknessProperty); } set { this.SetValue(BorderThicknessProperty, value); } } public string FontFamily { get { return this.GetValue(FontFamilyProperty); } set { this.SetValue(FontFamilyProperty, value); } } public double FontSize { get { return this.GetValue(FontSizeProperty); } set { this.SetValue(FontSizeProperty, value); } } public FontStyle FontStyle { get { return this.GetValue(FontStyleProperty); } set { this.SetValue(FontStyleProperty, value); } } public Brush Foreground { get { return this.GetValue(ForegroundProperty); } set { this.SetValue(ForegroundProperty, value); } } public Thickness Padding { get { return this.GetValue(PaddingProperty); } set { this.SetValue(PaddingProperty, value); } } public ControlTemplate Template { get { return this.GetValue(TemplateProperty); } set { this.SetValue(TemplateProperty, value); } } public override void Render(IDrawingContext context) { } public sealed override void ApplyTemplate() { if (!this.templateApplied) { this.ClearVisualChildren(); if (this.Template != null) { this.templateLog.Verbose("Creating control template"); var child = this.Template.Build(this); this.SetTemplatedParent(child); this.AddVisualChild(child); child.Parent = this; foreach (var i in this.GetTemplateChildren()) { i.ApplyTemplate(); } this.OnTemplateApplied(); } this.templateApplied = true; } } protected override Size ArrangeOverride(Size finalSize) { Control child = ((IVisual)this).VisualChildren.SingleOrDefault() as Control; if (child != null) { child.Arrange(new Rect(finalSize)); return child.Bounds.Size; } else { return new Size(); } } protected override Size MeasureOverride(Size availableSize) { Control child = ((IVisual)this).VisualChildren.SingleOrDefault() as Control; if (child != null) { child.Measure(availableSize); return child.DesiredSize; } return new Size(); } protected virtual void OnTemplateApplied() { } private void SetTemplatedParent(Control control) { control.TemplatedParent = this; if (!(control is IPresenter)) { foreach (var child in control.GetVisualChildren().OfType()) { this.SetTemplatedParent(child); } } } } }