Add background_color support for all existing wigets

pull/3/head
Florian Dehau 8 years ago
parent d038b283db
commit a36e20f217

@ -15,12 +15,13 @@ fn main() {
let stdin = io::stdin(); let stdin = io::stdin();
terminal.clear(); terminal.clear();
terminal.hide_cursor(); terminal.hide_cursor();
draw(&mut terminal);
for c in stdin.keys() { for c in stdin.keys() {
draw(&mut terminal);
let evt = c.unwrap(); let evt = c.unwrap();
if evt == event::Key::Char('q') { if evt == event::Key::Char('q') {
break; break;
} }
draw(&mut terminal);
} }
terminal.show_cursor(); terminal.show_cursor();
} }
@ -29,18 +30,38 @@ fn draw(t: &mut Terminal) {
Group::default() Group::default()
.direction(Direction::Vertical) .direction(Direction::Vertical)
.sizes(&[Size::Fixed(7), Size::Min(5), Size::Fixed(3)]) .sizes(&[Size::Fixed(7), Size::Min(0), Size::Fixed(7)])
.render(t, &Terminal::size().unwrap(), |t, chunks| { .render(t, &Terminal::size().unwrap(), |t, chunks| {
Block::default() Block::default()
.title("Block") .title("Top")
.title_color(Color::Red) .title_color(Color::Magenta)
.borders(border::ALL) .background_color(Color::White)
.border_color(Color::Magenta)
.borders(border::BOTTOM)
.render(&chunks[0], t); .render(&chunks[0], t);
Group::default() Group::default()
.direction(Direction::Vertical) .direction(Direction::Horizontal)
.sizes(&[Size::Fixed(7), Size::Min(5), Size::Fixed(3)]) .sizes(&[Size::Fixed(7), Size::Min(0), Size::Fixed(7)])
.render(t, &chunks[1], |t, chunks| { .render(t, &chunks[1], |t, chunks| {
Block::default().title("Block").render(&chunks[0], t); Block::default().title("Left").title_color(Color::Yellow).render(&chunks[0], t);
Block::default()
.title("Middle")
.title_color(Color::Cyan)
.border_color(Color::Cyan)
.borders(border::LEFT | border::RIGHT)
.render(&chunks[1], t);
Block::default()
.title("Right")
.title_color(Color::Green)
.render(&chunks[2], t);
}); });
Block::default()
.title("Bottom")
.title_color(Color::Red)
.border_color(Color::Red)
.borders(border::TOP)
.render(&chunks[2], t);
}); });
t.finish();
} }

@ -70,9 +70,10 @@ impl SinSignal {
impl Iterator for SinSignal { impl Iterator for SinSignal {
type Item = (f64, f64); type Item = (f64, f64);
fn next(&mut self) -> Option<(f64, f64)> { fn next(&mut self) -> Option<Self::Item> {
let point = (self.x, (self.x * 1.0 / self.period).sin() * self.scale);
self.x += self.interval; self.x += self.interval;
Some((self.x, ((self.x * 1.0 / self.period).sin() + 1.0) * self.scale)) Some(point)
} }
} }
@ -131,7 +132,7 @@ fn main() {
info!("Start"); info!("Start");
let mut rand_signal = RandomSignal::new(Range::new(0, 100)); let mut rand_signal = RandomSignal::new(Range::new(0, 100));
let mut sin_signal = SinSignal::new(1.0, 4.0, 20.0); let mut sin_signal = SinSignal::new(0.2, 5.0, 20.0);
let mut sin_signal2 = SinSignal::new(0.1, 2.0, 10.0); let mut sin_signal2 = SinSignal::new(0.1, 2.0, 10.0);
let mut app = App { let mut app = App {
@ -149,7 +150,7 @@ fn main() {
show_chart: true, show_chart: true,
progress: 0, progress: 0,
data: rand_signal.clone().take(200).collect(), data: rand_signal.clone().take(200).collect(),
data2: sin_signal.clone().take(30).collect(), data2: sin_signal.clone().take(100).collect(),
data3: sin_signal2.clone().take(200).collect(), data3: sin_signal2.clone().take(200).collect(),
data4: vec![("B1", 9), data4: vec![("B1", 9),
("B2", 12), ("B2", 12),
@ -173,7 +174,7 @@ fn main() {
let (tx, rx) = mpsc::channel(); let (tx, rx) = mpsc::channel();
let input_tx = tx.clone(); let input_tx = tx.clone();
for _ in 0..30 { for _ in 0..100 {
sin_signal.next(); sin_signal.next();
} }
for _ in 0..200 { for _ in 0..200 {
@ -246,12 +247,12 @@ fn main() {
} }
app.data.insert(0, rand_signal.next().unwrap()); app.data.insert(0, rand_signal.next().unwrap());
app.data.pop(); app.data.pop();
app.data2.remove(0); for _ in 0..5 {
app.data2.push(sin_signal.next().unwrap()); app.data2.remove(0);
for _ in 0..10 { app.data2.push(sin_signal.next().unwrap());
app.data3.remove(0);
} }
for _ in 0..10 { for _ in 0..10 {
app.data3.remove(0);
app.data3.push(sin_signal2.next().unwrap()); app.data3.push(sin_signal2.next().unwrap());
} }
let i = app.data4.pop().unwrap(); let i = app.data4.pop().unwrap();
@ -279,6 +280,7 @@ fn draw(t: &mut Terminal, app: &App) {
Tabs::default() Tabs::default()
.block(Block::default().borders(border::ALL).title("Tabs")) .block(Block::default().borders(border::ALL).title("Tabs"))
.titles(&app.tabs.titles) .titles(&app.tabs.titles)
.color(Color::Green)
.highlight_color(Color::Yellow) .highlight_color(Color::Yellow)
.select(app.tabs.selection) .select(app.tabs.selection)
.render(&chunks[0], t); .render(&chunks[0], t);
@ -292,15 +294,22 @@ fn draw(t: &mut Terminal, app: &App) {
.sizes(&[Size::Percent(50), Size::Percent(50)]) .sizes(&[Size::Percent(50), Size::Percent(50)])
.render(t, &chunks[1], |t, chunks| { .render(t, &chunks[1], |t, chunks| {
Table::default() Table::default()
.block(Block::default().title("Servers").borders(border::ALL)) .block(Block::default()
.titles(&["Server", "Location", "Status"]) .title("Servers")
.borders(border::ALL))
.header(&["Server", "Location", "Status"])
.header_color(Color::Red)
.widths(&[20, 20, 20]) .widths(&[20, 20, 20])
.rows(&[&["Europe#1", "Paris", "Up"], .rows(&[&["Europe#1", "Paris", "Up"],
&["Europe#2", "Berlin", "Up"]]) &["Europe#2", "Berlin", "Up"]])
.color(Color::Green)
.render(&chunks[0], t); .render(&chunks[0], t);
Canvas::default() Canvas::default()
.block(Block::default().title("World").borders(border::ALL)) .block(Block::default().title("World").borders(border::ALL))
.layers(&[&[Map::default().resolution(MapResolution::High)]]) .layers(&[&[&Map {
color: Color::Green,
resolution: MapResolution::High,
}]])
.x_bounds([-180.0, 180.0]) .x_bounds([-180.0, 180.0])
.y_bounds([-90.0, 90.0]) .y_bounds([-90.0, 90.0])
.render(&chunks[1], t); .render(&chunks[1], t);
@ -360,8 +369,8 @@ fn draw_main(t: &mut Terminal, app: &App, area: &Rect) {
.title("List")) .title("List"))
.items(&app.items) .items(&app.items)
.select(app.selected) .select(app.selected)
.selection_color(Color::Yellow) .highlight_color(Color::Yellow)
.selection_symbol(">") .highlight_symbol(">")
.render(&chunks[0], t); .render(&chunks[0], t);
List::default() List::default()
.block(Block::default() .block(Block::default()
@ -395,8 +404,8 @@ fn draw_main(t: &mut Terminal, app: &App, area: &Rect) {
.y_axis(Axis::default() .y_axis(Axis::default()
.title("Y Axis") .title("Y Axis")
.color(Color::Gray) .color(Color::Gray)
.bounds([0.0, 40.0]) .bounds([-25.0, 25.0])
.labels(&["0", "20", "40"])) .labels(&["-25", "0", "25"]))
.datasets(&[Dataset::default() .datasets(&[Dataset::default()
.marker(Marker::Dot) .marker(Marker::Dot)
.color(Color::Cyan) .color(Color::Cyan)
@ -411,9 +420,9 @@ fn draw_main(t: &mut Terminal, app: &App, area: &Rect) {
Text::default() Text::default()
.block(Block::default().borders(border::ALL).title("Footer")) .block(Block::default().borders(border::ALL).title("Footer"))
.wrap(true) .wrap(true)
.fg(app.colors[app.color_index]) .color(app.colors[app.color_index])
.text("This a paragraph with several lines.\nYou can change the \ .text("This is a paragraph with several lines.\nYou can change the \
color.\nUse \\{[color] [text]} to highlight the text with the \ color.\nUse \\{[color] [text]} to highlight the text with a \
color. For example, {red u}{green n}{yellow d}{magenta e}{cyan r} \ color. For example, {red u}{green n}{yellow d}{magenta e}{cyan r} \
{gray t}{light_gray h}{light_red e} {light_green r}{light_yellow \ {gray t}{light_gray h}{light_red e} {light_green r}{light_yellow \
a}{light_magenta i}{light_cyan n}{white b}{red o}{green w}.\nOh, \ a}{light_magenta i}{light_cyan n}{white b}{red o}{green w}.\nOh, \

@ -16,6 +16,7 @@ pub struct BarChart<'a> {
bar_color: Color, bar_color: Color,
value_color: Color, value_color: Color,
label_color: Color, label_color: Color,
background_color: Color,
data: &'a [(&'a str, u64)], data: &'a [(&'a str, u64)],
values: Vec<String>, values: Vec<String>,
} }
@ -25,13 +26,14 @@ impl<'a> Default for BarChart<'a> {
BarChart { BarChart {
block: None, block: None,
max: None, max: None,
data: &[],
values: Vec::new(),
bar_width: 1, bar_width: 1,
bar_gap: 1, bar_gap: 1,
bar_color: Color::Reset, bar_color: Color::Reset,
value_color: Color::Reset, value_color: Color::Reset,
label_color: Color::Reset, label_color: Color::Reset,
data: &[], background_color: Color::Reset,
values: Vec::new(),
} }
} }
} }
@ -75,6 +77,10 @@ impl<'a> BarChart<'a> {
self.label_color = color; self.label_color = color;
self self
} }
pub fn background_color(&'a mut self, color: Color) -> &mut BarChart<'a> {
self.background_color = color;
self
}
} }
impl<'a> Widget for BarChart<'a> { impl<'a> Widget for BarChart<'a> {
@ -91,6 +97,10 @@ impl<'a> Widget for BarChart<'a> {
return; return;
} }
if self.background_color != Color::Reset {
self.background(&chart_area, buf, self.background_color);
}
let max = self.max.unwrap_or(self.data.iter().fold(0, |acc, &(_, v)| max(v, acc))); let max = self.max.unwrap_or(self.data.iter().fold(0, |acc, &(_, v)| max(v, acc)));
let max_index = min((chart_area.width / (self.bar_width + self.bar_gap)) as usize, let max_index = min((chart_area.width / (self.bar_width + self.bar_gap)) as usize,
self.data.len()); self.data.len());
@ -119,7 +129,7 @@ impl<'a> Widget for BarChart<'a> {
chart_area.top() + j, chart_area.top() + j,
symbol, symbol,
self.bar_color, self.bar_color,
Color::Reset); self.background_color);
} }
if d.1 > 8 { if d.1 > 8 {
@ -149,7 +159,7 @@ impl<'a> Widget for BarChart<'a> {
label, label,
self.bar_width as usize, self.bar_width as usize,
self.label_color, self.label_color,
Color::Reset); self.background_color);
} }
} }
} }

@ -6,11 +6,11 @@ use symbols::line;
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
pub struct Block<'a> { pub struct Block<'a> {
title: Option<&'a str>, pub title: Option<&'a str>,
title_color: Color, pub title_color: Color,
borders: border::Flags, pub borders: border::Flags,
border_color: Color, pub border_color: Color,
bg: Color, pub background_color: Color,
} }
impl<'a> Default for Block<'a> { impl<'a> Default for Block<'a> {
@ -20,7 +20,7 @@ impl<'a> Default for Block<'a> {
title_color: Color::Reset, title_color: Color::Reset,
borders: border::NONE, borders: border::NONE,
border_color: Color::Reset, border_color: Color::Reset,
bg: Color::Reset, background_color: Color::Reset,
} }
} }
} }
@ -41,8 +41,8 @@ impl<'a> Block<'a> {
self self
} }
pub fn bg(mut self, color: Color) -> Block<'a> { pub fn background_color(mut self, color: Color) -> Block<'a> {
self.bg = color; self.background_color = color;
self self
} }
@ -81,27 +81,47 @@ impl<'a> Widget for Block<'a> {
return; return;
} }
if self.background_color != Color::Reset {
self.background(area, buf, self.background_color)
}
// Sides // Sides
if self.borders.intersects(border::LEFT) { if self.borders.intersects(border::LEFT) {
for y in area.top()..area.bottom() { for y in area.top()..area.bottom() {
buf.set_cell(area.left(), y, line::VERTICAL, self.border_color, self.bg); buf.set_cell(area.left(),
y,
line::VERTICAL,
self.border_color,
self.background_color);
} }
} }
if self.borders.intersects(border::TOP) { if self.borders.intersects(border::TOP) {
for x in area.left()..area.right() { for x in area.left()..area.right() {
buf.set_cell(x, area.top(), line::HORIZONTAL, self.border_color, self.bg); buf.set_cell(x,
area.top(),
line::HORIZONTAL,
self.border_color,
self.background_color);
} }
} }
if self.borders.intersects(border::RIGHT) { if self.borders.intersects(border::RIGHT) {
let x = area.right() - 1; let x = area.right() - 1;
for y in area.top()..area.bottom() { for y in area.top()..area.bottom() {
buf.set_cell(x, y, line::VERTICAL, self.border_color, self.bg); buf.set_cell(x,
y,
line::VERTICAL,
self.border_color,
self.background_color);
} }
} }
if self.borders.intersects(border::BOTTOM) { if self.borders.intersects(border::BOTTOM) {
let y = area.bottom() - 1; let y = area.bottom() - 1;
for x in area.left()..area.right() { for x in area.left()..area.right() {
buf.set_cell(x, y, line::HORIZONTAL, self.border_color, self.bg); buf.set_cell(x,
y,
line::HORIZONTAL,
self.border_color,
self.background_color);
} }
} }
@ -137,7 +157,7 @@ impl<'a> Widget for Block<'a> {
title, title,
width as usize, width as usize,
self.title_color, self.title_color,
self.bg); self.background_color);
} }
} }
} }

@ -19,8 +19,8 @@ impl MapResolution {
} }
pub struct Map { pub struct Map {
resolution: MapResolution, pub resolution: MapResolution,
color: Color, pub color: Color,
} }
impl Default for Map { impl Default for Map {
@ -41,13 +41,6 @@ impl<'a> Shape<'a> for Map {
} }
} }
impl Map {
pub fn resolution(&mut self, resolution: MapResolution) -> &mut Map {
self.resolution = resolution;
self
}
}
impl<'a> IntoIterator for &'a Map { impl<'a> IntoIterator for &'a Map {
type Item = (f64, f64); type Item = (f64, f64);
type IntoIter = PointsIterator<'a>; type IntoIter = PointsIterator<'a>;

@ -29,6 +29,7 @@ pub struct Canvas<'a> {
x_bounds: [f64; 2], x_bounds: [f64; 2],
y_bounds: [f64; 2], y_bounds: [f64; 2],
layers: &'a [&'a [&'a Shape<'a>]], layers: &'a [&'a [&'a Shape<'a>]],
background_color: Color,
} }
impl<'a> Default for Canvas<'a> { impl<'a> Default for Canvas<'a> {
@ -38,6 +39,7 @@ impl<'a> Default for Canvas<'a> {
x_bounds: [0.0, 0.0], x_bounds: [0.0, 0.0],
y_bounds: [0.0, 0.0], y_bounds: [0.0, 0.0],
layers: &[], layers: &[],
background_color: Color::Reset,
} }
} }
} }
@ -59,6 +61,11 @@ impl<'a> Canvas<'a> {
self.layers = layers; self.layers = layers;
self self
} }
pub fn background_color(&'a mut self, color: Color) -> &mut Canvas<'a> {
self.background_color = color;
self
}
} }
impl<'a> Widget for Canvas<'a> { impl<'a> Widget for Canvas<'a> {
@ -81,17 +88,17 @@ impl<'a> Widget for Canvas<'a> {
for layer in self.layers { for layer in self.layers {
let mut grid: Vec<u16> = vec![BRAILLE_OFFSET; width * height + 1]; let mut grid: Vec<u16> = vec![BRAILLE_OFFSET; width * height];
let mut colors: Vec<Color> = vec![Color::Reset; width * height + 1]; let mut colors: Vec<Color> = vec![Color::Reset; width * height];
for shape in layer.iter() { for shape in layer.iter() {
for (x, y) in shape.points().filter(|&(x, y)| { for (x, y) in shape.points().filter(|&(x, y)| {
!(x < x_bounds[0] || x > x_bounds[1] || y < y_bounds[0] || y > y_bounds[1]) !(x < x_bounds[0] || x > x_bounds[1] || y < y_bounds[0] || y > y_bounds[1])
}) { }) {
let dy = ((self.y_bounds[1] - y) * canvas_area.height as f64 * 4.0 / let dy = ((self.y_bounds[1] - y) * (canvas_area.height - 1) as f64 * 4.0 /
(self.y_bounds[1] - (self.y_bounds[1] -
self.y_bounds[0])) as usize; self.y_bounds[0])) as usize;
let dx = ((x - self.x_bounds[0]) * canvas_area.width as f64 * 2.0 / let dx = ((x - self.x_bounds[0]) * (canvas_area.width - 1) as f64 * 2.0 /
(self.x_bounds[1] - (self.x_bounds[1] -
self.x_bounds[0])) as usize; self.x_bounds[0])) as usize;
let index = dy / 4 * width + dx / 2; let index = dy / 4 * width + dx / 2;
@ -100,8 +107,7 @@ impl<'a> Widget for Canvas<'a> {
} }
} }
let mut string = String::from_utf16(&grid).unwrap(); let string = String::from_utf16(&grid).unwrap();
string.pop();
for (i, (ch, color)) in string.chars().zip(colors.into_iter()).enumerate() { for (i, (ch, color)) in string.chars().zip(colors.into_iter()).enumerate() {
if ch != BRAILLE_BLANK { if ch != BRAILLE_BLANK {
let (x, y) = (i % width, i / width); let (x, y) = (i % width, i / width);
@ -111,7 +117,7 @@ impl<'a> Widget for Canvas<'a> {
c.symbol.clear(); c.symbol.clear();
c.symbol.push(ch); c.symbol.push(ch);
c.fg = color; c.fg = color;
c.bg = Color::Reset; c.bg = self.background_color;
}); });
} }
} }

@ -131,7 +131,7 @@ pub struct Chart<'a> {
x_axis: Axis<'a>, x_axis: Axis<'a>,
y_axis: Axis<'a>, y_axis: Axis<'a>,
datasets: &'a [Dataset<'a>], datasets: &'a [Dataset<'a>],
bg: Color, background_color: Color,
} }
impl<'a> Default for Chart<'a> { impl<'a> Default for Chart<'a> {
@ -140,7 +140,7 @@ impl<'a> Default for Chart<'a> {
block: None, block: None,
x_axis: Axis::default(), x_axis: Axis::default(),
y_axis: Axis::default(), y_axis: Axis::default(),
bg: Color::Reset, background_color: Color::Reset,
datasets: &[], datasets: &[],
} }
} }
@ -152,8 +152,8 @@ impl<'a> Chart<'a> {
self self
} }
pub fn bg(&mut self, bg: Color) -> &mut Chart<'a> { pub fn background_color(&mut self, background_color: Color) -> &mut Chart<'a> {
self.bg = bg; self.background_color = background_color;
self self
} }
@ -237,18 +237,22 @@ impl<'a> Widget for Chart<'a> {
let layout = self.layout(&chart_area); let layout = self.layout(&chart_area);
let graph_area = layout.graph_area; let graph_area = layout.graph_area;
if graph_area.width == 0 || graph_area.height == 0 { if graph_area.width < 1 || graph_area.height < 1 {
return; return;
} }
if self.background_color != Color::Reset {
self.background(&chart_area, buf, self.background_color);
}
if let Some((x, y)) = layout.legend_x { if let Some((x, y)) = layout.legend_x {
let title = self.x_axis.title.unwrap(); let title = self.x_axis.title.unwrap();
buf.set_string(x, y, title, self.x_axis.title_color, self.bg); buf.set_string(x, y, title, self.x_axis.title_color, self.background_color);
} }
if let Some((x, y)) = layout.legend_y { if let Some((x, y)) = layout.legend_y {
let title = self.y_axis.title.unwrap(); let title = self.y_axis.title.unwrap();
buf.set_string(x, y, title, self.y_axis.title_color, self.bg); buf.set_string(x, y, title, self.y_axis.title_color, self.background_color);
} }
if let Some(y) = layout.label_x { if let Some(y) = layout.label_x {
@ -263,7 +267,7 @@ impl<'a> Widget for Chart<'a> {
y, y,
label, label,
self.x_axis.labels_color, self.x_axis.labels_color,
self.bg); self.background_color);
} }
} }
} }
@ -278,26 +282,38 @@ impl<'a> Widget for Chart<'a> {
graph_area.bottom() - 1 - dy, graph_area.bottom() - 1 - dy,
label, label,
self.y_axis.labels_color, self.y_axis.labels_color,
self.bg); self.background_color);
} }
} }
} }
if let Some(y) = layout.axis_x { if let Some(y) = layout.axis_x {
for x in graph_area.left()..graph_area.right() { for x in graph_area.left()..graph_area.right() {
buf.set_cell(x, y, symbols::line::HORIZONTAL, self.x_axis.color, self.bg); buf.set_cell(x,
y,
symbols::line::HORIZONTAL,
self.x_axis.color,
self.background_color);
} }
} }
if let Some(x) = layout.axis_y { if let Some(x) = layout.axis_y {
for y in graph_area.top()..graph_area.bottom() { for y in graph_area.top()..graph_area.bottom() {
buf.set_cell(x, y, symbols::line::VERTICAL, self.y_axis.color, self.bg); buf.set_cell(x,
y,
symbols::line::VERTICAL,
self.y_axis.color,
self.background_color);
} }
} }
if let Some(y) = layout.axis_x { if let Some(y) = layout.axis_x {
if let Some(x) = layout.axis_y { if let Some(x) = layout.axis_y {
buf.set_cell(x, y, symbols::line::BOTTOM_LEFT, self.x_axis.color, self.bg); buf.set_cell(x,
y,
symbols::line::BOTTOM_LEFT,
self.x_axis.color,
self.background_color);
} }
} }
@ -309,20 +325,23 @@ impl<'a> Widget for Chart<'a> {
y < self.y_axis.bounds[0] || y < self.y_axis.bounds[0] ||
y > self.y_axis.bounds[1]) y > self.y_axis.bounds[1])
}) { }) {
let dy = (self.y_axis.bounds[1] - y) * graph_area.height as f64 / let dy = ((self.y_axis.bounds[1] - y) * (graph_area.height - 1) as f64 /
(self.y_axis.bounds[1] - self.y_axis.bounds[0]); (self.y_axis.bounds[1] -
let dx = (x - self.x_axis.bounds[0]) * graph_area.width as f64 / self.y_axis.bounds[0])) as u16;
(self.x_axis.bounds[1] - self.x_axis.bounds[0]); let dx = ((x - self.x_axis.bounds[0]) * (graph_area.width - 1) as f64 /
(self.x_axis.bounds[1] -
buf.set_cell(dx as u16 + graph_area.left(), self.x_axis.bounds[0])) as u16;
dy as u16 + graph_area.top(),
buf.set_cell(graph_area.left() + dx,
graph_area.top() + dy,
symbols::BLACK_CIRCLE, symbols::BLACK_CIRCLE,
dataset.color, dataset.color,
self.bg); self.background_color);
} }
} }
Marker::Braille => { Marker::Braille => {
Canvas::default() Canvas::default()
.background_color(self.background_color)
.x_bounds(self.x_axis.bounds) .x_bounds(self.x_axis.bounds)
.y_bounds(self.y_axis.bounds) .y_bounds(self.y_axis.bounds)
.layers(&[&[&Points { .layers(&[&[&Points {

@ -70,28 +70,32 @@ impl<'a> Widget for Gauge<'a> {
}; };
if gauge_area.height < 1 { if gauge_area.height < 1 {
return; return;
} else { }
// Gauge
let width = (gauge_area.width * self.percent) / 100;
let end = gauge_area.left() + width;
for x in gauge_area.left()..end { if self.background_color != Color::Reset {
buf.set_symbol(x, gauge_area.top(), " "); self.background(&gauge_area, buf, self.background_color);
} }
// Label // Gauge
let label = format!("{}%", self.percent); let width = (gauge_area.width * self.percent) / 100;
let label_width = label.width() as u16; let end = gauge_area.left() + width;
let middle = (gauge_area.width - label_width) / 2 + gauge_area.left();
buf.set_string(middle,
gauge_area.top(),
&label,
self.color,
self.background_color);
for x in gauge_area.left()..end { for x in gauge_area.left()..end {
buf.set_colors(x, gauge_area.top(), self.background_color, self.color); buf.set_symbol(x, gauge_area.top(), " ");
} }
// Label
let label = format!("{}%", self.percent);
let label_width = label.width() as u16;
let middle = (gauge_area.width - label_width) / 2 + gauge_area.left();
buf.set_string(middle,
gauge_area.top(),
&label,
self.color,
self.background_color);
for x in gauge_area.left()..end {
buf.set_colors(x, gauge_area.top(), self.background_color, self.color);
} }
} }
} }

@ -9,24 +9,24 @@ use style::Color;
pub struct List<'a> { pub struct List<'a> {
block: Option<Block<'a>>, block: Option<Block<'a>>,
items: &'a [&'a str],
selected: usize, selected: usize,
selection_symbol: Option<&'a str>,
selection_color: Color,
color: Color, color: Color,
background_color: Color, background_color: Color,
items: &'a [&'a str], highlight_color: Color,
highlight_symbol: Option<&'a str>,
} }
impl<'a> Default for List<'a> { impl<'a> Default for List<'a> {
fn default() -> List<'a> { fn default() -> List<'a> {
List { List {
block: None, block: None,
items: &[],
selected: 0, selected: 0,
selection_symbol: None,
selection_color: Color::Reset,
color: Color::Reset, color: Color::Reset,
background_color: Color::Reset, background_color: Color::Reset,
items: &[], highlight_color: Color::Reset,
highlight_symbol: None,
} }
} }
} }
@ -52,13 +52,13 @@ impl<'a> List<'a> {
self self
} }
pub fn selection_symbol(&'a mut self, selection_symbol: &'a str) -> &mut List<'a> { pub fn highlight_symbol(&'a mut self, highlight_symbol: &'a str) -> &mut List<'a> {
self.selection_symbol = Some(selection_symbol); self.highlight_symbol = Some(highlight_symbol);
self self
} }
pub fn selection_color(&'a mut self, selection_color: Color) -> &mut List<'a> { pub fn highlight_color(&'a mut self, highlight_color: Color) -> &mut List<'a> {
self.selection_color = selection_color; self.highlight_color = highlight_color;
self self
} }
@ -79,10 +79,14 @@ impl<'a> Widget for List<'a> {
None => *area, None => *area,
}; };
if list_area.height < 1 { if list_area.width < 1 || list_area.height < 1 {
return; return;
} }
if self.background_color != Color::Reset {
self.background(&list_area, buf, self.background_color);
}
let list_length = self.items.len(); let list_length = self.items.len();
let list_height = list_area.height as usize; let list_height = list_area.height as usize;
let bound = min(list_height, list_length); let bound = min(list_height, list_length);
@ -91,7 +95,8 @@ impl<'a> Widget for List<'a> {
} else { } else {
0 0
}; };
let x = match self.selection_symbol {
let x = match self.highlight_symbol {
Some(s) => (s.width() + 1) as u16 + list_area.left(), Some(s) => (s.width() + 1) as u16 + list_area.left(),
None => list_area.left(), None => list_area.left(),
}; };
@ -102,7 +107,7 @@ impl<'a> Widget for List<'a> {
let index = i + offset; let index = i + offset;
let item = self.items[index]; let item = self.items[index];
let color = if index == self.selected { let color = if index == self.selected {
self.selection_color self.highlight_color
} else { } else {
self.color self.color
}; };
@ -113,13 +118,14 @@ impl<'a> Widget for List<'a> {
color, color,
self.background_color); self.background_color);
} }
}
if let Some(s) = self.selection_symbol { if let Some(s) = self.highlight_symbol {
buf.set_string(list_area.left(), buf.set_string(list_area.left(),
list_area.top() + (self.selected - offset) as u16, list_area.top() + (self.selected - offset) as u16,
s, s,
self.selection_color, self.highlight_color,
self.background_color); self.background_color);
}
} }
} }
} }

@ -22,6 +22,7 @@ pub use self::table::Table;
use buffer::Buffer; use buffer::Buffer;
use layout::Rect; use layout::Rect;
use terminal::Terminal; use terminal::Terminal;
use style::Color;
pub mod border { pub mod border {
bitflags! { bitflags! {
@ -38,6 +39,13 @@ pub mod border {
pub trait Widget { pub trait Widget {
fn buffer(&self, area: &Rect, buf: &mut Buffer); fn buffer(&self, area: &Rect, buf: &mut Buffer);
fn background(&self, area: &Rect, buf: &mut Buffer, color: Color) {
for y in area.top()..area.bottom() {
for x in area.left()..area.right() {
buf.set_bg(x, y, color);
}
}
}
fn render(&self, area: &Rect, t: &mut Terminal) fn render(&self, area: &Rect, t: &mut Terminal)
where Self: Sized where Self: Sized
{ {

@ -63,43 +63,44 @@ impl<'a> Widget for Sparkline<'a> {
} }
None => *area, None => *area,
}; };
if spark_area.height < 1 { if spark_area.height < 1 {
return; return;
} else { }
let max = match self.max {
Some(v) => v, let max = match self.max {
None => *self.data.iter().max().unwrap_or(&1u64), Some(v) => v,
}; None => *self.data.iter().max().unwrap_or(&1u64),
let max_index = min(spark_area.width as usize, self.data.len()); };
let mut data = self.data let max_index = min(spark_area.width as usize, self.data.len());
.iter() let mut data = self.data
.take(max_index) .iter()
.map(|e| e * spark_area.height as u64 * 8 / max) .take(max_index)
.collect::<Vec<u64>>(); .map(|e| e * spark_area.height as u64 * 8 / max)
for j in (0..spark_area.height).rev() { .collect::<Vec<u64>>();
for (i, d) in data.iter_mut().enumerate() { for j in (0..spark_area.height).rev() {
let symbol = match *d { for (i, d) in data.iter_mut().enumerate() {
0 => " ", let symbol = match *d {
1 => bar::ONE_EIGHTH, 0 => " ",
2 => bar::ONE_QUATER, 1 => bar::ONE_EIGHTH,
3 => bar::THREE_EIGHTHS, 2 => bar::ONE_QUATER,
4 => bar::HALF, 3 => bar::THREE_EIGHTHS,
5 => bar::FIVE_EIGHTHS, 4 => bar::HALF,
6 => bar::THREE_QUATERS, 5 => bar::FIVE_EIGHTHS,
7 => bar::SEVEN_EIGHTHS, 6 => bar::THREE_QUATERS,
_ => bar::FULL, 7 => bar::SEVEN_EIGHTHS,
}; _ => bar::FULL,
buf.set_cell(spark_area.left() + i as u16, };
spark_area.top() + j, buf.set_cell(spark_area.left() + i as u16,
symbol, spark_area.top() + j,
self.color, symbol,
self.background_color); self.color,
self.background_color);
if *d > 8 { if *d > 8 {
*d -= 8; *d -= 8;
} else { } else {
*d = 0; *d = 0;
}
} }
} }
} }

@ -9,20 +9,26 @@ use style::Color;
pub struct Table<'a> { pub struct Table<'a> {
block: Option<Block<'a>>, block: Option<Block<'a>>,
titles: &'a [&'a str], header: &'a [&'a str],
header_color: Color,
widths: &'a [u16], widths: &'a [u16],
rows: &'a [&'a [&'a str]], rows: &'a [&'a [&'a str]],
color: Color,
column_spacing: u16, column_spacing: u16,
background_color: Color,
} }
impl<'a> Default for Table<'a> { impl<'a> Default for Table<'a> {
fn default() -> Table<'a> { fn default() -> Table<'a> {
Table { Table {
block: None, block: None,
titles: &[], header: &[],
header_color: Color::Reset,
widths: &[], widths: &[],
rows: &[], rows: &[],
color: Color::Reset,
column_spacing: 1, column_spacing: 1,
background_color: Color::Reset,
} }
} }
} }
@ -33,8 +39,13 @@ impl<'a> Table<'a> {
self self
} }
pub fn titles(&mut self, titles: &'a [&'a str]) -> &mut Table<'a> { pub fn header(&mut self, header: &'a [&'a str]) -> &mut Table<'a> {
self.titles = titles; self.header = header;
self
}
pub fn header_color(&mut self, color: Color) -> &mut Table<'a> {
self.header_color = color;
self self
} }
@ -48,14 +59,26 @@ impl<'a> Table<'a> {
self self
} }
pub fn color(&mut self, color: Color) -> &mut Table<'a> {
self.color = color;
self
}
pub fn column_spacing(&mut self, spacing: u16) -> &mut Table<'a> { pub fn column_spacing(&mut self, spacing: u16) -> &mut Table<'a> {
self.column_spacing = spacing; self.column_spacing = spacing;
self self
} }
pub fn background_color(&mut self, color: Color) -> &mut Table<'a> {
self.background_color = color;
self
}
} }
impl<'a> Widget for Table<'a> { impl<'a> Widget for Table<'a> {
fn buffer(&self, area: &Rect, buf: &mut Buffer) { fn buffer(&self, area: &Rect, buf: &mut Buffer) {
// Render block if necessary and get the drawing area
let table_area = match self.block { let table_area = match self.block {
Some(ref b) => { Some(ref b) => {
b.buffer(area, buf); b.buffer(area, buf);
@ -64,9 +87,14 @@ impl<'a> Widget for Table<'a> {
None => *area, None => *area,
}; };
// Set the background
if self.background_color != Color::Reset {
self.background(&table_area, buf, self.background_color);
}
let mut x = 0; let mut x = 0;
let mut widths = Vec::with_capacity(self.widths.len()); let mut widths = Vec::with_capacity(self.widths.len());
for (width, title) in self.widths.iter().zip(self.titles.iter()) { for (width, title) in self.widths.iter().zip(self.header.iter()) {
let w = max(title.width() as u16, *width); let w = max(title.width() as u16, *width);
if x + w < table_area.width { if x + w < table_area.width {
widths.push(w); widths.push(w);
@ -78,8 +106,8 @@ impl<'a> Widget for Table<'a> {
if y < table_area.bottom() { if y < table_area.bottom() {
x = table_area.left(); x = table_area.left();
for (w, t) in widths.iter().zip(self.titles.iter()) { for (w, t) in widths.iter().zip(self.header.iter()) {
buf.set_string(x, y, t, Color::Reset, Color::Reset); buf.set_string(x, y, t, self.header_color, self.background_color);
x += *w + self.column_spacing; x += *w + self.column_spacing;
} }
} }
@ -94,8 +122,8 @@ impl<'a> Widget for Table<'a> {
y + i as u16, y + i as u16,
elt, elt,
*w as usize, *w as usize,
Color::Reset, self.color,
Color::Reset); self.background_color);
x += *w + self.column_spacing; x += *w + self.column_spacing;
} }
} }

@ -10,8 +10,9 @@ pub struct Tabs<'a> {
block: Option<Block<'a>>, block: Option<Block<'a>>,
titles: &'a [&'a str], titles: &'a [&'a str],
selected: usize, selected: usize,
highlight_color: Color,
color: Color, color: Color,
background_color: Color,
highlight_color: Color,
} }
impl<'a> Default for Tabs<'a> { impl<'a> Default for Tabs<'a> {
@ -20,8 +21,9 @@ impl<'a> Default for Tabs<'a> {
block: None, block: None,
titles: &[], titles: &[],
selected: 0, selected: 0,
highlight_color: Color::Reset,
color: Color::Reset, color: Color::Reset,
background_color: Color::Reset,
highlight_color: Color::Reset,
} }
} }
} }
@ -47,6 +49,11 @@ impl<'a> Tabs<'a> {
self self
} }
pub fn background_color(&mut self, color: Color) -> &mut Tabs<'a> {
self.background_color = color;
self
}
pub fn highlight_color(&mut self, color: Color) -> &mut Tabs<'a> { pub fn highlight_color(&mut self, color: Color) -> &mut Tabs<'a> {
self.highlight_color = color; self.highlight_color = color;
self self
@ -55,6 +62,7 @@ impl<'a> Tabs<'a> {
impl<'a> Widget for Tabs<'a> { impl<'a> Widget for Tabs<'a> {
fn buffer(&self, area: &Rect, buf: &mut Buffer) { fn buffer(&self, area: &Rect, buf: &mut Buffer) {
let tabs_area = match self.block { let tabs_area = match self.block {
Some(b) => { Some(b) => {
b.buffer(area, buf); b.buffer(area, buf);
@ -62,10 +70,15 @@ impl<'a> Widget for Tabs<'a> {
} }
None => *area, None => *area,
}; };
if tabs_area.height < 1 { if tabs_area.height < 1 {
return; return;
} }
if self.background_color != Color::Reset {
self.background(&tabs_area, buf, self.background_color);
}
let mut x = tabs_area.left(); let mut x = tabs_area.left();
for (title, color) in self.titles.iter().enumerate().map(|(i, t)| if i == self.selected { for (title, color) in self.titles.iter().enumerate().map(|(i, t)| if i == self.selected {
(t, self.highlight_color) (t, self.highlight_color)
@ -76,16 +89,16 @@ impl<'a> Widget for Tabs<'a> {
if x > tabs_area.right() { if x > tabs_area.right() {
break; break;
} else { } else {
buf.set_string(x, tabs_area.top(), title, color, Color::Reset); buf.set_string(x, tabs_area.top(), title, color, self.background_color);
x += title.width() as u16 + 1; x += title.width() as u16 + 1;
if x > tabs_area.right() { if x >= tabs_area.right() {
break; break;
} else { } else {
buf.set_cell(x, buf.set_cell(x,
tabs_area.top(), tabs_area.top(),
line::VERTICAL, line::VERTICAL,
Color::Reset, self.color,
Color::Reset); self.background_color);
x += 1; x += 1;
} }
} }

@ -7,8 +7,8 @@ use style::Color;
pub struct Text<'a> { pub struct Text<'a> {
block: Option<Block<'a>>, block: Option<Block<'a>>,
fg: Color, color: Color,
bg: Color, background_color: Color,
wrapping: bool, wrapping: bool,
text: &'a str, text: &'a str,
colors: &'a [(u16, u16, u16, Color, Color)], colors: &'a [(u16, u16, u16, Color, Color)],
@ -18,8 +18,8 @@ impl<'a> Default for Text<'a> {
fn default() -> Text<'a> { fn default() -> Text<'a> {
Text { Text {
block: None, block: None,
fg: Color::Reset, color: Color::Reset,
bg: Color::Reset, background_color: Color::Reset,
wrapping: false, wrapping: false,
text: "", text: "",
colors: &[], colors: &[],
@ -38,13 +38,13 @@ impl<'a> Text<'a> {
self self
} }
pub fn bg(&mut self, bg: Color) -> &mut Text<'a> { pub fn background_color(&mut self, background_color: Color) -> &mut Text<'a> {
self.bg = bg; self.background_color = background_color;
self self
} }
pub fn fg(&mut self, fg: Color) -> &mut Text<'a> { pub fn color(&mut self, color: Color) -> &mut Text<'a> {
self.fg = fg; self.color = color;
self self
} }
@ -64,17 +64,19 @@ struct Parser<'a> {
mark: bool, mark: bool,
color_string: String, color_string: String,
color: Color, color: Color,
base_color: Color,
escaping: bool, escaping: bool,
coloring: bool, coloring: bool,
} }
impl<'a> Parser<'a> { impl<'a> Parser<'a> {
fn new(text: &'a str) -> Parser<'a> { fn new(text: &'a str, base_color: Color) -> Parser<'a> {
Parser { Parser {
text: UnicodeSegmentation::graphemes(text, true).rev().collect::<Vec<&str>>(), text: UnicodeSegmentation::graphemes(text, true).rev().collect::<Vec<&str>>(),
mark: false, mark: false,
color_string: String::from(""), color_string: String::from(""),
color: Color::Reset, color: base_color,
base_color: base_color,
escaping: false, escaping: false,
coloring: false, coloring: false,
} }
@ -103,8 +105,8 @@ impl<'a> Parser<'a> {
fn reset(&mut self) { fn reset(&mut self) {
self.coloring = false; self.coloring = false;
self.mark = false; self.mark = false;
self.color = Color::Reset; self.color = self.base_color;
self.color_string = String::from(""); self.color_string.clear();
} }
} }
@ -125,7 +127,7 @@ impl<'a> Iterator for Parser<'a> {
self.escaping = false; self.escaping = false;
Some((s, self.color)) Some((s, self.color))
} else { } else {
self.color = Color::Reset; self.color = self.base_color;
self.mark = true; self.mark = true;
self.next() self.next()
} }
@ -162,9 +164,13 @@ impl<'a> Widget for Text<'a> {
return; return;
} }
if self.background_color != Color::Reset {
self.background(&text_area, buf, self.background_color);
}
let mut x = 0; let mut x = 0;
let mut y = 0; let mut y = 0;
for (s, c) in Parser::new(self.text) { for (s, c) in Parser::new(self.text, self.color) {
if s == "\n" { if s == "\n" {
x = 0; x = 0;
y += 1; y += 1;
@ -182,7 +188,11 @@ impl<'a> Widget for Text<'a> {
break; break;
} }
buf.set_cell(text_area.left() + x, text_area.top() + y, s, c, self.bg); buf.set_cell(text_area.left() + x,
text_area.top() + y,
s,
c,
self.background_color);
x += 1; x += 1;
} }

Loading…
Cancel
Save