I hope to have time tomorrow.

Looking quickly at the things you've tried to fix the problem, it occurs to me 
that the piece that is probably missing in MXRoyale is the propagation of 
something like invalidateSize() instead of just "layoutNeeded".  My thinking is 
that in the general case the child can't really know that because something 
about the child changed that the parent needs to run a new layout and 
especially the parent of that parent.

So some new plumbing may be needed where, when a component changes in a way 
that its measured or explicit size had changed (as opposed to the size change 
from the parent laying out the child), that some sort of layoutMightBeNeeded is 
sent to the parent which then uses its measurement code and explicit sizes to 
determine whether its size has changed and propagates a layoutMightBeNeeded to 
its parent.  But if it decides its size has not changed, it would then run 
layout which should start the parents laying out children.

We'll see if the test case points in that direction.

HTH,
-Alex

On 6/5/20, 3:05 AM, "Greg Dove" <greg.d...@gmail.com> wrote:

    Hi Alex, thanks for the detailed explanation and offer to take a look, for
    now some quick replies inline.... please add questions in the github issue
    if you want more details about anything I did so far.
    thanks
    Greg
    
    On Fri, Jun 5, 2020 at 6:50 PM Alex Harui <aha...@adobe.com.invalid> wrote:
    
    > Greg,
    >
    > I think this thread got forked somehow.  If you have a simple test case I
    > can try to look at it this weekend.
    >
    > Thanks. I added issue #849 [1] which should give you something to look at.
    I suggest you open the Flex build in a browser and then compare things to
    it in Royale. There are 2 royale builds as well with the same code in the
    other 2 zips. One without the modifications to MXRoyale and one with. The
    'one with' zip also has the modified MXRoyale files, so you should be able
    to drop them in and overwrite in your local MXRoyale and build to
    test/review/change what I did. I'm the first to admit that I do think it
    doesn't feel right. But so far at least it does make a bunch of code work
    in one app with a lot of deeply nested layouts that was not working before.
    It certainly does not make everything work. But it helps quite a bit.
    Certainly appreciate any review/consideration. I am really keen to
    collaborate on a solution that makes sense for most here.
    
    I don't doubt that the changes you propose work for you, but they make me
    > nervous although I'm not the best at reading code and understanding what 
it
    > does.  Here's a brain dump on layout in case it helps.
    >
    > So far they work better 'for me' I agree. But I think you probably know me
    enough by now to know that if I am confident that I have a contribution
    that is objectively good (passes unit tests compared with swf is my normal
    benchmark) then I will add it. Part of the reason I started this discussion
    is because I feel a bit the same way here. I am still learning this stuff
    and figuring things out, so I am not pushing it because I don't want to
    inflict anything that is not an objective improvement on others.
    
    In terms of describing it, the main thing I think, is that the view checks
    when layout happens if there was a size change since last time layout ran,
    or if there was a change in size during the current run. Then there is some
    somewhat awkward checking to see if the parent might be interested in this
    because there is some 'sizedToContent' aspect to it (which includes a
    percentage variation on that check). If we think it is relevant, then
    request the parent to layout. Is this likely to do it sometimes when it is
    not needed, I suspect so. But so far it has not caused any problems in the
    codebase I am working with.
    
    I'm also working on the Grid related stuff, but you could probably just
    ignore that for now and focus only on the BoxLayout stuff.
    
    In Flex, parents always size their children.  The children probably
    > shouldn't override that size or if they do they have to be careful that it
    > doesn't trigger the another layout in the parent in a way that you run
    > layout forever (a "layout loop").  In Flex, because of the LayoutManager
    > running on frame events, that generally doesn't freeze the UI and I have
    > seen situations where the LayoutManager never goes idle even though the 
app
    > appears to be running fine.  There is also the case where the first layout
    > pass results in scrollbars which causes children to adjust and results in
    > the removal of scrollbars and that loops forever with the scrollbars
    > blinking on and off.  In Royale, there is a greater chance of hanging.
    >
    > Also in Flex, with the LayoutManager, EVERY widget added itself to the
    > LayoutManager ensuring validation in a particular order, enforcing the
    > "parents size children" rule.
    >
    > In Royale, I tried to go without a LayoutManager because we started out
    > targeting IE8 and I wasn’t sure if there were some things that were
    > exceptions to requestAnimationFrame (like setting text or sizing images).
    > To this day, I'm concerned that it will create an poor debugging 
experience
    > because I think when you hit breakpoints the screen updates.  All of those
    > things need testing before we try a LayoutManager based on
    > requestAnimationFrame.  And then, as I think you mentioned, we have to be
    > concerned about how much code is going to run if we start running all of
    > the validation methods.
    >
    > On the other hand, I think Royale runs layout too often still because two
    > property changes can trigger two layout passes.  I looked at BoxLayout
    > which extends LayoutBase which does already watch for
    > widthChanged/heightChanged/sizeChanged so whatever is the root cause of
    > your problem may not be triggering the layout pass you want, although the
    > code paths in LayoutBase.childResizeHandler are there to prevent layout
    > loops.
    >
    > Usually, in Flex, a component didn't change its size in response to user
    > interaction or data loading, it changed its measured size and called
    > invalidateSize on itself and its parent.  The LayoutManager measured
    > children before parents, then layed out parents before children.
    >
    > Yeah, that's the vague notion I had, your explanation has helped cement my
    understanding.
    
    
    > In Royale, there is little to no measurement subsystem.  That's because we
    > rely on the browser to "immediately" measure by setting
    > offsetWidth/offsetHeight saving us the impossible task of writing code to
    > guess at how the browser measures.  For PAYG reasons in Basic, there is no
    > code looking for changes that should trigger a layout other than possibly
    > child size changes.  Everything else is supposed to use
    > LayoutChangeNotifier to wire the one event that signals a change to the
    > container/layout that cares.
    
    In MXRoyale, there are complex components that can't rely on
    > offsetWidth/Height since MXRoyale cannot rely on browser layout because of
    > things like overriding the meaning of width=100%.   MXRoyale has measure()
    > methods from Flex, but they don't always get run because there is no
    > LayoutManager measuring the children before the parents and existing
    > measure() methods expect the children to have been measured.  It might be
    > that is the root cause here.  That some or all invalidateSize() calls need
    > to call measure() and then instead of calling layoutNeeded on the parent,
    > call the parent's invalidateSize until somehow we know we've gone far
    > enough up the chain to start laying out again.
    >
    > After the changes I made I do still need to make changes in some specific
    areas, but usually this type of thing does the trick:
    
                var layout:BoxLayout =
    containerContents.getBeadByType(BoxLayout) as BoxLayout;
                if (layout) {
                    layout.measure();
                }
                containerContents.layoutNeeded();
    
    Note: calling measure() explicitly like that with BoxLayout seems to be
    necessary sometimes before an explicit layout request. It might only work
    more after the changes I made, not sure whether it makes a difference
    before or not.
    
    
    > HTH,
    > -Alex
    >
    >
    > On 6/4/20, 1:51 PM, "Greg Dove" <greg.d...@gmail.com> wrote:
    >
    >     'I don’t think we’ve dealt with a lot of children changing sizes 
(other
    >     than Images loading late and a few other things) so it may be time to
    >     listen to widthChanged/heightChanged/sizeChanged as children get added
    > if
    >     there isn’t already code doing that.'
    >
    >     That would be another way of doing it. There is already this code [1]
    > that
    >     is swf-only but seems to only be relevant before sawInitComplete.
    >
    >     But if the children run their layouts when their own size changes, 
then
    >     they can notify their parent as well if the size changed either before
    > or
    >     during layout. That's sort of what I was trying to do with the
    >     ContainerView change I mentioned earlier. It checks size for change in
    >     beforeLayout and again in afterLayout and then requests parent layout
    > if it
    >     thinks the parent needs to do something that could affect parent
    > layout or
    >     even re-apply its own rules to the current target. In this way there
    > is not
    >     a need to add listeners to every child. But I expect there are some
    >     downsides or things I cannot see with what I did so far because I have
    > not
    >     spent a lot of time in this code, as you have. I'll post more details
    > in
    >     the github issue at my EOD.
    >
    >     1.
    >
    > 
https://nam04.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2Fapache%2Froyale-asjs%2Fblob%2F9c70b052a6fef3ebe7c6a07ca887af4f7381d46f%2Fframeworks%2Fprojects%2FCore%2Fsrc%2Fmain%2Froyale%2Forg%2Fapache%2Froyale%2Fcore%2FLayoutBase.as%23L131&amp;data=02%7C01%7Caharui%40adobe.com%7C34080cf90f504c1b7ef508d809380095%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C637269483425406744&amp;sdata=na2D5dkZziw7na8WuNrz%2FRIJzphWgVEVmGX64aPJ1UA%3D&amp;reserved=0
    >
    >     On Fri, Jun 5, 2020 at 3:32 AM Alex Harui <aha...@adobe.com.invalid>
    > wrote:
    >
    >     > Serkan, is there a bug tracking your layout issue?
    >     >
    >     > There should be a difference between first layout if all children
    > have
    >     > known sizes and what Greg is describing which is responding to
    > children
    >     > changing sizes.  I don’t think we’ve dealt with a lot of children
    > changing
    >     > sizes (other than Images loading late and a few other things) so it
    > may be
    >     > time to listen to widthChanged/heightChanged/sizeChanged as children
    > get
    >     > added if there isn’t already code doing that.
    >     >
    >     > There might be other issues with containers having an inner
    > contentArea
    >     > that might be getting in the way too.
    >     >
    >     > HTH,
    >     > -Alex
    >     >
    >     > From: Yishay Weiss <yishayj...@hotmail.com>
    >     > Reply-To: "dev@royale.apache.org" <dev@royale.apache.org>
    >     > Date: Thursday, June 4, 2020 at 4:30 AM
    >     > To: "dev@royale.apache.org" <dev@royale.apache.org>
    >     > Subject: RE: MXRoyale layout issues - questions/discussion
    >     >
    >     > Call me lazy but this is a bit difficult to parse. If you can spare
    > some
    >     > time, maybe come up with a GitHub issue that describes a concrete
    > case so
    >     > we can discuss this.
    >     >
    >     > > I think the layouts work downward for this, but changes in the
    > children
    >     > don't seem to trigger the parent layout.
    >     >
    >     > Yes, I’ve seen that as well. Alex’s advice when I pointed it out to
    > him
    >     > was to just add a parent.dispatchEvent(new Event(‘layoutNeeded’)) if
    > it
    >     > solves a concrete bug. It’s true that this could result in a
    > performance
    >     > hit. If that’s your issue then I guess we can discuss emulation of
    > the
    >     > layout manager or some other optimization.
    >     >
    >     >
    >     > From: Greg Dove <greg.d...@gmail.com>
    >     > Sent: Thursday, June 4, 2020 11:12:08 AM
    >     > To: Apache Royale Development <dev@royale.apache.org>
    >     > Subject: MXRoyale layout issues - questions/discussion
    >     >
    >     > Hi,
    >     >
    >     > Just wondered if anyone else is dealing with layout issues in Flex
    >     > emulation. I have some layout issues that are slowing my progress on
    > a
    >     > project, and I'd like to resolve them as quickly as I can.
    >     >
    >     > In particular, I see issues with BoxLayout-based containers which
    > have
    >     > percentWidth or percentHeight set. These don't get determined as
    > having
    >     > width or height 'SizedToContent' when performing layout, but in many
    >     > situations they behave in a similar way (they can change their size
    > based
    >     > on their content in terms of layout rules applied by the parent
    > container).
    >     > This is because in Flex, percentages are not simply a percentage of
    > their
    >     > parent, but they follow something perhaps a little closer to flexbox
    > layout
    >     > rules for all the percentWidth or percentHeight siblings (managed by
    > their
    >     > parent's layout). In other words, they are also related to the
    > measured
    >     > size of their content if the parent needs to manage them (I'm not
    > sure how
    >     > best to describe this, but I think that sort of captures it). They
    > can
    >     > expand beyond their percent allocation or contract below it
    > depending on
    >     > their measured sizes.
    >     > I think the layouts work downward for this, but changes in the
    > children
    >     > don't seem to trigger the parent layout.
    >     >
    >     > An example might be
    >     > <mx:HBox id='addThingsToMe' width='50%' />
    >     >
    >     > If you have the above at the application level (where the
    > application has
    >     > vertical layout) and keep adding buttons (for example) to the HBox
    > via a UI
    >     > test button that adds a new Button to that on each click, then it
    > should
    >     > expand horizontally greater than 50% width when the volume of 
buttons
    >     > exceeds its nominal 50% width. It is definitely easier to see this
    > if you
    >     > add a border to the container.
    >     >
    >     > I have been working on this, and made progress, but the approach I
    > am using
    >     > feels a bit patchwork, and just wondered whether others are seeing
    > anything
    >     > like this, and/or how it has been addressed elsewhere....
    >     >
    >     > Here's a summary of some of the things I have been trying, which do
    > yield
    >     > improvements, but don't really solve the problem completely:
    >     >
    >     > 1. added extra listener for 'childrenRemoved' in BoxLayout strand
    > setter.
    >     >
    >     > 2. Created a new mx 'ContainerView' class
    >     > (mx.containers.beads.ContainerView extends
    >     > org.apache.royale.html.beads.ContainerView)
    >     > This has the following in it:
    >     >
    >     > private var widthBefore:Number = -1
    >     > private var heightBefore:Number = -1;
    >     > private var sizeChangedBeforeLayout:Boolean;
    >     >
    >     > COMPILE::JS
    >     > override public function beforeLayout():Boolean
    >     > {
    >     > var container:Container = host as Container;
    >     >
    >     > sizeChangedBeforeLayout = (widthBefore != container.width ||
    > heightBefore
    >     > != container.height);
    >     > widthBefore = container.width;
    >     > heightBefore = container.height;
    >     > return super.beforeLayout();
    >     > }
    >     >
    >     >     COMPILE::JS
    >     >     override public function afterLayout():void
    >     >     {
    >     >         var container:Container = host as Container;
    >     > //size might change during layout
    >     > var sizeChangedDuringLayout:Boolean = !sizeChangedBeforeLayout &&
    >     > (widthBefore != container.width || heightBefore != 
container.height);
    >     > if (sizeChangedDuringLayout) {
    >     > //prepare for next time
    >     > widthBefore = container.width;
    >     > heightBefore = container.height;
    >     > }
    >     > var requestParentLayout:Boolean = sizeChangedBeforeLayout
    >     > || sizeChangedDuringLayout
    >     >           || (!isNaN(container.percentWidth) && container.width <
    >     > container.measuredWidth) || (!isNaN(container.percentHeight) &&
    >     > container.height < container.measuredHeight);
    >     >         if (requestParentLayout && container.parent is Container) {
    >     > trace('requesting parent layout of ',(container as
    >     > Object).ROYALE_CLASS_INFO.names[0].qName );
    >     >             (container.parent as Container).layoutNeeded();
    >     >         }
    >     >     }
    >     >
    >     > That is pretty much it, and it is being used as a replacement in my
    > local
    >     > MXRoyale css for Container:
    >     >
    >     >  /*IBeadView:
    >     > ClassReference("org.apache.royale.html.beads.ContainerView");*/
    >     > IBeadView: ClassReference("mx.containers.beads.ContainerView");
    >     >
    >     > I'm not saying this is right, but it does help quite a bit with what
    > I am
    >     > facing.
    >     >
    >     > In addition to BoxLayout in general, I have been working on the
    >     > Grid/GridRow/GridItem layouts which are more specific in terms of
    > layout
    >     > changes needed, but also can have similar problems.
    >     >
    >     >
    >     > Although I am seeing improvements with what I have done so far, I'm
    > not
    >     > really satisfied with it, and I am keen for input/discussion (or
    >     > collaboration). I have been pursuing what I would mostly describe as
    > a
    >     > 'workaround' approach, so would welcome any thoughts on how best to
    > tackle
    >     > this.
    >     > I think there is something missing because of the way Flex does
    > layouts vs.
    >     > the way Royale does it, but I can't describe it fully yet. Perhaps
    > things
    >     > are only currently envisaged to work with mxml declarative content
    > onto
    >     > display and not so much with dynamic updates. But I think 
state-based
    >     > changes could have similar effects for some of these things if they
    > happen
    >     > inside containers that have their own percent dimensions.
    >     >
    >     >
    >     > Thanks,
    >     > Greg
    >     > From: Greg Dove<mailto:greg.d...@gmail.com>
    >     > Sent: Thursday, June 4, 2020 11:12 AM
    >     > To: Apache Royale Development<mailto:dev@royale.apache.org>
    >     > Subject: MXRoyale layout issues - questions/discussion
    >     >
    >     > Hi,
    >     >
    >     > Just wondered if anyone else is dealing with layout issues in Flex
    >     > emulation. I have some layout issues that are slowing my progress on
    > a
    >     > project, and I'd like to resolve them as quickly as I can.
    >     >
    >     > In particular, I see issues with BoxLayout-based containers which
    > have
    >     > percentWidth or percentHeight set. These don't get determined as
    > having
    >     > width or height 'SizedToContent' when performing layout, but in many
    >     > situations they behave in a similar way (they can change their size
    > based
    >     > on their content in terms of layout rules applied by the parent
    > container).
    >     > This is because in Flex, percentages are not simply a percentage of
    > their
    >     > parent, but they follow something perhaps a little closer to flexbox
    > layout
    >     > rules for all the percentWidth or percentHeight siblings (managed by
    > their
    >     > parent's layout). In other words, they are also related to the
    > measured
    >     > size of their content if the parent needs to manage them (I'm not
    > sure how
    >     > best to describe this, but I think that sort of captures it). They
    > can
    >     > expand beyond their percent allocation or contract below it
    > depending on
    >     > their measured sizes.
    >     > I think the layouts work downward for this, but changes in the
    > children
    >     > don't seem to trigger the parent layout.
    >     >
    >     > An example might be
    >     > <mx:HBox id='addThingsToMe' width='50%' />
    >     >
    >     > If you have the above at the application level (where the
    > application has
    >     > vertical layout) and keep adding buttons (for example) to the HBox
    > via a UI
    >     > test button that adds a new Button to that on each click, then it
    > should
    >     > expand horizontally greater than 50% width when the volume of 
buttons
    >     > exceeds its nominal 50% width. It is definitely easier to see this
    > if you
    >     > add a border to the container.
    >     >
    >     > I have been working on this, and made progress, but the approach I
    > am using
    >     > feels a bit patchwork, and just wondered whether others are seeing
    > anything
    >     > like this, and/or how it has been addressed elsewhere....
    >     >
    >     > Here's a summary of some of the things I have been trying, which do
    > yield
    >     > improvements, but don't really solve the problem completely:
    >     >
    >     > 1. added extra listener for 'childrenRemoved' in BoxLayout strand
    > setter.
    >     >
    >     > 2. Created a new mx 'ContainerView' class
    >     > (mx.containers.beads.ContainerView extends
    >     > org.apache.royale.html.beads.ContainerView)
    >     > This has the following in it:
    >     >
    >     > private var widthBefore:Number = -1
    >     > private var heightBefore:Number = -1;
    >     > private var sizeChangedBeforeLayout:Boolean;
    >     >
    >     > COMPILE::JS
    >     > override public function beforeLayout():Boolean
    >     > {
    >     > var container:Container = host as Container;
    >     >
    >     > sizeChangedBeforeLayout = (widthBefore != container.width ||
    > heightBefore
    >     > != container.height);
    >     > widthBefore = container.width;
    >     > heightBefore = container.height;
    >     > return super.beforeLayout();
    >     > }
    >     >
    >     >     COMPILE::JS
    >     >     override public function afterLayout():void
    >     >     {
    >     >         var container:Container = host as Container;
    >     > //size might change during layout
    >     > var sizeChangedDuringLayout:Boolean = !sizeChangedBeforeLayout &&
    >     > (widthBefore != container.width || heightBefore != 
container.height);
    >     > if (sizeChangedDuringLayout) {
    >     > //prepare for next time
    >     > widthBefore = container.width;
    >     > heightBefore = container.height;
    >     > }
    >     > var requestParentLayout:Boolean = sizeChangedBeforeLayout
    >     > || sizeChangedDuringLayout
    >     >           || (!isNaN(container.percentWidth) && container.width <
    >     > container.measuredWidth) || (!isNaN(container.percentHeight) &&
    >     > container.height < container.measuredHeight);
    >     >         if (requestParentLayout && container.parent is Container) {
    >     > trace('requesting parent layout of ',(container as
    >     > Object).ROYALE_CLASS_INFO.names[0].qName );
    >     >             (container.parent as Container).layoutNeeded();
    >     >         }
    >     >     }
    >     >
    >     > That is pretty much it, and it is being used as a replacement in my
    > local
    >     > MXRoyale css for Container:
    >     >
    >     >  /*IBeadView:
    >     > ClassReference("org.apache.royale.html.beads.ContainerView");*/
    >     > IBeadView: ClassReference("mx.containers.beads.ContainerView");
    >     >
    >     > I'm not saying this is right, but it does help quite a bit with what
    > I am
    >     > facing.
    >     >
    >     > In addition to BoxLayout in general, I have been working on the
    >     > Grid/GridRow/GridItem layouts which are more specific in terms of
    > layout
    >     > changes needed, but also can have similar problems.
    >     >
    >     >
    >     > Although I am seeing improvements with what I have done so far, I'm
    > not
    >     > really satisfied with it, and I am keen for input/discussion (or
    >     > collaboration). I have been pursuing what I would mostly describe as
    > a
    >     > 'workaround' approach, so would welcome any thoughts on how best to
    > tackle
    >     > this.
    >     > I think there is something missing because of the way Flex does
    > layouts vs.
    >     > the way Royale does it, but I can't describe it fully yet. Perhaps
    > things
    >     > are only currently envisaged to work with mxml declarative content
    > onto
    >     > display and not so much with dynamic updates. But I think 
state-based
    >     > changes could have similar effects for some of these things if they
    > happen
    >     > inside containers that have their own percent dimensions.
    >     >
    >     >
    >     > Thanks,
    >     > Greg
    >     >
    >     >
    >
    >
    >
    

Reply via email to