Cosmos/source/TxUI/TxUI.cs
Xenni_cp 413e171e7a Text UI Added to my playground - give it a test!
Manager Controls: 'tab' switch between controls; '`' switch back; '~' deselect all. Textbox Controls: 'ALT+q' cursor back; 'ALT+e' cursor forward; 'ALT+w' cursor up; 'ALT+s' cursor down; 'ALT+d' backspace. Button Controls: '[space]' activate.
New GUI will be merged directly into system if people approve. ('Cosmos.Text.Forms' sounds cool enough.)
2009-05-13 02:21:08 +00:00

792 lines
22 KiB
C#

using System;
using System.Runtime.InteropServices;
using System.Collections.Generic;
using Cosmos.Hardware;
using Cosmos.Kernel;
namespace Cosmos.Playground.Xenni.TxUI
{
public sealed class TxUIManager
{
public static TxUIManager Instance = null;
private List<TxCtrl> Controls = new List<TxCtrl>();
private TxCtrl FocusTarget = null;
private int CtrlCnt = 0;
public delegate void dOnUIFrame();
public dOnUIFrame OnUIFrame = null;
public class PointInfo
{
public char Character;
public ConsoleColor ForeColor;
public ConsoleColor BackColor;
public bool Changed = true;
}
public bool OveridePresent = false;
private List<List<PointInfo>> RenderTarget = new List<List<PointInfo>>();
public TxUIManager(VGAScreen.TextSize ScrSz)
:base()
{
Cosmos.Kernel.Heap.EnableDebug = false;
TextScreen.ReallyClearScreen();
for (int x = 0;x < Width;x++)
{
RenderTarget.Add(new List<PointInfo>());
for (int y = 0;y < Height;y++)
{
RenderTarget[RenderTarget.Count - 1].Add(new PointInfo() { ForeColor = ConsoleColor.White, BackColor = ConsoleColor.Black, Character = ' ' });
}
}
TextScreen.CurrentChar = -1;
TextScreen.CurrentRow = -1;
Present();
}
public void SetPoint(int x, int y, PointInfo info)
{
RenderTarget[x][y] = info;
}
public void SetPoint(int x, int y, ConsoleColor fore, ConsoleColor back, char c)
{
RenderTarget[x][y] = new PointInfo() { BackColor = back, ForeColor = fore, Character = c };
}
public PointInfo GetPoint(int x, int y)
{
return RenderTarget[x][y];
}
public void DrawAll()
{
if (OveridePresent)
return;
for (int i = 0;i < Controls.Count;i++)
Controls[i].Draw();
}
public void Present()
{
if (OveridePresent)
return;
for (int x = 0;x < Width;x++)
{
for (int y = 0;y < Height;y++)
{
if (!RenderTarget[x][y].Changed)
{
continue;
}
TextScreen.SetColors(RenderTarget[x][y].ForeColor, RenderTarget[x][y].BackColor);
TextScreen.PutChar(y, x, RenderTarget[x][y].Character);
RenderTarget[x][y].Changed = false;
}
}
}
public int Width
{
get
{
return TextScreen.Columns;
}
}
public int Height
{
get
{
return TextScreen.Rows + 1;
}
}
public void RegisterControl(TxCtrl ctrl)
{
if (ctrl._CtrlID != -1)
throw new InvalidOperationException("Control Allready Registered!");
Controls.Add(ctrl);
ctrl._CtrlID = (CtrlCnt++);
}
public void UnregisterControl(TxCtrl ctrl)
{
Controls.Remove(ctrl);
ctrl._CtrlID = -1;
if (ctrl == FocusTarget)
FocusTarget = null;
}
public void Focus(TxCtrl ctrl)
{
if (FocusTarget != null)
{
FocusTarget._HasFocus = false;
FocusTarget.OnDefocus();
}
FocusTarget = ctrl;
FocusTarget._HasFocus = true;
FocusTarget.OnFocus();
}
public void Defocus()
{
if (FocusTarget != null)
{
FocusTarget._HasFocus = false;
FocusTarget.OnDefocus();
}
FocusTarget = null;
}
public bool EnableCursor = true;
public void OnKeyStateChange(char c)
{
if (Controls.Count == 0)
{
return;
}
int csel = -1;
switch (c)
{
case '`':
if (FocusTarget == null)
{
Focus(Controls[Controls.Count - 1]);
break;
}
for (int i = 0;i < Controls.Count;i++)
{
if (Controls[i]._CtrlID == FocusTarget._CtrlID)
{
csel = i - 1;
break;
}
}
if (csel == -1)
csel = Controls.Count - 1;
Focus(Controls[csel]);
break;
case '\t':
if (FocusTarget == null)
{
Focus(Controls[0]);
break;
}
for (int i = 0;i < Controls.Count;i++)
{
if (Controls[i]._CtrlID == FocusTarget._CtrlID)
{
csel = i + 1;
break;
}
}
if (csel == Controls.Count)
csel = 0;
Focus(Controls[csel]);
break;
case '~':
Defocus();
break;
default:
if (FocusTarget == null || !FocusTarget.OnKeyPress(c))
{
Console.Beep(2048, 250);
}
break;
}
}
private bool doRun = true;
public void Run()
{
doRun = true;
char c = '\0';
while (doRun)
{
if (OnUIFrame != null)
{
OnUIFrame();
}
CPU.Halt();
while (Keyboard.GetChar(out c))
{
if (c == '\0')
{
continue;
}
/*
Cosmos.Debug.Debugger.Send(
"Key: '" + c.ToString() + "'; " +
(Keyboard.ShiftPressed ? "SHIFT " : "") +
(Keyboard.CtrlPressed ? "CTRL " : "") +
(Keyboard.AltPressed ? "ALT" : "")
);
*/
OnKeyStateChange(c);
}
}
}
public void Stop()
{
doRun = false;
}
}
public abstract class TxCtrl
{
private int _X = 0;
private int _Y = 0;
private int _Width = 0;
private int _Height = 0;
internal bool _HasFocus = false;
internal int _CtrlID = -1;
public bool HasFocus
{
get
{
return _HasFocus;
}
}
public int Width
{
get
{
return _Width;
}
set
{
_Width = value;
OnResize();
}
}
public int Height
{
get
{
return _Height;
}
set
{
_Height = value;
OnResize();
}
}
public int X
{
get
{
return _X;
}
set
{
_X = value;
OnMove();
}
}
public int Y
{
get
{
return _Y;
}
set
{
_Y = value;
OnMove();
}
}
public int CtrlID
{
get
{
return _CtrlID;
}
}
internal abstract void Draw();
internal virtual void OnResize()
{
TxUIManager.Instance.DrawAll();
TxUIManager.Instance.Present();
}
internal virtual void OnMove()
{
TxUIManager.Instance.DrawAll();
TxUIManager.Instance.Present();
}
internal virtual void OnFocus()
{
if (TxUIManager.Instance.EnableCursor)
{
TextScreen.CurrentRow = Y;
TextScreen.CurrentChar = X;
}
else
{
TextScreen.CurrentRow = -1;
TextScreen.CurrentChar = -1;
}
}
internal virtual void OnDefocus()
{
TextScreen.CurrentRow = -1;
TextScreen.CurrentChar = -1;
}
internal virtual bool OnKeyPress(char c)
{
return false;
}
protected void SetPoint(int x, int y, TxUIManager.PointInfo info)
{
TxUIManager.Instance.SetPoint(x + X, y + Y, info);
}
protected void SetPoint(int x, int y, ConsoleColor fore, ConsoleColor back, char c)
{
TxUIManager.Instance.SetPoint(x + X, y + Y, fore, back, c);
}
protected TxUIManager.PointInfo GetPoint(int x, int y)
{
return TxUIManager.Instance.GetPoint(x + X, y + Y);
}
}
public class TxLabl : TxCtrl
{
public String Text = "";
public ConsoleColor ForeColor = ConsoleColor.White;
public ConsoleColor BackColor = ConsoleColor.Black;
internal override void Draw()
{
char[] cText = Text.ToCharArray();
for (int i = 0;i < Width;i++)
{
if (i < cText.Length)
{
SetPoint(i, 0, ForeColor, BackColor, cText[i]);
}
else
{
SetPoint(i, 0, ForeColor, BackColor, ' ');
}
}
}
internal override void OnResize()
{
if (Width < 1)
Width = 1;
if (Height != 1)
Height = 1;
}
}
public class TxBtn : TxCtrl
{
public String Text = "";
public ConsoleColor UForeColor = ConsoleColor.White;
public ConsoleColor UBackColor = ConsoleColor.Gray;
public ConsoleColor FForeColor = ConsoleColor.White;
public ConsoleColor FBackColor = ConsoleColor.Black;
public ConsoleColor PForeColor = ConsoleColor.White;
public ConsoleColor PBackColor = ConsoleColor.Black;
private ConsoleColor _Fore = ConsoleColor.White;
private ConsoleColor _Back = ConsoleColor.Black;
public delegate void dOnActivate();
public dOnActivate OnActivate = null;
private bool SupressColorEval = false;
internal override void OnDefocus()
{
Draw();
TxUIManager.Instance.Present();
base.OnDefocus();
}
internal override void OnFocus()
{
Draw();
TxUIManager.Instance.Present();
TxUIManager.Instance.EnableCursor = false;
base.OnFocus();
TxUIManager.Instance.EnableCursor = true;
}
internal override void OnResize()
{
if (Width < 1)
Width = 1;
if (Height < 1)
Height = 1;
base.OnResize();
}
internal override bool OnKeyPress(char c)
{
if (c == ' ')
{
_Fore = PForeColor;
_Back = PBackColor;
SupressColorEval = true;
Draw();
SupressColorEval = false;
TxUIManager.Instance.Present();
if (OnActivate != null)
OnActivate();
Draw();
TxUIManager.Instance.Present();
return true;
}
return base.OnKeyPress(c);
}
internal override void Draw()
{
char[] cText = Text.ToCharArray();
if (!SupressColorEval)
{
if (HasFocus)
{
_Fore = FForeColor;
_Back = FBackColor;
}
else
{
_Fore = UForeColor;
_Back = UBackColor;
}
}
int spaceabove = (Height / 2);
int spacebelow = Height - (1 + spaceabove);
for (int y = 0;y < spaceabove;y++)
{
for (int x = 0;x < Width;x++)
{
SetPoint(x, y, _Fore, _Back, ' ');
}
}
for (int x = 0;x < Width;x++)
{
if (x < cText.Length)
{
SetPoint(x, spaceabove, _Fore, _Back, cText[x]);
}
else
{
SetPoint(x, spaceabove, _Fore, _Back, ' ');
}
}
for (int y = 0;y < spacebelow;y++)
{
for (int x = 0;x < Width;x++)
{
SetPoint(x, y + spaceabove + 1, _Fore, _Back, ' ');
}
}
}
}
public class TxEditbox : TxCtrl
{
public ConsoleColor UForeColor = ConsoleColor.White;
public ConsoleColor UBackColor = ConsoleColor.Gray;
public ConsoleColor FForeColor = ConsoleColor.White;
public ConsoleColor FBackColor = ConsoleColor.Black;
internal override void OnDefocus()
{
Draw();
TxUIManager.Instance.Present();
base.OnDefocus();
}
internal override void OnFocus()
{
_CursorPosX = 0;
_CursorPosY = 0;
Draw();
TxUIManager.Instance.Present();
base.OnFocus();
}
internal override void OnResize()
{
if (Width < 1)
Width = 1;
if (Height < 1)
Height = 1;
if (Lines.Length != Height)
{
String[] newlines = new String[Height];
for (int i = 0;i < Lines.Length;i++)
{
newlines[i] = Lines[i];
}
for (int i = Lines.Length;i < Height;i++)
{
newlines[i] = "";
}
Lines = newlines;
}
for (int i = 0;i < Lines.Length;i++)
{
if (Lines[i].Length > Width)
{
Lines[i] = Lines[i].Substring(0, Width);
}
}
if (this.HasFocus)
{
CursorPosX = 0;
CursorPosY = 0;
}
base.OnResize();
}
internal override bool OnKeyPress(char c)
{
switch (c)
{
case 'q':
if (!Keyboard.AltPressed)
{
goto default;
}
CursorPosX--;
break;
case 'e':
if (!Keyboard.AltPressed)
{
goto default;
}
CursorPosX++;
break;
case 'd':
if (!Keyboard.AltPressed)
{
goto default;
}
if (_CursorPosX == 0)
{
Console.Beep(2048, 250);
break;
}
Lines[_CursorPosY] = Lines[_CursorPosY].Substring(0, _CursorPosX - 1) + Lines[_CursorPosY].Substring(_CursorPosX, Lines[_CursorPosY].Length - _CursorPosX);
CursorPosX--;
if (OnTextChanged != null)
OnTextChanged();
Draw();
TxUIManager.Instance.Present();
break;
case 'w':
if (!Keyboard.AltPressed)
{
goto default;
}
if (_CursorPosY == 0)
{
Console.Beep(2048, 250);
break;
}
CursorPosY--;
if (_CursorPosX > Lines[_CursorPosY].Length)
{
CursorPosX = Lines[_CursorPosY].Length;
}
break;
case 's':
if (!Keyboard.AltPressed)
{
goto default;
}
if (_CursorPosY == (Height - 1))
{
Console.Beep(2048, 250);
break;
}
CursorPosY++;
if (_CursorPosX > Lines[_CursorPosY].Length)
{
CursorPosX = Lines[_CursorPosY].Length;
}
break;
default:
if (_CursorPosX == Width || Lines[_CursorPosY].Length == Width)
{
Console.Beep(2048, 250);
break;
}
Lines[_CursorPosY] = Lines[_CursorPosY].Substring(0, _CursorPosX) + c.ToString() + Lines[_CursorPosY].Substring(_CursorPosX, Lines[_CursorPosY].Length - _CursorPosX);
CursorPosX++;
if (OnTextChanged != null)
OnTextChanged();
Draw();
TxUIManager.Instance.Present();
break;
}
base.OnKeyPress(c);
return true;
}
private int _CursorPosX = 0;
private int _CursorPosY = 0;
public int CursorPosX
{
get
{
return _CursorPosX;
}
set
{
if (value < 0)
{
value = 0;
Console.Beep(2048, 250);
}
if (value > Width)
{
value = Width;
Console.Beep(2048, 250);
}
if (value > Lines[_CursorPosY].Length)
{
value = Lines[_CursorPosY].Length;
Console.Beep(2048, 250);
}
_CursorPosX = value;
TextScreen.CurrentChar = (X + _CursorPosX);
}
}
public int CursorPosY
{
get
{
return _CursorPosY;
}
set
{
if (value < 0)
{
value = 0;
Console.Beep(2048, 250);
}
if (value >= Height)
{
value = (Height - 1);
Console.Beep(2048, 250);
}
_CursorPosY = value;
TextScreen.CurrentRow = (Y + _CursorPosY);
}
}
public delegate void dOnTextChanged();
public dOnTextChanged OnTextChanged = null;
private String[] Lines = new String[0];
internal override void Draw()
{
ConsoleColor ForeColor = (HasFocus ? FForeColor : UForeColor);
ConsoleColor BackColor = (HasFocus ? FBackColor : UBackColor);
for (int y = 0;y < Height;y++)
{
char[] cText = Lines[y].ToCharArray();
for (int x = 0;x < Width;x++)
{
if (x < cText.Length)
{
SetPoint(x, y, ForeColor, BackColor, cText[x]);
}
else
{
SetPoint(x, y, ForeColor, BackColor, ' ');
}
}
}
}
public String this[int indx]
{
get
{
return Lines[indx];
}
set
{
Lines[indx] = value;
}
}
public String Text
{
get
{
String txt = "";
for (int i = 0;i < Lines.Length;i++)
{
txt = txt + Lines[i] + "\n";
}
return txt.Trim('\n');
}
}
}
}