1 //----------------------------------------------------------------
2 // <copyright company="Microsoft Corporation">
3 // Copyright (c) Microsoft Corporation. All rights reserved.
5 //----------------------------------------------------------------
7 namespace System.Activities.Presentation.Annotations
9 using System.Activities.Presentation.View;
12 using System.Windows.Controls;
13 using System.Windows.Documents;
14 using System.Windows.Media;
16 internal class AnnotationAdorner : Adorner
18 public static readonly DependencyProperty AnchorProperty = DependencyProperty.RegisterAttached("Anchor", typeof(AdornerLocation), typeof(AnnotationAdorner), new FrameworkPropertyMetadata(AdornerLocation.None));
19 private UIElement content;
21 public AnnotationAdorner(UIElement adornedElement)
22 : base(adornedElement)
26 internal ScrollViewer ScrollViewer
32 internal UIElement Content
41 if (this.content != value)
43 if (this.content != null)
45 this.RemoveVisualChild(this.content);
49 if (this.content != null)
51 this.AddVisualChild(this.content);
57 protected override int VisualChildrenCount
65 public static AdornerLocation GetAnchor(DependencyObject obj)
67 return (AdornerLocation)obj.GetValue(AnnotationAdorner.AnchorProperty);
70 public static void SetAnchor(DependencyObject obj, AdornerLocation anchor)
72 obj.SetValue(AnnotationAdorner.AnchorProperty, anchor);
79 // canvas is divided into four areas by anchorPoint
80 // try to figure out which area could fit desiredSize from area1 to area4, if there's no fit, default to area4.
81 internal static AdornerLocation FindAnchor(Point anchorPoint, Size desiredSize, Rect canvas)
83 Fx.Assert(anchorPoint.X >= canvas.X && anchorPoint.X <= canvas.X + canvas.Width, "X axis of anchorPoint not within canvas");
84 Fx.Assert(anchorPoint.Y >= canvas.Y && anchorPoint.Y <= canvas.Y + canvas.Height, "Y axis of anchorPoint not within canvas");
86 AdornerLocation anchor = AdornerLocation.None;
89 if (anchorPoint.X + desiredSize.Width <= canvas.X + canvas.Width)
92 if (anchorPoint.Y + desiredSize.Height <= canvas.Y + canvas.Height)
94 anchor = AdornerLocation.BottomRight;
98 if (anchor == AdornerLocation.None && anchorPoint.Y - desiredSize.Height >= canvas.Y)
100 anchor = AdornerLocation.TopRight;
105 if (anchor == AdornerLocation.None && anchorPoint.X - desiredSize.Width >= canvas.X && anchorPoint.Y - desiredSize.Height >= canvas.Y)
107 anchor = AdornerLocation.TopLeft;
111 if (anchor == AdornerLocation.None)
113 anchor = AdornerLocation.BottomLeft;
119 protected override Visual GetVisualChild(int index)
124 protected override Size MeasureOverride(Size constraint)
126 this.content.Measure(constraint);
127 return this.content.DesiredSize;
130 protected override Size ArrangeOverride(Size finalSize)
132 Point anchorPoint = this.AdornedElement.TranslatePoint(new Point(this.AdornedElement.RenderSize.Width, 0), this.ScrollViewer);
134 AdornerLocation anchor = AnnotationAdorner.GetAnchor(this);
135 if (anchor == AdornerLocation.None)
137 // Calculate based on the real size of the adorner, depending on current zoom level
138 DesignerView designerView = ((WorkflowViewElement)AdornedElement).Context.Services.GetService<DesignerView>();
139 double zoomLevel = designerView.ZoomFactor;
140 Size adornerSize = new Size(this.content.DesiredSize.Width * zoomLevel, this.content.DesiredSize.Height * zoomLevel);
141 anchor = FindAnchor(anchorPoint, adornerSize, new Rect(0, 0, this.ScrollViewer.ViewportWidth, this.ScrollViewer.ViewportHeight));
142 AnnotationAdorner.SetAnchor(this, anchor);
145 Point location = CalculateLocation(anchor, this.AdornedElement.RenderSize, this.content.DesiredSize);
147 this.content.Arrange(new Rect(location, finalSize));
152 private static Point CalculateLocation(AdornerLocation anchor, Size adorneeSize, Size adornerSize)
154 Point location = new Point();
158 case AdornerLocation.BottomRight:
159 location = new Point(adorneeSize.Width, 0);
161 case AdornerLocation.TopRight:
162 location = new Point(adorneeSize.Width, -adornerSize.Height);
164 case AdornerLocation.TopLeft:
165 location = new Point(adorneeSize.Width - adornerSize.Width, -adornerSize.Height);
167 case AdornerLocation.BottomLeft:
168 location = new Point(adorneeSize.Width - adornerSize.Width, 20);