Hybrid View
-
9 Jun 2012 11:31 PM #1
custom layout issue - header height
custom layout issue - header height
Hello,
I've created custom container layout (it's basically gridbag layout from java compiled to javascript). My layout needs to take into account height of docked items at top/bottom of panel, typically panel header. For some reason, header height is calculated only after it's width is set. This leads to layout failure in some cases.
As a temporary fix, I'm setting header width to some large constant number. Layout calculation doesn't get stuck then and it also considerably reduces layout cycles and therefore makes layout calculation faster. But diag.js gives me warnings - [W] BAD! P1_header.width set by P1<dock> and P1<ux.gridbag>.
My question is : why does header need to know it's width to calculate
it's height? It should need it, because "text-overflow: ellipsis;
white-space: nowrap; overflow: hidden" styles ensure, that header text
will always be single line and fit into header box.
Thanks in advance,
-
10 Jun 2012 12:00 AM #2
The layout doesn't interrogate the css at all, you may need to give the header a hint by specifying the shrinkWrap config on the component. Check out the comments in AbstractComponent.
Evan Trimboli
Sencha Developer
Twitter - @evantrimboli
Don't be afraid of the source code!
-
10 Jun 2012 10:05 PM #3
The general situation is that text and what-not can wrap, so we wait for the width to be determined. We don't interrogate the CSS to determine if *all* markup in a component is free of wrapping, but there is a "noWrap" option (undocumented iirc) that can be used to tell the component layout about this... basically for the reasons you mention: fewer cycles and less waiting.
That said, from the sounds of things it appears that your layout may be not marking itself as unfinished (this.done = false) when values it needs aren't available. Either that or you are attempting to shrinkWrap width and something else isn't connecting properly.
Can you post the code of your custom layout? Simply setting noWrap may help in this test case, but it is hard to tell if it will be correct in general (so perhaps other use cases may still fail).
In general, to get a container layout spot-on, you need to be able to properly describe the way it will handle sizing of its items (getItemSizePolicy) and then make sure you handle you own size model combinations correctly as you calculate. It is an easy mistake to make thinking that the container layout is always in charge of sizing when in fact, it may depend on values from "outside" itself (configuration and/or ownerLayout).Don Griffin
Ext JS Development Team Lead
Check the docs. Learn how to (properly) report a framework issue and a Sencha Cmd issue
"Use the source, Luke!"
-
27 Jun 2012 3:13 AM #4
Let me explain a few more details.
I've compiled http://docs.oracle.com/javase/6/docs...BagLayout.html using GWT/gwt-exporter to javascript. Swing layout managers such as GridBagLayout need to know preferred size of child items. Preferred size of labels, form fields etc. is simply their natural size, for containers it is calculated recursively by layout algorithm.
For containers, my layout returns following item sizing policy {readsWidth: 0, readsHeight: 0, setsWidth: 1, setsHeight:1}, isItemShrinkWrap returns false. That means, that sizing policy of containers is calculated/calculated.
Here is simple example, where layout calculation succeeds.
First p1 calculates layout of it's content, then it adds size of docked items, that invalidates height (because panel header height is unknown), but width is still OK. Layout of pmain then sets width to p1 and the rest of layout is easily finished. Log of layout calculation is at http://pastebin.com/nZvKfQX6 .Code:var l1 = {xtype:'label', text:'LLL1', layoutConstraints:{gridx:0, gridy:0}}; var p1 = {id:'p1', title:'P1', layout:'ux.gridbag', layoutConstraints:{gridx:0, gridy:0}, items:[l1]}; var pmain = {id:'main', title: 'Main', layout:'ux.gridbag', items:[p1]}; Ext.create('Ext.Viewport', {id : 'es-mainviewport', layout : 'fit', items:[pmain]});
If I add one more level of nesting, layout calculation fails.
Again p1 calculates layout of it's content, then it adds size of docked items, that invalidates height, but width is still OK. Because preferred size of p1 is unknown, p2 cannot calculate it's preferred size and that causes layout calculation to fail. Log of layout calculation is at http://pastebin.com/Z3CQbLUw.Code:var l1 = {xtype:'label', text:'LLL1', layoutConstraints:{gridx:0, gridy:0}}; var p1 = {id:'p1', title:'P1', layout:'ux.gridbag', layoutConstraints:{gridx:0, gridy:0}, items:[l1]}; var p2 = {id:'p2', title:'P2', layout:'ux.gridbag', layoutConstraints:{gridx:0, gridy:0}, items:[p1]}; var pmain = {id:'main', title: 'Main', layout:'ux.gridbag', items:[p2]}; Ext.create('Ext.Viewport', {id : 'es-mainviewport', layout : 'fit', items:[pmain]});
Can I (or should I) set some attributes to panel header to indicate, that it's height doesn't depend on it's content?
I could solve this problem by separating width and height calculation in gridbag layout. But I would like to avoid doing that, because it shouldn't be necessary. In future, I may need to add another swing layout, in which separation of width and height calculation is not possible (for example http://docs.oracle.com/javase/6/docs...lowLayout.html ) .
I've encountered another problem with form fields. Item sizing policy for fields is {readsWidth: 1, readsHeight: 1, setsWidth: 1, setsHeight:1}, isItemShrinkWrap returns false. Sizing policy of fields is then calculatedFromNatural/calculatedFromNatural.
Layout calculation succeeds, but log contains messages [W] BAD! f1.width set by f1<textfield> and main<ux.gridbag> . Textfield updates it's width to value set by ux.gridbag layout, but combobox does not. Log of layout calculation is at http://pastebin.com/zEUqN6bt. What's the best way to fix this issue?Code:var f1 = {id:'f1', xtype:'textfield', layoutConstraints:{gridx:0, gridy:0, pref_size:{width:300}}}; var f2 = {id:'f2', xtype:'combo', layoutConstraints:{gridx:0, gridy:1, pref_size:{width:300}}}; var pmain = {id:'main', title: 'Main', layout:'ux.gridbag', items:[f1, f2]}; Ext.create('Ext.Viewport', {id : 'es-mainviewport', layout : 'fit', items:[pmain]});
-
6 Jul 2012 1:00 AM #5
What you are describing is similar in behavior to a Box layout (hbox and vbox) when "align" is set to "stretchmax". In fact, this is one of the most complex maneuvers in the layout system.
The key thing is that your layout both reads and writes the size of the children. You probably fully understand the write you need to do, but the read is when you request the component's "preferred size", which we would call its "shrinkWrap" size.
If the layout is going to calculate the size of a component, we do not waste time determining this value (it isn't free). The way you have this structured in your description, your layout is indicating that it will be calculating the size and that is the whole story.
I believe what you need to do is:
In your calculate method, you'll want to make make sure that you know whether or not you are being called before the child has determined its size or after. The easiest thing to do would be to structure your calculations in 2 phases: 1) allow the children to determine their shrinkWrap size; 2) invalidate the children that need to change size based on your calculations.PHP Code:isItemShrinkWrap: function (item) {
return true; // otherwise, width shrinkWrap will usually be disabled
},
_sizePolicy: {
readsWidth: 1,
readsHeight: 1,
setsWidth: 1,
setsHeight: 1
},
getItemSizePolicy: function (item) {
// unless items have some config options that influence this, you can
// just ignore the passed item.
return this._sizePolicy; // important - cache this :)
}
Again, this is 2-step process is most tricky. I highly recommend you study the Box layout and its calculateStretchMax method.
To be of much more help, you'll probably need to post the layout class as you have it.Don Griffin
Ext JS Development Team Lead
Check the docs. Learn how to (properly) report a framework issue and a Sencha Cmd issue
"Use the source, Luke!"
-
10 Jul 2012 10:13 PM #6
I moved this thread from the now read-only prerelease forum... apologies if you tried to reply.
Don Griffin
Ext JS Development Team Lead
Check the docs. Learn how to (properly) report a framework issue and a Sencha Cmd issue
"Use the source, Luke!"


Reply With Quote
