using DataModel.Database; using Processor; using Timer = System.Timers.Timer; namespace UI_WinForms.Components; public partial class Translations : UserControl { private readonly Dictionary translationComponents = new(); private readonly Timer clearTimer; private Translation? mainCulture = null; public Translations() { this.InitializeComponent(); this.Enabled = false; this.clearTimer = new Timer { Enabled = false, Interval = 600, // ms AutoReset = false, }; this.clearTimer.Elapsed += (sender, args) => this.ClearTranslations(); this.Load += async (sender, args) => await this.SetupTranslations(); AppEvents.WhenTextElementChanged += async (sender, textElement) => { if(textElement is null) { this.clearTimer.Start(); return; } this.clearTimer.Stop(); if (!this.Enabled) this.Enabled = true; var allTranslations = await TranslationProcessor.GetTranslations(textElement); foreach (var translation in allTranslations) if (this.translationComponents.ContainsKey(translation.Culture)) await this.translationComponents[translation.Culture].Configure(translation); }; AppEvents.WhenSectionChanged += (sender, section) => this.ClearTranslations(); } private void ClearTranslations() { // Perform UI changes on the UI thread: if (this.InvokeRequired) { this.Invoke(this.ClearTranslations); return; } this.Enabled = false; foreach (var (_, translation) in this.translationComponents) translation.Clear(); } private async Task SetupTranslations() { if(this.DesignMode) return; // Apply a custom order for the cultures. We want to show the default culture first, // then the other cultures in order of their index. Please note: whatever we want to // show as first, we have to return last! async IAsyncEnumerable DesiredOrder() { // Get all configured cultures: var cultureInfos = (await AppSettings.GetCultureInfos()).OrderByDescending(n => n.Index).ToList(); // Get the main culture: var mainCultureIndex = await AppSettings.GetDeepLSourceCultureIndex(); // First, we return all the non-main cultures in descending order of their index: foreach (var cultureInfo in cultureInfos.Where(n => n.Index != mainCultureIndex)) yield return cultureInfo; // Last, we return the main culture: if(cultureInfos.Any(n => n.Index == mainCultureIndex)) yield return cultureInfos.First(n => n.Index == mainCultureIndex); } await foreach (var cultureInfo in DesiredOrder()) { var translationComponent = new Translation(cultureInfo); this.translationComponents.Add(cultureInfo.Code, translationComponent); this.panelTranslations.Controls.Add(translationComponent); } } internal void RegisterMainCultureTranslationComponent(Translation trans) { this.mainCulture = trans; // Register the main culture translation component into all the other // translation components: foreach (var (_, translation) in this.translationComponents.Where(n => n.Value != trans)) translation.SetMainCultureTranslation(trans); } internal async Task MainCultureWasChanged() { if(this.mainCulture is null || await AppSettings.GetDeepLMode() == SettingDeepLMode.DISABLED) return; var allTasks = new List(); foreach (var (_, translation) in this.translationComponents.Where(n => n.Value != this.mainCulture)) allTasks.Add(translation.Translate()); await Task.WhenAll(allTasks); } }