source/PoshTui/PoshTui/PoshTui_source.cs

/// PoshTui | Version 0.5.0
/// Class Library
///
 
 
using System;
using System.Collections.ObjectModel;
using System.Text;
using System.IO;
using System.Reflection;
using System.Management.Automation;
 
 
namespace PoshTui
{
    // PoshTui Enumerators
    public enum MenuItemFocusStyleEnum
    {
        HighlightForeground,
        HighlightBackground
    }
 
    public enum BorderStyleEnum
    {
        Unspecified,
        SingleLight,
        SingleHeavy,
        Rounded,
        Double
    }
 
    // UIColorTheme Class
    public class UIColorTheme
    {
        public string Reset = "\x1b[0m";
        public string BorderColor = "\x1b[38;5;230m";
        public string AccentColor = "\x1b[38;5;123m";
        public string FormTitleColor = "\x1b[38;5;51m";
        public string MenuTitleColor = "\x1b[38;5;51m";
        public string MenuItemColor = "\x1b[38;5;243m";
        public string MenuItemFocusColor = "\x1b[38;5;229m";
        public string DescriptionHeaderColor = "\x1b[38;5;229m";
        public string MenuItemDescriptionColor = "\x1b[38;5;85m";
 
        public UIColorTheme() { }
    }
 
    // Menu Border Style Classes
 
    // Single Border, Light
    public class MenuBorderSingleLight
    {
        public char CornerTopL = '┌';
        public char CornerTopR = '┐';
        public char Horizontal = '─';
        public char CornerBtmL = '└';
        public char CornerBtmR = '┘';
        public char Vertical = '│';
        public char VerticalSeparatorL = '├';
        public char VerticalSeparatorR = '┤';
        public char Separator = '─';
        public char AltSeparator = '┄';
        public char AccentChar = '█';
 
        public MenuBorderSingleLight() { }
 
    }
 
    // Single Border, Heavy
    public class MenuBorderSingleHeavy
    {
        public char CornerTopL = '┏';
        public char CornerTopR = '┓';
        public char Horizontal = '━';
        public char CornerBtmL = '┗';
        public char CornerBtmR = '┛';
        public char Vertical = '┃';
        public char VerticalSeparatorL = '┠';
        public char VerticalSeparatorR = '┨';
        public char Separator = '─';
        public char AltSeparator = '┄';
        public char AccentChar = '█';
 
        public MenuBorderSingleHeavy() { }
 
    }
 
    // Single Border, Rounded
    public class MenuBorderRounded
    {
        public char CornerTopL = '╭';
        public char CornerTopR = '╮';
        public char Horizontal = '─';
        public char CornerBtmL = '╰';
        public char CornerBtmR = '╯';
        public char Vertical = '│';
        public char VerticalSeparatorL = '├';
        public char VerticalSeparatorR = '┤';
        public char Separator = '─';
        public char AltSeparator = '┄';
        public char AccentChar = '█';
 
 
        public MenuBorderRounded() { }
 
    }
 
    // Double Border
    public class MenuBorderDouble
    {
        public char CornerTopL = '╔';
        public char CornerTopR = '╗';
        public char Horizontal = '═';
        public char CornerBtmL = '╚';
        public char CornerBtmR = '╝';
        public char Vertical = '║';
        public char VerticalSeparatorL = '╟';
        public char VerticalSeparatorR = '╢';
        public char Separator = '─';
        public char AltSeparator = '╍';
        public char AccentChar = '█';
 
        public MenuBorderDouble() { }
 
    }
 
    // Menu Item/UI Element Classes
 
    // Menu Item Class Definition
    public class MenuItem
    {
        public string DisplayName;
        public string Description;
        public ScriptBlock OnConfirm;
 
        public MenuItem() { }
 
        public void SetDisplayName(string displayName)
        {
            DisplayName = displayName;
        }
 
        public void SetDescription(string description)
        {
            Description = description;
        }
 
        public void SetOnConfirmScriptBlock(ScriptBlock scriptBlock)
        {
            OnConfirm = scriptBlock;
        }
    }
 
 
    public class ConsoleForm
    {
        public int FormId = 0;
        public string Name = "PoshTui ConsoleForm";
        public int UIWidth = 208;
        public BorderStyleEnum UIBorderStyle;
        public string FormTitle = "ConsoleForm Title";
        public string MenuTitle = "Menu Title";
        public MenuItem[] MenuItems;
        public MenuItemFocusStyleEnum MenuItemFocusStyle = MenuItemFocusStyleEnum.HighlightBackground;
        public UIColorTheme ColorTheme = new UIColorTheme();
 
        public ConsoleForm() { }
 
        public void AddMenuItem(MenuItem[] items)
        {
            if (MenuItems == null)
            {
                MenuItems = items;
            }
            else
            {
                var combined = new MenuItem[MenuItems.Length + items.Length];
                MenuItems.CopyTo(combined, 0);
                items.CopyTo(combined, MenuItems.Length);
                MenuItems = combined;
            }
        }
 
        public void Show()
        {
            // Set up border style
            object border = UIBorderStyle switch
            {
                BorderStyleEnum.SingleLight => new MenuBorderSingleLight(),
                BorderStyleEnum.SingleHeavy => new MenuBorderSingleHeavy(),
                BorderStyleEnum.Rounded => new MenuBorderRounded(),
                BorderStyleEnum.Double => new MenuBorderDouble(),
                _ => new MenuBorderSingleLight()
            };
 
            // Use reflection to access border chars
            char GetBorderChar(string name) => (char)border.GetType().GetField(name).GetValue(border);
 
            // Color theme
            var color = ColorTheme;
 
            // Console encoding
            Console.OutputEncoding = Encoding.Unicode;
 
            int charFillCount = UIWidth - 2;
            string EmptyFill = new string(' ', charFillCount);
            string HorizontalFill = new string(GetBorderChar("Horizontal"), charFillCount);
            string SeparatorFill = new string(GetBorderChar("Separator"), charFillCount);
            string SeparatorAltFill = new string(GetBorderChar("AltSeparator"), charFillCount);
            string AccentFill = new string(GetBorderChar("AccentChar"), charFillCount);
 
            int menuTitlePadding = (int)Math.Floor((UIWidth - MenuTitle.Length) / 2.0);
            string CenteredMenuTitle = MenuTitle.PadLeft(MenuTitle.Length + menuTitlePadding).PadRight(UIWidth - 2);
 
            string LineBorderTop = $"{color.BorderColor}{GetBorderChar("CornerTopL")}{HorizontalFill}{GetBorderChar("CornerTopR")}{color.Reset}";
            string LineFormTitle = $"{color.BorderColor}{GetBorderChar("Vertical")} {color.FormTitleColor} [{FormTitle}]{color.Reset}{new string(' ', UIWidth - FormTitle.Length - 6)}{color.BorderColor}{GetBorderChar("Vertical")}{color.Reset}";
            string LineBorderSeparator = $"{color.BorderColor}{GetBorderChar("Vertical")}{SeparatorFill}{GetBorderChar("Vertical")}{color.Reset}";
            string LineMenuTitle = $"{color.BorderColor}{GetBorderChar("Vertical")}{color.MenuTitleColor}{CenteredMenuTitle}{color.BorderColor}{GetBorderChar("Vertical")}{color.Reset}";
            string LineEmpty = $"{color.BorderColor}{GetBorderChar("Vertical")}{EmptyFill}{GetBorderChar("Vertical")}{color.Reset}";
            string LineBorderSeparatorAlt = $"{color.BorderColor}{GetBorderChar("Vertical")}{SeparatorAltFill}{GetBorderChar("Vertical")}{color.Reset}";
            string LineFullBlock = $"{color.BorderColor}{GetBorderChar("Vertical")}{color.AccentColor}{AccentFill}{color.BorderColor}{GetBorderChar("Vertical")}{color.Reset}";
            string LineBorderBottom = $"{color.BorderColor}{GetBorderChar("CornerBtmL")}{HorizontalFill}{GetBorderChar("CornerBtmR")}{color.Reset}";
 
            string MenuItemDescriptionHeader = "Item Details";
 
            int selectedIndex = 0;
            Console.CursorVisible = false;
 
            void Redraw()
            {
                Console.Write("\x1b[2J\x1b[H"); // Clear and home cursor
                Console.WriteLine(LineBorderTop);
                Console.WriteLine(LineFormTitle);
                Console.WriteLine(LineBorderSeparator);
                Console.WriteLine(LineMenuTitle);
                Console.WriteLine(LineBorderSeparatorAlt);
                Console.WriteLine(LineEmpty);
 
                for (int i = 0; i < MenuItems.Length; i++)
                {
                    var item = MenuItems[i];
                    int itemPadding = (int)Math.Floor((UIWidth - item.DisplayName.Length) / 2.0);
                    string centeredItem = item.DisplayName.PadLeft(item.DisplayName.Length + itemPadding).PadRight(UIWidth - 2);
 
                    if (i == selectedIndex)
                    {
                        string centeredItemFocus = centeredItem;
                        Console.WriteLine($"{color.BorderColor}{GetBorderChar("Vertical")}{centeredItemFocus}{color.BorderColor}{GetBorderChar("Vertical")}{color.Reset}");
                    }
                    else
                    {
                        Console.WriteLine($"{color.BorderColor}{GetBorderChar("Vertical")}{color.MenuItemColor}{centeredItem}{color.BorderColor}{GetBorderChar("Vertical")}{color.Reset}");
                    }
                }
 
                int detailsTitlePadding = (int)Math.Floor((UIWidth - MenuItemDescriptionHeader.Length) / 2.0);
                int itemInfoPadding = (int)Math.Floor((UIWidth - MenuItems[selectedIndex].Description.Length) / 2.0);
                string centeredInfoTag = MenuItemDescriptionHeader.PadLeft(MenuItemDescriptionHeader.Length + detailsTitlePadding).PadRight(UIWidth - 2);
                string centeredInfo = MenuItems[selectedIndex].Description.PadLeft(MenuItems[selectedIndex].Description.Length + itemInfoPadding).PadRight(UIWidth - 2);
 
                string LineInfoHeader = $"{color.BorderColor}{GetBorderChar("Vertical")}{color.DescriptionHeaderColor}{centeredInfoTag}{color.BorderColor}{GetBorderChar("Vertical")}{color.Reset}";
                string LineInfo = $"{color.BorderColor}{GetBorderChar("Vertical")}{color.MenuItemDescriptionColor}{centeredInfo}{color.BorderColor}{GetBorderChar("Vertical")}{color.Reset}";
 
                Console.WriteLine(LineEmpty);
                Console.WriteLine(LineBorderSeparator);
                Console.WriteLine(LineInfoHeader);
                Console.WriteLine(LineBorderSeparator);
                Console.WriteLine(LineEmpty);
                Console.WriteLine(LineInfo);
                Console.WriteLine(LineEmpty);
                Console.WriteLine(LineBorderSeparator);
                Console.WriteLine(LineFullBlock);
                Console.WriteLine(LineBorderSeparator);
                Console.WriteLine(LineEmpty);
                Console.WriteLine(LineBorderBottom);
            }
 
            Redraw();
 
            while (true)
            {
                var key = Console.ReadKey(true);
                if (key.Key == ConsoleKey.UpArrow)
                {
                    selectedIndex = (selectedIndex - 1 + MenuItems.Length) % MenuItems.Length;
                    Redraw();
                }
                else if (key.Key == ConsoleKey.DownArrow)
                {
                    selectedIndex = (selectedIndex + 1) % MenuItems.Length;
                    Redraw();
                }
                else if (key.Key == ConsoleKey.Enter)
                {
                    Console.Clear();
                    MenuItems[selectedIndex].OnConfirm?.Invoke();
                    break;
                }
            }
            Console.CursorVisible = true;
        }
    }
}