Flowchart.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / cdf / src / NetFx40 / System.Activities / System / Activities / Statements / Flowchart.cs / 1305376 / Flowchart.cs

                            //------------------------------------------------------------------------------ 
// Copyright (c) Microsoft Corporation.  All rights reserved.
//-----------------------------------------------------------------------------

namespace System.Activities.Statements 
{
    using System.Activities; 
    using System.Collections.Generic; 
    using System.Collections.ObjectModel;
    using System.Runtime; 
    using System.Runtime.Collections;
    using System.Windows.Markup;

    [ContentProperty("Nodes")] 
    public sealed class Flowchart : NativeActivity
    { 
        Collection variables; 
        Collection nodes;
        Collection allNodes; 

        CompletionCallback onStepCompleted;
        CompletionCallback onDecisionCompleted;
 
        Variable currentNode;
        public Flowchart() 
        { 
            this.currentNode = new Variable();
            this.allNodes = new Collection(); 
        }

        public Collection Variables
        { 
            get
            { 
                if (this.variables == null) 
                {
                    this.variables = new ValidatingCollection 
                    {
                        // disallow null values
                        OnAddValidationCallback = item =>
                        { 
                            if (item == null)
                            { 
                                throw FxTrace.Exception.ArgumentNull("item"); 
                            }
                        } 
                    };
                }
                return this.variables;
            } 
        }
 
        [DependsOn("Variables")] 
        public FlowNode StartNode
        { 
            get;
            set;
        }
 
        [DependsOn("StartNode")]
        public Collection Nodes 
        { 
            get
            { 
                if (this.nodes == null)
                {
                    this.nodes = new ValidatingCollection
                    { 
                        // disallow null values
                        OnAddValidationCallback = item => 
                        { 
                            if (item == null)
                            { 
                                throw FxTrace.Exception.ArgumentNull("item");
                            }
                        }
                    }; 
                }
 
                return this.nodes; 
            }
        } 

        protected override void CacheMetadata(NativeActivityMetadata metadata)
        {
            metadata.SetVariablesCollection(this.Variables); 
            metadata.AddImplementationVariable(this.currentNode);
 
            GatherAllNodes(metadata); 

            HashSet uniqueChildren = new HashSet(); 
            for (int i = 0; i < this.allNodes.Count; i++)
            {
                this.allNodes[i].GetChildActivities(uniqueChildren);
            } 

            List children = new List(uniqueChildren.Count); 
            foreach (Activity child in uniqueChildren) 
            {
                children.Add(child); 
            }

            metadata.SetChildrenCollection(new Collection(children));
        } 

        void GatherAllNodes(NativeActivityMetadata metadata) 
        { 
            // Clear out our cached list of all nodes
            this.allNodes.Clear(); 

            if (this.StartNode == null && this.Nodes.Count > 0)
            {
                metadata.AddValidationError(SR.FlowchartMissingStartNode(this.DisplayName)); 
            }
            else 
            { 
                DepthFirstVisitNodes((n) => VisitNode(n, metadata), this.StartNode);
            } 
        }

        // Returns true if we should visit connected nodes
        bool VisitNode(FlowNode node, NativeActivityMetadata metadata) 
        {
            if (node.Open(this, metadata)) 
            { 
                Fx.Assert(node.Index == -1 && !this.allNodes.Contains(node), "Corrupt Flowchart.allNodes.");
 
                node.Index = this.allNodes.Count;
                this.allNodes.Add(node);

                return true; 
            }
 
            return false; 
        }
 
        void DepthFirstVisitNodes(Func visitNodeCallback, FlowNode start)
        {
            Fx.Assert(visitNodeCallback != null, "This must be supplied since it stops us from infinitely looping.");
 
            List connected = new List();
            Stack stack = new Stack(); 
            if (start == null) 
            {
                return; 
            }
            stack.Push(start);
            while (stack.Count > 0)
            { 
                FlowNode current = stack.Pop();
 
                if (current == null) 
                {
                    continue; 
                }

                if (visitNodeCallback(current))
                { 
                    connected.Clear();
                    current.GetConnectedNodes(connected); 
 
                    for (int i = 0; i < connected.Count; i++)
                    { 
                        stack.Push(connected[i]);
                    }
                }
            } 
        }
 
 
        protected override void Execute(NativeActivityContext context)
        { 
            if (this.StartNode != null)
            {
                if (TD.FlowchartStartIsEnabled())
                { 
                    TD.FlowchartStart(this.DisplayName);
                } 
                ExecuteNodeChain(context, this.StartNode, null); 
            }
            else 
            {
                if (TD.FlowchartEmptyIsEnabled())
                {
                    TD.FlowchartEmpty(this.DisplayName); 
                }
            } 
        } 

        void ExecuteNodeChain(NativeActivityContext context, FlowNode node, ActivityInstance completedInstance) 
        {
            if (node == null)
            {
                if (context.IsCancellationRequested) 
                {
                    Fx.Assert(completedInstance != null, "cannot request cancel if we never scheduled any children"); 
                    // we are done but the last child didn't complete successfully 
                    if (completedInstance.State != ActivityInstanceState.Closed)
                    { 
                        context.MarkCanceled();
                    }
                }
 
                return;
            } 
 
            if (context.IsCancellationRequested)
            { 
                // we're not done and cancel has been requested
                context.MarkCanceled();
                return;
            } 

 
            Fx.Assert(node != null, "caller should validate"); 
            FlowNode current = node;
            do 
            {
                FlowNode next;
                if (ExecuteSingleNode(context, current, out next))
                { 
                    current = next;
                } 
                else 
                {
                    this.currentNode.Set(context, current.Index); 
                    current = null;
                }
            }
            while (current != null); 
        }
 
        bool ExecuteSingleNode(NativeActivityContext context, FlowNode node, out FlowNode nextNode) 
        {
            Fx.Assert(node != null, "caller should validate"); 
            FlowStep step = node as FlowStep;
            if (step != null)
            {
                if (this.onStepCompleted == null) 
                {
                    this.onStepCompleted = new CompletionCallback(OnStepCompleted); 
                } 

                return step.Execute(context, this.onStepCompleted, out nextNode); 
            }

            nextNode = null;
            FlowDecision decision = node as FlowDecision; 
            if (decision != null)
            { 
                if (this.onDecisionCompleted == null) 
                {
                    this.onDecisionCompleted = new CompletionCallback(OnDecisionCompleted); 
                }

                return decision.Execute(context, this.onDecisionCompleted);
            } 

            IFlowSwitch switchNode = node as IFlowSwitch; 
            Fx.Assert(switchNode != null, "unrecognized FlowNode"); 

            return switchNode.Execute(context, this); 
        }

        FlowNode GetCurrentNode(NativeActivityContext context)
        { 
            int index = this.currentNode.Get(context);
            FlowNode result = this.allNodes[index]; 
            Fx.Assert(result != null, "corrupt internal state"); 
            return result;
        } 

        void OnStepCompleted(NativeActivityContext context, ActivityInstance completedInstance)
        {
            FlowStep step = GetCurrentNode(context) as FlowStep; 
            Fx.Assert(step != null, "corrupt internal state");
            FlowNode next = step.Next; 
            ExecuteNodeChain(context, next, completedInstance); 
        }
 
        void OnDecisionCompleted(NativeActivityContext context, ActivityInstance completedInstance, bool result)
        {
            FlowDecision decision = GetCurrentNode(context) as FlowDecision;
            Fx.Assert(decision != null, "corrupt internal state"); 
            FlowNode next = result ? decision.True : decision.False;
            ExecuteNodeChain(context, next, completedInstance); 
        } 

        internal void OnSwitchCompleted(NativeActivityContext context, ActivityInstance completedInstance, T result) 
        {
            IFlowSwitch switchNode = GetCurrentNode(context) as IFlowSwitch;
            Fx.Assert(switchNode != null, "corrupt internal state");
            FlowNode next = switchNode.GetNextNode(result); 
            ExecuteNodeChain(context, next, completedInstance);
        } 
    } 
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK