123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311 |
- /*
- ConFrames - Gui Stuff for Console Windows
- Copyright (C) 2017-2018 Topten Software.
- ConFrames is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
- ConFrames is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with ConFrames. If not, see <http://www.gnu.org/licenses/>.
- */
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.Threading.Tasks;
- namespace ConFrames
- {
- public class ConsoleWindow : Window
- {
- public ConsoleWindow(string title, Rect frameRectangle) : base(title, frameRectangle)
- {
- _buffer.Add(null);
- ScrollPos = 0;
- _prompt = ">";
- CursorVisible = true;
- CursorPosition = new Point(_prompt.Length, 0);
- }
- public string Prompt
- {
- get { return _prompt; }
- set { _prompt = value; }
- }
- public void Write(string str)
- {
- if (string.IsNullOrEmpty(str))
- return;
- str = str.Replace("\r\n", "\n").Replace('\r', '\n');
- var lines = str.Split('\n');
- bool trailingCR = str.EndsWith("\n");
- int lineCount = trailingCR ? lines.Length - 1 : lines.Length;
- int oldBufferSize = _buffer.Count;
- for (int i=0; i < lineCount; i++)
- {
- int count = _buffer.Count;
- if (_buffer[count - 1] == null)
- _buffer[count - 1] = lines[i];
- else
- _buffer[count - 1] = _buffer[count - 1] + lines[i];
- if (i < lineCount-1)
- _buffer.Add(null);
- }
- if (trailingCR)
- _buffer.Add(null);
- CursorY += _buffer.Count - oldBufferSize;
- Invalidate();
- ScrollToBottom();
- }
- public void WriteLine(string str)
- {
- Write(str);
- Write("\n");
- }
- public void WriteLine(string str, params object[] args)
- {
- WriteLine(string.Format(str, args));
- }
- public override void OnPaint(PaintContext ctx)
- {
- base.OnPaint(ctx);
- var height = ClientSize.Height;
- if (_prompt!=null)
- height--;
- int firstLine = ScrollPos;
- int lastLine = ScrollPos + height + 1;
- if (lastLine > TrimmedBufferLines)
- lastLine = TrimmedBufferLines;
- if (firstLine < _buffer.Count)
- {
- for (int i=firstLine; i<lastLine; i++)
- {
- var line = _buffer[i];
- ctx.WriteLine(line == null ? "" : line);
- }
- }
- if (lastLine == TrimmedBufferLines && _prompt!= null)
- {
- ctx.Write(_prompt);
- ctx.WriteLine(_inputBuffer);
- }
- }
- int _scrollPos;
- public int ScrollPos
- {
- get
- {
- return _scrollPos;
- }
- set
- {
- if (value < 0)
- value = 0;
- if (value > TrimmedBufferLines)
- value = TrimmedBufferLines;
- if (_scrollPos == value)
- return;
- CursorY += _scrollPos - value;
- _scrollPos = value;
- Invalidate();
- }
- }
- List<string> _buffer = new List<string>();
- string _prompt = null;
- string _inputBuffer = "";
- void RedrawPrompt()
- {
- var ctx = GetPaintContext();
- ctx.ClearLineOnReturn = true;
- ctx.Position = new Point(0, TrimmedBufferLines - ScrollPos);
- ctx.Write(_prompt);
- ctx.WriteLine(_inputBuffer);
- }
- int TrimmedBufferLines
- {
- get
- {
- int count = _buffer.Count;
- if (_buffer[count - 1] == null)
- count--;
- return count;
- }
- }
- void ScrollToBottom()
- {
- ScrollPos = _buffer.Count - ClientSize.Height;
- if (ScrollPos < 0)
- ScrollPos = 0;
- }
- public override bool OnKey(ConsoleKeyInfo key)
- {
- int posInBuffer = CursorX - _prompt.Length;
- switch (key.Key)
- {
- case ConsoleKey.LeftArrow:
- if (posInBuffer > 0)
- CursorX--;
- ScrollToBottom();
- return true;
- case ConsoleKey.RightArrow:
- if (posInBuffer < _inputBuffer.Length)
- CursorX++;
- ScrollToBottom();
- return true;
- case ConsoleKey.UpArrow:
- if (key.Modifiers == ConsoleModifiers.Shift)
- ScrollPos--;
- else
- OnCommandHistory(-1);
- return true;
- case ConsoleKey.DownArrow:
- if (key.Modifiers == ConsoleModifiers.Shift)
- ScrollPos++;
- else
- OnCommandHistory(1);
- return true;
- case ConsoleKey.Home:
- CursorX = _prompt.Length;
- ScrollToBottom();
- return true;
- case ConsoleKey.End:
- CursorX = _prompt.Length + _inputBuffer.Length;
- ScrollToBottom();
- return true;
- case ConsoleKey.Backspace:
- if (posInBuffer > 0)
- {
- _inputBuffer = _inputBuffer.Substring(0, posInBuffer - 1) + _inputBuffer.Substring(posInBuffer);
- RedrawPrompt();
- CursorX--;
- }
- ScrollToBottom();
- return true;
- case ConsoleKey.Delete:
- if (posInBuffer < _inputBuffer.Length)
- {
- _inputBuffer = _inputBuffer.Substring(0, posInBuffer) + _inputBuffer.Substring(posInBuffer + 1);
- RedrawPrompt();
- }
- ScrollToBottom();
- return true;
- case ConsoleKey.Escape:
- _inputBuffer = "";
- RedrawPrompt();
- CursorX = _prompt.Length;
- ScrollToBottom();
- return true;
- case ConsoleKey.Enter:
- {
- WriteLine(_prompt + _inputBuffer);
- string str = _inputBuffer;
- _inputBuffer = "";
- CursorX = _prompt.Length;
- ScrollToBottom();
- OnCommand(str);
- return true;
- }
- }
- if (key.KeyChar!=0)
- {
- _inputBuffer = _inputBuffer.Substring(0, posInBuffer) + key.KeyChar + _inputBuffer.Substring(posInBuffer);
- CursorX++;
- ScrollToBottom();
- RedrawPrompt();
- return true;
- }
- return false;
- }
- public void SetInputBuffer(string str)
- {
- _inputBuffer = str;
- RedrawPrompt();
- CursorX = _prompt.Length + _inputBuffer.Length;
- ScrollToBottom();
- }
- List<string> _commandHistory = new List<String>();
- int _commandHistoryPos;
- protected virtual void OnCommand(string command)
- {
- if (_commandHistory.Count>0)
- {
- if (_commandHistory[_commandHistory.Count - 1] == command)
- {
- _commandHistoryPos = _commandHistory.Count;
- return;
- }
- }
- _commandHistory.Add(command);
- _commandHistoryPos = _commandHistory.Count;
- }
- void OnCommandHistory(int delta)
- {
- int newPos = _commandHistoryPos + delta;
- if (newPos < 0)
- return;
- if (newPos >= _commandHistory.Count)
- {
- SetInputBuffer("");
- return;
- }
- else
- {
- _commandHistoryPos = newPos;
- SetInputBuffer(_commandHistory[newPos]);
- }
- }
- }
- }
|