diff --git a/Src/ToastNotifications/Position/ControlPositionProvider.cs b/Src/ToastNotifications/Position/ControlPositionProvider.cs index 7d1b12d..18d38a9 100644 --- a/Src/ToastNotifications/Position/ControlPositionProvider.cs +++ b/Src/ToastNotifications/Position/ControlPositionProvider.cs @@ -5,32 +5,21 @@ namespace ToastNotifications.Position { - public class ControlPositionProvider : IPositionProvider + public class ControlPositionProvider : PositionProvider { - private readonly double _offsetX; - private readonly double _offsetY; - private readonly Corner _corner; - private readonly FrameworkElement _element; - public Window ParentWindow { get; } - public EjectDirection EjectDirection { get; private set; } + private readonly FrameworkElement _element; - public ControlPositionProvider(Window parentWindow, FrameworkElement trackingElement, Corner corner, double offsetX, double offsetY) + public ControlPositionProvider(Window parentWindow, + FrameworkElement trackingElement, + Corner corner, + double offsetX, + double offsetY) : base(parentWindow, corner, offsetX, offsetY) { - _corner = corner; - _offsetX = offsetX; - _offsetY = offsetY; _element = trackingElement; - - ParentWindow = parentWindow; - - parentWindow.SizeChanged += ParentWindowOnSizeChanged; - parentWindow.LocationChanged += ParentWindowOnLocationChanged; - - SetEjectDirection(corner); } - public Point GetPosition(double actualPopupWidth, double actualPopupHeight) + public override Point GetPosition(double actualPopupWidth, double actualPopupHeight) { var source = PresentationSource.FromVisual(ParentWindow); if (source?.CompositionTarget == null) @@ -39,98 +28,43 @@ public Point GetPosition(double actualPopupWidth, double actualPopupHeight) Matrix transform = source.CompositionTarget.TransformFromDevice; Point location = transform.Transform(_element.PointToScreen(new Point(0, 0))); - switch (_corner) - { - case Corner.TopRight: - return GetPositionForTopRightCorner(location, actualPopupWidth, actualPopupHeight); - case Corner.TopLeft: - return GetPositionForTopLeftCorner(location, actualPopupWidth, actualPopupHeight); - case Corner.BottomRight: - return GetPositionForBottomRightCorner(location, actualPopupWidth, actualPopupHeight); - case Corner.BottomCenter: - return GetPositionForBottomCenterCorner(location, actualPopupWidth, actualPopupHeight); - case Corner.BottomLeft: - return GetPositionForBottomLeftCorner(location, actualPopupWidth, actualPopupHeight); - default: - throw new ArgumentOutOfRangeException(); - } + return GetPositionForCorner(location, actualPopupWidth, actualPopupHeight); } - public double GetHeight() + public override double GetHeight() { return ParentWindow.ActualHeight; } - private void SetEjectDirection(Corner corner) - { - switch (corner) - { - case Corner.TopRight: - case Corner.TopLeft: - EjectDirection = EjectDirection.ToBottom; - break; - case Corner.BottomRight: - case Corner.BottomLeft: - case Corner.BottomCenter: - EjectDirection = EjectDirection.ToTop; - break; - default: - throw new ArgumentOutOfRangeException(nameof(corner), corner, null); - } - } - - private Point GetPositionForBottomLeftCorner(Point location, double actualPopupWidth, double actualPopupHeight) + protected override Point GetPositionForBottomLeftCorner(Point location, double actualPopupWidth, double actualPopupHeight) { return new Point(location.X + _offsetX, location.Y + _element.ActualHeight - _offsetY - actualPopupHeight); } - private Point GetPositionForBottomRightCorner(Point location, double actualPopupWidth, double actualPopupHeight) + protected override Point GetPositionForBottomRightCorner(Point location, double actualPopupWidth, double actualPopupHeight) { return new Point(location.X + _element.ActualWidth - _offsetX - actualPopupWidth, location.Y + _element.ActualHeight - _offsetY - actualPopupHeight); } - private Point GetPositionForBottomCenterCorner(Point location, double actualPopupWidth, double actualPopupHeight) + protected override Point GetPositionForBottomCenterCorner(Point location, double actualPopupWidth, double actualPopupHeight) { return new Point(location.X + (_element.ActualWidth - _offsetX - actualPopupWidth) / 2, location.Y + _element.ActualHeight - _offsetY - actualPopupHeight); } - - private Point GetPositionForTopLeftCorner(Point location, double actualPopupWidth, double actualPopupHeight) + protected override Point GetPositionForTopLeftCorner(Point location, double actualPopupWidth, double actualPopupHeight) { return new Point(location.X + _offsetX, location.Y + _offsetY); } - private Point GetPositionForTopRightCorner(Point location, double actualPopupWidth, double actualPopupHeight) + protected override Point GetPositionForTopRightCorner(Point location, double actualPopupWidth, double actualPopupHeight) { return new Point(location.X + _element.ActualWidth - _offsetX - actualPopupWidth, location.Y + _offsetY); } - public void Dispose() + protected override Point GetPositionForTopCenterCorner(Point location, double actualPopupWidth, double actualPopupHeight) { - ParentWindow.LocationChanged -= ParentWindowOnLocationChanged; - ParentWindow.SizeChanged -= ParentWindowOnSizeChanged; + return new Point(location.X + (_element.ActualWidth - _offsetX - actualPopupWidth) / 2, location.Y + _offsetY); } - protected virtual void RequestUpdatePosition() - { - UpdatePositionRequested?.Invoke(this, EventArgs.Empty); - } - - private void ParentWindowOnLocationChanged(object sender, EventArgs eventArgs) - { - RequestUpdatePosition(); - } - - private void ParentWindowOnSizeChanged(object sender, SizeChangedEventArgs sizeChangedEventArgs) - { - RequestUpdatePosition(); - } -#pragma warning disable CS0067 - public event EventHandler UpdatePositionRequested; - - public event EventHandler UpdateEjectDirectionRequested; - - public event EventHandler UpdateHeightRequested; -#pragma warning restore CS0067 - } + } } \ No newline at end of file diff --git a/Src/ToastNotifications/Position/Corner.cs b/Src/ToastNotifications/Position/Corner.cs index 87f7ac0..8787154 100644 --- a/Src/ToastNotifications/Position/Corner.cs +++ b/Src/ToastNotifications/Position/Corner.cs @@ -4,6 +4,7 @@ public enum Corner { TopRight, TopLeft, + TopCenter, BottomRight, BottomLeft, BottomCenter diff --git a/Src/ToastNotifications/Position/GdiPrimaryScreenPositionProvider.cs b/Src/ToastNotifications/Position/GdiPrimaryScreenPositionProvider.cs index 252016b..efa7f1e 100644 --- a/Src/ToastNotifications/Position/GdiPrimaryScreenPositionProvider.cs +++ b/Src/ToastNotifications/Position/GdiPrimaryScreenPositionProvider.cs @@ -5,13 +5,10 @@ namespace ToastNotifications.Position { - public class GdiPrimaryScreenPositionProvider : IPositionProvider + public class GdiPrimaryScreenPositionProvider : PositionProvider { - private readonly Corner _corner; private readonly float _dpiRatioX; private readonly float _dpiRatioY; - private readonly double _offsetX; - private readonly double _offsetY; private double ScreenHeight => Screen.PrimaryScreen.Bounds.Height / _dpiRatioY; private double ScreenWidth => Screen.PrimaryScreen.Bounds.Width / _dpiRatioX; @@ -19,71 +16,25 @@ public class GdiPrimaryScreenPositionProvider : IPositionProvider private double WorkAreaHeight => Screen.PrimaryScreen.WorkingArea.Height / _dpiRatioY; private double WorkAreaWidth => Screen.PrimaryScreen.WorkingArea.Width / _dpiRatioX; - public Window ParentWindow { get; } - public EjectDirection EjectDirection { get; private set; } - public GdiPrimaryScreenPositionProvider( Corner corner, double offsetX, - double offsetY) + double offsetY) : base(null, corner, offsetX, offsetY) { - _corner = corner; + using (var gfx = System.Drawing.Graphics.FromHwnd(IntPtr.Zero)) { _dpiRatioX = gfx.DpiX / 96F; _dpiRatioY = gfx.DpiY / 96F; } - _offsetX = offsetX; - _offsetY = offsetY; - - ParentWindow = null; - - SetEjectDirection(corner); - } - - public Point GetPosition(double actualPopupWidth, double actualPopupHeight) - { - switch (_corner) - { - case Corner.TopRight: - return GetPositionForTopRightCorner(actualPopupWidth, actualPopupHeight); - case Corner.TopLeft: - return GetPositionForTopLeftCorner(actualPopupWidth, actualPopupHeight); - case Corner.BottomRight: - return GetPositionForBottomRightCorner(actualPopupWidth, actualPopupHeight); - case Corner.BottomLeft: - return GetPositionForBottomLeftCorner(actualPopupWidth, actualPopupHeight); - case Corner.BottomCenter: - return GetPositionForBottomCenterCorner(actualPopupWidth, actualPopupHeight); - default: - throw new ArgumentOutOfRangeException(); - } } - public double GetHeight() + public override double GetHeight() { return ScreenHeight; } - private void SetEjectDirection(Corner corner) - { - switch (corner) - { - case Corner.TopRight: - case Corner.TopLeft: - EjectDirection = EjectDirection.ToBottom; - break; - case Corner.BottomRight: - case Corner.BottomLeft: - case Corner.BottomCenter: - EjectDirection = EjectDirection.ToTop; - break; - default: - throw new ArgumentOutOfRangeException(nameof(corner), corner, null); - } - } - - private Point GetPositionForBottomLeftCorner(double actualPopupWidth, double actualPopupHeight) + protected override Point GetPositionForBottomLeftCorner(Point parentPosition, double actualPopupWidth, double actualPopupHeight) { double pointX = _offsetX; double pointY = WorkAreaHeight - _offsetY - actualPopupHeight; @@ -102,7 +53,7 @@ private Point GetPositionForBottomLeftCorner(double actualPopupWidth, double act return new Point(pointX, pointY); } - private Point GetPositionForBottomCenterCorner(double actualPopupWidth, double actualPopupHeight) + protected override Point GetPositionForBottomCenterCorner(Point parentPosition, double actualPopupWidth, double actualPopupHeight) { double pointX = (WorkAreaWidth - _offsetX - actualPopupWidth) / 2; double pointY = WorkAreaHeight - _offsetY - actualPopupHeight; @@ -122,7 +73,7 @@ private Point GetPositionForBottomCenterCorner(double actualPopupWidth, double a } - private Point GetPositionForBottomRightCorner(double actualPopupWidth, double actualPopupHeight) + protected override Point GetPositionForBottomRightCorner(Point parentPosition, double actualPopupWidth, double actualPopupHeight) { double pointX = WorkAreaWidth - _offsetX - actualPopupWidth; double pointY = WorkAreaHeight - _offsetY - actualPopupHeight; @@ -141,7 +92,7 @@ private Point GetPositionForBottomRightCorner(double actualPopupWidth, double ac return new Point(pointX, pointY); } - private Point GetPositionForTopLeftCorner(double actualPopupWidth, double actualPopupHeight) + protected override Point GetPositionForTopLeftCorner(Point parentPosition, double actualPopupWidth, double actualPopupHeight) { double pointX = _offsetX; double pointY = _offsetY; @@ -160,7 +111,7 @@ private Point GetPositionForTopLeftCorner(double actualPopupWidth, double actual return new Point(pointX, pointY); } - private Point GetPositionForTopRightCorner(double actualPopupWidth, double actualPopupHeight) + protected override Point GetPositionForTopRightCorner(Point parentPosition, double actualPopupWidth, double actualPopupHeight) { double pointX = WorkAreaWidth - _offsetX - actualPopupWidth; double pointY = _offsetY; @@ -179,6 +130,24 @@ private Point GetPositionForTopRightCorner(double actualPopupWidth, double actua return new Point(pointX, pointY); } + protected override Point GetPositionForTopCenterCorner(Point parentPosition, double actualPopupWidth, double actualPopupHeight) + { + double pointX = (WorkAreaWidth - _offsetX - actualPopupWidth) / 2; + double pointY = _offsetY; + + switch (GetTaskBarLocation()) + { + case WindowsTaskBarLocation.Left: + pointX = (ScreenWidth - _offsetX - actualPopupWidth) / 2; + break; + + case WindowsTaskBarLocation.Top: + pointY = ScreenHeight - WorkAreaHeight + _offsetY; + break; + } + + return new Point(pointX, pointY); + } private WindowsTaskBarLocation GetTaskBarLocation() { @@ -195,18 +164,5 @@ private WindowsTaskBarLocation GetTaskBarLocation() return WindowsTaskBarLocation.Bottom; } - - public void Dispose() - { - // nothing to do here - } - -#pragma warning disable CS0067 - public event EventHandler UpdatePositionRequested; - - public event EventHandler UpdateEjectDirectionRequested; - - public event EventHandler UpdateHeightRequested; -#pragma warning restore CS0067 } } diff --git a/Src/ToastNotifications/Position/PositionProvider.cs b/Src/ToastNotifications/Position/PositionProvider.cs new file mode 100644 index 0000000..e47cd2a --- /dev/null +++ b/Src/ToastNotifications/Position/PositionProvider.cs @@ -0,0 +1,153 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Windows; +using ToastNotifications.Core; + +namespace ToastNotifications.Position +{ + public abstract class PositionProvider : IPositionProvider + { + protected readonly Corner _corner; + protected readonly double _offsetX; + protected readonly double _offsetY; + + public Window ParentWindow { get; } + public EjectDirection EjectDirection { get; protected set; } + + public PositionProvider( + Window parentWindow, + Corner corner, + double offsetX, + double offsetY) + { + _corner = corner; + _offsetX = offsetX; + _offsetY = offsetY; + if(parentWindow != null) + { + ParentWindow = parentWindow; + parentWindow.SizeChanged += ParentWindowOnSizeChanged; + parentWindow.LocationChanged += ParentWindowOnLocationChanged; + parentWindow.StateChanged += ParentWindowOnStateChanged; + parentWindow.Activated += ParentWindowOnActivated; + } + + SetEjectDirection(corner); + } + + public virtual Point GetPosition(double actualPopupWidth, double actualPopupHeight) + { + Point parentPosition; + if (ParentWindow == null) + //inheriting classes can ignore this value if they do not use a parent; + parentPosition = new Point(0, 0); + else + parentPosition = ParentWindow.GetActualPosition(); + + return GetPositionForCorner(parentPosition,actualPopupWidth, actualPopupHeight); + } + + protected virtual Point GetPositionForCorner(Point parentPosition, double actualPopupWidth, double actualPopupHeight) + { + switch (_corner) + { + case Corner.TopRight: + return GetPositionForTopRightCorner(parentPosition, actualPopupWidth, actualPopupHeight); + case Corner.TopLeft: + return GetPositionForTopLeftCorner(parentPosition, actualPopupWidth, actualPopupHeight); + case Corner.TopCenter: + return GetPositionForTopCenterCorner(parentPosition, actualPopupWidth, actualPopupHeight); + case Corner.BottomRight: + return GetPositionForBottomRightCorner(parentPosition, actualPopupWidth, actualPopupHeight); + case Corner.BottomLeft: + return GetPositionForBottomLeftCorner(parentPosition, actualPopupWidth, actualPopupHeight); + case Corner.BottomCenter: + return GetPositionForBottomCenterCorner(parentPosition, actualPopupWidth, actualPopupHeight); + default: + throw new ArgumentOutOfRangeException(); + } + } + + public abstract double GetHeight(); + + protected virtual void SetEjectDirection(Corner corner) + { + switch (corner) + { + case Corner.TopRight: + case Corner.TopLeft: + case Corner.TopCenter: + EjectDirection = EjectDirection.ToBottom; + break; + case Corner.BottomRight: + case Corner.BottomLeft: + case Corner.BottomCenter: + EjectDirection = EjectDirection.ToTop; + break; + default: + throw new ArgumentOutOfRangeException(nameof(corner), corner, null); + } + } + + protected abstract Point GetPositionForBottomLeftCorner(Point parentPosition, double actualPopupWidth, double actualPopupHeight); + + protected abstract Point GetPositionForBottomRightCorner(Point parentPosition, double actualPopupWidth, double actualPopupHeight); + + protected abstract Point GetPositionForBottomCenterCorner(Point parentPosition, double actualPopupWidth, double actualPopupHeight); + + protected abstract Point GetPositionForTopLeftCorner(Point parentPosition, double actualPopupWidth, double actualPopupHeight); + + protected abstract Point GetPositionForTopRightCorner(Point parentPosition, double actualPopupWidth, double actualPopupHeight); + + protected abstract Point GetPositionForTopCenterCorner(Point parentPosition, double actualPopupWidth, double actualPopupHeight); + + public void Dispose() + { + if(ParentWindow != null) + { + ParentWindow.LocationChanged -= ParentWindowOnLocationChanged; + ParentWindow.SizeChanged -= ParentWindowOnSizeChanged; + ParentWindow.StateChanged -= ParentWindowOnStateChanged; + ParentWindow.Activated -= ParentWindowOnActivated; + } + } + + protected virtual void RequestUpdatePosition() + { + UpdateHeightRequested?.Invoke(this, EventArgs.Empty); + UpdateEjectDirectionRequested?.Invoke(this, EventArgs.Empty); + UpdatePositionRequested?.Invoke(this, EventArgs.Empty); + } + + protected virtual void ParentWindowOnLocationChanged(object sender, EventArgs eventArgs) + { + RequestUpdatePosition(); + } + + protected virtual void ParentWindowOnSizeChanged(object sender, SizeChangedEventArgs sizeChangedEventArgs) + { + RequestUpdatePosition(); + } + + protected virtual void ParentWindowOnStateChanged(object sender, EventArgs eventArgs) + { + RequestUpdatePosition(); + } + + protected virtual void ParentWindowOnActivated(object sender, EventArgs eventArgs) + { + RequestUpdatePosition(); + } + +#pragma warning disable CS0067 + public event EventHandler UpdatePositionRequested; + + public event EventHandler UpdateEjectDirectionRequested; + + public event EventHandler UpdateHeightRequested; +#pragma warning restore CS0067 + + } +} diff --git a/Src/ToastNotifications/Position/PrimaryScreenPositionProvider.cs b/Src/ToastNotifications/Position/PrimaryScreenPositionProvider.cs index 250e029..8892273 100644 --- a/Src/ToastNotifications/Position/PrimaryScreenPositionProvider.cs +++ b/Src/ToastNotifications/Position/PrimaryScreenPositionProvider.cs @@ -4,11 +4,8 @@ namespace ToastNotifications.Position { - public class PrimaryScreenPositionProvider : IPositionProvider + public class PrimaryScreenPositionProvider : PositionProvider { - private readonly Corner _corner; - private readonly double _offsetX; - private readonly double _offsetY; private double ScreenHeight => SystemParameters.PrimaryScreenHeight; private double ScreenWidth => SystemParameters.PrimaryScreenWidth; @@ -22,60 +19,17 @@ public class PrimaryScreenPositionProvider : IPositionProvider public PrimaryScreenPositionProvider( Corner corner, double offsetX, - double offsetY) + double offsetY) : base(null, corner, offsetX, offsetY) { - _corner = corner; - _offsetX = offsetX; - _offsetY = offsetY; - - ParentWindow = null; - - SetEjectDirection(corner); } - public Point GetPosition(double actualPopupWidth, double actualPopupHeight) - { - switch (_corner) - { - case Corner.TopRight: - return GetPositionForTopRightCorner(actualPopupWidth, actualPopupHeight); - case Corner.TopLeft: - return GetPositionForTopLeftCorner(actualPopupWidth, actualPopupHeight); - case Corner.BottomRight: - return GetPositionForBottomRightCorner(actualPopupWidth, actualPopupHeight); - case Corner.BottomLeft: - return GetPositionForBottomLeftCorner(actualPopupWidth, actualPopupHeight); - case Corner.BottomCenter: - return GetPositionForBottomCenterCorner(actualPopupWidth, actualPopupHeight); - default: - throw new ArgumentOutOfRangeException(); - } - } - public double GetHeight() + public override double GetHeight() { return ScreenHeight; } - private void SetEjectDirection(Corner corner) - { - switch (corner) - { - case Corner.TopRight: - case Corner.TopLeft: - EjectDirection = EjectDirection.ToBottom; - break; - case Corner.BottomRight: - case Corner.BottomLeft: - case Corner.BottomCenter: - EjectDirection = EjectDirection.ToTop; - break; - default: - throw new ArgumentOutOfRangeException(nameof(corner), corner, null); - } - } - - private Point GetPositionForBottomLeftCorner(double actualPopupWidth, double actualPopupHeight) + protected override Point GetPositionForBottomLeftCorner(Point parentPosition, double actualPopupWidth, double actualPopupHeight) { double pointX = _offsetX; double pointY = WorkAreaHeight - _offsetY - actualPopupHeight; @@ -94,7 +48,7 @@ private Point GetPositionForBottomLeftCorner(double actualPopupWidth, double act return new Point(pointX, pointY); } - private Point GetPositionForBottomCenterCorner(double actualPopupWidth, double actualPopupHeight) + protected override Point GetPositionForBottomCenterCorner(Point parentPosition, double actualPopupWidth, double actualPopupHeight) { double pointX = (WorkAreaWidth - _offsetX - actualPopupWidth) / 2; double pointY = WorkAreaHeight - _offsetY - actualPopupHeight; @@ -114,7 +68,7 @@ private Point GetPositionForBottomCenterCorner(double actualPopupWidth, double a } - private Point GetPositionForBottomRightCorner(double actualPopupWidth, double actualPopupHeight) + protected override Point GetPositionForBottomRightCorner(Point parentPosition, double actualPopupWidth, double actualPopupHeight) { double pointX = WorkAreaWidth - _offsetX - actualPopupWidth; double pointY = WorkAreaHeight - _offsetY - actualPopupHeight; @@ -133,7 +87,7 @@ private Point GetPositionForBottomRightCorner(double actualPopupWidth, double ac return new Point(pointX, pointY); } - private Point GetPositionForTopLeftCorner(double actualPopupWidth, double actualPopupHeight) + protected override Point GetPositionForTopLeftCorner(Point parentPosition, double actualPopupWidth, double actualPopupHeight) { double pointX = _offsetX; double pointY = _offsetY; @@ -152,7 +106,7 @@ private Point GetPositionForTopLeftCorner(double actualPopupWidth, double actual return new Point(pointX, pointY); } - private Point GetPositionForTopRightCorner(double actualPopupWidth, double actualPopupHeight) + protected override Point GetPositionForTopRightCorner(Point parentPosition, double actualPopupWidth, double actualPopupHeight) { double pointX = WorkAreaWidth - _offsetX - actualPopupWidth; double pointY = _offsetY; @@ -170,6 +124,24 @@ private Point GetPositionForTopRightCorner(double actualPopupWidth, double actua return new Point(pointX, pointY); } + protected override Point GetPositionForTopCenterCorner(Point parentPosition, double actualPopupWidth, double actualPopupHeight) + { + double pointX = (WorkAreaWidth - _offsetX - actualPopupWidth) / 2; + double pointY = _offsetY; + + switch (GetTaskBarLocation()) + { + case WindowsTaskBarLocation.Left: + pointX = (ScreenWidth - _offsetX - actualPopupWidth) / 2; + break; + + case WindowsTaskBarLocation.Top: + pointY = ScreenHeight - WorkAreaHeight + _offsetY; + break; + } + + return new Point(pointX, pointY); + } private WindowsTaskBarLocation GetTaskBarLocation() @@ -187,18 +159,5 @@ private WindowsTaskBarLocation GetTaskBarLocation() return WindowsTaskBarLocation.Bottom; } - - public void Dispose() - { - // nothing to do here - } - -#pragma warning disable CS0067 - public event EventHandler UpdatePositionRequested; - - public event EventHandler UpdateEjectDirectionRequested; - - public event EventHandler UpdateHeightRequested; -#pragma warning restore CS0067 } } \ No newline at end of file diff --git a/Src/ToastNotifications/Position/WindowPositionProvider.cs b/Src/ToastNotifications/Position/WindowPositionProvider.cs index eff7eba..1c47249 100644 --- a/Src/ToastNotifications/Position/WindowPositionProvider.cs +++ b/Src/ToastNotifications/Position/WindowPositionProvider.cs @@ -4,53 +4,20 @@ namespace ToastNotifications.Position { - public class WindowPositionProvider : IPositionProvider + public class WindowPositionProvider : PositionProvider { - private readonly Corner _corner; - private readonly double _offsetX; - private readonly double _offsetY; - public Window ParentWindow { get; } - public EjectDirection EjectDirection { get; private set; } - - public WindowPositionProvider(Window parentWindow, Corner corner, double offsetX, double offsetY) + public WindowPositionProvider( + Window parentWindow, + Corner corner, + double offsetX, + double offsetY) : base(parentWindow, corner, offsetX, offsetY) { - _corner = corner; - _offsetX = offsetX; - _offsetY = offsetY; - ParentWindow = parentWindow; - - parentWindow.SizeChanged += ParentWindowOnSizeChanged; - parentWindow.LocationChanged += ParentWindowOnLocationChanged; - parentWindow.StateChanged += ParentWindowOnStateChanged; - parentWindow.Activated += ParentWindowOnActivated; - SetEjectDirection(corner); } - public Point GetPosition(double actualPopupWidth, double actualPopupHeight) - { - var parentPosition = ParentWindow.GetActualPosition(); - - switch(_corner) - { - case Corner.TopRight: - return GetPositionForTopRightCorner(parentPosition, actualPopupWidth, actualPopupHeight); - case Corner.TopLeft: - return GetPositionForTopLeftCorner(parentPosition, actualPopupWidth, actualPopupHeight); - case Corner.BottomRight: - return GetPositionForBottomRightCorner(parentPosition, actualPopupWidth, actualPopupHeight); - case Corner.BottomLeft: - return GetPositionForBottomLeftCorner(parentPosition, actualPopupWidth, actualPopupHeight); - case Corner.BottomCenter: - return GetPositionForBottomCenter(parentPosition, actualPopupWidth, actualPopupHeight); - default: - throw new ArgumentOutOfRangeException(); - } - } - - public double GetHeight() - { + public override double GetHeight() + {//ToDo fix null exception here. var actualHeight = (ParentWindow.Content as FrameworkElement)?.ActualHeight ?? ParentWindow.ActualHeight; return actualHeight; @@ -63,89 +30,35 @@ private double GetWindowWidth() return actualWidth; } - private void SetEjectDirection(Corner corner) - { - switch (corner) - { - case Corner.TopRight: - case Corner.TopLeft: - EjectDirection = EjectDirection.ToBottom; - break; - case Corner.BottomRight: - case Corner.BottomLeft: - case Corner.BottomCenter: - EjectDirection = EjectDirection.ToTop; - break; - default: - throw new ArgumentOutOfRangeException(nameof(corner), corner, null); - } - } - - private Point GetPositionForBottomLeftCorner(Point parentPosition, double actualPopupWidth, double actualPopupHeight) + protected override Point GetPositionForBottomLeftCorner(Point parentPosition, double actualPopupWidth, double actualPopupHeight) { return new Point(parentPosition.X + _offsetX, parentPosition.Y - _offsetY); } - private Point GetPositionForBottomRightCorner(Point parentPosition, double actualPopupWidth, double actualPopupHeight) + protected override Point GetPositionForBottomRightCorner(Point parentPosition, double actualPopupWidth, double actualPopupHeight) { return new Point(parentPosition.X + GetWindowWidth() - _offsetX - actualPopupWidth, parentPosition.Y - _offsetY); } - private Point GetPositionForBottomCenter(Point parentPosition, double actualPopupWidth, double actualPopupHeight) + protected override Point GetPositionForBottomCenterCorner(Point parentPosition, double actualPopupWidth, double actualPopupHeight) { return new Point(parentPosition.X + (GetWindowWidth() - actualPopupWidth) / 2, parentPosition.Y - _offsetY); } - - private Point GetPositionForTopLeftCorner(Point parentPosition, double actualPopupWidth, double actualPopupHeight) + protected override Point GetPositionForTopLeftCorner(Point parentPosition, double actualPopupWidth, double actualPopupHeight) { return new Point(parentPosition.X + _offsetX, parentPosition.Y + _offsetY); } - private Point GetPositionForTopRightCorner(Point parentPosition, double actualPopupWidth, double actualPopupHeight) - { - return new Point( parentPosition.X + GetWindowWidth() - _offsetX - actualPopupWidth, parentPosition.Y + _offsetY); - } - - public void Dispose() + protected override Point GetPositionForTopRightCorner(Point parentPosition, double actualPopupWidth, double actualPopupHeight) { - ParentWindow.LocationChanged -= ParentWindowOnLocationChanged; - ParentWindow.SizeChanged -= ParentWindowOnSizeChanged; - ParentWindow.StateChanged -= ParentWindowOnStateChanged; - ParentWindow.Activated -= ParentWindowOnActivated; + return new Point(parentPosition.X + GetWindowWidth() - _offsetX - actualPopupWidth, parentPosition.Y + _offsetY); } - protected virtual void RequestUpdatePosition() + protected override Point GetPositionForTopCenterCorner(Point parentPosition, double actualPopupWidth, double actualPopupHeight) { - UpdateHeightRequested?.Invoke(this, EventArgs.Empty); - UpdateEjectDirectionRequested?.Invoke(this, EventArgs.Empty); - UpdatePositionRequested?.Invoke(this, EventArgs.Empty); + return new Point(parentPosition.X + (GetWindowWidth() - actualPopupWidth) / 2, parentPosition.Y + _offsetY); } - private void ParentWindowOnLocationChanged(object sender, EventArgs eventArgs) - { - RequestUpdatePosition(); - } - - private void ParentWindowOnSizeChanged(object sender, SizeChangedEventArgs sizeChangedEventArgs) - { - RequestUpdatePosition(); - } - - private void ParentWindowOnStateChanged(object sender, EventArgs eventArgs) - { - RequestUpdatePosition(); - } - - private void ParentWindowOnActivated(object sender, EventArgs eventArgs) - { - RequestUpdatePosition(); - } - - public event EventHandler UpdatePositionRequested; - - public event EventHandler UpdateEjectDirectionRequested; - - public event EventHandler UpdateHeightRequested; } } \ No newline at end of file