ScheduleCanvas.cs 4.7 KB
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace RoboforkApp
{
    public class ScheduleCanvas : Canvas
    {
        const double COOR_Y = 65;
        const double RADIUS_NODE = 25;
        private simulationRobo simulation;
        private Point startPoint;
        private Point endPoint;
        private bool _isGoal = false;
        private double _speed = 0.2; //Now _speed is fixed, but when update node
        private int index;

        private List<ucNode> _lstNode;

        /// <summary>
        /// Create simulation
        /// </summary>
        /// <param name="lstNode"></param>
        public void CreateSimulation(List<ucNode> lstNode)
        {
            //If node is less than 2 so return
            if (this.Children.Count < 2)
            {
                return;
            }

            this.Children.Remove(simulation);

            //Init data
            this._lstNode = lstNode;
            this.startPoint = new Point(Canvas.GetLeft(_lstNode[index]) + RADIUS_NODE, COOR_Y);
            this.endPoint = new Point(Canvas.GetLeft(_lstNode[index + 1]) + RADIUS_NODE, COOR_Y);
            this.index += 1;
            if (index == _lstNode.Count - 1)
            {
                _isGoal = true;
            }

            // Start simulation
            RoboSimulation();
        }

        /// <summary>
        /// Create robo simulation on line
        /// </summary>
        private void RoboSimulation()
        {
            simulation = new simulationRobo();
            simulation.storyBoard = CreatPathAnimation(startPoint, endPoint, _speed); //pathAnimationStoryboard;
            this.Children.Add(simulation);
        }

        /// <summary>
        /// Get storyboard
        /// </summary>
        /// <param name="startPoint">Point start line</param>
        /// <param name="endPoit">Point end line</param>
        /// <param name="speed">speed on line</param>
        /// <returns>Storyboard</returns>
        private Storyboard CreatPathAnimation(Point startPoint, Point endPoit, double speed)
        {
            PathGeometry animationPath = new PathGeometry();
            PathFigure pFigure = new PathFigure();
            pFigure.StartPoint = startPoint; //new Point(50, 65);
            LineSegment lineSegment = new LineSegment();
            lineSegment.Point = endPoit; // new Point(800, 65);
            pFigure.Segments.Add(lineSegment);
            animationPath.Figures.Add(pFigure);

            // Freeze the PathGeometry for performance benefits.
            animationPath.Freeze();

            // Create a MatrixAnimationUsingPath to move the
            // simulation along the path by animating
            // its MatrixTransform.
            MatrixAnimationUsingPath matrixAnimation = new MatrixAnimationUsingPath();
            matrixAnimation.PathGeometry = animationPath;
            matrixAnimation.SpeedRatio = speed;
            matrixAnimation.AutoReverse = false;
            matrixAnimation.DoesRotateWithTangent = true;
            matrixAnimation.Completed += delegate { AnimationCompleted(this._isGoal); };

            // Set the animation to target the Matrix property
            // of the MatrixTransform named "ButtonMatrixTransform".
            Storyboard.SetTargetName(matrixAnimation, "fl");
            Storyboard.SetTargetProperty(matrixAnimation, new PropertyPath(MatrixTransform.MatrixProperty));

            // Create a Storyboard to contain and apply the animation.
            Storyboard pathAnimationStoryboard = new Storyboard();
            pathAnimationStoryboard.Children.Add(matrixAnimation);

            return pathAnimationStoryboard;
        }

        /// <summary>
        /// Process when simulation is end line
        /// </summary>
        /// <param name="isGoal">check is node end</param>
        private void AnimationCompleted(bool isGoal)
        {
            // If not end node
            if (!isGoal)
            {
                this.index += 1;
                this.Children.Remove(simulation);
                this.startPoint = endPoint;
                this.endPoint = new Point(Canvas.GetLeft(_lstNode[index]) + RADIUS_NODE, COOR_Y);
                
                if (this.index == this._lstNode.Count - 1)
                {
                    this._isGoal = true;
                }
                this._speed += 0.2;
                RoboSimulation();
                return;
            }

            // Reset data when finish
            this.index = 0;
            this._speed = 0.2;
            this._isGoal = false;
        }
    }
}