#region License Information
/* HeuristicLab
* Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
*
* This file is part of HeuristicLab.
*
* HeuristicLab is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* HeuristicLab 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with HeuristicLab. If not, see .
*/
#endregion
using System;
using System.Windows.Forms;
namespace HeuristicLab.MainForm.WindowsForms {
internal sealed partial class ProgressView : UserControl {
private const int defaultControlHeight = 88;
private const int collapsedControlHeight = 55;
private readonly Control control;
public Control Control {
get { return control; }
}
private readonly IProgress content;
public IProgress Content {
get { return content; }
}
public ProgressView(Control control, IProgress content)
: base() {
if (control == null) throw new ArgumentNullException("control", "The control is null.");
if (content == null) throw new ArgumentNullException("content", "The passed progress is null.");
InitializeComponent();
this.control = control;
this.content = content;
if (content.ProgressState == ProgressState.Started)
ShowProgress();
RegisterContentEvents();
}
///
/// Clean up any resources being used.
///
/// true if managed resources should be disposed; otherwise, false.
protected override void Dispose(bool disposing) {
DeregisterContentEvents();
HideProgress();
if (disposing && (components != null)) {
components.Dispose();
}
base.Dispose(disposing);
}
private void RegisterContentEvents() {
content.StatusChanged += new EventHandler(progress_StatusChanged);
content.ProgressValueChanged += new EventHandler(progress_ProgressValueChanged);
content.ProgressStateChanged += new EventHandler(Content_ProgressStateChanged);
content.CanBeCanceledChanged += new EventHandler(Content_CanBeCanceledChanged);
}
private void DeregisterContentEvents() {
content.StatusChanged -= new EventHandler(progress_StatusChanged);
content.ProgressValueChanged -= new EventHandler(progress_ProgressValueChanged);
content.ProgressStateChanged -= new EventHandler(Content_ProgressStateChanged);
content.CanBeCanceledChanged -= new EventHandler(Content_CanBeCanceledChanged);
}
private void ShowProgress() {
if (Control.InvokeRequired) {
Control.Invoke((Action)ShowProgress);
return;
}
int height = Content.CanBeCanceled ? Height : collapsedControlHeight;
Left = (Control.ClientRectangle.Width / 2) - (Width / 2);
Top = (Control.ClientRectangle.Height / 2) - (height / 2);
Anchor = AnchorStyles.None;
control.Enabled = false;
Parent = Control.Parent;
BringToFront();
UpdateProgressValue();
UpdateProgressStatus();
UpdateCancelButton();
Visible = true;
}
private void HideProgress() {
if (InvokeRequired) Invoke((Action)HideProgress);
else {
control.Enabled = true;
Parent = null;
Visible = false;
}
}
private void progress_StatusChanged(object sender, EventArgs e) {
UpdateProgressStatus();
}
private void progress_ProgressValueChanged(object sender, EventArgs e) {
UpdateProgressValue();
}
private void Content_ProgressStateChanged(object sender, EventArgs e) {
switch (content.ProgressState) {
case ProgressState.Finished: HideProgress(); break;
case ProgressState.Canceled: HideProgress(); break;
case ProgressState.Started: ShowProgress(); break;
default: throw new NotSupportedException("The progress state " + content.ProgressState + " is not supported by the ProgressView.");
}
}
private void Content_CanBeCanceledChanged(object sender, EventArgs e) {
UpdateCancelButton();
}
private void UpdateCancelButton() {
cancelButton.Visible = content != null && content.CanBeCanceled;
cancelButton.Enabled = content != null && content.CanBeCanceled;
if (content != null && content.CanBeCanceled) {
Height = defaultControlHeight;
} else if (content != null && !content.CanBeCanceled) {
Height = collapsedControlHeight;
}
}
private void UpdateProgressValue() {
// prevent problems with object disposal and invoke as suggested by http://stackoverflow.com/a/18647091
if (!IsHandleCreated) return;
if (InvokeRequired) {
try {
Invoke((Action)UpdateProgressValue);
}
catch (InvalidOperationException) {
// swallow ObjectDisposedException
// which might occur if the invoke call is executed after or while the control is disposing
}
} else {
if (content != null) {
double progressValue = content.ProgressValue;
if (progressValue <= 0.0 || progressValue > 1.0) {
progressBar.Style = ProgressBarStyle.Marquee;
} else {
progressBar.Style = ProgressBarStyle.Blocks;
progressBar.Value =
(int)Math.Round(progressBar.Minimum + progressValue * (progressBar.Maximum - progressBar.Minimum));
}
}
}
}
private void UpdateProgressStatus() {
if (InvokeRequired) Invoke((Action)UpdateProgressStatus);
else if (content != null)
statusLabel.Text = content.Status;
}
private void cancelButton_Click(object sender, EventArgs e) {
content.Cancel();
}
}
}