Compare commits

...

13 Commits

Author SHA1 Message Date
Florian Dehau
05c96eaa28 Release v0.2.3 2018-06-09 11:49:44 +02:00
Florian Dehau
9a9f49f467 fix(backend): Add missing color pattern 2018-06-09 11:49:44 +02:00
Florian Dehau
c552ae98b4 chore(README): Add link to third-party widgets and other crates 2018-06-09 11:32:49 +02:00
Florian Dehau
df7493fd33 style: Run rustfmt 2018-06-09 11:26:59 +02:00
Florian Dehau
5de571fb03 feat(widgets): Add start_corner option to List 2018-06-09 11:26:59 +02:00
Florian Dehau
62df7badf3 feat(layout): Add Corner enum 2018-06-09 11:26:59 +02:00
Robin Nehls
597e219257 [examples] update paragraph example to show text alignment 2018-05-25 21:09:27 +02:00
Robin Nehls
3f8a9079ee [widgets] implement text alignment for paragraph widget 2018-05-25 21:09:27 +02:00
Robin Nehls
5981767543 [style] add enum for text alignment 2018-05-25 21:09:27 +02:00
Florian Dehau
36146d970a [style] rustfmt 2018-05-25 07:57:00 +02:00
Florian Dehau
464ba4f334 travis: check style on stable only 2018-05-06 15:54:47 +02:00
Florian Dehau
36a5eb2110 Format code 2018-05-06 15:54:47 +02:00
Florian Dehau
55840210c7 Simplify travis configuration 2018-05-06 15:54:47 +02:00
42 changed files with 275 additions and 255 deletions

View File

@@ -5,18 +5,17 @@ rust:
- beta
- nightly
env:
- NO_RUSTUP=1
cache: cargo
matrix:
fast_finish: true
allow_failures:
- rust: nightly
- rust: beta
before_script:
- ./scripts/travis/before_script.sh
- rustup component add rustfmt-preview
script:
- ./scripts/travis/script.sh
- if [ "$TRAVIS_RUST_VERSION" == "stable" ]; then make fmt; fi
- make build
- make test

View File

@@ -2,6 +2,13 @@
## To be released
## v0.2.3 - 2018-06-09
### Added
* Add `start_corner` option for `List`
* Add more text aligment options for `Paragraph`
## v0.2.2 - 2018-05-06
### Added

View File

@@ -1,6 +1,6 @@
[package]
name = "tui"
version = "0.2.2"
version = "0.2.3"
authors = ["Florian Dehau <work@fdehau.com>"]
description = """
A library to build rich terminal user interfaces or dashboards
@@ -19,6 +19,7 @@ default = ["termion"]
[dependencies]
bitflags = "1.0.1"
cassowary = "0.3.0"
itertools = "0.7.8"
log = "0.4.1"
unicode-segmentation = "1.2.0"
unicode-width = "0.1.4"

View File

@@ -27,26 +27,6 @@ help: ## Print all the available commands
awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-20s\033[0m %s\n", $$1, $$2}'
# ================================ Tools ======================================
install-tools: install-rustfmt install-clippy ## Install tools dependencies
INSTALL_RUSTFMT = ./scripts/tools/install.sh --name=rustfmt-nightly
ifndef CI
INSTALL_RUSTFMT += --channel=nightly
endif
install-rustfmt: ## Intall rustfmt
$(INSTALL_RUSTFMT)
INSTALL_CLIPPY = ./scripts/tools/install.sh --name=clippy
ifndef CI
INSTALL_CLIPPY += --channel=nightly
endif
install-clippy: ## Intall rustfmt
$(INSTALL_CLIPPY)
# =============================== Build =======================================
check: ## Validate the project code

View File

@@ -32,6 +32,10 @@ you may rely on the previously cited libraries to achieve such features.
### [Documentation](https://docs.rs/tui)
### Demo
The [source code](examples/demo.rs) of the demo gif.
### Widgets
The library comes with the following list of widgets:
@@ -50,14 +54,15 @@ The library comes with the following list of widgets:
Click on each item to see the source of the example. Run the examples with with
cargo (e.g. to run the demo `cargo run --example demo`), and quit by pressing `q`.
### Demo
### Third-party widgets
The [source code](examples/demo.rs) of the demo gif.
* [tui-logger](https://github.com/gin66/tui-logger)
### Alternatives
You might want to checkout [Cursive](https://github.com/gyscos/Cursive) for an
alternative solution to build text user interfaces in Rust.
## License
[MIT](LICENSE)
## Author
Florian Dehau

View File

@@ -2,18 +2,18 @@ extern crate termion;
extern crate tui;
use std::io;
use std::sync::mpsc;
use std::thread;
use std::time;
use std::sync::mpsc;
use termion::event;
use termion::input::TermRead;
use tui::Terminal;
use tui::backend::MouseBackend;
use tui::widgets::{BarChart, Block, Borders, Widget};
use tui::layout::{Direction, Group, Rect, Size};
use tui::style::{Color, Modifier, Style};
use tui::widgets::{BarChart, Block, Borders, Widget};
use tui::Terminal;
struct App<'a> {
size: Rect,

View File

@@ -5,11 +5,11 @@ use std::io;
use termion::event;
use termion::input::TermRead;
use tui::Terminal;
use tui::backend::MouseBackend;
use tui::widgets::{Block, Borders, Widget};
use tui::layout::{Direction, Group, Rect, Size};
use tui::style::{Color, Modifier, Style};
use tui::widgets::{Block, Borders, Widget};
use tui::Terminal;
fn main() {
let mut terminal = Terminal::new(MouseBackend::new().unwrap()).unwrap();

View File

@@ -2,19 +2,19 @@ extern crate termion;
extern crate tui;
use std::io;
use std::sync::mpsc;
use std::thread;
use std::time;
use std::sync::mpsc;
use termion::event;
use termion::input::TermRead;
use tui::Terminal;
use tui::backend::MouseBackend;
use tui::widgets::{Block, Borders, Widget};
use tui::widgets::canvas::{Canvas, Line, Map, MapResolution};
use tui::layout::{Direction, Group, Rect, Size};
use tui::style::Color;
use tui::widgets::canvas::{Canvas, Line, Map, MapResolution};
use tui::widgets::{Block, Borders, Widget};
use tui::Terminal;
struct App {
size: Rect,

View File

@@ -5,18 +5,18 @@ mod util;
use util::*;
use std::io;
use std::sync::mpsc;
use std::thread;
use std::time;
use std::sync::mpsc;
use termion::event;
use termion::input::TermRead;
use tui::Terminal;
use tui::backend::MouseBackend;
use tui::widgets::{Axis, Block, Borders, Chart, Dataset, Marker, Widget};
use tui::layout::Rect;
use tui::style::{Color, Modifier, Style};
use tui::widgets::{Axis, Block, Borders, Chart, Dataset, Marker, Widget};
use tui::Terminal;
struct App {
size: Rect,

View File

@@ -1,11 +1,11 @@
extern crate tui;
use tui::Terminal;
use tui::backend::MouseBackend;
use tui::widgets::Widget;
use tui::buffer::Buffer;
use tui::layout::Rect;
use tui::style::Style;
use tui::widgets::Widget;
use tui::Terminal;
struct Label<'a> {
text: &'a str,

View File

@@ -7,20 +7,20 @@ extern crate tui;
mod util;
use std::io;
use std::sync::mpsc;
use std::thread;
use std::time;
use std::sync::mpsc;
use termion::event;
use termion::input::TermRead;
use tui::Terminal;
use tui::backend::MouseBackend;
use tui::widgets::{Axis, BarChart, Block, Borders, Chart, Dataset, Gauge, Item, List, Marker,
Paragraph, Row, SelectableList, Sparkline, Table, Tabs, Widget};
use tui::widgets::canvas::{Canvas, Line, Map, MapResolution};
use tui::layout::{Direction, Group, Rect, Size};
use tui::style::{Color, Modifier, Style};
use tui::widgets::canvas::{Canvas, Line, Map, MapResolution};
use tui::widgets::{Axis, BarChart, Block, Borders, Chart, Dataset, Gauge, Item, List, Marker,
Paragraph, Row, SelectableList, Sparkline, Table, Tabs, Widget};
use tui::Terminal;
use util::*;

View File

@@ -2,18 +2,18 @@ extern crate termion;
extern crate tui;
use std::io;
use std::sync::mpsc;
use std::thread;
use std::time;
use std::sync::mpsc;
use termion::event;
use termion::input::TermRead;
use tui::Terminal;
use tui::backend::MouseBackend;
use tui::widgets::{Block, Borders, Gauge, Widget};
use tui::layout::{Direction, Group, Rect, Size};
use tui::style::{Color, Modifier, Style};
use tui::widgets::{Block, Borders, Gauge, Widget};
use tui::Terminal;
struct App {
size: Rect,

View File

@@ -4,16 +4,16 @@ extern crate termion;
extern crate tui;
use std::io;
use std::thread;
use std::sync::mpsc;
use std::thread;
use termion::event;
use termion::input::TermRead;
use tui::Terminal;
use tui::backend::MouseBackend;
use tui::widgets::{Block, Borders, Widget};
use tui::layout::{Direction, Group, Rect, Size};
use tui::widgets::{Block, Borders, Widget};
use tui::Terminal;
struct App {
size: Rect,

View File

@@ -2,18 +2,18 @@ extern crate termion;
extern crate tui;
use std::io;
use std::sync::mpsc;
use std::thread;
use std::time;
use std::sync::mpsc;
use termion::event;
use termion::input::TermRead;
use tui::Terminal;
use tui::backend::MouseBackend;
use tui::widgets::{Block, Borders, Item, List, SelectableList, Widget};
use tui::layout::{Direction, Group, Rect, Size};
use tui::layout::{Corner, Direction, Group, Rect, Size};
use tui::style::{Color, Modifier, Style};
use tui::widgets::{Block, Borders, Item, List, SelectableList, Widget};
use tui::Terminal;
struct App<'a> {
size: Rect,
@@ -183,6 +183,7 @@ fn draw(t: &mut Terminal<MouseBackend>, app: &App) {
});
List::new(events)
.block(Block::default().borders(Borders::ALL).title("List"))
.start_corner(Corner::BottomLeft)
.render(t, &chunks[1]);
}
});

View File

@@ -5,11 +5,11 @@ use std::io;
use termion::event;
use termion::input::TermRead;
use tui::Terminal;
use tui::backend::MouseBackend;
use tui::widgets::{Block, Paragraph, Widget};
use tui::layout::{Direction, Group, Rect, Size};
use tui::style::{Color, Style};
use tui::style::{Alignment, Color, Style};
use tui::widgets::{Block, Paragraph, Widget};
use tui::Terminal;
fn main() {
let mut terminal = Terminal::new(MouseBackend::new().unwrap()).unwrap();
@@ -44,13 +44,46 @@ fn draw(t: &mut Terminal<MouseBackend>, size: &Rect) {
Group::default()
.direction(Direction::Vertical)
.margin(5)
.sizes(&[Size::Percent(100)])
.sizes(&[Size::Percent(30), Size::Percent(30), Size::Percent(30)])
.render(t, size, |t, chunks| {
Group::default()
.direction(Direction::Horizontal)
.sizes(&[Size::Percent(100)])
.render(t, &chunks[0], |t, chunks| {
Paragraph::default()
.alignment(Alignment::Left)
.text(
"This is a line\n{fg=red This is a line}\n{bg=red This is a \
line}\n{mod=italic This is a line}\n{mod=bold This is a \
line}\n{mod=crossed_out This is a line}\n{mod=invert This is a \
line}\n{mod=underline This is a \
line}\n{bg=green;fg=yellow;mod=italic This is a line}\n",
)
.render(t, &chunks[0]);
});
Group::default()
.direction(Direction::Horizontal)
.sizes(&[Size::Percent(100)])
.render(t, &chunks[1], |t, chunks| {
Paragraph::default()
.alignment(Alignment::Center)
.wrap(true)
.text(
"This is a line\n{fg=red This is a line}\n{bg=red This is a \
line}\n{mod=italic This is a line}\n{mod=bold This is a \
line}\n{mod=crossed_out This is a line}\n{mod=invert This is a \
line}\n{mod=underline This is a \
line}\n{bg=green;fg=yellow;mod=italic This is a line}\n",
)
.render(t, &chunks[0]);
});
Group::default()
.direction(Direction::Horizontal)
.sizes(&[Size::Percent(100)])
.render(t, &chunks[2], |t, chunks| {
Paragraph::default()
.alignment(Alignment::Right)
.wrap(true)
.text(
"This is a line\n{fg=red This is a line}\n{bg=red This is a \
line}\n{mod=italic This is a line}\n{mod=bold This is a \

View File

@@ -1,14 +1,14 @@
extern crate rustbox;
extern crate tui;
use std::error::Error;
use rustbox::Key;
use std::error::Error;
use tui::Terminal;
use tui::backend::RustboxBackend;
use tui::widgets::{Block, Borders, Paragraph, Widget};
use tui::layout::{Direction, Group, Size};
use tui::style::{Color, Modifier, Style};
use tui::widgets::{Block, Borders, Paragraph, Widget};
use tui::Terminal;
fn main() {
let mut terminal = Terminal::new(RustboxBackend::new().unwrap()).unwrap();

View File

@@ -5,18 +5,18 @@ mod util;
use util::*;
use std::io;
use std::sync::mpsc;
use std::thread;
use std::time;
use std::sync::mpsc;
use termion::event;
use termion::input::TermRead;
use tui::Terminal;
use tui::backend::MouseBackend;
use tui::widgets::{Block, Borders, Sparkline, Widget};
use tui::layout::{Direction, Group, Rect, Size};
use tui::style::{Color, Style};
use tui::widgets::{Block, Borders, Sparkline, Widget};
use tui::Terminal;
struct App {
size: Rect,

View File

@@ -6,11 +6,11 @@ use std::io;
use termion::event;
use termion::input::TermRead;
use tui::Terminal;
use tui::backend::MouseBackend;
use tui::widgets::{Block, Borders, Row, Table, Widget};
use tui::layout::{Direction, Group, Rect, Size};
use tui::style::{Color, Modifier, Style};
use tui::widgets::{Block, Borders, Row, Table, Widget};
use tui::Terminal;
struct App<'a> {
size: Rect,

View File

@@ -8,11 +8,11 @@ use std::io;
use termion::event;
use termion::input::TermRead;
use tui::Terminal;
use tui::backend::MouseBackend;
use tui::widgets::{Block, Borders, Tabs, Widget};
use tui::layout::{Direction, Group, Rect, Size};
use tui::style::{Color, Style};
use tui::widgets::{Block, Borders, Tabs, Widget};
use tui::Terminal;
struct App<'a> {
size: Rect,

View File

@@ -13,17 +13,17 @@ extern crate termion;
extern crate tui;
use std::io;
use std::thread;
use std::sync::mpsc;
use std::thread;
use termion::event;
use termion::input::TermRead;
use tui::Terminal;
use tui::backend::MouseBackend;
use tui::widgets::{Block, Borders, Item, List, Paragraph, Widget};
use tui::layout::{Direction, Group, Rect, Size};
use tui::style::{Color, Style};
use tui::widgets::{Block, Borders, Item, List, Paragraph, Widget};
use tui::Terminal;
struct App {
size: Rect,

View File

@@ -1,65 +0,0 @@
#!/bin/bash
set -e
USAGE="$0 --name=STRING [--channel=STRING]"
# Default values
CARGO="cargo"
NAME=""
CHANNEL=""
# Parse args
for i in "$@"; do
case $i in
--name=*)
NAME="${i#*=}"
shift
;;
--channel=*)
CHANNEL="${i#*=}"
shift
;;
*)
echo "$USAGE"
exit 1
;;
esac
done
current_version() {
local crate="$1"
$CARGO install --list | \
grep "$crate" | \
head -n 1 | \
cut -d ' ' -f 2 | \
sed 's/v\(.*\):/\1/g'
}
upstream_version() {
local crate="$1"
$CARGO search "$crate" | \
grep "$crate" | \
head -n 1 | \
cut -d' ' -f 3 | \
sed 's/"//g'
}
if [ "$NAME" == "" ]; then
echo "$USAGE"
exit 1
fi
if [ "$CHANNEL" != "" ]; then
CARGO+=" +$CHANNEL"
fi
CURRENT_VERSION=$(current_version "$NAME")
UPSTREAM_VERSION=$(upstream_version "$NAME")
if [[ "$CURRENT_VERSION" != "$UPSTREAM_VERSION" ]]; then
echo "WARN: Latest version of $NAME not installed: $CURRENT_VERSION -> $UPSTREAM_VERSION"
$CARGO install --force "$NAME"
else
echo "INFO: Latest version of $NAME already installed ($CURRENT_VERSION)"
fi

View File

@@ -1,9 +0,0 @@
#!/bin/bash
set -eu
export PATH="$PATH:$HOME/.cargo/bin"
if [[ "$TRAVIS_RUST_VERSION" == "nightly" ]]; then
export LD_LIBRARY_PATH="$(rustc +nightly --print sysroot)/lib:${LD_LIBRARY_PATH:-""}"
make install-tools
fi

View File

@@ -1,9 +0,0 @@
#!/bin/bash
set -eu
make build
make test
if [[ "$TRAVIS_RUST_VERSION" == "nightly" ]]; then
make lint
fi

View File

@@ -11,7 +11,7 @@ pub use self::rustbox::RustboxBackend;
#[cfg(feature = "termion")]
mod termion;
#[cfg(feature = "termion")]
pub use self::termion::{MouseBackend, RawBackend, TermionBackend, AlternateScreenBackend};
pub use self::termion::{AlternateScreenBackend, MouseBackend, RawBackend, TermionBackend};
pub trait Backend {
fn draw<'a, I>(&mut self, content: I) -> Result<(), io::Error>

View File

@@ -85,6 +85,7 @@ impl Into<rustbox::Color> for Color {
Color::Magenta | Color::LightMagenta => rustbox::Color::Magenta,
Color::Cyan | Color::LightCyan => rustbox::Color::Cyan,
Color::White => rustbox::Color::White,
Color::Blue | Color::LightBlue => rustbox::Color::Blue,
Color::Rgb(r, g, b) => rustbox::Color::Byte(rgb_to_byte(r, g, b)),
}
}

View File

@@ -157,33 +157,33 @@ where
}
macro_rules! termion_fg {
($color:ident) => (
($color:ident) => {
format!("{}", termion::color::Fg(termion::color::$color))
);
};
}
macro_rules! termion_fg_rgb {
($r:expr, $g:expr, $b:expr) => (
($r:expr, $g:expr, $b:expr) => {
format!("{}", termion::color::Fg(termion::color::Rgb($r, $g, $b)))
);
};
}
macro_rules! termion_bg {
($color:ident) => (
($color:ident) => {
format!("{}", termion::color::Bg(termion::color::$color))
);
};
}
macro_rules! termion_bg_rgb {
($r:expr, $g:expr, $b:expr) => (
($r:expr, $g:expr, $b:expr) => {
format!("{}", termion::color::Bg(termion::color::Rgb($r, $g, $b)))
);
};
}
macro_rules! termion_modifier {
($style:ident) => (
($style:ident) => {
format!("{}", termion::style::$style)
);
};
}
impl Color {

View File

@@ -1,14 +1,22 @@
use std::cmp::{max, min};
use std::collections::HashMap;
use cassowary::{Constraint, Expression, Solver, Variable};
use cassowary::WeightedRelation::*;
use cassowary::strength::{REQUIRED, WEAK};
use cassowary::WeightedRelation::*;
use cassowary::{Constraint, Expression, Solver, Variable};
use terminal::Terminal;
use backend::Backend;
use terminal::Terminal;
#[derive(Debug, Hash, Clone, Copy, PartialEq, Eq)]
pub enum Corner {
TopLeft,
TopRight,
BottomRight,
BottomLeft,
}
#[derive(Debug, Hash, Clone, PartialEq, Eq)]
pub enum Direction {
Horizontal,
Vertical,

View File

@@ -156,17 +156,18 @@
#[macro_use]
extern crate bitflags;
extern crate cassowary;
extern crate itertools;
#[macro_use]
extern crate log;
extern crate unicode_segmentation;
extern crate unicode_width;
pub mod buffer;
pub mod symbols;
pub mod backend;
pub mod buffer;
pub mod layout;
pub mod style;
pub mod symbols;
pub mod terminal;
pub mod widgets;
pub mod style;
pub mod layout;
pub use self::terminal::Terminal;

View File

@@ -40,6 +40,13 @@ pub enum Modifier {
Underline,
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum Alignment {
Left,
Center,
Right,
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct Style {
pub fg: Color,

View File

@@ -1,5 +1,5 @@
use std::io;
use std::collections::HashMap;
use std::io;
use backend::Backend;
use buffer::Buffer;

View File

@@ -2,11 +2,11 @@ use std::cmp::{max, min};
use unicode_width::UnicodeWidthStr;
use widgets::{Block, Widget};
use buffer::Buffer;
use layout::Rect;
use style::Style;
use symbols::bar;
use widgets::{Block, Widget};
/// Display multiple bars in a single widgets
///

View File

@@ -1,8 +1,8 @@
use buffer::Buffer;
use layout::Rect;
use style::Style;
use widgets::{Borders, Widget};
use symbols::line;
use widgets::{Borders, Widget};
/// Base widget to be used with all upper level ones. It may be used to display a box border around
/// the widget and/or add a title.

View File

@@ -1,7 +1,7 @@
use widgets::canvas::Shape;
use style::Color;
use widgets::canvas::points::PointsIterator;
use widgets::canvas::world::{WORLD_HIGH_RESOLUTION, WORLD_LOW_RESOLUTION};
use style::Color;
use widgets::canvas::Shape;
#[derive(Clone, Copy)]
pub enum MapResolution {

View File

@@ -1,16 +1,16 @@
mod points;
mod line;
mod map;
mod points;
mod world;
pub use self::points::Points;
pub use self::line::Line;
pub use self::map::{Map, MapResolution};
pub use self::points::Points;
use style::{Color, Style};
use buffer::Buffer;
use widgets::{Block, Widget};
use layout::Rect;
use style::{Color, Style};
use widgets::{Block, Widget};
pub const DOTS: [[u16; 2]; 4] = [
[0x0001, 0x0008],

View File

@@ -2,12 +2,12 @@ use std::cmp::max;
use unicode_width::UnicodeWidthStr;
use widgets::{Block, Borders, Widget};
use widgets::canvas::{Canvas, Points};
use buffer::Buffer;
use layout::Rect;
use style::Style;
use symbols;
use widgets::canvas::{Canvas, Points};
use widgets::{Block, Borders, Widget};
/// An X or Y axis for the chart widget
pub struct Axis<'a, L>

View File

@@ -1,9 +1,9 @@
use unicode_width::UnicodeWidthStr;
use widgets::{Block, Widget};
use buffer::Buffer;
use style::{Color, Style};
use layout::Rect;
use style::{Color, Style};
use widgets::{Block, Widget};
/// A widget to display a task progress.
///

View File

@@ -1,13 +1,13 @@
use std::iter;
use std::fmt::Display;
use std::iter;
use std::iter::Iterator;
use unicode_width::UnicodeWidthStr;
use buffer::Buffer;
use widgets::{Block, Widget};
use layout::Rect;
use layout::{Corner, Rect};
use style::Style;
use widgets::{Block, Widget};
pub enum Item<'i, D: 'i> {
Data(D),
@@ -21,6 +21,7 @@ where
block: Option<Block<'b>>,
items: L,
style: Style,
start_corner: Corner,
}
impl<'b, 'i, L, D> Default for List<'b, 'i, L, D>
@@ -32,6 +33,7 @@ where
block: None,
items: L::default(),
style: Default::default(),
start_corner: Corner::TopLeft,
}
}
}
@@ -45,6 +47,7 @@ where
block: None,
items: items,
style: Default::default(),
start_corner: Corner::TopLeft,
}
}
@@ -65,6 +68,11 @@ where
self.style = style;
self
}
pub fn start_corner(&'b mut self, corner: Corner) -> &mut List<'b, 'i, L, D> {
self.start_corner = corner;
self
}
}
impl<'b, 'i, L, D> Widget for List<'b, 'i, L, D>
@@ -92,24 +100,24 @@ where
.enumerate()
.take(list_area.height as usize)
{
let (x, y) = match self.start_corner {
Corner::TopLeft => (list_area.left(), list_area.top() + i as u16),
Corner::BottomLeft => (list_area.left(), list_area.bottom() - (i + 1) as u16),
// Not supported
_ => (list_area.left(), list_area.top() + i as u16),
};
match item {
Item::Data(ref v) => {
buf.set_stringn(
list_area.left(),
list_area.top() + i as u16,
x,
y,
&format!("{}", v),
list_area.width as usize,
&Style::default(),
);
}
Item::StyledData(ref v, s) => {
buf.set_stringn(
list_area.left(),
list_area.top() + i as u16,
&format!("{}", v),
list_area.width as usize,
s,
);
buf.set_stringn(x, y, &format!("{}", v), list_area.width as usize, s);
}
};
}

View File

@@ -1,29 +1,29 @@
mod block;
mod paragraph;
mod list;
mod gauge;
mod sparkline;
mod chart;
mod barchart;
mod tabs;
mod table;
mod block;
pub mod canvas;
mod chart;
mod gauge;
mod list;
mod paragraph;
mod sparkline;
mod table;
mod tabs;
pub use self::block::Block;
pub use self::paragraph::Paragraph;
pub use self::list::{Item, List, SelectableList};
pub use self::gauge::Gauge;
pub use self::sparkline::Sparkline;
pub use self::chart::{Axis, Chart, Dataset, Marker};
pub use self::barchart::BarChart;
pub use self::tabs::Tabs;
pub use self::block::Block;
pub use self::chart::{Axis, Chart, Dataset, Marker};
pub use self::gauge::Gauge;
pub use self::list::{Item, List, SelectableList};
pub use self::paragraph::Paragraph;
pub use self::sparkline::Sparkline;
pub use self::table::{Row, Table};
pub use self::tabs::Tabs;
use backend::Backend;
use buffer::Buffer;
use layout::Rect;
use terminal::Terminal;
use backend::Backend;
use style::Color;
use terminal::Terminal;
/// Bitflags that can be composed to set the visible borders essentially on the block widget.
bitflags! {

View File

@@ -1,10 +1,11 @@
use itertools::{multipeek, MultiPeek};
use unicode_segmentation::UnicodeSegmentation;
use unicode_width::UnicodeWidthStr;
use widgets::{Block, Widget};
use buffer::Buffer;
use layout::Rect;
use style::{Color, Modifier, Style};
use style::{Alignment, Color, Modifier, Style};
use widgets::{Block, Widget};
/// A widget to display some text. You can specify colors using commands embedded in
/// the text such as "{[color] [text]}".
@@ -36,6 +37,8 @@ pub struct Paragraph<'a> {
raw: bool,
/// Scroll
scroll: u16,
/// Aligenment of the text
alignment: Alignment,
}
impl<'a> Default for Paragraph<'a> {
@@ -47,6 +50,7 @@ impl<'a> Default for Paragraph<'a> {
raw: false,
text: "",
scroll: 0,
alignment: Alignment::Left,
}
}
}
@@ -81,6 +85,11 @@ impl<'a> Paragraph<'a> {
self.scroll = offset;
self
}
pub fn alignment(&mut self, alignment: Alignment) -> &mut Paragraph<'a> {
self.alignment = alignment;
self
}
}
struct Parser<'a, T>
@@ -236,8 +245,6 @@ impl<'a> Widget for Paragraph<'a> {
self.background(&text_area, buf, self.style.bg);
let mut x = 0;
let mut y = 0;
let graphemes = UnicodeSegmentation::graphemes(self.text, true);
let styled: Box<Iterator<Item = (&str, Style)>> = if self.raw {
Box::new(graphemes.map(|g| (g, self.style)))
@@ -245,38 +252,83 @@ impl<'a> Widget for Paragraph<'a> {
Box::new(Parser::new(graphemes, self.style))
};
let mut styled = multipeek(styled);
fn get_cur_line_len<'a, I: Iterator<Item = (&'a str, Style)>>(
styled: &mut MultiPeek<I>,
) -> u16 {
let mut line_len = 0;
while match &styled.peek() {
Some(&(x, _)) => x != "\n",
None => false,
} {
line_len += 1;
}
line_len
};
let mut x = match self.alignment {
Alignment::Center => {
(text_area.width / 2).saturating_sub(get_cur_line_len(&mut styled) / 2)
}
Alignment::Right => (text_area.width).saturating_sub(get_cur_line_len(&mut styled)),
Alignment::Left => 0,
};
let mut y = 0;
let mut remove_leading_whitespaces = false;
for (string, style) in styled {
if string == "\n" {
x = 0;
y += 1;
continue;
}
if x >= text_area.width {
if self.wrapping {
x = 0;
loop {
if let Some((string, style)) = styled.next() {
if string == "\n" {
x = match self.alignment {
Alignment::Center => {
(text_area.width / 2).saturating_sub(get_cur_line_len(&mut styled) / 2)
}
Alignment::Right => {
(text_area.width).saturating_sub(get_cur_line_len(&mut styled))
}
Alignment::Left => 0,
};
y += 1;
remove_leading_whitespaces = true
continue;
}
}
if x >= text_area.width {
if self.wrapping {
x = match self.alignment {
Alignment::Center => (text_area.width / 2)
.saturating_sub(get_cur_line_len(&mut styled) / 2),
if remove_leading_whitespaces && string == " " {
continue;
}
remove_leading_whitespaces = false;
Alignment::Right => {
(text_area.width).saturating_sub(get_cur_line_len(&mut styled) + 1)
}
Alignment::Left => 0,
};
y += 1;
remove_leading_whitespaces = true
}
}
if y > text_area.height + self.scroll - 1 {
if remove_leading_whitespaces && string == " " {
continue;
}
remove_leading_whitespaces = false;
if y > text_area.height + self.scroll - 1 {
break;
}
if y < self.scroll {
continue;
}
buf.get_mut(text_area.left() + x, text_area.top() + y - self.scroll)
.set_symbol(string)
.set_style(style);
x += string.width() as u16;
} else {
break;
}
if y < self.scroll {
continue;
}
buf.get_mut(text_area.left() + x, text_area.top() + y - self.scroll)
.set_symbol(string)
.set_style(style);
x += string.width() as u16;
}
}
}

View File

@@ -1,10 +1,10 @@
use std::cmp::min;
use layout::Rect;
use buffer::Buffer;
use widgets::{Block, Widget};
use layout::Rect;
use style::Style;
use symbols::bar;
use widgets::{Block, Widget};
/// Widget to render a sparkline over one or more lines.
///

View File

@@ -2,9 +2,9 @@ use std::fmt::Display;
use std::iter::Iterator;
use buffer::Buffer;
use widgets::{Block, Widget};
use layout::Rect;
use style::Style;
use widgets::{Block, Widget};
/// Holds data to be displayed in a Table widget
pub enum Row<'i, D, I>

View File

@@ -1,10 +1,10 @@
use unicode_width::UnicodeWidthStr;
use widgets::{Block, Widget};
use buffer::Buffer;
use layout::Rect;
use style::Style;
use symbols::line;
use widgets::{Block, Widget};
/// A widget to display available tabs in a multiple panels context.
///