PDA

View Full Version : [FIXED][3.0rc1.1] hbox layout messing with form fields heights



usiw
9 May 2009, 5:50 AM
I am trying to achieve a flex based horizontal layout of fields and hbox is giving me issues. Here is what I am trying to achieve:


+-FormPanel-----------------------------------------+
| |
| +-FieldSet-(hbox layout)----------------------+ |
| | | |
| | TextField#1 [ ] TextField#2 [ ] | |
| | | |
| +---------------------------------------------+ |
| |
+---------------------------------------------------+

But what happens is the text fields inside the FieldSet show up as only a pixel or two high. I don't want to set the height as that is always an ugly workaround. Using a column layout resolves the issue but hbox should produce nearly identical results, just without the hassle of setting percentages. Here is the sample code:



var viewport = new Ext.Viewport({
items: {
xtype: 'form',
items: [{
xtype: 'fieldset',
title: 'Fieldset',
layout: 'hbox',
defaults: {
layout: 'form',
defaultType: 'textfield'
},
items: [{
flex: 1,
items: {
fieldLabel: 'Field 1'
}
}, {
flex: 1,
items: {
fieldLabel: 'Field 2'
}
}, {
flex: 1,
items: {
fieldLabel: 'Field 3'
}
}]

}]
}
});


Is this possibly a bug?

sven
9 May 2009, 7:09 AM
Setting the height is not a ugly workaround. It is needed. hbox and vbox are absolute positioning layouts.

usiw
10 May 2009, 5:36 PM
Once I resize the browser window and the panels refresh their layout it appears correct, or if I have the example in a tab and navigate away then back to the tab it appears correct. It appears that only on the first layout after render it has issues.

usiw
11 May 2009, 3:43 AM
From the conference it was explained that hbox is an easier-to-work-with column layout with advanced features (stretching, etc) and should produce the same result as :



var viewport = new Ext.Viewport({
items: {
xtype: 'form',
items: [{
xtype: 'fieldset',
title: 'Fieldset',
layout: 'column',
defaults: {
layout: 'form',
defaultType: 'textfield'
},
items: [{
columnWidth: 1/3,
items: {
fieldLabel: 'Field 1'
}
}, {
columnWidth: 1/3,
items: {
fieldLabel: 'Field 2'
}
}, {
columnWidth: 1/3,
items: {
fieldLabel: 'Field 3'
}
}]

}]
}
});

Maybe there is some confusion on the functionality since the documentation for 3.0 is still largely incomplete, at least in regards to the new features.

Condor
11 May 2009, 4:19 AM
Yes, it would seem that this is a bug.

HBoxLayout should be calculating the height AFTER setting the width.

Here is a patch:

Ext.override(Ext.layout.HBoxLayout, {
onLayout : function(ct, target){
Ext.layout.HBoxLayout.superclass.onLayout.call(this, ct, target);
var cs = ct.items.items, len = cs.length, c, i, last = len-1, cm;
var size = this.getTargetSize(target);
var w = size.width - target.getPadding('lr') - this.scrollOffset,
h = size.height - target.getPadding('tb'),
l = this.padding.left, t = this.padding.top;
if ((Ext.isIE && !Ext.isStrict) && (w < 1 || h < 1)) {
return;
} else if (w < 1 && h < 1) {
return;
}
var totalFlex = 0,
totalWidth = 0;
for(i = 0; i < len; i++){
c = cs[i];
cm = c.margins;
totalFlex += c.flex || 0;
totalWidth += c.getWidth() + cm.left + cm.right;
}
var extraWidth = w - totalWidth - this.padding.left - this.padding.right,
allocated = 0,
cw;
if(this.pack == 'center'){
l += extraWidth ? extraWidth/2 : 0;
}else if(this.pack == 'end'){
l += extraWidth;
}
for(i = 0; i < len; i++){
c = cs[i];
cm = c.margins;
cw = c.getWidth();
l += cm.left;
c.setPosition(l, t + cm.top);
if(this.pack == 'start' && c.flex){
var ratio = c.flex/totalFlex;
var add = Math.floor(extraWidth*ratio);
allocated += add;
if(i == last){
add += (extraWidth-allocated);
}
cw += add;
c.setWidth(cw);
}
l += cw + cm.right;
}
var stretchHeight = h - (this.padding.top + this.padding.bottom),
maxHeight = 0;
for(i = 0; i < len; i++){
c = cs[i];
cm = c.margins;
maxHeight = Math.max(maxHeight, c.getHeight() + cm.top + cm.bottom);
}
var innerCtHeight = maxHeight + this.padding.top + this.padding.bottom;
switch(this.align){
case 'stretch':
this.innerCt.setSize(w, h);
break;
case 'stretchmax':
case 'top':
this.innerCt.setSize(w, innerCtHeight);
break;
case 'middle':
this.innerCt.setSize(w, h = Math.max(h, innerCtHeight));
break;
}
var availableHeight = h - this.padding.top - this.padding.bottom;
for(i = 0; i < len; i++){
c = cs[i];
if(this.align == 'middle'){
var diff = availableHeight - (c.getHeight() + cm.top + cm.bottom);
if(diff > 0){
c.setPosition(c.x, t + cm.top + (diff/2));
}
}else if(this.align == 'stretch'){
c.setHeight((stretchHeight - (cm.top + cm.bottom)).constrain(
c.minHeight || 0, c.maxHeight || 1000000));
}else if(this.align == 'stretchmax'){
c.setHeight((maxHeight - (cm.top + cm.bottom)).constrain(
c.minHeight || 0, c.maxHeight || 1000000));
}
}
}
});

(and the same is true for VBoxLayout, but with width and height reversed)

ps. This patch will show a quick flicker while doing a layout with align:'center' (child items are first positioned at the top and moved to the center when the height is known).

evant
12 May 2009, 5:32 AM
Committed this change and the associated one for vbox.