Skip to content

Commit

Permalink
Added a language selector to the chat ui (kmp)
Browse files Browse the repository at this point in the history
  • Loading branch information
Mnemotechnician committed Feb 23, 2024
1 parent 1f5dc56 commit cd7e250
Show file tree
Hide file tree
Showing 6 changed files with 280 additions and 6 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
using Content.Shared.Chat;
using Content.Client._NF.Language.Systems.Chat.Controls;
using Content.Client.UserInterface.Systems.Language;
using Content.Shared.Chat;
using Content.Shared.Input;
using Content.Shared.Language;
using Robust.Client.UserInterface;
using Robust.Client.UserInterface.Controls;

namespace Content.Client.UserInterface.Systems.Chat.Controls;
Expand All @@ -8,6 +12,7 @@ namespace Content.Client.UserInterface.Systems.Chat.Controls;
public class ChatInputBox : PanelContainer
{
public readonly ChannelSelectorButton ChannelSelector;
public readonly LanguageSelectorButton LanguageSelector; // Frontier
public readonly HistoryLineEdit Input;
public readonly ChannelFilterButton FilterButton;
protected readonly BoxContainer Container;
Expand All @@ -30,6 +35,17 @@ public ChatInputBox()
MinWidth = 75
};
Container.AddChild(ChannelSelector);
// frontier block - begin
LanguageSelector = new LanguageSelectorButton
{
Name = "LanguageSelector",
ToggleMode = true,
StyleClasses = { "chatSelectorOptionButton" },
MinWidth = 75
};
Container.AddChild(LanguageSelector);
LanguageSelector.OnLanguageSelect += SelectLanguage;
// frontier block - end
Input = new HistoryLineEdit
{
Name = "Input",
Expand All @@ -52,6 +68,13 @@ private void UpdateActiveChannel(ChatSelectChannel selectedChannel)
ActiveChannel = (ChatChannel) selectedChannel;
}

// Frontier
private void SelectLanguage(LanguagePrototype language)
{
// This sucks a lot
IoCManager.Resolve<IUserInterfaceManager>().GetUIController<LanguageMenuUIController>().SetLanguage(language.ID);
}

private static string GetChatboxInfoPlaceholder()
{
return (BoundKeyHelper.IsBound(ContentKeyFunctions.FocusChat), BoundKeyHelper.IsBound(ContentKeyFunctions.CycleChatChannelForward)) switch
Expand Down
7 changes: 3 additions & 4 deletions Content.Client/_NF/Language/LanguageMenuWindow.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,14 @@ namespace Content.Client._NF.Language; // This EXACT class must have the _NF par
[GenerateTypedNameReferences]
public sealed partial class LanguageMenuWindow : DefaultWindow
{
[Dependency] private readonly IConsoleHost _consoleHost = default!;
private readonly LanguageSystem _language;

private readonly List<EntryState> _entries = new();

public Action<string>? OnLanguageSelected;

public LanguageMenuWindow()
{
RobustXamlLoader.Load(this);
IoCManager.InjectDependencies(this);
_language = IoCManager.Resolve<IEntitySystemManager>().GetEntitySystem<LanguageSystem>();

Title = Loc.GetString("language-menu-window-title");
Expand Down Expand Up @@ -113,7 +112,7 @@ private void AddLanguageEntry(string language)

private void OnLanguageChosen(string id)
{
_consoleHost.ExecuteCommand("lsselectlang " + id);
OnLanguageSelected?.Invoke(id);
}

private struct EntryState
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
using System.Linq;
using System.Numerics;
using Content.Client.UserInterface.Systems.Chat.Controls;
using Content.Shared.Language;
using Robust.Shared.Utility;

namespace Content.Client._NF.Language.Systems.Chat.Controls;

// Mostly copied from ChannelSelectorButton
public sealed class LanguageSelectorButton : ChatPopupButton<LanguageSelectorPopup>
{
public event Action<LanguagePrototype>? OnLanguageSelect;

public LanguagePrototype? SelectedLanguage { get; private set; }

private const int SelectorDropdownOffset = 38;

public LanguageSelectorButton()
{
Name = "LanguageSelector";

Popup.Selected += OnLanguageSelected;

if (Popup.FirstLanguage is { } firstSelector)
{
Select(firstSelector);
}
}

protected override UIBox2 GetPopupPosition()
{
var globalLeft = GlobalPosition.X;
var globalBot = GlobalPosition.Y + Height;
return UIBox2.FromDimensions(
new Vector2(globalLeft, globalBot),
new Vector2(SizeBox.Width, SelectorDropdownOffset));
}

private void OnLanguageSelected(LanguagePrototype channel)
{
Select(channel);
}

public void Select(LanguagePrototype language)
{
if (Popup.Visible)
{
Popup.Close();
}

if (SelectedLanguage == language)
return;
SelectedLanguage = language;
OnLanguageSelect?.Invoke(language);

Text = LanguageSelectorName(language);
}

public static string LanguageSelectorName(LanguagePrototype language, bool full = false)
{
var name = language.LocalizedName;

// if the language name is short enough, just return it
if (full || name.Length < 5)
return name;

// If the language name is multi-word, collect first letters and capitalize them
if (name.Contains(' '))
{
var result = name
.Split(" ")
.Select(it => it.FirstOrNull())
.Where(it => it != null)
.Select(it => char.ToUpper(it!.Value));

return new string(result.ToArray());
}

// Alternatively, take the first 5 letters
return name[..5];
}

// public Color ChannelSelectColor(ChatSelectChannel channel)
// {
// return channel switch
// {
// ChatSelectChannel.Radio => Color.LimeGreen,
// ChatSelectChannel.LOOC => Color.MediumTurquoise,
// ChatSelectChannel.OOC => Color.LightSkyBlue,
// ChatSelectChannel.Dead => Color.MediumPurple,
// ChatSelectChannel.Admin => Color.HotPink,
// _ => Color.DarkGray
// };
// }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
using Content.Client.Stylesheets;
using Content.Client.UserInterface.Systems.Chat;
using Content.Client.UserInterface.Systems.Chat.Controls;
using Content.Shared.Chat;
using Content.Shared.Language;
using Robust.Client.UserInterface.Controls;

namespace Content.Client._NF.Language.Systems.Chat.Controls;

// Mostly copied from ChannelSelectorItemButton
public sealed class LanguageSelectorItemButton : Button
{
public readonly LanguagePrototype Language;

public bool IsHidden => Parent == null;

public LanguageSelectorItemButton(LanguagePrototype language)
{
Language = language;
AddStyleClass(StyleNano.StyleClassChatChannelSelectorButton);

Text = LanguageSelectorButton.LanguageSelectorName(language, full: true);

// var prefix = ChatUIController.ChannelPrefixes[selector];
// if (prefix != default)
// Text = Loc.GetString("hud-chatbox-select-name-prefixed", ("name", Text), ("prefix", prefix));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
using System.Reflection.Metadata.Ecma335;
using Content.Client.Language.Systems;
using Content.Client.UserInterface.Systems.Chat.Controls;
using Content.Client.UserInterface.Systems.Language;
using Content.Shared.Chat;
using Content.Shared.Language;
using Content.Shared.Language.Systems;
using Robust.Client.UserInterface.Controls;
using static Robust.Client.UserInterface.Controls.BaseButton;

namespace Content.Client._NF.Language.Systems.Chat.Controls;

// Mostly copied from LanguageSelectorPopup
public sealed class LanguageSelectorPopup : Popup
{
private readonly BoxContainer _channelSelectorHBox;
private readonly Dictionary<string, LanguageSelectorItemButton> _selectorStates = new();
private readonly LanguageMenuUIController _languageMenuController;

public event Action<LanguagePrototype>? Selected;

public LanguageSelectorPopup()
{
_channelSelectorHBox = new BoxContainer
{
Orientation = BoxContainer.LayoutOrientation.Horizontal,
SeparationOverride = 1
};

_languageMenuController = UserInterfaceManager.GetUIController<LanguageMenuUIController>();
_languageMenuController.LanguagesChanged += SetLanguages;

AddChild(_channelSelectorHBox);
}

public LanguagePrototype? FirstLanguage
{
get
{
foreach (var selector in _selectorStates.Values)
{
if (!selector.IsHidden)
return selector.Language;
}

return null;
}
}

private bool IsPreferredAvailable()
{
var preferred = _languageMenuController.LastPreferredLanguage;
return preferred != null && _selectorStates.TryGetValue(preferred, out var selector) && !selector.IsHidden;
}

public void SetLanguages(List<string> languages)
{
var languageSystem = IoCManager.Resolve<IEntitySystemManager>().GetEntitySystem<LanguageSystem>();
_channelSelectorHBox.RemoveAllChildren();

foreach (var language in languages)
{
if (!_selectorStates.TryGetValue(language, out var selector))
{
var proto = languageSystem.GetLanguage(language);
if (proto == null)
continue;

selector = new LanguageSelectorItemButton(proto);
_selectorStates[language] = selector;
selector.OnPressed += OnSelectorPressed;
}

if (selector.IsHidden)
{
_channelSelectorHBox.AddChild(selector);
}
}

var isPreferredAvailable = IsPreferredAvailable();
if (!isPreferredAvailable)
{
var first = FirstLanguage;
if (first != null)
Select(first);
}
}

private void OnSelectorPressed(ButtonEventArgs args)
{
var button = (LanguageSelectorItemButton) args.Button;
Select(button.Language);
}

private void Select(LanguagePrototype language)
{
Selected?.Invoke(language);
}

protected override void Dispose(bool disposing)
{
base.Dispose(disposing);

if (!disposing)
return;

_languageMenuController.LanguagesChanged -= SetLanguages;
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
using Content.Client._NF.Language;
using Content.Client.Gameplay;
using Content.Client.UserInterface.Systems.Chat;
using Content.Shared.Language;
using Robust.Client.UserInterface.Controllers;
using Robust.Client.UserInterface.Controls;
using Robust.Shared.Console;
using Robust.Shared.Timing;
using static Content.Shared.Language.Systems.SharedLanguageSystem;

Expand All @@ -13,7 +15,11 @@ public sealed class LanguageMenuUIController : UIController, IOnStateEntered<Gam
public LanguageMenuWindow? _languageWindow;
private TimeSpan _lastToggle = TimeSpan.Zero;

public string? LastPreferredLanguage;
public Action<List<string>>? LanguagesChanged;

[Dependency] private readonly IGameTiming _timing = default!;
[Dependency] private readonly IConsoleHost _consoleHost = default!;

public override void Initialize()
{
Expand All @@ -28,6 +34,7 @@ private void OnStateUpdate(LanguageMenuStateMessage ev)
return;

_languageWindow.UpdateState(ev);
LanguagesChanged?.Invoke(ev.Options);
}

private void OnActionMenu(EntityUid uid, LanguageSpeakerComponent component, LanguageMenuActionEvent args)
Expand All @@ -43,16 +50,29 @@ private void OnActionMenu(EntityUid uid, LanguageSpeakerComponent component, Lan
else
{
_languageWindow!.Open();
EntityManager.EntityNetManager?.SendSystemNetworkMessage(new RequestLanguageMenuStateMessage());
RequestUpdate();
}

args.Handled = true;
}

public void RequestUpdate()
{
EntityManager.EntityNetManager?.SendSystemNetworkMessage(new RequestLanguageMenuStateMessage());
}

public void SetLanguage(string id)
{
_consoleHost.ExecuteCommand("lsselectlang " + id);
LastPreferredLanguage = id;
}

public void OnStateEntered(GameplayState state)
{
_languageWindow = UIManager.CreateWindow<LanguageMenuWindow>();
_languageWindow.OnLanguageSelected += SetLanguage;
LayoutContainer.SetAnchorPreset(_languageWindow, LayoutContainer.LayoutPreset.Center);
RequestUpdate();
}

public void OnStateExited(GameplayState state)
Expand Down

0 comments on commit cd7e250

Please sign in to comment.