#region License
/**
* Ingenious MVC : An MVC framework for .NET 2.0
* Copyright (C) 2006, JDP Group
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Authors: - Kent Boogaart (kentcb@internode.on.net)
*/
#endregion
using System;
using Ingenious.Mvc;
using Ingenious.Mvc.Configuration;
using Ingenious.Mvc.Configuration.Configurators;
using Ingenious.Mvc.Util;
namespace Ingenious.Mvc.Navigators{
/// <include file='WizardNavigator.doc.xml' path='/doc/member[@name="T:WizardNavigator"]/*'/>
[Serializable]
[XmlCustomParser(typeof(WizardNavigatorXmlCustomParser))]
public class WizardNavigator : GraphNavigator, ICustomConfigurable
{
private readonly IdCollection<Id<IView>> _viewIds;
private bool _aliasesNeedUpdating;
private static readonly Log _log = Log.CreateForType(typeof(WizardNavigator));
/// <include file='WizardNavigator.doc.xml' path='/doc/member[@name="F:NextViewAliasId"]/*'/>
public static readonly Id<IView> NextViewAliasId = "__next__";
/// <include file='WizardNavigator.doc.xml' path='/doc/member[@name="F:PreviousViewAliasId"]/*'/>
public static readonly Id<IView> PreviousViewAliasId = "__previous__";
/// <include file='WizardNavigator.doc.xml' path='/doc/member[@name="P:ViewIds"]/*'/>
public IdCollection<Id<IView>> ViewIds
{
get
{
return _viewIds;
}
}
/// <include file='WizardNavigator.doc.xml' path='/doc/member[@name="M:.ctor(Ingenious.Mvc.Id`1,Ingenious.Mvc.Task,Ingenious.Mvc.Id`1,Ingenious.Mvc.IViewManager)"]/*'/>
public WizardNavigator(Id<INavigator> id, Task task, Id<IView> startingViewId, IViewManager viewManager) : base(id, task, startingViewId, viewManager)
{
_viewIds = new IdCollection<Id<IView>>();
//listen for any changes to the views in the wizard so we can update aliases
_viewIds.IdAdded += new EventHandler<IdEventArgs<Id<IView>>>(_viewIds_ViewIdAddedRemoved);
_viewIds.IdRemoved += new EventHandler<IdEventArgs<Id<IView>>>(_viewIds_ViewIdAddedRemoved);
_log.Verbose("Constructed WizardNavigator with ID '{0}' for task with ID '{1}'.", id, task.Id);
}
/// <include file='WizardNavigator.doc.xml' path='/doc/member[@name="M:NavigateToNext()"]/*'/>
public void NavigateToNext()
{
NavigateTo(NextViewAliasId);
}
/// <include file='WizardNavigator.doc.xml' path='/doc/member[@name="M:NavigateToPrevious()"]/*'/>
public void NavigateToPrevious()
{
NavigateTo(PreviousViewAliasId);
}
/// <include file='WizardNavigator.doc.xml' path='/doc/member[@name="M:AddAlias(Ingenious.Mvc.Id`1,Ingenious.Mvc.Id`1,Ingenious.Mvc.Id`1)"]/*'/>
public override void AddAlias(Id<IView> fromView, Id<IView> toView, Id<IView> viewAliasId)
{
//here we are simply ensuring that the from and to views are defined in our collection of views
ExceptionHelper.ThrowIf(!_viewIds.Contains(fromView), "AddAlias.fromViewNotFound", Id, fromView);
ExceptionHelper.ThrowIf(!_viewIds.Contains(toView), "AddAlias.toViewNotFound", Id, toView);
//now just use the base class to add the alias
base.AddAlias(fromView, toView, viewAliasId);
}
/// <include file='WizardNavigator.doc.xml' path='/doc/member[@name="M:AssertNavigateToValid(Ingenious.Mvc.Id`1)"]/*'/>
protected override bool AssertNavigateToValid(ref Id<IView> viewOrAliasId, bool throwOnError)
{
//make sure that any next / previous request is valid (gives a more specific exception message than base class can)
if (viewOrAliasId == PreviousViewAliasId)
{
if (base.GetViewForAlias(PreviousViewAliasId).IsEmpty)
{
_log.Error("Cannot navigate to previous view because none is configured for the current view with ID '{0}'.", ViewManager.ActiveView.Id);
if (throwOnError)
{
ExceptionHelper.Throw("AssertNavigateToValid.noPreviousView", new object[] {ViewManager.ActiveView, viewOrAliasId}, Id, LastNavigateTo);
}
else
{
return false;
}
}
}
else if (viewOrAliasId == NextViewAliasId)
{
_log.Error("Cannot navigate to next view because none is configured for the current view with ID '{0}'.", ViewManager.ActiveView.Id);
if (base.GetViewForAlias(NextViewAliasId).IsEmpty)
{
if (throwOnError)
{
ExceptionHelper.Throw("AssertNavigateToValid.noNextView", new object[] {ViewManager.ActiveView, viewOrAliasId}, Id, LastNavigateTo);
}
else
{
return false;
}
}
}
return base.AssertNavigateToValid(ref viewOrAliasId, throwOnError);
}
/// <include file='WizardNavigator.doc.xml' path='/doc/member[@name="M:BeforeNavigateTo(Ingenious.Mvc.Id`1,System.Object)"]/*'/>
protected override void BeforeNavigateTo(Id<IView> targetViewOrAliasId, object viewData)
{
base.BeforeNavigateTo(targetViewOrAliasId, viewData);
//check if we need to update the aliases
if (_aliasesNeedUpdating)
{
for (int i = 0; i < _viewIds.Count; ++i)
{
Id<IView> viewId = _viewIds[i];
//remove any old aliases
base.RemoveAlias(viewId, PreviousViewAliasId);
base.RemoveAlias(viewId, NextViewAliasId);
//add a previous alias if relevant
if (i > 0)
{
base.AddAlias(viewId, _viewIds[i - 1], PreviousViewAliasId);
}
//add a next alias if relevant
if (i <= (_viewIds.Count - 2))
{
base.AddAlias(viewId, _viewIds[i + 1], NextViewAliasId);
}
}
_aliasesNeedUpdating = false;
}
}
/// <include file='WizardNavigator.doc.xml' path='/doc/member[@name="M:Ingenious.Mvc.Configuration.ICustomConfigurable.SetCustomConfiguration(System.Object)"]/*'/>
void ICustomConfigurable.SetCustomConfiguration(object customConfiguration)
{
ArgumentHelper.AssertNotNull(customConfiguration, "customConfiguration");
CustomConfiguration customConfig = customConfiguration as CustomConfiguration;
ExceptionHelper.ThrowIf(customConfig == null, "SetCustomConfiguration.incorrectType", typeof(CustomConfiguration).FullName, customConfiguration.GetType().FullName);
_viewIds.Clear();
_viewIds.AddRange(customConfig.ViewIds);
//TODO: couldn't find a way to do base.SetCustomConfiguration so resorted to a protected method to achieve the same thing
base.ApplyCustomConfiguration(customConfig.Aliases);
}
private void _viewIds_ViewIdAddedRemoved(object sender, IdEventArgs<Id<IView>> e)
{
//if the view IDs collection is modified, we have to make sure we update aliases prior to navigating
_aliasesNeedUpdating = true;
}
/// <include file='WizardNavigator.doc.xml' path='/doc/member[@name="T:WizardNavigator+CustomConfiguration"]/*'/>
[Serializable]
public new sealed class CustomConfiguration
{
private IdCollection<Id<IView>> _viewIds;
private GraphNavigator.CustomConfiguration _aliases;
/// <include file='WizardNavigator.doc.xml' path='/doc/member[@name="P:CustomConfiguration.ViewIds"]/*'/>
public IdCollection<Id<IView>> ViewIds
{
get
{
return _viewIds;
}
}
/// <include file='WizardNavigator.doc.xml' path='/doc/member[@name="P:CustomConfiguration.Aliases"]/*'/>
public GraphNavigator.CustomConfiguration Aliases
{
get
{
return _aliases;
}
}
/// <include file='WizardNavigator.doc.xml' path='/doc/member[@name="M:CustomConfiguration.ctor()"]/*'/>
public CustomConfiguration()
{
_viewIds = new IdCollection<Id<IView>>();
_aliases = new GraphNavigator.CustomConfiguration();
}
}
}
}
|