internal static Visual OptimizePropertyValues(Visual root) { var graph = ObjectGraph <Graph.Node> .FromCompositionObject(root, includeVertices : false); foreach (var(_, obj) in graph.CompositionObjectNodes) { switch (obj.Type) { case CompositionObjectType.ContainerVisual: case CompositionObjectType.SpriteVisual: case CompositionObjectType.ShapeVisual: OptimizeVisualProperties((Visual)obj); break; case CompositionObjectType.CompositionSpriteShape: OptimizeSpriteShapeProperties((CompositionSpriteShape)obj); break; case CompositionObjectType.CompositionContainerShape: OptimizeShapeProperties((CompositionShape)obj); break; } } return(root); }
internal static Visual OptimizeContainers(Visual root) { var graph = ObjectGraph <Node> .FromCompositionObject(root, includeVertices : true); // Discover the parents of each container foreach (var node in graph.CompositionObjectNodes) { switch (node.Object.Type) { case CompositionObjectType.CompositionContainerShape: case CompositionObjectType.ShapeVisual: foreach (var child in ((IContainShapes)node.Object).Shapes) { graph[child].Parent = node.Object; } break; case CompositionObjectType.ContainerVisual: foreach (var child in ((ContainerVisual)node.Object).Children) { graph[child].Parent = node.Object; } break; } } RemoveTransparentShapes(graph); RemoveEmptyContainers(graph); SimplifyProperties(graph); CoalesceContainerShapes(graph); CoalesceContainerVisuals(graph); return(root); }
/// <summary> /// Analyzes the given tree and returns information about its compatibility with a runtime. /// </summary> /// <returns>An object with properties describing the compatibility requirements of the tree.</returns> public static ApiCompatibility Analyze(CompositionObject graphRoot) { var objectGraph = ObjectGraph <Graph.Node> .FromCompositionObject(graphRoot, includeVertices : false); var requiresCompositionVisualSurface = (from node in objectGraph.CompositionObjectNodes where node.Object.Type == CompositionObjectType.CompositionVisualSurface select node).Any(); // Always require CompostionGeometryClip - this ensures that we are never compatible with // RS4 (geometries are flaky in RS4, and CompositionGeometryClip is new in RS5). return(new ApiCompatibility { RequiresCompositionGeometricClip = true, RequiresCompositionVisualSurface = requiresCompositionVisualSurface }); }
internal static Visual OptimizePropertyValues(Visual root) { var graph = ObjectGraph <Graph.Node> .FromCompositionObject(root, includeVertices : false); foreach (var(_, obj) in graph.CompositionObjectNodes) { switch (obj.Type) { case CompositionObjectType.ContainerVisual: case CompositionObjectType.LayerVisual: case CompositionObjectType.SpriteVisual: case CompositionObjectType.ShapeVisual: OptimizeVisualProperties((Visual)obj); break; case CompositionObjectType.CompositionSpriteShape: OptimizeSpriteShapeProperties((CompositionSpriteShape)obj); break; case CompositionObjectType.CompositionContainerShape: OptimizeShapeProperties((CompositionShape)obj); break; case CompositionObjectType.StepEasingFunction: OptimizeStepEasingFunctionProperties((StepEasingFunction)obj); break; case CompositionObjectType.CompositionLinearGradientBrush: case CompositionObjectType.CompositionRadialGradientBrush: OptimizeGradientBrush((CompositionGradientBrush)obj); break; case CompositionObjectType.CompositionVisualSurface: OptimizeVisualSurfaceProperties((CompositionVisualSurface)obj); break; } } return(root); }
XDocument ToXDocument(CompositionObject compositionObject) { // Build the graph of objects. _objectGraph = ObjectGraph <ObjectData> .FromCompositionObject(compositionObject, includeVertices : true); // Give names to each object. foreach ((var node, var name) in CodeGen.NodeNamer <ObjectData> .GenerateNodeNames(_objectGraph.Nodes)) { node.Name = name; } // Initialize each node. foreach (var n in _objectGraph.Nodes) { n.Initialize(this); } // Second stage initialization - relies on all nodes having had the first stage of initialization. foreach (var n in _objectGraph.Nodes) { n.Initialize2(); } var rootNode = _objectGraph[compositionObject]; // Give the root object a special name and category. rootNode.Name = $"{rootNode.Name} (Root)"; rootNode.Category = CategoryRoot; // Get the groups. var groups = GroupTree(rootNode, null).ToArray(); // Get the Nodes for the objects that are going to show up in the DGML. var objectNodes = _objectGraph.Nodes.Where(n => n.IsDgmlNode).ToArray(); // Create the DGML nodes. var nodes = from n in objectNodes select CreateNodeXml(id : n.Id, label : n.Name, category : n.Category.Id); // Create the DGML nodes for the groups. nodes = nodes.Concat( from gn in groups select CreateNodeXml(id: gn.Id, label: gn.GroupName, @group: "Expanded")); // Create the categories used by object nodes. var categories = (from n in objectNodes select n.Category).Distinct(); // Create the links between the nodes. var links = from n in objectNodes from otherNode in n.Children select new XElement(ns + "Link", new XAttribute("Source", n.Id), new XAttribute("Target", otherNode.Id)); // Create the "contains" links for the nodes contained in groups. var containsLinks = (from g in groups from member in g.ItemsInGroup select new XElement(ns + "Link", new XAttribute("Source", g.Id), new XAttribute("Target", member.Id), new XAttribute("Category", "Contains"))).ToArray(); // Create the "contains" links for the groups contained in groups var groupContainsGroupsLinks = (from g in groups from member in g.GroupsInGroup select new XElement(ns + "Link", new XAttribute("Source", g.Id), new XAttribute("Target", member.Id), new XAttribute("Category", "Contains"))).ToArray(); containsLinks = containsLinks.Concat(groupContainsGroupsLinks).ToArray(); // Create the XML return(new XDocument( new XElement( ns + "DirectedGraph", new XElement(ns + "Nodes", nodes), new XElement(ns + "Links", links.Concat(containsLinks)), new XElement( ns + "Categories", categories.Select(c => c.ToXElement()).Append( new XElement( ns + "Category", new XAttribute("Id", "Contains"), new XAttribute("Label", "Contains"), new XAttribute("Description", "Whether the source of the link contains the target object"), new XAttribute("CanBeDataDriven", "False"), new XAttribute("CanLinkedNodesBeDataDriven", "True"), new XAttribute("IncomingActionLabel", "Contained By"), new XAttribute("IsContainment", "True"), new XAttribute("OutgoingActionLabel", "Contains"))) ), new XElement( ns + "Properties", CreatePropertyXml(id: "Bounds", dataType: "System.Windows.Rect"), CreatePropertyXml(id: "CanBeDataDriven", label: "CanBeDataDriven", description: "CanBeDataDriven", dataType: "System.Boolean"), CreatePropertyXml(id: "CanLinkedNodesBeDataDriven", label: "CanLinkedNodesBeDataDriven", description: "CanLinkedNodesBeDataDriven", dataType: "System.Boolean"), CreatePropertyXml(id: "Group", label: "Group", description: "Display the node as a group", dataType: "Microsoft.VisualStudio.GraphModel.GraphGroupStyle"), CreatePropertyXml(id: "IncomingActionLabel", label: "IncomingActionLabel", description: "IncomingActionLabel", dataType: "System.String"), CreatePropertyXml(id: "IsContainment", dataType: "System.Boolean"), CreatePropertyXml(id: "Label", label: "Label", description: "Displayable label of an Annotatable object", dataType: "System.String"), CreatePropertyXml(id: "Layout", dataType: "System.String"), CreatePropertyXml(id: "OutgoingActionLabel", label: "OutgoingActionLabel", description: "OutgoingActionLabel", dataType: "System.String"), CreatePropertyXml(id: "UseManualLocation", dataType: "System.Boolean"), CreatePropertyXml(id: "ZoomLevel", dataType: "System.String") ) ) )); }
public static ObjectGraph <Node> FromCompositionObject(CompositionObject root, bool includeVertices) => ObjectGraph <Node> .FromCompositionObject(root, includeVertices);