private static void SetAttachedToToNull(List <RenderInfo <TDependencyObject> > copy, IDependencyPropertyService <TDependencyObject, TStyle, TDependencyProperty> dependencyPropertyService, ISwitchableTreeNodeProvider <TDependencyObject> switchableTreeNodeProvider, INativeStyleService <TStyle, TDependencyObject, TDependencyProperty> nativeStyleService) { var removedStyleSheets = copy .Where(x => x.RenderTargetKind == RenderTargetKind.Stylesheet && x.ChangeKind == ChangeKind.Remove) .Select(x => x.StyleSheet) .Distinct() .ToList(); foreach (var removedStyleSheet in removedStyleSheets) { switchableTreeNodeProvider.Switch(SelectorType.LogicalTree); ReevaluateStylesheetInSubTree(switchableTreeNodeProvider.GetDomElement((TDependencyObject)removedStyleSheet.AttachedTo), removedStyleSheet, dependencyPropertyService, nativeStyleService); removedStyleSheet.AttachedTo = null; } }
private List <StyleMatchInfo> UpdateMatchingStyles(TUIElement styleResourceReferenceHolder, StyleSheet styleSheet, TUIElement startFrom) { var requiredStyleInfos = new List <StyleMatchInfo>(); IDomElement <TDependencyObject> root = null; IDomElement <TDependencyObject> visualTree = null; IDomElement <TDependencyObject> logicalTree = null; foreach (var rule in styleSheet.Rules) { // Debug.WriteLine($"--- RULE {rule.SelectorString} ----"); if (rule.SelectorType == SelectorType.VisualTree) { treeNodeProvider.Switch(SelectorType.VisualTree); if (visualTree == null) { visualTree = treeNodeProvider.GetDomElement(startFrom ?? styleResourceReferenceHolder); visualTree.XamlCssStyleSheets.Clear(); visualTree.XamlCssStyleSheets.Add(styleSheet); } root = visualTree; } else { treeNodeProvider.Switch(SelectorType.LogicalTree); if (logicalTree == null) { if (!treeNodeProvider.IsInTree(startFrom ?? styleResourceReferenceHolder)) { continue; } logicalTree = treeNodeProvider.GetDomElement(startFrom ?? styleResourceReferenceHolder); logicalTree.XamlCssStyleSheets.Clear(); logicalTree.XamlCssStyleSheets.Add(styleSheet); } root = logicalTree; } // apply our selector var matchedNodes = root.QuerySelectorAllWithSelf(rule.SelectorString) .Where(x => x != null) .Cast <IDomElement <TDependencyObject> >() .ToList(); var otherStyleElements = matchedNodes .Where(x => { var parent = GetStyleSheetParent(x.Element); // parent happens to be null if class was changed by binding if (parent == null) { return(true); } var elementStyleSheet = dependencyPropertyService.GetStyleSheet(parent); return(elementStyleSheet != null && elementStyleSheet != styleSheet); }).ToList(); matchedNodes = matchedNodes.Except(otherStyleElements).ToList(); var matchedElementTypes = matchedNodes .Select(x => x.Element.GetType()) .Distinct() .ToList(); foreach (var matchingNode in matchedNodes) { var element = matchingNode.Element; var oldMatchingStyles = dependencyPropertyService.GetMatchingStyles(element) ?? new string[0]; var resourceKey = nativeStyleService.GetStyleResourceKey(styleSheet.Id, element.GetType(), rule.SelectorString); var newMatchingStyles = oldMatchingStyles.Concat(new[] { resourceKey }).Distinct() .Select(x => new { key = x, selector = new Selector { Value = x.Split('{')[1] } }) .OrderBy(x => x.selector.IdSpecificity) .ThenBy(x => x.selector.ClassSpecificity) .ThenBy(x => x.selector.SimpleSpecificity) .ToArray(); var newMatchingStylesStrings = newMatchingStyles.Select(x => x.key).ToArray(); // Debug.WriteLine($"'{rule.SelectorString}' {GetPath(matchingNode)}: " + string.Join("|", newMatchingStylesStrings)); dependencyPropertyService.SetMatchingStyles(element, newMatchingStylesStrings); if (requiredStyleInfos.Any(x => x.Rule == rule && x.MatchedType == element.GetType()) == false) { requiredStyleInfos.Add(new StyleMatchInfo { Rule = rule, MatchedType = element.GetType() }); } } } return(requiredStyleInfos); }
public static void Render( List <RenderInfo <TDependencyObject> > copy, ISwitchableTreeNodeProvider <TDependencyObject> switchableTreeNodeProvider, IDependencyPropertyService <TDependencyObject, TStyle, TDependencyProperty> dependencyPropertyService, INativeStyleService <TStyle, TDependencyObject, TDependencyProperty> nativeStyleService, IStyleResourcesService applicationResourcesService, CssTypeHelper <TDependencyObject, TDependencyProperty, TStyle> cssTypeHelper) { try { "BeginUpdate".Measure(() => applicationResourcesService.BeginUpdate()); "RemoveOldStyleObjects".Measure(() => { RemoveOldStyleObjects(copy, nativeStyleService, applicationResourcesService); }); "SetAttachedToToNull".Measure(() => { SetAttachedToToNull(copy, dependencyPropertyService, switchableTreeNodeProvider, nativeStyleService); }); "SetAttachedToToNewStyleSheet".Measure(() => { SetAttachedToToNewStyleSheet(copy, dependencyPropertyService, switchableTreeNodeProvider, nativeStyleService); }); var styleUpdateInfos = new Dictionary <TDependencyObject, StyleUpdateInfo>(); var newOrUpdatedStyleSheets = copy .Where(x => x.RenderTargetKind == RenderTargetKind.Stylesheet) .Select(x => x.StyleSheet) .Distinct() .ToList(); var newOrUpdatedStyleHolders = copy .Where(x => x.ChangeKind == ChangeKind.New || x.ChangeKind == ChangeKind.Update || x.ChangeKind == ChangeKind.Remove) .Select(x => new { x.ChangeKind, x.StartFrom, x.StyleSheet, x.StyleSheetHolder }) .Distinct() .ToList(); "SetupStyleInfo LOGICAL".Measure(() => { switchableTreeNodeProvider.Switch(SelectorType.LogicalTree); foreach (var item in newOrUpdatedStyleHolders) { var start = item.StartFrom ?? item.StyleSheetHolder; if (!switchableTreeNodeProvider.IsInTree(start)) { continue; } var domElement = switchableTreeNodeProvider.GetDomElement(start); "EnsureParents".Measure(() => { EnsureParents(domElement, switchableTreeNodeProvider, dependencyPropertyService, nativeStyleService, styleUpdateInfos); }); SetupStyleInfo(domElement, item.StyleSheet, styleUpdateInfos, switchableTreeNodeProvider, dependencyPropertyService, nativeStyleService, false, item.ChangeKind == ChangeKind.Remove); } }); "SetupStyleInfo VisualTree".Measure(() => { switchableTreeNodeProvider.Switch(SelectorType.VisualTree); foreach (var item in newOrUpdatedStyleHolders) { var start = item.StartFrom ?? item.StyleSheetHolder; if (!switchableTreeNodeProvider.IsInTree(start)) { continue; } var domElement = switchableTreeNodeProvider.GetDomElement(start); "EnsureParents".Measure(() => { EnsureParents(domElement, switchableTreeNodeProvider, dependencyPropertyService, nativeStyleService, styleUpdateInfos); }); var discardOldMatchingStyles = newOrUpdatedStyleSheets.Contains(item.StyleSheet); SetupStyleInfo(domElement, item.StyleSheet, styleUpdateInfos, switchableTreeNodeProvider, dependencyPropertyService, nativeStyleService, discardOldMatchingStyles, item.ChangeKind == ChangeKind.Remove); } }); var tasks = new List <Task <IList <IDomElement <TDependencyObject> > > >(); foreach (var item in copy.Select(x => new { x.StartFrom, x.StyleSheetHolder, x.StyleSheet }).Distinct().ToList()) { var start = item.StartFrom ?? item.StyleSheetHolder; if (!styleUpdateInfos.ContainsKey(start)) { continue; } switchableTreeNodeProvider.Switch(SelectorType.LogicalTree); var logical = switchableTreeNodeProvider.GetDomElement(start); logical.StyleInfo = styleUpdateInfos[start]; if (!switchableTreeNodeProvider.IsInTree(start)) { logical = null; } switchableTreeNodeProvider.Switch(SelectorType.VisualTree); var visual = switchableTreeNodeProvider.GetDomElement(start); visual.StyleInfo = styleUpdateInfos[start]; if (!switchableTreeNodeProvider.IsInTree(start)) { visual = null; } "UpdateMatchingStyles".Measure(() => { //var task = Task.Run(() => //{ tasks.Add(Task.FromResult(UpdateMatchingStyles(item.StyleSheet, logical, visual, styleUpdateInfos, dependencyPropertyService, nativeStyleService))); //return UpdateMatchingStyles(item.StyleSheet, logical, visual, styleUpdateInfos, dependencyPropertyService, nativeStyleService); //}); //tasks.Add(task); }); } //Task.WaitAll(tasks.ToArray()); var allFound = tasks.SelectMany(x => x.Result).ToList(); var allFoundElements = allFound.Select(x => x.Element).ToList(); "allNotFoundElements".Measure(() => { var allNotFoundKeys = styleUpdateInfos .Where(x => !allFoundElements.Contains(x.Key)) .ToList(); foreach (var item in allNotFoundKeys) { var styleUpdateInfo = item.Value; // styleUpdateInfo.CurrentMatchedSelectors = new List<string>(); styleUpdateInfo.OldMatchedSelectors = new List <string>(); styleUpdateInfo.DoMatchCheck = SelectorType.None; // remove style nativeStyleService.SetStyle(item.Key, dependencyPropertyService.GetInitialStyle(item.Key)); } }); "GenerateStyles".Measure(() => { var groups = styleUpdateInfos.Where(x => allFoundElements.Contains(x.Key)).GroupBy(x => x.Value.CurrentStyleSheet).ToList(); foreach (var group in groups) { GenerateStyles( group.Key, group.ToDictionary(x => x.Key, x => x.Value), applicationResourcesService, dependencyPropertyService, nativeStyleService, cssTypeHelper); } }); "ApplyMatchingStyles".Measure(() => { foreach (var item in copy.Select(x => new { x.StartFrom, x.StyleSheetHolder, x.StyleSheet }).Distinct().ToList()) { var start = item.StartFrom ?? item.StyleSheetHolder; switchableTreeNodeProvider.Switch(SelectorType.LogicalTree); if (switchableTreeNodeProvider.IsInTree(start)) { var logical = switchableTreeNodeProvider.GetDomElement(start); ApplyMatchingStyles(logical, item.StyleSheet, applicationResourcesService, nativeStyleService); } switchableTreeNodeProvider.Switch(SelectorType.VisualTree); if (switchableTreeNodeProvider.IsInTree(start)) { var visual = switchableTreeNodeProvider.GetDomElement(start); ApplyMatchingStyles(visual, item.StyleSheet, applicationResourcesService, nativeStyleService); } } }); } finally { "EndUpdate".Measure(() => applicationResourcesService.EndUpdate()); } }