mirror of
https://github.com/ratatui-org/ratatui
synced 2024-11-10 15:14:27 +00:00
Add background_color support for all existing wigets
This commit is contained in:
parent
d038b283db
commit
a36e20f217
14 changed files with 330 additions and 182 deletions
|
@ -15,12 +15,13 @@ fn main() {
|
|||
let stdin = io::stdin();
|
||||
terminal.clear();
|
||||
terminal.hide_cursor();
|
||||
draw(&mut terminal);
|
||||
for c in stdin.keys() {
|
||||
draw(&mut terminal);
|
||||
let evt = c.unwrap();
|
||||
if evt == event::Key::Char('q') {
|
||||
break;
|
||||
}
|
||||
draw(&mut terminal);
|
||||
}
|
||||
terminal.show_cursor();
|
||||
}
|
||||
|
@ -29,18 +30,38 @@ fn draw(t: &mut Terminal) {
|
|||
|
||||
Group::default()
|
||||
.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| {
|
||||
Block::default()
|
||||
.title("Block")
|
||||
.title_color(Color::Red)
|
||||
.borders(border::ALL)
|
||||
.title("Top")
|
||||
.title_color(Color::Magenta)
|
||||
.background_color(Color::White)
|
||||
.border_color(Color::Magenta)
|
||||
.borders(border::BOTTOM)
|
||||
.render(&chunks[0], t);
|
||||
Group::default()
|
||||
.direction(Direction::Vertical)
|
||||
.sizes(&[Size::Fixed(7), Size::Min(5), Size::Fixed(3)])
|
||||
.direction(Direction::Horizontal)
|
||||
.sizes(&[Size::Fixed(7), Size::Min(0), Size::Fixed(7)])
|
||||
.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 {
|
||||
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;
|
||||
Some((self.x, ((self.x * 1.0 / self.period).sin() + 1.0) * self.scale))
|
||||
Some(point)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -131,7 +132,7 @@ fn main() {
|
|||
info!("Start");
|
||||
|
||||
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 app = App {
|
||||
|
@ -149,7 +150,7 @@ fn main() {
|
|||
show_chart: true,
|
||||
progress: 0,
|
||||
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(),
|
||||
data4: vec![("B1", 9),
|
||||
("B2", 12),
|
||||
|
@ -173,7 +174,7 @@ fn main() {
|
|||
let (tx, rx) = mpsc::channel();
|
||||
let input_tx = tx.clone();
|
||||
|
||||
for _ in 0..30 {
|
||||
for _ in 0..100 {
|
||||
sin_signal.next();
|
||||
}
|
||||
for _ in 0..200 {
|
||||
|
@ -246,12 +247,12 @@ fn main() {
|
|||
}
|
||||
app.data.insert(0, rand_signal.next().unwrap());
|
||||
app.data.pop();
|
||||
app.data2.remove(0);
|
||||
app.data2.push(sin_signal.next().unwrap());
|
||||
for _ in 0..10 {
|
||||
app.data3.remove(0);
|
||||
for _ in 0..5 {
|
||||
app.data2.remove(0);
|
||||
app.data2.push(sin_signal.next().unwrap());
|
||||
}
|
||||
for _ in 0..10 {
|
||||
app.data3.remove(0);
|
||||
app.data3.push(sin_signal2.next().unwrap());
|
||||
}
|
||||
let i = app.data4.pop().unwrap();
|
||||
|
@ -279,6 +280,7 @@ fn draw(t: &mut Terminal, app: &App) {
|
|||
Tabs::default()
|
||||
.block(Block::default().borders(border::ALL).title("Tabs"))
|
||||
.titles(&app.tabs.titles)
|
||||
.color(Color::Green)
|
||||
.highlight_color(Color::Yellow)
|
||||
.select(app.tabs.selection)
|
||||
.render(&chunks[0], t);
|
||||
|
@ -292,15 +294,22 @@ fn draw(t: &mut Terminal, app: &App) {
|
|||
.sizes(&[Size::Percent(50), Size::Percent(50)])
|
||||
.render(t, &chunks[1], |t, chunks| {
|
||||
Table::default()
|
||||
.block(Block::default().title("Servers").borders(border::ALL))
|
||||
.titles(&["Server", "Location", "Status"])
|
||||
.block(Block::default()
|
||||
.title("Servers")
|
||||
.borders(border::ALL))
|
||||
.header(&["Server", "Location", "Status"])
|
||||
.header_color(Color::Red)
|
||||
.widths(&[20, 20, 20])
|
||||
.rows(&[&["Europe#1", "Paris", "Up"],
|
||||
&["Europe#2", "Berlin", "Up"]])
|
||||
.color(Color::Green)
|
||||
.render(&chunks[0], t);
|
||||
Canvas::default()
|
||||
.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])
|
||||
.y_bounds([-90.0, 90.0])
|
||||
.render(&chunks[1], t);
|
||||
|
@ -360,8 +369,8 @@ fn draw_main(t: &mut Terminal, app: &App, area: &Rect) {
|
|||
.title("List"))
|
||||
.items(&app.items)
|
||||
.select(app.selected)
|
||||
.selection_color(Color::Yellow)
|
||||
.selection_symbol(">")
|
||||
.highlight_color(Color::Yellow)
|
||||
.highlight_symbol(">")
|
||||
.render(&chunks[0], t);
|
||||
List::default()
|
||||
.block(Block::default()
|
||||
|
@ -395,8 +404,8 @@ fn draw_main(t: &mut Terminal, app: &App, area: &Rect) {
|
|||
.y_axis(Axis::default()
|
||||
.title("Y Axis")
|
||||
.color(Color::Gray)
|
||||
.bounds([0.0, 40.0])
|
||||
.labels(&["0", "20", "40"]))
|
||||
.bounds([-25.0, 25.0])
|
||||
.labels(&["-25", "0", "25"]))
|
||||
.datasets(&[Dataset::default()
|
||||
.marker(Marker::Dot)
|
||||
.color(Color::Cyan)
|
||||
|
@ -411,9 +420,9 @@ fn draw_main(t: &mut Terminal, app: &App, area: &Rect) {
|
|||
Text::default()
|
||||
.block(Block::default().borders(border::ALL).title("Footer"))
|
||||
.wrap(true)
|
||||
.fg(app.colors[app.color_index])
|
||||
.text("This a paragraph with several lines.\nYou can change the \
|
||||
color.\nUse \\{[color] [text]} to highlight the text with the \
|
||||
.color(app.colors[app.color_index])
|
||||
.text("This is a paragraph with several lines.\nYou can change the \
|
||||
color.\nUse \\{[color] [text]} to highlight the text with a \
|
||||
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 \
|
||||
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,
|
||||
value_color: Color,
|
||||
label_color: Color,
|
||||
background_color: Color,
|
||||
data: &'a [(&'a str, u64)],
|
||||
values: Vec<String>,
|
||||
}
|
||||
|
@ -25,13 +26,14 @@ impl<'a> Default for BarChart<'a> {
|
|||
BarChart {
|
||||
block: None,
|
||||
max: None,
|
||||
data: &[],
|
||||
values: Vec::new(),
|
||||
bar_width: 1,
|
||||
bar_gap: 1,
|
||||
bar_color: Color::Reset,
|
||||
value_color: Color::Reset,
|
||||
label_color: Color::Reset,
|
||||
data: &[],
|
||||
values: Vec::new(),
|
||||
background_color: Color::Reset,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -75,6 +77,10 @@ impl<'a> BarChart<'a> {
|
|||
self.label_color = color;
|
||||
self
|
||||
}
|
||||
pub fn background_color(&'a mut self, color: Color) -> &mut BarChart<'a> {
|
||||
self.background_color = color;
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Widget for BarChart<'a> {
|
||||
|
@ -91,6 +97,10 @@ impl<'a> Widget for BarChart<'a> {
|
|||
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_index = min((chart_area.width / (self.bar_width + self.bar_gap)) as usize,
|
||||
self.data.len());
|
||||
|
@ -119,7 +129,7 @@ impl<'a> Widget for BarChart<'a> {
|
|||
chart_area.top() + j,
|
||||
symbol,
|
||||
self.bar_color,
|
||||
Color::Reset);
|
||||
self.background_color);
|
||||
}
|
||||
|
||||
if d.1 > 8 {
|
||||
|
@ -149,7 +159,7 @@ impl<'a> Widget for BarChart<'a> {
|
|||
label,
|
||||
self.bar_width as usize,
|
||||
self.label_color,
|
||||
Color::Reset);
|
||||
self.background_color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,11 +6,11 @@ use symbols::line;
|
|||
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct Block<'a> {
|
||||
title: Option<&'a str>,
|
||||
title_color: Color,
|
||||
borders: border::Flags,
|
||||
border_color: Color,
|
||||
bg: Color,
|
||||
pub title: Option<&'a str>,
|
||||
pub title_color: Color,
|
||||
pub borders: border::Flags,
|
||||
pub border_color: Color,
|
||||
pub background_color: Color,
|
||||
}
|
||||
|
||||
impl<'a> Default for Block<'a> {
|
||||
|
@ -20,7 +20,7 @@ impl<'a> Default for Block<'a> {
|
|||
title_color: Color::Reset,
|
||||
borders: border::NONE,
|
||||
border_color: Color::Reset,
|
||||
bg: Color::Reset,
|
||||
background_color: Color::Reset,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -41,8 +41,8 @@ impl<'a> Block<'a> {
|
|||
self
|
||||
}
|
||||
|
||||
pub fn bg(mut self, color: Color) -> Block<'a> {
|
||||
self.bg = color;
|
||||
pub fn background_color(mut self, color: Color) -> Block<'a> {
|
||||
self.background_color = color;
|
||||
self
|
||||
}
|
||||
|
||||
|
@ -81,27 +81,47 @@ impl<'a> Widget for Block<'a> {
|
|||
return;
|
||||
}
|
||||
|
||||
if self.background_color != Color::Reset {
|
||||
self.background(area, buf, self.background_color)
|
||||
}
|
||||
|
||||
// Sides
|
||||
if self.borders.intersects(border::LEFT) {
|
||||
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) {
|
||||
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) {
|
||||
let x = area.right() - 1;
|
||||
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) {
|
||||
let y = area.bottom() - 1;
|
||||
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,
|
||||
width as usize,
|
||||
self.title_color,
|
||||
self.bg);
|
||||
self.background_color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,8 +19,8 @@ impl MapResolution {
|
|||
}
|
||||
|
||||
pub struct Map {
|
||||
resolution: MapResolution,
|
||||
color: Color,
|
||||
pub resolution: MapResolution,
|
||||
pub color: Color,
|
||||
}
|
||||
|
||||
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 {
|
||||
type Item = (f64, f64);
|
||||
type IntoIter = PointsIterator<'a>;
|
||||
|
|
|
@ -29,6 +29,7 @@ pub struct Canvas<'a> {
|
|||
x_bounds: [f64; 2],
|
||||
y_bounds: [f64; 2],
|
||||
layers: &'a [&'a [&'a Shape<'a>]],
|
||||
background_color: Color,
|
||||
}
|
||||
|
||||
impl<'a> Default for Canvas<'a> {
|
||||
|
@ -38,6 +39,7 @@ impl<'a> Default for Canvas<'a> {
|
|||
x_bounds: [0.0, 0.0],
|
||||
y_bounds: [0.0, 0.0],
|
||||
layers: &[],
|
||||
background_color: Color::Reset,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -59,6 +61,11 @@ impl<'a> Canvas<'a> {
|
|||
self.layers = layers;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn background_color(&'a mut self, color: Color) -> &mut Canvas<'a> {
|
||||
self.background_color = color;
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Widget for Canvas<'a> {
|
||||
|
@ -81,17 +88,17 @@ impl<'a> Widget for Canvas<'a> {
|
|||
|
||||
for layer in self.layers {
|
||||
|
||||
let mut grid: Vec<u16> = vec![BRAILLE_OFFSET; width * height + 1];
|
||||
let mut colors: Vec<Color> = vec![Color::Reset; width * height + 1];
|
||||
let mut grid: Vec<u16> = vec![BRAILLE_OFFSET; width * height];
|
||||
let mut colors: Vec<Color> = vec![Color::Reset; width * height];
|
||||
|
||||
for shape in layer.iter() {
|
||||
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])
|
||||
}) {
|
||||
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[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[0])) as usize;
|
||||
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();
|
||||
string.pop();
|
||||
let string = String::from_utf16(&grid).unwrap();
|
||||
for (i, (ch, color)) in string.chars().zip(colors.into_iter()).enumerate() {
|
||||
if ch != BRAILLE_BLANK {
|
||||
let (x, y) = (i % width, i / width);
|
||||
|
@ -111,7 +117,7 @@ impl<'a> Widget for Canvas<'a> {
|
|||
c.symbol.clear();
|
||||
c.symbol.push(ch);
|
||||
c.fg = color;
|
||||
c.bg = Color::Reset;
|
||||
c.bg = self.background_color;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -131,7 +131,7 @@ pub struct Chart<'a> {
|
|||
x_axis: Axis<'a>,
|
||||
y_axis: Axis<'a>,
|
||||
datasets: &'a [Dataset<'a>],
|
||||
bg: Color,
|
||||
background_color: Color,
|
||||
}
|
||||
|
||||
impl<'a> Default for Chart<'a> {
|
||||
|
@ -140,7 +140,7 @@ impl<'a> Default for Chart<'a> {
|
|||
block: None,
|
||||
x_axis: Axis::default(),
|
||||
y_axis: Axis::default(),
|
||||
bg: Color::Reset,
|
||||
background_color: Color::Reset,
|
||||
datasets: &[],
|
||||
}
|
||||
}
|
||||
|
@ -152,8 +152,8 @@ impl<'a> Chart<'a> {
|
|||
self
|
||||
}
|
||||
|
||||
pub fn bg(&mut self, bg: Color) -> &mut Chart<'a> {
|
||||
self.bg = bg;
|
||||
pub fn background_color(&mut self, background_color: Color) -> &mut Chart<'a> {
|
||||
self.background_color = background_color;
|
||||
self
|
||||
}
|
||||
|
||||
|
@ -237,18 +237,22 @@ impl<'a> Widget for Chart<'a> {
|
|||
|
||||
let layout = self.layout(&chart_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;
|
||||
}
|
||||
|
||||
if self.background_color != Color::Reset {
|
||||
self.background(&chart_area, buf, self.background_color);
|
||||
}
|
||||
|
||||
if let Some((x, y)) = layout.legend_x {
|
||||
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 {
|
||||
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 {
|
||||
|
@ -263,7 +267,7 @@ impl<'a> Widget for Chart<'a> {
|
|||
y,
|
||||
label,
|
||||
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,
|
||||
label,
|
||||
self.y_axis.labels_color,
|
||||
self.bg);
|
||||
self.background_color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(y) = layout.axis_x {
|
||||
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 {
|
||||
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(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[1])
|
||||
}) {
|
||||
let dy = (self.y_axis.bounds[1] - y) * graph_area.height as f64 /
|
||||
(self.y_axis.bounds[1] - self.y_axis.bounds[0]);
|
||||
let dx = (x - self.x_axis.bounds[0]) * graph_area.width as f64 /
|
||||
(self.x_axis.bounds[1] - self.x_axis.bounds[0]);
|
||||
let dy = ((self.y_axis.bounds[1] - y) * (graph_area.height - 1) as f64 /
|
||||
(self.y_axis.bounds[1] -
|
||||
self.y_axis.bounds[0])) as u16;
|
||||
let dx = ((x - self.x_axis.bounds[0]) * (graph_area.width - 1) as f64 /
|
||||
(self.x_axis.bounds[1] -
|
||||
self.x_axis.bounds[0])) as u16;
|
||||
|
||||
buf.set_cell(dx as u16 + graph_area.left(),
|
||||
dy as u16 + graph_area.top(),
|
||||
buf.set_cell(graph_area.left() + dx,
|
||||
graph_area.top() + dy,
|
||||
symbols::BLACK_CIRCLE,
|
||||
dataset.color,
|
||||
self.bg);
|
||||
self.background_color);
|
||||
}
|
||||
}
|
||||
Marker::Braille => {
|
||||
Canvas::default()
|
||||
.background_color(self.background_color)
|
||||
.x_bounds(self.x_axis.bounds)
|
||||
.y_bounds(self.y_axis.bounds)
|
||||
.layers(&[&[&Points {
|
||||
|
|
|
@ -70,28 +70,32 @@ impl<'a> Widget for Gauge<'a> {
|
|||
};
|
||||
if gauge_area.height < 1 {
|
||||
return;
|
||||
} else {
|
||||
// Gauge
|
||||
let width = (gauge_area.width * self.percent) / 100;
|
||||
let end = gauge_area.left() + width;
|
||||
}
|
||||
|
||||
for x in gauge_area.left()..end {
|
||||
buf.set_symbol(x, gauge_area.top(), " ");
|
||||
}
|
||||
if self.background_color != Color::Reset {
|
||||
self.background(&gauge_area, buf, self.background_color);
|
||||
}
|
||||
|
||||
// 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);
|
||||
// Gauge
|
||||
let width = (gauge_area.width * self.percent) / 100;
|
||||
let end = gauge_area.left() + width;
|
||||
|
||||
for x in gauge_area.left()..end {
|
||||
buf.set_colors(x, gauge_area.top(), self.background_color, self.color);
|
||||
}
|
||||
for x in gauge_area.left()..end {
|
||||
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> {
|
||||
block: Option<Block<'a>>,
|
||||
items: &'a [&'a str],
|
||||
selected: usize,
|
||||
selection_symbol: Option<&'a str>,
|
||||
selection_color: Color,
|
||||
color: Color,
|
||||
background_color: Color,
|
||||
items: &'a [&'a str],
|
||||
highlight_color: Color,
|
||||
highlight_symbol: Option<&'a str>,
|
||||
}
|
||||
|
||||
impl<'a> Default for List<'a> {
|
||||
fn default() -> List<'a> {
|
||||
List {
|
||||
block: None,
|
||||
items: &[],
|
||||
selected: 0,
|
||||
selection_symbol: None,
|
||||
selection_color: Color::Reset,
|
||||
color: Color::Reset,
|
||||
background_color: Color::Reset,
|
||||
items: &[],
|
||||
highlight_color: Color::Reset,
|
||||
highlight_symbol: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -52,13 +52,13 @@ impl<'a> List<'a> {
|
|||
self
|
||||
}
|
||||
|
||||
pub fn selection_symbol(&'a mut self, selection_symbol: &'a str) -> &mut List<'a> {
|
||||
self.selection_symbol = Some(selection_symbol);
|
||||
pub fn highlight_symbol(&'a mut self, highlight_symbol: &'a str) -> &mut List<'a> {
|
||||
self.highlight_symbol = Some(highlight_symbol);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn selection_color(&'a mut self, selection_color: Color) -> &mut List<'a> {
|
||||
self.selection_color = selection_color;
|
||||
pub fn highlight_color(&'a mut self, highlight_color: Color) -> &mut List<'a> {
|
||||
self.highlight_color = highlight_color;
|
||||
self
|
||||
}
|
||||
|
||||
|
@ -79,10 +79,14 @@ impl<'a> Widget for List<'a> {
|
|||
None => *area,
|
||||
};
|
||||
|
||||
if list_area.height < 1 {
|
||||
if list_area.width < 1 || list_area.height < 1 {
|
||||
return;
|
||||
}
|
||||
|
||||
if self.background_color != Color::Reset {
|
||||
self.background(&list_area, buf, self.background_color);
|
||||
}
|
||||
|
||||
let list_length = self.items.len();
|
||||
let list_height = list_area.height as usize;
|
||||
let bound = min(list_height, list_length);
|
||||
|
@ -91,7 +95,8 @@ impl<'a> Widget for List<'a> {
|
|||
} else {
|
||||
0
|
||||
};
|
||||
let x = match self.selection_symbol {
|
||||
|
||||
let x = match self.highlight_symbol {
|
||||
Some(s) => (s.width() + 1) as u16 + list_area.left(),
|
||||
None => list_area.left(),
|
||||
};
|
||||
|
@ -102,7 +107,7 @@ impl<'a> Widget for List<'a> {
|
|||
let index = i + offset;
|
||||
let item = self.items[index];
|
||||
let color = if index == self.selected {
|
||||
self.selection_color
|
||||
self.highlight_color
|
||||
} else {
|
||||
self.color
|
||||
};
|
||||
|
@ -113,13 +118,14 @@ impl<'a> Widget for List<'a> {
|
|||
color,
|
||||
self.background_color);
|
||||
}
|
||||
}
|
||||
if let Some(s) = self.selection_symbol {
|
||||
buf.set_string(list_area.left(),
|
||||
list_area.top() + (self.selected - offset) as u16,
|
||||
s,
|
||||
self.selection_color,
|
||||
self.background_color);
|
||||
|
||||
if let Some(s) = self.highlight_symbol {
|
||||
buf.set_string(list_area.left(),
|
||||
list_area.top() + (self.selected - offset) as u16,
|
||||
s,
|
||||
self.highlight_color,
|
||||
self.background_color);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@ pub use self::table::Table;
|
|||
use buffer::Buffer;
|
||||
use layout::Rect;
|
||||
use terminal::Terminal;
|
||||
use style::Color;
|
||||
|
||||
pub mod border {
|
||||
bitflags! {
|
||||
|
@ -38,6 +39,13 @@ pub mod border {
|
|||
|
||||
pub trait Widget {
|
||||
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)
|
||||
where Self: Sized
|
||||
{
|
||||
|
|
|
@ -63,43 +63,44 @@ impl<'a> Widget for Sparkline<'a> {
|
|||
}
|
||||
None => *area,
|
||||
};
|
||||
|
||||
if spark_area.height < 1 {
|
||||
return;
|
||||
} else {
|
||||
let max = match self.max {
|
||||
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
|
||||
.iter()
|
||||
.take(max_index)
|
||||
.map(|e| e * spark_area.height as u64 * 8 / max)
|
||||
.collect::<Vec<u64>>();
|
||||
for j in (0..spark_area.height).rev() {
|
||||
for (i, d) in data.iter_mut().enumerate() {
|
||||
let symbol = match *d {
|
||||
0 => " ",
|
||||
1 => bar::ONE_EIGHTH,
|
||||
2 => bar::ONE_QUATER,
|
||||
3 => bar::THREE_EIGHTHS,
|
||||
4 => bar::HALF,
|
||||
5 => bar::FIVE_EIGHTHS,
|
||||
6 => bar::THREE_QUATERS,
|
||||
7 => bar::SEVEN_EIGHTHS,
|
||||
_ => bar::FULL,
|
||||
};
|
||||
buf.set_cell(spark_area.left() + i as u16,
|
||||
spark_area.top() + j,
|
||||
symbol,
|
||||
self.color,
|
||||
self.background_color);
|
||||
}
|
||||
|
||||
if *d > 8 {
|
||||
*d -= 8;
|
||||
} else {
|
||||
*d = 0;
|
||||
}
|
||||
let max = match self.max {
|
||||
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
|
||||
.iter()
|
||||
.take(max_index)
|
||||
.map(|e| e * spark_area.height as u64 * 8 / max)
|
||||
.collect::<Vec<u64>>();
|
||||
for j in (0..spark_area.height).rev() {
|
||||
for (i, d) in data.iter_mut().enumerate() {
|
||||
let symbol = match *d {
|
||||
0 => " ",
|
||||
1 => bar::ONE_EIGHTH,
|
||||
2 => bar::ONE_QUATER,
|
||||
3 => bar::THREE_EIGHTHS,
|
||||
4 => bar::HALF,
|
||||
5 => bar::FIVE_EIGHTHS,
|
||||
6 => bar::THREE_QUATERS,
|
||||
7 => bar::SEVEN_EIGHTHS,
|
||||
_ => bar::FULL,
|
||||
};
|
||||
buf.set_cell(spark_area.left() + i as u16,
|
||||
spark_area.top() + j,
|
||||
symbol,
|
||||
self.color,
|
||||
self.background_color);
|
||||
|
||||
if *d > 8 {
|
||||
*d -= 8;
|
||||
} else {
|
||||
*d = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,20 +9,26 @@ use style::Color;
|
|||
|
||||
pub struct Table<'a> {
|
||||
block: Option<Block<'a>>,
|
||||
titles: &'a [&'a str],
|
||||
header: &'a [&'a str],
|
||||
header_color: Color,
|
||||
widths: &'a [u16],
|
||||
rows: &'a [&'a [&'a str]],
|
||||
color: Color,
|
||||
column_spacing: u16,
|
||||
background_color: Color,
|
||||
}
|
||||
|
||||
impl<'a> Default for Table<'a> {
|
||||
fn default() -> Table<'a> {
|
||||
Table {
|
||||
block: None,
|
||||
titles: &[],
|
||||
header: &[],
|
||||
header_color: Color::Reset,
|
||||
widths: &[],
|
||||
rows: &[],
|
||||
color: Color::Reset,
|
||||
column_spacing: 1,
|
||||
background_color: Color::Reset,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -33,8 +39,13 @@ impl<'a> Table<'a> {
|
|||
self
|
||||
}
|
||||
|
||||
pub fn titles(&mut self, titles: &'a [&'a str]) -> &mut Table<'a> {
|
||||
self.titles = titles;
|
||||
pub fn header(&mut self, header: &'a [&'a str]) -> &mut Table<'a> {
|
||||
self.header = header;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn header_color(&mut self, color: Color) -> &mut Table<'a> {
|
||||
self.header_color = color;
|
||||
self
|
||||
}
|
||||
|
||||
|
@ -48,14 +59,26 @@ impl<'a> Table<'a> {
|
|||
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> {
|
||||
self.column_spacing = spacing;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn background_color(&mut self, color: Color) -> &mut Table<'a> {
|
||||
self.background_color = color;
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Widget for Table<'a> {
|
||||
fn buffer(&self, area: &Rect, buf: &mut Buffer) {
|
||||
|
||||
// Render block if necessary and get the drawing area
|
||||
let table_area = match self.block {
|
||||
Some(ref b) => {
|
||||
b.buffer(area, buf);
|
||||
|
@ -64,9 +87,14 @@ impl<'a> Widget for Table<'a> {
|
|||
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 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);
|
||||
if x + w < table_area.width {
|
||||
widths.push(w);
|
||||
|
@ -78,8 +106,8 @@ impl<'a> Widget for Table<'a> {
|
|||
|
||||
if y < table_area.bottom() {
|
||||
x = table_area.left();
|
||||
for (w, t) in widths.iter().zip(self.titles.iter()) {
|
||||
buf.set_string(x, y, t, Color::Reset, Color::Reset);
|
||||
for (w, t) in widths.iter().zip(self.header.iter()) {
|
||||
buf.set_string(x, y, t, self.header_color, self.background_color);
|
||||
x += *w + self.column_spacing;
|
||||
}
|
||||
}
|
||||
|
@ -94,8 +122,8 @@ impl<'a> Widget for Table<'a> {
|
|||
y + i as u16,
|
||||
elt,
|
||||
*w as usize,
|
||||
Color::Reset,
|
||||
Color::Reset);
|
||||
self.color,
|
||||
self.background_color);
|
||||
x += *w + self.column_spacing;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,8 +10,9 @@ pub struct Tabs<'a> {
|
|||
block: Option<Block<'a>>,
|
||||
titles: &'a [&'a str],
|
||||
selected: usize,
|
||||
highlight_color: Color,
|
||||
color: Color,
|
||||
background_color: Color,
|
||||
highlight_color: Color,
|
||||
}
|
||||
|
||||
impl<'a> Default for Tabs<'a> {
|
||||
|
@ -20,8 +21,9 @@ impl<'a> Default for Tabs<'a> {
|
|||
block: None,
|
||||
titles: &[],
|
||||
selected: 0,
|
||||
highlight_color: Color::Reset,
|
||||
color: Color::Reset,
|
||||
background_color: Color::Reset,
|
||||
highlight_color: Color::Reset,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -47,6 +49,11 @@ impl<'a> Tabs<'a> {
|
|||
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> {
|
||||
self.highlight_color = color;
|
||||
self
|
||||
|
@ -55,6 +62,7 @@ impl<'a> Tabs<'a> {
|
|||
|
||||
impl<'a> Widget for Tabs<'a> {
|
||||
fn buffer(&self, area: &Rect, buf: &mut Buffer) {
|
||||
|
||||
let tabs_area = match self.block {
|
||||
Some(b) => {
|
||||
b.buffer(area, buf);
|
||||
|
@ -62,10 +70,15 @@ impl<'a> Widget for Tabs<'a> {
|
|||
}
|
||||
None => *area,
|
||||
};
|
||||
|
||||
if tabs_area.height < 1 {
|
||||
return;
|
||||
}
|
||||
|
||||
if self.background_color != Color::Reset {
|
||||
self.background(&tabs_area, buf, self.background_color);
|
||||
}
|
||||
|
||||
let mut x = tabs_area.left();
|
||||
for (title, color) in self.titles.iter().enumerate().map(|(i, t)| if i == self.selected {
|
||||
(t, self.highlight_color)
|
||||
|
@ -76,16 +89,16 @@ impl<'a> Widget for Tabs<'a> {
|
|||
if x > tabs_area.right() {
|
||||
break;
|
||||
} 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;
|
||||
if x > tabs_area.right() {
|
||||
if x >= tabs_area.right() {
|
||||
break;
|
||||
} else {
|
||||
buf.set_cell(x,
|
||||
tabs_area.top(),
|
||||
line::VERTICAL,
|
||||
Color::Reset,
|
||||
Color::Reset);
|
||||
self.color,
|
||||
self.background_color);
|
||||
x += 1;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,8 +7,8 @@ use style::Color;
|
|||
|
||||
pub struct Text<'a> {
|
||||
block: Option<Block<'a>>,
|
||||
fg: Color,
|
||||
bg: Color,
|
||||
color: Color,
|
||||
background_color: Color,
|
||||
wrapping: bool,
|
||||
text: &'a str,
|
||||
colors: &'a [(u16, u16, u16, Color, Color)],
|
||||
|
@ -18,8 +18,8 @@ impl<'a> Default for Text<'a> {
|
|||
fn default() -> Text<'a> {
|
||||
Text {
|
||||
block: None,
|
||||
fg: Color::Reset,
|
||||
bg: Color::Reset,
|
||||
color: Color::Reset,
|
||||
background_color: Color::Reset,
|
||||
wrapping: false,
|
||||
text: "",
|
||||
colors: &[],
|
||||
|
@ -38,13 +38,13 @@ impl<'a> Text<'a> {
|
|||
self
|
||||
}
|
||||
|
||||
pub fn bg(&mut self, bg: Color) -> &mut Text<'a> {
|
||||
self.bg = bg;
|
||||
pub fn background_color(&mut self, background_color: Color) -> &mut Text<'a> {
|
||||
self.background_color = background_color;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn fg(&mut self, fg: Color) -> &mut Text<'a> {
|
||||
self.fg = fg;
|
||||
pub fn color(&mut self, color: Color) -> &mut Text<'a> {
|
||||
self.color = color;
|
||||
self
|
||||
}
|
||||
|
||||
|
@ -64,17 +64,19 @@ struct Parser<'a> {
|
|||
mark: bool,
|
||||
color_string: String,
|
||||
color: Color,
|
||||
base_color: Color,
|
||||
escaping: bool,
|
||||
coloring: bool,
|
||||
}
|
||||
|
||||
impl<'a> Parser<'a> {
|
||||
fn new(text: &'a str) -> Parser<'a> {
|
||||
fn new(text: &'a str, base_color: Color) -> Parser<'a> {
|
||||
Parser {
|
||||
text: UnicodeSegmentation::graphemes(text, true).rev().collect::<Vec<&str>>(),
|
||||
mark: false,
|
||||
color_string: String::from(""),
|
||||
color: Color::Reset,
|
||||
color: base_color,
|
||||
base_color: base_color,
|
||||
escaping: false,
|
||||
coloring: false,
|
||||
}
|
||||
|
@ -103,8 +105,8 @@ impl<'a> Parser<'a> {
|
|||
fn reset(&mut self) {
|
||||
self.coloring = false;
|
||||
self.mark = false;
|
||||
self.color = Color::Reset;
|
||||
self.color_string = String::from("");
|
||||
self.color = self.base_color;
|
||||
self.color_string.clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -125,7 +127,7 @@ impl<'a> Iterator for Parser<'a> {
|
|||
self.escaping = false;
|
||||
Some((s, self.color))
|
||||
} else {
|
||||
self.color = Color::Reset;
|
||||
self.color = self.base_color;
|
||||
self.mark = true;
|
||||
self.next()
|
||||
}
|
||||
|
@ -162,9 +164,13 @@ impl<'a> Widget for Text<'a> {
|
|||
return;
|
||||
}
|
||||
|
||||
if self.background_color != Color::Reset {
|
||||
self.background(&text_area, buf, self.background_color);
|
||||
}
|
||||
|
||||
let mut x = 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" {
|
||||
x = 0;
|
||||
y += 1;
|
||||
|
@ -182,7 +188,11 @@ impl<'a> Widget for Text<'a> {
|
|||
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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue