From 0c2060c07fdc76c9c7299d9dcc8ddc4a411e36b6 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Thu, 26 May 2016 01:04:04 +0100 Subject: [PATCH 1/2] added horizontal and vertical offset properties to popup. --- src/Avalonia.Controls/Primitives/Popup.cs | 43 +++++++++++++++++++++-- 1 file changed, 40 insertions(+), 3 deletions(-) diff --git a/src/Avalonia.Controls/Primitives/Popup.cs b/src/Avalonia.Controls/Primitives/Popup.cs index c24d1cef2d..6bb4f31a56 100644 --- a/src/Avalonia.Controls/Primitives/Popup.cs +++ b/src/Avalonia.Controls/Primitives/Popup.cs @@ -39,6 +39,18 @@ namespace Avalonia.Controls.Primitives public static readonly StyledProperty PlacementModeProperty = AvaloniaProperty.Register(nameof(PlacementMode), defaultValue: PlacementMode.Bottom); + /// + /// Defines the property. + /// + public static readonly StyledProperty HorizontalOffsetProperty = + AvaloniaProperty.Register(nameof(HorizontalOffset)); + + /// + /// Defines the property. + /// + public static readonly StyledProperty VerticalOffsetProperty = + AvaloniaProperty.Register(nameof(VerticalOffset)); + /// /// Defines the property. /// @@ -122,6 +134,24 @@ namespace Avalonia.Controls.Primitives set { SetValue(PlacementModeProperty, value); } } + /// + /// Gets or sets the Horizontal offset of the popup in relation to the + /// + public double HorizontalOffset + { + get { return GetValue(HorizontalOffsetProperty); } + set { SetValue(HorizontalOffsetProperty, value); } + } + + /// + /// Gets or sets the Vertical offset of the popup in relation to the + /// + public double VerticalOffset + { + get { return GetValue(VerticalOffsetProperty); } + set { SetValue(VerticalOffsetProperty, value); } + } + /// /// Gets or sets the control that is used to determine the popup's position. /// @@ -292,13 +322,20 @@ namespace Avalonia.Controls.Primitives switch (mode) { case PlacementMode.Pointer: - return MouseDevice.Instance?.Position ?? default(Point); + if (MouseDevice.Instance != null) + { + var offset = new Point(HorizontalOffset, VerticalOffset); + + return new Point(MouseDevice.Instance.Position.X + offset.X, MouseDevice.Instance.Position.Y + offset.Y); + } + + return default(Point); case PlacementMode.Bottom: - return target?.PointToScreen(new Point(0, target.Bounds.Height)) ?? zero; + return target?.PointToScreen(new Point(0 + HorizontalOffset, target.Bounds.Height + VerticalOffset)) ?? zero; case PlacementMode.Right: - return target?.PointToScreen(new Point(target.Bounds.Width, 0)) ?? zero; + return target?.PointToScreen(new Point(target.Bounds.Width + HorizontalOffset, 0 + VerticalOffset)) ?? zero; default: throw new InvalidOperationException("Invalid value for Popup.PlacementMode"); From e931bcf79c30fe9345c8ca1d56123775ca318acb Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Fri, 27 May 2016 22:41:10 +0100 Subject: [PATCH 2/2] correctly scale offsets for pointer placement mode. --- src/Avalonia.Controls/Primitives/Popup.cs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/Avalonia.Controls/Primitives/Popup.cs b/src/Avalonia.Controls/Primitives/Popup.cs index 6bb4f31a56..81d01ff74f 100644 --- a/src/Avalonia.Controls/Primitives/Popup.cs +++ b/src/Avalonia.Controls/Primitives/Popup.cs @@ -10,6 +10,7 @@ using Avalonia.LogicalTree; using Avalonia.Metadata; using Avalonia.Rendering; using Avalonia.VisualTree; +using Avalonia.Layout; namespace Avalonia.Controls.Primitives { @@ -317,21 +318,22 @@ namespace Avalonia.Controls.Primitives if (target?.GetVisualRoot() == null) { mode = PlacementMode.Pointer; - } + } switch (mode) { case PlacementMode.Pointer: if (MouseDevice.Instance != null) { - var offset = new Point(HorizontalOffset, VerticalOffset); - - return new Point(MouseDevice.Instance.Position.X + offset.X, MouseDevice.Instance.Position.Y + offset.Y); + // Scales the Horizontal and Vertical offset to screen co-ordinates. + var screenOffset = new Point(HorizontalOffset * (PopupRoot as ILayoutRoot).LayoutScaling, VerticalOffset * (PopupRoot as ILayoutRoot).LayoutScaling); + return MouseDevice.Instance.Position + screenOffset; } return default(Point); case PlacementMode.Bottom: + return target?.PointToScreen(new Point(0 + HorizontalOffset, target.Bounds.Height + VerticalOffset)) ?? zero; case PlacementMode.Right: