/// <summary> /// ユニット名を置換する /// </summary> /// <param name="s">置換元文字列</param> /// <param name="t">置換先文字列</param> /// <param name="country">国タグ</param> /// <param name="type">ユニット名種類</param> /// <param name="regex">正規表現を使用するか</param> public static void Replace(string s, string t, Country country, UnitNameType type, bool regex) { List <string> names = Items[country][type].Select(name => regex ? Regex.Replace(name, s, t) : name.Replace(s, t)).ToList(); SetNames(names, country, type); }
/// <summary> /// ユニット種類リストボックスの項目描画処理 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void OnTypeListBoxDrawItem(object sender, DrawItemEventArgs e) { // 項目がなければ何もしない if (e.Index == -1) { return; } // 背景を描画する e.DrawBackground(); // 項目の文字列を描画する Brush brush; if ((e.State & DrawItemState.Selected) != DrawItemState.Selected) { // 変更ありの項目は文字色を変更する Country country = Countries.Tags[countryListBox.SelectedIndex]; UnitNameType type = UnitNames.Types[e.Index]; brush = UnitNames.IsDirty(country, type) ? new SolidBrush(Color.Red) : new SolidBrush(SystemColors.WindowText); } else { brush = new SolidBrush(SystemColors.HighlightText); } string s = typeListBox.Items[e.Index].ToString(); e.Graphics.DrawString(s, e.Font, brush, e.Bounds); brush.Dispose(); // フォーカスを描画する e.DrawFocusRectangle(); }
/// <summary> /// ユニット名リストを設定する /// </summary> /// <param name="names">ユニット名リスト</param> /// <param name="country">国タグ</param> /// <param name="type">ユニット名の種類</param> public static void SetNames(List <string> names, Country country, UnitNameType type) { // 未登録の場合は項目を作成する if (!ExistsCountry(country)) { Items.Add(country, new Dictionary <UnitNameType, List <string> >()); } if (!ExistsType(country, type)) { Items[country].Add(type, new List <string>()); } // ユニット名リストに変更がなければ戻る if (names.SequenceEqual(Items[country][type])) { return; } Log.Info("[UnitName] Set: [{0}] <{1}>", Config.GetText(TypeNames[(int)type]), Countries.Strings[(int)country]); // ユニット名リストを設定する Items[country][type] = names; // 編集済みフラグを設定する SetDirty(country, type); }
/// <summary> /// ユニット名リストを更新する /// </summary> private void UpdateNameList() { nameTextBox.Clear(); // 選択中の国家がなければ戻る if (countryListBox.SelectedIndex < 0) { return; } Country country = Countries.Tags[countryListBox.SelectedIndex]; // 選択中のユニット名種類がなければ戻る if (typeListBox.SelectedIndex < 0) { return; } UnitNameType type = UnitNames.Types[typeListBox.SelectedIndex]; // ユニット名を順に追加する StringBuilder sb = new StringBuilder(); foreach (string name in UnitNames.GetNames(country, type)) { sb.AppendLine(name); } nameTextBox.Text = sb.ToString(); }
/// <summary> /// ユニット名定義行を解釈する /// </summary> /// <param name="lexer">字句解析器</param> private static void ParseLine(CsvLexer lexer) { string[] tokens = lexer.GetTokens(); // 空行を読み飛ばす if (tokens == null) { return; } // トークン数が足りない行は読み飛ばす if (tokens.Length != 3) { Log.Warning("[UnitName] Invalid token count: {0} ({1} L{2})", tokens.Length, lexer.FileName, lexer.LineNo); // 余分な項目がある場合は解析を続ける if (tokens.Length < 3) { return; } } // 国タグ string countryName = tokens[0].ToUpper(); if (!Countries.StringMap.ContainsKey(countryName)) { Log.Warning("[UnitName] Invalid country: {0} ({1} L{2})", tokens[0], lexer.FileName, lexer.LineNo); return; } Country country = Countries.StringMap[countryName]; // ユニット種類 string typeName = tokens[1].ToUpper(); if (!TypeStringMap.ContainsKey(typeName)) { Log.Warning("[UnitName] Invalid unit type: {0} ({1} L{2})", tokens[1], lexer.FileName, lexer.LineNo); return; } UnitNameType type = TypeStringMap[typeName]; if (!Types.Contains(type)) { Log.Warning("[UnitName] Invalid unit type: {0} ({1} L{2})", tokens[1], lexer.FileName, lexer.LineNo); return; } // ユニット名 string name = tokens[2]; if (string.IsNullOrEmpty(name)) { return; } // ユニット名を追加する AddName(name, country, type); }
/// <summary> /// 指定したユニット種類の項目が存在するかを返す /// </summary> /// <param name="country">国タグ</param> /// <param name="type">ユニット名の種類</param> /// <returns>項目が存在すればtrueを返す</returns> private static bool ExistsType(Country country, UnitNameType type) { if (!ExistsCountry(country)) { return(false); } return(Items[country].ContainsKey(type)); }
/// <summary> /// 項目が存在するかを返す /// </summary> /// <param name="name">項目名</param> /// <param name="country">国タグ</param> /// <param name="type">ユニット名の種類</param> /// <returns>項目が存在すればtrueを返す</returns> private static bool Exists(string name, Country country, UnitNameType type) { if (!ExistsType(country, type)) { return(false); } return(Items[country][type].Contains(name)); }
/// <summary> /// ユニット名リストを取得する /// </summary> /// <param name="country">国タグ</param> /// <param name="type">ユニット名の種類</param> /// <returns>ユニット名リスト</returns> public static IEnumerable <string> GetNames(Country country, UnitNameType type) { // 未登録の場合は空のリストを返す if (!ExistsType(country, type)) { return(new List <string>()); } return(Items[country][type]); }
/// <summary> /// 全ての国のユニット名を置換する /// </summary> /// <param name="s">置換元文字列</param> /// <param name="t">置換先文字列</param> /// <param name="type">ユニット名種類</param> /// <param name="regex">正規表現を使用するか</param> public static void ReplaceAllCountries(string s, string t, UnitNameType type, bool regex) { List <Country> countries = Items.Select(pair => pair.Key).Where(country => Items[country].ContainsKey(type)).ToList(); foreach (Country country in countries) { Replace(s, t, country, type, regex); } }
/// <summary> /// 全ての国のユニット名を連番補間する /// </summary> /// <param name="type">ユニット名種類</param> public static void InterpolateAllCountries(UnitNameType type) { List <Country> countries = Items.Select(pair => pair.Key).Where(country => Items[country].ContainsKey(type)).ToList(); foreach (Country country in countries) { Interpolate(country, type); } }
/// <summary> /// ユニット名を連番追加する /// </summary> /// <param name="prefix">接頭辞</param> /// <param name="suffix">接尾辞</param> /// <param name="start">開始番号</param> /// <param name="end">終了番号</param> /// <param name="country">国タグ</param> /// <param name="type">ユニット名種類</param> public static void AddSequential(string prefix, string suffix, int start, int end, Country country, UnitNameType type) { for (int i = start; i <= end; i++) { string name = $"{prefix}{i}{suffix}"; if (!Exists(name, country, type)) { AddName(name, country, type); SetDirty(country, type); } } }
/// <summary> /// ユニット名を追加する /// </summary> /// <param name="name">ユニット名</param> /// <param name="country">国タグ</param> /// <param name="type">ユニット名の種類</param> private static void AddName(string name, Country country, UnitNameType type) { // 未登録の場合は項目を作成する if (!ExistsCountry(country)) { Items.Add(country, new Dictionary <UnitNameType, List <string> >()); } if (!ExistsType(country, type)) { Items[country].Add(type, new List <string>()); } // ユニット名を追加する Items[country][type].Add(name); }
/// <summary> /// 追加ボタン押下時の処理 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void OnAddButtonClick(object sender, EventArgs e) { // 選択中の国家がなければ戻る if (countryListBox.SelectedIndex < 0) { return; } Country country = Countries.Tags[countryListBox.SelectedIndex]; // 選択中のユニット名種類がなければ戻る if (typeListBox.SelectedIndex < 0) { return; } UnitNameType type = UnitNames.Types[typeListBox.SelectedIndex]; string prefix = prefixComboBox.Text; string suffix = suffixComboBox.Text; int start = (int)startNumericUpDown.Value; int end = (int)endNumericUpDown.Value; Log.Info("[UnitName] Add: {0}-{1} {2} {3} [{4}] <{5}>", start, end, prefix, suffix, Config.GetText(UnitNames.TypeNames[(int)type]), Countries.Strings[(int)country]); // ユニット名を一括追加する UnitNames.AddSequential(prefix, suffix, start, end, country, type); // ユニット名リストの表示を更新する UpdateNameList(); // 編集済みフラグが更新されるため国家リストボックスの表示を更新する countryListBox.Refresh(); typeListBox.Refresh(); // 履歴を更新する _prefixHistory.Add(prefix); _suffixHistory.Add(suffix); HoI2EditorController.Settings.UnitNameEditor.PrefixHistory = _prefixHistory.Get().ToList(); HoI2EditorController.Settings.UnitNameEditor.SuffixHistory = _suffixHistory.Get().ToList(); // 履歴コンボボックスを更新する UpdateAddHistory(); }
/// <summary> /// ユニット名を連番補間する /// </summary> /// <param name="country">国タグ</param> /// <param name="type">ユニット名種類</param> public static void Interpolate(Country country, UnitNameType type) { List <string> names = new List <string>(); Regex r = new Regex("([^\\d]*)(\\d+)(.*)"); string pattern = ""; int prev = 0; bool found = false; foreach (string name in Items[country][type]) { if (r.IsMatch(name)) { int n; if (int.TryParse(r.Replace(name, "$2"), out n)) { if (!found) { // 出力パターンを設定する pattern = r.Replace(name, "$1{0}$3"); found = true; } else { // 前の番号と現在の番号の間を補間する if (prev + 1 < n) { for (int i = prev + 1; i < n; i++) { string s = string.Format(pattern, i); if (!names.Contains(s)) { names.Add(s); } } } } prev = n; } } names.Add(name); } SetNames(names, country, type); }
/// <summary> /// ユニット名リスト変更時の処理 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void OnNameTextBoxValidated(object sender, EventArgs e) { // 選択中の国家がなければ戻る if (countryListBox.SelectedIndex < 0) { return; } Country country = Countries.Tags[countryListBox.SelectedIndex]; // 選択中のユニット名種類がなければ戻る if (typeListBox.SelectedIndex < 0) { return; } UnitNameType type = UnitNames.Types[typeListBox.SelectedIndex]; // ユニット名リストを更新する UnitNames.SetNames(nameTextBox.Lines.Where(line => !string.IsNullOrEmpty(line)).ToList(), country, type); // 編集済みフラグが更新されるため国家リストボックスの表示を更新する countryListBox.Refresh(); typeListBox.Refresh(); }
/// <summary> /// 編集済みフラグを設定する /// </summary> /// <param name="country">国タグ</param> /// <param name="type">ユニット名種類</param> private static void SetDirty(Country country, UnitNameType type) { TypeDirtyFlags[(int)country, (int)type] = true; CountryDirtyFlags[(int)country] = true; _dirtyFlag = true; }
/// <summary> /// 編集済みかどうかを取得する /// </summary> /// <param name="country">国タグ</param> /// <param name="type">ユニット名種類</param> /// <returns>編集済みならばtrueを返す</returns> public static bool IsDirty(Country country, UnitNameType type) { return(TypeDirtyFlags[(int)country, (int)type]); }