Browse Source

Fixed label positions to begin at Margins not just bottom left of screen (#1488)

* Fixed label positions to begin at Margins not just bottom left of screen

* Tidied up Axis GetLabels and added margin control to GraphViewExample

* Added tests for very large margins
Thomas Nind 3 years ago
parent
commit
b5799c3ded

+ 26 - 31
Terminal.Gui/Core/Graphs/Axis.cs

@@ -256,7 +256,7 @@ namespace Terminal.Gui.Graphs {
 			int labels = 0;
 			int y = GetAxisYPosition (graph);
 
-			var start = graph.ScreenToGraphSpace (0, y);
+			var start = graph.ScreenToGraphSpace ((int)graph.MarginLeft, y);
 			var end = graph.ScreenToGraphSpace (bounds.Width, y);
 
 			// don't draw labels below the minimum
@@ -270,24 +270,22 @@ namespace Terminal.Gui.Graphs {
 
 				int screenX = graph.GraphSpaceToScreen (new PointF (current.X, current.Y)).X;
 
-				// Ensure the axis point does not draw into the margin
-				if (screenX >= graph.MarginLeft) {
-					// The increment we will render (normally a top T unicode symbol)
-					var toRender = new AxisIncrementToRender (Orientation, screenX, current.X);
+				// The increment we will render (normally a top T unicode symbol)
+				var toRender = new AxisIncrementToRender (Orientation, screenX, current.X);
 
-					// Not every increment has to have a label
-					if (ShowLabelsEvery != 0) {
+				// Not every increment has to have a label
+				if (ShowLabelsEvery != 0) {
 
-						// if this increment does also needs a label
-						if (labels++ % ShowLabelsEvery == 0) {
-							toRender.Text = LabelGetter (toRender);
-						};
-					}
-
-					// Label or no label definetly render it
-					yield return toRender;
+					// if this increment does also needs a label
+					if (labels++ % ShowLabelsEvery == 0) {
+						toRender.Text = LabelGetter (toRender);
+					};
 				}
 
+				// Label or no label definetly render it
+				yield return toRender;
+				
+
 				current.X += Increment;
 			}
 		}
@@ -426,7 +424,7 @@ namespace Terminal.Gui.Graphs {
 
 			// remember screen space is top down so the lowest graph
 			// space value is at the bottom of the screen
-			var start = graph.ScreenToGraphSpace (x, bounds.Height - 1);
+			var start = graph.ScreenToGraphSpace (x, bounds.Height - (1 + (int)graph.MarginBottom));
 			var end = graph.ScreenToGraphSpace (x, 0);
 
 			// don't draw labels below the minimum
@@ -435,30 +433,27 @@ namespace Terminal.Gui.Graphs {
 			}
 
 			var current = start;
-			var dontDrawBelowScreenY = bounds.Height - graph.MarginBottom;
 
 			while (current.Y < end.Y) {
 
 				int screenY = graph.GraphSpaceToScreen (new PointF (current.X, current.Y)).Y;
 
-				// if the axis label is above the bottom margin (screen y starts at 0 at the top)
-				if (screenY < dontDrawBelowScreenY) {
-					// Create the axis symbol
-					var toRender = new AxisIncrementToRender (Orientation, screenY, current.Y);
+				// Create the axis symbol
+				var toRender = new AxisIncrementToRender (Orientation, screenY, current.Y);
 
-					// and the label (if we are due one)
-					if (ShowLabelsEvery != 0) {
+				// and the label (if we are due one)
+				if (ShowLabelsEvery != 0) {
 
-						// if this increment also needs a label
-						if (labels++ % ShowLabelsEvery == 0) {
-							toRender.Text = LabelGetter (toRender);
-						};
-					}
-
-					// draw the axis symbol (and label if it has one)
-					yield return toRender;
+					// if this increment also needs a label
+					if (labels++ % ShowLabelsEvery == 0) {
+						toRender.Text = LabelGetter (toRender);
+					};
 				}
 
+				// draw the axis symbol (and label if it has one)
+				yield return toRender;
+				
+
 				current.Y += Increment;
 			}
 		}

+ 12 - 2
Terminal.Gui/Views/GraphView.cs

@@ -114,6 +114,15 @@ namespace Terminal.Gui {
 				return;
 			}
 
+			// The drawable area of the graph (anything that isn't in the margins)
+			var graphScreenWidth = Bounds.Width - ((int)MarginLeft);
+			var graphScreenHeight = Bounds.Height - (int)MarginBottom;
+
+			// if the margins take up the full draw bounds don't render
+			if (graphScreenWidth < 0 || graphScreenHeight < 0) {
+				return;
+			}
+
 			// Draw 'before' annotations
 			foreach (var a in Annotations.ToArray().Where (a => a.BeforeSeries)) {
 				a.Render (this);
@@ -137,8 +146,9 @@ namespace Terminal.Gui {
 
 			SetDriverColorToGraphColor ();
 
-			// The drawable area of the graph (anything that isn't in the margins)
-			Rect drawBounds = new Rect((int)MarginLeft,0, Bounds.Width - ((int)MarginLeft), Bounds.Height - (int)MarginBottom);
+
+			Rect drawBounds = new Rect((int)MarginLeft,0, graphScreenWidth, graphScreenHeight);
+			
 			RectangleF graphSpace = ScreenToGraphSpace (drawBounds);
 
 			foreach (var s in Series.ToArray ()) {

+ 15 - 0
UICatalog/Scenarios/GraphViewExample.cs

@@ -52,6 +52,10 @@ namespace UICatalog.Scenarios {
 				new MenuBarItem ("_View", new MenuItem [] {
 					new MenuItem ("Zoom _In", "", () => Zoom(0.5f)),
 					 new MenuItem ("Zoom _Out", "", () =>  Zoom(2f)),
+					new MenuItem ("MarginLeft++", "", () => Margin(true,true)),
+					new MenuItem ("MarginLeft--", "", () => Margin(true,false)),
+					new MenuItem ("MarginBottom++", "", () => Margin(false,true)),
+					new MenuItem ("MarginBottom--", "", () => Margin(false,false)),
 				}),
 
 				});
@@ -676,6 +680,17 @@ namespace UICatalog.Scenarios {
 
 			graphView.SetNeedsDisplay ();
 		}
+		private void Margin (bool left, bool increase)
+		{
+			if (left) {
+				graphView.MarginLeft = (uint)Math.Max(0,graphView.MarginLeft + (increase ? 1 : -1));
+			}
+			else {
+				graphView.MarginBottom = (uint)Math.Max (0, graphView.MarginBottom + (increase ? 1 : -1));
+			}
+
+			graphView.SetNeedsDisplay ();
+		}
 
 		private void Quit ()
 		{

+ 132 - 0
UnitTests/GraphViewTests.cs

@@ -1398,6 +1398,138 @@ namespace Terminal.Gui.Views {
 			Application.Shutdown ();
 		}
 
+		[Fact]
+		public void YAxisLabels_With_MarginBottom ()
+		{
+			GraphViewTests.InitFakeDriver ();
+			var gv = new GraphView {
+				ColorScheme = new ColorScheme (),
+				Bounds = new Rect (0, 0, 10, 7)
+			};
+
+			gv.CellSize = new PointF (1, 0.5f);
+			gv.AxisY.Increment = 1;
+			gv.AxisY.ShowLabelsEvery = 1;
+
+			gv.Series.Add (new ScatterSeries {
+				Points = { new PointF (1, 1), new PointF (5, 0) }
+			});
+
+			// reserve 3 cells of the console for the margin
+			gv.MarginBottom = 3;
+			gv.MarginLeft = 1;
+
+			gv.Redraw (gv.Bounds);
+
+			var expected =
+@"
+ │
+1┤x
+ │ 
+0┼┬┬┬┬x┬┬┬
+ 0    5   
+          
+          ";
+			GraphViewTests.AssertDriverContentsAre (expected, output);
+
+
+			// Shutdown must be called to safely clean up Application if Init has been called
+			Application.Shutdown ();
+		}
+			
+		[Fact]
+		public void XAxisLabels_With_MarginLeft()
+		{
+			GraphViewTests.InitFakeDriver ();
+			var gv = new GraphView {
+				ColorScheme = new ColorScheme (),
+				Bounds = new Rect (0, 0, 10, 7)
+			};
+
+			gv.CellSize = new PointF (1, 0.5f);
+			gv.AxisY.Increment = 1;
+			gv.AxisY.ShowLabelsEvery = 1;
+
+			gv.Series.Add (new ScatterSeries {
+				Points = { new PointF (1, 1), new PointF (5, 0) }
+			});
+
+			// reserve 3 cells of the left for the margin
+			gv.MarginLeft = 3; 
+			gv.MarginBottom = 1;
+
+			gv.Redraw (gv.Bounds);
+
+			var expected =
+	@"
+   │
+  2┤
+   │
+  1┤x
+   │ 
+  0┼┬┬┬┬x┬
+   0    5
+         
+          ";
+				GraphViewTests.AssertDriverContentsAre (expected, output);
+
+
+			// Shutdown must be called to safely clean up Application if Init has been called
+			Application.Shutdown ();
+		}
+
+
+		[Fact]
+		public void MarginBottom_BiggerThanHeight_ExpectBlankGraph ()
+		{
+			var gv = GraphViewTests.GetGraph ();
+			gv.Height = 10;
+			gv.MarginBottom = 20;
+
+			gv.Series.Add (new ScatterSeries {
+				Points = { new PointF (1, 1), new PointF (5, 0) }
+			});
+
+
+			gv.Redraw (gv.Bounds);
+
+			var expected =
+	@"
+         
+         
+          ";
+			GraphViewTests.AssertDriverContentsAre (expected, output);
+
+
+			// Shutdown must be called to safely clean up Application if Init has been called
+			Application.Shutdown ();
+		}
+		[Fact]
+		public void MarginLeft_BiggerThanWidth_ExpectBlankGraph ()
+		{
+			var gv = GraphViewTests.GetGraph ();
+			gv.Width = 10;
+			gv.MarginLeft = 20;
+
+			gv.Series.Add (new ScatterSeries {
+				Points = { new PointF (1, 1), new PointF (5, 0) }
+			});
+
+
+			gv.Redraw (gv.Bounds);
+
+			var expected =
+	@"
+         
+         
+          ";
+			GraphViewTests.AssertDriverContentsAre (expected, output);
+
+
+			// Shutdown must be called to safely clean up Application if Init has been called
+			Application.Shutdown ();
+		}
+
 		[Fact]
 		public void PathAnnotation_Diamond ()
 		{