Browse Source

Make popup appear in right place.

pull/39/head
Steven Kirk 11 years ago
parent
commit
1b1d60d0c0
  1. 5
      Perspex.Controls.UnitTests/ControlTests.cs
  2. 5
      Perspex.Controls.UnitTests/TestRoot.cs
  3. 2
      Perspex.Controls/Platform/IPopupImpl.cs
  4. 2
      Perspex.Controls/Platform/ITopLevelImpl.cs
  5. 22
      Perspex.Controls/Popup.cs
  6. 5
      Perspex.Controls/PopupRoot.cs
  7. 7
      Perspex.Controls/TopLevel.cs
  8. 5
      Perspex.SceneGraph.UnitTests/TestRoot.cs
  9. 10
      Perspex.SceneGraph/Point.cs
  10. 2
      Perspex.SceneGraph/Rendering/IRenderRoot.cs
  11. 20
      Perspex.SceneGraph/Visual.cs
  12. 1
      Perspex.Themes.Default/DropDownStyle.cs
  13. 12
      Windows/Perspex.Win32/PopupImpl.cs
  14. 7
      Windows/Perspex.Win32/WindowImpl.cs

5
Perspex.Controls.UnitTests/ControlTests.cs

@ -92,6 +92,11 @@ namespace Perspex.Controls.UnitTests
{
get { throw new NotImplementedException(); }
}
public Point TranslatePointToScreen(Point p)
{
throw new NotImplementedException();
}
}
}
}

5
Perspex.Controls.UnitTests/TestRoot.cs

@ -33,5 +33,10 @@ namespace Perspex.Controls.UnitTests
{
get { throw new NotImplementedException(); }
}
public Point TranslatePointToScreen(Point p)
{
throw new NotImplementedException();
}
}
}

2
Perspex.Controls/Platform/IPopupImpl.cs

@ -12,6 +12,8 @@ namespace Perspex.Platform
public interface IPopupImpl : ITopLevelImpl
{
void SetPosition(Point p);
void Show();
void Hide();

2
Perspex.Controls/Platform/ITopLevelImpl.cs

@ -30,5 +30,7 @@ namespace Perspex.Platform
void Invalidate(Rect rect);
void SetOwner(TopLevel owner);
Point PointToScreen(Point point);
}
}

22
Perspex.Controls/Popup.cs

@ -18,6 +18,9 @@ namespace Perspex.Controls
public static readonly PerspexProperty<bool> IsOpenProperty =
PerspexProperty.Register<Popup, bool>("IsOpen");
public static readonly PerspexProperty<Control> PlacementTargetProperty =
PerspexProperty.Register<Popup, Control>("PlacementTarget");
private PopupRoot root;
private Window window;
@ -54,6 +57,12 @@ namespace Perspex.Controls
set { this.SetValue(IsOpenProperty, value); }
}
public Control PlacementTarget
{
get { return this.GetValue(PlacementTargetProperty); }
set { this.SetValue(PlacementTargetProperty, value); }
}
public void Open()
{
if (this.root == null)
@ -62,6 +71,7 @@ namespace Perspex.Controls
this.root[~PopupRoot.ContentProperty] = this[~ChildProperty];
}
this.root.SetPosition(this.GetPosition());
this.root.Show();
}
@ -84,5 +94,17 @@ namespace Perspex.Controls
base.OnDetachedFromVisualTree(oldRoot);
this.window = null;
}
private Point GetPosition()
{
if (this.PlacementTarget != null)
{
return this.PlacementTarget.PointToScreen(new Point(0, this.PlacementTarget.ActualSize.Height));
}
else
{
return new Point();
}
}
}
}

5
Perspex.Controls/PopupRoot.cs

@ -27,6 +27,11 @@ namespace Perspex.Controls
get { return (IPopupImpl)base.PlatformImpl; }
}
public void SetPosition(Point p)
{
this.PlatformImpl.SetPosition(p);
}
public void Hide()
{
this.PlatformImpl.Hide();

7
Perspex.Controls/TopLevel.cs

@ -131,7 +131,12 @@ namespace Perspex.Controls
{
get { return this.renderManager; }
}
Point IRenderRoot.TranslatePointToScreen(Point p)
{
return this.PlatformImpl.PointToScreen(p);
}
protected IDisposable BeginAutoSizing()
{
this.autoSizing = true;

5
Perspex.SceneGraph.UnitTests/TestRoot.cs

@ -20,5 +20,10 @@ namespace Perspex.SceneGraph.UnitTests
{
get { throw new NotImplementedException(); }
}
public Point TranslatePointToScreen(Point p)
{
throw new NotImplementedException();
}
}
}

10
Perspex.SceneGraph/Point.cs

@ -77,11 +77,21 @@ namespace Perspex
return new Point(a.x + b.x, a.y + b.y);
}
public static Point operator +(Point a, Vector b)
{
return new Point(a.x + b.X, a.y + b.Y);
}
public static Point operator -(Point a, Point b)
{
return new Point(a.x - b.x, a.y - b.y);
}
public static Point operator -(Point a, Vector b)
{
return new Point(a.x - b.X, a.y - b.Y);
}
public static Point operator *(Point point, Matrix matrix)
{
return new Point(

2
Perspex.SceneGraph/Rendering/IRenderRoot.cs

@ -13,5 +13,7 @@ namespace Perspex.Rendering
IRenderer Renderer { get; }
IRenderManager RenderManager { get; }
Point TranslatePointToScreen(Point p);
}
}

20
Perspex.SceneGraph/Visual.cs

@ -14,6 +14,7 @@ namespace Perspex
using Perspex.Animation;
using Perspex.Collections;
using Perspex.Media;
using Perspex.Platform;
using Perspex.Rendering;
using Perspex.VisualTree;
using Splat;
@ -118,10 +119,16 @@ namespace Perspex
Contract.Requires<ArgumentNullException>(context != null);
}
public Point PointToScreen(Point point)
{
var p = GetOffsetFromRoot(this);
return p.Item1.TranslatePointToScreen(point + p.Item2);
}
public Matrix TransformToVisual(IVisual visual)
{
var thisOffset = GetOffsetFromRoot(this);
var thatOffset = GetOffsetFromRoot(visual);
var thisOffset = GetOffsetFromRoot(this).Item2;
var thatOffset = GetOffsetFromRoot(visual).Item2;
return Matrix.Translation(-thisOffset) * Matrix.Translation(thatOffset);
}
@ -198,7 +205,7 @@ namespace Perspex
}
}
private static Vector GetOffsetFromRoot(IVisual v)
private static Tuple<IRenderRoot, Vector> GetOffsetFromRoot(IVisual v)
{
var result = new Vector();
@ -206,9 +213,14 @@ namespace Perspex
{
result = new Vector(result.X + v.Bounds.X, result.Y + v.Bounds.Y);
v = v.VisualParent;
if (v == null)
{
throw new InvalidOperationException("Control is not attached to visual tree.");
}
}
return result;
return Tuple.Create((IRenderRoot)v, result);
}
private static void RenderTransformChanged(PerspexPropertyChangedEventArgs e)

1
Perspex.Themes.Default/DropDownStyle.cs

@ -82,6 +82,7 @@ namespace Perspex.Themes.Default
new Popup
{
Child = new TextBlock { Text = "Hello World" },
PlacementTarget = control,
[~Popup.IsOpenProperty] = control[~DropDown.IsDropDownOpenProperty],
}
},

12
Windows/Perspex.Win32/PopupImpl.cs

@ -12,6 +12,18 @@ namespace Perspex.Win32
public class PopupImpl : WindowImpl, IPopupImpl
{
public void SetPosition(Point p)
{
UnmanagedMethods.SetWindowPos(
this.Handle.Handle,
IntPtr.Zero,
(int)p.X,
(int)p.Y,
0,
0,
UnmanagedMethods.SetWindowPosFlags.SWP_NOSIZE);
}
protected override IntPtr CreateWindowOverride(ushort atom)
{
UnmanagedMethods.WindowStyles style =

7
Windows/Perspex.Win32/WindowImpl.cs

@ -111,6 +111,13 @@ namespace Perspex.Win32
UnmanagedMethods.InvalidateRect(this.hwnd, ref r, false);
}
public Point PointToScreen(Point point)
{
var p = new UnmanagedMethods.POINT { X = (int)point.X, Y = (int)point.Y };
UnmanagedMethods.ClientToScreen(this.hwnd, ref p);
return new Point(p.X, p.Y);
}
public void SetOwner(TopLevel owner)
{
this.owner = owner;

Loading…
Cancel
Save