PDA

View Full Version : What's the best way to make nested containers just as large as needed?



tboemker
2 Nov 2011, 10:56 AM
This code creates a vbox nested in an hbox, but the vbox is not allocated any height, so nothing is visible on screen:


App = Ext.extend(Ext.Viewport, {
initComponent: function(){
Ext.apply(this, {
layout: 'hbox',
items: [{
xtype: 'container',
layout: 'vbox',
items: [{
html: 'supercalifragilisticexpialidocious',
style: {
borderStyle: 'solid',
borderWidth: '1px'
}
}]
}]
});
App.superclass.initComponent.call(this);
}
});

Ext.onReady(function() {
app = new App();
app.show();
});

I read through some of the ExtJS code, and I see that the vbox layout results in a call to calculateChildBoxes to find the space needed by the innermost element, but that result is not being used to set the size of the vbox container.

I noticed that BoxLayout has a provision for an overflow handler, but the only one defined ("None") doesn't do anything. By defining my own overflow handler and changing one line of code in BoxLayout.onLayout, I was able to get the program to allocate space. Here's the revised code:


Ext.layout.boxOverflow.grow = Ext.extend(Object, {
constructor: function(layout, config) {
this.layout = layout;
Ext.apply(this, config || {});
},
handleOverflow: function(calcs, tSize) {
return {
targetSize: {
width: calcs.meta.maxWidth,
height: calcs.meta.minimumHeight // desiredHeight?
}
};
},
clearOverflow: Ext.emptyFn
});

App = Ext.extend(Ext.Viewport, {
initComponent: function(){
Ext.apply(this, {
layout: {
type: 'hbox',
overflowHandler: 'grow'
},
items: [{
xtype: 'container',
layout: {
type: 'vbox',
overflowHandler: 'grow'
},
items: [{
html: 'supercalifragilisticexpialidocious',
style: {
borderStyle: 'solid',
borderWidth: '1px'
}
}]
}]
});
App.superclass.initComponent.call(this);
}
});

Ext.onReady(function() {
app = new App();
app.show();
});

I modified BoxLayout.onLayout to call the overflow handler unconditionally:


onLayout: function(container, target) {
Ext.layout.BoxLayout.superclass.onLayout.call(this, container, target);

var tSize = this.getLayoutTargetSize(),
items = this.getVisibleItems(container),
calcs = this.calculateChildBoxes(items, tSize),
boxes = calcs.boxes,
meta = calcs.meta;

if (true) { // condition used to be tSize.width > 0
var handler = this.overflowHandler,
method = meta.tooNarrow ? 'handleOverflow' : 'clearOverflow';

var results = handler[method](calcs, tSize);

My code seems to work, but I think that maybe I'm going in the wrong direction, for the following reasons:

I had to modify ExtJS code (BoxLayout.onLayout).



The absence of any other pre-defined overflow handlers suggests that this feature was abandoned.



The fact that overflow handlers are all defined in Ext.layout.boxOverflow suggests that end users weren't expected to write their own.

Is there a better way to accomplish the same result?

mitchellsimoens
18 Nov 2011, 11:07 AM
VBox and HBox do not support auto sizing.

So for VBox, to do width you need to either specify the width of the children or use the align layout config. For height you have to specify a height or a flex.

For HBox, to do height you need to either specify the height of the children or use the align layout config. For width, you have ot specify a width or a flex.