Merge pull request #6281 from mizipzor/tab-completion

Added tab completion to in-game and lobby chat.
This commit is contained in:
Paul Chote
2014-08-24 17:29:38 +12:00
4 changed files with 106 additions and 15 deletions

View File

@@ -19,6 +19,7 @@ Previous developers included:
Also thanks to: Also thanks to:
* Adam Valy (Tschokky) * Adam Valy (Tschokky)
* Akseli Virtanen (RAGEQUIT) * Akseli Virtanen (RAGEQUIT)
* Alexander Fast (mizipzor)
* Allen262 * Allen262
* Andrew Aldridge (i80and) * Andrew Aldridge (i80and)
* Andrew Perkins * Andrew Perkins

View File

@@ -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)

View File

@@ -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 = orderManager.LobbyInfo.Clients.Select(c => c.Name).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;
@@ -71,18 +78,23 @@ namespace OpenRA.Mods.RA.Widgets.Logic
orderManager.IssueOrder(Order.Chat(team, chatText.Text.Trim())); orderManager.IssueOrder(Order.Chat(team, chatText.Text.Trim()));
else else
if (chatTraits != null) if (chatTraits != null)
chatTraits.All(x => x.OnChat(orderManager.LocalClient.Name, chatText.Text.Trim())); {
var text = chatText.Text.Trim();
foreach (var trait in chatTraits)
trait.OnChat(orderManager.LocalClient.Name, text);
}
CloseChat(); CloseChat();
return true; return true;
}; };
chatText.OnTabKey = AutoCompleteText;
chatText.OnEscKey = () => { CloseChat(); return true; }; chatText.OnEscKey = () => { CloseChat(); return true; };
var chatClose = chatChrome.Get<ButtonWidget>("CHAT_CLOSE"); var chatClose = chatChrome.Get<ButtonWidget>("CHAT_CLOSE");
chatClose.OnClick += () => CloseChat(); chatClose.OnClick += CloseChat;
chatPanel.OnKeyPress = (e) => chatPanel.OnKeyPress = e =>
{ {
if (e.Event == KeyInputEvent.Up) if (e.Event == KeyInputEvent.Up)
return false; return false;
@@ -166,5 +178,43 @@ 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;
if (chatText.Text.LastOrDefault() == ' ')
return false;
var suggestion = "";
if (chatText.Text.StartsWith("/"))
{
suggestion = commandNames.FirstOrDefault(x => x.StartsWith(chatText.Text));
if (suggestion == null)
return false;
}
else
{
var oneWord = !chatText.Text.Contains(' ');
var toComplete = oneWord
? chatText.Text
: chatText.Text.Substring(chatText.Text.LastIndexOf(' ') + 1);
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;
}
} }
} }

View File

@@ -35,18 +35,23 @@ namespace OpenRA.Mods.RA.Widgets.Logic
enum PanelType { Players, Options, Kick, ForceStart } enum PanelType { Players, Options, Kick, ForceStart }
PanelType panel = PanelType.Players; PanelType panel = PanelType.Players;
Widget lobby; readonly Widget lobby;
readonly Widget editablePlayerTemplate;
readonly Widget nonEditablePlayerTemplate;
readonly Widget emptySlotTemplate;
readonly Widget editableSpectatorTemplate;
readonly Widget nonEditableSpectatorTemplate;
readonly Widget newSpectatorTemplate;
Widget editablePlayerTemplate, nonEditablePlayerTemplate, emptySlotTemplate, readonly ScrollPanelWidget chatPanel;
editableSpectatorTemplate, nonEditableSpectatorTemplate, newSpectatorTemplate; readonly Widget chatTemplate;
ScrollPanelWidget chatPanel; readonly ScrollPanelWidget players;
Widget chatTemplate; readonly Dictionary<string, string> countryNames;
ScrollPanelWidget players; readonly ColorPreviewManagerWidget colorPreview;
Dictionary<string, string> countryNames;
ColorPreviewManagerWidget colorPreview; List<string> playerNames;
// Listen for connection failures // Listen for connection failures
void ConnectionStateChanged(OrderManager om) void ConnectionStateChanged(OrderManager om)
@@ -498,13 +503,13 @@ namespace OpenRA.Mods.RA.Widgets.Logic
chatTextField.Text = ""; chatTextField.Text = "";
return true; return true;
}; };
chatTextField.OnAltKey = () =>
chatTextField.OnTabKey = () =>
{ {
teamChat ^= true; teamChat ^= true;
chatLabel.Text = teamChat ? "Team:" : "Chat:"; chatLabel.Text = teamChat ? "Team:" : "Chat:";
return true; return true;
}; };
chatTextField.OnTabKey = AutoCompleteText;
chatPanel = lobby.Get<ScrollPanelWidget>("CHAT_DISPLAY"); chatPanel = lobby.Get<ScrollPanelWidget>("CHAT_DISPLAY");
chatTemplate = chatPanel.Get("CHAT_TEMPLATE"); chatTemplate = chatPanel.Get("CHAT_TEMPLATE");
@@ -764,6 +769,8 @@ namespace OpenRA.Mods.RA.Widgets.Logic
while (players.Children.Count > idx) while (players.Children.Count > idx)
players.RemoveChild(players.Children[idx]); players.RemoveChild(players.Children[idx]);
playerNames = orderManager.LobbyInfo.Clients.Select(c => c.Name).ToList();
} }
void OnGameStart() void OnGameStart()
@@ -772,6 +779,35 @@ namespace OpenRA.Mods.RA.Widgets.Logic
onStart(); onStart();
} }
bool AutoCompleteText()
{
var chatText = lobby.Get<TextFieldWidget>("CHAT_TEXTFIELD");
if (chatText == null || string.IsNullOrEmpty(chatText.Text))
return false;
if (chatText.Text.LastOrDefault() == ' ')
return false;
var suggestion = "";
var oneWord = !chatText.Text.Contains(' ');
var toComplete = oneWord
? chatText.Text
: chatText.Text.Substring(chatText.Text.LastIndexOf(' ') + 1);
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;
}
class DropDownOption class DropDownOption
{ {
public string Title; public string Title;