mirror of
https://github.com/ratatui-org/ratatui
synced 2024-11-29 16:10:34 +00:00
815757fcbb
Many widgets can be rendered without changing their state. This commit implements The `Widget` trait for references to widgets and changes their implementations to be immutable. This allows us to render widgets without consuming them by passing a ref to the widget when calling `Frame::render_widget()`. ```rust // this might be stored in a struct let paragraph = Paragraph::new("Hello world!"); let [left, right] = area.split(&Layout::horizontal([20, 20])); frame.render_widget(¶graph, left); frame.render_widget(¶graph, right); // we can reuse the widget ``` Implemented for all widgets except BarChart (which has an implementation that modifies the internal state and requires a rewrite to fix. Other widgets will be implemented in follow up commits. Fixes: https://github.com/ratatui-org/ratatui/discussions/164 Replaces PRs: https://github.com/ratatui-org/ratatui/pull/122 and https://github.com/ratatui-org/ratatui/pull/16 Enables: https://github.com/ratatui-org/ratatui/issues/132 Validated as a viable working solution by: https://github.com/ratatui-org/ratatui/pull/836
34 lines
1.5 KiB
Rust
34 lines
1.5 KiB
Rust
use palette::{IntoColor, Okhsv, Srgb};
|
|
use ratatui::prelude::*;
|
|
|
|
/// A widget that renders a color swatch of RGB colors.
|
|
///
|
|
/// The widget is rendered as a rectangle with the hue changing along the x-axis from 0.0 to 360.0
|
|
/// and the value changing along the y-axis (from 1.0 to 0.0). Each pixel is rendered as a block
|
|
/// character with the top half slightly lighter than the bottom half.
|
|
pub struct RgbSwatch;
|
|
|
|
impl Widget for RgbSwatch {
|
|
fn render(self, area: Rect, buf: &mut Buffer) {
|
|
for (yi, y) in (area.top()..area.bottom()).enumerate() {
|
|
let value = area.height as f32 - yi as f32;
|
|
let value_fg = value / (area.height as f32);
|
|
let value_bg = (value - 0.5) / (area.height as f32);
|
|
for (xi, x) in (area.left()..area.right()).enumerate() {
|
|
let hue = xi as f32 * 360.0 / area.width as f32;
|
|
let fg = color_from_oklab(hue, Okhsv::max_saturation(), value_fg);
|
|
let bg = color_from_oklab(hue, Okhsv::max_saturation(), value_bg);
|
|
buf.get_mut(x, y).set_char('▀').set_fg(fg).set_bg(bg);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Convert a hue and value into an RGB color via the OkLab color space.
|
|
///
|
|
/// See <https://bottosson.github.io/posts/oklab/> for more details.
|
|
pub fn color_from_oklab(hue: f32, saturation: f32, value: f32) -> Color {
|
|
let color: Srgb = Okhsv::new(hue, saturation, value).into_color();
|
|
let color = color.into_format();
|
|
Color::Rgb(color.red, color.green, color.blue)
|
|
}
|