OSDN Git Service

svnプロパティをファイルの種類に応じたものに更新
[wptscs/wpts.git] / Wptscs / MainForm.cs
index 391227c..07c6c2e 100644 (file)
-// ================================================================================================\r
-// <summary>\r
-//      Wikipedia翻訳支援ツール主画面クラスソース</summary>\r
-//\r
-// <copyright file="MainForm.cs" company="honeplusのメモ帳">\r
-//      Copyright (C) 2011 Honeplus. All rights reserved.</copyright>\r
-// <author>\r
-//      Honeplus</author>\r
-// ================================================================================================\r
-\r
-namespace Honememo.Wptscs\r
-{\r
-    using System;\r
-    using System.Collections.Generic;\r
-    using System.ComponentModel;\r
-    using System.Data;\r
-    using System.Drawing;\r
-    using System.IO;\r
-    using System.Text;\r
-    using System.Windows.Forms;\r
-    using Honememo.Utilities;\r
-    using Honememo.Wptscs.Logics;\r
-    using Honememo.Wptscs.Models;\r
-    using Honememo.Wptscs.Properties;\r
-\r
-    /// <summary>\r
-    /// Wikipedia翻訳支援ツール主画面のクラスです。\r
-    /// </summary>\r
-    public partial class MainForm : Form\r
-    {\r
-        #region private変数\r
-\r
-        /// <summary>\r
-        /// 現在読み込んでいるアプリケーションの設定。\r
-        /// </summary>\r
-        private Config config;\r
-\r
-        /// <summary>\r
-        /// 検索支援処理クラスのオブジェクト。\r
-        /// </summary>\r
-        private Translator translate;\r
-\r
-        /// <summary>\r
-        /// 表示済みログ文字列長。\r
-        /// </summary>\r
-        private int logLastLength;\r
-\r
-        #endregion\r
-\r
-        #region コンストラクタ\r
-\r
-        /// <summary>\r
-        /// コンストラクタ。初期化メソッド呼び出しのみ。\r
-        /// </summary>\r
-        public MainForm()\r
-        {\r
-            // Windows フォーム デザイナで生成されたコード\r
-            this.InitializeComponent();\r
-        }\r
-\r
-        #endregion\r
-\r
-        #region 各イベントのメソッド\r
-\r
-        /// <summary>\r
-        /// フォームロード時の処理。初期化。\r
-        /// </summary>\r
-        /// <param name="sender">イベント発生オブジェクト。</param>\r
-        /// <param name="e">発生したイベント。</param>\r
-        private void MainForm_Load(object sender, EventArgs e)\r
-        {\r
-            // 設定ファイルの読み込み\r
-            if (!this.LoadConfig())\r
-            {\r
-                // 読み込み失敗時はどうしようもないのでそのまま終了\r
-                this.Close();\r
-            }\r
-\r
-            this.translate = null;\r
-            Control.CheckForIllegalCrossThreadCalls = false;\r
-\r
-            // コンボボックス設定\r
-            this.Initialize();\r
-\r
-            // 前回の処理状態を復元\r
-            this.textBoxSaveDirectory.Text = Settings.Default.SaveDirectory;\r
-            this.comboBoxSource.SelectedText = Settings.Default.LastSelectedSource;\r
-            this.comboBoxTarget.SelectedText = Settings.Default.LastSelectedTarget;\r
-\r
-            // コンボボックス変更時の処理をコール\r
-            this.ComboBoxSource_SelectedIndexChanged(sender, e);\r
-            this.ComboBoxTarget_SelectedIndexChanged(sender, e);\r
-        }\r
-\r
-        /// <summary>\r
-        /// フォームクローズ時の処理。処理状態を保存。\r
-        /// </summary>\r
-        /// <param name="sender">イベント発生オブジェクト。</param>\r
-        /// <param name="e">発生したイベント。</param>\r
-        private void MainForm_FormClosed(object sender, FormClosedEventArgs e)\r
-        {\r
-            // 現在の作業フォルダ、絞込み文字列を保存\r
-            Settings.Default.SaveDirectory = this.textBoxSaveDirectory.Text;\r
-            Settings.Default.LastSelectedSource = this.comboBoxSource.Text;\r
-            Settings.Default.LastSelectedTarget = this.comboBoxTarget.Text;\r
-            Settings.Default.Save();\r
-        }\r
-\r
-        /// <summary>\r
-        /// 翻訳元コンボボックス変更時の処理。\r
-        /// </summary>\r
-        /// <param name="sender">イベント発生オブジェクト。</param>\r
-        /// <param name="e">発生したイベント。</param>\r
-        private void ComboBoxSource_SelectedIndexChanged(object sender, EventArgs e)\r
-        {\r
-            // ラベルに言語名を表示する\r
-            this.labelSource.Text = String.Empty;\r
-            this.linkLabelSourceURL.Text = "http://";\r
-            if (!String.IsNullOrWhiteSpace(this.comboBoxSource.Text))\r
-            {\r
-                this.comboBoxSource.Text = this.comboBoxSource.Text.Trim().ToLower();\r
-\r
-                // その言語の、ユーザーが使用している言語での表示名を表示\r
-                // (日本語環境だったら日本語を、英語だったら英語を)\r
-                Language.LanguageName name;\r
-                this.labelSource.Text = String.Empty;\r
-                if (this.config.GetWebsite(this.comboBoxSource.Text) != null &&\r
-                    this.config.GetWebsite(this.comboBoxSource.Text).Language.Names.TryGetValue(\r
-                    System.Globalization.CultureInfo.CurrentCulture.TwoLetterISOLanguageName,\r
-                    out name))\r
-                {\r
-                    this.labelSource.Text = name.Name;\r
-                }\r
-\r
-                // サーバーURLの表示\r
-                this.linkLabelSourceURL.Text = this.config.GetWebsite(\r
-                    this.comboBoxSource.Text).Location;\r
-            }\r
-        }\r
-\r
-        /// <summary>\r
-        /// 翻訳元コンボボックスフォーカス喪失時の処理。\r
-        /// </summary>\r
-        /// <param name="sender">イベント発生オブジェクト。</param>\r
-        /// <param name="e">発生したイベント。</param>\r
-        private void ComboBoxSource_Leave(object sender, EventArgs e)\r
-        {\r
-            // 直接入力された場合の対策、変更時の処理をコール\r
-            this.ComboBoxSource_SelectedIndexChanged(sender, e);\r
-        }\r
-\r
-        /// <summary>\r
-        /// リンクラベルのリンククリック時の処理。\r
-        /// </summary>\r
-        /// <param name="sender">イベント発生オブジェクト。</param>\r
-        /// <param name="e">発生したイベント。</param>\r
-        private void LinkLabelSourceURL_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)\r
-        {\r
-            // リンクを開く\r
-            System.Diagnostics.Process.Start(((LinkLabel)sender).Text);\r
-        }\r
-\r
-        /// <summary>\r
-        /// 翻訳先コンボボックス変更時の処理。\r
-        /// </summary>\r
-        /// <param name="sender">イベント発生オブジェクト。</param>\r
-        /// <param name="e">発生したイベント。</param>\r
-        private void ComboBoxTarget_SelectedIndexChanged(object sender, EventArgs e)\r
-        {\r
-            // ラベルに言語名を表示する\r
-            this.labelTarget.Text = String.Empty;\r
-            if (!String.IsNullOrWhiteSpace(this.comboBoxTarget.Text))\r
-            {\r
-                this.comboBoxTarget.Text = this.comboBoxTarget.Text.Trim().ToLower();\r
-\r
-                // その言語の、ユーザーが使用している言語での表示名を表示\r
-                // (日本語環境だったら日本語を、英語だったら英語を)\r
-                if (this.config.GetWebsite(\r
-                    this.comboBoxTarget.Text) != null)\r
-                {\r
-                    this.labelTarget.Text = this.config.GetWebsite(\r
-                        this.comboBoxTarget.Text).Language.Names[System.Globalization.CultureInfo.CurrentCulture.TwoLetterISOLanguageName].Name;\r
-                }\r
-            }\r
-        }\r
-\r
-        /// <summary>\r
-        /// 翻訳先コンボボックスフォーカス喪失時の処理。\r
-        /// </summary>\r
-        /// <param name="sender">イベント発生オブジェクト。</param>\r
-        /// <param name="e">発生したイベント。</param>\r
-        private void ComboBoxTarget_Leave(object sender, EventArgs e)\r
-        {\r
-            // 直接入力された場合の対策、変更時の処理をコール\r
-            this.ComboBoxTarget_SelectedIndexChanged(sender, e);\r
-        }\r
-\r
-        /// <summary>\r
-        /// 設定ボタン押下時の処理。\r
-        /// </summary>\r
-        /// <param name="sender">イベント発生オブジェクト。</param>\r
-        /// <param name="e">発生したイベント。</param>\r
-        private void ButtonConfig_Click(object sender, EventArgs e)\r
-        {\r
-            // 設定画面を開く\r
-            ConfigForm form = new ConfigForm(this.config);\r
-            form.ShowDialog();\r
-\r
-            // 戻ってきたら設定ファイルを再読み込み\r
-            // ※ 万が一エラーでもとりあえず続行\r
-            this.LoadConfig();\r
-\r
-            // コンボボックス設定\r
-            string backupSourceSelected = this.comboBoxSource.SelectedText;\r
-            string backupSourceTarget = this.comboBoxTarget.SelectedText;\r
-            this.Initialize();\r
-            this.comboBoxSource.SelectedText = backupSourceSelected;\r
-            this.comboBoxTarget.SelectedText = backupSourceTarget;\r
-\r
-            // コンボボックス変更時の処理をコール\r
-            this.ComboBoxSource_SelectedIndexChanged(sender, e);\r
-            this.ComboBoxTarget_SelectedIndexChanged(sender, e);\r
-        }\r
-\r
-        /// <summary>\r
-        /// 参照ボタン押下時の処理。\r
-        /// </summary>\r
-        /// <param name="sender">イベント発生オブジェクト。</param>\r
-        /// <param name="e">発生したイベント。</param>\r
-        private void ButtonSaveDirectory_Click(object sender, EventArgs e)\r
-        {\r
-            // フォルダ名が入力されている場合、それを初期位置に設定\r
-            if (!String.IsNullOrEmpty(this.textBoxSaveDirectory.Text))\r
-            {\r
-                this.folderBrowserDialogSaveDirectory.SelectedPath = this.textBoxSaveDirectory.Text;\r
-            }\r
-\r
-            // フォルダ選択画面をオープン\r
-            if (this.folderBrowserDialogSaveDirectory.ShowDialog() == System.Windows.Forms.DialogResult.OK)\r
-            {\r
-                // フォルダが選択された場合、フォルダ名に選択されたフォルダを設定\r
-                this.textBoxSaveDirectory.Text = this.folderBrowserDialogSaveDirectory.SelectedPath;\r
-            }\r
-        }\r
-\r
-        /// <summary>\r
-        /// 出力先テキストボックスフォーカス喪失時の処理。\r
-        /// </summary>\r
-        /// <param name="sender">イベント発生オブジェクト。</param>\r
-        /// <param name="e">発生したイベント。</param>\r
-        private void TextBoxSaveDirectory_Leave(object sender, EventArgs e)\r
-        {\r
-            // 空白を削除\r
-            this.textBoxSaveDirectory.Text = this.textBoxSaveDirectory.Text.Trim();\r
-        }\r
-\r
-        /// <summary>\r
-        /// 実行ボタン押下時の処理。\r
-        /// </summary>\r
-        /// <param name="sender">イベント発生オブジェクト。</param>\r
-        /// <param name="e">発生したイベント。</param>\r
-        private void ButtonRun_Click(object sender, EventArgs e)\r
-        {\r
-            // フォーム入力値をチェック\r
-            if (String.IsNullOrWhiteSpace(this.comboBoxSource.Text))\r
-            {\r
-                FormUtils.WarningDialog(Resources.WarningMessageNotSelectedSource);\r
-                this.comboBoxSource.Focus();\r
-                return;\r
-            }\r
-            else if (String.IsNullOrWhiteSpace(this.comboBoxTarget.Text))\r
-            {\r
-                FormUtils.WarningDialog(Resources.WarningMessageNotSelectedTarget);\r
-                this.comboBoxTarget.Focus();\r
-                return;\r
-            }\r
-            else if (!String.IsNullOrWhiteSpace(this.comboBoxSource.Text)\r
-                && this.comboBoxSource.Text == this.comboBoxTarget.Text)\r
-            {\r
-                FormUtils.WarningDialog(Resources.WarningMessageEqualsSourceAndTarget);\r
-                this.comboBoxTarget.Focus();\r
-                return;\r
-            }\r
-            else if (String.IsNullOrWhiteSpace(this.textBoxSaveDirectory.Text))\r
-            {\r
-                FormUtils.WarningDialog(Resources.WarningMessageEmptySaveDirectory);\r
-                this.textBoxSaveDirectory.Focus();\r
-                return;\r
-            }\r
-            else if (!Directory.Exists(this.textBoxSaveDirectory.Text))\r
-            {\r
-                FormUtils.WarningDialog(Resources.WarningMessageIgnoreSaveDirectory);\r
-                this.textBoxSaveDirectory.Focus();\r
-                return;\r
-            }\r
-            else if (String.IsNullOrWhiteSpace(this.textBoxArticle.Text))\r
-            {\r
-                FormUtils.WarningDialog(Resources.WarningMessageEmptyArticle);\r
-                this.textBoxArticle.Focus();\r
-                return;\r
-            }\r
-\r
-            // 画面をロック\r
-            this.LockOperation();\r
-\r
-            // バックグラウンド処理を実行\r
-            this.backgroundWorkerRun.RunWorkerAsync();\r
-        }\r
-\r
-        /// <summary>\r
-        /// 中止ボタン押下時の処理。\r
-        /// </summary>\r
-        /// <param name="sender">イベント発生オブジェクト。</param>\r
-        /// <param name="e">発生したイベント。</param>\r
-        private void ButtonStop_Click(object sender, EventArgs e)\r
-        {\r
-            // 処理を中断\r
-            this.buttonStop.Enabled = false;\r
-            if (this.backgroundWorkerRun.IsBusy == true)\r
-            {\r
-                System.Diagnostics.Debug.WriteLine("MainForm.-Stop_Click > 処理中断");\r
-                this.backgroundWorkerRun.CancelAsync();\r
-                if (this.translate != null)\r
-                {\r
-                    this.translate.CancellationPending = true;\r
-                }\r
-            }\r
-        }\r
-\r
-        /// <summary>\r
-        /// 実行ボタン バックグラウンド処理(スレッド)。\r
-        /// </summary>\r
-        /// <param name="sender">イベント発生オブジェクト。</param>\r
-        /// <param name="e">発生したイベント。</param>\r
-        private void BackgroundWorkerRun_DoWork(object sender, DoWorkEventArgs e)\r
-        {\r
-            try\r
-            {\r
-                // 翻訳支援処理の前処理\r
-                this.textBoxLog.Clear();\r
-                this.logLastLength = 0;\r
-                this.textBoxLog.AppendText(\r
-                    String.Format(\r
-                        Resources.LogMessage_Start,\r
-                        FormUtils.ApplicationName(),\r
-                        DateTime.Now.ToString("F")));\r
-\r
-                // 処理結果とログのための出力ファイル名を作成\r
-                string fileName;\r
-                string logName;\r
-                this.MakeFileName(out fileName, out logName, this.textBoxArticle.Text.Trim(), this.textBoxSaveDirectory.Text);\r
-\r
-                // 翻訳支援処理を実行し、結果とログをファイルに出力\r
-                try\r
-                {\r
-                    this.translate = Translator.Create(this.config, this.comboBoxSource.Text, this.comboBoxTarget.Text);\r
-                }\r
-                catch (NotImplementedException)\r
-                {\r
-                    // 将来の拡張用\r
-                    this.textBoxLog.AppendText(String.Format(Resources.InformationMessage_DevelopingMethod, "Wikipedia以外の処理"));\r
-                    FormUtils.InformationDialog(Resources.InformationMessage_DevelopingMethod, "Wikipedia以外の処理");\r
-                    return;\r
-                }\r
-\r
-                this.translate.LogUpdate += new EventHandler(this.GetLogUpdate);\r
-\r
-                // 実行前に、ユーザーから中止要求がされているかをチェック\r
-                if (this.backgroundWorkerRun.CancellationPending)\r
-                {\r
-                    this.textBoxLog.AppendText(String.Format(Resources.LogMessage_Stop, logName));\r
-                }\r
-                else\r
-                {\r
-                    // 翻訳支援処理を実行\r
-                    bool successFlag = this.translate.Run(this.textBoxArticle.Text.Trim());\r
-\r
-                    // 処理に時間がかかるため、出力ファイル名を再確認\r
-                    this.MakeFileName(out fileName, out logName, this.textBoxArticle.Text.Trim(), this.textBoxSaveDirectory.Text);\r
-                    if (successFlag)\r
-                    {\r
-                        // 処理結果を出力\r
-                        try\r
-                        {\r
-                            StreamWriter sw = new StreamWriter(Path.Combine(this.textBoxSaveDirectory.Text, fileName));\r
-                            try\r
-                            {\r
-                                sw.Write(this.translate.Text);\r
-                                this.textBoxLog.AppendText(String.Format(Resources.LogMessage_End, fileName, logName));\r
-                            }\r
-                            finally\r
-                            {\r
-                                sw.Close();\r
-                            }\r
-                        }\r
-                        catch (Exception ex)\r
-                        {\r
-                            this.textBoxLog.AppendText(String.Format(Resources.LogMessage_ErrorFileSave, Path.Combine(this.textBoxSaveDirectory.Text, fileName), ex.Message));\r
-                            this.textBoxLog.AppendText(String.Format(Resources.LogMessage_Stop, logName));\r
-                        }\r
-                    }\r
-                    else\r
-                    {\r
-                        this.textBoxLog.AppendText(String.Format(Resources.LogMessage_Stop, logName));\r
-                    }\r
-                }\r
-\r
-                // ログを出力\r
-                try\r
-                {\r
-                    StreamWriter sw = new StreamWriter(Path.Combine(this.textBoxSaveDirectory.Text, logName));\r
-                    try\r
-                    {\r
-                        sw.Write(this.textBoxLog.Text);\r
-                    }\r
-                    finally\r
-                    {\r
-                        sw.Close();\r
-                    }\r
-                }\r
-                catch (Exception ex)\r
-                {\r
-                    this.textBoxLog.AppendText(String.Format(Resources.LogMessage_ErrorFileSave, Path.Combine(this.textBoxSaveDirectory.Text, logName), ex.Message));\r
-                }\r
-            }\r
-            catch (Exception ex)\r
-            {\r
-                this.textBoxLog.AppendText("\r\n" + String.Format(Resources.ErrorMessageDevelopmentError, ex.Message, ex.StackTrace) + "\r\n");\r
-                System.Diagnostics.Debug.WriteLine("MainForm.backgroundWorkerRun_DoWork > 想定外のエラー : " + ex.Message);\r
-                System.Diagnostics.Debug.WriteLine(ex.StackTrace);\r
-            }\r
-        }\r
-\r
-        /// <summary>\r
-        /// 実行ボタン バックグラウンド処理(終了時)。\r
-        /// </summary>\r
-        /// <param name="sender">イベント発生オブジェクト。</param>\r
-        /// <param name="e">発生したイベント。</param>\r
-        private void BackgroundWorkerRun_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)\r
-        {\r
-            // 設定ファイルのキャッシュ情報を更新\r
-            try\r
-            {\r
-                this.config.Save(Settings.Default.ConfigurationFile);\r
-            }\r
-            catch (Exception ex)\r
-            {\r
-                FormUtils.WarningDialog(\r
-                    Resources.WarningMessageCacheSaveFailed,\r
-                    ex.Message);\r
-            }\r
-\r
-            // 画面をロック中から解放\r
-            this.Release();\r
-        }\r
-\r
-        #endregion\r
-\r
-        #region それ以外のメソッド\r
-\r
-        /// <summary>\r
-        /// 画面初期化処理。\r
-        /// </summary>\r
-        private void Initialize()\r
-        {\r
-            // コンボボックス設定\r
-            this.comboBoxSource.Items.Clear();\r
-            this.comboBoxTarget.Items.Clear();\r
-\r
-            // 設定ファイルに存在する全言語を選択肢として登録する\r
-            foreach (Website site in this.config.Websites)\r
-            {\r
-                this.comboBoxSource.Items.Add(site.Language.Code);\r
-                this.comboBoxTarget.Items.Add(site.Language.Code);\r
-            }\r
-        }\r
-\r
-        /// <summary>\r
-        /// 設定ファイル読み込み。\r
-        /// </summary>\r
-        /// <returns>読み込み成功時は<c>true</c>。</returns>\r
-        private bool LoadConfig()\r
-        {\r
-            // 設定ファイルの読み込み\r
-            try\r
-            {\r
-                this.config = Config.GetInstance(Settings.Default.ConfigurationFile);\r
-            }\r
-            catch (FileNotFoundException ex)\r
-            {\r
-                // 設定ファイルが見つからない場合\r
-                System.Diagnostics.Debug.WriteLine(\r
-                    "MainForm.LoadConfig > 設定ファイル読み込み失敗 : " + ex.Message);\r
-                FormUtils.ErrorDialog(\r
-                    Resources.ErrorMessageConfigNotFound,\r
-                    Settings.Default.ConfigurationFile);\r
-\r
-                return false;\r
-            }\r
-            catch (Exception ex)\r
-            {\r
-                System.Diagnostics.Debug.WriteLine(\r
-                    "MainForm.LoadConfig > 設定ファイル読み込み時エラー : " + ex.StackTrace);\r
-                FormUtils.ErrorDialog(\r
-                    Resources.ErrorMessageConfigLordFailed,\r
-                    ex.Message);\r
-\r
-                return false;\r
-            }\r
-\r
-            return true;\r
-        }\r
-\r
-        /// <summary>\r
-        /// 画面をロック中に移行。\r
-        /// </summary>\r
-        private void LockOperation()\r
-        {\r
-            // 各種ボタンなどを入力不可に変更\r
-            this.groupBoxTransfer.Enabled = false;\r
-            this.groupBoxSaveDirectory.Enabled = false;\r
-            this.textBoxArticle.Enabled = false;\r
-            this.buttonRun.Enabled = false;\r
-\r
-            // 中止ボタンを有効に変更\r
-            this.buttonStop.Enabled = true;\r
-        }\r
-\r
-        /// <summary>\r
-        /// 画面をロック中から解放。\r
-        /// </summary>\r
-        private void Release()\r
-        {\r
-            // 中止ボタンを入力不可に変更\r
-            this.buttonStop.Enabled = false;\r
-\r
-            // 各種ボタンなどを有効に変更\r
-            this.groupBoxTransfer.Enabled = true;\r
-            this.groupBoxSaveDirectory.Enabled = true;\r
-            this.textBoxArticle.Enabled = true;\r
-            this.buttonRun.Enabled = true;\r
-        }\r
-\r
-        /// <summary>\r
-        /// 渡された文字列から.txtと.logの重複していないファイル名を作成。\r
-        /// </summary>\r
-        /// <param name="fileName">出力結果ファイル名。</param>\r
-        /// <param name="logName">出力ログファイル名。</param>\r
-        /// <param name="text">出力する結果テキスト。</param>\r
-        /// <param name="dir">出力先ディレクトリ。</param>\r
-        /// <returns><c>true</c> 出力成功</returns>\r
-        private bool MakeFileName(out string fileName, out string logName, string text, string dir)\r
-        {\r
-            // 出力先フォルダに存在しないファイル名(の拡張子より前)を作成\r
-            // ※渡されたWikipedia等の記事名にファイル名に使えない文字が含まれている場合、_ に置き換える\r
-            //   また、ファイル名が重複している場合、xx[0].txtのように連番を付ける\r
-            string fileNameBase = FormUtils.ReplaceInvalidFileNameChars(text);\r
-            fileName = fileNameBase + ".txt";\r
-            logName = fileNameBase + ".log";\r
-            bool success = false;\r
-            for (int i = 0; i < 100000; i++)\r
-            {\r
-                // ※100000まで試して空きが見つからないことは無いはず、もし見つからなかったら最後のを上書き\r
-                if (!File.Exists(Path.Combine(dir, fileName))\r
-                    && !File.Exists(Path.Combine(dir, logName)))\r
-                {\r
-                    success = true;\r
-                    break;\r
-                }\r
-\r
-                fileName = fileNameBase + "[" + i + "]" + ".txt";\r
-                logName = fileNameBase + "[" + i + "]" + ".log";\r
-            }\r
-\r
-            // 結果設定\r
-            return success;\r
-        }\r
-\r
-        /// <summary>\r
-        /// 翻訳支援処理クラスのイベント用。\r
-        /// </summary>\r
-        /// <param name="sender">イベント発生オブジェクト。</param>\r
-        /// <param name="e">発生したイベント。</param>\r
-        private void GetLogUpdate(object sender, System.EventArgs e)\r
-        {\r
-            // 前回以降に追加されたログをテキストボックスに出力\r
-            int length = this.translate.Log.Length;\r
-            if (length > this.logLastLength)\r
-            {\r
-                this.textBoxLog.AppendText(this.translate.Log.Substring(this.logLastLength, length - this.logLastLength));\r
-            }\r
-\r
-            this.logLastLength = length;\r
-        }\r
-\r
-        #endregion\r
-    }\r
+// ================================================================================================
+// <summary>
+//      Wikipedia翻訳支援ツール主画面クラスソース</summary>
+//
+// <copyright file="MainForm.cs" company="honeplusのメモ帳">
+//      Copyright (C) 2011 Honeplus. All rights reserved.</copyright>
+// <author>
+//      Honeplus</author>
+// ================================================================================================
+
+namespace Honememo.Wptscs
+{
+    using System;
+    using System.Collections.Generic;
+    using System.ComponentModel;
+    using System.Data;
+    using System.Drawing;
+    using System.IO;
+    using System.Text;
+    using System.Windows.Forms;
+    using Honememo.Utilities;
+    using Honememo.Wptscs.Logics;
+    using Honememo.Wptscs.Models;
+    using Honememo.Wptscs.Properties;
+
+    /// <summary>
+    /// Wikipedia翻訳支援ツール主画面のクラスです。
+    /// </summary>
+    public partial class MainForm : Form
+    {
+        #region private変数
+
+        /// <summary>
+        /// 現在読み込んでいるアプリケーションの設定。
+        /// </summary>
+        private Config config;
+
+        /// <summary>
+        /// 検索支援処理クラスのオブジェクト。
+        /// </summary>
+        private Translator translate;
+
+        /// <summary>
+        /// 表示済みログ文字列長。
+        /// </summary>
+        private int logLastLength;
+
+        #endregion
+
+        #region コンストラクタ
+
+        /// <summary>
+        /// コンストラクタ。初期化メソッド呼び出しのみ。
+        /// </summary>
+        public MainForm()
+        {
+            // Windows フォーム デザイナで生成されたコード
+            this.InitializeComponent();
+        }
+
+        #endregion
+
+        #region 各イベントのメソッド
+
+        /// <summary>
+        /// フォームロード時の処理。初期化。
+        /// </summary>
+        /// <param name="sender">イベント発生オブジェクト。</param>
+        /// <param name="e">発生したイベント。</param>
+        private void MainForm_Load(object sender, EventArgs e)
+        {
+            // 設定ファイルの読み込み
+            if (!this.LoadConfig())
+            {
+                // 読み込み失敗時はどうしようもないのでそのまま終了
+                this.Close();
+            }
+
+            this.translate = null;
+            Control.CheckForIllegalCrossThreadCalls = false;
+
+            // コンボボックス設定
+            this.Initialize();
+
+            // 前回の処理状態を復元
+            this.textBoxSaveDirectory.Text = Settings.Default.SaveDirectory;
+            this.comboBoxSource.SelectedText = Settings.Default.LastSelectedSource;
+            this.comboBoxTarget.SelectedText = Settings.Default.LastSelectedTarget;
+
+            // コンボボックス変更時の処理をコール
+            this.ComboBoxSource_SelectedIndexChanged(sender, e);
+            this.ComboBoxTarget_SelectedIndexChanged(sender, e);
+        }
+
+        /// <summary>
+        /// フォームクローズ時の処理。処理状態を保存。
+        /// </summary>
+        /// <param name="sender">イベント発生オブジェクト。</param>
+        /// <param name="e">発生したイベント。</param>
+        private void MainForm_FormClosed(object sender, FormClosedEventArgs e)
+        {
+            // 現在の作業フォルダ、絞込み文字列を保存
+            Settings.Default.SaveDirectory = this.textBoxSaveDirectory.Text;
+            Settings.Default.LastSelectedSource = this.comboBoxSource.Text;
+            Settings.Default.LastSelectedTarget = this.comboBoxTarget.Text;
+            Settings.Default.Save();
+        }
+
+        /// <summary>
+        /// 翻訳元コンボボックス変更時の処理。
+        /// </summary>
+        /// <param name="sender">イベント発生オブジェクト。</param>
+        /// <param name="e">発生したイベント。</param>
+        private void ComboBoxSource_SelectedIndexChanged(object sender, EventArgs e)
+        {
+            // ラベルに言語名を表示する
+            this.labelSource.Text = String.Empty;
+            this.linkLabelSourceURL.Text = "http://";
+            if (!String.IsNullOrWhiteSpace(this.comboBoxSource.Text))
+            {
+                this.comboBoxSource.Text = this.comboBoxSource.Text.Trim().ToLower();
+
+                // その言語の、ユーザーが使用している言語での表示名を表示
+                // (日本語環境だったら日本語を、英語だったら英語を)
+                Language.LanguageName name;
+                this.labelSource.Text = String.Empty;
+                if (this.config.GetWebsite(this.comboBoxSource.Text) != null &&
+                    this.config.GetWebsite(this.comboBoxSource.Text).Language.Names.TryGetValue(
+                    System.Globalization.CultureInfo.CurrentCulture.TwoLetterISOLanguageName,
+                    out name))
+                {
+                    this.labelSource.Text = name.Name;
+                }
+
+                // サーバーURLの表示
+                this.linkLabelSourceURL.Text = this.config.GetWebsite(
+                    this.comboBoxSource.Text).Location;
+            }
+        }
+
+        /// <summary>
+        /// 翻訳元コンボボックスフォーカス喪失時の処理。
+        /// </summary>
+        /// <param name="sender">イベント発生オブジェクト。</param>
+        /// <param name="e">発生したイベント。</param>
+        private void ComboBoxSource_Leave(object sender, EventArgs e)
+        {
+            // 直接入力された場合の対策、変更時の処理をコール
+            this.ComboBoxSource_SelectedIndexChanged(sender, e);
+        }
+
+        /// <summary>
+        /// リンクラベルのリンククリック時の処理。
+        /// </summary>
+        /// <param name="sender">イベント発生オブジェクト。</param>
+        /// <param name="e">発生したイベント。</param>
+        private void LinkLabelSourceURL_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
+        {
+            // リンクを開く
+            System.Diagnostics.Process.Start(((LinkLabel)sender).Text);
+        }
+
+        /// <summary>
+        /// 翻訳先コンボボックス変更時の処理。
+        /// </summary>
+        /// <param name="sender">イベント発生オブジェクト。</param>
+        /// <param name="e">発生したイベント。</param>
+        private void ComboBoxTarget_SelectedIndexChanged(object sender, EventArgs e)
+        {
+            // ラベルに言語名を表示する
+            this.labelTarget.Text = String.Empty;
+            if (!String.IsNullOrWhiteSpace(this.comboBoxTarget.Text))
+            {
+                this.comboBoxTarget.Text = this.comboBoxTarget.Text.Trim().ToLower();
+
+                // その言語の、ユーザーが使用している言語での表示名を表示
+                // (日本語環境だったら日本語を、英語だったら英語を)
+                if (this.config.GetWebsite(
+                    this.comboBoxTarget.Text) != null)
+                {
+                    this.labelTarget.Text = this.config.GetWebsite(
+                        this.comboBoxTarget.Text).Language.Names[System.Globalization.CultureInfo.CurrentCulture.TwoLetterISOLanguageName].Name;
+                }
+            }
+        }
+
+        /// <summary>
+        /// 翻訳先コンボボックスフォーカス喪失時の処理。
+        /// </summary>
+        /// <param name="sender">イベント発生オブジェクト。</param>
+        /// <param name="e">発生したイベント。</param>
+        private void ComboBoxTarget_Leave(object sender, EventArgs e)
+        {
+            // 直接入力された場合の対策、変更時の処理をコール
+            this.ComboBoxTarget_SelectedIndexChanged(sender, e);
+        }
+
+        /// <summary>
+        /// 設定ボタン押下時の処理。
+        /// </summary>
+        /// <param name="sender">イベント発生オブジェクト。</param>
+        /// <param name="e">発生したイベント。</param>
+        private void ButtonConfig_Click(object sender, EventArgs e)
+        {
+            // 設定画面を開く
+            ConfigForm form = new ConfigForm(this.config);
+            form.ShowDialog();
+
+            // 戻ってきたら設定ファイルを再読み込み
+            // ※ 万が一エラーでもとりあえず続行
+            this.LoadConfig();
+
+            // コンボボックス設定
+            string backupSourceSelected = this.comboBoxSource.SelectedText;
+            string backupSourceTarget = this.comboBoxTarget.SelectedText;
+            this.Initialize();
+            this.comboBoxSource.SelectedText = backupSourceSelected;
+            this.comboBoxTarget.SelectedText = backupSourceTarget;
+
+            // コンボボックス変更時の処理をコール
+            this.ComboBoxSource_SelectedIndexChanged(sender, e);
+            this.ComboBoxTarget_SelectedIndexChanged(sender, e);
+        }
+
+        /// <summary>
+        /// 参照ボタン押下時の処理。
+        /// </summary>
+        /// <param name="sender">イベント発生オブジェクト。</param>
+        /// <param name="e">発生したイベント。</param>
+        private void ButtonSaveDirectory_Click(object sender, EventArgs e)
+        {
+            // フォルダ名が入力されている場合、それを初期位置に設定
+            if (!String.IsNullOrEmpty(this.textBoxSaveDirectory.Text))
+            {
+                this.folderBrowserDialogSaveDirectory.SelectedPath = this.textBoxSaveDirectory.Text;
+            }
+
+            // フォルダ選択画面をオープン
+            if (this.folderBrowserDialogSaveDirectory.ShowDialog() == System.Windows.Forms.DialogResult.OK)
+            {
+                // フォルダが選択された場合、フォルダ名に選択されたフォルダを設定
+                this.textBoxSaveDirectory.Text = this.folderBrowserDialogSaveDirectory.SelectedPath;
+            }
+        }
+
+        /// <summary>
+        /// 出力先テキストボックスフォーカス喪失時の処理。
+        /// </summary>
+        /// <param name="sender">イベント発生オブジェクト。</param>
+        /// <param name="e">発生したイベント。</param>
+        private void TextBoxSaveDirectory_Leave(object sender, EventArgs e)
+        {
+            // 空白を削除
+            this.textBoxSaveDirectory.Text = this.textBoxSaveDirectory.Text.Trim();
+        }
+
+        /// <summary>
+        /// 実行ボタン押下時の処理。
+        /// </summary>
+        /// <param name="sender">イベント発生オブジェクト。</param>
+        /// <param name="e">発生したイベント。</param>
+        private void ButtonRun_Click(object sender, EventArgs e)
+        {
+            // フォーム入力値をチェック
+            if (String.IsNullOrWhiteSpace(this.comboBoxSource.Text))
+            {
+                FormUtils.WarningDialog(Resources.WarningMessageNotSelectedSource);
+                this.comboBoxSource.Focus();
+                return;
+            }
+            else if (String.IsNullOrWhiteSpace(this.comboBoxTarget.Text))
+            {
+                FormUtils.WarningDialog(Resources.WarningMessageNotSelectedTarget);
+                this.comboBoxTarget.Focus();
+                return;
+            }
+            else if (!String.IsNullOrWhiteSpace(this.comboBoxSource.Text)
+                && this.comboBoxSource.Text == this.comboBoxTarget.Text)
+            {
+                FormUtils.WarningDialog(Resources.WarningMessageEqualsSourceAndTarget);
+                this.comboBoxTarget.Focus();
+                return;
+            }
+            else if (String.IsNullOrWhiteSpace(this.textBoxSaveDirectory.Text))
+            {
+                FormUtils.WarningDialog(Resources.WarningMessageEmptySaveDirectory);
+                this.textBoxSaveDirectory.Focus();
+                return;
+            }
+            else if (!Directory.Exists(this.textBoxSaveDirectory.Text))
+            {
+                FormUtils.WarningDialog(Resources.WarningMessageIgnoreSaveDirectory);
+                this.textBoxSaveDirectory.Focus();
+                return;
+            }
+            else if (String.IsNullOrWhiteSpace(this.textBoxArticle.Text))
+            {
+                FormUtils.WarningDialog(Resources.WarningMessageEmptyArticle);
+                this.textBoxArticle.Focus();
+                return;
+            }
+
+            // 画面をロック
+            this.LockOperation();
+
+            // バックグラウンド処理を実行
+            this.backgroundWorkerRun.RunWorkerAsync();
+        }
+
+        /// <summary>
+        /// 中止ボタン押下時の処理。
+        /// </summary>
+        /// <param name="sender">イベント発生オブジェクト。</param>
+        /// <param name="e">発生したイベント。</param>
+        private void ButtonStop_Click(object sender, EventArgs e)
+        {
+            // 処理を中断
+            this.buttonStop.Enabled = false;
+            if (this.backgroundWorkerRun.IsBusy == true)
+            {
+                System.Diagnostics.Debug.WriteLine("MainForm.-Stop_Click > 処理中断");
+                this.backgroundWorkerRun.CancelAsync();
+                if (this.translate != null)
+                {
+                    this.translate.CancellationPending = true;
+                }
+            }
+        }
+
+        /// <summary>
+        /// 実行ボタン バックグラウンド処理(スレッド)。
+        /// </summary>
+        /// <param name="sender">イベント発生オブジェクト。</param>
+        /// <param name="e">発生したイベント。</param>
+        private void BackgroundWorkerRun_DoWork(object sender, DoWorkEventArgs e)
+        {
+            try
+            {
+                // 翻訳支援処理の前処理
+                this.textBoxLog.Clear();
+                this.logLastLength = 0;
+                this.textBoxLog.AppendText(
+                    String.Format(
+                        Resources.LogMessage_Start,
+                        FormUtils.ApplicationName(),
+                        DateTime.Now.ToString("F")));
+
+                // 処理結果とログのための出力ファイル名を作成
+                string fileName;
+                string logName;
+                this.MakeFileName(out fileName, out logName, this.textBoxArticle.Text.Trim(), this.textBoxSaveDirectory.Text);
+
+                // 翻訳支援処理を実行し、結果とログをファイルに出力
+                try
+                {
+                    this.translate = Translator.Create(this.config, this.comboBoxSource.Text, this.comboBoxTarget.Text);
+                }
+                catch (NotImplementedException)
+                {
+                    // 将来の拡張用
+                    this.textBoxLog.AppendText(String.Format(Resources.InformationMessage_DevelopingMethod, "Wikipedia以外の処理"));
+                    FormUtils.InformationDialog(Resources.InformationMessage_DevelopingMethod, "Wikipedia以外の処理");
+                    return;
+                }
+
+                this.translate.LogUpdate += new EventHandler(this.GetLogUpdate);
+
+                // 実行前に、ユーザーから中止要求がされているかをチェック
+                if (this.backgroundWorkerRun.CancellationPending)
+                {
+                    this.textBoxLog.AppendText(String.Format(Resources.LogMessage_Stop, logName));
+                }
+                else
+                {
+                    // 翻訳支援処理を実行
+                    bool successFlag = this.translate.Run(this.textBoxArticle.Text.Trim());
+
+                    // 処理に時間がかかるため、出力ファイル名を再確認
+                    this.MakeFileName(out fileName, out logName, this.textBoxArticle.Text.Trim(), this.textBoxSaveDirectory.Text);
+                    if (successFlag)
+                    {
+                        // 処理結果を出力
+                        try
+                        {
+                            StreamWriter sw = new StreamWriter(Path.Combine(this.textBoxSaveDirectory.Text, fileName));
+                            try
+                            {
+                                sw.Write(this.translate.Text);
+                                this.textBoxLog.AppendText(String.Format(Resources.LogMessage_End, fileName, logName));
+                            }
+                            finally
+                            {
+                                sw.Close();
+                            }
+                        }
+                        catch (Exception ex)
+                        {
+                            this.textBoxLog.AppendText(String.Format(Resources.LogMessage_ErrorFileSave, Path.Combine(this.textBoxSaveDirectory.Text, fileName), ex.Message));
+                            this.textBoxLog.AppendText(String.Format(Resources.LogMessage_Stop, logName));
+                        }
+                    }
+                    else
+                    {
+                        this.textBoxLog.AppendText(String.Format(Resources.LogMessage_Stop, logName));
+                    }
+                }
+
+                // ログを出力
+                try
+                {
+                    StreamWriter sw = new StreamWriter(Path.Combine(this.textBoxSaveDirectory.Text, logName));
+                    try
+                    {
+                        sw.Write(this.textBoxLog.Text);
+                    }
+                    finally
+                    {
+                        sw.Close();
+                    }
+                }
+                catch (Exception ex)
+                {
+                    this.textBoxLog.AppendText(String.Format(Resources.LogMessage_ErrorFileSave, Path.Combine(this.textBoxSaveDirectory.Text, logName), ex.Message));
+                }
+            }
+            catch (Exception ex)
+            {
+                this.textBoxLog.AppendText("\r\n" + String.Format(Resources.ErrorMessageDevelopmentError, ex.Message, ex.StackTrace) + "\r\n");
+                System.Diagnostics.Debug.WriteLine("MainForm.backgroundWorkerRun_DoWork > 想定外のエラー : " + ex.Message);
+                System.Diagnostics.Debug.WriteLine(ex.StackTrace);
+            }
+        }
+
+        /// <summary>
+        /// 実行ボタン バックグラウンド処理(終了時)。
+        /// </summary>
+        /// <param name="sender">イベント発生オブジェクト。</param>
+        /// <param name="e">発生したイベント。</param>
+        private void BackgroundWorkerRun_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
+        {
+            // 設定ファイルのキャッシュ情報を更新
+            try
+            {
+                this.config.Save(Settings.Default.ConfigurationFile);
+            }
+            catch (Exception ex)
+            {
+                FormUtils.WarningDialog(
+                    Resources.WarningMessageCacheSaveFailed,
+                    ex.Message);
+            }
+
+            // 画面をロック中から解放
+            this.Release();
+        }
+
+        #endregion
+
+        #region それ以外のメソッド
+
+        /// <summary>
+        /// 画面初期化処理。
+        /// </summary>
+        private void Initialize()
+        {
+            // コンボボックス設定
+            this.comboBoxSource.Items.Clear();
+            this.comboBoxTarget.Items.Clear();
+
+            // 設定ファイルに存在する全言語を選択肢として登録する
+            foreach (Website site in this.config.Websites)
+            {
+                this.comboBoxSource.Items.Add(site.Language.Code);
+                this.comboBoxTarget.Items.Add(site.Language.Code);
+            }
+        }
+
+        /// <summary>
+        /// 設定ファイル読み込み。
+        /// </summary>
+        /// <returns>読み込み成功時は<c>true</c>。</returns>
+        private bool LoadConfig()
+        {
+            // 設定ファイルの読み込み
+            try
+            {
+                this.config = Config.GetInstance(Settings.Default.ConfigurationFile);
+            }
+            catch (FileNotFoundException ex)
+            {
+                // 設定ファイルが見つからない場合
+                System.Diagnostics.Debug.WriteLine(
+                    "MainForm.LoadConfig > 設定ファイル読み込み失敗 : " + ex.Message);
+                FormUtils.ErrorDialog(
+                    Resources.ErrorMessageConfigNotFound,
+                    Settings.Default.ConfigurationFile);
+
+                return false;
+            }
+            catch (Exception ex)
+            {
+                System.Diagnostics.Debug.WriteLine(
+                    "MainForm.LoadConfig > 設定ファイル読み込み時エラー : " + ex.StackTrace);
+                FormUtils.ErrorDialog(
+                    Resources.ErrorMessageConfigLordFailed,
+                    ex.Message);
+
+                return false;
+            }
+
+            return true;
+        }
+
+        /// <summary>
+        /// 画面をロック中に移行。
+        /// </summary>
+        private void LockOperation()
+        {
+            // 各種ボタンなどを入力不可に変更
+            this.groupBoxTransfer.Enabled = false;
+            this.groupBoxSaveDirectory.Enabled = false;
+            this.textBoxArticle.Enabled = false;
+            this.buttonRun.Enabled = false;
+
+            // 中止ボタンを有効に変更
+            this.buttonStop.Enabled = true;
+        }
+
+        /// <summary>
+        /// 画面をロック中から解放。
+        /// </summary>
+        private void Release()
+        {
+            // 中止ボタンを入力不可に変更
+            this.buttonStop.Enabled = false;
+
+            // 各種ボタンなどを有効に変更
+            this.groupBoxTransfer.Enabled = true;
+            this.groupBoxSaveDirectory.Enabled = true;
+            this.textBoxArticle.Enabled = true;
+            this.buttonRun.Enabled = true;
+        }
+
+        /// <summary>
+        /// 渡された文字列から.txtと.logの重複していないファイル名を作成。
+        /// </summary>
+        /// <param name="fileName">出力結果ファイル名。</param>
+        /// <param name="logName">出力ログファイル名。</param>
+        /// <param name="text">出力する結果テキスト。</param>
+        /// <param name="dir">出力先ディレクトリ。</param>
+        /// <returns><c>true</c> 出力成功</returns>
+        private bool MakeFileName(out string fileName, out string logName, string text, string dir)
+        {
+            // 出力先フォルダに存在しないファイル名(の拡張子より前)を作成
+            // ※渡されたWikipedia等の記事名にファイル名に使えない文字が含まれている場合、_ に置き換える
+            //   また、ファイル名が重複している場合、xx[0].txtのように連番を付ける
+            string fileNameBase = FormUtils.ReplaceInvalidFileNameChars(text);
+            fileName = fileNameBase + ".txt";
+            logName = fileNameBase + ".log";
+            bool success = false;
+            for (int i = 0; i < 100000; i++)
+            {
+                // ※100000まで試して空きが見つからないことは無いはず、もし見つからなかったら最後のを上書き
+                if (!File.Exists(Path.Combine(dir, fileName))
+                    && !File.Exists(Path.Combine(dir, logName)))
+                {
+                    success = true;
+                    break;
+                }
+
+                fileName = fileNameBase + "[" + i + "]" + ".txt";
+                logName = fileNameBase + "[" + i + "]" + ".log";
+            }
+
+            // 結果設定
+            return success;
+        }
+
+        /// <summary>
+        /// 翻訳支援処理クラスのイベント用。
+        /// </summary>
+        /// <param name="sender">イベント発生オブジェクト。</param>
+        /// <param name="e">発生したイベント。</param>
+        private void GetLogUpdate(object sender, System.EventArgs e)
+        {
+            // 前回以降に追加されたログをテキストボックスに出力
+            int length = this.translate.Log.Length;
+            if (length > this.logLastLength)
+            {
+                this.textBoxLog.AppendText(this.translate.Log.Substring(this.logLastLength, length - this.logLastLength));
+            }
+
+            this.logLastLength = length;
+        }
+
+        #endregion
+    }
 }
\ No newline at end of file