diff --git a/Examples/Example/Example.cs b/Examples/Example/Example.cs index 7fab15af2..15d4b5ce9 100644 --- a/Examples/Example/Example.cs +++ b/Examples/Example/Example.cs @@ -20,6 +20,9 @@ using Terminal.Gui.Views; ConfigurationManager.RuntimeConfig = """{ "Theme": "Light" }"""; ConfigurationManager.Enable (ConfigLocations.All); +// Setup automatic key injection for testing +ExampleContextInjector.SetupAutomaticInjection (); + // Check for test context to determine driver string? contextJson = Environment.GetEnvironmentVariable (ExampleContext.ENVIRONMENT_VARIABLE_NAME); string? driverName = null; diff --git a/Examples/FluentExample/Program.cs b/Examples/FluentExample/Program.cs index 97e25c19a..4d92e6b53 100644 --- a/Examples/FluentExample/Program.cs +++ b/Examples/FluentExample/Program.cs @@ -13,6 +13,9 @@ using Terminal.Gui.Views; [assembly: ExampleDemoKeyStrokes (KeyStrokes = ["CursorDown", "CursorDown", "CursorRight", "Enter"], Order = 1)] [assembly: ExampleDemoKeyStrokes (KeyStrokes = ["Esc"], DelayMs = 100, Order = 2)] +// Setup automatic key injection for testing +ExampleContextInjector.SetupAutomaticInjection (); + // Check for test context to determine driver string? contextJson = Environment.GetEnvironmentVariable (ExampleContext.ENVIRONMENT_VARIABLE_NAME); string? driverName = null; diff --git a/Examples/RunnableWrapperExample/Program.cs b/Examples/RunnableWrapperExample/Program.cs index aedf66e54..7e575cf80 100644 --- a/Examples/RunnableWrapperExample/Program.cs +++ b/Examples/RunnableWrapperExample/Program.cs @@ -16,6 +16,9 @@ using Terminal.Gui.Views; [assembly: ExampleDemoKeyStrokes (KeyStrokes = ["Enter", "Esc"], DelayMs = 100, Order = 4)] [assembly: ExampleDemoKeyStrokes (KeyStrokes = ["Enter", "Esc"], DelayMs = 100, Order = 5)] +// Setup automatic key injection for testing +ExampleContextInjector.SetupAutomaticInjection (); + // Check for test context to determine driver string? contextJson = Environment.GetEnvironmentVariable (ExampleContext.ENVIRONMENT_VARIABLE_NAME); string? driverName = null; diff --git a/Terminal.Gui/Drivers/FakeDriver/FakeComponentFactory.cs b/Terminal.Gui/Drivers/FakeDriver/FakeComponentFactory.cs index 77fc1acdd..5b023afca 100644 --- a/Terminal.Gui/Drivers/FakeDriver/FakeComponentFactory.cs +++ b/Terminal.Gui/Drivers/FakeDriver/FakeComponentFactory.cs @@ -1,5 +1,4 @@ using System.Collections.Concurrent; -using Terminal.Gui.Examples; namespace Terminal.Gui.Drivers; @@ -29,30 +28,7 @@ public class FakeComponentFactory : ComponentFactoryImpl /// public override IInput CreateInput () { - // Use provided input instance or create a new one if none was provided - FakeInput fakeInput = _input ?? new FakeInput (); - - // Check for test context in environment variable - string? contextJson = Environment.GetEnvironmentVariable (ExampleContext.ENVIRONMENT_VARIABLE_NAME); - - if (!string.IsNullOrEmpty (contextJson)) - { - ExampleContext? context = ExampleContext.FromJson (contextJson); - - if (context is { }) - { - foreach (string keyStr in context.KeysToInject) - { - if (Key.TryParse (keyStr, out Key? key) && key is { }) - { - ConsoleKeyInfo consoleKeyInfo = ConvertKeyToConsoleKeyInfo (key); - fakeInput.AddInput (consoleKeyInfo); - } - } - } - } - - return fakeInput; + return _input ?? new FakeInput (); } /// @@ -66,105 +42,4 @@ public class FakeComponentFactory : ComponentFactoryImpl { return _sizeMonitor ?? new SizeMonitorImpl (consoleOutput); } - - private static ConsoleKeyInfo ConvertKeyToConsoleKeyInfo (Key key) - { - ConsoleModifiers modifiers = 0; - - if (key.IsShift) - { - modifiers |= ConsoleModifiers.Shift; - } - - if (key.IsAlt) - { - modifiers |= ConsoleModifiers.Alt; - } - - if (key.IsCtrl) - { - modifiers |= ConsoleModifiers.Control; - } - - // Remove the modifier masks to get the base key code - KeyCode baseKeyCode = key.KeyCode & KeyCode.CharMask; - - // Map KeyCode to ConsoleKey - ConsoleKey consoleKey = baseKeyCode switch - { - KeyCode.A => ConsoleKey.A, - KeyCode.B => ConsoleKey.B, - KeyCode.C => ConsoleKey.C, - KeyCode.D => ConsoleKey.D, - KeyCode.E => ConsoleKey.E, - KeyCode.F => ConsoleKey.F, - KeyCode.G => ConsoleKey.G, - KeyCode.H => ConsoleKey.H, - KeyCode.I => ConsoleKey.I, - KeyCode.J => ConsoleKey.J, - KeyCode.K => ConsoleKey.K, - KeyCode.L => ConsoleKey.L, - KeyCode.M => ConsoleKey.M, - KeyCode.N => ConsoleKey.N, - KeyCode.O => ConsoleKey.O, - KeyCode.P => ConsoleKey.P, - KeyCode.Q => ConsoleKey.Q, - KeyCode.R => ConsoleKey.R, - KeyCode.S => ConsoleKey.S, - KeyCode.T => ConsoleKey.T, - KeyCode.U => ConsoleKey.U, - KeyCode.V => ConsoleKey.V, - KeyCode.W => ConsoleKey.W, - KeyCode.X => ConsoleKey.X, - KeyCode.Y => ConsoleKey.Y, - KeyCode.Z => ConsoleKey.Z, - KeyCode.D0 => ConsoleKey.D0, - KeyCode.D1 => ConsoleKey.D1, - KeyCode.D2 => ConsoleKey.D2, - KeyCode.D3 => ConsoleKey.D3, - KeyCode.D4 => ConsoleKey.D4, - KeyCode.D5 => ConsoleKey.D5, - KeyCode.D6 => ConsoleKey.D6, - KeyCode.D7 => ConsoleKey.D7, - KeyCode.D8 => ConsoleKey.D8, - KeyCode.D9 => ConsoleKey.D9, - KeyCode.Enter => ConsoleKey.Enter, - KeyCode.Esc => ConsoleKey.Escape, - KeyCode.Space => ConsoleKey.Spacebar, - KeyCode.Tab => ConsoleKey.Tab, - KeyCode.Backspace => ConsoleKey.Backspace, - KeyCode.Delete => ConsoleKey.Delete, - KeyCode.Home => ConsoleKey.Home, - KeyCode.End => ConsoleKey.End, - KeyCode.PageUp => ConsoleKey.PageUp, - KeyCode.PageDown => ConsoleKey.PageDown, - KeyCode.CursorUp => ConsoleKey.UpArrow, - KeyCode.CursorDown => ConsoleKey.DownArrow, - KeyCode.CursorLeft => ConsoleKey.LeftArrow, - KeyCode.CursorRight => ConsoleKey.RightArrow, - KeyCode.F1 => ConsoleKey.F1, - KeyCode.F2 => ConsoleKey.F2, - KeyCode.F3 => ConsoleKey.F3, - KeyCode.F4 => ConsoleKey.F4, - KeyCode.F5 => ConsoleKey.F5, - KeyCode.F6 => ConsoleKey.F6, - KeyCode.F7 => ConsoleKey.F7, - KeyCode.F8 => ConsoleKey.F8, - KeyCode.F9 => ConsoleKey.F9, - KeyCode.F10 => ConsoleKey.F10, - KeyCode.F11 => ConsoleKey.F11, - KeyCode.F12 => ConsoleKey.F12, - _ => 0 - }; - - var keyChar = '\0'; - Rune rune = key.AsRune; - - if (Rune.IsValid (rune.Value)) - { - keyChar = (char)rune.Value; - } - - return new (keyChar, consoleKey, key.IsShift, key.IsAlt, key.IsCtrl); - } } diff --git a/Terminal.Gui/Examples/ExampleContextInjector.cs b/Terminal.Gui/Examples/ExampleContextInjector.cs new file mode 100644 index 000000000..a492b2017 --- /dev/null +++ b/Terminal.Gui/Examples/ExampleContextInjector.cs @@ -0,0 +1,75 @@ +namespace Terminal.Gui.Examples; + +/// +/// Handles automatic injection of test context into running examples. +/// This class monitors for the presence of an in the environment +/// and automatically injects keystrokes via after the application initializes. +/// +public static class ExampleContextInjector +{ + private static bool _initialized; + + /// + /// Sets up automatic key injection if a test context is present in the environment. + /// Call this method before calling or . + /// + /// + /// This method is safe to call multiple times - it will only set up injection once. + /// The actual key injection happens after the application is initialized, via the + /// event. + /// + public static void SetupAutomaticInjection () + { + if (_initialized) + { + return; + } + + _initialized = true; + + // Check for test context in environment variable + string? contextJson = Environment.GetEnvironmentVariable (ExampleContext.ENVIRONMENT_VARIABLE_NAME); + + if (string.IsNullOrEmpty (contextJson)) + { + return; + } + + ExampleContext? context = ExampleContext.FromJson (contextJson); + + if (context is null || context.KeysToInject.Count == 0) + { + return; + } + + // Subscribe to InitializedChanged to inject keys after initialization + Application.InitializedChanged += OnInitializedChanged; + + return; + + void OnInitializedChanged (object? sender, EventArgs e) + { + if (!e.Value) + { + return; + } + + // Application has been initialized, inject the keys + if (Application.Driver is null) + { + return; + } + + foreach (string keyStr in context.KeysToInject) + { + if (Input.Key.TryParse (keyStr, out Input.Key? key) && key is { }) + { + Application.Driver.EnqueueKeyEvent (key); + } + } + + // Unsubscribe after injecting keys once + Application.InitializedChanged -= OnInitializedChanged; + } + } +}