parent
a6377d1a57
commit
d0853e23bc
@ -0,0 +1,39 @@
|
|||||||
|
using System.Diagnostics;
|
||||||
|
|
||||||
|
namespace SCI.AsciiArt;
|
||||||
|
|
||||||
|
public class Generator {
|
||||||
|
public static async Task<string> FromImage (string imagePath, int width) {
|
||||||
|
// Ensure image exists
|
||||||
|
if (!File.Exists (imagePath)) {
|
||||||
|
throw new FileNotFoundException ($"The specified file '{imagePath}' does not exist");
|
||||||
|
}
|
||||||
|
|
||||||
|
var process = new Process ();
|
||||||
|
process.StartInfo = new ProcessStartInfo () {
|
||||||
|
FileName = "jp2a",
|
||||||
|
Arguments = $"--width={width} \"{imagePath}\"",
|
||||||
|
RedirectStandardInput = true,
|
||||||
|
RedirectStandardOutput = true,
|
||||||
|
RedirectStandardError = true,
|
||||||
|
CreateNoWindow = true,
|
||||||
|
UseShellExecute = false
|
||||||
|
};
|
||||||
|
|
||||||
|
process.Start ();
|
||||||
|
|
||||||
|
// Wait up to one second for the task to finish
|
||||||
|
try {
|
||||||
|
var cancellationTokenSource = new CancellationTokenSource (1000);
|
||||||
|
await process.WaitForExitAsync (cancellationTokenSource.Token);
|
||||||
|
} catch (TaskCanceledException) {
|
||||||
|
throw new TimeoutException ("jp2a did not finish after 1000ms, process was killed");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (process.ExitCode != 0) {
|
||||||
|
throw new Exception ($"jp2a returned with exit code {process.ExitCode}.\n{process.StandardError.ReadToEnd ()}");
|
||||||
|
}
|
||||||
|
|
||||||
|
return await process.StandardOutput.ReadToEndAsync ();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,37 @@
|
|||||||
|
using Mindmagma.Curses;
|
||||||
|
|
||||||
|
namespace SCI.CursesWrapper;
|
||||||
|
|
||||||
|
public class ContentWindow : Window {
|
||||||
|
public ContentWindow (nint rootScreen, InputHandler inputHandler) :
|
||||||
|
base (
|
||||||
|
0, 1,
|
||||||
|
CursesWrapper.GetWidth (rootScreen),
|
||||||
|
CursesWrapper.GetHeight (rootScreen) - 2,
|
||||||
|
inputHandler
|
||||||
|
)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new nested child window without inner padding
|
||||||
|
/// </summary>
|
||||||
|
public Window CreateInnerWindow () {
|
||||||
|
return new Window (-1, -1, -2, -2, this) {
|
||||||
|
BorderEnabled = false
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Removes all children elements and redraws the window
|
||||||
|
/// </summary>
|
||||||
|
public void Clean () {
|
||||||
|
foreach (var window in ChildWindows.ToList ()) {
|
||||||
|
window.Destroy (true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear window and redraw
|
||||||
|
NCurses.ClearWindow (WindowId);
|
||||||
|
SetBorder (true);
|
||||||
|
Draw ();
|
||||||
|
}
|
||||||
|
}
|
@ -1,12 +0,0 @@
|
|||||||
namespace SCI.CursesWrapper;
|
|
||||||
|
|
||||||
public class InnerWindow : Window {
|
|
||||||
public InnerWindow (nint rootScreen, InputHandler inputHandler) :
|
|
||||||
base (
|
|
||||||
0, 1,
|
|
||||||
CursesWrapper.GetWidth (rootScreen),
|
|
||||||
CursesWrapper.GetHeight (rootScreen) - 2,
|
|
||||||
inputHandler
|
|
||||||
)
|
|
||||||
{ }
|
|
||||||
}
|
|
@ -0,0 +1,109 @@
|
|||||||
|
|
||||||
|
using System.Drawing;
|
||||||
|
using Mindmagma.Curses;
|
||||||
|
|
||||||
|
namespace SCI.CursesWrapper;
|
||||||
|
|
||||||
|
public class ScrollWindow : Window {
|
||||||
|
private nint _innerPadId;
|
||||||
|
public nint InnerPadId { get { return _innerPadId; }}
|
||||||
|
|
||||||
|
private Point _scrollPosition;
|
||||||
|
public Point ScrollPosition { get { return _scrollPosition; }}
|
||||||
|
|
||||||
|
private Size _padSize;
|
||||||
|
public Size PadSize { get { return _padSize; }}
|
||||||
|
|
||||||
|
public ScrollWindow (Window parentWindow, InputHandler inputHandler, int innerHeight = -1) :
|
||||||
|
base (0, 0, 0, 0, inputHandler, parentWindow)
|
||||||
|
{
|
||||||
|
var padWidth = GetUsableWidth ();
|
||||||
|
var padHeight = innerHeight;
|
||||||
|
|
||||||
|
if (padHeight == -1) {
|
||||||
|
padHeight = parentWindow.GetUsableHeight ();
|
||||||
|
}
|
||||||
|
|
||||||
|
_innerPadId = NCurses.NewPad (padHeight, padWidth);
|
||||||
|
|
||||||
|
_padSize = new Size (padWidth, padHeight);
|
||||||
|
|
||||||
|
NCurses.WindowBackground (InnerPadId, ColorSchemes.TextInputField ());
|
||||||
|
ShowPad ();
|
||||||
|
|
||||||
|
OnKeyPress += ScrollKeyHandler;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Scrolls the window up or down on up key or down key
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sender"></param>
|
||||||
|
/// <param name="e"></param>
|
||||||
|
private void ScrollKeyHandler (object sender, NCursesKeyPressEventArgs e) {
|
||||||
|
if (e.SourceWindow is null || e.SourceWindow != this) return;
|
||||||
|
|
||||||
|
if (e.KeyCode == CursesKey.UP) {
|
||||||
|
ScrollTo (ScrollPosition.X, ScrollPosition.Y - 1);
|
||||||
|
} else if (e.KeyCode == CursesKey.DOWN) {
|
||||||
|
ScrollTo (ScrollPosition.X, ScrollPosition.Y + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Scrolls the pad to the specified coordinates
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="scrollX"></param>
|
||||||
|
/// <param name="scrollY"></param>
|
||||||
|
public void ScrollTo (int scrollX, int scrollY) {
|
||||||
|
if (ParentWindow is null) return;
|
||||||
|
|
||||||
|
_scrollPosition = new Point (scrollX, scrollY);
|
||||||
|
ShowPad ();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Shows the pad the current scroll location
|
||||||
|
/// </summary>
|
||||||
|
public void ShowPad () {
|
||||||
|
if (ParentWindow is null) return;
|
||||||
|
|
||||||
|
var scrollToX = ScrollPosition.X;
|
||||||
|
var scrollToY = ScrollPosition.Y;
|
||||||
|
|
||||||
|
var viewableWidth = GetUsableWidth ();
|
||||||
|
var viewableHeight = GetUsableHeight ();
|
||||||
|
|
||||||
|
// Check for unnecessary scrolling due to small Pad size
|
||||||
|
if (PadSize.Width <= viewableWidth) {
|
||||||
|
scrollToX = 0;
|
||||||
|
}
|
||||||
|
if (PadSize.Height <= viewableHeight) {
|
||||||
|
scrollToY = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check values for upper bounds
|
||||||
|
if (scrollToX > PadSize.Width - viewableWidth) scrollToX = PadSize.Width - viewableWidth;
|
||||||
|
if (scrollToY > PadSize.Height - viewableHeight) scrollToY = PadSize.Height - viewableHeight;
|
||||||
|
|
||||||
|
// Check values for lower bounds
|
||||||
|
if (scrollToX < 0) scrollToX = 0;
|
||||||
|
if (scrollToY < 0) scrollToY = 0;
|
||||||
|
|
||||||
|
// Store potentially updated scroll coordinates
|
||||||
|
_scrollPosition = new Point (scrollToX, scrollToY);
|
||||||
|
|
||||||
|
var fromY = Position.Y;
|
||||||
|
var fromX = Position.X;
|
||||||
|
var toY = viewableHeight;
|
||||||
|
var toX = viewableWidth - 2; // TODO: Why the two? How is the geometry this wong?!
|
||||||
|
|
||||||
|
NCurses.PadRefresh (
|
||||||
|
_innerPadId,
|
||||||
|
scrollToY, scrollToX,
|
||||||
|
fromY,
|
||||||
|
fromX,
|
||||||
|
toY,
|
||||||
|
toX
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -1,8 +0,0 @@
|
|||||||
namespace ANSI_Fahrplan.Screens;
|
|
||||||
|
|
||||||
public abstract class ScrollableScreen : Screen {
|
|
||||||
|
|
||||||
public ScrollableScreen (nint rootWindow) : base (rootWindow) {}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
After Width: | Height: | Size: 16 KiB |
Loading…
Reference in new issue