You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@flex.apache.org by Harbs <ha...@gmail.com> on 2017/07/31 10:42:10 UTC

FlexJS PAYG and layouts

Here’s a dilema I ran into this morning:

The OneFlexibleLayout beads have some code which look like this:
if (!contentView.element.style["align-items"])
    contentView.element.style["align-items"] = "center”;

What that does, is check if “align-items” is already set and sets it to center if not. I’m assuming the reason it sets it to center is because the default of flex-box is “stretch” which is not a very good default.

The problem is that center is not necessarily the best default either. I would have probably made flex-start the default. In fact, it looks like it is the default for swf is left. (flex-start is what I needed in my situation.)

I have just committed a change to make the JS consistent with the SWF. It now defaults to “flex-start” due to CSS defined on Container. I had to add a Container typename for all containers for this to work. I hope this is okay. I think it makes sense anyway, because otherwise, there’s no way to set custom CSS for all containers. If the style sets “center”, then that is honored to center it. The default can be overridden using CSS on the JS side, but it will not have an effect on the SWF side.

So far, so good.

Now my question is the follows: It seems kind of random that only alignItems:center does anything. I’d think that it should either support flex-start, flex-end,center and stretch or not do anything. I’d guess the answer is to create OneFlexibleLayoutWithAlignment?

The problem with that is we’d end up writing lots of duplicate code. In fact, I went through the different layout classes and the general pattern is constant across them:

1. Do something to the parent
2. Loop through the children, and do something to each one of them.

There are exceptions to this rule (such as the swf side of OneFlexibleChild layouts), but the majority of the layouts follow this pattern. I was thinking of the following idea to make it easier to modularize functionality and avoid code repeat:

Change LayoutBase to the following:

public function layout():Boolean
{
	var contentView:ILayoutView = layoutView;
	var n:int = contentView.numElements;
	if (n == 0) return false;
	if(!layoutParent())
		return false

	for(var i:int=0; i < n; i++) {
		var child:UIBase = contentView.getElementAt(i) as UIBase;
		if(!layoutChild(child))
			return false;
	}

	return true;
}
protected function layoutParent():Boolean{
    // override in subclass
	return false;
}
protected function layoutChild(child:UIBase):Boolean{
    // override in subclass
	return false;
}

Then in the subclasses, you would only override layout() if it does not follow this pattern. When it does, you would just override layoutParent() and layoutChild(). That has the following benefits:

1. You do not need to write the loop in every subclass.
2. Each subclass can use the pieces of the layout that make sense.
3. If a subclass is just adding additional functionality (such as setting the alignment of the children), it only needs to add code for that specific functionality without the need to either rewrite the layout function twice or make two loops.

Thoughts?
Harbs


Re: FlexJS PAYG and layouts

Posted by Harbs <ha...@gmail.com>.
I did think of the variable issues. Using instance variables does not generally strike me as problematic. (unless there’s a lot of them)

I did find some interesting articles on inlining vs function calling. Here’s one.[1]

Too many super calls might be bad because “call” can be expensive.

Yes. A more functional approach might be appropriate. Yishay had an interesting idea on maybe using CSS to apply functionality.

I’m going to sit on this one for a while and see if I come up with any brainstorms.

Harbs

[1]http://blog.calyptus.eu/seb/2011/01/javascript-call-performance-just-inline-it/ <http://blog.calyptus.eu/seb/2011/01/javascript-call-performance-just-inline-it/>

> On Jul 31, 2017, at 3:58 PM, Alex Harui <ah...@adobe.com.INVALID> wrote:
> 
> You're welcome to try different approaches to sharing code in the base
> classes.  Often, though, loops over children need to be inlined not only
> for performance reasons (to cut out one function call in the inner loop),
> but also for information sharing reasons (local variables accumulating
> values would now need to be instance variables).  But maybe a more
> functional programming style would work here.
> 
> OneFlexibleLayout probably shouldn't set align-items or any CSS styles at
> all on the JS side.  Those values should be set in CSS.  If the SWF side
> has to run this sort of code, that's the cost of emulating JS in SWF.  Or
> maybe we need a SWF-side layout base that truly tries to emulate browser
> behavior.
> 
> Also, for OneFlexible, there is no promise that it uses flex-box under the
> hood, it just has to solve what I found to be a hard problem in the
> browser (one stretchy thing), so the implementations for JS and SWF can be
> widely divergent.  If on the other hand we had a FlexBoxContainer, it
> would be the job of that code to emulate flex-box on the SWF side and do
> almost nothing on the JS side except set flex-box on the div.
> 
> My 2 cents,
> -Alex
> 
> On 7/31/17, 3:42 AM, "Harbs" <ha...@gmail.com> wrote:
> 
>> Here’s a dilema I ran into this morning:
>> 
>> The OneFlexibleLayout beads have some code which look like this:
>> if (!contentView.element.style["align-items"])
>>   contentView.element.style["align-items"] = "center”;
>> 
>> What that does, is check if “align-items” is already set and sets it to
>> center if not. I’m assuming the reason it sets it to center is because
>> the default of flex-box is “stretch” which is not a very good default.
>> 
>> The problem is that center is not necessarily the best default either. I
>> would have probably made flex-start the default. In fact, it looks like
>> it is the default for swf is left. (flex-start is what I needed in my
>> situation.)
>> 
>> I have just committed a change to make the JS consistent with the SWF. It
>> now defaults to “flex-start” due to CSS defined on Container. I had to
>> add a Container typename for all containers for this to work. I hope this
>> is okay. I think it makes sense anyway, because otherwise, there’s no way
>> to set custom CSS for all containers. If the style sets “center”, then
>> that is honored to center it. The default can be overridden using CSS on
>> the JS side, but it will not have an effect on the SWF side.
>> 
>> So far, so good.
>> 
>> Now my question is the follows: It seems kind of random that only
>> alignItems:center does anything. I’d think that it should either support
>> flex-start, flex-end,center and stretch or not do anything. I’d guess the
>> answer is to create OneFlexibleLayoutWithAlignment?
>> 
>> The problem with that is we’d end up writing lots of duplicate code. In
>> fact, I went through the different layout classes and the general pattern
>> is constant across them:
>> 
>> 1. Do something to the parent
>> 2. Loop through the children, and do something to each one of them.
>> 
>> There are exceptions to this rule (such as the swf side of
>> OneFlexibleChild layouts), but the majority of the layouts follow this
>> pattern. I was thinking of the following idea to make it easier to
>> modularize functionality and avoid code repeat:
>> 
>> Change LayoutBase to the following:
>> 
>> public function layout():Boolean
>> {
>> 	var contentView:ILayoutView = layoutView;
>> 	var n:int = contentView.numElements;
>> 	if (n == 0) return false;
>> 	if(!layoutParent())
>> 		return false
>> 
>> 	for(var i:int=0; i < n; i++) {
>> 		var child:UIBase = contentView.getElementAt(i) as UIBase;
>> 		if(!layoutChild(child))
>> 			return false;
>> 	}
>> 
>> 	return true;
>> }
>> protected function layoutParent():Boolean{
>>   // override in subclass
>> 	return false;
>> }
>> protected function layoutChild(child:UIBase):Boolean{
>>   // override in subclass
>> 	return false;
>> }
>> 
>> Then in the subclasses, you would only override layout() if it does not
>> follow this pattern. When it does, you would just override layoutParent()
>> and layoutChild(). That has the following benefits:
>> 
>> 1. You do not need to write the loop in every subclass.
>> 2. Each subclass can use the pieces of the layout that make sense.
>> 3. If a subclass is just adding additional functionality (such as setting
>> the alignment of the children), it only needs to add code for that
>> specific functionality without the need to either rewrite the layout
>> function twice or make two loops.
>> 
>> Thoughts?
>> Harbs
>> 
> 


Re: FlexJS PAYG and layouts

Posted by Alex Harui <ah...@adobe.com.INVALID>.
You're welcome to try different approaches to sharing code in the base
classes.  Often, though, loops over children need to be inlined not only
for performance reasons (to cut out one function call in the inner loop),
but also for information sharing reasons (local variables accumulating
values would now need to be instance variables).  But maybe a more
functional programming style would work here.

OneFlexibleLayout probably shouldn't set align-items or any CSS styles at
all on the JS side.  Those values should be set in CSS.  If the SWF side
has to run this sort of code, that's the cost of emulating JS in SWF.  Or
maybe we need a SWF-side layout base that truly tries to emulate browser
behavior.

Also, for OneFlexible, there is no promise that it uses flex-box under the
hood, it just has to solve what I found to be a hard problem in the
browser (one stretchy thing), so the implementations for JS and SWF can be
widely divergent.  If on the other hand we had a FlexBoxContainer, it
would be the job of that code to emulate flex-box on the SWF side and do
almost nothing on the JS side except set flex-box on the div.

My 2 cents,
-Alex

On 7/31/17, 3:42 AM, "Harbs" <ha...@gmail.com> wrote:

>Here’s a dilema I ran into this morning:
>
>The OneFlexibleLayout beads have some code which look like this:
>if (!contentView.element.style["align-items"])
>    contentView.element.style["align-items"] = "center”;
>
>What that does, is check if “align-items” is already set and sets it to
>center if not. I’m assuming the reason it sets it to center is because
>the default of flex-box is “stretch” which is not a very good default.
>
>The problem is that center is not necessarily the best default either. I
>would have probably made flex-start the default. In fact, it looks like
>it is the default for swf is left. (flex-start is what I needed in my
>situation.)
>
>I have just committed a change to make the JS consistent with the SWF. It
>now defaults to “flex-start” due to CSS defined on Container. I had to
>add a Container typename for all containers for this to work. I hope this
>is okay. I think it makes sense anyway, because otherwise, there’s no way
>to set custom CSS for all containers. If the style sets “center”, then
>that is honored to center it. The default can be overridden using CSS on
>the JS side, but it will not have an effect on the SWF side.
>
>So far, so good.
>
>Now my question is the follows: It seems kind of random that only
>alignItems:center does anything. I’d think that it should either support
>flex-start, flex-end,center and stretch or not do anything. I’d guess the
>answer is to create OneFlexibleLayoutWithAlignment?
>
>The problem with that is we’d end up writing lots of duplicate code. In
>fact, I went through the different layout classes and the general pattern
>is constant across them:
>
>1. Do something to the parent
>2. Loop through the children, and do something to each one of them.
>
>There are exceptions to this rule (such as the swf side of
>OneFlexibleChild layouts), but the majority of the layouts follow this
>pattern. I was thinking of the following idea to make it easier to
>modularize functionality and avoid code repeat:
>
>Change LayoutBase to the following:
>
>public function layout():Boolean
>{
>	var contentView:ILayoutView = layoutView;
>	var n:int = contentView.numElements;
>	if (n == 0) return false;
>	if(!layoutParent())
>		return false
>
>	for(var i:int=0; i < n; i++) {
>		var child:UIBase = contentView.getElementAt(i) as UIBase;
>		if(!layoutChild(child))
>			return false;
>	}
>
>	return true;
>}
>protected function layoutParent():Boolean{
>    // override in subclass
>	return false;
>}
>protected function layoutChild(child:UIBase):Boolean{
>    // override in subclass
>	return false;
>}
>
>Then in the subclasses, you would only override layout() if it does not
>follow this pattern. When it does, you would just override layoutParent()
>and layoutChild(). That has the following benefits:
>
>1. You do not need to write the loop in every subclass.
>2. Each subclass can use the pieces of the layout that make sense.
>3. If a subclass is just adding additional functionality (such as setting
>the alignment of the children), it only needs to add code for that
>specific functionality without the need to either rewrite the layout
>function twice or make two loops.
>
>Thoughts?
>Harbs
>