diff --git a/Directory.Build.props b/Directory.Build.props index a6d26161..6f2ded36 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -2,8 +2,8 @@ latest true - 11.0.0-preview6 - 1.0.52 + 11.0.0-preview8 + 1.0.55 beta diff --git a/src/AvaloniaEdit.TextMate/TextEditorModel.cs b/src/AvaloniaEdit.TextMate/TextEditorModel.cs index 1583ae3d..641919e1 100644 --- a/src/AvaloniaEdit.TextMate/TextEditorModel.cs +++ b/src/AvaloniaEdit.TextMate/TextEditorModel.cs @@ -187,7 +187,7 @@ private void TokenizeViewPort() ForceTokenization( _textView.VisualLines[0].FirstDocumentLine.LineNumber - 1, _textView.VisualLines[_textView.VisualLines.Count - 1].LastDocumentLine.LineNumber - 1); - }, DispatcherPriority.MinValue); + }, DispatcherPriority.Default); } internal class InvalidLineRange diff --git a/src/AvaloniaEdit/Editing/EditingCommandHandler.cs b/src/AvaloniaEdit/Editing/EditingCommandHandler.cs index e77c611b..277ba070 100644 --- a/src/AvaloniaEdit/Editing/EditingCommandHandler.cs +++ b/src/AvaloniaEdit/Editing/EditingCommandHandler.cs @@ -24,6 +24,7 @@ using AvaloniaEdit.Document; using Avalonia.Input; using AvaloniaEdit.Utils; +using Avalonia.Controls; namespace AvaloniaEdit.Editing { @@ -415,17 +416,17 @@ private static bool CopySelectedText(TextArea textArea) var text = textArea.Selection.GetText(); text = TextUtilities.NormalizeNewLines(text, Environment.NewLine); - SetClipboardText(text); + SetClipboardText(text, textArea); textArea.OnTextCopied(new TextEventArgs(text)); return true; } - private static void SetClipboardText(string text) + private static void SetClipboardText(string text, Visual visual) { try { - Application.Current.Clipboard.SetTextAsync(text).GetAwaiter().GetResult(); + TopLevel.GetTopLevel(visual)?.Clipboard?.SetTextAsync(text).GetAwaiter().GetResult(); } catch (Exception) { @@ -470,7 +471,7 @@ private static bool CopyWholeLine(TextArea textArea, DocumentLine line) //if (copyingEventArgs.CommandCancelled) // return false; - SetClipboardText(text); + SetClipboardText(text, textArea); textArea.OnTextCopied(new TextEventArgs(text)); return true; @@ -496,7 +497,7 @@ private static async void OnPaste(object target, ExecutedRoutedEventArgs args) string text = null; try { - text = await Application.Current.Clipboard.GetTextAsync(); + text = await TopLevel.GetTopLevel(textArea)?.Clipboard?.GetTextAsync(); } catch (Exception) { diff --git a/src/AvaloniaEdit/Editing/TextArea.xaml b/src/AvaloniaEdit/Editing/TextArea.xaml index 62e747c0..43488055 100644 --- a/src/AvaloniaEdit/Editing/TextArea.xaml +++ b/src/AvaloniaEdit/Editing/TextArea.xaml @@ -15,7 +15,7 @@ + ItemsSource="{TemplateBinding LeftMargins}"> diff --git a/test/AvaloniaEdit.Tests/AvaloniaEdit.Tests.csproj b/test/AvaloniaEdit.Tests/AvaloniaEdit.Tests.csproj index 1d5d78ca..b7b4234e 100644 --- a/test/AvaloniaEdit.Tests/AvaloniaEdit.Tests.csproj +++ b/test/AvaloniaEdit.Tests/AvaloniaEdit.Tests.csproj @@ -5,13 +5,14 @@ - - - - - - - + + + + + + + + diff --git a/test/AvaloniaEdit.Tests/AvaloniaMocks/MockFontManagerImpl.cs b/test/AvaloniaEdit.Tests/AvaloniaMocks/MockFontManagerImpl.cs deleted file mode 100644 index deae986e..00000000 --- a/test/AvaloniaEdit.Tests/AvaloniaMocks/MockFontManagerImpl.cs +++ /dev/null @@ -1,54 +0,0 @@ -using Avalonia.Media; -using Avalonia.Platform; - -using Moq; - -using System.Collections.Generic; -using System.Globalization; -using System.IO; - -#nullable enable - -namespace AvaloniaEdit.AvaloniaMocks -{ - public class MockFontManagerImpl : IFontManagerImpl - { - private readonly string _defaultFamilyName; - - public MockFontManagerImpl(string defaultFamilyName = "Default") - { - _defaultFamilyName = defaultFamilyName; - } - - public string GetDefaultFontFamilyName() - { - return _defaultFamilyName; - } - - public string[] GetInstalledFontFamilyNames(bool checkForUpdates = false) - { - return new[] { _defaultFamilyName }; - } - - public bool TryMatchCharacter(int codepoint, FontStyle fontStyle, FontWeight fontWeight, FontStretch fontStretch, - FontFamily? fontFamily, CultureInfo? culture, out Typeface typeface) - { - typeface = new Typeface(_defaultFamilyName); - - return true; - } - - public bool TryCreateGlyphTypeface(string familyName, FontStyle style, FontWeight weight, - FontStretch stretch, out IGlyphTypeface glyphTypeface) - { - glyphTypeface = new MockGlyphTypeface(); - return true; - } - - public bool TryCreateGlyphTypeface(Stream stream, out IGlyphTypeface glyphTypeface) - { - glyphTypeface = new MockGlyphTypeface(); - return true; - } - } -} diff --git a/test/AvaloniaEdit.Tests/AvaloniaMocks/MockGlyphRun.cs b/test/AvaloniaEdit.Tests/AvaloniaMocks/MockGlyphRun.cs deleted file mode 100644 index 377c6e31..00000000 --- a/test/AvaloniaEdit.Tests/AvaloniaMocks/MockGlyphRun.cs +++ /dev/null @@ -1,36 +0,0 @@ -using Avalonia; -using Avalonia.Media.TextFormatting; -using Avalonia.Platform; -using System.Collections.Generic; - -namespace AvaloniaEdit.AvaloniaMocks -{ - internal class MockGlyphRun : IGlyphRunImpl - { - public MockGlyphRun(IReadOnlyList glyphInfos) - { - var width = 0.0; - - for (var i = 0; i < glyphInfos.Count; ++i) - { - width += glyphInfos[i].GlyphAdvance; - } - - Bounds = new Rect(new Size(width, 10)); - } - - public Rect Bounds { get; } - - public Point BaselineOrigin => new Point(0, 8); - - public void Dispose() - { - - } - - public IReadOnlyList GetIntersections(float lowerBound, float upperBound) - { - return null; - } - } -} diff --git a/test/AvaloniaEdit.Tests/AvaloniaMocks/MockGlyphTypeface.cs b/test/AvaloniaEdit.Tests/AvaloniaMocks/MockGlyphTypeface.cs deleted file mode 100644 index 279aed08..00000000 --- a/test/AvaloniaEdit.Tests/AvaloniaMocks/MockGlyphTypeface.cs +++ /dev/null @@ -1,81 +0,0 @@ -using Avalonia.Media; - -using System; - -namespace AvaloniaEdit.AvaloniaMocks -{ - public class MockGlyphTypeface : IGlyphTypeface - { - public FontMetrics Metrics => new FontMetrics - { - DesignEmHeight = 10, - Ascent = 2, - Descent = 10, - IsFixedPitch = true - }; - - public FontStretch Stretch { get; } - public int GlyphCount => 1337; - - public FontSimulations FontSimulations => throw new NotImplementedException(); - - public ushort GetGlyph(uint codepoint) - { - return (ushort)codepoint; - } - - public ushort[] GetGlyphs(ReadOnlySpan codepoints) - { - return new ushort[codepoints.Length]; - } - - public int GetGlyphAdvance(ushort glyph) - { - return 8; - } - - public bool TryGetGlyph(uint codepoint, out ushort glyph) - { - glyph = 8; - - return true; - } - - public static int GlyphAdvance => 8; - - public int[] GetGlyphAdvances(ReadOnlySpan glyphs) - { - var advances = new int[glyphs.Length]; - - for (var i = 0; i < advances.Length; i++) - { - advances[i] = GlyphAdvance; - } - - return advances; - } - - public void Dispose() { } - - public bool TryGetTable(uint tag, out byte[] table) - { - table = null; - return false; - } - - public string FamilyName => ""; - public FontWeight Weight => FontWeight.Normal; - public FontStyle Style => FontStyle.Normal; - - public bool TryGetGlyphMetrics(ushort glyph, out GlyphMetrics metrics) - { - metrics = new GlyphMetrics - { - Width = 10, - Height = 10 - }; - - return true; - } - } -} diff --git a/test/AvaloniaEdit.Tests/AvaloniaMocks/MockPlatformHotkeyConfiguration.cs b/test/AvaloniaEdit.Tests/AvaloniaMocks/MockPlatformHotkeyConfiguration.cs deleted file mode 100644 index 31f78549..00000000 --- a/test/AvaloniaEdit.Tests/AvaloniaMocks/MockPlatformHotkeyConfiguration.cs +++ /dev/null @@ -1,13 +0,0 @@ -using Avalonia.Input.Platform; - -namespace AvaloniaEdit.AvaloniaMocks -{ - public class MockPlatformHotkeyConfiguration : PlatformHotkeyConfiguration - { - public MockPlatformHotkeyConfiguration() : base(Avalonia.Input.KeyModifiers.Control) - { - - } - - } -} diff --git a/test/AvaloniaEdit.Tests/AvaloniaMocks/MockPlatformRenderInterface.cs b/test/AvaloniaEdit.Tests/AvaloniaMocks/MockPlatformRenderInterface.cs deleted file mode 100644 index 1da9463d..00000000 --- a/test/AvaloniaEdit.Tests/AvaloniaMocks/MockPlatformRenderInterface.cs +++ /dev/null @@ -1,162 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using Avalonia; -using Avalonia.Media; -using Avalonia.Media.Imaging; -using Avalonia.Media.TextFormatting; -using Avalonia.Platform; -using Moq; - -namespace AvaloniaEdit.AvaloniaMocks -{ - public class MockPlatformRenderInterface : IPlatformRenderInterface - { - public IEnumerable InstalledFontNames => throw new NotImplementedException(); - - public bool SupportsIndividualRoundRects => throw new NotImplementedException(); - - public AlphaFormat DefaultAlphaFormat => throw new NotImplementedException(); - - public PixelFormat DefaultPixelFormat => throw new NotImplementedException(); - - public IGeometryImpl CreateEllipseGeometry(Rect rect) - { - throw new NotImplementedException(); - } - - public IGeometryImpl CreateLineGeometry(Point p1, Point p2) - { - throw new NotImplementedException(); - } - - public IGeometryImpl CreateRectangleGeometry(Rect rect) - { - throw new NotImplementedException(); - } - - public IRenderTarget CreateRenderTarget(IEnumerable surfaces) - { - return Mock.Of(); - } - - public IRenderTargetBitmapImpl CreateRenderTargetBitmap( - int width, - int height, - double dpiX, - double dpiY) - { - return Mock.Of(); - } - - public IRenderTargetBitmapImpl CreateRenderTargetBitmap(PixelSize size, Vector dpi) - { - throw new NotImplementedException(); - } - - public IStreamGeometryImpl CreateStreamGeometry() - { - return new MockStreamGeometryImpl(); - } - - public IWriteableBitmapImpl CreateWriteableBitmap(PixelSize size, Vector dpi, PixelFormat? format = null) - { - throw new NotImplementedException(); - } - - public IBitmapImpl LoadBitmap(Stream stream) - { - return Mock.Of(); - } - - public IBitmapImpl LoadBitmap(string fileName) - { - return Mock.Of(); - } - - public IBitmapImpl LoadBitmap(PixelFormat format, IntPtr data, PixelSize size, Vector dpi, int stride) - { - throw new NotImplementedException(); - } - - public IGeometryImpl CreateGeometryGroup(FillRule fillRule, IReadOnlyList children) - { - throw new NotImplementedException(); - } - - public IGeometryImpl CreateCombinedGeometry(GeometryCombineMode combineMode, Geometry g1, Geometry g2) - { - throw new NotImplementedException(); - } - - public IWriteableBitmapImpl CreateWriteableBitmap(PixelSize size, Vector dpi, PixelFormat format, AlphaFormat alphaFormat) - { - throw new NotImplementedException(); - } - - public IWriteableBitmapImpl LoadWriteableBitmapToWidth(Stream stream, int width, BitmapInterpolationMode interpolationMode = BitmapInterpolationMode.HighQuality) - { - throw new NotImplementedException(); - } - - public IWriteableBitmapImpl LoadWriteableBitmapToHeight(Stream stream, int height, BitmapInterpolationMode interpolationMode = BitmapInterpolationMode.HighQuality) - { - throw new NotImplementedException(); - } - - public IWriteableBitmapImpl LoadWriteableBitmap(string fileName) - { - throw new NotImplementedException(); - } - - public IWriteableBitmapImpl LoadWriteableBitmap(Stream stream) - { - throw new NotImplementedException(); - } - - public IBitmapImpl LoadBitmapToWidth(Stream stream, int width, BitmapInterpolationMode interpolationMode = BitmapInterpolationMode.HighQuality) - { - throw new NotImplementedException(); - } - - public IBitmapImpl LoadBitmapToHeight(Stream stream, int height, BitmapInterpolationMode interpolationMode = BitmapInterpolationMode.HighQuality) - { - throw new NotImplementedException(); - } - - public IBitmapImpl ResizeBitmap(IBitmapImpl bitmapImpl, PixelSize destinationSize, BitmapInterpolationMode interpolationMode = BitmapInterpolationMode.HighQuality) - { - throw new NotImplementedException(); - } - - public IBitmapImpl LoadBitmap(PixelFormat format, AlphaFormat alphaFormat, IntPtr data, PixelSize size, Vector dpi, int stride) - { - throw new NotImplementedException(); - } - - public IGlyphRunImpl CreateGlyphRun(GlyphRun glyphRun) - { - throw new NotImplementedException(); - } - - public IGeometryImpl BuildGlyphRunGeometry(GlyphRun glyphRun) - { - throw new NotImplementedException(); - } - - public IGlyphRunImpl CreateGlyphRun(IGlyphTypeface glyphTypeface, double fontRenderingEmSize, IReadOnlyList glyphInfos, Point baselineOrigin) - { - return new MockGlyphRun(glyphInfos); - } - - public IPlatformRenderInterfaceContext CreateBackendContext(IPlatformGraphicsContext graphicsApiContext) - { - throw new NotImplementedException(); - } - - public bool IsSupportedBitmapPixelFormat(PixelFormat format) - { - throw new NotImplementedException(); - } - } -} \ No newline at end of file diff --git a/test/AvaloniaEdit.Tests/AvaloniaMocks/MockRuntimePlatform.cs b/test/AvaloniaEdit.Tests/AvaloniaMocks/MockRuntimePlatform.cs deleted file mode 100644 index d275b1ca..00000000 --- a/test/AvaloniaEdit.Tests/AvaloniaMocks/MockRuntimePlatform.cs +++ /dev/null @@ -1,28 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -using Avalonia.Platform; - -namespace AvaloniaEdit.AvaloniaMocks -{ - public class MockRuntimePlatform : IRuntimePlatform - { - IUnmanagedBlob IRuntimePlatform.AllocBlob(int size) - { - throw new NotImplementedException(); - } - - RuntimePlatformInfo IRuntimePlatform.GetRuntimeInfo() - { - return new RuntimePlatformInfo(); - } - - IDisposable IRuntimePlatform.StartSystemTimer(TimeSpan interval, Action tick) - { - throw new NotImplementedException(); - } - } -} diff --git a/test/AvaloniaEdit.Tests/AvaloniaMocks/MockStreamGeometryImpl.cs b/test/AvaloniaEdit.Tests/AvaloniaMocks/MockStreamGeometryImpl.cs deleted file mode 100644 index b6c3a50e..00000000 --- a/test/AvaloniaEdit.Tests/AvaloniaMocks/MockStreamGeometryImpl.cs +++ /dev/null @@ -1,176 +0,0 @@ -using System; -using System.Collections.Generic; -using Avalonia; -using Avalonia.Media; -using Avalonia.Platform; - -namespace AvaloniaEdit.AvaloniaMocks -{ - public class MockStreamGeometryImpl : IStreamGeometryImpl, ITransformedGeometryImpl - { - private MockStreamGeometryContext _context; - - public MockStreamGeometryImpl() - { - Transform = Matrix.Identity; - _context = new MockStreamGeometryContext(); - } - - public MockStreamGeometryImpl(Matrix transform) - { - Transform = transform; - _context = new MockStreamGeometryContext(); - } - - private MockStreamGeometryImpl(Matrix transform, MockStreamGeometryContext context) - { - Transform = transform; - _context = context; - } - - public IGeometryImpl SourceGeometry { get; } - - public Rect Bounds => _context.CalculateBounds(); - - public Matrix Transform { get; } - - public double ContourLength => throw new NotImplementedException(); - - public IStreamGeometryImpl Clone() - { - return this; - } - - public void Dispose() - { - } - - public bool FillContains(Point point) - { - return _context.FillContains(point); - } - - public bool StrokeContains(IPen pen, Point point) - { - return false; - } - - public Rect GetRenderBounds(IPen pen) => Bounds; - - public IGeometryImpl Intersect(IGeometryImpl geometry) - { - return new MockStreamGeometryImpl(Transform); - } - - public IStreamGeometryContextImpl Open() - { - return _context; - } - - public ITransformedGeometryImpl WithTransform(Matrix transform) - { - return new MockStreamGeometryImpl(transform, _context); - } - - public bool TryGetPointAtDistance(double distance, out Point point) - { - throw new NotImplementedException(); - } - - public bool TryGetPointAndTangentAtDistance(double distance, out Point point, out Point tangent) - { - throw new NotImplementedException(); - } - - public bool TryGetSegment(double startDistance, double stopDistance, bool startOnBeginFigure, out IGeometryImpl segmentGeometry) - { - throw new NotImplementedException(); - } - - class MockStreamGeometryContext : IStreamGeometryContextImpl - { - private List points = new List(); - public void ArcTo(Point point, Size size, double rotationAngle, bool isLargeArc, SweepDirection sweepDirection) - { - } - - public void BeginFigure(Point startPoint, bool isFilled) - { - points.Add(startPoint); - } - - public Rect CalculateBounds() - { - var left = double.MaxValue; - var right = double.MinValue; - var top = double.MaxValue; - var bottom = double.MinValue; - - foreach (var p in points) - { - left = Math.Min(p.X, left); - right = Math.Max(p.X, right); - top = Math.Min(p.Y, top); - bottom = Math.Max(p.Y, bottom); - } - - return new Rect(new Point(left, top), new Point(right, bottom)); - } - - public void CubicBezierTo(Point point1, Point point2, Point point3) - { - } - - public void Dispose() - { - } - - public void EndFigure(bool isClosed) - { - } - - public void LineTo(Point point) - { - points.Add(point); - } - - public void QuadraticBezierTo(Point control, Point endPoint) - { - throw new NotImplementedException(); - } - - public void SetFillRule(FillRule fillRule) - { - } - - public bool FillContains(Point point) - { - // Use the algorithm from https://www.blackpawn.com/texts/pointinpoly/default.html - // to determine if the point is in the geometry (since it will always be convex in this situation) - for (int i = 0; i < points.Count; i++) - { - var a = points[i]; - var b = points[(i + 1) % points.Count]; - var c = points[(i + 2) % points.Count]; - - Vector v0 = c - a; - Vector v1 = b - a; - Vector v2 = point - a; - - var dot00 = v0 * v0; - var dot01 = v0 * v1; - var dot02 = v0 * v2; - var dot11 = v1 * v1; - var dot12 = v1 * v2; - - - var invDenom = 1 / (dot00 * dot11 - dot01 * dot01); - var u = (dot11 * dot02 - dot01 * dot12) * invDenom; - var v = (dot00 * dot12 - dot01 * dot02) * invDenom; - if ((u >= 0) && (v >= 0) && (u + v < 1)) return true; - } - return false; - } - } - } -} \ No newline at end of file diff --git a/test/AvaloniaEdit.Tests/AvaloniaMocks/MockTextShaperImpl.cs b/test/AvaloniaEdit.Tests/AvaloniaMocks/MockTextShaperImpl.cs deleted file mode 100644 index 4c573559..00000000 --- a/test/AvaloniaEdit.Tests/AvaloniaMocks/MockTextShaperImpl.cs +++ /dev/null @@ -1,37 +0,0 @@ -using System; -using System.Globalization; -using Avalonia.Media; -using Avalonia.Media.TextFormatting; -using Avalonia.Media.TextFormatting.Unicode; -using Avalonia.Platform; -using Avalonia.Utilities; - -namespace AvaloniaEdit.AvaloniaMocks; - -#nullable enable - -public class MockTextShaperImpl : ITextShaperImpl -{ - public ShapedBuffer ShapeText(ReadOnlyMemory text, TextShaperOptions options) - { - var typeface = options.Typeface; - var fontRenderingEmSize = options.FontRenderingEmSize; - var bidiLevel = options.BidiLevel; - - var shapedBuffer = new ShapedBuffer(text, text.Length, typeface, fontRenderingEmSize, bidiLevel); - - for (var i = 0; i < shapedBuffer.Length;) - { - var glyphCluster = i; - var codepoint = Codepoint.ReadAt(text.Span, i, out var count); - - var glyphIndex = typeface.GetGlyph(codepoint); - - shapedBuffer[i] = new GlyphInfo(glyphIndex, glyphCluster, 10); - - i += count; - } - - return shapedBuffer; - } -} \ No newline at end of file diff --git a/test/AvaloniaEdit.Tests/AvaloniaMocks/MockWindowingPlatform.cs b/test/AvaloniaEdit.Tests/AvaloniaMocks/MockWindowingPlatform.cs deleted file mode 100644 index 1f3e77cf..00000000 --- a/test/AvaloniaEdit.Tests/AvaloniaMocks/MockWindowingPlatform.cs +++ /dev/null @@ -1,35 +0,0 @@ -using System; -using Avalonia.Platform; -using Moq; - -namespace AvaloniaEdit.AvaloniaMocks -{ - public class MockWindowingPlatform : IWindowingPlatform - { - private readonly Func _windowImpl; - private readonly Func _popupImpl; - - public MockWindowingPlatform(Func windowImpl = null, Func popupImpl = null) - { - _windowImpl = windowImpl; - _popupImpl = popupImpl; - } - - public IWindowImpl CreateWindow() - { - return _windowImpl?.Invoke() ?? Mock.Of(x => x.RenderScaling == 1); - } - - public IWindowImpl CreateEmbeddableWindow() - { - throw new NotImplementedException(); - } - - public ITrayIconImpl CreateTrayIcon() - { - throw new NotImplementedException(); - } - - public IPopupImpl CreatePopup() => _popupImpl?.Invoke() ?? Mock.Of(x => x.RenderScaling == 1); - } -} \ No newline at end of file diff --git a/test/AvaloniaEdit.Tests/AvaloniaMocks/TestServices.cs b/test/AvaloniaEdit.Tests/AvaloniaMocks/TestServices.cs deleted file mode 100644 index a2916f8d..00000000 --- a/test/AvaloniaEdit.Tests/AvaloniaMocks/TestServices.cs +++ /dev/null @@ -1,162 +0,0 @@ -using System; -using Avalonia; -using Avalonia.Input; -using Avalonia.Input.Platform; -using Avalonia.Layout; -using Avalonia.Markup.Xaml.Styling; -using Avalonia.Platform; -using Avalonia.Rendering; -using Avalonia.Styling; -using Avalonia.Themes.Simple; -using Avalonia.Themes.Fluent; -using Moq; - -namespace AvaloniaEdit.AvaloniaMocks -{ - public class TestServices - { - public static readonly TestServices StyledWindow = new TestServices( - assetLoader: new AssetLoader(), - platform: new AppBuilder().RuntimePlatform, - renderInterface: new MockPlatformRenderInterface(), - standardCursorFactory: Mock.Of(), - theme: () => CreateDefaultTheme(), - threadingInterface: Mock.Of(x => x.CurrentThreadIsLoopThread == true), - windowingPlatform: new MockWindowingPlatform(), - fontManagerImpl: new MockFontManagerImpl(), - textShaperImpl: new MockTextShaperImpl()); - - public static readonly TestServices MockPlatformRenderInterface = new TestServices( - renderInterface: new MockPlatformRenderInterface()); - - public static readonly TestServices MockPlatformWrapper = new TestServices( - platform: Mock.Of()); - - public static readonly TestServices MockThreadingInterface = new TestServices( - threadingInterface: Mock.Of(x => x.CurrentThreadIsLoopThread == true)); - - public static readonly TestServices MockWindowingPlatform = new TestServices( - windowingPlatform: new MockWindowingPlatform()); - - public static readonly TestServices RealFocus = new TestServices( - focusManager: new FocusManager(), - keyboardDevice: () => new KeyboardDevice(), - keyboardNavigation: new KeyboardNavigationHandler(), - inputManager: new InputManager()); - - public TestServices( - IAssetLoader assetLoader = null, - IFocusManager focusManager = null, - IInputManager inputManager = null, - Func keyboardDevice = null, - IKeyboardNavigationHandler keyboardNavigation = null, - ILayoutManager layoutManager = null, - Func mouseDevice = null, - IRuntimePlatform platform = null, - IPlatformRenderInterface renderInterface = null, - IRenderLoop renderLoop = null, - ICursorFactory standardCursorFactory = null, - Func theme = null, - IPlatformThreadingInterface threadingInterface = null, - IWindowImpl windowImpl = null, - IWindowingPlatform windowingPlatform = null, - PlatformHotkeyConfiguration platformHotkeyConfiguration = null, - IFontManagerImpl fontManagerImpl = null, - ITextShaperImpl textShaperImpl = null) - { - AssetLoader = assetLoader; - FocusManager = focusManager; - InputManager = inputManager; - KeyboardDevice = keyboardDevice; - KeyboardNavigation = keyboardNavigation; - LayoutManager = layoutManager; - MouseDevice = mouseDevice; - Platform = platform; - RenderInterface = renderInterface; - StandardCursorFactory = standardCursorFactory; - Theme = theme; - ThreadingInterface = threadingInterface; - WindowImpl = windowImpl; - WindowingPlatform = windowingPlatform; - PlatformHotkeyConfiguration = platformHotkeyConfiguration; - FontManagerImpl = fontManagerImpl; - TextShaperImpl = textShaperImpl; - } - - public IAssetLoader AssetLoader { get; } - public IInputManager InputManager { get; } - public IFocusManager FocusManager { get; } - public Func KeyboardDevice { get; } - public IKeyboardNavigationHandler KeyboardNavigation { get; } - public ILayoutManager LayoutManager { get; } - public Func MouseDevice { get; } - public IRuntimePlatform Platform { get; } - public IPlatformRenderInterface RenderInterface { get; } - public ICursorFactory StandardCursorFactory { get; } - public Func Theme { get; } - public IPlatformThreadingInterface ThreadingInterface { get; } - public IWindowImpl WindowImpl { get; } - public IWindowingPlatform WindowingPlatform { get; } - public PlatformHotkeyConfiguration PlatformHotkeyConfiguration { get; } - public IFontManagerImpl FontManagerImpl { get; } - - public ITextShaperImpl TextShaperImpl { get; } - - public TestServices With( - IAssetLoader assetLoader = null, - IFocusManager focusManager = null, - IInputManager inputManager = null, - Func keyboardDevice = null, - IKeyboardNavigationHandler keyboardNavigation = null, - ILayoutManager layoutManager = null, - Func mouseDevice = null, - IRuntimePlatform platform = null, - IPlatformRenderInterface renderInterface = null, - IRenderLoop renderLoop = null, - ICursorFactory standardCursorFactory = null, - Func theme = null, - IPlatformThreadingInterface threadingInterface = null, - IWindowImpl windowImpl = null, - IWindowingPlatform windowingPlatform = null, - PlatformHotkeyConfiguration platformHotkeyConfiguration = null, - IFontManagerImpl fontManagerImpl = null, - ITextShaperImpl textShaperImpl = null) - { - return new TestServices( - assetLoader: assetLoader ?? AssetLoader, - focusManager: focusManager ?? FocusManager, - inputManager: inputManager ?? InputManager, - keyboardDevice: keyboardDevice ?? KeyboardDevice, - keyboardNavigation: keyboardNavigation ?? KeyboardNavigation, - layoutManager: layoutManager ?? LayoutManager, - mouseDevice: mouseDevice ?? MouseDevice, - platform: platform ?? Platform, - renderInterface: renderInterface ?? RenderInterface, - standardCursorFactory: standardCursorFactory ?? StandardCursorFactory, - theme: theme ?? Theme, - threadingInterface: threadingInterface ?? ThreadingInterface, - windowingPlatform: windowingPlatform ?? WindowingPlatform, - windowImpl: windowImpl ?? WindowImpl, - platformHotkeyConfiguration: platformHotkeyConfiguration ?? PlatformHotkeyConfiguration, - fontManagerImpl: fontManagerImpl ?? FontManagerImpl, - textShaperImpl: textShaperImpl ?? TextShaperImpl); - } - - private static Styles CreateDefaultTheme() - { - var result = new Styles - { - new SimpleTheme() - }; - - return result; - } - - private static IPlatformRenderInterface CreateRenderInterfaceMock() - { - return Mock.Of(x => - x.CreateStreamGeometry() == Mock.Of( - y => y.Open() == Mock.Of())); - } - } -} \ No newline at end of file diff --git a/test/AvaloniaEdit.Tests/AvaloniaMocks/UnitTestApplication.cs b/test/AvaloniaEdit.Tests/AvaloniaMocks/UnitTestApplication.cs index a52a3d60..af4fbb77 100644 --- a/test/AvaloniaEdit.Tests/AvaloniaMocks/UnitTestApplication.cs +++ b/test/AvaloniaEdit.Tests/AvaloniaMocks/UnitTestApplication.cs @@ -1,66 +1,19 @@ -using System; -using System.Reflection; -using Avalonia; -using Avalonia.Input; -using Avalonia.Input.Platform; -using Avalonia.Layout; -using Avalonia.Platform; -using Avalonia.Styling; -using Avalonia.Threading; -using AvaloniaEdit.Utils; +using Avalonia; +using Avalonia.Headless; +using AvaloniaEdit.AvaloniaMocks; + +[assembly: AvaloniaTestApplication(typeof(UnitTestApplication))] namespace AvaloniaEdit.AvaloniaMocks { public class UnitTestApplication : Application { - public UnitTestApplication(TestServices services) - { - Services = services ?? new TestServices(); - RegisterServices(); - } - - public TestServices Services { get; } - - public static IDisposable Start(TestServices services = null) - { - AvaloniaLocator.Current = (AvaloniaLocator.CurrentMutable = new AvaloniaLocator()); - var app = new UnitTestApplication(services); - AvaloniaLocator.CurrentMutable.BindToSelf(app); - var updateServices = Dispatcher.UIThread.GetType().GetMethod("UpdateServices", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); - updateServices?.Invoke(Dispatcher.UIThread, null); - return new Disposable(() => - { - updateServices?.Invoke(Dispatcher.UIThread, null); - AvaloniaLocator.CurrentMutable = null; - AvaloniaLocator.Current = null; - }); - } - - public override void RegisterServices() - { - AvaloniaLocator.CurrentMutable - .Bind().ToConstant(Services.AssetLoader) - .Bind().ToConstant(Services.FocusManager) - .BindToSelf(this) - .Bind().ToConstant(Services.InputManager) - .Bind().ToConstant(Services.KeyboardDevice?.Invoke()) - .Bind().ToConstant(Services.KeyboardNavigation) - .Bind().ToConstant(Services.LayoutManager) - .Bind().ToConstant(Services.MouseDevice?.Invoke()) - .Bind().ToConstant(Services.Platform) - .Bind().ToConstant(Services.RenderInterface) - .Bind().ToConstant(Services.ThreadingInterface) - .Bind().ToConstant(Services.StandardCursorFactory) - .Bind().ToConstant(Services.WindowingPlatform) - .Bind().ToConstant(Services.PlatformHotkeyConfiguration) - .Bind().ToConstant(Services.FontManagerImpl) - .Bind().ToConstant(Services.TextShaperImpl); - //var styles = Services.Theme?.Invoke(); - //if (styles != null) - //{ - // Styles.AddRange(styles); - //} - } + public static AppBuilder BuildAvaloniaApp() + => AppBuilder.Configure() + .UseHeadless(new AvaloniaHeadlessPlatformOptions + { + UseHeadlessDrawing = true + }); } } \ No newline at end of file diff --git a/test/AvaloniaEdit.Tests/Editing/ChangeDocumentTests.cs b/test/AvaloniaEdit.Tests/Editing/ChangeDocumentTests.cs index 7c4e34d6..cdc86dbe 100644 --- a/test/AvaloniaEdit.Tests/Editing/ChangeDocumentTests.cs +++ b/test/AvaloniaEdit.Tests/Editing/ChangeDocumentTests.cs @@ -17,7 +17,7 @@ // DEALINGS IN THE SOFTWARE. using System.Text; -using AvaloniaEdit.AvaloniaMocks; +using Avalonia.Headless.NUnit; using AvaloniaEdit.Document; using NUnit.Framework; @@ -26,76 +26,52 @@ namespace AvaloniaEdit.Editing [TestFixture] public class ChangeDocumentTests { - [Test] + [AvaloniaTest] public void ClearCaretAndSelectionOnDocumentChange() { - using (UnitTestApplication.Start(new TestServices( - renderInterface: new MockPlatformRenderInterface(), - platform: new MockRuntimePlatform(), - platformHotkeyConfiguration: new MockPlatformHotkeyConfiguration(), - fontManagerImpl: new MockFontManagerImpl(), - textShaperImpl: new MockTextShaperImpl()))) - { - TextArea textArea = new TextArea(); - textArea.Document = new TextDocument("1\n2\n3\n4th line"); - textArea.Caret.Offset = 6; - textArea.Selection = Selection.Create(textArea, 3, 6); - textArea.Document = new TextDocument("1\n2nd"); - Assert.AreEqual(0, textArea.Caret.Offset); - Assert.AreEqual(new TextLocation(1, 1), textArea.Caret.Location); - Assert.IsTrue(textArea.Selection.IsEmpty); - } + TextArea textArea = new TextArea(); + textArea.Document = new TextDocument("1\n2\n3\n4th line"); + textArea.Caret.Offset = 6; + textArea.Selection = Selection.Create(textArea, 3, 6); + textArea.Document = new TextDocument("1\n2nd"); + Assert.AreEqual(0, textArea.Caret.Offset); + Assert.AreEqual(new TextLocation(1, 1), textArea.Caret.Location); + Assert.IsTrue(textArea.Selection.IsEmpty); } - [Test] + [AvaloniaTest] public void SetDocumentToNull() { - using (UnitTestApplication.Start(new TestServices( - renderInterface: new MockPlatformRenderInterface(), - platform: new MockRuntimePlatform(), - platformHotkeyConfiguration: new MockPlatformHotkeyConfiguration(), - fontManagerImpl: new MockFontManagerImpl(), - textShaperImpl: new MockTextShaperImpl()))) - { - TextArea textArea = new TextArea(); - textArea.Document = new TextDocument("1\n2\n3\n4th line"); - textArea.Caret.Offset = 6; - textArea.Selection = Selection.Create(textArea, 3, 6); - textArea.Document = null; - Assert.AreEqual(0, textArea.Caret.Offset); - Assert.AreEqual(new TextLocation(1, 1), textArea.Caret.Location); - Assert.IsTrue(textArea.Selection.IsEmpty); - } + TextArea textArea = new TextArea(); + textArea.Document = new TextDocument("1\n2\n3\n4th line"); + textArea.Caret.Offset = 6; + textArea.Selection = Selection.Create(textArea, 3, 6); + textArea.Document = null; + Assert.AreEqual(0, textArea.Caret.Offset); + Assert.AreEqual(new TextLocation(1, 1), textArea.Caret.Location); + Assert.IsTrue(textArea.Selection.IsEmpty); } - [Test] + [AvaloniaTest] public void CheckEventOrderOnDocumentChange() { - using (UnitTestApplication.Start(new TestServices( - renderInterface: new MockPlatformRenderInterface(), - platform: new MockRuntimePlatform(), - platformHotkeyConfiguration: new MockPlatformHotkeyConfiguration(), - fontManagerImpl: new MockFontManagerImpl(), - textShaperImpl: new MockTextShaperImpl()))) + TextArea textArea = new TextArea(); + TextDocument newDocument = new TextDocument(); + StringBuilder b = new StringBuilder(); + textArea.TextView.DocumentChanged += delegate + { + b.Append("TextView.DocumentChanged;"); + Assert.AreSame(newDocument, textArea.TextView.Document); + Assert.AreSame(newDocument, textArea.Document); + }; + textArea.DocumentChanged += delegate { - TextArea textArea = new TextArea(); - TextDocument newDocument = new TextDocument(); - StringBuilder b = new StringBuilder(); - textArea.TextView.DocumentChanged += delegate - { - b.Append("TextView.DocumentChanged;"); - Assert.AreSame(newDocument, textArea.TextView.Document); - Assert.AreSame(newDocument, textArea.Document); - }; - textArea.DocumentChanged += delegate - { - b.Append("TextArea.DocumentChanged;"); - Assert.AreSame(newDocument, textArea.TextView.Document); - Assert.AreSame(newDocument, textArea.Document); - }; - textArea.Document = newDocument; - Assert.AreEqual("TextView.DocumentChanged;TextArea.DocumentChanged;", b.ToString()); - } + b.Append("TextArea.DocumentChanged;"); + Assert.AreSame(newDocument, textArea.TextView.Document); + Assert.AreSame(newDocument, textArea.Document); + }; + textArea.Document = newDocument; + Assert.AreEqual("TextView.DocumentChanged;TextArea.DocumentChanged;", b.ToString()); } } } diff --git a/test/AvaloniaEdit.Tests/Rendering/TextViewTests.cs b/test/AvaloniaEdit.Tests/Rendering/TextViewTests.cs index 4a2e1912..2994a2de 100644 --- a/test/AvaloniaEdit.Tests/Rendering/TextViewTests.cs +++ b/test/AvaloniaEdit.Tests/Rendering/TextViewTests.cs @@ -1,7 +1,6 @@ using Avalonia; -using Avalonia.Controls; using Avalonia.Controls.Primitives; -using AvaloniaEdit.AvaloniaMocks; +using Avalonia.Headless.NUnit; using AvaloniaEdit.Document; using AvaloniaEdit.Rendering; @@ -9,14 +8,14 @@ namespace AvaloniaEdit.Tests.Rendering { - [TestFixture] internal class TextViewTests { - [Test] + // https://github.com/AvaloniaUI/Avalonia/blob/master/src/Headless/Avalonia.Headless/HeadlessPlatformStubs.cs#L126 + private const int HeadlessGlyphAdvance = 8; + + [AvaloniaTest] public void Visual_Line_Should_Create_Two_Text_Lines_When_Wrapping() { - using var app = UnitTestApplication.Start(TestServices.StyledWindow); - TextView textView = new TextView(); TextDocument document = new TextDocument("hello world".ToCharArray()); @@ -24,7 +23,7 @@ public void Visual_Line_Should_Create_Two_Text_Lines_When_Wrapping() textView.Document = document; ((ILogicalScrollable)textView).CanHorizontallyScroll = false; - textView.Width = MockGlyphTypeface.GlyphAdvance * 8; + textView.Width = HeadlessGlyphAdvance * 8; textView.Measure(Size.Infinity); @@ -35,11 +34,9 @@ public void Visual_Line_Should_Create_Two_Text_Lines_When_Wrapping() Assert.AreEqual("world", new string(visualLine.TextLines[1].TextRuns[0].Text.Span)); } - [Test()] + [AvaloniaTest] public void Visual_Line_Should_Create_One_Text_Lines_When_Not_Wrapping() { - using var app = UnitTestApplication.Start(TestServices.StyledWindow); - TextView textView = new TextView(); TextDocument document = new TextDocument("hello world".ToCharArray()); @@ -47,7 +44,7 @@ public void Visual_Line_Should_Create_One_Text_Lines_When_Not_Wrapping() textView.Document = document; textView.EnsureVisualLines(); ((ILogicalScrollable)textView).CanHorizontallyScroll = false; - textView.Width = MockGlyphTypeface.GlyphAdvance * 500; + textView.Width = HeadlessGlyphAdvance * 500; textView.Measure(Size.Infinity);