feat(linegauge): customized symbols (#1601)
With this PR any symbol (`&str`) can be used to render `filled` and `unfilled` parts of `LineGauge` now. Before that change, only [`symbols::line::Set`](https://docs.rs/ratatui/latest/ratatui/symbols/line/struct.Set.html) was accepted. Note: New methods are introduced to define those symbols: `filled_symbol` and `unfilled_symbol`. The method [`line_set`](https://docs.rs/ratatui/latest/ratatui/widgets/struct.LineGauge.html#method.line_set) is still there, but marked as `deprecated`. 
This commit is contained in:
@@ -84,10 +84,15 @@ fn draw_gauges(frame: &mut Frame, app: &mut App, area: Rect) {
|
||||
let line_gauge = LineGauge::default()
|
||||
.block(Block::new().title("LineGauge:"))
|
||||
.filled_style(Style::default().fg(Color::Magenta))
|
||||
.line_set(if app.enhanced_graphics {
|
||||
symbols::line::THICK
|
||||
.filled_symbol(if app.enhanced_graphics {
|
||||
symbols::line::THICK_HORIZONTAL
|
||||
} else {
|
||||
symbols::line::NORMAL
|
||||
symbols::line::HORIZONTAL
|
||||
})
|
||||
.unfilled_symbol(if app.enhanced_graphics {
|
||||
symbols::line::THICK_HORIZONTAL
|
||||
} else {
|
||||
symbols::line::HORIZONTAL
|
||||
})
|
||||
.ratio(app.progress);
|
||||
frame.render_widget(line_gauge, chunks[2]);
|
||||
|
||||
@@ -159,6 +159,7 @@ fn render_line_gauge(percent: f64, area: Rect, buf: &mut Buffer) {
|
||||
.style(Style::new().light_blue())
|
||||
.filled_style(Style::new().fg(filled_color))
|
||||
.unfilled_style(Style::new().fg(unfilled_color))
|
||||
.line_set(symbols::line::THICK)
|
||||
.filled_symbol(symbols::line::THICK_HORIZONTAL)
|
||||
.unfilled_symbol(symbols::line::THICK_HORIZONTAL)
|
||||
.render(area, buf);
|
||||
}
|
||||
|
||||
@@ -80,6 +80,7 @@ pub fn render_line_gauge(frame: &mut Frame, area: Rect) {
|
||||
.unfilled_style(Style::new().gray().on_black())
|
||||
.label("❤️ HP")
|
||||
.ratio(0.42)
|
||||
.line_set(symbols::line::THICK);
|
||||
.filled_symbol(symbols::line::THICK_HORIZONTAL)
|
||||
.unfilled_symbol(symbols::line::THICK_HORIZONTAL);
|
||||
frame.render_widget(line_gauge, area);
|
||||
}
|
||||
|
||||
161
ratatui-widgets/examples/line_gauge.rs
Normal file
161
ratatui-widgets/examples/line_gauge.rs
Normal file
@@ -0,0 +1,161 @@
|
||||
//! # [Ratatui] `LineGauge` example
|
||||
//!
|
||||
//! The latest version of this example is available in the [widget examples] folder in the
|
||||
//! repository.
|
||||
//!
|
||||
//! Please note that the examples are designed to be run against the `main` branch of the Github
|
||||
//! repository. This means that you may not be able to compile with the latest release version on
|
||||
//! crates.io, or the one that you have installed locally.
|
||||
//!
|
||||
//! See the [examples readme] for more information on finding examples that match the version of the
|
||||
//! library you are using.
|
||||
//!
|
||||
//! [Ratatui]: https://github.com/ratatui/ratatui
|
||||
//! [widget examples]: https://github.com/ratatui/ratatui/blob/main/ratatui-widgets/examples
|
||||
//! [examples readme]: https://github.com/ratatui/ratatui/blob/main/examples/README.md
|
||||
|
||||
use std::time::Duration;
|
||||
|
||||
use color_eyre::Result;
|
||||
use ratatui::{
|
||||
buffer::Buffer,
|
||||
crossterm::event::{self, Event, KeyCode, KeyEventKind},
|
||||
layout::{
|
||||
Constraint::{Length, Min},
|
||||
Layout, Rect,
|
||||
},
|
||||
style::{palette::tailwind, Style, Stylize},
|
||||
widgets::{LineGauge, Paragraph, Widget},
|
||||
DefaultTerminal,
|
||||
};
|
||||
|
||||
fn main() -> Result<()> {
|
||||
color_eyre::install()?;
|
||||
let terminal = ratatui::init();
|
||||
let app_result = App::default().run(terminal);
|
||||
ratatui::restore();
|
||||
app_result
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone, Copy)]
|
||||
struct App {
|
||||
state: AppState,
|
||||
progress_columns: u16,
|
||||
progress: f64,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
|
||||
enum AppState {
|
||||
#[default]
|
||||
Start,
|
||||
Stop,
|
||||
Quit,
|
||||
}
|
||||
|
||||
impl App {
|
||||
fn run(mut self, mut terminal: DefaultTerminal) -> Result<()> {
|
||||
while self.state != AppState::Quit {
|
||||
terminal.draw(|frame| frame.render_widget(&self, frame.area()))?;
|
||||
self.handle_events()?;
|
||||
self.update(terminal.size()?.width);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn update(&mut self, terminal_width: u16) {
|
||||
if self.state != AppState::Start {
|
||||
return;
|
||||
}
|
||||
|
||||
self.progress_columns = (self.progress_columns + 1).clamp(0, terminal_width);
|
||||
self.progress = f64::from(self.progress_columns) / f64::from(terminal_width);
|
||||
}
|
||||
|
||||
fn handle_events(&mut self) -> Result<()> {
|
||||
let timeout = Duration::from_secs_f32(1.0 / 20.0);
|
||||
if event::poll(timeout)? {
|
||||
if let Event::Key(key) = event::read()? {
|
||||
if key.kind == KeyEventKind::Press {
|
||||
match key.code {
|
||||
KeyCode::Char(' ') => {
|
||||
// toggle start / stop
|
||||
if self.state == AppState::Stop {
|
||||
self.state = AppState::Start;
|
||||
} else {
|
||||
self.state = AppState::Stop;
|
||||
}
|
||||
}
|
||||
KeyCode::Char('r') => self.reset(),
|
||||
KeyCode::Char('q') => self.state = AppState::Quit,
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn reset(&mut self) {
|
||||
self.progress = 0.0;
|
||||
self.progress_columns = 0;
|
||||
self.state = AppState::Stop;
|
||||
}
|
||||
}
|
||||
|
||||
impl Widget for &App {
|
||||
fn render(self, area: Rect, buf: &mut Buffer) {
|
||||
let layout = Layout::vertical([Length(3), Min(0)]);
|
||||
let [header_area, main_area] = layout.areas(area);
|
||||
|
||||
let [gauge1_area, gauge4_area, gauge6_area] =
|
||||
Layout::vertical([Length(2); 3]).areas(main_area);
|
||||
|
||||
header(header_area, buf);
|
||||
|
||||
self.render_gauge1(gauge1_area, buf);
|
||||
self.render_gauge2(gauge4_area, buf);
|
||||
self.render_gauge3(gauge6_area, buf);
|
||||
}
|
||||
}
|
||||
|
||||
fn header(area: Rect, buf: &mut Buffer) {
|
||||
let [p1_area, p2_area] = Layout::vertical([Length(1), Min(1)]).areas(area);
|
||||
Paragraph::new("LineGauge Example")
|
||||
.bold()
|
||||
.centered()
|
||||
.render(p1_area, buf);
|
||||
|
||||
Paragraph::new("(Press 'SPACE' to start/stop progress, 'r' to reset progress, 'q' to quit)")
|
||||
.centered()
|
||||
.render(p2_area, buf);
|
||||
}
|
||||
|
||||
impl App {
|
||||
fn render_gauge1(&self, area: Rect, buf: &mut Buffer) {
|
||||
LineGauge::default()
|
||||
.filled_style(Style::default().fg(tailwind::LIME.c400))
|
||||
.unfilled_style(Style::default().fg(tailwind::LIME.c800))
|
||||
.ratio(self.progress)
|
||||
.render(area, buf);
|
||||
}
|
||||
|
||||
fn render_gauge2(&self, area: Rect, buf: &mut Buffer) {
|
||||
LineGauge::default()
|
||||
.filled_symbol("⣿")
|
||||
.unfilled_symbol("⣿")
|
||||
.filled_style(Style::default().fg(tailwind::CYAN.c400))
|
||||
.unfilled_style(Style::default().fg(tailwind::CYAN.c800))
|
||||
.ratio(self.progress)
|
||||
.render(area, buf);
|
||||
}
|
||||
|
||||
fn render_gauge3(&self, area: Rect, buf: &mut Buffer) {
|
||||
LineGauge::default()
|
||||
.filled_symbol("▰")
|
||||
.unfilled_symbol("▱")
|
||||
.filled_style(Style::default().fg(tailwind::BLUE.c400))
|
||||
.unfilled_style(Style::default().fg(tailwind::BLUE.c800))
|
||||
.ratio(self.progress)
|
||||
.render(area, buf);
|
||||
}
|
||||
}
|
||||
@@ -234,7 +234,8 @@ fn get_unicode_block<'a>(frac: f64) -> &'a str {
|
||||
///
|
||||
/// This can be useful to indicate the progression of a task, like a download.
|
||||
///
|
||||
/// A `LineGauge` renders a thin line filled according to the value given to [`LineGauge::ratio`].
|
||||
/// A `LineGauge` renders a line filled with symbols defined by [`LineGauge::filled_symbol`] and
|
||||
/// [`LineGauge::unfilled_symbol`] according to the value given to [`LineGauge::ratio`].
|
||||
/// Unlike [`Gauge`], only the width can be defined by the [rendering](Widget::render) [`Rect`]. The
|
||||
/// height is always 1.
|
||||
///
|
||||
@@ -259,24 +260,40 @@ fn get_unicode_block<'a>(frac: f64) -> &'a str {
|
||||
/// LineGauge::default()
|
||||
/// .block(Block::bordered().title("Progress"))
|
||||
/// .filled_style(Style::new().white().on_black().bold())
|
||||
/// .line_set(symbols::line::THICK)
|
||||
/// .filled_symbol(symbols::line::THICK_HORIZONTAL)
|
||||
/// .ratio(0.4);
|
||||
/// ```
|
||||
///
|
||||
/// # See also
|
||||
///
|
||||
/// - [`Gauge`] for bigger, higher precision and more configurable progress bar
|
||||
#[derive(Debug, Default, Clone, PartialEq)]
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub struct LineGauge<'a> {
|
||||
block: Option<Block<'a>>,
|
||||
ratio: f64,
|
||||
label: Option<Line<'a>>,
|
||||
line_set: symbols::line::Set,
|
||||
style: Style,
|
||||
filled_symbol: &'a str,
|
||||
unfilled_symbol: &'a str,
|
||||
filled_style: Style,
|
||||
unfilled_style: Style,
|
||||
}
|
||||
|
||||
impl Default for LineGauge<'_> {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
block: None,
|
||||
ratio: 0.0,
|
||||
label: None,
|
||||
style: Style::default(),
|
||||
filled_symbol: symbols::line::HORIZONTAL,
|
||||
unfilled_symbol: symbols::line::HORIZONTAL,
|
||||
filled_style: Style::default(),
|
||||
unfilled_style: Style::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> LineGauge<'a> {
|
||||
/// Surrounds the `LineGauge` with a [`Block`].
|
||||
#[must_use = "method moves the value of self and returns the modified value"]
|
||||
@@ -311,8 +328,27 @@ impl<'a> LineGauge<'a> {
|
||||
/// [`NORMAL`](symbols::line::NORMAL), [`DOUBLE`](symbols::line::DOUBLE) and
|
||||
/// [`THICK`](symbols::line::THICK).
|
||||
#[must_use = "method moves the value of self and returns the modified value"]
|
||||
#[deprecated(
|
||||
since = "0.30.0",
|
||||
note = "You should use `LineGauge::filled_symbol` and `LineGauge::unfilled_symbol` instead."
|
||||
)]
|
||||
pub const fn line_set(mut self, set: symbols::line::Set) -> Self {
|
||||
self.line_set = set;
|
||||
self.filled_symbol = set.horizontal;
|
||||
self.unfilled_symbol = set.horizontal;
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the symbol for the filled part of the gauge.
|
||||
#[must_use = "method moves the value of self and returns the modified value"]
|
||||
pub const fn filled_symbol(mut self, symbol: &'a str) -> Self {
|
||||
self.filled_symbol = symbol;
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the symbol for the unfilled part of the gauge.
|
||||
#[must_use = "method moves the value of self and returns the modified value"]
|
||||
pub const fn unfilled_symbol(mut self, symbol: &'a str) -> Self {
|
||||
self.unfilled_symbol = symbol;
|
||||
self
|
||||
}
|
||||
|
||||
@@ -412,12 +448,12 @@ impl Widget for &LineGauge<'_> {
|
||||
+ (f64::from(gauge_area.right().saturating_sub(start)) * self.ratio).floor() as u16;
|
||||
for col in start..end {
|
||||
buf[(col, row)]
|
||||
.set_symbol(self.line_set.horizontal)
|
||||
.set_symbol(self.filled_symbol)
|
||||
.set_style(self.filled_style);
|
||||
}
|
||||
for col in end..gauge_area.right() {
|
||||
buf[(col, row)]
|
||||
.set_symbol(self.line_set.horizontal)
|
||||
.set_symbol(self.unfilled_symbol)
|
||||
.set_style(self.unfilled_style);
|
||||
}
|
||||
}
|
||||
@@ -520,6 +556,27 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn line_gauge_set_filled_symbol() {
|
||||
assert_eq!(LineGauge::default().filled_symbol("▰").filled_symbol, "▰");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn line_gauge_set_unfilled_symbol() {
|
||||
assert_eq!(
|
||||
LineGauge::default().unfilled_symbol("▱").unfilled_symbol,
|
||||
"▱"
|
||||
);
|
||||
}
|
||||
|
||||
#[allow(deprecated)]
|
||||
#[test]
|
||||
fn line_gauge_deprecated_line_set() {
|
||||
let gauge = LineGauge::default().line_set(symbols::line::DOUBLE);
|
||||
assert_eq!(gauge.filled_symbol, symbols::line::DOUBLE.horizontal);
|
||||
assert_eq!(gauge.unfilled_symbol, symbols::line::DOUBLE.horizontal);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn line_gauge_default() {
|
||||
assert_eq!(
|
||||
@@ -529,7 +586,8 @@ mod tests {
|
||||
ratio: 0.0,
|
||||
label: None,
|
||||
style: Style::default(),
|
||||
line_set: symbols::line::NORMAL,
|
||||
filled_symbol: symbols::line::HORIZONTAL,
|
||||
unfilled_symbol: symbols::line::HORIZONTAL,
|
||||
filled_style: Style::default(),
|
||||
unfilled_style: Style::default()
|
||||
}
|
||||
|
||||
@@ -192,11 +192,6 @@ name = "layout"
|
||||
required-features = ["crossterm"]
|
||||
doc-scrape-examples = true
|
||||
|
||||
[[example]]
|
||||
name = "line_gauge"
|
||||
required-features = ["crossterm"]
|
||||
doc-scrape-examples = true
|
||||
|
||||
[[example]]
|
||||
name = "hyperlink"
|
||||
required-features = ["crossterm"]
|
||||
|
||||
@@ -1,179 +0,0 @@
|
||||
//! # [Ratatui] Line Gauge example
|
||||
//!
|
||||
//! The latest version of this example is available in the [examples] folder in the repository.
|
||||
//!
|
||||
//! Please note that the examples are designed to be run against the `main` branch of the Github
|
||||
//! repository. This means that you may not be able to compile with the latest release version on
|
||||
//! crates.io, or the one that you have installed locally.
|
||||
//!
|
||||
//! See the [examples readme] for more information on finding examples that match the version of the
|
||||
//! library you are using.
|
||||
//!
|
||||
//! [Ratatui]: https://github.com/ratatui/ratatui
|
||||
//! [examples]: https://github.com/ratatui/ratatui/blob/main/examples
|
||||
//! [examples readme]: https://github.com/ratatui/ratatui/blob/main/examples/README.md
|
||||
|
||||
use std::time::Duration;
|
||||
|
||||
use color_eyre::Result;
|
||||
use ratatui::{
|
||||
buffer::Buffer,
|
||||
crossterm::event::{self, Event, KeyCode, KeyEventKind},
|
||||
layout::{Alignment, Constraint, Layout, Rect},
|
||||
style::{palette::tailwind, Color, Style, Stylize},
|
||||
text::Line,
|
||||
widgets::{Block, Borders, LineGauge, Padding, Paragraph, Widget},
|
||||
DefaultTerminal,
|
||||
};
|
||||
|
||||
const CUSTOM_LABEL_COLOR: Color = tailwind::SLATE.c200;
|
||||
|
||||
fn main() -> Result<()> {
|
||||
color_eyre::install()?;
|
||||
let terminal = ratatui::init();
|
||||
let app_result = App::default().run(terminal);
|
||||
ratatui::restore();
|
||||
app_result
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone, Copy)]
|
||||
struct App {
|
||||
state: AppState,
|
||||
progress_columns: u16,
|
||||
progress: f64,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
|
||||
enum AppState {
|
||||
#[default]
|
||||
Running,
|
||||
Started,
|
||||
Quitting,
|
||||
}
|
||||
|
||||
impl App {
|
||||
fn run(mut self, mut terminal: DefaultTerminal) -> Result<()> {
|
||||
while self.state != AppState::Quitting {
|
||||
terminal.draw(|frame| frame.render_widget(&self, frame.area()))?;
|
||||
self.handle_events()?;
|
||||
self.update(terminal.size()?.width);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn update(&mut self, terminal_width: u16) {
|
||||
if self.state != AppState::Started {
|
||||
return;
|
||||
}
|
||||
|
||||
self.progress_columns = (self.progress_columns + 1).clamp(0, terminal_width);
|
||||
self.progress = f64::from(self.progress_columns) / f64::from(terminal_width);
|
||||
}
|
||||
|
||||
fn handle_events(&mut self) -> Result<()> {
|
||||
let timeout = Duration::from_secs_f32(1.0 / 20.0);
|
||||
if event::poll(timeout)? {
|
||||
if let Event::Key(key) = event::read()? {
|
||||
if key.kind == KeyEventKind::Press {
|
||||
match key.code {
|
||||
KeyCode::Char(' ') | KeyCode::Enter => self.start(),
|
||||
KeyCode::Char('q') | KeyCode::Esc => self.quit(),
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn start(&mut self) {
|
||||
self.state = AppState::Started;
|
||||
}
|
||||
|
||||
fn quit(&mut self) {
|
||||
self.state = AppState::Quitting;
|
||||
}
|
||||
}
|
||||
|
||||
impl Widget for &App {
|
||||
fn render(self, area: Rect, buf: &mut Buffer) {
|
||||
use Constraint::{Length, Min, Ratio};
|
||||
let layout = Layout::vertical([Length(2), Min(0), Length(1)]);
|
||||
let [header_area, main_area, footer_area] = layout.areas(area);
|
||||
|
||||
let layout = Layout::vertical([Ratio(1, 3); 3]);
|
||||
let [gauge1_area, gauge2_area, gauge3_area] = layout.areas(main_area);
|
||||
|
||||
header().render(header_area, buf);
|
||||
footer().render(footer_area, buf);
|
||||
|
||||
self.render_gauge1(gauge1_area, buf);
|
||||
self.render_gauge2(gauge2_area, buf);
|
||||
self.render_gauge3(gauge3_area, buf);
|
||||
}
|
||||
}
|
||||
|
||||
fn header() -> impl Widget {
|
||||
Paragraph::new("Ratatui Line Gauge Example")
|
||||
.bold()
|
||||
.alignment(Alignment::Center)
|
||||
.fg(CUSTOM_LABEL_COLOR)
|
||||
}
|
||||
|
||||
fn footer() -> impl Widget {
|
||||
Paragraph::new("Press ENTER / SPACE to start")
|
||||
.alignment(Alignment::Center)
|
||||
.fg(CUSTOM_LABEL_COLOR)
|
||||
.bold()
|
||||
}
|
||||
|
||||
impl App {
|
||||
fn render_gauge1(&self, area: Rect, buf: &mut Buffer) {
|
||||
let title = title_block("Blue / red only foreground");
|
||||
LineGauge::default()
|
||||
.block(title)
|
||||
.filled_style(Style::default().fg(Color::Blue))
|
||||
.unfilled_style(Style::default().fg(Color::Red))
|
||||
.label("Foreground:")
|
||||
.ratio(self.progress)
|
||||
.render(area, buf);
|
||||
}
|
||||
|
||||
fn render_gauge2(&self, area: Rect, buf: &mut Buffer) {
|
||||
let title = title_block("Blue / red only background");
|
||||
LineGauge::default()
|
||||
.block(title)
|
||||
.filled_style(Style::default().fg(Color::Blue).bg(Color::Blue))
|
||||
.unfilled_style(Style::default().fg(Color::Red).bg(Color::Red))
|
||||
.label("Background:")
|
||||
.ratio(self.progress)
|
||||
.render(area, buf);
|
||||
}
|
||||
|
||||
fn render_gauge3(&self, area: Rect, buf: &mut Buffer) {
|
||||
let title = title_block("Fully styled with background");
|
||||
LineGauge::default()
|
||||
.block(title)
|
||||
.filled_style(
|
||||
Style::default()
|
||||
.fg(tailwind::BLUE.c400)
|
||||
.bg(tailwind::BLUE.c600),
|
||||
)
|
||||
.unfilled_style(
|
||||
Style::default()
|
||||
.fg(tailwind::RED.c400)
|
||||
.bg(tailwind::RED.c800),
|
||||
)
|
||||
.label("Both:")
|
||||
.ratio(self.progress)
|
||||
.render(area, buf);
|
||||
}
|
||||
}
|
||||
|
||||
fn title_block(title: &str) -> Block {
|
||||
Block::default()
|
||||
.title(Line::from(title).centered())
|
||||
.borders(Borders::NONE)
|
||||
.fg(CUSTOM_LABEL_COLOR)
|
||||
.padding(Padding::vertical(1))
|
||||
}
|
||||
@@ -3,12 +3,10 @@
|
||||
Output "target/line_gauge.gif"
|
||||
Set Theme "Aardvark Blue"
|
||||
Set Width 1200
|
||||
Set Height 850
|
||||
Set Height 400
|
||||
Hide
|
||||
Type "cargo run --example=line_gauge --features=crossterm"
|
||||
Type "cargo run -p ratatui-widgets --example line_gauge"
|
||||
Enter
|
||||
Sleep 2s
|
||||
Sleep 1s
|
||||
Show
|
||||
Sleep 2s
|
||||
Enter 1
|
||||
Sleep 15s
|
||||
Sleep 6s
|
||||
|
||||
@@ -175,7 +175,7 @@ fn widgets_gauge_supports_large_labels() {
|
||||
|
||||
#[test]
|
||||
fn widgets_line_gauge_renders() {
|
||||
let backend = TestBackend::new(20, 4);
|
||||
let backend = TestBackend::new(20, 6);
|
||||
let mut terminal = Terminal::new(backend).unwrap();
|
||||
terminal
|
||||
.draw(|f| {
|
||||
@@ -192,10 +192,12 @@ fn widgets_line_gauge_renders() {
|
||||
height: 1,
|
||||
},
|
||||
);
|
||||
// custom (same) symbols for filled and unfilled parts
|
||||
let gauge = LineGauge::default()
|
||||
.block(Block::bordered().title("Gauge 2"))
|
||||
.filled_style(Style::default().fg(Color::Green))
|
||||
.line_set(symbols::line::THICK)
|
||||
.filled_symbol(symbols::line::THICK_HORIZONTAL)
|
||||
.unfilled_symbol(symbols::line::THICK_HORIZONTAL)
|
||||
.ratio(0.211_313_934_313_1);
|
||||
f.render_widget(
|
||||
gauge,
|
||||
@@ -206,6 +208,31 @@ fn widgets_line_gauge_renders() {
|
||||
height: 3,
|
||||
},
|
||||
);
|
||||
// default symbol for filled part, but empty for unfilled part
|
||||
let gauge = LineGauge::default().unfilled_symbol(" ").ratio(0.50);
|
||||
f.render_widget(
|
||||
gauge,
|
||||
Rect {
|
||||
x: 0,
|
||||
y: 4,
|
||||
width: 20,
|
||||
height: 1,
|
||||
},
|
||||
);
|
||||
// different custom symbols for filled unfilled parts
|
||||
let gauge = LineGauge::default()
|
||||
.filled_symbol("█") // similar to `symbols::bar::FULL`
|
||||
.unfilled_symbol("░") // similar to `symbols::shade::LIGHT`
|
||||
.ratio(0.80);
|
||||
f.render_widget(
|
||||
gauge,
|
||||
Rect {
|
||||
x: 0,
|
||||
y: 5,
|
||||
width: 20,
|
||||
height: 1,
|
||||
},
|
||||
);
|
||||
})
|
||||
.unwrap();
|
||||
let mut expected = Buffer::with_lines([
|
||||
@@ -213,6 +240,8 @@ fn widgets_line_gauge_renders() {
|
||||
"┌Gauge 2───────────┐",
|
||||
"│21% ━━━━━━━━━━━━━━│",
|
||||
"└──────────────────┘",
|
||||
"50% ──────── ",
|
||||
"80% ████████████░░░░",
|
||||
]);
|
||||
for col in 4..10 {
|
||||
expected[(col, 0)].set_fg(Color::Green);
|
||||
|
||||
Reference in New Issue
Block a user