Skip to content

Commit

Permalink
Merge pull request #2250 from AvaloniaUI/refactor/window-position
Browse files Browse the repository at this point in the history
Refactored Window Positioning
  • Loading branch information
grokys authored Jan 18, 2019
2 parents 50a3877 + b5fac96 commit 9bd182d
Show file tree
Hide file tree
Showing 53 changed files with 941 additions and 265 deletions.
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));
}
}
}
}
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

0 comments on commit 9bd182d

Please sign in to comment.