Terminal.Gui icon indicating copy to clipboard operation
Terminal.Gui copied to clipboard

`TabView` assumes `Frame == Bounds`

Open tig opened this issue 2 years ago • 13 comments

Similar to #2989, TabView does not work well if any of the Frames have any dimensions.

To repro, change the TabViewExample.cs scenario to give the TabView a border:

			tabView = new TabView () {
				X = 0,
				Y = 0,
				Width = 60,
				Height = 20,
				BorderStyle = LineStyle.Single
			};

image

tig avatar Nov 14 '23 01:11 tig

With the TabView you can't use the border. You need to explicit draw the frame.

BDisp avatar Nov 14 '23 01:11 BDisp

With the TabView you can't use the border. You need to explicit draw the frame.

That is precisely the bug I'm reporting. Border should work. So should margin and padding.

tig avatar Nov 14 '23 01:11 tig

Well I'm really curious to know if WPF and Windows.Forms use the margin or padding of the control to draw the tabs.

BDisp avatar Nov 14 '23 12:11 BDisp

So I'm clear: I'm not talking about the lines that make up the tabs themselves or the lines that make up the box beside and below the tabs (contiguous with the tabs). I'm talking about the space AROUND all of that.

Am I making sense to you?

tig avatar Nov 14 '23 18:11 tig

Sorry @tig, I didn't realizes that you refer to the space around the TabView. I'll investigate that but I thing the TabView is overwriting something.

BDisp avatar Nov 14 '23 18:11 BDisp

Well the problem is LineCanvas of the TabView is used to deal with two borders. When I call the DrawFrame it add more lines to the LineCanvas , but seems they not touch each other. If it's then the OnRenderLineCanvas isn't work as supposed. Right?

BDisp avatar Nov 14 '23 19:11 BDisp

Here is how the LineCanvas looks like on TabView:

┌──────────────────────────────────────────────────────────┐
│                                                          │
│                                                          │
│┌────────────────────────────────────────────────────────┐│
││                                                        ││
││                                                        ││
││                                                        ││
││                                                        ││
││                                                        ││
││                                                        ││
││                                                        ││
││                                                        ││
││                                                        ││
││                                                        ││
││                                                        ││
││                                                        ││
││                                                        ││
││                                                        ││
│└────────────────────────────────────────────────────────┘│
└──────────────────────────────────────────────────────────┘

If I don't call the OnRenderLineCanvas on the DrawFrame the output is this:

image

BDisp avatar Nov 14 '23 19:11 BDisp

@tig I already find the solution for this. Is there any problem to create a public property for _lines). See the solution on the TabView:

		///<inheritdoc/>
		public override void OnDrawContent (Rect contentArea)
		{
			Move (0, 0);
			Driver.SetAttribute (GetNormalColor ());

			if (Style.ShowBorder) {

				// How much space do we need to leave at the bottom to show the tabs
				int spaceAtBottom = Math.Max (0, GetTabHeight (false) - 1);
				int startAtY = Math.Max (0, GetTabHeight (true) - 1);
				var lc = new LineCanvas () { _lines = new List<StraightLine> (LineCanvas._lines) };

				DrawFrame (new Rect (0, startAtY, Bounds.Width,
					Math.Max (Bounds.Height - spaceAtBottom - startAtY, 0)), LineStyle.Single);

				LineCanvas._lines = lc._lines;
			}

			if (Tabs.Any ()) {
				tabsBar.OnDrawContent (contentArea);
				contentView.SetNeedsDisplay ();
				var savedClip = contentView.ClipToBounds ();
				contentView.Draw ();
				Driver.Clip = savedClip;
			}
		}

image

BDisp avatar Nov 14 '23 19:11 BDisp

What is the core issue here? is it the explicit use of DrawFrame that causes the problem?

i.e. this bit:

Border.DrawFrame (new Rect (0, startAtY, Bounds.Width,
Math.Max (Bounds.Height - spaceAtBottom - startAtY, 0)), false);

It looks like your proposed code is taking the state of LineCanvas and then doing the DrawFrame method then restoring the LineCanvas to it's original state before DrawFrame which seems confusing to me.

Regarding your changes I think we should be more elegant than _lines. But need to understand the use case

var lc = new LineCanvas () { _lines = new List<StraightLine> (LineCanvas._lines) };

Is this just a clone method? If so we should do:

var lc = LineCanvas.Clone()

The internals of that method would be able to access private instance variables.

tznind avatar Nov 14 '23 19:11 tznind

Regarding your changes I think we should be more elegant than _lines. But need to understand the use case

_lines is the field that already exist. I only made it public to test. What I was asking is if I can create a public property Lines to get/set this value.

var lc = LineCanvas.Clone();

CS1061 'LineCanvas' does not contain a definition for 'Clone' and no accessible extension method 'Clone' accepting a first argument of type 'LineCanvas' could be found (are you missing a using directive or an assembly reference?)

BDisp avatar Nov 14 '23 20:11 BDisp

'LineCanvas' does not contain a definition for 'Clone'

Yeah we would have to write it >< but I think that is more elegant?

There is still

LineCanvas._lines = lc._lines;

But maybe that could just be

LineCanvas = lc;

tznind avatar Nov 14 '23 20:11 tznind

No @tznind you have to test the code. If I save only the property it's by reference and lc will be empty after ran the DrawFrame method. The solution is the creation of Lines property on the LineCanvas class. And the Clone method doesn't exist.

var lc = LineCanvas;

DrawFrame (new Rect (0, startAtY, Bounds.Width,
	Math.Max (Bounds.Height - spaceAtBottom - startAtY, 0)), LineStyle.Single);

LineCanvas = lc;

BDisp avatar Nov 14 '23 20:11 BDisp

See #2980.

BDisp avatar Nov 14 '23 20:11 BDisp

This was already fixed on #2980.

BDisp avatar Aug 11 '24 21:08 BDisp