From 2cb3b5f9163b8232ccde9276b67a25517b24bba4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Pedro?= Date: Sun, 1 Mar 2020 23:26:06 +0000 Subject: [PATCH 001/158] Updated obsolete API usages in interfaces. --- src/Avalonia.Input/FocusManager.cs | 14 +++++++------- src/Avalonia.Input/IFocusManager.cs | 6 +++--- src/Avalonia.Input/IKeyboardDevice.cs | 2 +- src/Avalonia.Input/IKeyboardNavigationHandler.cs | 6 +++--- src/Avalonia.Input/KeyboardDevice.cs | 4 ++-- src/Avalonia.Input/KeyboardNavigationHandler.cs | 8 ++++---- .../WinForms/WinFormsAvaloniaControlHost.cs | 2 +- .../Avalonia.Win32/Input/WindowsKeyboardDevice.cs | 2 +- .../KeyboardDeviceTests.cs | 4 ++-- 9 files changed, 24 insertions(+), 24 deletions(-) diff --git a/src/Avalonia.Input/FocusManager.cs b/src/Avalonia.Input/FocusManager.cs index a9ce8ee494..85f5ffefdc 100644 --- a/src/Avalonia.Input/FocusManager.cs +++ b/src/Avalonia.Input/FocusManager.cs @@ -56,11 +56,11 @@ namespace Avalonia.Input /// /// The control to focus. /// The method by which focus was changed. - /// Any input modifiers active at the time of focus. + /// Any key modifiers active at the time of focus. public void Focus( IInputElement control, NavigationMethod method = NavigationMethod.Unspecified, - InputModifiers modifiers = InputModifiers.None) + KeyModifiers keyModifiers = KeyModifiers.None) { if (control != null) { @@ -70,7 +70,7 @@ namespace Avalonia.Input if (scope != null) { Scope = scope; - SetFocusedElement(scope, control, method, modifiers); + SetFocusedElement(scope, control, method, keyModifiers); } } else if (Current != null) @@ -98,7 +98,7 @@ namespace Avalonia.Input /// The focus scope. /// The element to focus. May be null. /// The method by which focus was changed. - /// Any input modifiers active at the time of focus. + /// Any key modifiers active at the time of focus. /// /// If the specified scope is the current then the keyboard focus /// will change. @@ -107,7 +107,7 @@ namespace Avalonia.Input IFocusScope scope, IInputElement element, NavigationMethod method = NavigationMethod.Unspecified, - InputModifiers modifiers = InputModifiers.None) + KeyModifiers keyModifiers = KeyModifiers.None) { Contract.Requires(scope != null); @@ -126,7 +126,7 @@ namespace Avalonia.Input if (Scope == scope) { - KeyboardDevice.Instance?.SetFocusedElement(element, method, modifiers); + KeyboardDevice.Instance?.SetFocusedElement(element, method, keyModifiers); } } @@ -198,7 +198,7 @@ namespace Avalonia.Input { if (element is IInputElement inputElement && CanFocus(inputElement)) { - Instance?.Focus(inputElement, NavigationMethod.Pointer, ev.InputModifiers); + Instance?.Focus(inputElement, NavigationMethod.Pointer, ev.KeyModifiers); break; } diff --git a/src/Avalonia.Input/IFocusManager.cs b/src/Avalonia.Input/IFocusManager.cs index 29a22b86b2..9d4ccab5b8 100644 --- a/src/Avalonia.Input/IFocusManager.cs +++ b/src/Avalonia.Input/IFocusManager.cs @@ -23,11 +23,11 @@ namespace Avalonia.Input /// /// The control to focus. /// The method by which focus was changed. - /// Any input modifiers active at the time of focus. + /// Any key modifiers active at the time of focus. void Focus( - IInputElement control, + IInputElement control, NavigationMethod method = NavigationMethod.Unspecified, - InputModifiers modifiers = InputModifiers.None); + KeyModifiers keyModifiers = KeyModifiers.None); /// /// Notifies the focus manager of a change in focus scope. diff --git a/src/Avalonia.Input/IKeyboardDevice.cs b/src/Avalonia.Input/IKeyboardDevice.cs index 144979523f..90e5541e22 100644 --- a/src/Avalonia.Input/IKeyboardDevice.cs +++ b/src/Avalonia.Input/IKeyboardDevice.cs @@ -66,6 +66,6 @@ namespace Avalonia.Input void SetFocusedElement( IInputElement element, NavigationMethod method, - InputModifiers modifiers); + KeyModifiers modifiers); } } diff --git a/src/Avalonia.Input/IKeyboardNavigationHandler.cs b/src/Avalonia.Input/IKeyboardNavigationHandler.cs index db3a3cf114..4c5dba09fb 100644 --- a/src/Avalonia.Input/IKeyboardNavigationHandler.cs +++ b/src/Avalonia.Input/IKeyboardNavigationHandler.cs @@ -22,10 +22,10 @@ namespace Avalonia.Input /// /// The current element. /// The direction to move. - /// Any input modifiers active at the time of focus. + /// Any key modifiers active at the time of focus. void Move( IInputElement element, NavigationDirection direction, - InputModifiers modifiers = InputModifiers.None); + KeyModifiers keyModifiers = KeyModifiers.None); } -} \ No newline at end of file +} diff --git a/src/Avalonia.Input/KeyboardDevice.cs b/src/Avalonia.Input/KeyboardDevice.cs index 9db8525591..391ed58607 100644 --- a/src/Avalonia.Input/KeyboardDevice.cs +++ b/src/Avalonia.Input/KeyboardDevice.cs @@ -38,7 +38,7 @@ namespace Avalonia.Input public void SetFocusedElement( IInputElement element, NavigationMethod method, - InputModifiers modifiers) + KeyModifiers keyModifiers) { if (element != FocusedElement) { @@ -56,7 +56,7 @@ namespace Avalonia.Input { RoutedEvent = InputElement.GotFocusEvent, NavigationMethod = method, - InputModifiers = modifiers, + KeyModifiers = keyModifiers, }); } } diff --git a/src/Avalonia.Input/KeyboardNavigationHandler.cs b/src/Avalonia.Input/KeyboardNavigationHandler.cs index aef98ddff8..36c9032e2f 100644 --- a/src/Avalonia.Input/KeyboardNavigationHandler.cs +++ b/src/Avalonia.Input/KeyboardNavigationHandler.cs @@ -94,11 +94,11 @@ namespace Avalonia.Input /// /// The current element. /// The direction to move. - /// Any input modifiers active at the time of focus. + /// Any key modifiers active at the time of focus. public void Move( IInputElement element, NavigationDirection direction, - InputModifiers modifiers = InputModifiers.None) + KeyModifiers keyModifiers = KeyModifiers.None) { Contract.Requires(element != null); @@ -109,7 +109,7 @@ namespace Avalonia.Input var method = direction == NavigationDirection.Next || direction == NavigationDirection.Previous ? NavigationMethod.Tab : NavigationMethod.Directional; - FocusManager.Instance.Focus(next, method, modifiers); + FocusManager.Instance.Focus(next, method, keyModifiers); } } @@ -126,7 +126,7 @@ namespace Avalonia.Input { var direction = (e.KeyModifiers & KeyModifiers.Shift) == 0 ? NavigationDirection.Next : NavigationDirection.Previous; - Move(current, direction, e.Modifiers); + Move(current, direction, e.KeyModifiers); e.Handled = true; } } diff --git a/src/Windows/Avalonia.Win32.Interop/WinForms/WinFormsAvaloniaControlHost.cs b/src/Windows/Avalonia.Win32.Interop/WinForms/WinFormsAvaloniaControlHost.cs index fe626f4d38..abace92f08 100644 --- a/src/Windows/Avalonia.Win32.Interop/WinForms/WinFormsAvaloniaControlHost.cs +++ b/src/Windows/Avalonia.Win32.Interop/WinForms/WinFormsAvaloniaControlHost.cs @@ -45,7 +45,7 @@ namespace Avalonia.Win32.Embedding focused = focused.VisualParent; if (focused == _root) - KeyboardDevice.Instance.SetFocusedElement(null, NavigationMethod.Unspecified, InputModifiers.None); + KeyboardDevice.Instance.SetFocusedElement(null, NavigationMethod.Unspecified, KeyModifiers.None); } private void PlatformImpl_LostFocus() diff --git a/src/Windows/Avalonia.Win32/Input/WindowsKeyboardDevice.cs b/src/Windows/Avalonia.Win32/Input/WindowsKeyboardDevice.cs index fda5483b00..6fce14dbe8 100644 --- a/src/Windows/Avalonia.Win32/Input/WindowsKeyboardDevice.cs +++ b/src/Windows/Avalonia.Win32/Input/WindowsKeyboardDevice.cs @@ -47,7 +47,7 @@ namespace Avalonia.Win32.Input public void WindowActivated(Window window) { - SetFocusedElement(window, NavigationMethod.Unspecified, InputModifiers.None); + SetFocusedElement(window, NavigationMethod.Unspecified, KeyModifiers.None); } public string StringFromVirtualKey(uint virtualKey) diff --git a/tests/Avalonia.Input.UnitTests/KeyboardDeviceTests.cs b/tests/Avalonia.Input.UnitTests/KeyboardDeviceTests.cs index 3c8e800fca..df0a077c7f 100644 --- a/tests/Avalonia.Input.UnitTests/KeyboardDeviceTests.cs +++ b/tests/Avalonia.Input.UnitTests/KeyboardDeviceTests.cs @@ -35,7 +35,7 @@ namespace Avalonia.Input.UnitTests target.SetFocusedElement( focused.Object, NavigationMethod.Unspecified, - InputModifiers.None); + KeyModifiers.None); target.ProcessRawEvent( new RawKeyEventArgs( @@ -75,7 +75,7 @@ namespace Avalonia.Input.UnitTests target.SetFocusedElement( focused.Object, NavigationMethod.Unspecified, - InputModifiers.None); + KeyModifiers.None); target.ProcessRawEvent( new RawTextInputEventArgs( From 370590f3e02964d64b6b35a3e10bf94289b7409e Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Wed, 18 Mar 2020 11:15:01 +0100 Subject: [PATCH 002/158] Add failing tests for #2838. --- .../Xaml/StyleTests.cs | 62 +++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/tests/Avalonia.Markup.Xaml.UnitTests/Xaml/StyleTests.cs b/tests/Avalonia.Markup.Xaml.UnitTests/Xaml/StyleTests.cs index f7629e5b9e..818aa29f1c 100644 --- a/tests/Avalonia.Markup.Xaml.UnitTests/Xaml/StyleTests.cs +++ b/tests/Avalonia.Markup.Xaml.UnitTests/Xaml/StyleTests.cs @@ -278,5 +278,67 @@ namespace Avalonia.Markup.Xaml.UnitTests.Xaml Assert.Equal(Colors.Red, ((ISolidColorBrush)notFoo.Background).Color); } } + + [Fact] + public void Style_Can_Use_Or_Selector_1() + { + using (UnitTestApplication.Start(TestServices.StyledWindow)) + { + var xaml = @" + + + + + + + + + +"; + var loader = new AvaloniaXamlLoader(); + var window = (Window)loader.Load(xaml); + var foo = window.FindControl("foo"); + var bar = window.FindControl("bar"); + var baz = window.FindControl("baz"); + + Assert.Equal(Brushes.Red, foo.Background); + Assert.Equal(Brushes.Red, bar.Background); + Assert.Null(baz.Background); + } + } + + [Fact] + public void Style_Can_Use_Or_Selector_2() + { + using (UnitTestApplication.Start(TestServices.StyledWindow)) + { + var xaml = @" + + + + + + + + + +"; + var loader = new AvaloniaXamlLoader(); + var window = (Window)loader.Load(xaml); + var border = window.FindControl("border"); + var canvas = window.FindControl("canvas"); + var listBox = window.FindControl("listBox"); + + Assert.Equal(Brushes.Red, border.Background); + Assert.Equal(Brushes.Red, canvas.Background); + Assert.Equal(Brushes.Red, listBox.Background); + } + } } } From 33d3a66c8621f60c8d6e2fb6bab03e00a253bf86 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Wed, 18 Mar 2020 11:21:40 +0100 Subject: [PATCH 003/158] Fix comma (or) style selector. - `Selector.Or`'s first parameter isn't a `Selector` - remove that check as I don't think it's needed anyway - Make sure last selector is added to `XamlIlOrSelectorNode` Fixes #2838 --- .../Transformers/AvaloniaXamlIlSelectorTransformer.cs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/Transformers/AvaloniaXamlIlSelectorTransformer.cs b/src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/Transformers/AvaloniaXamlIlSelectorTransformer.cs index aac07f5b6e..96d78b5092 100644 --- a/src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/Transformers/AvaloniaXamlIlSelectorTransformer.cs +++ b/src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/Transformers/AvaloniaXamlIlSelectorTransformer.cs @@ -104,6 +104,11 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers } } + if (results != null && result != null) + { + results.Add(result); + } + return results ?? result; } @@ -158,9 +163,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers protected void EmitCall(XamlIlEmitContext context, IXamlIlEmitter codeGen, Func method) { var selectors = context.Configuration.TypeSystem.GetType("Avalonia.Styling.Selectors"); - var found = selectors.FindMethod(m => m.IsStatic && m.Parameters.Count > 0 && - m.Parameters[0].FullName == "Avalonia.Styling.Selector" - && method(m)); + var found = selectors.FindMethod(m => m.IsStatic && m.Parameters.Count > 0 && method(m)); codeGen.EmitCall(found); } } From aa5c1a6ed487de0b08cf9d08294c0edf51a0c9cc Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Thu, 2 Apr 2020 19:03:13 +0200 Subject: [PATCH 004/158] Added ScrollViewer.ScrollChanged event. The API for `ScrollChangedEventArgs` is different to WPF's here, because: - Avalonia's `ScrollViewer` exposes `Extent`, `Offset` and `Viewport` as `Size`/`Vector` structs whereas WPF exposes separate `double` values for the X and Y components for each of these - The current values are not included in the event args: then can easily be read from the `sender` - UWP doesn't expose these values at all --- .../ScrollChangedEventArgs.cs | 45 ++++++++++++ src/Avalonia.Controls/ScrollViewer.cs | 49 ++++++++++++- .../ScrollViewerTests.cs | 73 ++++++++++++++++++- 3 files changed, 162 insertions(+), 5 deletions(-) create mode 100644 src/Avalonia.Controls/ScrollChangedEventArgs.cs diff --git a/src/Avalonia.Controls/ScrollChangedEventArgs.cs b/src/Avalonia.Controls/ScrollChangedEventArgs.cs new file mode 100644 index 0000000000..fed23964f5 --- /dev/null +++ b/src/Avalonia.Controls/ScrollChangedEventArgs.cs @@ -0,0 +1,45 @@ +using Avalonia.Interactivity; + +namespace Avalonia.Controls +{ + /// + /// Describes a change in scrolling state. + /// + public class ScrollChangedEventArgs : RoutedEventArgs + { + public ScrollChangedEventArgs( + Vector extentDelta, + Vector offsetDelta, + Vector viewportDelta) + : this(ScrollViewer.ScrollChangedEvent, extentDelta, offsetDelta, viewportDelta) + { + } + + public ScrollChangedEventArgs( + RoutedEvent routedEvent, + Vector extentDelta, + Vector offsetDelta, + Vector viewportDelta) + : base(routedEvent) + { + ExtentDelta = extentDelta; + OffsetDelta = offsetDelta; + ViewportDelta = viewportDelta; + } + + /// + /// Gets the change to the value of . + /// + public Vector ExtentDelta { get; } + + /// + /// Gets the change to the value of . + /// + public Vector OffsetDelta { get; } + + /// + /// Gets the change to the value of . + /// + public Vector ViewportDelta { get; } + } +} diff --git a/src/Avalonia.Controls/ScrollViewer.cs b/src/Avalonia.Controls/ScrollViewer.cs index f5881a8efe..fa95895fce 100644 --- a/src/Avalonia.Controls/ScrollViewer.cs +++ b/src/Avalonia.Controls/ScrollViewer.cs @@ -2,6 +2,7 @@ using System; using Avalonia.Controls.Presenters; using Avalonia.Controls.Primitives; using Avalonia.Input; +using Avalonia.Interactivity; namespace Avalonia.Controls { @@ -167,6 +168,14 @@ namespace Avalonia.Controls nameof(VerticalScrollBarVisibility), ScrollBarVisibility.Auto); + /// + /// Defines the event. + /// + public static readonly RoutedEvent ScrollChangedEvent = + RoutedEvent.Register( + nameof(ScrollChanged), + RoutingStrategies.Bubble); + private IDisposable _childSubscription; private ILogicalScrollable _logicalScrollable; private Size _extent; @@ -191,6 +200,15 @@ namespace Avalonia.Controls { } + /// + /// Occurs when changes are detected to the scroll position, extent, or viewport size. + /// + public event EventHandler ScrollChanged + { + add => AddHandler(ScrollChangedEvent, value); + remove => RemoveHandler(ScrollChangedEvent, value); + } + /// /// Gets the extent of the scrollable content. /// @@ -203,9 +221,11 @@ namespace Avalonia.Controls private set { + var old = _extent; + if (SetAndRaise(ExtentProperty, ref _extent, value)) { - CalculatedPropertiesChanged(); + CalculatedPropertiesChanged(extentDelta: value - old); } } } @@ -222,11 +242,13 @@ namespace Avalonia.Controls set { + var old = _offset; + value = ValidateOffset(this, value); if (SetAndRaise(OffsetProperty, ref _offset, value)) { - CalculatedPropertiesChanged(); + CalculatedPropertiesChanged(offsetDelta: value - old); } } } @@ -243,9 +265,11 @@ namespace Avalonia.Controls private set { + var old = _viewport; + if (SetAndRaise(ViewportProperty, ref _viewport, value)) { - CalculatedPropertiesChanged(); + CalculatedPropertiesChanged(viewportDelta: value - old); } } } @@ -525,7 +549,10 @@ namespace Avalonia.Controls } } - private void CalculatedPropertiesChanged() + private void CalculatedPropertiesChanged( + Size extentDelta = default, + Vector offsetDelta = default, + Size viewportDelta = default) { // Pass old values of 0 here because we don't have the old values at this point, // and it shouldn't matter as only the template uses these properies. @@ -546,6 +573,20 @@ namespace Avalonia.Controls SetAndRaise(SmallChangeProperty, ref _smallChange, s_defaultSmallChange); SetAndRaise(LargeChangeProperty, ref _largeChange, Viewport); } + + if (extentDelta != default || offsetDelta != default || viewportDelta != default) + { + using var route = BuildEventRoute(ScrollChangedEvent); + + if (route.HasHandlers) + { + var e = new ScrollChangedEventArgs( + new Vector(extentDelta.Width, extentDelta.Height), + offsetDelta, + new Vector(viewportDelta.Width, viewportDelta.Height)); + route.RaiseEvent(this, e); + } + } } protected override void OnKeyDown(KeyEventArgs e) diff --git a/tests/Avalonia.Controls.UnitTests/ScrollViewerTests.cs b/tests/Avalonia.Controls.UnitTests/ScrollViewerTests.cs index 5375a244c9..8da1e26f0d 100644 --- a/tests/Avalonia.Controls.UnitTests/ScrollViewerTests.cs +++ b/tests/Avalonia.Controls.UnitTests/ScrollViewerTests.cs @@ -4,7 +4,6 @@ using Avalonia.Controls.Presenters; using Avalonia.Controls.Primitives; using Avalonia.Controls.Templates; using Avalonia.Layout; -using Avalonia.LogicalTree; using Moq; using Xunit; @@ -147,6 +146,78 @@ namespace Avalonia.Controls.UnitTests Assert.Equal(new Size(45, 67), target.LargeChange); } + [Fact] + public void Changing_Extent_Should_Raise_ScrollChanged() + { + var target = new ScrollViewer(); + var raised = 0; + + target.SetValue(ScrollViewer.ExtentProperty, new Size(100, 100)); + target.SetValue(ScrollViewer.ViewportProperty, new Size(50, 50)); + target.Offset = new Vector(10, 10); + + target.ScrollChanged += (s, e) => + { + Assert.Equal(new Vector(11, 12), e.ExtentDelta); + Assert.Equal(default, e.OffsetDelta); + Assert.Equal(default, e.ViewportDelta); + ++raised; + }; + + target.SetValue(ScrollViewer.ExtentProperty, new Size(111, 112)); + + Assert.Equal(1, raised); + + } + + [Fact] + public void Changing_Offset_Should_Raise_ScrollChanged() + { + var target = new ScrollViewer(); + var raised = 0; + + target.SetValue(ScrollViewer.ExtentProperty, new Size(100, 100)); + target.SetValue(ScrollViewer.ViewportProperty, new Size(50, 50)); + target.Offset = new Vector(10, 10); + + target.ScrollChanged += (s, e) => + { + Assert.Equal(default, e.ExtentDelta); + Assert.Equal(new Vector(12, 14), e.OffsetDelta); + Assert.Equal(default, e.ViewportDelta); + ++raised; + }; + + target.Offset = new Vector(22, 24); + + Assert.Equal(1, raised); + + } + + [Fact] + public void Changing_Viewport_Should_Raise_ScrollChanged() + { + var target = new ScrollViewer(); + var raised = 0; + + target.SetValue(ScrollViewer.ExtentProperty, new Size(100, 100)); + target.SetValue(ScrollViewer.ViewportProperty, new Size(50, 50)); + target.Offset = new Vector(10, 10); + + target.ScrollChanged += (s, e) => + { + Assert.Equal(default, e.ExtentDelta); + Assert.Equal(default, e.OffsetDelta); + Assert.Equal(new Vector(6, 8), e.ViewportDelta); + ++raised; + }; + + target.SetValue(ScrollViewer.ViewportProperty, new Size(56, 58)); + + Assert.Equal(1, raised); + + } + private Control CreateTemplate(ScrollViewer control, INameScope scope) { return new Grid From d7ca28a443113a541769d3768747fc8641a10faa Mon Sep 17 00:00:00 2001 From: Deadpikle Date: Sun, 5 Apr 2020 11:28:54 -0400 Subject: [PATCH 005/158] Add failing test for clearing SelectedText --- .../TextBoxTests.cs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/tests/Avalonia.Controls.UnitTests/TextBoxTests.cs b/tests/Avalonia.Controls.UnitTests/TextBoxTests.cs index 7f24a57678..f47aa915c9 100644 --- a/tests/Avalonia.Controls.UnitTests/TextBoxTests.cs +++ b/tests/Avalonia.Controls.UnitTests/TextBoxTests.cs @@ -425,6 +425,24 @@ namespace Avalonia.Controls.UnitTests } } + [Fact] + public void SelectedText_CanClearText() + { + using (UnitTestApplication.Start(Services)) + { + var target = new TextBox + { + Template = CreateTemplate(), + Text = "0123" + }; + target.SelectionStart = 1; + target.SelectionEnd = 3; + target.SelectedText = ""; + + Assert.True(target.Text == "03"); + } + } + [Fact] public void CoerceCaretIndex_Doesnt_Cause_Exception_with_malformed_line_ending() { From 14b227037b929abea8878a3a8f8911186560eaaa Mon Sep 17 00:00:00 2001 From: Deadpikle Date: Sun, 5 Apr 2020 11:42:48 -0400 Subject: [PATCH 006/158] Delete selection if SelectedText = "" --- src/Avalonia.Controls/TextBox.cs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/Avalonia.Controls/TextBox.cs b/src/Avalonia.Controls/TextBox.cs index d25649f2a1..2920e3a5cf 100644 --- a/src/Avalonia.Controls/TextBox.cs +++ b/src/Avalonia.Controls/TextBox.cs @@ -283,7 +283,14 @@ namespace Avalonia.Controls } _undoRedoHelper.Snapshot(); - HandleTextInput(value); + if (value != "") + { + HandleTextInput(value); + } + else + { + DeleteSelection(); + } _undoRedoHelper.Snapshot(); } } From ab6720095469e8cc18310b307ffc01ea18b28f7f Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Mon, 6 Apr 2020 11:55:38 +0200 Subject: [PATCH 007/158] Implement finding common base type. Had to also change the unit test to use controls that all have the `Background` property in a common base type. --- .../AvaloniaXamlIlSelectorTransformer.cs | 31 +++++++++++++++++-- .../Xaml/StyleTests.cs | 14 ++++----- 2 files changed, 36 insertions(+), 9 deletions(-) diff --git a/src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/Transformers/AvaloniaXamlIlSelectorTransformer.cs b/src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/Transformers/AvaloniaXamlIlSelectorTransformer.cs index 96d78b5092..d5114244cf 100644 --- a/src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/Transformers/AvaloniaXamlIlSelectorTransformer.cs +++ b/src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/Transformers/AvaloniaXamlIlSelectorTransformer.cs @@ -311,8 +311,35 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers _selectors.Add(node); } - //TODO: actually find the type - public override IXamlIlType TargetType => _selectors.FirstOrDefault()?.TargetType; + public override IXamlIlType TargetType + { + get + { + IXamlIlType result = null; + + foreach (var selector in _selectors) + { + if (selector.TargetType == null) + { + return null; + } + else if (result == null) + { + result = selector.TargetType; + } + else + { + while (!result.IsAssignableFrom(selector.TargetType)) + { + result = result.BaseType; + } + } + } + + return result; + } + } + protected override void DoEmit(XamlIlEmitContext context, IXamlIlEmitter codeGen) { if (_selectors.Count == 0) diff --git a/tests/Avalonia.Markup.Xaml.UnitTests/Xaml/StyleTests.cs b/tests/Avalonia.Markup.Xaml.UnitTests/Xaml/StyleTests.cs index 95c5ac89e4..02f0d7072c 100644 --- a/tests/Avalonia.Markup.Xaml.UnitTests/Xaml/StyleTests.cs +++ b/tests/Avalonia.Markup.Xaml.UnitTests/Xaml/StyleTests.cs @@ -316,24 +316,24 @@ namespace Avalonia.Markup.Xaml.UnitTests.Xaml - - - + From 908eef0b0dac71748e1b46350609ad9faf842c43 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Fri, 17 Apr 2020 18:02:29 +0200 Subject: [PATCH 076/158] Added failing tests for #3796. --- .../Primitives/PopupRootTests.cs | 63 +++++++++++++++++-- .../WindowTests.cs | 26 ++++++++ .../MockWindowingPlatform.cs | 6 +- 3 files changed, 90 insertions(+), 5 deletions(-) diff --git a/tests/Avalonia.Controls.UnitTests/Primitives/PopupRootTests.cs b/tests/Avalonia.Controls.UnitTests/Primitives/PopupRootTests.cs index b03f8b8892..5ffb6027c4 100644 --- a/tests/Avalonia.Controls.UnitTests/Primitives/PopupRootTests.cs +++ b/tests/Avalonia.Controls.UnitTests/Primitives/PopupRootTests.cs @@ -2,12 +2,14 @@ using System; using System.Linq; using Avalonia.Controls.Presenters; using Avalonia.Controls.Primitives; +using Avalonia.Controls.Primitives.PopupPositioning; using Avalonia.Controls.Templates; using Avalonia.LogicalTree; using Avalonia.Platform; using Avalonia.Styling; using Avalonia.UnitTests; using Avalonia.VisualTree; +using Moq; using Xunit; namespace Avalonia.Controls.UnitTests.Primitives @@ -216,12 +218,10 @@ namespace Avalonia.Controls.UnitTests.Primitives var window = new Window(); var popupImpl = MockWindowingPlatform.CreatePopupMock(window.PlatformImpl); - popupImpl.Setup(x => x.ClientSize).Returns(new Size(400, 480)); - var child = new Canvas { Width = 400, - Height = 800, + Height = 1344, }; var target = CreateTarget(window, popupImpl.Object); @@ -229,7 +229,7 @@ namespace Avalonia.Controls.UnitTests.Primitives target.Show(); - Assert.Equal(new Size(400, 480), target.Bounds.Size); + Assert.Equal(new Size(400, 1024), target.Bounds.Size); // Issue #3784 causes this to be (0, 160) which makes no sense as Window has no // parent control to be offset against. @@ -237,6 +237,61 @@ namespace Avalonia.Controls.UnitTests.Primitives } } + [Fact] + public void MinWidth_MinHeight_Should_Be_Respected() + { + // Issue #3796 + using (UnitTestApplication.Start(TestServices.StyledWindow)) + { + var window = new Window(); + var popupImpl = MockWindowingPlatform.CreatePopupMock(window.PlatformImpl); + + var target = CreateTarget(window, popupImpl.Object); + target.MinWidth = 400; + target.MinHeight = 800; + target.Content = new Border + { + Width = 100, + Height = 100, + }; + + target.Show(); + + Assert.Equal(new Rect(0, 0, 400, 800), target.Bounds); + Assert.Equal(new Size(400, 800), target.ClientSize); + Assert.Equal(new Size(400, 800), target.PlatformImpl.ClientSize); + } + } + + [Fact] + public void Setting_Width_Should_Resize_WindowImpl() + { + // Issue #3796 + using (UnitTestApplication.Start(TestServices.StyledWindow)) + { + var window = new Window(); + var popupImpl = MockWindowingPlatform.CreatePopupMock(window.PlatformImpl); + var positioner = new Mock(); + popupImpl.Setup(x => x.PopupPositioner).Returns(positioner.Object); + + var target = CreateTarget(window, popupImpl.Object); + target.Width = 400; + target.Height = 800; + + target.Show(); + + Assert.Equal(400, target.Width); + Assert.Equal(800, target.Height); + + target.Width = 410; + target.LayoutManager.ExecuteLayoutPass(); + + positioner.Verify(x => + x.Update(It.Is(x => x.Size.Width == 410))); + Assert.Equal(410, target.Width); + } + } + private PopupRoot CreateTarget(TopLevel popupParent, IPopupImpl impl = null) { impl ??= popupParent.PlatformImpl.CreatePopup(); diff --git a/tests/Avalonia.Controls.UnitTests/WindowTests.cs b/tests/Avalonia.Controls.UnitTests/WindowTests.cs index 5382e6ea3e..1ac4d7a236 100644 --- a/tests/Avalonia.Controls.UnitTests/WindowTests.cs +++ b/tests/Avalonia.Controls.UnitTests/WindowTests.cs @@ -514,6 +514,32 @@ namespace Avalonia.Controls.UnitTests } } + [Fact] + public void Setting_Width_Should_Resize_WindowImpl() + { + // Issue #3796 + using (UnitTestApplication.Start(TestServices.StyledWindow)) + { + var target = new Window() + { + Width = 400, + Height = 800, + }; + + target.Show(); + + Assert.Equal(400, target.Width); + Assert.Equal(800, target.Height); + + target.Width = 410; + target.LayoutManager.ExecuteLayoutPass(); + + var windowImpl = Mock.Get(target.PlatformImpl); + windowImpl.Verify(x => x.Resize(new Size(410, 800))); + Assert.Equal(410, target.Width); + } + } + private IWindowImpl CreateImpl(Mock renderer) { return Mock.Of(x => diff --git a/tests/Avalonia.UnitTests/MockWindowingPlatform.cs b/tests/Avalonia.UnitTests/MockWindowingPlatform.cs index b8b7512c9e..b3e4b4edbc 100644 --- a/tests/Avalonia.UnitTests/MockWindowingPlatform.cs +++ b/tests/Avalonia.UnitTests/MockWindowingPlatform.cs @@ -66,15 +66,19 @@ namespace Avalonia.UnitTests public static Mock CreatePopupMock(IWindowBaseImpl parent) { var popupImpl = new Mock(); + var clientSize = new Size(); var positionerHelper = new ManagedPopupPositionerPopupImplHelper(parent, (pos, size, scale) => { + clientSize = size.Constrain(s_screenSize); popupImpl.Object.PositionChanged?.Invoke(pos); - popupImpl.Object.Resized?.Invoke(size); + popupImpl.Object.Resized?.Invoke(clientSize); }); var positioner = new ManagedPopupPositioner(positionerHelper); + popupImpl.SetupAllProperties(); + popupImpl.Setup(x => x.ClientSize).Returns(() => clientSize); popupImpl.Setup(x => x.Scaling).Returns(1); popupImpl.Setup(x => x.PopupPositioner).Returns(positioner); From 945054be250ca53dc2324abdd3b2c6f7c334e988 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Fri, 17 Apr 2020 18:05:41 +0200 Subject: [PATCH 077/158] Make Window and Popup respect layout properties. Had to remove syncing client size to `Width`/`Height` in `PopupRoot` bceause without the `SizeToContent` property it was impossible to tell whether its `Width`/`Height` came from a requested bound or from the actual window size. --- src/Avalonia.Controls/Primitives/PopupRoot.cs | 27 +++++++++++++++++++ src/Avalonia.Controls/Window.cs | 23 +++++++++++++--- src/Avalonia.Controls/WindowBase.cs | 2 -- 3 files changed, 47 insertions(+), 5 deletions(-) diff --git a/src/Avalonia.Controls/Primitives/PopupRoot.cs b/src/Avalonia.Controls/Primitives/PopupRoot.cs index 4546a1aadb..788fe03162 100644 --- a/src/Avalonia.Controls/Primitives/PopupRoot.cs +++ b/src/Avalonia.Controls/Primitives/PopupRoot.cs @@ -117,6 +117,33 @@ namespace Avalonia.Controls.Primitives }); } + protected override Size MeasureOverride(Size availableSize) + { + var measured = base.MeasureOverride(availableSize); + var width = measured.Width; + var height = measured.Height; + var widthCache = Width; + var heightCache = Height; + + if (!double.IsNaN(widthCache)) + { + width = widthCache; + } + + width = Math.Min(width, MaxWidth); + width = Math.Max(width, MinWidth); + + if (!double.IsNaN(heightCache)) + { + height = heightCache; + } + + height = Math.Min(height, MaxHeight); + height = Math.Max(height, MinHeight); + + return new Size(width, height); + } + protected override sealed Size ArrangeSetBounds(Size size) { using (BeginAutoSizing()) diff --git a/src/Avalonia.Controls/Window.cs b/src/Avalonia.Controls/Window.cs index dcf4e98528..b21f18a59d 100644 --- a/src/Avalonia.Controls/Window.cs +++ b/src/Avalonia.Controls/Window.cs @@ -570,8 +570,8 @@ namespace Avalonia.Controls protected override Size MeasureOverride(Size availableSize) { var sizeToContent = SizeToContent; + var constraint = availableSize; var clientSize = ClientSize; - var constraint = clientSize; if (sizeToContent.HasFlagCustom(SizeToContent.Width)) { @@ -587,12 +587,26 @@ namespace Avalonia.Controls if (!sizeToContent.HasFlagCustom(SizeToContent.Width)) { - result = result.WithWidth(clientSize.Width); + if (!double.IsInfinity(availableSize.Width)) + { + result = result.WithWidth(availableSize.Width); + } + else + { + result = result.WithWidth(clientSize.Width); + } } if (!sizeToContent.HasFlagCustom(SizeToContent.Height)) { - result = result.WithHeight(clientSize.Height); + if (!double.IsInfinity(availableSize.Height)) + { + result = result.WithHeight(availableSize.Height); + } + else + { + result = result.WithHeight(clientSize.Height); + } } return result; @@ -622,6 +636,9 @@ namespace Avalonia.Controls SizeToContent = SizeToContent.Manual; } + Width = clientSize.Width; + Height = clientSize.Height; + base.HandleResized(clientSize); } diff --git a/src/Avalonia.Controls/WindowBase.cs b/src/Avalonia.Controls/WindowBase.cs index 025dfde610..ea722f2952 100644 --- a/src/Avalonia.Controls/WindowBase.cs +++ b/src/Avalonia.Controls/WindowBase.cs @@ -224,8 +224,6 @@ namespace Avalonia.Controls /// The new client size. protected override void HandleResized(Size clientSize) { - Width = clientSize.Width; - Height = clientSize.Height; ClientSize = clientSize; LayoutManager.ExecuteLayoutPass(); Renderer?.Resized(clientSize); From ec24030bac5101139a48258957e9728d5e32e9f5 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Sat, 18 Apr 2020 14:25:10 +0200 Subject: [PATCH 078/158] Added another failing PopupRoot test. --- .../Primitives/PopupRootTests.cs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/tests/Avalonia.Controls.UnitTests/Primitives/PopupRootTests.cs b/tests/Avalonia.Controls.UnitTests/Primitives/PopupRootTests.cs index 5ffb6027c4..a61d313c8c 100644 --- a/tests/Avalonia.Controls.UnitTests/Primitives/PopupRootTests.cs +++ b/tests/Avalonia.Controls.UnitTests/Primitives/PopupRootTests.cs @@ -209,6 +209,24 @@ namespace Avalonia.Controls.UnitTests.Primitives } } + [Fact] + public void Child_Should_Be_Measured_With_MaxWidth_MaxHeight_When_Set() + { + using (UnitTestApplication.Start(TestServices.StyledWindow)) + { + var child = new ChildControl(); + var window = new Window(); + var target = CreateTarget(window); + + target.MaxWidth = 500; + target.MaxHeight = 600; + target.Content = child; + target.Show(); + + Assert.Equal(new Size(500, 600), child.MeasureSize); + } + } + [Fact] public void Should_Not_Have_Offset_On_Bounds_When_Content_Larger_Than_Max_Window_Size() { From 0d109ea996fe482ae8403b90657bc3def8fbcb74 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Sat, 18 Apr 2020 14:25:23 +0200 Subject: [PATCH 079/158] Apply all layout constraints in WindowBase. --- src/Avalonia.Controls/WindowBase.cs | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/src/Avalonia.Controls/WindowBase.cs b/src/Avalonia.Controls/WindowBase.cs index ea722f2952..bb63d1b353 100644 --- a/src/Avalonia.Controls/WindowBase.cs +++ b/src/Avalonia.Controls/WindowBase.cs @@ -244,17 +244,7 @@ namespace Avalonia.Controls ApplyStyling(); ApplyTemplate(); - var constraint = availableSize; - - if (!double.IsNaN(Width)) - { - constraint = constraint.WithWidth(Width); - } - - if (!double.IsNaN(Height)) - { - constraint = constraint.WithHeight(Height); - } + var constraint = LayoutHelper.ApplyLayoutConstraints(this, availableSize); return MeasureOverride(constraint); } From 19570abec07d20b42a2a90bd6511431fdd097376 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Sat, 18 Apr 2020 14:25:48 +0200 Subject: [PATCH 080/158] Fix calculating min/max layout size. Code ported from WPF. --- src/Avalonia.Layout/LayoutHelper.cs | 50 +++++++++++++++++++++++------ 1 file changed, 40 insertions(+), 10 deletions(-) diff --git a/src/Avalonia.Layout/LayoutHelper.cs b/src/Avalonia.Layout/LayoutHelper.cs index af7d8ee52e..2b61de00a7 100644 --- a/src/Avalonia.Layout/LayoutHelper.cs +++ b/src/Avalonia.Layout/LayoutHelper.cs @@ -1,4 +1,5 @@ using System; +using Avalonia.Utilities; using Avalonia.VisualTree; namespace Avalonia.Layout @@ -19,16 +20,11 @@ namespace Avalonia.Layout /// The control's size. public static Size ApplyLayoutConstraints(ILayoutable control, Size constraints) { - var controlWidth = control.Width; - var controlHeight = control.Height; - - double width = (controlWidth > 0) ? controlWidth : constraints.Width; - double height = (controlHeight > 0) ? controlHeight : constraints.Height; - width = Math.Min(width, control.MaxWidth); - width = Math.Max(width, control.MinWidth); - height = Math.Min(height, control.MaxHeight); - height = Math.Max(height, control.MinHeight); - return new Size(width, height); + var minmax = new MinMax(control); + + return new Size( + MathUtilities.Clamp(constraints.Width, minmax.MinWidth, minmax.MaxWidth), + MathUtilities.Clamp(constraints.Height, minmax.MinHeight, minmax.MaxHeight)); } public static Size MeasureChild(ILayoutable control, Size availableSize, Thickness padding, @@ -85,5 +81,39 @@ namespace Avalonia.Layout InnerInvalidateMeasure(control); } + + /// + /// Calculates the min and max height for a control. Ported from WPF. + /// + private readonly struct MinMax + { + public MinMax(ILayoutable e) + { + MaxHeight = e.MaxHeight; + MinHeight = e.MinHeight; + double l = e.Height; + + double height = (double.IsNaN(l) ? double.PositiveInfinity : l); + MaxHeight = Math.Max(Math.Min(height, MaxHeight), MinHeight); + + height = (double.IsNaN(l) ? 0 : l); + MinHeight = Math.Max(Math.Min(MaxHeight, height), MinHeight); + + MaxWidth = e.MaxWidth; + MinWidth = e.MinWidth; + l = e.Width; + + double width = (double.IsNaN(l) ? double.PositiveInfinity : l); + MaxWidth = Math.Max(Math.Min(width, MaxWidth), MinWidth); + + width = (double.IsNaN(l) ? 0 : l); + MinWidth = Math.Max(Math.Min(MaxWidth, width), MinWidth); + } + + public double MinWidth { get; } + public double MaxWidth { get; } + public double MinHeight { get; } + public double MaxHeight { get; } + } } } From 30975465984ea8be8e9d105587295fe4257b5ca1 Mon Sep 17 00:00:00 2001 From: Nikita Tsukanov Date: Sun, 19 Apr 2020 16:53:29 +0300 Subject: [PATCH 081/158] What the actual duck --- native/Avalonia.Native/src/OSX/menu.h | 11 +++-- native/Avalonia.Native/src/OSX/menu.mm | 57 ++++++++++++++++++-------- 2 files changed, 46 insertions(+), 22 deletions(-) diff --git a/native/Avalonia.Native/src/OSX/menu.h b/native/Avalonia.Native/src/OSX/menu.h index 3c68cc222b..cb13713a54 100644 --- a/native/Avalonia.Native/src/OSX/menu.h +++ b/native/Avalonia.Native/src/OSX/menu.h @@ -14,7 +14,8 @@ class AvnAppMenuItem; class AvnAppMenu; -@interface AvnMenu : NSMenu +@interface AvnMenu : NSMenu +- (id) initWithDelegate: (NSObject*) del; @end @interface AvnMenuItem : NSMenuItem @@ -62,9 +63,7 @@ public: FORWARD_IUNKNOWN() AvnAppMenu(); - - AvnAppMenu(AvnMenu* native); - + AvnMenu* GetNative(); virtual HRESULT InsertItem (int index, IAvnAppMenuItem* item) override; @@ -77,5 +76,9 @@ public: }; +@interface AvnMenuDelegate : NSObject +- (id) initWithParent: (AvnAppMenu*) parent; +@end + #endif diff --git a/native/Avalonia.Native/src/OSX/menu.mm b/native/Avalonia.Native/src/OSX/menu.mm index 55a6f385d8..5eed5a88e4 100644 --- a/native/Avalonia.Native/src/OSX/menu.mm +++ b/native/Avalonia.Native/src/OSX/menu.mm @@ -4,20 +4,17 @@ #include "window.h" @implementation AvnMenu -- (void)menuNeedsUpdate:(NSMenu *)menu { - printf("TEST"); + NSObject* _wtf; } - -- (void)menuWillOpen:(NSMenu *)menu +- (id) initWithDelegate: (NSObject*)del { - + self = [super init]; + self.delegate = del; + _wtf = del; + return self; } -- (void)menuDidClose:(NSMenu *)menu -{ - -} @end @implementation AvnMenuItem @@ -159,15 +156,10 @@ void AvnAppMenuItem::RaiseOnClicked() AvnAppMenu::AvnAppMenu() { - _native = [AvnMenu new]; - [_native setDelegate:_native]; + id del = [[AvnMenuDelegate alloc] initWithParent: this]; + _native = [[AvnMenu alloc] initWithDelegate: del]; } -AvnAppMenu::AvnAppMenu(AvnMenu* native) -{ - _native = native; - [_native setDelegate:_native]; -} AvnMenu* AvnAppMenu::GetNative() { @@ -214,12 +206,41 @@ HRESULT AvnAppMenu::Clear() return S_OK; } +@implementation AvnMenuDelegate +{ + ComPtr _parent; +} +- (id) initWithParent:(AvnAppMenu *)parent +{ + self = [super init]; + _parent = parent; + return self; +} +- (BOOL)menu:(NSMenu *)menu updateItem:(NSMenuItem *)item atIndex:(NSInteger)index shouldCancel:(BOOL)shouldCancel +{ + if(shouldCancel) + return NO; + return YES; +} + +- (NSInteger)numberOfItemsInMenu:(NSMenu *)menu +{ + return [menu numberOfItems]; +} + +- (void)menuNeedsUpdate:(NSMenu *)menu +{ + printf("NEEDSUPDATE\n"); +} + + +@end + extern IAvnAppMenu* CreateAppMenu() { @autoreleasepool { - id menuBar = [NSMenu new]; - return new AvnAppMenu(menuBar); + return new AvnAppMenu(); } } From df6dc0abb7e7f38561a27598a7393b7723ef3d3f Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Mon, 20 Apr 2020 16:18:58 +0200 Subject: [PATCH 082/158] Fix window sizing tests. We need to make sure the window is being measured the correct number of times to know that the measure pass is correct. --- tests/Avalonia.Controls.UnitTests/WindowTests.cs | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/tests/Avalonia.Controls.UnitTests/WindowTests.cs b/tests/Avalonia.Controls.UnitTests/WindowTests.cs index 1ac4d7a236..cf2920998a 100644 --- a/tests/Avalonia.Controls.UnitTests/WindowTests.cs +++ b/tests/Avalonia.Controls.UnitTests/WindowTests.cs @@ -352,7 +352,8 @@ namespace Avalonia.Controls.UnitTests target.Show(); - Assert.Equal(new Size(100, 50), child.MeasureSize); + Assert.Equal(1, child.MeasureSizes.Count); + Assert.Equal(new Size(100, 50), child.MeasureSizes[0]); } } @@ -373,7 +374,8 @@ namespace Avalonia.Controls.UnitTests target.Show(); - Assert.Equal(new Size(550, 450), child.MeasureSize); + Assert.Equal(1, child.MeasureSizes.Count); + Assert.Equal(new Size(550, 450), child.MeasureSizes[0]); } } @@ -393,7 +395,8 @@ namespace Avalonia.Controls.UnitTests target.Show(); - Assert.Equal(Size.Infinity, child.MeasureSize); + Assert.Equal(1, child.MeasureSizes.Count); + Assert.Equal(Size.Infinity, child.MeasureSizes[0]); } } @@ -549,11 +552,11 @@ namespace Avalonia.Controls.UnitTests private class ChildControl : Control { - public Size MeasureSize { get; private set; } + public List MeasureSizes { get; } = new List(); protected override Size MeasureOverride(Size availableSize) { - MeasureSize = availableSize; + MeasureSizes.Add(availableSize); return base.MeasureOverride(availableSize); } } From 5b5c2e44c7691c3408fb9b68ec59f9816c48c56a Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Mon, 20 Apr 2020 16:19:37 +0200 Subject: [PATCH 083/158] Fix window sizing again. We need to measure with the client size when `SizeToContent` is `Manual`. --- src/Avalonia.Controls/Window.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Avalonia.Controls/Window.cs b/src/Avalonia.Controls/Window.cs index b21f18a59d..ee596432f7 100644 --- a/src/Avalonia.Controls/Window.cs +++ b/src/Avalonia.Controls/Window.cs @@ -570,8 +570,8 @@ namespace Avalonia.Controls protected override Size MeasureOverride(Size availableSize) { var sizeToContent = SizeToContent; - var constraint = availableSize; var clientSize = ClientSize; + var constraint = clientSize; if (sizeToContent.HasFlagCustom(SizeToContent.Width)) { From 2eca7bc08a118e2a7c59f0d004e5d1cc142a80ec Mon Sep 17 00:00:00 2001 From: Nikita Tsukanov Date: Mon, 20 Apr 2020 18:18:47 +0300 Subject: [PATCH 084/158] [GTK] Use gtk_file_chooser_set_filename for open dialogs --- samples/ControlCatalog/Pages/DialogsPage.xaml.cs | 7 ++++++- src/Avalonia.X11/NativeDialogs/GtkNativeFileDialogs.cs | 8 +++++++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/samples/ControlCatalog/Pages/DialogsPage.xaml.cs b/samples/ControlCatalog/Pages/DialogsPage.xaml.cs index ba68b113e3..ba1921a185 100644 --- a/samples/ControlCatalog/Pages/DialogsPage.xaml.cs +++ b/samples/ControlCatalog/Pages/DialogsPage.xaml.cs @@ -1,4 +1,7 @@ +using System; using System.Collections.Generic; +using System.Linq; +using System.Reflection; using Avalonia.Controls; using Avalonia.Markup.Xaml; #pragma warning disable 4014 @@ -34,7 +37,9 @@ namespace ControlCatalog.Pages new OpenFileDialog() { Title = "Open file", - Filters = GetFilters() + Filters = GetFilters(), + // Almost guaranteed to exist + InitialFileName = Assembly.GetEntryAssembly()?.GetModules().FirstOrDefault()?.FullyQualifiedName }.ShowAsync(GetWindow()); }; this.FindControl