Re: MXRoyale layout issues - questions/discussion
The changes in the ChildResize branch didn't take too long because it only hooked up re-layout for width/height changes in children. It doesn’t have the propagation of measurement changes because the test case didn't seem to need it. If you have a scenario where measurement does change then we can work on adding the propagation. Lots of components get an initial measured width/height of 0. Sometimes that's because offsetWidth/Height are 0 at initialization, sometimes it is because no content has been assigned yet. So the 0 trigger is sort of a hack to deal with that. It might go away if we implement the measurement change propagation. The getting of measuredWidth/Height was a way to call measure() on demand. But I think we'll end up shifting to calling measure() more often as properties that affect measurement change. It is tempting to have invalidateSize() immediately call measure() and then send an event if measurement changes, but I'm concerned that measure() might get called too often so we might just have setters call measure and send the event. For the existing code, my thinking was that components where 0 is a valid measuredWidth/Height would override the getter and do some other computation to return a valid number, including 0. HTH, -Alex On 6/8/20, 4:57 PM, "Greg Dove" wrote: Alex, I found another layout related issue to do with measurement. measuredWidth and measuredHeight can be zero as valid values. But the getters in UIComponent consider <= 0 as a trigger to re-evaluate the measurement. I'm assuming that we have the zero value to also re-trigger calculation (and not just NaN) in js for a specific reason. In that case I believe the following needs to be added to the measuredWidth and measuredHeight getters: e.g. inside public function get measuredHeight():Number the part that is like this: if (child) mh = Math.max(mh, child.getExplicitOrMeasuredHeight()); should, IMO, be like: if (child && child.includeInLayout) mh = Math.max(mh, child.getExplicitOrMeasuredHeight()); (Likewise, similar for measuredWidth) This fixes an issue in the app I am porting with containers where all children can have includeInLayout=false (and the measured height is assigned calculated and assigned as zero at the end of the BoxLayout's measure method, but then the getter on the target recalculates with a higher measuredHeight because it is still including the children which ought to be excluded from the calculation : includeInLayout=false) I'm tempted to make these changes in MXRoyale, but I don't know if others may be relying on the current behavior. What do you think? thanks, Greg On Tue, Jun 9, 2020 at 8:35 AM Greg Dove wrote: > Thanks Alex, that was quick! I will try to find time during my > Tuesday-Friday to work on this. Otherwise, if I can't get to it then, I can > definitely spend time on it during my next weekend. > > > On Mon, Jun 8, 2020 at 8:07 PM Alex Harui > wrote: > >> I pushed a branch called ChildResize. It seemed to make the example work >> much better, without even getting into measure() changes, possibly because >> the example doesn't really test measurement changes. >> >> IMO, to handle measurement changes, the measure() logic would dispatch >> some new event if the measureWidth/Height change. The BoxLayout would be >> listening, run its measure(), and dispatch that same event to its parent if >> it changes, and if it doesn't change, then run layout. That event would be >> listened for in the listenToChildren() method I added to BoxLayout. >> >> There should be a difference between measurement changes and setting >> width/height. If you set width/height on a child, then the child's layout >> should run. Assuming layout only runs if width/height change, then I think >> it shouldn't really matter that much if it runs before or after notifying >> the parent. The parent should honor the width/height so the child's layout >> shouldn't run again. The child can check isWidthSizedToContent() to >> determine if the parent needs notification. >> >> If you want to modify the test case to introduce a measurement change >> then we can try handling that. Feel free to try adding the measure() >> handling to the test case and to BoxLayout. Otherwise I will try to code >> it up sometime this week. >> >> HTH, >> -Alex >> >> On 6/7/20, 4:26 PM, "Greg Dove" wrote: >> >> > >> > That's my goal in the changes I'm playing with: to mimic the 2 >> passes. >> > We'll see how it goes. >> >> >> Ok, that's good to know. I hadn't picked up on it being that >> extensive. If >> there's anything
Re: MXRoyale layout issues - questions/discussion
Alex, I found another layout related issue to do with measurement. measuredWidth and measuredHeight can be zero as valid values. But the getters in UIComponent consider <= 0 as a trigger to re-evaluate the measurement. I'm assuming that we have the zero value to also re-trigger calculation (and not just NaN) in js for a specific reason. In that case I believe the following needs to be added to the measuredWidth and measuredHeight getters: e.g. inside public function get measuredHeight():Number the part that is like this: if (child) mh = Math.max(mh, child.getExplicitOrMeasuredHeight()); should, IMO, be like: if (child && child.includeInLayout) mh = Math.max(mh, child.getExplicitOrMeasuredHeight()); (Likewise, similar for measuredWidth) This fixes an issue in the app I am porting with containers where all children can have includeInLayout=false (and the measured height is assigned calculated and assigned as zero at the end of the BoxLayout's measure method, but then the getter on the target recalculates with a higher measuredHeight because it is still including the children which ought to be excluded from the calculation : includeInLayout=false) I'm tempted to make these changes in MXRoyale, but I don't know if others may be relying on the current behavior. What do you think? thanks, Greg On Tue, Jun 9, 2020 at 8:35 AM Greg Dove wrote: > Thanks Alex, that was quick! I will try to find time during my > Tuesday-Friday to work on this. Otherwise, if I can't get to it then, I can > definitely spend time on it during my next weekend. > > > On Mon, Jun 8, 2020 at 8:07 PM Alex Harui > wrote: > >> I pushed a branch called ChildResize. It seemed to make the example work >> much better, without even getting into measure() changes, possibly because >> the example doesn't really test measurement changes. >> >> IMO, to handle measurement changes, the measure() logic would dispatch >> some new event if the measureWidth/Height change. The BoxLayout would be >> listening, run its measure(), and dispatch that same event to its parent if >> it changes, and if it doesn't change, then run layout. That event would be >> listened for in the listenToChildren() method I added to BoxLayout. >> >> There should be a difference between measurement changes and setting >> width/height. If you set width/height on a child, then the child's layout >> should run. Assuming layout only runs if width/height change, then I think >> it shouldn't really matter that much if it runs before or after notifying >> the parent. The parent should honor the width/height so the child's layout >> shouldn't run again. The child can check isWidthSizedToContent() to >> determine if the parent needs notification. >> >> If you want to modify the test case to introduce a measurement change >> then we can try handling that. Feel free to try adding the measure() >> handling to the test case and to BoxLayout. Otherwise I will try to code >> it up sometime this week. >> >> HTH, >> -Alex >> >> On 6/7/20, 4:26 PM, "Greg Dove" wrote: >> >> > >> > That's my goal in the changes I'm playing with: to mimic the 2 >> passes. >> > We'll see how it goes. >> >> >> Ok, that's good to know. I hadn't picked up on it being that >> extensive. If >> there's anything I can help with, please let me know. >> >> On Mon, Jun 8, 2020 at 11:07 AM Alex Harui >> wrote: >> >> > Responses inline. >> > >> > On 6/7/20, 2:49 PM, "Greg Dove" wrote: >> > >> > > >> > > Turns out I was wrong and JS LayoutBase is not listening for >> > > widthChanged/heightChanged/sizeChanged. That was SWF-only >> code I saw >> > > earlier. IMO, that's the first thing to change by overriding >> > > handleChildrenAdded in BoxLayout and other MX Layouts. I >> don't >> > think Basic >> > > layouts need to watch children for size changes. >> > >> > Yeah, I mentioned that earlier. Not only was it swf-only, it >> was only >> > prior >> > to 'sawInitCompleted' (or whatever the exact name for that flag >> is, >> > going >> > from memory). >> > >> > I thought I'd read that in one of your posts but couldn't find it >> when I >> > looked for it. Anyway, the parent needs to listen to each child >> for some >> > event. >> > >> > For the 'handleChildrenAdded' thing it also needs to cover >> > 'handleChildrenRemoved'. Doing things this way would mean >> adding the 3 >> > size-related listeners on 'add' child and then removing them on >> > 'remove' >> > child. But I still think that could be avoidable. >> > Why? Because the children are already listening to these events >> for >> > their own layouts. Their own layouts respond to their size >> changes. So >> > the >> > question is : when does the parent need to know about the >> child's size >> > change: is it before it does
Re: MXRoyale layout issues - questions/discussion
Thanks Alex, that was quick! I will try to find time during my Tuesday-Friday to work on this. Otherwise, if I can't get to it then, I can definitely spend time on it during my next weekend. On Mon, Jun 8, 2020 at 8:07 PM Alex Harui wrote: > I pushed a branch called ChildResize. It seemed to make the example work > much better, without even getting into measure() changes, possibly because > the example doesn't really test measurement changes. > > IMO, to handle measurement changes, the measure() logic would dispatch > some new event if the measureWidth/Height change. The BoxLayout would be > listening, run its measure(), and dispatch that same event to its parent if > it changes, and if it doesn't change, then run layout. That event would be > listened for in the listenToChildren() method I added to BoxLayout. > > There should be a difference between measurement changes and setting > width/height. If you set width/height on a child, then the child's layout > should run. Assuming layout only runs if width/height change, then I think > it shouldn't really matter that much if it runs before or after notifying > the parent. The parent should honor the width/height so the child's layout > shouldn't run again. The child can check isWidthSizedToContent() to > determine if the parent needs notification. > > If you want to modify the test case to introduce a measurement change then > we can try handling that. Feel free to try adding the measure() handling > to the test case and to BoxLayout. Otherwise I will try to code it up > sometime this week. > > HTH, > -Alex > > On 6/7/20, 4:26 PM, "Greg Dove" wrote: > > > > > That's my goal in the changes I'm playing with: to mimic the 2 > passes. > > We'll see how it goes. > > > Ok, that's good to know. I hadn't picked up on it being that > extensive. If > there's anything I can help with, please let me know. > > On Mon, Jun 8, 2020 at 11:07 AM Alex Harui > wrote: > > > Responses inline. > > > > On 6/7/20, 2:49 PM, "Greg Dove" wrote: > > > > > > > > Turns out I was wrong and JS LayoutBase is not listening for > > > widthChanged/heightChanged/sizeChanged. That was SWF-only > code I saw > > > earlier. IMO, that's the first thing to change by overriding > > > handleChildrenAdded in BoxLayout and other MX Layouts. I don't > > think Basic > > > layouts need to watch children for size changes. > > > > Yeah, I mentioned that earlier. Not only was it swf-only, it was > only > > prior > > to 'sawInitCompleted' (or whatever the exact name for that flag > is, > > going > > from memory). > > > > I thought I'd read that in one of your posts but couldn't find it > when I > > looked for it. Anyway, the parent needs to listen to each child for > some > > event. > > > > For the 'handleChildrenAdded' thing it also needs to cover > > 'handleChildrenRemoved'. Doing things this way would mean adding > the 3 > > size-related listeners on 'add' child and then removing them on > > 'remove' > > child. But I still think that could be avoidable. > > Why? Because the children are already listening to these events > for > > their own layouts. Their own layouts respond to their size > changes. So > > the > > question is : when does the parent need to know about the > child's size > > change: is it before it does it's own layout, or after (and > could that > > requirement be different for some 'parent' layouts)? The child's > own > > layout > > process can inform the parent in either case via beforeLayout > (where > > the > > parent could even signal to the child not to continue its own > layout, > > in > > which case presumably the parent will simply 'take over') or > > afterLayout(), > > which could trigger a re-flow downwards from the parent - I > definitely > > did > > not do all this with the 'workaround' I already added, but maybe > there > > is > > something to this approach? On the other hand, if as you > suggest, the > > parent layouts are also adding their own listeners to each > child, then > > assuming the execution order of the size change listeners on the > > children > > will be deterministic in terms of when the parent layout runs its > > listener > > versus when the child's own layout runs its listener, it seems > to me > > that > > adding individual listeners to each of the children could be > doubling > > up on > > something that is already possible without doing that (just by > thinking > > about it in a different way : 'the children layouts are already > > listening > > to those events, and it is possible for them to talk to their > parent > > layouts'). > > If all
Re: new bead LayoutChildren for Jewel StyledLayoutBase
A final note. In Jewel most of the layouts are based on flex-box, so you don't need anything (as you already saw in TDJ). Tile layouts need to be aware of browser sizing, since they need to update margins and gaps on child elements depending on width or height container. I didn't find a way to do tile layout just using flexbox (not adding some as3/javascript code), and think it can't be done (if someone knows a way, please let me know). DataGridLayout is another layout that needs a mix of css flexbox and code. We probably will need to add grid css layout at some point, and that could make tile layout easier and just depend on browser. Until now I didn't want to add flexbox since it will mean not support IE11. But recently I saw there's some grid css polyfills out there. Maybe it wouldn't support all grid spec, but could be just what we need without left IE11 support. El lun., 8 jun. 2020 a las 10:24, Carlos Rovira () escribió: > Hi, > > continuing with sizing and layout. Just added "BrowserResizeListener" and > renamed the old one to "BrowserResizeApplicationListener" to avoid > confusion, since the latter can be used only at app level. > > About how to deal with browser resizing and make your inner components > respond accordingly. I found basically three ways to deal with > child layouts when you really needed and avoid performance issues running > code that you really not need. > > 1.- The best way is to add a "BrowserResizeListener" at component level, > so the rest of your app just uses the browser layout as usual. This will be > the best for the performance of your application since we are just running > code in the part we need. > > 2.- For layouts more in the "Flex style" where there's a chain of > parent-child layout calls you can: > >- Add "BrowserResizeApplicationListener" art app level >- Add width/height 100% to View level (notice that in a normal jewel >app we don't set up this to allow natural browser resizing) >- Then add "LayoutChildren" bead to any container/component in the >tree that need to signal a change in size and need to refresh layout. >(notice that this could mean to add this bead to many components down the >hierarchy, so this could be a bit cumbersome) > > This way seems to me not ideal, since it can inherit all Flex performance > problems since we'll be running lots of layout code that could not be > needed at all, but it will depend on your app. I recommend avoiding this > method if possible. > > 3.- (Basically a MIX of 1 & 2). You choose a part of the mxml tree where > you need to manage sizing and choose when you want to notify childrens: > >- Add "BrowserResizeListener" to the component/container you want >(that could have more subcomponents or containers in its subtree) >- Add "LayoutChildren" too in that component/container >- Add "LayoutChildren" to any component/container you need until you >reach the inner component that need to relayout to show in the right way. >This could be just few sub components in that tree, or all... Just notice >that you need "LayoutChildren" from the where "BrowserResizeListener" is >added down to the component that need to react to browser size changes. > > I tried three ways, but I think 1 is of course more simple to implement > and more performant. > > I think this way we have all sizing in Jewel under control. Let me know if > you find any issue we need to take into account. > > HTH > > Carlos > > > El dom., 7 jun. 2020 a las 21:52, Carlos Rovira () > escribió: > >> Hi, >> >> I added a new bead "LayoutChildren" that can be added to a jewel component >> if StyledLayoutBase detect this bead it will signal a "sizeChanged" for >> childs when needed. >> >> It uses the same technique as the itemrenderer initializers of composing >> the bead and in that case >> use its code. If no bead is added, no code is run. >> >> Until now Jewel was adding a loop in all layouts to manage child >> elements, but since we use browser layouts in many cases >> this loop is not needed and could cause a performance problem. >> >> So from now on, if you need that extra processing just add this bead to >> the component. >> >> A case of the use is in the recent change in TDJ in the second card of >> DataGridPlayGround >> >> Best >> >> >> -- >> Carlos Rovira >> http://about.me/carlosrovira >> >> > > -- > Carlos Rovira > http://about.me/carlosrovira > > -- Carlos Rovira http://about.me/carlosrovira
Re: new bead LayoutChildren for Jewel StyledLayoutBase
Hi, continuing with sizing and layout. Just added "BrowserResizeListener" and renamed the old one to "BrowserResizeApplicationListener" to avoid confusion, since the latter can be used only at app level. About how to deal with browser resizing and make your inner components respond accordingly. I found basically three ways to deal with child layouts when you really needed and avoid performance issues running code that you really not need. 1.- The best way is to add a "BrowserResizeListener" at component level, so the rest of your app just uses the browser layout as usual. This will be the best for the performance of your application since we are just running code in the part we need. 2.- For layouts more in the "Flex style" where there's a chain of parent-child layout calls you can: - Add "BrowserResizeApplicationListener" art app level - Add width/height 100% to View level (notice that in a normal jewel app we don't set up this to allow natural browser resizing) - Then add "LayoutChildren" bead to any container/component in the tree that need to signal a change in size and need to refresh layout. (notice that this could mean to add this bead to many components down the hierarchy, so this could be a bit cumbersome) This way seems to me not ideal, since it can inherit all Flex performance problems since we'll be running lots of layout code that could not be needed at all, but it will depend on your app. I recommend avoiding this method if possible. 3.- (Basically a MIX of 1 & 2). You choose a part of the mxml tree where you need to manage sizing and choose when you want to notify childrens: - Add "BrowserResizeListener" to the component/container you want (that could have more subcomponents or containers in its subtree) - Add "LayoutChildren" too in that component/container - Add "LayoutChildren" to any component/container you need until you reach the inner component that need to relayout to show in the right way. This could be just few sub components in that tree, or all... Just notice that you need "LayoutChildren" from the where "BrowserResizeListener" is added down to the component that need to react to browser size changes. I tried three ways, but I think 1 is of course more simple to implement and more performant. I think this way we have all sizing in Jewel under control. Let me know if you find any issue we need to take into account. HTH Carlos El dom., 7 jun. 2020 a las 21:52, Carlos Rovira () escribió: > Hi, > > I added a new bead "LayoutChildren" that can be added to a jewel component > if StyledLayoutBase detect this bead it will signal a "sizeChanged" for > childs when needed. > > It uses the same technique as the itemrenderer initializers of composing > the bead and in that case > use its code. If no bead is added, no code is run. > > Until now Jewel was adding a loop in all layouts to manage child elements, > but since we use browser layouts in many cases > this loop is not needed and could cause a performance problem. > > So from now on, if you need that extra processing just add this bead to > the component. > > A case of the use is in the recent change in TDJ in the second card of > DataGridPlayGround > > Best > > > -- > Carlos Rovira > http://about.me/carlosrovira > > -- Carlos Rovira http://about.me/carlosrovira
Re: MXRoyale layout issues - questions/discussion
I pushed a branch called ChildResize. It seemed to make the example work much better, without even getting into measure() changes, possibly because the example doesn't really test measurement changes. IMO, to handle measurement changes, the measure() logic would dispatch some new event if the measureWidth/Height change. The BoxLayout would be listening, run its measure(), and dispatch that same event to its parent if it changes, and if it doesn't change, then run layout. That event would be listened for in the listenToChildren() method I added to BoxLayout. There should be a difference between measurement changes and setting width/height. If you set width/height on a child, then the child's layout should run. Assuming layout only runs if width/height change, then I think it shouldn't really matter that much if it runs before or after notifying the parent. The parent should honor the width/height so the child's layout shouldn't run again. The child can check isWidthSizedToContent() to determine if the parent needs notification. If you want to modify the test case to introduce a measurement change then we can try handling that. Feel free to try adding the measure() handling to the test case and to BoxLayout. Otherwise I will try to code it up sometime this week. HTH, -Alex On 6/7/20, 4:26 PM, "Greg Dove" wrote: > > That's my goal in the changes I'm playing with: to mimic the 2 passes. > We'll see how it goes. Ok, that's good to know. I hadn't picked up on it being that extensive. If there's anything I can help with, please let me know. On Mon, Jun 8, 2020 at 11:07 AM Alex Harui wrote: > Responses inline. > > On 6/7/20, 2:49 PM, "Greg Dove" wrote: > > > > > Turns out I was wrong and JS LayoutBase is not listening for > > widthChanged/heightChanged/sizeChanged. That was SWF-only code I saw > > earlier. IMO, that's the first thing to change by overriding > > handleChildrenAdded in BoxLayout and other MX Layouts. I don't > think Basic > > layouts need to watch children for size changes. > > Yeah, I mentioned that earlier. Not only was it swf-only, it was only > prior > to 'sawInitCompleted' (or whatever the exact name for that flag is, > going > from memory). > > I thought I'd read that in one of your posts but couldn't find it when I > looked for it. Anyway, the parent needs to listen to each child for some > event. > > For the 'handleChildrenAdded' thing it also needs to cover > 'handleChildrenRemoved'. Doing things this way would mean adding the 3 > size-related listeners on 'add' child and then removing them on > 'remove' > child. But I still think that could be avoidable. > Why? Because the children are already listening to these events for > their own layouts. Their own layouts respond to their size changes. So > the > question is : when does the parent need to know about the child's size > change: is it before it does it's own layout, or after (and could that > requirement be different for some 'parent' layouts)? The child's own > layout > process can inform the parent in either case via beforeLayout (where > the > parent could even signal to the child not to continue its own layout, > in > which case presumably the parent will simply 'take over') or > afterLayout(), > which could trigger a re-flow downwards from the parent - I definitely > did > not do all this with the 'workaround' I already added, but maybe there > is > something to this approach? On the other hand, if as you suggest, the > parent layouts are also adding their own listeners to each child, then > assuming the execution order of the size change listeners on the > children > will be deterministic in terms of when the parent layout runs its > listener > versus when the child's own layout runs its listener, it seems to me > that > adding individual listeners to each of the children could be doubling > up on > something that is already possible without doing that (just by thinking > about it in a different way : 'the children layouts are already > listening > to those events, and it is possible for them to talk to their parent > layouts'). > If all the MXRoyale layouts were doing something like the 'measure if > needed' before the layout, then maybe it could actually mimic the 2 > passes > of the Flex approach, using beforeLayout() and afterLayout() to advise > the > parent layouts... just pondering this, not at all sure yet. > > I have concerns about using beforeLayout/afterLayout to trigger another > layout such as the "layout loop" I wrote