From a1af663682cce72d49244c194f072a6a1f064fe5 Mon Sep 17 00:00:00 2001 From: Dragon Date: Sun, 13 Nov 2022 20:49:26 +0100 Subject: [PATCH 01/20] Implemented previous messages lookup in the ChatTextBox.cs --- osu.Game/Overlays/Chat/ChatTextBox.cs | 57 +++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/osu.Game/Overlays/Chat/ChatTextBox.cs b/osu.Game/Overlays/Chat/ChatTextBox.cs index 887eb96c15..fc4c2ae727 100644 --- a/osu.Game/Overlays/Chat/ChatTextBox.cs +++ b/osu.Game/Overlays/Chat/ChatTextBox.cs @@ -1,14 +1,23 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System.Collections.Generic; using osu.Framework.Bindables; +using osu.Framework.Input.Events; using osu.Game.Graphics.UserInterface; using osu.Game.Resources.Localisation.Web; +using osuTK.Input; namespace osu.Game.Overlays.Chat { public class ChatTextBox : FocusedTextBox { + private readonly List messageHistory = new List(); + + private int messageIndex = -1; + + private string originalMessage = string.Empty; + public readonly BindableBool ShowSearch = new BindableBool(); public override bool HandleLeftRightArrows => !ShowSearch.Value; @@ -28,11 +37,59 @@ namespace osu.Game.Overlays.Chat }, true); } + protected override bool OnKeyDown(KeyDownEvent e) + { + /* Behavior: + * add when on last element -> last element stays + * subtract when on first element -> sets to original text + * reset indexing when Text is set to Empty + */ + + switch (e.Key) + { + case Key.Up: + if (messageIndex == -1) + originalMessage = Text; + + if (messageIndex == messageHistory.Count - 1) + return true; + + Text = messageHistory[++messageIndex]; + + return true; + + case Key.Down: + if (messageIndex == -1) + return true; + + if (messageIndex == 0) + { + messageIndex = -1; + Text = originalMessage; + return true; + } + + Text = messageHistory[--messageIndex]; + + return true; + } + + bool onKeyDown = base.OnKeyDown(e); + + if (string.IsNullOrEmpty(Text)) + messageIndex = -1; + + return onKeyDown; + } + protected override void Commit() { if (ShowSearch.Value) return; + messageHistory.Insert(0, Text); + messageIndex = -1; + base.Commit(); } } From b9590320b750d64ed532ce0621f54019940c1f4c Mon Sep 17 00:00:00 2001 From: Dragon Date: Sun, 13 Nov 2022 22:34:02 +0100 Subject: [PATCH 02/20] Moved implementation to ChatRecentTextBox.cs and derived ChatTextBox.cs and StandAloneChatDisplay.cs from it. --- osu.Game/Online/Chat/StandAloneChatDisplay.cs | 14 ++-- osu.Game/Overlays/Chat/ChatRecentTextBox.cs | 74 +++++++++++++++++++ osu.Game/Overlays/Chat/ChatTextBox.cs | 60 +-------------- 3 files changed, 83 insertions(+), 65 deletions(-) create mode 100644 osu.Game/Overlays/Chat/ChatRecentTextBox.cs diff --git a/osu.Game/Online/Chat/StandAloneChatDisplay.cs b/osu.Game/Online/Chat/StandAloneChatDisplay.cs index 81db3f0d53..de0387e017 100644 --- a/osu.Game/Online/Chat/StandAloneChatDisplay.cs +++ b/osu.Game/Online/Chat/StandAloneChatDisplay.cs @@ -12,7 +12,6 @@ using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.UserInterface; using osu.Framework.Input.Events; using osu.Game.Graphics; -using osu.Game.Graphics.UserInterface; using osu.Game.Overlays.Chat; using osu.Game.Resources.Localisation.Web; using osuTK.Graphics; @@ -120,17 +119,20 @@ namespace osu.Game.Online.Chat AddInternal(drawableChannel); } - public class ChatTextBox : FocusedTextBox + public class ChatTextBox : ChatRecentTextBox { protected override bool OnKeyDown(KeyDownEvent e) { // Chat text boxes are generally used in places where they retain focus, but shouldn't block interaction with other // elements on the same screen. - switch (e.Key) + if (!HoldFocus) { - case Key.Up: - case Key.Down: - return false; + switch (e.Key) + { + case Key.Up: + case Key.Down: + return false; + } } return base.OnKeyDown(e); diff --git a/osu.Game/Overlays/Chat/ChatRecentTextBox.cs b/osu.Game/Overlays/Chat/ChatRecentTextBox.cs new file mode 100644 index 0000000000..87bc3ee48c --- /dev/null +++ b/osu.Game/Overlays/Chat/ChatRecentTextBox.cs @@ -0,0 +1,74 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Collections.Generic; +using osu.Framework.Input.Events; +using osu.Game.Graphics.UserInterface; +using osuTK.Input; + +namespace osu.Game.Overlays.Chat +{ + public class ChatRecentTextBox : FocusedTextBox + { + private readonly List messageHistory = new List(); + + private int messageIndex = -1; + + private string originalMessage = string.Empty; + + protected override bool OnKeyDown(KeyDownEvent e) + { + /* Behavior: + * add when on last element -> last element stays + * subtract when on first element -> sets to original text + * reset indexing when Text is set to Empty + */ + + switch (e.Key) + { + case Key.Up: + if (messageIndex == -1) + originalMessage = Text; + + if (messageIndex == messageHistory.Count - 1) + return true; + + Text = messageHistory[++messageIndex]; + + return true; + + case Key.Down: + if (messageIndex == -1) + return true; + + if (messageIndex == 0) + { + messageIndex = -1; + Text = originalMessage; + return true; + } + + Text = messageHistory[--messageIndex]; + + return true; + } + + bool onKeyDown = base.OnKeyDown(e); + + if (string.IsNullOrEmpty(Text)) + messageIndex = -1; + + return onKeyDown; + } + + protected override void Commit() + { + if (!string.IsNullOrEmpty(Text)) + messageHistory.Insert(0, Text); + + messageIndex = -1; + + base.Commit(); + } + } +} diff --git a/osu.Game/Overlays/Chat/ChatTextBox.cs b/osu.Game/Overlays/Chat/ChatTextBox.cs index fc4c2ae727..d3c1a4ad8b 100644 --- a/osu.Game/Overlays/Chat/ChatTextBox.cs +++ b/osu.Game/Overlays/Chat/ChatTextBox.cs @@ -1,23 +1,13 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System.Collections.Generic; using osu.Framework.Bindables; -using osu.Framework.Input.Events; -using osu.Game.Graphics.UserInterface; using osu.Game.Resources.Localisation.Web; -using osuTK.Input; namespace osu.Game.Overlays.Chat { - public class ChatTextBox : FocusedTextBox + public class ChatTextBox : ChatRecentTextBox { - private readonly List messageHistory = new List(); - - private int messageIndex = -1; - - private string originalMessage = string.Empty; - public readonly BindableBool ShowSearch = new BindableBool(); public override bool HandleLeftRightArrows => !ShowSearch.Value; @@ -37,59 +27,11 @@ namespace osu.Game.Overlays.Chat }, true); } - protected override bool OnKeyDown(KeyDownEvent e) - { - /* Behavior: - * add when on last element -> last element stays - * subtract when on first element -> sets to original text - * reset indexing when Text is set to Empty - */ - - switch (e.Key) - { - case Key.Up: - if (messageIndex == -1) - originalMessage = Text; - - if (messageIndex == messageHistory.Count - 1) - return true; - - Text = messageHistory[++messageIndex]; - - return true; - - case Key.Down: - if (messageIndex == -1) - return true; - - if (messageIndex == 0) - { - messageIndex = -1; - Text = originalMessage; - return true; - } - - Text = messageHistory[--messageIndex]; - - return true; - } - - bool onKeyDown = base.OnKeyDown(e); - - if (string.IsNullOrEmpty(Text)) - messageIndex = -1; - - return onKeyDown; - } - protected override void Commit() { if (ShowSearch.Value) return; - messageHistory.Insert(0, Text); - messageIndex = -1; - base.Commit(); } } From 6d83af01e21228e56753d200e7aee0c94e0b2e67 Mon Sep 17 00:00:00 2001 From: Terochi Date: Tue, 15 Nov 2022 13:06:02 +0100 Subject: [PATCH 03/20] Moved and renamed MessageHistoryTextBox.cs for better fit. --- .../UserInterface/MessageHistoryTextBox.cs} | 21 +++++++++++-------- osu.Game/Online/Chat/StandAloneChatDisplay.cs | 3 ++- osu.Game/Overlays/Chat/ChatTextBox.cs | 3 ++- 3 files changed, 16 insertions(+), 11 deletions(-) rename osu.Game/{Overlays/Chat/ChatRecentTextBox.cs => Graphics/UserInterface/MessageHistoryTextBox.cs} (82%) diff --git a/osu.Game/Overlays/Chat/ChatRecentTextBox.cs b/osu.Game/Graphics/UserInterface/MessageHistoryTextBox.cs similarity index 82% rename from osu.Game/Overlays/Chat/ChatRecentTextBox.cs rename to osu.Game/Graphics/UserInterface/MessageHistoryTextBox.cs index 87bc3ee48c..45497e0451 100644 --- a/osu.Game/Overlays/Chat/ChatRecentTextBox.cs +++ b/osu.Game/Graphics/UserInterface/MessageHistoryTextBox.cs @@ -3,12 +3,11 @@ using System.Collections.Generic; using osu.Framework.Input.Events; -using osu.Game.Graphics.UserInterface; using osuTK.Input; -namespace osu.Game.Overlays.Chat +namespace osu.Game.Graphics.UserInterface { - public class ChatRecentTextBox : FocusedTextBox + public class MessageHistoryTextBox : FocusedTextBox { private readonly List messageHistory = new List(); @@ -16,6 +15,15 @@ namespace osu.Game.Overlays.Chat private string originalMessage = string.Empty; + public MessageHistoryTextBox() + { + Current.ValueChanged += text => + { + if (string.IsNullOrEmpty(text.NewValue)) + messageIndex = -1; + }; + } + protected override bool OnKeyDown(KeyDownEvent e) { /* Behavior: @@ -53,12 +61,7 @@ namespace osu.Game.Overlays.Chat return true; } - bool onKeyDown = base.OnKeyDown(e); - - if (string.IsNullOrEmpty(Text)) - messageIndex = -1; - - return onKeyDown; + return base.OnKeyDown(e); } protected override void Commit() diff --git a/osu.Game/Online/Chat/StandAloneChatDisplay.cs b/osu.Game/Online/Chat/StandAloneChatDisplay.cs index de0387e017..fe279d50a9 100644 --- a/osu.Game/Online/Chat/StandAloneChatDisplay.cs +++ b/osu.Game/Online/Chat/StandAloneChatDisplay.cs @@ -12,6 +12,7 @@ using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.UserInterface; using osu.Framework.Input.Events; using osu.Game.Graphics; +using osu.Game.Graphics.UserInterface; using osu.Game.Overlays.Chat; using osu.Game.Resources.Localisation.Web; using osuTK.Graphics; @@ -119,7 +120,7 @@ namespace osu.Game.Online.Chat AddInternal(drawableChannel); } - public class ChatTextBox : ChatRecentTextBox + public class ChatTextBox : MessageHistoryTextBox { protected override bool OnKeyDown(KeyDownEvent e) { diff --git a/osu.Game/Overlays/Chat/ChatTextBox.cs b/osu.Game/Overlays/Chat/ChatTextBox.cs index d3c1a4ad8b..26ff4a5b4e 100644 --- a/osu.Game/Overlays/Chat/ChatTextBox.cs +++ b/osu.Game/Overlays/Chat/ChatTextBox.cs @@ -2,11 +2,12 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Bindables; +using osu.Game.Graphics.UserInterface; using osu.Game.Resources.Localisation.Web; namespace osu.Game.Overlays.Chat { - public class ChatTextBox : ChatRecentTextBox + public class ChatTextBox : MessageHistoryTextBox { public readonly BindableBool ShowSearch = new BindableBool(); From a79af6671eceb918dd598a0c60d997030f57fdcb Mon Sep 17 00:00:00 2001 From: Terochi Date: Tue, 15 Nov 2022 13:07:05 +0100 Subject: [PATCH 04/20] Added SetUp for new tests. --- .../Online/TestSceneChatManipulation.cs | 74 +++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 osu.Game.Tests/Visual/Online/TestSceneChatManipulation.cs diff --git a/osu.Game.Tests/Visual/Online/TestSceneChatManipulation.cs b/osu.Game.Tests/Visual/Online/TestSceneChatManipulation.cs new file mode 100644 index 0000000000..6de2584c72 --- /dev/null +++ b/osu.Game.Tests/Visual/Online/TestSceneChatManipulation.cs @@ -0,0 +1,74 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +#nullable disable + +using NUnit.Framework; +using osu.Framework.Graphics; +using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; +using osu.Game.Overlays.Chat; + +namespace osu.Game.Tests.Visual.Online +{ + [TestFixture] + public class TestSceneChatManipulation : OsuTestScene + { + private ChatTextBox box; + private OsuSpriteText text; + + [SetUp] + public void SetUp() + { + Schedule(() => + { + Children = new Drawable[] + { + box = new ChatTextBox + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.X, + Width = 0.99f, + }, + text = new OsuSpriteText + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.X, + Width = 0.99f, + Y = -box.Height, + Font = OsuFont.Default.With(size: 20), + } + }; + box.OnCommit += (_, __) => + { + text.Text = $"{nameof(box.OnCommit)}: {box.Text}"; + box.Text = string.Empty; + box.TakeFocus(); + text.FadeOutFromOne(1000, Easing.InQuint); + }; + }); + } + + [Test] + public void TestReachingLimitOfMessages() + { + } + + [Test] + public void TestStayOnLastIndex() + { + } + + [Test] + public void TestKeepOriginalMessage() + { + } + + [Test] + public void TestResetIndexOnEmpty() + { + } + } +} From 3d4962e1810e3f53e22125cf1012a5c036dade05 Mon Sep 17 00:00:00 2001 From: Terochi Date: Tue, 15 Nov 2022 16:12:24 +0100 Subject: [PATCH 05/20] Added functioning tests. --- .../Online/TestSceneChatManipulation.cs | 59 +++++++++++++++++-- ...ageHistoryTextBox.cs => HistoryTextBox.cs} | 32 +++++----- osu.Game/Online/Chat/StandAloneChatDisplay.cs | 2 +- osu.Game/Overlays/Chat/ChatTextBox.cs | 2 +- 4 files changed, 69 insertions(+), 26 deletions(-) rename osu.Game/Graphics/UserInterface/{MessageHistoryTextBox.cs => HistoryTextBox.cs} (62%) diff --git a/osu.Game.Tests/Visual/Online/TestSceneChatManipulation.cs b/osu.Game.Tests/Visual/Online/TestSceneChatManipulation.cs index 6de2584c72..4fe0cb685e 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneChatManipulation.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneChatManipulation.cs @@ -3,16 +3,18 @@ #nullable disable +using System.Linq; using NUnit.Framework; using osu.Framework.Graphics; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Overlays.Chat; +using osuTK.Input; namespace osu.Game.Tests.Visual.Online { [TestFixture] - public class TestSceneChatManipulation : OsuTestScene + public class TestSceneChatManipulation : OsuManualInputManagerTestScene { private ChatTextBox box; private OsuSpriteText text; @@ -41,6 +43,7 @@ namespace osu.Game.Tests.Visual.Online Font = OsuFont.Default.With(size: 20), } }; + box.OnCommit += (_, __) => { text.Text = $"{nameof(box.OnCommit)}: {box.Text}"; @@ -48,27 +51,71 @@ namespace osu.Game.Tests.Visual.Online box.TakeFocus(); text.FadeOutFromOne(1000, Easing.InQuint); }; - }); - } - [Test] - public void TestReachingLimitOfMessages() - { + box.TakeFocus(); + }); } [Test] public void TestStayOnLastIndex() { + addMessages(2); + AddRepeatStep("Move to last", () => InputManager.Key(Key.Up), 2); + + string lastText = string.Empty; + AddStep("Move up", () => + { + lastText = box.Text; + InputManager.Key(Key.Up); + }); + + AddAssert("Text hasn't changed", () => lastText == box.Text); } [Test] public void TestKeepOriginalMessage() { + addMessages(1); + AddStep("Start writing", () => box.Text = "A random 文, ..."); + + AddStep("Move up", () => InputManager.Key(Key.Up)); + AddStep("Rewrite old message", () => box.Text = "Old Message"); + + AddStep("Move back down", () => InputManager.Key(Key.Down)); + AddAssert("Text back to previous", () => box.Text == "A random 文, ..."); } [Test] public void TestResetIndexOnEmpty() { + addMessages(2); + AddRepeatStep("Move up", () => InputManager.Key(Key.Up), 2); + AddStep("Remove text", () => box.Text = string.Empty); + + AddStep("Move up again", () => InputManager.Key(Key.Up)); + AddAssert("Back to first message", () => box.Text == "Message 2"); + } + + [Test] + public void TestReachingLimitOfMessages() + { + addMessages(100); + AddAssert("List is full of <100-1>", () => + Enumerable.Range(0, 100).Select(number => $"Message {100 - number}").SequenceEqual(box.MessageHistory)); + + addMessages(2); + AddAssert("List is full of <102-3>", () => + Enumerable.Range(0, 100).Select(number => $"Message {102 - number}").SequenceEqual(box.MessageHistory)); + } + + private void addMessages(int count) + { + int iterations = 0; + AddRepeatStep("Add messages", () => + { + box.Text = $"Message {++iterations}"; + InputManager.Key(Key.Enter); + }, count); } } } diff --git a/osu.Game/Graphics/UserInterface/MessageHistoryTextBox.cs b/osu.Game/Graphics/UserInterface/HistoryTextBox.cs similarity index 62% rename from osu.Game/Graphics/UserInterface/MessageHistoryTextBox.cs rename to osu.Game/Graphics/UserInterface/HistoryTextBox.cs index 45497e0451..1b553576d5 100644 --- a/osu.Game/Graphics/UserInterface/MessageHistoryTextBox.cs +++ b/osu.Game/Graphics/UserInterface/HistoryTextBox.cs @@ -7,56 +7,52 @@ using osuTK.Input; namespace osu.Game.Graphics.UserInterface { - public class MessageHistoryTextBox : FocusedTextBox + public class HistoryTextBox : FocusedTextBox { private readonly List messageHistory = new List(); - private int messageIndex = -1; + public IReadOnlyList MessageHistory => messageHistory; + + private int historyIndex = -1; private string originalMessage = string.Empty; - public MessageHistoryTextBox() + public HistoryTextBox() { Current.ValueChanged += text => { if (string.IsNullOrEmpty(text.NewValue)) - messageIndex = -1; + historyIndex = -1; }; } protected override bool OnKeyDown(KeyDownEvent e) { - /* Behavior: - * add when on last element -> last element stays - * subtract when on first element -> sets to original text - * reset indexing when Text is set to Empty - */ - switch (e.Key) { case Key.Up: - if (messageIndex == -1) + if (historyIndex == -1) originalMessage = Text; - if (messageIndex == messageHistory.Count - 1) + if (historyIndex == messageHistory.Count - 1) return true; - Text = messageHistory[++messageIndex]; + Text = messageHistory[++historyIndex]; return true; case Key.Down: - if (messageIndex == -1) + if (historyIndex == -1) return true; - if (messageIndex == 0) + if (historyIndex == 0) { - messageIndex = -1; + historyIndex = -1; Text = originalMessage; return true; } - Text = messageHistory[--messageIndex]; + Text = messageHistory[--historyIndex]; return true; } @@ -69,7 +65,7 @@ namespace osu.Game.Graphics.UserInterface if (!string.IsNullOrEmpty(Text)) messageHistory.Insert(0, Text); - messageIndex = -1; + historyIndex = -1; base.Commit(); } diff --git a/osu.Game/Online/Chat/StandAloneChatDisplay.cs b/osu.Game/Online/Chat/StandAloneChatDisplay.cs index fe279d50a9..03728b427f 100644 --- a/osu.Game/Online/Chat/StandAloneChatDisplay.cs +++ b/osu.Game/Online/Chat/StandAloneChatDisplay.cs @@ -120,7 +120,7 @@ namespace osu.Game.Online.Chat AddInternal(drawableChannel); } - public class ChatTextBox : MessageHistoryTextBox + public class ChatTextBox : HistoryTextBox { protected override bool OnKeyDown(KeyDownEvent e) { diff --git a/osu.Game/Overlays/Chat/ChatTextBox.cs b/osu.Game/Overlays/Chat/ChatTextBox.cs index 26ff4a5b4e..f0bdbce08d 100644 --- a/osu.Game/Overlays/Chat/ChatTextBox.cs +++ b/osu.Game/Overlays/Chat/ChatTextBox.cs @@ -7,7 +7,7 @@ using osu.Game.Resources.Localisation.Web; namespace osu.Game.Overlays.Chat { - public class ChatTextBox : MessageHistoryTextBox + public class ChatTextBox : HistoryTextBox { public readonly BindableBool ShowSearch = new BindableBool(); From 44c3e71746b43337ad8cbaab0410e73d8f959d54 Mon Sep 17 00:00:00 2001 From: Terochi Date: Tue, 15 Nov 2022 18:10:43 +0100 Subject: [PATCH 06/20] Reversed indexing --- .../Graphics/UserInterface/HistoryTextBox.cs | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/HistoryTextBox.cs b/osu.Game/Graphics/UserInterface/HistoryTextBox.cs index 1b553576d5..96c0734d63 100644 --- a/osu.Game/Graphics/UserInterface/HistoryTextBox.cs +++ b/osu.Game/Graphics/UserInterface/HistoryTextBox.cs @@ -13,7 +13,7 @@ namespace osu.Game.Graphics.UserInterface public IReadOnlyList MessageHistory => messageHistory; - private int historyIndex = -1; + private int historyIndex; private string originalMessage = string.Empty; @@ -22,7 +22,7 @@ namespace osu.Game.Graphics.UserInterface Current.ValueChanged += text => { if (string.IsNullOrEmpty(text.NewValue)) - historyIndex = -1; + historyIndex = messageHistory.Count; }; } @@ -31,28 +31,28 @@ namespace osu.Game.Graphics.UserInterface switch (e.Key) { case Key.Up: - if (historyIndex == -1) + if (historyIndex == messageHistory.Count) originalMessage = Text; - if (historyIndex == messageHistory.Count - 1) + if (historyIndex == 0) return true; - Text = messageHistory[++historyIndex]; + Text = messageHistory[--historyIndex]; return true; case Key.Down: - if (historyIndex == -1) + if (historyIndex == messageHistory.Count) return true; - if (historyIndex == 0) + if (historyIndex == messageHistory.Count - 1) { - historyIndex = -1; + historyIndex = messageHistory.Count; Text = originalMessage; return true; } - Text = messageHistory[--historyIndex]; + Text = messageHistory[++historyIndex]; return true; } @@ -63,9 +63,9 @@ namespace osu.Game.Graphics.UserInterface protected override void Commit() { if (!string.IsNullOrEmpty(Text)) - messageHistory.Insert(0, Text); + messageHistory.Add(Text); - historyIndex = -1; + historyIndex = messageHistory.Count; base.Commit(); } From 5253f5309e0224ef993786ffb84fd9d7a64f212e Mon Sep 17 00:00:00 2001 From: Terochi Date: Tue, 15 Nov 2022 23:51:57 +0100 Subject: [PATCH 07/20] Added more tests for new features --- .../Online/TestSceneChatManipulation.cs | 75 ++++++++++++++++++- .../Graphics/UserInterface/HistoryTextBox.cs | 57 ++++++++++---- 2 files changed, 116 insertions(+), 16 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneChatManipulation.cs b/osu.Game.Tests/Visual/Online/TestSceneChatManipulation.cs index 4fe0cb685e..efa4cd41b3 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneChatManipulation.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneChatManipulation.cs @@ -8,7 +8,7 @@ using NUnit.Framework; using osu.Framework.Graphics; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; -using osu.Game.Overlays.Chat; +using osu.Game.Graphics.UserInterface; using osuTK.Input; namespace osu.Game.Tests.Visual.Online @@ -16,7 +16,7 @@ namespace osu.Game.Tests.Visual.Online [TestFixture] public class TestSceneChatManipulation : OsuManualInputManagerTestScene { - private ChatTextBox box; + private HistoryTextBox box; private OsuSpriteText text; [SetUp] @@ -26,7 +26,7 @@ namespace osu.Game.Tests.Visual.Online { Children = new Drawable[] { - box = new ChatTextBox + box = new HistoryTextBox(5) { Anchor = Anchor.Centre, Origin = Anchor.Centre, @@ -56,6 +56,75 @@ namespace osu.Game.Tests.Visual.Online }); } + [Test] + public void TestEmptyHistory() + { + const string temp = "Temp message"; + AddStep("Set text", () => box.Text = temp); + + AddStep("Move down", () => InputManager.Key(Key.Down)); + AddAssert("Text is the same", () => box.Text == temp); + + AddStep("Move Up", () => InputManager.Key(Key.Up)); + AddAssert("Text is the same", () => box.Text == temp); + } + + [Test] + public void TestPartialHistory() + { + addMessages(2); + + const string temp = "Temp message"; + AddStep("Set text", () => box.Text = temp); + + AddStep("Move down", () => InputManager.Key(Key.Down)); + AddAssert("Text is the same", () => box.Text == temp); + + AddRepeatStep("Move Up", () => InputManager.Key(Key.Up), 2); + AddAssert("Same as 1st message", () => box.Text == "Message 1"); + + AddStep("Move Up", () => InputManager.Key(Key.Up)); + AddAssert("Text is the same", () => box.Text == "Message 1"); + + AddRepeatStep("Move down", () => InputManager.Key(Key.Down), 2); + AddAssert("Same as temp message", () => box.Text == temp); + + AddStep("Move down", () => InputManager.Key(Key.Down)); + AddAssert("Text is the same", () => box.Text == temp); + } + + [Test] + public void TestFullHistory() + { + addMessages(5); + AddAssert("History saved as <1-5>", () => + Enumerable.Range(1, 5).Select(number => $"Message {number}").SequenceEqual(box.MessageHistory)); + + const string temp = "Temp message"; + AddStep("Set text", () => box.Text = temp); + + AddStep("Move down", () => InputManager.Key(Key.Down)); + AddAssert("Text is the same", () => box.Text == temp); + + addMessages(2); + AddAssert("Overwrote history to <3-7>", () => + Enumerable.Range(3, 5).Select(number => $"Message {number}").SequenceEqual(box.MessageHistory)); + + AddStep("Set text", () => box.Text = temp); + + AddRepeatStep("Move Up", () => InputManager.Key(Key.Up), 5); + AddAssert("Same as 3rd message", () => box.Text == "Message 3"); + + AddStep("Move Up", () => InputManager.Key(Key.Up)); + AddAssert("Text is the same", () => box.Text == "Message 3"); + + AddRepeatStep("Move down", () => InputManager.Key(Key.Down), 4); + AddAssert("Same as previous message", () => box.Text == "Message 7"); + + AddStep("Move down", () => InputManager.Key(Key.Down)); + AddAssert("Same as temp message", () => box.Text == temp); + } + [Test] public void TestStayOnLastIndex() { diff --git a/osu.Game/Graphics/UserInterface/HistoryTextBox.cs b/osu.Game/Graphics/UserInterface/HistoryTextBox.cs index 96c0734d63..c91e5dcb41 100644 --- a/osu.Game/Graphics/UserInterface/HistoryTextBox.cs +++ b/osu.Game/Graphics/UserInterface/HistoryTextBox.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using System.Collections.Generic; using osu.Framework.Input.Events; using osuTK.Input; @@ -9,50 +10,71 @@ namespace osu.Game.Graphics.UserInterface { public class HistoryTextBox : FocusedTextBox { - private readonly List messageHistory = new List(); + private readonly int historyLimit; + + private readonly List messageHistory; public IReadOnlyList MessageHistory => messageHistory; - private int historyIndex; + private int startIndex; private string originalMessage = string.Empty; + private int nullIndex => -1; + private int historyIndex = -1; + private int endIndex => (messageHistory.Count + startIndex - 1) % Math.Max(1, messageHistory.Count); - public HistoryTextBox() + public HistoryTextBox(int historyLimit = 100) { + this.historyLimit = historyLimit; + messageHistory = new List(historyLimit); + Current.ValueChanged += text => { if (string.IsNullOrEmpty(text.NewValue)) - historyIndex = messageHistory.Count; + historyIndex = nullIndex; }; } + public string GetOldMessage(int index) + { + if (index < 0 || index >= messageHistory.Count) + throw new ArgumentOutOfRangeException(); + + return messageHistory[(startIndex + index) % messageHistory.Count]; + } + protected override bool OnKeyDown(KeyDownEvent e) { switch (e.Key) { case Key.Up: - if (historyIndex == messageHistory.Count) + if (historyIndex == nullIndex) + { + historyIndex = endIndex; originalMessage = Text; + } - if (historyIndex == 0) + if (historyIndex == startIndex) return true; - Text = messageHistory[--historyIndex]; + historyIndex = (historyLimit + historyIndex - 1) % historyLimit; + Text = messageHistory[historyIndex]; return true; case Key.Down: - if (historyIndex == messageHistory.Count) + if (historyIndex == nullIndex) return true; - if (historyIndex == messageHistory.Count - 1) + if (historyIndex == endIndex) { - historyIndex = messageHistory.Count; + historyIndex = nullIndex; Text = originalMessage; return true; } - Text = messageHistory[++historyIndex]; + historyIndex = (historyIndex + 1) % historyLimit; + Text = messageHistory[historyIndex]; return true; } @@ -63,9 +85,18 @@ namespace osu.Game.Graphics.UserInterface protected override void Commit() { if (!string.IsNullOrEmpty(Text)) - messageHistory.Add(Text); + { + if (messageHistory.Count == historyLimit) + { + messageHistory[startIndex++] = Text; + } + else + { + messageHistory.Add(Text); + } + } - historyIndex = messageHistory.Count; + historyIndex = nullIndex; base.Commit(); } From 19dc31c7ae6c3b5a2ad6bdd3422e1d60eb5ec8d5 Mon Sep 17 00:00:00 2001 From: Terochi Date: Wed, 16 Nov 2022 13:12:43 +0100 Subject: [PATCH 08/20] Changed tests. --- .../Online/TestSceneChatManipulation.cs | 75 +++++++------------ 1 file changed, 29 insertions(+), 46 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneChatManipulation.cs b/osu.Game.Tests/Visual/Online/TestSceneChatManipulation.cs index efa4cd41b3..3bff321d0d 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneChatManipulation.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneChatManipulation.cs @@ -6,6 +6,7 @@ using System.Linq; using NUnit.Framework; using osu.Framework.Graphics; +using osu.Framework.Input; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; @@ -19,6 +20,8 @@ namespace osu.Game.Tests.Visual.Online private HistoryTextBox box; private OsuSpriteText text; + private int messageCounter; + [SetUp] public void SetUp() { @@ -52,6 +55,8 @@ namespace osu.Game.Tests.Visual.Online text.FadeOutFromOne(1000, Easing.InQuint); }; + messageCounter = 0; + box.TakeFocus(); }); } @@ -97,8 +102,8 @@ namespace osu.Game.Tests.Visual.Online public void TestFullHistory() { addMessages(5); - AddAssert("History saved as <1-5>", () => - Enumerable.Range(1, 5).Select(number => $"Message {number}").SequenceEqual(box.MessageHistory)); + AddAssert("History saved as <5-1>", () => + Enumerable.Range(0, 5).Select(number => $"Message {5 - number}").SequenceEqual(box.MessageHistory)); const string temp = "Temp message"; AddStep("Set text", () => box.Text = temp); @@ -107,8 +112,8 @@ namespace osu.Game.Tests.Visual.Online AddAssert("Text is the same", () => box.Text == temp); addMessages(2); - AddAssert("Overwrote history to <3-7>", () => - Enumerable.Range(3, 5).Select(number => $"Message {number}").SequenceEqual(box.MessageHistory)); + AddAssert("Overrode history to <7-3>", () => + Enumerable.Range(0, 5).Select(number => $"Message {7 - number}").SequenceEqual(box.MessageHistory)); AddStep("Set text", () => box.Text = temp); @@ -126,63 +131,41 @@ namespace osu.Game.Tests.Visual.Online } [Test] - public void TestStayOnLastIndex() + public void TestOverrideFullHistory() { - addMessages(2); - AddRepeatStep("Move to last", () => InputManager.Key(Key.Up), 2); + addMessages(5); + AddAssert("History saved as <5-1>", () => + Enumerable.Range(0, 5).Select(number => $"Message {5 - number}").SequenceEqual(box.MessageHistory)); - string lastText = string.Empty; - AddStep("Move up", () => - { - lastText = box.Text; - InputManager.Key(Key.Up); - }); - - AddAssert("Text hasn't changed", () => lastText == box.Text); + addMessages(6); + AddAssert("Overrode history to <11-7>", () => + Enumerable.Range(0, 5).Select(number => $"Message {11 - number}").SequenceEqual(box.MessageHistory)); } [Test] - public void TestKeepOriginalMessage() - { - addMessages(1); - AddStep("Start writing", () => box.Text = "A random 文, ..."); - - AddStep("Move up", () => InputManager.Key(Key.Up)); - AddStep("Rewrite old message", () => box.Text = "Old Message"); - - AddStep("Move back down", () => InputManager.Key(Key.Down)); - AddAssert("Text back to previous", () => box.Text == "A random 文, ..."); - } - - [Test] - public void TestResetIndexOnEmpty() + public void TestResetIndex() { addMessages(2); - AddRepeatStep("Move up", () => InputManager.Key(Key.Up), 2); + + AddRepeatStep("Move Up", () => InputManager.Key(Key.Up), 2); + AddAssert("Same as 1st message", () => box.Text == "Message 1"); + AddStep("Remove text", () => box.Text = string.Empty); + AddStep("Move Up", () => InputManager.Key(Key.Up)); + AddAssert("Same as previous message", () => box.Text == "Message 2"); - AddStep("Move up again", () => InputManager.Key(Key.Up)); - AddAssert("Back to first message", () => box.Text == "Message 2"); - } - - [Test] - public void TestReachingLimitOfMessages() - { - addMessages(100); - AddAssert("List is full of <100-1>", () => - Enumerable.Range(0, 100).Select(number => $"Message {100 - number}").SequenceEqual(box.MessageHistory)); - - addMessages(2); - AddAssert("List is full of <102-3>", () => - Enumerable.Range(0, 100).Select(number => $"Message {102 - number}").SequenceEqual(box.MessageHistory)); + AddStep("Move Up", () => InputManager.Key(Key.Up)); + AddStep("Select text", () => InputManager.Keys(PlatformAction.SelectAll)); + AddStep("Replace text", () => box.Text = "New text"); + AddStep("Move Up", () => InputManager.Key(Key.Up)); + AddAssert("Same as previous message", () => box.Text == "Message 2"); } private void addMessages(int count) { - int iterations = 0; AddRepeatStep("Add messages", () => { - box.Text = $"Message {++iterations}"; + box.Text = $"Message {++messageCounter}"; InputManager.Key(Key.Enter); }, count); } From 0100c01b82f547ced0d3b040fbba14d88b13847e Mon Sep 17 00:00:00 2001 From: Terochi Date: Wed, 16 Nov 2022 13:16:01 +0100 Subject: [PATCH 09/20] Implemented finite limit of stored history. --- .../Graphics/UserInterface/HistoryTextBox.cs | 64 +++++++++++-------- 1 file changed, 39 insertions(+), 25 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/HistoryTextBox.cs b/osu.Game/Graphics/UserInterface/HistoryTextBox.cs index c91e5dcb41..6c9df5aca2 100644 --- a/osu.Game/Graphics/UserInterface/HistoryTextBox.cs +++ b/osu.Game/Graphics/UserInterface/HistoryTextBox.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Linq; using osu.Framework.Input.Events; using osuTK.Input; @@ -12,16 +13,23 @@ namespace osu.Game.Graphics.UserInterface { private readonly int historyLimit; + private bool everythingSelected; + + public int HistoryLength => messageHistory.Count; + private readonly List messageHistory; - public IReadOnlyList MessageHistory => messageHistory; + public IReadOnlyList MessageHistory => + Enumerable.Range(0, HistoryLength).Select(GetOldMessage).ToList(); + + private string originalMessage = string.Empty; + + private int historyIndex = -1; private int startIndex; - private string originalMessage = string.Empty; - private int nullIndex => -1; - private int historyIndex = -1; - private int endIndex => (messageHistory.Count + startIndex - 1) % Math.Max(1, messageHistory.Count); + private int getNormalizedIndex(int index) => + (HistoryLength + startIndex - index - 1) % HistoryLength; public HistoryTextBox(int historyLimit = 100) { @@ -30,17 +38,27 @@ namespace osu.Game.Graphics.UserInterface Current.ValueChanged += text => { - if (string.IsNullOrEmpty(text.NewValue)) - historyIndex = nullIndex; + if (string.IsNullOrEmpty(text.NewValue) || everythingSelected) + { + historyIndex = -1; + everythingSelected = false; + } }; } + protected override void OnTextSelectionChanged(TextSelectionType selectionType) + { + everythingSelected = SelectedText == Text; + + base.OnTextSelectionChanged(selectionType); + } + public string GetOldMessage(int index) { - if (index < 0 || index >= messageHistory.Count) + if (index < 0 || index >= HistoryLength) throw new ArgumentOutOfRangeException(); - return messageHistory[(startIndex + index) % messageHistory.Count]; + return HistoryLength == 0 ? string.Empty : messageHistory[getNormalizedIndex(index)]; } protected override bool OnKeyDown(KeyDownEvent e) @@ -48,33 +66,28 @@ namespace osu.Game.Graphics.UserInterface switch (e.Key) { case Key.Up: - if (historyIndex == nullIndex) - { - historyIndex = endIndex; - originalMessage = Text; - } - - if (historyIndex == startIndex) + if (historyIndex == HistoryLength - 1) return true; - historyIndex = (historyLimit + historyIndex - 1) % historyLimit; - Text = messageHistory[historyIndex]; + if (historyIndex == -1) + originalMessage = Text; + + Text = messageHistory[getNormalizedIndex(++historyIndex)]; return true; case Key.Down: - if (historyIndex == nullIndex) + if (historyIndex == -1) return true; - if (historyIndex == endIndex) + if (historyIndex == 0) { - historyIndex = nullIndex; + historyIndex = -1; Text = originalMessage; return true; } - historyIndex = (historyIndex + 1) % historyLimit; - Text = messageHistory[historyIndex]; + Text = messageHistory[getNormalizedIndex(--historyIndex)]; return true; } @@ -86,9 +99,10 @@ namespace osu.Game.Graphics.UserInterface { if (!string.IsNullOrEmpty(Text)) { - if (messageHistory.Count == historyLimit) + if (HistoryLength == historyLimit) { messageHistory[startIndex++] = Text; + startIndex %= historyLimit; } else { @@ -96,7 +110,7 @@ namespace osu.Game.Graphics.UserInterface } } - historyIndex = nullIndex; + historyIndex = -1; base.Commit(); } From a9747d367cc9a7321c414622a89777e89f321ca0 Mon Sep 17 00:00:00 2001 From: Dragon Date: Thu, 17 Nov 2022 10:18:17 +0100 Subject: [PATCH 10/20] Cleaning up --- .../TestSceneHistoryTextBox.cs} | 23 ++++++------- .../Graphics/UserInterface/HistoryTextBox.cs | 34 +++++++++---------- 2 files changed, 28 insertions(+), 29 deletions(-) rename osu.Game.Tests/Visual/{Online/TestSceneChatManipulation.cs => UserInterface/TestSceneHistoryTextBox.cs} (95%) diff --git a/osu.Game.Tests/Visual/Online/TestSceneChatManipulation.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneHistoryTextBox.cs similarity index 95% rename from osu.Game.Tests/Visual/Online/TestSceneChatManipulation.cs rename to osu.Game.Tests/Visual/UserInterface/TestSceneHistoryTextBox.cs index 3bff321d0d..f27711f512 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneChatManipulation.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneHistoryTextBox.cs @@ -12,16 +12,18 @@ using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; using osuTK.Input; -namespace osu.Game.Tests.Visual.Online +namespace osu.Game.Tests.Visual.UserInterface { [TestFixture] - public class TestSceneChatManipulation : OsuManualInputManagerTestScene + public class TestSceneHistoryTextBox : OsuManualInputManagerTestScene { - private HistoryTextBox box; - private OsuSpriteText text; + private const string temp = "Temp message"; private int messageCounter; + private HistoryTextBox box; + private OsuSpriteText text; + [SetUp] public void SetUp() { @@ -49,6 +51,9 @@ namespace osu.Game.Tests.Visual.Online box.OnCommit += (_, __) => { + if (string.IsNullOrEmpty(box.Text)) + return; + text.Text = $"{nameof(box.OnCommit)}: {box.Text}"; box.Text = string.Empty; box.TakeFocus(); @@ -64,7 +69,6 @@ namespace osu.Game.Tests.Visual.Online [Test] public void TestEmptyHistory() { - const string temp = "Temp message"; AddStep("Set text", () => box.Text = temp); AddStep("Move down", () => InputManager.Key(Key.Down)); @@ -78,8 +82,6 @@ namespace osu.Game.Tests.Visual.Online public void TestPartialHistory() { addMessages(2); - - const string temp = "Temp message"; AddStep("Set text", () => box.Text = temp); AddStep("Move down", () => InputManager.Key(Key.Down)); @@ -102,21 +104,18 @@ namespace osu.Game.Tests.Visual.Online public void TestFullHistory() { addMessages(5); + AddStep("Set text", () => box.Text = temp); AddAssert("History saved as <5-1>", () => Enumerable.Range(0, 5).Select(number => $"Message {5 - number}").SequenceEqual(box.MessageHistory)); - const string temp = "Temp message"; - AddStep("Set text", () => box.Text = temp); - AddStep("Move down", () => InputManager.Key(Key.Down)); AddAssert("Text is the same", () => box.Text == temp); addMessages(2); + AddStep("Set text", () => box.Text = temp); AddAssert("Overrode history to <7-3>", () => Enumerable.Range(0, 5).Select(number => $"Message {7 - number}").SequenceEqual(box.MessageHistory)); - AddStep("Set text", () => box.Text = temp); - AddRepeatStep("Move Up", () => InputManager.Key(Key.Up), 5); AddAssert("Same as 3rd message", () => box.Text == "Message 3"); diff --git a/osu.Game/Graphics/UserInterface/HistoryTextBox.cs b/osu.Game/Graphics/UserInterface/HistoryTextBox.cs index 6c9df5aca2..bebe21da47 100644 --- a/osu.Game/Graphics/UserInterface/HistoryTextBox.cs +++ b/osu.Game/Graphics/UserInterface/HistoryTextBox.cs @@ -12,27 +12,27 @@ namespace osu.Game.Graphics.UserInterface public class HistoryTextBox : FocusedTextBox { private readonly int historyLimit; - - private bool everythingSelected; - - public int HistoryLength => messageHistory.Count; - private readonly List messageHistory; public IReadOnlyList MessageHistory => Enumerable.Range(0, HistoryLength).Select(GetOldMessage).ToList(); - private string originalMessage = string.Empty; - - private int historyIndex = -1; + public int HistoryLength => messageHistory.Count; private int startIndex; + private int selectedIndex = -1; + + private string originalMessage = string.Empty; + private bool everythingSelected; private int getNormalizedIndex(int index) => (HistoryLength + startIndex - index - 1) % HistoryLength; public HistoryTextBox(int historyLimit = 100) { + if (historyLimit <= 0) + throw new ArgumentOutOfRangeException(); + this.historyLimit = historyLimit; messageHistory = new List(historyLimit); @@ -40,7 +40,7 @@ namespace osu.Game.Graphics.UserInterface { if (string.IsNullOrEmpty(text.NewValue) || everythingSelected) { - historyIndex = -1; + selectedIndex = -1; everythingSelected = false; } }; @@ -66,28 +66,28 @@ namespace osu.Game.Graphics.UserInterface switch (e.Key) { case Key.Up: - if (historyIndex == HistoryLength - 1) + if (selectedIndex == HistoryLength - 1) return true; - if (historyIndex == -1) + if (selectedIndex == -1) originalMessage = Text; - Text = messageHistory[getNormalizedIndex(++historyIndex)]; + Text = messageHistory[getNormalizedIndex(++selectedIndex)]; return true; case Key.Down: - if (historyIndex == -1) + if (selectedIndex == -1) return true; - if (historyIndex == 0) + if (selectedIndex == 0) { - historyIndex = -1; + selectedIndex = -1; Text = originalMessage; return true; } - Text = messageHistory[getNormalizedIndex(--historyIndex)]; + Text = messageHistory[getNormalizedIndex(--selectedIndex)]; return true; } @@ -110,7 +110,7 @@ namespace osu.Game.Graphics.UserInterface } } - historyIndex = -1; + selectedIndex = -1; base.Commit(); } From a25c94d567e9bdc4407e9882b0917bd85c6ba2ed Mon Sep 17 00:00:00 2001 From: Dragon Date: Thu, 17 Nov 2022 11:35:13 +0100 Subject: [PATCH 11/20] Replacing structure to use LimitedCapacityQueue.cs --- .../UserInterface/TestSceneHistoryTextBox.cs | 11 +-- .../Graphics/UserInterface/HistoryTextBox.cs | 70 +++++++------------ 2 files changed, 31 insertions(+), 50 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneHistoryTextBox.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneHistoryTextBox.cs index f27711f512..862777c500 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneHistoryTextBox.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneHistoryTextBox.cs @@ -49,7 +49,7 @@ namespace osu.Game.Tests.Visual.UserInterface } }; - box.OnCommit += (_, __) => + box.OnCommit += (_, _) => { if (string.IsNullOrEmpty(box.Text)) return; @@ -70,6 +70,7 @@ namespace osu.Game.Tests.Visual.UserInterface public void TestEmptyHistory() { AddStep("Set text", () => box.Text = temp); + AddAssert("History is empty", () => !box.GetMessageHistory().Any()); AddStep("Move down", () => InputManager.Key(Key.Down)); AddAssert("Text is the same", () => box.Text == temp); @@ -106,7 +107,7 @@ namespace osu.Game.Tests.Visual.UserInterface addMessages(5); AddStep("Set text", () => box.Text = temp); AddAssert("History saved as <5-1>", () => - Enumerable.Range(0, 5).Select(number => $"Message {5 - number}").SequenceEqual(box.MessageHistory)); + Enumerable.Range(0, 5).Select(number => $"Message {5 - number}").SequenceEqual(box.GetMessageHistory())); AddStep("Move down", () => InputManager.Key(Key.Down)); AddAssert("Text is the same", () => box.Text == temp); @@ -114,7 +115,7 @@ namespace osu.Game.Tests.Visual.UserInterface addMessages(2); AddStep("Set text", () => box.Text = temp); AddAssert("Overrode history to <7-3>", () => - Enumerable.Range(0, 5).Select(number => $"Message {7 - number}").SequenceEqual(box.MessageHistory)); + Enumerable.Range(0, 5).Select(number => $"Message {7 - number}").SequenceEqual(box.GetMessageHistory())); AddRepeatStep("Move Up", () => InputManager.Key(Key.Up), 5); AddAssert("Same as 3rd message", () => box.Text == "Message 3"); @@ -134,11 +135,11 @@ namespace osu.Game.Tests.Visual.UserInterface { addMessages(5); AddAssert("History saved as <5-1>", () => - Enumerable.Range(0, 5).Select(number => $"Message {5 - number}").SequenceEqual(box.MessageHistory)); + Enumerable.Range(0, 5).Select(number => $"Message {5 - number}").SequenceEqual(box.GetMessageHistory())); addMessages(6); AddAssert("Overrode history to <11-7>", () => - Enumerable.Range(0, 5).Select(number => $"Message {11 - number}").SequenceEqual(box.MessageHistory)); + Enumerable.Range(0, 5).Select(number => $"Message {11 - number}").SequenceEqual(box.GetMessageHistory())); } [Test] diff --git a/osu.Game/Graphics/UserInterface/HistoryTextBox.cs b/osu.Game/Graphics/UserInterface/HistoryTextBox.cs index bebe21da47..17858ea16d 100644 --- a/osu.Game/Graphics/UserInterface/HistoryTextBox.cs +++ b/osu.Game/Graphics/UserInterface/HistoryTextBox.cs @@ -1,46 +1,44 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System; using System.Collections.Generic; -using System.Linq; using osu.Framework.Input.Events; +using osu.Game.Rulesets.Difficulty.Utils; using osuTK.Input; namespace osu.Game.Graphics.UserInterface { public class HistoryTextBox : FocusedTextBox { - private readonly int historyLimit; - private readonly List messageHistory; + private readonly LimitedCapacityQueue messageHistory; - public IReadOnlyList MessageHistory => - Enumerable.Range(0, HistoryLength).Select(GetOldMessage).ToList(); + public IEnumerable GetMessageHistory() + { + if (HistoryCount == 0) + yield break; - public int HistoryLength => messageHistory.Count; + for (int i = HistoryCount - 1; i >= 0; i--) + yield return messageHistory[i]; + } - private int startIndex; - private int selectedIndex = -1; + public int HistoryCount => messageHistory.Count; + + private int selectedIndex; private string originalMessage = string.Empty; private bool everythingSelected; - private int getNormalizedIndex(int index) => - (HistoryLength + startIndex - index - 1) % HistoryLength; + public string GetOldMessage(int index) => messageHistory[HistoryCount - index - 1]; - public HistoryTextBox(int historyLimit = 100) + public HistoryTextBox(int capacity = 100) { - if (historyLimit <= 0) - throw new ArgumentOutOfRangeException(); - - this.historyLimit = historyLimit; - messageHistory = new List(historyLimit); + messageHistory = new LimitedCapacityQueue(capacity); Current.ValueChanged += text => { if (string.IsNullOrEmpty(text.NewValue) || everythingSelected) { - selectedIndex = -1; + selectedIndex = HistoryCount; everythingSelected = false; } }; @@ -53,41 +51,33 @@ namespace osu.Game.Graphics.UserInterface base.OnTextSelectionChanged(selectionType); } - public string GetOldMessage(int index) - { - if (index < 0 || index >= HistoryLength) - throw new ArgumentOutOfRangeException(); - - return HistoryLength == 0 ? string.Empty : messageHistory[getNormalizedIndex(index)]; - } - protected override bool OnKeyDown(KeyDownEvent e) { switch (e.Key) { case Key.Up: - if (selectedIndex == HistoryLength - 1) + if (selectedIndex == 0) return true; - if (selectedIndex == -1) + if (selectedIndex == HistoryCount) originalMessage = Text; - Text = messageHistory[getNormalizedIndex(++selectedIndex)]; + Text = messageHistory[--selectedIndex]; return true; case Key.Down: - if (selectedIndex == -1) + if (selectedIndex == HistoryCount) return true; - if (selectedIndex == 0) + if (selectedIndex == HistoryCount - 1) { - selectedIndex = -1; + selectedIndex = HistoryCount; Text = originalMessage; return true; } - Text = messageHistory[getNormalizedIndex(--selectedIndex)]; + Text = messageHistory[++selectedIndex]; return true; } @@ -98,19 +88,9 @@ namespace osu.Game.Graphics.UserInterface protected override void Commit() { if (!string.IsNullOrEmpty(Text)) - { - if (HistoryLength == historyLimit) - { - messageHistory[startIndex++] = Text; - startIndex %= historyLimit; - } - else - { - messageHistory.Add(Text); - } - } + messageHistory.Enqueue(Text); - selectedIndex = -1; + selectedIndex = HistoryCount; base.Commit(); } From eff6c7be6499aecd6ecf7bfb3faf999334b04d41 Mon Sep 17 00:00:00 2001 From: Terochi Date: Sat, 19 Nov 2022 16:53:35 +0100 Subject: [PATCH 12/20] Removed unnecessary methods, changed tests, and moved LimitedCapacityQueue.cs to a more generic namespace. --- .../Difficulty/Skills/Rhythm.cs | 2 +- .../NonVisual/LimitedCapacityQueueTest.cs | 2 +- .../UserInterface/TestSceneHistoryTextBox.cs | 24 ++----------------- .../Graphics/UserInterface/HistoryTextBox.cs | 14 +---------- .../Utils/LimitedCapacityQueue.cs | 2 +- 5 files changed, 6 insertions(+), 38 deletions(-) rename osu.Game/{Rulesets/Difficulty => }/Utils/LimitedCapacityQueue.cs (98%) diff --git a/osu.Game.Rulesets.Taiko/Difficulty/Skills/Rhythm.cs b/osu.Game.Rulesets.Taiko/Difficulty/Skills/Rhythm.cs index 4a2b97a4cb..ff187a133a 100644 --- a/osu.Game.Rulesets.Taiko/Difficulty/Skills/Rhythm.cs +++ b/osu.Game.Rulesets.Taiko/Difficulty/Skills/Rhythm.cs @@ -6,10 +6,10 @@ using System; using osu.Game.Rulesets.Difficulty.Preprocessing; using osu.Game.Rulesets.Difficulty.Skills; -using osu.Game.Rulesets.Difficulty.Utils; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Taiko.Difficulty.Preprocessing; using osu.Game.Rulesets.Taiko.Objects; +using osu.Game.Utils; namespace osu.Game.Rulesets.Taiko.Difficulty.Skills { diff --git a/osu.Game.Tests/NonVisual/LimitedCapacityQueueTest.cs b/osu.Game.Tests/NonVisual/LimitedCapacityQueueTest.cs index 8cd26901c5..8809ce3adc 100644 --- a/osu.Game.Tests/NonVisual/LimitedCapacityQueueTest.cs +++ b/osu.Game.Tests/NonVisual/LimitedCapacityQueueTest.cs @@ -5,7 +5,7 @@ using System; using NUnit.Framework; -using osu.Game.Rulesets.Difficulty.Utils; +using osu.Game.Utils; namespace osu.Game.Tests.NonVisual { diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneHistoryTextBox.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneHistoryTextBox.cs index 862777c500..8918e53056 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneHistoryTextBox.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneHistoryTextBox.cs @@ -1,9 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -#nullable disable - -using System.Linq; using NUnit.Framework; using osu.Framework.Graphics; using osu.Framework.Input; @@ -21,8 +18,8 @@ namespace osu.Game.Tests.Visual.UserInterface private int messageCounter; - private HistoryTextBox box; - private OsuSpriteText text; + private HistoryTextBox box = null!; + private OsuSpriteText text = null!; [SetUp] public void SetUp() @@ -70,7 +67,6 @@ namespace osu.Game.Tests.Visual.UserInterface public void TestEmptyHistory() { AddStep("Set text", () => box.Text = temp); - AddAssert("History is empty", () => !box.GetMessageHistory().Any()); AddStep("Move down", () => InputManager.Key(Key.Down)); AddAssert("Text is the same", () => box.Text == temp); @@ -106,16 +102,12 @@ namespace osu.Game.Tests.Visual.UserInterface { addMessages(5); AddStep("Set text", () => box.Text = temp); - AddAssert("History saved as <5-1>", () => - Enumerable.Range(0, 5).Select(number => $"Message {5 - number}").SequenceEqual(box.GetMessageHistory())); AddStep("Move down", () => InputManager.Key(Key.Down)); AddAssert("Text is the same", () => box.Text == temp); addMessages(2); AddStep("Set text", () => box.Text = temp); - AddAssert("Overrode history to <7-3>", () => - Enumerable.Range(0, 5).Select(number => $"Message {7 - number}").SequenceEqual(box.GetMessageHistory())); AddRepeatStep("Move Up", () => InputManager.Key(Key.Up), 5); AddAssert("Same as 3rd message", () => box.Text == "Message 3"); @@ -130,18 +122,6 @@ namespace osu.Game.Tests.Visual.UserInterface AddAssert("Same as temp message", () => box.Text == temp); } - [Test] - public void TestOverrideFullHistory() - { - addMessages(5); - AddAssert("History saved as <5-1>", () => - Enumerable.Range(0, 5).Select(number => $"Message {5 - number}").SequenceEqual(box.GetMessageHistory())); - - addMessages(6); - AddAssert("Overrode history to <11-7>", () => - Enumerable.Range(0, 5).Select(number => $"Message {11 - number}").SequenceEqual(box.GetMessageHistory())); - } - [Test] public void TestResetIndex() { diff --git a/osu.Game/Graphics/UserInterface/HistoryTextBox.cs b/osu.Game/Graphics/UserInterface/HistoryTextBox.cs index 17858ea16d..e9da67e553 100644 --- a/osu.Game/Graphics/UserInterface/HistoryTextBox.cs +++ b/osu.Game/Graphics/UserInterface/HistoryTextBox.cs @@ -1,9 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System.Collections.Generic; using osu.Framework.Input.Events; -using osu.Game.Rulesets.Difficulty.Utils; +using osu.Game.Utils; using osuTK.Input; namespace osu.Game.Graphics.UserInterface @@ -12,15 +11,6 @@ namespace osu.Game.Graphics.UserInterface { private readonly LimitedCapacityQueue messageHistory; - public IEnumerable GetMessageHistory() - { - if (HistoryCount == 0) - yield break; - - for (int i = HistoryCount - 1; i >= 0; i--) - yield return messageHistory[i]; - } - public int HistoryCount => messageHistory.Count; private int selectedIndex; @@ -28,8 +18,6 @@ namespace osu.Game.Graphics.UserInterface private string originalMessage = string.Empty; private bool everythingSelected; - public string GetOldMessage(int index) => messageHistory[HistoryCount - index - 1]; - public HistoryTextBox(int capacity = 100) { messageHistory = new LimitedCapacityQueue(capacity); diff --git a/osu.Game/Rulesets/Difficulty/Utils/LimitedCapacityQueue.cs b/osu.Game/Utils/LimitedCapacityQueue.cs similarity index 98% rename from osu.Game/Rulesets/Difficulty/Utils/LimitedCapacityQueue.cs rename to osu.Game/Utils/LimitedCapacityQueue.cs index d20eb5e885..86a106a678 100644 --- a/osu.Game/Rulesets/Difficulty/Utils/LimitedCapacityQueue.cs +++ b/osu.Game/Utils/LimitedCapacityQueue.cs @@ -7,7 +7,7 @@ using System; using System.Collections; using System.Collections.Generic; -namespace osu.Game.Rulesets.Difficulty.Utils +namespace osu.Game.Utils { /// /// An indexed queue with limited capacity. From 33b2fe46d950fc125035290b8663ffbfc2858d70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 20 Nov 2022 12:29:41 +0100 Subject: [PATCH 13/20] Add xmldoc to `HistoryTextBox` --- osu.Game/Graphics/UserInterface/HistoryTextBox.cs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/osu.Game/Graphics/UserInterface/HistoryTextBox.cs b/osu.Game/Graphics/UserInterface/HistoryTextBox.cs index e9da67e553..5d2cd18e9b 100644 --- a/osu.Game/Graphics/UserInterface/HistoryTextBox.cs +++ b/osu.Game/Graphics/UserInterface/HistoryTextBox.cs @@ -7,6 +7,12 @@ using osuTK.Input; namespace osu.Game.Graphics.UserInterface { + /// + /// A which additionally retains a history of text committed, up to a limit + /// (100 by default, specified in constructor). + /// The history of committed text can be navigated using up/down arrows. + /// This resembles the operation of command-line terminals. + /// public class HistoryTextBox : FocusedTextBox { private readonly LimitedCapacityQueue messageHistory; @@ -18,6 +24,13 @@ namespace osu.Game.Graphics.UserInterface private string originalMessage = string.Empty; private bool everythingSelected; + /// + /// Creates a new . + /// + /// + /// The maximum number of committed lines to keep in history. + /// When exceeded, the oldest lines in history will be dropped to make space for new ones. + /// public HistoryTextBox(int capacity = 100) { messageHistory = new LimitedCapacityQueue(capacity); From 8f942f130b82b6ec5c37018a4d67d745eb160a28 Mon Sep 17 00:00:00 2001 From: Terochi Date: Mon, 21 Nov 2022 09:32:44 +0100 Subject: [PATCH 14/20] Variant 1: edit changes history, empty text resets index --- .../UserInterface/TestSceneHistoryTextBox.cs | 59 ++++--------------- .../Graphics/UserInterface/HistoryTextBox.cs | 18 ++---- osu.Game/Utils/LimitedCapacityQueue.cs | 7 +++ 3 files changed, 24 insertions(+), 60 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneHistoryTextBox.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneHistoryTextBox.cs index 8918e53056..6ead7bc168 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneHistoryTextBox.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneHistoryTextBox.cs @@ -3,7 +3,6 @@ using NUnit.Framework; using osu.Framework.Graphics; -using osu.Framework.Input; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; @@ -64,62 +63,32 @@ namespace osu.Game.Tests.Visual.UserInterface } [Test] - public void TestEmptyHistory() + public void TestChangedHistory() { + addMessages(2); AddStep("Set text", () => box.Text = temp); + AddStep("Move up", () => InputManager.Key(Key.Up)); + AddStep("Change text", () => box.Text = "New message"); AddStep("Move down", () => InputManager.Key(Key.Down)); - AddAssert("Text is the same", () => box.Text == temp); - - AddStep("Move Up", () => InputManager.Key(Key.Up)); - AddAssert("Text is the same", () => box.Text == temp); + AddStep("Move up", () => InputManager.Key(Key.Up)); + AddAssert("Changes kept", () => box.Text == "New message"); } [Test] - public void TestPartialHistory() + public void TestInputOnEdge() { addMessages(2); AddStep("Set text", () => box.Text = temp); AddStep("Move down", () => InputManager.Key(Key.Down)); - AddAssert("Text is the same", () => box.Text == temp); + AddAssert("Text unchanged", () => box.Text == temp); - AddRepeatStep("Move Up", () => InputManager.Key(Key.Up), 2); + AddRepeatStep("Move up", () => InputManager.Key(Key.Up), 2); AddAssert("Same as 1st message", () => box.Text == "Message 1"); - AddStep("Move Up", () => InputManager.Key(Key.Up)); - AddAssert("Text is the same", () => box.Text == "Message 1"); - - AddRepeatStep("Move down", () => InputManager.Key(Key.Down), 2); - AddAssert("Same as temp message", () => box.Text == temp); - - AddStep("Move down", () => InputManager.Key(Key.Down)); - AddAssert("Text is the same", () => box.Text == temp); - } - - [Test] - public void TestFullHistory() - { - addMessages(5); - AddStep("Set text", () => box.Text = temp); - - AddStep("Move down", () => InputManager.Key(Key.Down)); - AddAssert("Text is the same", () => box.Text == temp); - - addMessages(2); - AddStep("Set text", () => box.Text = temp); - - AddRepeatStep("Move Up", () => InputManager.Key(Key.Up), 5); - AddAssert("Same as 3rd message", () => box.Text == "Message 3"); - - AddStep("Move Up", () => InputManager.Key(Key.Up)); - AddAssert("Text is the same", () => box.Text == "Message 3"); - - AddRepeatStep("Move down", () => InputManager.Key(Key.Down), 4); - AddAssert("Same as previous message", () => box.Text == "Message 7"); - - AddStep("Move down", () => InputManager.Key(Key.Down)); - AddAssert("Same as temp message", () => box.Text == temp); + AddStep("Move up", () => InputManager.Key(Key.Up)); + AddAssert("Text unchanged", () => box.Text == "Message 1"); } [Test] @@ -133,12 +102,6 @@ namespace osu.Game.Tests.Visual.UserInterface AddStep("Remove text", () => box.Text = string.Empty); AddStep("Move Up", () => InputManager.Key(Key.Up)); AddAssert("Same as previous message", () => box.Text == "Message 2"); - - AddStep("Move Up", () => InputManager.Key(Key.Up)); - AddStep("Select text", () => InputManager.Keys(PlatformAction.SelectAll)); - AddStep("Replace text", () => box.Text = "New text"); - AddStep("Move Up", () => InputManager.Key(Key.Up)); - AddAssert("Same as previous message", () => box.Text == "Message 2"); } private void addMessages(int count) diff --git a/osu.Game/Graphics/UserInterface/HistoryTextBox.cs b/osu.Game/Graphics/UserInterface/HistoryTextBox.cs index 5d2cd18e9b..b0ca5beb66 100644 --- a/osu.Game/Graphics/UserInterface/HistoryTextBox.cs +++ b/osu.Game/Graphics/UserInterface/HistoryTextBox.cs @@ -22,7 +22,6 @@ namespace osu.Game.Graphics.UserInterface private int selectedIndex; private string originalMessage = string.Empty; - private bool everythingSelected; /// /// Creates a new . @@ -37,21 +36,11 @@ namespace osu.Game.Graphics.UserInterface Current.ValueChanged += text => { - if (string.IsNullOrEmpty(text.NewValue) || everythingSelected) - { + if (string.IsNullOrEmpty(text.NewValue)) selectedIndex = HistoryCount; - everythingSelected = false; - } }; } - protected override void OnTextSelectionChanged(TextSelectionType selectionType) - { - everythingSelected = SelectedText == Text; - - base.OnTextSelectionChanged(selectionType); - } - protected override bool OnKeyDown(KeyDownEvent e) { switch (e.Key) @@ -62,6 +51,8 @@ namespace osu.Game.Graphics.UserInterface if (selectedIndex == HistoryCount) originalMessage = Text; + else if (!string.IsNullOrEmpty(Text)) + messageHistory[selectedIndex] = Text; Text = messageHistory[--selectedIndex]; @@ -71,6 +62,9 @@ namespace osu.Game.Graphics.UserInterface if (selectedIndex == HistoryCount) return true; + if (!string.IsNullOrEmpty(Text)) + messageHistory[selectedIndex] = Text; + if (selectedIndex == HistoryCount - 1) { selectedIndex = HistoryCount; diff --git a/osu.Game/Utils/LimitedCapacityQueue.cs b/osu.Game/Utils/LimitedCapacityQueue.cs index 86a106a678..8f3b36a059 100644 --- a/osu.Game/Utils/LimitedCapacityQueue.cs +++ b/osu.Game/Utils/LimitedCapacityQueue.cs @@ -103,6 +103,13 @@ namespace osu.Game.Utils return array[(start + index) % capacity]; } + set + { + if (index < 0 || index >= Count) + throw new ArgumentOutOfRangeException(nameof(index)); + + array[(start + index) % capacity] = value; + } } /// From 672e1cd45bfc1ad6d495ad833d02c7ae7a9e7b40 Mon Sep 17 00:00:00 2001 From: Terochi Date: Mon, 21 Nov 2022 09:38:33 +0100 Subject: [PATCH 15/20] Variant 2: edit changes history, cannot reset index (similar to stable) --- .../Visual/UserInterface/TestSceneHistoryTextBox.cs | 2 +- osu.Game/Graphics/UserInterface/HistoryTextBox.cs | 6 ------ 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneHistoryTextBox.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneHistoryTextBox.cs index 6ead7bc168..e0f734fce0 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneHistoryTextBox.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneHistoryTextBox.cs @@ -101,7 +101,7 @@ namespace osu.Game.Tests.Visual.UserInterface AddStep("Remove text", () => box.Text = string.Empty); AddStep("Move Up", () => InputManager.Key(Key.Up)); - AddAssert("Same as previous message", () => box.Text == "Message 2"); + AddAssert("Text unchanged", () => box.Text == string.Empty); } private void addMessages(int count) diff --git a/osu.Game/Graphics/UserInterface/HistoryTextBox.cs b/osu.Game/Graphics/UserInterface/HistoryTextBox.cs index b0ca5beb66..6791812b98 100644 --- a/osu.Game/Graphics/UserInterface/HistoryTextBox.cs +++ b/osu.Game/Graphics/UserInterface/HistoryTextBox.cs @@ -33,12 +33,6 @@ namespace osu.Game.Graphics.UserInterface public HistoryTextBox(int capacity = 100) { messageHistory = new LimitedCapacityQueue(capacity); - - Current.ValueChanged += text => - { - if (string.IsNullOrEmpty(text.NewValue)) - selectedIndex = HistoryCount; - }; } protected override bool OnKeyDown(KeyDownEvent e) From 58288275a6f38291a283840ec12e6009f8479332 Mon Sep 17 00:00:00 2001 From: Terochi Date: Mon, 21 Nov 2022 09:43:36 +0100 Subject: [PATCH 16/20] Variant 3: cannot change history, cannot reset index (the "default") --- .../Visual/UserInterface/TestSceneHistoryTextBox.cs | 2 +- osu.Game/Graphics/UserInterface/HistoryTextBox.cs | 5 ----- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneHistoryTextBox.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneHistoryTextBox.cs index e0f734fce0..414c1276e1 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneHistoryTextBox.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneHistoryTextBox.cs @@ -72,7 +72,7 @@ namespace osu.Game.Tests.Visual.UserInterface AddStep("Change text", () => box.Text = "New message"); AddStep("Move down", () => InputManager.Key(Key.Down)); AddStep("Move up", () => InputManager.Key(Key.Up)); - AddAssert("Changes kept", () => box.Text == "New message"); + AddAssert("Changes lost", () => box.Text == "Message 2"); } [Test] diff --git a/osu.Game/Graphics/UserInterface/HistoryTextBox.cs b/osu.Game/Graphics/UserInterface/HistoryTextBox.cs index 6791812b98..290457564b 100644 --- a/osu.Game/Graphics/UserInterface/HistoryTextBox.cs +++ b/osu.Game/Graphics/UserInterface/HistoryTextBox.cs @@ -45,8 +45,6 @@ namespace osu.Game.Graphics.UserInterface if (selectedIndex == HistoryCount) originalMessage = Text; - else if (!string.IsNullOrEmpty(Text)) - messageHistory[selectedIndex] = Text; Text = messageHistory[--selectedIndex]; @@ -56,9 +54,6 @@ namespace osu.Game.Graphics.UserInterface if (selectedIndex == HistoryCount) return true; - if (!string.IsNullOrEmpty(Text)) - messageHistory[selectedIndex] = Text; - if (selectedIndex == HistoryCount - 1) { selectedIndex = HistoryCount; From 7dc7729ac2464c9967c1deff87056d1721897626 Mon Sep 17 00:00:00 2001 From: Terochi Date: Mon, 21 Nov 2022 10:11:26 +0100 Subject: [PATCH 17/20] Variant 4: cannot change history, empty text/everything selected resets index (current with bug fix) --- .../UserInterface/TestSceneHistoryTextBox.cs | 9 +++++- .../Graphics/UserInterface/HistoryTextBox.cs | 28 +++++++++++++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneHistoryTextBox.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneHistoryTextBox.cs index 414c1276e1..29f1e29b55 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneHistoryTextBox.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneHistoryTextBox.cs @@ -3,6 +3,7 @@ using NUnit.Framework; using osu.Framework.Graphics; +using osu.Framework.Input; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; @@ -101,7 +102,13 @@ namespace osu.Game.Tests.Visual.UserInterface AddStep("Remove text", () => box.Text = string.Empty); AddStep("Move Up", () => InputManager.Key(Key.Up)); - AddAssert("Text unchanged", () => box.Text == string.Empty); + AddAssert("Same as previous message", () => box.Text == "Message 2"); + + AddStep("Move Up", () => InputManager.Key(Key.Up)); + AddStep("Select text", () => InputManager.Keys(PlatformAction.SelectAll)); + AddStep("Replace text", () => box.Text = "New text"); + AddStep("Move Up", () => InputManager.Key(Key.Up)); + AddAssert("Same as previous message", () => box.Text == "Message 2"); } private void addMessages(int count) diff --git a/osu.Game/Graphics/UserInterface/HistoryTextBox.cs b/osu.Game/Graphics/UserInterface/HistoryTextBox.cs index 290457564b..f2b975226c 100644 --- a/osu.Game/Graphics/UserInterface/HistoryTextBox.cs +++ b/osu.Game/Graphics/UserInterface/HistoryTextBox.cs @@ -22,6 +22,7 @@ namespace osu.Game.Graphics.UserInterface private int selectedIndex; private string originalMessage = string.Empty; + private bool everythingSelected; /// /// Creates a new . @@ -33,6 +34,29 @@ namespace osu.Game.Graphics.UserInterface public HistoryTextBox(int capacity = 100) { messageHistory = new LimitedCapacityQueue(capacity); + + Current.ValueChanged += text => + { + if (string.IsNullOrEmpty(text.NewValue) || everythingSelected) + { + selectedIndex = HistoryCount; + everythingSelected = false; + } + }; + } + + protected override void OnTextDeselected() + { + base.OnTextDeselected(); + + everythingSelected = false; + } + + protected override void OnTextSelectionChanged(TextSelectionType selectionType) + { + base.OnTextSelectionChanged(selectionType); + + everythingSelected = SelectedText == Text; } protected override bool OnKeyDown(KeyDownEvent e) @@ -43,6 +67,8 @@ namespace osu.Game.Graphics.UserInterface if (selectedIndex == 0) return true; + everythingSelected = false; + if (selectedIndex == HistoryCount) originalMessage = Text; @@ -54,6 +80,8 @@ namespace osu.Game.Graphics.UserInterface if (selectedIndex == HistoryCount) return true; + everythingSelected = false; + if (selectedIndex == HistoryCount - 1) { selectedIndex = HistoryCount; From d81ef541bc8ff8f49119b4491a6842277c60983c Mon Sep 17 00:00:00 2001 From: Terochi Date: Mon, 21 Nov 2022 10:17:28 +0100 Subject: [PATCH 18/20] Variant 5: cannot change history, edit resets index --- .../UserInterface/TestSceneHistoryTextBox.cs | 9 +------- .../Graphics/UserInterface/HistoryTextBox.cs | 22 +------------------ 2 files changed, 2 insertions(+), 29 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneHistoryTextBox.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneHistoryTextBox.cs index 29f1e29b55..78b1bdb18c 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneHistoryTextBox.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneHistoryTextBox.cs @@ -3,7 +3,6 @@ using NUnit.Framework; using osu.Framework.Graphics; -using osu.Framework.Input; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; @@ -100,13 +99,7 @@ namespace osu.Game.Tests.Visual.UserInterface AddRepeatStep("Move Up", () => InputManager.Key(Key.Up), 2); AddAssert("Same as 1st message", () => box.Text == "Message 1"); - AddStep("Remove text", () => box.Text = string.Empty); - AddStep("Move Up", () => InputManager.Key(Key.Up)); - AddAssert("Same as previous message", () => box.Text == "Message 2"); - - AddStep("Move Up", () => InputManager.Key(Key.Up)); - AddStep("Select text", () => InputManager.Keys(PlatformAction.SelectAll)); - AddStep("Replace text", () => box.Text = "New text"); + AddStep("Change text", () => box.Text = "New message"); AddStep("Move Up", () => InputManager.Key(Key.Up)); AddAssert("Same as previous message", () => box.Text == "Message 2"); } diff --git a/osu.Game/Graphics/UserInterface/HistoryTextBox.cs b/osu.Game/Graphics/UserInterface/HistoryTextBox.cs index f2b975226c..0958e1832e 100644 --- a/osu.Game/Graphics/UserInterface/HistoryTextBox.cs +++ b/osu.Game/Graphics/UserInterface/HistoryTextBox.cs @@ -22,7 +22,6 @@ namespace osu.Game.Graphics.UserInterface private int selectedIndex; private string originalMessage = string.Empty; - private bool everythingSelected; /// /// Creates a new . @@ -37,28 +36,13 @@ namespace osu.Game.Graphics.UserInterface Current.ValueChanged += text => { - if (string.IsNullOrEmpty(text.NewValue) || everythingSelected) + if (selectedIndex != HistoryCount && text.NewValue != messageHistory[selectedIndex]) { selectedIndex = HistoryCount; - everythingSelected = false; } }; } - protected override void OnTextDeselected() - { - base.OnTextDeselected(); - - everythingSelected = false; - } - - protected override void OnTextSelectionChanged(TextSelectionType selectionType) - { - base.OnTextSelectionChanged(selectionType); - - everythingSelected = SelectedText == Text; - } - protected override bool OnKeyDown(KeyDownEvent e) { switch (e.Key) @@ -67,8 +51,6 @@ namespace osu.Game.Graphics.UserInterface if (selectedIndex == 0) return true; - everythingSelected = false; - if (selectedIndex == HistoryCount) originalMessage = Text; @@ -80,8 +62,6 @@ namespace osu.Game.Graphics.UserInterface if (selectedIndex == HistoryCount) return true; - everythingSelected = false; - if (selectedIndex == HistoryCount - 1) { selectedIndex = HistoryCount; From 39934bccd6f78d7d328b1b7b9901147304a9c08b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 22 Nov 2022 19:47:41 +0100 Subject: [PATCH 19/20] Add back removed test coverage --- .../UserInterface/TestSceneHistoryTextBox.cs | 62 +++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneHistoryTextBox.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneHistoryTextBox.cs index 78b1bdb18c..8ed5dd43cc 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneHistoryTextBox.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneHistoryTextBox.cs @@ -62,6 +62,68 @@ namespace osu.Game.Tests.Visual.UserInterface }); } + [Test] + public void TestEmptyHistory() + { + AddStep("Set text", () => box.Text = temp); + + AddStep("Move down", () => InputManager.Key(Key.Down)); + AddAssert("Text is unchanged", () => box.Text == temp); + + AddStep("Move up", () => InputManager.Key(Key.Up)); + AddAssert("Text is unchanged", () => box.Text == temp); + } + + [Test] + public void TestPartialHistory() + { + addMessages(3); + AddStep("Set text", () => box.Text = temp); + + AddStep("Move down", () => InputManager.Key(Key.Down)); + AddAssert("Text is unchanged", () => box.Text == temp); + + AddRepeatStep("Move up", () => InputManager.Key(Key.Up), 3); + AddAssert("Same as 1st message", () => box.Text == "Message 1"); + + AddStep("Move up", () => InputManager.Key(Key.Up)); + AddAssert("Same as 1st message", () => box.Text == "Message 1"); + + AddStep("Move down", () => InputManager.Key(Key.Down)); + AddAssert("Same as 2nd message", () => box.Text == "Message 2"); + + AddRepeatStep("Move down", () => InputManager.Key(Key.Down), 2); + AddAssert("Temporary message restored", () => box.Text == temp); + + AddStep("Move down", () => InputManager.Key(Key.Down)); + AddAssert("Text is unchanged", () => box.Text == temp); + } + + [Test] + public void TestFullHistory() + { + addMessages(7); + AddStep("Set text", () => box.Text = temp); + + AddStep("Move down", () => InputManager.Key(Key.Down)); + AddAssert("Text is unchanged", () => box.Text == temp); + + AddRepeatStep("Move up", () => InputManager.Key(Key.Up), 5); + AddAssert("Same as 3rd message", () => box.Text == "Message 3"); + + AddStep("Move up", () => InputManager.Key(Key.Up)); + AddAssert("Same as 3rd message", () => box.Text == "Message 3"); + + AddRepeatStep("Move down", () => InputManager.Key(Key.Down), 4); + AddAssert("Same as 7th message", () => box.Text == "Message 7"); + + AddStep("Move down", () => InputManager.Key(Key.Down)); + AddAssert("Temporary message restored", () => box.Text == temp); + + AddStep("Move down", () => InputManager.Key(Key.Down)); + AddAssert("Text is unchanged", () => box.Text == temp); + } + [Test] public void TestChangedHistory() { From 8dbc38e17a83e3737c17b0faa72dc047a5fd95f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 22 Nov 2022 20:14:22 +0100 Subject: [PATCH 20/20] Remove unused setter --- osu.Game/Utils/LimitedCapacityQueue.cs | 7 ------- 1 file changed, 7 deletions(-) diff --git a/osu.Game/Utils/LimitedCapacityQueue.cs b/osu.Game/Utils/LimitedCapacityQueue.cs index 8f3b36a059..86a106a678 100644 --- a/osu.Game/Utils/LimitedCapacityQueue.cs +++ b/osu.Game/Utils/LimitedCapacityQueue.cs @@ -103,13 +103,6 @@ namespace osu.Game.Utils return array[(start + index) % capacity]; } - set - { - if (index < 0 || index >= Count) - throw new ArgumentOutOfRangeException(nameof(index)); - - array[(start + index) % capacity] = value; - } } ///