|
|
|
@ -382,11 +382,6 @@ namespace Avalonia |
|
|
|
return _stylesApplied; |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Detaches all styles from the element and queues a restyle.
|
|
|
|
/// </summary>
|
|
|
|
protected virtual void InvalidateStyles() => DetachStyles(); |
|
|
|
|
|
|
|
protected void InitializeIfNeeded() |
|
|
|
{ |
|
|
|
if (_initCount == 0 && !IsInitialized) |
|
|
|
@ -508,17 +503,16 @@ namespace Avalonia |
|
|
|
}; |
|
|
|
} |
|
|
|
|
|
|
|
void IStyleable.DetachStyles() => DetachStyles(); |
|
|
|
|
|
|
|
void IStyleHost.StylesAdded(IReadOnlyList<IStyle> styles) |
|
|
|
{ |
|
|
|
InvalidateStylesOnThisAndDescendents(); |
|
|
|
if (HasSettersOrAnimations(styles)) |
|
|
|
InvalidateStyles(recurse: true); |
|
|
|
} |
|
|
|
|
|
|
|
void IStyleHost.StylesRemoved(IReadOnlyList<IStyle> styles) |
|
|
|
{ |
|
|
|
var allStyles = RecurseStyles(styles); |
|
|
|
DetachStylesFromThisAndDescendents(allStyles); |
|
|
|
if (FlattenStyles(styles) is { } allStyles) |
|
|
|
DetachStyles(allStyles); |
|
|
|
} |
|
|
|
|
|
|
|
protected virtual void LogicalChildrenCollectionChanged(object? sender, NotifyCollectionChangedEventArgs e) |
|
|
|
@ -663,6 +657,23 @@ namespace Avalonia |
|
|
|
return null; |
|
|
|
} |
|
|
|
|
|
|
|
internal virtual void InvalidateStyles(bool recurse) |
|
|
|
{ |
|
|
|
var values = GetValueStore(); |
|
|
|
values.BeginStyling(); |
|
|
|
try { values.RemoveFrames(FrameType.Style); } |
|
|
|
finally { values.EndStyling(); } |
|
|
|
|
|
|
|
_stylesApplied = false; |
|
|
|
|
|
|
|
if (recurse && GetInheritanceChildren() is { } children) |
|
|
|
{ |
|
|
|
var childCount = children.Count; |
|
|
|
for (var i = 0; i < childCount; ++i) |
|
|
|
(children[i] as StyledElement)?.InvalidateStyles(recurse); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
private static void DataContextNotifying(IAvaloniaObject o, bool updateStarted) |
|
|
|
{ |
|
|
|
if (o is StyledElement element) |
|
|
|
@ -822,7 +833,7 @@ namespace Avalonia |
|
|
|
{ |
|
|
|
_logicalRoot = null; |
|
|
|
_implicitTheme = null; |
|
|
|
DetachStyles(); |
|
|
|
InvalidateStyles(recurse: false); |
|
|
|
OnDetachedFromLogicalTree(e); |
|
|
|
DetachedFromLogicalTree?.Invoke(this, e); |
|
|
|
|
|
|
|
@ -884,71 +895,81 @@ namespace Avalonia |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
private void DetachStyles(IReadOnlyList<StyleBase>? styles = null) |
|
|
|
private void DetachStyles(IReadOnlyList<Style> styles) |
|
|
|
{ |
|
|
|
var valueStore = GetValueStore(); |
|
|
|
|
|
|
|
valueStore.BeginStyling(); |
|
|
|
var values = GetValueStore(); |
|
|
|
values.BeginStyling(); |
|
|
|
try { values.RemoveFrames(styles); } |
|
|
|
finally { values.EndStyling(); } |
|
|
|
|
|
|
|
for (var i = valueStore.Frames.Count - 1; i >= 0; --i) |
|
|
|
if (_logicalChildren is not null) |
|
|
|
{ |
|
|
|
if (valueStore.Frames[i] is StyleInstance si && |
|
|
|
si.Source is not ControlTheme && |
|
|
|
(styles is null || styles.Contains(si.Source))) |
|
|
|
var childCount = _logicalChildren.Count; |
|
|
|
|
|
|
|
for (var i = 0; i < childCount; ++i) |
|
|
|
{ |
|
|
|
valueStore.RemoveFrame(si); |
|
|
|
(_logicalChildren[i] as StyledElement)?.DetachStyles(styles); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
valueStore.EndStyling(); |
|
|
|
_stylesApplied = false; |
|
|
|
} |
|
|
|
|
|
|
|
private void InvalidateStylesOnThisAndDescendents() |
|
|
|
private void NotifyResourcesChanged( |
|
|
|
ResourcesChangedEventArgs? e = null, |
|
|
|
bool propagate = true) |
|
|
|
{ |
|
|
|
InvalidateStyles(); |
|
|
|
|
|
|
|
if (_logicalChildren is object) |
|
|
|
if (ResourcesChanged is object) |
|
|
|
{ |
|
|
|
var childCount = _logicalChildren.Count; |
|
|
|
e ??= ResourcesChangedEventArgs.Empty; |
|
|
|
ResourcesChanged(this, e); |
|
|
|
} |
|
|
|
|
|
|
|
for (var i = 0; i < childCount; ++i) |
|
|
|
{ |
|
|
|
(_logicalChildren[i] as StyledElement)?.InvalidateStylesOnThisAndDescendents(); |
|
|
|
} |
|
|
|
if (propagate) |
|
|
|
{ |
|
|
|
e ??= ResourcesChangedEventArgs.Empty; |
|
|
|
NotifyChildResourcesChanged(e); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
private void DetachStylesFromThisAndDescendents(IReadOnlyList<StyleBase> styles) |
|
|
|
private static IReadOnlyList<Style>? FlattenStyles(IReadOnlyList<IStyle> styles) |
|
|
|
{ |
|
|
|
DetachStyles(styles); |
|
|
|
List<Style>? result = null; |
|
|
|
|
|
|
|
if (_logicalChildren is object) |
|
|
|
static void FlattenStyle(IStyle style, ref List<Style>? result) |
|
|
|
{ |
|
|
|
var childCount = _logicalChildren.Count; |
|
|
|
if (style is Style s) |
|
|
|
(result ??= new()).Add(s); |
|
|
|
FlattenStyles(style.Children, ref result); |
|
|
|
} |
|
|
|
|
|
|
|
for (var i = 0; i < childCount; ++i) |
|
|
|
{ |
|
|
|
(_logicalChildren[i] as StyledElement)?.DetachStylesFromThisAndDescendents(styles); |
|
|
|
} |
|
|
|
static void FlattenStyles(IReadOnlyList<IStyle> styles, ref List<Style>? result) |
|
|
|
{ |
|
|
|
var count = styles.Count; |
|
|
|
for (var i = 0; i < count; ++i) |
|
|
|
FlattenStyle(styles[i], ref result); |
|
|
|
} |
|
|
|
|
|
|
|
FlattenStyles(styles, ref result); |
|
|
|
return result; |
|
|
|
} |
|
|
|
|
|
|
|
private void NotifyResourcesChanged( |
|
|
|
ResourcesChangedEventArgs? e = null, |
|
|
|
bool propagate = true) |
|
|
|
private static bool HasSettersOrAnimations(IReadOnlyList<IStyle> styles) |
|
|
|
{ |
|
|
|
if (ResourcesChanged is object) |
|
|
|
static bool StyleHasSettersOrAnimations(IStyle style) |
|
|
|
{ |
|
|
|
e ??= ResourcesChangedEventArgs.Empty; |
|
|
|
ResourcesChanged(this, e); |
|
|
|
if (style is StyleBase s && s.HasSettersOrAnimations) |
|
|
|
return true; |
|
|
|
return HasSettersOrAnimations(style.Children); |
|
|
|
} |
|
|
|
|
|
|
|
if (propagate) |
|
|
|
var count = styles.Count; |
|
|
|
|
|
|
|
for (var i = 0; i < count; ++i) |
|
|
|
{ |
|
|
|
e ??= ResourcesChangedEventArgs.Empty; |
|
|
|
NotifyChildResourcesChanged(e); |
|
|
|
if (StyleHasSettersOrAnimations(styles[i])) |
|
|
|
return true; |
|
|
|
} |
|
|
|
|
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
private static IReadOnlyList<StyleBase> RecurseStyles(IReadOnlyList<IStyle> styles) |
|
|
|
|