Browse Source

Merge branch 'master' into xamlil

pull/2322/head
Wiesław Šoltés 7 years ago
committed by GitHub
parent
commit
a2431c0526
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 4
      samples/ControlCatalog/SideBar.xaml
  2. 2
      src/Avalonia.Controls/Presenters/CarouselPresenter.cs
  3. 10
      src/Avalonia.Themes.Default/TabItem.xaml
  4. 110
      src/Avalonia.Visuals/Media/FontFamily.cs
  5. 35
      src/Avalonia.Visuals/Media/Fonts/FamilyNameCollection.cs
  6. 2
      src/Avalonia.Visuals/Media/Fonts/FontFamilyKey.cs
  7. 6
      src/Avalonia.X11/XIStructs.cs
  8. 23
      tests/Avalonia.Controls.UnitTests/CarouselTests.cs
  9. 48
      tests/Avalonia.Visuals.UnitTests/Media/FontFamilyTests.cs
  10. 11
      tests/Avalonia.Visuals.UnitTests/Media/Fonts/FamilyNameCollectionTests.cs

4
samples/ControlCatalog/SideBar.xaml

@ -63,13 +63,13 @@
<Style Selector="TabControl.sidebar > TabItem:pointerover">
<Setter Property="Opacity" Value="1"/>
</Style>
<Style Selector="TabControl.sidebar > TabItem:pointerover /template/ ContentPresenter#PART_ContentPresenter">
<Style Selector="TabControl.sidebar > TabItem:pointerover">
<Setter Property="Background" Value="Transparent"/>
</Style>
<Style Selector="TabControl.sidebar > TabItem:selected">
<Setter Property="Opacity" Value="1"/>
</Style>
<Style Selector="TabControl.sidebar > TabItem:selected /template/ ContentPresenter#PART_ContentPresenter">
<Style Selector="TabControl.sidebar > TabItem:selected">
<Setter Property="Background" Value="{DynamicResource ThemeAccentBrush2}"/>
</Style>
</Styles>

2
src/Avalonia.Controls/Presenters/CarouselPresenter.cs

@ -210,7 +210,7 @@ namespace Avalonia.Controls.Presenters
{
var container = ItemContainerGenerator.ContainerFromIndex(index);
if (container == null)
if (container == null && IsVirtualized)
{
var item = Items.Cast<object>().ElementAt(index);
var materialized = ItemContainerGenerator.Materialize(index, item, MemberSelector);

10
src/Avalonia.Themes.Default/TabItem.xaml

@ -24,19 +24,19 @@
<Style Selector="TabItem:disabled">
<Setter Property="Opacity" Value="{DynamicResource ThemeDisabledOpacity}"/>
</Style>
<Style Selector="TabItem:pointerover /template/ ContentPresenter#PART_ContentPresenter">
<Style Selector="TabItem:pointerover">
<Setter Property="Background" Value="{DynamicResource ThemeControlHighlightMidBrush}"/>
</Style>
<Style Selector="TabItem:selected /template/ ContentPresenter#PART_ContentPresenter">
<Style Selector="TabItem:selected">
<Setter Property="Background" Value="{DynamicResource ThemeAccentBrush4}"/>
</Style>
<Style Selector="TabItem:selected:focus /template/ ContentPresenter#PART_ContentPresenter">
<Style Selector="TabItem:selected:focus">
<Setter Property="Background" Value="{DynamicResource ThemeAccentBrush3}"/>
</Style>
<Style Selector="TabItem:selected:pointerover /template/ ContentPresenter#PART_ContentPresenter">
<Style Selector="TabItem:selected:pointerover">
<Setter Property="Background" Value="{DynamicResource ThemeAccentBrush3}"/>
</Style>
<Style Selector="TabItem:selected:focus:pointerover /template/ ContentPresenter#PART_ContentPresenter">
<Style Selector="TabItem:selected:focus:pointerover">
<Setter Property="Background" Value="{DynamicResource ThemeAccentBrush2}"/>
</Style>
<Style Selector="TabItem[TabStripPlacement=Right]">

110
src/Avalonia.Visuals/Media/FontFamily.cs

@ -11,46 +11,49 @@ namespace Avalonia.Media
{
public class FontFamily
{
/// <inheritdoc />
/// <summary>
/// Initializes a new instance of the <see cref="T:Avalonia.Media.FontFamily" /> class.
/// </summary>
/// <param name="name">The name of the <see cref="FontFamily"/>.</param>
/// <exception cref="T:System.ArgumentNullException">name</exception>
public FontFamily(string name)
/// <param name="name">The name of the <see cref="T:Avalonia.Media.FontFamily" />.</param>
public FontFamily(string name) : this(null, name)
{
Contract.Requires<ArgumentNullException>(name != null);
FamilyNames = new FamilyNameCollection(new[] { name });
}
/// <summary>
/// Initializes a new instance of the <see cref="T:Avalonia.Media.FontFamily" /> class.
/// </summary>
/// <param name="names">The names of the <see cref="FontFamily"/>.</param>
/// <exception cref="T:System.ArgumentNullException">name</exception>
public FontFamily(IEnumerable<string> names)
/// <param name="baseUri">Specifies the base uri that is used to resolve font family assets.</param>
/// <param name="name">The name of the <see cref="T:Avalonia.Media.FontFamily" />.</param>
/// <exception cref="T:System.ArgumentException">Base uri must be an absolute uri.</exception>
public FontFamily(Uri baseUri, string name)
{
Contract.Requires<ArgumentNullException>(names != null);
if (string.IsNullOrEmpty(name))
{
FamilyNames = new FamilyNameCollection(string.Empty);
FamilyNames = new FamilyNameCollection(names);
}
return;
}
/// <inheritdoc />
/// <summary>
/// Initializes a new instance of the <see cref="T:Avalonia.Media.FontFamily" /> class.
/// </summary>
/// <param name="name">The name of the <see cref="T:Avalonia.Media.FontFamily" />.</param>
/// <param name="source">The source of font resources.</param>
/// <param name="baseUri"></param>
public FontFamily(string name, Uri source, Uri baseUri = null) : this(name)
{
Key = new FontFamilyKey(source, baseUri);
var fontFamilySegment = GetFontFamilyIdentifier(name);
if (fontFamilySegment.Source != null)
{
if (baseUri != null && !baseUri.IsAbsoluteUri)
{
throw new ArgumentException("Base uri must be an absolute uri.", nameof(baseUri));
}
Key = new FontFamilyKey(fontFamilySegment.Source, baseUri);
}
FamilyNames = new FamilyNameCollection(fontFamilySegment.Name);
}
/// <summary>
/// Represents the default font family
/// </summary>
public static FontFamily Default => new FontFamily(String.Empty);
public static FontFamily Default => new FontFamily(string.Empty);
/// <summary>
/// Represents all font families in the system. This can be an expensive call depending on platform implementation.
@ -88,46 +91,40 @@ namespace Avalonia.Media
/// <param name="s"></param>
public static implicit operator FontFamily(string s)
{
return Parse(s);
return new FontFamily(s);
}
/// <summary>
/// Parses a <see cref="T:Avalonia.Media.FontFamily"/> string.
/// </summary>
/// <param name="s">The <see cref="T:Avalonia.Media.FontFamily"/> string.</param>
/// <param name="baseUri"></param>
/// <returns></returns>
/// <exception cref="ArgumentException">
/// Specified family is not supported.
/// </exception>
public static FontFamily Parse(string s, Uri baseUri = null)
private struct FontFamilyIdentifier
{
if (string.IsNullOrEmpty(s))
public FontFamilyIdentifier(string name, Uri source)
{
throw new ArgumentException("Specified family is not supported.");
Name = name;
Source = source;
}
var segments = s.Split('#');
public string Name { get; }
public Uri Source { get; }
}
private static FontFamilyIdentifier GetFontFamilyIdentifier(string name)
{
var segments = name.Split('#');
switch (segments.Length)
{
case 1:
{
var names = segments[0].Split(',')
.Select(x => x.Trim())
.Where(x => !string.IsNullOrWhiteSpace(x));
return new FontFamily(names);
return new FontFamilyIdentifier(segments[0], null);
}
case 2:
{
var uri = segments[0].StartsWith("/")
? new Uri(segments[0], UriKind.Relative)
: new Uri(segments[0], UriKind.RelativeOrAbsolute);
var source = segments[0].StartsWith("/")
? new Uri(segments[0], UriKind.Relative)
: new Uri(segments[0], UriKind.RelativeOrAbsolute);
return uri.IsAbsoluteUri
? new FontFamily(segments[1], uri)
: new FontFamily(segments[1], uri, baseUri);
return new FontFamilyIdentifier(segments[1], source);
}
default:
@ -137,6 +134,25 @@ namespace Avalonia.Media
}
}
/// <summary>
/// Parses a <see cref="T:Avalonia.Media.FontFamily"/> string.
/// </summary>
/// <param name="s">The <see cref="T:Avalonia.Media.FontFamily"/> string.</param>
/// <param name="baseUri">Specifies the base uri that is used to resolve font family assets.</param>
/// <returns></returns>
/// <exception cref="ArgumentException">
/// Specified family is not supported.
/// </exception>
public static FontFamily Parse(string s, Uri baseUri = null)
{
if (string.IsNullOrEmpty(s))
{
throw new ArgumentException("Specified family is not supported.", nameof(s));
}
return new FontFamily(baseUri, s);
}
/// <summary>
/// Returns a <see cref="string" /> that represents this instance.
/// </summary>

35
src/Avalonia.Visuals/Media/Fonts/FamilyNameCollection.cs

@ -4,31 +4,28 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
namespace Avalonia.Media.Fonts
{
using System.Text;
public class FamilyNameCollection : IEnumerable<string>
{
{
/// <summary>
/// Initializes a new instance of the <see cref="FamilyNameCollection"/> class.
/// </summary>
/// <param name="familyNames">The family names.</param>
/// <exception cref="ArgumentException">familyNames</exception>
public FamilyNameCollection(IEnumerable<string> familyNames)
public FamilyNameCollection(string familyNames)
{
Contract.Requires<ArgumentNullException>(familyNames != null);
var names = new List<string>(familyNames);
if (names.Count == 0) throw new ArgumentException($"{nameof(familyNames)} must not be empty.");
if (familyNames == null)
{
throw new ArgumentNullException(nameof(familyNames));
}
Names = new ReadOnlyCollection<string>(names);
Names = familyNames.Split(',').Select(x => x.Trim()).ToArray();
PrimaryFamilyName = Names.First();
PrimaryFamilyName = Names[0];
HasFallbacks = Names.Count > 1;
}
@ -55,7 +52,7 @@ namespace Avalonia.Media.Fonts
/// <value>
/// The names.
/// </value>
internal ReadOnlyCollection<string> Names { get; }
internal IReadOnlyList<string> Names { get; }
/// <inheritdoc />
/// <summary>
@ -95,7 +92,10 @@ namespace Avalonia.Media.Fonts
{
builder.Append(Names[index]);
if (index == Names.Count - 1) break;
if (index == Names.Count - 1)
{
break;
}
builder.Append(", ");
}
@ -123,9 +123,12 @@ namespace Avalonia.Media.Fonts
/// </returns>
public override bool Equals(object obj)
{
if (!(obj is FamilyNameCollection other)) return false;
if (!(obj is FamilyNameCollection other))
{
return false;
}
return other.ToString().Equals(ToString());
}
}
}
}

2
src/Avalonia.Visuals/Media/Fonts/FontFamilyKey.cs

@ -95,7 +95,7 @@ namespace Avalonia.Media.Fonts
{
if (!Source.IsAbsoluteUri && BaseUri != null)
{
return BaseUri.Authority + Source;
return BaseUri.AbsoluteUri + Source.OriginalString;
}
return Source.ToString();

6
src/Avalonia.X11/XIStructs.cs

@ -197,7 +197,7 @@ namespace Avalonia.X11
unsafe struct XIDeviceChangedEvent
{
public int Type; /* GenericEvent */
public ulong Serial; /* # of last request processed by server */
public UIntPtr Serial; /* # of last request processed by server */
public Bool SendEvent; /* true if this came from a SendEvent request */
public IntPtr Display; /* Display the event was read from */
public int Extension; /* XI extension offset */
@ -214,7 +214,7 @@ namespace Avalonia.X11
struct XIDeviceEvent
{
public XEventName type; /* GenericEvent */
public ulong serial; /* # of last request processed by server */
public UIntPtr serial; /* # of last request processed by server */
public Bool send_event; /* true if this came from a SendEvent request */
public IntPtr display; /* Display the event was read from */
public int extension; /* XI extension offset */
@ -241,7 +241,7 @@ namespace Avalonia.X11
unsafe struct XIEvent
{
public int type; /* GenericEvent */
public ulong serial; /* # of last request processed by server */
public UIntPtr serial; /* # of last request processed by server */
public Bool send_event; /* true if this came from a SendEvent request */
public IntPtr display; /* Display the event was read from */
public int extension; /* XI extension offset */

23
tests/Avalonia.Controls.UnitTests/CarouselTests.cs

@ -152,6 +152,29 @@ namespace Avalonia.Controls.UnitTests
Assert.Equal("Bar", ((TextBlock)child).Text);
}
[Fact]
public void Selected_Item_Changes_To_First_Item_When_Item_Added()
{
var items = new ObservableCollection<string>();
var target = new Carousel
{
Template = new FuncControlTemplate<Carousel>(CreateTemplate),
Items = items,
IsVirtualized = false
};
target.ApplyTemplate();
target.Presenter.ApplyTemplate();
Assert.Equal(-1, target.SelectedIndex);
Assert.Empty(target.GetLogicalChildren());
items.Add("Foo");
Assert.Equal(0, target.SelectedIndex);
Assert.Single(target.GetLogicalChildren());
}
[Fact]
public void Selected_Index_Changes_To_When_Items_Assigned_Null()
{

48
tests/Avalonia.Visuals.UnitTests/Media/FontFamilyTests.cs

@ -2,7 +2,6 @@
// 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;
using Avalonia.Media;
using Avalonia.Media.Fonts;
@ -12,18 +11,6 @@ namespace Avalonia.Visuals.UnitTests.Media
{
public class FontFamilyTests
{
[Fact]
public void Exception_Should_Be_Thrown_If_Name_Is_Null()
{
Assert.Throws<ArgumentNullException>(() => new FontFamily((string)null));
}
[Fact]
public void Exception_Should_Be_Thrown_If_Names_Is_Null()
{
Assert.Throws<ArgumentNullException>(() => new FontFamily((IEnumerable<string>)null));
}
[Fact]
public void Should_Implicitly_Convert_String_To_FontFamily()
{
@ -41,7 +28,7 @@ namespace Avalonia.Visuals.UnitTests.Media
}
[Fact]
public void Parse_Parses_FontFamily_With_Name()
public void Should_Parse_FontFamily_With_SystemFont_Name()
{
var fontFamily = FontFamily.Parse("Courier New");
@ -49,7 +36,7 @@ namespace Avalonia.Visuals.UnitTests.Media
}
[Fact]
public void Parse_Parses_FontFamily_With_Names()
public void Should_Parse_FontFamily_With_Fallbacks()
{
var fontFamily = FontFamily.Parse("Courier New, Times New Roman");
@ -61,7 +48,7 @@ namespace Avalonia.Visuals.UnitTests.Media
}
[Fact]
public void Parse_Parses_FontFamily_With_Resource_Folder()
public void Should_Parse_FontFamily_With_Resource_Folder()
{
var source = new Uri("resm:Avalonia.Visuals.UnitTests#MyFont");
@ -75,7 +62,7 @@ namespace Avalonia.Visuals.UnitTests.Media
}
[Fact]
public void Parse_Parses_FontFamily_With_Resource_Filename()
public void Should_Parse_FontFamily_With_Resource_Filename()
{
var source = new Uri("resm:Avalonia.Visuals.UnitTests.MyFont.ttf#MyFont");
@ -87,5 +74,32 @@ namespace Avalonia.Visuals.UnitTests.Media
Assert.Equal(key, fontFamily.Key);
}
[Theory]
[InlineData("resm:Avalonia.Visuals.UnitTests/Assets/Fonts#MyFont")]
[InlineData("avares://Avalonia.Visuals.UnitTests/Assets/Fonts#MyFont")]
public void Should_Create_FontFamily_From_Uri(string name)
{
var fontFamily = new FontFamily(name);
Assert.Equal("MyFont", fontFamily.Name);
Assert.NotNull(fontFamily.Key);
}
[Theory]
[InlineData("resm:Avalonia.Visuals.UnitTests.Assets.Fonts", "#MyFont")]
[InlineData("avares://Avalonia.Visuals.UnitTests/Assets/Fonts", "#MyFont")]
[InlineData("avares://Avalonia.Visuals.UnitTests", "/Assets/Fonts#MyFont")]
public void Should_Create_FontFamily_From_Uri_With_Base_Uri(string @base, string name)
{
var baseUri = new Uri(@base);
var fontFamily = new FontFamily(baseUri, name);
Assert.Equal("MyFont", fontFamily.Name);
Assert.NotNull(fontFamily.Key);
}
}
}

11
tests/Avalonia.Visuals.UnitTests/Media/Fonts/FamilyNameCollectionTests.cs

@ -2,7 +2,6 @@
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using System;
using System.Linq;
using Avalonia.Media.Fonts;
using Xunit;
@ -16,18 +15,12 @@ namespace Avalonia.Visuals.UnitTests.Media.Fonts
Assert.Throws<ArgumentNullException>(() => new FamilyNameCollection(null));
}
[Fact]
public void Exception_Should_Be_Thrown_If_Names_Is_Empty()
{
Assert.Throws<ArgumentException>(() => new FamilyNameCollection(Enumerable.Empty<string>()));
}
[Fact]
public void Should_Be_Equal()
{
var familyNames = new FamilyNameCollection(new[] { "Arial", "Times New Roman" });
var familyNames = new FamilyNameCollection("Arial, Times New Roman");
Assert.Equal(new FamilyNameCollection(new[] { "Arial", "Times New Roman" }), familyNames);
Assert.Equal(new FamilyNameCollection("Arial, Times New Roman"), familyNames);
}
}
}

Loading…
Cancel
Save