Git Product home page Git Product logo

Comments (9)

Omxjep3434 avatar Omxjep3434 commented on June 8, 2024 1

Just wanted to share my tentative solution. When the measure func is invoked, I am saving both the measure size (measure func params) and the measurement result. In my custom distribution phase, if the computed size of the node equals the saved measurement result, I am assuming the node is being measured and distributing against the saved measure size. I don't think that's perfect but should work reasonably well.

Nick, if you're not interested in any of my API proposals, you can go ahead and close the issue. I'll also put in a vote for exposing the YGNodeGetHasNewLayout like you originally mentioned. That would be useful to my project in multiple ways.

from yoga.

NickGerleman avatar NickGerleman commented on June 8, 2024

If Yoga executes the measure func, the measure size is provided as parameters to the measure func, so it can easily be used. But, if the measure func is not invoked because the leaf node has fixed dimensions, I need to compute a measure size by basically duplicating what I think Yoga does to compute a measure size which of course is very hacky and bug-prone.

As you mention, Yoga is not guaranteed to call the measure function, and the last call might not be the final layout. As part of YGNodeCalculateLayout, Yoga will set a flag on every Node where it or one of its children may have a new layout result compared to the last layout. A common pattern is to traverse down, applying the results of any nodes with a new layout, and resetting the flag.

The size which should be imposed on the content is the computed layout of the node, minus any padding or border. Yoga will have called into the platforms measure function as part of determining this, if neccesary.

There's an open issue where JS does not currently expose YGNodeGetHasNewLayout or YGNodeSetHasNewLayout but I think adding it would be pretty simple. #681

from yoga.

Omxjep3434 avatar Omxjep3434 commented on June 8, 2024

I'm not sure that exposing YGNodeGetHasNewLayout would solve my issue.

Let me try to articulate my problem a bit more in a visual way.

Below is a screenshot where the gray node is the Yoga root node, and the red node is an auto-sized leaf node where the measure width comes from the root node. The white squares are arbitrary children that can be thought of as objects outside of the Yoga layout.

The leaf node distributes N children in an ellipse that is the size of the available area. Notice that the distribution is different depending on the available size, so the results are different if the available width is 10 vs. 3, for example. No matter if the leaf node is auto or fixed size, an algorithm needs to execute to distribute the children after Yoga has processed. It's crucial that the children are distributed against the measure size, not the computed size. For example, using the screenshot as a reference, if the width measure size of the leaf node is 10, the computed width might only be 4. It would be incorrect to distribute the children in the leaf node using a width of 4 because it changes the shape and size of the distribution - it would be much more narrow than it should be.

yoga_measure_issue

So, things are trivial on the first execution of Yoga. I know if the measure func has executed and I have the measure size. If the measure func didn't execute, I can assume the node is fixed-size and compute a measure size using the node's computed size, padding and borders.

But, after that, it seems nearly impossible to get a reliable measure size because of caching. Even if I had a YGNodeGetHasNewLayout value, it wouldn't tell me if the node is auto-sized or fixed size (if the measure func is being used or not), and which dimensions specifically are auto/fixed. I also want to point out how difficult it would be to determine if a dimension is auto or fixed. Even if a dimension layout value is set to 'auto', it may have a 'flex' value that effectively makes it fixed-size. Further, whether a dimension is auto-sized is dependent on the parent flex direction and align type. I'm sure there are other things I'm not even thinking of.

Possible Yoga API solutions:

  1. I think the ideal solution would be the ability to get the measure size of a node at any time after Yoga has executed. I know the measure func can be executed more than once, but after execution, isn't there a final measure size that has been computed/used for a node? Or, another way to say it - isn't there a measure size that corresponds to the computed size of a node? Also, if the node is fixed-size, then the measure size would be the computed dimensions minus padding and borders, and both the width/height measure mode would be 'fixed'.
  2. Some method to determine if the measure func was used during the last execution of Yoga, even if it was not invoked because of caching. This allows the developer to know if the last provided measure size should be used, or all dimensions are fixed and a measure size can be computed using padding/borders.
  3. Some method to determine if a dimension is auto-sized / measured using the logic described above. If either the width or height are auto, it can be assumed that the measure func is being used, and the last provided measure size can be used. Otherwise, the node should be treated as fixed-size.

from yoga.

NickGerleman avatar NickGerleman commented on June 8, 2024

Or, another way to say it - isn't there a measure size that corresponds to the computed size of a node? Also, if the node is fixed-size, then the measure size would be the computed dimensions minus padding and borders, and both the width/height measure mode would be 'fixed'.

The content size should be the final computed size (border-box size), minus padding and borders, regardless of the mode of measurement. I.e. you should read this off of the layout results to use for sizing with the external layout system.

The results from a measure function should not be assumed to be related to the final layout of the node.

from yoga.

Omxjep3434 avatar Omxjep3434 commented on June 8, 2024

Okay, I think that's my disconnect. I don't think my use case is supported by Yoga. Can you confirm Nick, and do you understand what I'm trying to articulate with my description and image? It's sort of a catch-22. If Yoga asks me the size of my node via the measure func, I need to use its provided measure size to predict how my items will be distributed and return a computed size. But, I can't then later use that computed size (or the border-box size) to distribute my items because that makes a distribution that has a different size than what was provided to Yoga in the measure func result and the layout is simply incorrect.

If this use case isn't supported by Yoga, do you have any other suggestions on how I might at least partially implement this? Identifying if a dimension is auto-sized would help, but as I mentioned in my previous message, I feel like that might be too complicated. Also knowing whether the measure func is being used (even if cached) would help, but I've run out of ideas on how to reliably know that.

from yoga.

NickGerleman avatar NickGerleman commented on June 8, 2024

If I am understanding correctly, the overall scenario should be supported, but how it needs to be handles depends on what the hosting code looks like.

The measure function is Yoga asking for hypothetical size (but Yoga can impose its own).

After the Yoga layout step, the leaf node with measure function has a known size, as calculated by Yoga, but the item has not yet been laid out.

The step needed, is after Yoga does layout, the node with measure function should be told to calculate its own layout, using the final result Yoga came up with. I.e. tell the red box to distribute its items, using the final layout result from Yoga.

This will incorporate intrinsic size as returned by the measure function, if the size in CSS would depend on content, but box size is allowed to be larger or smaller or smaller than content, e.g. if user sets explicit width/height. How to handle the larger or smaller box than natural content depends on desired integration with external layout system.

from yoga.

Omxjep3434 avatar Omxjep3434 commented on June 8, 2024

Hmm, I'm still not seeing how my use case would be possible.

Here's another screenshot of the entire layout process. To summarize, the leaf node distributes N children in an ellipse that is the size of the available area.

yoga_measure_issue 2 small

The crux of the issue here is that the distribution algorithm is not linear like traditional layout systems. Notice that if I were distributing items against a horizontal line, like Yoga, this issue would not exist.

from yoga.

NickGerleman avatar NickGerleman commented on June 8, 2024

Okay, when you mention "measure size", you mean the available space the node can be sized into. I think I have been misunderstanding that.

This size is not always consistent with the parent. E.g. Yoga (or other layout systems) can size the node into infinite available space (like when overflow: "scroll" is set). Or, the parent may be sized on its content, and its final dimensions end up smaller than the available size.

In this example, it seems like you could distribute using the measured size of the parent. Is that something you could do more generally?

from yoga.

Omxjep3434 avatar Omxjep3434 commented on June 8, 2024

Ah, sorry. When I say "measure size" I'm referring to the parameters of the measure func (width, widthMode, height, heightMode). From experimentation, it seems that the measure size of an auto dimension comes from the first fixed-size ancestor. The measure size of a fixed dimension is the border box size (the fixed dimension minus border and padding).

In this example, it seems like you could distribute using the measured size of the parent. Is that something you could do more generally?

That seems intuitive but I'm not sure that would work in all cases. What if the parent is autosized? Then the measure size comes from an ancestor. The key to the issue is knowing what size was used to produce the measurement (the parameters of the measure func). I've explained above why that is difficult to get reliably because of caching, but let me know if you want me to expand on that.

from yoga.

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.