61 changed files with 1344 additions and 499 deletions
@ -0,0 +1,56 @@ |
|||
// Copyright (c) The Perspex Project. All rights reserved.
|
|||
// Licensed under the MIT license. See licence.md file in the project root for full license information.
|
|||
|
|||
using System; |
|||
using Perspex.LogicalTree; |
|||
|
|||
namespace Perspex.Styling |
|||
{ |
|||
internal class ChildSelector : Selector |
|||
{ |
|||
private readonly Selector _parent; |
|||
private string _selectorString; |
|||
|
|||
public ChildSelector(Selector parent) |
|||
{ |
|||
if (parent == null) |
|||
{ |
|||
throw new InvalidOperationException("Child selector must be preceeded by a selector."); |
|||
} |
|||
|
|||
_parent = parent; |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public override bool InTemplate => _parent.InTemplate; |
|||
|
|||
/// <inheritdoc/>
|
|||
public override Type TargetType => null; |
|||
|
|||
public override string ToString() |
|||
{ |
|||
if (_selectorString == null) |
|||
{ |
|||
_selectorString = _parent.ToString() + " > "; |
|||
} |
|||
|
|||
return _selectorString; |
|||
} |
|||
|
|||
protected override SelectorMatch Evaluate(IStyleable control, bool subscribe) |
|||
{ |
|||
var controlParent = ((ILogical)control).LogicalParent; |
|||
|
|||
if (controlParent != null) |
|||
{ |
|||
return _parent.Match((IStyleable)controlParent, subscribe); |
|||
} |
|||
else |
|||
{ |
|||
return SelectorMatch.False; |
|||
} |
|||
} |
|||
|
|||
protected override Selector MovePrevious() => null; |
|||
} |
|||
} |
|||
@ -0,0 +1,80 @@ |
|||
// Copyright (c) The Perspex Project. All rights reserved.
|
|||
// Licensed under the MIT license. See licence.md file in the project root for full license information.
|
|||
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using Perspex.LogicalTree; |
|||
|
|||
namespace Perspex.Styling |
|||
{ |
|||
internal class DescendentSelector : Selector |
|||
{ |
|||
private readonly Selector _parent; |
|||
private string _selectorString; |
|||
|
|||
public DescendentSelector(Selector parent) |
|||
{ |
|||
if (parent == null) |
|||
{ |
|||
throw new InvalidOperationException("Descendent selector must be preceeded by a selector."); |
|||
} |
|||
|
|||
_parent = parent; |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public override bool InTemplate => _parent.InTemplate; |
|||
|
|||
/// <inheritdoc/>
|
|||
public override Type TargetType => null; |
|||
|
|||
public override string ToString() |
|||
{ |
|||
if (_selectorString == null) |
|||
{ |
|||
_selectorString = _parent.ToString() + ' '; |
|||
} |
|||
|
|||
return _selectorString; |
|||
} |
|||
|
|||
protected override SelectorMatch Evaluate(IStyleable control, bool subscribe) |
|||
{ |
|||
ILogical c = (ILogical)control; |
|||
List<IObservable<bool>> descendentMatches = new List<IObservable<bool>>(); |
|||
|
|||
while (c != null) |
|||
{ |
|||
c = c.LogicalParent; |
|||
|
|||
if (c is IStyleable) |
|||
{ |
|||
var match = _parent.Match((IStyleable)c, subscribe); |
|||
|
|||
if (match.ImmediateResult != null) |
|||
{ |
|||
if (match.ImmediateResult == true) |
|||
{ |
|||
return SelectorMatch.True; |
|||
} |
|||
} |
|||
else |
|||
{ |
|||
descendentMatches.Add(match.ObservableResult); |
|||
} |
|||
} |
|||
} |
|||
|
|||
if (descendentMatches.Count > 0) |
|||
{ |
|||
return new SelectorMatch(StyleActivator.Or(descendentMatches)); |
|||
} |
|||
else |
|||
{ |
|||
return SelectorMatch.False; |
|||
} |
|||
} |
|||
|
|||
protected override Selector MovePrevious() => null; |
|||
} |
|||
} |
|||
@ -0,0 +1,91 @@ |
|||
// Copyright (c) The Perspex Project. All rights reserved.
|
|||
// Licensed under the MIT license. See licence.md file in the project root for full license information.
|
|||
|
|||
using System; |
|||
using System.Reactive.Linq; |
|||
using System.Text; |
|||
|
|||
namespace Perspex.Styling |
|||
{ |
|||
/// <summary>
|
|||
/// A selector that matches the common case of a type and/or name followed by a collection of
|
|||
/// style classes and pseudoclasses.
|
|||
/// </summary>
|
|||
internal class PropertyEqualsSelector : Selector |
|||
{ |
|||
private readonly Selector _previous; |
|||
private readonly PerspexProperty _property; |
|||
private readonly object _value; |
|||
private string _selectorString; |
|||
|
|||
public PropertyEqualsSelector(Selector previous, PerspexProperty property, object value) |
|||
{ |
|||
Contract.Requires<ArgumentNullException>(property != null); |
|||
|
|||
_previous = previous; |
|||
_property = property; |
|||
_value = value; |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public override bool InTemplate => _previous?.InTemplate ?? false; |
|||
|
|||
/// <summary>
|
|||
/// Gets the name of the control to match.
|
|||
/// </summary>
|
|||
public string Name { get; private set; } |
|||
|
|||
/// <inheritdoc/>
|
|||
public override Type TargetType => _previous?.TargetType; |
|||
|
|||
/// <inheritdoc/>
|
|||
public override string ToString() |
|||
{ |
|||
if (_selectorString == null) |
|||
{ |
|||
var builder = new StringBuilder(); |
|||
|
|||
if (_previous != null) |
|||
{ |
|||
builder.Append(_previous.ToString()); |
|||
} |
|||
|
|||
builder.Append('['); |
|||
|
|||
if (_property.IsAttached) |
|||
{ |
|||
builder.Append(_property.OwnerType.Name); |
|||
builder.Append('.'); |
|||
} |
|||
|
|||
builder.Append(_property.Name); |
|||
builder.Append('='); |
|||
builder.Append(_value); |
|||
builder.Append(']'); |
|||
|
|||
_selectorString = builder.ToString(); |
|||
} |
|||
|
|||
return _selectorString; |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
protected override SelectorMatch Evaluate(IStyleable control, bool subscribe) |
|||
{ |
|||
if (!PerspexPropertyRegistry.Instance.IsRegistered(control, _property)) |
|||
{ |
|||
return SelectorMatch.False; |
|||
} |
|||
else if (subscribe) |
|||
{ |
|||
return new SelectorMatch(control.GetObservable(_property).Select(v => Equals(v, _value))); |
|||
} |
|||
else |
|||
{ |
|||
return new SelectorMatch(control.GetValue(_property).Equals(_value)); |
|||
} |
|||
} |
|||
|
|||
protected override Selector MovePrevious() => _previous; |
|||
} |
|||
} |
|||
@ -0,0 +1,54 @@ |
|||
// Copyright (c) The Perspex Project. All rights reserved.
|
|||
// Licensed under the MIT license. See licence.md file in the project root for full license information.
|
|||
|
|||
using System; |
|||
|
|||
namespace Perspex.Styling |
|||
{ |
|||
internal class TemplateSelector : Selector |
|||
{ |
|||
private readonly Selector _parent; |
|||
private string _selectorString; |
|||
|
|||
public TemplateSelector(Selector parent) |
|||
{ |
|||
if (parent == null) |
|||
{ |
|||
throw new InvalidOperationException("Template selector must be preceeded by a selector."); |
|||
} |
|||
|
|||
_parent = parent; |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public override bool InTemplate => true; |
|||
|
|||
/// <inheritdoc/>
|
|||
public override Type TargetType => null; |
|||
|
|||
public override string ToString() |
|||
{ |
|||
if (_selectorString == null) |
|||
{ |
|||
_selectorString = _parent.ToString() + " /template/ "; |
|||
} |
|||
|
|||
return _selectorString; |
|||
} |
|||
|
|||
protected override SelectorMatch Evaluate(IStyleable control, bool subscribe) |
|||
{ |
|||
IStyleable templatedParent = control.TemplatedParent as IStyleable; |
|||
|
|||
if (templatedParent == null) |
|||
{ |
|||
throw new InvalidOperationException( |
|||
"Cannot call Template selector on control with null TemplatedParent."); |
|||
} |
|||
|
|||
return _parent.Match(templatedParent, subscribe) ?? SelectorMatch.True; |
|||
} |
|||
|
|||
protected override Selector MovePrevious() => null; |
|||
} |
|||
} |
|||
@ -0,0 +1,207 @@ |
|||
// Copyright (c) The Perspex Project. All rights reserved.
|
|||
// Licensed under the MIT license. See licence.md file in the project root for full license information.
|
|||
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Collections.Specialized; |
|||
using System.Reactive; |
|||
using System.Reactive.Linq; |
|||
using System.Reflection; |
|||
using System.Text; |
|||
|
|||
namespace Perspex.Styling |
|||
{ |
|||
/// <summary>
|
|||
/// A selector that matches the common case of a type and/or name followed by a collection of
|
|||
/// style classes and pseudoclasses.
|
|||
/// </summary>
|
|||
internal class TypeNameAndClassSelector : Selector |
|||
{ |
|||
private readonly Selector _previous; |
|||
private Type _targetType; |
|||
private Lazy<List<string>> _classes = new Lazy<List<string>>(() => new List<string>()); |
|||
private string _selectorString; |
|||
|
|||
public static TypeNameAndClassSelector OfType(Selector previous, Type targetType) |
|||
{ |
|||
var result = new TypeNameAndClassSelector(previous); |
|||
result._targetType = targetType; |
|||
result.IsConcreteType = true; |
|||
return result; |
|||
} |
|||
|
|||
public static TypeNameAndClassSelector Is(Selector previous, Type targetType) |
|||
{ |
|||
var result = new TypeNameAndClassSelector(previous); |
|||
result._targetType = targetType; |
|||
result.IsConcreteType = false; |
|||
return result; |
|||
} |
|||
|
|||
public static TypeNameAndClassSelector ForName(Selector previous, string name) |
|||
{ |
|||
var result = new TypeNameAndClassSelector(previous); |
|||
result.Name = name; |
|||
return result; |
|||
} |
|||
|
|||
public static TypeNameAndClassSelector ForClass(Selector previous, string className) |
|||
{ |
|||
var result = new TypeNameAndClassSelector(previous); |
|||
result.Classes.Add(className); |
|||
return result; |
|||
} |
|||
|
|||
protected TypeNameAndClassSelector(Selector previous) |
|||
{ |
|||
_previous = previous; |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public override bool InTemplate => _previous?.InTemplate ?? false; |
|||
|
|||
/// <summary>
|
|||
/// Gets the name of the control to match.
|
|||
/// </summary>
|
|||
public string Name { get; set; } |
|||
|
|||
/// <inheritdoc/>
|
|||
public override Type TargetType => _targetType ?? _previous?.TargetType; |
|||
|
|||
/// <summary>
|
|||
/// Whether the selector matches the concrete <see cref="TargetType"/> or any object which
|
|||
/// implements <see cref="TargetType"/>.
|
|||
/// </summary>
|
|||
public bool IsConcreteType { get; private set; } |
|||
|
|||
/// <summary>
|
|||
/// The style classes which the selector matches.
|
|||
/// </summary>
|
|||
public IList<string> Classes => _classes.Value; |
|||
|
|||
/// <inheritdoc/>
|
|||
public override string ToString() |
|||
{ |
|||
if (_selectorString == null) |
|||
{ |
|||
_selectorString = BuildSelectorString(); |
|||
} |
|||
|
|||
return _selectorString; |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
protected override SelectorMatch Evaluate(IStyleable control, bool subscribe) |
|||
{ |
|||
if (TargetType != null) |
|||
{ |
|||
var controlType = control.StyleKey ?? control.GetType(); |
|||
|
|||
if (IsConcreteType) |
|||
{ |
|||
if (controlType != TargetType) |
|||
{ |
|||
return SelectorMatch.False; |
|||
} |
|||
} |
|||
else |
|||
{ |
|||
if (!TargetType.GetTypeInfo().IsAssignableFrom(controlType.GetTypeInfo())) |
|||
{ |
|||
return SelectorMatch.False; |
|||
} |
|||
} |
|||
} |
|||
|
|||
if (Name != null && control.Name != Name) |
|||
{ |
|||
return SelectorMatch.False; |
|||
} |
|||
|
|||
if (_classes.IsValueCreated && _classes.Value.Count > 0) |
|||
{ |
|||
if (subscribe) |
|||
{ |
|||
var observable = Observable.FromEventPattern< |
|||
NotifyCollectionChangedEventHandler, |
|||
NotifyCollectionChangedEventArgs>( |
|||
x => control.Classes.CollectionChanged += x, |
|||
x => control.Classes.CollectionChanged -= x) |
|||
.StartWith((EventPattern<NotifyCollectionChangedEventArgs>)null) |
|||
.Select(_ => Matches(control.Classes)); |
|||
return new SelectorMatch(observable); |
|||
} |
|||
else |
|||
{ |
|||
return new SelectorMatch(Matches(control.Classes)); |
|||
} |
|||
} |
|||
else |
|||
{ |
|||
return SelectorMatch.True; |
|||
} |
|||
} |
|||
|
|||
protected override Selector MovePrevious() => _previous; |
|||
|
|||
private bool Matches(IEnumerable<string> classes) |
|||
{ |
|||
int remaining = Classes.Count; |
|||
|
|||
foreach (var c in classes) |
|||
{ |
|||
if (Classes.Contains(c)) |
|||
{ |
|||
--remaining; |
|||
} |
|||
} |
|||
|
|||
return remaining == 0; |
|||
} |
|||
|
|||
private string BuildSelectorString() |
|||
{ |
|||
var builder = new StringBuilder(); |
|||
|
|||
if (_previous != null) |
|||
{ |
|||
builder.Append(_previous.ToString()); |
|||
} |
|||
|
|||
if (TargetType != null) |
|||
{ |
|||
if (IsConcreteType) |
|||
{ |
|||
builder.Append(TargetType.Name); |
|||
} |
|||
else |
|||
{ |
|||
builder.Append(":is("); |
|||
builder.Append(TargetType.Name); |
|||
builder.Append(")"); |
|||
} |
|||
} |
|||
|
|||
if (Name != null) |
|||
{ |
|||
builder.Append('#'); |
|||
builder.Append(Name); |
|||
} |
|||
|
|||
if (_classes.IsValueCreated && _classes.Value.Count > 0) |
|||
{ |
|||
foreach (var c in Classes) |
|||
{ |
|||
if (!c.StartsWith(":")) |
|||
{ |
|||
builder.Append('.'); |
|||
} |
|||
|
|||
builder.Append(c); |
|||
} |
|||
} |
|||
|
|||
return builder.ToString(); |
|||
} |
|||
} |
|||
} |
|||
@ -1,13 +1,12 @@ |
|||
<Style xmlns="https://github.com/perspex" Selector="ContentControl"> |
|||
<Setter Property="Template"> |
|||
<ControlTemplate> |
|||
<Border Background="{TemplateBinding Background}" |
|||
BorderBrush="{TemplateBinding BorderBrush}" |
|||
BorderThickness="{TemplateBinding BorderThickness}"> |
|||
<ContentPresenter Name="PART_ContentPresenter" |
|||
Content="{TemplateBinding Content}" |
|||
Margin="{TemplateBinding Padding}"/> |
|||
</Border> |
|||
<ContentPresenter Name="PART_ContentPresenter" |
|||
Background="{TemplateBinding Background}" |
|||
BorderBrush="{TemplateBinding BorderBrush}" |
|||
BorderThickness="{TemplateBinding BorderThickness}" |
|||
Content="{TemplateBinding Content}" |
|||
Padding="{TemplateBinding Padding}"/> |
|||
</ControlTemplate> |
|||
</Setter> |
|||
</Style> |
|||
@ -0,0 +1,14 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<configuration> |
|||
<startup> |
|||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" /> |
|||
</startup> |
|||
<runtime> |
|||
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> |
|||
<dependentAssembly> |
|||
<assemblyIdentity name="Moq" publicKeyToken="69f491c39445e920" culture="neutral" /> |
|||
<bindingRedirect oldVersion="0.0.0.0-4.2.1510.2205" newVersion="4.2.1510.2205" /> |
|||
</dependentAssembly> |
|||
</assemblyBinding> |
|||
</runtime> |
|||
</configuration> |
|||
@ -0,0 +1,130 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> |
|||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> |
|||
<PropertyGroup> |
|||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> |
|||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> |
|||
<ProjectGuid>{410AC439-81A1-4EB5-B5E9-6A7FC6B77F4B}</ProjectGuid> |
|||
<OutputType>Exe</OutputType> |
|||
<AppDesignerFolder>Properties</AppDesignerFolder> |
|||
<RootNamespace>Perspex.Benchmarks</RootNamespace> |
|||
<AssemblyName>Perspex.Benchmarks</AssemblyName> |
|||
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion> |
|||
<FileAlignment>512</FileAlignment> |
|||
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects> |
|||
<TargetFrameworkProfile /> |
|||
</PropertyGroup> |
|||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> |
|||
<PlatformTarget>AnyCPU</PlatformTarget> |
|||
<DebugSymbols>true</DebugSymbols> |
|||
<DebugType>full</DebugType> |
|||
<Optimize>false</Optimize> |
|||
<OutputPath>bin\Debug\</OutputPath> |
|||
<DefineConstants>DEBUG;TRACE</DefineConstants> |
|||
<ErrorReport>prompt</ErrorReport> |
|||
<WarningLevel>4</WarningLevel> |
|||
<Prefer32Bit>false</Prefer32Bit> |
|||
</PropertyGroup> |
|||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> |
|||
<PlatformTarget>AnyCPU</PlatformTarget> |
|||
<DebugType>pdbonly</DebugType> |
|||
<Optimize>true</Optimize> |
|||
<OutputPath>bin\Release\</OutputPath> |
|||
<DefineConstants>TRACE</DefineConstants> |
|||
<ErrorReport>prompt</ErrorReport> |
|||
<WarningLevel>4</WarningLevel> |
|||
</PropertyGroup> |
|||
<ItemGroup> |
|||
<Reference Include="BenchmarkDotNet, Version=0.9.2.0, Culture=neutral, processorArchitecture=MSIL"> |
|||
<HintPath>..\..\packages\BenchmarkDotNet.0.9.2\lib\net45\BenchmarkDotNet.dll</HintPath> |
|||
<Private>True</Private> |
|||
</Reference> |
|||
<Reference Include="Microsoft.Build" /> |
|||
<Reference Include="Microsoft.Build.Framework" /> |
|||
<Reference Include="Microsoft.Build.Utilities.v4.0" /> |
|||
<Reference Include="Moq, Version=4.2.1510.2205, Culture=neutral, PublicKeyToken=69f491c39445e920, processorArchitecture=MSIL"> |
|||
<HintPath>..\..\packages\Moq.4.2.1510.2205\lib\net40\Moq.dll</HintPath> |
|||
<Private>True</Private> |
|||
</Reference> |
|||
<Reference Include="Ploeh.AutoFixture, Version=3.40.0.0, Culture=neutral, PublicKeyToken=b24654c590009d4f, processorArchitecture=MSIL"> |
|||
<HintPath>..\..\packages\AutoFixture.3.40.0\lib\net40\Ploeh.AutoFixture.dll</HintPath> |
|||
<Private>True</Private> |
|||
</Reference> |
|||
<Reference Include="Ploeh.AutoFixture.AutoMoq, Version=3.40.0.0, Culture=neutral, PublicKeyToken=b24654c590009d4f, processorArchitecture=MSIL"> |
|||
<HintPath>..\..\packages\AutoFixture.AutoMoq.3.40.0\lib\net40\Ploeh.AutoFixture.AutoMoq.dll</HintPath> |
|||
<Private>True</Private> |
|||
</Reference> |
|||
<Reference Include="System" /> |
|||
<Reference Include="System.Core" /> |
|||
<Reference Include="System.Management" /> |
|||
<Reference Include="System.Xml.Linq" /> |
|||
<Reference Include="System.Data.DataSetExtensions" /> |
|||
<Reference Include="Microsoft.CSharp" /> |
|||
<Reference Include="System.Data" /> |
|||
<Reference Include="System.Net.Http" /> |
|||
<Reference Include="System.Xml" /> |
|||
</ItemGroup> |
|||
<ItemGroup> |
|||
<Compile Include="Styling\ApplyStyling.cs" /> |
|||
<Compile Include="Program.cs" /> |
|||
<Compile Include="Properties\AssemblyInfo.cs" /> |
|||
</ItemGroup> |
|||
<ItemGroup> |
|||
<None Include="App.config" /> |
|||
<None Include="packages.config" /> |
|||
</ItemGroup> |
|||
<ItemGroup> |
|||
<ProjectReference Include="..\..\src\Perspex.Animation\Perspex.Animation.csproj"> |
|||
<Project>{d211e587-d8bc-45b9-95a4-f297c8fa5200}</Project> |
|||
<Name>Perspex.Animation</Name> |
|||
</ProjectReference> |
|||
<ProjectReference Include="..\..\src\Perspex.Application\Perspex.Application.csproj"> |
|||
<Project>{799a7bb5-3c2c-48b6-85a7-406a12c420da}</Project> |
|||
<Name>Perspex.Application</Name> |
|||
</ProjectReference> |
|||
<ProjectReference Include="..\..\src\Perspex.Base\Perspex.Base.csproj"> |
|||
<Project>{b09b78d8-9b26-48b0-9149-d64a2f120f3f}</Project> |
|||
<Name>Perspex.Base</Name> |
|||
</ProjectReference> |
|||
<ProjectReference Include="..\..\src\Perspex.Controls\Perspex.Controls.csproj"> |
|||
<Project>{d2221c82-4a25-4583-9b43-d791e3f6820c}</Project> |
|||
<Name>Perspex.Controls</Name> |
|||
</ProjectReference> |
|||
<ProjectReference Include="..\..\src\Perspex.Input\Perspex.Input.csproj"> |
|||
<Project>{62024b2d-53eb-4638-b26b-85eeaa54866e}</Project> |
|||
<Name>Perspex.Input</Name> |
|||
</ProjectReference> |
|||
<ProjectReference Include="..\..\src\Perspex.Interactivity\Perspex.Interactivity.csproj"> |
|||
<Project>{6b0ed19d-a08b-461c-a9d9-a9ee40b0c06b}</Project> |
|||
<Name>Perspex.Interactivity</Name> |
|||
</ProjectReference> |
|||
<ProjectReference Include="..\..\src\Perspex.Layout\Perspex.Layout.csproj"> |
|||
<Project>{42472427-4774-4c81-8aff-9f27b8e31721}</Project> |
|||
<Name>Perspex.Layout</Name> |
|||
</ProjectReference> |
|||
<ProjectReference Include="..\..\src\Perspex.SceneGraph\Perspex.SceneGraph.csproj"> |
|||
<Project>{eb582467-6abb-43a1-b052-e981ba910e3a}</Project> |
|||
<Name>Perspex.SceneGraph</Name> |
|||
</ProjectReference> |
|||
<ProjectReference Include="..\..\src\Perspex.Styling\Perspex.Styling.csproj"> |
|||
<Project>{f1baa01a-f176-4c6a-b39d-5b40bb1b148f}</Project> |
|||
<Name>Perspex.Styling</Name> |
|||
</ProjectReference> |
|||
<ProjectReference Include="..\..\src\Perspex.Themes.Default\Perspex.Themes.Default.csproj"> |
|||
<Project>{3e10a5fa-e8da-48b1-ad44-6a5b6cb7750f}</Project> |
|||
<Name>Perspex.Themes.Default</Name> |
|||
</ProjectReference> |
|||
<ProjectReference Include="..\Perspex.UnitTests\Perspex.UnitTests.csproj"> |
|||
<Project>{88060192-33d5-4932-b0f9-8bd2763e857d}</Project> |
|||
<Name>Perspex.UnitTests</Name> |
|||
</ProjectReference> |
|||
</ItemGroup> |
|||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> |
|||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it. |
|||
Other similar extension points exist, see Microsoft.Common.targets. |
|||
<Target Name="BeforeBuild"> |
|||
</Target> |
|||
<Target Name="AfterBuild"> |
|||
</Target> |
|||
--> |
|||
</Project> |
|||
@ -0,0 +1,28 @@ |
|||
// Copyright (c) The Perspex Project. All rights reserved.
|
|||
// Licensed under the MIT license. See licence.md file in the project root for full license information.
|
|||
|
|||
using System.Linq; |
|||
using System.Reflection; |
|||
using BenchmarkDotNet.Attributes; |
|||
using BenchmarkDotNet.Running; |
|||
|
|||
namespace Perspex.Benchmarks |
|||
{ |
|||
class Program |
|||
{ |
|||
static void Main(string[] args) |
|||
{ |
|||
// Use reflection for a more maintainable way of creating the benchmark switcher,
|
|||
// Benchmarks are listed in namespace order first (e.g. BenchmarkDotNet.Samples.CPU,
|
|||
// BenchmarkDotNet.Samples.IL, etc) then by name, so the output is easy to understand
|
|||
var benchmarks = Assembly.GetExecutingAssembly().GetTypes() |
|||
.Where(t => t.GetMethods(BindingFlags.Instance | BindingFlags.Public) |
|||
.Any(m => m.GetCustomAttributes(typeof(BenchmarkAttribute), false).Any())) |
|||
.OrderBy(t => t.Namespace) |
|||
.ThenBy(t => t.Name) |
|||
.ToArray(); |
|||
var benchmarkSwitcher = new BenchmarkSwitcher(benchmarks); |
|||
benchmarkSwitcher.Run(args); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,36 @@ |
|||
using System.Reflection; |
|||
using System.Runtime.CompilerServices; |
|||
using System.Runtime.InteropServices; |
|||
|
|||
// General Information about an assembly is controlled through the following
|
|||
// set of attributes. Change these attribute values to modify the information
|
|||
// associated with an assembly.
|
|||
[assembly: AssemblyTitle("Perspex.Benchmarks")] |
|||
[assembly: AssemblyDescription("")] |
|||
[assembly: AssemblyConfiguration("")] |
|||
[assembly: AssemblyCompany("")] |
|||
[assembly: AssemblyProduct("Perspex.Benchmarks")] |
|||
[assembly: AssemblyCopyright("Copyright © 2016")] |
|||
[assembly: AssemblyTrademark("")] |
|||
[assembly: AssemblyCulture("")] |
|||
|
|||
// Setting ComVisible to false makes the types in this assembly not visible
|
|||
// to COM components. If you need to access a type in this assembly from
|
|||
// COM, set the ComVisible attribute to true on that type.
|
|||
[assembly: ComVisible(false)] |
|||
|
|||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
|||
[assembly: Guid("410ac439-81a1-4eb5-b5e9-6a7fc6b77f4b")] |
|||
|
|||
// Version information for an assembly consists of the following four values:
|
|||
//
|
|||
// Major Version
|
|||
// Minor Version
|
|||
// Build Number
|
|||
// Revision
|
|||
//
|
|||
// You can specify all the values or you can default the Build and Revision Numbers
|
|||
// by using the '*' as shown below:
|
|||
// [assembly: AssemblyVersion("1.0.*")]
|
|||
[assembly: AssemblyVersion("1.0.0.0")] |
|||
[assembly: AssemblyFileVersion("1.0.0.0")] |
|||
@ -0,0 +1,68 @@ |
|||
// Copyright (c) The Perspex Project. All rights reserved.
|
|||
// Licensed under the MIT license. See licence.md file in the project root for full license information.
|
|||
|
|||
using System; |
|||
using System.Linq; |
|||
using BenchmarkDotNet.Attributes; |
|||
using Perspex.Controls; |
|||
using Perspex.Styling; |
|||
using Perspex.UnitTests; |
|||
using Perspex.VisualTree; |
|||
|
|||
namespace Perspex.Benchmarks.Styling |
|||
{ |
|||
public class ApplyStyling : IDisposable |
|||
{ |
|||
private IDisposable _app; |
|||
private Window _window; |
|||
|
|||
public ApplyStyling() |
|||
{ |
|||
_app = UnitTestApplication.Start(TestServices.StyledWindow); |
|||
|
|||
TextBox textBox; |
|||
|
|||
_window = new Window |
|||
{ |
|||
Content = textBox = new TextBox(), |
|||
}; |
|||
|
|||
_window.ApplyTemplate(); |
|||
textBox.ApplyTemplate(); |
|||
|
|||
var border = (Border)textBox.GetVisualChildren().Single(); |
|||
|
|||
if (border.BorderThickness != 2) |
|||
{ |
|||
throw new Exception("Styles not applied."); |
|||
} |
|||
|
|||
_window.Content = null; |
|||
|
|||
// Add a bunch of styles with lots of class selectors to complicate matters.
|
|||
for (int i = 0; i < 100; ++i) |
|||
{ |
|||
_window.Styles.Add(new Style(x => x.OfType<TextBox>().Class("foo").Class("bar").Class("baz")) |
|||
{ |
|||
Setters = new[] |
|||
{ |
|||
new Setter(TextBox.TextProperty, "foo"), |
|||
} |
|||
}); |
|||
} |
|||
} |
|||
|
|||
public void Dispose() |
|||
{ |
|||
_app.Dispose(); |
|||
} |
|||
|
|||
[Benchmark] |
|||
public void Add_And_Style_TextBox() |
|||
{ |
|||
var textBox = new TextBox(); |
|||
_window.Content = textBox; |
|||
textBox.ApplyTemplate(); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,7 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<packages> |
|||
<package id="AutoFixture" version="3.40.0" targetFramework="net45" /> |
|||
<package id="AutoFixture.AutoMoq" version="3.40.0" targetFramework="net45" /> |
|||
<package id="BenchmarkDotNet" version="0.9.2" targetFramework="net46" /> |
|||
<package id="Moq" version="4.2.1510.2205" targetFramework="net45" /> |
|||
</packages> |
|||
@ -0,0 +1,11 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<configuration> |
|||
<runtime> |
|||
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> |
|||
<dependentAssembly> |
|||
<assemblyIdentity name="Moq" publicKeyToken="69f491c39445e920" culture="neutral" /> |
|||
<bindingRedirect oldVersion="0.0.0.0-4.2.1510.2205" newVersion="4.2.1510.2205" /> |
|||
</dependentAssembly> |
|||
</assemblyBinding> |
|||
</runtime> |
|||
</configuration> |
|||
Loading…
Reference in new issue