/// <summary> /// This function adapts the children of the view that they represent the children of the node this view is for. /// Children are added and removed. /// </summary> /// <param name="processedBehaviors">A list of previously processed behaviours to deal with circular references.</param> public override void SynchronizeWithNode(ProcessedBehaviors processedBehaviors) { // if we have a circular reference, we must skip it if (!processedBehaviors.MayProcessCheckOnly(_node)) { _children.ClearChildren(); return; } base.SynchronizeWithNode(processedBehaviors); }
public override void DoSynchronizeWithNode(ProcessedBehaviors processedBehaviors) { // make all connectors changable for (int i = 0; i < _children.Connectors.Count; ++i) { _children.Connectors[i].IsReadOnly = false; } if (_isExpanded) { base.DoSynchronizeWithNode(processedBehaviors); } else { _subGraphNeedsToBeRebuilt = false; _children.ClearConnectors(); RemoveAllConnectorSubItems(); //foreach(Connector connector in _node.Connectors) // connector.Clone(_children); new ConnectorMultiple(_children, string.Empty, "GenericChildren", 1, int.MaxValue); // generate the dummy nodes for the sub-referenced behaviours foreach (Node child in ((Node)((ReferencedBehaviorNode)_node).Reference).Children) { GenerateReferencedBehaviorsTree(processedBehaviors, this, child); } // make all connectors readonly for (int i = 0; i < _children.Connectors.Count; ++i) { _children.Connectors[i].IsReadOnly = true; } GenerateNewLabel(); } }
/// <summary> /// Recalculates the layout if necessary. /// </summary> /// <param name="graphics">The graphics object which is used to measure the strings.</param> internal void UpdateLayout(Graphics graphics) { if (_layoutChanged) { _layoutChanged = false; // synchronize layout ProcessedBehaviors processedBehaviors = new ProcessedBehaviors(); _rootNodeLayout.SynchronizeWithNode(processedBehaviors); // calculate the size of each node _rootNodeLayout.UpdateFinalSize(graphics, _rootNodeLayout.RootBehavior); _rootNodeLayout.UpdateExtent(); // calculate the total size of the branches _rootNodeLayout.CalculateLayoutSize(_padding); // align the branches _rootNodeLayout.Layout(_padding); // align the parents at the centre of their children _rootNodeLayout.UpdateLocation(); } }
/// <summary> /// Adds nodes to the referenced behaviour which represent sub-referenced behaviours. /// </summary> /// <param name="processedBehaviors">A list of processed behaviours to handle circular references.</param> /// <param name="parent">The node the sub-referenced behaviours will be added to.</param> /// <param name="node">The current node we are checking.</param> protected void GenerateReferencedBehaviorsTree(ProcessedBehaviors processedBehaviors, NodeViewData parent, Node node) { if (!processedBehaviors.MayProcess(node)) { return; } // check if this is a referenced behaviour if (node is ReferencedBehaviorNode) { // create the dummy node and add it without marking the behaviour as being modified as these are no REAL nodes. NodeViewData rb = node.CreateNodeViewData(parent, _rootBehavior); #if DEBUG rb.IsSubreferencedGraphNode(); #endif rb.DoSynchronizeWithNode(processedBehaviors); Connector conn = parent.GetConnector("GenericChildren"); Debug.Check(conn != null); Connector rbconn = parent.GetConnector("GenericChildren"); Debug.Check(rbconn != null); bool parentReadOnly = conn.IsReadOnly; conn.IsReadOnly = false; parent.AddChildNotModified(conn, rb); conn.IsReadOnly = parentReadOnly; // we have a circular reference here. Skip the children if (((ReferencedBehaviorNode)node).Reference == _rootBehavior) { rbconn.IsReadOnly = true; return; } // do the same for all the children foreach (Node child in node.Children) { GenerateReferencedBehaviorsTree(processedBehaviors.Branch(child), rb, child); } rbconn.IsReadOnly = true; } else if (node is Impulse) { // create the dummy node and add it without marking the behaviour as being modified as these are no REAL nodes. NodeViewData ip = node.CreateNodeViewData(parent, _rootBehavior); ip.DoSynchronizeWithNode(processedBehaviors); // do the same for all the children foreach (Node child in node.Children) { GenerateReferencedBehaviorsTree(processedBehaviors.Branch(child), ip, child); } if (ip.Children.Count > 0) { Connector conn = parent.GetConnector("GenericChildren"); Debug.Check(conn != null); Connector ipconn = ip.GetConnector("GenericChildren"); Debug.Check(ipconn != null); parent.AddChildNotModified(conn, ip); ipconn.IsReadOnly = true; } } else { // do the same for all the children foreach (Node child in node.Children) { GenerateReferencedBehaviorsTree(processedBehaviors.Branch(child), parent, child); } } }
/// <summary> /// Used to branch a new list for its children. /// </summary> /// <param name="previous">The list of processed behaviours the parent used.</param> protected ProcessedBehaviors(ProcessedBehaviors previous) { _processedBehaviors.AddRange(previous._processedBehaviors); }