using Content.Client.Language.Systems; using Content.Shared.Language; using Content.Shared.Language.Components; using Content.Shared.Language.Events; using Robust.Client.AutoGenerated; using Robust.Client.UserInterface.Controls; using Robust.Client.UserInterface.CustomControls; using Robust.Client.UserInterface.XAML; using Robust.Shared.Prototypes; namespace Content.Client.Language; [GenerateTypedNameReferences] public sealed partial class LanguageMenuWindow : DefaultWindow { private readonly LanguageSystem _clientLanguageSystem; private readonly List _entries = new(); public LanguageMenuWindow() { RobustXamlLoader.Load(this); _clientLanguageSystem = IoCManager.Resolve().GetEntitySystem(); _clientLanguageSystem.OnLanguagesChanged += UpdateState; } protected override void Dispose(bool disposing) { base.Dispose(disposing); if (disposing) _clientLanguageSystem.OnLanguagesChanged -= UpdateState; } protected override void Opened() { UpdateState(); } private void UpdateState() { var languageSpeaker = _clientLanguageSystem.GetLocalSpeaker(); if (languageSpeaker == null) return; UpdateState(languageSpeaker.CurrentLanguage, languageSpeaker.SpokenLanguages); } public void UpdateState(ProtoId currentLanguage, List> spokenLanguages) { var langName = Loc.GetString($"language-{currentLanguage}-name"); CurrentLanguageLabel.Text = Loc.GetString("language-menu-current-language", ("language", langName)); OptionsList.RemoveAllChildren(); _entries.Clear(); foreach (var language in spokenLanguages) { AddLanguageEntry(language); } // Disable the button for the currently chosen language foreach (var entry in _entries) { if (entry.Button != null) entry.Button.Disabled = entry.Language == currentLanguage; } } private void AddLanguageEntry(ProtoId language) { var proto = _clientLanguageSystem.GetLanguagePrototype(language); var state = new EntryState { Language = language }; var container = new BoxContainer { Orientation = BoxContainer.LayoutOrientation.Vertical }; #region Header var header = new BoxContainer { Orientation = BoxContainer.LayoutOrientation.Horizontal, HorizontalExpand = true, SeparationOverride = 2 }; var name = new Label { Text = proto?.Name ?? Loc.GetString("generic-error"), MinWidth = 50, HorizontalExpand = true }; var button = new Button { Text = "Choose", MinWidth = 80, }; // WD EDIT button.OnPressed += _ => OnLanguageChosen(language); state.Button = button; header.AddChild(name); header.AddChild(button); container.AddChild(header); #endregion #region Collapsible description var body = new CollapsibleBody { HorizontalExpand = true, Margin = new Thickness(4f, 4f) }; var description = new RichTextLabel { HorizontalExpand = true }; description.SetMessage(proto?.Description ?? Loc.GetString("generic-error")); body.AddChild(description); var collapser = new Collapsible(Loc.GetString("language-menu-description-header"), body) { Orientation = BoxContainer.LayoutOrientation.Vertical, HorizontalExpand = true }; container.AddChild(collapser); #endregion // Before adding, wrap the new container in a PanelContainer to give it a distinct look var wrapper = new PanelContainer(); wrapper.StyleClasses.Add("PdaBorderRect"); wrapper.AddChild(container); OptionsList.AddChild(wrapper); _entries.Add(state); } private void OnLanguageChosen(ProtoId id) { _clientLanguageSystem.RequestSetLanguage(id); // Predict the change if (_clientLanguageSystem.GetLocalSpeaker()?.SpokenLanguages is {} languages) UpdateState(id, languages); } private struct EntryState { public ProtoId Language; public Button? Button; } }