/* 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()); } } } }