Merge pull request #9582 from ChaoticMind/ctrl_backspace

Implement some keyboard hotkeys for chat (TextFieldWidget)
This commit is contained in:
abcdefg30
2015-11-18 20:48:05 +01:00
6 changed files with 202 additions and 70 deletions

View File

@@ -61,6 +61,7 @@ namespace OpenRA
Bitmap TakeScreenshot(); Bitmap TakeScreenshot();
void PumpInput(IInputHandler inputHandler); void PumpInput(IInputHandler inputHandler);
string GetClipboardText(); string GetClipboardText();
bool SetClipboardText(string text);
void DrawPrimitives(PrimitiveType type, int firstVertex, int numVertices); void DrawPrimitives(PrimitiveType type, int firstVertex, int numVertices);
void SetLineWidth(float width); void SetLineWidth(float width);

View File

@@ -267,5 +267,10 @@ namespace OpenRA
{ {
return Device.GetClipboardText(); return Device.GetClipboardText();
} }
public bool SetClipboardText(string text)
{
return Device.SetClipboardText(text);
}
} }
} }

View File

@@ -69,6 +69,12 @@ namespace OpenRA.Mods.Common.Widgets
return base.YieldKeyboardFocus(); return base.YieldKeyboardFocus();
} }
protected void ResetBlinkCycle()
{
blinkCycle = 10;
showCursor = true;
}
public override bool HandleMouseInput(MouseInput mi) public override bool HandleMouseInput(MouseInput mi)
{ {
if (IsDisabled()) if (IsDisabled())
@@ -81,15 +87,14 @@ namespace OpenRA.Mods.Common.Widgets
if (!RenderBounds.Contains(mi.Location) || !TakeKeyboardFocus()) if (!RenderBounds.Contains(mi.Location) || !TakeKeyboardFocus())
return false; return false;
blinkCycle = 10; ResetBlinkCycle();
showCursor = true;
CursorPosition = ClosestCursorPosition(mi.Location.X); CursorPosition = ClosestCursorPosition(mi.Location.X);
return true; return true;
} }
protected virtual string GetApparentText() { return text; } protected virtual string GetApparentText() { return text; }
public int ClosestCursorPosition(int x) int ClosestCursorPosition(int x)
{ {
var apparentText = GetApparentText(); var apparentText = GetApparentText();
var font = Game.Renderer.Fonts[Font]; var font = Game.Renderer.Fonts[Font];
@@ -113,6 +118,23 @@ namespace OpenRA.Mods.Common.Widgets
return minIndex; return minIndex;
} }
int GetPrevWhitespaceIndex()
{
return Text.Substring(0, CursorPosition).TrimEnd().LastIndexOf(' ') + 1;
}
int GetNextWhitespaceIndex()
{
var substr = Text.Substring(CursorPosition);
var substrTrimmed = substr.TrimStart();
var trimmedSpaces = substr.Length - substrTrimmed.Length;
var nextWhitespace = substrTrimmed.IndexOf(' ');
if (nextWhitespace == -1)
return Text.Length;
return CursorPosition + trimmedSpaces + nextWhitespace;
}
public override bool HandleKeyPress(KeyInput e) public override bool HandleKeyPress(KeyInput e)
{ {
if (IsDisabled() || e.Event == KeyInputEvent.Up) if (IsDisabled() || e.Event == KeyInputEvent.Up)
@@ -122,83 +144,179 @@ namespace OpenRA.Mods.Common.Widgets
if (!HasKeyboardFocus) if (!HasKeyboardFocus)
return false; return false;
if ((e.Key == Keycode.RETURN || e.Key == Keycode.KP_ENTER) && OnEnterKey()) var isOSX = Platform.CurrentPlatform == PlatformType.OSX;
return true;
if (e.Key == Keycode.TAB && OnTabKey()) switch (e.Key) {
return true; case Keycode.RETURN:
case Keycode.KP_ENTER:
if (OnEnterKey())
return true;
break;
if (e.Key == Keycode.ESCAPE && OnEscKey()) case Keycode.TAB:
return true; if (OnTabKey())
return true;
break;
if (e.Key == Keycode.LALT && OnAltKey()) case Keycode.ESCAPE:
return true; if (OnEscKey())
return true;
break;
if (e.Key == Keycode.LEFT) case Keycode.LALT:
{ if (OnAltKey())
if (CursorPosition > 0) return true;
CursorPosition--; break;
return true; case Keycode.LEFT:
} ResetBlinkCycle();
if (CursorPosition > 0)
{
if ((!isOSX && e.Modifiers.HasModifier(Modifiers.Ctrl)) || (isOSX && e.Modifiers.HasModifier(Modifiers.Alt)))
CursorPosition = GetPrevWhitespaceIndex();
else if (isOSX && e.Modifiers.HasModifier(Modifiers.Meta))
CursorPosition = 0;
else
CursorPosition--;
}
if (e.Key == Keycode.RIGHT) break;
{
if (CursorPosition <= Text.Length - 1)
CursorPosition++;
return true; case Keycode.RIGHT:
} ResetBlinkCycle();
if (CursorPosition <= Text.Length - 1)
{
if ((!isOSX && e.Modifiers.HasModifier(Modifiers.Ctrl)) || (isOSX && e.Modifiers.HasModifier(Modifiers.Alt)))
CursorPosition = GetNextWhitespaceIndex();
else if (isOSX && e.Modifiers.HasModifier(Modifiers.Meta))
CursorPosition = Text.Length;
else
CursorPosition++;
}
if (e.Key == Keycode.HOME) break;
{
CursorPosition = 0;
return true;
}
if (e.Key == Keycode.END) case Keycode.HOME:
{ ResetBlinkCycle();
CursorPosition = Text.Length; CursorPosition = 0;
return true; break;
}
if (e.Key == Keycode.DELETE) case Keycode.END:
{ ResetBlinkCycle();
if (CursorPosition < Text.Length) CursorPosition = Text.Length;
{ break;
Text = Text.Remove(CursorPosition, 1);
OnTextEdited(); case Keycode.D:
if (e.Modifiers.HasModifier(Modifiers.Ctrl) && CursorPosition < Text.Length)
{
Text = Text.Remove(CursorPosition, 1);
OnTextEdited();
}
break;
case Keycode.K:
// ctrl+k is equivalent to cmd+delete on osx (but also works on osx)
ResetBlinkCycle();
if (e.Modifiers.HasModifier(Modifiers.Ctrl) && CursorPosition < Text.Length)
{
Text = Text.Remove(CursorPosition);
OnTextEdited();
}
break;
case Keycode.U:
// ctrl+u is equivalent to cmd+backspace on osx
ResetBlinkCycle();
if (!isOSX && e.Modifiers.HasModifier(Modifiers.Ctrl) && CursorPosition > 0)
{
Text = Text.Substring(CursorPosition);
CursorPosition = 0;
OnTextEdited();
}
break;
case Keycode.X:
ResetBlinkCycle();
if (((!isOSX && e.Modifiers.HasModifier(Modifiers.Ctrl)) || (isOSX && e.Modifiers.HasModifier(Modifiers.Meta))) &&
!string.IsNullOrEmpty(Text))
{
Game.Renderer.SetClipboardText(Text);
Text = Text.Remove(0);
CursorPosition = 0;
OnTextEdited();
}
break;
case Keycode.DELETE:
// cmd+delete is equivalent to ctrl+k on non-osx
ResetBlinkCycle();
if (CursorPosition < Text.Length)
{
if ((!isOSX && e.Modifiers.HasModifier(Modifiers.Ctrl)) || (isOSX && e.Modifiers.HasModifier(Modifiers.Alt)))
Text = Text.Substring(0, CursorPosition) + Text.Substring(GetNextWhitespaceIndex());
else if (isOSX && e.Modifiers.HasModifier(Modifiers.Meta))
Text = Text.Remove(CursorPosition);
else
Text = Text.Remove(CursorPosition, 1);
OnTextEdited();
}
break;
case Keycode.BACKSPACE:
// cmd+backspace is equivalent to ctrl+u on non-osx
ResetBlinkCycle();
if (CursorPosition > 0)
{
if ((!isOSX && e.Modifiers.HasModifier(Modifiers.Ctrl)) || (isOSX && e.Modifiers.HasModifier(Modifiers.Alt)))
{
var prevWhitespace = GetPrevWhitespaceIndex();
Text = Text.Substring(0, prevWhitespace) + Text.Substring(CursorPosition);
CursorPosition = prevWhitespace;
}
else if (isOSX && e.Modifiers.HasModifier(Modifiers.Meta))
{
Text = Text.Substring(CursorPosition);
CursorPosition = 0;
}
else
{
CursorPosition--;
Text = Text.Remove(CursorPosition, 1);
}
OnTextEdited();
}
break;
case Keycode.V:
ResetBlinkCycle();
if ((!isOSX && e.Modifiers.HasModifier(Modifiers.Ctrl)) || (isOSX && e.Modifiers.HasModifier(Modifiers.Meta)))
{
var clipboardText = Game.Renderer.GetClipboardText();
// Take only the first line of the clipboard contents
var nl = clipboardText.IndexOf('\n');
if (nl > 0)
clipboardText = clipboardText.Substring(0, nl);
clipboardText = clipboardText.Trim();
if (clipboardText.Length > 0)
HandleTextInput(clipboardText);
}
break;
default:
break;
} }
return true;
}
if (e.Key == Keycode.BACKSPACE && CursorPosition > 0)
{
CursorPosition--;
Text = Text.Remove(CursorPosition, 1);
OnTextEdited();
return true;
}
if (e.Key == Keycode.V &&
((Platform.CurrentPlatform != PlatformType.OSX && e.Modifiers.HasModifier(Modifiers.Ctrl)) ||
(Platform.CurrentPlatform == PlatformType.OSX && e.Modifiers.HasModifier(Modifiers.Meta))))
{
var clipboardText = Game.Renderer.GetClipboardText();
// Take only the first line of the clipboard contents
var nl = clipboardText.IndexOf('\n');
if (nl > 0)
clipboardText = clipboardText.Substring(0, nl);
clipboardText = clipboardText.Trim();
if (clipboardText.Length > 0)
HandleTextInput(clipboardText);
return true;
}
return true; return true;
} }

View File

@@ -382,6 +382,12 @@ namespace OpenRA.Platforms.Default
return input.GetClipboardText(); return input.GetClipboardText();
} }
public bool SetClipboardText(string text)
{
VerifyThreadAffinity();
return input.SetClipboardText(text);
}
public IVertexBuffer<Vertex> CreateVertexBuffer(int size) public IVertexBuffer<Vertex> CreateVertexBuffer(int size)
{ {
VerifyThreadAffinity(); VerifyThreadAffinity();

View File

@@ -20,6 +20,7 @@ namespace OpenRA.Platforms.Default
MouseButton lastButtonBits = (MouseButton)0; MouseButton lastButtonBits = (MouseButton)0;
public string GetClipboardText() { return SDL.SDL_GetClipboardText(); } public string GetClipboardText() { return SDL.SDL_GetClipboardText(); }
public bool SetClipboardText(string text) { return SDL.SDL_SetClipboardText(text) == 0; }
static MouseButton MakeButton(byte b) static MouseButton MakeButton(byte b)
{ {

View File

@@ -42,6 +42,7 @@ namespace OpenRA.Platforms.Null
public Bitmap TakeScreenshot() { return new Bitmap(1, 1); } public Bitmap TakeScreenshot() { return new Bitmap(1, 1); }
public string GetClipboardText() { return ""; } public string GetClipboardText() { return ""; }
public bool SetClipboardText(string text) { return false; }
public void PumpInput(IInputHandler ih) public void PumpInput(IInputHandler ih)
{ {
Game.HasInputFocus = false; Game.HasInputFocus = false;