Browse Source

Merge branch 'master' into fix-next-draw-as

pull/3940/head
Dariusz Komosiński 6 years ago
committed by GitHub
parent
commit
dbc38de0f2
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 28
      src/Avalonia.Controls/Repeater/ItemsRepeater.cs
  2. 36
      src/Avalonia.Controls/Repeater/ViewManager.cs
  3. 10
      src/Avalonia.DesignerSupport/Remote/RemoteDesignerEntryPoint.cs
  4. 10
      src/Avalonia.Layout/FlowLayoutAlgorithm.cs
  5. 20
      src/Avalonia.Layout/StackLayout.cs
  6. 2
      src/Avalonia.Layout/StackLayoutState.cs
  7. 1
      src/Avalonia.Layout/UniformGridLayout.cs
  8. 24
      src/Avalonia.Remote.Protocol/DesignMessages.cs
  9. 4
      src/Avalonia.Visuals/Media/BoxShadows.cs
  10. 6
      src/Avalonia.Visuals/Media/DrawingContext.cs

28
src/Avalonia.Controls/Repeater/ItemsRepeater.cs

@ -10,6 +10,7 @@ using Avalonia.Controls.Templates;
using Avalonia.Data;
using Avalonia.Input;
using Avalonia.Layout;
using Avalonia.VisualTree;
namespace Avalonia.Controls
{
@ -379,14 +380,19 @@ namespace Avalonia.Controls
{
if (property == ItemsProperty)
{
var oldEnumerable = oldValue.GetValueOrDefault<IEnumerable>();
var newEnumerable = newValue.GetValueOrDefault<IEnumerable>();
var newDataSource = newEnumerable as ItemsSourceView;
if (newEnumerable != null && newDataSource == null)
if (oldEnumerable != newEnumerable)
{
newDataSource = new ItemsSourceView(newEnumerable);
}
var newDataSource = newEnumerable as ItemsSourceView;
if (newEnumerable != null && newDataSource == null)
{
newDataSource = new ItemsSourceView(newEnumerable);
}
OnDataSourcePropertyChanged(ItemsSourceView, newDataSource);
OnDataSourcePropertyChanged(ItemsSourceView, newDataSource);
}
}
else if (property == ItemTemplateProperty)
{
@ -431,8 +437,16 @@ namespace Avalonia.Controls
private int GetElementIndexImpl(IControl element)
{
var virtInfo = TryGetVirtualizationInfo(element);
return _viewManager.GetElementIndex(virtInfo);
// Verify that element is actually a child of this ItemsRepeater
var parent = element.GetVisualParent();
if (parent == this)
{
var virtInfo = TryGetVirtualizationInfo(element);
return _viewManager.GetElementIndex(virtInfo);
}
return -1;
}
private IControl GetElementFromIndexImpl(int index)

36
src/Avalonia.Controls/Repeater/ViewManager.cs

@ -388,19 +388,24 @@ namespace Avalonia.Controls
}
case NotifyCollectionChangedAction.Reset:
if (_owner.ItemsSourceView.HasKeyIndexMapping)
// If we get multiple resets back to back before
// running layout, we dont have to clear all the elements again.
if (!_isDataSourceStableResetPending)
{
_isDataSourceStableResetPending = true;
}
if (_owner.ItemsSourceView.HasKeyIndexMapping)
{
_isDataSourceStableResetPending = true;
}
// Walk through all the elements and make sure they are cleared, they will go into
// the stable id reset pool.
foreach (var element in _owner.Children)
{
var virtInfo = ItemsRepeater.GetVirtualizationInfo(element);
if (virtInfo.IsRealized && virtInfo.AutoRecycleCandidate)
// Walk through all the elements and make sure they are cleared, they will go into
// the stable id reset pool.
foreach (var element in _owner.Children)
{
_owner.ClearElementImpl(element);
var virtInfo = ItemsRepeater.GetVirtualizationInfo(element);
if (virtInfo.IsRealized && virtInfo.AutoRecycleCandidate)
{
_owner.ClearElementImpl(element);
}
}
}
@ -441,6 +446,9 @@ namespace Avalonia.Controls
}
_resetPool.Clear();
// Flush the realized indices once the stable reset pool is cleared to start fresh.
InvalidateRealizedIndicesHeldByLayout();
}
}
@ -498,6 +506,10 @@ namespace Avalonia.Controls
var virtInfo = ItemsRepeater.GetVirtualizationInfo(element);
virtInfo.MoveOwnershipToLayoutFromUniqueIdResetPool();
UpdateElementIndex(element, virtInfo, index);
// Update realized indices
_firstRealizedElementIndexHeldByLayout = Math.Min(_firstRealizedElementIndexHeldByLayout, index);
_lastRealizedElementIndexHeldByLayout = Math.Max(_lastRealizedElementIndexHeldByLayout, index);
}
}
@ -519,6 +531,10 @@ namespace Avalonia.Controls
_pinnedPool.RemoveAt(i);
element = elementInfo.PinnedElement;
elementInfo.VirtualizationInfo.MoveOwnershipToLayoutFromPinnedPool();
// Update realized indices
_firstRealizedElementIndexHeldByLayout = Math.Min(_firstRealizedElementIndexHeldByLayout, index);
_lastRealizedElementIndexHeldByLayout = Math.Max(_lastRealizedElementIndexHeldByLayout, index);
break;
}
}

10
src/Avalonia.DesignerSupport/Remote/RemoteDesignerEntryPoint.cs

@ -234,18 +234,10 @@ namespace Avalonia.DesignerSupport.Remote
}
catch (Exception e)
{
var xmlException = e as XmlException;
s_transport.Send(new UpdateXamlResultMessage
{
Error = e.ToString(),
Exception = new ExceptionDetails
{
ExceptionType = e.GetType().FullName,
Message = e.Message.ToString(),
LineNumber = xmlException?.LineNumber,
LinePosition = xmlException?.LinePosition,
}
Exception = new ExceptionDetails(e),
});
}
}

10
src/Avalonia.Layout/FlowLayoutAlgorithm.cs

@ -74,6 +74,7 @@ namespace Avalonia.Layout
double lineSpacing,
int maxItemsPerLine,
ScrollOrientation orientation,
bool disableVirtualization,
string layoutId)
{
_orientation.ScrollOrientation = orientation;
@ -95,14 +96,14 @@ namespace Avalonia.Layout
_elementManager.OnBeginMeasure(orientation);
int anchorIndex = GetAnchorIndex(availableSize, isWrapping, minItemSpacing, layoutId);
Generate(GenerateDirection.Forward, anchorIndex, availableSize, minItemSpacing, lineSpacing, maxItemsPerLine, layoutId);
Generate(GenerateDirection.Backward, anchorIndex, availableSize, minItemSpacing, lineSpacing, maxItemsPerLine, layoutId);
Generate(GenerateDirection.Forward, anchorIndex, availableSize, minItemSpacing, lineSpacing, maxItemsPerLine, disableVirtualization, layoutId);
Generate(GenerateDirection.Backward, anchorIndex, availableSize, minItemSpacing, lineSpacing, maxItemsPerLine, disableVirtualization, layoutId);
if (isWrapping && IsReflowRequired())
{
var firstElementBounds = _elementManager.GetLayoutBoundsForRealizedIndex(0);
_orientation.SetMinorStart(ref firstElementBounds, 0);
_elementManager.SetLayoutBoundsForRealizedIndex(0, firstElementBounds);
Generate(GenerateDirection.Forward, 0 /*anchorIndex*/, availableSize, minItemSpacing, lineSpacing, maxItemsPerLine, layoutId);
Generate(GenerateDirection.Forward, 0 /*anchorIndex*/, availableSize, minItemSpacing, lineSpacing, maxItemsPerLine, disableVirtualization, layoutId);
}
RaiseLineArranged();
@ -273,6 +274,7 @@ namespace Avalonia.Layout
double minItemSpacing,
double lineSpacing,
int maxItemsPerLine,
bool disableVirtualization,
string layoutId)
{
if (anchorIndex != -1)
@ -288,7 +290,7 @@ namespace Avalonia.Layout
bool lineNeedsReposition = false;
while (_elementManager.IsIndexValidInData(currentIndex) &&
ShouldContinueFillingUpSpace(previousIndex, direction))
(disableVirtualization || ShouldContinueFillingUpSpace(previousIndex, direction)))
{
// Ensure layout element.
_elementManager.EnsureElementRealized(direction == GenerateDirection.Forward, currentIndex, layoutId);

20
src/Avalonia.Layout/StackLayout.cs

@ -14,6 +14,12 @@ namespace Avalonia.Layout
/// </summary>
public class StackLayout : VirtualizingLayout, IFlowLayoutAlgorithmDelegates
{
/// <summary>
/// Defines the <see cref="DisableVirtualization"/> property.
/// </summary>
public static readonly StyledProperty<bool> DisableVirtualizationProperty =
AvaloniaProperty.Register<StackLayout, bool>(nameof(DisableVirtualization));
/// <summary>
/// Defines the <see cref="Orientation"/> property.
/// </summary>
@ -36,6 +42,15 @@ namespace Avalonia.Layout
LayoutId = "StackLayout";
}
/// <summary>
/// Gets or sets a value indicating whether virtualization is disabled on the layout.
/// </summary>
public bool DisableVirtualization
{
get => GetValue(DisableVirtualizationProperty);
set => SetValue(DisableVirtualizationProperty, value);
}
/// <summary>
/// Gets or sets the axis along which items are laid out.
/// </summary>
@ -262,6 +277,8 @@ namespace Avalonia.Layout
protected internal override Size MeasureOverride(VirtualizingLayoutContext context, Size availableSize)
{
((StackLayoutState)context.LayoutState).OnMeasureStart();
var desiredSize = GetFlowAlgorithm(context).Measure(
availableSize,
context,
@ -270,6 +287,7 @@ namespace Avalonia.Layout
Spacing,
int.MaxValue,
_orientation.ScrollOrientation,
DisableVirtualization,
LayoutId);
return new Size(desiredSize.Width, desiredSize.Height);
@ -284,8 +302,6 @@ namespace Avalonia.Layout
FlowLayoutAlgorithm.LineAlignment.Start,
LayoutId);
((StackLayoutState)context.LayoutState).OnArrangeLayoutEnd();
return new Size(value.Width, value.Height);
}

2
src/Avalonia.Layout/StackLayoutState.cs

@ -56,6 +56,6 @@ namespace Avalonia.Layout
MaxArrangeBounds = Math.Max(MaxArrangeBounds, minorSize);
}
internal void OnArrangeLayoutEnd() => MaxArrangeBounds = 0;
internal void OnMeasureStart() => MaxArrangeBounds = 0;
}
}

1
src/Avalonia.Layout/UniformGridLayout.cs

@ -433,6 +433,7 @@ namespace Avalonia.Layout
LineSpacing,
_maximumRowsOrColumns,
_orientation.ScrollOrientation,
false,
LayoutId);
// If after Measure the first item is in the realization rect, then we revoke grid state's ownership,

24
src/Avalonia.Remote.Protocol/DesignMessages.cs

@ -1,4 +1,7 @@
using System;
using System.Reflection;
using System.Runtime.ExceptionServices;
using System.Xml;
namespace Avalonia.Remote.Protocol.Designer
{
@ -26,6 +29,27 @@ namespace Avalonia.Remote.Protocol.Designer
public class ExceptionDetails
{
public ExceptionDetails()
{
}
public ExceptionDetails(Exception e)
{
if (e is TargetInvocationException)
{
e = e.InnerException;
}
ExceptionType = e.GetType().Name;
Message = e.Message;
if (e is XmlException xml)
{
LineNumber = xml.LineNumber;
LinePosition = xml.LinePosition;
}
}
public string ExceptionType { get; set; }
public string Message { get; set; }
public int? LineNumber { get; set; }

4
src/Avalonia.Visuals/Media/BoxShadows.cs

@ -21,7 +21,7 @@ namespace Avalonia.Media
{
_first = shadow;
_list = null;
Count = 1;
Count = _first.IsEmpty ? 0 : 1;
}
public BoxShadows(BoxShadow first, BoxShadow[] rest)
@ -105,8 +105,6 @@ namespace Avalonia.Media
return false;
}
}
public static implicit operator BoxShadows(BoxShadow shadow) => new BoxShadows(shadow);
public bool Equals(BoxShadows other)
{

6
src/Avalonia.Visuals/Media/DrawingContext.cs

@ -141,13 +141,13 @@ namespace Avalonia.Media
/// <param name="radiusY">The radius in the Y dimension of the rounded corners.
/// This value will be clamped to the range of 0 to Height/2
/// </param>
/// <param name="boxShadow">Box shadow effect parameters</param>
/// <param name="boxShadows">Box shadow effect parameters</param>
/// <remarks>
/// The brush and the pen can both be null. If the brush is null, then no fill is performed.
/// If the pen is null, then no stoke is performed. If both the pen and the brush are null, then the drawing is not visible.
/// </remarks>
public void DrawRectangle(IBrush brush, IPen pen, Rect rect, double radiusX = 0, double radiusY = 0,
BoxShadow boxShadow = default)
BoxShadows boxShadows = default)
{
if (brush == null && !PenIsVisible(pen))
{
@ -164,7 +164,7 @@ namespace Avalonia.Media
radiusY = Math.Min(radiusY, rect.Height / 2);
}
PlatformImpl.DrawRectangle(brush, pen, new RoundedRect(rect, radiusX, radiusY), boxShadow);
PlatformImpl.DrawRectangle(brush, pen, new RoundedRect(rect, radiusX, radiusY), boxShadows);
}
/// <summary>

Loading…
Cancel
Save