#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 System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using Ingenious.Mvc;
using Ingenious.Mvc.Configuration;
using Ingenious.Mvc.Configuration.Configurators;
using Ingenious.Mvc.Util;
using Ingenious.Mvc.ViewManagers;
using Ingenious.Mvc.Windows.Forms.Views;
namespace Ingenious.Mvc.Windows.Forms.ViewManagers{
/// <include file='UserControlsViewManager.doc.xml' path='/doc/member[@name="T:UserControlsViewManager"]/*'/>
[Serializable]
[XmlCustomParser(typeof(UserControlsViewManagerXmlCustomParser))]
public class UserControlsViewManager : ViewManagerBase, ICustomConfigurable
{
private IDictionary<Task, TaskInfo> _tasks;
private object _tasksLock;
private string _containerName;
private static readonly Log _log = Log.CreateForType(typeof(UserControlsViewManager));
/// <include file='UserControlsViewManager.doc.xml' path='/doc/member[@name="P:ContainerName"]/*'/>
public string ContainerName
{
get
{
return _containerName;
}
set
{
_containerName = value;
}
}
/// <include file='UserControlsViewManager.doc.xml' path='/doc/member[@name="E:ViewCreated"]/*'/>
[field: NonSerialized]
public event EventHandler<ViewEventArgs> ViewCreated;
/// <include file='UserControlsViewManager.doc.xml' path='/doc/member[@name="E:ViewDisplaying"]/*'/>
[field: NonSerialized]
public event EventHandler<ViewEventArgs> ViewDisplaying;
/// <include file='UserControlsViewManager.doc.xml' path='/doc/member[@name="E:ViewDisplayed"]/*'/>
[field: NonSerialized]
public event EventHandler<ViewEventArgs> ViewDisplayed;
/// <include file='UserControlsViewManager.doc.xml' path='/doc/member[@name="E:ViewClosed"]/*'/>
[field: NonSerialized]
public event EventHandler<ViewEventArgs> ViewClosed;
/// <include file='UserControlsViewManager.doc.xml' path='/doc/member[@name="M:.ctor(Ingenious.Mvc.Id`1,Ingenious.Mvc.TaskManager)"]/*'/>
public UserControlsViewManager(Id<IViewManager> id, TaskManager taskManager) : base(id, taskManager)
{
_tasks = new Dictionary<Task, TaskInfo>();
_tasksLock = new object();
_log.Verbose("Constructed UserControlsViewManager with ID '{0}'.", id);
}
/// <include file='UserControlsViewManager.doc.xml' path='/doc/member[@name="M:Activate(Ingenious.Mvc.Task,Ingenious.Mvc.Id`1,System.Object)"]/*'/>
public override IView Activate(Task task, Id<IView> viewId, object viewData)
{
ArgumentHelper.AssertNotNull(task, "task");
ArgumentHelper.AssertNotEmpty(viewId, "viewId");
_log.Verbose("Activating view with ID '{0}' for task with ID '{1}'.", viewId, task.Id);
IUserControlContainer container = GetUserControlContainer(task);
//if we still don't have a container then throw
ExceptionHelper.ThrowIf(container == null, "Activate.containerNotFound", task.Id, Id);
//create the view only once per task
bool viewCreated = false;
IView view = GetViewInTask(task, viewId);
if (view == null)
{
_log.Verbose("Creating view.");
view = CreateView(task, viewId);
viewCreated = true;
}
//the view type must implement IUserControlView, not just IView
ExceptionHelper.ThrowIf(!(view is IUserControlView), "Activate.viewTypeDoesntImplementInterface", viewId, view.GetType().FullName, typeof(IUserControlView).FullName);
ExceptionHelper.ThrowIf(view.Task != task, "Activate.viewTaskNotSet", viewId, task.Id);
IUserControlView userControlView = (IUserControlView) view;
if (viewCreated)
{
//raise the ViewCreated event
OnViewCreated(userControlView);
//store the view in a list of views for the relevant task
AddViewToTask(userControlView);
}
//pass any data to the view
userControlView.SetData(viewData);
//raise the ViewDisplaying event
OnViewDisplaying(userControlView);
//deactivate the old view, if any
if (ActiveView != null)
{
((IUserControlView) ActiveView).Deactivate();
OnViewDeactivated(ActiveView);
}
_log.Verbose("Assigning view to container.");
//ask the container to show the user control
container.SetUserControl(_containerName, userControlView);
//it is now the active view
userControlView.Activate();
OnViewActivated(userControlView);
//raise the ViewDisplayed event
OnViewDisplayed(userControlView);
//return the displayed view
return userControlView;
}
/// <include file='UserControlsViewManager.doc.xml' path='/doc/member[@name="M:GetUserControlContainer(Ingenious.Mvc.Task)"]/*'/>
protected virtual IUserControlContainer GetUserControlContainer(Task task)
{
IUserControlContainer retVal = null;
Debug.Assert(task != null);
lock (_tasksLock)
{
TaskInfo taskInfo;
if (!_tasks.TryGetValue(task, out taskInfo))
{
taskInfo = new TaskInfo();
_tasks[task] = taskInfo;
}
retVal = taskInfo.Container;
if (retVal == null)
{
ExceptionHelper.ThrowIf(_containerName == null, "FindUserControlContainer.containerNameNotSpecified", Id);
//we need the owner task in order to find the container control
ExceptionHelper.ThrowIf(task.Owner == null, "FindUserControlContainer.taskHasNoOwner", Id, _containerName);
IViewManager ownerViewManager = TaskManager.GetViewManagerForTask(task.Owner);
//this should never happen but we'll check anyway
ExceptionHelper.ThrowIf(ownerViewManager == null, "FindUserControlContainer.viewManagerForOwnerTaskNotFound", Id, task.Owner.Id);
IView activeView = ownerViewManager.ActiveView;
//we need the active view from the owning view manager
ExceptionHelper.ThrowIf(activeView == null, "FindUserControlContainer.activeViewNotFound", Id, ownerViewManager.Id);
//the view must implement IUserControlContainer in order for us to manipulate the user controls
ExceptionHelper.ThrowIf(!typeof(IUserControlContainer).IsAssignableFrom(activeView.GetType()), "FindUserControlContainer.activeViewDoesNotImplementInterface", Id, ownerViewManager.Id, activeView.Id, typeof(IUserControlContainer).FullName);
//we've found our user control container
retVal = (IUserControlContainer) activeView;
taskInfo.Container = retVal;
}
}
return retVal;
}
private void AddViewToTask(IUserControlView view)
{
_log.Verbose("Adding view with ID '{0}' to current task.", view.Id);
lock (_tasksLock)
{
TaskInfo taskInfo;
if (!_tasks.TryGetValue(view.Task, out taskInfo))
{
taskInfo = new TaskInfo();
_tasks[view.Task] = taskInfo;
}
//add the view to the list of views for the task
taskInfo.Views.Add(view);
//make sure we handle the various events raised by the view
view.Activated += new EventHandler<EventArgs>(view_Activated);
view.Deactivated += new EventHandler<EventArgs>(view_Deactivated);
view.Closed += new EventHandler<EventArgs>(view_Closed);
}
}
private IUserControlView GetViewInTask(Task task, Id<IView> viewId)
{
lock (_tasksLock)
{
if (_tasks.ContainsKey(task))
{
TaskInfo taskInfo = (TaskInfo) _tasks[task];
foreach (IUserControlView view in taskInfo.Views)
{
if (view.Id == viewId)
{
return view;
}
}
}
return null;
}
}
private void RemoveViewFromTask(IUserControlView view)
{
_log.Verbose("Removing view with ID '{0}' from current task.", view.Id);
lock (_tasksLock)
{
Debug.Assert(_tasks.ContainsKey(view.Task));
TaskInfo taskInfo = (TaskInfo) _tasks[view.Task];
Debug.Assert(taskInfo.Views.Contains(view));
//remove the view from the list of views for the task
taskInfo.Views.Remove(view);
//detach from handling the closed event
view.Closed -= new EventHandler<EventArgs>(view_Closed);
//end the task if there are no more views open for it
if (taskInfo.Views.Count == 0)
{
view.Task.End();
}
}
}
private void SetActiveView(IUserControlView view)
{
Debug.Assert(view != null);
lock (_tasksLock)
{
Debug.Assert(_tasks.ContainsKey(view.Task));
TaskInfo taskInfo = (TaskInfo) _tasks[view.Task];
Debug.Assert(taskInfo.Views.Contains(view));
//now set the active view
taskInfo.ActiveView = view;
}
}
/// <include file='UserControlsViewManager.doc.xml' path='/doc/member[@name="M:GetActiveView(Ingenious.Mvc.Task)"]/*'/>
public IUserControlView GetActiveView(Task task)
{
ArgumentHelper.AssertNotNull(task, "task");
lock (_tasksLock)
{
ExceptionHelper.ThrowIf(!_tasks.ContainsKey(task), "GetActiveView.taskNotFound", task.Id, Id);
return _tasks[task].ActiveView;
}
}
/// <include file='UserControlsViewManager.doc.xml' path='/doc/member[@name="M:OnViewCreated(Ingenious.Mvc.Windows.Forms.Views.IUserControlView)"]/*'/>
protected virtual void OnViewCreated(IUserControlView view)
{
EventHelper.Raise(ViewCreated, this, new ViewEventArgs(view));
}
/// <include file='UserControlsViewManager.doc.xml' path='/doc/member[@name="M:OnViewDisplaying(Ingenious.Mvc.Windows.Forms.Views.IUserControlView)"]/*'/>
protected virtual void OnViewDisplaying(IUserControlView view)
{
EventHelper.Raise(ViewDisplaying, this, new ViewEventArgs(view));
}
/// <include file='UserControlsViewManager.doc.xml' path='/doc/member[@name="M:OnViewDisplayed(Ingenious.Mvc.Windows.Forms.Views.IUserControlView)"]/*'/>
protected virtual void OnViewDisplayed(IUserControlView view)
{
EventHelper.Raise(ViewDisplayed, this, new ViewEventArgs(view));
}
/// <include file='UserControlsViewManager.doc.xml' path='/doc/member[@name="M:OnViewClosed(Ingenious.Mvc.Windows.Forms.Views.IUserControlView)"]/*'/>
protected virtual void OnViewClosed(IUserControlView view)
{
EventHelper.Raise(ViewClosed, this, new ViewEventArgs(view));
}
/// <include file='UserControlsViewManager.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);
_containerName = customConfig.ContainerName;
}
private void view_Activated(object sender, EventArgs e)
{
IUserControlView userControlView = (IUserControlView) sender;
//remember the active view for each task
SetActiveView(userControlView);
//raise the ViewActivated event
OnViewActivated(userControlView);
}
private void view_Deactivated(object sender, EventArgs e)
{
IUserControlView userControlView = (IUserControlView) sender;
//raise the ViewDeactivated event
OnViewDeactivated(userControlView);
}
private void view_Closed(object sender, EventArgs e)
{
IUserControlView userControlView = (IUserControlView) sender;
//the view has been closed so remove it from the list of views for the related task
RemoveViewFromTask(userControlView);
//raise the ViewClosed event
OnViewClosed(userControlView);
}
/// <include file='UserControlsViewManager.doc.xml' path='/doc/member[@name="T:UserControlsViewManager+CustomConfiguration"]/*'/>
[Serializable]
public sealed class CustomConfiguration
{
private string _containerName;
/// <include file='UserControlsViewManager.doc.xml' path='/doc/member[@name="P:CustomConfiguration.ContainerName"]/*'/>
public string ContainerName
{
get
{
return _containerName;
}
set
{
_containerName = value;
}
}
}
[Serializable]
private sealed class TaskInfo
{
[field: NonSerialized]
private IUserControlContainer _container;
[field: NonSerialized]
private IUserControlView _activeView;
[field: NonSerialized]
private IList<IUserControlView> _views;
public IUserControlContainer Container
{
get
{
return _container;
}
set
{
_container = value;
}
}
public IUserControlView ActiveView
{
get
{
return _activeView;
}
set
{
_activeView = value;
}
}
public IList<IUserControlView> Views
{
get
{
return _views;
}
}
public TaskInfo()
{
_views = new List<IUserControlView>();
}
}
}
}
|