feat(cli): ✨ switch widget
This commit is contained in:
parent
79842ae70d
commit
7e896d04bd
@ -110,3 +110,8 @@ required-features = ["cli.tui.widgets", "tokio.rt"]
|
||||
name = "widget_grid_selector"
|
||||
path = "examples/widget_grid_selector.rs"
|
||||
required-features = ["cli.tui.widgets", "tokio.rt"]
|
||||
|
||||
[[example]]
|
||||
name = "widget_switch"
|
||||
path = "examples/widget_switch.rs"
|
||||
required-features = ["cli.tui.widgets", "tokio.rt"]
|
||||
|
||||
@ -34,6 +34,11 @@ tasks:
|
||||
cmds:
|
||||
- cargo watch --features=cli.tui.widgets,tokio.rt -c -x "run --example widget_grid_selector"
|
||||
|
||||
example:switch:
|
||||
desc: 🚀 run lool «example widget_switch»
|
||||
cmds:
|
||||
- cargo watch --features=cli.tui.widgets,tokio.rt -c -x "run --example widget_switch"
|
||||
|
||||
fmt:
|
||||
desc: 🎨 format lool
|
||||
cmds:
|
||||
|
||||
80
examples/widget_switch.rs
Normal file
80
examples/widget_switch.rs
Normal file
@ -0,0 +1,80 @@
|
||||
use {
|
||||
lool::tui::{
|
||||
ratatui::{
|
||||
backend::CrosstermBackend,
|
||||
crossterm::{
|
||||
event::{self},
|
||||
execute,
|
||||
terminal::{
|
||||
disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen,
|
||||
},
|
||||
},
|
||||
layout::{Constraint, Layout},
|
||||
Terminal,
|
||||
},
|
||||
widgets::{
|
||||
switch::Switch,
|
||||
textarea::{Input, Key},
|
||||
},
|
||||
},
|
||||
ratatui::layout::Flex,
|
||||
std::io,
|
||||
};
|
||||
|
||||
fn main() -> io::Result<()> {
|
||||
let stdout = io::stdout();
|
||||
let mut stdout = stdout.lock();
|
||||
|
||||
enable_raw_mode()?;
|
||||
execute!(stdout, EnterAlternateScreen)?;
|
||||
let backend = CrosstermBackend::new(stdout);
|
||||
let mut term = Terminal::new(backend)?;
|
||||
let mut switch_state = false;
|
||||
|
||||
loop {
|
||||
term.draw(|f| {
|
||||
// Render the textarea
|
||||
let switch =
|
||||
Switch::with_status(switch_state).with_color_on(ratatui::style::Color::Blue);
|
||||
|
||||
let [horiz] = Layout::horizontal([Constraint::Percentage(100)])
|
||||
.flex(Flex::Center)
|
||||
.areas(f.area());
|
||||
|
||||
let [verti] = Layout::vertical([Constraint::Length(2)]).flex(Flex::Center).areas(horiz);
|
||||
|
||||
let [centered] =
|
||||
Layout::horizontal([Constraint::Length(14)]).flex(Flex::Center).areas(verti);
|
||||
|
||||
f.render_widget(switch, centered);
|
||||
})?;
|
||||
match event::read()?.into() {
|
||||
Input { key: Key::Esc, .. }
|
||||
| Input {
|
||||
key: Key::Char('c'),
|
||||
shift: false,
|
||||
ctrl: true,
|
||||
alt: false,
|
||||
} => break,
|
||||
Input {
|
||||
key: Key::Enter,
|
||||
ctrl: false,
|
||||
shift: false,
|
||||
alt: false,
|
||||
}
|
||||
| Input {
|
||||
key: Key::Char(' '),
|
||||
..
|
||||
} => {
|
||||
switch_state = !switch_state;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
disable_raw_mode()?;
|
||||
execute!(term.backend_mut(), LeaveAlternateScreen)?;
|
||||
term.show_cursor()?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@ -244,3 +244,12 @@ As a part of this library, the `Into<GridItem>` trait is implemented for `String
|
||||
|
||||
The example at [`widget_grid_selector.rs`](/examples/widget_grid_selector.rs) demonstrates how to
|
||||
implement the `Into<GridItem>` trait for a custom type.
|
||||
|
||||
## `Switch` Widget
|
||||
|
||||
A simple stateless switch widget that can be used to show visual feedback of a boolean state.
|
||||
|
||||
### Example
|
||||
|
||||
See the [`widget_switch.rs`](/examples/widget_switch.rs) example for a full demonstration of how to
|
||||
use the `Switch` widget.
|
||||
@ -40,6 +40,11 @@ pub mod widgets {
|
||||
}
|
||||
|
||||
pub mod textarea;
|
||||
|
||||
pub mod switch {
|
||||
mod widget;
|
||||
pub use widget::*;
|
||||
}
|
||||
}
|
||||
|
||||
// ratatui prelude
|
||||
|
||||
@ -29,9 +29,9 @@ impl AsRef<str> for GridItem {
|
||||
}
|
||||
|
||||
// convert Label into String
|
||||
impl Into<String> for GridItem {
|
||||
fn into(self) -> String {
|
||||
self.0.clone()
|
||||
impl From<GridItem> for String {
|
||||
fn from(val: GridItem) -> Self {
|
||||
val.0.clone()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
88
lib/cli/tui/widgets/switch/widget.rs
Normal file
88
lib/cli/tui/widgets/switch/widget.rs
Normal file
@ -0,0 +1,88 @@
|
||||
use ratatui::{
|
||||
buffer::Buffer,
|
||||
layout::{Constraint, Layout, Rect},
|
||||
style::{Color, Style},
|
||||
widgets::{Block, Widget},
|
||||
};
|
||||
|
||||
/// A switch widget
|
||||
///
|
||||
/// This widget is used to show visual confirmation of a boolean state
|
||||
pub struct Switch {
|
||||
/// The state of the switch
|
||||
state: bool,
|
||||
/// The color of the "on" state (`Green` by default)
|
||||
color_on: Color,
|
||||
/// The color of the "off" state (`DarkGray` by default)
|
||||
color_off: Color,
|
||||
/// The color of the switch itself (`White` by default)
|
||||
color_switch: Color,
|
||||
}
|
||||
|
||||
impl Switch {
|
||||
pub fn with_status(state: bool) -> Self {
|
||||
Switch {
|
||||
state,
|
||||
color_on: Color::Green,
|
||||
color_off: Color::DarkGray,
|
||||
color_switch: Color::White,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with_color_on(mut self, color: Color) -> Self {
|
||||
self.color_on = color;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_color_off(mut self, color: Color) -> Self {
|
||||
self.color_off = color;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_color_switch(mut self, color: Color) -> Self {
|
||||
self.color_switch = color;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn get_layout(&self, area: Rect) -> (Rect, Rect) {
|
||||
let main = Layout::default()
|
||||
.direction(ratatui::layout::Direction::Vertical)
|
||||
.constraints([Constraint::Length(2)])
|
||||
.split(area);
|
||||
|
||||
let layout = Layout::default()
|
||||
.direction(ratatui::layout::Direction::Horizontal)
|
||||
.constraints([Constraint::Length(7), Constraint::Length(7)])
|
||||
.split(main[0]);
|
||||
|
||||
(layout[0], layout[1])
|
||||
}
|
||||
|
||||
fn get_left_color(&self) -> Color {
|
||||
if self.state {
|
||||
self.color_on
|
||||
} else {
|
||||
self.color_switch
|
||||
}
|
||||
}
|
||||
|
||||
fn get_right_color(&self) -> Color {
|
||||
if self.state {
|
||||
self.color_switch
|
||||
} else {
|
||||
self.color_off
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Widget for Switch {
|
||||
fn render(self, area: Rect, buf: &mut Buffer) {
|
||||
let (left, right) = self.get_layout(area);
|
||||
|
||||
let left_block = Block::default().style(Style::default().bg(self.get_left_color()));
|
||||
let right_block = Block::default().style(Style::default().bg(self.get_right_color()));
|
||||
|
||||
left_block.render(left, buf);
|
||||
right_block.render(right, buf);
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user