sproutcore/sproutcore — pull request #1012 by mirion (2013-07-16 14:31:00+00:00)
Title: SC.FlowedLayout - when adding a child view, the layout is not calculated properly and the new child is positioned on top of others

The calculation of the layout is triggered by an observer on childViews. There are several aspects involved into this issue:

- Due to the special handling of childViews array, the observer is never triggered if attached with ".observes". For the observer to work, it has to be attached using "addObserver". Probably we could fix this special handling but I don't know if this would not bring more trouble.

- When changing the content of an array, since the array itself is not changing, the observer has to be attached on "childViews.[]"

It is very easy to reproduce the problem using a small app:

```javascript
TestPanelButton.mainPage = SC.Page.design({

// The main pane is made visible on screen as soon as your app is loaded.
// Add childViews to this pane for views to display immediately on page
// load.
mainPane: SC.MainPane.design({
childViews: ["fl", "fladd" ],

fl: SC.View.extend( SC.FlowedLayout, {
layout: { top: 250, right: 0, width: 200, height: 200 },
childViews: [ "fl1", "fl2" ],

fl1: SC.LabelView.extend( { layout: { width: 60, height: 24 }, value: "label 1" } ),
fl2: SC.LabelView.extend( { layout: { width: 60, height: 24 }, value: "label 2" } ),
} ),

fladd: SC.ButtonView.extend( {
layout: { top: 450, right: 0, width: 200, height: 24 },
title: "Add label - not working",
idx: 2,
action: function()
{
var newLabel = SC.LabelView.create( { layout: { width: 60, height: 24 }, value: "label " + ++this.idx } )

TestPanelButton.mainPage.mainPane.fl.appendChild( newLabel );
}
} )
})
});
```

I wrote a skeleton of test case but I don't know how exactly to fit it into the test configuration because in that context, any operation on the FlowedLayout triggers a reflow => the appearance of correctness

```javascript
test("Append child", function() {
var view = SC.View.create(SC.FlowedLayout, {
layout: { left: 0, top: 0, width: 400, height: 400 },
childViews: 'a'.w(),

a: SC.View.create({
layout: { width: 100, height: 100 }
})
});

view._doRender();
view._doAttach(document.body);

view.appendChild( SC.View.create({
layout: { width: 300, height: 100 }
}) );

view.appendChild( SC.View.create({
layout: { width: 200, height: 100 }
}) );

var expect = [
{ left: 0, top: 0, width: 100, height: 100 },
{ left: 100, top: 0, width: 300, height: 100 },
{ left: 0, top: 100, width: 200, height: 100 } ];

for( var i = 0; i < checkSteps.length; ++i )
if( checkSteps[ i ].name == 'final' )
checkSteps[ i ]( view, expect, null );

view.destroy();
});
```