Git Product home page Git Product logo

Comments (12)

BDisp avatar BDisp commented on July 20, 2024 1

This unit test proves what I meant. In this case, I think that adding and removing a view is not the best option and in this case, let the layout deal with it based on the Visibility property.

    [Fact]
    public void Removing_View_Referenced_On_Another_View_Throws_On_LayoutSubviews ()
    {
        var view1 = new View { Width = 10, Height = 1 };
        var view2 = new View { X = Pos.Right (view1), Width = 10, Height = 1 };
        var view3 = new View { X = Pos.Right (view2), Width = 10, Height = 1 };
        var top = new View { Width = 30, Height = 1 };
        top.Add (view1, view2, view3);

        top.LayoutSubviews ();
        Assert.Equal (new  (0, 0, 10, 1), view1.Frame);
        Assert.Equal (new (10, 0, 10, 1), view2.Frame);
        Assert.Equal (new (20, 0, 10, 1), view3.Frame);

        view2.Visible = false;
        top.Remove (view2);
        Exception exception = Record.Exception (() => top.LayoutSubviews ());
        // Throw view was not found
        Assert.NotNull (exception);
    }

@tig if you proceed with the Visibility enum I suggest changing HiddenFromLayout to HiddenWidthFromLayout and adding HiddenHeightFromLayout, because there may only be a need to ignore just one of the sizes, both or none of the layout.

from terminal.gui.

tznind avatar tznind commented on July 20, 2024 1

This is for Shortcut which has 3 subviews that I'm using Pos.Align. If, say, [...]

This code makes the most sense to me. Nice and un ambigious

[...]
var view2 = new View { X = Pos.Right (view1), Width = 10, Height = 1 };

I don't think adding a 'hide from layout' state improves matters in this scenario.

If view1 is opting out of layout then it doesn't have a position so really you should still be throwing. Hence I feel that 'hidden from layout' is the same as 'not in the view' (i.e. Remove).

I always found SuspendLayout in winforms to be a bit of a hack. Making it a 'per view' state that affects positioning of other siblings (not just children) sounds like recipie for disaster.

I'm all for any helper methods that make things easier. For example I handle this situation in TGD to do things like:

  • prevent deleting a View if another has e.g. a Pos.Left dependency on it
  • AND that other view is not also being deleted at the same time (e.g. as part of multi select delete)
    private bool DependsOnUs(Design other, Design[] everyone)
    {
        // obviously we cannot depend on ourselves
        if (other == this)
        {
            return false;
        }

        // if their X depends on us
        if (other.View.X.GetPosType(everyone, out _, out _, out var relativeTo, out _, out _))
        {
            if (relativeTo == this)
            {
                return true;
            }
        }

        // if their Y depends on us
        if (other.View.Y.GetPosType(everyone, out _, out _, out relativeTo, out _, out _))
        {
            if (relativeTo == this)
            {
                return true;
            }
        }

        return false;
    }

from terminal.gui.

BDisp avatar BDisp commented on July 20, 2024

I have come across this same dilemma several times, especially when dealing with layout-related code. I still thought of another option that you didn't mention, which was to let the user worry about this, subscribing to the LayoutStarted event and then defining the Pos/Dim depending on whether the subview is visible or not.
Given that I deeply value automation, making life as easy as possible for the user in development, I would opt for suggestion 3.

from terminal.gui.

tig avatar tig commented on July 20, 2024

One challenge with this is dealing with other subviews that reference the view being "hidden".

There will need to be logic that at least lets devs know this is not supported (debug spew or exception).

from terminal.gui.

BDisp avatar BDisp commented on July 20, 2024

One challenge with this is dealing with other subviews that reference the view being "hidden".

I understand your point of view. Visibility.HiddenFromLayout should only affect Dim and not Pos, as this will always have the same value. Dim must return 0 if it is Visibility.HiddenFromLayout, otherwise the defined value will be calculated. Imagine the following scenario (no tested):

var view1 = new View { Width = 10, Height = 1 };
var view2 = new View { X = Pos.Right(view1), Width = 10, Height = 1, Visibility = Visibility.HiddenFromLayout };
var view3 = new View { X = Pos.Right(view2), Width = 10, Height = 1 };

The position of view3.Frame.X will be 10 (10 returned from the width of view1 + 0 returned from view2). If view2 has the Visibility property as Visible or Hidden, then the position of view3.Frame.X will be 20 (10 returned from view1's width + 10 returned from view2).

There will need to be logic that at least lets devs know this is not supported (debug spew or exception).

If it is actually not implemented then developers should know that it is not supported.

from terminal.gui.

tznind avatar tznind commented on July 20, 2024

from terminal.gui.

BDisp avatar BDisp commented on July 20, 2024

There are situations where I'd like to "hide" a subview from layout.
What is the use case? As an API user I think I would just call Remove on the view for most cases.

It has logic but what will happen if the Pos/Dim is referenced in another view? Will it throw an exception? Good question for creating a unit test to check what happens.

from terminal.gui.

tig avatar tig commented on July 20, 2024

There are situations where I'd like to "hide" a subview from layout.
What is the use case? As an API user I think I would just call Remove on the view for most cases.

Message ID: @.***>

Hmmm.... Maybe I have been over thinking this! I think you may be right that Remove/Add is all I need. Will ponder and report back.

from terminal.gui.

tig avatar tig commented on July 20, 2024

FWIW, for my immediate case, add/remove is working fine. I say we leave this Issue open though.

from terminal.gui.

tig avatar tig commented on July 20, 2024

And MFWIW (Moar For What It's Worth):

This is for Shortcut which has 3 subviews that I'm using Pos.Align. If, say, HelpText is not set, I want to hide the view from layout so it's like it doesn't exist. Here's the current logic. Note I have to ensure the order of Add is consistent so Pos.Align works properly.

        RemoveAll ();
        if (!string.IsNullOrEmpty (CommandView.Text))
        {
            Add (CommandView);
        }
        if (!string.IsNullOrEmpty (HelpView.Text))
        {
            Add (HelpView);
        }
        if (Key != Key.Empty)
        {
            Add (KeyView);
        }

from terminal.gui.

BDisp avatar BDisp commented on July 20, 2024

I still think that the location is always calculated regardless of whether it is visible or not. Only the dimension will be calculated or not if it is included or excluded from the layout, respectively. The location will always have the correct value calculated, regardless of whether it is visible or not and that value will be used by any view that is referencing it. If the view is invisible and excluded from the layout, the dimension calculation must return 0 (zero). However, if the other view that references the invisible view that is excluded from the layout contains something like X = Pos.Right (view2) + 1, the value returned will be 0 + 1 = 1, that is, just the value of Pos.Right (view2) should return 0 (zero) and the value 1 should remain because it is not relative to view2.
That's why I think that Pos.Align doesn't even have to be included in these calculations and removing and adding it will affect performance and can be a bit messy and doesn't solve cases where we just want to exclude one of the sides from the layout.

from terminal.gui.

BDisp avatar BDisp commented on July 20, 2024

I don't think adding a 'hide from layout' state improves matters in this scenario.

It doesn't make sense at design time, but only at run time.

If view1 is opting out of layout then it doesn't have a position so really you should still be throwing. Hence I feel that 'hidden from layout' is the same as 'not in the view' (i.e. Remove).

Yes, you're right, it also threw an exception, but I chose view2 because of the first example.

I always found SuspendLayout in winforms to be a bit of a hack. Making it a 'per view' state that affects positioning of other siblings (not just children) sounds like recipie for disaster.

SuspendLayout and ResumeLayout could be of some value especially at design time to prevent TGD from always performing the layout while adding views. It would be great to add them, I think it is activating or deactivating a flag. But of course it has nothing to do with invisible views, it just doesn't perform the layout until ResumeLayout is called.

I'm all for any helper methods that make things easier. For example I handle this situation in TGD to do things like:

  • prevent deleting a View if another has e.g. a Pos.Left dependency on it
  • AND that other view is not also being deleted at the same time (e.g. as part of multi select delete)

I think that for TGD you will have to deal with these situations, because it is not related to layout but to design, although this check can also be done in TG and would help a lot in cases where it is necessary. In this case the SuspendLayout and ResumeLayout methods could be used to prevent the layout from throwing an exception, or take advantage of the exception in a try/catch block to return true or false.
Don't forget that this check will also have to be used for width and height, because Dim may also be referencing a view.

from terminal.gui.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.