Added tab completion to in-game chat.
Both player names and chat commands can be completed. Names of local players and bots are not candidates for completion. If a completed name is the first word ": " is appended to the end. The hotkey for toggling team/all chat has been moved to left Alt.
This commit is contained in:
@@ -30,6 +30,7 @@ namespace OpenRA.Widgets
|
|||||||
public Func<bool> OnEnterKey = () => false;
|
public Func<bool> OnEnterKey = () => false;
|
||||||
public Func<bool> OnTabKey = () => false;
|
public Func<bool> OnTabKey = () => false;
|
||||||
public Func<bool> OnEscKey = () => false;
|
public Func<bool> OnEscKey = () => false;
|
||||||
|
public Func<bool> OnAltKey = () => false;
|
||||||
public Action OnLoseFocus = () => { };
|
public Action OnLoseFocus = () => { };
|
||||||
public Action OnTextEdited = () => { };
|
public Action OnTextEdited = () => { };
|
||||||
public int CursorPosition { get; set; }
|
public int CursorPosition { get; set; }
|
||||||
@@ -121,6 +122,9 @@ namespace OpenRA.Widgets
|
|||||||
if (e.Key == Keycode.ESCAPE && OnEscKey())
|
if (e.Key == Keycode.ESCAPE && OnEscKey())
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
if (e.Key == Keycode.LALT && OnAltKey())
|
||||||
|
return true;
|
||||||
|
|
||||||
if (e.Key == Keycode.LEFT)
|
if (e.Key == Keycode.LEFT)
|
||||||
{
|
{
|
||||||
if (CursorPosition > 0)
|
if (CursorPosition > 0)
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
*/
|
*/
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
@@ -30,6 +31,9 @@ namespace OpenRA.Mods.RA.Widgets.Logic
|
|||||||
|
|
||||||
readonly List<INotifyChat> chatTraits;
|
readonly List<INotifyChat> chatTraits;
|
||||||
|
|
||||||
|
readonly List<string> commandNames;
|
||||||
|
readonly List<string> playerNames;
|
||||||
|
|
||||||
bool teamChat;
|
bool teamChat;
|
||||||
|
|
||||||
[ObjectCreator.UseCtor]
|
[ObjectCreator.UseCtor]
|
||||||
@@ -43,6 +47,9 @@ namespace OpenRA.Mods.RA.Widgets.Logic
|
|||||||
var disableTeamChat = world.LocalPlayer == null || world.LobbyInfo.IsSinglePlayer || !players.Any(p => p.IsAlliedWith(world.LocalPlayer));
|
var disableTeamChat = world.LocalPlayer == null || world.LobbyInfo.IsSinglePlayer || !players.Any(p => p.IsAlliedWith(world.LocalPlayer));
|
||||||
teamChat = !disableTeamChat;
|
teamChat = !disableTeamChat;
|
||||||
|
|
||||||
|
commandNames = chatTraits.OfType<ChatCommands>().SelectMany(x => x.Commands.Keys).Select(x => "/" + x).ToList();
|
||||||
|
playerNames = players.Select(x => x.PlayerName).ToList();
|
||||||
|
|
||||||
var chatPanel = (ContainerWidget)widget;
|
var chatPanel = (ContainerWidget)widget;
|
||||||
chatOverlay = chatPanel.Get<ContainerWidget>("CHAT_OVERLAY");
|
chatOverlay = chatPanel.Get<ContainerWidget>("CHAT_OVERLAY");
|
||||||
chatOverlayDisplay = chatOverlay.Get<ChatDisplayWidget>("CHAT_DISPLAY");
|
chatOverlayDisplay = chatOverlay.Get<ChatDisplayWidget>("CHAT_DISPLAY");
|
||||||
@@ -57,7 +64,7 @@ namespace OpenRA.Mods.RA.Widgets.Logic
|
|||||||
chatMode.IsDisabled = () => disableTeamChat;
|
chatMode.IsDisabled = () => disableTeamChat;
|
||||||
|
|
||||||
chatText = chatChrome.Get<TextFieldWidget>("CHAT_TEXTFIELD");
|
chatText = chatChrome.Get<TextFieldWidget>("CHAT_TEXTFIELD");
|
||||||
chatText.OnTabKey = () =>
|
chatText.OnAltKey = () =>
|
||||||
{
|
{
|
||||||
if (!disableTeamChat)
|
if (!disableTeamChat)
|
||||||
teamChat ^= true;
|
teamChat ^= true;
|
||||||
@@ -76,6 +83,7 @@ namespace OpenRA.Mods.RA.Widgets.Logic
|
|||||||
CloseChat();
|
CloseChat();
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
chatText.OnTabKey = () => AutoCompleteText();
|
||||||
|
|
||||||
chatText.OnEscKey = () => { CloseChat(); return true; };
|
chatText.OnEscKey = () => { CloseChat(); return true; };
|
||||||
|
|
||||||
@@ -166,5 +174,48 @@ namespace OpenRA.Mods.RA.Widgets.Logic
|
|||||||
|
|
||||||
Sound.PlayNotification(modRules, null, "Sounds", "ChatLine", null);
|
Sound.PlayNotification(modRules, null, "Sounds", "ChatLine", null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool AutoCompleteText()
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(chatText.Text))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
string suggestion;
|
||||||
|
|
||||||
|
if (chatText.Text.StartsWith("/"))
|
||||||
|
{
|
||||||
|
suggestion = commandNames.FirstOrDefault(x => x.StartsWith(chatText.Text));
|
||||||
|
if (suggestion == null)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
string toComplete;
|
||||||
|
bool oneWord;
|
||||||
|
if (chatText.Text.Contains(' '))
|
||||||
|
{
|
||||||
|
toComplete = chatText.Text.Substring(chatText.Text.LastIndexOf(' ') + 1);
|
||||||
|
oneWord = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
toComplete = chatText.Text;
|
||||||
|
oneWord = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
suggestion = playerNames.FirstOrDefault(x => x.StartsWith(toComplete, StringComparison.InvariantCultureIgnoreCase));
|
||||||
|
if (suggestion == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (oneWord)
|
||||||
|
suggestion += ": ";
|
||||||
|
else
|
||||||
|
suggestion = chatText.Text.Substring(0, chatText.Text.Length - toComplete.Length) + suggestion;
|
||||||
|
}
|
||||||
|
|
||||||
|
chatText.Text = suggestion;
|
||||||
|
chatText.CursorPosition = chatText.Text.Length;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user