Browse Source

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

Miguel de Icaza 7 years ago
parent
commit
171b1430c1
6 changed files with 322 additions and 21 deletions
  1. 23 7
      Terminal.Gui/Core.cs
  2. 215 10
      Terminal.Gui/Driver.cs
  3. 3 2
      Terminal.Gui/Views/Dialog.cs
  4. 1 1
      Terminal.Gui/Views/Menu.cs
  5. 79 0
      Terminal.Gui/Views/ScrollView.cs
  6. 1 1
      demo.cs

+ 23 - 7
Terminal.Gui/Core.cs

@@ -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);

+ 215 - 10
Terminal.Gui/Driver.cs

@@ -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();
+		}
+	}
 }

+ 3 - 2
Terminal.Gui/Views/Dialog.cs

@@ -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;
 

+ 1 - 1
Terminal.Gui/Views/Menu.cs

@@ -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];

+ 79 - 0
Terminal.Gui/Views/ScrollView.cs

@@ -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);
+		}
 	}
 }

+ 1 - 1
demo.cs

@@ -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;
 	}