Пример #1
0
        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)
            {
                if (rule.SelectorType == SelectorType.VisualTree)
                {
                    if (visualTree == null)
                    {
                        visualTree = treeNodeProvider.GetDomElement(startFrom ?? styleResourceReferenceHolder);
                        visualTree.XamlCssStyleSheets.Clear();
                        visualTree.XamlCssStyleSheets.Add(styleSheet);
                    }

                    root = visualTree;
                }
                else
                {
                    if (logicalTree == null)
                    {
                        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> >()
                                   .Where(x => treeNodeProvider.GetParent(x.Element) != null) // workaround WPF: somehow dom-tree is out of sync with UI-tree!?!
                                   .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();

                // Debug.WriteLine($"matchedNodes: ({matchedNodes.Count}) " + string.Join(", ", matchedNodes.Select(x => x.Id)));

                var matchedElementTypes = matchedNodes
                                          .Select(x => x.Element.GetType())
                                          .Distinct()
                                          .ToList();

                // Debug.WriteLine($"Matched Types: ({matchedElementTypes.Count}) " + string.Join(", ", matchedElementTypes.Select(x => x.Name)));

                foreach (var matchingNode in matchedNodes)
                {
                    var element = matchingNode.Element;

                    var matchingStyles = dependencyPropertyService.GetMatchingStyles(element) ?? new string[0];

                    var resourceKey = nativeStyleService.GetStyleResourceKey(styleSheet.Id, element.GetType(), rule.SelectorString);

                    dependencyPropertyService.SetMatchingStyles(element, matchingStyles.Concat(new[] { resourceKey }).Distinct().ToArray());

                    if (requiredStyleInfos.Any(x => x.Rule == rule && x.MatchedType == element.GetType()) == false)
                    {
                        requiredStyleInfos.Add(new StyleMatchInfo
                        {
                            Rule        = rule,
                            MatchedType = element.GetType()
                        });
                    }
                }
            }

            return(requiredStyleInfos);
        }
Пример #2
0
        private static IList <IDomElement <TDependencyObject, TDependencyProperty> > UpdateMatchingStyles(
            StyleSheet styleSheet,
            IDomElement <TDependencyObject, TDependencyProperty> startFrom,
            Dictionary <TDependencyObject, StyleUpdateInfo> styleUpdateInfos,
            IDependencyPropertyService <TDependencyObject, TStyle, TDependencyProperty> dependencyPropertyService,
            INativeStyleService <TStyle, TDependencyObject, TDependencyProperty> nativeStyleService)
        {
            // var requiredStyleInfos = new List<StyleMatchInfo>();
            var found = new HashSet <IDomElement <TDependencyObject, TDependencyProperty> >();

            if (startFrom == null ||
                !startFrom.IsReady)
            {
                return(found.ToList());
            }

            if (startFrom.StyleInfo.DoMatchCheck == SelectorType.None)
            {
                return(new List <IDomElement <TDependencyObject, TDependencyProperty> >());
            }

            startFrom.XamlCssStyleSheets.Clear();
            startFrom.XamlCssStyleSheets.Add(styleSheet);

            var traversed = SelectorType.None;

            foreach (var rule in styleSheet.Rules)
            {
                // // Debug.WriteLine($"--- RULE {rule.SelectorString} ----");

                // apply our selector

                var type = SelectorType.LogicalTree;
                if (rule.Selectors[0].StartOnVisualTree())
                {
                    type = SelectorType.VisualTree;
                }

                if ((type == SelectorType.LogicalTree && !startFrom.IsInLogicalTree) ||
                    (type == SelectorType.VisualTree && !startFrom.IsInVisualTree)
                    )
                {
                    continue;
                }

                traversed |= type;

                var matchedNodes = startFrom.QuerySelectorAllWithSelf(styleSheet, rule.Selectors[0], type)
                                   .Where(x => x != null)
                                   .Cast <IDomElement <TDependencyObject, TDependencyProperty> >()
                                   .ToList();

                var matchedElementTypes = matchedNodes
                                          .Select(x => x.Element.GetType())
                                          .Distinct()
                                          .ToList();

                foreach (var matchingNode in matchedNodes)
                {
                    var element = matchingNode.Element;

                    if (!found.Contains(matchingNode))
                    {
                        found.Add(matchingNode);
                    }

                    matchingNode.StyleInfo.CurrentMatchedSelectors.Add(rule.Selectors[0]);

                    var initialStyle  = dependencyPropertyService.GetInitialStyle(element);
                    var discriminator = initialStyle != null?initialStyle.GetHashCode().ToString() : "";

                    var resourceKey = nativeStyleService.GetStyleResourceKey(styleSheet.Id + discriminator, element.GetType(), rule.SelectorString);
                    //var resourceKey = nativeStyleService.GetStyleResourceKey(rule.StyleSheetId, element.GetType(), rule.SelectorString);

                    if (!matchingNode.StyleInfo.CurrentMatchedResourceKeys.Contains(resourceKey))
                    {
                        matchingNode.StyleInfo.CurrentMatchedResourceKeys.Add(resourceKey);
                    }
                }
            }

            foreach (var f in found)
            {
                f.StyleInfo.DoMatchCheck = SelectorType.None;

                f.StyleInfo.CurrentMatchedSelectors = f.StyleInfo.CurrentMatchedSelectors.Distinct()
                                                      .OrderBy(x => x.IdSpecificity)
                                                      .ThenBy(x => x.ClassSpecificity)
                                                      .ThenBy(x => x.SimpleSpecificity)
                                                      .ToList()
                                                      .ToLinkedHashSet();
            }

            if ((traversed & SelectorType.VisualTree) > 0)
            {
                SetDoMatchCheckToNoneInSubTree(startFrom, styleSheet, SelectorType.VisualTree);
            }
            if ((traversed & SelectorType.LogicalTree) > 0)
            {
                SetDoMatchCheckToNoneInSubTree(startFrom, styleSheet, SelectorType.LogicalTree);
            }
            return(found.ToList());
        }
Пример #3
0
        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)
            {
                if (rule.SelectorType == SelectorType.VisualTree)
                {
                    if (visualTree == null)
                    {
                        visualTree = treeNodeProvider.GetDomElement(startFrom ?? styleResourceReferenceHolder);
                        visualTree.XamlCssStyleSheets.Clear();
                        visualTree.XamlCssStyleSheets.Add(styleSheet);
                    }

                    root = visualTree;
                }
                else
                {
                    if (logicalTree == null)
                    {
                        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();

                // Debug.WriteLine($"matchedNodes: ({matchedNodes.Count}) " + string.Join(", ", matchedNodes.Select(x => x.Id)));

                var matchedElementTypes = matchedNodes
                                          .Select(x => x.Element.GetType())
                                          .Distinct()
                                          .ToList();

                // Debug.WriteLine($"Matched Types: ({matchedElementTypes.Count}) " + string.Join(", ", matchedElementTypes.Select(x => x.Name)));

                foreach (var matchingNode in matchedNodes)
                {
                    var element = matchingNode.Element;

                    var matchingStyles = dependencyPropertyService.GetMatchingStyles(element) ?? new string[0];

                    var resourceKey = nativeStyleService.GetStyleResourceKey(element.GetType(), rule.SelectorString);

                    dependencyPropertyService.SetMatchingStyles(element, matchingStyles.Concat(new[] { resourceKey }).Distinct().ToArray());

                    if (requiredStyleInfos.Any(x => x.Rule == rule && x.MatchedType == element.GetType()) == false)
                    {
                        requiredStyleInfos.Add(new StyleMatchInfo
                        {
                            Rule        = rule,
                            MatchedType = element.GetType()
                        });
                    }
                }
            }

            return(requiredStyleInfos);
        }
Пример #4
0
        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);
        }
Пример #5
0
        private static IList <IDomElement <TDependencyObject> > UpdateMatchingStyles(
            StyleSheet styleSheet,
            IDomElement <TDependencyObject> startFromLogical,
            IDomElement <TDependencyObject> startFromVisual,
            Dictionary <TDependencyObject, StyleUpdateInfo> styleUpdateInfos,
            IDependencyPropertyService <TDependencyObject, TStyle, TDependencyProperty> dependencyPropertyService,
            INativeStyleService <TStyle, TDependencyObject, TDependencyProperty> nativeStyleService)
        {
            // var requiredStyleInfos = new List<StyleMatchInfo>();
            IDomElement <TDependencyObject> root = null;

            IDomElement <TDependencyObject> visualTree  = null;
            IDomElement <TDependencyObject> logicalTree = null;

            var found = new List <IDomElement <TDependencyObject> >();

            if (startFromVisual?.StyleInfo.DoMatchCheck == SelectorType.None ||
                startFromLogical?.StyleInfo.DoMatchCheck == SelectorType.None)
            {
                return(new List <IDomElement <TDependencyObject> >());
            }

            return($"{startFromLogical?.GetPath() ?? startFromVisual?.GetPath() ?? "NULL!?!"}".Measure(() =>
            {
                foreach (var rule in styleSheet.Rules)
                {
                    $"{rule.SelectorString}".Measure(() =>
                    {
                        // // Debug.WriteLine($"--- RULE {rule.SelectorString} ----");
                        if (rule.SelectorType == SelectorType.VisualTree)
                        {
                            if (startFromVisual == null)
                            {
                                //continue;
                                return;
                            }
                            if (visualTree == null)
                            {
                                visualTree = startFromVisual;
                                visualTree?.XamlCssStyleSheets.Clear();
                                visualTree?.XamlCssStyleSheets.Add(styleSheet);
                            }

                            root = visualTree;
                        }
                        else
                        {
                            if (startFromLogical == null)
                            {
                                //continue;
                                return;
                            }
                            if (logicalTree == null)
                            {
                                logicalTree = startFromLogical;
                                logicalTree?.XamlCssStyleSheets.Clear();
                                logicalTree?.XamlCssStyleSheets.Add(styleSheet);
                            }

                            root = logicalTree;
                        }

                        if (root == null)
                        {
                            //continue;
                            return;
                        }

                        // apply our selector
                        var matchedNodes = "QuerySelectorAllWithSelf".Measure(() => root.QuerySelectorAllWithSelf(styleSheet, rule.Selectors[0])
                                                                              .Where(x => x != null)
                                                                              .Cast <IDomElement <TDependencyObject> >()
                                                                              .ToList());

                        var matchedElementTypes = matchedNodes
                                                  .Select(x => x.Element.GetType())
                                                  .Distinct()
                                                  .ToList();

                        $"foreach {matchedNodes.Count}".Measure(() =>
                        {
                            foreach (var matchingNode in matchedNodes)
                            {
                                var element = matchingNode.Element;

                                if (!found.Contains(matchingNode))
                                {
                                    found.Add(matchingNode);
                                }

                                var discriminator = "GetInitialStyle".Measure(() => dependencyPropertyService.GetInitialStyle(element) != null ? element.GetHashCode().ToString() : "");
                                var resourceKey = "GetStyleResourceKey".Measure(() => nativeStyleService.GetStyleResourceKey(styleSheet.Id + discriminator, element.GetType(), rule.SelectorString));
                                //var resourceKey = nativeStyleService.GetStyleResourceKey(rule.StyleSheetId, element.GetType(), rule.SelectorString);

                                if (!matchingNode.StyleInfo.CurrentMatchedSelectors.Contains(resourceKey))
                                {
                                    matchingNode.StyleInfo.CurrentMatchedSelectors.Add(resourceKey);
                                }
                            }
                        });
                    });
                }

                "found".Measure(() =>
                {
                    found = found.Distinct().ToList();

                    foreach (var f in found)
                    {
                        f.StyleInfo.DoMatchCheck = SelectorType.None;

                        f.StyleInfo.CurrentMatchedSelectors = f.StyleInfo.CurrentMatchedSelectors.Distinct().Select(x => new
                        {
                            key = x,
                            SpecificityResult = SpecificityCalculator.Calculate(x.Split('{')[1])
                        })
                                                              .OrderBy(x => x.SpecificityResult.IdSpecificity)
                                                              .ThenBy(x => x.SpecificityResult.ClassSpecificity)
                                                              .ThenBy(x => x.SpecificityResult.SimpleSpecificity)
                                                              .ToList()
                                                              .Select(x => x.key)
                                                              .ToList();
                    }
                });

                "SetDoMatchCheckToNoneInSubTree".Measure(() =>
                {
                    SetDoMatchCheckToNoneInSubTree(startFromLogical, styleSheet);
                    SetDoMatchCheckToNoneInSubTree(startFromVisual, styleSheet);
                });
                return found;
            }));
        }