Re: MXRoyale layout issues - questions/discussion

2020-06-08 Thread Alex Harui
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

2020-06-08 Thread Greg Dove
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

2020-06-08 Thread Greg Dove
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

2020-06-08 Thread Carlos Rovira
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

2020-06-08 Thread Carlos Rovira
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

2020-06-08 Thread Alex Harui
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