Feature: possibility to hide nodes #241
Reference in New Issue
Block a user
No description provided.
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
I know this is currently by design, but it would be great if we could hide / show nodes. Any roadmap on this? Maybe we can have a chat and I can implement this?
What is the use case? Why not just remove the node and re-attach it, it should have the same effect unless i'm misunderstanding you.
Hey @emilsjolander yes removing would be a solution though probably less convenient that toggling the visiblity. My use case is a GUI that uses CssLayout where you often have things that you want to show/hide: for example selectboxes, menus, popups etc. Adding/removing a node dynamically (and making sure the order stays the same) means quite some extra bookkeeping compared to having a visibility toggle. Especially because it's quite common in guis to hide/show things. Do you have any concerns with adding this visibility flag?
I have concerns about adding things which are not needed as it bloats the API. That said I think you have made a good point regarding keeping ordering and the bookkeeping needed for that. Adding visibility to cssnode would make sense. It would be great if you can implement this as then you can also test that it works for your situation 👍 All that should be required is to skip invisible children when iterating of the list of children. This could be done by
if (child->invisible) continue;
at the top of each child loop. Make sure to add tests for this as well 💯(Y) awesome, I'll look into this.
Thanks!
Not sure if this is a great feature as in pure css
visibility: hidden
still takes the space. The same forUIView
on iOS. See26bcc1e
which explicitly reverts this from css-layout.To not confuse users, maybe its better to not name this something like
visible
. Maybe it should be called something like the cssdisplay:none
which leads to the desired behaviour.@emilsjolander are you on irc or skype?
@roxlu totally missed this sorry. Feel free to hit me up on fb messenger (m.me/sjolander.emil)
@woehrl01 I agree, using
visible
could be very confusing@emilsjolander I did some experimenting and I think it's almost working. There is only one issue that needs to be solved: when you hide a node before calling layout() it will never be shown again. When you hide after calling layout() it works as expected.
I've pasted some test code using my fork: https://gist.github.com/roxlu/5d489941de7956c808823f85fd71ab49
It seems that things are cached. @emilsjolander shall we have a call to look into this?
@roxlu I would suggest stepping through the code with a debugger and figuring out why your hidden node is not being shown when hiding it before calling layout()
@emilsjolander thanks for your reply, but currently I don't have time to dive into the code. It would take me some time to be able to understand the code in detail. Though ... maybe you have some ideas where to look?
@roxlu If it is using cached measurements you can have a look at the
CSSNodeCanUseCachedMeasurement
function. Perhaps make it always returnfalse
to see if this is the problem.@emilsjolander I just tested with a
CSSNodeCanUseCacheMeasurement
returning always false and this gives me these results: https://gist.github.com/roxlu/db899e390deda9e06445d2759a482fa1Interestingly it seems that the version A and B works, but then at step C where I hide the first 5 items (see paste) it is still using the values after that were calculated at step B.
Sounds like you may just not be reseting the nodes output in between
On Thu, 1 Dec 2016 at 10:43, @roxlu notifications@github.com wrote:
I've set gPrintTree / gPrintChanges to true, it that what you mean?
@emilsjolander Do I need to make a parent dirty when one of it's children changes visibility? Maybe the root not (and so all children) is just skipped when I only mark a child as dirty (?).
Yes you do, the dirty marking function does this for you though
On Thu, 1 Dec 2016 at 11:00, @roxlu notifications@github.com wrote:
What I meant by not reseting nodes is that perhaps the nodes are just skipped over in the last pass (as expected) so that their layout outputs (width/height/x/y) are never reset and they just keep the ones from before. I don't have time now to dig down into your code :/
It's okay if the width/height/x/y stay the same as before when hiding a element. It seems that the issue is related to the dirty flag. When I call
CSSNodeHide()
orCSSNodeShow()
on a child, the parent is not marked as dirty. See here for these functions.Also, when I set
needToVisitNode = true
inlayoutNodeInternal()
, it seems to give me the expected results. But thisneedToVisitNode
is set to false becausenode->isDirty
is false.Look at the definition of
_CSSNodeMarkDirty
, it's a recursive function calling up to the parent so I don't this this is your issue.I agree :) that it seems wrong that it's the dirty flag. I'm printing out the condition results in
layoutNodeInternal()
that set theneedToVisitNode
, this is what I get:And the code I'm using for this:
When looking at
gCurrentGenerationCount
it makes me wonder if this could be caused by multiple "root" instances?@roxlu No idea. As I said, step through the code (mainly where you made additions and it does cache / dirty checks) and see what is going on. Try it on the most minimal tree to make it easier.
"step through the code" would be okay if I knew the internals and I had time to learn the codebase which I don't have atm. I'll revisit this issue again when I've got some more time or when it's a bit on your radar too.
@emilsjolander maybe I found what was causing it, but please tell me if this sounds reasonable. I noticed that in
_CSSNodeMarkDirty()
you only traverse upwards when the given node is not dirty. I guess thisisDirty
is set to false somewhere; but this 'somewhere' is not doing that because the node was hidden. I can fix this by settingsnode->isDirty = false
before calling_CSSNodeMarkDirty(node)
in myCSSNodeHide()
andCSSNodeShow()
functions. It seems to work fine now.Thanks for your feedback before!
@roxlu you need to mark the layout as seen (
isDirty = false
), even so you skip the child.e.g. here and here and the other spots where you skip them.
@roxlu furthermore, I'd suggest changing boolean
isVisible
to an enumdisplay
. Withflex
andnone
as values, whereflex
is the default. So that it conforms more with the web.e.g.
CSSNodeStyleSetDisplay(node, CSSDisplayFlex)
andCSSNodeStyleSetDisplay(node, CSSDisplayNone)
This would simplify test generation.
@woehrl01 I like it
@roxlu for a feature I try to implement externally this would be a handy thing, do you mind doing a PR ?
Yep of course. Though I would love to see this being integrated here. @emilsjolander shall I do a pull request?
Go ahead and create a PR and we can discuss the details further there 👍