OSDN Git Service

AppliStation-GUI,進捗ダイアログのログテキスト表示領域がインストーラーファイルをダウンロードしているときに表示領域がカクカクする不具合を修正(その2...
[applistation/AppliStation.git] / AppliStation / AppliStation.Util / ExecutionProgressViewer.cs
1 using System;\r
2 using System.Drawing;\r
3 using System.Windows.Forms;\r
4 using System.Threading;\r
5 using NaGet.SubCommands;\r
6 using NaGet.Net;\r
7 \r
8 namespace AppliStation.Util\r
9 {\r
10         /// <summary>\r
11         /// Description of ExecutionProgressViewer.\r
12         /// </summary>\r
13         public partial class ExecutionProgressViewer : Form\r
14         {\r
15                 private NaGetTaskSet taskSet;\r
16                 \r
17                 private Thread tasksetRunningThread = null;\r
18                 \r
19                 /// <summary>\r
20                 /// 終了時に何を行うかのフラグ\r
21                 /// </summary>\r
22                 private enum ActionOnDoneFlags {\r
23                         None = 0,\r
24                         FlashWindow = 1,\r
25                         AutoCloseOnSuccess = 2,\r
26                 }\r
27                 \r
28                 /// <summary>\r
29                 /// 終了時に何を行うか\r
30                 /// </summary>\r
31                 private ActionOnDoneFlags ActionOnDone = ActionOnDoneFlags.FlashWindow;\r
32                                 \r
33                 public ExecutionProgressViewer()\r
34                 {\r
35                         //\r
36                         // The InitializeComponent() call is required for Windows Forms designer support.\r
37                         //\r
38                         InitializeComponent();\r
39                         \r
40                         this.Icon = Icon.ExtractAssociatedIcon(Application.ExecutablePath);\r
41                         toolTip.SetToolTip(autoCloseCheckBox,\r
42                                            string.Format("エラーがなく正常に終了した場合、{0}秒後に自動的にこのダイアログを閉じます", autoCloseTimer.Interval/1000));\r
43                 }\r
44                                 \r
45                 private void onDownloadEvent(object sender, DownloadEventArgs a)\r
46                 {\r
47                         if (InvokeRequired) {\r
48                                 Invoke(new EventHandler<DownloadEventArgs>(onDownloadEvent), sender, a);\r
49                                 return;\r
50                         }\r
51                         \r
52                         switch (a.Type) {\r
53                                 case DownloadEventType.INITED:\r
54                                 case DownloadEventType.CONNECTED:\r
55                                         progressSubLabel.Text = a.TaskMessage;\r
56                                         \r
57                                         progressBarSub.Visible = true;\r
58                                         progressSubLabel.Visible = true;\r
59                                         break;\r
60                                 case DownloadEventType.DOWNLOADING:\r
61                                         progressSubLabel.Text = a.TaskMessage;\r
62                                         break;\r
63                                 case DownloadEventType.COMPLETED:\r
64                                         progressBarSub.Visible = false;\r
65                                         progressSubLabel.Visible = false;\r
66                                         break;\r
67                                 case DownloadEventType.ERROR:\r
68                                         progressBarSub.Visible = false;\r
69                                         progressSubLabel.Visible = false;\r
70                                         \r
71                                         logBox.SelectionColor = System.Drawing.Color.Red;\r
72                                         logBox.AppendText("   [エラー] " + a.TaskMessage + System.Environment.NewLine);\r
73                                         logBox.SelectionColor = logBox.ForeColor;\r
74                                         break;\r
75                         }\r
76                         \r
77                         // ダウンロードの進捗を表示\r
78                         if (a.TaskProgressPercent >= 0) {\r
79                                 progressBarSub.Value = (int) a.TaskProgressPercent;\r
80                                 progressBarSub.Style = ProgressBarStyle.Continuous;\r
81                         } else {\r
82                                 progressBarSub.Style = ProgressBarStyle.Marquee;\r
83                         }\r
84                 }\r
85                 \r
86                 #region NaGetTaskSet関連\r
87                 \r
88                 private void onTaskSetRaised(object sender, NaGetTaskSetEventArgs e)\r
89                 {\r
90                         NaGetTaskSet taskSet = (NaGetTaskSet) sender;\r
91                         NativeMethods.ProgressBarState progressState = NativeMethods.ProgressBarState.Normal;\r
92                         \r
93                         cancelButton.Enabled = taskSet.Running && taskSet.Cancelable;\r
94                         \r
95                         switch (e.Type) {\r
96                                 case NaGetTaskSetEventType.COMPLETED:\r
97                                         logBox.AppendText("完了." + System.Environment.NewLine);\r
98                                         if (taskSet.Done) {\r
99                                                 okButton.Enabled = true;\r
100                                                 cancelButton.Enabled = false;\r
101                                                 \r
102                                                 // タスクが完了したらしばらく待って閉じるために、自動クローズタイマーを起動する\r
103                                                 autoCloseTimer.Start();\r
104                                         }\r
105                                         break;\r
106                                 case NaGetTaskSetEventType.STARTED_TASKSET:\r
107                                         progressLabel.Text = taskSet.TaskSetNames[taskSet.CurrentTaskSetIndex];\r
108                                         logBox.AppendText("  " + e.TaskMessage + System.Environment.NewLine);\r
109                                         break;\r
110                                 case NaGetTaskSetEventType.COMPLETED_TASKSET:\r
111                                         if (progressBarSub.Visible) progressBarSub.Hide();\r
112                                         if (progressSubLabel.Visible) progressSubLabel.Hide();\r
113                                         \r
114                                         progressState = NativeMethods.ProgressBarState.Normal;\r
115                                         \r
116                                         logBox.AppendText(string.Format(" ... 完了. [{0}%]", (int) e.TaskProgressPercent));\r
117                                         logBox.AppendText(System.Environment.NewLine);\r
118                                         break;\r
119                                 case NaGetTaskSetEventType.INFO:\r
120                                         logBox.AppendText("  " + e.TaskMessage + System.Environment.NewLine);\r
121                                         break;\r
122                                 case NaGetTaskSetEventType.ERROR:\r
123                                         logBox.SelectionColor = System.Drawing.Color.Red;\r
124                                         logBox.AppendText("  [エラー] " + e.TaskMessage + System.Environment.NewLine);\r
125                                         logBox.SelectionColor = logBox.ForeColor;\r
126                                         \r
127                                         progressState = NativeMethods.ProgressBarState.Error;\r
128                                         \r
129                                         autoCloseCheckBox.Enabled = false;\r
130                                         okButton.Enabled = true;\r
131                                         cancelButton.Enabled = false;\r
132                                         break;\r
133                                 case NaGetTaskSetEventType.CANCELED:\r
134                                         logBox.SelectionColor = System.Drawing.Color.Red;\r
135                                         logBox.AppendText(e.TaskMessage + System.Environment.NewLine);\r
136                                         logBox.SelectionColor = logBox.ForeColor;\r
137                                         \r
138                                         progressState = NativeMethods.ProgressBarState.Error;\r
139                                         \r
140                                         autoCloseCheckBox.Enabled = false;\r
141                                         okButton.Enabled = true;\r
142                                         cancelButton.Enabled = false;\r
143                                         break;\r
144                                 case NaGetTaskSetEventType.WARNING:\r
145                                         logBox.SelectionColor = System.Drawing.Color.Red;\r
146                                         logBox.AppendText("  [エラー] " + e.TaskMessage + System.Environment.NewLine);\r
147                                         logBox.SelectionColor = logBox.ForeColor;\r
148                                         \r
149                                         progressState = NativeMethods.ProgressBarState.Error;\r
150                                         \r
151                                         autoCloseCheckBox.Enabled = false;\r
152                                         break;\r
153                         }\r
154                         \r
155                         // タスクセット全体の進捗をプログレスバーに表示する\r
156                         if (e.TaskProgressPercent >= 0) {\r
157                                 progressBar.Value = (int) e.TaskProgressPercent;\r
158                                 progressBar.Style = ProgressBarStyle.Continuous;\r
159                         } else {\r
160                                 progressBar.Style = ProgressBarStyle.Marquee;\r
161                         }\r
162                         NativeMethods.ProgressBar_SetState(progressBar, progressState);\r
163                         NativeMethods.ProgressBar_SetState(progressBarSub, progressState);\r
164                         // タスクセット全体の進捗をタスクバーに表示する(Windows 7以降のみ)\r
165                         if (e.TaskProgressPercent >= 0 && e.TaskProgressPercent < 100) {\r
166                                 NativeMethods.Form_SetTaskbarProgressParams(this, progressBar.Style, progressState, (ulong) e.TaskProgressPercent, 100);\r
167                         } else {\r
168                                 NativeMethods.Form_SetTaskbarProgressParams(this, progressBar.Style, progressState, 0, 0);\r
169                         }\r
170                         \r
171                         if (taskSet.Done) {\r
172                                 if ((ActionOnDone & ActionOnDoneFlags.FlashWindow) != 0) {\r
173                                         NativeMethods.Form_FlashWindow(this,\r
174                                                                NativeMethods.FlashFlag.All | NativeMethods.FlashFlag.TimerNoFG,\r
175                                                                uint.MaxValue, 0);\r
176                                 }\r
177                                 if (okButton.Enabled && (ActionOnDone & ActionOnDoneFlags.AutoCloseOnSuccess) != 0) {\r
178                                         this.DialogResult = DialogResult.OK;\r
179                                         Close();\r
180                                         Dispose();\r
181                                 }\r
182                         }\r
183                 }\r
184                 \r
185                 private NaGetTaskQueryResult onTaskQueryRaised(object sender, NaGetTaskQueryArgs e)\r
186                 {\r
187                         MessageBoxButtons buttons = MessageBoxButtons.OKCancel;\r
188                         if (e.SelectionFlag == (NaGetTaskQueryResult.CONTINUE | NaGetTaskQueryResult.RETRY | NaGetTaskQueryResult.CANCEL)) {\r
189                                 buttons = MessageBoxButtons.AbortRetryIgnore;\r
190                         } else if (e.SelectionFlag == (NaGetTaskQueryResult.RETRY | NaGetTaskQueryResult.CANCEL)) {\r
191                                 buttons = MessageBoxButtons.RetryCancel;\r
192                         } else if (e.SelectionFlag == NaGetTaskQueryResult.CONTINUE) {\r
193                                 buttons = MessageBoxButtons.OK;\r
194                         }\r
195                         \r
196                         DialogResult result = MessageBox.Show(e.Message, this.Text, buttons);\r
197                         \r
198                         switch (result) {\r
199                                 case DialogResult.OK:\r
200                                 case DialogResult.Ignore:\r
201                                         return NaGetTaskQueryResult.CONTINUE;\r
202                                 case DialogResult.Cancel:\r
203                                 case DialogResult.Abort:\r
204                                         return NaGetTaskQueryResult.CANCEL;\r
205                                 case DialogResult.Retry:\r
206                                         return NaGetTaskQueryResult.RETRY;\r
207                                 default:\r
208                                         return NaGetTaskQueryResult.CANCELED_AUTOMATICALLY;\r
209                         }\r
210                 }\r
211                 \r
212                 public void SetTaskSet(NaGetTaskSet taskSet)\r
213                 {\r
214                         this.taskSet = taskSet;\r
215                         \r
216                         taskSet.TaskSetRaised += delegate(object sender, NaGetTaskSetEventArgs e) {\r
217                                 if (InvokeRequired) {\r
218                                         Invoke(new EventHandler<NaGetTaskSetEventArgs>(onTaskSetRaised), taskSet, e);\r
219                                 } else {\r
220                                         onTaskSetRaised(taskSet, e);\r
221                                 }\r
222                         };\r
223                         \r
224                         System.Reflection.PropertyInfo fDownloader = taskSet.GetType().GetProperty("Downloader");\r
225                         if (fDownloader != null && (fDownloader.PropertyType == typeof(Downloader))) {\r
226                                 ((Downloader) fDownloader.GetValue(taskSet, null)).DownloadEventRaised += onDownloadEvent;\r
227                         }\r
228                         \r
229                         taskSet.TaskQueryRaised += onTaskQueryRaised;\r
230                 }\r
231 \r
232                 public void StartTaskSet()\r
233                 {\r
234                         tasksetRunningThread = new Thread(taskSet.Run);\r
235                         // スレッドをSTAにしないとCOMアクセスできず、ウイルススキャンができない。\r
236                         tasksetRunningThread.SetApartmentState(ApartmentState.STA);\r
237                         tasksetRunningThread.Start();\r
238                 }\r
239                 \r
240                 #endregion\r
241                 \r
242                 void LogBoxTextChanged(object sender, EventArgs e)\r
243                 {       \r
244                         logBox.Select(logBox.TextLength, 0);\r
245                         logBox.ScrollToCaret();\r
246                 }\r
247                 \r
248                 void LogBoxTextLayouted(object sender, LayoutEventArgs e)\r
249                 {\r
250                         logBox.ScrollToCaret();\r
251                 }\r
252                 \r
253                 void OkButtonClick(object sender, EventArgs e)\r
254                 {\r
255                         if (taskSet == null || taskSet.Done) {\r
256                                 this.Close();\r
257                                 this.Dispose();\r
258                         }\r
259                 }\r
260                 \r
261                 void CancelButtonClick(object sender, EventArgs e)\r
262                 {\r
263                         if (InvokeRequired) {\r
264                                 Invoke(new EventHandler(CancelButtonClickConcrete), sender, e);\r
265                         } else {\r
266                                 CancelButtonClickConcrete(sender,e);\r
267                         }\r
268                 }\r
269                 \r
270                 void CancelButtonClickConcrete(object sender, EventArgs e)\r
271                 {\r
272                         autoCloseCheckBox.Enabled = false;\r
273                         if (taskSet != null && taskSet.Running && taskSet.Cancelable) {\r
274                                 cancelButton.Enabled = false;\r
275                                 \r
276                                 NativeMethods.ProgressBar_SetState(progressBar, NativeMethods.ProgressBarState.Paused);\r
277                                 NativeMethods.Form_SetTaskbarProgressParams(this, progressBar.Style,NativeMethods.ProgressBarState.Paused, (ulong) progressBar.Value, (ulong) progressBar.Maximum);\r
278                                 \r
279                                 taskSet.Cancel();\r
280                         }\r
281                 }\r
282                 \r
283                 void ExecutionProgressViewerShown(object sender, EventArgs e)\r
284                 {\r
285                         this.BringToFront();\r
286                 }\r
287                 \r
288                 void ExecutionProgressViewerFormClosed(object sender, FormClosedEventArgs e)\r
289                 {\r
290                         autoCloseTimer.Enabled = false;\r
291                 }\r
292                 \r
293                 void AutoCloseTimerTick(object sender, EventArgs e)\r
294                 {\r
295                         autoCloseTimer.Stop();\r
296                         \r
297                         if (InvokeRequired) {\r
298                                 Invoke(new EventHandler(AutoCloseTimerTickConcrete), sender, e);\r
299                         } else {\r
300                                 AutoCloseTimerTickConcrete(sender,e);\r
301                         }\r
302                 }\r
303                 \r
304                 void AutoCloseTimerTickConcrete(object sender, EventArgs e)\r
305                 {\r
306                         // autoCloseCheckBoxが有効(正常終了)かつチェックのときに限り、OKボタンを自動的にクリック\r
307                         if (autoCloseCheckBox.Enabled && autoCloseCheckBox.Checked && okButton.Enabled) {\r
308                                 OkButtonClick(sender, e);\r
309                         } else if (! autoCloseCheckBox.Enabled) {\r
310                                 // タイマーの時間がすぎて、そのとき自動で閉じないようにしていしてあるならば、手動で閉じるように\r
311                                 autoCloseCheckBox.Enabled = false;\r
312                         }\r
313                 }\r
314         }\r
315 }\r