// // This code based on code available here: // // http://www.codeproject.com/KB/WPF/WPFJoshSmith.aspx // namespace VideoBrowser.Controls.AdornedControl { using System; using System.Collections; using System.Windows; using System.Windows.Documents; using System.Windows.Media; // // This class is an adorner that allows a FrameworkElement derived class to adorn another FrameworkElement. // public class FrameworkElementAdorner : Adorner { // // The framework element that is the adorner. // private FrameworkElement child; // // Placement of the child. // private readonly AdornerPlacement horizontalAdornerPlacement = AdornerPlacement.Inside; private readonly AdornerPlacement verticalAdornerPlacement = AdornerPlacement.Inside; // // Offset of the child. // private readonly double offsetX = 0.0; private readonly double offsetY = 0.0; // // Position of the child (when not set to NaN). // private double positionX = Double.NaN; private double positionY = Double.NaN; public FrameworkElementAdorner(FrameworkElement adornerChildElement, FrameworkElement adornedElement) : base(adornedElement) { this.child = adornerChildElement; base.AddLogicalChild(adornerChildElement); base.AddVisualChild(adornerChildElement); } public FrameworkElementAdorner(FrameworkElement adornerChildElement, FrameworkElement adornedElement, AdornerPlacement horizontalAdornerPlacement, AdornerPlacement verticalAdornerPlacement, double offsetX, double offsetY) : base(adornedElement) { this.child = adornerChildElement; this.horizontalAdornerPlacement = horizontalAdornerPlacement; this.verticalAdornerPlacement = verticalAdornerPlacement; this.offsetX = offsetX; this.offsetY = offsetY; adornedElement.SizeChanged += new SizeChangedEventHandler(adornedElement_SizeChanged); base.AddLogicalChild(adornerChildElement); base.AddVisualChild(adornerChildElement); } /// /// Event raised when the adorned control's size has changed. /// private void adornedElement_SizeChanged(object sender, SizeChangedEventArgs e) { InvalidateMeasure(); } // // Position of the child (when not set to NaN). // public double PositionX { get { return positionX; } set { positionX = value; } } public double PositionY { get { return positionY; } set { positionY = value; } } protected override Size MeasureOverride(Size constraint) { this.child.Measure(constraint); return this.child.DesiredSize; } /// /// Determine the X coordinate of the child. /// private double DetermineX() { switch (child.HorizontalAlignment) { case HorizontalAlignment.Left: { if (horizontalAdornerPlacement == AdornerPlacement.Outside) { return -child.DesiredSize.Width + offsetX; } else { return offsetX; } } case HorizontalAlignment.Right: { if (horizontalAdornerPlacement == AdornerPlacement.Outside) { double adornedWidth = AdornedElement.ActualWidth; return adornedWidth + offsetX; } else { double adornerWidth = this.child.DesiredSize.Width; double adornedWidth = AdornedElement.ActualWidth; double x = adornedWidth - adornerWidth; return x + offsetX; } } case HorizontalAlignment.Center: { double adornerWidth = this.child.DesiredSize.Width; double adornedWidth = AdornedElement.ActualWidth; double x = (adornedWidth / 2) - (adornerWidth / 2); return x + offsetX; } case HorizontalAlignment.Stretch: { return 0.0; } } return 0.0; } /// /// Determine the Y coordinate of the child. /// private double DetermineY() { switch (child.VerticalAlignment) { case VerticalAlignment.Top: { if (verticalAdornerPlacement == AdornerPlacement.Outside) { return -child.DesiredSize.Height + offsetY; } else { return offsetY; } } case VerticalAlignment.Bottom: { if (verticalAdornerPlacement == AdornerPlacement.Outside) { double adornedHeight = AdornedElement.ActualHeight; return adornedHeight + offsetY; } else { double adornerHeight = this.child.DesiredSize.Height; double adornedHeight = AdornedElement.ActualHeight; double x = adornedHeight - adornerHeight; return x + offsetY; } } case VerticalAlignment.Center: { double adornerHeight = this.child.DesiredSize.Height; double adornedHeight = AdornedElement.ActualHeight; double x = (adornedHeight / 2) - (adornerHeight / 2); return x + offsetY; } case VerticalAlignment.Stretch: { return 0.0; } } return 0.0; } /// /// Determine the width of the child. /// private double DetermineWidth() { if (!Double.IsNaN(PositionX)) { return this.child.DesiredSize.Width; } switch (child.HorizontalAlignment) { case HorizontalAlignment.Left: { return this.child.DesiredSize.Width; } case HorizontalAlignment.Right: { return this.child.DesiredSize.Width; } case HorizontalAlignment.Center: { return this.child.DesiredSize.Width; } case HorizontalAlignment.Stretch: { return AdornedElement.ActualWidth; } } return 0.0; } /// /// Determine the height of the child. /// private double DetermineHeight() { if (!Double.IsNaN(PositionY)) { return this.child.DesiredSize.Height; } switch (child.VerticalAlignment) { case VerticalAlignment.Top: { return this.child.DesiredSize.Height; } case VerticalAlignment.Bottom: { return this.child.DesiredSize.Height; } case VerticalAlignment.Center: { return this.child.DesiredSize.Height; } case VerticalAlignment.Stretch: { return AdornedElement.ActualHeight; } } return 0.0; } protected override Size ArrangeOverride(Size finalSize) { double x = PositionX; if (Double.IsNaN(x)) { x = DetermineX(); } double y = PositionY; if (Double.IsNaN(y)) { y = DetermineY(); } double adornerWidth = DetermineWidth(); double adornerHeight = DetermineHeight(); this.child.Arrange(new Rect(x, y, adornerWidth, adornerHeight)); return finalSize; } protected override Int32 VisualChildrenCount { get { return 1; } } protected override Visual GetVisualChild(Int32 index) { return this.child; } protected override IEnumerator LogicalChildren { get { ArrayList list = new ArrayList(); list.Add(this.child); return list.GetEnumerator(); } } /// /// Disconnect the child element from the visual tree so that it may be reused later. /// public void DisconnectChild() { base.RemoveLogicalChild(child); base.RemoveVisualChild(child); } /// /// Override AdornedElement from base class for less type-checking. /// public new FrameworkElement AdornedElement { get { return (FrameworkElement)base.AdornedElement; } } } }