// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. using osu.Framework.Input.Events; using osu.Game.Utils; 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; public int HistoryCount => messageHistory.Count; private int selectedIndex; 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); 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) { switch (e.Key) { case Key.Up: if (selectedIndex == 0) return true; everythingSelected = false; if (selectedIndex == HistoryCount) originalMessage = Text; Text = messageHistory[--selectedIndex]; return true; case Key.Down: if (selectedIndex == HistoryCount) return true; everythingSelected = false; if (selectedIndex == HistoryCount - 1) { selectedIndex = HistoryCount; Text = originalMessage; return true; } Text = messageHistory[++selectedIndex]; return true; } return base.OnKeyDown(e); } protected override void Commit() { if (!string.IsNullOrEmpty(Text)) messageHistory.Enqueue(Text); selectedIndex = HistoryCount; base.Commit(); } } }