From 8dd4ae55eeb71f24e2cb5647f57ab35e34e82e4b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 1 Jun 2023 16:47:04 +0900 Subject: [PATCH 1/4] Allow selecting all text in a textbox programatically --- .../Visual/UserInterface/TestSceneTextBox.cs | 23 +++++++++++ .../Graphics/UserInterface/TextBox.cs | 40 +++++++++++++------ 2 files changed, 51 insertions(+), 12 deletions(-) diff --git a/osu.Framework.Tests/Visual/UserInterface/TestSceneTextBox.cs b/osu.Framework.Tests/Visual/UserInterface/TestSceneTextBox.cs index d93431c243..02d6387ca8 100644 --- a/osu.Framework.Tests/Visual/UserInterface/TestSceneTextBox.cs +++ b/osu.Framework.Tests/Visual/UserInterface/TestSceneTextBox.cs @@ -168,6 +168,29 @@ public void VariousTextBoxes() }); } + [Test] + public void TestSelectAll() + { + BasicTextBox textBox = null; + + AddStep("add number textbox", () => + { + textBoxes.Add(textBox = new BasicTextBox + { + Size = new Vector2(500, 30), + TabbableContentContainer = textBoxes + }); + }); + + AddStep(@"set arbitrary text", () => textBox.Text = "some text"); + AddAssert("not focused", () => textBox.HasFocus, () => Is.False); + + AddStep("select all", () => textBox.SelectAll()); + + AddAssert("has focus", () => textBox.HasFocus, () => Is.True); + AddAssert("has selection", () => textBox.SelectedText, () => Is.EqualTo(textBox.Text)); + } + [Test] public void TestNumbersOnly() { diff --git a/osu.Framework/Graphics/UserInterface/TextBox.cs b/osu.Framework/Graphics/UserInterface/TextBox.cs index c28d411fc9..177ec91c5f 100644 --- a/osu.Framework/Graphics/UserInterface/TextBox.cs +++ b/osu.Framework/Graphics/UserInterface/TextBox.cs @@ -233,8 +233,6 @@ public virtual bool OnPressed(KeyBindingPressEvent e) if (e.Action.IsCommonTextEditingAction() && ImeCompositionActive) return true; - var lastSelectionBounds = getTextSelectionBounds(); - switch (e.Action) { // Clipboard @@ -262,10 +260,7 @@ public virtual bool OnPressed(KeyBindingPressEvent e) return true; case PlatformAction.SelectAll: - selectionStart = 0; - selectionEnd = text.Length; - cursorAndLayout.Invalidate(); - onTextSelectionChanged(TextSelectionType.All, lastSelectionBounds); + SelectAll(); return true; // Cursor Manipulation @@ -321,34 +316,34 @@ public virtual bool OnPressed(KeyBindingPressEvent e) // Expand selection case PlatformAction.SelectBackwardChar: ExpandSelectionBy(-1); - onTextSelectionChanged(TextSelectionType.Character, lastSelectionBounds); + onTextSelectionChanged(TextSelectionType.Character, getTextSelectionBounds()); return true; case PlatformAction.SelectForwardChar: ExpandSelectionBy(1); - onTextSelectionChanged(TextSelectionType.Character, lastSelectionBounds); + onTextSelectionChanged(TextSelectionType.Character, getTextSelectionBounds()); return true; case PlatformAction.SelectBackwardWord: ExpandSelectionBy(GetBackwardWordAmount()); - onTextSelectionChanged(TextSelectionType.Word, lastSelectionBounds); + onTextSelectionChanged(TextSelectionType.Word, getTextSelectionBounds()); return true; case PlatformAction.SelectForwardWord: ExpandSelectionBy(GetForwardWordAmount()); - onTextSelectionChanged(TextSelectionType.Word, lastSelectionBounds); + onTextSelectionChanged(TextSelectionType.Word, getTextSelectionBounds()); return true; case PlatformAction.SelectBackwardLine: ExpandSelectionBy(GetBackwardLineAmount()); // TODO: Differentiate 'line' and 'all' selection types if/when multi-line support is added - onTextSelectionChanged(TextSelectionType.All, lastSelectionBounds); + onTextSelectionChanged(TextSelectionType.All, getTextSelectionBounds()); return true; case PlatformAction.SelectForwardLine: ExpandSelectionBy(GetForwardLineAmount()); // TODO: Differentiate 'line' and 'all' selection types if/when multi-line support is added - onTextSelectionChanged(TextSelectionType.All, lastSelectionBounds); + onTextSelectionChanged(TextSelectionType.All, getTextSelectionBounds()); return true; } @@ -999,6 +994,27 @@ private void setText(string value) cursorAndLayout.Invalidate(); } + /// + /// Select all text. + /// + /// + /// This will force focus if not already focused. + /// + public void SelectAll() + { + if (!HasFocus) + { + GetContainingInputManager().ChangeFocus(this); + Schedule(SelectAll); + return; + } + + selectionStart = 0; + selectionEnd = text.Length; + cursorAndLayout.Invalidate(); + onTextSelectionChanged(TextSelectionType.All, getTextSelectionBounds()); + } + public string SelectedText => selectionLength > 0 ? Text.Substring(selectionLeft, selectionLength) : string.Empty; /// From 418c536a2996b3c56d455c74409d4722611988ef Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 1 Jun 2023 20:28:23 +0900 Subject: [PATCH 2/4] Undo inlining of thing that can't be --- .../Graphics/UserInterface/TextBox.cs | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/osu.Framework/Graphics/UserInterface/TextBox.cs b/osu.Framework/Graphics/UserInterface/TextBox.cs index 177ec91c5f..bca290f0ff 100644 --- a/osu.Framework/Graphics/UserInterface/TextBox.cs +++ b/osu.Framework/Graphics/UserInterface/TextBox.cs @@ -233,6 +233,8 @@ public virtual bool OnPressed(KeyBindingPressEvent e) if (e.Action.IsCommonTextEditingAction() && ImeCompositionActive) return true; + var lastSelectionBounds = getTextSelectionBounds(); + switch (e.Action) { // Clipboard @@ -316,34 +318,34 @@ public virtual bool OnPressed(KeyBindingPressEvent e) // Expand selection case PlatformAction.SelectBackwardChar: ExpandSelectionBy(-1); - onTextSelectionChanged(TextSelectionType.Character, getTextSelectionBounds()); + onTextSelectionChanged(TextSelectionType.Character, lastSelectionBounds); return true; case PlatformAction.SelectForwardChar: ExpandSelectionBy(1); - onTextSelectionChanged(TextSelectionType.Character, getTextSelectionBounds()); + onTextSelectionChanged(TextSelectionType.Character, lastSelectionBounds); return true; case PlatformAction.SelectBackwardWord: ExpandSelectionBy(GetBackwardWordAmount()); - onTextSelectionChanged(TextSelectionType.Word, getTextSelectionBounds()); + onTextSelectionChanged(TextSelectionType.Word, lastSelectionBounds); return true; case PlatformAction.SelectForwardWord: ExpandSelectionBy(GetForwardWordAmount()); - onTextSelectionChanged(TextSelectionType.Word, getTextSelectionBounds()); + onTextSelectionChanged(TextSelectionType.Word, lastSelectionBounds); return true; case PlatformAction.SelectBackwardLine: ExpandSelectionBy(GetBackwardLineAmount()); // TODO: Differentiate 'line' and 'all' selection types if/when multi-line support is added - onTextSelectionChanged(TextSelectionType.All, getTextSelectionBounds()); + onTextSelectionChanged(TextSelectionType.All, lastSelectionBounds); return true; case PlatformAction.SelectForwardLine: ExpandSelectionBy(GetForwardLineAmount()); // TODO: Differentiate 'line' and 'all' selection types if/when multi-line support is added - onTextSelectionChanged(TextSelectionType.All, getTextSelectionBounds()); + onTextSelectionChanged(TextSelectionType.All, lastSelectionBounds); return true; } @@ -1009,10 +1011,12 @@ public void SelectAll() return; } + var lastSelectionBounds = getTextSelectionBounds(); + selectionStart = 0; selectionEnd = text.Length; cursorAndLayout.Invalidate(); - onTextSelectionChanged(TextSelectionType.All, getTextSelectionBounds()); + onTextSelectionChanged(TextSelectionType.All, lastSelectionBounds); } public string SelectedText => selectionLength > 0 ? Text.Substring(selectionLeft, selectionLength) : string.Empty; From 768a37de14102d6ade5566de2814542d7477a818 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 30 Oct 2023 13:36:18 +0900 Subject: [PATCH 3/4] Update implementation to not steal focus for now --- .../Visual/UserInterface/TestSceneTextBox.cs | 50 ++++++++++--------- .../Graphics/UserInterface/TextBox.cs | 38 ++++++-------- 2 files changed, 42 insertions(+), 46 deletions(-) diff --git a/osu.Framework.Tests/Visual/UserInterface/TestSceneTextBox.cs b/osu.Framework.Tests/Visual/UserInterface/TestSceneTextBox.cs index 02d6387ca8..f3f09e793e 100644 --- a/osu.Framework.Tests/Visual/UserInterface/TestSceneTextBox.cs +++ b/osu.Framework.Tests/Visual/UserInterface/TestSceneTextBox.cs @@ -168,29 +168,6 @@ public void VariousTextBoxes() }); } - [Test] - public void TestSelectAll() - { - BasicTextBox textBox = null; - - AddStep("add number textbox", () => - { - textBoxes.Add(textBox = new BasicTextBox - { - Size = new Vector2(500, 30), - TabbableContentContainer = textBoxes - }); - }); - - AddStep(@"set arbitrary text", () => textBox.Text = "some text"); - AddAssert("not focused", () => textBox.HasFocus, () => Is.False); - - AddStep("select all", () => textBox.SelectAll()); - - AddAssert("has focus", () => textBox.HasFocus, () => Is.True); - AddAssert("has selection", () => textBox.SelectedText, () => Is.EqualTo(textBox.Text)); - } - [Test] public void TestNumbersOnly() { @@ -825,6 +802,33 @@ public void TestSetTextSelection() AddAssert("nothing selected", () => textBox.SelectedText == string.Empty); } + [Test] + public void TestSelectAll() + { + TextBox textBox = null; + + AddStep("add textbox", () => + { + textBoxes.Add(textBox = new BasicTextBox + { + Size = new Vector2(300, 40), + Text = "initial text", + }); + }); + + AddAssert("select all fails", () => textBox.SelectAll(), () => Is.False); + AddAssert("no text selected", () => textBox.SelectedText, () => Is.EqualTo(string.Empty)); + + AddStep("click on textbox", () => + { + InputManager.MoveMouseTo(textBox); + InputManager.Click(MouseButton.Left); + }); + + AddAssert("select all succeeds", () => textBox.SelectAll(), () => Is.True); + AddAssert("all text selected", () => textBox.SelectedText, () => Is.EqualTo(textBox.Text)); + } + private void prependString(InsertableTextBox textBox, string text) { InputManager.Keys(PlatformAction.MoveBackwardLine); diff --git a/osu.Framework/Graphics/UserInterface/TextBox.cs b/osu.Framework/Graphics/UserInterface/TextBox.cs index 558631bbfd..617c7f9cff 100644 --- a/osu.Framework/Graphics/UserInterface/TextBox.cs +++ b/osu.Framework/Graphics/UserInterface/TextBox.cs @@ -359,6 +359,21 @@ public virtual void OnReleased(KeyBindingReleaseEvent e) { } + /// + /// Selects all text in this . Focus must be acquired before calling this method. + /// + /// Whether text has been selected successfully. Returns false if the text box does not have focus. + public bool SelectAll() + { + if (!HasFocus) + return false; + + selectionStart = 0; + selectionEnd = text.Length; + cursorAndLayout.Invalidate(); + return true; + } + /// /// Find the word boundary in the backward direction, then return the negative amount of characters. /// @@ -999,29 +1014,6 @@ private void setText(string value) cursorAndLayout.Invalidate(); } - /// - /// Select all text. - /// - /// - /// This will force focus if not already focused. - /// - public void SelectAll() - { - if (!HasFocus) - { - GetContainingInputManager().ChangeFocus(this); - Schedule(SelectAll); - return; - } - - var lastSelectionBounds = getTextSelectionBounds(); - - selectionStart = 0; - selectionEnd = text.Length; - cursorAndLayout.Invalidate(); - onTextSelectionChanged(TextSelectionType.All, lastSelectionBounds); - } - public string SelectedText => selectionLength > 0 ? Text.Substring(selectionLeft, selectionLength) : string.Empty; /// From 0cf3239e97f59145bb3a49f4b93212701fb9d56b Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Mon, 30 Oct 2023 08:16:09 +0300 Subject: [PATCH 4/4] Fix refactor error --- osu.Framework/Graphics/UserInterface/TextBox.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Framework/Graphics/UserInterface/TextBox.cs b/osu.Framework/Graphics/UserInterface/TextBox.cs index 617c7f9cff..d9a74aecab 100644 --- a/osu.Framework/Graphics/UserInterface/TextBox.cs +++ b/osu.Framework/Graphics/UserInterface/TextBox.cs @@ -266,6 +266,7 @@ public virtual bool OnPressed(KeyBindingPressEvent e) case PlatformAction.SelectAll: SelectAll(); + onTextSelectionChanged(TextSelectionType.All, lastSelectionBounds); return true; // Cursor Manipulation