Merge branch 'master' into test-chop-imageex

This commit is contained in:
Michael Hawker MSFT (XAML Llama) 2021-02-12 13:41:15 -08:00 коммит произвёл GitHub
Родитель 823984142e 99f4581d33
Коммит 9d9f2532a4
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
198 изменённых файлов: 10664 добавлений и 1175 удалений

Просмотреть файл

@ -0,0 +1,97 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netstandard1.4;netstandard2.0;netstandard2.1;net5.0</TargetFrameworks>
<LangVersion>9.0</LangVersion>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<Nullable>enable</Nullable>
<Title>Windows Community Toolkit Diagnostics .NET Standard</Title>
<Description>
This package includes .NET Standard code only helpers such as:
- Guard: Helper methods to verify conditions when running code.
- ThrowHelper: Helper methods to efficiently throw exceptions.
</Description>
<PackageTags>UWP Toolkit Windows IncrementalLoadingCollection String Array extensions helpers</PackageTags>
</PropertyGroup>
<Choose>
<When Condition=" '$(TargetFramework)' == 'netstandard1.4' ">
<ItemGroup>
<!-- .NET Standard 1.4 doesn't have the Span<T> type, ValueTuple or the [Pure] attribute -->
<PackageReference Include="System.Diagnostics.Contracts" Version="4.3.0" />
<PackageReference Include="System.ValueTuple" Version="4.5.0" />
<PackageReference Include="System.Memory" Version="4.5.4" />
</ItemGroup>
</When>
<When Condition=" '$(TargetFramework)' == 'netstandard2.0' ">
<ItemGroup>
<!-- .NET Standard 2.0 doesn't have the Span<T> type -->
<PackageReference Include="System.Memory" Version="4.5.4" />
</ItemGroup>
</When>
<When Condition=" '$(TargetFramework)' == 'netstandard2.1' ">
<PropertyGroup>
<DefineConstants>NETSTANDARD2_1_OR_GREATER</DefineConstants>
</PropertyGroup>
<ItemGroup>
<!-- .NET Standard 2.1 doesn't have the Unsafe type -->
<PackageReference Include="System.Runtime.CompilerServices.Unsafe" Version="5.0.0" />
</ItemGroup>
</When>
<When Condition=" '$(TargetFramework)' == 'net5.0' ">
<PropertyGroup>
<DefineConstants>NETSTANDARD2_1_OR_GREATER</DefineConstants>
</PropertyGroup>
</When>
</Choose>
<ItemGroup>
<None Update="Generated\Guard.Comparable.Numeric.tt">
<Generator>TextTemplatingFileGenerator</Generator>
<LastGenOutput>Guard.Comparable.Numeric.g.cs</LastGenOutput>
</None>
<None Update="Generated\Guard.Collection.tt">
<Generator>TextTemplatingFileGenerator</Generator>
<LastGenOutput>Guard.Collection.g.cs</LastGenOutput>
</None>
<None Update="Generated\ThrowHelper.Collection.tt">
<Generator>TextTemplatingFileGenerator</Generator>
<LastGenOutput>ThrowHelper.Collection.g.cs</LastGenOutput>
</None>
<None Update="Generated\TypeInfo.ttinclude">
<Generator>TextTemplatingFileGenerator</Generator>
<LastGenOutput>TypeInfo.g.cs</LastGenOutput>
</None>
</ItemGroup>
<!-- T4 service used by the Guard APIs -->
<ItemGroup>
<Service Include="{508349b6-6b84-4df5-91f0-309beebad82d}" />
</ItemGroup>
<ItemGroup>
<Compile Update="Generated\Guard.Comparable.Numeric.g.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>Guard.Comparable.Numeric.tt</DependentUpon>
</Compile>
<Compile Update="Generated\Guard.Collection.g.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>Guard.Collection.tt</DependentUpon>
</Compile>
<Compile Update="Generated\ThrowHelper.Collection.g.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>ThrowHelper.Collection.tt</DependentUpon>
</Compile>
<Compile Update="Generated\TypeInfo.g.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>TypeInfo.ttinclude</DependentUpon>
</Compile>
</ItemGroup>
</Project>

Просмотреть файл

@ -11,7 +11,6 @@ using Microsoft.Toolkit.HighPerformance.Buffers.Internals;
#endif
using Microsoft.Toolkit.HighPerformance.Enumerables;
using Microsoft.Toolkit.HighPerformance.Helpers.Internals;
using Microsoft.Toolkit.HighPerformance.Memory;
using RuntimeHelpers = Microsoft.Toolkit.HighPerformance.Helpers.Internals.RuntimeHelpers;
namespace Microsoft.Toolkit.HighPerformance.Extensions

Просмотреть файл

@ -10,7 +10,6 @@ using System.Runtime.InteropServices;
using Microsoft.Toolkit.HighPerformance.Buffers.Internals;
#endif
using Microsoft.Toolkit.HighPerformance.Helpers.Internals;
using Microsoft.Toolkit.HighPerformance.Memory;
using RuntimeHelpers = Microsoft.Toolkit.HighPerformance.Helpers.Internals.RuntimeHelpers;
namespace Microsoft.Toolkit.HighPerformance.Extensions

Просмотреть файл

@ -23,7 +23,14 @@ namespace Microsoft.Toolkit.HighPerformance.Extensions
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static unsafe byte ToByte(this bool flag)
{
return *(byte*)&flag;
// Whenever we need to take the address of an argument, we make a local copy first.
// This will be removed by the JIT anyway, but it can help produce better codegen and
// remove unwanted stack spills if the caller is using constant arguments. This is
// because taking the address of an argument can interfere with some of the flow
// analysis executed by the JIT, which can in some cases block constant propagation.
bool copy = flag;
return *(byte*)&copy;
}
/// <summary>
@ -58,7 +65,8 @@ namespace Microsoft.Toolkit.HighPerformance.Extensions
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static unsafe int ToBitwiseMask32(this bool flag)
{
byte rangeFlag = *(byte*)&flag;
bool copy = flag;
byte rangeFlag = *(byte*)&copy;
int
negativeFlag = rangeFlag - 1,
mask = ~negativeFlag;
@ -77,7 +85,8 @@ namespace Microsoft.Toolkit.HighPerformance.Extensions
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static unsafe long ToBitwiseMask64(this bool flag)
{
byte rangeFlag = *(byte*)&flag;
bool copy = flag;
byte rangeFlag = *(byte*)&copy;
long
negativeFlag = (long)rangeFlag - 1,
mask = ~negativeFlag;

Просмотреть файл

@ -7,9 +7,6 @@ using System.Diagnostics.Contracts;
using System.IO;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
#if SPAN_RUNTIME_SUPPORT
using Microsoft.Toolkit.HighPerformance.Memory;
#endif
using MemoryStream = Microsoft.Toolkit.HighPerformance.Streams.MemoryStream;
namespace Microsoft.Toolkit.HighPerformance.Extensions

Просмотреть файл

@ -10,9 +10,6 @@ using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using Microsoft.Toolkit.HighPerformance.Buffers.Internals;
using Microsoft.Toolkit.HighPerformance.Buffers.Internals.Interfaces;
#if SPAN_RUNTIME_SUPPORT
using Microsoft.Toolkit.HighPerformance.Memory;
#endif
using MemoryStream = Microsoft.Toolkit.HighPerformance.Streams.MemoryStream;
namespace Microsoft.Toolkit.HighPerformance.Extensions

Просмотреть файл

@ -8,9 +8,6 @@ using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using Microsoft.Toolkit.HighPerformance.Enumerables;
using Microsoft.Toolkit.HighPerformance.Helpers.Internals;
#if SPAN_RUNTIME_SUPPORT
using Microsoft.Toolkit.HighPerformance.Memory;
#endif
namespace Microsoft.Toolkit.HighPerformance.Extensions
{

Просмотреть файл

@ -8,9 +8,6 @@ using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using Microsoft.Toolkit.HighPerformance.Enumerables;
using Microsoft.Toolkit.HighPerformance.Helpers.Internals;
#if SPAN_RUNTIME_SUPPORT
using Microsoft.Toolkit.HighPerformance.Memory;
#endif
namespace Microsoft.Toolkit.HighPerformance.Extensions
{

Просмотреть файл

@ -209,8 +209,9 @@ namespace Microsoft.Toolkit.HighPerformance.Helpers
// and perform an OR with the resulting value of the previous
// operation. This will always guaranteed to work, thanks to the
// initial code clearing that bit before setting it again.
bool copy = flag;
uint
flag32 = *(byte*)&flag,
flag32 = *(byte*)&copy,
shift = flag32 << n,
or = and | shift;
@ -378,8 +379,9 @@ namespace Microsoft.Toolkit.HighPerformance.Helpers
ulong
bit = 1ul << n,
not = ~bit,
and = value & not,
flag64 = *(byte*)&flag,
and = value & not;
bool copy = flag;
ulong flag64 = *(byte*)&copy,
shift = flag64 << n,
or = and | shift;

Просмотреть файл

@ -5,7 +5,6 @@
using System;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using Microsoft.Toolkit.HighPerformance.Memory;
namespace Microsoft.Toolkit.HighPerformance.Helpers
{

Просмотреть файл

@ -5,7 +5,6 @@
using System;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using Microsoft.Toolkit.HighPerformance.Memory;
namespace Microsoft.Toolkit.HighPerformance.Helpers
{

Просмотреть файл

@ -19,7 +19,7 @@ using static Microsoft.Toolkit.HighPerformance.Helpers.Internals.RuntimeHelpers;
#pragma warning disable CA2231
namespace Microsoft.Toolkit.HighPerformance.Memory
namespace Microsoft.Toolkit.HighPerformance
{
/// <summary>
/// <see cref="Memory2D{T}"/> represents a 2D region of arbitrary memory. It is to <see cref="Span2D{T}"/>
@ -894,7 +894,7 @@ namespace Microsoft.Toolkit.HighPerformance.Memory
/// <inheritdoc/>
public override string ToString()
{
return $"Microsoft.Toolkit.HighPerformance.Memory.Memory2D<{typeof(T)}>[{this.height}, {this.width}]";
return $"Microsoft.Toolkit.HighPerformance.Memory2D<{typeof(T)}>[{this.height}, {this.width}]";
}
/// <summary>

Просмотреть файл

@ -19,7 +19,7 @@ using static Microsoft.Toolkit.HighPerformance.Helpers.Internals.RuntimeHelpers;
#pragma warning disable CA2231
namespace Microsoft.Toolkit.HighPerformance.Memory
namespace Microsoft.Toolkit.HighPerformance
{
/// <summary>
/// A readonly version of <see cref="Memory2D{T}"/>.
@ -907,7 +907,7 @@ namespace Microsoft.Toolkit.HighPerformance.Memory
/// <inheritdoc/>
public override string ToString()
{
return $"Microsoft.Toolkit.HighPerformance.Memory.ReadOnlyMemory2D<{typeof(T)}>[{this.height}, {this.width}]";
return $"Microsoft.Toolkit.HighPerformance.ReadOnlyMemory2D<{typeof(T)}>[{this.height}, {this.width}]";
}
/// <summary>

Просмотреть файл

@ -13,7 +13,7 @@ using System.Runtime.InteropServices;
using RuntimeHelpers = Microsoft.Toolkit.HighPerformance.Helpers.Internals.RuntimeHelpers;
#endif
namespace Microsoft.Toolkit.HighPerformance.Memory
namespace Microsoft.Toolkit.HighPerformance
{
/// <inheritdoc cref="ReadOnlySpan2D{T}"/>
public readonly ref partial struct ReadOnlySpan2D<T>

Просмотреть файл

@ -17,7 +17,7 @@ using RuntimeHelpers = Microsoft.Toolkit.HighPerformance.Helpers.Internals.Runti
#pragma warning disable CS0809, CA1065
namespace Microsoft.Toolkit.HighPerformance.Memory
namespace Microsoft.Toolkit.HighPerformance
{
/// <summary>
/// A readonly version of <see cref="Span2D{T}"/>.
@ -974,7 +974,7 @@ namespace Microsoft.Toolkit.HighPerformance.Memory
/// <inheritdoc/>
public override string ToString()
{
return $"Microsoft.Toolkit.HighPerformance.Memory.ReadOnlySpan2D<{typeof(T)}>[{Height}, {this.width}]";
return $"Microsoft.Toolkit.HighPerformance.ReadOnlySpan2D<{typeof(T)}>[{Height}, {this.width}]";
}
/// <summary>

Просмотреть файл

@ -13,7 +13,7 @@ using System.Runtime.InteropServices;
using RuntimeHelpers = Microsoft.Toolkit.HighPerformance.Helpers.Internals.RuntimeHelpers;
#endif
namespace Microsoft.Toolkit.HighPerformance.Memory
namespace Microsoft.Toolkit.HighPerformance
{
/// <inheritdoc cref="Span2D{T}"/>
public readonly ref partial struct Span2D<T>

Просмотреть файл

@ -17,7 +17,7 @@ using RuntimeHelpers = Microsoft.Toolkit.HighPerformance.Helpers.Internals.Runti
#pragma warning disable CS0809, CA1065
namespace Microsoft.Toolkit.HighPerformance.Memory
namespace Microsoft.Toolkit.HighPerformance
{
/// <summary>
/// <see cref="Span2D{T}"/> represents a 2D region of arbitrary memory. Like the <see cref="Span{T}"/> type,
@ -1130,7 +1130,7 @@ namespace Microsoft.Toolkit.HighPerformance.Memory
/// <inheritdoc/>
public override string ToString()
{
return $"Microsoft.Toolkit.HighPerformance.Memory.Span2D<{typeof(T)}>[{Height}, {this.width}]";
return $"Microsoft.Toolkit.HighPerformance.Span2D<{typeof(T)}>[{Height}, {this.width}]";
}
/// <summary>

Просмотреть файл

@ -35,6 +35,11 @@
<PackageReference Include="Microsoft.NETCore.UniversalWindowsPlatform" Version="$(ExtrasUwpMetaPackageVersion)" PrivateAssets="all" IsImplicitlyDefined="true" />
</ItemGroup>
<!-- In order to support .NET Native, we need to include an appropriate .rd.xml for UWP (remove from everything else) -->
<ItemGroup Condition="'$(TargetFramework)' != 'uap10.0.19041' and '$(TargetFramework)' != 'native'">
<EmbeddedResource Remove="Properties\Microsoft.Toolkit.Uwp.Notifications.rd.xml" />
</ItemGroup>
<ItemGroup>
<None Include="Microsoft.Toolkit.Uwp.Notifications.targets" Pack="true" PackagePath="build\native" />
</ItemGroup>

Просмотреть файл

@ -0,0 +1,13 @@
<!--
This file enable reflections for Toolkit.Notifications and all of its public/private members,
enabling the library to work in .NET Native even if developers modified their default rd.xml.
See issue https://github.com/windows-toolkit/WindowsCommunityToolkit/issues/3093 for more details.
-->
<Directives xmlns="http://schemas.microsoft.com/netfx/2013/01/metadata">
<Library Name="Microsoft.Toolkit.Uwp.Notifications">
<!-- TODO: We can potentially minimize the metadata needed, but further
investigation is needed to fill this in and adequately test this -->
<Assembly Name="Microsoft.Toolkit.Uwp.Notifications" Dynamic="Required All" />
</Library>
</Directives>

Просмотреть файл

@ -112,7 +112,7 @@ namespace Microsoft.Toolkit.Uwp.Notifications
/// <returns>The current instance of <see cref="ToastContentBuilder"/></returns>
public ToastContentBuilder AddButton(IToastButton button)
{
if (button is ToastButton toastButton && toastButton.Content == null)
if (button is ToastButton toastButton && toastButton.Content == null && toastButton.NeedsContent())
{
throw new InvalidOperationException("Content is required on button.");
}

Просмотреть файл

@ -20,6 +20,17 @@ namespace Microsoft.Toolkit.Uwp.Notifications
private bool _usingCustomArguments;
private bool _usingSnoozeActivation;
private string _snoozeSelectionBoxId;
private bool _usingDismissActivation;
internal bool NeedsContent()
{
// Snooze/dismiss buttons don't need content (the system will auto-add the localized strings).
return !_usingDismissActivation && !_usingSnoozeActivation;
}
/// <summary>
/// Initializes a new instance of the <see cref="ToastButton"/> class.
/// </summary>
@ -213,6 +224,11 @@ namespace Microsoft.Toolkit.Uwp.Notifications
throw new InvalidOperationException("You cannot use the AddArgument methods when using protocol activation.");
}
if (_usingDismissActivation || _usingSnoozeActivation)
{
throw new InvalidOperationException("You cannot use the AddArgument methods when using dismiss or snooze activation.");
}
bool alreadyExists = _arguments.ContainsKey(key);
_arguments[key] = value;
@ -314,6 +330,48 @@ namespace Microsoft.Toolkit.Uwp.Notifications
return this;
}
/// <summary>
/// Configures the button to use system snooze activation when the button is clicked, using the default system snooze time.
/// </summary>
/// <returns>The current instance of <see cref="ToastButton"/></returns>
public ToastButton SetSnoozeActivation()
{
return SetSnoozeActivation(null);
}
/// <summary>
/// Configures the button to use system snooze activation when the button is clicked, with a snooze time defined by the specified selection box.
/// </summary>
/// <param name="selectionBoxId">The ID of an existing <see cref="ToastSelectionBox"/> which allows the user to pick a custom snooze time. The ID's of the <see cref="ToastSelectionBoxItem"/>s inside the selection box must represent the snooze interval in minutes. For example, if the user selects an item that has an ID of "120", then the notification will be snoozed for 2 hours. When the user clicks this button, if you specified a SelectionBoxId, the system will parse the ID of the selected item and snooze by that amount of minutes.</param>
/// <returns>The current instance of <see cref="ToastButton"/></returns>
public ToastButton SetSnoozeActivation(string selectionBoxId)
{
if (_arguments.Count > 0)
{
throw new InvalidOperationException($"{nameof(SetSnoozeActivation)} cannot be used in conjunction with ${nameof(AddArgument)}.");
}
_usingSnoozeActivation = true;
_snoozeSelectionBoxId = selectionBoxId;
return this;
}
/// <summary>
/// Configures the button to use system dismiss activation when the button is clicked (the toast will simply dismiss rather than activating).
/// </summary>
/// <returns>The current instance of <see cref="ToastButton"/></returns>
public ToastButton SetDismissActivation()
{
if (_arguments.Count > 0)
{
throw new InvalidOperationException($"{nameof(SetDismissActivation)} cannot be used in conjunction with ${nameof(AddArgument)}.");
}
_usingDismissActivation = true;
return this;
}
/// <summary>
/// Sets an identifier used in telemetry to identify your category of action. This should be something like "Delete", "Reply", or "Archive". In the upcoming toast telemetry dashboard in Dev Center, you will be able to view how frequently your actions are being clicked.
/// </summary>
@ -349,7 +407,7 @@ namespace Microsoft.Toolkit.Uwp.Notifications
internal bool CanAddArguments()
{
return ActivationType != ToastActivationType.Protocol && !_usingCustomArguments;
return ActivationType != ToastActivationType.Protocol && !_usingCustomArguments && !_usingDismissActivation && !_usingSnoozeActivation;
}
internal bool ContainsArgument(string key)
@ -362,13 +420,44 @@ namespace Microsoft.Toolkit.Uwp.Notifications
var el = new Element_ToastAction()
{
Content = Content,
Arguments = Arguments,
ActivationType = Element_Toast.ConvertActivationType(ActivationType),
ImageUri = ImageUri,
InputId = TextBoxId,
HintActionId = HintActionId
};
if (_usingSnoozeActivation)
{
el.ActivationType = Element_ToastActivationType.System;
el.Arguments = "snooze";
if (_snoozeSelectionBoxId != null)
{
el.InputId = _snoozeSelectionBoxId;
}
// Content needs to be specified as empty for auto-generated Snooze content
if (el.Content == null)
{
el.Content = string.Empty;
}
}
else if (_usingDismissActivation)
{
el.ActivationType = Element_ToastActivationType.System;
el.Arguments = "dismiss";
// Content needs to be specified as empty for auto-generated Dismiss content
if (el.Content == null)
{
el.Content = string.Empty;
}
}
else
{
el.ActivationType = Element_Toast.ConvertActivationType(ActivationType);
el.Arguments = Arguments;
}
ActivationOptions?.PopulateElement(el);
return el;

Просмотреть файл

@ -272,12 +272,14 @@
<Content Include="Icons\More.png" />
<Content Include="Icons\Notifications.png" />
<Content Include="Icons\Services.png" />
<Content Include="SamplePages\TabbedCommandBar\TabbedCommandBar.png" />
<Content Include="SamplePages\Animations\Effects\FadeBehavior.png" />
<Content Include="SamplePages\ColorPicker\ColorPicker.png" />
<Content Include="SamplePages\TilesBrush\TilesBrush.png" />
<Content Include="SamplePages\Eyedropper\Eyedropper.png" />
<Content Include="SamplePages\OnDevice\OnDevice.png" />
<Content Include="SamplePages\AcrylicBrush\AcrylicBrush.png" />
<Content Include="SamplePages\CanvasPathGeometry\CanvasPathGeometry.png" />
<Content Include="SamplePages\PipelineBrush\PipelineBrush.png" />
<Content Include="SamplePages\RemoteDeviceHelper\RemoteDeviceHelper.png" />
<Content Include="SamplePages\ImageCropper\ImageCropper.png" />
@ -496,6 +498,7 @@
<Compile Include="SamplePages\AutoFocusBehavior\AutoFocusBehaviorPage.xaml.cs">
<DependentUpon>AutoFocusBehaviorPage.xaml</DependentUpon>
</Compile>
<Compile Include="SamplePages\CanvasPathGeometry\GeometryStreamReader.cs" />
<Compile Include="SamplePages\ColorPicker\ColorPickerButtonPage.xaml.cs">
<DependentUpon>ColorPickerButtonPage.xaml</DependentUpon>
</Compile>
@ -505,6 +508,9 @@
<Compile Include="SamplePages\EnumValuesExtension\EnumValuesExtensionPage.xaml.cs">
<DependentUpon>EnumValuesExtensionPage.xaml</DependentUpon>
</Compile>
<Compile Include="SamplePages\CanvasPathGeometry\CanvasPathGeometryPage.xaml.cs">
<DependentUpon>CanvasPathGeometryPage.xaml</DependentUpon>
</Compile>
<Compile Include="SamplePages\FocusBehavior\FocusBehaviorPage.xaml.cs">
<DependentUpon>FocusBehaviorPage.xaml</DependentUpon>
</Compile>
@ -990,6 +996,13 @@
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Content Include="SamplePages\TabbedCommandBar\TabbedCommandBar.bind">
<SubType>Designer</SubType>
</Content>
<Page Include="SamplePages\CanvasPathGeometry\CanvasPathGeometryPage.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="SamplePages\TilesBrush\TilesBrushPage.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 4.5 KiB

Просмотреть файл

@ -0,0 +1,156 @@
<Page x:Class="Microsoft.Toolkit.Uwp.SampleApp.SamplePages.CanvasPathGeometryPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:win2d="using:Microsoft.Graphics.Canvas.UI.Xaml"
mc:Ignorable="d">
<Grid Padding="10">
<Grid.RowDefinitions>
<RowDefinition Height="32" />
<RowDefinition Height="48" />
<RowDefinition Height="0.1*" />
<RowDefinition Height="48" />
<RowDefinition Height="0.9*" />
</Grid.RowDefinitions>
<TextBlock Margin="12,3"
VerticalAlignment="Center"
Text="Samples: " />
<Grid Grid.Row="1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"
MinWidth="145" />
<ColumnDefinition Width="*"
MinWidth="145" />
<ColumnDefinition Width="*"
MinWidth="145" />
<ColumnDefinition Width="*"
MinWidth="145" />
<ColumnDefinition Width="*"
MinWidth="145" />
</Grid.ColumnDefinitions>
<Button Grid.Column="0"
Width="120"
Height="36"
Margin="10,3"
HorizontalAlignment="Center"
Click="{x:Bind OnShowRoundedStarSample}"
Content="Rounded Star" />
<Button Grid.Column="1"
Width="120"
Height="36"
Margin="10,3"
HorizontalAlignment="Center"
Click="{x:Bind OnShowStarSample}"
Content="Star" />
<Button Grid.Column="2"
Width="120"
Height="36"
Margin="10,3"
HorizontalAlignment="Center"
Click="{x:Bind OnShowSpiralSample}"
Content="Spiral" />
<Button Grid.Column="3"
Width="120"
Height="36"
Margin="10,3"
HorizontalAlignment="Center"
Click="{x:Bind OnShowFlowerSample}"
Content="Flower" />
<Button Grid.Column="4"
Width="120"
Height="36"
Margin="10,3"
HorizontalAlignment="Center"
Click="{x:Bind OnShowGearSample}"
Content="Gear" />
</Grid>
<TextBox x:Name="InputData"
Grid.Row="2"
Margin="10,3"
FontFamily="Courier New"
FontSize="14"
PlaceholderText="Enter SVG/XAML Path Data and press Parse. (Or click on one of the Samples from above)"
ScrollViewer.VerticalScrollBarVisibility="Auto"
SelectionHighlightColor="#007aff"
Text="{Binding InputText, Mode=TwoWay}"
TextChanged="{x:Bind OnInputTextChanged}"
TextWrapping="Wrap" />
<Button Grid.Row="3"
Width="120"
Height="36"
Margin="10,3"
HorizontalAlignment="Left"
Click="{x:Bind OnClearCanvas}"
Content="Clear" />
<Pivot x:Name="RootPivot"
Grid.Row="4">
<PivotItem Foreground="Black"
Header="Canvas">
<ScrollViewer x:Name="RenderScroll"
HorizontalScrollBarVisibility="Auto"
VerticalScrollBarVisibility="Auto">
<win2d:CanvasControl x:Name="RenderCanvas"
Width="{Binding ElementName=RenderScroll, Path=ActualWidth}"
Height="{Binding ElementName=RenderScroll, Path=ActualHeight}"
MinWidth="1200"
MinHeight="800"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
HorizontalContentAlignment="Stretch"
VerticalContentAlignment="Stretch"
ClearColor="#A7A7A7"
Draw="{x:Bind OnCanvasDraw}" />
</ScrollViewer>
</PivotItem>
<PivotItem Foreground="Black"
Header="Commands">
<ScrollViewer Background="#272727"
HorizontalScrollBarVisibility="Disabled"
VerticalScrollBarVisibility="Auto">
<TextBlock x:Name="CommandsList"
Padding="10"
FontFamily="Courier New"
FontSize="16"
Foreground="White"
IsTextSelectionEnabled="True"
SelectionHighlightColor="#007aff"
TextWrapping="Wrap" />
</ScrollViewer>
</PivotItem>
</Pivot>
<StackPanel Grid.Row="4"
HorizontalAlignment="Right"
VerticalAlignment="Top"
Orientation="Horizontal">
<TextBlock Margin="10,10,5,-10"
Text="StrokeThickness" />
<Slider x:Name="StrokeThickness"
Width="150"
Height="30"
Margin="0,4,10,4"
Background="White"
Foreground="White"
Maximum="10"
Minimum="0"
StepFrequency="0.1"
ValueChanged="{x:Bind OnStrokeThicknessChanged}" />
<TextBlock Margin="10,10,5,-10"
Text="Stroke Color: " />
<ComboBox x:Name="StrokeList"
Width="150"
Height="30"
Margin="0,4,10,4"
SelectionChanged="{x:Bind OnStrokeColorChanged}" />
<TextBlock Margin="10,10,5,-10"
Text="Fill Color: " />
<ComboBox x:Name="FillList"
Width="150"
Height="30"
Margin="0,4,10,4"
SelectionChanged="{x:Bind OnFillColorChanged}" />
</StackPanel>
</Grid>
</Page>

Просмотреть файл

@ -0,0 +1,330 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Graphics.Canvas.Geometry;
using Microsoft.Graphics.Canvas.UI.Xaml;
using Microsoft.Toolkit.Uwp.Extensions;
using Microsoft.Toolkit.Uwp.UI.Media.Geometry;
using Windows.System;
using Windows.UI;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Media;
namespace Microsoft.Toolkit.Uwp.SampleApp.SamplePages
{
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class CanvasPathGeometryPage : Page
{
private const string Sample1 =
"F0 M 656.500,400.500 C 656.500,350.637 598.572,307.493 514.292,286.708 C 493.507,202.428 450.363,144.500 400.500,144.500 C 350.637,144.500 307.493,202.428 286.708,286.708 C 202.428,307.493 144.500,350.637 144.500,400.500 C 144.500,450.363 202.428,493.507 286.708,514.292 C 307.493,598.572 350.637,656.500 400.500,656.500 C 450.363,656.500 493.507,598.572 514.292,514.292 C 598.572,493.507 656.500,450.363 656.500,400.500 ZM 581.519,219.481 C 546.261,184.222 474.793,194.676 400.500,239.574 C 326.207,194.676 254.739,184.222 219.481,219.481 C 184.222,254.739 194.676,326.207 239.574,400.500 C 194.676,474.792 184.222,546.261 219.481,581.519 C 254.739,616.778 326.207,606.324 400.500,561.426 C 474.793,606.324 546.261,616.778 581.519,581.519 C 616.778,546.261 606.324,474.792 561.426,400.500 C 606.324,326.207 616.778,254.739 581.519,219.481 ZU 112.5 112.5 570 570 36 36";
private const string Sample2 =
"F1 M 331.341,81.975 L 398.766,218.593 L 549.533,240.500 L 440.437,346.842 L 466.191,497.000 L 331.341,426.105 L 196.491,497.000 L 222.245,346.842 L 113.150,240.500 L 263.916,218.593 L 331.341,81.975 Z";
private const string Sample3 =
"F1 M 545.497,397.058 C 454.492,512.882 286.824,533.003 171.000,441.998 C 78.340,369.194 62.244,235.059 135.048,142.400 C 193.291,68.272 300.599,55.395 374.726,113.639 C 434.028,160.233 444.330,246.079 397.736,305.381 C 360.460,352.823 291.783,361.064 244.341,323.788 C 206.388,293.968 199.795,239.026 229.616,201.073 C 253.472,170.711 297.425,165.436 327.788,189.293 C 352.078,208.378 356.297,243.540 337.212,267.830 C 321.944,287.262 293.814,290.638 274.382,275.370 C 258.836,263.155 256.136,240.651 268.350,225.106 C 278.122,212.669 296.125,210.509 308.562,220.280 C 318.511,228.098 320.239,242.500 312.422,252.449";
private const string Sample4 =
"F1 M 311.717,332.110 C 285.669,332.110 264.552,310.994 264.552,284.945 C 264.552,258.897 285.669,237.781 311.717,237.781 C 337.765,237.781 358.881,258.897 358.881,284.945 C 358.881,310.994 337.765,332.110 311.717,332.110 Z M 505.712,232.846 C 634.939,203.833 411.705,171.395 371.772,213.383 C 411.705,171.395 311.872,-30.889 311.872,92.013 C 311.872,-30.889 212.038,171.395 251.972,213.383 C 212.038,171.395 -11.196,203.833 118.031,232.846 C -11.196,203.833 150.338,361.289 214.951,327.320 C 150.338,361.289 112.205,583.622 192.072,460.719 C 112.205,583.622 311.872,478.651 311.872,397.737 C 311.872,478.651 511.538,583.622 431.672,460.719 C 511.538,583.622 473.405,361.289 408.792,327.320 C 473.405,361.289 634.939,203.833 505.712,232.846 Z";
private const string Sample5 =
"F1 M 391.853,348.284 C 391.853,357.113 384.696,364.271 375.867,364.271 L 301.927,364.271 C 293.098,364.271 285.940,357.113 285.940,348.284 L 285.940,274.345 C 285.940,265.515 293.098,258.358 301.927,258.358 L 375.867,258.358 C 384.696,258.358 391.853,265.515 391.853,274.345 L 391.853,348.284 Z M 544.748,282.990 L 485.488,267.081 C 472.521,263.600 466.301,248.839 472.866,237.128 L 502.867,183.604 C 512.642,166.166 494.336,146.433 476.214,154.872 L 420.592,180.776 C 408.421,186.445 394.169,179.136 391.670,165.944 L 380.248,105.658 C 376.526,86.017 349.819,82.667 341.362,100.780 L 315.403,156.378 C 309.723,168.543 294.107,172.105 283.714,163.607 L 236.213,124.767 C 220.737,112.113 198.125,126.714 203.289,146.025 L 219.141,205.301 C 222.610,218.271 212.937,231.038 199.512,231.208 L 138.159,231.988 C 118.170,232.242 110.233,257.962 126.602,269.436 L 176.847,304.655 C 187.841,312.361 188.638,328.358 178.464,337.118 L 131.965,377.153 C 116.816,390.196 127.269,415.001 147.184,413.268 L 208.312,407.950 C 221.687,406.786 232.580,418.529 230.417,431.779 L 220.531,492.336 C 217.310,512.066 241.261,524.348 255.403,510.220 L 298.811,466.854 C 308.310,457.365 324.202,459.358 331.062,470.899 L 362.415,523.643 C 372.629,540.827 398.872,534.840 400.624,514.927 L 406.001,453.804 C 407.178,440.430 420.634,431.742 433.307,436.173 L 491.227,456.425 C 510.098,463.022 526.353,441.568 514.895,425.187 L 479.725,374.908 C 472.030,363.906 476.753,348.601 489.310,343.850 L 546.697,322.133 C 565.393,315.057 564.054,288.173 544.748,282.990 Z";
private const string ErrorString =
"F1 M 19.648,24.605 L 19.648,30.220 L 29.404,30.220 L 29.404,28.149 C 29.404,27.229 29.581,26.573 29.936,26.181 C 30.290,25.790 30.753,25.594 31.325,25.594 C 31.885,25.594 " +
"32.342,25.790 32.696,26.181 C 33.051,26.573 33.228,27.229 33.228,28.149 L 33.228,34.044 L 15.227,34.044 C 14.307,34.044 13.651,33.867 13.259,33.512 C 12.867,33.158 12.672,32.695 " +
"12.672,32.122 C 12.672,31.563 12.870,31.106 13.268,30.751 C 13.666,30.397 14.319,30.220 15.227,30.220 L 15.824,30.220 L 15.824,15.260 L 15.227,15.260 C 14.307,15.260 13.651,15.082 " +
"13.259,14.728 C 12.867,14.373 12.672,13.910 12.672,13.338 C 12.672,12.766 12.867,12.303 13.259,11.948 C 13.651,11.594 14.307,11.417 15.227,11.417 L 32.388,11.436 L 32.388,17.255 C " +
"32.388,18.163 32.214,18.813 31.866,19.205 C 31.518,19.596 31.058,19.792 30.486,19.792 C 29.914,19.792 29.451,19.600 29.096,19.214 C 28.742,18.829 28.564,18.176 28.564,17.255 L " +
"28.564,15.260 L 19.648,15.260 L 19.648,20.781 L 23.006,20.781 C 23.006,19.786 23.099,19.146 23.285,18.860 C 23.671,18.250 24.218,17.946 24.927,17.946 C 25.487,17.946 25.944,18.142 " +
"26.298,18.533 C 26.652,18.925 26.830,19.581 26.830,20.501 L 26.830,24.903 C 26.830,25.737 26.730,26.297 26.531,26.582 C 26.133,27.167 25.599,27.459 24.927,27.459 C 24.218,27.459 " +
"23.671,27.155 23.285,26.545 C 23.099,26.259 23.006,25.612 23.006,24.605 L 19.648,24.605 ZM 45.707,17.106 L 45.707,19.494 C 47.311,18.337 48.577,17.567 49.503,17.181 C 50.430,16.795 " +
"51.297,16.603 52.105,16.603 C 53.349,16.603 54.555,17.063 55.724,17.983 C 56.520,18.605 56.918,19.239 56.918,19.886 C 56.918,20.433 56.728,20.896 56.349,21.275 C 55.970,21.655 " +
"55.513,21.844 54.978,21.844 C 54.505,21.844 54.008,21.608 53.486,21.135 C 52.963,20.663 52.497,20.427 52.087,20.427 C 51.552,20.427 50.753,20.762 49.690,21.434 C 48.626,22.105 " +
"47.299,23.113 45.707,24.456 L 45.707,30.220 L 51.154,30.220 C 52.074,30.220 52.730,30.397 53.122,30.751 C 53.514,31.106 53.710,31.569 53.710,32.141 C 53.710,32.701 53.514,33.158 " +
"53.122,33.512 C 52.730,33.867 52.074,34.044 51.154,34.044 L 39.607,34.044 C 38.687,34.044 38.031,33.867 37.639,33.512 C 37.248,33.158 37.052,32.695 37.052,32.122 C 37.052,31.563 " +
"37.248,31.106 37.639,30.751 C 38.031,30.397 38.687,30.220 39.607,30.220 L 41.883,30.220 L 41.883,20.930 L 40.503,20.930 C 39.582,20.930 38.927,20.753 38.535,20.399 C 38.143,20.044 " +
"37.947,19.581 37.947,19.009 C 37.947,18.449 38.143,17.992 38.535,17.638 C 38.927,17.283 39.582,17.106 40.503,17.106 L 45.707,17.106 ZM 68.633,17.106 L 68.633,19.494 C 70.237,18.337 " +
"71.502,17.567 72.429,17.181 C 73.355,16.795 74.222,16.603 75.031,16.603 C 76.274,16.603 77.480,17.063 78.650,17.983 C 79.445,18.605 79.843,19.239 79.843,19.886 C 79.843,20.433 " +
"79.654,20.896 79.274,21.275 C 78.895,21.655 78.438,21.844 77.903,21.844 C 77.431,21.844 76.933,21.608 76.411,21.135 C 75.889,20.663 75.423,20.427 75.012,20.427 C 74.477,20.427 " +
"73.678,20.762 72.615,21.434 C 71.552,22.105 70.224,23.113 68.633,24.456 L 68.633,30.220 L 74.079,30.220 C 74.999,30.220 75.656,30.397 76.047,30.751 C 76.439,31.106 76.635,31.569 " +
"76.635,32.141 C 76.635,32.701 76.439,33.158 76.047,33.512 C 75.656,33.867 74.999,34.044 74.079,34.044 L 62.533,34.044 C 61.612,34.044 60.957,33.867 60.565,33.512 C 60.173,33.158 " +
"59.977,32.695 59.977,32.122 C 59.977,31.563 60.173,31.106 60.565,30.751 C 60.957,30.397 61.612,30.220 62.533,30.220 L 64.809,30.220 L 64.809,20.930 L 63.428,20.930 C 62.508,20.930 " +
"61.852,20.753 61.460,20.399 C 61.069,20.044 60.873,19.581 60.873,19.009 C 60.873,18.449 61.069,17.992 61.460,17.638 C 61.852,17.283 62.508,17.106 63.428,17.106 L 68.633,17.106 ZM " +
"98.460,25.911 C 98.460,24.680 98.018,23.548 97.135,22.516 C 95.929,21.123 94.343,20.427 92.379,20.427 C 90.650,20.427 89.208,20.980 88.051,22.087 C 86.895,23.194 86.316,24.474 " +
"86.316,25.929 C 86.316,27.123 86.901,28.239 88.070,29.278 C 89.239,30.316 90.675,30.835 92.379,30.835 C 94.095,30.835 95.537,30.316 96.706,29.278 C 97.875,28.239 98.460,27.117 " +
"98.460,25.911 Z M 102.284,25.892 C 102.284,27.360 101.876,28.780 101.062,30.154 C 100.247,31.529 99.035,32.623 97.425,33.438 C 95.814,34.252 94.132,34.659 92.379,34.659 C " +
"90.638,34.659 88.971,34.258 87.380,33.456 C 85.788,32.654 84.575,31.563 83.742,30.182 C 82.909,28.802 82.492,27.360 82.492,25.855 C 82.492,24.325 82.915,22.824 83.761,21.350 C " +
"84.606,19.876 85.822,18.717 87.408,17.871 C 88.993,17.026 90.650,16.603 92.379,16.603 C 94.119,16.603 95.795,17.035 97.406,17.899 C 99.016,18.763 100.232,19.926 101.053,21.387 C " +
"101.873,22.849 102.284,24.350 102.284,25.892 ZM 114.483,17.106 L 114.483,19.494 C 116.088,18.337 117.353,17.567 118.279,17.181 C 119.206,16.795 120.073,16.603 120.882,16.603 C " +
"122.125,16.603 123.331,17.063 124.500,17.983 C 125.296,18.605 125.694,19.239 125.694,19.886 C 125.694,20.433 125.504,20.896 125.125,21.275 C 124.746,21.655 124.289,21.844 " +
"123.754,21.844 C 123.282,21.844 122.784,21.608 122.262,21.135 C 121.740,20.663 121.273,20.427 120.863,20.427 C 120.328,20.427 119.529,20.762 118.466,21.434 C 117.403,22.105 " +
"116.075,23.113 114.483,24.456 L 114.483,30.220 L 119.930,30.220 C 120.850,30.220 121.506,30.397 121.898,30.751 C 122.290,31.106 122.486,31.569 122.486,32.141 C 122.486,32.701 " +
"122.290,33.158 121.898,33.512 C 121.506,33.867 120.850,34.044 119.930,34.044 L 108.384,34.044 C 107.463,34.044 106.807,33.867 106.416,33.512 C 106.024,33.158 105.828,32.695 " +
"105.828,32.122 C 105.828,31.563 106.024,31.106 106.416,30.751 C 106.807,30.397 107.463,30.220 108.384,30.220 L 110.659,30.220 L 110.659,20.930 L 109.279,20.930 C 108.359,20.930 " +
"107.703,20.753 107.311,20.399 C 106.919,20.044 106.723,19.581 106.723,19.009 C 106.723,18.449 106.919,17.992 107.311,17.638 C 107.703,17.283 108.359,17.106 109.279,17.106 L " +
"114.483,17.106 ZM 140.431,32.645 C 140.431,33.192 140.225,33.655 139.815,34.034 C 139.405,34.414 138.838,34.603 138.118,34.603 C 137.396,34.603 136.830,34.414 136.420,34.034 C " +
"136.010,33.655 135.804,33.192 135.804,32.645 C 135.804,32.110 136.006,31.653 136.411,31.274 C 136.815,30.895 137.384,30.705 138.118,30.705 C 138.851,30.705 139.420,30.891 " +
"139.824,31.264 C 140.228,31.637 140.431,32.098 140.431,32.645 Z M 141.046,13.655 L 139.983,25.183 C 139.933,25.780 139.734,26.244 139.386,26.573 C 139.038,26.903 138.603,27.067 " +
"138.080,27.067 C 137.558,27.067 137.123,26.903 136.774,26.573 C 136.426,26.244 136.227,25.780 136.178,25.183 L 135.096,13.655 C 135.046,13.071 135.021,12.685 135.021,12.499 C " +
"135.021,11.529 135.313,10.749 135.898,10.158 C 136.482,9.567 137.210,9.272 138.080,9.272 C 138.938,9.272 139.662,9.570 140.253,10.167 C 140.844,10.764 141.139,11.516 141.139,12.424 " +
"C 141.139,12.611 141.108,13.021 141.046,13.655 Z";
private const string ParseError1 = "Parameter \"(pathData matches.Count == 0)\" must be false, was true: ";
private const string ParseError2 = "Parameter \"(pathData matches.Count > 1)\" must be false, was true: ";
private const string ParseError3 = "PATH_ERR003";
private DispatcherQueueTimer _typeTimer = DispatcherQueue.GetForCurrentThread().CreateTimer();
private List<Color> _colors;
private List<string> _samples;
private string _data = string.Empty;
private StringBuilder _logger;
private float _strokeThickness;
private Color _strokeColor;
private Color _fillColor;
private bool _selectionChanged = false;
private bool _isParsing = false;
private CanvasGeometry _errorGeometry;
private GeometryStreamReader _reader;
private SolidColorBrush _commandBrush;
private SolidColorBrush _commandErrorBrush;
public string InputText { get; set; }
public CanvasPathGeometryPage()
{
this.InitializeComponent();
_reader = new GeometryStreamReader();
_logger = new StringBuilder();
_colors = new List<Color>()
{
Colors.Transparent,
Colors.Black,
Colors.White,
Colors.Crimson,
CanvasPathGeometry.CreateColor("#bf5af2"),
CanvasPathGeometry.CreateColor("#0a84ff"),
CanvasPathGeometry.CreateColor("#32d74b"),
CanvasPathGeometry.CreateColor("#ff9500"),
CanvasPathGeometry.CreateColor("#ffd60a")
};
_commandBrush = new SolidColorBrush(Colors.White);
_commandErrorBrush = new SolidColorBrush(Colors.Red);
var colorList = new List<string>()
{
"Transparent",
"Black",
"White",
"Crimson",
"Purple",
"LightBlue",
"LightGreen",
"Orange",
"Yellow"
};
this._samples = new List<string>()
{
string.Empty,
Sample1,
Sample2,
Sample3,
Sample4,
Sample5
};
var sampleList = new List<string>()
{
"None",
"Sample 1",
"Sample 2",
"Sample 3",
"Sample 4",
"Sample 5",
};
StrokeList.ItemsSource = colorList;
FillList.ItemsSource = colorList;
StrokeThickness.Value = 1;
StrokeList.SelectedIndex = 1;
FillList.SelectedIndex = 0;
_selectionChanged = false;
}
private void ParseData()
{
_data = InputData.Text;
_isParsing = true;
RenderCanvas.Invalidate();
_isParsing = false;
}
private void OnCanvasDraw(CanvasControl sender, CanvasDrawEventArgs args)
{
if (string.IsNullOrWhiteSpace(_data))
{
CommandsList.Text = string.Empty;
return;
}
this._errorGeometry ??= CanvasPathGeometry.CreateGeometry(sender, ErrorString);
_logger?.Clear();
CommandsList.Text = string.Empty;
try
{
_logger?.AppendLine("// The following commands represent the CanvasPathBuilder command(s) needed");
_logger?.AppendLine("// to create the CanvasGeometry from the specified Win2d Path Mini Language.");
var geometry = CanvasPathGeometry.CreateGeometry(sender, _data);
_reader.StartLogging();
geometry.SendPathTo(_reader);
_logger?.AppendLine(_reader.EndLogging());
CommandsList.Text = _logger?.ToString() ?? string.Empty;
args.DrawingSession.FillGeometry(geometry, _fillColor);
args.DrawingSession.DrawGeometry(geometry, _strokeColor, _strokeThickness);
RootPivot.SelectedIndex = 0;
CommandsList.Foreground = _commandBrush;
}
catch (ArgumentException argEx)
{
var message = argEx.Message;
var errorCode = message.Substring(0, 11);
var parseError = string.Empty;
if (message.StartsWith(ParseError1))
{
parseError = "Parse Error: No matching data!";
}
else if (message.StartsWith(ParseError2))
{
parseError = "Parse Error: Multiple FillRule elements present in Path Data!";
}
else if (message.StartsWith(ParseError3))
{
var tokens = message.Split('\n', StringSplitOptions.RemoveEmptyEntries);
if (tokens.Length == 3)
{
parseError = $"Parse Error at {tokens[1]}. Cannot parse '{tokens[2]}'.";
}
}
else
{
parseError = "Parsing error! Invalid input data!";
}
args.DrawingSession.FillGeometry(_errorGeometry, Colors.Black);
CommandsList.Text = parseError;
RootPivot.SelectedIndex = 1;
CommandsList.Foreground = _commandErrorBrush;
}
catch (Exception)
{
args.DrawingSession.FillGeometry(_errorGeometry, Colors.Black);
CommandsList.Text = "Parsing error! Invalid input data!";
RootPivot.SelectedIndex = 1;
CommandsList.Foreground = _commandErrorBrush;
}
}
private void OnStrokeThicknessChanged(object sender, RangeBaseValueChangedEventArgs e)
{
_strokeThickness = (float)StrokeThickness.Value;
_selectionChanged = true;
RenderCanvas.Invalidate();
}
private void OnStrokeColorChanged(object sender, SelectionChangedEventArgs e)
{
if (StrokeList.SelectedIndex > -1)
{
_strokeColor = _colors[StrokeList.SelectedIndex];
_selectionChanged = true;
}
RenderCanvas.Invalidate();
}
private void OnFillColorChanged(object sender, SelectionChangedEventArgs e)
{
if (FillList.SelectedIndex > -1)
{
_fillColor = _colors[FillList.SelectedIndex];
_selectionChanged = true;
}
RenderCanvas.Invalidate();
}
private void ShowSample(int index)
{
InputData.Text = _samples.ElementAt(index);
if (!_selectionChanged)
{
StrokeThickness.Value = 4;
StrokeList.SelectedIndex = 1;
FillList.SelectedIndex = 5;
_selectionChanged = false;
}
_data = InputData.Text;
RenderCanvas.Invalidate();
}
private void OnClearCanvas(object sender, RoutedEventArgs e)
{
InputData.Text = string.Empty;
ParseData();
}
private void OnShowRoundedStarSample(object sender, RoutedEventArgs e)
{
ShowSample(1);
}
private void OnShowStarSample(object sender, RoutedEventArgs e)
{
ShowSample(2);
}
private void OnShowSpiralSample(object sender, RoutedEventArgs e)
{
ShowSample(3);
}
private void OnShowFlowerSample(object sender, RoutedEventArgs e)
{
ShowSample(4);
}
private void OnShowGearSample(object sender, RoutedEventArgs e)
{
ShowSample(5);
}
public void OnInputTextChanged(object sender, RoutedEventArgs e)
{
// Call the ParseData method only after 0.3 seconds have elapsed since last trigger.
_typeTimer.Debounce(ParseData, TimeSpan.FromSeconds(0.3));
}
}
}

Просмотреть файл

@ -0,0 +1,127 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Numerics;
using System.Text;
using Microsoft.Graphics.Canvas.Geometry;
namespace Microsoft.Toolkit.Uwp.SampleApp.SamplePages
{
/// <summary>
/// Class to read the <see cref="CanvasGeometry"/> path data.
/// </summary>
internal class GeometryStreamReader : ICanvasPathReceiver
{
private readonly StringBuilder _cmdBuilder;
/// <summary>
/// Initializes a new instance of the <see cref="GeometryStreamReader"/> class.
/// </summary>
public GeometryStreamReader()
{
_cmdBuilder = new StringBuilder();
}
/// <summary>
/// Starts logging the data for the sample app
/// </summary>
public void StartLogging()
{
_cmdBuilder.Clear();
_cmdBuilder.AppendLine($"using (var pathBuilder = new CanvasPathBuilder(null))");
_cmdBuilder.AppendLine("{\n");
}
/// <summary>
/// Finishes reading the geometry path data and returns the data as formatted string.
/// </summary>
/// <returns><see cref="CanvasPathBuilder"/> commands to create the CanvasGeometry</returns>
public string EndLogging()
{
_cmdBuilder.AppendLine("}");
return _cmdBuilder.ToString();
}
/// <summary>
/// Starts a new figure at the specified point, with the specified figure fill option.
/// </summary>
/// <param name="point">Start point</param>
/// <param name="fill"><see cref="CanvasFigureFill"/></param>
public void BeginFigure(Vector2 point, CanvasFigureFill fill)
{
_cmdBuilder.AppendLine($"\n pathBuilder.BeginFigure(new Vector2({point.X}, {point.Y}));");
}
/// <summary>
/// Adds a single arc to the path, specified by start and end points through which an ellipse will be fitted.
/// </summary>
/// <param name="point">Start Point</param>
/// <param name="x">radiusX</param>
/// <param name="y">radiusY</param>
/// <param name="z">rotationAngle</param>
/// <param name="sweepDirection"><see cref="CanvasSweepDirection"/></param>
/// <param name="arcSize"><see cref="CanvasArcSize"/></param>
public void AddArc(Vector2 point, float x, float y, float z, CanvasSweepDirection sweepDirection, CanvasArcSize arcSize)
{
_cmdBuilder.AppendLine($" pathBuilder.AddArc(new Vector2({point.X}, {point.Y}), {x}, {y}, {z}, {sweepDirection}, {arcSize});");
}
/// <summary>
/// Adds a cubic bezier to the path. The bezier starts where the path left off, and has the specified control points and end point.
/// </summary>
/// <param name="controlPoint1">First ControlPoint</param>
/// <param name="controlPoint2">Second Control Point</param>
/// <param name="endPoint">EndPoint</param>
public void AddCubicBezier(Vector2 controlPoint1, Vector2 controlPoint2, Vector2 endPoint)
{
_cmdBuilder.AppendLine($" pathBuilder.AddCubicBezier(new Vector2({controlPoint1.X}, {controlPoint1.Y}), new Vector2({controlPoint2.X}, {controlPoint2.Y}), new Vector2({endPoint.X}, {endPoint.Y}));");
}
/// <summary>
/// Adds a line segment to the path, with the specified end point.
/// </summary>
/// <param name="endPoint">EndPoint</param>
public void AddLine(Vector2 endPoint)
{
_cmdBuilder.AppendLine($" pathBuilder.AddLine(new Vector2({endPoint.X}, {endPoint.Y}));");
}
/// <summary>
/// Adds a quadratic bezier to the path. The bezier starts where the path left off, and has the specified control point and end point.
/// </summary>
/// <param name="controlPoint">Control Point</param>
/// <param name="endPoint">EndPoint</param>
public void AddQuadraticBezier(Vector2 controlPoint, Vector2 endPoint)
{
_cmdBuilder.AppendLine($" pathBuilder.AddQuadraticBezier(new Vector2({controlPoint.X}, {controlPoint.Y}), new Vector2({endPoint.X}, {endPoint.Y}));");
}
/// <summary>
/// Specifies the method used to determine which points are inside the geometry described by this path builder, and which points are outside.
/// </summary>
/// <param name="filledRegionDetermination"><see cref="CanvasFilledRegionDetermination"/></param>
public void SetFilledRegionDetermination(CanvasFilledRegionDetermination filledRegionDetermination)
{
_cmdBuilder.AppendLine($" pathBuilder.SetFilledRegionDetermination(CanvasFilledRegionDetermination.{filledRegionDetermination});");
}
/// <summary>
/// Specifies stroke and join options to be applied to new segments added to the path builder.
/// </summary>
/// <param name="figureSegmentOptions"><see cref="CanvasFigureSegmentOptions"/></param>
public void SetSegmentOptions(CanvasFigureSegmentOptions figureSegmentOptions)
{
// Do nothing
}
/// <summary>
/// >Ends the current figure; optionally, closes it.
/// </summary>
/// <param name="figureLoop"><see cref="CanvasFigureLoop"/></param>
public void EndFigure(CanvasFigureLoop figureLoop)
{
_cmdBuilder.AppendLine($" pathBuilder.EndFigure({(figureLoop == CanvasFigureLoop.Closed ? "CanvasFigureLoop.Closed" : "CanvasFigureLoop.Open")});");
}
}
}

Просмотреть файл

@ -0,0 +1,147 @@
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:controls="using:Microsoft.Toolkit.Uwp.UI.Controls"
xmlns:converters="using:Microsoft.Toolkit.Uwp.UI.Converters"
mc:Ignorable="d">
<Page.Resources>
<converters:VisibilityToBoolConverter x:Key="VisBoolConverter"/>
</Page.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition/>
</Grid.RowDefinitions>
<controls:TabbedCommandBar>
<controls:TabbedCommandBar.PaneFooter>
<CommandBar Background="Transparent" DefaultLabelPosition="Right">
<AppBarButton Label="Share" Icon="Share"/>
<AppBarButton Label="Comments" Icon="Message"/>
</CommandBar>
</controls:TabbedCommandBar.PaneFooter>
<controls:TabbedCommandBar.MenuItems>
<controls:TabbedCommandBarItem Header="Home">
<AppBarButton Icon="Undo" Label="Undo"/>
<AppBarButton Icon="Redo" Label="Redo"/>
<AppBarButton Icon="Paste" Label="Paste"/>
<AppBarSeparator />
<AppBarElementContainer>
<controls:ColorPickerButton SelectedColor="{ThemeResource Brand-Color}"/>
</AppBarElementContainer>
<AppBarElementContainer>
<ComboBox SelectedIndex="0" MinWidth="175">
<ComboBoxItem Content="Arial" />
<ComboBoxItem Content="Calibri" />
<ComboBoxItem Content="JetBrains Mono" />
<ComboBoxItem Content="Roboto" />
<ComboBoxItem Content="Sergio UI" />
<ComboBoxItem Content="Sergio UI Semibold" />
</ComboBox>
</AppBarElementContainer>
<AppBarElementContainer>
<TextBox PlaceholderText="Size"/>
</AppBarElementContainer>
<AppBarToggleButton Icon="Bold" Label="Bold" />
<AppBarToggleButton Icon="Italic" Label="Italic" />
<AppBarToggleButton Icon="Underline" Label="Underline" />
</controls:TabbedCommandBarItem>
<controls:TabbedCommandBarItem Header="Insert">
<AppBarButton Icon="Pictures" Label="Pictures">
<AppBarButton.Flyout>
<MenuFlyout Placement="BottomEdgeAlignedLeft">
<MenuFlyoutItem Text="This Device">
<MenuFlyoutItem.Icon>
<FontIcon FontFamily="{ThemeResource SymbolThemeFontFamily}" Glyph="&#xEC4E;" />
</MenuFlyoutItem.Icon>
</MenuFlyoutItem>
<MenuFlyoutItem Text="Stock Images">
<MenuFlyoutItem.Icon>
<FontIcon FontFamily="{ThemeResource SymbolThemeFontFamily}" Glyph="&#xE721;" />
</MenuFlyoutItem.Icon>
</MenuFlyoutItem>
<MenuFlyoutItem Icon="Globe" Text="Online Pictures" />
</MenuFlyout>
</AppBarButton.Flyout>
</AppBarButton>
<AppBarButton Label="Shapes">
<AppBarButton.Icon>
<FontIcon FontFamily="Segoe UI Symbol" Glyph="&#x25A1;" />
</AppBarButton.Icon>
</AppBarButton>
<AppBarButton Label="Icons">
<AppBarButton.Icon>
<FontIcon FontFamily="{ThemeResource SymbolThemeFontFamily}" Glyph="&#xED58;" />
</AppBarButton.Icon>
</AppBarButton>
<AppBarButton Label="3D Models">
<AppBarButton.Icon>
<FontIcon FontFamily="{ThemeResource SymbolThemeFontFamily}" Glyph="&#xF158;" />
</AppBarButton.Icon>
</AppBarButton>
<AppBarSeparator/>
<AppBarButton Label="Add-ins">
<AppBarButton.Icon>
<FontIcon FontFamily="{ThemeResource SymbolThemeFontFamily}" Glyph="&#xECAA;" />
</AppBarButton.Icon>
</AppBarButton>
<controls:TabbedCommandBarItem.SecondaryCommands>
<AppBarButton Icon="Add" Label="New item" />
</controls:TabbedCommandBarItem.SecondaryCommands>
</controls:TabbedCommandBarItem>
<controls:TabbedCommandBarItem x:Name="PictureFormat"
Header="Picture Format"
IsContextual="True"
Visibility="Collapsed">
<AppBarButton Label="Remove Background">
<AppBarButton.Icon>
<FontIcon FontFamily="{ThemeResource SymbolThemeFontFamily}" Glyph="&#xE706;" />
</AppBarButton.Icon>
</AppBarButton>
<AppBarButton Label="Picture Effects">
<AppBarButton.Icon>
<FontIcon FontFamily="{ThemeResource SymbolThemeFontFamily}" Glyph="&#xF158;" />
</AppBarButton.Icon>
</AppBarButton>
<AppBarButton Label="Rotate">
<AppBarButton.Icon>
<FontIcon FontFamily="{ThemeResource SymbolThemeFontFamily}" Glyph="&#xE7AD;" />
</AppBarButton.Icon>
</AppBarButton>
<AppBarElementContainer>
<SplitButton>
<StackPanel Spacing="12" Orientation="Horizontal">
<FontIcon FontSize="16" FontFamily="{ThemeResource SymbolThemeFontFamily}" Glyph="&#xE7A8;" />
<TextBlock FontSize="12" Text="Crop"/>
</StackPanel>
<SplitButton.Flyout>
<MenuFlyout>
<MenuFlyoutItem Text="Crop">
<MenuFlyoutItem.Icon>
<FontIcon FontFamily="{ThemeResource SymbolThemeFontFamily}" Glyph="&#xE7A8;" />
</MenuFlyoutItem.Icon>
</MenuFlyoutItem>
<MenuFlyoutItem Text="Crop to Shape">
<MenuFlyoutItem.Icon>
<FontIcon FontFamily="{ThemeResource SymbolThemeFontFamily}" Glyph="&#xF407;" />
</MenuFlyoutItem.Icon>
</MenuFlyoutItem>
<MenuFlyoutItem Text="Aspect Ratio" />
<MenuFlyoutSeparator/>
<MenuFlyoutItem Text="Fill" />
<MenuFlyoutItem Text="Fit" />
</MenuFlyout>
</SplitButton.Flyout>
</SplitButton>
</AppBarElementContainer>
</controls:TabbedCommandBarItem>
</controls:TabbedCommandBar.MenuItems>
</controls:TabbedCommandBar>
<Grid Grid.Row="1">
<ToggleSwitch x:Name="ContextualToggle" IsOn="{Binding Visibility, ElementName=PictureFormat, Converter={StaticResource VisBoolConverter}, Mode=TwoWay}"
OffContent="Contextual Tab Off" OnContent="Contextual Tab On"/>
</Grid>
</Grid>
</Page>

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 2.9 KiB

Просмотреть файл

@ -13,7 +13,9 @@ private void PopToast()
("60", "1 hour"),
("240", "4 hours"),
("1440", "1 day"))
.AddButton(new ToastButtonSnooze() { SelectionBoxId = "snoozeTime" })
.AddButton(new ToastButtonDismiss())
.AddButton(new ToastButton()
.SetSnoozeActivation("snoozeTime"))
.AddButton(new ToastButton()
.SetDismissActivation())
.Show();
}

Просмотреть файл

@ -40,8 +40,10 @@ namespace Microsoft.Toolkit.Uwp.SampleApp.SamplePages
("60", "1 hour"),
("240", "4 hours"),
("1440", "1 day"))
.AddButton(new ToastButtonSnooze() { SelectionBoxId = "snoozeTime" })
.AddButton(new ToastButtonDismiss());
.AddButton(new ToastButton()
.SetSnoozeActivation("snoozeTime"))
.AddButton(new ToastButton()
.SetDismissActivation());
return builder.Content;
}

Просмотреть файл

@ -3,6 +3,7 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:ani="using:Microsoft.Toolkit.Uwp.UI.Animations"
xmlns:behaviors="using:Microsoft.Toolkit.Uwp.UI.Behaviors"
xmlns:converters="using:Microsoft.Toolkit.Uwp.UI.Converters"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:interactions="using:Microsoft.Xaml.Interactions.Core"
xmlns:interactivity="using:Microsoft.Xaml.Interactivity"
@ -17,6 +18,8 @@
<!-- Put a copy of any controls/resources required for XAML Parsing within XAML Only Samples -->
<!-- This page is never loaded by the app, but used to trick the compiler... -->
<Page.Resources>
<converters:VisibilityToBoolConverter x:Key="VisibilityBoolConverter" />
<converters:BoolToVisibilityConverter x:Key="BoolVisibilityConverter" />
<triggers:CompareStateTrigger x:Key="CompareStateTrigger" />
<triggers:IsEqualStateTrigger x:Key="IsEqualStateTrigger" />
<triggers:IsNotEqualStateTrigger x:Key="IsNotEqualStateTrigger" />
@ -34,17 +37,17 @@
<ani:OpacityAnimation />
<ani:StartAnimationActivity />
<ani:InvokeActionsActivity />
<ani:ClipAnimation/>
<ani:BlurEffectAnimation/>
<ani:SaturationEffectAnimation/>
<ani:AnimationScope/>
<ani:ExposureEffectAnimation/>
<ani:ClipAnimation />
<ani:BlurEffectAnimation />
<ani:SaturationEffectAnimation />
<ani:AnimationScope />
<ani:ExposureEffectAnimation />
</ani:AnimationSet>
</ani:Explicit.Animations>
<media:UIElementExtensions.VisualFactory>
<media:PipelineVisualFactory>
<media:OpacityEffect />
<media:ExposureEffect/>
<media:ExposureEffect />
</media:PipelineVisualFactory>
</media:UIElementExtensions.VisualFactory>
@ -52,6 +55,7 @@
<interactivity:Interaction.Behaviors>
<interactions:EventTriggerBehavior EventName="Loaded">
<interactions:ChangePropertyAction />
<interactions:InvokeCommandAction />
<mediaactions:PlaySoundAction />
</interactions:EventTriggerBehavior>
</interactivity:Interaction.Behaviors>

Просмотреть файл

@ -454,6 +454,15 @@
"XamlCodeFile": "TokenizingTextBoxXaml.bind",
"Icon": "/SamplePages/TokenizingTextBox/TokenizingTextBox.png",
"DocumentationUrl": "https://raw.githubusercontent.com/MicrosoftDocs/WindowsCommunityToolkitDocs/master/docs/controls/TokenizingTextBox.md"
},
{
"Name": "TabbedCommandBar",
"Subcategory": "Menus and Toolbars",
"About": "A control for displaying multiple CommandBars in the same space, like Microsoft Office's ribbon.",
"CodeUrl": "https://github.com/windows-toolkit/WindowsCommunityToolkit/tree/master/Microsoft.Toolkit.Uwp.UI.Controls/TabbedCommandBar",
"XamlCodeFile": "/SamplePages/TabbedCommandBar/TabbedCommandBar.bind",
"Icon": "/SamplePages/TabbedCommandBar/TabbedCommandBar.png",
"DocumentationUrl": "https://raw.githubusercontent.com/MicrosoftDocs/WindowsCommunityToolkitDocs/master/docs/controls/TabbedCommandBar.md"
}
]
},
@ -901,6 +910,14 @@
"Icon": "/Assets/Helpers.png",
"DocumentationUrl": "https://raw.githubusercontent.com/MicrosoftDocs/WindowsCommunityToolkitDocs/master/docs/parsers/MarkdownParser.md"
},
{
"Name": "Win2d Path Mini Language Parser",
"Type": "CanvasPathGeometryPage",
"Subcategory": "Parser",
"About": "CanvasPathGeometry class allows you to convert Win2d Path Mini Language string to CanvasGeometry, Brushes, CanvasStrokes or CanvasStrokeStyles.",
"Icon": "/SamplePages/CanvasPathGeometry/CanvasPathGeometry.png",
"DocumentationUrl": "https://raw.githubusercontent.com/MicrosoftDocs/WindowsCommunityToolkitDocs/master/docs/parsers/CanvasPathGeometry.md"
},
{
"Name": "LiveTile",
"Type": "LiveTilePage",

Просмотреть файл

@ -1,42 +0,0 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using Windows.UI.Xaml;
namespace Microsoft.Toolkit.Uwp.UI.Animations.Behaviors
{
/// <summary>
/// Performs an blur animation using composition.
/// </summary>
/// <seealso>
/// <cref>Microsoft.Xaml.Interactivity.Behavior{Windows.UI.Xaml.UIElement}</cref>
/// </seealso>
public class Blur : CompositionBehaviorBase<FrameworkElement>
{
/// <summary>
/// The Blur value of the associated object
/// </summary>
public static readonly DependencyProperty ValueProperty = DependencyProperty.Register(nameof(Value), typeof(double), typeof(Blur), new PropertyMetadata(0d, PropertyChangedCallback));
/// <summary>
/// Gets or sets the Blur.
/// </summary>
/// <value>
/// The Blur.
/// </value>
public double Value
{
get { return (double)GetValue(ValueProperty); }
set { SetValue(ValueProperty, value); }
}
/// <summary>
/// Starts the animation.
/// </summary>
public override void StartAnimation()
{
AssociatedObject?.Blur(duration: Duration, delay: Delay, value: (float)Value, easingType: EasingType, easingMode: EasingMode)?.Start();
}
}
}

Просмотреть файл

@ -1,141 +0,0 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using Microsoft.Toolkit.Uwp.UI.Behaviors;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Media.Animation;
namespace Microsoft.Toolkit.Uwp.UI.Animations.Behaviors
{
/// <summary>
/// A base class for all behaviors using composition.It contains some of the common properties to set on a visual.
/// </summary>
/// <typeparam name="T">The type of the associated object.</typeparam>
/// <seealso cref="Microsoft.Toolkit.Uwp.UI.Behaviors.BehaviorBase{T}" />
public abstract class CompositionBehaviorBase<T> : BehaviorBase<T>
where T : UIElement
{
/// <summary>
/// Called when the associated object has been loaded.
/// </summary>
protected override void OnAssociatedObjectLoaded()
{
base.OnAssociatedObjectLoaded();
if (AutomaticallyStart)
{
StartAnimation();
}
}
/// <summary>
/// The duration of the animation.
/// </summary>
public static readonly DependencyProperty DurationProperty = DependencyProperty.Register(nameof(Duration), typeof(double), typeof(CompositionBehaviorBase<T>), new PropertyMetadata(1d, PropertyChangedCallback));
/// <summary>
/// The delay of the animation.
/// </summary>
public static readonly DependencyProperty DelayProperty = DependencyProperty.Register(nameof(Delay), typeof(double), typeof(CompositionBehaviorBase<T>), new PropertyMetadata(0d, PropertyChangedCallback));
/// <summary>
/// The property sets if the animation should automatically start.
/// </summary>
public static readonly DependencyProperty AutomaticallyStartProperty = DependencyProperty.Register(nameof(AutomaticallyStart), typeof(bool), typeof(CompositionBehaviorBase<T>), new PropertyMetadata(true, PropertyChangedCallback));
/// <summary>
/// The <see cref="EasingType"/> used to generate the easing function of the animation.
/// </summary>
public static readonly DependencyProperty EasingTypeProperty = DependencyProperty.Register(nameof(EasingType), typeof(EasingType), typeof(CompositionBehaviorBase<T>), new PropertyMetadata(EasingType.Default, PropertyChangedCallback));
/// <summary>
/// The <see cref="EasingMode"/> used to generate the easing function of the animation.
/// </summary>
public static readonly DependencyProperty EasingModeProperty = DependencyProperty.Register(nameof(EasingMode), typeof(EasingMode), typeof(CompositionBehaviorBase<T>), new PropertyMetadata(EasingMode.EaseOut, PropertyChangedCallback));
/// <summary>
/// Gets or sets a value indicating whether [automatically start] on the animation is set.
/// </summary>
/// <value>
/// <c>true</c> if [automatically start]; otherwise, <c>false</c>.
/// </value>
public bool AutomaticallyStart
{
get { return (bool)GetValue(AutomaticallyStartProperty); }
set { SetValue(AutomaticallyStartProperty, value); }
}
/// <summary>
/// Gets or sets the delay.
/// </summary>
/// <value>
/// The delay.
/// </value>
public double Delay
{
get { return (double)GetValue(DelayProperty); }
set { SetValue(DelayProperty, value); }
}
/// <summary>
/// Gets or sets the duration.
/// </summary>
/// <value>
/// The duration.
/// </value>
public double Duration
{
get { return (double)GetValue(DurationProperty); }
set { SetValue(DurationProperty, value); }
}
/// <summary>
/// Gets or sets the <see cref="EasingType"/> used to generate the easing function of the animation.
/// </summary>
/// <value>
/// The easing function
/// </value>
public EasingType EasingType
{
get { return (EasingType)GetValue(EasingTypeProperty); }
set { SetValue(EasingTypeProperty, value); }
}
/// <summary>
/// Gets or sets the <see cref="EasingMode"/> used to generate the easing function of the animation.
/// </summary>
/// <value>
/// The easing mode
/// </value>
public EasingMode EasingMode
{
get { return (EasingMode)GetValue(EasingModeProperty); }
set { SetValue(EasingModeProperty, value); }
}
/// <summary>
/// Starts the animation.
/// </summary>
public abstract void StartAnimation();
/// <summary>
/// If any of the properties are changed then the animation is automatically started depending on the AutomaticallyStart property.
/// </summary>
/// <param name="dependencyObject">The dependency object.</param>
/// <param name="dependencyPropertyChangedEventArgs">The <see cref="DependencyPropertyChangedEventArgs"/> instance containing the event data.</param>
protected static void PropertyChangedCallback(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs)
{
var behavior = dependencyObject as CompositionBehaviorBase<T>;
if (behavior == null)
{
return;
}
if (behavior.AutomaticallyStart)
{
behavior.StartAnimation();
}
}
}
}

Просмотреть файл

@ -1,16 +0,0 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using Windows.UI.Xaml;
namespace Microsoft.Toolkit.Uwp.UI.Animations.Behaviors
{
/// <summary>
/// Non-generic convenience implementation to provide backwards compatibility.
/// </summary>
/// <seealso cref="Microsoft.Toolkit.Uwp.UI.Animations.Behaviors.CompositionBehaviorBase{T}" />
public abstract class CompositionBehaviorBase : CompositionBehaviorBase<UIElement>
{
}
}

Просмотреть файл

@ -1,42 +0,0 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using Windows.UI.Xaml;
namespace Microsoft.Toolkit.Uwp.UI.Animations.Behaviors
{
/// <summary>
/// Performs an fade animation using composition.
/// </summary>
/// <seealso>
/// <cref>Microsoft.Xaml.Interactivity.Behavior{Windows.UI.Xaml.UIElement}</cref>
/// </seealso>
public class Fade : CompositionBehaviorBase<UIElement>
{
/// <summary>
/// The Opacity value of the associated object
/// </summary>
public static readonly DependencyProperty ValueProperty = DependencyProperty.Register(nameof(Value), typeof(double), typeof(Fade), new PropertyMetadata(1d, PropertyChangedCallback));
/// <summary>
/// Gets or sets the Opacity.
/// </summary>
/// <value>
/// The Opacity.
/// </value>
public double Value
{
get { return (double)GetValue(ValueProperty); }
set { SetValue(ValueProperty, value); }
}
/// <summary>
/// Starts the animation.
/// </summary>
public override void StartAnimation()
{
AssociatedObject.Fade((float)Value, Duration, Delay, EasingType, EasingMode)?.Start();
}
}
}

Просмотреть файл

@ -1,65 +0,0 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using Windows.UI;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Media;
namespace Microsoft.Toolkit.Uwp.UI.Animations.Behaviors
{
/// <summary>
/// Applies a basic point light to a UIElement. You control the intensity by setting the distance of the light.
/// </summary>
/// <seealso cref="Microsoft.Toolkit.Uwp.UI.Animations.Behaviors.CompositionBehaviorBase" />
[Obsolete("The Light effect will be removed in a future major release. Please use XamlLight instead")]
public class Light : CompositionBehaviorBase<FrameworkElement>
{
/// <summary>
/// The Blur value of the associated object
/// </summary>
public static readonly DependencyProperty DistanceProperty = DependencyProperty.Register(nameof(Distance), typeof(double), typeof(Light), new PropertyMetadata(0d, PropertyChangedCallback));
/// <summary>
/// The Color of the spotlight no the associated object.
/// </summary>
public static readonly DependencyProperty ColorProperty = DependencyProperty.Register("Color", typeof(Brush), typeof(Light), new PropertyMetadata(new SolidColorBrush(Colors.White)));
/// <summary>
/// Gets or sets the Blur.
/// </summary>
/// <value>
/// The Blur.
/// </value>
public double Distance
{
get { return (double)GetValue(DistanceProperty); }
set { SetValue(DistanceProperty, value); }
}
/// <summary>
/// Gets or sets the color of the spotlight.
/// </summary>
public Brush Color
{
get { return (Brush)GetValue(ColorProperty); }
set { SetValue(ColorProperty, value); }
}
/// <summary>
/// Starts the animation.
/// </summary>
public override void StartAnimation()
{
AssociatedObject?.Light(
duration: Duration,
delay: Delay,
easingType: EasingType,
easingMode: EasingMode,
distance: (float)Distance,
color: ((SolidColorBrush)Color).Color)?.Start();
}
}
}

Просмотреть файл

@ -1,66 +0,0 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using Windows.UI.Xaml;
namespace Microsoft.Toolkit.Uwp.UI.Animations.Behaviors
{
/// <summary>
/// Performs an offset animation using composition.
/// </summary>
/// <seealso cref="Microsoft.Toolkit.Uwp.UI.Animations.Behaviors.CompositionBehaviorBase" />
/// <seealso>
/// <cref>Microsoft.Xaml.Interactivity.Behavior{Windows.UI.Xaml.UIElement}</cref>
/// </seealso>
public class Offset : CompositionBehaviorBase<UIElement>
{
/// <summary>
/// The Offset on the x axis of the associated object
/// </summary>
public static readonly DependencyProperty OffsetXProperty = DependencyProperty.Register(nameof(OffsetX), typeof(double), typeof(Offset), new PropertyMetadata(0d, PropertyChangedCallback));
/// <summary>
/// The Offset on the y axis of the associated object
/// </summary>
public static readonly DependencyProperty OffsetYProperty = DependencyProperty.Register(nameof(OffsetY), typeof(double), typeof(Offset), new PropertyMetadata(0d, PropertyChangedCallback));
/// <summary>
/// Gets or sets the Offset x.
/// </summary>
/// <value>
/// The Offset x.
/// </value>
public double OffsetX
{
get { return (double)GetValue(OffsetXProperty); }
set { SetValue(OffsetXProperty, value); }
}
/// <summary>
/// Gets or sets the Offset y.
/// </summary>
/// <value>
/// The Offset y.
/// </value>
public double OffsetY
{
get { return (double)GetValue(OffsetYProperty); }
set { SetValue(OffsetYProperty, value); }
}
/// <summary>
/// Starts the animation.
/// </summary>
public override void StartAnimation()
{
AssociatedObject.Offset(
duration: Duration,
delay: Delay,
easingType: EasingType,
easingMode: EasingMode,
offsetX: (float)OffsetX,
offsetY: (float)OffsetY)?.Start();
}
}
}

Просмотреть файл

@ -1,81 +0,0 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using Windows.UI.Xaml;
namespace Microsoft.Toolkit.Uwp.UI.Animations.Behaviors
{
/// <summary>
/// Performs a rotation animation using composition.
/// </summary>
public class Rotate : CompositionBehaviorBase<UIElement>
{
/// <summary>
/// The rotation of the associated object in degrees
/// </summary>
public static readonly DependencyProperty ValueProperty = DependencyProperty.Register(nameof(Value), typeof(double), typeof(Rotate), new PropertyMetadata(0d, PropertyChangedCallback));
/// <summary>
/// The center (x axis) of rotation for associated object
/// </summary>
public static readonly DependencyProperty CenterXProperty = DependencyProperty.Register(nameof(CenterX), typeof(double), typeof(Rotate), new PropertyMetadata(0d, PropertyChangedCallback));
/// <summary>
/// The center (y axis) of rotation for associated object
/// </summary>
public static readonly DependencyProperty CenterYProperty = DependencyProperty.Register(nameof(CenterY), typeof(double), typeof(Rotate), new PropertyMetadata(0d, PropertyChangedCallback));
/// <summary>
/// Gets or sets the center point (x axis) of the associated object.
/// </summary>
/// <value>
/// The center point (x axis) of the associated object.
/// </value>
public double CenterX
{
get { return (double)GetValue(CenterXProperty); }
set { SetValue(CenterXProperty, value); }
}
/// <summary>
/// Gets or sets the center point (y axis) of the associated object.
/// </summary>
/// <value>
/// The center point (y axis) of the associated object.
/// </value>
public double CenterY
{
get { return (double)GetValue(CenterYProperty); }
set { SetValue(CenterYProperty, value); }
}
/// <summary>
/// Gets or sets the Rotation in degrees.
/// </summary>
/// <value>
/// The Rotation of the associated object in degrees.
/// </value>
public double Value
{
get { return (double)GetValue(ValueProperty); }
set { SetValue(ValueProperty, value); }
}
/// <summary>
/// Starts the animation.
/// </summary>
public override void StartAnimation()
{
AssociatedObject.Rotate(
duration: Duration,
delay: Delay,
easingType: EasingType,
easingMode: EasingMode,
value: (float)Value,
centerX: (float)CenterX,
centerY: (float)CenterY)?
.Start();
}
}
}

Просмотреть файл

@ -1,61 +0,0 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using Windows.UI.Xaml;
namespace Microsoft.Toolkit.Uwp.UI.Animations.Behaviors
{
/// <summary>
/// A behavior to allow Saturation changes to a UI Element.
/// </summary>
public class Saturation : CompositionBehaviorBase
{
/// <summary>
/// The Saturation value of the associated object
/// </summary>
public static readonly DependencyProperty ValueProperty = DependencyProperty.Register(nameof(Value), typeof(double), typeof(Saturation), new PropertyMetadata(0d, PropertyChangedCallback));
/// <summary>
/// The _framework element
/// </summary>
private FrameworkElement _frameworkElement;
/// <summary>
/// Gets or sets the Saturation.
/// </summary>
/// <value>
/// The Saturation.
/// </value>
public double Value
{
get { return (double)GetValue(ValueProperty); }
set { SetValue(ValueProperty, value); }
}
/// <summary>
/// Starts the animation.
/// </summary>
public override void StartAnimation()
{
_frameworkElement?.Saturation(
duration: Duration,
delay: Delay,
easingType: EasingType,
easingMode: EasingMode,
value: (float)Value)?.StartAsync();
}
/// <summary>
/// Called after the behavior is attached to the <see cref="P:Microsoft.Xaml.Interactivity.Behavior.AssociatedObject" />.
/// </summary>
/// <remarks>
/// Override this to hook up functionality to the <see cref="P:Microsoft.Xaml.Interactivity.Behavior.AssociatedObject" />
/// </remarks>
protected override void OnAttached()
{
base.OnAttached();
_frameworkElement = AssociatedObject as FrameworkElement;
}
}
}

Просмотреть файл

@ -1,99 +0,0 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using Windows.UI.Xaml;
namespace Microsoft.Toolkit.Uwp.UI.Animations.Behaviors
{
/// <summary>
/// Performs a scale animation using composition.
/// </summary>
public class Scale : CompositionBehaviorBase<UIElement>
{
/// <summary>
/// The scale (x axis) of the associated object
/// </summary>
public static readonly DependencyProperty ScaleXProperty = DependencyProperty.Register(nameof(ScaleX), typeof(double), typeof(Scale), new PropertyMetadata(1d, PropertyChangedCallback));
/// <summary>
/// The scale (y axis) of the associated object
/// </summary>
public static readonly DependencyProperty ScaleYProperty = DependencyProperty.Register(nameof(ScaleY), typeof(double), typeof(Scale), new PropertyMetadata(1d, PropertyChangedCallback));
/// <summary>
/// The center (x axis) of scale for associated object
/// </summary>
public static readonly DependencyProperty CenterXProperty = DependencyProperty.Register(nameof(CenterX), typeof(double), typeof(Scale), new PropertyMetadata(0d, PropertyChangedCallback));
/// <summary>
/// The center (y axis) of scale for associated object
/// </summary>
public static readonly DependencyProperty CenterYProperty = DependencyProperty.Register(nameof(CenterY), typeof(double), typeof(Scale), new PropertyMetadata(0d, PropertyChangedCallback));
/// <summary>
/// Gets or sets the scale on the x axis.
/// </summary>
/// <value>
/// The scale on the x axis.
/// </value>
public double ScaleX
{
get { return (double)GetValue(ScaleXProperty); }
set { SetValue(ScaleXProperty, value); }
}
/// <summary>
/// Gets or sets the scale on the y axis.
/// </summary>
/// <value>
/// The scale on the y axis.
/// </value>
public double ScaleY
{
get { return (double)GetValue(ScaleYProperty); }
set { SetValue(ScaleYProperty, value); }
}
/// <summary>
/// Gets or sets the scale (x axis) of the associated object.
/// </summary>
/// <value>
/// The scale (x axis) of the associated object.
/// </value>
public double CenterX
{
get { return (double)GetValue(CenterXProperty); }
set { SetValue(CenterXProperty, value); }
}
/// <summary>
/// Gets or sets the scale (y axis) of the associated object.
/// </summary>
/// <value>
/// The scale (y axis) of the associated object.
/// </value>
public double CenterY
{
get { return (double)GetValue(CenterYProperty); }
set { SetValue(CenterYProperty, value); }
}
/// <summary>
/// Starts the animation.
/// </summary>
public override void StartAnimation()
{
AssociatedObject.Scale(
duration: Duration,
delay: Delay,
easingType: EasingType,
easingMode: EasingMode,
centerX: (float)CenterX,
centerY: (float)CenterY,
scaleX: (float)ScaleX,
scaleY: (float)ScaleY)?
.Start();
}
}
}

Просмотреть файл

@ -6,7 +6,6 @@
using System;
using System.Numerics;
using Microsoft.Toolkit.Diagnostics;
using Windows.UI.Composition;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Media;
@ -605,7 +604,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Animations
{
if (!Matrix4x4.Decompose(to, out Vector3 toScale, out Quaternion toRotation, out Vector3 toTranslation))
{
ThrowHelper.ThrowArgumentException("The destination matrix could not be decomposed");
ThrowThrowArgumentExceptionForToDecompose();
}
Vector3? fromScale = null;
@ -616,7 +615,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Animations
{
if (!Matrix4x4.Decompose(from.GetValueOrDefault(), out Vector3 scale3, out Quaternion rotation4, out Vector3 translation3))
{
ThrowHelper.ThrowArgumentException("The initial matrix could not be decomposed");
ThrowThrowArgumentExceptionForFromDecompose();
}
fromScale = scale3;
@ -629,6 +628,9 @@ namespace Microsoft.Toolkit.Uwp.UI.Animations
Translation(toTranslation, fromTranslation, delay, duration, easingType, easingMode);
return this;
static void ThrowThrowArgumentExceptionForToDecompose() => throw new ArgumentException("The destination matrix could not be decomposed");
static void ThrowThrowArgumentExceptionForFromDecompose() => throw new ArgumentException("The initial matrix could not be decomposed");
}
/// <summary>

Просмотреть файл

@ -6,7 +6,6 @@ using System;
using System.Diagnostics.Contracts;
using System.Numerics;
using System.Runtime.CompilerServices;
using Microsoft.Toolkit.Diagnostics;
using Windows.Foundation;
using Windows.UI;
using Windows.UI.Composition;
@ -161,7 +160,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Animations
easingFunction);
}
return ThrowHelper.ThrowInvalidOperationException<CompositionAnimation>("Invalid animation type");
throw new InvalidOperationException("Invalid animation type");
}
/// <inheritdoc/>
@ -216,7 +215,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Animations
easingFunction);
}
return ThrowHelper.ThrowInvalidOperationException<Timeline>("Invalid animation type");
throw new InvalidOperationException("Invalid animation type");
}
/// <summary>
@ -229,9 +228,33 @@ namespace Microsoft.Toolkit.Uwp.UI.Animations
private TValue GetToAs<TValue>()
where TValue : unmanaged
{
T to = To;
return Unsafe.As<T, TValue>(ref to);
// We employ this (T2)(object)t1 pattern multiple times in this library to alter generics.
// This is an equivalent but safer alternative to using Unsafe.As<TFrom, TTo>(ref TFrom).
// For instance, this method will result in the following IL being emitted:
// =============================
// IL_0000: ldarg.0
// IL_0001: call instance !0 class AnimationFactory`1<!T>::get_To()
// IL_0006: box !T
// IL_000b: unbox.any !!TValue
// IL_0010: ret
// =============================
// The key point is that the JIT (and AOT compilers such as .NET Native) can recognize this
// pattern and optimize the boxing away in case the types match. This is the case whenever
// the generic arguments are value types, which due to generic types in .NET being reified
// results in a completely different generic instantiation of the same method, making the
// type arguments effectively constant values known at compile time, ie. at JIT time.
// As a result of this, the boxing is completely avoided and the value is returned directly.
// Leveraging this pattern lets us keep the same optimal codegen while avoiding the extra
// NuGet package dependency on UWP, and the more dangerous path using the Unsafe APIs.
// As an example, assuming T is float, the JIT will produce the following codegen on x64:
// =============================
// L0000: vzeroupper
// L0003: vmovss xmm0, [rcx+8]
// L0008: ret
// =============================
// We can see how the property value is loaded directly from the underlying field and
// then returned to the caller: no boxing or unwanted overhead is introduced at all.
return (TValue)(object)To;
}
/// <summary>
@ -251,7 +274,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Animations
T from = From.GetValueOrDefault();
return Unsafe.As<T, TValue>(ref from);
return (TValue)(object)from;
}
}

Просмотреть файл

@ -9,7 +9,7 @@ using System.Runtime.CompilerServices;
namespace Microsoft.Toolkit.Uwp.UI.Animations.Builders.Helpers
{
/// <summary>
/// A small generic builder type that allows to create <see cref="ReadOnlySpan{T}"/> instances.
/// A small generic builder type that allows to create <see cref="ArraySegment{T}"/> instances.
/// </summary>
/// <typeparam name="T">The type of items to create a sequence of.</typeparam>
internal struct ListBuilder<T>
@ -56,14 +56,14 @@ namespace Microsoft.Toolkit.Uwp.UI.Animations.Builders.Helpers
}
/// <summary>
/// Gets a <see cref="ReadOnlySpan{T}"/> instance with the current items.
/// Gets a <see cref="ArraySegment{T}"/> instance with the current items.
/// </summary>
/// <returns>A <see cref="ReadOnlySpan{T}"/> instance with the current items.</returns>
/// <returns>A <see cref="ArraySegment{T}"/> instance with the current items.</returns>
[Pure]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public ReadOnlySpan<T> AsSpan()
public ArraySegment<T> GetArraySegment()
{
return this.array.AsSpan(0, this.index);
return new(this.array, 0, this.index);
}
}
}

Просмотреть файл

@ -4,7 +4,6 @@
using System;
using System.Numerics;
using Microsoft.Toolkit.Diagnostics;
using Windows.UI;
using Windows.UI.Composition;
using Windows.UI.Xaml.Media.Animation;
@ -33,7 +32,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Animations
TimeSpan? delay,
TimeSpan duration,
RepeatOption repeat,
ReadOnlySpan<TKeyFrame> keyFrames)
ArraySegment<TKeyFrame> keyFrames)
where TKeyFrame : struct, IKeyFrameInfo
{
KeyFrameAnimation animation;
@ -42,7 +41,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Animations
{
BooleanKeyFrameAnimation boolAnimation = target.Compositor.CreateBooleanKeyFrameAnimation();
foreach (ref readonly var keyFrame in keyFrames)
foreach (var keyFrame in keyFrames)
{
if (keyFrame.TryInsertExpressionKeyFrame(boolAnimation, duration))
{
@ -58,7 +57,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Animations
{
ScalarKeyFrameAnimation scalarAnimation = target.Compositor.CreateScalarKeyFrameAnimation();
foreach (ref readonly var keyFrame in keyFrames)
foreach (var keyFrame in keyFrames)
{
if (keyFrame.TryInsertExpressionKeyFrame(scalarAnimation, duration))
{
@ -83,7 +82,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Animations
{
ScalarKeyFrameAnimation scalarAnimation = target.Compositor.CreateScalarKeyFrameAnimation();
foreach (ref readonly var keyFrame in keyFrames)
foreach (var keyFrame in keyFrames)
{
if (keyFrame.TryInsertExpressionKeyFrame(scalarAnimation, duration))
{
@ -108,7 +107,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Animations
{
Vector2KeyFrameAnimation vector2Animation = target.Compositor.CreateVector2KeyFrameAnimation();
foreach (ref readonly var keyFrame in keyFrames)
foreach (var keyFrame in keyFrames)
{
if (keyFrame.TryInsertExpressionKeyFrame(vector2Animation, duration))
{
@ -133,7 +132,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Animations
{
Vector3KeyFrameAnimation vector3Animation = target.Compositor.CreateVector3KeyFrameAnimation();
foreach (ref readonly var keyFrame in keyFrames)
foreach (var keyFrame in keyFrames)
{
if (keyFrame.TryInsertExpressionKeyFrame(vector3Animation, duration))
{
@ -158,7 +157,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Animations
{
Vector4KeyFrameAnimation vector4Animation = target.Compositor.CreateVector4KeyFrameAnimation();
foreach (ref readonly var keyFrame in keyFrames)
foreach (var keyFrame in keyFrames)
{
if (keyFrame.TryInsertExpressionKeyFrame(vector4Animation, duration))
{
@ -183,7 +182,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Animations
{
ColorKeyFrameAnimation colorAnimation = target.Compositor.CreateColorKeyFrameAnimation();
foreach (ref readonly var keyFrame in keyFrames)
foreach (var keyFrame in keyFrames)
{
if (keyFrame.TryInsertExpressionKeyFrame(colorAnimation, duration))
{
@ -208,7 +207,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Animations
{
QuaternionKeyFrameAnimation quaternionAnimation = target.Compositor.CreateQuaternionKeyFrameAnimation();
foreach (ref readonly var keyFrame in keyFrames)
foreach (var keyFrame in keyFrames)
{
if (keyFrame.TryInsertExpressionKeyFrame(quaternionAnimation, duration))
{
@ -231,7 +230,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Animations
}
else
{
return ThrowHelper.ThrowInvalidOperationException<CompositionAnimation>("Invalid animation type");
throw new InvalidOperationException("Invalid animation type");
}
animation.Duration = duration;
@ -284,7 +283,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Animations
this.delay,
this.duration,
this.repeat,
this.keyFrames.AsSpan());
this.keyFrames.GetArraySegment());
}
}
}

Просмотреть файл

@ -45,7 +45,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Animations
this.delay,
this.duration,
this.repeat,
this.keyFrames.AsSpan());
this.keyFrames.GetArraySegment());
}
}
}

Просмотреть файл

@ -150,7 +150,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Animations
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public TValue GetValueAs<TValue>()
{
return Unsafe.As<T, TValue>(ref Unsafe.AsRef(in this.value));
return (TValue)(object)this.value;
}
/// <inheritdoc/>

Просмотреть файл

@ -47,8 +47,8 @@ namespace Microsoft.Toolkit.Uwp.UI.Animations
// We can retrieve the total duration from the last timed keyframe, and then set
// this as the target duration and use it to normalize the keyframe progresses.
ReadOnlySpan<KeyFrameInfo> keyFrames = this.keyFrames.AsSpan();
TimeSpan duration = keyFrames[keyFrames.Length - 1].GetTimedProgress(default);
ArraySegment<KeyFrameInfo> keyFrames = this.keyFrames.GetArraySegment();
TimeSpan duration = keyFrames[keyFrames.Count - 1].GetTimedProgress(default);
return NormalizedKeyFrameAnimationBuilder<T>.GetAnimation(
targetHint,

Просмотреть файл

@ -3,7 +3,6 @@
// See the LICENSE file in the project root for more information.
using System;
using Microsoft.Toolkit.Diagnostics;
using Windows.Foundation;
using Windows.UI;
using Windows.UI.Xaml;
@ -32,7 +31,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Animations
TimeSpan? delay,
TimeSpan duration,
RepeatOption repeat,
ReadOnlySpan<TKeyFrame> keyFrames)
ArraySegment<TKeyFrame> keyFrames)
where TKeyFrame : struct, IKeyFrameInfo
{
Timeline animation;
@ -118,7 +117,9 @@ namespace Microsoft.Toolkit.Uwp.UI.Animations
}
else
{
return ThrowHelper.ThrowInvalidOperationException<Timeline>("Invalid animation type");
static Timeline ThrowInvalidOperationException() => throw new InvalidOperationException("Invalid animation type");
return ThrowInvalidOperationException();
}
animation.BeginTime = delay;
@ -163,7 +164,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Animations
this.delay,
default,
this.repeat,
this.keyFrames.AsSpan());
this.keyFrames.GetArraySegment());
}
}
}

Просмотреть файл

@ -143,7 +143,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Animations
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public TValue GetValueAs<TValue>()
{
return Unsafe.As<T, TValue>(ref Unsafe.AsRef(in this.value));
return (TValue)(object)this.value;
}
/// <inheritdoc/>

Просмотреть файл

@ -1,170 +0,0 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Numerics;
using Windows.UI.Composition;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Hosting;
using Windows.UI.Xaml.Media.Animation;
namespace Microsoft.Toolkit.Uwp.UI.Animations.Effects
{
/// <summary>
/// An abstract class that provides the mechanism to create
/// an effect using composition.
/// </summary>
public abstract class AnimationEffect
{
private static string[] _effectProperties;
/// <summary>
/// Gets the name of the effect.
/// </summary>
/// <value>
/// The name of the effect.
/// </value>
public abstract string EffectName { get; }
/// <summary>
/// Gets or sets the compositor.
/// </summary>
/// <value>
/// The compositor.
/// </value>
public Compositor Compositor { get; set; }
/// <summary>
/// Gets or sets the effect brush.
/// </summary>
/// <value>
/// The effect brush.
/// </value>
public CompositionEffectBrush EffectBrush { get; set; }
/// <summary>
/// Applies the effect.
/// </summary>
/// <returns>An array of strings of the effect properties to change.</returns>
public abstract string[] ApplyEffect();
/// <summary>
/// An animation which will apply the derived effect.
/// </summary>
/// <param name="animationSet">The animation set.</param>
/// <param name="value">The value.</param>
/// <param name="duration">The duration in milliseconds.</param>
/// <param name="delay">The delay in milliseconds.</param>
/// <param name="easingType">The easing function to use</param>
/// <param name="easingMode">The easing mode to use</param>
/// <returns>An animation set with the effect added to it.</returns>
public AnimationSet EffectAnimation(
AnimationSet animationSet,
double value = 0d,
double duration = 500d,
double delay = 0d,
EasingType easingType = EasingType.Default,
EasingMode easingMode = EasingMode.EaseOut)
{
if (animationSet == null)
{
return null;
}
var visual = animationSet.Visual;
var associatedObject = animationSet.Element as FrameworkElement;
if (associatedObject == null)
{
return animationSet;
}
Compositor = visual?.Compositor;
if (Compositor == null)
{
return null;
}
// check to see if the visual already has an effect applied.
var spriteVisual = ElementCompositionPreview.GetElementChildVisual(associatedObject) as SpriteVisual;
EffectBrush = spriteVisual?.Brush as CompositionEffectBrush;
if (EffectBrush == null || EffectBrush?.Comment != EffectName)
{
_effectProperties = ApplyEffect();
EffectBrush.Comment = EffectName;
var sprite = Compositor.CreateSpriteVisual();
sprite.Brush = EffectBrush;
ElementCompositionPreview.SetElementChildVisual(associatedObject, sprite);
sprite.Size = new Vector2((float)associatedObject.ActualWidth, (float)associatedObject.ActualHeight);
associatedObject.SizeChanged +=
(s, e) =>
{
sprite.Size = new Vector2(
(float)associatedObject.ActualWidth,
(float)associatedObject.ActualHeight);
};
}
if (duration <= 0)
{
foreach (var effectProperty in _effectProperties)
{
animationSet.AddEffectDirectPropertyChange(EffectBrush, (float)value, effectProperty);
}
}
else
{
foreach (var effectProperty in _effectProperties)
{
var animation = Compositor.CreateScalarKeyFrameAnimation();
animation.InsertKeyFrame(1f, (float)value, AnimationExtensions.GetCompositionEasingFunction(easingType, Compositor, easingMode));
animation.Duration = TimeSpan.FromMilliseconds(duration);
animation.DelayTime = TimeSpan.FromMilliseconds(delay);
animationSet.AddCompositionEffectAnimation(EffectBrush, animation, effectProperty);
}
}
// Saturation starts from 1 to 0, instead of 0 to 1 so this makes sure the
// the brush isn't removed from the UI element incorrectly. Completing on
// Saturation as it's reusing the same sprite visual. Removing the Sprite removes the effect.
if (EffectName != "Saturation" && value == 0)
{
animationSet.Completed += AnimationSet_Completed;
}
return animationSet;
}
/// <summary>
/// Handles the Completed event of the AnimationSet control.
/// When an animation is completed the brush is removed from the sprite.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param>
private void AnimationSet_Completed(object sender, EventArgs e)
{
var animationSet = sender as AnimationSet;
if (animationSet != null)
{
animationSet.Completed -= AnimationSet_Completed;
var spriteVisual = ElementCompositionPreview.GetElementChildVisual(animationSet.Element) as SpriteVisual;
var brush = spriteVisual?.Brush as CompositionEffectBrush;
if (brush != null && brush.Comment == EffectName)
{
spriteVisual.Brush = null;
}
}
}
}
}

Просмотреть файл

@ -1,50 +0,0 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using Microsoft.Graphics.Canvas.Effects;
using Windows.UI.Composition;
namespace Microsoft.Toolkit.Uwp.UI.Animations.Effects
{
/// <summary>
/// An animation effect that applies blur.
/// </summary>
/// <seealso cref="Microsoft.Toolkit.Uwp.UI.Animations.Effects.AnimationEffect" />
public class Blur : AnimationEffect
{
/// <summary>
/// Gets the name of the effect.
/// </summary>
/// <value>
/// The name of the effect.
/// </value>
public override string EffectName { get; } = "Blur";
/// <summary>
/// Applies the effect.
/// </summary>
/// <returns>
/// An array of strings of the effect properties to change.
/// </returns>
public override string[] ApplyEffect()
{
var gaussianBlur = new GaussianBlurEffect
{
Name = EffectName,
BlurAmount = 0f,
Optimization = EffectOptimization.Balanced,
BorderMode = EffectBorderMode.Hard,
Source = new CompositionEffectSourceParameter("source")
};
var propertyToChange = $"{EffectName}.BlurAmount";
var propertiesToAnimate = new[] { propertyToChange };
EffectBrush = Compositor.CreateEffectFactory(gaussianBlur, propertiesToAnimate).CreateBrush();
EffectBrush.SetSourceParameter("source", Compositor.CreateBackdropBrush());
return propertiesToAnimate;
}
}
}

Просмотреть файл

@ -1,48 +0,0 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using Microsoft.Graphics.Canvas.Effects;
using Windows.UI.Composition;
namespace Microsoft.Toolkit.Uwp.UI.Animations.Effects
{
/// <summary>
/// An animation effect that applies saturation.
/// </summary>
/// <seealso cref="Microsoft.Toolkit.Uwp.UI.Animations.Effects.AnimationEffect" />
public class Saturation : AnimationEffect
{
/// <summary>
/// Gets the name of the effect.
/// </summary>
/// <value>
/// The name of the effect.
/// </value>
public override string EffectName { get; } = "Saturation";
/// <summary>
/// Applies the effect.
/// </summary>
/// <returns>
/// An array of strings of the effect properties to change.
/// </returns>
public override string[] ApplyEffect()
{
var saturationEffect = new SaturationEffect
{
Saturation = 1f,
Name = EffectName,
Source = new CompositionEffectSourceParameter("source")
};
var propertyToChange = $"{EffectName}.Saturation";
var propertiesToAnimate = new[] { propertyToChange };
EffectBrush = Compositor.CreateEffectFactory(saturationEffect, propertiesToAnimate).CreateBrush();
EffectBrush.SetSourceParameter("source", Compositor.CreateBackdropBrush());
return propertiesToAnimate;
}
}
}

Просмотреть файл

@ -6,7 +6,6 @@ using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.Numerics;
using Microsoft.Toolkit.Diagnostics;
using Windows.UI.Composition;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Media;
@ -111,7 +110,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Animations
Axis.X => "AnchorPoint.X",
Axis.Y => "AnchorPoint.Y",
Axis.Z => "AnchorPoint.Z",
_ => ThrowHelper.ThrowArgumentException<string>("Invalid axis")
_ => ThrowArgumentException<string>("Invalid axis")
};
/// <summary>
@ -132,7 +131,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Animations
Axis.X => "Translation.X",
Axis.Y => "Translation.Y",
Axis.Z => "Translation.Z",
_ => ThrowHelper.ThrowArgumentException<string>("Invalid axis")
_ => ThrowArgumentException<string>("Invalid axis")
};
/// <summary>
@ -153,7 +152,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Animations
Axis.X => "Offset.X",
Axis.Y => "Offset.Y",
Axis.Z => "Offset.Z",
_ => ThrowHelper.ThrowArgumentException<string>("Invalid axis")
_ => ThrowArgumentException<string>("Invalid axis")
};
/// <summary>
@ -174,7 +173,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Animations
Axis.X => "Scale.X",
Axis.Y => "Scale.Y",
Axis.Z => "Scale.Z",
_ => ThrowHelper.ThrowArgumentException<string>("Invalid axis")
_ => ThrowArgumentException<string>("Invalid axis")
};
/// <summary>
@ -195,7 +194,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Animations
Axis.X => "CenterPoint.X",
Axis.Y => "CenterPoint.Y",
Axis.Z => "CenterPoint.Z",
_ => ThrowHelper.ThrowArgumentException<string>("Invalid axis")
_ => ThrowArgumentException<string>("Invalid axis")
};
/// <summary>
@ -217,7 +216,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Animations
Side.Bottom => nameof(InsetClip.BottomInset),
Side.Right => nameof(InsetClip.RightInset),
Side.Left => nameof(InsetClip.LeftInset),
_ => ThrowHelper.ThrowArgumentException<string>("Invalid clip side")
_ => ThrowArgumentException<string>("Invalid clip side")
};
/// <summary>
@ -238,7 +237,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Animations
Axis.X => "Size.X",
Axis.Y => "Size.Y",
Axis.Z => "Size.Z",
_ => ThrowHelper.ThrowArgumentException<string>("Invalid axis")
_ => ThrowArgumentException<string>("Invalid axis")
};
}
@ -257,7 +256,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Animations
{
Axis.X => nameof(CompositeTransform.TranslateX),
Axis.Y => nameof(CompositeTransform.TranslateY),
_ => ThrowHelper.ThrowArgumentException<string>("Invalid axis")
_ => ThrowArgumentException<string>("Invalid axis")
};
/// <summary>
@ -270,7 +269,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Animations
{
Axis.X => nameof(CompositeTransform.ScaleX),
Axis.Y => nameof(CompositeTransform.ScaleY),
_ => ThrowHelper.ThrowArgumentException<string>("Invalid axis")
_ => ThrowArgumentException<string>("Invalid axis")
};
/// <summary>
@ -283,7 +282,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Animations
{
Axis.X => nameof(CompositeTransform.CenterX),
Axis.Y => nameof(CompositeTransform.CenterY),
_ => ThrowHelper.ThrowArgumentException<string>("Invalid axis")
_ => ThrowArgumentException<string>("Invalid axis")
};
/// <summary>
@ -296,9 +295,17 @@ namespace Microsoft.Toolkit.Uwp.UI.Animations
{
Axis.X => nameof(FrameworkElement.Width),
Axis.Y => nameof(FrameworkElement.Height),
_ => ThrowHelper.ThrowArgumentException<string>("Invalid axis")
_ => ThrowArgumentException<string>("Invalid axis")
};
}
/// <summary>
/// Throws a new <see cref="ArgumentException"/> with a given message.
/// </summary>
private static T ThrowArgumentException<T>(string message)
{
throw new ArgumentException(message);
}
}
}
}

Просмотреть файл

@ -4,8 +4,8 @@
#nullable enable
using System;
using System.Diagnostics.Contracts;
using Microsoft.Toolkit.Diagnostics;
using Windows.UI.Xaml.Media.Animation;
using static Microsoft.Toolkit.Uwp.UI.Animations.AnimationExtensions;
@ -46,8 +46,10 @@ namespace Microsoft.Toolkit.Uwp.UI.Animations
EasingType.Quintic => new QuinticEase { EasingMode = easingMode },
EasingType.Sine => new SineEase { EasingMode = easingMode },
_ => ThrowHelper.ThrowArgumentException<EasingFunctionBase?>("Invalid easing type")
_ => ThrowArgumentException()
};
static EasingFunctionBase ThrowArgumentException() => throw new ArgumentException("Invalid easing type");
}
}
}

Просмотреть файл

@ -2,8 +2,8 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Numerics;
using Microsoft.Toolkit.Diagnostics;
using Windows.UI.Composition;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
@ -66,11 +66,13 @@ namespace Microsoft.Toolkit.Uwp.UI.Animations
visual.StartAnimation($"{nameof(Visual.Offset)}.{targetAxis}", animation);
break;
default:
ThrowHelper.ThrowArgumentException("Invalid target property");
ThrowArgumentException();
break;
}
return animation;
static ExpressionAnimation ThrowArgumentException() => throw new ArgumentException("Invalid target property");
}
}
}

Просмотреть файл

@ -18,22 +18,6 @@
<LangVersion>9.0</LangVersion>
</PropertyGroup>
<!-- TODO: Figure out where these go... -->
<ItemGroup>
<Compile Remove="Behaviors\**" />
<Compile Remove="Effects\**" />
<Compile Remove="fg\**" />
<EmbeddedResource Remove="Behaviors\**" />
<EmbeddedResource Remove="Effects\**" />
<EmbeddedResource Remove="fg\**" />
<None Remove="Behaviors\**" />
<None Remove="Effects\**" />
<None Remove="fg\**" />
<Page Remove="Behaviors\**" />
<Page Remove="Effects\**" />
<Page Remove="fg\**" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="System.ValueTuple" Version="4.5.0" />
<ProjectReference Include="..\Microsoft.Toolkit.Uwp.UI\Microsoft.Toolkit.Uwp.UI.csproj" />

Просмотреть файл

@ -4,7 +4,6 @@
using System;
using System.Diagnostics.Contracts;
using Microsoft.Toolkit.Diagnostics;
using Windows.Foundation.Metadata;
using Windows.UI.Composition;
using Windows.UI.Xaml.Media.Animation;
@ -52,7 +51,10 @@ namespace Microsoft.Toolkit.Uwp.UI.Animations
[Pure]
public static RepeatOption Count(int count)
{
Guard.IsGreaterThanOrEqualTo(count, 0, nameof(count));
if (count < 0)
{
ThrowArgumentOutOfRangeForCount();
}
return new(count);
}
@ -76,7 +78,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Animations
return Forever;
}
return ThrowHelper.ThrowArgumentException<RepeatOption>("Invalid input text");
return ThrowArgumentExceptionForText();
}
/// <summary>
@ -109,5 +111,21 @@ namespace Microsoft.Toolkit.Uwp.UI.Animations
return (AnimationIterationBehavior.Count, this.value);
}
/// <summary>
/// Throws a new <see cref="ArgumentOutOfRangeException"/> when the constructor is invoked with an incorrect parameter.
/// </summary>
private static void ThrowArgumentOutOfRangeForCount()
{
throw new ArgumentOutOfRangeException("The parameter \"count\" must be greater than or equal to 0.");
}
/// <summary>
/// Throws a new <see cref="ArgumentOutOfRangeException"/> when the constructor is invoked with an incorrect parameter.
/// </summary>
private static RepeatOption ThrowArgumentExceptionForText()
{
throw new ArgumentException("The input text is not valid to parse a new RepeatOption instance. It must be either a natural number or \"Forever\".");
}
}
}

Просмотреть файл

@ -2,9 +2,9 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Toolkit.Diagnostics;
using Windows.UI.Xaml;
namespace Microsoft.Toolkit.Uwp.UI.Animations
@ -53,7 +53,10 @@ namespace Microsoft.Toolkit.Uwp.UI.Animations
/// <inheritdoc/>
public override async Task InvokeAsync(UIElement element, CancellationToken token)
{
Guard.IsNotNull(Animation, nameof(Animation));
if (Animation is null)
{
ThrowArgumentNullException();
}
await base.InvokeAsync(element, token);
@ -72,6 +75,8 @@ namespace Microsoft.Toolkit.Uwp.UI.Animations
{
await Animation.StartAsync(token);
}
static void ThrowArgumentNullException() => throw new ArgumentNullException(nameof(Animation));
}
}
}

Просмотреть файл

@ -2,9 +2,9 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Toolkit.Diagnostics;
using Windows.UI.Xaml;
namespace Microsoft.Toolkit.Uwp.UI.Animations
@ -53,7 +53,10 @@ namespace Microsoft.Toolkit.Uwp.UI.Animations
/// <inheritdoc/>
public override async Task InvokeAsync(UIElement element, CancellationToken token)
{
Guard.IsNotNull(Animation, nameof(Animation));
if (Animation is null)
{
ThrowArgumentNullException();
}
await base.InvokeAsync(element, token);
@ -69,6 +72,8 @@ namespace Microsoft.Toolkit.Uwp.UI.Animations
{
Animation.Stop();
}
static void ThrowArgumentNullException() => throw new ArgumentNullException(nameof(Animation));
}
}
}

Просмотреть файл

@ -9,7 +9,6 @@ using System.Diagnostics.Contracts;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Toolkit.Diagnostics;
using Windows.UI.Xaml;
namespace Microsoft.Toolkit.Uwp.UI.Animations
@ -33,16 +32,9 @@ namespace Microsoft.Toolkit.Uwp.UI.Animations
public event EventHandler? Started;
/// <summary>
/// Raised whenever the current animation ends.
/// Raised whenever the current animation completes.
/// </summary>
public event EventHandler? Ended;
/// <summary>
/// An interface representing a node in an <see cref="AnimationSet"/> instance.
/// </summary>
public interface INode
{
}
public event EventHandler? Completed;
/// <summary>
/// Gets or sets a value indicating whether top level animation nodes in this collection are invoked
@ -74,7 +66,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Animations
// Here we're using an async void method on purpose, in order to be able to await
// the completion of the animation and rethrow exceptions. We can't just use the
// synchronous AnimationBuilder.Start method here, as we also need to await for the
// animation to complete in either case in order to raise the Ended event when that
// animation to complete in either case in order to raise the Completed event when that
// happens. So we add an async state machine here to work around this.
await StartAsync();
}
@ -125,7 +117,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Animations
if (IsSequential)
{
foreach (INode node in this)
foreach (object node in this)
{
if (node is ITimeline timeline)
{
@ -152,6 +144,10 @@ namespace Microsoft.Toolkit.Uwp.UI.Animations
break;
}
}
else
{
ThrowArgumentException();
}
// This should in theory only be necessary in the timeline branch, but doing this check
// after running activities too help guard against 3rd party activities that might not
@ -166,7 +162,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Animations
{
var builder = AnimationBuilder.Create();
foreach (INode node in this)
foreach (object node in this)
{
switch (node)
{
@ -176,13 +172,18 @@ namespace Microsoft.Toolkit.Uwp.UI.Animations
case IActivity activity:
_ = activity.InvokeAsync(element, token);
break;
default:
ThrowArgumentException();
break;
}
}
await builder.StartAsync(element, token);
}
Ended?.Invoke(this, EventArgs.Empty);
Completed?.Invoke(this, EventArgs.Empty);
static void ThrowArgumentException() => throw new ArgumentException($"An animation set can only contain nodes implementing either ITimeline or IActivity");
}
/// <summary>
@ -218,10 +219,12 @@ namespace Microsoft.Toolkit.Uwp.UI.Animations
if (ParentReference?.TryGetTarget(out parent) != true)
{
ThrowHelper.ThrowInvalidOperationException("The current animation collection isn't bound to a parent UIElement instance.");
ThrowInvalidOperationException();
}
return parent!;
static void ThrowInvalidOperationException() => throw new InvalidOperationException("The current AnimationSet object isn't bound to a parent UIElement instance.");
}
}
}

Просмотреть файл

@ -6,7 +6,6 @@
using System;
using System.Diagnostics.Contracts;
using Microsoft.Toolkit.Diagnostics;
using Windows.UI.Composition;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Hosting;
@ -85,10 +84,12 @@ namespace Microsoft.Toolkit.Uwp.UI.Animations
if (ParentReference?.TryGetTarget(out parent) != true)
{
ThrowHelper.ThrowInvalidOperationException("The current animation collection isn't bound to a parent UIElement instance.");
ThrowInvalidOperationException();
}
return parent!;
static void ThrowInvalidOperationException() => throw new InvalidOperationException("The current ImplicitAnimationSet object isn't bound to a parent UIElement instance.");
}
}
}

Просмотреть файл

@ -11,7 +11,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Animations
/// <summary>
/// An interface representing a XAML model for a custom activity or action within an <see cref="AnimationSet"/>.
/// </summary>
public interface IActivity : AnimationSet.INode
public interface IActivity
{
/// <summary>
/// Invokes the current activity.

Просмотреть файл

@ -10,7 +10,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Animations
/// <summary>
/// An interface representing a XAML model for a custom animation.
/// </summary>
public interface ITimeline : AnimationSet.INode
public interface ITimeline
{
/// <summary>
/// Appens the current animation to a target <see cref="AnimationBuilder"/> instance.

Просмотреть файл

@ -10,9 +10,9 @@ using Microsoft.Xaml.Interactivity;
namespace Microsoft.Toolkit.Uwp.UI.Behaviors
{
/// <summary>
/// A custom <see cref="Trigger"/> that fires whenever a linked <see cref="AnimationSet"/> ends.
/// A custom <see cref="Trigger"/> that fires whenever a linked <see cref="AnimationSet"/> completes.
/// </summary>
public sealed class AnimationEndBehavior : Trigger<AnimationSet>
public sealed class AnimationCompletedTriggerBehavior : Trigger<AnimationSet>
{
/// <summary>
/// The current <see cref="AnimationSet"/> instance in use.
@ -48,14 +48,14 @@ namespace Microsoft.Toolkit.Uwp.UI.Behaviors
if (this.animationCollection is not null)
{
this.animationCollection.Ended -= AnimationCollection_Ended;
this.animationCollection.Completed -= AnimationCollection_Completed;
}
this.animationCollection = animationCollection;
if (animationCollection is not null)
{
animationCollection.Ended += AnimationCollection_Ended;
animationCollection.Completed += AnimationCollection_Completed;
}
}
@ -64,7 +64,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Behaviors
/// </summary>
/// <param name="sender">The source <see cref="AnimationSet"/> instance.</param>
/// <param name="e">The arguments for the event (unused).</param>
private void AnimationCollection_Ended(object sender, System.EventArgs e)
private void AnimationCollection_Completed(object sender, System.EventArgs e)
{
Interaction.ExecuteActions(sender, Actions, e);
}

Просмотреть файл

@ -12,7 +12,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Behaviors
/// <summary>
/// A custom <see cref="Trigger"/> that fires whenever a linked <see cref="AnimationSet"/> starts.
/// </summary>
public sealed class AnimationStartBehavior : Trigger<AnimationSet>
public sealed class AnimationStartedTriggerBehavior : Trigger<AnimationSet>
{
/// <summary>
/// The current <see cref="AnimationSet"/> instance in use.

Просмотреть файл

@ -2,7 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using Microsoft.Toolkit.Diagnostics;
using System;
using Microsoft.Toolkit.Uwp.UI.Animations;
using Microsoft.Xaml.Interactivity;
using Windows.UI.Xaml;
@ -53,7 +53,10 @@ namespace Microsoft.Toolkit.Uwp.UI.Behaviors
/// <inheritdoc/>
public object Execute(object sender, object parameter)
{
Guard.IsNotNull(Animation, nameof(Animation));
if (Animation is null)
{
ThrowArgumentNullException();
}
if (TargetObject is not null)
{
@ -65,6 +68,8 @@ namespace Microsoft.Toolkit.Uwp.UI.Behaviors
}
return null!;
static void ThrowArgumentNullException() => throw new ArgumentNullException(nameof(Animation));
}
}
}

Просмотреть файл

@ -2,7 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using Microsoft.Toolkit.Diagnostics;
using System;
using Microsoft.Toolkit.Uwp.UI.Animations;
using Microsoft.Xaml.Interactivity;
using Windows.UI.Xaml;
@ -53,7 +53,10 @@ namespace Microsoft.Toolkit.Uwp.UI.Behaviors
/// <inheritdoc/>
public object Execute(object sender, object parameter)
{
Guard.IsNotNull(Animation, nameof(Animation));
if (Animation is null)
{
ThrowArgumentNullException();
}
if (TargetObject is not null)
{
@ -65,6 +68,8 @@ namespace Microsoft.Toolkit.Uwp.UI.Behaviors
}
return null!;
static void ThrowArgumentNullException() => throw new ArgumentNullException(nameof(Animation));
}
}
}

Просмотреть файл

@ -0,0 +1,28 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.ComponentModel;
using Microsoft.Toolkit.Uwp.UI.Controls.Design.Properties;
using Microsoft.VisualStudio.DesignTools.Extensibility;
using Microsoft.VisualStudio.DesignTools.Extensibility.Metadata;
namespace Microsoft.Toolkit.Uwp.UI.Controls.Design
{
internal class TabbedCommandBarMetadata : AttributeTableBuilder
{
public TabbedCommandBarMetadata()
: base()
{
AddCallback(ControlTypes.TabbedCommandBar,
b =>
{
b.AddCustomAttributes(nameof(TabbedCommandBar.CollapsedState), new CategoryAttribute(Resources.CategoryAppearance));
b.AddCustomAttributes(new ToolboxCategoryAttribute(ToolboxCategoryPaths.Toolkit, false));
}
);
}
}
}

Просмотреть файл

@ -0,0 +1,18 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
namespace Microsoft.Toolkit.Uwp.UI.Controls.Design
{
internal static partial class ControlTypes
{
internal const string TabbedCommandBar = RootNamespace + "." + nameof(TabbedCommandBar);
}
internal static class TabbedCommandBar
{
internal const string CollapsedState = nameof(CollapsedState);
}
}

Просмотреть файл

@ -0,0 +1,35 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.ComponentModel;
using Microsoft.Toolkit.Uwp.UI.Controls.Design.Properties;
using Microsoft.VisualStudio.DesignTools.Extensibility;
using Microsoft.VisualStudio.DesignTools.Extensibility.Metadata;
namespace Microsoft.Toolkit.Uwp.UI.Controls.Design
{
internal class TabbedCommandBarItemMetadata : AttributeTableBuilder
{
public TabbedCommandBarItemMetadata()
: base()
{
AddCallback(ControlTypes.TabbedCommandBarItem,
b =>
{
// TODO
// b.AddCustomAttributes(nameof(TabbedCommandBarItem.Header), new CategoryAttribute(Resources.CategoryCommon));
// b.AddCustomAttributes(nameof(TabbedCommandBarItem.Footer), new CategoryAttribute(Resources.CategoryCommon));
b.AddCustomAttributes(nameof(TabbedCommandBarItem.IsContextual), new CategoryAttribute(Resources.CategoryCommon));
b.AddCustomAttributes(nameof(TabbedCommandBarItem.OverflowButtonAlignment),
new CategoryAttribute(Resources.CategoryLayout),
new EditorBrowsableAttribute(EditorBrowsableState.Advanced)
);
b.AddCustomAttributes(new ToolboxCategoryAttribute(ToolboxCategoryPaths.Toolkit, false));
}
);
}
}
}

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше