Browse Source

Merge branch 'master' into datagridcolumn-sortcomparer

pull/5847/head
Dan Walmsley 6 years ago
committed by GitHub
parent
commit
2f0724acc8
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      samples/ControlCatalog/Pages/ContextMenuPage.xaml
  2. 14
      src/Avalonia.Base/Data/Optional.cs
  3. 4
      src/Avalonia.Base/PropertyStore/BindingEntry.cs
  4. 4
      src/Avalonia.Base/PropertyStore/ConstantValueEntry.cs
  5. 4
      src/Avalonia.Base/PropertyStore/LocalValueEntry.cs
  6. 4
      src/Avalonia.Base/PropertyStore/PriorityValue.cs
  7. 5
      src/Avalonia.Controls/ApiCompatBaseline.txt
  8. 6
      src/Avalonia.Controls/IMenuItem.cs
  9. 16
      src/Avalonia.Controls/MenuItem.cs
  10. 6
      src/Avalonia.Controls/Platform/DefaultMenuInteractionHandler.cs
  11. 49
      tests/Avalonia.Base.UnitTests/AvaloniaObjectTests_BatchUpdate.cs

1
samples/ControlCatalog/Pages/ContextMenuPage.xaml

@ -31,6 +31,7 @@
<CheckBox BorderThickness="0" IsHitTestVisible="False" IsChecked="True"/>
</MenuItem.Icon>
</MenuItem>
<MenuItem Header="Menu Item that won't close on click" StaysOpenOnClick="True" />
</ContextMenu>
</Border.ContextMenu>
<TextBlock Text="Defined in XAML"/>

14
src/Avalonia.Base/Data/Optional.cs

@ -153,4 +153,18 @@ namespace Avalonia.Data
/// </summary>
public static Optional<T> Empty => default;
}
public static class OptionalExtensions
{
/// <summary>
/// Casts the type of an <see cref="Optional{T}"/> using only the C# cast operator.
/// </summary>
/// <typeparam name="T">The target type.</typeparam>
/// <param name="value">The binding value.</param>
/// <returns>The cast value.</returns>
public static Optional<T> Cast<T>(this Optional<object> value)
{
return value.HasValue ? new Optional<T>((T)value.Value) : Optional<T>.Empty;
}
}
}

4
src/Avalonia.Base/PropertyStore/BindingEntry.cs

@ -127,8 +127,8 @@ namespace Avalonia.PropertyStore
sink.ValueChanged(new AvaloniaPropertyChangedEventArgs<T>(
owner,
(AvaloniaProperty<T>)property,
oldValue.GetValueOrDefault<T>(),
newValue.GetValueOrDefault<T>(),
oldValue.Cast<T>(),
newValue.Cast<T>(),
Priority));
}

4
src/Avalonia.Base/PropertyStore/ConstantValueEntry.cs

@ -65,8 +65,8 @@ namespace Avalonia.PropertyStore
sink.ValueChanged(new AvaloniaPropertyChangedEventArgs<T>(
owner,
(AvaloniaProperty<T>)property,
oldValue.GetValueOrDefault<T>(),
newValue.GetValueOrDefault<T>(),
oldValue.Cast<T>(),
newValue.Cast<T>(),
Priority));
}
}

4
src/Avalonia.Base/PropertyStore/LocalValueEntry.cs

@ -36,8 +36,8 @@ namespace Avalonia.PropertyStore
sink.ValueChanged(new AvaloniaPropertyChangedEventArgs<T>(
owner,
(AvaloniaProperty<T>)property,
oldValue.GetValueOrDefault<T>(),
newValue.GetValueOrDefault<T>(),
oldValue.Cast<T>(),
newValue.Cast<T>(),
BindingPriority.LocalValue));
}
}

4
src/Avalonia.Base/PropertyStore/PriorityValue.cs

@ -197,8 +197,8 @@ namespace Avalonia.PropertyStore
sink.ValueChanged(new AvaloniaPropertyChangedEventArgs<T>(
owner,
(AvaloniaProperty<T>)property,
oldValue.GetValueOrDefault<T>(),
newValue.GetValueOrDefault<T>(),
oldValue.Cast<T>(),
newValue.Cast<T>(),
Priority));
}

5
src/Avalonia.Controls/ApiCompatBaseline.txt

@ -1,4 +1,7 @@
Compat issues with assembly Avalonia.Controls:
InterfacesShouldHaveSameMembers : Interface member 'public System.Boolean Avalonia.Controls.IMenuItem.StaysOpenOnClick' is present in the implementation but not in the contract.
InterfacesShouldHaveSameMembers : Interface member 'public System.Boolean Avalonia.Controls.IMenuItem.StaysOpenOnClick.get()' is present in the implementation but not in the contract.
InterfacesShouldHaveSameMembers : Interface member 'public void Avalonia.Controls.IMenuItem.StaysOpenOnClick.set(System.Boolean)' is present in the implementation but not in the contract.
InterfacesShouldHaveSameMembers : Interface member 'public void Avalonia.Controls.INativeMenuExporterEventsImplBridge.RaiseClosed()' is present in the implementation but not in the contract.
InterfacesShouldHaveSameMembers : Interface member 'public void Avalonia.Controls.INativeMenuExporterEventsImplBridge.RaiseOpening()' is present in the implementation but not in the contract.
MembersMustExist : Member 'public void Avalonia.Controls.Embedding.Offscreen.OffscreenTopLevelImplBase.SetCursor(Avalonia.Platform.IPlatformHandle)' does not exist in the implementation but it does exist in the contract.
@ -7,4 +10,4 @@ EnumValuesMustMatch : Enum value 'Avalonia.Platform.ExtendClientAreaChromeHints
InterfacesShouldHaveSameMembers : Interface member 'public void Avalonia.Platform.ITopLevelImpl.SetCursor(Avalonia.Platform.ICursorImpl)' is present in the implementation but not in the contract.
InterfacesShouldHaveSameMembers : Interface member 'public void Avalonia.Platform.ITopLevelImpl.SetCursor(Avalonia.Platform.IPlatformHandle)' is present in the contract but not in the implementation.
MembersMustExist : Member 'public void Avalonia.Platform.ITopLevelImpl.SetCursor(Avalonia.Platform.IPlatformHandle)' does not exist in the implementation but it does exist in the contract.
Total Issues: 7
Total Issues: 11

6
src/Avalonia.Controls/IMenuItem.cs

@ -23,6 +23,12 @@ namespace Avalonia.Controls
/// </summary>
bool IsSubMenuOpen { get; set; }
/// <summary>
/// Gets or sets a value that indicates the submenu that this <see cref="MenuItem"/> is
/// within should not close when this item is clicked.
/// </summary>
bool StaysOpenOnClick { get; set; }
/// <summary>
/// Gets a value that indicates whether the <see cref="MenuItem"/> is a top-level main menu item.
/// </summary>

16
src/Avalonia.Controls/MenuItem.cs

@ -69,6 +69,12 @@ namespace Avalonia.Controls
public static readonly StyledProperty<bool> IsSubMenuOpenProperty =
AvaloniaProperty.Register<MenuItem, bool>(nameof(IsSubMenuOpen));
/// <summary>
/// Defines the <see cref="StaysOpenOnClick"/> property.
/// </summary>
public static readonly StyledProperty<bool> StaysOpenOnClickProperty =
AvaloniaProperty.Register<MenuItem, bool>(nameof(StaysOpenOnClick));
/// <summary>
/// Defines the <see cref="Click"/> event.
/// </summary>
@ -265,6 +271,16 @@ namespace Avalonia.Controls
set { SetValue(IsSubMenuOpenProperty, value); }
}
/// <summary>
/// Gets or sets a value that indicates the submenu that this <see cref="MenuItem"/> is
/// within should not close when this item is clicked.
/// </summary>
public bool StaysOpenOnClick
{
get { return GetValue(StaysOpenOnClickProperty); }
set { SetValue(StaysOpenOnClickProperty, value); }
}
/// <summary>
/// Gets or sets a value that indicates whether the <see cref="MenuItem"/> has a submenu.
/// </summary>

6
src/Avalonia.Controls/Platform/DefaultMenuInteractionHandler.cs

@ -449,7 +449,11 @@ namespace Avalonia.Controls.Platform
protected void Click(IMenuItem item)
{
item.RaiseClick();
CloseMenu(item);
if (!item.StaysOpenOnClick)
{
CloseMenu(item);
}
}
protected void CloseMenu(IMenuItem item)

49
tests/Avalonia.Base.UnitTests/AvaloniaObjectTests_BatchUpdate.cs

@ -5,6 +5,7 @@ using System.Reactive.Disposables;
using System.Reactive.Linq;
using System.Text;
using Avalonia.Data;
using Avalonia.Layout;
using Xunit;
namespace Avalonia.Base.UnitTests
@ -104,6 +105,25 @@ namespace Avalonia.Base.UnitTests
Assert.Equal("baz", target.Foo);
}
[Fact]
public void SetValue_Change_Should_Be_Raised_After_Batch_Update_3()
{
var target = new TestClass();
var raised = new List<AvaloniaPropertyChangedEventArgs>();
target.PropertyChanged += (s, e) => raised.Add(e);
target.BeginBatchUpdate();
target.SetValue(TestClass.BazProperty, Orientation.Horizontal, BindingPriority.LocalValue);
target.EndBatchUpdate();
Assert.Equal(1, raised.Count);
Assert.Equal(TestClass.BazProperty, raised[0].Property);
Assert.Equal(Orientation.Vertical, raised[0].OldValue);
Assert.Equal(Orientation.Horizontal, raised[0].NewValue);
Assert.Equal(Orientation.Horizontal, target.Baz);
}
[Fact]
public void SetValue_Changes_Should_Be_Raised_In_Correct_Order_After_Batch_Update()
{
@ -234,6 +254,26 @@ namespace Avalonia.Base.UnitTests
Assert.Equal("baz", raised[0].NewValue);
}
[Fact]
public void Binding_Change_Should_Be_Raised_After_Batch_Update_3()
{
var target = new TestClass();
var observable = new TestObservable<Orientation>(Orientation.Horizontal);
var raised = new List<AvaloniaPropertyChangedEventArgs>();
target.PropertyChanged += (s, e) => raised.Add(e);
target.BeginBatchUpdate();
target.Bind(TestClass.BazProperty, observable, BindingPriority.LocalValue);
target.EndBatchUpdate();
Assert.Equal(1, raised.Count);
Assert.Equal(TestClass.BazProperty, raised[0].Property);
Assert.Equal(Orientation.Vertical, raised[0].OldValue);
Assert.Equal(Orientation.Horizontal, raised[0].NewValue);
Assert.Equal(Orientation.Horizontal, target.Baz);
}
[Fact]
public void Binding_Completion_Should_Be_Raised_After_Batch_Update()
{
@ -579,6 +619,9 @@ namespace Avalonia.Base.UnitTests
public static readonly StyledProperty<string> BarProperty =
AvaloniaProperty.Register<TestClass, string>(nameof(Bar));
public static readonly StyledProperty<Orientation> BazProperty =
AvaloniaProperty.Register<TestClass, Orientation>(nameof(Bar), Orientation.Vertical);
public string Foo
{
get => GetValue(FooProperty);
@ -590,6 +633,12 @@ namespace Avalonia.Base.UnitTests
get => GetValue(BarProperty);
set => SetValue(BarProperty, value);
}
public Orientation Baz
{
get => GetValue(BazProperty);
set => SetValue(BazProperty, value);
}
}
public class TestObservable<T> : ObservableBase<BindingValue<T>>

Loading…
Cancel
Save