PDA

View Full Version : [FIXED][3.x] VBoxLayout bug with align:'center'



Animal
8 Dec 2009, 8:31 AM
The examples/layout/vbox.html does not align the buttons centered when you click the "Align : middle" button.

Fix:



Ext.override(Ext.layout.VBoxLayout, {
onLayout : function(ct, target){
Ext.layout.VBoxLayout.superclass.onLayout.call(this, ct, target);

var cs = this.getItems(ct), cm, ch, margin, cl, diff,
size = this.getTargetSize(target),
w = size.width - target.getPadding('lr'),
h = size.height - target.getPadding('tb') - this.scrollOffset,
l = this.padding.left, t = this.padding.top,
isStart = this.pack == 'start',
isRestore = ['stretch', 'stretchmax'].indexOf(this.align) == -1,
stretchWidth = w - (this.padding.left + this.padding.right),
extraHeight = 0,
maxWidth = 0,
totalFlex = 0,
flexHeight = 0,
usedHeight = 0,
idx = 0,
heights = [],
restore = [],
c,
csLen = cs.length;

// Do only width calculations and apply those first, as they can affect height
for (i = 0 ; i < csLen; i++) {
c = cs[i];
cm = c.margins;
margin = cm.top + cm.bottom;
maxWidth = Math.max(maxWidth, c.getWidth() + cm.left + cm.right);
}

var innerCtWidth = maxWidth + this.padding.left + this.padding.right;
switch(this.align){
case 'stretch':
this.innerCt.setSize(w, h);
break;
case 'stretchmax':
case 'left':
this.innerCt.setSize(innerCtWidth, h);
break;
case 'center':
this.innerCt.setSize(w = Math.max(w, innerCtWidth), h);
break;
}

var availableWidth = Math.max(0, w - this.padding.left - this.padding.right);
// Apply widths
for (i = 0 ; i < csLen; i++) {
c = cs[i];
cm = c.margins;
if(this.align == 'stretch'){
c.setWidth((stretchWidth - (cm.left + cm.right)).constrain(
c.minWidth || 0, c.maxWidth || 1000000));
}else if(this.align == 'stretchmax'){
c.setWidth((maxWidth - (cm.left + cm.right)).constrain(
c.minWidth || 0, c.maxWidth || 1000000));
}else{
if(this.align == 'center'){
var diff = availableWidth - (c.getWidth() + cm.left + cm.right);
if(diff > 0){
c.setPosition(l + cm.left + (diff/2), c.y);
}
}
if(isStart && c.flex){
c.setWidth(restore[idx++]);
}
}
}

// Do height calculations
for (i = 0 ; i < csLen; i++) {
c = cs[i];
cm = c.margins;
totalFlex += c.flex || 0;
ch = c.getHeight();
margin = cm.top + cm.bottom;
extraHeight += ch + margin;
flexHeight += margin + (c.flex ? 0 : ch);
}
extraHeight = h - extraHeight - this.padding.top - this.padding.bottom;

var availHeight = Math.max(0, h - this.padding.top - this.padding.bottom - flexHeight),
leftOver = availHeight;
for (i = 0 ; i < csLen; i++) {
c = cs[i];
if(isStart && c.flex){
ch = Math.floor(availHeight * (c.flex / totalFlex));
leftOver -= ch;
heights.push(ch);
}
}
if(this.pack == 'center'){
t += extraHeight ? extraHeight / 2 : 0;
}else if(this.pack == 'end'){
t += extraHeight;
}
idx = 0;
// Apply heights
for (i = 0 ; i < csLen; i++) {
c = cs[i];
cm = c.margins;
t += cm.top;
cl = l + cm.left // default left pos

// Adjust left pos for centering
if(this.align == 'center'){
if((diff = availableWidth - (c.getWidth() + cm.left + cm.right)) > 0){
cl += (diff/2);
}
}

c.setPosition(cl, t);
if(isStart && c.flex){
ch = Math.max(0, heights[idx++] + (leftOver-- > 0 ? 1 : 0));
if(isRestore){
restore.push(c.getWidth());
}
c.setSize(availableWidth, ch);
}else{
ch = c.getHeight();
}
t += ch + cm.bottom;
}
}
});

Jamie Avins
8 Dec 2009, 10:37 AM
Almost, but you need adjust the availableWidth by that diff so the flex will be correct. In the example, the Flex: All even and Flex: Ratio are broken. Looks like they have been broken because they are supposed to be centered...



Ext.override(Ext.layout.VBoxLayout, {
onLayout : function(ct, target){
Ext.layout.VBoxLayout.superclass.onLayout.call(this, ct, target);

var cs = this.getItems(ct), cm, ch, margin, cl, diff, aw,
size = this.getTargetSize(target),
w = size.width - target.getPadding('lr'),
h = size.height - target.getPadding('tb') - this.scrollOffset,
l = this.padding.left, t = this.padding.top,
isStart = this.pack == 'start',
isRestore = ['stretch', 'stretchmax'].indexOf(this.align) == -1,
stretchWidth = w - (this.padding.left + this.padding.right),
extraHeight = 0,
maxWidth = 0,
totalFlex = 0,
flexHeight = 0,
usedHeight = 0,
idx = 0,
heights = [],
restore = [],
c,
csLen = cs.length;

// Do only width calculations and apply those first, as they can affect height
for (i = 0 ; i < csLen; i++) {
c = cs[i];
cm = c.margins;
margin = cm.top + cm.bottom;
maxWidth = Math.max(maxWidth, c.getWidth() + cm.left + cm.right);
}

var innerCtWidth = maxWidth + this.padding.left + this.padding.right;
switch(this.align){
case 'stretch':
this.innerCt.setSize(w, h);
break;
case 'stretchmax':
case 'left':
this.innerCt.setSize(innerCtWidth, h);
break;
case 'center':
this.innerCt.setSize(w = Math.max(w, innerCtWidth), h);
break;
}

var availableWidth = Math.max(0, w - this.padding.left - this.padding.right);
// Apply widths
for (i = 0 ; i < csLen; i++) {
c = cs[i];
cm = c.margins;
if(this.align == 'stretch'){
c.setWidth((stretchWidth - (cm.left + cm.right)).constrain(
c.minWidth || 0, c.maxWidth || 1000000));
}else if(this.align == 'stretchmax'){
c.setWidth((maxWidth - (cm.left + cm.right)).constrain(
c.minWidth || 0, c.maxWidth || 1000000));
}else if(isStart && c.flex){
c.setWidth(restore[idx++]);
}

}

// Do height calculations
for (i = 0 ; i < csLen; i++) {
c = cs[i];
cm = c.margins;
totalFlex += c.flex || 0;
ch = c.getHeight();
margin = cm.top + cm.bottom;
extraHeight += ch + margin;
flexHeight += margin + (c.flex ? 0 : ch);
}
extraHeight = h - extraHeight - this.padding.top - this.padding.bottom;

var availHeight = Math.max(0, h - this.padding.top - this.padding.bottom - flexHeight),
leftOver = availHeight;
for (i = 0 ; i < csLen; i++) {
c = cs[i];
if(isStart && c.flex){
ch = Math.floor(availHeight * (c.flex / totalFlex));
leftOver -= ch;
heights.push(ch);
}
}
if(this.pack == 'center'){
t += extraHeight ? extraHeight / 2 : 0;
}else if(this.pack == 'end'){
t += extraHeight;
}
idx = 0;
// Apply heights
for (i = 0 ; i < csLen; i++) {
c = cs[i];
cm = c.margins;
t += cm.top;
aw = availableWidth;
cl = l + cm.left // default left pos

// Adjust left pos for centering
if(this.align == 'center'){
if((diff = availableWidth - (c.getWidth() + cm.left + cm.right)) > 0){
cl += (diff/2);
aw -= diff;
}
}

c.setPosition(cl, t);
if(isStart && c.flex){
ch = Math.max(0, heights[idx++] + (leftOver-- > 0 ? 1 : 0));
if(isRestore){
restore.push(c.getWidth());
}
c.setSize(aw, ch);
}else{
ch = c.getHeight();
}
t += ch + cm.bottom;
}
}
});

Jamie Avins
8 Dec 2009, 10:45 AM
Updated in 5753 and updated the example with more descriptive buttons.