private static void EnsureParents(IDomElement <TDependencyObject> domElement, ISwitchableTreeNodeProvider <TDependencyObject> switchableTreeNodeProvider, IDependencyPropertyService <TDependencyObject, TStyle, TDependencyProperty> dependencyPropertyService, INativeStyleService <TStyle, TDependencyObject, TDependencyProperty> nativeStyleService, IDictionary <TDependencyObject, StyleUpdateInfo> styleUpdateInfos) { var current = domElement.Parent; while (current != null) { var styleUpdateInfo = current.StyleInfo = current.StyleInfo ?? (styleUpdateInfos.ContainsKey(current.Element) ? styleUpdateInfos[current.Element] : GetNewStyleUpdateInfo(current, dependencyPropertyService, nativeStyleService)); if ((styleUpdateInfo.DoMatchCheck & switchableTreeNodeProvider.CurrentSelectorType) == switchableTreeNodeProvider.CurrentSelectorType) { return; } object a; "ClassList".Measure(() => a = current.ClassList); //"Id".Measure(() => a = current.Id); "TagName".Measure(() => a = current.TagName); "AssemblyQualifiedNamespaceName".Measure(() => a = current.AssemblyQualifiedNamespaceName); //"HasAttribute".Measure(() => a = current.HasAttribute("Name")); /*// a = domElement.Parent; */ a = current.ChildNodes; current = current.Parent; } }
private static void SetupStyleInfo( IDomElement <TDependencyObject> domElement, StyleSheet styleSheet, Dictionary <TDependencyObject, StyleUpdateInfo> styleUpdateInfos, ISwitchableTreeNodeProvider <TDependencyObject> switchableTreeNodeProvider, IDependencyPropertyService <TDependencyObject, TStyle, TDependencyProperty> dependencyPropertyService, INativeStyleService <TStyle, TDependencyObject, TDependencyProperty> nativeStyleService, bool styleChanged, bool styleSheetRemoved) { var styleUpdateInfo = "get styleUpdateInfo".Measure(() => domElement.StyleInfo = domElement.StyleInfo ?? (styleUpdateInfos.ContainsKey(domElement.Element) ? styleUpdateInfos[domElement.Element] : GetNewStyleUpdateInfo(domElement, dependencyPropertyService, nativeStyleService))); var styleSheetFromDom = "GetStyleSheet".Measure(() => dependencyPropertyService.GetStyleSheet(domElement.Element)); if (styleSheetFromDom != null && styleSheetFromDom != styleSheet) { // another stylesheet's domelement SetupStyleInfo(domElement, styleSheetFromDom, styleUpdateInfos, switchableTreeNodeProvider, dependencyPropertyService, nativeStyleService, styleChanged, false); return; } "set styleUpdateInfo values".Measure(() => { if (!styleSheetRemoved) { styleUpdateInfo.CurrentStyleSheet = styleSheet; } if (styleChanged) { styleUpdateInfo.OldMatchedSelectors = new List <string>(); } styleUpdateInfo.CurrentMatchedSelectors.Clear(); styleUpdateInfo.DoMatchCheck |= switchableTreeNodeProvider.CurrentSelectorType; styleUpdateInfos[domElement.Element] = styleUpdateInfo; }); "fill DomElement".Measure(() => { object a; "ClassList".Measure(() => a = domElement.ClassList); "Id".Measure(() => a = domElement.Id); "TagName".Measure(() => a = domElement.TagName); "NamespaceUri".Measure(() => a = domElement.AssemblyQualifiedNamespaceName); //"HasAttribute".Measure(() => a = domElement.HasAttribute("Name")); /*// a = domElement.Parent; */ }); foreach (var child in domElement.ChildNodes) { SetupStyleInfo(child, styleSheet, styleUpdateInfos, switchableTreeNodeProvider, dependencyPropertyService, nativeStyleService, styleChanged, styleSheetRemoved); } }
private static StyleUpdateInfo GetNewStyleUpdateInfo(IDomElement <TDependencyObject, TDependencyProperty> domElement, IDependencyPropertyService <TDependencyObject, TStyle, TDependencyProperty> dependencyPropertyService, INativeStyleService <TStyle, TDependencyObject, TDependencyProperty> nativeStyleService) { var initialStyle = nativeStyleService.GetStyle(domElement.Element); return(new StyleUpdateInfo { MatchedType = domElement.Element.GetType(), InitialStyle = initialStyle }); }
private static StyleUpdateInfo GetNewStyleUpdateInfo(IDomElement <TDependencyObject> domElement, IDependencyPropertyService <TDependencyObject, TStyle, TDependencyProperty> dependencyPropertyService, INativeStyleService <TStyle, TDependencyObject, TDependencyProperty> nativeStyleService) { if (dependencyPropertyService.GetInitialStyle(domElement.Element) == null) { dependencyPropertyService.SetInitialStyle(domElement.Element, nativeStyleService.GetStyle(domElement.Element)); } return(new StyleUpdateInfo { MatchedType = domElement.Element.GetType() }); }
private static void SetupStyleInfo( IDomElement <TDependencyObject, TDependencyProperty> domElement, StyleSheet styleSheet, Dictionary <TDependencyObject, StyleUpdateInfo> styleUpdateInfos, ITreeNodeProvider <TDependencyObject, TDependencyProperty> treeNodeProvider, IDependencyPropertyService <TDependencyObject, TStyle, TDependencyProperty> dependencyPropertyService, INativeStyleService <TStyle, TDependencyObject, TDependencyProperty> nativeStyleService, bool styleChanged, bool styleSheetRemoved, SelectorType type) { if (!domElement.IsReady) { return; } var styleUpdateInfo = domElement.StyleInfo = domElement.StyleInfo ?? (styleUpdateInfos.ContainsKey(domElement.Element) ? styleUpdateInfos[domElement.Element] : GetNewStyleUpdateInfo(domElement, dependencyPropertyService, nativeStyleService)); styleUpdateInfos[domElement.Element] = styleUpdateInfo; var styleSheetFromDom = dependencyPropertyService.GetStyleSheet(domElement.Element); if (styleSheetFromDom != null && styleSheetFromDom != styleSheet) { // another stylesheet's domelement SetupStyleInfo(domElement, styleSheetFromDom, styleUpdateInfos, treeNodeProvider, dependencyPropertyService, nativeStyleService, styleChanged, false, type); return; } if (!styleSheetRemoved) { styleUpdateInfo.CurrentStyleSheet = styleSheet; } if (styleChanged) { styleUpdateInfo.OldMatchedSelectors = new LinkedHashSet <ISelector>(); } styleUpdateInfo.CurrentMatchedSelectors.Clear(); styleUpdateInfo.CurrentMatchedResourceKeys.Clear(); styleUpdateInfo.DoMatchCheck |= type; var children = type == SelectorType.VisualTree ? domElement.ChildNodes : domElement.LogicalChildNodes; foreach (var child in children) { SetupStyleInfo(child, styleSheet, styleUpdateInfos, treeNodeProvider, dependencyPropertyService, nativeStyleService, styleChanged, styleSheetRemoved, type); } }
private static void RemoveStyleResourcesInternal( TDependencyObject styleResourceReferenceHolder, StyleSheet styleSheet, IStyleResourcesService applicationResourcesService, INativeStyleService <TStyle, TDependencyObject, TDependencyProperty> nativeStyleService) { var resourceKeys = applicationResourcesService.GetKeys() .OfType <string>() .Where(x => x.StartsWith($"{nativeStyleService.BaseStyleResourceKey}_{styleSheet.Id}", StringComparison.Ordinal)) .ToList(); foreach (var key in resourceKeys) { applicationResourcesService.RemoveResource(key); } }
public BaseCss(IDependencyPropertyService <TDependencyObject, TUIElement, TStyle, TDependencyProperty> dependencyPropertyService, ITreeNodeProvider <TDependencyObject> treeNodeProvider, IStyleResourcesService applicationResourcesService, INativeStyleService <TStyle, TDependencyObject, TDependencyProperty> nativeStyleService, string defaultCssNamespace, IMarkupExtensionParser markupExpressionParser, Action <Action> uiInvoker) { this.dependencyPropertyService = dependencyPropertyService; this.treeNodeProvider = treeNodeProvider; this.applicationResourcesService = applicationResourcesService; this.nativeStyleService = nativeStyleService; this.markupExpressionParser = markupExpressionParser; this.uiInvoker = uiInvoker; CssParser.Initialize(defaultCssNamespace); }
private static void RemoveOldStyleObjects(List <RenderInfo <TDependencyObject> > copy, INativeStyleService <TStyle, TDependencyObject, TDependencyProperty> nativeStyleService, IStyleResourcesService applicationResourcesService) { var updatedOrRemovedStyleSheets = copy .Where(x => x.RenderTargetKind == RenderTargetKind.Stylesheet) .Where(x => x.ChangeKind == ChangeKind.Update || x.ChangeKind == ChangeKind.Remove) .Select(x => new { x.StyleSheet, x.StyleSheetHolder }) .Distinct() .ToList(); foreach (var item in updatedOrRemovedStyleSheets) { RemoveStyleResourcesInternal(item.StyleSheetHolder, item.StyleSheet, applicationResourcesService, nativeStyleService); } }
private static void SetAttachedToToNull(List <RenderInfo <TDependencyObject> > copy, IDependencyPropertyService <TDependencyObject, TStyle, TDependencyProperty> dependencyPropertyService, ITreeNodeProvider <TDependencyObject, TDependencyProperty> treeNodeProvider, 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) { ReevaluateStylesheetInSubTree(treeNodeProvider.GetDomElement((TDependencyObject)removedStyleSheet.AttachedTo), removedStyleSheet, dependencyPropertyService, nativeStyleService); removedStyleSheet.AttachedTo = null; } }
public BaseCss(IDependencyPropertyService <TDependencyObject, TUIElement, TStyle, TDependencyProperty> dependencyPropertyService, ITreeNodeProvider <TDependencyObject> treeNodeProvider, IStyleResourcesService applicationResourcesService, INativeStyleService <TStyle, TDependencyObject, TDependencyProperty> nativeStyleService, string defaultCssNamespace, IMarkupExtensionParser markupExpressionParser, Action <Action> uiInvoker, ICssFileProvider fileProvider) { this.dependencyPropertyService = dependencyPropertyService; this.treeNodeProvider = treeNodeProvider; this.applicationResourcesService = applicationResourcesService; this.nativeStyleService = nativeStyleService; this.markupExpressionParser = markupExpressionParser; this.uiInvoker = uiInvoker; this.cssTypeHelper = new CssTypeHelper <TDependencyObject, TUIElement, TDependencyProperty, TStyle>(markupExpressionParser, dependencyPropertyService); CssParser.Initialize(defaultCssNamespace, fileProvider); StyleSheet.GetParent = parent => treeNodeProvider.GetParent((TDependencyObject)parent); StyleSheet.GetStyleSheet = treeNode => dependencyPropertyService.GetStyleSheet((TDependencyObject)treeNode); }
private static void SetAttachedToToNewStyleSheet(List <RenderInfo <TDependencyObject> > copy, IDependencyPropertyService <TDependencyObject, TStyle, TDependencyProperty> dependencyPropertyService, ITreeNodeProvider <TDependencyObject, TDependencyProperty> treeNodeProvider, INativeStyleService <TStyle, TDependencyObject, TDependencyProperty> nativeStyleService) { var addedStyleSheets = copy .Where(x => x.RenderTargetKind == RenderTargetKind.Stylesheet && x.ChangeKind == ChangeKind.New) .Select(x => new { x.StyleSheet, x.StyleSheetHolder }) .Distinct() .ToList(); foreach (var item in addedStyleSheets) { var domElement = treeNodeProvider.GetDomElement(item.StyleSheetHolder); item.StyleSheet.AttachedTo = item.StyleSheetHolder; ReevaluateStylesheetInSubTree(domElement, domElement.StyleInfo?.CurrentStyleSheet, dependencyPropertyService, nativeStyleService); } }
private static void EnsureParents(IDomElement <TDependencyObject, TDependencyProperty> domElement, ITreeNodeProvider <TDependencyObject, TDependencyProperty> treeNodeProvider, IDependencyPropertyService <TDependencyObject, TStyle, TDependencyProperty> dependencyPropertyService, INativeStyleService <TStyle, TDependencyObject, TDependencyProperty> nativeStyleService, IDictionary <TDependencyObject, StyleUpdateInfo> styleUpdateInfos, SelectorType type) { var current = type == SelectorType.VisualTree ? domElement.Parent : domElement.LogicalParent; while (current != null && current.IsReady) { var styleUpdateInfo = current.StyleInfo = current.StyleInfo ?? (styleUpdateInfos.ContainsKey(current.Element) ? styleUpdateInfos[current.Element] : GetNewStyleUpdateInfo(current, dependencyPropertyService, nativeStyleService)); if ((styleUpdateInfo.DoMatchCheck & type) != type) { return; } object a; a = current.ClassList; //"Id".Measure(() => a = current.Id); a = current.TagName; a = current.AssemblyQualifiedNamespaceName; //"HasAttribute".Measure(() => a = current.HasAttribute("Name")); /*// a = domElement.Parent; */ if (type == SelectorType.VisualTree) { a = current.ChildNodes; current = current.Parent; } else { a = current.LogicalChildNodes; current = current.LogicalParent; } } }
private static void ReevaluateStylesheetInSubTree(IDomElement <TDependencyObject> domElement, StyleSheet oldStyleSheet, IDependencyPropertyService <TDependencyObject, TStyle, TDependencyProperty> dependencyPropertyService, INativeStyleService <TStyle, TDependencyObject, TDependencyProperty> nativeStyleService) { if (domElement.StyleInfo == null) { return; } if (domElement == null || domElement.StyleInfo.CurrentStyleSheet != oldStyleSheet) { return; } domElement.StyleInfo.CurrentStyleSheet = GetStyleSheetFromTree(domElement, dependencyPropertyService); foreach (var child in domElement.ChildNodes) { ReevaluateStylesheetInSubTree(child, oldStyleSheet, dependencyPropertyService, nativeStyleService); } }
private static void ReevaluateStylesheetInSubTree(IDomElement <TDependencyObject, TDependencyProperty> domElement, StyleSheet oldStyleSheet, IDependencyPropertyService <TDependencyObject, TStyle, TDependencyProperty> dependencyPropertyService, INativeStyleService <TStyle, TDependencyObject, TDependencyProperty> nativeStyleService) { if (domElement.StyleInfo == null) { return; } if (domElement == null || !ReferenceEquals(domElement.StyleInfo.CurrentStyleSheet, oldStyleSheet)) { return; } domElement.StyleInfo.CurrentStyleSheet = GetStyleSheetFromTree(domElement, dependencyPropertyService); domElement.ClearAttributeWatcher(); foreach (var child in domElement.LogicalChildNodes.Concat(domElement.ChildNodes).Distinct().ToList()) { ReevaluateStylesheetInSubTree(child, oldStyleSheet, dependencyPropertyService, nativeStyleService); } }
private static void GenerateStyles(StyleSheet styleSheet, IDictionary <TDependencyObject, StyleUpdateInfo> styleMatchInfos, IStyleResourcesService applicationResourcesService, IDependencyPropertyService <TDependencyObject, TStyle, TDependencyProperty> dependencyPropertyService, INativeStyleService <TStyle, TDependencyObject, TDependencyProperty> nativeStyleService, CssTypeHelper <TDependencyObject, TDependencyProperty, TStyle> cssTypeHelper) { applicationResourcesService.EnsureResources(); foreach (var styleMatchInfoKeyValue in styleMatchInfos) { var styleMatchInfo = styleMatchInfoKeyValue.Value; var matchedElementType = styleMatchInfo.MatchedType; for (var i = 0; i < styleMatchInfo.CurrentMatchedSelectors.Count; i++) { var selector = styleMatchInfo.CurrentMatchedSelectors.ElementAt(i); var resourceKey = styleMatchInfo.CurrentMatchedResourceKeys.ElementAt(i); if (applicationResourcesService.Contains(resourceKey)) { // Debug.WriteLine($"GenerateStyles: Already contains '{s}' ({matchedElementType.Name})"); continue; } // Debug.WriteLine($"GenerateStyles: Generating '{s}' ({matchedElementType.Name})"); var rule = styleMatchInfo.CurrentStyleSheet.Rules.Where(x => x.SelectorString == selector.Value).First(); CreateStyleDictionaryFromDeclarationBlockResult <TDependencyProperty> result = null; try { result = CreateStyleDictionaryFromDeclarationBlock( styleSheet.Namespaces, rule.DeclarationBlock, matchedElementType, (TDependencyObject)styleSheet.AttachedTo, cssTypeHelper); var propertyStyleValues = result.PropertyStyleValues; foreach (var error in result.Errors) { // Debug.WriteLine($@" ERROR (normal) in Selector ""{rule.SelectorString}"": {error}"); styleSheet.AddError($@"ERROR in Selector ""{rule.SelectorString}"": {error}"); } var nativeTriggers = rule.DeclarationBlock.Triggers .Select(x => nativeStyleService.CreateTrigger(styleSheet, x, styleMatchInfo.MatchedType, (TDependencyObject)styleSheet.AttachedTo)) .ToList(); var initalStyle = dependencyPropertyService.GetInitialStyle(styleMatchInfoKeyValue.Key); if (initalStyle != null) { var subDict = nativeStyleService.GetStyleAsDictionary(initalStyle as TStyle); foreach (var item in subDict) { // only set not-overridden properties if (!propertyStyleValues.ContainsKey(item.Key)) { propertyStyleValues[item.Key] = item.Value; } } var triggers = nativeStyleService.GetTriggersAsList(initalStyle as TStyle); nativeTriggers.InsertRange(0, triggers); } //Debug.WriteLine(" Values: " + string.Join(", ", propertyStyleValues.Select(x => ((dynamic)x.Key).PropertyName + ": " + x.Value.ToString()))); var style = nativeStyleService.CreateFrom(propertyStyleValues, nativeTriggers, matchedElementType); applicationResourcesService.SetResource(resourceKey, style); // Debug.WriteLine("Finished generate Style " + resourceKey); } catch (Exception e) { // Debug.WriteLine($@" ERROR (exception) in Selector ""{rule.SelectorString}"": {e.Message}"); styleSheet.AddError($@"ERROR in Selector ""{rule.SelectorString}"": {e.Message}"); } } } }
private static void ApplyMatchingStyles(IDomElement <TDependencyObject> domElement, StyleSheet styleSheet, IStyleResourcesService applicationResourcesService, INativeStyleService <TStyle, TDependencyObject, TDependencyProperty> nativeStyleService) { var visualElement = domElement.Element; if (domElement.StyleInfo == null) { throw new Exception($"StyleInfo null {domElement.GetType().Name.Replace("DomElement", "")} {domElement.GetPath()}"); } var matchingStyles = domElement.StyleInfo.CurrentMatchedSelectors; var appliedMatchingStyles = domElement.StyleInfo.OldMatchedSelectors; var styledBy = domElement.StyleInfo.CurrentStyleSheet; if (styledBy != null && styledBy != styleSheet) { // Debug.WriteLine(" Another Stylesheet"); return; } domElement.StyleInfo.CurrentStyleSheet = styleSheet; if (!AppliedStyleIdsAreMatchedStyleIds(appliedMatchingStyles, matchingStyles)) { object styleToApply = null; if (matchingStyles == null) { // RemoveOutdatedStylesFromElementInternal(visualElement, styleSheet, true, true); } else if (matchingStyles?.Count == 1) { if (applicationResourcesService.Contains(matchingStyles[0]) == true) { styleToApply = applicationResourcesService.GetResource(matchingStyles[0]); } if (styleToApply != null) { nativeStyleService.SetStyle(visualElement, (TStyle)styleToApply); } else { nativeStyleService.SetStyle(visualElement, null); // Debug.WriteLine(" Style not found! " + matchingStyles[0]); } } else if (matchingStyles?.Count > 1) { var dict = new Dictionary <TDependencyProperty, object>(); var listTriggers = new List <TDependencyObject>(); foreach (var matchingStyle in matchingStyles) { TStyle s = null; if (applicationResourcesService.Contains(matchingStyle) == true) { s = (TStyle)applicationResourcesService.GetResource(matchingStyle); } else { // Debug.WriteLine(" Style not found! " + matchingStyle); } if (s != null) { var subDict = nativeStyleService.GetStyleAsDictionary(s as TStyle); foreach (var i in subDict) { dict[i.Key] = i.Value; } var triggers = nativeStyleService.GetTriggersAsList(s as TStyle); listTriggers.AddRange(triggers); } } if (dict.Keys.Count > 0 || listTriggers.Count > 0) { styleToApply = nativeStyleService.CreateFrom(dict, listTriggers, visualElement.GetType()); } if (styleToApply != null) { nativeStyleService.SetStyle(visualElement, (TStyle)styleToApply); } else { nativeStyleService.SetStyle(visualElement, null); } } domElement.StyleInfo.OldMatchedSelectors = matchingStyles.ToList(); } foreach (var child in domElement.ChildNodes) { ApplyMatchingStyles(child, styleSheet, applicationResourcesService, nativeStyleService); } }
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()); }
private static void ApplyMatchingStylesNode(IDomElement <TDependencyObject, TDependencyProperty> domElement, IStyleResourcesService applicationResourcesService, INativeStyleService <TStyle, TDependencyObject, TDependencyProperty> nativeStyleService) { var visualElement = domElement.Element; var matchingStyles = domElement.StyleInfo.CurrentMatchedSelectors; var appliedMatchingStyles = domElement.StyleInfo.OldMatchedSelectors; var matchingResourceKeys = domElement.StyleInfo.CurrentMatchedResourceKeys; if (!AppliedStyleIdsAreMatchedStyleIds(appliedMatchingStyles, matchingStyles)) { object styleToApply = null; if (matchingResourceKeys == null) { // RemoveOutdatedStylesFromElementInternal(visualElement, styleSheet, true, true); } else if (matchingResourceKeys.Count == 1) { if (applicationResourcesService.Contains(matchingResourceKeys.First()) == true) { styleToApply = applicationResourcesService.GetResource(matchingResourceKeys.First()); } if (styleToApply != null) { nativeStyleService.SetStyle(visualElement, (TStyle)styleToApply); } else { nativeStyleService.SetStyle(visualElement, null); // Debug.WriteLine(" Style not found! " + matchingResourceKeys[0]); } } else if (matchingResourceKeys.Count > 1) { var resourceKey = string.Join(", ", matchingResourceKeys); if (applicationResourcesService.Contains(resourceKey)) { nativeStyleService.SetStyle(visualElement, (TStyle)applicationResourcesService.GetResource(resourceKey)); } else { var dict = new Dictionary <TDependencyProperty, object>(); var listTriggers = new List <TDependencyObject>(); foreach (var matchingResourceKey in matchingResourceKeys) { TStyle s = null; if (applicationResourcesService.Contains(matchingResourceKey) == true) { s = (TStyle)applicationResourcesService.GetResource(matchingResourceKey); } else { // Debug.WriteLine(" Style not found! " + matchingStyle); } if (s != null) { var subDict = nativeStyleService.GetStyleAsDictionary(s as TStyle); foreach (var i in subDict) { dict[i.Key] = i.Value; } var triggers = nativeStyleService.GetTriggersAsList(s as TStyle); listTriggers.AddRange(triggers); } } if (dict.Keys.Count > 0 || listTriggers.Count > 0) { styleToApply = nativeStyleService.CreateFrom(dict, listTriggers, visualElement.GetType()); } if (styleToApply != null) { applicationResourcesService.SetResource(resourceKey, styleToApply); nativeStyleService.SetStyle(visualElement, (TStyle)styleToApply); } else { nativeStyleService.SetStyle(visualElement, null); } } } domElement.StyleInfo.OldMatchedSelectors = matchingStyles.ToLinkedHashSet(); } }
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; })); }
private static void GenerateStyles(StyleSheet styleSheet, IDictionary <TDependencyObject, StyleUpdateInfo> styleMatchInfos, IStyleResourcesService applicationResourcesService, IDependencyPropertyService <TDependencyObject, TStyle, TDependencyProperty> dependencyPropertyService, INativeStyleService <TStyle, TDependencyObject, TDependencyProperty> nativeStyleService, CssTypeHelper <TDependencyObject, TDependencyProperty, TStyle> cssTypeHelper) { applicationResourcesService.EnsureResources(); foreach (var styleMatchInfoKeyValue in styleMatchInfos) { var styleMatchInfo = styleMatchInfoKeyValue.Value; var matchedElementType = styleMatchInfo.MatchedType; foreach (var resourceKey in styleMatchInfo.CurrentMatchedSelectors) { if (applicationResourcesService.Contains(resourceKey)) { continue; } var s = resourceKey.Split('{')[1]; var rule = styleMatchInfo.CurrentStyleSheet.Rules.Where(x => x.SelectorString == s).First(); // // Debug.WriteLine("Generate Style " + resourceKey); CreateStyleDictionaryFromDeclarationBlockResult <TDependencyProperty> result = null; try { result = "CreateStyleDictionaryFromDeclarationBlock".Measure(() => CreateStyleDictionaryFromDeclarationBlock( styleSheet.Namespaces, rule.DeclarationBlock, matchedElementType, (TDependencyObject)styleSheet.AttachedTo, cssTypeHelper)); var propertyStyleValues = result.PropertyStyleValues; foreach (var error in result.Errors) { Debug.WriteLine($@" ERROR (normal) in Selector ""{rule.SelectorString}"": {error}"); styleSheet.AddError($@"ERROR in Selector ""{rule.SelectorString}"": {error}"); } var nativeTriggers = $"CreateTriggers ({rule.DeclarationBlock.Triggers.Count})".Measure(() => rule.DeclarationBlock.Triggers .Select(x => nativeStyleService.CreateTrigger(styleSheet, x, styleMatchInfo.MatchedType, (TDependencyObject)styleSheet.AttachedTo)) .ToList()); var initalStyle = dependencyPropertyService.GetInitialStyle(styleMatchInfoKeyValue.Key); if (initalStyle != null) { var subDict = nativeStyleService.GetStyleAsDictionary(initalStyle as TStyle); foreach (var i in subDict) { propertyStyleValues[i.Key] = i.Value; } var triggers = nativeStyleService.GetTriggersAsList(initalStyle as TStyle); nativeTriggers.AddRange(triggers); } foreach (var item in propertyStyleValues) { if (item.Value == null) { } } var style = "Create Style".Measure(() => nativeStyleService.CreateFrom(propertyStyleValues, nativeTriggers, matchedElementType)); applicationResourcesService.SetResource(resourceKey, style); // // Debug.WriteLine("Finished generate Style " + resourceKey); } catch (Exception e) { Debug.WriteLine($@" ERROR (exception) in Selector ""{rule.SelectorString}"": {e.Message}"); styleSheet.AddError($@"ERROR in Selector ""{rule.SelectorString}"": {e.Message}"); } } } }
public static void Render( List <RenderInfo <TDependencyObject> > copy, ITreeNodeProvider <TDependencyObject, TDependencyProperty> treeNodeProvider, IDependencyPropertyService <TDependencyObject, TStyle, TDependencyProperty> dependencyPropertyService, INativeStyleService <TStyle, TDependencyObject, TDependencyProperty> nativeStyleService, IStyleResourcesService applicationResourcesService, CssTypeHelper <TDependencyObject, TDependencyProperty, TStyle> cssTypeHelper) { try { applicationResourcesService.BeginUpdate(); RemoveOldStyleObjects(copy, nativeStyleService, applicationResourcesService); SetAttachedToToNull(copy, dependencyPropertyService, treeNodeProvider, nativeStyleService); SetAttachedToToNewStyleSheet(copy, dependencyPropertyService, treeNodeProvider, nativeStyleService); var styleUpdateInfos = new Dictionary <TDependencyObject, StyleUpdateInfo>(); var newOrUpdatedStyleSheets = copy .Where(x => x.RenderTargetKind == RenderTargetKind.Stylesheet) .Select(x => x.StyleSheet) .Distinct() .ToHashSet(); 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() .ToHashSet(); foreach (var item in newOrUpdatedStyleHolders) { var start = item.StartFrom ?? item.StyleSheetHolder; var domElement = treeNodeProvider.GetDomElement(start); if (!domElement.IsInLogicalTree) { continue; } EnsureParents(domElement, treeNodeProvider, dependencyPropertyService, nativeStyleService, styleUpdateInfos, SelectorType.LogicalTree); var discardOldMatchingStyles = newOrUpdatedStyleSheets.Contains(item.StyleSheet); SetupStyleInfo(domElement, item.StyleSheet, styleUpdateInfos, treeNodeProvider, dependencyPropertyService, nativeStyleService, discardOldMatchingStyles, item.ChangeKind == ChangeKind.Remove, SelectorType.LogicalTree); } foreach (var item in newOrUpdatedStyleHolders) { var start = item.StartFrom ?? item.StyleSheetHolder; var domElement = treeNodeProvider.GetDomElement(start); if (!domElement.IsInVisualTree) { continue; } EnsureParents(domElement, treeNodeProvider, dependencyPropertyService, nativeStyleService, styleUpdateInfos, SelectorType.VisualTree); var discardOldMatchingStyles = newOrUpdatedStyleSheets.Contains(item.StyleSheet); SetupStyleInfo(domElement, item.StyleSheet, styleUpdateInfos, treeNodeProvider, dependencyPropertyService, nativeStyleService, discardOldMatchingStyles, item.ChangeKind == ChangeKind.Remove, SelectorType.VisualTree); } var tasks = new List <Task <IList <IDomElement <TDependencyObject, TDependencyProperty> > > >(); var distinctCopy = copy.Select(x => new { x.StartFrom, x.StyleSheetHolder, x.StyleSheet }).Distinct().ToList(); foreach (var item in distinctCopy) { var start = item.StartFrom ?? item.StyleSheetHolder; if (!styleUpdateInfos.ContainsKey(start)) { continue; } //treeNodeProvider.Switch(SelectorType.VisualTree); var domElement = treeNodeProvider.GetDomElement(start); //visual.StyleInfo = styleUpdateInfos[start]; //if (!switchableTreeNodeProvider.IsInTree(start)) //{ // visual = null; //} //var task = Task.Run(() => UpdateMatchingStyles(item.StyleSheet, domElement, styleUpdateInfos, dependencyPropertyService, nativeStyleService)); //tasks.Add(task); tasks.Add(Task.FromResult(UpdateMatchingStyles(item.StyleSheet, domElement, styleUpdateInfos, dependencyPropertyService, nativeStyleService))); } //Task.WaitAll(tasks.ToArray()); var allFound = tasks.SelectMany(x => x.Result).ToList(); var allFoundElements = allFound.Select(x => x.Element).ToHashSet(); 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 LinkedHashSet <ISelector>(); styleUpdateInfo.DoMatchCheck = SelectorType.None; // remove style nativeStyleService.SetStyle(item.Key, dependencyPropertyService.GetInitialStyle(item.Key)); } 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); } foreach (var f in allFound) { ApplyMatchingStylesNode(f, applicationResourcesService, nativeStyleService); } } finally { applicationResourcesService.EndUpdate(); } }
private static void RemoveRemovedDomElements(List <RenderInfo <TDependencyObject> > copy, ITreeNodeProvider <TDependencyObject, TDependencyProperty> treeNodeProvider, INativeStyleService <TStyle, TDependencyObject, TDependencyProperty> nativeStyleService) { var updatedOrRemovedStyleSheets = copy .Where(x => x.RenderTargetKind == RenderTargetKind.Element) .Where(x => x.ChangeKind == ChangeKind.Remove) .Select(x => x.StartFrom) .Distinct() .ToList(); foreach (var item in updatedOrRemovedStyleSheets) { var domElement = treeNodeProvider.GetDomElement(item); if (domElement.StyleInfo is object) { nativeStyleService.SetStyle(item, (TStyle)domElement.StyleInfo.InitialStyle); domElement.StyleInfo = null; } RemoveRemovedDomElementsInternal(domElement, nativeStyleService); } }
private static void ApplyMatchingStylesNode(IDomElement <TDependencyObject, TDependencyProperty> domElement, IStyleResourcesService applicationResourcesService, INativeStyleService <TStyle, TDependencyObject, TDependencyProperty> nativeStyleService) { var visualElement = domElement.Element; var matchingStyles = domElement.StyleInfo.CurrentMatchedSelectors; var appliedMatchingStyles = domElement.StyleInfo.OldMatchedSelectors; var matchingResourceKeys = domElement.StyleInfo.CurrentMatchedResourceKeys; if (!AppliedStyleIdsAreMatchedStyleIds(appliedMatchingStyles, matchingStyles)) { object styleToApply = null; if (matchingResourceKeys == null) { } else if (matchingResourceKeys.Count == 1) { if (applicationResourcesService.Contains(matchingResourceKeys.First()) == true) { styleToApply = applicationResourcesService.GetResource(matchingResourceKeys.First()); } try { if (styleToApply != null) { nativeStyleService.SetStyle(visualElement, (TStyle)styleToApply); domElement.StyleInfo.OldMatchedSelectors = matchingStyles.ToList(); } else { nativeStyleService.SetStyle(visualElement, null); domElement.StyleInfo.OldMatchedSelectors = emptySelectorList; // Debug.WriteLine(" Style not found! " + matchingResourceKeys[0]); } } catch (Exception exc) { applicationResourcesService.RemoveResource(matchingResourceKeys.First()); domElement.StyleInfo.OldMatchedSelectors = emptySelectorList; domElement.XamlCssStyleSheets.First().AddError($"Cannot apply style to an element matching {string.Join(", ", matchingStyles.Select(x => x.Value))}: {exc.Message}"); nativeStyleService.SetStyle(visualElement, null); return; } } else if (matchingResourceKeys.Count > 1) { var resourceKey = string.Join(", ", matchingResourceKeys); if (applicationResourcesService.Contains(resourceKey)) { try { nativeStyleService.SetStyle(visualElement, (TStyle)applicationResourcesService.GetResource(resourceKey)); domElement.StyleInfo.OldMatchedSelectors = matchingStyles.ToList(); } catch (Exception exc) { applicationResourcesService.RemoveResource(resourceKey); domElement.StyleInfo.OldMatchedSelectors = emptySelectorList; domElement.XamlCssStyleSheets.First().AddError($"Cannot apply style to an element matching {string.Join(", ", matchingStyles.Select(x => x.Value))}: {exc.Message}"); nativeStyleService.SetStyle(visualElement, null); return; } } else { var dict = new Dictionary <TDependencyProperty, object>(); var listTriggers = new List <TDependencyObject>(); foreach (var matchingResourceKey in matchingResourceKeys) { TStyle s = null; if (applicationResourcesService.Contains(matchingResourceKey) == true) { s = (TStyle)applicationResourcesService.GetResource(matchingResourceKey); } else { // Debug.WriteLine(" Style not found! " + matchingStyle); } if (s != null) { var subDict = nativeStyleService.GetStyleAsDictionary(s as TStyle); foreach (var i in subDict) { dict[i.Key] = i.Value; } var triggers = nativeStyleService.GetTriggersAsList(s as TStyle); listTriggers.AddRange(triggers); } } if (dict.Keys.Count > 0 || listTriggers.Count > 0) { styleToApply = nativeStyleService.CreateFrom(dict, listTriggers, visualElement.GetType()); } try { if (styleToApply != null) { nativeStyleService.SetStyle(visualElement, (TStyle)styleToApply); applicationResourcesService.SetResource(resourceKey, styleToApply); } else { nativeStyleService.SetStyle(visualElement, null); } domElement.StyleInfo.OldMatchedSelectors = matchingStyles.ToList(); } catch (Exception exc) { applicationResourcesService.RemoveResource(resourceKey); domElement.StyleInfo.OldMatchedSelectors = emptySelectorList; nativeStyleService.SetStyle(visualElement, null); domElement.XamlCssStyleSheets.First().AddError($"Cannot apply style to an element matching {string.Join(", ", matchingStyles.Select(x => x.Value))}: {exc.Message}"); return; } } } else { domElement.StyleInfo.OldMatchedSelectors = matchingStyles.ToList(); } } }
private static void RemoveRemovedDomElementsInternal(IDomElement <TDependencyObject, TDependencyProperty> domElement, INativeStyleService <TStyle, TDependencyObject, TDependencyProperty> nativeStyleService) { foreach (var item in domElement.ChildNodes) { if (item.StyleInfo is object) { nativeStyleService.SetStyle(item.Element, (TStyle)item.StyleInfo.InitialStyle); item.StyleInfo = null; } RemoveRemovedDomElementsInternal(item, nativeStyleService); } }