PlatformManager.cs 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Reactive.Disposables;
  5. using System.Text;
  6. using System.Threading.Tasks;
  7. using Perspex.Input;
  8. using Perspex.Input.Raw;
  9. using Perspex.Media;
  10. using Perspex.Media.Imaging;
  11. using Perspex.Platform;
  12. namespace Perspex.Controls.Platform
  13. {
  14. public static partial class PlatformManager
  15. {
  16. static IPlatformSettings GetSettings()
  17. => PerspexLocator.Current.GetService<IPlatformSettings>();
  18. static bool s_designerMode;
  19. private static double _designerScalingFactor = 1;
  20. public static IRenderTarget CreateRenderTarget(ITopLevelImpl window)
  21. {
  22. return
  23. new RenderTargetDecorator(
  24. PerspexLocator.Current.GetService<IPlatformRenderInterface>().CreateRenderer(window.Handle), window);
  25. }
  26. public static IDisposable DesignerMode()
  27. {
  28. s_designerMode = true;
  29. return Disposable.Create(() => s_designerMode = false);
  30. }
  31. public static void SetDesignerScalingFactor(double factor)
  32. {
  33. _designerScalingFactor = factor;
  34. }
  35. static double RenderScalingFactor => (GetSettings()?.RenderScalingFactor ?? 1)*_designerScalingFactor;
  36. static double LayoutScalingFactor => (GetSettings()?.LayoutScalingFactor ?? 1) * _designerScalingFactor;
  37. class RenderTargetDecorator : IRenderTarget
  38. {
  39. private readonly IRenderTarget _target;
  40. private readonly ITopLevelImpl _window;
  41. public RenderTargetDecorator(IRenderTarget target, ITopLevelImpl window)
  42. {
  43. _target = target;
  44. var dec = window as WindowDecorator;
  45. if (dec != null)
  46. window = dec.TopLevel;
  47. _window = window;
  48. }
  49. public void Dispose() => _target.Dispose();
  50. public DrawingContext CreateDrawingContext()
  51. {
  52. var cs = _window.ClientSize;
  53. var ctx = _target.CreateDrawingContext();
  54. var factor = RenderScalingFactor;
  55. if (factor != 1)
  56. {
  57. ctx.PushPostTransform(Matrix.CreateScale(factor, factor));
  58. ctx.PushTransformContainer();
  59. }
  60. return ctx;
  61. }
  62. }
  63. class WindowDecorator : IPopupImpl, IWindowImpl
  64. {
  65. private readonly ITopLevelImpl _tl;
  66. private readonly IWindowImpl _window;
  67. private readonly IPopupImpl _popup;
  68. public ITopLevelImpl TopLevel => _tl;
  69. double ScalingFactor => LayoutScalingFactor;
  70. public WindowDecorator(ITopLevelImpl tl)
  71. {
  72. _tl = tl;
  73. _window = tl as IWindowImpl;
  74. _popup = tl as IPopupImpl;
  75. _tl.Input = OnInput;
  76. _tl.Paint = OnPaint;
  77. _tl.Resized = OnResized;
  78. }
  79. private void OnResized(Size size)
  80. {
  81. Resized?.Invoke(size/ScalingFactor);
  82. }
  83. private void OnPaint(Rect rc)
  84. {
  85. var f = ScalingFactor;
  86. Paint?.Invoke(new Rect(rc.X/f, rc.Y/f, rc.Width/f, rc.Height/f));
  87. }
  88. private void OnInput(RawInputEventArgs obj)
  89. {
  90. var mouseEvent = obj as RawMouseEventArgs;
  91. if (mouseEvent != null)
  92. mouseEvent.Position /= ScalingFactor;
  93. //TODO: Transform event coordinates
  94. Input?.Invoke(obj);
  95. }
  96. public Point PointToClient(Point point)
  97. {
  98. return _tl.PointToClient(point / ScalingFactor) * ScalingFactor;
  99. }
  100. public Point PointToScreen(Point point)
  101. {
  102. return _tl.PointToScreen(point * ScalingFactor) / ScalingFactor;
  103. }
  104. public void Invalidate(Rect rc)
  105. {
  106. var f = ScalingFactor;
  107. _tl.Invalidate(new Rect(rc.X*f, rc.Y*f, (rc.Width + 1)*f, (rc.Height + 1)*f));
  108. }
  109. public Size ClientSize
  110. {
  111. get { return _tl.ClientSize/ScalingFactor; }
  112. set { _tl.ClientSize = value*ScalingFactor; }
  113. }
  114. public Size MaxClientSize => _window.MaxClientSize/ScalingFactor;
  115. public Action<RawInputEventArgs> Input { get; set; }
  116. public Action<Rect> Paint { get; set; }
  117. public Action<Size> Resized { get; set; }
  118. public Action Activated
  119. {
  120. get { return _tl.Activated; }
  121. set { _tl.Activated = value; }
  122. }
  123. public Action Closed
  124. {
  125. get { return _tl.Closed; }
  126. set { _tl.Closed = value; }
  127. }
  128. public Action Deactivated
  129. {
  130. get { return _tl.Deactivated; }
  131. set { _tl.Deactivated = value; }
  132. }
  133. public WindowState WindowState
  134. {
  135. get { return _window.WindowState; }
  136. set { _window.WindowState = value; }
  137. }
  138. public void Dispose() => _tl.Dispose();
  139. public IPlatformHandle Handle => _tl.Handle;
  140. public void Activate() => _tl.Activate();
  141. public void SetInputRoot(IInputRoot inputRoot) => _tl.SetInputRoot(inputRoot);
  142. public void SetCursor(IPlatformHandle cursor) => _tl.SetCursor(cursor);
  143. public void SetTitle(string title) => _window.SetTitle(title);
  144. public void Show() => _tl.Show();
  145. public void BeginMoveDrag() => _tl.BeginMoveDrag();
  146. public void BeginResizeDrag(WindowEdge edge) => _tl.BeginResizeDrag(edge);
  147. public Point Position
  148. {
  149. get { return _tl.Position; }
  150. set { _tl.Position = value; }
  151. }
  152. public IDisposable ShowDialog() => _window.ShowDialog();
  153. public void Hide() => _popup.Hide();
  154. public void SetSystemDecorations(bool enabled) => _window.SetSystemDecorations(enabled);
  155. }
  156. public static IWindowImpl CreateWindow()
  157. {
  158. var platform = PerspexLocator.Current.GetService<IWindowingPlatform>();
  159. return
  160. new WindowDecorator(s_designerMode ? platform.CreateEmbeddableWindow() : platform.CreateWindow());
  161. }
  162. public static IPopupImpl CreatePopup()
  163. {
  164. return new WindowDecorator(PerspexLocator.Current.GetService<IWindowingPlatform>().CreatePopup());
  165. }
  166. }
  167. }