- 多语言编辑器已恢复使用
- 保存为翻译模组已恢复使用
This commit is contained in:
Hakoyu
2024-04-15 23:02:21 +08:00
parent 4d64fdc766
commit 3a349aa0b4
23 changed files with 392 additions and 744 deletions

View File

@ -238,7 +238,7 @@ public class ModLoader
return; return;
foreach (var dis in langDirectory.EnumerateDirectories()) foreach (var dis in langDirectory.EnumerateDirectories())
{ {
I18nDatas.TryAdd(dis.Name, new()); I18nDatas.TryAdd(dis.Name, []);
foreach (FileInfo fi in dis.EnumerateFiles("*.lps")) foreach (FileInfo fi in dis.EnumerateFiles("*.lps"))
{ {
var lps = new LPS(File.ReadAllText(fi.FullName)); var lps = new LPS(File.ReadAllText(fi.FullName));

View File

@ -127,7 +127,7 @@ public class ClickTextModel : ObservableObjectX
[AdaptIgnore] [AdaptIgnore]
public string Text public string Text
{ {
get => ModInfoModel.Current.I18nResource.GetCurrentCultureDataOrDefault(ID, string.Empty); get => ModInfoModel.Current.I18nResource.GetCurrentCultureDataOrDefault(ID);
set => ModInfoModel.Current.I18nResource.SetCurrentCultureData(ID, value); set => ModInfoModel.Current.I18nResource.SetCurrentCultureData(ID, value);
} }
#endregion #endregion

View File

@ -119,7 +119,7 @@ public class FoodModel : ObservableObjectX
[AdaptIgnore] [AdaptIgnore]
public string Name public string Name
{ {
get => ModInfoModel.Current.I18nResource.GetCurrentCultureDataOrDefault(ID, string.Empty); get => ModInfoModel.Current.I18nResource.GetCurrentCultureDataOrDefault(ID);
set => ModInfoModel.Current.I18nResource.SetCurrentCultureData(ID, value); set => ModInfoModel.Current.I18nResource.SetCurrentCultureData(ID, value);
} }

View File

@ -74,7 +74,7 @@ public class LowTextModel : ObservableObjectX
[AdaptIgnore] [AdaptIgnore]
public string Text public string Text
{ {
get => ModInfoModel.Current.I18nResource.GetCurrentCultureDataOrDefault(ID, string.Empty); get => ModInfoModel.Current.I18nResource.GetCurrentCultureDataOrDefault(ID);
set => ModInfoModel.Current.I18nResource.SetCurrentCultureData(ID, value); set => ModInfoModel.Current.I18nResource.SetCurrentCultureData(ID, value);
} }
#endregion #endregion

View File

@ -123,6 +123,7 @@ public class ModInfoModel : ObservableObjectX
RefreshAllID(); RefreshAllID();
if (I18nResource.CultureDatas.HasValue()) if (I18nResource.CultureDatas.HasValue())
RefreshID(); RefreshID();
I18nResource.FillDefaultValue();
} }
private void ModInfoModel_PropertyChanged(object? sender, PropertyChangedEventArgs e) private void ModInfoModel_PropertyChanged(object? sender, PropertyChangedEventArgs e)
@ -142,17 +143,18 @@ public class ModInfoModel : ObservableObjectX
/// </summary> /// </summary>
public static ModInfoModel Current { get; set; } = new(); public static ModInfoModel Current { get; set; } = new();
public I18nResource<string, string> I18nResource { get; } = new(); public I18nResource<string, string> I18nResource { get; } =
new() { FillDefaultValueForNewCulture = true, DefaultValue = string.Empty };
#region I18nData #region I18nData
public string Name public string Name
{ {
get => I18nResource.GetCurrentCultureDataOrDefault(ID, string.Empty); get => I18nResource.GetCurrentCultureDataOrDefault(ID);
set => I18nResource.SetCurrentCultureData(ID, value); set => I18nResource.SetCurrentCultureData(ID, value);
} }
public string Description public string Description
{ {
get => I18nResource.GetCurrentCultureDataOrDefault(DescriptionID, string.Empty); get => I18nResource.GetCurrentCultureDataOrDefault(DescriptionID);
set => I18nResource.SetCurrentCultureData(DescriptionID, value); set => I18nResource.SetCurrentCultureData(DescriptionID, value);
} }
#endregion #endregion
@ -448,15 +450,16 @@ public class ModInfoModel : ObservableObjectX
{ {
if (modLoader.I18nDatas.HasValue() is false) if (modLoader.I18nDatas.HasValue() is false)
return; return;
foreach (var cultureDatas in modLoader.I18nDatas) foreach (var cultureDatas in modLoader.I18nDatas)
{ {
var culture = CultureInfo.GetCultureInfo(cultureDatas.Key); var culture = CultureInfo.GetCultureInfo(cultureDatas.Key);
I18nResource.AddCulture(culture); I18nResource.AddCulture(culture);
foreach (var data in cultureDatas.Value) foreach (var data in cultureDatas.Value)
I18nResource.AddCultureData(culture, data.Key, data.Value); I18nResource.SetCultureData(culture, data.Key, data.Value);
} }
if (I18nResource.SetCurrentCulture(CultureInfo.CurrentCulture) is false) if (I18nResource.SetCurrentCulture(CultureInfo.CurrentCulture) is false)
I18nResource.SetCurrentCulture(I18nResource.CultureDatas.First().Key); I18nResource.SetCurrentCulture(I18nResource.Cultures.First());
I18nResource.I18nObjectInfos.Add( I18nResource.I18nObjectInfos.Add(
new( new(
this, this,
@ -613,22 +616,15 @@ public class ModInfoModel : ObservableObjectX
new Line("itemid", ItemID.ToString()), new Line("itemid", ItemID.ToString()),
new Line("cachedate", DateTime.Now.Date.ToString("s")) new Line("cachedate", DateTime.Now.Date.ToString("s"))
}; };
foreach (var cultureData in Current.I18nResource.CultureDatas) foreach (var culture in Current.I18nResource.Cultures)
{ {
lps.Add( lps.Add(
new Line("cultureDatas", cultureData.Key.Name) new Line("cultureDatas", culture.Name)
{ {
new Sub( new Sub(ID, I18nResource.GetCultureDataOrDefault(culture, ID, string.Empty)),
ID,
I18nResource.GetCultureDataOrDefault(cultureData.Key.Name, ID, string.Empty)
),
new Sub( new Sub(
DescriptionID, DescriptionID,
I18nResource.GetCultureDataOrDefault( I18nResource.GetCultureDataOrDefault(culture, DescriptionID, string.Empty)
cultureData.Key.Name,
DescriptionID,
string.Empty
)
), ),
} }
); );
@ -756,15 +752,18 @@ public class ModInfoModel : ObservableObjectX
{ {
var langPath = Path.Combine(path, "lang"); var langPath = Path.Combine(path, "lang");
Directory.CreateDirectory(langPath); Directory.CreateDirectory(langPath);
foreach (var cultureData in I18nResource.CultureDatas) foreach (var culture in I18nResource.Cultures)
{ {
var culturePath = Path.Combine(langPath, cultureData.Key.Name); var culturePath = Path.Combine(langPath, culture.Name);
Directory.CreateDirectory(culturePath); Directory.CreateDirectory(culturePath);
var cultureFile = Path.Combine(culturePath, $"{cultureData.Key.Name}.lps"); var cultureFile = Path.Combine(culturePath, $"{culture.Name}.lps");
File.Create(cultureFile).Close(); File.Create(cultureFile).Close();
var lps = new LPS(); var lps = new LPS();
foreach (var data in cultureData.Value) foreach (var datas in I18nResource.CultureDatas)
lps.Add(new Line(data.Key, data.Value)); {
if (I18nResource.TryGetCultureData(culture, datas.Key, out var data))
lps.Add(new Line(datas.Key, data));
}
File.WriteAllText(cultureFile, lps.ToString()); File.WriteAllText(cultureFile, lps.ToString());
} }
} }
@ -803,53 +802,23 @@ public class ModInfoModel : ObservableObjectX
Current = null!; Current = null!;
} }
public void SaveTranslationMod(string path, IEnumerable<string> cultures) public void SaveTranslationMod(string path, IEnumerable<CultureInfo> cultures)
{ {
// 保存模型信息 // 保存模型信息
SaveModInfo(path); SaveModInfo(path);
// 保存文化数据 // 保存文化数据
var langPath = Path.Combine(path, "cultureDatas"); var langPath = Path.Combine(path, "lang");
Directory.CreateDirectory(langPath); Directory.CreateDirectory(langPath);
foreach (var cultureName in cultures) foreach (var culture in cultures)
{ {
var culturePath = Path.Combine(langPath, cultureName); var culturePath = Path.Combine(langPath, culture.Name);
Directory.CreateDirectory(culturePath); Directory.CreateDirectory(culturePath);
var cultureFile = Path.Combine(culturePath, $"{cultureName}.lps"); var cultureFile = Path.Combine(culturePath, $"{culture}.lps");
File.Create(cultureFile).Close(); File.Create(cultureFile).Close();
var lps = new LPS(); var lps = new LPS();
//TODO foreach (var data in I18nResource.CultureDatas.Values)
//foreach (var data in I18nEditWindow.Current.ViewModel.AllI18nDatas) lps.Add(new Line(data.Key, data[culture]));
// lps.Add(
// new Line(
// data.Key,
// data.Value.Datas[I18nHelper.Current.CultureNames.IndexOf(cultureName)].Value
// )
// );
File.WriteAllText(cultureFile, lps.ToString()); File.WriteAllText(cultureFile, lps.ToString());
} }
} }
} }
//public class I18nModInfoModel : ObservableObjectX
//{
// #region Name
// [DebuggerBrowsable(DebuggerBrowsableState.Never)]
// private string _name = string.Empty;
// public string Name
// {
// get => _name;
// set => SetProperty(ref _name, value);
// }
// #endregion
// #region Description
// [DebuggerBrowsable(DebuggerBrowsableState.Never)]
// private string _description = string.Empty;
// public string Description
// {
// get => _description;
// set => SetProperty(ref _description, value);
// }
// #endregion
//}

View File

@ -196,7 +196,7 @@ public class PetModel : ObservableObjectX
[AdaptIgnore] [AdaptIgnore]
public string Name public string Name
{ {
get => ModInfoModel.Current.I18nResource.GetCurrentCultureDataOrDefault(ID, string.Empty); get => ModInfoModel.Current.I18nResource.GetCurrentCultureDataOrDefault(ID);
set => ModInfoModel.Current.I18nResource.SetCurrentCultureData(ID, value); set => ModInfoModel.Current.I18nResource.SetCurrentCultureData(ID, value);
} }

View File

@ -138,7 +138,7 @@ public class SelectTextModel : ObservableObjectX
[AdaptIgnore] [AdaptIgnore]
public string Text public string Text
{ {
get => ModInfoModel.Current.I18nResource.GetCurrentCultureDataOrDefault(ID, string.Empty); get => ModInfoModel.Current.I18nResource.GetCurrentCultureDataOrDefault(ID);
set => ModInfoModel.Current.I18nResource.SetCurrentCultureData(ID, value); set => ModInfoModel.Current.I18nResource.SetCurrentCultureData(ID, value);
} }

View File

@ -129,7 +129,7 @@ public class WorkModel : ObservableObjectX
[AdaptIgnore] [AdaptIgnore]
public string Name public string Name
{ {
get => ModInfoModel.Current.I18nResource.GetCurrentCultureDataOrDefault(ID, string.Empty); get => ModInfoModel.Current.I18nResource.GetCurrentCultureDataOrDefault(ID);
set => ModInfoModel.Current.I18nResource.SetCurrentCultureData(ID, value); set => ModInfoModel.Current.I18nResource.SetCurrentCultureData(ID, value);
} }
#endregion #endregion

View File

@ -46,7 +46,7 @@
</ControlTemplate> </ControlTemplate>
<ControlTemplate x:Key="ListBox_ShowLangs" TargetType="ListBox"> <ControlTemplate x:Key="ListBox_ShowLangs" TargetType="ListBox">
<ListBox <ListBox
ItemsSource="{Binding I18nResource.CultureDatas.ObservableKeys}" ItemsSource="{Binding I18nResource.Cultures}"
ScrollViewer.VerticalScrollBarVisibility="Auto" ScrollViewer.VerticalScrollBarVisibility="Auto"
SelectedItem="{Binding I18nResource.CurrentCulture}"> SelectedItem="{Binding I18nResource.CurrentCulture}">
<ListBox.ItemContainerStyle> <ListBox.ItemContainerStyle>

View File

@ -1,6 +1,7 @@
using System; using System;
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics; using System.Diagnostics;
using System.Drawing; using System.Drawing;
using System.Drawing.Imaging; using System.Drawing.Imaging;
@ -118,27 +119,6 @@ public static class NativeExtensions
stream.Seek(position, SeekOrigin.Begin); stream.Seek(position, SeekOrigin.Begin);
} }
/// <summary>
/// 尝试添加
/// </summary>
/// <typeparam name="TKey">键类型</typeparam>
/// <typeparam name="TValue"></typeparam>
/// <param name="dictionary"></param>
/// <param name="key">键</param>
/// <param name="value">值</param>
/// <returns>成功为 <see langword="true"/> 失败为 <see langword="false"/></returns>
public static bool TryAdd<TKey, TValue>(
this IDictionary<TKey, TValue> dictionary,
TKey key,
TValue value
)
{
if (dictionary.ContainsKey(key))
return false;
dictionary.Add(key, value);
return true;
}
/// <summary> /// <summary>
/// 流内容对比 /// 流内容对比
/// </summary> /// </summary>
@ -290,4 +270,65 @@ public static class NativeExtensions
catch { } catch { }
}; };
} }
private static Dictionary<Window, WindowCloseState> _windowCloseStates = new();
/// <summary>
/// 设置关闭状态
/// </summary>
/// <param name="window"></param>
/// <param name="state">关闭状态</param>
public static void SetCloseState(this Window window, WindowCloseState state)
{
window.Closing -= WindowCloseState_Closing;
window.Closing += WindowCloseState_Closing;
_windowCloseStates[window] = state;
}
/// <summary>
/// 强制关闭
/// </summary>
/// <param name="window"></param>
public static void CloseX(this Window? window)
{
if (window is null)
return;
_windowCloseStates.Remove(window);
window.Closing -= WindowCloseState_Closing;
window.Close();
}
/// <summary>
/// 显示或者聚焦
/// </summary>
/// <param name="window"></param>
public static void ShowOrActivate(this Window? window)
{
if (window is null)
return;
if (window.IsVisible is false)
window.Show();
window.Activate();
}
private static void WindowCloseState_Closing(object sender, CancelEventArgs e)
{
if (sender is not Window window)
return;
if (_windowCloseStates.TryGetValue(window, out var state) is false)
return;
if (state is WindowCloseState.Close)
return;
e.Cancel = true;
window.Visibility =
state is WindowCloseState.Hidden ? Visibility.Hidden : Visibility.Collapsed;
return;
}
}
public enum WindowCloseState
{
Close,
Hidden,
Collapsed
} }

View File

@ -28,8 +28,8 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.2.2" /> <PackageReference Include="CommunityToolkit.Mvvm" Version="8.2.2" />
<PackageReference Include="HKW.Utils" Version="1.2.13" /> <PackageReference Include="HKW.Utils" Version="1.2.19" />
<PackageReference Include="HKW.WPF" Version="1.0.4" /> <PackageReference Include="HKW.WPF" Version="1.0.5" />
<PackageReference Include="Mapster" Version="7.4.0" /> <PackageReference Include="Mapster" Version="7.4.0" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -1,520 +0,0 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using HKW.HKWUtils.Observable;
using Mapster;
using VPet.ModMaker.Models;
namespace VPet.ModMaker.ViewModels.ModEdit.I18nEdit;
public class I18nEditWindowVM : ObservableObjectX { }
//{
// public I18nEditWindowVM()
// {
// I18nDatas = new()
// {
// Filter = (d) =>
// {
// if (SearchTarget == nameof(ModInfoModel.ID))
// {
// return d.ID.Contains(Search, StringComparison.OrdinalIgnoreCase);
// }
// else
// {
// var cultureIndex = I18nHelper.Current.CultureNames.IndexOf(SearchTarget);
// throw new();
// //return d.Datas[cultureIndex]()
// // .Contains(Search, StringComparison.OrdinalIgnoreCase);
// }
// },
// FilteredList = new()
// };
// SearchTarget = nameof(ModInfoModel.ID);
// PropertyChanged += I18nEditWindowVM_PropertyChanged;
// }
// private void I18nEditWindowVM_PropertyChanged(
// object? sender,
// System.ComponentModel.PropertyChangedEventArgs e
// )
// {
// if (e.PropertyName == nameof(Search))
// {
// I18nDatas.Refresh();
// }
// else if (e.PropertyName == nameof(SearchTarget))
// {
// I18nDatas.Refresh();
// }
// }
// #region Search
// [DebuggerBrowsable(DebuggerBrowsableState.Never)]
// private string _search = string.Empty;
// /// <summary>
// /// 搜索
// /// </summary>
// public string Search
// {
// get => _search;
// set => SetProperty(ref _search, value);
// }
// #endregion
// /// <summary>
// /// 全部I18n资源 (ID, I18nData)
// /// </summary>
// public Dictionary<string, I18nData> AllI18nDatas { get; } = new();
// /// <summary>
// /// 全部的I18n资源
// /// </summary>
// #region ShowI18nDatas
// [DebuggerBrowsable(DebuggerBrowsableState.Never)]
// private ObservableFilterList<I18nData, ObservableList<I18nData>> _i18nDatas;
// public ObservableFilterList<I18nData, ObservableList<I18nData>> I18nDatas
// {
// get => _i18nDatas;
// set => SetProperty(ref _i18nDatas, value);
// }
// #endregion
// /// <summary>
// /// 搜索目标列表
// /// </summary>
// public ObservableList<string> SearchTargets { get; } = new() { nameof(ModInfoModel.ID) };
// /// <summary>
// /// 搜索目标
// /// </summary>
// #region SearchTarget
// [DebuggerBrowsable(DebuggerBrowsableState.Never)]
// private string _searchTarget;
// public string SearchTarget
// {
// get => _searchTarget;
// set => SetProperty(ref _searchTarget, value);
// }
// #endregion
// /// <summary>
// /// 文化列表改变事件
// /// </summary>
// /// <param name="sender"></param>
// /// <param name="e"></param>
// private void CultureNames_CollectionChanged(object? sender, NotifyCollectionChangedEventArgs e)
// {
// if (e.Action is NotifyCollectionChangedAction.Add)
// {
// var newCulture = (string)e.NewItems[0];
// AddCulture(newCulture);
// SearchTargets.Add(newCulture);
// foreach (var data in AllI18nDatas)
// data.Value.Datas.Add(new());
// }
// else if (e.Action is NotifyCollectionChangedAction.Remove)
// {
// var oldCulture = (string)e.OldItems[0];
// RemoveCulture(oldCulture);
// SearchTargets.Remove(oldCulture);
// foreach (var data in AllI18nDatas)
// {
// var value = data.Value.Datas[e.OldStartingIndex];
// value.Group?.Remove(value);
// data.Value.Datas.RemoveAt(e.OldStartingIndex);
// }
// if (SearchTarget is null)
// SearchTarget = nameof(ModInfoModel.ID);
// }
// else if (e.Action is NotifyCollectionChangedAction.Replace)
// {
// var oldCulture = (string)e.OldItems[0];
// var newCulture = (string)e.NewItems[0];
// ReplaceCulture(oldCulture, newCulture);
// SearchTargets[SearchTargets.IndexOf(oldCulture)] = newCulture;
// }
// }
// #region LoadData
// /// <summary>
// /// 初始化I18n资源
// /// </summary>
// /// <param name="model"></param>
// public void InitializeI18nData(ModInfoModel model)
// {
// foreach (var culture in I18nHelper.Current.CultureNames)
// {
// AddCulture(culture);
// SearchTargets.Add(culture);
// }
// try
// {
// LoadFood(model);
// LoadClickText(model);
// LoadLowText(model);
// LoadSelectText(model);
// LoadPets(model);
// }
// catch
// {
// Close();
// throw;
// }
// I18nHelper.Current.CultureNames.CollectionChanged -= CultureNames_CollectionChanged;
// I18nHelper.Current.CultureNames.CollectionChanged += CultureNames_CollectionChanged;
// }
// /// <summary>
// /// 载入食物
// /// </summary>
// /// <param name="model"></param>
// private void LoadFood(ModInfoModel model)
// {
// foreach (var food in model.Foods)
// {
// AddData(food.ID, food, (m) => m.Name);
// AddData(food.DescriptionID, food, (m) => m.Description);
// }
// model.Foods.CollectionChanged += (s, e) =>
// {
// if (e.Action is NotifyCollectionChangedAction.Add)
// {
// var newModel = (FoodModel)e.NewItems[0];
// AddData(newModel.ID, newModel, (m) => m.Name);
// AddData(newModel.DescriptionID, newModel, (m) => m.Description);
// }
// else if (e.Action is NotifyCollectionChangedAction.Remove)
// {
// var oldModel = (FoodModel)e.OldItems[0];
// RemoveData(oldModel.ID, oldModel, (m) => m.Name);
// RemoveData(oldModel.DescriptionID, oldModel, (m) => m.Description);
// }
// else if (e.Action is NotifyCollectionChangedAction.Replace)
// {
// var newModel = (FoodModel)e.NewItems[0];
// var oldModel = (FoodModel)e.OldItems[0];
// ReplaceData(newModel.ID, newModel, (m) => m.Name);
// ReplaceData(newModel.DescriptionID, newModel, (m) => m.Description);
// }
// };
// }
// /// <summary>
// /// 载入点击文本
// /// </summary>
// /// <param name="model"></param>
// private void LoadClickText(ModInfoModel model)
// {
// foreach (var text in model.ClickTexts)
// {
// AddData(text.ID, text, (m) => m.Text);
// }
// model.ClickTexts.CollectionChanged += (s, e) =>
// {
// if (e.Action is NotifyCollectionChangedAction.Add)
// {
// var newModel = (ClickTextModel)e.NewItems[0];
// AddData(newModel.ID, newModel, (m) => m.Text);
// }
// else if (e.Action is NotifyCollectionChangedAction.Remove)
// {
// var oldModel = (ClickTextModel)e.OldItems[0];
// RemoveData(oldModel.ID, oldModel, (m) => m.Text);
// }
// else if (e.Action is NotifyCollectionChangedAction.Replace)
// {
// var newModel = (ClickTextModel)e.NewItems[0];
// var oldModel = (ClickTextModel)e.OldItems[0];
// ReplaceData(newModel.ID, newModel, (m) => m.Text);
// }
// };
// }
// /// <summary>
// /// 载入低状态为文本
// /// </summary>
// /// <param name="model"></param>
// private void LoadLowText(ModInfoModel model)
// {
// foreach (var text in model.LowTexts)
// {
// AddData(text.ID, text, (m) => m.Text);
// }
// model.LowTexts.CollectionChanged += (s, e) =>
// {
// if (e.Action is NotifyCollectionChangedAction.Add)
// {
// var newModel = (LowTextModel)e.NewItems[0];
// AddData(newModel.ID, newModel, (m) => m.Text);
// }
// else if (e.Action is NotifyCollectionChangedAction.Remove)
// {
// var oldModel = (LowTextModel)e.OldItems[0];
// RemoveData(oldModel.ID, oldModel, (m) => m.Text);
// }
// else if (e.Action is NotifyCollectionChangedAction.Replace)
// {
// var newModel = (LowTextModel)e.NewItems[0];
// var oldModel = (LowTextModel)e.OldItems[0];
// ReplaceData(newModel.ID, newModel, (m) => m.Text);
// }
// };
// }
// /// <summary>
// /// 载入选择文本
// /// </summary>
// /// <param name="model"></param>
// private void LoadSelectText(ModInfoModel model)
// {
// foreach (var text in model.SelectTexts)
// {
// AddData(text.ID, text, (m) => m.Text);
// AddData(text.ChooseId, text, (m) => m.Choose);
// }
// model.SelectTexts.CollectionChanged += (s, e) =>
// {
// if (e.Action is NotifyCollectionChangedAction.Add)
// {
// var newModel = (SelectTextModel)e.NewItems[0];
// AddData(newModel.ID, newModel, (m) => m.Text);
// AddData(newModel.ChooseId, newModel, (m) => m.Choose);
// }
// else if (e.Action is NotifyCollectionChangedAction.Remove)
// {
// var oldModel = (SelectTextModel)e.OldItems[0];
// RemoveData(oldModel.ID, oldModel, (m) => m.Text);
// RemoveData(oldModel.ChooseId, oldModel, (m) => m.Choose);
// }
// else if (e.Action is NotifyCollectionChangedAction.Replace)
// {
// var newModel = (SelectTextModel)e.NewItems[0];
// var oldModel = (SelectTextModel)e.OldItems[0];
// ReplaceData(newModel.ID, newModel, (m) => m.Text);
// ReplaceData(newModel.ChooseId, newModel, (m) => m.Choose);
// }
// };
// }
// /// <summary>
// /// 载入宠物
// /// </summary>
// /// <param name="model"></param>
// public void LoadPets(ModInfoModel model)
// {
// foreach (var pet in model.Pets)
// {
// if (pet.FromMain.Value)
// continue;
// AddData(pet.ID, pet, (m) => m.Name);
// AddData(pet.PetNameId, pet, (m) => m.PetName);
// AddData(pet.DescriptionID, pet, (m) => m.Description);
// foreach (var work in pet.Works)
// AddData(work.ID, work, (m) => m.Name);
// }
// model.Pets.CollectionChanged += (s, e) =>
// {
// if (e.Action is NotifyCollectionChangedAction.Add)
// {
// var newModel = (PetModel)e.NewItems[0];
// AddData(newModel.ID, newModel, (m) => m.Name);
// AddData(newModel.DescriptionID, newModel, (m) => m.Description);
// foreach (var work in newModel.Works)
// AddData(work.ID, work, (m) => m.Name);
// }
// else if (e.Action is NotifyCollectionChangedAction.Remove)
// {
// var oldModel = (PetModel)e.OldItems[0];
// if (oldModel.FromMain.Value)
// return;
// RemoveData(oldModel.ID, oldModel, (m) => m.Name);
// RemoveData(oldModel.DescriptionID, oldModel, (m) => m.Description);
// foreach (var work in oldModel.Works)
// RemoveData(work.ID, work, (m) => m.Name);
// }
// else if (e.Action is NotifyCollectionChangedAction.Replace)
// {
// var newModel = (PetModel)e.NewItems[0];
// var oldModel = (PetModel)e.OldItems[0];
// ReplaceData(newModel.ID, newModel, (m) => m.Name);
// ReplaceData(newModel.DescriptionID, newModel, (m) => m.Description);
// foreach (var work in newModel.Works)
// ReplaceData(work.ID, work, (m) => m.Name);
// }
// };
// }
// #endregion
// #region DatEdit
// /// <summary>
// /// 添加数据
// /// </summary>
// /// <typeparam name="T"></typeparam>
// /// <param name="id"></param>
// /// <param name="i18nModel"></param>
// /// <param name="i18nValue"></param>
// private void AddData<TViewModel, TI18nModel>(
// TViewModel viewModel,
// Func<TViewModel, string> getID,
// Action<TViewModel, string> setID,
// Func<TI18nModel, string> getI18nData,
// Action<TI18nModel, string> setI18nData
// )
// where TViewModel : I18nModel<TI18nModel>
// where TI18nModel : ObservableObjectX, new()
// {
// if (AllI18nDatas.TryGetValue(getID(viewModel), out var outData))
// {
// AdaptMemberAttribute
// foreach (var culture in I18nHelper.Current.CultureNames.EnumerateIndex())
// {
// if (outData.Datas[culture.Index].Group is null)
// {
// var group = new ObservableValueGroup<string>() { outData.Datas[culture.Index] };
// }
// outData
// .Datas[culture.Index]
// .Group!.Add(i18nValue(i18nModel.I18nDatas[culture.Value]));
// }
// }
// else
// {
// var data = new I18nData();
// data.ID = getID(viewModel);
// foreach (var culture in I18nHelper.Current.CultureNames)
// data.Datas.Add(i18nValue(i18nModel.I18nDatas[culture]));
// I18nDatas.Add(data);
// AllI18nDatas.Add(id.Value, data);
// //id.ValueChanged += IdChange;
// }
// }
// /// <summary>
// /// Id改变
// /// </summary>
// /// <param name="oldValue"></param>
// /// <param name="newValue"></param>
// private void IdChange(ObservableValue<string> sender, ValueChangedEventArgs<string> e)
// {
// var sourceData = AllI18nDatas[e.OldValue];
// //sourceData.ID.Group?.Remove(sourceData.ID); //TODO
// if (AllI18nDatas.TryGetValue(e.OldValue, out var outData))
// {
// foreach (var culture in I18nHelper.Current.CultureNames.EnumerateIndex())
// {
// if (outData.Datas[culture.Index].Group is null)
// {
// var group = new ObservableValueGroup<string>() { outData.Datas[culture.Index] };
// }
// outData.Datas[culture.Index].Group!.Add(sourceData.Datas[culture.Index]);
// }
// }
// else
// {
// sourceData.ID = e.NewValue;
// AllI18nDatas.Remove(e.OldValue);
// AllI18nDatas.Add(e.NewValue, sourceData);
// }
// }
// /// <summary>
// /// 删除I18n资源
// /// </summary>
// /// <typeparam name="T"></typeparam>
// /// <param name="id"></param>
// /// <param name="i18nModel"></param>
// /// <param name="i18nValue"></param>
// private void RemoveData<T>(
// ObservableValue<string> id,
// I18nModel<T> i18nModel,
// Func<T, ObservableValue<string>> i18nValue
// )
// where T : class, new()
// {
// var data = AllI18nDatas[id.Value];
// foreach (var culture in I18nHelper.Current.CultureNames.EnumerateIndex())
// {
// if (data.Datas[culture.Index].Group is ObservableValueGroup<string> group)
// {
// group.Remove(i18nValue(i18nModel.I18nDatas[culture.Value]));
// if (group.Count == 1)
// {
// group.Clear();
// return;
// }
// }
// else
// {
// I18nDatas.Remove(data);
// AllI18nDatas.Remove(id.Value);
// return;
// }
// }
// }
// /// <summary>
// /// 替换I18n资源
// /// </summary>
// /// <typeparam name="T"></typeparam>
// /// <param name="id"></param>
// /// <param name="i18nModel"></param>
// /// <param name="i18nValue"></param>
// private void ReplaceData<T>(
// ObservableValue<string> id,
// I18nModel<T> i18nModel,
// Func<T, ObservableValue<string>> i18nValue
// )
// where T : class, new()
// {
// var data = AllI18nDatas[id.Value];
// foreach (var culture in I18nHelper.Current.CultureNames.EnumerateIndex())
// {
// var oldValue = data.Datas[culture.Index];
// var newValue = i18nValue(i18nModel.I18nDatas[culture.Value]);
// if (oldValue.Group is ObservableValueGroup<string> group)
// {
// group.Add(newValue);
// group.Remove(oldValue);
// }
// data.Datas[culture.Index] = newValue;
// }
// }
// #endregion
// public void Close()
// {
// I18nHelper.Current.CultureNames.CollectionChanged -= CultureNames_CollectionChanged;
// foreach (var i18nData in AllI18nDatas)
// {
// foreach (var data in i18nData.Value.Datas)
// data.Group?.Clear();
// }
// }
// #region Event
// private void AddCulture(string culture)
// {
// CultureChanged?.Invoke(null, culture);
// }
// private void RemoveCulture(string culture)
// {
// CultureChanged?.Invoke(culture, string.Empty);
// }
// private void ReplaceCulture(string oldCulture, string newCulture)
// {
// CultureChanged?.Invoke(oldCulture, newCulture);
// }
// public event EventHandler<string> CultureChanged;
// #endregion
//}

View File

@ -0,0 +1,157 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using HKW.HKWUtils.Extensions;
using HKW.HKWUtils.Observable;
using Mapster;
using VPet.ModMaker.Models;
namespace VPet.ModMaker.ViewModels.ModEdit.I18nEdit;
public class I18nEditWindowVM : ObservableObjectX
{
public I18nEditWindowVM()
{
SearchTarget = SearchTargets.First();
PropertyChanged += I18nEditWindowVM_PropertyChanged;
ModInfoModel.Current.I18nResource.Cultures.SetChanged -= Cultures_SetChanged;
ModInfoModel.Current.I18nResource.Cultures.SetChanged += Cultures_SetChanged;
I18nDatas = new() { Filter = DataFilter, FilteredList = [] };
foreach (var data in ModInfoModel.Current.I18nResource.CultureDatas.Values)
I18nDatas.Add(data);
foreach (var culture in ModInfoModel.Current.I18nResource.Cultures)
SearchTargets.Add(culture.Name);
}
#region Search
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string _search = string.Empty;
/// <summary>
/// 搜索
/// </summary>
public string Search
{
get => _search;
set => SetProperty(ref _search, value);
}
#endregion
/// <summary>
/// 全部I18n资源
/// <para>
/// (ID, (CultureName, Value))
/// </para>
/// </summary>
public ObservableFilterList<
ObservableCultureDataDictionary<string, string>,
ObservableList<ObservableCultureDataDictionary<string, string>>
> I18nDatas { get; } = null!;
/// <summary>
/// 搜索目标列表
/// </summary>
public ObservableSet<string> SearchTargets { get; } = [nameof(ModInfoModel.ID)];
/// <summary>
/// 搜索目标
/// </summary>
#region SearchTarget
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string _searchTarget = string.Empty;
public string SearchTarget
{
get => _searchTarget;
set => SetProperty(ref _searchTarget, value);
}
#endregion
private bool DataFilter(ObservableCultureDataDictionary<string, string> item)
{
if (SearchTarget == nameof(ModInfoModel.ID))
{
// 如果是ID则搜索ID
return item.Key.Contains(Search, StringComparison.OrdinalIgnoreCase);
}
else
{
// 如果是I18n数据则搜索对应文化
if (item.TryGetValue(CultureInfo.GetCultureInfo(SearchTarget), out var data))
{
return data.Contains(Search, StringComparison.OrdinalIgnoreCase);
}
return false;
}
}
private void Cultures_SetChanged(
IObservableSet<CultureInfo> sender,
NotifySetChangedEventArgs<CultureInfo> e
)
{
if (e.Action is SetChangeAction.Add)
{
if (e.NewItems is null)
return;
foreach (var item in e.NewItems)
{
AddCulture(item.Name);
SearchTargets.Add(item.Name);
}
}
else if (e.Action is SetChangeAction.Remove)
{
if (e.OldItems is null)
return;
foreach (var item in e.OldItems)
{
RemoveCulture(item.Name);
SearchTargets.Remove(item.Name);
}
}
}
private void I18nEditWindowVM_PropertyChanged(object? sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == nameof(Search))
{
I18nDatas.Refresh();
}
else if (e.PropertyName == nameof(SearchTarget))
{
I18nDatas.Refresh();
}
}
#region Event
private void AddCulture(string culture)
{
CultureChanged?.Invoke(string.Empty, culture);
}
private void RemoveCulture(string culture)
{
CultureChanged?.Invoke(culture, string.Empty);
}
private void ReplaceCulture(string oldCulture, string newCulture)
{
CultureChanged?.Invoke(oldCulture, newCulture);
}
public event CultureChangedEventHandler? CultureChanged;
#endregion
}
public delegate void CultureChangedEventHandler(string oldCulture, string newCulture);

View File

@ -27,8 +27,6 @@ public class ModEditWindowVM : ObservableObjectX
{ {
public ModEditWindowVM(ModEditWindow window) public ModEditWindowVM(ModEditWindow window)
{ {
//TODO
//I18nEditWindow.Initialize();
ModEditWindow = window; ModEditWindow = window;
ChangeImageCommand.ExecuteCommand += ChangeImageCommand_ExecuteCommand; ChangeImageCommand.ExecuteCommand += ChangeImageCommand_ExecuteCommand;
AddCultureCommand.ExecuteCommand += AddCultureCommand_ExecuteCommand; AddCultureCommand.ExecuteCommand += AddCultureCommand_ExecuteCommand;
@ -123,8 +121,7 @@ public class ModEditWindowVM : ObservableObjectX
private void EditI18nCommand_ExecuteCommand() private void EditI18nCommand_ExecuteCommand()
{ {
I18nEditWindow.Current.Visibility = Visibility.Visible; ModEditWindow.I18nEditWindow.ShowOrActivate();
I18nEditWindow.Current.Activate();
} }
/// <summary> /// <summary>
@ -133,7 +130,6 @@ public class ModEditWindowVM : ObservableObjectX
public void Close() public void Close()
{ {
ModInfo.Image?.StreamSource?.Close(); ModInfo.Image?.StreamSource?.Close();
I18nEditWindow.Current?.Close(true);
} }
/// <summary> /// <summary>

View File

@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.ComponentModel; using System.ComponentModel;
using System.Diagnostics; using System.Diagnostics;
using System.Globalization;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
@ -38,22 +39,20 @@ public class SaveTranslationModWindowVM : ObservableObjectX
public SaveTranslationModWindowVM() public SaveTranslationModWindowVM()
{ {
//TODO foreach (var culture in ModInfoModel.Current.I18nResource.Cultures)
//foreach (var culture in I18nHelper.Current.CultureNames) {
//{ var model = new CheckCultureModel(culture);
// var model = new CheckCultureModel(); model.Culture = culture;
// model.CultureName.Value = culture; model.PropertyChangedX += Model_PropertyChangedX;
// CheckCultures.Add(model); CheckCultures.Add(model);
// CheckAll.AddNotifySender(model.IsChecked); }
//} PropertyChangedX += SaveTranslationModWindowVM_PropertyChangedX;
//CheckAll.ValueChanged += CheckAll_ValueChanged; SaveCommand.ExecuteCommand += Save;
//CheckAll.SenderPropertyChanged += CheckAll_SenderPropertyChanged;
//SaveCommand.ExecuteCommand += Save;
} }
private void CheckAll_ValueChanged( private void SaveTranslationModWindowVM_PropertyChangedX(
ObservableValue<bool?> sender, object? sender,
ValueChangedEventArgs<bool?> e PropertyChangedXEventArgs e
) )
{ {
if (e.NewValue is null) if (e.NewValue is null)
@ -65,25 +64,21 @@ public class SaveTranslationModWindowVM : ObservableObjectX
return; return;
} }
foreach (var model in CheckCultures) foreach (var model in CheckCultures)
model.IsChecked = e.NewValue.Value; model.IsChecked = e.NewValue is true;
} }
private void CheckAll_SenderPropertyChanged( private void Model_PropertyChangedX(object? sender, PropertyChangedXEventArgs e)
ObservableValue<bool?> source,
INotifyPropertyChanged sender
)
{ {
var count = 0; var count = 0;
foreach (var model in CheckCultures) foreach (var model in CheckCultures)
if (model.IsChecked) if (model.IsChecked)
count += 1; count += 1;
if (count == CheckCultures.Count) if (count == CheckCultures.Count)
source.Value = true; CheckAll = true;
else if (count == 0) else if (count == 0)
source.Value = false; CheckAll = false;
else else
source.Value = null; CheckAll = null;
} }
public void Save() public void Save()
@ -100,8 +95,8 @@ public class SaveTranslationModWindowVM : ObservableObjectX
try try
{ {
ModInfoModel.Current.SaveTranslationMod( ModInfoModel.Current.SaveTranslationMod(
Path.GetDirectoryName(saveFileDialog.FileName), Path.GetDirectoryName(saveFileDialog.FileName)!,
CheckCultures.Where(m => m.IsChecked).Select(m => m.CultureName) CheckCultures.Where(m => m.IsChecked).Select(m => m.Culture)
); );
MessageBox.Show("保存成功".Translate()); MessageBox.Show("保存成功".Translate());
} }
@ -114,6 +109,12 @@ public class SaveTranslationModWindowVM : ObservableObjectX
public class CheckCultureModel : ObservableObjectX public class CheckCultureModel : ObservableObjectX
{ {
public CheckCultureModel(CultureInfo culture)
{
_culture = culture;
Culture = culture;
}
#region IsChecked #region IsChecked
[DebuggerBrowsable(DebuggerBrowsableState.Never)] [DebuggerBrowsable(DebuggerBrowsableState.Never)]
private bool _isChecked; private bool _isChecked;
@ -126,12 +127,13 @@ public class CheckCultureModel : ObservableObjectX
#endregion #endregion
#region CultureName #region CultureName
[DebuggerBrowsable(DebuggerBrowsableState.Never)] [DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string _cultureName = string.Empty; private CultureInfo _culture;
public string CultureName public CultureInfo Culture
{ {
get => _cultureName; get => _culture;
set => SetProperty(ref _cultureName, value); set => SetProperty(ref _culture, value);
} }
#endregion #endregion
} }

View File

@ -304,9 +304,7 @@ public class ModMakerWindowVM : ObservableObjectX
ModEditWindow?.Close(); ModEditWindow?.Close();
ModEditWindow = null!; ModEditWindow = null!;
ModInfoModel.Current?.Close(); ModInfoModel.Current?.Close();
I18nEditWindow.Current?.Close(true); ModMakerWindow.ShowOrActivate();
ModMakerWindow.Show();
ModMakerWindow.Activate();
MessageBox.Show(ModMakerWindow, "模组载入失败:\n{0}".Translate(ex)); MessageBox.Show(ModMakerWindow, "模组载入失败:\n{0}".Translate(ex));
GC.Collect(); GC.Collect();
} }

View File

@ -53,7 +53,7 @@ public partial class AddCultureWindow : WindowX
return; return;
} }
if ( if (
ModInfoModel.Current.I18nResource.CultureDatas.ContainsKey( ModInfoModel.Current.I18nResource.Cultures.Contains(
CultureInfo.GetCultureInfo(ViewModel.Culture) CultureInfo.GetCultureInfo(ViewModel.Culture)
) )
) )
@ -65,10 +65,30 @@ public partial class AddCultureWindow : WindowX
Close(); Close();
} }
public const string CultureLink =
"https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-lcid/a9eac961-e77d-41a6-90a5-ce1a8b0cdb9c";
private void Hyperlink_Click(object? sender, RoutedEventArgs e) private void Hyperlink_Click(object? sender, RoutedEventArgs e)
{ {
NativeUtils.OpenLink( try
"https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-lcid/a9eac961-e77d-41a6-90a5-ce1a8b0cdb9c" {
); NativeUtils.OpenLink(CultureLink);
}
catch
{
if (
MessageBoxX.Show(
this,
"无法正确打开链接,需要复制自行访问吗",
"",
MessageBoxButton.YesNo,
MessageBoxIcon.Warning
)
is not MessageBoxResult.Yes
)
return;
Clipboard.SetText(CultureLink);
MessageBoxX.Show(this, "已复制到剪贴板".Translate());
}
} }
} }

View File

@ -27,7 +27,6 @@
</Grid.ColumnDefinitions> </Grid.ColumnDefinitions>
<TextBox <TextBox
pu:TextBoxHelper.Watermark="{ll:Str 搜索}" pu:TextBoxHelper.Watermark="{ll:Str 搜索}"
IsEnabled="{Binding SearchTarget, Converter={StaticResource NullToFalseConverter}}"
Style="{DynamicResource StandardTextBoxStyle}" Style="{DynamicResource StandardTextBoxStyle}"
Text="{Binding Search, UpdateSourceTrigger=PropertyChanged}" /> Text="{Binding Search, UpdateSourceTrigger=PropertyChanged}" />
<ComboBox <ComboBox
@ -44,7 +43,7 @@
CanUserAddRows="False" CanUserAddRows="False"
CanUserDeleteRows="False" CanUserDeleteRows="False"
CanUserReorderColumns="False" CanUserReorderColumns="False"
ItemsSource="{Binding ShowI18nDatas}" ItemsSource="{Binding I18nDatas.FilteredList}"
ScrollViewer.IsDeferredScrollingEnabled="True" ScrollViewer.IsDeferredScrollingEnabled="True"
VirtualizingStackPanel.VirtualizationMode="Recycling"> VirtualizingStackPanel.VirtualizationMode="Recycling">
<DataGrid.Columns> <DataGrid.Columns>
@ -52,12 +51,12 @@
Width="300" Width="300"
MinWidth="200" MinWidth="200"
MaxWidth="500" MaxWidth="500"
Binding="{Binding Id}" Binding="{Binding Key}"
CanUserSort="True" CanUserSort="True"
ElementStyle="{StaticResource TextBlock_Wrap}" ElementStyle="{StaticResource TextBlock_Wrap}"
Header="Id" Header="ID"
IsReadOnly="True" IsReadOnly="True"
SortMemberPath="Id" /> SortMemberPath="Key" />
</DataGrid.Columns> </DataGrid.Columns>
</DataGrid> </DataGrid>
</Grid> </Grid>

View File

@ -21,63 +21,30 @@ public partial class I18nEditWindow : WindowX
{ {
public bool IsCancel { get; private set; } = true; public bool IsCancel { get; private set; } = true;
public static I18nEditWindow Current { get; private set; } = null!;
public I18nEditWindowVM ViewModel => (I18nEditWindowVM)DataContext; public I18nEditWindowVM ViewModel => (I18nEditWindowVM)DataContext;
public I18nEditWindow() public I18nEditWindow()
{ {
// 只隐藏, 不关闭
Closing += (s, e) =>
{
Hide();
if (_close is false)
e.Cancel = true;
};
Closed += (s, e) =>
{
//TODO
//ViewModel.Close();
try
{
DataContext = null;
Current = null;
}
catch { }
};
InitializeComponent(); InitializeComponent();
DataContext = new I18nEditWindowVM(); this.SetDataContext<I18nEditWindowVM>();
//TODO this.SetCloseState(WindowCloseState.Collapsed);
//ViewModel.CultureChanged += ViewModel_CultureChanged; foreach (var culture in ModInfoModel.Current.I18nResource.Cultures)
//ViewModel.InitializeI18nData(ModInfoModel.Current); AddCulture(culture.Name);
ViewModel.CultureChanged += ViewModel_CultureChanged;
} }
public static void Initialize() private void ViewModel_CultureChanged(string oldCultureName, string newCultureName)
{ {
Current = new(); if (string.IsNullOrEmpty(oldCultureName))
} AddCulture(newCultureName);
else if (string.IsNullOrEmpty(newCultureName))
private bool _close = false; RemoveCulture(oldCultureName);
public void Close(bool close)
{
_close = close;
Close();
}
private void ViewModel_CultureChanged(object? sender, string newCulture)
{
var oldCulture = sender as string;
if (string.IsNullOrEmpty(oldCulture))
AddCulture(newCulture);
else if (string.IsNullOrEmpty(newCulture))
RemoveCulture(oldCulture);
else else
ReplaceCulture(oldCulture, newCulture); ReplaceCulture(oldCultureName, newCultureName);
} }
#region CultureEdit #region CultureEdit
private const string ValueBindingFormat = "Datas[{0}].Value"; private const string ValueBindingFormat = "[{0}]";
/// <summary> /// <summary>
/// (culture, Column) /// (culture, Column)
@ -87,36 +54,27 @@ public partial class I18nEditWindow : WindowX
/// <summary> /// <summary>
/// 添加文化列 /// 添加文化列
/// </summary> /// </summary>
/// <param name="culture"></param> /// <param name="cultureName"></param>
public void AddCulture(string culture) public void AddCulture(string cultureName)
{ {
var dataPath = string.Format(ValueBindingFormat, culture); var dataPath = string.Format(ValueBindingFormat, cultureName);
// 文化数据列 // 文化数据列
var column = new DataGridTextColumn() var column = CreateColumn(cultureName, dataPath);
{
Width = 300,
MinWidth = 100,
MaxWidth = 500,
Header = culture,
Binding = new Binding(dataPath) { Mode = BindingMode.TwoWay },
ElementStyle = (Style)ModMakerInfo.NativeStyles["TextBlock_Wrap"],
SortMemberPath = dataPath
};
DataGrid_Datas.Columns.Add(column); DataGrid_Datas.Columns.Add(column);
_dataGridI18nColumns.Add(culture, column); _dataGridI18nColumns.Add(cultureName, column);
} }
/// <summary> /// <summary>
/// 删除文化列 /// 删除文化列
/// </summary> /// </summary>
/// <param name="culture"></param> /// <param name="cultureName"></param>
public void RemoveCulture(string culture) public void RemoveCulture(string cultureName)
{ {
DataGrid_Datas.Columns.Remove(_dataGridI18nColumns[culture]); DataGrid_Datas.Columns.Remove(_dataGridI18nColumns[cultureName]);
_dataGridI18nColumns.Remove(culture); _dataGridI18nColumns.Remove(cultureName);
foreach (var columnData in _dataGridI18nColumns) foreach (var columnData in _dataGridI18nColumns)
{ {
var dataPath = string.Format(ValueBindingFormat, culture); var dataPath = string.Format(ValueBindingFormat, cultureName);
columnData.Value.Binding = new Binding(dataPath) { Mode = BindingMode.TwoWay }; columnData.Value.Binding = new Binding(dataPath) { Mode = BindingMode.TwoWay };
columnData.Value.SortMemberPath = dataPath; columnData.Value.SortMemberPath = dataPath;
} }
@ -125,16 +83,31 @@ public partial class I18nEditWindow : WindowX
/// <summary> /// <summary>
/// 替换文化列 /// 替换文化列
/// </summary> /// </summary>
/// <param name="oldCulture"></param> /// <param name="oldCultureName"></param>
/// <param name="newCulture"></param> /// <param name="newCultureName"></param>
public void ReplaceCulture(string oldCulture, string newCulture) public void ReplaceCulture(string oldCultureName, string newCultureName)
{ {
//if (_dataGridI18nColumns.ContainsKey(newCultureName)) //if (_dataGridI18nColumns.ContainsKey(newCultureName))
// throw new(); // throw new();
var column = _dataGridI18nColumns[oldCulture]; var column = _dataGridI18nColumns[oldCultureName];
column.Header = newCulture; column.Header = newCultureName;
_dataGridI18nColumns.Remove(oldCulture); _dataGridI18nColumns.Remove(oldCultureName);
_dataGridI18nColumns.Add(newCulture, column); _dataGridI18nColumns.Add(newCultureName, column);
}
public static DataGridTextColumn CreateColumn(string header, string dataPath)
{
return new DataGridTextColumn()
{
Width = 300,
MinWidth = 100,
MaxWidth = 500,
Header = header,
Binding = new Binding(dataPath) { Mode = BindingMode.TwoWay },
ElementStyle = (Style)ModMakerInfo.NativeStyles["TextBlock_Wrap"],
SortMemberPath = dataPath,
CanUserSort = true
};
} }
#endregion #endregion

View File

@ -279,7 +279,7 @@
x:Name="ListBox_Cultures" x:Name="ListBox_Cultures"
Grid.Row="1" Grid.Row="1"
d:ItemsSource="{d:SampleData ItemCount=5}" d:ItemsSource="{d:SampleData ItemCount=5}"
ItemsSource="{Binding I18nResource.CultureDatas.ObservableKeys}" ItemsSource="{Binding I18nResource.Cultures}"
ScrollViewer.VerticalScrollBarVisibility="Auto" ScrollViewer.VerticalScrollBarVisibility="Auto"
SelectedItem="{Binding I18nResource.CurrentCulture}"> SelectedItem="{Binding I18nResource.CurrentCulture}">
<ListBox.ItemContainerStyle> <ListBox.ItemContainerStyle>
@ -311,7 +311,6 @@
<Button <Button
Command="{Binding EditI18nCommand}" Command="{Binding EditI18nCommand}"
Content="{ll:Str 编辑多语言内容}" Content="{ll:Str 编辑多语言内容}"
IsEnabled="False"
Style="{DynamicResource ThemedButtonStyle}" /> Style="{DynamicResource ThemedButtonStyle}" />
<Button <Button
Command="{Binding SaveCommand}" Command="{Binding SaveCommand}"
@ -325,17 +324,7 @@
<Button <Button
Command="{Binding SaveAsTranslationModCommand}" Command="{Binding SaveAsTranslationModCommand}"
Content="{ll:Str 保存为翻译模组}" Content="{ll:Str 保存为翻译模组}"
IsEnabled="False"
Style="{DynamicResource ThemedButtonStyle}" /> Style="{DynamicResource ThemedButtonStyle}" />
<!--<Menu
x:Name="Button_SaveAs"
HorizontalContentAlignment="Stretch"
pu:MenuHelper.TopLevelItemsHorizontalContentAlignment="Stretch"
Style="{DynamicResource Menu_Style}">
<MenuItem Header="{ll:Str 保存为}">
<MenuItem Command="{Binding SaveAsCommand}" />
</MenuItem>
</Menu>-->
</StackPanel> </StackPanel>
</Grid> </Grid>
</Grid> </Grid>

View File

@ -26,6 +26,7 @@ using VPet.ModMaker.ViewModels.ModEdit;
using VPet.ModMaker.Views.ModEdit.AnimeEdit; using VPet.ModMaker.Views.ModEdit.AnimeEdit;
using VPet.ModMaker.Views.ModEdit.ClickTextEdit; using VPet.ModMaker.Views.ModEdit.ClickTextEdit;
using VPet.ModMaker.Views.ModEdit.FoodEdit; using VPet.ModMaker.Views.ModEdit.FoodEdit;
using VPet.ModMaker.Views.ModEdit.I18nEdit;
using VPet.ModMaker.Views.ModEdit.LowTextEdit; using VPet.ModMaker.Views.ModEdit.LowTextEdit;
using VPet.ModMaker.Views.ModEdit.MoveEdit; using VPet.ModMaker.Views.ModEdit.MoveEdit;
using VPet.ModMaker.Views.ModEdit.PetEdit; using VPet.ModMaker.Views.ModEdit.PetEdit;
@ -50,6 +51,7 @@ public partial class ModEditWindow : WindowX
public WorkPage WorkPage { get; } = null!; public WorkPage WorkPage { get; } = null!;
public MovePage MovePage { get; } = null!; public MovePage MovePage { get; } = null!;
public AnimePage AnimePage { get; } = null!; public AnimePage AnimePage { get; } = null!;
public I18nEditWindow I18nEditWindow { get; } = null!;
public ModEditWindow() public ModEditWindow()
{ {
@ -66,6 +68,7 @@ public partial class ModEditWindow : WindowX
WorkPage = new(); WorkPage = new();
MovePage = new(); MovePage = new();
AnimePage = new(); AnimePage = new();
I18nEditWindow = new();
} }
/// <summary> /// <summary>
@ -85,7 +88,7 @@ public partial class ModEditWindow : WindowX
ModInfoModel.Current.I18nResource.CultureDatas.HasValue() is false ModInfoModel.Current.I18nResource.CultureDatas.HasValue() is false
|| MessageBox.Show( || MessageBox.Show(
"需要将文化 {0} 设为主要文化吗?".Translate( "需要将文化 {0} 设为主要文化吗?".Translate(
ModInfoModel.Current.I18nResource.CultureDatas.First().Key.Name ModInfoModel.Current.I18nResource.Cultures.First().Name
), ),
"", "",
MessageBoxButton.YesNo MessageBoxButton.YesNo
@ -94,7 +97,7 @@ public partial class ModEditWindow : WindowX
) )
return; return;
ViewModel.SetMainCultureCommand_ExecuteCommand( ViewModel.SetMainCultureCommand_ExecuteCommand(
ModInfoModel.Current.I18nResource.CultureDatas.First().Key.Name ModInfoModel.Current.I18nResource.Cultures.First().Name
); );
} }
} }
@ -121,6 +124,7 @@ public partial class ModEditWindow : WindowX
WorkPage.DataContext = null; WorkPage.DataContext = null;
MovePage.DataContext = null; MovePage.DataContext = null;
AnimePage.DataContext = null; AnimePage.DataContext = null;
I18nEditWindow.CloseX();
} }
catch { } catch { }
} }

View File

@ -35,7 +35,7 @@
<CheckBox <CheckBox
d:Content="zh-CN" d:Content="zh-CN"
d:IsChecked="True" d:IsChecked="True"
Content="{Binding CultureName}" Content="{Binding Culture}"
IsChecked="{Binding IsChecked}" /> IsChecked="{Binding IsChecked}" />
</DataTemplate> </DataTemplate>
</ListBox.ItemTemplate> </ListBox.ItemTemplate>
@ -48,7 +48,7 @@
<CheckBox <CheckBox
Margin="5,0,5,0" Margin="5,0,5,0"
Content="{ll:Str 全选}" Content="{ll:Str 全选}"
IsChecked="{Binding CheckAll.Value}" IsChecked="{Binding CheckAll}"
IsThreeState="True" /> IsThreeState="True" />
<Button <Button
Grid.Column="1" Grid.Column="1"

View File

@ -38,7 +38,6 @@ public partial class ModMakerWindow : WindowX
InitializeComponent(); InitializeComponent();
DataContext = new ModMakerWindowVM(this); DataContext = new ModMakerWindowVM(this);
Closed += ModMakerWindow_Closed; Closed += ModMakerWindow_Closed;
//new AnimeEditWindow().Show();
} }
private void ModMakerWindow_Closed(object? sender, EventArgs e) private void ModMakerWindow_Closed(object? sender, EventArgs e)
@ -72,8 +71,29 @@ public partial class ModMakerWindow : WindowX
ViewModel.LoadMod(history.SourcePath); ViewModel.LoadMod(history.SourcePath);
} }
public const string WikiLink = "https://github.com/LorisYounger/VPet.ModMaker/wiki";
private void Hyperlink_Click(object? sender, RoutedEventArgs e) private void Hyperlink_Click(object? sender, RoutedEventArgs e)
{ {
NativeUtils.OpenLink("https://github.com/LorisYounger/VPet.ModMaker/wiki"); try
{
NativeUtils.OpenLink(WikiLink);
}
catch
{
if (
MessageBoxX.Show(
this,
"无法正确打开链接,需要复制自行访问吗".Translate(),
"",
MessageBoxButton.YesNo,
MessageBoxIcon.Warning
)
is not MessageBoxResult.Yes
)
return;
Clipboard.SetText(WikiLink);
MessageBoxX.Show(this, "已复制到剪贴板".Translate());
}
} }
} }