GabrielTofvesson 939f6c910b Fixed som graphics routines
Added support for on-the-fly textview contents updates
Added iterative view removal to ConsoleController
Added dumy layouts to Common
Added support for account removal
Fixed command management (now supports leading, padding and trailing spaces)
Various smaller changes
2018-05-18 20:45:43 +02:00

174 lines
8.3 KiB
C#

using Client.ConsoleForms;
using Client.ConsoleForms.Parameters;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Tofvesson.Collections;
namespace Client.ConsoleForms.Graphics
{
public abstract class View
{
protected delegate void EventAction();
public delegate void ViewEvent(View v);
protected static readonly Padding DEFAULT_PADDING = new AbsolutePadding(0, 0, 0, 0);
protected internal readonly Padding padding;
protected readonly Gravity gravity;
protected readonly bool vCenter, hCenter;
protected readonly string back_data;
public char Border { get; set; }
public bool DrawBorder { get; set; }
public ConsoleColor BorderColor { get; set; }
public ConsoleColor BackgroundColor { get; set; }
public ConsoleColor TextColor { get; set; }
public int ContentWidth { get; protected set; }
public int ContentHeight { get; protected set; }
public abstract Region Occlusion { get; } // Reports dimensions of entire view
public Region ContentOcclusion { get => Occlusion; }// Reports dimensions of contents (SHOULD for most applications be smaller than or equal in size to Occlusion)
public bool Dirty { get; set; } // Flag for whether or not view requires re-rendering
public LangManager I18n { get; private set; } // Translation
public ViewEvent OnBackEvent { get; set; } // Callback for [ESC] key
public ViewEvent OnClose { get; set; } // Callback called immediately before controller removes view from render queue
public View(ViewData parameters, LangManager lang)
{
padding = new AbsolutePadding(parameters.AttribueAsInt("padding_left"), parameters.AttribueAsInt("padding_right"), parameters.AttribueAsInt("padding_top"), parameters.AttribueAsInt("padding_bottom"));
gravity = (Gravity)parameters.AttribueAsInt("gravity");
BorderColor = (ConsoleColor)parameters.AttribueAsInt("border", (int)ConsoleColor.Blue);
BackgroundColor = (ConsoleColor)parameters.AttribueAsInt("color_background", (int)ConsoleColor.White);
TextColor = (ConsoleColor)parameters.AttribueAsInt("color_text", (int)ConsoleColor.Black);
Border = ' ';
DrawBorder = true;// parameters.attributes.ContainsKey("border");
I18n = lang;
back_data = parameters.GetAttribute("back");
// Do check to ensure that gravity flags are valid
Enums.LayoutCheck(ref gravity);
vCenter = !Enums.HasFlag(gravity, Gravity.LEFT) && !Enums.HasFlag(gravity, Gravity.RIGHT);
hCenter = !Enums.HasFlag(gravity, Gravity.TOP) && !Enums.HasFlag(gravity, Gravity.BOTTOM);
}
public void ResetRenderColors() => SetRenderColors(BackgroundColor, TextColor);
public void SetRenderColors(ConsoleColor bg, ConsoleColor fg)
{
Console.BackgroundColor = bg;
Console.ForegroundColor = fg;
}
public void Draw(Tuple<int, int> t) => Draw(t.Item1, t.Item2);
public void Draw(int left, int top) => Draw(left, ref top);
public void Draw(int left, ref int top)
{
Dirty = false;
if (DrawBorder)
_DrawBorder(left, top);
DrawPadding(ref left, ref top);
_Draw(left, ref top);
}
public virtual void _DrawBorder(int left, int top)
{
Console.BackgroundColor = BorderColor;
Console.SetCursorPosition(left - 1 - padding.Left(), top - 1 - padding.Top());
Console.Write(Filler(Border, ContentWidth + padding.Left() + padding.Right() + 4));
for (int i = 0; i < ContentHeight + padding.Top() + padding.Bottom(); ++i)
{
Console.SetCursorPosition(left - padding.Left() - 1, top - padding.Top() + i);
Console.Write(Filler(Border, 2));
Console.SetCursorPosition(left + ContentWidth + padding.Left() + padding.Right() - 1, top - padding.Top() + i);
Console.Write(Filler(Border, 2));
}
Console.SetCursorPosition(left - padding.Left() - 1, top + ContentHeight + padding.Bottom());
Console.Write(Filler(Border, ContentWidth + padding.Left() + padding.Right() + 4));
Console.BackgroundColor = ConsoleColor.Black;
}
public virtual void DrawPadding(ref int left, ref int top)
{
Console.BackgroundColor = BackgroundColor;
// Top padding
for(int i = 0; i<padding.Top(); ++i)
{
Console.SetCursorPosition(left - padding.Left() + 1, top + i - padding.Top());
Console.Write(Filler(' ', padding.Left() + ContentWidth + padding.Right()));
}
// Left-right padding
for(int i = 0; i<ContentHeight; ++i)
{
Console.SetCursorPosition(left - padding.Left() + 1, top + i);
Console.Write(Filler(' ', padding.Left()));
Console.SetCursorPosition(left + ContentWidth + padding.Left() - 1, top + i);
Console.Write(Filler(' ', padding.Right()));
}
// Bottom padding
for(int i = 0; i<padding.Bottom(); ++i)
{
Console.SetCursorPosition(left - 1, top + ContentHeight + i);
Console.Write(Filler(' ', padding.Left() + ContentWidth + padding.Right()));
}
left += padding.Left() / 2; // Increment left offset
}
protected abstract void _Draw(int left, ref int top);
public virtual bool HandleKeyEvent(ConsoleController.KeyEvent info, bool inFocus, bool triggered)
{
if ((back_data.Length != 0 || OnBackEvent!=null) && (triggered || (info.ValidEvent && inFocus)) && info.Event.Key == ConsoleKey.Escape)
{
info.ValidEvent = false;
if(back_data.Length!=0) ParseAction(back_data, true)();
OnBackEvent?.Invoke(this);
}
return false;
}
public virtual void TriggerKeyEvent(ConsoleKeyInfo info) => TriggerKeyEvent(new ConsoleController.KeyEvent(info));
public virtual void TriggerKeyEvent(ConsoleController.KeyEvent info) => HandleKeyEvent(info, true, true);
protected void DrawTopPadding(int left, ref int top) => DrawPadding(left, ref top, padding.Top());
protected void DrawBottomPadding(int left, ref int top) => DrawPadding(left, ref top, padding.Bottom());
private void DrawPadding(int left, ref int top, int count)
{
for (int i = 0; i < count; ++i)
{
Console.SetCursorPosition(left, top++);
Console.Write(Filler(' ', ContentWidth));
}
}
protected EventAction ParseAction(ViewData data)
{
bool.TryParse(data?.GetAttribute("close") ?? "false", out bool close);
bool.TryParse(data?.GetAttribute("exit") ?? "false", out bool exit);
return ParseAction(data.GetAttribute("event"), close, exit);
}
protected EventAction ParseAction(string action, bool close, bool triggerExit = false)
{
string[] components;
if (action == null || !action.Contains(':') || (components = action.Split(':')).Length != 2)
return () => {
if (close) ConsoleController.singleton.CloseView(this);
if (triggerExit) ConsoleController.singleton.ShouldExit = true;
};
var views = ConsoleController.LoadResourceViews(components[0], I18n);
var view = views.GetNamed(components[1]);
return () =>
{
if (close) ConsoleController.singleton.CloseView(this);
ConsoleController.singleton.AddView(view);
if (triggerExit) ConsoleController.singleton.ShouldExit = true;
};
}
protected internal static string Filler(char c, int count)
{
if (count == 0) return "";
StringBuilder builder = new StringBuilder(count);
for (int i = 0; i < count; ++i) builder.Append(c);
return builder.ToString();
}
}
}