Start of a System.Console driver, needs xplat MainLoop support first; Dialogs have padding, some work on ScrollView

This commit is contained in:
Miguel de Icaza
2018-01-19 21:57:18 -05:00
parent 8eb4949cbc
commit 171b1430c1
6 changed files with 322 additions and 21 deletions

View File

@@ -444,13 +444,14 @@ namespace Terminal.Gui {
/// Draws a frame in the current view, clipped by the boundary of this view
/// </summary>
/// <param name="rect">Rectangular region for the frame to be drawn.</param>
/// <param name="padding">The padding to add to the drawn frame.</param>
/// <param name="fill">If set to <c>true</c> it fill will the contents.</param>
public void DrawFrame (Rect rect, bool fill = false)
public void DrawFrame (Rect rect, int padding = 0, bool fill = false)
{
var scrRect = RectToScreen (rect);
var savedClip = Driver.Clip;
Driver.Clip = ScreenClip (RectToScreen (Bounds));
Driver.DrawFrame (scrRect, fill);
Driver.DrawFrame (scrRect, padding, fill);
Driver.Clip = savedClip;
}
@@ -933,10 +934,25 @@ namespace Terminal.Gui {
/// </summary>
/// <param name="frame">Frame.</param>
/// <param name="title">Title.</param>
public Window (Rect frame, string title = null) : base (frame)
public Window (Rect frame, string title = null) : this (frame, title, padding: 0)
{
}
int padding;
/// <summary>
/// Initializes a new instance of the <see cref="T:Terminal.Window"/> with
/// the specified frame for its location, with the specified border
/// an optional title.
/// </summary>
/// <param name="frame">Frame.</param>
/// <param name="padding">Number of characters to use for padding of the drawn frame.</param>
/// <param name="title">Title.</param>
public Window (Rect frame, string title = null, int padding = 0) : base (frame)
{
this.Title = title;
var cFrame = new Rect (1, 1, frame.Width - 2, frame.Height - 2);
int wb = 2 * (1 + padding);
this.padding = padding;
var cFrame = new Rect (1 + padding, 1 + padding, frame.Width - wb, frame.Height - wb);
contentView = new ContentView (cFrame);
base.Add (contentView);
}
@@ -952,7 +968,7 @@ namespace Terminal.Gui {
void DrawFrame ()
{
DrawFrame (new Rect (0, 0, Frame.Width, Frame.Height), true);
DrawFrame (new Rect (0, 0, Frame.Width, Frame.Height), padding, fill: true);
}
/// <summary>
@@ -973,7 +989,7 @@ namespace Terminal.Gui {
Driver.SetAttribute (ColorScheme.Normal);
var width = Frame.Width;
if (Title != null && width > 4) {
Move (1, 0);
Move (1+padding, padding);
Driver.AddCh (' ');
var str = Title.Length > width ? Title.Substring (0, width - 4) : Title;
Driver.AddStr (str);
@@ -1397,7 +1413,7 @@ namespace Terminal.Gui {
// Need to look into why this does not work properly.
static void DrawBounds (View v)
{
v.DrawFrame (v.Frame, false);
v.DrawFrame (v.Frame, padding: 0, fill: false);
if (v.Subviews != null && v.Subviews.Count > 0)
foreach (var sub in v.Subviews)
DrawBounds (sub);

View File

@@ -222,7 +222,7 @@ namespace Terminal.Gui {
/// <param name="backgroundColorId">Background color identifier.</param>
public abstract void SetColors (short foregroundColorId, short backgroundColorId);
public abstract void DrawFrame (Rect region, bool fill);
public abstract void DrawFrame (Rect region, int padding, bool fill);
/// <summary>
/// Draws a special characters in the screen
/// </summary>
@@ -275,7 +275,7 @@ namespace Terminal.Gui {
}
}
static bool sync;
static bool sync = true;
public override void AddCh (int rune)
{
if (Clip.Contains (ccol, crow)) {
@@ -444,32 +444,59 @@ namespace Terminal.Gui {
}
public override void DrawFrame (Rect region, bool fill)
public override void DrawFrame (Rect region, int padding, bool fill)
{
int width = region.Width;
int height = region.Height;
int b;
int fwidth = width - padding * 2;
int fheight = height - 1 - padding;
Move (region.X, region.Y);
if (padding > 0) {
for (int l = 0; l < padding; l++)
for (b = 0; b < width; b++)
AddCh (' ');
}
Move (region.X, region.Y + padding);
for (int c = 0; c < padding; c++)
AddCh (' ');
AddCh (Curses.ACS_ULCORNER);
for (b = 0; b < width - 2; b++)
for (b = 0; b < fwidth - 2; b++)
AddCh (Curses.ACS_HLINE);
AddCh (Curses.ACS_URCORNER);
for (b = 1; b < height - 1; b++) {
for (int c = 0; c < padding; c++)
AddCh (' ');
for (b = 1+padding; b < fheight; b++) {
Move (region.X, region.Y + b);
for (int c = 0; c < padding; c++)
AddCh (' ');
AddCh (Curses.ACS_VLINE);
if (fill) {
for (int x = 1; x < width - 1; x++)
if (fill) {
for (int x = 1; x < fwidth - 1; x++)
AddCh (' ');
} else
Move (region.X + width - 1, region.Y + b);
Move (region.X + fwidth - 1, region.Y + b);
AddCh (Curses.ACS_VLINE);
for (int c = 0; c < padding; c++)
AddCh (' ');
}
Move (region.X, region.Y + height - 1);
Move (region.X, region.Y + fheight);
for (int c = 0; c < padding; c++)
AddCh (' ');
AddCh (Curses.ACS_LLCORNER);
for (b = 0; b < width - 2; b++)
for (b = 0; b < fwidth - 2; b++)
AddCh (Curses.ACS_HLINE);
AddCh (Curses.ACS_LRCORNER);
for (int c = 0; c < padding; c++)
AddCh (' ');
if (padding > 0) {
Move (region.X, region.Y + height - padding);
for (int l = 0; l < padding; l++)
for (b = 0; b < width; b++)
AddCh (' ');
}
}
Curses.Event oldMouseEvents, reportableMouseEvents;
@@ -625,4 +652,182 @@ namespace Terminal.Gui {
return true;
}
}
internal class NetDriver : ConsoleDriver {
public override int Cols => Console.WindowWidth;
public override int Rows => Console.WindowHeight;
int [,,] contents;
bool [] dirtyLine;
static int MakeColor (int fg, int bg)
{
return (fg << 16) | bg;
}
void UpdateOffscreen ()
{
int cols = Cols;
int rows = Rows;
contents = new int [cols, rows, 3];
for (int r = 0; r < rows; r++) {
for (int c = 0; c < cols; c++) {
contents [r, c, 0] = ' ';
contents [r, c, 1] = MakeColor (7, 0);
contents [r, c, 2] = 0;
}
}
dirtyLine = new bool [rows];
for (int row = 0; row < rows; row++)
dirtyLine [row] = true;
}
public NetDriver ()
{
UpdateOffscreen ();
}
// Current row, and current col, tracked by Move/AddCh only
int ccol, crow;
public override void Move (int col, int row)
{
ccol = col;
crow = row;
}
public override void AddCh (int rune)
{
if (Clip.Contains (ccol, crow)) {
contents [crow, ccol, 0] = rune;
contents [crow, ccol, 2] = 1;
}
ccol++;
if (ccol == Cols) {
ccol = 0;
if (crow + 1 < Rows)
crow++;
}
}
public override void AddSpecial (SpecialChar ch)
{
AddCh ('*');
}
public override void AddStr (string str)
{
foreach (var rune in str)
AddCh ((int)rune);
}
public override void DrawFrame(Rect region, int padding, bool fill)
{
int width = region.Width;
int height = region.Height;
int b;
Move (region.X, region.Y);
AddCh ('+');
for (b = 0; b < width - 2; b++)
AddCh ('-');
AddCh ('+');
for (b = 1; b < height - 1; b++) {
Move (region.X, region.Y + b);
AddCh ('|');
if (fill) {
for (int x = 1; x < width - 1; x++)
AddCh (' ');
} else
Move (region.X + width - 1, region.Y + b);
AddCh ('|');
}
Move (region.X, region.Y + height - 1);
AddCh ('+');
for (b = 0; b < width - 2; b++)
AddCh ('-');
AddCh ('+');
}
public override void End()
{
}
public override void Init(Action terminalResized)
{
}
public override void RedrawTop()
{
int rows = Rows;
int cols = Cols;
Console.CursorTop = 0;
Console.CursorLeft = 0;
for (int row = 0; row < rows; row++) {
dirtyLine [row] = false;
for (int col = 0; col < cols; col++) {
contents [row, col, 2] = 0;
Console.Write ((char)contents [row, col, 0]);
}
}
}
public override void Refresh()
{
int rows = Rows;
int cols = Cols;
for (int row = 0; row < rows; row++) {
if (!dirtyLine [row])
continue;
dirtyLine [row] = false;
for (int col = 0; col < cols; col++) {
if (contents [row, col, 2] != 1)
continue;
Console.CursorTop = row;
Console.CursorLeft = col;
for (; col < cols && contents [row, col, 2] == 1; col++) {
Console.Write ((char)contents [row, col, 0]);
contents [row, col, 2] = 0;
}
}
}
}
public override void StartReportingMouseMoves()
{
}
public override void StopReportingMouseMoves()
{
}
public override void Suspend()
{
}
public override void SetAttribute(Attribute c)
{
throw new NotImplementedException();
}
public override void PrepareToRun(MainLoop mainLoop, Action<KeyEvent> target, Action<MouseEvent> mouse)
{
throw new NotImplementedException();
}
public override void SetColors(ConsoleColor foreground, ConsoleColor background)
{
throw new NotImplementedException();
}
public override void SetColors(short foregroundColorId, short backgroundColorId)
{
throw new NotImplementedException();
}
}
}

View File

@@ -15,6 +15,7 @@ namespace Terminal.Gui {
/// </summary>
public class Dialog : Window {
List<Button> buttons = new List<Button> ();
const int padding = 1;
/// <summary>
/// Initializes a new instance of the <see cref="T:Terminal.Dialog"/> class with an optional set of buttons to display
@@ -23,7 +24,7 @@ namespace Terminal.Gui {
/// <param name="width">Width for the dialog.</param>
/// <param name="height">Height for the dialog.</param>
/// <param name="buttons">Optional buttons to lay out at the bottom of the dialog.</param>
public Dialog (string title, int width, int height, params Button [] buttons) : base (Application.MakeCenteredRect (new Size (width, height)), title)
public Dialog (string title, int width, int height, params Button [] buttons) : base (Application.MakeCenteredRect (new Size (width, height)), title, padding: padding)
{
ColorScheme = Colors.Dialog;
@@ -61,7 +62,7 @@ namespace Terminal.Gui {
const int borderWidth = 2;
var start = (Frame.Width-borderWidth - buttonSpace) / 2;
var y = Frame.Height - borderWidth - maxHeight;
var y = Frame.Height - borderWidth - maxHeight-1-padding;
foreach (var b in buttons) {
var bf = b.Frame;

View File

@@ -143,7 +143,7 @@ namespace Terminal.Gui {
public override void Redraw (Rect region)
{
Driver.SetAttribute (ColorScheme.Normal);
DrawFrame (region, true);
DrawFrame (region, padding: 0, fill: true);
for (int i = 0; i < barItems.Children.Length; i++){
var item = barItems.Children [i];

View File

@@ -1,8 +1,87 @@
using System;
namespace Terminal.Gui {
/// <summary>
///
/// </summary>
/// <remarks>
/// <para>
/// The subviews that are added to this scrollview are offset by the
/// ContentOffset property. The view itself is a window into the
/// space represented by the ContentSize.
/// </para>
/// <para>
///
/// </para>
/// </remarks>
public class ScrollView : View {
public ScrollView (Rect frame) : base (frame)
{
}
Rect contentSize;
Point contentOffset;
bool showHorizontalScrollIndicator;
bool showVerticalScrollIndicator;
/// <summary>
/// Represents the contents of the data shown inside the scrolview
/// </summary>
/// <value>The size of the content.</value>
public Rect ContentSize {
get {
return contentSize;
}
set {
contentSize = value;
}
}
/// <summary>
/// Represents the top left corner coordinate that is displayed by the scrollview
/// </summary>
/// <value>The content offset.</value>
public Point ContentOffset {
get {
return contentOffset;
}
set {
contentOffset = value;
}
}
/// <summary>
/// Gets or sets the visibility for the horizontal scroll indicator.
/// </summary>
/// <value><c>true</c> if show vertical scroll indicator; otherwise, <c>false</c>.</value>
public bool ShowHorizontalScrollIndicator {
get => showHorizontalScrollIndicator;
set {
showHorizontalScrollIndicator = value;
SetNeedsDisplay ();
}
}
/// <summary>
/// /// Gets or sets the visibility for the vertical scroll indicator.
/// </summary>
/// <value><c>true</c> if show vertical scroll indicator; otherwise, <c>false</c>.</value>
public bool ShowVerticalScrollIndicator {
get => showVerticalScrollIndicator;
set {
showVerticalScrollIndicator = value;
SetNeedsDisplay ();
}
}
/// <summary>
/// This event is raised when the contents have scrolled
/// </summary>
public event Action<ScrollView> Scrolled;
public override void Redraw(Rect region)
{
base.Redraw(region);
}
}
}

View File

@@ -40,7 +40,7 @@ class Demo {
static bool Quit ()
{
var n = MessageBox.Query (50, 5, "Quit Demo", "Are you sure you want to quit this demo?", "Yes", "No");
var n = MessageBox.Query (50, 7, "Quit Demo", "Are you sure you want to quit this demo?", "Yes", "No");
return n == 0;
}