private static TimeSpan GetTimeToFinished(Timeline timeline)
 {
     if (timeline.Duration.HasTimeSpan)
     {
         var beginTime = timeline.BeginTime ?? TimeSpan.Zero;
         return beginTime + timeline.Duration.TimeSpan;
     }
     var storyboard = timeline as Storyboard;
     if (storyboard != null)
     {
         if (storyboard.Children.Count == 0)
         {
             return TimeSpan.Zero;
         }
         return storyboard.Children.Max(x => GetTimeToFinished(x));
     }
     throw new NotImplementedException(string.Format("GetTimeToFinished not implemented for: {0}", timeline.GetType().FullName));
 }
        internal static Clock AllocateClock(
            Timeline timeline,
            bool hasControllableRoot)
        {
            Clock clock = timeline.AllocateClock();

            // Assert that we weren't given an existing clock
            Debug.Assert(!clock.IsTimeManager);

            ClockGroup clockGroup = clock as ClockGroup;

            if (   clock._parent != null
                || (   clockGroup != null
                    && clockGroup.InternalChildren != null ))
            {
                // The derived class is trying to fool us -- we require a new,
                // fresh, unassociated clock here
                throw new InvalidOperationException(
                    SR.Get(
                        SRID.Timing_CreateClockMustReturnNewClock,
                        timeline.GetType().Name));
            }

            clock.SetFlag(ClockFlags.HasControllableRoot, hasControllableRoot);

            return clock;
        }
        private static CodeExpression GenerateTimeline(CodeMemberMethod method, string baseName, Timeline timeline)
        {
            string timelineTypeName = timeline.GetType().Name;
            if (timelineTypeName == "DoubleAnimation")
            {
                // TODO check this later, all double values in WPF are float in EK UI, so that's why this is needed
                timelineTypeName = "FloatAnimation";
            }

            var timelineVar = new CodeVariableDeclarationStatement(timelineTypeName, baseName, new CodeObjectCreateExpression(timelineTypeName));
            method.Statements.Add(timelineVar);

            var timelineVarRef = new CodeVariableReferenceExpression(baseName);

            var nameAssign = new CodeAssignStatement(new CodeFieldReferenceExpression(timelineVarRef, "Name"), new CodePrimitiveExpression(baseName));
            method.Statements.Add(nameAssign);

            CodeComHelper.GenerateField<bool>(method, timelineVarRef, timeline, Timeline.AutoReverseProperty);

            if (timeline.Duration != Duration.Automatic)
            {
                if (timeline.Duration == Duration.Forever)
                {
                    CodeSnippetStatement error = new CodeSnippetStatement("#error Duration can not be Duration.Forever value");
                    method.Statements.Add(error);
                    return null;
                }

                var durationTimeSpan = new CodeObjectCreateExpression("TimeSpan",
                    new CodePrimitiveExpression(timeline.Duration.TimeSpan.Days),
                    new CodePrimitiveExpression(timeline.Duration.TimeSpan.Hours),
                    new CodePrimitiveExpression(timeline.Duration.TimeSpan.Minutes),
                    new CodePrimitiveExpression(timeline.Duration.TimeSpan.Seconds),
                    new CodePrimitiveExpression(timeline.Duration.TimeSpan.Milliseconds));

                CodeExpression durationValue = new CodeObjectCreateExpression("Duration", durationTimeSpan);
                var durationAssign = new CodeAssignStatement(new CodeFieldReferenceExpression(timelineVarRef, "Duration"), durationValue);
                method.Statements.Add(durationAssign);
            }

            if (!(timeline.RepeatBehavior.HasCount && timeline.RepeatBehavior.Count == 1))
            {
                CodeExpression repeatValue = null;
                if (timeline.RepeatBehavior == RepeatBehavior.Forever)
                {
                    repeatValue = new CodeFieldReferenceExpression(new CodeTypeReferenceExpression("RepeatBehavior"), "Forever");
                }
                else if (timeline.RepeatBehavior.HasCount)
                {
                    repeatValue = new CodeObjectCreateExpression("RepeatBehavior", new CodePrimitiveExpression((float)timeline.RepeatBehavior.Count));
                }
                else
                {
                    var repeatTimeSpan = new CodeObjectCreateExpression("TimeSpan",
                        new CodePrimitiveExpression(timeline.RepeatBehavior.Duration.Days),
                        new CodePrimitiveExpression(timeline.RepeatBehavior.Duration.Hours),
                        new CodePrimitiveExpression(timeline.RepeatBehavior.Duration.Minutes),
                        new CodePrimitiveExpression(timeline.RepeatBehavior.Duration.Seconds),
                        new CodePrimitiveExpression(timeline.RepeatBehavior.Duration.Milliseconds));
                    repeatValue = new CodeObjectCreateExpression("RepeatBehavior", repeatTimeSpan);
                }

                var repeatAssign = new CodeAssignStatement(new CodeFieldReferenceExpression(timelineVarRef, "RepeatBehavior"), repeatValue);
                method.Statements.Add(repeatAssign);
            }


            return timelineVarRef;
        }