/// <summary> /// Positions one rectangle relative to another, according to the specified <see cref="PopupAlignmentPoint"/> values. /// </summary> /// <param name="actualTargetElement">The element that was actually targeted for placement of the popup.</param> /// <param name="targetOrigin">The origin point of the target rectangle.</param> /// <param name="target">The target rectangle.</param> /// <param name="popupOrigin">The origin point of the popup rectangle.</param> /// <param name="popup">The popup size.</param> /// <returns>The popup rectangle positioned relative to the target rectangle and including the /// values of <see cref="HorizontalOffset"/> and <see cref="VerticalOffset"/> properties.</returns> private RectangleD PositionRects(UIElement actualTargetElement, PopupAlignmentPoint targetOrigin, RectangleD target, PopupAlignmentPoint popupOrigin, Size2D popup) { var transformOriginX = 0.0; switch (popupOrigin) { case PopupAlignmentPoint.TopCenter: case PopupAlignmentPoint.Center: case PopupAlignmentPoint.BottomCenter: transformOriginX = popup.Width / 2.0; break; case PopupAlignmentPoint.TopRight: case PopupAlignmentPoint.MiddleRight: case PopupAlignmentPoint.BottomRight: transformOriginX = popup.Width; break; } var transformOriginY = 0.0; switch (popupOrigin) { case PopupAlignmentPoint.MiddleLeft: case PopupAlignmentPoint.Center: case PopupAlignmentPoint.MiddleRight: transformOriginY = popup.Height / 2.0; break; case PopupAlignmentPoint.BottomLeft: case PopupAlignmentPoint.BottomCenter: case PopupAlignmentPoint.BottomRight: transformOriginY = popup.Height; break; } var resultX = 0.0; var resultY = 0.0; switch (targetOrigin) { case PopupAlignmentPoint.TopLeft: resultX = target.Left; resultY = target.Top; break; case PopupAlignmentPoint.TopCenter: resultX = target.Left + (target.Width / 2.0); resultY = target.Top; break; case PopupAlignmentPoint.TopRight: resultX = target.Right; resultY = target.Top; break; case PopupAlignmentPoint.MiddleLeft: resultX = target.Left; resultY = target.Top + (target.Height / 2.0); break; case PopupAlignmentPoint.Center: resultX = target.Left + (target.Width / 2.0); resultY = target.Top + (target.Height / 2.0); break; case PopupAlignmentPoint.MiddleRight: resultX = target.Right; resultY = target.Top + (target.Height / 2.0); break; case PopupAlignmentPoint.BottomLeft: resultX = target.Left; resultY = target.Bottom; break; case PopupAlignmentPoint.BottomCenter: resultX = target.Left + (target.Width / 2.0); resultY = target.Bottom; break; case PopupAlignmentPoint.BottomRight: resultX = target.Right; resultY = target.Bottom; break; } popupTransformOrigin = new Point2D(transformOriginX, transformOriginY); if (actualTargetElement != null) { var actualTargetTransform = actualTargetElement.GetTransformToViewMatrix(); var actualTargetPosition = new Point2D(HorizontalOffset + resultX, VerticalOffset + resultY); Point2D.Transform(ref actualTargetPosition, ref actualTargetTransform, out popupPosition); } else { popupPosition = new Point2D( PlacementRectangle.X + HorizontalOffset + resultX, PlacementRectangle.Y + VerticalOffset + resultY); } ComputeTransformationMatrices(); return new RectangleD(-transformOriginX, -transformOriginY, popup.Width, popup.Height); }