mirror of
https://github.com/gui-cs/Terminal.Gui.git
synced 2025-12-26 07:47:54 +01:00
Fixes #4243 - ConsoleDriverFacade.CreateClipboard now honors FakeDriver.FakeBehaviors.UseFakeClipboard (#4244)
* updatd ConsoleDriverFacade.CreateClipboard to honor FakeDriver.FakeBehaviors.UseFakeClipboard * Code cleanup of fake driver v2
This commit is contained in:
@@ -1,5 +1,4 @@
|
||||
using System.Diagnostics;
|
||||
|
||||
#nullable enable
|
||||
namespace Terminal.Gui.App;
|
||||
|
||||
/// <summary>Provides cut, copy, and paste support for the OS clipboard.</summary>
|
||||
@@ -20,10 +19,10 @@ namespace Terminal.Gui.App;
|
||||
/// </remarks>
|
||||
public static class Clipboard
|
||||
{
|
||||
private static string _contents = string.Empty;
|
||||
private static string? _contents = string.Empty;
|
||||
|
||||
/// <summary>Gets (copies from) or sets (pastes to) the contents of the OS clipboard.</summary>
|
||||
public static string Contents
|
||||
public static string? Contents
|
||||
{
|
||||
get
|
||||
{
|
||||
@@ -31,13 +30,8 @@ public static class Clipboard
|
||||
{
|
||||
if (IsSupported)
|
||||
{
|
||||
string clipData = Application.Driver?.Clipboard.GetClipboardData ();
|
||||
|
||||
if (clipData is null)
|
||||
{
|
||||
// throw new InvalidOperationException ($"{Application.Driver?.GetType ().Name}.GetClipboardData returned null instead of string.Empty");
|
||||
clipData = string.Empty;
|
||||
}
|
||||
// throw new InvalidOperationException ($"{Application.Driver?.GetType ().Name}.GetClipboardData returned null instead of string.Empty");
|
||||
string? clipData = Application.Driver?.Clipboard?.GetClipboardData () ?? string.Empty;
|
||||
|
||||
_contents = clipData;
|
||||
}
|
||||
@@ -55,12 +49,9 @@ public static class Clipboard
|
||||
{
|
||||
if (IsSupported)
|
||||
{
|
||||
if (value is null)
|
||||
{
|
||||
value = string.Empty;
|
||||
}
|
||||
value ??= string.Empty;
|
||||
|
||||
Application.Driver?.Clipboard.SetClipboardData (value);
|
||||
Application.Driver?.Clipboard?.SetClipboardData (value);
|
||||
}
|
||||
|
||||
_contents = value;
|
||||
@@ -74,126 +65,5 @@ public static class Clipboard
|
||||
|
||||
/// <summary>Returns true if the environmental dependencies are in place to interact with the OS clipboard.</summary>
|
||||
/// <remarks></remarks>
|
||||
public static bool IsSupported => Application.Driver?.Clipboard.IsSupported ?? false;
|
||||
|
||||
/// <summary>Copies the _contents of the OS clipboard to <paramref name="result"/> if possible.</summary>
|
||||
/// <param name="result">The _contents of the OS clipboard if successful, <see cref="string.Empty"/> if not.</param>
|
||||
/// <returns><see langword="true"/> the OS clipboard was retrieved, <see langword="false"/> otherwise.</returns>
|
||||
public static bool TryGetClipboardData (out string result)
|
||||
{
|
||||
if (IsSupported && Application.Driver!.Clipboard.TryGetClipboardData (out result))
|
||||
{
|
||||
_contents = result;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
result = string.Empty;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>Pastes the <paramref name="text"/> to the OS clipboard if possible.</summary>
|
||||
/// <param name="text">The text to paste to the OS clipboard.</param>
|
||||
/// <returns><see langword="true"/> the OS clipboard was set, <see langword="false"/> otherwise.</returns>
|
||||
public static bool TrySetClipboardData (string text)
|
||||
{
|
||||
if (IsSupported && Application.Driver!.Clipboard.TrySetClipboardData (text))
|
||||
{
|
||||
_contents = text;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper class for console drivers to invoke shell commands to interact with the clipboard. Used primarily by
|
||||
/// CursesDriver, but also used in Unit tests which is why it is in IConsoleDriver.cs.
|
||||
/// </summary>
|
||||
internal static class ClipboardProcessRunner
|
||||
{
|
||||
public static (int exitCode, string result) Bash (
|
||||
string commandLine,
|
||||
string inputText = "",
|
||||
bool waitForOutput = false
|
||||
)
|
||||
{
|
||||
var arguments = $"-c \"{commandLine}\"";
|
||||
(int exitCode, string result) = Process ("bash", arguments, inputText, waitForOutput);
|
||||
|
||||
return (exitCode, result.TrimEnd ());
|
||||
}
|
||||
|
||||
public static bool DoubleWaitForExit (this Process process)
|
||||
{
|
||||
bool result = process.WaitForExit (500);
|
||||
|
||||
if (result)
|
||||
{
|
||||
process.WaitForExit ();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static bool FileExists (this string value) { return !string.IsNullOrEmpty (value) && !value.Contains ("not found"); }
|
||||
|
||||
public static (int exitCode, string result) Process (
|
||||
string cmd,
|
||||
string arguments,
|
||||
string input = null,
|
||||
bool waitForOutput = true
|
||||
)
|
||||
{
|
||||
var output = string.Empty;
|
||||
|
||||
using (var process = new Process
|
||||
{
|
||||
StartInfo = new()
|
||||
{
|
||||
FileName = cmd,
|
||||
Arguments = arguments,
|
||||
RedirectStandardOutput = true,
|
||||
RedirectStandardError = true,
|
||||
RedirectStandardInput = true,
|
||||
UseShellExecute = false,
|
||||
CreateNoWindow = true
|
||||
}
|
||||
})
|
||||
{
|
||||
TaskCompletionSource<bool> eventHandled = new ();
|
||||
process.Start ();
|
||||
|
||||
if (!string.IsNullOrEmpty (input))
|
||||
{
|
||||
process.StandardInput.Write (input);
|
||||
process.StandardInput.Close ();
|
||||
}
|
||||
|
||||
if (!process.WaitForExit (5000))
|
||||
{
|
||||
var timeoutError =
|
||||
$@"Process timed out. Command line: {process.StartInfo.FileName} {process.StartInfo.Arguments}.";
|
||||
|
||||
throw new TimeoutException (timeoutError);
|
||||
}
|
||||
|
||||
if (waitForOutput && process.StandardOutput.Peek () != -1)
|
||||
{
|
||||
output = process.StandardOutput.ReadToEnd ();
|
||||
}
|
||||
|
||||
if (process.ExitCode > 0)
|
||||
{
|
||||
output = $@"Process failed to run. Command line: {cmd} {arguments}.
|
||||
Output: {output}
|
||||
Error: {process.StandardError.ReadToEnd ()}";
|
||||
}
|
||||
|
||||
return (process.ExitCode, output);
|
||||
}
|
||||
}
|
||||
}
|
||||
public static bool IsSupported => Application.Driver?.Clipboard?.IsSupported ?? false;
|
||||
}
|
||||
79
Terminal.Gui/App/Clipboard/ClipboardProcessRunner.cs
Normal file
79
Terminal.Gui/App/Clipboard/ClipboardProcessRunner.cs
Normal file
@@ -0,0 +1,79 @@
|
||||
#nullable enable
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace Terminal.Gui.App;
|
||||
|
||||
/// <summary>
|
||||
/// Helper class for console drivers to invoke shell commands to interact with the clipboard. Used primarily by
|
||||
/// CursesDriver, but also used in Unit tests which is why it is in IConsoleDriver.cs.
|
||||
/// </summary>
|
||||
internal static class ClipboardProcessRunner
|
||||
{
|
||||
public static (int exitCode, string result) Bash (
|
||||
string commandLine,
|
||||
string inputText = "",
|
||||
bool waitForOutput = false
|
||||
)
|
||||
{
|
||||
var arguments = $"-c \"{commandLine}\"";
|
||||
(int exitCode, string result) = Process ("bash", arguments, inputText, waitForOutput);
|
||||
|
||||
return (exitCode, result.TrimEnd ());
|
||||
}
|
||||
|
||||
public static bool FileExists (this string value) { return !string.IsNullOrEmpty (value) && !value.Contains ("not found"); }
|
||||
|
||||
public static (int exitCode, string result) Process (
|
||||
string cmd,
|
||||
string arguments,
|
||||
string? input = null,
|
||||
bool waitForOutput = true
|
||||
)
|
||||
{
|
||||
var output = string.Empty;
|
||||
|
||||
using var process = new Process ();
|
||||
|
||||
process.StartInfo = new()
|
||||
{
|
||||
FileName = cmd,
|
||||
Arguments = arguments,
|
||||
RedirectStandardOutput = true,
|
||||
RedirectStandardError = true,
|
||||
RedirectStandardInput = true,
|
||||
UseShellExecute = false,
|
||||
CreateNoWindow = true
|
||||
};
|
||||
|
||||
TaskCompletionSource<bool> eventHandled = new ();
|
||||
process.Start ();
|
||||
|
||||
if (!string.IsNullOrEmpty (input))
|
||||
{
|
||||
process.StandardInput.Write (input);
|
||||
process.StandardInput.Close ();
|
||||
}
|
||||
|
||||
if (!process.WaitForExit (5000))
|
||||
{
|
||||
var timeoutError =
|
||||
$@"Process timed out. Command line: {process.StartInfo.FileName} {process.StartInfo.Arguments}.";
|
||||
|
||||
throw new TimeoutException (timeoutError);
|
||||
}
|
||||
|
||||
if (waitForOutput && process.StandardOutput.Peek () != -1)
|
||||
{
|
||||
output = process.StandardOutput.ReadToEnd ();
|
||||
}
|
||||
|
||||
if (process.ExitCode > 0)
|
||||
{
|
||||
output = $@"Process failed to run. Command line: {cmd} {arguments}.
|
||||
Output: {output}
|
||||
Error: {process.StandardError.ReadToEnd ()}";
|
||||
}
|
||||
|
||||
return (process.ExitCode, output);
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
//
|
||||
#nullable enable
|
||||
//
|
||||
// FakeDriver.cs: A fake IConsoleDriver for unit tests.
|
||||
//
|
||||
|
||||
@@ -36,7 +37,7 @@ public class FakeDriver : ConsoleDriver
|
||||
public bool UseFakeClipboard { get; internal set; }
|
||||
}
|
||||
|
||||
public static Behaviors FakeBehaviors = new ();
|
||||
public static Behaviors FakeBehaviors { get; } = new ();
|
||||
public override bool SupportsTrueColor => false;
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -47,8 +48,8 @@ public class FakeDriver : ConsoleDriver
|
||||
|
||||
public FakeDriver ()
|
||||
{
|
||||
Cols = FakeConsole.WindowWidth = FakeConsole.BufferWidth = FakeConsole.WIDTH;
|
||||
Rows = FakeConsole.WindowHeight = FakeConsole.BufferHeight = FakeConsole.HEIGHT;
|
||||
base.Cols = FakeConsole.WindowWidth = FakeConsole.BufferWidth = FakeConsole.WIDTH;
|
||||
base.Rows = FakeConsole.WindowHeight = FakeConsole.BufferHeight = FakeConsole.HEIGHT;
|
||||
|
||||
if (FakeBehaviors.UseFakeClipboard)
|
||||
{
|
||||
@@ -87,7 +88,7 @@ public class FakeDriver : ConsoleDriver
|
||||
FakeConsole.Clear ();
|
||||
}
|
||||
|
||||
private FakeMainLoop _mainLoopDriver;
|
||||
private FakeMainLoop? _mainLoopDriver;
|
||||
|
||||
public override MainLoop Init ()
|
||||
{
|
||||
@@ -124,7 +125,7 @@ public class FakeDriver : ConsoleDriver
|
||||
|
||||
for (int row = top; row < rows; row++)
|
||||
{
|
||||
if (!_dirtyLines [row])
|
||||
if (!_dirtyLines! [row])
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@@ -144,7 +145,7 @@ public class FakeDriver : ConsoleDriver
|
||||
|
||||
for (; col < cols; col++)
|
||||
{
|
||||
if (!Contents [row, col].IsDirty)
|
||||
if (!Contents! [row, col].IsDirty)
|
||||
{
|
||||
if (output.Length > 0)
|
||||
{
|
||||
@@ -168,7 +169,7 @@ public class FakeDriver : ConsoleDriver
|
||||
lastCol = col;
|
||||
}
|
||||
|
||||
Attribute attr = Contents [row, col].Attribute.Value;
|
||||
Attribute attr = Contents [row, col].Attribute!.Value;
|
||||
|
||||
// Performance: Only send the escape sequence if the attribute has changed.
|
||||
if (attr != redrawAttr)
|
||||
@@ -209,18 +210,18 @@ public class FakeDriver : ConsoleDriver
|
||||
|
||||
//SetCursorVisibility (savedVisibility);
|
||||
|
||||
void WriteToConsole (StringBuilder output, ref int lastCol, int row, ref int outputWidth)
|
||||
void WriteToConsole (StringBuilder outputSb, ref int lastColumn, int row, ref int outputWidth)
|
||||
{
|
||||
FakeConsole.CursorTop = row;
|
||||
FakeConsole.CursorLeft = lastCol;
|
||||
FakeConsole.CursorLeft = lastColumn;
|
||||
|
||||
foreach (char c in output.ToString ())
|
||||
foreach (char c in outputSb.ToString ())
|
||||
{
|
||||
FakeConsole.Write (c);
|
||||
}
|
||||
|
||||
output.Clear ();
|
||||
lastCol += outputWidth;
|
||||
outputSb.Clear ();
|
||||
lastColumn += outputWidth;
|
||||
outputWidth = 0;
|
||||
}
|
||||
|
||||
@@ -506,7 +507,7 @@ public class FakeDriver : ConsoleDriver
|
||||
|
||||
public class FakeClipboard : ClipboardBase
|
||||
{
|
||||
public Exception FakeException;
|
||||
public Exception? FakeException { get; set; }
|
||||
|
||||
private readonly bool _isSupportedAlwaysFalse;
|
||||
private string _contents = string.Empty;
|
||||
@@ -536,19 +537,14 @@ public class FakeDriver : ConsoleDriver
|
||||
return _contents;
|
||||
}
|
||||
|
||||
protected override void SetClipboardDataImpl (string text)
|
||||
protected override void SetClipboardDataImpl (string? text)
|
||||
{
|
||||
if (text is null)
|
||||
{
|
||||
throw new ArgumentNullException (nameof (text));
|
||||
}
|
||||
|
||||
if (FakeException is { })
|
||||
{
|
||||
throw FakeException;
|
||||
}
|
||||
|
||||
_contents = text;
|
||||
_contents = text ?? throw new ArgumentNullException (nameof (text));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
using System.Runtime.InteropServices;
|
||||
using Microsoft.Extensions.Logging;
|
||||
#nullable enable
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Terminal.Gui.Drivers;
|
||||
|
||||
@@ -11,7 +11,7 @@ internal class ConsoleDriverFacade<T> : IConsoleDriver, IConsoleDriverFacade
|
||||
private CursorVisibility _lastCursor = CursorVisibility.Default;
|
||||
|
||||
/// <summary>The event fired when the terminal is resized.</summary>
|
||||
public event EventHandler<SizeChangedEventArgs> SizeChanged;
|
||||
public event EventHandler<SizeChangedEventArgs>? SizeChanged;
|
||||
|
||||
public IInputProcessor InputProcessor { get; }
|
||||
public IOutputBuffer OutputBuffer => _outputBuffer;
|
||||
@@ -48,6 +48,13 @@ internal class ConsoleDriverFacade<T> : IConsoleDriver, IConsoleDriverFacade
|
||||
|
||||
private void CreateClipboard ()
|
||||
{
|
||||
if (FakeDriver.FakeBehaviors.UseFakeClipboard)
|
||||
{
|
||||
Clipboard = new FakeDriver.FakeClipboard ();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
PlatformID p = Environment.OSVersion.Platform;
|
||||
|
||||
if (p == PlatformID.Win32NT || p == PlatformID.Win32S || p == PlatformID.Win32Windows)
|
||||
@@ -88,7 +95,7 @@ internal class ConsoleDriverFacade<T> : IConsoleDriver, IConsoleDriverFacade
|
||||
/// to.
|
||||
/// </summary>
|
||||
/// <value>The rectangle describing the of <see cref="Clip"/> region.</value>
|
||||
public Region Clip
|
||||
public Region? Clip
|
||||
{
|
||||
get => _outputBuffer.Clip;
|
||||
set => _outputBuffer.Clip = value;
|
||||
@@ -114,7 +121,7 @@ internal class ConsoleDriverFacade<T> : IConsoleDriver, IConsoleDriverFacade
|
||||
/// The contents of the application output. The driver outputs this buffer to the terminal.
|
||||
/// <remarks>The format of the array is rows, columns. The first index is the row, the second index is the column.</remarks>
|
||||
/// </summary>
|
||||
public Cell [,] Contents
|
||||
public Cell [,]? Contents
|
||||
{
|
||||
get => _outputBuffer.Contents;
|
||||
set => _outputBuffer.Contents = value;
|
||||
@@ -229,7 +236,7 @@ internal class ConsoleDriverFacade<T> : IConsoleDriver, IConsoleDriverFacade
|
||||
/// <summary>
|
||||
/// Raised each time <see cref="ConsoleDriver.ClearContents"/> is called. For benchmarking.
|
||||
/// </summary>
|
||||
public event EventHandler<EventArgs> ClearedContents;
|
||||
public event EventHandler<EventArgs>? ClearedContents;
|
||||
|
||||
/// <summary>
|
||||
/// Fills the specified rectangle with the specified rune, using <see cref="ConsoleDriver.CurrentAttribute"/>
|
||||
@@ -397,7 +404,7 @@ internal class ConsoleDriverFacade<T> : IConsoleDriver, IConsoleDriverFacade
|
||||
}
|
||||
|
||||
/// <summary>Event fired when a key is pressed down. This is a precursor to <see cref="ConsoleDriver.KeyUp"/>.</summary>
|
||||
public event EventHandler<Key> KeyDown;
|
||||
public event EventHandler<Key>? KeyDown;
|
||||
|
||||
/// <summary>Event fired when a key is released.</summary>
|
||||
/// <remarks>
|
||||
@@ -405,10 +412,10 @@ internal class ConsoleDriverFacade<T> : IConsoleDriver, IConsoleDriverFacade
|
||||
/// processing is
|
||||
/// complete.
|
||||
/// </remarks>
|
||||
public event EventHandler<Key> KeyUp;
|
||||
public event EventHandler<Key>? KeyUp;
|
||||
|
||||
/// <summary>Event fired when a mouse event occurs.</summary>
|
||||
public event EventHandler<MouseEventArgs> MouseEvent;
|
||||
public event EventHandler<MouseEventArgs>? MouseEvent;
|
||||
|
||||
/// <summary>Simulates a key press.</summary>
|
||||
/// <param name="keyChar">The key character.</param>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
namespace Terminal.Gui.Drivers;
|
||||
#nullable enable
|
||||
namespace Terminal.Gui.Drivers;
|
||||
|
||||
/// <summary>
|
||||
/// Interface for v2 driver abstraction layer
|
||||
|
||||
@@ -12,7 +12,7 @@ public interface IOutputBuffer
|
||||
/// <summary>
|
||||
/// The contents of the application output. The driver outputs this buffer to the terminal when UpdateScreen is called.
|
||||
/// </summary>
|
||||
Cell [,] Contents { get; set; }
|
||||
Cell [,]? Contents { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the clip rectangle that <see cref="AddRune(Rune)"/> and <see cref="AddStr(string)"/> are subject
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
#nullable enable
|
||||
using System.Drawing;
|
||||
using TerminalGuiFluentTesting;
|
||||
|
||||
namespace Terminal.Gui.Drivers;
|
||||
|
||||
#pragma warning disable CS1591
|
||||
public class FakeApplicationFactory
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates an initialized fake application which will be cleaned up when result object
|
||||
/// is disposed.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public IDisposable SetupFakeApplication ()
|
||||
{
|
||||
var cts = new CancellationTokenSource ();
|
||||
var fakeInput = new FakeNetInput (cts.Token);
|
||||
FakeOutput output = new ();
|
||||
output.Size = new (25, 25);
|
||||
|
||||
IApplication origApp = ApplicationImpl.Instance;
|
||||
|
||||
var sizeMonitor = new FakeSizeMonitor ();
|
||||
|
||||
var v2 = new ApplicationV2 (new FakeNetComponentFactory (fakeInput, output, sizeMonitor));
|
||||
|
||||
ApplicationImpl.ChangeInstance (v2);
|
||||
v2.Init (null, "v2net");
|
||||
|
||||
ConsoleDriverFacade<ConsoleKeyInfo> d = (ConsoleDriverFacade<ConsoleKeyInfo>)Application.Driver!;
|
||||
|
||||
sizeMonitor.SizeChanging += (_, e) =>
|
||||
{
|
||||
if (e.Size != null)
|
||||
{
|
||||
Size s = e.Size.Value;
|
||||
output.Size = s;
|
||||
d.OutputBuffer.SetWindowSize (s.Width, s.Height);
|
||||
}
|
||||
};
|
||||
|
||||
return new FakeApplicationLifecycle (origApp, cts);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
#nullable enable
|
||||
namespace Terminal.Gui.Drivers;
|
||||
|
||||
#pragma warning disable CS1591
|
||||
internal class FakeApplicationLifecycle (IApplication origApp, CancellationTokenSource hardStop) : IDisposable
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public void Dispose ()
|
||||
{
|
||||
hardStop.Cancel ();
|
||||
|
||||
Application.Top?.Dispose ();
|
||||
Application.Shutdown ();
|
||||
ApplicationImpl.ChangeInstance (origApp);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
#nullable enable
|
||||
namespace Terminal.Gui.Drivers;
|
||||
|
||||
#pragma warning disable CS1591
|
||||
public class FakeDriverFactory
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a new instance of <see cref="FakeDriverV2"/> using default options
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public IFakeDriverV2 Create ()
|
||||
{
|
||||
return new FakeDriverV2 (
|
||||
new (),
|
||||
new (),
|
||||
new (),
|
||||
() => DateTime.Now,
|
||||
new ());
|
||||
}
|
||||
}
|
||||
58
Tests/TerminalGuiFluentTesting/FakeDriver/FakeDriverV2.cs
Normal file
58
Tests/TerminalGuiFluentTesting/FakeDriver/FakeDriverV2.cs
Normal file
@@ -0,0 +1,58 @@
|
||||
#nullable enable
|
||||
using System.Collections.Concurrent;
|
||||
using System.Drawing;
|
||||
using TerminalGuiFluentTesting;
|
||||
|
||||
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
|
||||
|
||||
namespace Terminal.Gui.Drivers;
|
||||
|
||||
/// <summary>
|
||||
/// Implementation of <see cref="IConsoleDriver"/> that uses fake input/output.
|
||||
/// This is a lightweight alternative to <see cref="GuiTestContext"/> (if you don't
|
||||
/// need the entire application main loop running).
|
||||
/// </summary>
|
||||
internal class FakeDriverV2 : ConsoleDriverFacade<ConsoleKeyInfo>, IFakeDriverV2
|
||||
{
|
||||
internal FakeDriverV2 (
|
||||
ConcurrentQueue<ConsoleKeyInfo> inputBuffer,
|
||||
OutputBuffer outputBuffer,
|
||||
FakeOutput fakeOutput,
|
||||
Func<DateTime> datetimeFunc,
|
||||
FakeSizeMonitor sizeMonitor
|
||||
) :
|
||||
base (
|
||||
new NetInputProcessor (inputBuffer),
|
||||
outputBuffer,
|
||||
fakeOutput,
|
||||
new (new AnsiResponseParser (), datetimeFunc),
|
||||
sizeMonitor)
|
||||
{
|
||||
FakeOutput fakeOutput1;
|
||||
InputBuffer = inputBuffer;
|
||||
SizeMonitor = sizeMonitor;
|
||||
OutputBuffer = outputBuffer;
|
||||
ConsoleOutput = fakeOutput1 = fakeOutput;
|
||||
|
||||
SizeChanged += (_, e) =>
|
||||
{
|
||||
if (e.Size != null)
|
||||
{
|
||||
Size s = e.Size.Value;
|
||||
fakeOutput1.Size = s;
|
||||
OutputBuffer.SetWindowSize (s.Width, s.Height);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public void SetBufferSize (int width, int height)
|
||||
{
|
||||
SizeMonitor.RaiseSizeChanging (new (width, height));
|
||||
OutputBuffer.SetWindowSize (width, height);
|
||||
}
|
||||
|
||||
public IConsoleOutput ConsoleOutput { get; }
|
||||
public ConcurrentQueue<ConsoleKeyInfo> InputBuffer { get; }
|
||||
public new OutputBuffer OutputBuffer { get; }
|
||||
public FakeSizeMonitor SizeMonitor { get; }
|
||||
}
|
||||
20
Tests/TerminalGuiFluentTesting/FakeDriver/FakeSizeMonitor.cs
Normal file
20
Tests/TerminalGuiFluentTesting/FakeDriver/FakeSizeMonitor.cs
Normal file
@@ -0,0 +1,20 @@
|
||||
#nullable enable
|
||||
using System.Drawing;
|
||||
|
||||
namespace Terminal.Gui.Drivers;
|
||||
|
||||
#pragma warning disable CS1591
|
||||
public class FakeSizeMonitor : IWindowSizeMonitor
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public event EventHandler<SizeChangedEventArgs>? SizeChanging;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public bool Poll () { return false; }
|
||||
|
||||
/// <summary>
|
||||
/// Raises the <see cref="SizeChanging"/> event.
|
||||
/// </summary>
|
||||
/// <param name="newSize"></param>
|
||||
public void RaiseSizeChanging (Size newSize) { SizeChanging?.Invoke (this, new (newSize)); }
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
#nullable enable
|
||||
namespace Terminal.Gui.Drivers;
|
||||
|
||||
#pragma warning disable CS1591
|
||||
public interface IFakeDriverV2 : IConsoleDriver, IConsoleDriverFacade
|
||||
{
|
||||
void SetBufferSize (int width, int height);
|
||||
}
|
||||
@@ -1,159 +0,0 @@
|
||||
using System.Collections.Concurrent;
|
||||
using System.Drawing;
|
||||
using TerminalGuiFluentTesting;
|
||||
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
|
||||
|
||||
namespace Terminal.Gui.Drivers;
|
||||
|
||||
public class FakeApplicationFactory
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates an initialized fake application which will be cleaned up when result object
|
||||
/// is disposed.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public IDisposable SetupFakeApplication ()
|
||||
{
|
||||
var cts = new CancellationTokenSource ();
|
||||
var fakeInput = new FakeNetInput (cts.Token);
|
||||
FakeOutput output = new ();
|
||||
output.Size = new (25, 25);
|
||||
|
||||
|
||||
IApplication origApp = ApplicationImpl.Instance;
|
||||
|
||||
var sizeMonitor = new FakeSizeMonitor ();
|
||||
|
||||
var v2 = new ApplicationV2 (new FakeNetComponentFactory (fakeInput, output, sizeMonitor));
|
||||
|
||||
ApplicationImpl.ChangeInstance (v2);
|
||||
v2.Init (null,"v2net");
|
||||
|
||||
var d = (ConsoleDriverFacade<ConsoleKeyInfo>)Application.Driver!;
|
||||
sizeMonitor.SizeChanging += (_, e) =>
|
||||
{
|
||||
if (e.Size != null)
|
||||
{
|
||||
var s = e.Size.Value;
|
||||
output.Size = s;
|
||||
d.OutputBuffer.SetWindowSize (s.Width, s.Height);
|
||||
}
|
||||
};
|
||||
|
||||
return new FakeApplicationLifecycle (origApp,cts);
|
||||
}
|
||||
}
|
||||
|
||||
class FakeApplicationLifecycle : IDisposable
|
||||
{
|
||||
private readonly IApplication _origApp;
|
||||
private readonly CancellationTokenSource _hardStop;
|
||||
|
||||
public FakeApplicationLifecycle (IApplication origApp, CancellationTokenSource hardStop)
|
||||
{
|
||||
_origApp = origApp;
|
||||
_hardStop = hardStop;
|
||||
}
|
||||
/// <inheritdoc />
|
||||
public void Dispose ()
|
||||
{
|
||||
_hardStop.Cancel();
|
||||
|
||||
Application.Top?.Dispose ();
|
||||
Application.Shutdown ();
|
||||
ApplicationImpl.ChangeInstance (_origApp);
|
||||
}
|
||||
}
|
||||
|
||||
public class FakeDriverFactory
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a new instance of <see cref="FakeDriverV2"/> using default options
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public IFakeDriverV2 Create ()
|
||||
{
|
||||
return new FakeDriverV2 (
|
||||
new ConcurrentQueue<ConsoleKeyInfo> (),
|
||||
new OutputBuffer (),
|
||||
new FakeOutput (),
|
||||
() => DateTime.Now,
|
||||
new FakeSizeMonitor ());
|
||||
}
|
||||
}
|
||||
|
||||
public interface IFakeDriverV2 : IConsoleDriver, IConsoleDriverFacade
|
||||
{
|
||||
void SetBufferSize (int width, int height);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Implementation of <see cref="IConsoleDriver"/> that uses fake input/output.
|
||||
/// This is a lightweight alternative to <see cref="GuiTestContext"/> (if you don't
|
||||
/// need the entire application main loop running).
|
||||
/// </summary>
|
||||
class FakeDriverV2 : ConsoleDriverFacade<ConsoleKeyInfo>, IFakeDriverV2
|
||||
{
|
||||
public ConcurrentQueue<ConsoleKeyInfo> InputBuffer { get; }
|
||||
public FakeSizeMonitor SizeMonitor { get; }
|
||||
public new OutputBuffer OutputBuffer { get; }
|
||||
|
||||
public IConsoleOutput ConsoleOutput { get; }
|
||||
|
||||
private FakeOutput _fakeOutput;
|
||||
|
||||
internal FakeDriverV2 (
|
||||
ConcurrentQueue<ConsoleKeyInfo> inputBuffer,
|
||||
OutputBuffer outputBuffer,
|
||||
FakeOutput fakeOutput,
|
||||
Func<DateTime> datetimeFunc,
|
||||
FakeSizeMonitor sizeMonitor) :
|
||||
base (new NetInputProcessor (inputBuffer),
|
||||
outputBuffer,
|
||||
fakeOutput,
|
||||
new (new AnsiResponseParser (), datetimeFunc),
|
||||
sizeMonitor)
|
||||
{
|
||||
InputBuffer = inputBuffer;
|
||||
SizeMonitor = sizeMonitor;
|
||||
OutputBuffer = outputBuffer;
|
||||
ConsoleOutput = _fakeOutput = fakeOutput;
|
||||
SizeChanged += (_, e) =>
|
||||
{
|
||||
if (e.Size != null)
|
||||
{
|
||||
var s = e.Size.Value;
|
||||
_fakeOutput.Size = s;
|
||||
OutputBuffer.SetWindowSize (s.Width,s.Height);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
public void SetBufferSize (int width, int height)
|
||||
{
|
||||
SizeMonitor.RaiseSizeChanging (new Size (width,height));
|
||||
OutputBuffer.SetWindowSize (width,height);
|
||||
}
|
||||
}
|
||||
|
||||
public class FakeSizeMonitor : IWindowSizeMonitor
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public event EventHandler<SizeChangedEventArgs>? SizeChanging;
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool Poll ()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Raises the <see cref="SizeChanging"/> event.
|
||||
/// </summary>
|
||||
/// <param name="newSize"></param>
|
||||
public void RaiseSizeChanging (Size newSize)
|
||||
{
|
||||
SizeChanging?.Invoke (this,new (newSize));
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,7 @@ namespace TerminalGuiFluentTesting;
|
||||
|
||||
internal class FakeOutput : IConsoleOutput
|
||||
{
|
||||
public IOutputBuffer LastBuffer { get; set; }
|
||||
public IOutputBuffer? LastBuffer { get; set; }
|
||||
public Size Size { get; set; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
|
||||
Reference in New Issue
Block a user