OSDN Git Service

WinGui:
[handbrake-jp/handbrake-jp-git.git] / win / C# / frmQueue.cs
1 /*  frmQueue.cs $\r
2     This file is part of the HandBrake source code.\r
3     Homepage: <http://handbrake.fr>.\r
4     It may be used under the terms of the GNU General Public License. */\r
5 \r
6 namespace Handbrake\r
7 {\r
8     using System;\r
9     using System.Collections.Generic;\r
10     using System.Collections.ObjectModel;\r
11     using System.ComponentModel;\r
12     using System.IO;\r
13     using System.Windows.Forms;\r
14     using Functions;\r
15 \r
16     using HandBrake.ApplicationServices.Model;\r
17     using HandBrake.ApplicationServices.Services;\r
18     using HandBrake.ApplicationServices.Services.Interfaces;\r
19 \r
20     using Model;\r
21 \r
22     /// <summary>\r
23     /// The Queue Window\r
24     /// </summary>\r
25     public partial class frmQueue : Form\r
26     {\r
27         /// <summary>\r
28         /// Update Handler Delegate\r
29         /// </summary>\r
30         private delegate void UpdateHandler();\r
31 \r
32         /// <summary>\r
33         /// An instance of the Queue service\r
34         /// </summary>\r
35         private readonly IQueue queue;\r
36 \r
37         /// <summary>\r
38         /// A reference to the main application window\r
39         /// </summary>\r
40         private readonly frmMain mainWindow;\r
41 \r
42         /// <summary>\r
43         /// Initializes a new instance of the <see cref="frmQueue"/> class.\r
44         /// </summary>\r
45         /// <param name="q">\r
46         /// An instance of the queue service.\r
47         /// </param>\r
48         /// <param name="mw">\r
49         /// The main window.\r
50         /// </param>\r
51         public frmQueue(IQueue q, frmMain mw)\r
52         {\r
53             InitializeComponent();\r
54 \r
55             this.mainWindow = mw;\r
56 \r
57             this.queue = q;\r
58             queue.EncodeStarted += new EventHandler(QueueOnEncodeStart);\r
59             queue.QueueCompleted += new EventHandler(QueueOnQueueFinished);\r
60             queue.QueuePauseRequested += new EventHandler(QueueOnPaused);\r
61             queue.QueueListChanged += new EventHandler(queue_QueueListChanged);\r
62 \r
63             queue.EncodeStarted += new EventHandler(queue_EncodeStarted);\r
64             queue.EncodeEnded += new EventHandler(queue_EncodeEnded);\r
65 \r
66             drp_completeOption.Text = Properties.Settings.Default.CompletionOption;\r
67         }\r
68 \r
69         /// <summary>\r
70         /// Queue Changed\r
71         /// </summary>\r
72         /// <param name="sender">\r
73         /// The sender.\r
74         /// </param>\r
75         /// <param name="e">\r
76         /// The e.\r
77         /// </param>\r
78         private void queue_QueueListChanged(object sender, EventArgs e)\r
79         {\r
80             UpdateUiElementsOnQueueChange();\r
81         }\r
82 \r
83         /// <summary>\r
84         /// Encode Ended\r
85         /// </summary>\r
86         /// <param name="sender">\r
87         /// The sender.\r
88         /// </param>\r
89         /// <param name="e">\r
90         /// The e.\r
91         /// </param>\r
92         private void queue_EncodeEnded(object sender, EventArgs e)\r
93         {\r
94             queue.EncodeStatusChanged -= EncodeQueue_EncodeStatusChanged;\r
95             ResetEncodeText();\r
96         }\r
97 \r
98         /// <summary>\r
99         /// Queue Started\r
100         /// </summary>\r
101         /// <param name="sender">\r
102         /// The sender.\r
103         /// </param>\r
104         /// <param name="e">\r
105         /// The e.\r
106         /// </param>\r
107         private void queue_EncodeStarted(object sender, EventArgs e)\r
108         {\r
109             this.SetCurrentEncodeInformation();\r
110             queue.EncodeStatusChanged += EncodeQueue_EncodeStatusChanged;        \r
111         }\r
112 \r
113         /// <summary>\r
114         /// Display the Encode Status\r
115         /// </summary>\r
116         /// <param name="sender">\r
117         /// The sender.\r
118         /// </param>\r
119         /// <param name="e">\r
120         /// The e.\r
121         /// </param>\r
122         private void EncodeQueue_EncodeStatusChanged(object sender, HandBrake.ApplicationServices.EncodeProgressEventArgs e)\r
123         {\r
124             if (this.InvokeRequired)\r
125             {\r
126                 this.BeginInvoke(new Encode.EncodeProgessStatus(EncodeQueue_EncodeStatusChanged), new[] { sender, e });\r
127                 return;\r
128             }\r
129 \r
130             lbl_encodeStatus.Text =\r
131                 string.Format(\r
132                 "Encoding: Pass {0} of {1}, {2:00.00}% Time Remaining: {3}",\r
133                 e.Task,\r
134                 e.Task,\r
135                 e.PercentComplete,\r
136                 e.EstimatedTimeLeft);\r
137         }\r
138 \r
139         /// <summary>\r
140         /// Handle the Queue Paused event\r
141         /// </summary>\r
142         /// <param name="sender">\r
143         /// The sender.\r
144         /// </param>\r
145         /// <param name="e">\r
146         /// The EventArgs.\r
147         /// </param>\r
148         private void QueueOnPaused(object sender, EventArgs e)\r
149         {\r
150             SetUiEncodeFinished();\r
151             UpdateUiElementsOnQueueChange();\r
152         }\r
153 \r
154         /// <summary>\r
155         /// Handle the Queue Finished event.\r
156         /// </summary>\r
157         /// <param name="sender">\r
158         /// The sender.\r
159         /// </param>\r
160         /// <param name="e">\r
161         /// The EventArgs.\r
162         /// </param>\r
163         private void QueueOnQueueFinished(object sender, EventArgs e)\r
164         {\r
165             SetUiEncodeFinished();\r
166             ResetQueue(); // Reset the Queue Window\r
167         }\r
168 \r
169         /// <summary>\r
170         /// Handle the Encode Started event\r
171         /// </summary>\r
172         /// <param name="sender">\r
173         /// The sender.\r
174         /// </param>\r
175         /// <param name="e">\r
176         /// The e.\r
177         /// </param>\r
178         private void QueueOnEncodeStart(object sender, EventArgs e)\r
179         {\r
180             SetUiEncodeStarted(); // make sure the UI is set correctly\r
181             UpdateUiElementsOnQueueChange(); // Redraw the Queue, a new encode has started.\r
182         }\r
183 \r
184         /// <summary>\r
185         /// Initializes the Queue list with the Arraylist from the Queue class\r
186         /// </summary>\r
187         public void SetQueue()\r
188         {\r
189             UpdateUiElementsOnQueueChange();\r
190         }\r
191 \r
192         /// <summary>\r
193         /// Initializes the Queue list, then shows and activates the window\r
194         /// </summary>\r
195         public new void Show()\r
196         {\r
197             Show(true);\r
198         }\r
199 \r
200         /// <summary>\r
201         /// Initializes the Queue list only if doSetQueue is true, then shows and activates the window\r
202         /// </summary>\r
203         /// <param name="doSetQueue">Indicates whether to call setQueue() before showing the window</param>\r
204         public void Show(bool doSetQueue)\r
205         {\r
206             if (doSetQueue) SetQueue();\r
207             base.Show();\r
208         }\r
209 \r
210         /// <summary>\r
211         /// Handle the Encode button Click event\r
212         /// </summary>\r
213         /// <param name="sender">The sender</param>\r
214         /// <param name="e">the EventArgs</param>\r
215         private void BtnEncodeClick(object sender, EventArgs e)\r
216         {\r
217             if (queue.Paused)\r
218             {\r
219                 SetUiEncodeStarted();\r
220             }\r
221 \r
222             lbl_encodeStatus.Text = "Encoding ...";\r
223             queue.Start();\r
224         }\r
225 \r
226         /// <summary>\r
227         /// Handle the Pause button click event.\r
228         /// </summary>\r
229         /// <param name="sender">\r
230         /// The sender.\r
231         /// </param>\r
232         /// <param name="e">\r
233         /// The EventArgs.\r
234         /// </param>\r
235         private void BtnPauseClick(object sender, EventArgs e)\r
236         {\r
237             queue.Pause();\r
238             MessageBox.Show(\r
239                 "No further items on the queue will start. The current encode process will continue until it is finished. \nClick 'Encode' when you wish to continue encoding the queue.",\r
240                 "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);\r
241         }\r
242 \r
243         // UI Work\r
244 \r
245         /// <summary>\r
246         /// Setup the UI to show that an encode has started\r
247         /// </summary>\r
248         private void SetUiEncodeStarted()\r
249         {\r
250             if (InvokeRequired)\r
251             {\r
252                 BeginInvoke(new UpdateHandler(SetUiEncodeStarted));\r
253                 return;\r
254             }\r
255             btn_encode.Enabled = false;\r
256             btn_pause.Visible = true;\r
257         }\r
258 \r
259         /// <summary>\r
260         /// Setup the UI to indicate that an encode has finished.\r
261         /// </summary>\r
262         private void SetUiEncodeFinished()\r
263         {\r
264             if (InvokeRequired)\r
265             {\r
266                 BeginInvoke(new UpdateHandler(SetUiEncodeFinished));\r
267                 return;\r
268             }\r
269             btn_pause.Visible = false;\r
270             btn_encode.Enabled = true;\r
271         }\r
272 \r
273         /// <summary>\r
274         /// Reset the Queue Window display\r
275         /// </summary>\r
276         private void ResetQueue()\r
277         {\r
278             if (InvokeRequired)\r
279             {\r
280                 BeginInvoke(new UpdateHandler(ResetQueue));\r
281                 return;\r
282             }\r
283             btn_pause.Visible = false;\r
284             btn_encode.Enabled = true;\r
285 \r
286             ResetEncodeText();\r
287         }\r
288 \r
289         /// <summary>\r
290         /// Reset the current job text\r
291         /// </summary>\r
292         private void ResetEncodeText()\r
293         {\r
294             if (InvokeRequired)\r
295             {\r
296                 BeginInvoke(new UpdateHandler(ResetEncodeText));\r
297                 return;\r
298             }\r
299             lbl_encodeStatus.Text = "Ready";\r
300 \r
301             lbl_source.Text = "-";\r
302             lbl_dest.Text = "-";\r
303             lbl_encodeOptions.Text = "-";\r
304 \r
305             lbl_encodesPending.Text = list_queue.Items.Count + " encode(s) pending";\r
306         }\r
307 \r
308         /// <summary>\r
309         /// Redraw the Queue window with the latest information about HandBrakes status\r
310         /// </summary>\r
311         private void RedrawQueue()\r
312         {\r
313             if (InvokeRequired)\r
314             {\r
315                 BeginInvoke(new UpdateHandler(RedrawQueue));\r
316                 return;\r
317             }\r
318 \r
319             list_queue.Items.Clear();\r
320             ReadOnlyCollection<Job> theQueue = queue.CurrentQueue;\r
321             foreach (Job queueItem in theQueue)\r
322             {\r
323                 string qItem = queueItem.Query;\r
324                 QueryParser parsed = Functions.QueryParser.Parse(qItem);\r
325 \r
326                 // Get the DVD Title\r
327                 string title = parsed.Title == 0 ? "Auto" : parsed.Title.ToString();\r
328 \r
329                 // Get the DVD Chapters\r
330                 string chapters;\r
331                 if (parsed.ChapterStart == 0)\r
332                     chapters = "Auto";\r
333                 else\r
334                 {\r
335                     chapters = parsed.ChapterStart.ToString();\r
336                     if (parsed.ChapterFinish != 0)\r
337                         chapters = chapters + " - " + parsed.ChapterFinish;\r
338                 }\r
339 \r
340                 ListViewItem item = new ListViewItem();\r
341                 item.Text = title; // Title\r
342                 item.SubItems.Add(chapters); // Chapters\r
343                 item.SubItems.Add(queueItem.Source); // Source\r
344                 item.SubItems.Add(queueItem.Destination); // Destination\r
345                 item.SubItems.Add(parsed.VideoEncoder); // Video\r
346 \r
347                 // Display The Audio Track Information\r
348                 string audio = string.Empty;\r
349                 foreach (AudioTrack track in parsed.AudioInformation)\r
350                 {\r
351                     if (audio != string.Empty)\r
352                         audio += ", " + track.Encoder;\r
353                     else\r
354                         audio = track.Encoder;\r
355                 }\r
356                 item.SubItems.Add(audio); // Audio\r
357 \r
358                 list_queue.Items.Add(item);\r
359             }\r
360         }\r
361 \r
362         /// <summary>\r
363         /// Update the UI elements\r
364         /// </summary>\r
365         private void UpdateUiElementsOnQueueChange()\r
366         {\r
367             if (InvokeRequired)\r
368             {\r
369                 BeginInvoke(new UpdateHandler(UpdateUiElementsOnQueueChange));\r
370                 return;\r
371             }\r
372 \r
373             RedrawQueue();\r
374             lbl_encodesPending.Text = list_queue.Items.Count + " encode(s) pending";\r
375         }\r
376 \r
377         /// <summary>\r
378         /// Set the window up with the current encode information\r
379         /// </summary>\r
380         private void SetCurrentEncodeInformation()\r
381         {\r
382             try\r
383             {\r
384                 if (InvokeRequired)\r
385                 {\r
386                     BeginInvoke(new UpdateHandler(SetCurrentEncodeInformation));\r
387                 }\r
388 \r
389                 QueryParser parsed = QueryParser.Parse(queue.LastEncode.Query);\r
390 \r
391                 // Get title and chapters\r
392                 string title = parsed.Title == 0 ? "Auto" : parsed.Title.ToString();\r
393                 string chapterlbl;\r
394                 if (Equals(parsed.ChapterStart, 0))\r
395                     chapterlbl = "Auto";\r
396                 else\r
397                 {\r
398                     string chapters = parsed.ChapterStart.ToString();\r
399                     if (parsed.ChapterFinish != 0)\r
400                         chapters = chapters + " - " + parsed.ChapterFinish;\r
401                     chapterlbl = chapters;\r
402                 }\r
403 \r
404                 // Get audio information\r
405                 string audio = string.Empty;\r
406                 foreach (AudioTrack track in parsed.AudioInformation)\r
407                 {\r
408                     if (audio != string.Empty) \r
409                         audio += ", " + track.Encoder;\r
410                     else\r
411                         audio = track.Encoder;\r
412                 }\r
413 \r
414                 // found query is a global varible        \r
415                 lbl_encodeStatus.Text = "Encoding ...";\r
416                 lbl_source.Text = queue.LastEncode.Source + "(Title: " + title + " Chapters: " + chapterlbl + ")";\r
417                 lbl_dest.Text = queue.LastEncode.Destination;\r
418                 lbl_encodeOptions.Text = "Video: " + parsed.VideoEncoder + " Audio: " + audio + Environment.NewLine +\r
419                                     "x264 Options: " + parsed.H264Query;\r
420                }\r
421             catch (Exception)\r
422             {\r
423                 // Do Nothing\r
424             }\r
425         }\r
426 \r
427         /* Right Click Menu */\r
428 \r
429         /// <summary>\r
430         /// Handle the Move Up Menu Item\r
431         /// </summary>\r
432         /// <param name="sender">\r
433         /// The sender.\r
434         /// </param>\r
435         /// <param name="e">\r
436         /// The e.\r
437         /// </param>\r
438         private void MnuUpClick(object sender, EventArgs e)\r
439         {\r
440             MoveUp();\r
441         }\r
442 \r
443         /// <summary>\r
444         /// Handle the Move down Menu Item\r
445         /// </summary>\r
446         /// <param name="sender">\r
447         /// The sender.\r
448         /// </param>\r
449         /// <param name="e">\r
450         /// The e.\r
451         /// </param>\r
452         private void MnuDownClick(object sender, EventArgs e)\r
453         {\r
454             MoveDown();\r
455         }\r
456 \r
457         /// <summary>\r
458         /// Edit a job\r
459         /// </summary>\r
460         /// <param name="sender">\r
461         /// The sender.\r
462         /// </param>\r
463         /// <param name="e">\r
464         /// The e.\r
465         /// </param>\r
466         private void MnuEditClick(object sender, EventArgs e)\r
467         {\r
468             if (list_queue.SelectedIndices != null && list_queue.SelectedIndices.Count != 0)\r
469             {\r
470                 lock (queue)\r
471                 {\r
472                     lock (list_queue)\r
473                     {\r
474                         int index = list_queue.SelectedIndices[0];\r
475                         mainWindow.RecievingJob(queue.GetJob(index));\r
476                         queue.Remove(index);\r
477                         RedrawQueue();\r
478                     }\r
479                 }\r
480             }\r
481         }\r
482 \r
483         /// <summary>\r
484         /// Handle the delete Menu Item\r
485         /// </summary>\r
486         /// <param name="sender">\r
487         /// The sender.\r
488         /// </param>\r
489         /// <param name="e">\r
490         /// The e.\r
491         /// </param>\r
492         private void MnuDeleteClick(object sender, EventArgs e)\r
493         {\r
494             DeleteSelectedItems();\r
495         }\r
496 \r
497         /* Keyboard Shortcuts */\r
498 \r
499         /// <summary>\r
500         /// Handle the delete keyboard press\r
501         /// </summary>\r
502         /// <param name="sender">\r
503         /// The sender.\r
504         /// </param>\r
505         /// <param name="e">\r
506         /// The e.\r
507         /// </param>\r
508         private void ListQueueDeleteKey(object sender, KeyEventArgs e)\r
509         {\r
510             if (e.KeyCode == Keys.Delete)\r
511                 DeleteSelectedItems();\r
512         }\r
513 \r
514         /* Queue Management */\r
515 \r
516         /// <summary>\r
517         /// Move items up in the queue\r
518         /// </summary>\r
519         private void MoveUp()\r
520         {\r
521             // If there are selected items and the first item is not selected\r
522             if (list_queue.SelectedIndices.Count > 0 && !list_queue.SelectedIndices.Contains(0))\r
523             {\r
524                 // Copy the selected indices to preserve them during the movement\r
525                 List<int> selectedIndices = new List<int>(list_queue.SelectedIndices.Count);\r
526                 foreach (int selectedIndex in list_queue.SelectedIndices)\r
527                     selectedIndices.Add(selectedIndex);\r
528 \r
529                 // Move up each selected item\r
530                 foreach (int selectedIndex in selectedIndices)\r
531                     queue.MoveUp(selectedIndex);\r
532 \r
533                 // Keep the selected item(s) selected, now moved up one index\r
534                 foreach (int selectedIndex in selectedIndices)\r
535                     if (selectedIndex - 1 > -1) // Defensive programming: ensure index is good\r
536                         list_queue.Items[selectedIndex - 1].Selected = true;\r
537             }\r
538 \r
539             list_queue.Select(); // Activate the control to show the selected items\r
540         }\r
541 \r
542         /// <summary>\r
543         /// Move items down in the queue\r
544         /// </summary>\r
545         private void MoveDown()\r
546         {\r
547             // If there are selected items and the last item is not selected\r
548             if (list_queue.SelectedIndices.Count > 0 &&\r
549                 !list_queue.SelectedIndices.Contains(list_queue.Items[list_queue.Items.Count - 1].Index))\r
550             {\r
551                 // Copy the selected indices to preserve them during the movement\r
552                 List<int> selectedIndices = new List<int>(list_queue.SelectedIndices.Count);\r
553                 foreach (int selectedIndex in list_queue.SelectedIndices)\r
554                     selectedIndices.Add(selectedIndex);\r
555 \r
556                 // Reverse the indices to move the items down from last to first (preserves indices)\r
557                 selectedIndices.Reverse();\r
558 \r
559                 // Move down each selected item\r
560                 foreach (int selectedIndex in selectedIndices)\r
561                     queue.MoveDown(selectedIndex);\r
562 \r
563                 // Keep the selected item(s) selected, now moved down one index\r
564                 foreach (int selectedIndex in selectedIndices)\r
565                     if (selectedIndex + 1 < list_queue.Items.Count) // Defensive programming: ensure index is good\r
566                         list_queue.Items[selectedIndex + 1].Selected = true;\r
567             }\r
568 \r
569             list_queue.Select(); // Activate the control to show the selected items\r
570         }\r
571 \r
572         /// <summary>\r
573         /// Delete the currently selected items on the queue\r
574         /// </summary>\r
575         private void DeleteSelectedItems()\r
576         {\r
577             // If there are selected items\r
578             if (list_queue.SelectedIndices.Count > 0)\r
579             {\r
580                 // Save the selected indices to select them after the move\r
581                 List<int> selectedIndices = new List<int>(list_queue.SelectedIndices.Count);\r
582                 foreach (int selectedIndex in list_queue.SelectedIndices)\r
583                     selectedIndices.Add(selectedIndex);\r
584 \r
585                 int firstSelectedIndex = selectedIndices[0];\r
586 \r
587                 // Reverse the list to delete the items from last to first (preserves indices)\r
588                 selectedIndices.Reverse();\r
589 \r
590                 // Remove each selected item\r
591                 foreach (int selectedIndex in selectedIndices)\r
592                     queue.Remove(selectedIndex);\r
593 \r
594                 // Select the item where the first deleted item was previously\r
595                 if (firstSelectedIndex < list_queue.Items.Count)\r
596                     list_queue.Items[firstSelectedIndex].Selected = true;\r
597             }\r
598 \r
599             list_queue.Select(); // Activate the control to show the selected items\r
600         }\r
601 \r
602         /* Queue Import / Export features */\r
603 \r
604         /// <summary>\r
605         /// Create a batch script\r
606         /// </summary>\r
607         /// <param name="sender">\r
608         /// The sender.\r
609         /// </param>\r
610         /// <param name="e">\r
611         /// The e.\r
612         /// </param>\r
613         private void MnuBatchClick(object sender, EventArgs e)\r
614         {\r
615             SaveFile.FileName = string.Empty;\r
616             SaveFile.Filter = "Batch|.bat";\r
617             SaveFile.ShowDialog();\r
618             if (SaveFile.FileName != String.Empty)\r
619                 queue.WriteBatchScriptToFile(SaveFile.FileName);\r
620         }\r
621 \r
622         /// <summary>\r
623         /// Export Queue\r
624         /// </summary>\r
625         /// <param name="sender">\r
626         /// The sender.\r
627         /// </param>\r
628         /// <param name="e">\r
629         /// The e.\r
630         /// </param>\r
631         private void MnuExportClick(object sender, EventArgs e)\r
632         {\r
633             SaveFile.FileName = string.Empty;\r
634             SaveFile.Filter = "HandBrake Queue|*.queue";\r
635             SaveFile.ShowDialog();\r
636             if (SaveFile.FileName != String.Empty)\r
637                 queue.WriteQueueStateToFile(SaveFile.FileName);\r
638         }\r
639 \r
640         /// <summary>\r
641         /// Import Queue\r
642         /// </summary>\r
643         /// <param name="sender">\r
644         /// The sender.\r
645         /// </param>\r
646         /// <param name="e">\r
647         /// The e.\r
648         /// </param>\r
649         private void MnuImportClick(object sender, EventArgs e)\r
650         {\r
651             OpenFile.FileName = string.Empty;\r
652             OpenFile.ShowDialog();\r
653             if (OpenFile.FileName != String.Empty)\r
654                 queue.LoadQueueFromFile(OpenFile.FileName);\r
655         }\r
656 \r
657         /// <summary>\r
658         /// Readd current job to queue\r
659         /// </summary>\r
660         /// <param name="sender">\r
661         /// The sender.\r
662         /// </param>\r
663         /// <param name="e">\r
664         /// The e.\r
665         /// </param>\r
666         private void MnuReaddClick(object sender, EventArgs e)\r
667         {\r
668             if (!queue.LastEncode.IsEmpty)\r
669             {\r
670                 queue.Add(\r
671                     queue.LastEncode.Query, \r
672                     queue.LastEncode.Title, \r
673                     queue.LastEncode.Source,\r
674                     queue.LastEncode.Destination,\r
675                     queue.LastEncode.CustomQuery);\r
676             }\r
677         }\r
678 \r
679         /* Overrides */\r
680 \r
681         /// <summary>\r
682         /// Hide's the window when the user tries to "x" out of the window instead of closing it.\r
683         /// </summary>\r
684         /// <param name="e">\r
685         /// The e.\r
686         /// </param>\r
687         protected override void OnClosing(CancelEventArgs e)\r
688         {\r
689             e.Cancel = true;\r
690             this.Hide();\r
691             base.OnClosing(e);\r
692         }\r
693 \r
694         /// <summary>\r
695         /// Change the OnComplete option setting.\r
696         /// </summary>\r
697         /// <param name="sender">\r
698         /// The sender.\r
699         /// </param>\r
700         /// <param name="e">\r
701         /// The EventArgs.\r
702         /// </param>\r
703         private void CompleteOptionChanged(object sender, EventArgs e)\r
704         {\r
705             Properties.Settings.Default.CompletionOption = drp_completeOption.Text;\r
706             Properties.Settings.Default.Save();\r
707         }\r
708     }\r
709 }