Procházet zdrojové kódy

Added console window

Brad Robinson před 8 roky
rodič
revize
2de64f42f6
3 změnil soubory, kde provedl 326 přidání a 3 odebrání
  1. 1 0
      ConFrames/ConFrames.csproj
  2. 293 0
      ConFrames/ConsoleWindow.cs
  3. 32 3
      Sample/Program.cs

+ 1 - 0
ConFrames/ConFrames.csproj

@@ -35,6 +35,7 @@
     <Reference Include="Microsoft.CSharp" />
   </ItemGroup>
   <ItemGroup>
+    <Compile Include="ConsoleWindow.cs" />
     <Compile Include="Desktop.cs" />
     <Compile Include="Interop.cs" />
     <Compile Include="PaintContext.cs" />

+ 293 - 0
ConFrames/ConsoleWindow.cs

@@ -0,0 +1,293 @@
+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]);
+            }
+        }
+    }
+}

+ 32 - 3
Sample/Program.cs

@@ -9,22 +9,32 @@ namespace Sample
 {
     class Window1 : Window
     {
-        public Window1() :base("Window 1", new Rect(0, 0, 100, 20))
+        public Window1() :base("Window 1", new Rect(0, 0, 50, 20))
         {
         }
 
         public override void OnPaint(PaintContext ctx)
         {
+            ctx.ForegroundColor = ConsoleColor.Cyan;
             for (int i=0; i<20; i++)
             {
-                ctx.WriteLine("This is line {0}", i + 1);
+                ctx.WriteLine("This is line {0}", _baseNumber + i);
             }
         }
+
+        public override bool OnKey(ConsoleKeyInfo key)
+        {
+            _baseNumber += 5;
+            Invalidate();
+            return base.OnKey(key);
+        }
+
+        int _baseNumber = 1;
     }
 
     class Window2 : Window
     {
-        public Window2() : base("Window 2", new Rect(0, 20, 100, 20))
+        public Window2() : base("Window 2", new Rect(50, 0, 50, 20))
         {
             CursorVisible = true;
             CursorX = 5;
@@ -64,6 +74,23 @@ namespace Sample
         }
     }
 
+    class CommandWindow : ConsoleWindow
+    {
+        public CommandWindow() : base("Command", new Rect(0, 20, 100, 20))
+        {
+            Prompt = ">";
+            WriteLine("Type something and press enter.  Use Shift+Up/Down to scroll");
+        }
+
+        protected override void OnCommand(string command)
+        {
+            WriteLine("You typed: '{0}'", command);
+
+            // Call base to update command history (up/down arrow)
+            base.OnCommand(command);
+        }
+    }
+
     class Program
     {
         static void Main(string[] args)
@@ -71,8 +98,10 @@ namespace Sample
             var desktop = new Desktop(100, 40);
             var w1 = new Window1();
             var w2 = new Window2();
+            var cmd = new CommandWindow();
             w1.Open(desktop);
             w2.Open(desktop);
+            cmd.Open(desktop);
 
             desktop.Process();
         }