Browse Source

Added a SimpleGrid to use in DevTools.

As our `Grid` performance is currently terrible :(
pull/543/head
Steven Kirk 10 years ago
parent
commit
1f185f0701
  1. 3
      src/Avalonia.Diagnostics/Avalonia.Diagnostics.csproj
  2. 12
      src/Avalonia.Diagnostics/Views/ControlDetailsView.cs
  3. 30
      src/Avalonia.Diagnostics/Views/GridRepeater.cs
  4. 147
      src/Avalonia.Diagnostics/Views/SimpleGrid.cs

3
src/Avalonia.Diagnostics/Avalonia.Diagnostics.csproj

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.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>
@ -105,6 +105,7 @@
<Compile Include="ViewModels\LogicalTreeNode.cs" />
<Compile Include="ViewModels\TreeNode.cs" />
<Compile Include="ViewModels\VisualTreeNode.cs" />
<Compile Include="Views\SimpleGrid.cs" />
<Compile Include="Views\TreePage.xaml.cs">
<DependentUpon>TreePageView.xaml</DependentUpon>
</Compile>

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

@ -6,6 +6,7 @@ using System.Collections.Generic;
using System.Reactive.Linq;
using Avalonia.Controls;
using Avalonia.Diagnostics.ViewModels;
using Avalonia.Media;
using Avalonia.Styling;
using ReactiveUI;
@ -35,14 +36,8 @@ namespace Avalonia.Diagnostics.Views
Content = new ScrollViewer
{
Content = new Grid
Content = new SimpleGrid
{
ColumnDefinitions = new ColumnDefinitions
{
new ColumnDefinition(GridLength.Auto),
new ColumnDefinition(GridLength.Auto),
new ColumnDefinition(GridLength.Auto),
},
Styles = new Styles
{
new Style(x => x.Is<Control>())
@ -66,16 +61,19 @@ namespace Avalonia.Diagnostics.Views
yield return new TextBlock
{
Text = property.Name,
TextWrapping = TextWrapping.NoWrap,
[!ToolTip.TipProperty] = property.WhenAnyValue(x => x.Diagnostic),
};
yield return new TextBlock
{
TextWrapping = TextWrapping.NoWrap,
[!TextBlock.TextProperty] = property.WhenAnyValue(v => v.Value).Select(v => v?.ToString()),
};
yield return new TextBlock
{
TextWrapping = TextWrapping.NoWrap,
[!TextBlock.TextProperty] = property.WhenAnyValue(x => x.Priority),
};
}

30
src/Avalonia.Diagnostics/Views/GridRepeater.cs

@ -11,10 +11,10 @@ namespace Avalonia.Diagnostics.Views
internal static class GridRepeater
{
public static readonly AttachedProperty<IEnumerable> ItemsProperty =
AvaloniaProperty.RegisterAttached<Grid, IEnumerable>("Items", typeof(GridRepeater));
AvaloniaProperty.RegisterAttached<SimpleGrid, IEnumerable>("Items", typeof(GridRepeater));
public static readonly AttachedProperty<Func<object, IEnumerable<Control>>> TemplateProperty =
AvaloniaProperty.RegisterAttached<Grid, Func<object, IEnumerable<Control>>>("Template", typeof(GridRepeater));
AvaloniaProperty.RegisterAttached<SimpleGrid, Func<object, IEnumerable<Control>>>("Template", typeof(GridRepeater));
static GridRepeater()
{
@ -23,7 +23,7 @@ namespace Avalonia.Diagnostics.Views
private static void ItemsChanged(AvaloniaPropertyChangedEventArgs e)
{
var grid = (Grid)e.Sender;
var grid = (SimpleGrid)e.Sender;
var items = (IEnumerable)e.NewValue;
var template = grid.GetValue(TemplateProperty);
@ -32,36 +32,18 @@ namespace Avalonia.Diagnostics.Views
if (items != null)
{
int count = 0;
int cols = grid.ColumnDefinitions.Count;
int cols = 3;
foreach (var item in items)
{
foreach (var control in template(item))
{
grid.Children.Add(control);
Grid.SetColumn(control, count % cols);
Grid.SetRow(control, count / cols);
SimpleGrid.SetColumn(control, count % cols);
SimpleGrid.SetRow(control, count / cols);
++count;
}
}
int rows = (int)Math.Ceiling((double)count / cols);
int difference = rows - grid.RowDefinitions.Count;
if (difference > 0)
{
for (int i = 0; i < difference; ++i)
{
grid.RowDefinitions.Add(new RowDefinition(GridLength.Auto));
}
}
else if (difference < 0)
{
for (int i = 0; i < difference; ++i)
{
grid.RowDefinitions.RemoveAt(grid.RowDefinitions.Count - 1);
}
}
}
}
}

147
src/Avalonia.Diagnostics/Views/SimpleGrid.cs

@ -0,0 +1,147 @@
// 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.Collections.Generic;
using System.Linq;
using Avalonia.Controls;
namespace Avalonia.Diagnostics.Views
{
/// <summary>
/// A simple grid control that lays out columns with a equal width and rows to their desired
/// size.
/// </summary>
/// <remarks>
/// This is used in the devtools because our <see cref="Grid"/> performance sucks.
/// </remarks>
public class SimpleGrid : Panel
{
private List<double> _columnWidths = new List<double>();
private List<double> _rowHeights = new List<double>();
private double _totalWidth;
private double _totalHeight;
/// <summary>
/// Defines the Column attached property.
/// </summary>
public static readonly AttachedProperty<int> ColumnProperty =
AvaloniaProperty.RegisterAttached<SimpleGrid, Control, int>("Column");
/// <summary>
/// Defines the Row attached property.
/// </summary>
public static readonly AttachedProperty<int> RowProperty =
AvaloniaProperty.RegisterAttached<SimpleGrid, Control, int>("Row");
/// <summary>
/// Gets the value of the Column attached property for a control.
/// </summary>
/// <param name="control">The control.</param>
/// <returns>The control's column.</returns>
public static int GetColumn(IControl control)
{
return control.GetValue(ColumnProperty);
}
/// <summary>
/// Gets the value of the Row attached property for a control.
/// </summary>
/// <param name="control">The control.</param>
/// <returns>The control's row.</returns>
public static int GetRow(IControl control)
{
return control.GetValue(RowProperty);
}
/// <summary>
/// Sets the value of the Column attached property for a control.
/// </summary>
/// <param name="control">The control.</param>
/// <param name="value">The column value.</param>
public static void SetColumn(IControl control, int value)
{
control.SetValue(ColumnProperty, value);
}
/// <summary>
/// Sets the value of the Row attached property for a control.
/// </summary>
/// <param name="control">The control.</param>
/// <param name="value">The row value.</param>
public static void SetRow(IControl control, int value)
{
control.SetValue(RowProperty, value);
}
protected override Size MeasureOverride(Size availableSize)
{
_columnWidths.Clear();
_rowHeights.Clear();
_totalWidth = 0;
_totalHeight = 0;
foreach (var child in Children)
{
var column = GetColumn(child);
var row = GetRow(child);
child.Measure(availableSize);
var desired = child.DesiredSize;
UpdateCell(_columnWidths, column, desired.Width, ref _totalWidth);
UpdateCell(_rowHeights, row, desired.Height, ref _totalHeight);
}
return new Size(_totalWidth, _totalHeight);
}
protected override Size ArrangeOverride(Size finalSize)
{
var columnWidth = finalSize.Width / _columnWidths.Count;
foreach (var child in Children)
{
var column = GetColumn(child);
var row = GetRow(child);
var rect = new Rect(column * columnWidth, GetRowTop(row), columnWidth, _rowHeights[row]);
child.Arrange(rect);
}
return new Size(finalSize.Width, _totalHeight);
}
private double UpdateCell(IList<double> cells, int cell, double value, ref double total)
{
while (cells.Count < cell + 1)
{
cells.Add(0);
}
var existing = cells[cell];
if (value > existing)
{
cells[cell] = value;
total += value - existing;
return value;
}
else
{
return existing;
}
}
private double GetRowTop(int row)
{
var result = 0.0;
for (var i = 0; i < row; ++i)
{
result += _rowHeights[i];
}
return result;
}
}
}
Loading…
Cancel
Save