Improves tab completion in chat.

Pressing tab after completion now cycles to the next candidate.
This commit is contained in:
Alexander Fast
2014-08-26 15:47:51 +02:00
parent f9255ecc49
commit 16965d5797
4 changed files with 95 additions and 76 deletions

View File

@@ -298,6 +298,7 @@
<Compile Include="Warheads\CreateResourceWarhead.cs" />
<Compile Include="Warheads\LeaveSmudgeWarhead.cs" />
<Compile Include="RemoveOnConditions.cs" />
<Compile Include="Widgets\Logic\TabCompletionLogic.cs" />
<Compile Include="World\RadarPings.cs" />
<Compile Include="Player\TechTree.cs" />
<Compile Include="PrimaryBuilding.cs" />

View File

@@ -8,7 +8,6 @@
*/
#endregion
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
@@ -31,8 +30,7 @@ namespace OpenRA.Mods.RA.Widgets.Logic
readonly List<INotifyChat> chatTraits;
readonly List<string> commandNames;
readonly List<string> playerNames;
readonly TabCompletionLogic tabCompletion = new TabCompletionLogic();
bool teamChat;
@@ -47,8 +45,8 @@ namespace OpenRA.Mods.RA.Widgets.Logic
var disableTeamChat = world.LocalPlayer == null || world.LobbyInfo.IsSinglePlayer || !players.Any(p => p.IsAlliedWith(world.LocalPlayer));
teamChat = !disableTeamChat;
commandNames = chatTraits.OfType<ChatCommands>().SelectMany(x => x.Commands.Keys).Select(x => "/" + x).ToList();
playerNames = orderManager.LobbyInfo.Clients.Select(c => c.Name).ToList();
tabCompletion.Commands = chatTraits.OfType<ChatCommands>().SelectMany(x => x.Commands.Keys).ToList();
tabCompletion.Names = orderManager.LobbyInfo.Clients.Select(c => c.Name).Distinct().ToList();
var chatPanel = (ContainerWidget)widget;
chatOverlay = chatPanel.Get<ContainerWidget>("CHAT_OVERLAY");
@@ -87,7 +85,12 @@ namespace OpenRA.Mods.RA.Widgets.Logic
CloseChat();
return true;
};
chatText.OnTabKey = AutoCompleteText;
chatText.OnTabKey = () =>
{
chatText.Text = tabCompletion.Complete(chatText.Text);
chatText.CursorPosition = chatText.Text.Length;
return true;
};
chatText.OnEscKey = () => { CloseChat(); return true; };
@@ -178,43 +181,5 @@ namespace OpenRA.Mods.RA.Widgets.Logic
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

@@ -51,7 +51,7 @@ namespace OpenRA.Mods.RA.Widgets.Logic
readonly ColorPreviewManagerWidget colorPreview;
List<string> playerNames;
readonly TabCompletionLogic tabCompletion = new TabCompletionLogic();
// Listen for connection failures
void ConnectionStateChanged(OrderManager om)
@@ -509,7 +509,12 @@ namespace OpenRA.Mods.RA.Widgets.Logic
chatLabel.Text = teamChat ? "Team:" : "Chat:";
return true;
};
chatTextField.OnTabKey = AutoCompleteText;
chatTextField.OnTabKey = () =>
{
chatTextField.Text = tabCompletion.Complete(chatTextField.Text);
chatTextField.CursorPosition = chatTextField.Text.Length;
return true;
};
chatPanel = lobby.Get<ScrollPanelWidget>("CHAT_DISPLAY");
chatTemplate = chatPanel.Get("CHAT_TEMPLATE");
@@ -770,7 +775,7 @@ namespace OpenRA.Mods.RA.Widgets.Logic
while (players.Children.Count > idx)
players.RemoveChild(players.Children[idx]);
playerNames = orderManager.LobbyInfo.Clients.Select(c => c.Name).ToList();
tabCompletion.Names = orderManager.LobbyInfo.Clients.Select(c => c.Name).Distinct().ToList();
}
void OnGameStart()
@@ -779,35 +784,6 @@ namespace OpenRA.Mods.RA.Widgets.Logic
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
{
public string Title;

View File

@@ -0,0 +1,77 @@
#region Copyright & License Information
/*
* Copyright 2007-2014 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using System;
using System.Collections.Generic;
using System.Linq;
namespace OpenRA.Mods.RA.Widgets.Logic
{
class TabCompletionLogic
{
IList<string> candidates = new List<string>();
int currentCandidateIndex = 0;
string lastCompleted;
string prefix;
string suffix;
public IList<string> Commands { get; set; }
public IList<string> Names { get; set; }
public string Complete(string text)
{
if (string.IsNullOrWhiteSpace(text))
return text;
if (lastCompleted == text)
{
lastCompleted = prefix + candidates[++currentCandidateIndex % candidates.Count] + suffix;
return lastCompleted;
}
var toComplete = "";
if (text.StartsWith("/") && Commands != null)
{
prefix = "/";
suffix = "";
toComplete = text.Substring(1);
candidates = Commands.Where(x => x.StartsWith(toComplete, StringComparison.InvariantCultureIgnoreCase)).ToList();
}
else if (Names != null)
{
var oneWord = text.Contains(' ');
if (oneWord)
{
prefix = text.Substring(0, text.LastIndexOf(' ') + 1);
suffix = "";
toComplete = text.Substring(prefix.Length);
}
else
{
prefix = "";
suffix = ": ";
toComplete = text;
}
candidates = Names.Where(x => x.StartsWith(toComplete, StringComparison.InvariantCultureIgnoreCase)).ToList();
}
else
return text;
currentCandidateIndex = 0;
if (candidates.Count == 0)
return text;
lastCompleted = prefix + candidates[currentCandidateIndex] + suffix;
return lastCompleted;
}
}
}