mirror of
https://github.com/chjj/blessed.git
synced 2026-02-06 13:51:52 +00:00
button and shrink work.
This commit is contained in:
parent
2c632522e7
commit
f0b107978b
38
README.md
38
README.md
@ -143,6 +143,7 @@ screen.render();
|
||||
Blessed comes with a number of high-level widgets so you can avoid all the
|
||||
nasty low-level terminal stuff.
|
||||
|
||||
|
||||
#### Node (from EventEmitter)
|
||||
|
||||
The base node which everything inherits from.
|
||||
@ -173,6 +174,7 @@ The base node which everything inherits from.
|
||||
- **remove(node)** - remove child node from node.
|
||||
- **detach()** - remove node from its parent.
|
||||
|
||||
|
||||
#### Screen (from Node)
|
||||
|
||||
The screen on which every other node renders.
|
||||
@ -218,6 +220,7 @@ The screen on which every other node renders.
|
||||
- **focusPush(element)** - push element on the focus stack (equivalent to `screen.focused = el`).
|
||||
- **focusPop()/focusLast()** - pop element off the focus stack.
|
||||
|
||||
|
||||
#### Element (from Node)
|
||||
|
||||
The base element.
|
||||
@ -277,6 +280,7 @@ The base element.
|
||||
- **toggle()** - toggle hidden/shown.
|
||||
- **focus()** - focus element.
|
||||
|
||||
|
||||
#### Box (from Element)
|
||||
|
||||
A box element which draws a simple box containing `content` or other elements.
|
||||
@ -296,6 +300,7 @@ An element similar to Box, but geared towards rendering simple text elements.
|
||||
|
||||
Inherits all options, properties, events, and methods from Element.
|
||||
|
||||
|
||||
#### Line (from Box)
|
||||
|
||||
A simple line which can be `ascii` or `bg` styled.
|
||||
@ -308,6 +313,7 @@ A simple line which can be `ascii` or `bg` styled.
|
||||
|
||||
Inherits all options, properties, events, and methods from Box.
|
||||
|
||||
|
||||
#### ScrollableBox (from Box)
|
||||
|
||||
A box with scrollable content.
|
||||
@ -334,6 +340,7 @@ A box with scrollable content.
|
||||
|
||||
- **scroll(offset)** - scroll the content by an offset.
|
||||
|
||||
|
||||
#### List (from ScrollableBox)
|
||||
|
||||
A scrollable list which can display selectable items.
|
||||
@ -367,6 +374,7 @@ A scrollable list which can display selectable items.
|
||||
- **up(amount)** - select item above selected.
|
||||
- **down(amount)** - select item below selected.
|
||||
|
||||
|
||||
#### ScrollableText (from ScrollableBox)
|
||||
|
||||
A scrollable text box which can display and scroll text, as well as handle pre-existing newlines and escape codes.
|
||||
@ -392,6 +400,7 @@ A scrollable text box which can display and scroll text, as well as handle pre-e
|
||||
|
||||
A form input.
|
||||
|
||||
|
||||
#### Textbox (from Input)
|
||||
|
||||
A box which allows text input.
|
||||
@ -416,6 +425,34 @@ A box which allows text input.
|
||||
- **setEditor(callback)** - open text editor in $EDITOR, read the output from the
|
||||
resulting file. takes a callback which receives the final value.
|
||||
|
||||
|
||||
#### Button (from Input)
|
||||
|
||||
A button which can be focused and allows key and mouse input.
|
||||
|
||||
##### Options:
|
||||
|
||||
- inherits all from Input.
|
||||
|
||||
##### Properties:
|
||||
|
||||
- inherits all from Input.
|
||||
|
||||
##### Events:
|
||||
|
||||
- inherits all from ScrollableBox.
|
||||
- **press** - received when the button is clicked/pressed.
|
||||
|
||||
##### Methods:
|
||||
|
||||
- inherits all from ScrollableBox.
|
||||
- **add(text)** - add an item based on a string.
|
||||
- **select(index)** - select an index of an item.
|
||||
- **move(offset)** - select item based on current offset.
|
||||
- **up(amount)** - select item above selected.
|
||||
- **down(amount)** - select item below selected.
|
||||
|
||||
|
||||
#### ProgressBar (from Input)
|
||||
|
||||
A progress bar allowing various styles.
|
||||
@ -443,6 +480,7 @@ A progress bar allowing various styles.
|
||||
- **progress(amount)** - progress the bar by a fill amount.
|
||||
- **reset()** - reset the bar.
|
||||
|
||||
|
||||
### Positioning
|
||||
|
||||
Offsets may be a number, a percentage (e.g. `50%`), or a keyword (e.g.
|
||||
|
||||
139
lib/widget.js
139
lib/widget.js
@ -438,7 +438,10 @@ Screen.prototype.draw = function(start, end) {
|
||||
}
|
||||
|
||||
if (bgColor !== 0x1ff) {
|
||||
if (bgColor < 16 || (this.tput && this.tput.colors <= 16)) {
|
||||
if (this.tput) {
|
||||
bgColor = this._reduceColor(bgColor);
|
||||
}
|
||||
if (bgColor < 16) {
|
||||
if (bgColor < 8) {
|
||||
bgColor += 40;
|
||||
} else if (bgColor < 16) {
|
||||
@ -452,7 +455,10 @@ Screen.prototype.draw = function(start, end) {
|
||||
}
|
||||
|
||||
if (fgColor !== 0x1ff) {
|
||||
if (fgColor < 16 || (this.tput && this.tput.colors <= 16)) {
|
||||
if (this.tput) {
|
||||
fgColor = this._reduceColor(fgColor);
|
||||
}
|
||||
if (fgColor < 16) {
|
||||
if (fgColor < 8) {
|
||||
fgColor += 30;
|
||||
} else if (fgColor < 16) {
|
||||
@ -489,6 +495,22 @@ Screen.prototype.draw = function(start, end) {
|
||||
this.program.restoreCursor();
|
||||
};
|
||||
|
||||
Screen.prototype._reduceColor = function(col) {
|
||||
if (this.tput) {
|
||||
if (col >= 16 && this.tput.colors <= 16) {
|
||||
//col = Screen.ccolors[col];
|
||||
if (col >= 244) col = colors.white;
|
||||
else if (col >= 232) col = colors.black;
|
||||
else col = colors.blue;
|
||||
} else if (col >= 8 && this.tput.colors <= 8) {
|
||||
col -= 8;
|
||||
} else if (col >= 2 && this.tput.colors <= 2) {
|
||||
col %= 2;
|
||||
}
|
||||
}
|
||||
return col;
|
||||
};
|
||||
|
||||
Screen.prototype.focus = function(offset) {
|
||||
if (!this.input.length || !offset) return;
|
||||
var i = this.input.indexOf(this.focused);
|
||||
@ -632,6 +654,8 @@ function Element(options) {
|
||||
if (type === 'mouse'
|
||||
|| type === 'click'
|
||||
|| type === 'hover'
|
||||
|| type === 'mouseover'
|
||||
|| type === 'mouseout'
|
||||
|| type === 'mousedown'
|
||||
|| type === 'mouseup'
|
||||
|| type === 'mousewheel'
|
||||
@ -697,11 +721,7 @@ Element.prototype.setContent = function(content) {
|
||||
var ret = this.render(true);
|
||||
// TODO: Maybe simply set _pcontent with _parseTags result.
|
||||
this.content = this._parseTags(content || '');
|
||||
this.screen.clearRegion(
|
||||
ret.xi + (this.border ? 1 : 0),
|
||||
ret.xl - (this.border ? 1 : 0),
|
||||
ret.yi + (this.border ? 1 : 0),
|
||||
ret.yl - (this.border ? 1 : 0));
|
||||
this.screen.clearRegion(ret.xi, ret.xl, ret.yi, ret.yl);
|
||||
};
|
||||
|
||||
// Convert `{red-fg}foo{/red-fg}` to `\x1b[31mfoo\x1b[39m`.
|
||||
@ -1021,6 +1041,19 @@ function Box(options) {
|
||||
|
||||
Box.prototype.__proto__ = Element.prototype;
|
||||
|
||||
Box.prototype._getShrinkSize = function(content) {
|
||||
var lines = content.replace(/\x1b\[[\d;]*m/g, '').split('\n');
|
||||
return {
|
||||
height: lines.length,
|
||||
width: lines.reduce(function(current, line) {
|
||||
return line.length > current
|
||||
? line.length //+ (lines.length > 1 ? 1 : 0) // for newlines
|
||||
: current;
|
||||
}, 0)
|
||||
};
|
||||
};
|
||||
|
||||
// Here be dragons.
|
||||
Box.prototype.render = function(stop) {
|
||||
// NOTE: Maybe move this `hidden` check down below `stop` check and return `ret`.
|
||||
if (this.hidden) return;
|
||||
@ -1065,19 +1098,48 @@ Box.prototype.render = function(stop) {
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE: Could simply change some offsets around and move this below the
|
||||
// shrink block. Could also stop passing a string to _getShrinkSize.
|
||||
if (this.align === 'center' || this.align === 'right') {
|
||||
var ncontent = content.split('\n')[0].replace(/\x1b\[[\d;]*m/g, '')
|
||||
, width = this.width;
|
||||
var ncontent = content.replace(/\x1b\[[\d;]*m/g, '')
|
||||
, width = this.width - (this.border ? 2 : 0) - this.padding * 2;
|
||||
if (ncontent.length < width) {
|
||||
var s = width - ncontent.length;
|
||||
if (this.align === 'center') {
|
||||
content = Array(((s / 2 | 0) - (this.border ? 1 : 0)) + 1).join(' ') + content;
|
||||
s = Array(((s / 2 | 0) - (this.border ? 1 : 0)) + 1).join(' ');
|
||||
content = s + content + (this.shrink ? s : '');
|
||||
//s = (s / 2 | 0) - (this.border ? 1 : 0);
|
||||
//ci -= s;
|
||||
//xl += s * 2;
|
||||
} else {
|
||||
content = Array((s - (this.border ? 2 : 0)) + 1).join(' ') + content;
|
||||
s -= this.left; // this shouldn't be necessary
|
||||
s = Array((s - (this.border ? 2 : 0)) + 1).join(' ');
|
||||
content = s + content;
|
||||
//s = s - (this.border ? 2 : 0);
|
||||
//ci -= s;
|
||||
//xl += s;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (this.shrink) {
|
||||
var hw = this._getShrinkSize(content)
|
||||
, h = hw.height
|
||||
, w = hw.width;
|
||||
if (this.options.left == null && this.options.right != null) {
|
||||
xi_ = xl - w - (this.border ? 2 : 0) - this.padding;
|
||||
//xi_--; // make it one cell wider for newlines
|
||||
} else {
|
||||
xl = xi_ + w + (this.border ? 2 : 0) + this.padding;
|
||||
//xl++; // make it one cell wider for newlines
|
||||
}
|
||||
if (this.options.top == null && this.options.bottom != null) {
|
||||
yi_ = yl - h - (this.border ? 2 : 0) - this.padding;
|
||||
} else {
|
||||
yl = yi_ + h + (this.border ? 2 : 0) + this.padding;
|
||||
}
|
||||
}
|
||||
|
||||
var ret = {
|
||||
xi: xi_,
|
||||
xl: xl,
|
||||
@ -1109,6 +1171,7 @@ Box.prototype.render = function(stop) {
|
||||
|
||||
if (this.border) yi_++, yl--, xi_++, xl--;
|
||||
|
||||
// TODO: Fix padding.
|
||||
if (this.padding) {
|
||||
yi_ += this.padding, yl -= this.padding;
|
||||
xi_ += this.padding, xl -= this.padding;
|
||||
@ -1121,12 +1184,6 @@ outer:
|
||||
cell = lines[yi][xi];
|
||||
if (!cell) break;
|
||||
|
||||
if (this.shrink && !content[ci] && yi === yi_) {
|
||||
// Need to subtract 1 and padding for below.
|
||||
xl = xi + 1 - 1 - this.padding;
|
||||
break outer;
|
||||
}
|
||||
|
||||
ch = content[ci++] || ' ';
|
||||
|
||||
// Handle escape codes.
|
||||
@ -1144,6 +1201,15 @@ outer:
|
||||
// Handle newlines.
|
||||
if (ch === '\t') ch = ' ';
|
||||
if (ch === '\n' || ch === '\r') {
|
||||
// If we're on the first cell and we find a newline and the last cell
|
||||
// of the last line was not a newline, let's just treat this like the
|
||||
// newline was already "counted".
|
||||
if (xi === xi_ && yi !== yi_ && content[ci-2] !== '\n') {
|
||||
xi--;
|
||||
continue;
|
||||
}
|
||||
// this.screen.fillRegion(attr, ' ', xi, xl, yi, yi + 1);
|
||||
// continue outer;
|
||||
ch = ' ';
|
||||
for (; xi < xl; xi++) {
|
||||
cell = lines[yi][xi];
|
||||
@ -1722,14 +1788,51 @@ Textarea.prototype.__proto__ = Input.prototype;
|
||||
*/
|
||||
|
||||
function Button(options) {
|
||||
var self = this;
|
||||
|
||||
if (!(this instanceof Button)) {
|
||||
return new Button(options);
|
||||
}
|
||||
|
||||
Input.call(this, options);
|
||||
|
||||
this.on('keypress', function(ch, key) {
|
||||
if (key.name === 'enter' || key.name === 'space') {
|
||||
self.press();
|
||||
}
|
||||
});
|
||||
|
||||
this.on('click', function() {
|
||||
self.press();
|
||||
});
|
||||
|
||||
this.on('mouseover', function() {
|
||||
self.inverse = !self.options.inverse;
|
||||
self.screen.render();
|
||||
});
|
||||
|
||||
this.on('mouseout', function() {
|
||||
self.inverse = self.options.inverse;
|
||||
self.screen.render();
|
||||
});
|
||||
}
|
||||
|
||||
Button.prototype.__proto__ = Input.prototype;
|
||||
|
||||
Button.prototype.press = function() {
|
||||
var self = this;
|
||||
this.emit('press');
|
||||
if (this.border) {
|
||||
var color = this.border.color;
|
||||
this.border.color = 2;
|
||||
this.screen.render();
|
||||
setTimeout(function() {
|
||||
self.border.color = color;
|
||||
self.screen.render();
|
||||
}, 300);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* ProgressBar
|
||||
*/
|
||||
@ -2002,6 +2105,7 @@ function convert(color) {
|
||||
var val = colors[color];
|
||||
if (val == null) val = color;
|
||||
if (val == null) val = -1;
|
||||
//if (typeof val === 'string') val = Screen._findColor(val);
|
||||
if (val === -1) return 0x1ff;
|
||||
return val;
|
||||
}
|
||||
@ -2029,5 +2133,6 @@ exports.List = List;
|
||||
exports.ScrollableText = ScrollableText;
|
||||
exports.Input = Input;
|
||||
exports.Textbox = Textbox;
|
||||
exports.Textarea = Textarea;
|
||||
exports.Button = Button;
|
||||
exports.ProgressBar = ProgressBar;
|
||||
|
||||
@ -9,7 +9,8 @@ screen.append(new blessed.Text({
|
||||
top: 0,
|
||||
left: 2,
|
||||
width: '100%',
|
||||
content: '{green-fg}Welcome{/green-fg} to my {red-bg,ul}program{/}',
|
||||
//bg: 'blue',
|
||||
content: '{green-fg}Welcome{/green-fg} to my {red-fg,ul}program{/red-fg,ul}',
|
||||
tags: true,
|
||||
align: 'center'
|
||||
}));
|
||||
@ -196,6 +197,28 @@ var input = new blessed.Textbox({
|
||||
|
||||
screen.append(input);
|
||||
|
||||
var button = blessed.Button({
|
||||
//content: 'Click me!',
|
||||
content: 'Click\nme!',
|
||||
shrink: true,
|
||||
border: {
|
||||
type: 'ascii'
|
||||
},
|
||||
fg: 'red',
|
||||
bg: 'blue',
|
||||
//height: 3,
|
||||
right: 4,
|
||||
//bottom: 6,
|
||||
bottom: 2,
|
||||
padding: 0
|
||||
});
|
||||
|
||||
button.on('press', function() {
|
||||
button.setContent('Clicked!');
|
||||
});
|
||||
|
||||
screen.append(button);
|
||||
|
||||
screen.on('keypress', function(ch, key) {
|
||||
if (key.name === 'tab') {
|
||||
return key.shift
|
||||
|
||||
Loading…
Reference in New Issue
Block a user