diff --git a/src/Task.Monitor.System/Controls/MessageBox/MessageBox.cs b/src/Task.Monitor.System/Controls/MessageBox/MessageBox.cs index eb8db96..6e0f568 100644 --- a/src/Task.Monitor.System/Controls/MessageBox/MessageBox.cs +++ b/src/Task.Monitor.System/Controls/MessageBox/MessageBox.cs @@ -1,5 +1,6 @@ using System.Drawing; using Task.Monitor.Cli.Utils; +using Task.Monitor.System.Screens; namespace Task.Monitor.System.Controls.MessageBox; @@ -14,15 +15,16 @@ public sealed class MessageBox : Control private bool okFocused = true; - // TODO: Theme. - private Color dialogColour = ConsolePalette.Gray; - private Color dialogShadowColour = ConsolePalette.DarkGray; - private Color dialogTitleColour = ConsolePalette.White; - public MessageBox(ISystemTerminal terminal) : base(terminal) { } public MessageBoxButtons Buttons { get; set; } = MessageBoxButtons.OkCancel; + public Color DialogBackgroundColour { get; set; } = ConsolePalette.Gray; + public Color DialogBorderColour { get; set; } = ConsolePalette.Black; + public Color DialogButtonBackgroundColour { get; set; } = ConsolePalette.DarkGray; + public Color DialogButtonForegroundColour { get; set; } = ConsolePalette.Black; + public Color DialogForegroundColour { get; set; } = ConsolePalette.Black; + private void DrawButton( int x, int y, @@ -38,11 +40,11 @@ private void DrawButton( y, width, height, - dialogTitleColour); + DialogBackgroundColour); string centredText = text.CentreWithLength(width); - Terminal.BackgroundColor = dialogTitleColour; - Terminal.ForegroundColor = ConsolePalette.Black; + Terminal.BackgroundColor = DialogButtonBackgroundColour; + Terminal.ForegroundColor = DialogButtonForegroundColour; Terminal.SetCursorPosition(x, y); @@ -58,7 +60,7 @@ private void DrawButton( if (isHighlightChar && selected) { Terminal.ForegroundColor = ConsolePalette.Red; Terminal.Write(ch); - Terminal.ForegroundColor = ConsolePalette.Black; + Terminal.ForegroundColor = DialogButtonForegroundColour; isHighlightChar = false; continue; } @@ -75,51 +77,51 @@ protected override void OnDraw() } using TerminalColourRestorer _ = new(); - - DrawRectangle( - X + 1, - Y + 1, - Width, - Height, - dialogShadowColour); DrawRectangle( X, Y, Width, Height, - dialogColour); + DialogBackgroundColour); int y = Y; - string centredTitle = Title.CentreWithLength(Width); - Terminal.BackgroundColor = dialogTitleColour; - Terminal.ForegroundColor = ConsolePalette.Black; + int dialogWidth = Width - 2; + string title = Title.Length > 0 ? $" {Title} " : string.Empty; + int titleLen = Math.Min(title.Length, dialogWidth); + int leftDashes = (dialogWidth - titleLen) / 2; + int rightDashes = dialogWidth - titleLen - leftDashes; + + Terminal.BackgroundColor = DialogBackgroundColour; + Terminal.ForegroundColor = DialogForegroundColour; Terminal.SetCursorPosition(X, y); - Terminal.Write(centredTitle); + Terminal.Write('\u256D'); + Terminal.Write('\u2500', leftDashes); + Terminal.Write(titleLen < title.Length ? title[..titleLen] : title); + Terminal.Write('\u2500', rightDashes); + Terminal.Write('\u256E'); - string spacer = new(' ', Width); - Terminal.BackgroundColor = dialogColour; - Terminal.ForegroundColor = ConsolePalette.Black; + string spacer = new(' ', dialogWidth); Terminal.SetCursorPosition(X, ++y); - Terminal.Write(spacer); - + Terminal.Write($"\u2502{spacer}\u2502"); + string[] lines = Text.Split('\n'); for (int n = 0; n < MaxTextLines; n++) { Terminal.SetCursorPosition(X, ++y); if (n < lines.Length) { - Terminal.Write(lines[n].CentreWithLength(Width)); + Terminal.Write($"\u2502{lines[n].CentreWithLength(dialogWidth)}\u2502"); continue; } - Terminal.Write(spacer); + Terminal.Write($"\u2502{spacer}\u2502"); } for (int n = 0; n < 2; n++) { Terminal.SetCursorPosition(X, ++y); - Terminal.Write(spacer); + Terminal.Write($"\u2502{spacer}\u2502"); } int buttonX = Buttons == MessageBoxButtons.Ok @@ -127,6 +129,8 @@ protected override void OnDraw() : X + (Width / 2 - (ButtonWidth + ButtonGap + ButtonWidth) / 2); int buttonY = ++y; + Terminal.SetCursorPosition(X, buttonY); + Terminal.Write($"\u2502{spacer}\u2502"); if (Buttons == MessageBoxButtons.Ok || Buttons == MessageBoxButtons.OkCancel) { DrawButton( @@ -148,14 +152,19 @@ protected override void OnDraw() selected: !okFocused); } - Terminal.BackgroundColor = dialogColour; - Terminal.ForegroundColor = ConsolePalette.Black; + Terminal.BackgroundColor = DialogBackgroundColour; + Terminal.ForegroundColor = DialogForegroundColour; Terminal.SetCursorPosition(X, ++y); - Terminal.Write(spacer); + Terminal.Write($"\u2502{spacer}\u2502"); string help = "Use \u2190 \u2192 and \u21B5 to select"; Terminal.SetCursorPosition(X, ++y); - Terminal.Write(help.CentreWithLength(Width)); + Terminal.Write($"\u2502{help.CentreWithLength(dialogWidth)}\u2502"); + + Terminal.SetCursorPosition(X, ++y); + Terminal.Write('\u2570'); + Terminal.Write('\u2500', dialogWidth); + Terminal.Write('\u256F'); } protected override void OnKeyPressed(ConsoleKeyInfo keyInfo, ref bool handled) diff --git a/src/Task.Monitor.System/ISystemTerminal.cs b/src/Task.Monitor.System/ISystemTerminal.cs index b36e5d5..6e4773a 100644 --- a/src/Task.Monitor.System/ISystemTerminal.cs +++ b/src/Task.Monitor.System/ISystemTerminal.cs @@ -20,6 +20,7 @@ public interface ISystemTerminal int WindowWidth { get; } int WindowHeight { get; } void Write(char ch); + void Write(char ch, int count); void Write(ReadOnlySpan chars); void Write(string message); void WriteEmptyLine(); diff --git a/src/Task.Monitor.System/Screens/Screen.cs b/src/Task.Monitor.System/Screens/Screen.cs index 785b43e..f1b5bdb 100644 --- a/src/Task.Monitor.System/Screens/Screen.cs +++ b/src/Task.Monitor.System/Screens/Screen.cs @@ -1,3 +1,4 @@ +using System.Buffers.Text; using System.Drawing; using Task.Monitor.System.Controls; using Task.Monitor.System.Controls.InputBox; @@ -40,7 +41,6 @@ public override Color BackgroundColour get => base.BackgroundColour; set { base.BackgroundColour = value; - messageBox.BackgroundColour = value; inputBox.BackgroundColour = value; } } @@ -53,6 +53,12 @@ public void Close() public bool CursorVisible { get; set; } = true; + public Color DialogBackgroundColour { get => messageBox.DialogBackgroundColour; set => messageBox.DialogBackgroundColour = value; } + public Color DialogBorderColour { get => messageBox.DialogBorderColour; set => messageBox.DialogBorderColour = value; } + public Color DialogButtonBackgroundColour { get => messageBox.DialogButtonBackgroundColour; set => messageBox.DialogButtonBackgroundColour = value; } + public Color DialogButtonForegroundColour { get => messageBox.DialogButtonForegroundColour; set => messageBox.DialogButtonForegroundColour = value; } + public Color DialogForegroundColour { get => messageBox.DialogForegroundColour; set => messageBox.DialogForegroundColour = value; } + private void Focus() { if (focusedControl != null) { @@ -87,21 +93,12 @@ public override Color ForegroundColour get => base.ForegroundColour; set { base.ForegroundColour = value; - messageBox.ForegroundColour = value; inputBox.ForegroundColour = value; } } private bool IsActive { get; set; } = false; - - protected override void OnClear() - { - base.OnClear(); - - messageBox.Clear(); - inputBox.Clear(); - } - + protected override void OnDraw() { base.OnDraw(); diff --git a/src/Task.Monitor.System/SystemTerminal.cs b/src/Task.Monitor.System/SystemTerminal.cs index 02a0968..e79e2f3 100644 --- a/src/Task.Monitor.System/SystemTerminal.cs +++ b/src/Task.Monitor.System/SystemTerminal.cs @@ -87,6 +87,14 @@ public void SetCursorPosition(int left, int top) public int WindowWidth => Console.WindowWidth; public int WindowHeight => Console.WindowHeight; public void Write(char ch) => Console.Out.Write(ch); + + public void Write(char ch, int count) + { + Span buffer = stackalloc char[count]; + buffer.Fill(ch); + Write(buffer); + } + public void Write(ReadOnlySpan chars) => Console.Out.Write(chars); public void Write(string message) => Console.Out.Write(message); public void WriteEmptyLine() => WriteEmptyLineTo(Console.WindowWidth); diff --git a/src/taskmon/Gui/MainScreen.cs b/src/taskmon/Gui/MainScreen.cs index 7c6e533..6020ddc 100644 --- a/src/taskmon/Gui/MainScreen.cs +++ b/src/taskmon/Gui/MainScreen.cs @@ -133,6 +133,12 @@ protected override void OnLoad() BackgroundColour = runContext.AppConfig.DefaultTheme.Background; ForegroundColour = runContext.AppConfig.DefaultTheme.Foreground; + + DialogBackgroundColour = runContext.AppConfig.DefaultTheme.HeaderBackground; + DialogBorderColour = runContext.AppConfig.DefaultTheme.HeaderForeground; + DialogForegroundColour = runContext.AppConfig.DefaultTheme.HeaderForeground; + DialogButtonBackgroundColour = runContext.AppConfig.DefaultTheme.BackgroundHighlight; + DialogButtonForegroundColour = runContext.AppConfig.DefaultTheme.ForegroundHighlight; foreach (Control ctrl in Controls) { ctrl.BackgroundColour = BackgroundColour; diff --git a/tests/Task.Monitor.System.Tests/Controls/ForwardingTerminal.cs b/tests/Task.Monitor.System.Tests/Controls/ForwardingTerminal.cs index b5b7c92..26fd1a3 100644 --- a/tests/Task.Monitor.System.Tests/Controls/ForwardingTerminal.cs +++ b/tests/Task.Monitor.System.Tests/Controls/ForwardingTerminal.cs @@ -27,6 +27,7 @@ public sealed class ForwardingTerminal(ISystemTerminal inner) : ISystemTerminal public ConsoleKeyInfo ReadKey() => inner.ReadKey(); public void SetCursorPosition(int left, int top) => inner.SetCursorPosition(left, top); public void Write(char ch) => inner.Write(ch); + public void Write(char ch, int count) => inner.Write(ch, count); public void Write(string message) => inner.Write(message); public void WriteEmptyLine() => inner.WriteEmptyLine(); public void WriteEmptyLineTo(int x) => inner.WriteEmptyLineTo(x); diff --git a/tests/Task.Monitor.System.Tests/Controls/MessageBox/MessageBoxTests.cs b/tests/Task.Monitor.System.Tests/Controls/MessageBox/MessageBoxTests.cs index 6e04d02..755e770 100644 --- a/tests/Task.Monitor.System.Tests/Controls/MessageBox/MessageBoxTests.cs +++ b/tests/Task.Monitor.System.Tests/Controls/MessageBox/MessageBoxTests.cs @@ -11,7 +11,7 @@ public sealed class MessageBoxTests { [Fact] public void MessageBox_Canary_Test() => - Assert.Equal(15, CanaryTestHelper.GetPropertyCount()); + Assert.Equal(20, CanaryTestHelper.GetPropertyCount()); [Fact] public void Should_Construct_Default() @@ -20,10 +20,15 @@ public void Should_Construct_Default() MessageBoxControl control = new(new ForwardingTerminal(terminal.Object)); Assert.Equal(ConsolePalette.Black, control.BackgroundColour); + Assert.Equal(MessageBoxButtons.OkCancel, control.Buttons); Assert.Empty(control.Controls); + Assert.Equal(ConsolePalette.Gray, control.DialogBackgroundColour); + Assert.Equal(ConsolePalette.Black, control.DialogBorderColour); + Assert.Equal(ConsolePalette.DarkGray, control.DialogButtonBackgroundColour); + Assert.Equal(ConsolePalette.Black, control.DialogButtonForegroundColour); + Assert.Equal(ConsolePalette.Black, control.DialogForegroundColour); Assert.Equal(ConsolePalette.White, control.ForegroundColour); Assert.Equal(0, control.Height); - Assert.Equal(MessageBoxButtons.OkCancel, control.Buttons); Assert.NotNull(control.Name); Assert.Equal(MessageBoxResult.None, control.Result); Assert.True(0 == control.TabIndex); @@ -48,6 +53,11 @@ public void Should_Set_Initial_Properties() MessageBoxControl control = new(new ForwardingTerminal(terminal.Object)) { BackgroundColour = ConsolePalette.Gray, + DialogBackgroundColour = ConsolePalette.Green, + DialogBorderColour = ConsolePalette.Yellow, + DialogButtonBackgroundColour = ConsolePalette.Magenta, + DialogButtonForegroundColour = ConsolePalette.Red, + DialogForegroundColour = ConsolePalette.DarkBlue, ForegroundColour = ConsolePalette.Black, Buttons = MessageBoxButtons.OkCancel, Height = 12, @@ -60,6 +70,11 @@ public void Should_Set_Initial_Properties() }; Assert.Equal(ConsolePalette.Gray, control.BackgroundColour); + Assert.Equal(ConsolePalette.Green, control.DialogBackgroundColour); + Assert.Equal(ConsolePalette.Yellow, control.DialogBorderColour); + Assert.Equal(ConsolePalette.Magenta, control.DialogButtonBackgroundColour); + Assert.Equal(ConsolePalette.Red, control.DialogButtonForegroundColour); + Assert.Equal(ConsolePalette.DarkBlue, control.DialogForegroundColour); Assert.Equal(ConsolePalette.Black, control.ForegroundColour); Assert.True(control.Buttons == MessageBoxButtons.OkCancel); Assert.Equal(12, control.Height); diff --git a/tests/Task.Monitor.System.Tests/Controls/RecordingTerminal.cs b/tests/Task.Monitor.System.Tests/Controls/RecordingTerminal.cs index 0cfb63e..a62e2ba 100644 --- a/tests/Task.Monitor.System.Tests/Controls/RecordingTerminal.cs +++ b/tests/Task.Monitor.System.Tests/Controls/RecordingTerminal.cs @@ -40,6 +40,12 @@ public void Write(char ch) output.Append(ch); } + public void Write(char ch, int count) + { + WriteCharCalls++; + output.Append(new string(ch, count)); + } + public void Write(string message) { WriteStringCalls++; diff --git a/tests/Task.Monitor.System.Tests/Screens/ScreenTests.cs b/tests/Task.Monitor.System.Tests/Screens/ScreenTests.cs index 00c7e8a..49f540b 100644 --- a/tests/Task.Monitor.System.Tests/Screens/ScreenTests.cs +++ b/tests/Task.Monitor.System.Tests/Screens/ScreenTests.cs @@ -14,7 +14,7 @@ public class TestScreen2(ISystemTerminal systemTerminal) : Screen(systemTerminal [Fact] public void InputBox_Canary_Test() => - Assert.Equal(12, CanaryTestHelper.GetPropertyCount()); + Assert.Equal(17, CanaryTestHelper.GetPropertyCount()); [Fact] public void Should_Construct_Default() @@ -25,6 +25,11 @@ public void Should_Construct_Default() Assert.Equal(ConsolePalette.Black, testScreen.BackgroundColour); Assert.Empty(testScreen.Controls); Assert.True(testScreen.CursorVisible); + Assert.Equal(ConsolePalette.Gray, testScreen.DialogBackgroundColour); + Assert.Equal(ConsolePalette.Black, testScreen.DialogBorderColour); + Assert.Equal(ConsolePalette.DarkGray, testScreen.DialogButtonBackgroundColour); + Assert.Equal(ConsolePalette.Black, testScreen.DialogButtonForegroundColour); + Assert.Equal(ConsolePalette.Gray, testScreen.DialogBackgroundColour); Assert.Equal(ConsolePalette.White, testScreen.ForegroundColour); Assert.Equal(0, testScreen.Height); Assert.NotNull(testScreen.Name); diff --git a/tests/Task.Monitor.Tests/Gui/HelpScreenTests.cs b/tests/Task.Monitor.Tests/Gui/HelpScreenTests.cs index b460467..d9bf16d 100644 --- a/tests/Task.Monitor.Tests/Gui/HelpScreenTests.cs +++ b/tests/Task.Monitor.Tests/Gui/HelpScreenTests.cs @@ -20,7 +20,7 @@ public HelpScreenTests() [Fact] public void HelpScreen_Canary_Test() => - Assert.Equal(12, CanaryTestHelper.GetPropertyCount()); + Assert.Equal(17, CanaryTestHelper.GetPropertyCount()); [Fact] public void Constructor_With_Valid_Run_Context_Initialises_Successfully() @@ -42,6 +42,11 @@ public void Default_Properties_After_Construction_Have_Default_Values() Assert.Equal(ConsolePalette.Black, helpScreen.BackgroundColour); Assert.Empty(helpScreen.Controls); Assert.True(helpScreen.CursorVisible); + Assert.Equal(ConsolePalette.Gray, helpScreen.DialogBackgroundColour); + Assert.Equal(ConsolePalette.Black, helpScreen.DialogBorderColour); + Assert.Equal(ConsolePalette.DarkGray, helpScreen.DialogButtonBackgroundColour); + Assert.Equal(ConsolePalette.Black, helpScreen.DialogButtonForegroundColour); + Assert.Equal(ConsolePalette.Gray, helpScreen.DialogBackgroundColour); Assert.Equal(ConsolePalette.White, helpScreen.ForegroundColour); Assert.Equal(0, helpScreen.Height); Assert.NotNull(helpScreen.Name); diff --git a/tests/Task.Monitor.Tests/Gui/MainScreenTests.cs b/tests/Task.Monitor.Tests/Gui/MainScreenTests.cs index 3be6d18..ce5695c 100644 --- a/tests/Task.Monitor.Tests/Gui/MainScreenTests.cs +++ b/tests/Task.Monitor.Tests/Gui/MainScreenTests.cs @@ -21,7 +21,7 @@ public MainScreenTests() [Fact] public void MainScreen_Canary_Test() => - Assert.Equal(12, CanaryTestHelper.GetPropertyCount()); + Assert.Equal(17, CanaryTestHelper.GetPropertyCount()); [Fact] public void Constructor_With_Valid_Run_Context_Initialises_Successfully() @@ -47,6 +47,11 @@ public void Default_Properties_After_Construction_Have_Default_Values() Assert.Equal(ConsolePalette.Black, mainScreen.BackgroundColour); Assert.NotEmpty(mainScreen.Controls); Assert.True(mainScreen.CursorVisible); + Assert.Equal(ConsolePalette.Gray, mainScreen.DialogBackgroundColour); + Assert.Equal(ConsolePalette.Black, mainScreen.DialogBorderColour); + Assert.Equal(ConsolePalette.DarkGray, mainScreen.DialogButtonBackgroundColour); + Assert.Equal(ConsolePalette.Black, mainScreen.DialogButtonForegroundColour); + Assert.Equal(ConsolePalette.Gray, mainScreen.DialogBackgroundColour); Assert.Equal(ConsolePalette.White, mainScreen.ForegroundColour); Assert.Equal(0, mainScreen.Height); Assert.NotNull(mainScreen.Name); diff --git a/tests/Task.Monitor.Tests/Gui/SetupScreenTests.cs b/tests/Task.Monitor.Tests/Gui/SetupScreenTests.cs index 6ebeee8..73d163a 100644 --- a/tests/Task.Monitor.Tests/Gui/SetupScreenTests.cs +++ b/tests/Task.Monitor.Tests/Gui/SetupScreenTests.cs @@ -21,7 +21,7 @@ public SetupScreenTests() [Fact] public void SetupScreen_Canary_Test() => - Assert.Equal(12, CanaryTestHelper.GetPropertyCount()); + Assert.Equal(17, CanaryTestHelper.GetPropertyCount()); [Fact] public void Constructor_With_Valid_Run_Context_Initialises_Successfully() @@ -43,6 +43,11 @@ public void Default_Properties_After_Construction_Have_Default_Values() Assert.Equal(ConsolePalette.Black, setupScreen.BackgroundColour); Assert.NotEmpty(setupScreen.Controls); Assert.True(setupScreen.CursorVisible); + Assert.Equal(ConsolePalette.Gray, setupScreen.DialogBackgroundColour); + Assert.Equal(ConsolePalette.Black, setupScreen.DialogBorderColour); + Assert.Equal(ConsolePalette.DarkGray, setupScreen.DialogButtonBackgroundColour); + Assert.Equal(ConsolePalette.Black, setupScreen.DialogButtonForegroundColour); + Assert.Equal(ConsolePalette.Gray, setupScreen.DialogBackgroundColour); Assert.Equal(ConsolePalette.White, setupScreen.ForegroundColour); Assert.Equal(0, setupScreen.Height); Assert.NotNull(setupScreen.Name);