[FlexJS] Layout Issue/Change

classic Classic list List threaded Threaded
7 messages Options
Reply | Threaded
Open this post in threaded view
|

[FlexJS] Layout Issue/Change

Peter Ent
Hi,

My main goal of the recent set of changes to containers and layouts was to make the HTML/CSS/JS side as minimal as possible, letting the browser and friends take care of things as much as possible. For the most part, I think it works.  But there is an issue that has been bothering me.

Right now, the LayoutBase class sets up event listeners on the layout host to automatically re-run the layout under certain conditions. The more I think about this the less PAYG it is and it is also inconsistent how things are handled.

The layout code is set up to recognize changes in the layout host's size. When that happens the layout is re-run. That, to me, is a good thing.

The layout code also waits for the initial "childrenAdded" event and if it sees it, the layout code will set event listeners for size changes on the children. If you later add children, those new children may not have listeners attached (this is an inconsistency). It is the responsibility of the app developer to dispatch a "layoutNeeded" event on the layout host to trigger the layout. Again, this is inconsistent as a component could dispatch "childrenAdded" while another component may not.

I see three possibilities here:


  1.  Do nothing with children (PAYG). The layout code would listen for size changes to the layout host, but it would not set up listeners on the children. An application that changes an items size or adds or removes an item will have to dispatch "layoutNeeded" on the item's (or items') parent. This way you can change a component frequently and only trigger its layout when the changes are complete.
  2.  Do everything (Pay Heavily). The layout code would really try to listen for all sorts of events on the layout host and respond to them.  The cost would be high however, if a large number of items were being changed inside of a loop: the layout code would be run for each pass of the loop.
  3.  Do everything, but wait (Partial Payment). The layout code would do the same as #2, but allow for updating loops. A number of systems have this: host.beginUpdate(); /* do a bunch of things */ host.endUpdate(). While the loop is running the layout would ask the host if it is OK to update and if not, the layout would not run. Once the endUpdate() was executed, the host would dispatch a final "layoutNeeded" and the layout would run once.

I am in favor of #1. It is in the spirit of PAYG and if you decided you needed either #2 or #3, you could extend a layout and build that yourself. Or we could add it to the Express package or something like that.

In choice 1, changing an item's size trigger's its own layout. If you have a Group with 100 elements, all of which are Groups themselves, and you were to resize each sub-Group in a loop, the resize of a sub-Group would trigger its layout. This is desired behavior. Once that loop has completed, the outer Group would also need its layout run to account of the newly resized children and that's where you do: outer.dispatchEvent(new Event("layoutNeeded")); In choice 2 or choice 3, each time a sub-Group was resized, the outer Group's layout would run for a total of 100 times, which may even cause some of the sub-Group's layouts to run again, depending on the layout algorithm.

If I were to remove the child event listeners in the layout code, any place your app or example that counted on the layout running, you would need to add a dispatch event for "layoutNeeded" if you did not resize the component.

I hope that made sense.
Peter

Reply | Threaded
Open this post in threaded view
|

Re: [FlexJS] Layout Issue/Change

piotrz
Hi Peter,

It look like we have partially implemented "layoutNeeded".

Your suggestion in #1 - is to completely remove current listeners which are dispatch "layoutNeeded". - Am I understand correctly ? - So if I will add children later - those will resize itself, but in order to correct parent resizing it will need to dispatch "layoutNeeded" ? Am I understand correctly ?

In case of #2 and #3 - I think both cases are good for express components, but Option #3 seems to me to complicated in case of later usage.  

Piotr
Reply | Threaded
Open this post in threaded view
|

Re: [FlexJS] Layout Issue/Change

Peter Ent
The current listeners in LayoutBase (Basic Project) are for the children
of a component. Right now, if you have a Group with 10 buttons and
VerticalLayout, and you resize one of those buttons,
LayoutBase/VerticalLayout will detect that and automatically re-run the
VerticalLayout algorithm.

What I propose is to eliminate those event listeners on the children. So
if you resize one of the buttons you will have dispatch "layoutNeeded" on
the Group to get the VerticalLayout to reformat the Group.

If you resize the Group, that will continue to re-run the layout.

Another example is FirstFlexibleChildHorizontalLayout (or whatever that's
called). If you delete that first child, the layout will not run. My
change will not affect this situation - you must still dispatch
"layoutNeeded" to get the layout to recalculate the next child as the
flexible item. On the JS side, this is crucial because this layout sets
flex-grow:1 on the first child and flex-grow:0 on the rest. When you
remove the first child, all children have flex-grow:0, so you must re-run
the layout.

This is the inconsistency: sometimes you need to dispatch "layoutNeeded"
and sometimes you do not. I propose you always dispatch "layoutNeeded"
whenever you add a child, remove a child, resize a child, or do anything
that would require the layout to run.

‹peter

On 5/1/17, 10:27 AM, "piotrz" <[hidden email]> wrote:

>Hi Peter,
>
>It look like we have partially implemented "layoutNeeded".
>
>Your suggestion in #1 - is to completely remove current listeners which
>are
>dispatch "layoutNeeded". - Am I understand correctly ? - So if I will add
>children later - those will resize itself, but in order to correct parent
>resizing it will need to dispatch "layoutNeeded" ? Am I understand
>correctly
>?
>
>In case of #2 and #3 - I think both cases are good for express components,
>but Option #3 seems to me to complicated in case of later usage.
>
>Piotr
>
>
>
>-----
>Apache Flex PMC
>[hidden email]
>--
>View this message in context:
>https://na01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fapache-fle
>x-development.2333347.n4.nabble.com%2FFlexJS-Layout-Issue-Change-tp61440p6
>1442.html&data=02%7C01%7C%7C3f4bcd255fbb43120cbc08d4909fcd58%7Cfa7b1b5a7b3
>4438794aed2c178decee1%7C0%7C0%7C636292463395237341&sdata=stp%2Fct7tHsUCkn8
>X5ZeFclHxbyIal3vC%2F5KUoRYin4Y%3D&reserved=0
>Sent from the Apache Flex Development mailing list archive at Nabble.com.

Reply | Threaded
Open this post in threaded view
|

Re: [FlexJS] Layout Issue/Change

Alex Harui
Without having looked at every layout, it does make sense to me that
LayoutBase should not need to watch children for size changes on the JS
side.  That's because the browser already has installed those listeners
and will re-calculate the layout as needed.  The SWF-side will continue to
need to watch the children since there is no runtime support for layout.

Even on the JS side, some layouts still need to "visit the children".
Basic needs to set position:absolute, the old VerticalLayout will set
display:block.  When is the right time to do that is up to the layout.
childrenAdded is a good time.

And even on the JS side, someone should still be allowed to write a layout
that doesn't rely on CSS and needs to visit the children and watch for
size changes in the children.

It is true that having display objects dispatch size changing events when
nobody is listening is wasteful.  There might be fancier ways for us to
make that more PAYG on the JS-side, but I don't think that is a priority
right now.

The original vision for "layoutNeeded" event is for "other scenarios".
That's why there is a LayoutChangeNotifier that allows you to set a
binding expression to trigger a layoutNeeded somewhere else when a
component's property changes, so we don't waste as much code watching for
things "just-in-case".

HTH,
-Alex

On 5/1/17, 7:59 AM, "Peter Ent" <[hidden email]> wrote:

>The current listeners in LayoutBase (Basic Project) are for the children
>of a component. Right now, if you have a Group with 10 buttons and
>VerticalLayout, and you resize one of those buttons,
>LayoutBase/VerticalLayout will detect that and automatically re-run the
>VerticalLayout algorithm.
>
>What I propose is to eliminate those event listeners on the children. So
>if you resize one of the buttons you will have dispatch "layoutNeeded" on
>the Group to get the VerticalLayout to reformat the Group.
>
>If you resize the Group, that will continue to re-run the layout.
>
>Another example is FirstFlexibleChildHorizontalLayout (or whatever that's
>called). If you delete that first child, the layout will not run. My
>change will not affect this situation - you must still dispatch
>"layoutNeeded" to get the layout to recalculate the next child as the
>flexible item. On the JS side, this is crucial because this layout sets
>flex-grow:1 on the first child and flex-grow:0 on the rest. When you
>remove the first child, all children have flex-grow:0, so you must re-run
>the layout.
>
>This is the inconsistency: sometimes you need to dispatch "layoutNeeded"
>and sometimes you do not. I propose you always dispatch "layoutNeeded"
>whenever you add a child, remove a child, resize a child, or do anything
>that would require the layout to run.
>
>‹peter
>
>On 5/1/17, 10:27 AM, "piotrz" <[hidden email]> wrote:
>
>>Hi Peter,
>>
>>It look like we have partially implemented "layoutNeeded".
>>
>>Your suggestion in #1 - is to completely remove current listeners which
>>are
>>dispatch "layoutNeeded". - Am I understand correctly ? - So if I will add
>>children later - those will resize itself, but in order to correct parent
>>resizing it will need to dispatch "layoutNeeded" ? Am I understand
>>correctly
>>?
>>
>>In case of #2 and #3 - I think both cases are good for express
>>components,
>>but Option #3 seems to me to complicated in case of later usage.
>>
>>Piotr
>>
>>
>>
>>-----
>>Apache Flex PMC
>>[hidden email]
>>--
>>View this message in context:
>>https://na01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fapache-fl
>>e
>>x-development.2333347.n4.nabble.com%2FFlexJS-Layout-Issue-Change-tp61440p
>>6
>>1442.html&data=02%7C01%7C%7C3f4bcd255fbb43120cbc08d4909fcd58%7Cfa7b1b5a7b
>>3
>>4438794aed2c178decee1%7C0%7C0%7C636292463395237341&sdata=stp%2Fct7tHsUCkn
>>8
>>X5ZeFclHxbyIal3vC%2F5KUoRYin4Y%3D&reserved=0
>>Sent from the Apache Flex Development mailing list archive at Nabble.com.
>

Reply | Threaded
Open this post in threaded view
|

Re: [FlexJS] Layout Issue/Change

piotrz
In reply to this post by Peter Ent
Understand. It is not bad changes in terms of complex layout.
I think this changes need to be done on feature branch. I would like to test it and see how it affects current examples.

Piotr
Reply | Threaded
Open this post in threaded view
|

Re: [FlexJS] Layout Issue/Change

Peter Ent
I'm trying to find the balance between PAYG and mimicking the HTML/JS/CSS
side on the SWF side.

Take HorizontalLayout for example. On the JS side, this layout waits for
"childrenAdded" and then changes each child's display style to
"inline-block". If you then programmatically change one child's width, the
browser automatically pushes the children apart to make room. Since the
Flash Player does not have that capability, the HorizontalLayout, SWF
version, must watch for changes in the size of the children and re-run the
layout. This is the mimicking part.

I put the children size watching into the LayoutBase, thinking it was a
common enough, frequent enough process that it could be done in the base
class. But that really is not the case. Each layout is different.

Plus, there is no provision in the base layout for watching for new
children or removed children. In the PAYG world, those feature would be
part of other layouts:

HorizontalLayoutWatchForAddChild
HorizontalLayoutWatchForRemoveChild
HorizontalLayoutWatchForAddAndRemoveChild

Here's the catch: going back to the HorizontalLayout, if you remove a
child, the browser will automatically reposition the children to close the
space left by the child removed. You do not need to write a specialty
layout to do. So for HorizontalLayout, do we including watching for
children added and removed because it mimics the browser or is it really a
specialty?

Right now, the event listeners watching for changes in the children are
multi-platform. A better, more PAYG approach (I think), is to make those
event listeners SWF-side only and they should be part of the layouts that
actually need them to mimic what the browser can do.

So perhaps that best thing to do now is wait for FlexJS 0.9 and try this
out an another branch to determine what the procedure should be.

‹peter


On 5/2/17, 2:52 AM, "piotrz" <[hidden email]> wrote:

>Understand. It is not bad changes in terms of complex layout.
>I think this changes need to be done on feature branch. I would like to
>test
>it and see how it affects current examples.
>
>Piotr
>
>
>
>-----
>Apache Flex PMC
>[hidden email]
>--
>View this message in context:
>https://na01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fapache-fle
>x-development.2333347.n4.nabble.com%2FFlexJS-Layout-Issue-Change-tp61440p6
>1459.html&data=02%7C01%7C%7Ce012b30ad5354126a6a908d491297b5e%7Cfa7b1b5a7b3
>4438794aed2c178decee1%7C0%7C0%7C636293054727198273&sdata=2NhFc2LDt8sTFE17K
>Ylnjms1oE6YvbWo6lFVcolThHk%3D&reserved=0
>Sent from the Apache Flex Development mailing list archive at Nabble.com.

Reply | Threaded
Open this post in threaded view
|

Re: [FlexJS] Layout Issue/Change

Alex Harui


On 5/2/17, 5:54 AM, "Peter Ent" <[hidden email]> wrote:
>Plus, there is no provision in the base layout for watching for new
>children or removed children. In the PAYG world, those feature would be
>part of other layouts:
>
>HorizontalLayoutWatchForAddChild
>HorizontalLayoutWatchForRemoveChild
>HorizontalLayoutWatchForAddAndRemoveChild

This is theoretically true, but in reality, because we have to listen for
children being added at startup time, all you need to offer as an option
is the watching for remove.

>
>Here's the catch: going back to the HorizontalLayout, if you remove a
>child, the browser will automatically reposition the children to close the
>space left by the child removed. You do not need to write a specialty
>layout to do. So for HorizontalLayout, do we including watching for
>children added and removed because it mimics the browser or is it really a
>specialty?

IMO, it isn't "specialty", it is PAYG.  We don't want to only offer
fully-implemented browser support.  It would be too big and slow and take
us a long time to write and test.  Many apps can be written without
removing a child, so that is an option for our customers.  Basic should
offer those choices, Express can default to the fattest, slowest,
feature-rich thing that still makes us look good.

>
>Right now, the event listeners watching for changes in the children are
>multi-platform. A better, more PAYG approach (I think), is to make those
>event listeners SWF-side only and they should be part of the layouts that
>actually need them to mimic what the browser can do.

IMO, LayoutBase on the SWF-side could always implement size change
listeners since it would be hard to write a layout without out.

>
>So perhaps that best thing to do now is wait for FlexJS 0.9 and try this
>out an another branch to determine what the procedure should be.

I think we have until the end of the week to finish features.  Next week
should be all bug fixing, and the following week will hopefully be the one
vote thread so we can get the release on the mirrors and have it propagate
before the Summit.  I don't have an opinion on whether this work should be
done before the release or not.

-Alex