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

Refactored Window Positioning #2250

Merged
merged 10 commits into from
Jan 18, 2019
9 changes: 6 additions & 3 deletions samples/ControlCatalog/Pages/DialogsPage.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,13 @@ public DialogsPage()
};
this.FindControl<Button>("Dialog").Click += delegate
{
new MainWindow().ShowDialog(GetWindow());
var window = new Window();
window.Height = 200;
window.Width = 200;
window.Content = new TextBlock { Text = "Hello world!" };
window.WindowStartupLocation = WindowStartupLocation.CenterOwner;
window.ShowDialog(GetWindow());
};


}

Window GetWindow() => (Window)this.VisualRoot;
Expand Down
4 changes: 3 additions & 1 deletion samples/ControlCatalog/Pages/ScreenPage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using Avalonia.Markup.Xaml;
using Avalonia.Media;
using Avalonia.Platform;
using Avalonia.Rendering;

namespace ControlCatalog.Pages
{
Expand All @@ -23,6 +24,7 @@ public override void Render(DrawingContext context)
base.Render(context);
Window w = (Window)VisualRoot;
Screen[] screens = w.Screens.All;
var scaling = ((IRenderRoot)w).RenderScaling;

Pen p = new Pen(Brushes.Black);
if (screens != null)
Expand Down Expand Up @@ -56,7 +58,7 @@ public override void Render(DrawingContext context)
text.Text = $"Primary: {screen.Primary}";
context.DrawText(Brushes.Black, boundsRect.Position.WithY(boundsRect.Size.Height + 40), text);

text.Text = $"Current: {screen.Equals(w.Screens.ScreenFromBounds(new Rect(w.Position, w.Bounds.Size)))}";
text.Text = $"Current: {screen.Equals(w.Screens.ScreenFromBounds(new PixelRect(w.Position, PixelSize.FromSize(w.Bounds.Size, scaling))))}";
context.DrawText(Brushes.Black, boundsRect.Position.WithY(boundsRect.Size.Height + 60), text);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@ namespace Avalonia.Android.Platform.SkiaPlatform
{
class PopupImpl : TopLevelImpl, IPopupImpl
{
private Point _position;
private PixelPoint _position;
private bool _isAdded;
Action IWindowBaseImpl.Activated { get; set; }
public Action<Point> PositionChanged { get; set; }
public Action<PixelPoint> PositionChanged { get; set; }
public Action Deactivated { get; set; }

public PopupImpl() : base(ActivityTracker.Current, true)
Expand All @@ -36,7 +36,7 @@ public void SetMinMaxSize(Size minSize, Size maxSize)

public IScreenImpl Screen { get; }

public Point Position
public PixelPoint Position
{
get { return _position; }
set
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,14 +99,14 @@ public void Invalidate(Rect rect)
if (_view.Holder?.Surface?.IsValid == true) _view.Invalidate();
}

public Point PointToClient(Point point)
public Point PointToClient(PixelPoint point)
{
return point;
return point.ToPoint(1);
}

public Point PointToScreen(Point point)
public PixelPoint PointToScreen(Point point)
{
return point;
return PixelPoint.FromPoint(point, 1);
}

public void SetCursor(IPlatformHandle cursor)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,9 @@ public double Scaling
public Action<double> ScalingChanged { get; set; }
public void SetInputRoot(IInputRoot inputRoot) => InputRoot = inputRoot;

public virtual Point PointToClient(Point point) => point;
public virtual Point PointToClient(PixelPoint point) => point.ToPoint(1);

public virtual Point PointToScreen(Point point) => point;
public virtual PixelPoint PointToScreen(Point point) => PixelPoint.FromPoint(point, 1);

public virtual void SetCursor(IPlatformHandle cursor)
{
Expand Down
27 changes: 27 additions & 0 deletions src/Avalonia.Controls/PixelPointEventArgs.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// Copyright (c) The Avalonia Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.

using System;

namespace Avalonia.Controls
{
/// <summary>
/// Provides <see cref="PixelPoint"/> data for events.
/// </summary>
public class PixelPointEventArgs : EventArgs
{
/// <summary>
/// Initializes a new instance of the <see cref="PixelPointEventArgs"/> class.
/// </summary>
/// <param name="point">The <see cref=PixelPoint"/> data.</param>
public PixelPointEventArgs(PixelPoint point)
{
Point = point;
}

/// <summary>
/// Gets the <see cref="PixelPoint"/> data.
/// </summary>
public PixelPoint Point { get; }
}
}
4 changes: 2 additions & 2 deletions src/Avalonia.Controls/Platform/ITopLevelImpl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -82,14 +82,14 @@ public interface ITopLevelImpl : IDisposable
/// </summary>
/// <param name="point">The point in screen coordinates.</param>
/// <returns>The point in client coordinates.</returns>
Point PointToClient(Point point);
Point PointToClient(PixelPoint point);

/// <summary>
/// Converts a point from client to screen coordinates.
/// </summary>
/// <param name="point">The point in client coordinates.</param>
/// <returns>The point in screen coordinates.</returns>
Point PointToScreen(Point point);
PixelPoint PointToScreen(Point point);

/// <summary>
/// Sets the cursor associated with the toplevel.
Expand Down
6 changes: 3 additions & 3 deletions src/Avalonia.Controls/Platform/IWindowBaseImpl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,14 @@ public interface IWindowBaseImpl : ITopLevelImpl
void BeginResizeDrag(WindowEdge edge);

/// <summary>
/// Gets position of the window relatively to the screen
/// Gets the position of the window in device pixels.
/// </summary>
Point Position { get; set; }
PixelPoint Position { get; set; }

/// <summary>
/// Gets or sets a method called when the window's position changes.
/// </summary>
Action<Point> PositionChanged { get; set; }
Action<PixelPoint> PositionChanged { get; set; }

/// <summary>
/// Activates the window.
Expand Down
8 changes: 4 additions & 4 deletions src/Avalonia.Controls/Platform/Screen.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,17 @@
{
public class Screen
{
public Rect Bounds { get; }
public PixelRect Bounds { get; }

public Rect WorkingArea { get; }
public PixelRect WorkingArea { get; }

public bool Primary { get; }

public Screen(Rect bounds, Rect workingArea, bool primary)
public Screen(PixelRect bounds, PixelRect workingArea, bool primary)
{
this.Bounds = bounds;
this.WorkingArea = workingArea;
this.Primary = primary;
}
}
}
}
27 changes: 0 additions & 27 deletions src/Avalonia.Controls/PointEventArgs.cs

This file was deleted.

30 changes: 13 additions & 17 deletions src/Avalonia.Controls/Primitives/Popup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -380,43 +380,39 @@ private void ChildChanged(AvaloniaPropertyChangedEventArgs e)
/// Gets the position for the popup based on the placement properties.
/// </summary>
/// <returns>The popup's position in screen coordinates.</returns>
protected virtual Point GetPosition()
protected virtual PixelPoint GetPosition()
{
var result = GetPosition(PlacementTarget ?? this.GetVisualParent<Control>(), PlacementMode, PopupRoot,
HorizontalOffset, VerticalOffset);

return result;
}

internal static Point GetPosition(Control target, PlacementMode placement, PopupRoot popupRoot, double horizontalOffset, double verticalOffset)
internal static PixelPoint GetPosition(Control target, PlacementMode placement, PopupRoot popupRoot, double horizontalOffset, double verticalOffset)
{
var zero = default(Point);
var mode = placement;

if (target?.GetVisualRoot() == null)
{
mode = PlacementMode.Pointer;
}
var root = target?.GetVisualRoot();
var mode = root != null ? placement : PlacementMode.Pointer;
var scaling = root?.RenderScaling ?? 1;

switch (mode)
{
case PlacementMode.Pointer:
if (popupRoot != null)
{
// 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 (((IInputRoot)popupRoot)?.MouseDevice?.Position ?? default(Point)) + screenOffset;
var screenOffset = PixelPoint.FromPoint(new Point(horizontalOffset, verticalOffset), scaling);
var mouseOffset = ((IInputRoot)popupRoot)?.MouseDevice?.Position ?? default;
return new PixelPoint(
screenOffset.X + mouseOffset.X,
screenOffset.Y + mouseOffset.Y);
}

return default(Point);
return default;

case PlacementMode.Bottom:
return target?.PointToScreen(new Point(0 + horizontalOffset, target.Bounds.Height + verticalOffset)) ??
zero;
return target?.PointToScreen(new Point(0 + horizontalOffset, target.Bounds.Height + verticalOffset)) ?? default;

case PlacementMode.Right:
return target?.PointToScreen(new Point(target.Bounds.Width + horizontalOffset, 0 + verticalOffset)) ?? zero;
return target?.PointToScreen(new Point(target.Bounds.Width + horizontalOffset, 0 + verticalOffset)) ?? default;

default:
throw new InvalidOperationException("Invalid value for Popup.PlacementMode");
Expand Down
10 changes: 5 additions & 5 deletions src/Avalonia.Controls/Primitives/PopupRoot.cs
Original file line number Diff line number Diff line change
Expand Up @@ -85,18 +85,18 @@ public void SnapInsideScreenEdges()
if (screen != null)
{
var scaling = VisualRoot.RenderScaling;

var screenX = Position.X + (Bounds.Width * scaling) - screen.Bounds.X;
var screenY = Position.Y + (Bounds.Height * scaling) - screen.Bounds.Y;
var bounds = PixelRect.FromRect(Bounds, scaling);
var screenX = Position.X + bounds.Width - screen.Bounds.X;
var screenY = Position.Y + bounds.Height - screen.Bounds.Y;

if (screenX > screen.Bounds.Width)
{
Position = Position.WithX(Position.X - (screenX - screen.Bounds.Width));
Position = Position.WithX(Position.X - screenX - bounds.Width);
}

if (screenY > screen.Bounds.Height)
{
Position = Position.WithY(Position.Y - (screenY - screen.Bounds.Height));
Position = Position.WithY(Position.Y - screenY - bounds.Height);
}
}
}
Expand Down
14 changes: 7 additions & 7 deletions src/Avalonia.Controls/Screens.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public Screens(IScreenImpl iScreenImpl)
_iScreenImpl = iScreenImpl;
}

public Screen ScreenFromBounds(Rect bounds){
public Screen ScreenFromBounds(PixelRect bounds){

Screen currMaxScreen = null;
double maxAreaSize = 0;
Expand All @@ -39,16 +39,16 @@ public Screen ScreenFromBounds(Rect bounds){
return currMaxScreen;
}

public Screen ScreenFromPoint(Point point)
public Screen ScreenFromPoint(PixelPoint point)
{
return All.FirstOrDefault(x=>x.Bounds.Contains(point));
return All.FirstOrDefault(x => x.Bounds.Contains(point));
}

public Screen ScreenFromVisual(IVisual visual)
{
Point tl = visual.PointToScreen(visual.Bounds.TopLeft);
Point br = visual.PointToScreen(visual.Bounds.BottomRight);
return ScreenFromBounds(new Rect(tl,br));
var tl = visual.PointToScreen(visual.Bounds.TopLeft);
var br = visual.PointToScreen(visual.Bounds.BottomRight);
return ScreenFromBounds(new PixelRect(tl, br));
}
}
}
}
1 change: 1 addition & 0 deletions src/Avalonia.Controls/ToolTip.cs
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,7 @@ private void Open(Control control)

_popup = new PopupRoot { Content = this, };
((ISetLogicalParent)_popup).SetParent(control);

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: whitespace

_popup.Position = Popup.GetPosition(control, GetPlacement(control), _popup,
GetHorizontalOffset(control), GetVerticalOffset(control));
_popup.Show();
Expand Down
8 changes: 4 additions & 4 deletions src/Avalonia.Controls/TopLevel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -233,15 +233,15 @@ void IRenderRoot.Invalidate(Rect rect)
}

/// <inheritdoc/>
Point IRenderRoot.PointToClient(Point p)
Point IRenderRoot.PointToClient(PixelPoint p)
{
return PlatformImpl?.PointToClient(p) ?? default(Point);
return PlatformImpl?.PointToClient(p) ?? default;
}

/// <inheritdoc/>
Point IRenderRoot.PointToScreen(Point p)
PixelPoint IRenderRoot.PointToScreen(Point p)
{
return PlatformImpl?.PointToScreen(p) ?? default(Point);
return PlatformImpl?.PointToScreen(p) ?? default;
}

/// <summary>
Expand Down
Loading