From 70d75c0eb5db776fa59fffaaf69c1b9c8ba6d9f1 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Mon, 12 Feb 2018 23:55:36 +0100 Subject: [PATCH 01/18] Fix Window auto-sizing. `Window` was acting like `SizeToContent="WidthAndHeight"` was set even when it wasn't. This fixes that. --- src/Avalonia.Controls/Window.cs | 38 ++++++++++++++++++--------------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/src/Avalonia.Controls/Window.cs b/src/Avalonia.Controls/Window.cs index 7fed712e07..f3ad4dbbd9 100644 --- a/src/Avalonia.Controls/Window.cs +++ b/src/Avalonia.Controls/Window.cs @@ -374,27 +374,31 @@ namespace Avalonia.Controls { var sizeToContent = SizeToContent; var clientSize = ClientSize; - Size constraint; + Size constraint = clientSize; - switch (sizeToContent) + if ((sizeToContent & SizeToContent.Width) != 0) { - case SizeToContent.Width: - constraint = new Size(double.PositiveInfinity, ClientSize.Height); - break; - case SizeToContent.Height: - constraint = new Size(ClientSize.Width, double.PositiveInfinity); - break; - case SizeToContent.WidthAndHeight: - constraint = Size.Infinity; - break; - case SizeToContent.Manual: - constraint = ClientSize; - break; - default: - throw new InvalidOperationException("Invalid value for SizeToContent."); + constraint = constraint.WithWidth(double.PositiveInfinity); } - return base.MeasureOverride(constraint); + if ((sizeToContent & SizeToContent.Height) != 0) + { + constraint = constraint.WithHeight(double.PositiveInfinity); + } + + var result = base.MeasureOverride(constraint); + + if ((sizeToContent & SizeToContent.Width) == 0) + { + result = result.WithWidth(clientSize.Width); + } + + if ((sizeToContent & SizeToContent.Height) == 0) + { + result = result.WithHeight(clientSize.Height); + } + + return result; } protected override void HandleClosed() From 88179105499705dccfd77b277e2a079b5cf4718d Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Mon, 12 Feb 2018 17:00:43 -0600 Subject: [PATCH 02/18] Add ref-counting for the scene instance in DeferredRenderer to ensure that we don't dispose a scene while it is being rendered. Also rename Scene.Clone to Scene.CloneScene to prevent confusion between IRef.Clone and Scene.Clone. --- .../Rendering/DeferredRenderer.cs | 26 +++++++++++++------ .../Rendering/SceneGraph/Scene.cs | 2 +- .../Rendering/SceneGraph/SceneBuilderTests.cs | 22 ++++++++-------- .../SceneGraph/SceneBuilderTests_Layers.cs | 6 ++--- .../Rendering/SceneGraph/SceneTests.cs | 2 +- 5 files changed, 34 insertions(+), 24 deletions(-) diff --git a/src/Avalonia.Visuals/Rendering/DeferredRenderer.cs b/src/Avalonia.Visuals/Rendering/DeferredRenderer.cs index 344f3f8f2b..dbf032b037 100644 --- a/src/Avalonia.Visuals/Rendering/DeferredRenderer.cs +++ b/src/Avalonia.Visuals/Rendering/DeferredRenderer.cs @@ -28,7 +28,7 @@ namespace Avalonia.Rendering private readonly ISceneBuilder _sceneBuilder; private bool _running; - private Scene _scene; + private volatile IRef _scene; private DirtyVisuals _dirty; private IRef _overlay; private bool _updateQueued; @@ -128,7 +128,7 @@ namespace Avalonia.Rendering UpdateScene(); } - return _scene?.HitTest(p, root, filter) ?? Enumerable.Empty(); + return _scene?.Item.HitTest(p, root, filter) ?? Enumerable.Empty(); } /// @@ -180,7 +180,7 @@ namespace Avalonia.Rendering internal void UnitTestUpdateScene() => UpdateScene(); - internal void UnitTestRender() => Render(_scene); + internal void UnitTestRender() => Render(_scene.Item); private void Render(Scene scene) { @@ -381,7 +381,8 @@ namespace Avalonia.Rendering { if (_root.IsVisible) { - var scene = _scene?.Clone() ?? new Scene(_root); + var sceneRef = RefCountable.Create(_scene?.Item.CloneScene() ?? new Scene(_root)); + var scene = sceneRef.Item; if (_dirty == null) { @@ -396,7 +397,7 @@ namespace Avalonia.Rendering } } - var oldScene = Interlocked.Exchange(ref _scene, scene); + var oldScene = Interlocked.Exchange(ref _scene, sceneRef); oldScene?.Dispose(); _dirty.Clear(); @@ -426,9 +427,18 @@ namespace Avalonia.Rendering _dispatcher.Post(UpdateScene, DispatcherPriority.Render); } - Scene scene = null; - Interlocked.Exchange(ref scene, _scene); - Render(scene); + var scene = _scene?.Clone(); + if (scene == null) + { + Render(null); + } + else + { + using (scene) + { + Render(scene.Item); + } + } } catch { } finally diff --git a/src/Avalonia.Visuals/Rendering/SceneGraph/Scene.cs b/src/Avalonia.Visuals/Rendering/SceneGraph/Scene.cs index f2e4f5fdbd..352d41d024 100644 --- a/src/Avalonia.Visuals/Rendering/SceneGraph/Scene.cs +++ b/src/Avalonia.Visuals/Rendering/SceneGraph/Scene.cs @@ -82,7 +82,7 @@ namespace Avalonia.Rendering.SceneGraph /// Clones the scene. /// /// The cloned scene. - public Scene Clone() + public Scene CloneScene() { var index = new Dictionary(); var root = Clone((VisualNode)Root, null, index); diff --git a/tests/Avalonia.Visuals.UnitTests/Rendering/SceneGraph/SceneBuilderTests.cs b/tests/Avalonia.Visuals.UnitTests/Rendering/SceneGraph/SceneBuilderTests.cs index f44be3f82e..dda1d73649 100644 --- a/tests/Avalonia.Visuals.UnitTests/Rendering/SceneGraph/SceneBuilderTests.cs +++ b/tests/Avalonia.Visuals.UnitTests/Rendering/SceneGraph/SceneBuilderTests.cs @@ -99,7 +99,7 @@ namespace Avalonia.Visuals.UnitTests.Rendering.SceneGraph Assert.Equal(new Rect(10, 20, 160, 240), canvasNode.ClipBounds); // Initial ClipBounds are correct, make sure they're still correct after updating canvas. - result = result.Clone(); + result = result.CloneScene(); Assert.True(sceneBuilder.Update(result, canvas)); canvasNode = result.FindNode(canvas); @@ -197,7 +197,7 @@ namespace Avalonia.Visuals.UnitTests.Rendering.SceneGraph canvas.Arrange(new Rect(tree.DesiredSize)); // Initial ClipBounds are correct, make sure they're still correct after updating canvas. - scene = scene.Clone(); + scene = scene.CloneScene(); Assert.True(sceneBuilder.Update(scene, canvas)); borderNode = scene.FindNode(border); @@ -309,7 +309,7 @@ namespace Avalonia.Visuals.UnitTests.Rendering.SceneGraph var borderNode = scene.FindNode(border); Assert.Equal(expectedTransform, borderNode.Transform); - scene = scene.Clone(); + scene = scene.CloneScene(); Assert.True(sceneBuilder.Update(scene, border)); borderNode = scene.FindNode(border); @@ -354,7 +354,7 @@ namespace Avalonia.Visuals.UnitTests.Rendering.SceneGraph border.Background = Brushes.Green; - var result = initial.Clone(); + var result = initial.CloneScene(); sceneBuilder.Update(result, border); var borderNode = (VisualNode)result.Root.Children[0]; @@ -402,7 +402,7 @@ namespace Avalonia.Visuals.UnitTests.Rendering.SceneGraph sceneBuilder.UpdateAll(initial); border.Child = decorator; - var result = initial.Clone(); + var result = initial.CloneScene(); Assert.True(sceneBuilder.Update(result, decorator)); @@ -457,7 +457,7 @@ namespace Avalonia.Visuals.UnitTests.Rendering.SceneGraph sceneBuilder.UpdateAll(initial); border.Child = null; - var result = initial.Clone(); + var result = initial.CloneScene(); Assert.True(sceneBuilder.Update(result, decorator)); Assert.False(sceneBuilder.Update(result, canvas)); @@ -501,7 +501,7 @@ namespace Avalonia.Visuals.UnitTests.Rendering.SceneGraph sceneBuilder.UpdateAll(initial); border.IsVisible = false; - var result = initial.Clone(); + var result = initial.CloneScene(); Assert.True(sceneBuilder.Update(result, border)); Assert.False(sceneBuilder.Update(result, canvas)); @@ -552,7 +552,7 @@ namespace Avalonia.Visuals.UnitTests.Rendering.SceneGraph decorator.Margin = new Thickness(0, 20, 0, 0); layout.ExecuteLayoutPass(); - scene = scene.Clone(); + scene = scene.CloneScene(); sceneBuilder.Update(scene, decorator); borderNode = scene.FindNode(border); @@ -600,7 +600,7 @@ namespace Avalonia.Visuals.UnitTests.Rendering.SceneGraph decorator.Margin = new Thickness(0, 20, 0, 0); layout.ExecuteLayoutPass(); - scene = scene.Clone(); + scene = scene.CloneScene(); sceneBuilder.Update(scene, decorator); @@ -640,7 +640,7 @@ namespace Avalonia.Visuals.UnitTests.Rendering.SceneGraph Assert.Equal(new Size(100, 100), scene.Size); tree.ClientSize = new Size(110, 120); - scene = scene.Clone(); + scene = scene.CloneScene(); sceneBuilder.Update(scene, tree); Assert.Equal(new Size(110, 120), scene.Size); @@ -735,7 +735,7 @@ namespace Avalonia.Visuals.UnitTests.Rendering.SceneGraph tree.Child = new Decorator(); - using (var result = scene.Clone()) + using (var result = scene.CloneScene()) { sceneBuilder.Update(result, img); scene.Dispose(); diff --git a/tests/Avalonia.Visuals.UnitTests/Rendering/SceneGraph/SceneBuilderTests_Layers.cs b/tests/Avalonia.Visuals.UnitTests/Rendering/SceneGraph/SceneBuilderTests_Layers.cs index f2d137249a..ac00b8ccfc 100644 --- a/tests/Avalonia.Visuals.UnitTests/Rendering/SceneGraph/SceneBuilderTests_Layers.cs +++ b/tests/Avalonia.Visuals.UnitTests/Rendering/SceneGraph/SceneBuilderTests_Layers.cs @@ -62,7 +62,7 @@ namespace Avalonia.Visuals.UnitTests.Rendering.SceneGraph Assert.Empty(scene.Layers.Select(x => x.LayerRoot).Except(new IVisual[] { tree, border })); animation.OnCompleted(); - scene = scene.Clone(); + scene = scene.CloneScene(); sceneBuilder.Update(scene, border); @@ -160,7 +160,7 @@ namespace Avalonia.Visuals.UnitTests.Rendering.SceneGraph Assert.Equal(3, scene.Layers.Count); decorator.Child = null; - scene = scene.Clone(); + scene = scene.CloneScene(); sceneBuilder.Update(scene, border); @@ -210,7 +210,7 @@ namespace Avalonia.Visuals.UnitTests.Rendering.SceneGraph Assert.Equal(3, scene.Layers.Count); border.IsVisible = false; - scene = scene.Clone(); + scene = scene.CloneScene(); sceneBuilder.Update(scene, border); diff --git a/tests/Avalonia.Visuals.UnitTests/Rendering/SceneGraph/SceneTests.cs b/tests/Avalonia.Visuals.UnitTests/Rendering/SceneGraph/SceneTests.cs index 9c0adc432d..bba0c8b8f3 100644 --- a/tests/Avalonia.Visuals.UnitTests/Rendering/SceneGraph/SceneTests.cs +++ b/tests/Avalonia.Visuals.UnitTests/Rendering/SceneGraph/SceneTests.cs @@ -25,7 +25,7 @@ namespace Avalonia.Visuals.UnitTests.Rendering.SceneGraph scene.Layers[tree].Dirty.Add(new Rect(0, 0, 100, 100)); scene.Layers[decorator].Dirty.Add(new Rect(0, 0, 50, 100)); - scene = scene.Clone(); + scene = scene.CloneScene(); Assert.Equal(2, scene.Layers.Count()); Assert.Empty(scene.Layers[0].Dirty); Assert.Empty(scene.Layers[1].Dirty); From 2af1f20108a1d3ce1c854e30899f7a67327cbe89 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Tue, 13 Feb 2018 00:12:12 +0100 Subject: [PATCH 03/18] Mark SizeToContent with [Flags]. And explicitly assign values. --- src/Avalonia.Controls/Window.cs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/Avalonia.Controls/Window.cs b/src/Avalonia.Controls/Window.cs index f3ad4dbbd9..893859b915 100644 --- a/src/Avalonia.Controls/Window.cs +++ b/src/Avalonia.Controls/Window.cs @@ -19,27 +19,28 @@ namespace Avalonia.Controls /// /// Determines how a will size itself to fit its content. /// + [Flags] public enum SizeToContent { /// /// The window will not automatically size itself to fit its content. /// - Manual, + Manual = 0, /// /// The window will size itself horizontally to fit its content. /// - Width, + Width = 1, /// /// The window will size itself vertically to fit its content. /// - Height, + Height = 2, /// /// The window will size itself horizontally and vertically to fit its content. /// - WidthAndHeight, + WidthAndHeight = 3, } /// From 53bf2431edb9c9021ab8931bcc450b7568095815 Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Mon, 12 Feb 2018 17:50:28 -0600 Subject: [PATCH 04/18] Clean up OnRenderLoopTick code. --- src/Avalonia.Visuals/Rendering/DeferredRenderer.cs | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/src/Avalonia.Visuals/Rendering/DeferredRenderer.cs b/src/Avalonia.Visuals/Rendering/DeferredRenderer.cs index dbf032b037..fd6b149837 100644 --- a/src/Avalonia.Visuals/Rendering/DeferredRenderer.cs +++ b/src/Avalonia.Visuals/Rendering/DeferredRenderer.cs @@ -426,18 +426,10 @@ namespace Avalonia.Rendering _updateQueued = true; _dispatcher.Post(UpdateScene, DispatcherPriority.Render); } - - var scene = _scene?.Clone(); - if (scene == null) - { - Render(null); - } - else + + using (var scene = _scene?.Clone()) { - using (scene) - { - Render(scene.Item); - } + Render(scene?.Item); } } catch { } From 3a42ef34633a52e899c56ee8878013a0ca413a99 Mon Sep 17 00:00:00 2001 From: Nikita Tsukanov Date: Tue, 13 Feb 2018 09:19:58 +0300 Subject: [PATCH 05/18] Fixed designer focus issue --- src/Avalonia.DesignerSupport/Remote/RemoteDesignerEntryPoint.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Avalonia.DesignerSupport/Remote/RemoteDesignerEntryPoint.cs b/src/Avalonia.DesignerSupport/Remote/RemoteDesignerEntryPoint.cs index c4febff434..f5893ae69a 100644 --- a/src/Avalonia.DesignerSupport/Remote/RemoteDesignerEntryPoint.cs +++ b/src/Avalonia.DesignerSupport/Remote/RemoteDesignerEntryPoint.cs @@ -140,6 +140,7 @@ namespace Avalonia.DesignerSupport.Remote BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); if (builderMethod == null) throw Die($"{entryPoint.DeclaringType.FullName} doesn't have a method named {BuilderMethodName}"); + Design.IsDesignMode = true; Log($"Obtaining AppBuilder instance from {builderMethod.DeclaringType.FullName}.{builderMethod.Name}"); var appBuilder = builderMethod.Invoke(null, null); Log($"Initializing application in design mode"); From fafcecf0f38d0c2cb30457fe0e951f2ba4ad7d7e Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Tue, 13 Feb 2018 15:15:16 +0000 Subject: [PATCH 06/18] system dialog combines the initialDirectory and InitialFileName on Gtk. --- src/Gtk/Avalonia.Gtk3/SystemDialogs.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/Gtk/Avalonia.Gtk3/SystemDialogs.cs b/src/Gtk/Avalonia.Gtk3/SystemDialogs.cs index fb8af02d5d..cff376ad1f 100644 --- a/src/Gtk/Avalonia.Gtk3/SystemDialogs.cs +++ b/src/Gtk/Avalonia.Gtk3/SystemDialogs.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; @@ -79,9 +80,11 @@ namespace Avalonia.Gtk3 public Task ShowFileDialogAsync(FileDialog dialog, IWindowImpl parent) { - return ShowDialog(dialog.Title, ((WindowBaseImpl) parent)?.GtkWidget, + return ShowDialog(dialog.Title, ((WindowBaseImpl)parent)?.GtkWidget, dialog is OpenFileDialog ? GtkFileChooserAction.Open : GtkFileChooserAction.Save, - (dialog as OpenFileDialog)?.AllowMultiple ?? false, dialog.InitialFileName); + (dialog as OpenFileDialog)?.AllowMultiple ?? false, + Path.Combine(string.IsNullOrEmpty(dialog.InitialDirectory) ? "" : dialog.InitialDirectory, + string.IsNullOrEmpty(dialog.InitialFileName) ? "" : dialog.InitialFileName)); } public async Task ShowFolderDialogAsync(OpenFolderDialog dialog, IWindowImpl parent) From b7de65f1aaebde38087150674cb0a80b46836ed8 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Tue, 13 Feb 2018 20:39:08 +0100 Subject: [PATCH 07/18] Fix TextBox text truncation. Correctly set the value of the `TextBox`'s `HorizontalScrollBarVisibility` so that the text is not truncated. Fixes #1354 --- src/Avalonia.Controls/TextBox.cs | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/Avalonia.Controls/TextBox.cs b/src/Avalonia.Controls/TextBox.cs index 7366ff3f91..158157766e 100644 --- a/src/Avalonia.Controls/TextBox.cs +++ b/src/Avalonia.Controls/TextBox.cs @@ -98,9 +98,19 @@ namespace Avalonia.Controls var horizontalScrollBarVisibility = Observable.CombineLatest( this.GetObservable(AcceptsReturnProperty), this.GetObservable(TextWrappingProperty), - (acceptsReturn, wrapping) => acceptsReturn && wrapping == TextWrapping.NoWrap ? - ScrollBarVisibility.Auto : ScrollBarVisibility.Disabled); - + (acceptsReturn, wrapping) => + { + if (acceptsReturn) + { + return wrapping == TextWrapping.NoWrap ? + ScrollBarVisibility.Visible : + ScrollBarVisibility.Disabled; + } + else + { + return ScrollBarVisibility.Hidden; + } + }); Bind( ScrollViewer.HorizontalScrollBarVisibilityProperty, horizontalScrollBarVisibility, From e5800c17f1405bdfdcba082c573420ee5d248776 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Tue, 13 Feb 2018 20:44:16 +0100 Subject: [PATCH 08/18] Fix TextBlock click positioning. When the click was outside the `TextPresenter`, it was not registering with the `TextBox` so the caret was being moved to the beginning. --- src/Avalonia.Controls/TextBox.cs | 49 +++++++++++++++----------------- 1 file changed, 23 insertions(+), 26 deletions(-) diff --git a/src/Avalonia.Controls/TextBox.cs b/src/Avalonia.Controls/TextBox.cs index 158157766e..e939ace66d 100644 --- a/src/Avalonia.Controls/TextBox.cs +++ b/src/Avalonia.Controls/TextBox.cs @@ -497,37 +497,34 @@ namespace Avalonia.Controls protected override void OnPointerPressed(PointerPressedEventArgs e) { - if (e.Source == _presenter) - { - var point = e.GetPosition(_presenter); - var index = CaretIndex = _presenter.GetCaretIndex(point); - var text = Text; + var point = e.GetPosition(_presenter); + var index = CaretIndex = _presenter.GetCaretIndex(point); + var text = Text; - if (text != null) + if (text != null) + { + switch (e.ClickCount) { - switch (e.ClickCount) - { - case 1: - SelectionStart = SelectionEnd = index; - break; - case 2: - if (!StringUtils.IsStartOfWord(text, index)) - { - SelectionStart = StringUtils.PreviousWord(text, index); - } + case 1: + SelectionStart = SelectionEnd = index; + break; + case 2: + if (!StringUtils.IsStartOfWord(text, index)) + { + SelectionStart = StringUtils.PreviousWord(text, index); + } - SelectionEnd = StringUtils.NextWord(text, index); - break; - case 3: - SelectionStart = 0; - SelectionEnd = text.Length; - break; - } + SelectionEnd = StringUtils.NextWord(text, index); + break; + case 3: + SelectionStart = 0; + SelectionEnd = text.Length; + break; } - - e.Device.Capture(_presenter); - e.Handled = true; } + + e.Device.Capture(_presenter); + e.Handled = true; } protected override void OnPointerMoved(PointerEventArgs e) From 458d8bf76031a95b1f46cabee185aabf1153963c Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Wed, 14 Feb 2018 15:55:31 -0600 Subject: [PATCH 09/18] Don't dispose replaced visual nodes if they're replaced with themselves. --- src/Avalonia.Visuals/Rendering/SceneGraph/VisualNode.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/Avalonia.Visuals/Rendering/SceneGraph/VisualNode.cs b/src/Avalonia.Visuals/Rendering/SceneGraph/VisualNode.cs index 3cb7e53d21..427f819200 100644 --- a/src/Avalonia.Visuals/Rendering/SceneGraph/VisualNode.cs +++ b/src/Avalonia.Visuals/Rendering/SceneGraph/VisualNode.cs @@ -148,7 +148,10 @@ namespace Avalonia.Rendering.SceneGraph EnsureChildrenCreated(); var old = _children[index]; _children[index] = node; - old.Dispose(); + if (node != old) + { + old.Dispose(); + } } /// @@ -329,7 +332,7 @@ namespace Avalonia.Rendering.SceneGraph _drawOperationsCloned = false; } } - + public void Dispose() { foreach (var child in Children) From 92094473e3e08953475e5223364f27dac6bf3cfc Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Thu, 15 Feb 2018 22:00:10 +0100 Subject: [PATCH 10/18] Handle pointer down/up events in Thumb. Fixes #1372. --- src/Avalonia.Controls/Primitives/Thumb.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Avalonia.Controls/Primitives/Thumb.cs b/src/Avalonia.Controls/Primitives/Thumb.cs index da4dc63d1e..b0f9ab1f85 100644 --- a/src/Avalonia.Controls/Primitives/Thumb.cs +++ b/src/Avalonia.Controls/Primitives/Thumb.cs @@ -75,6 +75,7 @@ namespace Avalonia.Controls.Primitives protected override void OnPointerPressed(PointerPressedEventArgs e) { e.Device.Capture(this); + e.Handled = true; _lastPoint = e.GetPosition(this); var ev = new VectorEventArgs @@ -91,6 +92,7 @@ namespace Avalonia.Controls.Primitives if (_lastPoint.HasValue) { e.Device.Capture(null); + e.Handled = true; _lastPoint = null; var ev = new VectorEventArgs From 53a73df9fc6c5f7199f4c8659155f0fd896a4854 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Sun, 18 Feb 2018 00:55:41 +0100 Subject: [PATCH 11/18] Updated version. --- src/Shared/SharedAssemblyInfo.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Shared/SharedAssemblyInfo.cs b/src/Shared/SharedAssemblyInfo.cs index 548a46dde4..98047b4cc8 100644 --- a/src/Shared/SharedAssemblyInfo.cs +++ b/src/Shared/SharedAssemblyInfo.cs @@ -14,6 +14,6 @@ using System.Runtime.CompilerServices; [assembly: AssemblyTrademark("")] [assembly: NeutralResourcesLanguage("en")] -[assembly: AssemblyVersion("0.5.2")] -[assembly: AssemblyFileVersion("0.5.2")] -[assembly: AssemblyInformationalVersion("0.5.2")] +[assembly: AssemblyVersion("0.6.0")] +[assembly: AssemblyFileVersion("0.6.0")] +[assembly: AssemblyInformationalVersion("0.6.0")] From c93335e6c88760d2055f9254d349bfb866b673f3 Mon Sep 17 00:00:00 2001 From: Nikita Tsukanov Date: Sun, 18 Feb 2018 09:06:47 +0300 Subject: [PATCH 12/18] Removed NUGET_API_KEY from appveyor.yml --- appveyor.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 55e703d0d5..5fe05598af 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -5,8 +5,6 @@ configuration: environment: DOTNET_SKIP_FIRST_TIME_EXPERIENCE: 1 DOTNET_CLI_TELEMETRY_OPTOUT: 1 - NUGET_API_KEY: - secure: Xv89dlP2MSBZKhl1nrWSxqcDgCXB0HRhOd4SWQ+jRJ7QoLxQel5mLTipXM++J3G5 NUGET_API_URL: https://www.nuget.org/api/v2/package MYGET_API_KEY: secure: OtVfyN3ErqQrDTnWH2HDfJDlCiu/i4/X4wFmK3ZXXP7HmCiXYPSbTjMPwwdOxRaK From 53ff0e178c169c4bf074803f96fa6431b2f5b8b3 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Sun, 18 Feb 2018 18:17:33 +0100 Subject: [PATCH 13/18] Added failing test for #1376 --- .../TextBoxTests.cs | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/tests/Avalonia.Controls.UnitTests/TextBoxTests.cs b/tests/Avalonia.Controls.UnitTests/TextBoxTests.cs index b091f6826e..5ddc8e71e7 100644 --- a/tests/Avalonia.Controls.UnitTests/TextBoxTests.cs +++ b/tests/Avalonia.Controls.UnitTests/TextBoxTests.cs @@ -4,10 +4,12 @@ using System; using System.Reactive.Linq; using Avalonia.Controls.Presenters; +using Avalonia.Controls.Primitives; using Avalonia.Controls.Templates; using Avalonia.Data; using Avalonia.Input; using Avalonia.Markup.Xaml.Data; +using Avalonia.Media; using Avalonia.Platform; using Avalonia.UnitTests; using Moq; @@ -245,6 +247,28 @@ namespace Avalonia.Controls.UnitTests } } + [Theory] + [InlineData(new object[] { false, TextWrapping.NoWrap, ScrollBarVisibility.Hidden })] + [InlineData(new object[] { false, TextWrapping.Wrap, ScrollBarVisibility.Hidden })] + [InlineData(new object[] { true, TextWrapping.NoWrap, ScrollBarVisibility.Auto })] + [InlineData(new object[] { true, TextWrapping.Wrap, ScrollBarVisibility.Disabled })] + public void Has_Correct_Horizontal_ScrollBar_Visibility( + bool acceptsReturn, + TextWrapping wrapping, + ScrollBarVisibility expected) + { + using (UnitTestApplication.Start(Services)) + { + var target = new TextBox + { + AcceptsReturn = acceptsReturn, + TextWrapping = wrapping, + }; + + Assert.Equal(expected, ScrollViewer.GetHorizontalScrollBarVisibility(target)); + } + } + private static TestServices Services => TestServices.MockThreadingInterface.With( standardCursorFactory: Mock.Of()); From 83f795480ba8b10431b925acd58854a1430eadec Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Sun, 18 Feb 2018 18:17:41 +0100 Subject: [PATCH 14/18] Fixed #1376 --- src/Avalonia.Controls/TextBox.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Avalonia.Controls/TextBox.cs b/src/Avalonia.Controls/TextBox.cs index e939ace66d..3ec3d6ed5b 100644 --- a/src/Avalonia.Controls/TextBox.cs +++ b/src/Avalonia.Controls/TextBox.cs @@ -103,7 +103,7 @@ namespace Avalonia.Controls if (acceptsReturn) { return wrapping == TextWrapping.NoWrap ? - ScrollBarVisibility.Visible : + ScrollBarVisibility.Auto : ScrollBarVisibility.Disabled; } else From 92d171f154b4537213ce2e073039cde1188de629 Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Sun, 18 Feb 2018 12:51:49 -0600 Subject: [PATCH 15/18] VisualNodes are now owned by Scene objects, not by their parents. Add a Disposed member to make it easier to diagnose ownership bugs. --- .../Rendering/SceneGraph/IVisualNode.cs | 2 ++ .../Rendering/SceneGraph/Scene.cs | 7 +++++- .../Rendering/SceneGraph/VisualNode.cs | 22 ++++++++++--------- 3 files changed, 20 insertions(+), 11 deletions(-) diff --git a/src/Avalonia.Visuals/Rendering/SceneGraph/IVisualNode.cs b/src/Avalonia.Visuals/Rendering/SceneGraph/IVisualNode.cs index 681f00799b..1668f592ec 100644 --- a/src/Avalonia.Visuals/Rendering/SceneGraph/IVisualNode.cs +++ b/src/Avalonia.Visuals/Rendering/SceneGraph/IVisualNode.cs @@ -93,5 +93,7 @@ namespace Avalonia.Rendering.SceneGraph /// to hit test children they must be hit tested manually. /// bool HitTest(Point p); + + bool Disposed { get; } } } diff --git a/src/Avalonia.Visuals/Rendering/SceneGraph/Scene.cs b/src/Avalonia.Visuals/Rendering/SceneGraph/Scene.cs index 352d41d024..ffa0b0bcc5 100644 --- a/src/Avalonia.Visuals/Rendering/SceneGraph/Scene.cs +++ b/src/Avalonia.Visuals/Rendering/SceneGraph/Scene.cs @@ -98,7 +98,10 @@ namespace Avalonia.Rendering.SceneGraph public void Dispose() { - Root.Dispose(); + foreach (var node in _index.Values) + { + node.Dispose(); + } } /// @@ -137,6 +140,8 @@ namespace Avalonia.Rendering.SceneGraph Contract.Requires(node != null); _index.Remove(node.Visual); + + node.Dispose(); } private VisualNode Clone(VisualNode source, IVisualNode parent, Dictionary index) diff --git a/src/Avalonia.Visuals/Rendering/SceneGraph/VisualNode.cs b/src/Avalonia.Visuals/Rendering/SceneGraph/VisualNode.cs index 427f819200..3ee689b6d2 100644 --- a/src/Avalonia.Visuals/Rendering/SceneGraph/VisualNode.cs +++ b/src/Avalonia.Visuals/Rendering/SceneGraph/VisualNode.cs @@ -113,6 +113,11 @@ namespace Avalonia.Rendering.SceneGraph /// The child to add. public void AddChild(IVisualNode child) { + if (child.Disposed) + { + throw new ObjectDisposedException("Visual node for {node.Visual}"); + } + EnsureChildrenCreated(); _children.Add(child); } @@ -135,7 +140,6 @@ namespace Avalonia.Rendering.SceneGraph { EnsureChildrenCreated(); _children.Remove(child); - child.Dispose(); } /// @@ -145,13 +149,13 @@ namespace Avalonia.Rendering.SceneGraph /// The child to add. public void ReplaceChild(int index, IVisualNode node) { - EnsureChildrenCreated(); - var old = _children[index]; - _children[index] = node; - if (node != old) + if (node.Disposed) { - old.Dispose(); + throw new ObjectDisposedException("Visual node for {node.Visual}"); } + + EnsureChildrenCreated(); + _children[index] = node; } /// @@ -332,13 +336,11 @@ namespace Avalonia.Rendering.SceneGraph _drawOperationsCloned = false; } } + + public bool Disposed { get; } public void Dispose() { - foreach (var child in Children) - { - child.Dispose(); - } _drawOperationsRefCounter?.Dispose(); } From 559d389547eab8ab0548c915c22ad5105410dbe0 Mon Sep 17 00:00:00 2001 From: Nikita Tsukanov Date: Mon, 19 Feb 2018 16:09:20 +0300 Subject: [PATCH 16/18] Update readme.md --- readme.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/readme.md b/readme.md index 906c3a4b5c..6f2d7e41c6 100644 --- a/readme.md +++ b/readme.md @@ -35,9 +35,9 @@ https://ci.appveyor.com/project/AvaloniaUI/Avalonia/branch/master/artifacts ## Documentation -As mentioned above, Avalonia is still in alpha and as such there's not much documentation yet. You can take a look at the [getting started page](http://avaloniaui.net/tutorial/gettingstarted) for an overview of how to get started but probably the best thing to do for now is to already know a little bit about WPF/Silverlight/UWP/XAML and ask questions in our [Gitter room](https://gitter.im/AvaloniaUI/Avalonia). +As mentioned above, Avalonia is still in alpha and as such there's not much documentation yet. You can take a look at the [getting started page](http://avaloniaui.net/guides/quickstart) for an overview of how to get started but probably the best thing to do for now is to already know a little bit about WPF/Silverlight/UWP/XAML and ask questions in our [Gitter room](https://gitter.im/AvaloniaUI/Avalonia). -There's also a high-level [architecture document](http://avaloniaui.net/spec/architecture) that is currently a little bit out of date, and I've also started writing blog posts on Avalonia at http://grokys.github.io/. +There's also a high-level [architecture document](http://avaloniaui.net/architecture/project-structure) that is currently a little bit out of date, and I've also started writing blog posts on Avalonia at http://grokys.github.io/. Contributions are always welcome! From 91998ff678e8636f1810065c768c55e8c2f73f11 Mon Sep 17 00:00:00 2001 From: Andrey Kudashkin Date: Mon, 19 Feb 2018 21:43:09 +0300 Subject: [PATCH 17/18] Update readme.md Fidex broken links --- readme.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/readme.md b/readme.md index 6f2d7e41c6..3253ce7138 100644 --- a/readme.md +++ b/readme.md @@ -43,8 +43,8 @@ Contributions are always welcome! ## Building and Using -See the [build instructions here](http://avaloniaui.net/guidelines/build). +See the [build instructions here](http://avaloniaui.net/contributing/build). ## Contributing -Please read the [contribution guidelines](http://avaloniaui.net/guidelines/contributing) before submitting a pull request. +Please read the [contribution guidelines](http://avaloniaui.net/contributing/contributing) before submitting a pull request. From d716fa5e8e57d32503a1e2ad92db8981282e745a Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Fri, 23 Feb 2018 11:06:46 +0100 Subject: [PATCH 18/18] We're in beta now. --- readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.md b/readme.md index 3253ce7138..f074faa2c4 100644 --- a/readme.md +++ b/readme.md @@ -10,7 +10,7 @@ Avalonia is a WPF-inspired cross-platform XAML-based UI framework providing a flexible styling system and supporting a wide range of OSs: Windows (.NET Framework, .NET Core), Linux (GTK), MacOS, Android and iOS. -Avalonia is now in alpha. This means that framework is now at a stage where you can have a play and hopefully create simple applications. There's still a lot missing, and you *will* find bugs, and the API *will* change, but this represents the first time where we've made it somewhat easy to have a play and experiment with the framework. +**Avalonia is currently in beta** which means that the framework is generally usable for writing applications, but there may be some bugs and breaking changes as we continue development. | Control catalog | Desktop platforms | Mobile platforms | |---|---|---|