Example #1
0
        public Terminal(RenderWindow window, Font font, IInput input, Func <ICommandRunner> getCommandRunner, Func <string, List <string> > getSuggestions)
        {
            _closedYPos       = window.Size.Y / 2f;
            _reportBackground = new RectangleShape(new Vector2f(window.Size.X, window.Size.Y / 2f))
            {
                FillColor = _reportBackgroundColor,
            };
            _inputBackground =
                new RectangleShape(new Vector2f(window.Size.X, font.GetLineSpacing(CharacterSize) * 1.1f))
            {
                FillColor = _inputBackgroundColor
            };

            _reportText = new WrappedTextRenderer(() => _reportBackground.GetGlobalBounds(), font, CharacterSize, new Dictionary <Tag, Color>
            {
                { Tag.Input, InputTextColor },
                { Tag.Response, ResponseTextColor },
                { Tag.Error, new Color(255, 100, 100) },
                { Tag.Warning, new Color(255, 155, 55) },
                { Tag.Debug, Color.Yellow },
                { Tag.SuperLowDebug, Color.Green }
            });
            _inputHistory = new List <string>();

            _inputText = new CursorizedText(new Text("", font, CharacterSize)
            {
                Color = InputTextColor
            },
                                            _inputBackground.GetGlobalBounds, CharacterSize,
                                            () =>
            {
                var fraction = MathF.Sin(3 * (Core.TimeInfo.CurrentTime - _lastInputTime));
                fraction    *= fraction;
                return(Color.White.Lerp(new Color(255, 255, 255, 0), fraction));
            });

            _completer = new AutoCompleter(getSuggestions, () => _inputBackground.Position + new Vector2f(5, CharacterSize * 1.5f), font, CharacterSize);

            _inputText.OnTextChanged += str => _completer.UpdateInputString(str);
            var inputHistoryIndex = 0;
            var toggled           = false;

            input.TextEntered += args =>
            {
                if (args.Unicode == "`")
                {
                    switch (_state)
                    {
                    case OpenState.Closed:
                        _state = OpenState.Open;
                        input.Consume();
                        toggled = true;
                        break;

                    case OpenState.Open:
                        _state = OpenState.Closed;
                        input.Release();
                        toggled = true;
                        break;

                    default:
                        throw new ArgumentOutOfRangeException();
                    }
                }

                if (_state == OpenState.Open && !input.IsControlDown)
                {
                    _lastInputTime = Core.TimeInfo.CurrentTime;
                    if (!toggled)
                    {
                        switch (args.Unicode)
                        {
                        case "\b":
                        {
                            _inputText.Backspace();
                        }
                        break;

                        case "\r":
                        {
                            if (false)        //_completer.IsActive)
                            {
                                _inputText.SetString(_completer.ChooseSelectedItem());
                                _completer.Escape();
                            }
                            else
                            {
                                var inputString = _inputText.ToString();
                                if (string.IsNullOrWhiteSpace(inputString))
                                {
                                    break;
                                }
                                _inputText.SetString("");
                                _inputHistory.Add(inputString);
                                inputHistoryIndex = _inputHistory.Count;
                                _reportText.AddLine(inputString, Tag.Input);
                                getCommandRunner().RunCommand(inputString)
                                .ForEach(a => _reportText.AddLine(a, Tag.Response));
                            }
                        }
                        break;

                        case @"\u001b":
                            break;

                        default:
                            var text = Regex.Replace(args.Unicode, @"[^\u0020-\u007E]", string.Empty);
                            if (string.IsNullOrEmpty(text))
                            {
                                break;
                            }
                            _inputText.AddString(text);
                            break;
                        }
                    }
                    else
                    {
                        toggled = false;
                    }
                }
                if (toggled)
                {
                    UpdateOpenness();
                }
            };
            input.KeyPressed += args =>
            {
                if (_state != OpenState.Open)
                {
                    return;
                }

                _lastInputTime = Core.TimeInfo.CurrentTime;
                switch (args.Code)
                {
                case Keyboard.Key.Up:
                    if (_completer.IsActive)
                    {
                        _completer.IncrementSelection();
                    }
                    else if (_inputHistory.Any())
                    {
                        inputHistoryIndex--;
                        if (inputHistoryIndex < 0)
                        {
                            inputHistoryIndex = 0;
                        }
                        _inputText.SetString(_inputHistory[inputHistoryIndex]);
                    }
                    break;

                case Keyboard.Key.Down:
                    if (_completer.IsActive)
                    {
                        _completer.DecrementSelection();
                    }
                    else if (_inputHistory.Any())
                    {
                        inputHistoryIndex++;
                        if (inputHistoryIndex >= _inputHistory.Count)
                        {
                            inputHistoryIndex = _inputHistory.Count - 1;
                        }
                        _inputText.SetString(_inputHistory[inputHistoryIndex]);
                    }
                    break;

                case Keyboard.Key.Left:
                    _inputText.RecedeCursor(args.Control, args.Shift);
                    break;

                case Keyboard.Key.Right:
                    _inputText.AdvanceCursor(args.Control, args.Shift);
                    break;

                case Keyboard.Key.Delete:
                    _inputText.Delete();
                    break;

                case Keyboard.Key.Home:
                    _inputText.Home(args.Shift);
                    break;

                case Keyboard.Key.End:
                    _inputText.End(args.Shift);
                    break;

                case Keyboard.Key.Z:
                    if (args.Control)
                    {
                        _inputText.Undo();
                    }
                    if (args.Control && args.Shift)
                    {
                        _inputText.Redo();
                    }
                    break;

                case Keyboard.Key.A:
                    if (args.Control)
                    {
                        _inputText.SelectAll();
                    }
                    break;

                case Keyboard.Key.C:
                    if (args.Control)
                    {
                        var selected = _inputText.SelectedText;
                        if (string.IsNullOrWhiteSpace(selected))
                        {
                            break;
                        }
                        Clippy.PushStringToClipboard(selected);
                    }
                    break;

                case Keyboard.Key.X:
                    if (args.Control)
                    {
                        var selected = _inputText.SelectedText;
                        if (string.IsNullOrWhiteSpace(selected))
                        {
                            break;
                        }
                        Clippy.PushStringToClipboard(selected);
                        _inputText.Delete();
                    }
                    break;

                case Keyboard.Key.V:
                    if (args.Control)
                    {
                        _inputText.AddString(Clippy.GetText());
                    }
                    break;

                case Keyboard.Key.Escape:
                    if (_completer.IsActive)
                    {
                        _completer.Escape();
                    }
                    else
                    {
                        _state = OpenState.Closed;
                        input.Release();
                        toggled = true;
                    }
                    break;

                case Keyboard.Key.Tab:
                    if (_completer.IsActive)
                    {
                        _inputText.SetString(_completer.ChooseSelectedItem());
                        _completer.Escape();
                    }
                    break;

                case Keyboard.Key.Space:
                    if (input.IsControlDown && !_completer.IsActive)
                    {
                        _completer.UpdateInputString(_inputText.ToString());
                    }
                    break;
                }
                if (toggled)
                {
                    UpdateOpenness();
                }
            };

            input.MouseButtonDown    += args => _inputText.HandleMouseDown(new Vector2f(args.X, args.Y), input.IsShiftDown);
            input.MouseButtonUp      += args => _inputText.HandleMouseUp(new Vector2f(args.X, args.Y));
            input.MouseMoved         += args => _inputText.HandleMouseMoved(new Vector2f(args.X, args.Y));
            input.MouseWheelScrolled += args =>
            {
                if (args.Delta > 0)
                {
                    _reportText.ScrollUp();
                }
                else
                {
                    _reportText.ScrollDown();
                }
            };
        }