Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added Top center corner, refactored position providers to common class #128

Open
wants to merge 2 commits into
base: master-v2
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
102 changes: 18 additions & 84 deletions Src/ToastNotifications/Position/ControlPositionProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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
}
}
}
1 change: 1 addition & 0 deletions Src/ToastNotifications/Position/Corner.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ public enum Corner
{
TopRight,
TopLeft,
TopCenter,
BottomRight,
BottomLeft,
BottomCenter
Expand Down
98 changes: 27 additions & 71 deletions Src/ToastNotifications/Position/GdiPrimaryScreenPositionProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,85 +5,36 @@

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;

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;
Expand All @@ -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;
Expand All @@ -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;
Expand All @@ -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;
Expand All @@ -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;
Expand All @@ -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()
{
Expand All @@ -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
}
}
Loading