using System;
using System.Drawing;
using System.Windows.Forms;
using System.Threading;
using NaGet.SubCommands;
using NaGet.Net;
namespace AppliStation.Util
{
///
/// Description of ExecutionProgressViewer.
///
public partial class ExecutionProgressViewer : Form
{
private NaGetTaskSet taskSet;
private Thread tasksetRunningThread = null;
///
/// 終了時に何を行うかのフラグ
///
private enum ActionOnDoneFlags {
None = 0,
FlashWindow = 1,
AutoCloseOnSuccess = 2,
}
///
/// 終了時に何を行うか
///
private ActionOnDoneFlags ActionOnDone = ActionOnDoneFlags.FlashWindow;
public ExecutionProgressViewer()
{
//
// The InitializeComponent() call is required for Windows Forms designer support.
//
InitializeComponent();
this.Icon = Icon.ExtractAssociatedIcon(Application.ExecutablePath);
toolTip.SetToolTip(autoCloseCheckBox,
string.Format("エラーがなく正常に終了した場合、{0}秒後に自動的にこのダイアログを閉じます", autoCloseTimer.Interval/1000));
}
private void onDownloadEvent(object sender, DownloadEventArgs a)
{
if (InvokeRequired) {
Invoke(new EventHandler(onDownloadEvent), sender, a);
return;
}
switch (a.Type) {
case DownloadEventType.INITED:
case DownloadEventType.CONNECTED:
progressSubLabel.Text = a.TaskMessage;
progressBarSub.Visible = true;
progressSubLabel.Visible = true;
break;
case DownloadEventType.DOWNLOADING:
progressSubLabel.Text = a.TaskMessage;
break;
case DownloadEventType.COMPLETED:
progressBarSub.Visible = false;
progressSubLabel.Visible = false;
break;
case DownloadEventType.ERROR:
progressBarSub.Visible = false;
progressSubLabel.Visible = false;
logBox.SelectionColor = System.Drawing.Color.Red;
logBox.AppendText(" [エラー] " + a.TaskMessage + System.Environment.NewLine);
logBox.SelectionColor = logBox.ForeColor;
break;
}
// ダウンロードの進捗を表示
if (a.TaskProgressPercent >= 0) {
progressBarSub.Value = (int) a.TaskProgressPercent;
progressBarSub.Style = ProgressBarStyle.Continuous;
} else {
progressBarSub.Style = ProgressBarStyle.Marquee;
}
}
#region NaGetTaskSet関連
private void onTaskSetRaised(object sender, NaGetTaskSetEventArgs e)
{
NaGetTaskSet taskSet = (NaGetTaskSet) sender;
NativeMethods.ProgressBarState progressState = NativeMethods.ProgressBarState.Normal;
cancelButton.Enabled = taskSet.Running && taskSet.Cancelable;
switch (e.Type) {
case NaGetTaskSetEventType.COMPLETED:
logBox.AppendText("完了." + System.Environment.NewLine);
if (taskSet.Done) {
okButton.Enabled = true;
cancelButton.Enabled = false;
// タスクが完了したらしばらく待って閉じるために、自動クローズタイマーを起動する
autoCloseTimer.Start();
}
break;
case NaGetTaskSetEventType.STARTED_TASKSET:
progressLabel.Text = taskSet.TaskSetNames[taskSet.CurrentTaskSetIndex];
logBox.AppendText(" " + e.TaskMessage + System.Environment.NewLine);
break;
case NaGetTaskSetEventType.COMPLETED_TASKSET:
if (progressBarSub.Visible) progressBarSub.Hide();
if (progressSubLabel.Visible) progressSubLabel.Hide();
progressState = NativeMethods.ProgressBarState.Normal;
logBox.AppendText(string.Format(" ... 完了. [{0}%]", (int) e.TaskProgressPercent));
logBox.AppendText(System.Environment.NewLine);
break;
case NaGetTaskSetEventType.INFO:
logBox.AppendText(" " + e.TaskMessage + System.Environment.NewLine);
break;
case NaGetTaskSetEventType.ERROR:
logBox.SelectionColor = System.Drawing.Color.Red;
logBox.AppendText(" [エラー] " + e.TaskMessage + System.Environment.NewLine);
logBox.SelectionColor = logBox.ForeColor;
progressState = NativeMethods.ProgressBarState.Error;
autoCloseCheckBox.Enabled = false;
okButton.Enabled = true;
cancelButton.Enabled = false;
break;
case NaGetTaskSetEventType.CANCELED:
logBox.SelectionColor = System.Drawing.Color.Red;
logBox.AppendText(e.TaskMessage + System.Environment.NewLine);
logBox.SelectionColor = logBox.ForeColor;
progressState = NativeMethods.ProgressBarState.Error;
autoCloseCheckBox.Enabled = false;
okButton.Enabled = true;
cancelButton.Enabled = false;
break;
case NaGetTaskSetEventType.WARNING:
logBox.SelectionColor = System.Drawing.Color.Red;
logBox.AppendText(" [エラー] " + e.TaskMessage + System.Environment.NewLine);
logBox.SelectionColor = logBox.ForeColor;
progressState = NativeMethods.ProgressBarState.Error;
autoCloseCheckBox.Enabled = false;
break;
}
// タスクセット全体の進捗をプログレスバーに表示する
if (e.TaskProgressPercent >= 0) {
progressBar.Value = (int) e.TaskProgressPercent;
progressBar.Style = ProgressBarStyle.Continuous;
} else {
progressBar.Style = ProgressBarStyle.Marquee;
}
NativeMethods.ProgressBar_SetState(progressBar, progressState);
NativeMethods.ProgressBar_SetState(progressBarSub, progressState);
// タスクセット全体の進捗をタスクバーに表示する(Windows 7以降のみ)
if (e.TaskProgressPercent >= 0 && e.TaskProgressPercent < 100) {
NativeMethods.Form_SetTaskbarProgressParams(this, progressBar.Style, progressState, (ulong) e.TaskProgressPercent, 100);
} else {
NativeMethods.Form_SetTaskbarProgressParams(this, progressBar.Style, progressState, 0, 0);
}
if (taskSet.Done) {
if ((ActionOnDone & ActionOnDoneFlags.FlashWindow) != 0) {
NativeMethods.Form_FlashWindow(this,
NativeMethods.FlashFlag.All | NativeMethods.FlashFlag.TimerNoFG,
uint.MaxValue, 0);
}
if (okButton.Enabled && (ActionOnDone & ActionOnDoneFlags.AutoCloseOnSuccess) != 0) {
this.DialogResult = DialogResult.OK;
Close();
Dispose();
}
}
}
private NaGetTaskQueryResult onTaskQueryRaised(object sender, NaGetTaskQueryArgs e)
{
MessageBoxButtons buttons = MessageBoxButtons.OKCancel;
if (e.SelectionFlag == (NaGetTaskQueryResult.CONTINUE | NaGetTaskQueryResult.RETRY | NaGetTaskQueryResult.CANCEL)) {
buttons = MessageBoxButtons.AbortRetryIgnore;
} else if (e.SelectionFlag == (NaGetTaskQueryResult.RETRY | NaGetTaskQueryResult.CANCEL)) {
buttons = MessageBoxButtons.RetryCancel;
} else if (e.SelectionFlag == NaGetTaskQueryResult.CONTINUE) {
buttons = MessageBoxButtons.OK;
}
DialogResult result = MessageBox.Show(e.Message, this.Text, buttons);
switch (result) {
case DialogResult.OK:
case DialogResult.Ignore:
return NaGetTaskQueryResult.CONTINUE;
case DialogResult.Cancel:
case DialogResult.Abort:
return NaGetTaskQueryResult.CANCEL;
case DialogResult.Retry:
return NaGetTaskQueryResult.RETRY;
default:
return NaGetTaskQueryResult.CANCELED_AUTOMATICALLY;
}
}
public void SetTaskSet(NaGetTaskSet taskSet)
{
this.taskSet = taskSet;
taskSet.TaskSetRaised += delegate(object sender, NaGetTaskSetEventArgs e) {
if (InvokeRequired) {
Invoke(new EventHandler(onTaskSetRaised), taskSet, e);
} else {
onTaskSetRaised(taskSet, e);
}
};
System.Reflection.PropertyInfo fDownloader = taskSet.GetType().GetProperty("Downloader");
if (fDownloader != null && (fDownloader.PropertyType == typeof(Downloader))) {
((Downloader) fDownloader.GetValue(taskSet, null)).DownloadEventRaised += onDownloadEvent;
}
taskSet.TaskQueryRaised += onTaskQueryRaised;
}
public void StartTaskSet()
{
tasksetRunningThread = new Thread(taskSet.Run);
// スレッドをSTAにしないとCOMアクセスできず、ウイルススキャンができない。
tasksetRunningThread.SetApartmentState(ApartmentState.STA);
tasksetRunningThread.Start();
}
#endregion
void LogBoxTextChanged(object sender, EventArgs e)
{
logBox.Select(logBox.TextLength, 0);
logBox.ScrollToCaret();
}
void OkButtonClick(object sender, EventArgs e)
{
if (taskSet == null || taskSet.Done) {
this.Close();
this.Dispose();
}
}
void CancelButtonClick(object sender, EventArgs e)
{
if (InvokeRequired) {
Invoke(new EventHandler(CancelButtonClickConcrete), sender, e);
} else {
CancelButtonClickConcrete(sender,e);
}
}
void CancelButtonClickConcrete(object sender, EventArgs e)
{
autoCloseCheckBox.Enabled = false;
if (taskSet != null && taskSet.Running && taskSet.Cancelable) {
cancelButton.Enabled = false;
NativeMethods.ProgressBar_SetState(progressBar, NativeMethods.ProgressBarState.Paused);
NativeMethods.Form_SetTaskbarProgressParams(this, progressBar.Style,NativeMethods.ProgressBarState.Paused, (ulong) progressBar.Value, (ulong) progressBar.Maximum);
taskSet.Cancel();
}
}
void ExecutionProgressViewerShown(object sender, EventArgs e)
{
this.BringToFront();
}
void ExecutionProgressViewerFormClosed(object sender, FormClosedEventArgs e)
{
autoCloseTimer.Enabled = false;
}
void AutoCloseTimerTick(object sender, EventArgs e)
{
autoCloseTimer.Stop();
if (InvokeRequired) {
Invoke(new EventHandler(AutoCloseTimerTickConcrete), sender, e);
} else {
AutoCloseTimerTickConcrete(sender,e);
}
}
void AutoCloseTimerTickConcrete(object sender, EventArgs e)
{
// autoCloseCheckBoxが有効(正常終了)かつチェックのときに限り、OKボタンを自動的にクリック
if (autoCloseCheckBox.Enabled && autoCloseCheckBox.Checked && okButton.Enabled) {
OkButtonClick(sender, e);
} else if (! autoCloseCheckBox.Enabled) {
// タイマーの時間がすぎて、そのとき自動で閉じないようにしていしてあるならば、手動で閉じるように
autoCloseCheckBox.Enabled = false;
}
}
}
}