using System;
using System.ComponentModel;
namespace Chernobyl.ComponentModel
{
///
/// A default implementation of the interface. This
/// class is intended to make the creation of s easier.
/// You should never use this class as part of your interface (like as an
/// argument to a method) as not all instances will
/// derive from this class.
///
public abstract class Task : ITask
{
///
/// Initializes a new instance of the class.
///
protected Task() : this(0)
{}
///
/// Initializes a new instance of the class.
///
/// The percentage of work, from 0% to
/// 100%, that has been completed on this task.
protected Task(int progressPercentage)
{
ProgressPercentage = progressPercentage;
}
///
/// Cancels the work being done but only if it has not been canceled
/// already and the has not
/// reached 100%. If cancellation is successful, the
/// event will be raised. Note that, when the work being done is on
/// another thread, it is possible that the work will finish just as
/// this method is invoked.
///
public void Cancel()
{
if (IsCanceled == false && ProgressPercentage != 100)
{
IsCanceled = true;
ProgressPercentage = 0;
if(Canceled != null)
Canceled(this, EventArgs.Empty);
}
}
///
/// True if the task has been canceled, false if otherwise.
///
public bool IsCanceled { get; private set; }
///
/// The percentage of work, from 0% to 100%, that has been completed on
/// this task. Note that setting this property will cause the
/// event to be raised if the amount of
/// change between the new value and the old value is not equal to zero.
/// If the task is Canceled (i.e. is invoked) the
/// value of this property will be set to zero by this .
///
/// Thrown if the new
/// is less than 0% or if the
/// is over 100%.
public int ProgressPercentage
{
get { return _progressPercentage; }
protected set
{
if (value < 0)
throw new ArgumentOutOfRangeException("value",
"You must provide a positive value for the amount " +
"of progress made.");
if (value > 100)
throw new ArgumentOutOfRangeException("value",
"The ITask.ProgressPercentage cannot be over 100%.");
int changeAmount = value - _progressPercentage;
_progressPercentage = value;
if(changeAmount != 0 && ProgressChanged != null)
ProgressChanged(this, new ProgressChangedEventArgs(ProgressPercentage, null));
}
}
///
/// An event that is raised when the is invoked
/// on this instance. Note that this event is only raised once,
/// regardless of how many times is invoked. This
/// event will not be invoked if the
/// is at 100%.
///
public event EventHandler Canceled;
///
/// An event that is raised when the progress of the task has changed.
///
public event ProgressChangedEventHandler ProgressChanged;
///
/// An implementation of the interface that
/// represents a minor task that is completed immediately.
///
public static readonly ITask Simple = new SimpleTask();
///
/// Checks if the event has subscribers.
///
/// True if the has subscribers,
/// false if otherwise.
protected bool ProgressChangedHasSubscribers()
{
return ProgressChanged != null;
}
///
/// Raises the event. Note that this
/// method does not check if has subscribers
/// so you must invoke to find
/// out before invoking this method.
///
/// The instance
/// containing the event data.
protected void RaiseProgressChanged(ProgressChangedEventArgs e)
{
ProgressChanged(this, e);
}
///
/// Checks if the event has subscribers.
///
/// True if the has subscribers, false
/// if otherwise.
protected bool CanceledHasSubscribers()
{
return Canceled != null;
}
///
/// Raises the event. Note that this
/// method does not check if has subscribers
/// so you must invoke to find
/// out before invoking this method.
///
/// The instance containing the
/// event data.
protected void RaiseCanceled(EventArgs e)
{
Canceled(this, e);
}
///
/// The backing field to .
///
int _progressPercentage;
}
///
/// A type that is used for the field. This type
/// represents a minor task that is completed immediately.
///
class SimpleTask : Task
{
///
/// Prevents a default instance of the class
/// from being created.
///
public SimpleTask() : base(100)
{ }
}
}