瀏覽代碼

Diagnostic padding and ruler

Tig Kindel 2 年之前
父節點
當前提交
214fe97bd8

+ 1 - 1
Example/Example.csproj

@@ -1,7 +1,7 @@
 <Project Sdk="Microsoft.NET.Sdk">
   <PropertyGroup>
     <OutputType>Exe</OutputType>
-    <TargetFramework>net6.0</TargetFramework>
+    <TargetFramework>net7.0</TargetFramework>
     <!-- Version numbers are automatically updated by gitversion when a release is released -->
     <!-- In the source tree the version will always be 1.0 for all projects. -->
     <!-- Do not modify these. -->

+ 1 - 1
ReactiveExample/ReactiveExample.csproj

@@ -1,7 +1,7 @@
 <Project Sdk="Microsoft.NET.Sdk">
   <PropertyGroup>
     <OutputType>Exe</OutputType>
-    <TargetFramework>net6.0</TargetFramework>
+    <TargetFramework>net7.0</TargetFramework>
     <!-- Version numbers are automatically updated by gitversion when a release is released -->
     <!-- In the source tree the version will always be 2.0 for all projects. -->
     <!-- Do not modify these. -->

+ 92 - 29
Terminal.Gui/Core/Border.cs

@@ -3,6 +3,8 @@ using System;
 using System.Collections.Generic;
 using Terminal.Gui.Graphs;
 using System.Text.Json.Serialization;
+using System.Data;
+using System.Text;
 
 namespace Terminal.Gui {
 	/// <summary>
@@ -14,17 +16,22 @@ namespace Terminal.Gui {
 		/// </summary>
 		None,
 		/// <summary>
-		/// The border is drawn with a single line limits.
+		/// The border is drawn using single-width line glyphs.
 		/// </summary>
 		Single,
 		/// <summary>
-		/// The border is drawn with a double line limits.
+		/// The border is drawn using double-width line glyphs.
 		/// </summary>
 		Double,
 		/// <summary>
-		/// The border is drawn with a single line and rounded corners limits.
+		/// The border is drawn using single-width line glyphs with rounded corners.
 		/// </summary>
-		Rounded
+		Rounded,
+		// TODO: Support Ruler
+		///// <summary>
+		///// The border is drawn as a diagnostic ruler ("|123456789...").
+		///// </summary>
+		//Ruler
 	}
 
 	/// <summary>
@@ -103,45 +110,83 @@ namespace Terminal.Gui {
 			return new Rect (new Point (rect.X + Left, rect.Y + Top), size);
 		}
 
+		private void FillRect (Rect rect, System.Rune rune = default)
+		{
+			for (var r = rect.Y; r < rect.Y + rect.Height; r++) {
+				for (var c = rect.X; c < rect.X + rect.Width; c++) {
+					Application.Driver.Move (c, r);
+					Application.Driver.AddRune (rune == default ? ' ' : rune);
+				}
+			}
+		}
 
 		/// <summary>
-		/// Draws the thickness rectangle with an optional diagnostics label.
+		/// Draws the <see cref="Thickness"/> rectangle with an optional diagnostics label.
 		/// </summary>
+		/// <remarks>
+		/// If <see cref="ConsoleDriver.DiagnosticFlags"/> is set to <see cref="ConsoleDriver.DiagnosticFlags.FramePadding"/> then
+		/// 'T', 'L', 'R', and 'B' glyphs will be used instead of space. If <see cref="ConsoleDriver.DiagnosticFlags"/>
+		/// is set to <see cref="ConsoleDriver.DiagnosticFlags.FrameRuler"/> then a ruler will be drawn on the outer edge of the
+		/// Thickness.
+		/// </remarks>
 		/// <param name="rect">The location and size of the rectangle that bounds the thickness rectangle, in 
 		/// screen coordinates.</param>
 		/// <param name="label">The diagnostics label to draw on the bottom of the <see cref="Bottom"/>.</param>
 		/// <returns>The inner rectangle remaining to be drawn.</returns>
 		public Rect Draw (Rect rect, string label = null)
 		{
-			// Draw the Top side
-			for (var r = rect.Y; r < Math.Min (rect.Y + rect.Height, rect.Y + Top); r++) {
-				for (var c = rect.X; c < rect.X + rect.Width; c++) {
-					Application.Driver.Move (c, r);
-					Application.Driver.AddRune (' ');
-				}
+			System.Rune clearChar = ' ';
+			System.Rune leftChar = clearChar;
+			System.Rune rightChar = clearChar;
+			System.Rune topChar = clearChar;
+			System.Rune bottomChar = clearChar;
+
+			if ((ConsoleDriver.Diagnostics & ConsoleDriver.DiagnosticFlags.FramePadding) == ConsoleDriver.DiagnosticFlags.FramePadding) {
+				leftChar = 'L';
+				rightChar = 'R';
+				topChar = 'T';
+				bottomChar = 'B';
 			}
 
+			ustring hrule = ustring.Empty;
+			ustring vrule = ustring.Empty;
+			if ((ConsoleDriver.Diagnostics & ConsoleDriver.DiagnosticFlags.FrameRuler) == ConsoleDriver.DiagnosticFlags.FrameRuler) {
+
+				string h = "0123456789";
+				hrule = h.Repeat ((int)Math.Ceiling ((double)(rect.Width) / (double)h.Length)) [0..(rect.Width)];
+				string v = "0123456789";
+				vrule = v.Repeat ((int)Math.Ceiling ((double)(rect.Height * 2) / (double)v.Length)) [0..(rect.Height * 2)];
+			};
+
+			// Draw the Top side
+			FillRect (new Rect (rect.X, rect.Y, rect.Width, Math.Min (rect.Height, Top)), topChar);
+
 			// Draw the Left side
-			for (var r = rect.Y; r < rect.Y + rect.Height; r++) {
-				for (var c = rect.X; c < Math.Min (rect.X + rect.Width, rect.X + Left); c++) {
-					Application.Driver.Move (c, r);
-					Application.Driver.AddRune (' ');
-				}
-			}
+			FillRect (new Rect (rect.X, rect.Y, Math.Min (rect.Width, Left), rect.Height), leftChar);
 
 			// Draw the Right side			
-			for (var r = rect.Y; r < rect.Y + rect.Height; r++) {
-				for (var c = rect.X + Math.Max (0, rect.Width - Right); c < rect.X + rect.Width; c++) {
-					Application.Driver.Move (c, r);
-					Application.Driver.AddRune (' ');
-				}
-			}
+			FillRect (new Rect (Math.Max (0, rect.X + rect.Width - Right), rect.Y, Math.Min (rect.Width, Right), rect.Height), rightChar);
 
 			// Draw the Bottom side
-			for (var r = rect.Y + Math.Max (0, rect.Height - Bottom); r < rect.Y + rect.Height; r++) {
-				for (var c = rect.X; c < rect.X + rect.Width; c++) {
-					Application.Driver.Move (c, r);
-					Application.Driver.AddRune (' ');
+			FillRect (new Rect (rect.X, rect.Y + Math.Max (0, rect.Height - Bottom), rect.Width, Bottom), bottomChar);
+
+			// TODO: This should be moved to LineCanvas as a new BorderStyle.Ruler
+			if ((ConsoleDriver.Diagnostics & ConsoleDriver.DiagnosticFlags.FrameRuler) == ConsoleDriver.DiagnosticFlags.FrameRuler) {
+				// Top
+				Application.Driver.Move (rect.X, rect.Y);
+				Application.Driver.AddStr (hrule);
+				//Left
+				for (var r = rect.Y; r < rect.Y + rect.Height; r++) {
+					Application.Driver.Move (rect.X, r);
+					Application.Driver.AddRune (vrule [r - rect.Y]);
+				}
+				// Bottom
+				Application.Driver.Move (rect.X, rect.Y + rect.Height - Bottom + 1);
+				Application.Driver.AddStr (hrule);
+				// Right
+				for (var r = rect.Y + 1; r < rect.Y + rect.Height; r++) {
+					Application.Driver.Move (rect.X + rect.Width - Right + 1, r);
+					Application.Driver.AddRune (vrule [r - rect.Y]);
 				}
 			}
 
@@ -151,7 +196,7 @@ namespace Terminal.Gui {
 				Alignment = TextAlignment.Centered,
 				VerticalAlignment = VerticalTextAlignment.Bottom
 			};
-			tf.Draw (rect, Application.Driver.CurrentAttribute, Application.Driver.CurrentAttribute);
+			tf.Draw (rect, Application.Driver.CurrentAttribute, Application.Driver.CurrentAttribute, rect, false);
 
 			return GetInnerRect (rect);
 
@@ -208,6 +253,24 @@ namespace Terminal.Gui {
 		{
 			return !(left == right);
 		}
+
+	}
+
+	internal static class StringExtensions {
+		public static string Repeat (this string instr, int n)
+		{
+			if (n <= 0) {
+				return null;
+			}
+
+			if (string.IsNullOrEmpty (instr) || n == 1) {
+				return instr;
+			}
+
+			return new StringBuilder (instr.Length * n)
+				.Insert (0, instr, n)
+				.ToString ();
+		}
 	}
 
 	/// <summary>
@@ -450,7 +513,7 @@ namespace Terminal.Gui {
 		/// <summary>
 		/// Specifies the <see cref="Gui.BorderStyle"/> for a view.
 		/// </summary>
-		[JsonInclude, JsonConverter (typeof(JsonStringEnumConverter))]
+		[JsonInclude, JsonConverter (typeof (JsonStringEnumConverter))]
 		public BorderStyle BorderStyle {
 			get => borderStyle;
 			set {

+ 0 - 19
Terminal.Gui/Core/ConsoleDriver.cs

@@ -1198,25 +1198,6 @@ namespace Terminal.Gui {
 			}
 		}
 
-		/// <summary>
-		/// Draws a frame on the specified region with the specified padding around the frame.
-		/// </summary>
-		/// <param name="region">Screen relative region where the frame will be drawn.</param>
-		/// <param name="padding">Padding to add on the sides.</param>
-		/// <param name="fill">If set to <c>true</c> it will clear the contents with the current color, otherwise the contents will be left untouched.</param>
-		/// <remarks>This API has been superseded by <see cref="DrawWindowFrame(Rect, int, int, int, int, bool, bool, Border)"/>.</remarks>
-		/// <remarks>This API is equivalent to calling <c>DrawWindowFrame(Rect, p - 1, p - 1, p - 1, p - 1)</c>. In other words,
-		/// A padding value of 0 means there is actually a one cell border.
-		/// </remarks>
-		public virtual void DrawFrame (Rect region, int padding, bool fill)
-		{
-			// DrawFrame assumes the border is always at least one row/col thick
-			// DrawWindowFrame assumes a padding of 0 means NO padding and no frame
-			DrawWindowFrame (new Rect (region.X, region.Y, region.Width, region.Height),
-				padding + 1, padding + 1, padding + 1, padding + 1, border: false, fill: fill);
-		}
-
-
 		/// <summary>
 		/// Suspend the application, typically needs to save the state, suspend the app and upon return, reset the console driver.
 		/// </summary>

+ 0 - 3
Terminal.Gui/Core/Container.cs

@@ -68,9 +68,6 @@ namespace Terminal.Gui {
 
 			//OnDrawContent (bounds); 
 
-			//if (Text != null) {
-			//	Thickness?.Draw (Frame, $"{Text} {DiagnosticsLabel?.Text}");
-			//}
 			if (BorderStyle != BorderStyle.None) {
 				var lc = new LineCanvas ();
 				lc.AddLine (Frame.Location, Frame.Width - 1, Orientation.Horizontal, BorderStyle);

+ 2 - 0
Terminal.Gui/Core/Graphs/LineCanvas.cs

@@ -201,6 +201,8 @@ namespace Terminal.Gui.Graphs {
 			// TODO: Remove these two once we have all of the below ported to IntersectionRuneResolvers
 			var useDouble = intersects.Any (i => i.Line.Style == BorderStyle.Double && i.Line.Length != 0);
 			var useRounded = intersects.Any (i => i.Line.Style == BorderStyle.Rounded && i.Line.Length != 0);
+			// TODO: Support ruler
+			//var useRuler = intersects.Any (i => i.Line.Style == BorderStyle.Ruler && i.Line.Length != 0);
 
 			// TODO: maybe make these resolvers to for simplicity?
 			// or for dotted lines later on or that kind of thing?

+ 1 - 1
Terminal.Gui/Terminal.Gui.csproj

@@ -62,7 +62,7 @@
     <PackageReference Include="System.Text.Json" Version="7.0.1" />
   </ItemGroup>
   <PropertyGroup>
-    <TargetFrameworks>net472;netstandard2.0;net6.0</TargetFrameworks>
+    <TargetFrameworks>net7.0</TargetFrameworks>
     <LangVersion>9.0</LangVersion>
     <RootNamespace>Terminal.Gui</RootNamespace>
     <AssemblyName>Terminal.Gui</AssemblyName>