/// <summary> /// Indicates whether a navigation would be valid if it were to be performed. /// </summary> /// <param name="command">The navigation command to test.</param> /// <param name="activity">The destination activity, if this is a choice navigation.</param> /// <returns>True if the navigation would be valid, false otherwise.</returns> /// <remarks> /// <para> /// This makes a partial copy of the activity tree for processing and attempts to /// perform a navigation on that copy. This may result in poor performance if this /// is called many times, but the alternative is to duplicate most of the sequencing /// code with lots of special cases for changes of state that should have happened but /// could not because of the temporary nature of this request. This makes it a /// maintenance nightmare, for something that should only rarely be called anyway /// except in the case of <Mth>LoadTableOfContents</Mth>. /// </para> /// <para> /// The case of <Mth>LoadTableOfContents</Mth> is tough, but steps are taken within /// that method to reduce the number of calls to this method to a bare minimum. /// </para> /// </remarks> protected bool IsNavigationValid(NavigationCommand command, Activity activity) { SeqNav seqNav; try { NavigatorData clone = CloneForNavigationTest(); Activity destination; if (activity != null) { destination = clone.Activities[activity.ActivityId]; } else { destination = null; } if (m_packageFormat == PackageFormat.V1p3) { seqNav = new Scorm2004SeqNav(clone); } else { seqNav = new Scorm12SeqNav(clone); } seqNav.OverallSequencingProcess(command, destination); } catch (SequencingException) { // if there was a sequencing exception, // this is a failure condition. return(false); } return(true); }
/// <summary> /// Produces an incomplete clone sufficient for testing sequencing and navigation. /// </summary> /// <returns>A new object with enough data cloned to be viable for sequencing and navigation.</returns> public virtual NavigatorData CloneForNavigationTest() { NavigatorData clone = new NavigatorData(); clone.RootActivity = m_activityTree.Root.CloneForNavigationTest(); clone.Activities.Add(clone.RootActivity.ActivityId, clone.RootActivity); if (CurrentActivity == RootActivity) { clone.CurrentActivity = clone.RootActivity; } if (SuspendedActivity == RootActivity) { clone.SuspendedActivity = clone.RootActivity; } CloneChildren(clone, clone.RootActivity, m_activityTree.Root); clone.SortActivityTree(); return(clone); }
/// <summary> /// Recursively clones children of the specified activity and inserts them into the clone tree. /// </summary> /// <param name="navigator">The cloned navigator data object.</param> /// <param name="cloneParent">The cloned parent to add the children to.</param> /// <param name="originalParent">The original parent to clone the children from.</param> protected void CloneChildren(NavigatorData navigator, Activity cloneParent, Activity originalParent) { foreach (Activity child in originalParent.Children) { Activity clone = child.CloneForNavigationTest(); cloneParent.AddChild(clone); clone.Parent = cloneParent; if (CurrentActivity == child) { navigator.CurrentActivity = clone; } if (SuspendedActivity == child) { navigator.SuspendedActivity = clone; } navigator.Activities.Add(clone.ActivityId, clone); CloneChildren(navigator, clone, child); } }
/// <summary> /// Initializes the class that performs sequencing/navigation using SCORM 2004 sequencing/navigation rules. /// </summary> /// <param name="navigator">The <Typ>Navigator</Typ> performing the sequencing operation.</param> public Scorm2004SeqNav(NavigatorData navigator) : base(navigator) { }
/// <summary> /// Initializes the class that performs sequencing/navigation. /// </summary> /// <param name="navigator">The <Typ>Navigator</Typ> performing the sequencing operation.</param> public SeqNav(NavigatorData navigator) { m_navigator = navigator; }
/// <summary> /// Initializes the class that performs sequencing/navigation using SCORM 1.2004 sequencing/navigation rules. /// </summary> /// <param name="navigator">The <Typ>Navigator</Typ> performing the sequencing operation.</param> public Scorm12SeqNav(NavigatorData navigator) : base(navigator) { }
/// <summary> /// Produces an incomplete clone sufficient for testing sequencing and navigation. /// </summary> /// <returns>A new object with enough data cloned to be viable for sequencing and navigation.</returns> public virtual NavigatorData CloneForNavigationTest() { NavigatorData clone = new NavigatorData(); clone.RootActivity = m_activityTree.Root.CloneForNavigationTest(); clone.Activities.Add(clone.RootActivity.ActivityId, clone.RootActivity); if(CurrentActivity == RootActivity) { clone.CurrentActivity = clone.RootActivity; } if(SuspendedActivity == RootActivity) { clone.SuspendedActivity = clone.RootActivity; } CloneChildren(clone, clone.RootActivity, m_activityTree.Root); clone.SortActivityTree(); return clone; }
/// <summary> /// Recursively clones children of the specified activity and inserts them into the clone tree. /// </summary> /// <param name="navigator">The cloned navigator data object.</param> /// <param name="cloneParent">The cloned parent to add the children to.</param> /// <param name="originalParent">The original parent to clone the children from.</param> protected void CloneChildren(NavigatorData navigator, Activity cloneParent, Activity originalParent) { foreach(Activity child in originalParent.Children) { Activity clone = child.CloneForNavigationTest(); cloneParent.AddChild(clone); clone.Parent = cloneParent; if(CurrentActivity == child) { navigator.CurrentActivity = clone; } if(SuspendedActivity == child) { navigator.SuspendedActivity = clone; } navigator.Activities.Add(clone.ActivityId, clone); CloneChildren(navigator, clone, child); } }