add a distinct `grid` and `inline` layout. see #23.

This commit is contained in:
Christopher Jeffrey 2015-05-07 17:25:23 -07:00
parent f89e6661f3
commit e214141ccb
3 changed files with 94 additions and 19 deletions

View File

@ -1337,6 +1337,10 @@ By default, the Layout element automatically positions children as if they were
- __renderer__ - a callback which is called right before the children are
iterated over to be rendered. should return an iterator callback which is
called on each child element: __iterator(el, i)__.
- __layout__ - using the default renderer, it provides two layouts: inline, and
grid. `inline` is the default and will render akin to `inline-block`. `grid`
will create an automatic grid based on element dimensions. the grid cells'
width and height are always determined by the largest children in the layout.
##### Properties:

View File

@ -33,6 +33,8 @@ function Layout(options) {
throw new Error('`Layout` must have a width and height!');
}
options.layout = options.layout || 'inline';
Element.call(this, options);
if (options.renderer) {
@ -87,6 +89,15 @@ Layout.prototype.renderer = function(coords) {
// The index of the first child in the row
var rowIndex = 0;
var lastRowIndex = 0;
// Figure out the highest width child
if (this.options.layout === 'grid') {
var highWidth = this.children.reduce(function(out, el) {
out = Math.max(out, el.width);
return out;
}, 0);
}
return function iterator(el, i) {
// Make our children shrinkable. If they don't have a height, for
@ -106,6 +117,14 @@ Layout.prototype.renderer = function(coords) {
// rendered element. This child will end up directly to the right of it.
el.position.left = last.lpos.xl - xi;
// Make sure the position matches the highest width element
if (self.options.layout === 'grid') {
// Compensate with width:
// el.position.width = el.width + (highWidth - el.width);
// Compensate with position:
el.position.left += highWidth - (last.lpos.xl - last.lpos.xi);
}
// If our child does not overlap the right side of the Layout, set it's
// `top`/`y` to the current `rowOffset` (the coordinate for the current
// row).
@ -120,12 +139,32 @@ Layout.prototype.renderer = function(coords) {
out = Math.max(out, el.lpos.yl - el.lpos.yi);
return out;
}, 0);
lastRowIndex = rowIndex;
rowIndex = i;
el.position.left = 0;
el.position.top = rowOffset;
}
}
// Make sure the elements on lower rows graviatate up as much as possible
if (self.options.layout === 'inline') {
var above = null;
var abovea = Infinity;
for (var j = lastRowIndex; j < rowIndex; j++) {
var l = self.children[j];
if (!self.isRendered(l)) continue;
var abs = Math.abs(el.position.left - (l.lpos.xi - xi));
// if (abs < abovea && (l.lpos.xl - l.lpos.xi) <= el.width) {
if (abs < abovea) {
above = l;
abovea = abs;
}
}
if (above) {
el.position.top = above.lpos.yl - yi;
}
}
// If our child overflows the Layout, do not render it!
// Disable this feature for now.
if (el.position.top + el.height > height) {

View File

@ -14,6 +14,7 @@ var layout = blessed.layout({
width: '50%',
height: '50%',
border: 'line',
layout: 'inline',
style: {
bg: 'red',
border: {
@ -28,7 +29,8 @@ var box1 = blessed.box({
left: 'center',
width: 20,
height: 10,
border: 'line'
border: 'line',
content: '1'
});
var box2 = blessed.box({
@ -37,79 +39,108 @@ var box2 = blessed.box({
left: 0,
width: 10,
height: 5,
border: 'line'
border: 'line',
content: '2'
});
var box2 = blessed.box({
var box3 = blessed.box({
parent: layout,
top: 0,
left: 0,
width: 10,
height: 5,
border: 'line'
border: 'line',
content: '3'
});
var box2 = blessed.box({
var box4 = blessed.box({
parent: layout,
top: 0,
left: 0,
width: 10,
height: 5,
border: 'line'
border: 'line',
content: '4'
});
var box2 = blessed.box({
var box5 = blessed.box({
parent: layout,
top: 0,
left: 0,
width: 10,
height: 5,
border: 'line'
border: 'line',
content: '5'
});
var box2 = blessed.box({
var box6 = blessed.box({
parent: layout,
top: 0,
left: 0,
width: 10,
height: 5,
border: 'line'
border: 'line',
content: '6'
});
var box2 = blessed.box({
var box7 = blessed.box({
parent: layout,
top: 0,
left: 0,
width: 10,
height: 5,
border: 'line'
border: 'line',
content: '7'
});
var box1 = blessed.box({
var box8 = blessed.box({
parent: layout,
top: 'center',
left: 'center',
width: 20,
height: 10,
border: 'line'
border: 'line',
content: '8'
});
var box2 = blessed.box({
var box9 = blessed.box({
parent: layout,
top: 0,
left: 0,
width: 10,
height: 5,
border: 'line'
border: 'line',
content: '9'
});
var box1 = blessed.box({
var box10 = blessed.box({
parent: layout,
top: 'center',
left: 'center',
width: 20,
height: 10,
border: 'line'
border: 'line',
content: '10'
});
var box11 = blessed.box({
parent: layout,
top: 0,
left: 0,
width: 10,
height: 5,
border: 'line',
content: '11'
});
var box12 = blessed.box({
parent: layout,
top: 'center',
left: 'center',
width: 20,
height: 10,
border: 'line',
content: '12'
});
/*
@ -118,7 +149,8 @@ for (var i = 0; i < 10; i++) {
parent: layout,
width: i % 2 === 0 ? 10 : 20,
height: i % 2 === 0 ? 5 : 10,
border: 'line'
border: 'line',
content: (i + 1) + ''
});
}
*/