Browse Source

Merge branch 'compiled-bindings' of https://github.com/jkoritzinsky/Avalonia into compiled-bindings

pull/2734/head
Jeremy Koritzinsky 7 years ago
parent
commit
b44cce0bd7
  1. 14
      build/NetFX.props
  2. 12
      samples/ControlCatalog/MainView.xaml
  3. 3
      src/Avalonia.Base/Utilities/WeakEventHandlerManager.cs
  4. 6
      src/Avalonia.Controls/Primitives/PopupPositioning/ManagedPopupPositioner.cs
  5. 129
      src/Avalonia.Input/KeyGesture.cs
  6. 4
      src/Avalonia.X11/X11KeyTransform.cs
  7. 4
      src/Windows/Avalonia.Win32/WindowsMountedVolumeInfoListener.cs
  8. 20
      tests/Avalonia.Base.UnitTests/WeakEventHandlerManagerTests.cs
  9. 4
      tests/Avalonia.Controls.UnitTests/Utils/HotKeyManagerTests.cs
  10. 20
      tests/Avalonia.Input.UnitTests/KeyGestureTests.cs

14
build/NetFX.props

@ -1,11 +1,7 @@
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Condition=" '$(TargetFramework)' == 'net461' and '$(OS)' == 'Unix' ">
<FrameworkPathOverride>/usr/lib/mono/4.6.1-api</FrameworkPathOverride>
<FrameworkPathOverride Condition="$([MSBuild]::IsOsPlatform('OSX'))">/Library/Frameworks/Mono.framework/Versions/Current/lib/mono/4.6.1-api</FrameworkPathOverride>
</PropertyGroup>
<PropertyGroup Condition=" '$(TargetFramework)' == 'net47' and '$(OS)' == 'Unix' ">
<FrameworkPathOverride>/usr/lib/mono/4.7-api/</FrameworkPathOverride>
<FrameworkPathOverride Condition="$([MSBuild]::IsOsPlatform('OSX'))">/Library/Frameworks/Mono.framework/Versions/Current/lib/mono/4.7-api</FrameworkPathOverride>
</PropertyGroup>
<Project>
<ItemGroup>
<PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies" Version="1.0.0-preview.2" PrivateAssets="All" />
</ItemGroup>
</Project>

12
samples/ControlCatalog/MainView.xaml

@ -24,7 +24,6 @@
<TabItem Header="CheckBox"><pages:CheckBoxPage/></TabItem>
<TabItem Header="ComboBox"><pages:ComboBoxPage/></TabItem>
<TabItem Header="ContextMenu"><pages:ContextMenuPage/></TabItem>
<!-- DataGrid is our special snowflake -->
<TabItem Header="DataGrid"
ScrollViewer.VerticalScrollBarVisibility="Disabled"
ScrollViewer.HorizontalScrollBarVisibility="Disabled">
@ -34,12 +33,15 @@
<TabItem Header="Drag+Drop"><pages:DragAndDropPage/></TabItem>
<TabItem Header="Expander"><pages:ExpanderPage/></TabItem>
<TabItem Header="Image"><pages:ImagePage/></TabItem>
<TabItem Header="ItemsRepeater"><pages:ItemsRepeaterPage/></TabItem>
<TabItem Header="ItemsRepeater"
ScrollViewer.VerticalScrollBarVisibility="Disabled">
<pages:ItemsRepeaterPage/>
</TabItem>
<TabItem Header="LayoutTransformControl"><pages:LayoutTransformControlPage/></TabItem>
<TabItem Header="ListBox"><pages:ListBoxPage/></TabItem>
<TabItem Header="Menu"><pages:MenuPage/></TabItem>
<TabItem Header="Notifications"><pages:NotificationsPage/></TabItem>
<TabItem Header="NumericUpDown"><pages:NumericUpDownPage/></TabItem>
<TabItem Header="NumericUpDown"><pages:NumericUpDownPage/></TabItem>
<TabItem Header="Pointers (Touch)"><pages:PointersPage/></TabItem>
<TabItem Header="ProgressBar"><pages:ProgressBarPage/></TabItem>
<TabItem Header="RadioButton"><pages:RadioButtonPage/></TabItem>
@ -50,12 +52,12 @@
<TabItem Header="ToolTip"><pages:ToolTipPage/></TabItem>
<TabItem Header="TreeView"><pages:TreeViewPage/></TabItem>
<TabItem Header="Viewbox"><pages:ViewboxPage/></TabItem>
<TabControl.Tag>
<TabControl.Tag>
<ComboBox x:Name="Themes" SelectedIndex="0" Width="100" Margin="8" HorizontalAlignment="Right" VerticalAlignment="Bottom">
<ComboBoxItem>Light</ComboBoxItem>
<ComboBoxItem>Dark</ComboBoxItem>
</ComboBox>
</TabControl.Tag>
</TabControl.Tag>
</TabControl>
</Grid>
</UserControl>

3
src/Avalonia.Base/Utilities/WeakEventHandlerManager.cs

@ -161,9 +161,8 @@ namespace Avalonia.Utilities
for (int c = 0; c < _count; ++c)
{
var reference = _data[c].Subscriber;
TSubscriber instance;
if (reference != null && reference.TryGetTarget(out instance) && instance == s)
if (reference != null && reference.TryGetTarget(out TSubscriber instance) && Equals(instance, s.Target))
{
_data[c] = default;
removed = true;

6
src/Avalonia.Controls/Primitives/PopupPositioning/ManagedPopupPositioner.cs

@ -100,6 +100,12 @@ namespace Avalonia.Controls.Primitives.PopupPositioning
?? screens.FirstOrDefault(s => s.Bounds.Contains(parentGeometry.TopLeft))
?? screens.FirstOrDefault(s => s.Bounds.Intersects(parentGeometry))
?? screens.FirstOrDefault();
if (targetScreen != null && targetScreen.WorkingArea.IsEmpty)
{
return targetScreen.Bounds;
}
return targetScreen?.WorkingArea
?? new Rect(0, 0, double.MaxValue, double.MaxValue);
}

129
src/Avalonia.Input/KeyGesture.cs

@ -1,41 +1,56 @@
// Copyright (c) The Avalonia Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using System;
using System.Collections.Generic;
using System.Linq;
namespace Avalonia.Input
{
/// <summary>
/// Defines a keyboard input combination.
/// </summary>
public sealed class KeyGesture : IEquatable<KeyGesture>
{
public KeyGesture()
private static readonly Dictionary<string, Key> s_keySynonyms = new Dictionary<string, Key>
{
{ "+", Key.OemPlus }, { "-", Key.OemMinus }, { ".", Key.OemPeriod }
};
[Obsolete("Use constructor taking KeyModifiers")]
public KeyGesture(Key key, InputModifiers modifiers)
{
Key = key;
KeyModifiers = (KeyModifiers)(((int)modifiers) & 0xf);
}
public KeyGesture(Key key, InputModifiers modifiers = InputModifiers.None)
public KeyGesture(Key key, KeyModifiers modifiers = KeyModifiers.None)
{
Key = key;
Modifiers = modifiers;
KeyModifiers = modifiers;
}
public bool Equals(KeyGesture other)
{
if (ReferenceEquals(null, other)) return false;
if (ReferenceEquals(this, other)) return true;
return Key == other.Key && Modifiers == other.Modifiers;
return Key == other.Key && KeyModifiers == other.KeyModifiers;
}
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
return obj is KeyGesture && Equals((KeyGesture) obj);
return obj is KeyGesture && Equals((KeyGesture)obj);
}
public override int GetHashCode()
{
unchecked
{
return ((int) Key*397) ^ (int) Modifiers;
return ((int)Key * 397) ^ (int)KeyModifiers;
}
}
@ -49,85 +64,85 @@ namespace Avalonia.Input
return !Equals(left, right);
}
public Key Key { get; set; }
public Key Key { get; }
[Obsolete("Use KeyModifiers")]
public InputModifiers Modifiers
{
get => (InputModifiers)KeyModifiers;
set => KeyModifiers = (KeyModifiers)(((int)value) & 0xf);
}
public KeyModifiers KeyModifiers { get; set; }
public InputModifiers Modifiers => (InputModifiers)KeyModifiers;
static readonly Dictionary<string, Key> KeySynonyms = new Dictionary<string, Key>
{
{"+", Key.OemPlus },
{"-", Key.OemMinus},
{".", Key.OemPeriod }
};
//TODO: Move that to external key parser
static Key ParseKey(string key)
{
Key rv;
if (KeySynonyms.TryGetValue(key.ToLower(), out rv))
return rv;
return (Key)Enum.Parse(typeof (Key), key, true);
}
static InputModifiers ParseModifier(string modifier)
{
if (modifier.Equals("ctrl", StringComparison.OrdinalIgnoreCase))
return InputModifiers.Control;
return (InputModifiers) Enum.Parse(typeof (InputModifiers), modifier, true);
}
public KeyModifiers KeyModifiers { get; }
public static KeyGesture Parse(string gesture)
{
//string.Split can't be used here because "Ctrl++" is a perfectly valid key gesture
// string.Split can't be used here because "Ctrl++" is a perfectly valid key gesture
var parts = new List<string>();
var key = Key.None;
var keyModifiers = KeyModifiers.None;
var cstart = 0;
for (var c = 0; c <= gesture.Length; c++)
{
var ch = c == gesture.Length ? '\0' : gesture[c];
if (c == gesture.Length || (ch == '+' && cstart != c))
bool isLast = c == gesture.Length;
if (isLast || (ch == '+' && cstart != c))
{
parts.Add(gesture.Substring(cstart, c - cstart));
var partSpan = gesture.AsSpan(cstart, c - cstart).Trim();
if (isLast)
{
key = ParseKey(partSpan.ToString());
}
else
{
keyModifiers |= ParseModifier(partSpan);
}
cstart = c + 1;
}
}
for (var c = 0; c < parts.Count; c++)
parts[c] = parts[c].Trim();
var rv = new KeyGesture();
for (var c = 0; c < parts.Count; c++)
{
if (c == parts.Count - 1)
rv.Key = ParseKey(parts[c]);
else
rv.Modifiers |= ParseModifier(parts[c]);
}
return rv;
return new KeyGesture(key, keyModifiers);
}
public override string ToString()
{
var parts = new List<string>();
foreach (var flag in Enum.GetValues(typeof (InputModifiers)).Cast<InputModifiers>())
foreach (var flag in Enum.GetValues(typeof(KeyModifiers)).Cast<KeyModifiers>())
{
if (Modifiers.HasFlag(flag) && flag != InputModifiers.None)
if (KeyModifiers.HasFlag(flag) && flag != KeyModifiers.None)
{
parts.Add(flag.ToString());
}
}
parts.Add(Key.ToString());
return string.Join(" + ", parts);
}
public bool Matches(KeyEventArgs keyEvent) => ResolveNumPadOperationKey(keyEvent.Key) == Key && keyEvent.Modifiers == Modifiers;
public bool Matches(KeyEventArgs keyEvent) => ResolveNumPadOperationKey(keyEvent.Key) == Key && keyEvent.KeyModifiers == KeyModifiers;
// TODO: Move that to external key parser
private static Key ParseKey(string key)
{
if (s_keySynonyms.TryGetValue(key.ToLower(), out Key rv))
return rv;
return (Key)Enum.Parse(typeof(Key), key, true);
}
private static KeyModifiers ParseModifier(ReadOnlySpan<char> modifier)
{
if (modifier.Equals("ctrl".AsSpan(), StringComparison.OrdinalIgnoreCase))
{
return KeyModifiers.Control;
}
return (KeyModifiers)Enum.Parse(typeof(KeyModifiers), modifier.ToString(), true);
}
private Key ResolveNumPadOperationKey(Key key)
{

4
src/Avalonia.X11/X11KeyTransform.cs

@ -104,8 +104,8 @@ namespace Avalonia.X11
{X11Key.x, Key.X},
{X11Key.y, Key.Y},
{X11Key.z, Key.Z},
{X11Key.Meta_L, Key.LWin },
{X11Key.Meta_R, Key.RWin },
{X11Key.Super_L, Key.LWin },
{X11Key.Super_R, Key.RWin },
{X11Key.Menu, Key.Apps},
//{ X11Key.?, Key.Sleep }
{X11Key.KP_0, Key.NumPad0},

4
src/Windows/Avalonia.Win32/WindowsMountedVolumeInfoListener.cs

@ -32,9 +32,11 @@ namespace Avalonia.Win32
var allDrives = DriveInfo.GetDrives();
var mountVolInfos = allDrives
.Where(p => p.IsReady)
.Select(p => new MountedVolumeInfo()
{
VolumeLabel = p.VolumeLabel,
VolumeLabel = string.IsNullOrEmpty(p.VolumeLabel.Trim()) ? p.RootDirectory.FullName
: $"{p.VolumeLabel} ({p.Name})",
VolumePath = p.RootDirectory.FullName,
VolumeSizeBytes = (ulong)p.TotalSize
})

20
tests/Avalonia.Base.UnitTests/WeakEventHandlerManagerTests.cs

@ -36,7 +36,7 @@ namespace Avalonia.Base.UnitTests
}
[Fact]
public void EventShoudBePassedToSubscriber()
public void EventShouldBePassedToSubscriber()
{
bool handled = false;
var subscriber = new Subscriber(() => handled = true);
@ -47,7 +47,23 @@ namespace Avalonia.Base.UnitTests
Assert.True(handled);
}
[Fact]
public void EventShouldNotBeRaisedAfterUnsubscribe()
{
bool handled = false;
var subscriber = new Subscriber(() => handled = true);
var source = new EventSource();
WeakEventHandlerManager.Subscribe<EventSource, EventArgs, Subscriber>(source, "Event",
subscriber.OnEvent);
WeakEventHandlerManager.Unsubscribe<EventArgs, Subscriber>(source, "Event",
subscriber.OnEvent);
source.Fire();
Assert.False(handled);
}
[Fact]
public void EventHandlerShouldNotBeKeptAlive()
{

4
tests/Avalonia.Controls.UnitTests/Utils/HotKeyManagerTests.cs

@ -24,8 +24,8 @@ namespace Avalonia.Controls.UnitTests.Utils
.Bind<IWindowingPlatform>().ToConstant(new WindowingPlatformMock())
.Bind<IStyler>().ToConstant(styler.Object);
var gesture1 = new KeyGesture {Key = Key.A, Modifiers = InputModifiers.Control};
var gesture2 = new KeyGesture {Key = Key.B, Modifiers = InputModifiers.Control};
var gesture1 = new KeyGesture(Key.A, InputModifiers.Control);
var gesture2 = new KeyGesture(Key.B, InputModifiers.Control);
var tl = new Window();
var button = new Button();

20
tests/Avalonia.Input.UnitTests/KeyGestureTests.cs

@ -1,8 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xunit;
namespace Avalonia.Input.UnitTests
@ -11,13 +7,11 @@ namespace Avalonia.Input.UnitTests
{
public static readonly IEnumerable<object[]> SampleData = new object[][]
{
new object[]{"Ctrl+A", new KeyGesture {Key = Key.A, Modifiers = InputModifiers.Control}},
new object[]{" \tShift\t+Alt +B", new KeyGesture {Key = Key.B, Modifiers = InputModifiers.Shift|InputModifiers.Alt} },
new object[]{"Control++", new KeyGesture {Key = Key.OemPlus, Modifiers = InputModifiers.Control} }
new object[]{"Ctrl+A", new KeyGesture(Key.A, InputModifiers.Control)},
new object[]{" \tShift\t+Alt +B", new KeyGesture(Key.B, InputModifiers.Shift | InputModifiers.Alt) },
new object[]{"Control++", new KeyGesture(Key.OemPlus, InputModifiers.Control) }
};
[Theory]
[MemberData(nameof(SampleData))]
public void Key_Gesture_Is_Able_To_Parse_Sample_Data(string text, KeyGesture gesture)
@ -31,10 +25,8 @@ namespace Avalonia.Input.UnitTests
[InlineData(Key.OemPeriod, Key.Decimal)]
public void Key_Gesture_Matches_NumPad_To_Regular_Digit(Key gestureKey, Key pressedKey)
{
var keyGesture = new KeyGesture
{
Key = gestureKey
};
var keyGesture = new KeyGesture(gestureKey);
Assert.True(keyGesture.Matches(new KeyEventArgs
{
Key = pressedKey

Loading…
Cancel
Save