Browse Source

Merge branch 'master' into netstandard2.0-migration

pull/1145/head
Nikita Tsukanov 9 years ago
committed by GitHub
parent
commit
abd23cce8d
  1. 2
      build/Moq.props
  2. 19
      build/UnitTests.NetCore.targets
  3. 53
      samples/ControlCatalog/Pages/ToolTipPage.xaml
  4. 15
      src/Avalonia.Controls/Application.cs
  5. 22
      src/Avalonia.Controls/Control.cs
  6. 14
      src/Avalonia.Controls/IControl.cs
  7. 6
      src/Avalonia.Controls/IGlobalDataTemplates.cs
  8. 26
      src/Avalonia.Controls/Primitives/Popup.cs
  9. 24
      src/Avalonia.Controls/Templates/DataTemplateExtensions.cs
  10. 27
      src/Avalonia.Controls/Templates/IDataTemplateHost.cs
  11. 236
      src/Avalonia.Controls/ToolTip.cs
  12. 98
      src/Avalonia.Controls/ToolTipService.cs
  13. 2
      src/Avalonia.Diagnostics/DevTools.xaml.cs
  14. 2
      src/Avalonia.Diagnostics/Views/ControlDetailsView.cs
  15. 13
      src/Avalonia.DotNetFrameworkRuntime/AppBuilder.cs
  16. 1
      src/Avalonia.HtmlRenderer/Avalonia.HtmlRenderer.csproj
  17. 20
      src/Avalonia.Interactivity/Interactive.cs
  18. 12
      src/Avalonia.Styling/Styling/IStyleHost.cs
  19. 11
      src/Avalonia.Styling/Styling/StyleExtensions.cs
  20. 5
      src/Avalonia.Styling/Styling/Styler.cs
  21. 1
      src/Linux/Avalonia.LinuxFramebuffer/NativeUnsafeMethods.cs
  22. 1
      src/Windows/Avalonia.Designer/AppHost/HostedAppModel.cs
  23. 38
      src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs
  24. 2
      src/Windows/Avalonia.Win32/Win32Platform.cs
  25. 6
      src/Windows/Avalonia.Win32/WindowImpl.cs
  26. 2
      tests/Avalonia.Controls.UnitTests/ItemsControlTests.cs
  27. 8
      tests/Avalonia.Controls.UnitTests/ListBoxTests.cs
  28. 2
      tests/Avalonia.Controls.UnitTests/Presenters/ContentPresenterTests_Unrooted.cs
  29. 1
      tests/Avalonia.Controls.UnitTests/Primitives/PopupTests.cs
  30. 8
      tests/Avalonia.Controls.UnitTests/Primitives/TemplatedControlTests.cs
  31. 4
      tests/Avalonia.Controls.UnitTests/TabControlTests.cs
  32. 28
      tests/Avalonia.Controls.UnitTests/TreeViewTests.cs
  33. 2
      tests/Avalonia.Controls.UnitTests/UserControlTests.cs
  34. 31
      tests/Avalonia.Input.UnitTests/Avalonia.Input.UnitTests.csproj
  35. 1
      tests/Avalonia.Layout.UnitTests/FullLayoutTests.cs
  36. 2
      tests/Avalonia.LeakTests/ControlTests.cs
  37. 1
      tests/Avalonia.Styling.UnitTests/Avalonia.Styling.UnitTests.csproj
  38. 20
      tests/Avalonia.Styling.UnitTests/ResourceTests.cs

2
build/Moq.props

@ -1,5 +1,5 @@
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup> <ItemGroup>
<PackageReference Include="Moq" Version="4.7.25" /> <PackageReference Include="Moq" Version="4.7.99" />
</ItemGroup> </ItemGroup>
</Project> </Project>

19
build/UnitTests.NetCore.targets

@ -3,25 +3,6 @@
<GenerateAssemblyInfo>false</GenerateAssemblyInfo> <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles> <GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="System.Threading.Thread" Version="4.3.0" /> <PackageReference Include="System.Threading.Thread" Version="4.3.0" />
</ItemGroup> </ItemGroup>

53
samples/ControlCatalog/Pages/ToolTipPage.xaml

@ -1,22 +1,41 @@
<UserControl xmlns="https://github.com/avaloniaui"> <UserControl xmlns="https://github.com/avaloniaui">
<StackPanel Orientation="Vertical" Gap="4"> <StackPanel Orientation="Vertical"
<TextBlock Classes="h1">ToolTip</TextBlock> Gap="4">
<TextBlock Classes="h2">A control which pops up a hint when a control is hovered</TextBlock> <TextBlock Classes="h1">ToolTip</TextBlock>
<TextBlock Classes="h2">A control which pops up a hint when a control is hovered</TextBlock>
<StackPanel Orientation="Horizontal" <Grid RowDefinitions="Auto,Auto"
ColumnDefinitions="Auto,Auto"
Margin="0,16,0,0" Margin="0,16,0,0"
HorizontalAlignment="Center" HorizontalAlignment="Center">
Gap="16"> <Border Grid.Column="0"
<Border Background="{StyleResource ThemeAccentBrush}" Grid.Row="1"
Padding="48,48,48,48"> Background="{StyleResource ThemeAccentBrush}"
<ToolTip.Tip> Margin="5"
<StackPanel> Padding="50"
<TextBlock Classes="h1">ToolTip</TextBlock> ToolTip.Tip="This is a ToolTip">
<TextBlock Classes="h2">A control which pops up a hint when a control is hovered</TextBlock> <TextBlock>Hover Here</TextBlock>
</StackPanel> </Border>
</ToolTip.Tip> <CheckBox Grid.Column="1"
<TextBlock>Hover Here</TextBlock> Margin="5"
</Border> Grid.Row="0"
IsChecked="{Binding ElementName=Border, Path=(ToolTip.IsOpen)}"
Content="ToolTip Open" />
<Border Name="Border"
Grid.Column="1"
Grid.Row="1"
Background="{StyleResource ThemeAccentBrush}"
Margin="5"
Padding="50"
ToolTip.Placement="Bottom">
<ToolTip.Tip>
<StackPanel>
<TextBlock Classes="h1">ToolTip</TextBlock>
<TextBlock Classes="h2">A control which pops up a hint when a control is hovered</TextBlock>
</StackPanel>
</ToolTip.Tip>
<TextBlock>ToolTip bottom placement</TextBlock>
</Border>
</Grid>
</StackPanel> </StackPanel>
</StackPanel>
</UserControl> </UserControl>

15
src/Avalonia.Controls/Application.cs

@ -39,6 +39,7 @@ namespace Avalonia
private readonly Lazy<IClipboard> _clipboard = private readonly Lazy<IClipboard> _clipboard =
new Lazy<IClipboard>(() => (IClipboard)AvaloniaLocator.Current.GetService(typeof(IClipboard))); new Lazy<IClipboard>(() => (IClipboard)AvaloniaLocator.Current.GetService(typeof(IClipboard)));
private readonly Styler _styler = new Styler(); private readonly Styler _styler = new Styler();
private Styles _styles;
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="Application"/> class. /// Initializes a new instance of the <see cref="Application"/> class.
@ -65,11 +66,7 @@ namespace Avalonia
/// <value> /// <value>
/// The application's global data templates. /// The application's global data templates.
/// </value> /// </value>
public DataTemplates DataTemplates public DataTemplates DataTemplates => _dataTemplates ?? (_dataTemplates = new DataTemplates());
{
get { return _dataTemplates ?? (_dataTemplates = new DataTemplates()); }
set { _dataTemplates = value; }
}
/// <summary> /// <summary>
/// Gets the application's focus manager. /// Gets the application's focus manager.
@ -109,13 +106,19 @@ namespace Avalonia
/// <remarks> /// <remarks>
/// Global styles apply to all windows in the application. /// Global styles apply to all windows in the application.
/// </remarks> /// </remarks>
public Styles Styles { get; } = new Styles(); public Styles Styles => _styles ?? (_styles = new Styles());
/// <inheritdoc/>
bool IDataTemplateHost.IsDataTemplatesInitialized => _dataTemplates != null;
/// <summary> /// <summary>
/// Gets the styling parent of the application, which is null. /// Gets the styling parent of the application, which is null.
/// </summary> /// </summary>
IStyleHost IStyleHost.StylingParent => null; IStyleHost IStyleHost.StylingParent => null;
/// <inheritdoc/>
bool IStyleHost.IsStylesInitialized => _styles != null;
/// <summary> /// <summary>
/// Initializes the application by loading XAML etc. /// Initializes the application by loading XAML etc.
/// </summary> /// </summary>

22
src/Avalonia.Controls/Control.cs

@ -97,8 +97,8 @@ namespace Avalonia.Controls
private bool _isAttachedToLogicalTree; private bool _isAttachedToLogicalTree;
private IAvaloniaList<ILogical> _logicalChildren; private IAvaloniaList<ILogical> _logicalChildren;
private INameScope _nameScope; private INameScope _nameScope;
private Styles _styles;
private bool _styled; private bool _styled;
private Styles _styles;
private Subject<IStyleable> _styleDetach = new Subject<IStyleable>(); private Subject<IStyleable> _styleDetach = new Subject<IStyleable>();
/// <summary> /// <summary>
@ -243,11 +243,7 @@ namespace Avalonia.Controls
/// Each control may define data templates which are applied to the control itself and its /// Each control may define data templates which are applied to the control itself and its
/// children. /// children.
/// </remarks> /// </remarks>
public DataTemplates DataTemplates public DataTemplates DataTemplates => _dataTemplates ?? (_dataTemplates = new DataTemplates());
{
get { return _dataTemplates ?? (_dataTemplates = new DataTemplates()); }
set { _dataTemplates = value; }
}
/// <summary> /// <summary>
/// Gets a value that indicates whether the element has finished initialization. /// Gets a value that indicates whether the element has finished initialization.
@ -259,18 +255,14 @@ namespace Avalonia.Controls
public bool IsInitialized { get; private set; } public bool IsInitialized { get; private set; }
/// <summary> /// <summary>
/// Gets or sets the styles for the control. /// Gets the styles for the control.
/// </summary> /// </summary>
/// <remarks> /// <remarks>
/// Styles for the entire application are added to the Application.Styles collection, but /// 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 /// each control may in addition define its own styles which are applied to the control
/// itself and its children. /// itself and its children.
/// </remarks> /// </remarks>
public Styles Styles public Styles Styles => _styles ?? (_styles = new Styles());
{
get { return _styles ?? (_styles = new Styles()); }
set { _styles = value; }
}
/// <summary> /// <summary>
/// Gets the control's logical parent. /// Gets the control's logical parent.
@ -304,6 +296,9 @@ namespace Avalonia.Controls
internal set { SetValue(TemplatedParentProperty, value); } internal set { SetValue(TemplatedParentProperty, value); }
} }
/// <inheritdoc/>
bool IDataTemplateHost.IsDataTemplatesInitialized => _dataTemplates != null;
/// <summary> /// <summary>
/// Gets a value indicating whether the element is attached to a rooted logical tree. /// Gets a value indicating whether the element is attached to a rooted logical tree.
/// </summary> /// </summary>
@ -336,6 +331,9 @@ namespace Avalonia.Controls
/// <inheritdoc/> /// <inheritdoc/>
IObservable<IStyleable> IStyleable.StyleDetach => _styleDetach; IObservable<IStyleable> IStyleable.StyleDetach => _styleDetach;
/// <inheritdoc/>
bool IStyleHost.IsStylesInitialized => _styles != null;
/// <inheritdoc/> /// <inheritdoc/>
IStyleHost IStyleHost.StylingParent => (IStyleHost)InheritanceParent; IStyleHost IStyleHost.StylingParent => (IStyleHost)InheritanceParent;

14
src/Avalonia.Controls/IControl.cs

@ -14,7 +14,14 @@ namespace Avalonia.Controls
/// <summary> /// <summary>
/// Interface for Avalonia controls. /// Interface for Avalonia controls.
/// </summary> /// </summary>
public interface IControl : IVisual, ILogical, ILayoutable, IInputElement, INamed, IStyleable, IStyleHost public interface IControl : IVisual,
IDataTemplateHost,
ILogical,
ILayoutable,
IInputElement,
INamed,
IStyleable,
IStyleHost
{ {
/// <summary> /// <summary>
/// Occurs when the control has finished initialization. /// Occurs when the control has finished initialization.
@ -31,11 +38,6 @@ namespace Avalonia.Controls
/// </summary> /// </summary>
object DataContext { get; set; } object DataContext { get; set; }
/// <summary>
/// Gets the data templates for the control.
/// </summary>
DataTemplates DataTemplates { get; }
/// <summary> /// <summary>
/// Gets a value that indicates whether the element has finished initialization. /// Gets a value that indicates whether the element has finished initialization.
/// </summary> /// </summary>

6
src/Avalonia.Controls/IGlobalDataTemplates.cs

@ -8,11 +8,7 @@ namespace Avalonia.Controls
/// <summary> /// <summary>
/// Defines the application-global data templates. /// Defines the application-global data templates.
/// </summary> /// </summary>
public interface IGlobalDataTemplates public interface IGlobalDataTemplates : IDataTemplateHost
{ {
/// <summary>
/// Gets the application-global data templates.
/// </summary>
DataTemplates DataTemplates { get; }
} }
} }

26
src/Avalonia.Controls/Primitives/Popup.cs

@ -277,7 +277,7 @@ namespace Avalonia.Controls.Primitives
{ {
base.OnDetachedFromLogicalTree(e); base.OnDetachedFromLogicalTree(e);
_topLevel = null; _topLevel = null;
if (_popupRoot != null) if (_popupRoot != null)
{ {
((ISetLogicalParent)_popupRoot).SetParent(null); ((ISetLogicalParent)_popupRoot).SetParent(null);
@ -327,34 +327,40 @@ namespace Avalonia.Controls.Primitives
/// </summary> /// </summary>
/// <returns>The popup's position in screen coordinates.</returns> /// <returns>The popup's position in screen coordinates.</returns>
protected virtual Point GetPosition() protected virtual Point GetPosition()
{
return GetPosition(PlacementTarget ?? this.GetVisualParent<Control>(), PlacementMode, PopupRoot,
HorizontalOffset, VerticalOffset);
}
internal static Point GetPosition(Control target, PlacementMode placement, PopupRoot popupRoot, double horizontalOffset, double verticalOffset)
{ {
var zero = default(Point); var zero = default(Point);
var mode = PlacementMode; var mode = placement;
var target = PlacementTarget ?? this.GetVisualParent<Control>();
if (target?.GetVisualRoot() == null) if (target?.GetVisualRoot() == null)
{ {
mode = PlacementMode.Pointer; mode = PlacementMode.Pointer;
} }
switch (mode) switch (mode)
{ {
case PlacementMode.Pointer: case PlacementMode.Pointer:
if(PopupRoot != null) if (popupRoot != null)
{ {
// Scales the Horizontal and Vertical offset to screen co-ordinates. // Scales the Horizontal and Vertical offset to screen co-ordinates.
var screenOffset = new Point(HorizontalOffset * (PopupRoot as ILayoutRoot).LayoutScaling, VerticalOffset * (PopupRoot as ILayoutRoot).LayoutScaling); var screenOffset = new Point(horizontalOffset * (popupRoot as ILayoutRoot).LayoutScaling,
return (((IInputRoot)PopupRoot)?.MouseDevice?.Position ?? default(Point)) + screenOffset; verticalOffset * (popupRoot as ILayoutRoot).LayoutScaling);
return (((IInputRoot)popupRoot)?.MouseDevice?.Position ?? default(Point)) + screenOffset;
} }
return default(Point); return default(Point);
case PlacementMode.Bottom: case PlacementMode.Bottom:
return target?.PointToScreen(new Point(0 + horizontalOffset, target.Bounds.Height + verticalOffset)) ??
return target?.PointToScreen(new Point(0 + HorizontalOffset, target.Bounds.Height + VerticalOffset)) ?? zero; zero;
case PlacementMode.Right: case PlacementMode.Right:
return target?.PointToScreen(new Point(target.Bounds.Width + HorizontalOffset, 0 + VerticalOffset)) ?? zero; return target?.PointToScreen(new Point(target.Bounds.Width + horizontalOffset, 0 + verticalOffset)) ?? zero;
default: default:
throw new InvalidOperationException("Invalid value for Popup.PlacementMode"); throw new InvalidOperationException("Invalid value for Popup.PlacementMode");

24
src/Avalonia.Controls/Templates/DataTemplateExtensions.cs

@ -17,8 +17,8 @@ namespace Avalonia.Controls.Templates
/// <param name="control">The control searching for the data template.</param> /// <param name="control">The control searching for the data template.</param>
/// <param name="data">The data.</param> /// <param name="data">The data.</param>
/// <param name="primary"> /// <param name="primary">
/// An optional primary template that can will be tried before the /// An optional primary template that can will be tried before the DataTemplates in the
/// <see cref="IControl.DataTemplates"/> in the tree are searched. /// tree are searched.
/// </param> /// </param>
/// <returns>The data template or null if no matching data template was found.</returns> /// <returns>The data template or null if no matching data template was found.</returns>
public static IDataTemplate FindDataTemplate( public static IDataTemplate FindDataTemplate(
@ -31,13 +31,16 @@ namespace Avalonia.Controls.Templates
return primary; return primary;
} }
foreach (var i in control.GetSelfAndLogicalAncestors().OfType<IControl>()) foreach (var i in control.GetSelfAndLogicalAncestors().OfType<IDataTemplateHost>())
{ {
foreach (IDataTemplate dt in i.DataTemplates) if (i.IsDataTemplatesInitialized)
{ {
if (dt.Match(data)) foreach (IDataTemplate dt in i.DataTemplates)
{ {
return dt; if (dt.Match(data))
{
return dt;
}
} }
} }
} }
@ -46,11 +49,14 @@ namespace Avalonia.Controls.Templates
if (global != null) if (global != null)
{ {
foreach (IDataTemplate dt in global.DataTemplates) if (global.IsDataTemplatesInitialized)
{ {
if (dt.Match(data)) foreach (IDataTemplate dt in global.DataTemplates)
{ {
return dt; if (dt.Match(data))
{
return dt;
}
} }
} }
} }

27
src/Avalonia.Controls/Templates/IDataTemplateHost.cs

@ -0,0 +1,27 @@
// 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.Controls.Templates
{
/// <summary>
/// Defines an element that has a <see cref="DataTemplates"/> collection.
/// </summary>
public interface IDataTemplateHost
{
/// <summary>
/// Gets the data templates for the element.
/// </summary>
DataTemplates DataTemplates { get; }
/// <summary>
/// Gets a value indicating whether <see cref="DataTemplates"/> is initialized.
/// </summary>
/// <remarks>
/// The <see cref="DataTemplates"/> property may be lazily initialized, if so this property
/// indicates whether it has been initialized.
/// </remarks>
bool IsDataTemplatesInitialized { get; }
}
}

236
src/Avalonia.Controls/ToolTip.cs

@ -3,11 +3,7 @@
using System; using System;
using System.Reactive.Linq; using System.Reactive.Linq;
using System.Reactive.Subjects;
using Avalonia.Controls.Primitives; using Avalonia.Controls.Primitives;
using Avalonia.Input;
using Avalonia.Threading;
using Avalonia.VisualTree;
namespace Avalonia.Controls namespace Avalonia.Controls
{ {
@ -29,29 +25,50 @@ namespace Avalonia.Controls
AvaloniaProperty.RegisterAttached<ToolTip, Control, object>("Tip"); AvaloniaProperty.RegisterAttached<ToolTip, Control, object>("Tip");
/// <summary> /// <summary>
/// The popup window used to display the active tooltip. /// Defines the ToolTip.IsOpen attached property.
/// </summary> /// </summary>
private static PopupRoot s_popup; public static readonly AttachedProperty<bool> IsOpenProperty =
AvaloniaProperty.RegisterAttached<ToolTip, Control, bool>("IsOpen");
/// <summary> /// <summary>
/// The control that the currently visible tooltip is attached to. /// Defines the ToolTip.Placement property.
/// </summary> /// </summary>
private static Control s_current; public static readonly AttachedProperty<PlacementMode> PlacementProperty =
AvaloniaProperty.RegisterAttached<Popup, Control, PlacementMode>("Placement", defaultValue: PlacementMode.Pointer);
/// <summary> /// <summary>
/// Observable fired when a tooltip should be displayed for a control. The output from this /// Defines the ToolTip.HorizontalOffset property.
/// observable is throttled and calls <see cref="ShowToolTip(Control)"/> when the time
/// period expires.
/// </summary> /// </summary>
private static readonly Subject<Control> s_show = new Subject<Control>(); public static readonly AttachedProperty<double> HorizontalOffsetProperty =
AvaloniaProperty.RegisterAttached<Popup, Control, double>("HorizontalOffset");
/// <summary>
/// Defines the ToolTip.VerticalOffset property.
/// </summary>
public static readonly AttachedProperty<double> VerticalOffsetProperty =
AvaloniaProperty.RegisterAttached<Popup, Control, double>("VerticalOffset", 20);
/// <summary>
/// Defines the ToolTip.ShowDelay property.
/// </summary>
public static readonly AttachedProperty<int> ShowDelayProperty =
AvaloniaProperty.RegisterAttached<Popup, Control, int>("ShowDelay", 400);
/// <summary>
/// Stores the curernt <see cref="ToolTip"/> instance in the control.
/// </summary>
private static readonly AttachedProperty<ToolTip> ToolTipProperty =
AvaloniaProperty.RegisterAttached<ToolTip, Control, ToolTip>("ToolTip");
private PopupRoot _popup;
/// <summary> /// <summary>
/// Initializes static members of the <see cref="ToolTip"/> class. /// Initializes static members of the <see cref="ToolTip"/> class.
/// </summary> /// </summary>
static ToolTip() static ToolTip()
{ {
TipProperty.Changed.Subscribe(TipChanged); TipProperty.Changed.Subscribe(ToolTipService.Instance.TipChanged);
s_show.Throttle(TimeSpan.FromSeconds(0.5), AvaloniaScheduler.Instance).Subscribe(ShowToolTip); IsOpenProperty.Changed.Subscribe(IsOpenChanged);
} }
/// <summary> /// <summary>
@ -77,101 +94,160 @@ namespace Avalonia.Controls
} }
/// <summary> /// <summary>
/// called when the <see cref="TipProperty"/> property changes on a control. /// Gets the value of the ToolTip.IsOpen attached property.
/// </summary> /// </summary>
/// <param name="e">The event args.</param> /// <param name="element">The control to get the property from.</param>
private static void TipChanged(AvaloniaPropertyChangedEventArgs e) /// <returns>
/// A value indicating whether the tool tip is visible.
/// </returns>
public static bool GetIsOpen(Control element)
{ {
var control = (Control)e.Sender; return element.GetValue(IsOpenProperty);
}
if (e.OldValue != null) /// <summary>
{ /// Sets the value of the ToolTip.IsOpen attached property.
control.PointerEnter -= ControlPointerEnter; /// </summary>
control.PointerLeave -= ControlPointerLeave; /// <param name="element">The control to get the property from.</param>
} /// <param name="value">A value indicating whether the tool tip is visible.</param>
public static void SetIsOpen(Control element, bool value)
{
element.SetValue(IsOpenProperty, value);
}
if (e.NewValue != null) /// <summary>
{ /// Gets the value of the ToolTip.Placement attached property.
control.PointerEnter += ControlPointerEnter; /// </summary>
control.PointerLeave += ControlPointerLeave; /// <param name="element">The control to get the property from.</param>
} /// <returns>
/// A value indicating how the tool tip is positioned.
/// </returns>
public static PlacementMode GetPlacement(Control element)
{
return element.GetValue(PlacementProperty);
} }
/// <summary> /// <summary>
/// Shows a tooltip for the specified control. /// Sets the value of the ToolTip.Placement attached property.
/// </summary> /// </summary>
/// <param name="control">The control.</param> /// <param name="element">The control to get the property from.</param>
private static void ShowToolTip(Control control) /// <param name="value">A value indicating how the tool tip is positioned.</param>
public static void SetPlacement(Control element, PlacementMode value)
{ {
if (control != null && control.IsVisible && control.GetVisualRoot() != null) element.SetValue(PlacementProperty, value);
{ }
var cp = (control.GetVisualRoot() as IInputRoot)?.MouseDevice?.GetPosition(control);
if (cp.HasValue && control.IsVisible && new Rect(control.Bounds.Size).Contains(cp.Value)) /// <summary>
{ /// Gets the value of the ToolTip.HorizontalOffset attached property.
var position = control.PointToScreen(cp.Value) + new Vector(0, 22); /// </summary>
/// <param name="element">The control to get the property from.</param>
if (s_popup == null) /// <returns>
{ /// A value indicating how the tool tip is positioned.
s_popup = new PopupRoot(); /// </returns>
s_popup.Content = new ToolTip(); public static double GetHorizontalOffset(Control element)
} {
else return element.GetValue(HorizontalOffsetProperty);
{ }
((ISetLogicalParent)s_popup).SetParent(null);
} /// <summary>
/// Sets the value of the ToolTip.HorizontalOffset attached property.
((ISetLogicalParent)s_popup).SetParent(control); /// </summary>
((ToolTip)s_popup.Content).Content = GetTip(control); /// <param name="element">The control to get the property from.</param>
s_popup.Position = position; /// <param name="value">A value indicating how the tool tip is positioned.</param>
s_popup.Show(); public static void SetHorizontalOffset(Control element, double value)
{
s_current = control; element.SetValue(HorizontalOffsetProperty, value);
} }
}
/// <summary>
/// Gets the value of the ToolTip.VerticalOffset attached property.
/// </summary>
/// <param name="element">The control to get the property from.</param>
/// <returns>
/// A value indicating how the tool tip is positioned.
/// </returns>
public static double GetVerticalOffset(Control element)
{
return element.GetValue(VerticalOffsetProperty);
}
/// <summary>
/// Sets the value of the ToolTip.VerticalOffset attached property.
/// </summary>
/// <param name="element">The control to get the property from.</param>
/// <param name="value">A value indicating how the tool tip is positioned.</param>
public static void SetVerticalOffset(Control element, double value)
{
element.SetValue(VerticalOffsetProperty, value);
} }
/// <summary> /// <summary>
/// Called when the pointer enters a control with an attached tooltip. /// Gets the value of the ToolTip.ShowDelay attached property.
/// </summary> /// </summary>
/// <param name="sender">The event sender.</param> /// <param name="element">The control to get the property from.</param>
/// <param name="e">The event args.</param> /// <returns>
private static void ControlPointerEnter(object sender, PointerEventArgs e) /// A value indicating the time, in milliseconds, before a tool tip opens.
/// </returns>
public static int GetShowDelay(Control element)
{ {
s_current = (Control)sender; return element.GetValue(ShowDelayProperty);
s_show.OnNext(s_current);
} }
/// <summary> /// <summary>
/// Called when the pointer leaves a control with an attached tooltip. /// Sets the value of the ToolTip.ShowDelay attached property.
/// </summary> /// </summary>
/// <param name="sender">The event sender.</param> /// <param name="element">The control to get the property from.</param>
/// <param name="e">The event args.</param> /// <param name="value">A value indicating the time, in milliseconds, before a tool tip opens.</param>
private static void ControlPointerLeave(object sender, PointerEventArgs e) public static void SetShowDelay(Control element, int value)
{ {
var control = (Control)sender; element.SetValue(ShowDelayProperty, value);
}
private static void IsOpenChanged(AvaloniaPropertyChangedEventArgs e)
{
var control = (Control)e.Sender;
if (control == s_current) if ((bool)e.NewValue)
{ {
if (s_popup != null) var tip = GetTip(control);
if (tip == null) return;
var toolTip = control.GetValue(ToolTipProperty);
if (toolTip == null || (tip != toolTip && tip != toolTip.Content))
{ {
DisposeTooltip(); toolTip?.Close();
s_show.OnNext(null);
toolTip = tip as ToolTip ?? new ToolTip { Content = tip };
control.SetValue(ToolTipProperty, toolTip);
} }
toolTip.Open(control);
}
else
{
var toolTip = control.GetValue(ToolTipProperty);
toolTip?.Close();
} }
} }
private static void DisposeTooltip() private void Open(Control control)
{ {
if (s_popup != null) Close();
{
// Clear the ToolTip's Content in case it has control content: this will _popup = new PopupRoot { Content = this };
// reset its visual parent allowing it to be used again. ((ISetLogicalParent)_popup).SetParent(control);
((ToolTip)s_popup.Content).Content = null; _popup.Position = Popup.GetPosition(control, GetPlacement(control), _popup,
GetHorizontalOffset(control), GetVerticalOffset(control));
_popup.Show();
}
// Dispose of the popup. private void Close()
s_popup.Dispose(); {
s_popup = null; if (_popup != null)
{
_popup.Content = null;
_popup.Hide();
_popup = null;
} }
} }
} }

98
src/Avalonia.Controls/ToolTipService.cs

@ -0,0 +1,98 @@
using System;
using Avalonia.Input;
using Avalonia.Threading;
namespace Avalonia.Controls
{
/// <summary>
/// Handeles <see cref="ToolTip"/> interaction with controls.
/// </summary>
internal sealed class ToolTipService
{
public static ToolTipService Instance { get; } = new ToolTipService();
private DispatcherTimer _timer;
private ToolTipService() { }
/// <summary>
/// called when the <see cref="ToolTip.TipProperty"/> property changes on a control.
/// </summary>
/// <param name="e">The event args.</param>
internal void TipChanged(AvaloniaPropertyChangedEventArgs e)
{
var control = (Control)e.Sender;
if (e.OldValue != null)
{
control.PointerEnter -= ControlPointerEnter;
control.PointerLeave -= ControlPointerLeave;
}
if (e.NewValue != null)
{
control.PointerEnter += ControlPointerEnter;
control.PointerLeave += ControlPointerLeave;
}
}
/// <summary>
/// Called when the pointer enters a control with an attached tooltip.
/// </summary>
/// <param name="sender">The event sender.</param>
/// <param name="e">The event args.</param>
private void ControlPointerEnter(object sender, PointerEventArgs e)
{
StopTimer();
var control = (Control)sender;
var showDelay = ToolTip.GetShowDelay(control);
if (showDelay == 0)
{
Open(control);
}
else
{
StartShowTimer(showDelay, control);
}
}
/// <summary>
/// Called when the pointer leaves a control with an attached tooltip.
/// </summary>
/// <param name="sender">The event sender.</param>
/// <param name="e">The event args.</param>
private void ControlPointerLeave(object sender, PointerEventArgs e)
{
var control = (Control)sender;
Close(control);
}
private void StartShowTimer(int showDelay, Control control)
{
_timer = new DispatcherTimer { Interval = TimeSpan.FromMilliseconds(showDelay) };
_timer.Tick += (o, e) => Open(control);
_timer.Start();
}
private void Open(Control control)
{
StopTimer();
ToolTip.SetIsOpen(control, true);
}
private void Close(Control control)
{
StopTimer();
ToolTip.SetIsOpen(control, false);
}
private void StopTimer()
{
_timer?.Stop();
_timer = null;
}
}
}

2
src/Avalonia.Diagnostics/DevTools.xaml.cs

@ -71,7 +71,7 @@ namespace Avalonia.Diagnostics
Width = 1024, Width = 1024,
Height = 512, Height = 512,
Content = devTools, Content = devTools,
DataTemplates = new DataTemplates DataTemplates =
{ {
new ViewLocator<ViewModelBase>(), new ViewLocator<ViewModelBase>(),
} }

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

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

13
src/Avalonia.DotNetFrameworkRuntime/AppBuilder.cs

@ -59,7 +59,11 @@ namespace Avalonia
from attribute in assembly.GetCustomAttributes<ExportWindowingSubsystemAttribute>() from attribute in assembly.GetCustomAttributes<ExportWindowingSubsystemAttribute>()
where attribute.RequiredOS == os && CheckEnvironment(attribute.EnvironmentChecker) where attribute.RequiredOS == os && CheckEnvironment(attribute.EnvironmentChecker)
orderby attribute.Priority ascending orderby attribute.Priority ascending
select attribute).First(); select attribute).FirstOrDefault();
if (windowingSubsystemAttribute == null)
{
throw new InvalidOperationException("No windowing subsystem found. Are you missing assembly references?");
}
var renderingSubsystemAttribute = (from assembly in RuntimePlatform.GetLoadedAssemblies() var renderingSubsystemAttribute = (from assembly in RuntimePlatform.GetLoadedAssemblies()
from attribute in assembly.GetCustomAttributes<ExportRenderingSubsystemAttribute>() from attribute in assembly.GetCustomAttributes<ExportRenderingSubsystemAttribute>()
@ -67,7 +71,12 @@ namespace Avalonia
where attribute.RequiresWindowingSubsystem == null where attribute.RequiresWindowingSubsystem == null
|| attribute.RequiresWindowingSubsystem == windowingSubsystemAttribute.Name || attribute.RequiresWindowingSubsystem == windowingSubsystemAttribute.Name
orderby attribute.Priority ascending orderby attribute.Priority ascending
select attribute).First(); select attribute).FirstOrDefault();
if (renderingSubsystemAttribute == null)
{
throw new InvalidOperationException("No rendering subsystem found. Are you missing assembly references?");
}
UseWindowingSubsystem(() => windowingSubsystemAttribute.InitializationType UseWindowingSubsystem(() => windowingSubsystemAttribute.InitializationType
.GetRuntimeMethod(windowingSubsystemAttribute.InitializationMethod, Type.EmptyTypes).Invoke(null, null), .GetRuntimeMethod(windowingSubsystemAttribute.InitializationMethod, Type.EmptyTypes).Invoke(null, null),

1
src/Avalonia.HtmlRenderer/Avalonia.HtmlRenderer.csproj

@ -4,6 +4,7 @@
<EnableDefaultCompileItems>False</EnableDefaultCompileItems> <EnableDefaultCompileItems>False</EnableDefaultCompileItems>
<EnableDefaultItems>False</EnableDefaultItems> <EnableDefaultItems>False</EnableDefaultItems>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo> <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<NoWarn>CS0436</NoWarn>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' "> <PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
<DebugSymbols>true</DebugSymbols> <DebugSymbols>true</DebugSymbols>

20
src/Avalonia.Interactivity/Interactive.cs

@ -16,14 +16,18 @@ namespace Avalonia.Interactivity
/// </summary> /// </summary>
public class Interactive : Layoutable, IInteractive public class Interactive : Layoutable, IInteractive
{ {
private readonly Dictionary<RoutedEvent, List<EventSubscription>> _eventHandlers = private Dictionary<RoutedEvent, List<EventSubscription>> _eventHandlers;
new Dictionary<RoutedEvent, List<EventSubscription>>();
/// <summary> /// <summary>
/// Gets the interactive parent of the object for bubbling and tunnelling events. /// Gets the interactive parent of the object for bubbling and tunnelling events.
/// </summary> /// </summary>
IInteractive IInteractive.InteractiveParent => ((IVisual)this).VisualParent as IInteractive; IInteractive IInteractive.InteractiveParent => ((IVisual)this).VisualParent as IInteractive;
private Dictionary<RoutedEvent, List<EventSubscription>> EventHandlers
{
get { return _eventHandlers ?? (_eventHandlers = new Dictionary<RoutedEvent, List<EventSubscription>>()); }
}
/// <summary> /// <summary>
/// Adds a handler for the specified routed event. /// Adds a handler for the specified routed event.
/// </summary> /// </summary>
@ -43,10 +47,10 @@ namespace Avalonia.Interactivity
List<EventSubscription> subscriptions; List<EventSubscription> subscriptions;
if (!_eventHandlers.TryGetValue(routedEvent, out subscriptions)) if (!EventHandlers.TryGetValue(routedEvent, out subscriptions))
{ {
subscriptions = new List<EventSubscription>(); subscriptions = new List<EventSubscription>();
_eventHandlers.Add(routedEvent, subscriptions); EventHandlers.Add(routedEvent, subscriptions);
} }
var sub = new EventSubscription var sub = new EventSubscription
@ -89,9 +93,9 @@ namespace Avalonia.Interactivity
Contract.Requires<ArgumentNullException>(routedEvent != null); Contract.Requires<ArgumentNullException>(routedEvent != null);
Contract.Requires<ArgumentNullException>(handler != null); Contract.Requires<ArgumentNullException>(handler != null);
List<EventSubscription> subscriptions; List<EventSubscription> subscriptions = null;
if (_eventHandlers.TryGetValue(routedEvent, out subscriptions)) if (_eventHandlers?.TryGetValue(routedEvent, out subscriptions) == true)
{ {
subscriptions.RemoveAll(x => x.Handler == handler); subscriptions.RemoveAll(x => x.Handler == handler);
} }
@ -181,9 +185,9 @@ namespace Avalonia.Interactivity
e.RoutedEvent.InvokeRaised(this, e); e.RoutedEvent.InvokeRaised(this, e);
List<EventSubscription> subscriptions; List<EventSubscription> subscriptions = null;
if (_eventHandlers.TryGetValue(e.RoutedEvent, out subscriptions)) if (_eventHandlers?.TryGetValue(e.RoutedEvent, out subscriptions) == true)
{ {
foreach (var sub in subscriptions.ToList()) foreach (var sub in subscriptions.ToList())
{ {

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

@ -1,6 +1,8 @@
// Copyright (c) The Avalonia Project. All rights reserved. // 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. // Licensed under the MIT license. See licence.md file in the project root for full license information.
using System;
namespace Avalonia.Styling namespace Avalonia.Styling
{ {
/// <summary> /// <summary>
@ -8,6 +10,15 @@ namespace Avalonia.Styling
/// </summary> /// </summary>
public interface IStyleHost 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> /// <summary>
/// Gets the styles for the element. /// Gets the styles for the element.
/// </summary> /// </summary>
@ -17,6 +28,5 @@ namespace Avalonia.Styling
/// Gets the parent style host element. /// Gets the parent style host element.
/// </summary> /// </summary>
IStyleHost StylingParent { get; } IStyleHost StylingParent { get; }
} }
} }

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

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

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

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

1
src/Linux/Avalonia.LinuxFramebuffer/NativeUnsafeMethods.cs

@ -72,6 +72,7 @@ namespace Avalonia.LinuxFramebuffer
FB_VBLANK_HAVE_VSYNC = 0x100 /* verical syncs can be detected */ FB_VBLANK_HAVE_VSYNC = 0x100 /* verical syncs can be detected */
} }
[StructLayout(LayoutKind.Sequential)]
unsafe struct fb_vblank { unsafe struct fb_vblank {
public VBlankFlags flags; /* FB_VBLANK flags */ public VBlankFlags flags; /* FB_VBLANK flags */
__u32 count; /* counter of retraces since boot */ __u32 count; /* counter of retraces since boot */

1
src/Windows/Avalonia.Designer/AppHost/HostedAppModel.cs

@ -86,7 +86,6 @@ namespace Avalonia.Designer.AppHost
} }
double _currentScalingFactor = 1; double _currentScalingFactor = 1;
private string _color;
private string _background; private string _background;
public event PropertyChangedEventHandler PropertyChanged; public event PropertyChangedEventHandler PropertyChanged;

38
src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs

@ -699,10 +699,40 @@ namespace Avalonia.Win32.Interop
public static extern int GetSystemMetrics(SystemMetric smIndex); public static extern int GetSystemMetrics(SystemMetric smIndex);
[DllImport("user32.dll", SetLastError = true)] [DllImport("user32.dll", SetLastError = true)]
public static extern uint GetWindowLong(IntPtr hWnd, int nIndex); public static extern uint GetWindowLongPtr(IntPtr hWnd, int nIndex);
[DllImport("user32.dll", SetLastError = true, EntryPoint = "GetWindowLong")]
public static extern uint GetWindowLong32b(IntPtr hWnd, int nIndex);
public static uint GetWindowLong(IntPtr hWnd, int nIndex)
{
if(IntPtr.Size == 4)
{
return GetWindowLong32b(hWnd, nIndex);
}
else
{
return GetWindowLongPtr(hWnd, nIndex);
}
}
[DllImport("user32.dll", SetLastError = true, EntryPoint = "SetWindowLong")]
private static extern uint SetWindowLong32b(IntPtr hWnd, int nIndex, uint value);
[DllImport("user32.dll", SetLastError = true)] [DllImport("user32.dll", SetLastError = true)]
public static extern uint SetWindowLong(IntPtr hWnd, int nIndex, uint value); private static extern uint SetWindowLongPtr(IntPtr hWnd, int nIndex, uint value);
public static uint SetWindowLong(IntPtr hWnd, int nIndex, uint value)
{
if (IntPtr.Size == 4)
{
return SetWindowLong32b(hWnd, nIndex, value);
}
else
{
return SetWindowLongPtr(hWnd, nIndex, value);
}
}
[DllImport("user32.dll", SetLastError = true)] [DllImport("user32.dll", SetLastError = true)]
public static extern bool GetWindowPlacement(IntPtr hWnd, ref WINDOWPLACEMENT lpwndpl); public static extern bool GetWindowPlacement(IntPtr hWnd, ref WINDOWPLACEMENT lpwndpl);
@ -922,9 +952,7 @@ namespace Avalonia.Win32.Interop
[StructLayout(LayoutKind.Sequential)] [StructLayout(LayoutKind.Sequential)]
internal class MONITORINFO internal class MONITORINFO
{ {
#pragma warning disable CS0618 // Type or member is obsolete public int cbSize = Marshal.SizeOf<MONITORINFO>();
public int cbSize = Marshal.SizeOf(typeof(MONITORINFO));
#pragma warning restore CS0618 // Type or member is obsolete
public RECT rcMonitor = new RECT(); public RECT rcMonitor = new RECT();
public RECT rcWork = new RECT(); public RECT rcWork = new RECT();
public int dwFlags = 0; public int dwFlags = 0;

2
src/Windows/Avalonia.Win32/Win32Platform.cs

@ -167,7 +167,7 @@ namespace Avalonia.Win32
UnmanagedMethods.WNDCLASSEX wndClassEx = new UnmanagedMethods.WNDCLASSEX UnmanagedMethods.WNDCLASSEX wndClassEx = new UnmanagedMethods.WNDCLASSEX
{ {
cbSize = Marshal.SizeOf(typeof(UnmanagedMethods.WNDCLASSEX)), cbSize = Marshal.SizeOf<UnmanagedMethods.WNDCLASSEX>(),
lpfnWndProc = _wndProcDelegate, lpfnWndProc = _wndProcDelegate,
hInstance = UnmanagedMethods.GetModuleHandle(null), hInstance = UnmanagedMethods.GetModuleHandle(null),
lpszClassName = "AvaloniaMessageWindow " + Guid.NewGuid(), lpszClassName = "AvaloniaMessageWindow " + Guid.NewGuid(),

6
src/Windows/Avalonia.Win32/WindowImpl.cs

@ -426,7 +426,7 @@ namespace Avalonia.Win32
case UnmanagedMethods.WindowsMessage.WM_DPICHANGED: case UnmanagedMethods.WindowsMessage.WM_DPICHANGED:
var dpi = ToInt32(wParam) & 0xffff; var dpi = ToInt32(wParam) & 0xffff;
var newDisplayRect = (UnmanagedMethods.RECT)Marshal.PtrToStructure(lParam, typeof(UnmanagedMethods.RECT)); var newDisplayRect = Marshal.PtrToStructure<UnmanagedMethods.RECT>(lParam);
Position = new Point(newDisplayRect.left, newDisplayRect.top); Position = new Point(newDisplayRect.left, newDisplayRect.top);
_scaling = dpi / 96.0; _scaling = dpi / 96.0;
ScalingChanged?.Invoke(_scaling); ScalingChanged?.Invoke(_scaling);
@ -494,7 +494,7 @@ namespace Avalonia.Win32
{ {
var tm = new UnmanagedMethods.TRACKMOUSEEVENT var tm = new UnmanagedMethods.TRACKMOUSEEVENT
{ {
cbSize = Marshal.SizeOf(typeof(UnmanagedMethods.TRACKMOUSEEVENT)), cbSize = Marshal.SizeOf<UnmanagedMethods.TRACKMOUSEEVENT>(),
dwFlags = 2, dwFlags = 2,
hwndTrack = _hwnd, hwndTrack = _hwnd,
dwHoverTime = 0, dwHoverTime = 0,
@ -619,7 +619,7 @@ namespace Avalonia.Win32
UnmanagedMethods.WNDCLASSEX wndClassEx = new UnmanagedMethods.WNDCLASSEX UnmanagedMethods.WNDCLASSEX wndClassEx = new UnmanagedMethods.WNDCLASSEX
{ {
cbSize = Marshal.SizeOf(typeof(UnmanagedMethods.WNDCLASSEX)), cbSize = Marshal.SizeOf<UnmanagedMethods.WNDCLASSEX>(),
style = 0, style = 0,
lpfnWndProc = _wndProcDelegate, lpfnWndProc = _wndProcDelegate,
hInstance = UnmanagedMethods.GetModuleHandle(null), hInstance = UnmanagedMethods.GetModuleHandle(null),

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

@ -388,7 +388,7 @@ namespace Avalonia.Controls.UnitTests
{ {
Template = GetTemplate(), Template = GetTemplate(),
DataContext = "Base", DataContext = "Base",
DataTemplates = new DataTemplates DataTemplates =
{ {
new FuncDataTemplate<Item>(x => new Button { Content = x }) new FuncDataTemplate<Item>(x => new Button { Content = x })
}, },

8
tests/Avalonia.Controls.UnitTests/ListBoxTests.cs

@ -109,10 +109,10 @@ namespace Avalonia.Controls.UnitTests
{ {
Template = ListBoxTemplate(), Template = ListBoxTemplate(),
DataContext = "Base", DataContext = "Base",
DataTemplates = new DataTemplates DataTemplates =
{ {
new FuncDataTemplate<Item>(x => new Button { Content = x }) new FuncDataTemplate<Item>(x => new Button { Content = x })
}, },
Items = items, Items = items,
}; };

2
tests/Avalonia.Controls.UnitTests/Presenters/ContentPresenterTests_Unrooted.cs

@ -88,7 +88,7 @@ namespace Avalonia.Controls.UnitTests.Presenters
root.Child = null; root.Child = null;
root = new TestRoot root = new TestRoot
{ {
DataTemplates = new DataTemplates DataTemplates =
{ {
new FuncDataTemplate<string>(x => new Decorator()), new FuncDataTemplate<string>(x => new Decorator()),
}, },

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

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

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

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

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

@ -135,7 +135,7 @@ namespace Avalonia.Controls.UnitTests
{ {
var root = new TestRoot var root = new TestRoot
{ {
Styles = new Styles Styles =
{ {
new Style(x => x.OfType<TabItem>()) new Style(x => x.OfType<TabItem>())
{ {
@ -174,7 +174,7 @@ namespace Avalonia.Controls.UnitTests
{ {
Template = new FuncControlTemplate<TabControl>(CreateTabControlTemplate), Template = new FuncControlTemplate<TabControl>(CreateTabControlTemplate),
DataContext = "Base", DataContext = "Base",
DataTemplates = new DataTemplates DataTemplates =
{ {
new FuncDataTemplate<Item>(x => new Button { Content = x }) new FuncDataTemplate<Item>(x => new Button { Content = x })
}, },

28
tests/Avalonia.Controls.UnitTests/TreeViewTests.cs

@ -25,9 +25,9 @@ namespace Avalonia.Controls.UnitTests
{ {
Template = CreateTreeViewTemplate(), Template = CreateTreeViewTemplate(),
Items = CreateTestTreeData(), Items = CreateTestTreeData(),
DataTemplates = CreateNodeDataTemplate(),
}; };
CreateNodeDataTemplate(target);
ApplyTemplates(target); ApplyTemplates(target);
Assert.Equal(new[] { "Root" }, ExtractItemHeader(target, 0)); Assert.Equal(new[] { "Root" }, ExtractItemHeader(target, 0));
@ -69,9 +69,9 @@ namespace Avalonia.Controls.UnitTests
{ {
Template = CreateTreeViewTemplate(), Template = CreateTreeViewTemplate(),
Items = CreateTestTreeData(), Items = CreateTestTreeData(),
DataTemplates = CreateNodeDataTemplate(),
}; };
CreateNodeDataTemplate(target);
ApplyTemplates(target); ApplyTemplates(target);
var container = (TreeViewItem)target.ItemContainerGenerator.Containers.Single().ContainerControl; var container = (TreeViewItem)target.ItemContainerGenerator.Containers.Single().ContainerControl;
@ -87,7 +87,6 @@ namespace Avalonia.Controls.UnitTests
{ {
Template = CreateTreeViewTemplate(), Template = CreateTreeViewTemplate(),
Items = tree, Items = tree,
DataTemplates = CreateNodeDataTemplate(),
}; };
// For TreeViewItem to find its parent TreeView, OnAttachedToLogicalTree needs // For TreeViewItem to find its parent TreeView, OnAttachedToLogicalTree needs
@ -95,6 +94,7 @@ namespace Avalonia.Controls.UnitTests
var root = new TestRoot(); var root = new TestRoot();
root.Child = target; root.Child = target;
CreateNodeDataTemplate(target);
ApplyTemplates(target); ApplyTemplates(target);
var container = target.ItemContainerGenerator.Index.ContainerFromItem( var container = target.ItemContainerGenerator.Index.ContainerFromItem(
@ -116,11 +116,12 @@ namespace Avalonia.Controls.UnitTests
{ {
Template = CreateTreeViewTemplate(), Template = CreateTreeViewTemplate(),
Items = tree, Items = tree,
DataTemplates = CreateNodeDataTemplate(),
}; };
var visualRoot = new TestRoot(); var visualRoot = new TestRoot();
visualRoot.Child = target; visualRoot.Child = target;
CreateNodeDataTemplate(target);
ApplyTemplates(target); ApplyTemplates(target);
var item = tree[0].Children[1].Children[0]; var item = tree[0].Children[1].Children[0];
@ -146,11 +147,12 @@ namespace Avalonia.Controls.UnitTests
{ {
Template = CreateTreeViewTemplate(), Template = CreateTreeViewTemplate(),
Items = tree, Items = tree,
DataTemplates = CreateNodeDataTemplate(),
}; };
var visualRoot = new TestRoot(); var visualRoot = new TestRoot();
visualRoot.Child = target; visualRoot.Child = target;
CreateNodeDataTemplate(target);
ApplyTemplates(target); ApplyTemplates(target);
var item = tree[0].Children[1].Children[0]; var item = tree[0].Children[1].Children[0];
@ -191,12 +193,13 @@ namespace Avalonia.Controls.UnitTests
var target = new TreeView var target = new TreeView
{ {
Template = CreateTreeViewTemplate(), Template = CreateTreeViewTemplate(),
DataTemplates = CreateNodeDataTemplate(),
Items = tree, Items = tree,
}; };
var root = new TestRoot(); var root = new TestRoot();
root.Child = target; root.Child = target;
CreateNodeDataTemplate(target);
ApplyTemplates(target); ApplyTemplates(target);
Assert.Equal(5, target.ItemContainerGenerator.Index.Items.Count()); Assert.Equal(5, target.ItemContainerGenerator.Index.Items.Count());
@ -221,7 +224,7 @@ namespace Avalonia.Controls.UnitTests
{ {
Template = CreateTreeViewTemplate(), Template = CreateTreeViewTemplate(),
DataContext = "Base", DataContext = "Base",
DataTemplates = new DataTemplates DataTemplates =
{ {
new FuncDataTemplate<Node>(x => new Button { Content = x }) new FuncDataTemplate<Node>(x => new Button { Content = x })
}, },
@ -291,9 +294,9 @@ namespace Avalonia.Controls.UnitTests
{ {
Template = CreateTreeViewTemplate(), Template = CreateTreeViewTemplate(),
Items = data, Items = data,
DataTemplates = CreateNodeDataTemplate(),
}; };
CreateNodeDataTemplate(target);
ApplyTemplates(target); ApplyTemplates(target);
Assert.Equal(new[] { "Root" }, ExtractItemHeader(target, 0)); Assert.Equal(new[] { "Root" }, ExtractItemHeader(target, 0));
@ -328,7 +331,6 @@ namespace Avalonia.Controls.UnitTests
{ {
Template = CreateTreeViewTemplate(), Template = CreateTreeViewTemplate(),
Items = data, Items = data,
DataTemplates = CreateNodeDataTemplate(),
}; };
var button = new Button(); var button = new Button();
@ -341,6 +343,7 @@ namespace Avalonia.Controls.UnitTests
} }
}; };
CreateNodeDataTemplate(target);
ApplyTemplates(target); ApplyTemplates(target);
var item = data[0].Children[0]; var item = data[0].Children[0];
@ -411,12 +414,9 @@ namespace Avalonia.Controls.UnitTests
}; };
} }
private DataTemplates CreateNodeDataTemplate() private void CreateNodeDataTemplate(IControl control)
{ {
return new DataTemplates control.DataTemplates.Add(new TestTreeDataTemplate());
{
new TestTreeDataTemplate()
};
} }
private IControlTemplate CreateTreeViewTemplate() private IControlTemplate CreateTreeViewTemplate()

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

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

31
tests/Avalonia.Input.UnitTests/Avalonia.Input.UnitTests.csproj

@ -3,35 +3,6 @@
<TargetFrameworks>net461;netcoreapp2.0</TargetFrameworks> <TargetFrameworks>net461;netcoreapp2.0</TargetFrameworks>
<OutputType>Library</OutputType> <OutputType>Library</OutputType>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<DocumentationFile>bin\Debug\Avalonia.Input.UnitTests.XML</DocumentationFile>
<NoWarn>CS1591</NoWarn>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
<Reference Include="WindowsBase" />
</ItemGroup>
<Import Project="..\..\build\UnitTests.NetCore.targets" /> <Import Project="..\..\build\UnitTests.NetCore.targets" />
<Import Project="..\..\build\Moq.props" /> <Import Project="..\..\build\Moq.props" />
<Import Project="..\..\build\XUnit.props" /> <Import Project="..\..\build\XUnit.props" />
@ -49,6 +20,6 @@
<ProjectReference Include="..\Avalonia.UnitTests\Avalonia.UnitTests.csproj" /> <ProjectReference Include="..\Avalonia.UnitTests\Avalonia.UnitTests.csproj" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" /> <Service Include="{82a7f48d-3b50-4b1e-b82e-3ada8210c358}" />
</ItemGroup> </ItemGroup>
</Project> </Project>

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)); .Bind<IWindowingPlatform>().ToConstant(new Avalonia.Controls.UnitTests.WindowingPlatformMock(() => windowImpl.Object));
var theme = new DefaultTheme(); var theme = new DefaultTheme();
globalStyles.Setup(x => x.IsStylesInitialized).Returns(true);
globalStyles.Setup(x => x.Styles).Returns(theme); globalStyles.Setup(x => x.Styles).Returns(theme);
} }
} }

2
tests/Avalonia.LeakTests/ControlTests.cs

@ -276,7 +276,7 @@ namespace Avalonia.LeakTests
{ {
Content = target = new TreeView Content = target = new TreeView
{ {
DataTemplates = new DataTemplates DataTemplates =
{ {
new FuncTreeDataTemplate<Node>( new FuncTreeDataTemplate<Node>(
x => new TextBlock { Text = x.Name }, x => new TextBlock { Text = x.Name },

1
tests/Avalonia.Styling.UnitTests/Avalonia.Styling.UnitTests.csproj

@ -2,6 +2,7 @@
<PropertyGroup> <PropertyGroup>
<TargetFrameworks>net461;netcoreapp2.0</TargetFrameworks> <TargetFrameworks>net461;netcoreapp2.0</TargetFrameworks>
<OutputType>Library</OutputType> <OutputType>Library</OutputType>
<NoWarn>CS0067</NoWarn>
</PropertyGroup> </PropertyGroup>
<Import Project="..\..\build\UnitTests.NetCore.targets" /> <Import Project="..\..\build\UnitTests.NetCore.targets" />
<Import Project="..\..\build\Moq.props" /> <Import Project="..\..\build\Moq.props" />

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

@ -16,7 +16,7 @@ namespace Avalonia.Styling.UnitTests
var tree = new Decorator var tree = new Decorator
{ {
Styles = new Styles Styles =
{ {
new Style new Style
{ {
@ -29,7 +29,7 @@ namespace Avalonia.Styling.UnitTests
}, },
Child = target = new Border Child = target = new Border
{ {
Styles = new Styles Styles =
{ {
new Style new Style
{ {
@ -60,16 +60,16 @@ namespace Avalonia.Styling.UnitTests
var tree = target = new Border 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")); Assert.Equal(AvaloniaProperty.UnsetValue, target.FindStyleResource("Baz"));

Loading…
Cancel
Save