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; } /// /// Scrolls the window up or down on up key or down key /// /// /// 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); } } /// /// Scrolls the pad to the specified coordinates /// /// /// public void ScrollTo (int scrollX, int scrollY) { if (ParentWindow is null) return; _scrollPosition = new Point (scrollX, scrollY); ShowPad (); } /// /// Shows the pad the current scroll location /// 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 ); } }