question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

A view referencing a View that's not a peer (same superview) in Dim/Pos should not be allowed

See original GitHub issue

I was debugging tests and came across this test:

https://github.com/gui-cs/Terminal.Gui/blob/33c9a5fad44256ab1ade0d9ac478dab6af89b9b6/UnitTests/Types/DimTests.cs#LL541C3-L585C4

		public void DimCombine_Do_Not_Throws ()
		{
			Application.Init (new FakeDriver ());


			var t = Application.Top;


			var w = new Window ("w") {
				Width = Dim.Width (t) - 2,
				Height = Dim.Height (t) - 2
			};
			var f = new FrameView ("f");
			var v1 = new View ("v1") {
				Width = Dim.Width (w) - 2,
				Height = Dim.Height (w) - 2
			};
			var v2 = new View ("v2") {
				Width = Dim.Width (v1) - 2,
				Height = Dim.Height (v1) - 2
			};


			f.Add (v1, v2);
			w.Add (f);
			t.Add (w);


			f.Width = Dim.Width (t) - Dim.Width (v2);
			f.Height = Dim.Height (t) - Dim.Height (v2);


			t.Ready += (s, e) => {
				Assert.Equal (80, t.Frame.Width);
				Assert.Equal (25, t.Frame.Height);
				Assert.Equal (78, w.Frame.Width);
				Assert.Equal (23, w.Frame.Height);
				Assert.Equal (6, f.Frame.Width);
				Assert.Equal (6, f.Frame.Height);
				Assert.Equal (76, v1.Frame.Width);
				Assert.Equal (21, v1.Frame.Height);
				Assert.Equal (74, v2.Frame.Width);
				Assert.Equal (19, v2.Frame.Height);
			};


			Application.Iteration += () => Application.RequestStop ();


			Application.Run ();
			Application.Shutdown ();
		}

I have decided this test is totally bogus because views are referencing superviews.

This code would guard against this:

		internal void CollectPos (Pos pos, View from, ref HashSet<View> nNodes, ref HashSet<(View, View)> nEdges)
		{
			switch (pos) {
			case Pos.PosView pv:
				if (!from.InternalSubviews.Contains (pv.Target)) {
					throw new InvalidOperationException ($"View {pv.Target} is not a subview of {from}");
				}
				if (pv.Target != this) {
					nEdges.Add ((pv.Target, from));
				}
				foreach (var v in from.InternalSubviews) {
					CollectAll (v, ref nNodes, ref nEdges);
				}
				return;
			case Pos.PosCombine pc:
				foreach (var v in from.InternalSubviews) {
					CollectPos (pc.left, from, ref nNodes, ref nEdges);
					CollectPos (pc.right, from, ref nNodes, ref nEdges);
				}
				break;
			}
		}

		internal void CollectDim (Dim dim, View from, ref HashSet<View> nNodes, ref HashSet<(View, View)> nEdges)
		{
			switch (dim) {
			case Dim.DimView dv:
				if (!from.InternalSubviews.Contains (dv.Target)) {
					throw new InvalidOperationException ($"View {dv.Target} is not a subview of {from}");
				}
				if (dv.Target != this) {
					nEdges.Add ((dv.Target, from));
				}
				foreach (var v in from.InternalSubviews) {
					CollectAll (v, ref nNodes, ref nEdges);
				}
				return;
			case Dim.DimCombine dc:
				foreach (var v in from.InternalSubviews) {
					CollectDim (dc.left, from, ref nNodes, ref nEdges);
					CollectDim (dc.right, from, ref nNodes, ref nEdges);
				}
				break;
			}
		}

And this test would verify:

		[Fact]
		public void Dim_Referencing_SuperView_Throws ()
		{
			var super = new View ("super") {
				Width = 10,
				Height = 10
			};
			var view = new View ("view") {
				Width = Dim.Width (super),	// this is not allowed
				Height = Dim.Height (super),    // this is not allowed
			};

			super.Add (view);
			super.BeginInit ();
			super.EndInit ();
			Assert.Throws<InvalidOperationException> (() => super.LayoutSubviews ());
		}

This breaks a lot of existing code (e.g. TileView does this internally). So I’m not sure I’m correct.

Please debate 😉.

Thanks.

Issue Analytics

  • State:closed
  • Created 6 months ago
  • Comments:17

github_iconTop GitHub Comments

1reaction
tigcommented, Apr 16, 2023

I’m going to close this issue. I think @BDisp shows an interesting use-case.

0reactions
BDispcommented, Apr 8, 2023

@tig with the last fix in the #2504, the rightLabel now have the right Pos.AnchorEnd (1) instead of Pos.AnchorEnd (13).

subview-referencing-superview-rule

Read more comments on GitHub >

github_iconTop Results From Across the Web

Embed Views in super view without losing autolayout ...
Embed your content into a new superview using the storyboard. Do not set any new constraints yet. Give your new superview a restoration...
Read more >
Auto Layout Guide: Views with Intrinsic Content Size
Describes the constraint-based system for laying out user interface elements.
Read more >
LIFESPAN DEVELOPMENT
Developmental Psychology, also known as Human Development or Lifespan Development, is the scientific study of ways in which people change, as well as...
Read more >
ASL American Sign Language
ASL - American Sign Language: free, self-study sign language lessons including an ASL dictionary, signing videos, a printable sign language alphabet chart ...
Read more >
ED314826.pdf - ERIC
Educators have great moral, ethical, and legal obligations to create schools where all students can achieve their full potential and receive an equal...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found