Browse Source

Lazily initialize Styles.

Added an `IStyleHost.IsStylesInitialized` property to prevent the need for allocating empty `Styles` collections for many controls.
pull/1135/head
Steven Kirk 9 years ago
parent
commit
090a1ec8cf
  1. 6
      src/Avalonia.Controls/Application.cs
  2. 13
      src/Avalonia.Controls/Control.cs
  3. 2
      src/Avalonia.Diagnostics/Views/ControlDetailsView.cs
  4. 12
      src/Avalonia.Styling/Styling/IStyleHost.cs
  5. 11
      src/Avalonia.Styling/Styling/StyleExtensions.cs
  6. 5
      src/Avalonia.Styling/Styling/Styler.cs
  7. 1
      tests/Avalonia.Controls.UnitTests/Primitives/PopupTests.cs
  8. 8
      tests/Avalonia.Controls.UnitTests/Primitives/TemplatedControlTests.cs
  9. 2
      tests/Avalonia.Controls.UnitTests/TabControlTests.cs
  10. 2
      tests/Avalonia.Controls.UnitTests/UserControlTests.cs
  11. 1
      tests/Avalonia.Layout.UnitTests/FullLayoutTests.cs
  12. 20
      tests/Avalonia.Styling.UnitTests/ResourceTests.cs

6
src/Avalonia.Controls/Application.cs

@ -39,6 +39,7 @@ namespace Avalonia
private readonly Lazy<IClipboard> _clipboard =
new Lazy<IClipboard>(() => (IClipboard)AvaloniaLocator.Current.GetService(typeof(IClipboard)));
private readonly Styler _styler = new Styler();
private Styles _styles;
/// <summary>
/// Initializes a new instance of the <see cref="Application"/> class.
@ -109,13 +110,16 @@ namespace Avalonia
/// <remarks>
/// Global styles apply to all windows in the application.
/// </remarks>
public Styles Styles { get; } = new Styles();
public Styles Styles => _styles ?? (_styles = new Styles());
/// <summary>
/// Gets the styling parent of the application, which is null.
/// </summary>
IStyleHost IStyleHost.StylingParent => null;
/// <inheritdoc/>
bool IStyleHost.IsStylesInitialized => _styles != null;
/// <summary>
/// Initializes the application by loading XAML etc.
/// </summary>

13
src/Avalonia.Controls/Control.cs

@ -97,8 +97,8 @@ namespace Avalonia.Controls
private bool _isAttachedToLogicalTree;
private IAvaloniaList<ILogical> _logicalChildren;
private INameScope _nameScope;
private Styles _styles;
private bool _styled;
private Styles _styles;
private Subject<IStyleable> _styleDetach = new Subject<IStyleable>();
/// <summary>
@ -259,18 +259,14 @@ namespace Avalonia.Controls
public bool IsInitialized { get; private set; }
/// <summary>
/// Gets or sets the styles for the control.
/// Gets the styles for the control.
/// </summary>
/// <remarks>
/// Styles for the entire application are added to the Application.Styles collection, but
/// each control may in addition define its own styles which are applied to the control
/// itself and its children.
/// </remarks>
public Styles Styles
{
get { return _styles ?? (_styles = new Styles()); }
set { _styles = value; }
}
public Styles Styles => _styles ?? (_styles = new Styles());
/// <summary>
/// Gets the control's logical parent.
@ -336,6 +332,9 @@ namespace Avalonia.Controls
/// <inheritdoc/>
IObservable<IStyleable> IStyleable.StyleDetach => _styleDetach;
/// <inheritdoc/>
bool IStyleHost.IsStylesInitialized => _styles != null;
/// <inheritdoc/>
IStyleHost IStyleHost.StylingParent => (IStyleHost)InheritanceParent;

2
src/Avalonia.Diagnostics/Views/ControlDetailsView.cs

@ -42,7 +42,7 @@ namespace Avalonia.Diagnostics.Views
{
Content = _grid = new SimpleGrid
{
Styles = new Styles
Styles =
{
new Style(x => x.Is<Control>())
{

12
src/Avalonia.Styling/Styling/IStyleHost.cs

@ -1,6 +1,8 @@
// Copyright (c) The Avalonia Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using System;
namespace Avalonia.Styling
{
/// <summary>
@ -8,6 +10,15 @@ namespace Avalonia.Styling
/// </summary>
public interface IStyleHost
{
/// <summary>
/// Gets a value indicating whether <see cref="Styles"/> is initialized.
/// </summary>
/// <remarks>
/// The <see cref="Styles"/> property may be lazily initialized, if so this property
/// indicates whether it has been initialized.
/// </remarks>
bool IsStylesInitialized { get; }
/// <summary>
/// Gets the styles for the element.
/// </summary>
@ -17,6 +28,5 @@ namespace Avalonia.Styling
/// Gets the parent style host element.
/// </summary>
IStyleHost StylingParent { get; }
}
}

11
src/Avalonia.Styling/Styling/StyleExtensions.cs

@ -23,11 +23,14 @@ namespace Avalonia.Styling
while (control != null)
{
var result = control.Styles.FindResource(name);
if (result != AvaloniaProperty.UnsetValue)
if (control.IsStylesInitialized)
{
return result;
var result = control.Styles.FindResource(name);
if (result != AvaloniaProperty.UnsetValue)
{
return result;
}
}
control = control.StylingParent;

5
src/Avalonia.Styling/Styling/Styler.cs

@ -29,7 +29,10 @@ namespace Avalonia.Styling
ApplyStyles(control, parentContainer);
}
styleHost.Styles.Attach(control, styleHost);
if (styleHost.IsStylesInitialized)
{
styleHost.Styles.Attach(control, styleHost);
}
}
}
}

1
tests/Avalonia.Controls.UnitTests/Primitives/PopupTests.cs

@ -265,6 +265,7 @@ namespace Avalonia.Controls.UnitTests.Primitives
};
var globalStyles = new Mock<IGlobalStyles>();
globalStyles.Setup(x => x.IsStylesInitialized).Returns(true);
globalStyles.Setup(x => x.Styles).Returns(styles);
var renderInterface = new Mock<IPlatformRenderInterface>();

8
tests/Avalonia.Controls.UnitTests/Primitives/TemplatedControlTests.cs

@ -399,7 +399,7 @@ namespace Avalonia.Controls.UnitTests.Primitives
TestTemplatedControl target;
var root = new TestRoot
{
Styles = new Styles
Styles =
{
new Style(x => x.OfType<TestTemplatedControl>())
{
@ -435,7 +435,7 @@ namespace Avalonia.Controls.UnitTests.Primitives
TestTemplatedControl target;
var root = new TestRoot
{
Styles = new Styles
Styles =
{
new Style(x => x.OfType<TestTemplatedControl>())
{
@ -474,7 +474,7 @@ namespace Avalonia.Controls.UnitTests.Primitives
var root = new TestRoot
{
Styles = new Styles
Styles =
{
new Style(x => x.OfType<TestTemplatedControl>())
{
@ -494,7 +494,7 @@ namespace Avalonia.Controls.UnitTests.Primitives
var root2 = new TestRoot
{
Styles = new Styles
Styles =
{
new Style(x => x.OfType<TestTemplatedControl>())
{

2
tests/Avalonia.Controls.UnitTests/TabControlTests.cs

@ -135,7 +135,7 @@ namespace Avalonia.Controls.UnitTests
{
var root = new TestRoot
{
Styles = new Styles
Styles =
{
new Style(x => x.OfType<TabItem>())
{

2
tests/Avalonia.Controls.UnitTests/UserControlTests.cs

@ -21,7 +21,7 @@ namespace Avalonia.Controls.UnitTests
var target = new UserControl();
var root = new TestRoot
{
Styles = new Styles
Styles =
{
new Style(x => x.OfType<ContentControl>())
{

1
tests/Avalonia.Layout.UnitTests/FullLayoutTests.cs

@ -193,6 +193,7 @@ namespace Avalonia.Layout.UnitTests
.Bind<IWindowingPlatform>().ToConstant(new Avalonia.Controls.UnitTests.WindowingPlatformMock(() => windowImpl.Object));
var theme = new DefaultTheme();
globalStyles.Setup(x => x.IsStylesInitialized).Returns(true);
globalStyles.Setup(x => x.Styles).Returns(theme);
}
}

20
tests/Avalonia.Styling.UnitTests/ResourceTests.cs

@ -16,7 +16,7 @@ namespace Avalonia.Styling.UnitTests
var tree = new Decorator
{
Styles = new Styles
Styles =
{
new Style
{
@ -29,7 +29,7 @@ namespace Avalonia.Styling.UnitTests
},
Child = target = new Border
{
Styles = new Styles
Styles =
{
new Style
{
@ -60,16 +60,16 @@ namespace Avalonia.Styling.UnitTests
var tree = target = new Border
{
Styles = new Styles
Styles =
{
new Style
{
new Style
Resources = new StyleResources
{
Resources = new StyleResources
{
{ "Foo", "foo" },
}
},
}
{ "Foo", "foo" },
}
},
}
};
Assert.Equal(AvaloniaProperty.UnsetValue, target.FindStyleResource("Baz"));

Loading…
Cancel
Save