Actions can now have children.
authorStephaneLenclud
Wed, 31 Aug 2016 20:20:32 +0200
changeset 26582e87f4956ea
parent 264 4a08e1b7ba64
child 266 b11d7ebbdc7f
Actions can now have children.
Server/FormMain.cs
SharpLibEar/Action.cs
SharpLibEar/ActionDelay.cs
SharpLibEar/Event.cs
SharpLibEar/Manager.cs
SharpLibEar/Object.cs
     1.1 --- a/Server/FormMain.cs	Wed Aug 31 17:28:30 2016 +0200
     1.2 +++ b/Server/FormMain.cs	Wed Aug 31 20:20:32 2016 +0200
     1.3 @@ -309,6 +309,65 @@
     1.4  
     1.5          }
     1.6  
     1.7 +
     1.8 +        private static void AddActionsToTreeNode(TreeNode aParentNode, Ear.Object aObject)
     1.9 +        {
    1.10 +            foreach (Ear.Action a in aObject.Objects.OfType<Ear.Action>())
    1.11 +            {
    1.12 +                //Create action node
    1.13 +                TreeNode actionNode = aParentNode.Nodes.Add(a.Brief());
    1.14 +                actionNode.Tag = a;
    1.15 +                //Use color from parent unless our action itself is disabled
    1.16 +                actionNode.ForeColor = a.Enabled ? aParentNode.ForeColor : Color.DimGray;
    1.17 +                //Go recursive
    1.18 +                AddActionsToTreeNode(actionNode,a);
    1.19 +            }
    1.20 +        }
    1.21 +
    1.22 +
    1.23 +        /// <summary>
    1.24 +        /// 
    1.25 +        /// </summary>
    1.26 +        /// <param name="aObject"></param>
    1.27 +        /// <param name="aNode"></param>
    1.28 +        private static TreeNode FindTreeNodeForEarObject(Ear.Object aObject, TreeNode aNode)
    1.29 +        {
    1.30 +            if (aNode.Tag == aObject)
    1.31 +            {
    1.32 +                return aNode;
    1.33 +            }
    1.34 +
    1.35 +            foreach (TreeNode n in aNode.Nodes)
    1.36 +            {
    1.37 +                TreeNode found = FindTreeNodeForEarObject(aObject,n);
    1.38 +                if (found != null)
    1.39 +                {
    1.40 +                    return found;
    1.41 +                }
    1.42 +            }
    1.43 +
    1.44 +            return null;
    1.45 +        }
    1.46 +
    1.47 +
    1.48 +        /// <summary>
    1.49 +        /// 
    1.50 +        /// </summary>
    1.51 +        /// <param name="aObject"></param>
    1.52 +        private void SelectEarObject(Ear.Object aObject)
    1.53 +        {
    1.54 +            foreach (TreeNode n in iTreeViewEvents.Nodes)
    1.55 +            {
    1.56 +                TreeNode found = FindTreeNodeForEarObject(aObject, n);
    1.57 +                if (found != null)
    1.58 +                {
    1.59 +                    iTreeViewEvents.SelectedNode=found;
    1.60 +                    iTreeViewEvents.Focus();
    1.61 +                    return;
    1.62 +                }
    1.63 +            }
    1.64 +        }
    1.65 +
    1.66          /// <summary>
    1.67          /// Populate tree view with events and actions
    1.68          /// </summary>
    1.69 @@ -318,9 +377,6 @@
    1.70              buttonActionAdd.Enabled = false;
    1.71              buttonActionDelete.Enabled = false;
    1.72  
    1.73 -            Ear.Event currentEvent = CurrentEvent();
    1.74 -            Ear.Action currentAction = CurrentAction();
    1.75 -            TreeNode treeNodeToSelect = null;
    1.76              
    1.77              //Reset our tree
    1.78              iTreeViewEvents.Nodes.Clear();
    1.79 @@ -352,43 +408,14 @@
    1.80                  //Add event description as child node
    1.81                  eventNode.Nodes.Add(e.AttributeDescription).ForeColor = eventNode.ForeColor; 
    1.82                  //Create child node for actions root
    1.83 -                TreeNode actionsNodes = eventNode.Nodes.Add("Actions");
    1.84 -                actionsNodes.ForeColor = eventNode.ForeColor;
    1.85 -
    1.86 -                // Add our actions for that event
    1.87 -                foreach (Ear.Action a in e.Actions)
    1.88 -                {
    1.89 -                    TreeNode actionNode = actionsNodes.Nodes.Add(a.Brief());
    1.90 -                    actionNode.Tag = a;
    1.91 -                    //Use color from event unless our action itself is disabled
    1.92 -                    actionNode.ForeColor = a.Enabled? eventNode.ForeColor: Color.DimGray;
    1.93 -                    if (a == currentAction)
    1.94 -                    {
    1.95 -                        treeNodeToSelect = actionNode;
    1.96 -                    }
    1.97 -                }
    1.98 +                TreeNode actionsNode = eventNode.Nodes.Add("Actions");
    1.99 +                actionsNode.ForeColor = eventNode.ForeColor;
   1.100 +
   1.101 +                // Recursively add our actions for that event
   1.102 +                AddActionsToTreeNode(actionsNode,e);
   1.103              }
   1.104  
   1.105              iTreeViewEvents.ExpandAll();
   1.106 -            SelectEvent(currentEvent);
   1.107 -            
   1.108 -            if (treeNodeToSelect != null)
   1.109 -            {
   1.110 -                iTreeViewEvents.SelectedNode = treeNodeToSelect;
   1.111 -            }
   1.112 -            else if (iTreeViewEvents.SelectedNode != null && iTreeViewEvents.SelectedNode.Nodes[1].GetNodeCount(false) > 0)
   1.113 -            {
   1.114 -                //Select the last action if any 
   1.115 -                iTreeViewEvents.SelectedNode =
   1.116 -                    iTreeViewEvents.SelectedNode.Nodes[1].Nodes[
   1.117 -                        iTreeViewEvents.SelectedNode.Nodes[1].GetNodeCount(false) - 1];
   1.118 -            }
   1.119 -            else if (iTreeViewEvents.SelectedNode == null && iTreeViewEvents.Nodes.Count > 0)
   1.120 -            {
   1.121 -                //Still no selected node select the first one then
   1.122 -                iTreeViewEvents.SelectedNode = iTreeViewEvents.Nodes[0];
   1.123 -            }
   1.124 -
   1.125  
   1.126              UpdateEventView();
   1.127          }
   1.128 @@ -2650,26 +2677,6 @@
   1.129          }
   1.130  
   1.131  
   1.132 -        /// <summary>
   1.133 -        /// 
   1.134 -        /// </summary>
   1.135 -        /// <param name="aEvent"></param>
   1.136 -        private void SelectEvent(Ear.Event aEvent)
   1.137 -        {
   1.138 -            if (aEvent == null)
   1.139 -            {
   1.140 -                return;
   1.141 -            }
   1.142 -
   1.143 -            foreach (TreeNode node in iTreeViewEvents.Nodes)
   1.144 -            {
   1.145 -                if (node.Tag == aEvent)
   1.146 -                {
   1.147 -                    iTreeViewEvents.SelectedNode = node;
   1.148 -                    iTreeViewEvents.Focus();
   1.149 -                }
   1.150 -            }
   1.151 -        }
   1.152  
   1.153  
   1.154  
   1.155 @@ -2713,14 +2720,58 @@
   1.156          /// <summary>
   1.157          /// 
   1.158          /// </summary>
   1.159 +        /// <returns></returns>
   1.160 +        private Ear.Object CurrentEarObject()
   1.161 +        {
   1.162 +            Ear.Action a = CurrentAction();
   1.163 +            Ear.Event e = CurrentEvent();
   1.164 +
   1.165 +            if (a != null)
   1.166 +            {
   1.167 +                return a;
   1.168 +            }
   1.169 +
   1.170 +            return e;
   1.171 +        }
   1.172 +
   1.173 +        /// <summary>
   1.174 +        /// Get the current action based on event tree view selection
   1.175 +        /// </summary>
   1.176 +        /// <returns></returns>
   1.177 +        private Ear.Object CurrentEarParent()
   1.178 +        {
   1.179 +            TreeNode node = iTreeViewEvents.SelectedNode;
   1.180 +            if (node == null || node.Parent == null)
   1.181 +            {
   1.182 +                return null;
   1.183 +            }
   1.184 +
   1.185 +            if (node.Parent.Tag is Ear.Object)
   1.186 +            {
   1.187 +                return (Ear.Object)node.Parent.Tag;
   1.188 +            }
   1.189 +
   1.190 +            if (node.Parent.Parent != null && node.Parent.Parent.Tag is Ear.Object)
   1.191 +            {
   1.192 +                //Can be the case for events
   1.193 +                return (Ear.Object)node.Parent.Parent.Tag;
   1.194 +            }
   1.195 +
   1.196 +            return null;
   1.197 +        }
   1.198 +
   1.199 +
   1.200 +        /// <summary>
   1.201 +        /// 
   1.202 +        /// </summary>
   1.203          /// <param name="sender"></param>
   1.204          /// <param name="e"></param>
   1.205          private void buttonActionAdd_Click(object sender, EventArgs e)
   1.206          {
   1.207 -            Ear.Event selectedEvent = CurrentEvent();
   1.208 -            if (selectedEvent == null)
   1.209 +            Ear.Object parent = CurrentEarObject();
   1.210 +            if (parent == null )
   1.211              {
   1.212 -                //We did not find a corresponding event
   1.213 +                //We did not find a corresponding event or action
   1.214                  return;
   1.215              }
   1.216  
   1.217 @@ -2729,9 +2780,10 @@
   1.218              DialogResult res = CodeProject.Dialog.DlgBox.ShowDialog(ea);
   1.219              if (res == DialogResult.OK)
   1.220              {
   1.221 -                selectedEvent.Actions.Add(ea.Object);               
   1.222 +                parent.Objects.Add(ea.Object);               
   1.223                  Properties.Settings.Default.Save();
   1.224                  PopulateTreeViewEvents();
   1.225 +                SelectEarObject(ea.Object);
   1.226              }
   1.227          }
   1.228  
   1.229 @@ -2742,11 +2794,12 @@
   1.230          /// <param name="e"></param>
   1.231          private void buttonActionEdit_Click(object sender, EventArgs e)
   1.232          {
   1.233 -            Ear.Event selectedEvent = CurrentEvent();
   1.234              Ear.Action selectedAction = CurrentAction();
   1.235 -            if (selectedEvent == null || selectedAction == null)
   1.236 +            Ear.Object parent = CurrentEarParent()
   1.237 +            ;
   1.238 +            if (parent == null || selectedAction == null)
   1.239              {
   1.240 -                //We did not find a corresponding event
   1.241 +                //We did not find a corresponding parent
   1.242                  return;
   1.243              }
   1.244  
   1.245 @@ -2757,11 +2810,14 @@
   1.246              DialogResult res = CodeProject.Dialog.DlgBox.ShowDialog(ea);
   1.247              if (res == DialogResult.OK)
   1.248              {
   1.249 +                //Make sure we keep the same children as before
   1.250 +                ea.Object.Objects = parent.Objects[actionIndex].Objects;
   1.251                  //Update our action
   1.252 -                selectedEvent.Actions[actionIndex]=ea.Object;
   1.253 +                parent.Objects[actionIndex]=ea.Object;
   1.254                  //Save and rebuild our event tree view
   1.255                  Properties.Settings.Default.Save();
   1.256                  PopulateTreeViewEvents();
   1.257 +                SelectEarObject(ea.Object);
   1.258              }
   1.259          }
   1.260  
   1.261 @@ -2772,7 +2828,6 @@
   1.262          /// <param name="e"></param>
   1.263          private void buttonActionDelete_Click(object sender, EventArgs e)
   1.264          {
   1.265 -
   1.266              Ear.Action action = CurrentAction();
   1.267              if (action == null)
   1.268              {
   1.269 @@ -2816,16 +2871,17 @@
   1.270              }
   1.271  
   1.272              //Swap actions in event's action list
   1.273 -            Ear.Event currentEvent = CurrentEvent();
   1.274 +            Ear.Object parent = CurrentEarParent();
   1.275              int currentIndex = iTreeViewEvents.SelectedNode.Index;
   1.276 -            Ear.Action movingUp = currentEvent.Actions[currentIndex];
   1.277 -            Ear.Action movingDown = currentEvent.Actions[currentIndex-1];
   1.278 -            currentEvent.Actions[currentIndex] = movingDown;
   1.279 -            currentEvent.Actions[currentIndex-1] = movingUp;
   1.280 +            Ear.Action movingUp = parent.Objects[currentIndex] as Ear.Action;
   1.281 +            Ear.Action movingDown = parent.Objects[currentIndex-1] as Ear.Action;
   1.282 +            parent.Objects[currentIndex] = movingDown;
   1.283 +            parent.Objects[currentIndex-1] = movingUp;
   1.284  
   1.285              //Save and populate our tree again
   1.286              Properties.Settings.Default.Save();
   1.287              PopulateTreeViewEvents();
   1.288 +            SelectEarObject(a);
   1.289  
   1.290          }
   1.291  
   1.292 @@ -2845,16 +2901,17 @@
   1.293              }
   1.294  
   1.295              //Swap actions in event's action list
   1.296 -            Ear.Event currentEvent = CurrentEvent();
   1.297 +            Ear.Object parent = CurrentEarParent();
   1.298              int currentIndex = iTreeViewEvents.SelectedNode.Index;
   1.299 -            Ear.Action movingDown = currentEvent.Actions[currentIndex];
   1.300 -            Ear.Action movingUp = currentEvent.Actions[currentIndex + 1];
   1.301 -            currentEvent.Actions[currentIndex] = movingUp;
   1.302 -            currentEvent.Actions[currentIndex + 1] = movingDown;
   1.303 +            Ear.Action movingDown = parent.Objects[currentIndex] as Ear.Action;
   1.304 +            Ear.Action movingUp = parent.Objects[currentIndex + 1] as Ear.Action;
   1.305 +            parent.Objects[currentIndex] = movingUp;
   1.306 +            parent.Objects[currentIndex + 1] = movingDown;
   1.307  
   1.308              //Save and populate our tree again
   1.309              Properties.Settings.Default.Save();
   1.310              PopulateTreeViewEvents();
   1.311 +            SelectEarObject(a);
   1.312          }
   1.313  
   1.314  
   1.315 @@ -2930,7 +2987,7 @@
   1.316                  Properties.Settings.Default.EarManager.Events.Add(ea.Object);
   1.317                  Properties.Settings.Default.Save();
   1.318                  PopulateTreeViewEvents();
   1.319 -                SelectEvent(ea.Object);
   1.320 +                SelectEarObject(ea.Object);
   1.321              }
   1.322          }
   1.323  
   1.324 @@ -2975,12 +3032,13 @@
   1.325              if (res == DialogResult.OK)
   1.326              {                
   1.327                  //Make sure we keep the same actions as before
   1.328 -                ea.Object.Actions = Properties.Settings.Default.EarManager.Events[index].Actions;
   1.329 +                ea.Object.Objects = Properties.Settings.Default.EarManager.Events[index].Objects;
   1.330                  //Update our event
   1.331                  Properties.Settings.Default.EarManager.Events[index] = ea.Object;
   1.332                  //Save and rebuild our event tree view
   1.333                  Properties.Settings.Default.Save();
   1.334                  PopulateTreeViewEvents();
   1.335 +                SelectEarObject(ea.Object);
   1.336              }
   1.337          }
   1.338  
     2.1 --- a/SharpLibEar/Action.cs	Wed Aug 31 17:28:30 2016 +0200
     2.2 +++ b/SharpLibEar/Action.cs	Wed Aug 31 20:20:32 2016 +0200
     2.3 @@ -4,6 +4,7 @@
     2.4  using System;
     2.5  using System.Collections.Generic;
     2.6  using System.Diagnostics;
     2.7 +using System.Linq;
     2.8  using System.Runtime.Serialization;
     2.9  using System.Threading;
    2.10  using System.Threading.Tasks;
    2.11 @@ -11,7 +12,8 @@
    2.12  namespace SharpLib.Ear
    2.13  {
    2.14      [DataContract]
    2.15 -    public abstract class Action: Object
    2.16 +    [AttributeObject(Id = "Action", Name = "Action", Description = "An empty action.")]
    2.17 +    public class Action: Object
    2.18      {
    2.19          [DataMember]
    2.20          [AttributeObjectProperty
    2.21 @@ -34,7 +36,14 @@
    2.22              get { return Iterations > 0; }
    2.23          }
    2.24  
    2.25 -        protected abstract Task DoExecute();
    2.26 +        /// <summary>
    2.27 +        /// Basic action just does nothing
    2.28 +        /// </summary>
    2.29 +        /// <returns></returns>
    2.30 +        protected virtual async Task DoExecute()
    2.31 +        {
    2.32 +            
    2.33 +        }
    2.34  
    2.35          /// <summary>
    2.36          /// Allows testing from generic edit dialog.
    2.37 @@ -66,14 +75,25 @@
    2.38              for (int i = Iterations; i > 0; i--)
    2.39              {
    2.40                  Trace.WriteLine($"EAR: Action.Execute: [{Iterations - i + 1}/{Iterations}] - {BriefBase()}");
    2.41 +                //For each iteration
    2.42 +                //We first execute ourselves
    2.43                  await DoExecute();
    2.44 +
    2.45 +                //Then our children
    2.46 +                foreach (Action a in Objects.OfType<Action>())
    2.47 +                {
    2.48 +                    await a.Execute();
    2.49 +                }
    2.50              }            
    2.51          }
    2.52  
    2.53 -
    2.54 +        /// <summary>
    2.55 +        /// For inherited classes to override.
    2.56 +        /// </summary>
    2.57 +        /// <returns></returns>
    2.58          public virtual string BriefBase()
    2.59          {
    2.60 -            return base.Brief();
    2.61 +            return Name;
    2.62          }
    2.63  
    2.64          /// <summary>
     3.1 --- a/SharpLibEar/ActionDelay.cs	Wed Aug 31 17:28:30 2016 +0200
     3.2 +++ b/SharpLibEar/ActionDelay.cs	Wed Aug 31 20:20:32 2016 +0200
     3.3 @@ -8,7 +8,7 @@
     3.4  namespace SharpLib.Ear
     3.5  {
     3.6      [DataContract]
     3.7 -    [AttributeObject(Id = "Task.Delay", Name = "Delay", Description = "Delay the execution of the next task by the specified amount of milliseconds.")]
     3.8 +    [AttributeObject(Id = "Action.Task.Delay", Name = "Delay", Description = "Delay the execution of the next task.")]
     3.9      public class ActionDelay : Action
    3.10      {
    3.11          [DataMember]
    3.12 @@ -16,7 +16,7 @@
    3.13              (
    3.14                  Id = "Task.Delay.Milliseconds",
    3.15                  Name = "Delay (ms)",
    3.16 -                Description = "Specifies our delay in milliseconds.",
    3.17 +                Description = "Specifies the delay in milliseconds.",
    3.18                  Minimum = "0",
    3.19                  Maximum = "60000",
    3.20                  Increment = "1000"
     4.1 --- a/SharpLibEar/Event.cs	Wed Aug 31 17:28:30 2016 +0200
     4.2 +++ b/SharpLibEar/Event.cs	Wed Aug 31 20:20:32 2016 +0200
     4.3 @@ -4,6 +4,7 @@
     4.4  using System;
     4.5  using System.Collections.Generic;
     4.6  using System.Diagnostics;
     4.7 +using System.Linq;
     4.8  using System.Runtime.Serialization;
     4.9  using System.Threading.Tasks;
    4.10  
    4.11 @@ -24,41 +25,6 @@
    4.12          public bool Enabled { get; set; } = true;
    4.13  
    4.14  
    4.15 -        /// <summary>
    4.16 -        /// TODO: Should the name property be moved to our EAR Object?
    4.17 -        /// </summary>
    4.18 -        [DataMember]
    4.19 -        [AttributeObjectProperty
    4.20 -            (
    4.21 -                Id = "Event.Name",
    4.22 -                Name = "Name",
    4.23 -                Description = "Given event name. Can be used to trigger it."
    4.24 -            )
    4.25 -        ]
    4.26 -        public string Name { get; set; } = "";
    4.27 -
    4.28 -
    4.29 -        [DataMember]
    4.30 -        public List<Action> Actions = new List<Action>();
    4.31 -
    4.32 -
    4.33 -        protected override void DoConstruct()
    4.34 -        {
    4.35 -            base.DoConstruct();
    4.36 -
    4.37 -            //Make sure our name is not null
    4.38 -            if (Name == null)
    4.39 -            {
    4.40 -                Name = "";
    4.41 -            }
    4.42 -
    4.43 -            // TODO: Construct properties too
    4.44 -            foreach (Action a in Actions)
    4.45 -            {
    4.46 -                a.Construct();
    4.47 -            }
    4.48 -
    4.49 -        }
    4.50  
    4.51  
    4.52          /// <summary>
    4.53 @@ -74,7 +40,7 @@
    4.54          public async Task Trigger()
    4.55          {
    4.56              Trace.WriteLine("Event triggered: " + AttributeName);
    4.57 -            foreach (Action action in Actions)
    4.58 +            foreach (Action action in Objects.OfType<Action>())
    4.59              {
    4.60                  await action.Execute();
    4.61              }
     5.1 --- a/SharpLibEar/Manager.cs	Wed Aug 31 17:28:30 2016 +0200
     5.2 +++ b/SharpLibEar/Manager.cs	Wed Aug 31 20:20:32 2016 +0200
     5.3 @@ -102,12 +102,38 @@
     5.4          {
     5.5              foreach (Event e in Events)
     5.6              {
     5.7 -                if (e.Actions.Remove(aAction))
     5.8 +                if (RemoveObject(e,aAction))
     5.9                  {
    5.10                      //We removed our action, we are done here.
    5.11                      return;
    5.12                  }
    5.13              }
    5.14          }
    5.15 +
    5.16 +        /// <summary>
    5.17 +        /// Remove the specified action from the event it belongs too.
    5.18 +        /// </summary>
    5.19 +        /// <param name="aAction"></param>
    5.20 +        private static bool RemoveObject(Object aCurrent, Object aToRemove)
    5.21 +        {
    5.22 +            //Exit condition
    5.23 +            if (aCurrent.Objects.Remove(aToRemove))
    5.24 +            {
    5.25 +                //We removed our action, we are done here.
    5.26 +                return true;
    5.27 +            }
    5.28 +
    5.29 +            foreach (Object o in aCurrent.Objects)
    5.30 +            {
    5.31 +                bool done = RemoveObject(o, aToRemove);
    5.32 +                if (done)
    5.33 +                {
    5.34 +                    return true;
    5.35 +                } 
    5.36 +            }
    5.37 +
    5.38 +            return false;
    5.39 +        }
    5.40 +
    5.41      }
    5.42  }
    5.43 \ No newline at end of file
     6.1 --- a/SharpLibEar/Object.cs	Wed Aug 31 17:28:30 2016 +0200
     6.2 +++ b/SharpLibEar/Object.cs	Wed Aug 31 20:20:32 2016 +0200
     6.3 @@ -19,6 +19,22 @@
     6.4      {
     6.5          private bool iConstructed = false;
     6.6  
     6.7 +        [DataMember]
     6.8 +        public List<Object> Objects = new List<Object>();
     6.9 +
    6.10 +        /// <summary>
    6.11 +        /// </summary>
    6.12 +        [DataMember]
    6.13 +        [AttributeObjectProperty
    6.14 +            (
    6.15 +                Id = "Object.Name",
    6.16 +                Name = "Name",
    6.17 +                Description = "Given object name."
    6.18 +            )
    6.19 +        ]
    6.20 +        public string Name { get; set; } = "";
    6.21 +
    6.22 +
    6.23          protected Object()
    6.24          {
    6.25              Construct();
    6.26 @@ -29,11 +45,18 @@
    6.27          /// </summary>
    6.28          public void Construct()
    6.29          {
    6.30 +            //Construct ourselves first
    6.31              if (!iConstructed)
    6.32              {
    6.33                  DoConstruct();
    6.34                  iConstructed = true;
    6.35              }
    6.36 +
    6.37 +            //Then construct our children
    6.38 +            foreach (Object o in Objects)
    6.39 +            {
    6.40 +                o.Construct();
    6.41 +            }
    6.42          }
    6.43  
    6.44          /// <summary>
    6.45 @@ -41,10 +64,19 @@
    6.46          /// </summary>
    6.47          protected virtual void DoConstruct()
    6.48          {
    6.49 +            //Make sure our name is not null
    6.50 +            if (Name == null)
    6.51 +            {
    6.52 +                Name = "";
    6.53 +            }
    6.54  
    6.55 +            // Makes sure our objects are not null
    6.56 +            if (Objects == null)
    6.57 +            {
    6.58 +                Objects = new List<Object>();
    6.59 +            }
    6.60          }
    6.61  
    6.62 -
    6.63          public enum State
    6.64          {
    6.65              Rest=0,