/*
i-net software provides programming examples for illustration only, without warranty
either expressed or implied, including, but not limited to, the implied warranties
of merchantability and/or fitness for a particular purpose. This programming example
assumes that you are familiar with the programming language being demonstrated and
the tools used to create and debug procedures. i-net software support professionals
can help explain the functionality of a particular procedure, but they will not modify
these examples to provide added functionality or construct procedures to meet your
specific needs.
© i-net software 1998-2013
*/
using System;
using System.Threading;
namespace Inet.Viewer.Data
{
///
///
///
public enum ProgressMode
{
///
/// TotalProgress is unknown, so is just showing that it works
///
Continuous = 0,
///
/// TotalProgress is known, so progressing through the steps
///
Steps = 1
}
///
/// Class for all progresses, which should be handled as a Progress of the report viewer. A progress
/// encapsulates a special task with a state (such as idle, running or complete) and a value
/// (23 of 120) of its progress. To start the progress call the method and
/// the progress will perform its run method. In this method call , ,
/// to propagate the status of the progress.
/// The progress will be registered at the ProgressPool and will inform its listeners
/// about property changes such as its status, current step and total steps.
/// Depending on the progress type the progress will be displayed at the StatusBar
/// or not.
///
public abstract class Progress
{
///
/// The type is print Progress, which means the progress will be shown as printing progress in
/// the status bar
///
public enum ProgressType
{
///
/// The type is navigation Progress, which means the progress will be shown as navigation progress in
/// the status bar
///
PageLoader = 0,
///
/// The type is print Progress, which means the progress will be shown as printing progress in
/// the status bar
///
Print = 1,
///
/// The type is export Progress, which means the progress will be shown as export progress in
/// the status bar
/// @since 7.0
///
Export = 2,
///
/// The type is search Progress, which means the progress will be shown as search progress in
/// the status bar
///
Search = 3,
///
/// The type is invisible, do not show this progress in the status bar
///
Invisible = 4
}
///
/// The different possible status for the Progress
///
public enum ProgressStatus
{
///
/// The progress has not been created yet
///
NotInitialized = -1,
///
/// The progress has been created but has not been started yet
///
Initialized = 0,
///
/// The progress is running
///
Running = 1,
///
/// The progress was successfully completed
///
Completed = 2,
///
/// The progress was canceled
///
Canceled = 3,
///
/// The progress was canceled due to an error
///
Error = 4,
///
/// The progress idles
///
Idle = 5
}
///
/// Event when the ProgressCount or ProgressTotal changed
///
public event EventHandler ProgressChanged;
///
/// Event when the status (ProgressStatus of the Progress changed
///
public event EventHandler StatusChanged;
///
/// The property ProgressStatus for PropertyChangeEvents
///
public const string PropProgressStatus = "ProgressStatus";
///
/// The property ProgressTotal for PropertyChangeEvents
///
public const string PropProgressTotal = "ProgressTotal";
///
/// The property ProgressStep for PropertyChangeEvents
///
public const string PropProgressStep = "ProgressStep";
///
/// The property ProgressIndeterminate for PropertyChangeEvents
///
public const string PropProgressIndeterminate = "ProgressIndeterminate";
///
/// the status of the progress
private ProgressStatus status = ProgressStatus.NotInitialized;
///
/// the type of the progress
private ProgressType type;
///
/// the total number of steps to go
private int totalProgress;
///
/// the current step of the progress
private int progress;
///
/// if the progress is an indeterminate progress or not
private bool indeterminate = false;
///
/// the last error message
private string errorMessage;
///
/// the report view to which the progress belongs
private Action errorDelegate;
private Thread currentThread;
///
/// Creates a new progress object with the given type and sets it as being "indeterminate"
/// (that is, a "busy"/"not busy" progress) or determinate (that is, with clearly
/// defined steps - step 1 of 5, step 2 of 5, etc.)
/// The Progress will register itself to the viewer ProgressPool, which handles all progresses.
/// the error receiver which will be informed about failures during this progress
/// E.g. NAVIGATION, PRINT, EXPORT, SEARCH or a custom defined constant.
public Progress(Action errorDelegate, ProgressType type)
: this(type)
{
this.errorDelegate = errorDelegate;
}
///
/// Gets the error delegate.
///
protected Action ErrorDelegate
{
get
{
return errorDelegate;
}
}
///
/// Creates a new progress object with the given type and sets it as being "indeterminate"
/// (that is, a "busy"/"not busy" progress) or determinate (that is, with clearly
/// defined steps - step 1 of 5, step 2 of 5, etc.)
/// This Progress will NOT registered to the viewer ProgressPool. It is useful for export without report preview.
///
/// E.g. NAVIGATION, PRINT, EXPORT, SEARCH or a custom defined constant
public Progress(ProgressType type)
{
this.type = type;
this.Status = Progress.ProgressStatus.Initialized;
this.ProgressMode = Data.ProgressMode.Steps;
}
///
/// Starts the progress asynchronously in a background thread.
/// when progress is already running
public void StartProgress()
{
if (currentThread != null && currentThread.IsAlive)
{
throw new ViewerException("Progress '" + Name + "' is already running");
}
currentThread = new Thread(new ThreadStart(Run));
Status = ProgressStatus.Running;
ErrorMessage = null;
if (indeterminate)
{
this.ProgressMode = Data.ProgressMode.Continuous;
}
currentThread.Start();
}
///
/// Waits until this progress is finished.
///
public void WaitUntilFinished()
{
currentThread.Join();
}
///
/// The name of the daemon thread.
/// the name of the daemon thread.
public abstract string Name { get; }
///
/// Call this method to force a cancel of the progress - which must also
/// set both of the states "finished" and "canceled" to true.
/// Please note: some progresses may not be stoppable.
///
public abstract void Cancel();
///
/// Returns the type of the progress, which can be one of the following types.
/// Type of the progress
///
public virtual ProgressType Type
{
get
{
return this.type;
}
}
///
/// Performs this progress.
///
protected virtual void Run()
{
}
///
/// Returns whether this progress is indeterminate, that is, only a "busy" or "not busy" progress. If not, this progress has
/// specific steps and can be determined how far it is finished.
/// Whether this progress is indeterminate, that is, only a "busy" or "not busy" progress.
public virtual bool Indeterminate
{
get
{
return this.indeterminate;
}
set
{
bool old = this.indeterminate;
this.indeterminate = value;
if (old != value)
{
this.OnStatusChanged();
}
}
}
///
/// Call this method to set the status of this progress.
/// The status could be
/// All registered listeners will be informed about this change.
/// Status of this progress
public virtual ProgressStatus Status
{
set
{
ProgressStatus oldValue = this.status;
this.status = value;
if (oldValue != value)
{
OnStatusChanged();
}
}
get
{
return this.status;
}
}
///
/// Return true if the progress has stopped its task. The status of the Progress can be complete, canceled or error.
/// whether the progress has stopped
public virtual bool Finished
{
get
{
bool finished = this.status == Progress.ProgressStatus.Canceled || this.status == ProgressStatus.Completed || this.status == ProgressStatus.Error;
return finished;
}
}
///
/// Use this method to inform all registered listeners about the total steps (e.g. pages)
/// to go. If total is set to zero the progress will be declared as inactive (status = Progress.STATUS_IDLE).
/// steps to go
public virtual int TotalProgress
{
set
{
int old = this.totalProgress;
this.totalProgress = value;
if (value == 0)
{
this.Status = ProgressStatus.Idle;
}
else if (this.Status == ProgressStatus.Idle)
{
Status = ProgressStatus.Running;
}
if (old != value)
{
OnProgressChanged();
}
}
get
{
return this.totalProgress;
}
}
///
/// returns the ProgressMode, by default it is the step wise progress.
///
public virtual ProgressMode ProgressMode
{
get;
protected set;
}
///
/// Use this method to set the progress and
/// to inform all registered listeners about the current step.
/// Steps made in the progress so far (1-based)
public virtual int ProgressCount
{
set
{
int oldStep = this.progress;
this.progress = value;
if (oldStep != value)
{
OnProgressChanged();
}
}
get
{
return this.progress;
}
}
///
/// Returns the last error message of this Progress.
/// The last error of this Progress.
public virtual string ErrorMessage
{
get
{
return this.errorMessage;
}
set
{
this.errorMessage = value;
}
}
///
/// Shows an error dialog for this error message. If there is no ReportView it will print a stacktrace to the console.
/// It is calling SetErrorMessage(String) and SetStatus(STATUS_ERROR) before the error message is show.
/// The exception to show in the error dialog.
///
public virtual void ShowError(Exception th)
{
try
{
ErrorMessage = th.Message;
Status = ProgressStatus.Error;
if (errorDelegate != null)
{
errorDelegate(th);
}
ViewerUtils.PrintStackTrace(th);
}
catch (Exception ex)
{
// ignore exceptions during error handling
ViewerUtils.PrintStackTrace(ex);
}
}
///
///
///
public void OnStatusChanged()
{
if (this.StatusChanged != null)
{
StatusChanged(this, new EventArgs());
}
}
///
///
///
public void OnProgressChanged()
{
if (this.ProgressChanged != null)
{
ProgressChanged(this, new EventArgs());
}
}
}
}