docs(canvas): add documentation to canvas module (#913)

Document the whole `canvas` module. With this, the whole `widgets`
module is documented.
This commit is contained in:
Valentin271 2024-02-03 22:58:29 +01:00 committed by GitHub
parent fbb5dfaaa9
commit 61a827821d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
16 changed files with 179 additions and 72 deletions

View file

@ -1,3 +1,4 @@
#![warn(missing_docs)]
//! `widgets` is a collection of types that implement [`Widget`] or [`StatefulWidget`] or both.
//!
//! Widgets are created for each frame as they are consumed after rendered.
@ -215,7 +216,12 @@ pub trait Widget {
/// }
/// ```
pub trait StatefulWidget {
/// State associated with the stateful widget.
///
/// If you don't need this then you probably want to implement [`Widget`] instead.
type State;
/// Draws the current state of the widget in the given buffer. That is the only method required
/// to implement a custom stateful widget.
fn render(self, area: Rect, buf: &mut Buffer, state: &mut Self::State);
}
@ -290,6 +296,8 @@ pub trait StatefulWidget {
/// ```
#[stability::unstable(feature = "widget-ref")]
pub trait WidgetRef {
/// Draws the current state of the widget in the given buffer. That is the only method required
/// to implement a custom widget.
fn render_ref(&self, area: Rect, buf: &mut Buffer);
}
@ -385,7 +393,12 @@ impl<W: WidgetRef> WidgetRef for Option<W> {
/// ```
#[stability::unstable(feature = "widget-ref")]
pub trait StatefulWidgetRef {
/// State associated with the stateful widget.
///
/// If you don't need this then you probably want to implement [`WidgetRef`] instead.
type State;
/// Draws the current state of the widget in the given buffer. That is the only method required
/// to implement a custom stateful widget.
fn render_ref(&self, area: Rect, buf: &mut Buffer, state: &mut Self::State);
}

View file

@ -1,4 +1,3 @@
#![warn(missing_docs)]
use crate::{prelude::*, widgets::Block};
mod bar;

View file

@ -1,4 +1,3 @@
#![warn(missing_docs)]
//! Elements related to the `Block` base widget.
//!
//! This holds everything needed to display and configure a [`Block`].

View file

@ -1,3 +1,17 @@
//! A [`Canvas`] and a collection of [`Shape`]s.
//!
//! The [`Canvas`] is a blank space on which you can draw anything manually or use one of the
//! predefined [`Shape`]s.
//!
//! The available shapes are:
//!
//! - [`Circle`]: A basic circle
//! - [`Line`]: A line between two points
//! - [`Map`]: A world map
//! - [`Points`]: A scatter of points
//! - [`Rectangle`]: A basic rectangle
//!
//! You can also implement your own custom [`Shape`]s.
mod circle;
mod line;
mod map;
@ -18,8 +32,14 @@ pub use self::{
};
use crate::{prelude::*, symbols, text::Line as TextLine, widgets::Block};
/// Interface for all shapes that may be drawn on a Canvas widget.
/// Something that can be drawn on a [`Canvas`].
///
/// You may implement your own canvas custom widgets by implementing this trait.
pub trait Shape {
/// Draws this [`Shape`] using the given [`Painter`].
///
/// This is the only method required to implement a custom widget that can be drawn on a
/// [`Canvas`].
fn draw(&self, painter: &mut Painter);
}
@ -37,10 +57,10 @@ pub struct Label<'a> {
/// multiple shapes on the canvas in specific order.
#[derive(Debug, Default, Clone, Eq, PartialEq, Hash)]
struct Layer {
// a string of characters representing the grid. This will be wrapped to the width of the grid
// A string of characters representing the grid. This will be wrapped to the width of the grid
// when rendering
string: String,
// colors for foreground and background
// Colors for foreground and background of each cell
colors: Vec<(Color, Color)>,
}
@ -55,16 +75,18 @@ trait Grid: Debug {
fn width(&self) -> u16;
/// Get the height of the grid in number of terminal rows
fn height(&self) -> u16;
/// Get the resolution of the grid in number of dots. This doesn't have to be the same as the
/// number of rows and columns of the grid. For example, a grid of Braille patterns will have a
/// resolution of 2x4 dots per cell. This means that a grid of 10x10 cells will have a
/// resolution of 20x40 dots.
/// Get the resolution of the grid in number of dots.
///
/// This doesn't have to be the same as the number of rows and columns of the grid. For example,
/// a grid of Braille patterns will have a resolution of 2x4 dots per cell. This means that a
/// grid of 10x10 cells will have a resolution of 20x40 dots.
fn resolution(&self) -> (f64, f64);
/// Paint a point of the grid. The point is expressed in number of dots starting at the origin
/// of the grid in the top left corner. Note that this is not the same as the (x, y) coordinates
/// of the canvas.
/// Paint a point of the grid.
///
/// The point is expressed in number of dots starting at the origin of the grid in the top left
/// corner. Note that this is not the same as the `(x, y)` coordinates of the canvas.
fn paint(&mut self, x: usize, y: usize, color: Color);
/// Save the current state of the grid as a layer to be rendered
/// Save the current state of the [`Grid`] as a layer to be rendered
fn save(&self) -> Layer;
/// Reset the grid to its initial state
fn reset(&mut self);
@ -81,12 +103,12 @@ trait Grid: Debug {
/// to set the individual color of each dot in the braille pattern.
#[derive(Debug, Default, Clone, Eq, PartialEq, Hash)]
struct BrailleGrid {
/// width of the grid in number of terminal columns
/// Width of the grid in number of terminal columns
width: u16,
/// height of the grid in number of terminal rows
/// Height of the grid in number of terminal rows
height: u16,
/// represents the unicode braille patterns. Will take a value between 0x2800 and 0x28FF
/// this is converted to a utf16 string when converting to a layer. See
/// Represents the unicode braille patterns. Will take a value between `0x2800` and `0x28FF`
/// this is converted to an utf16 string when converting to a layer. See
/// <https://en.wikipedia.org/wiki/Braille_Patterns> for more info.
utf16_code_points: Vec<u16>,
/// The color of each cell only supports foreground colors for now as there's no way to
@ -152,11 +174,11 @@ impl Grid for BrailleGrid {
/// when you want to draw shapes with a low resolution.
#[derive(Debug, Default, Clone, Eq, PartialEq, Hash)]
struct CharGrid {
/// width of the grid in number of terminal columns
/// Width of the grid in number of terminal columns
width: u16,
/// height of the grid in number of terminal rows
/// Height of the grid in number of terminal rows
height: u16,
/// represents a single character for each cell
/// Represents a single character for each cell
cells: Vec<char>,
/// The color of each cell
colors: Vec<Color>,
@ -232,17 +254,17 @@ impl Grid for CharGrid {
/// character for each cell.
#[derive(Debug, Default, Clone, Eq, PartialEq, Hash)]
struct HalfBlockGrid {
/// width of the grid in number of terminal columns
/// Width of the grid in number of terminal columns
width: u16,
/// height of the grid in number of terminal rows
/// Height of the grid in number of terminal rows
height: u16,
/// represents a single color for each "pixel" arranged in column, row order
/// Represents a single color for each "pixel" arranged in column, row order
pixels: Vec<Vec<Color>>,
}
impl HalfBlockGrid {
/// Create a new HalfBlockGrid with the given width and height measured in terminal columns and
/// rows respectively.
/// Create a new `HalfBlockGrid` with the given width and height measured in terminal columns
/// and rows respectively.
fn new(width: u16, height: u16) -> HalfBlockGrid {
HalfBlockGrid {
width,
@ -346,33 +368,39 @@ pub struct Painter<'a, 'b> {
}
impl<'a, 'b> Painter<'a, 'b> {
/// Convert the (x, y) coordinates to location of a point on the grid
/// Convert the `(x, y)` coordinates to location of a point on the grid
///
/// (x, y) coordinates are expressed in the coordinate system of the canvas. The origin is in
/// the lower left corner of the canvas (unlike most other coordinates in Ratatui where the
/// origin is the upper left corner). The x and y bounds of the canvas define the specific area
/// of some coordinate system that will be drawn on the canvas. The resolution of the grid is
/// used to convert the (x, y) coordinates to the location of a point on the grid.
/// `(x, y)` coordinates are expressed in the coordinate system of the canvas. The origin is in
/// the lower left corner of the canvas (unlike most other coordinates in `Ratatui` where the
/// origin is the upper left corner). The `x` and `y` bounds of the canvas define the specific
/// area of some coordinate system that will be drawn on the canvas. The resolution of the grid
/// is used to convert the `(x, y)` coordinates to the location of a point on the grid.
///
/// The grid coordinates are expressed in the coordinate system of the grid. The origin is in
/// the top left corner of the grid. The x and y bounds of the grid are always [0, width - 1]
/// and [0, height - 1] respectively. The resolution of the grid is used to convert the (x, y)
/// coordinates to the location of a point on the grid.
/// the top left corner of the grid. The x and y bounds of the grid are always `[0, width - 1]`
/// and `[0, height - 1]` respectively. The resolution of the grid is used to convert the
/// `(x, y)` coordinates to the location of a point on the grid.
///
/// # Examples
///
/// # Examples:
/// ```
/// use ratatui::{prelude::*, widgets::canvas::*};
///
/// let mut ctx = Context::new(2, 2, [1.0, 2.0], [0.0, 2.0], symbols::Marker::Braille);
/// let mut painter = Painter::from(&mut ctx);
///
/// let point = painter.get_point(1.0, 0.0);
/// assert_eq!(point, Some((0, 7)));
///
/// let point = painter.get_point(1.5, 1.0);
/// assert_eq!(point, Some((1, 3)));
///
/// let point = painter.get_point(0.0, 0.0);
/// assert_eq!(point, None);
///
/// let point = painter.get_point(2.0, 2.0);
/// assert_eq!(point, Some((3, 0)));
///
/// let point = painter.get_point(1.0, 2.0);
/// assert_eq!(point, Some((0, 0)));
/// ```
@ -396,13 +424,14 @@ impl<'a, 'b> Painter<'a, 'b> {
/// Paint a point of the grid
///
/// # Examples:
/// # Example
///
/// ```
/// use ratatui::{prelude::*, widgets::canvas::*};
///
/// let mut ctx = Context::new(1, 1, [0.0, 2.0], [0.0, 2.0], symbols::Marker::Braille);
/// let mut painter = Painter::from(&mut ctx);
/// let cell = painter.paint(1, 3, Color::Red);
/// painter.paint(1, 3, Color::Red);
/// ```
pub fn paint(&mut self, x: usize, y: usize, color: Color) {
self.context.grid.paint(x, y, color);
@ -419,7 +448,7 @@ impl<'a, 'b> From<&'a mut Context<'b>> for Painter<'a, 'b> {
}
}
/// Holds the state of the Canvas when painting to it.
/// Holds the state of the [`Canvas`] when painting to it.
///
/// This is used by the [`Canvas`] widget to draw shapes on the grid. It can be useful to think of
/// this as similar to the [`Frame`] struct that is used to draw widgets on the terminal.
@ -437,14 +466,14 @@ pub struct Context<'a> {
impl<'a> Context<'a> {
/// Create a new Context with the given width and height measured in terminal columns and rows
/// respectively. The x and y bounds define the specific area of some coordinate system that
/// respectively. The `x` and `y` bounds define the specific area of some coordinate system that
/// will be drawn on the canvas. The marker defines the type of points used to draw the shapes.
///
/// Applications should not use this directly but rather use the [`Canvas`] widget. This will be
/// created by the [`Canvas::paint`] moethod and passed to the closure that is used to draw on
/// created by the [`Canvas::paint`] method and passed to the closure that is used to draw on
/// the canvas.
///
/// The x and y bounds should be specified as left/right and bottom/top respectively. For
/// The `x` and `y` bounds should be specified as left/right and bottom/top respectively. For
/// example, if you want to draw a map of the world, you might want to use the following bounds:
///
/// ```
@ -485,7 +514,7 @@ impl<'a> Context<'a> {
}
}
/// Draw any object that may implement the Shape trait
/// Draw the given [`Shape`] in this context
pub fn draw<S>(&mut self, shape: &S)
where
S: Shape,
@ -495,16 +524,23 @@ impl<'a> Context<'a> {
shape.draw(&mut painter);
}
/// Save the existing state of the grid as a layer to be rendered and reset the grid to its
/// initial state for the next layer.
/// Save the existing state of the grid as a layer.
///
/// Save the existing state as a layer to be rendered and reset the grid to its initial
/// state for the next layer.
///
/// This allows the canvas to be drawn in multiple layers. This is useful if you want to
/// draw multiple shapes on the [`Canvas`] in specific order.
pub fn layer(&mut self) {
self.layers.push(self.grid.save());
self.grid.reset();
self.dirty = false;
}
/// Print a string on the canvas at the given position. Note that the text is always printed
/// on top of the canvas and is not affected by the layers.
/// Print a [`Text`] on the [`Canvas`] at the given position.
///
/// Note that the text is always printed on top of the canvas and is **not** affected by the
/// layers.
pub fn print<T>(&mut self, x: f64, y: f64, line: T)
where
T: Into<TextLine<'a>>,
@ -516,7 +552,7 @@ impl<'a> Context<'a> {
});
}
/// Push the last layer if necessary
/// Save the last layer if necessary
fn finish(&mut self) {
if self.dirty {
self.layer();
@ -619,15 +655,22 @@ impl<'a, F> Canvas<'a, F>
where
F: Fn(&mut Context),
{
/// Set the block that will be rendered around the canvas
/// Wraps the canvas with a custom [`Block`] widget.
///
/// This is a fluent setter method which must be chained or used as it consumes self
#[must_use = "method moves the value of self and returns the modified value"]
pub fn block(mut self, block: Block<'a>) -> Canvas<'a, F> {
self.block = Some(block);
self
}
/// Define the viewport of the canvas.
///
/// If you were to "zoom" to a certain part of the world you may want to choose different
/// bounds.
///
/// This is a fluent setter method which must be chained or used as it consumes self
#[must_use = "method moves the value of self and returns the modified value"]
pub fn x_bounds(mut self, bounds: [f64; 2]) -> Canvas<'a, F> {
self.x_bounds = bounds;
self
@ -637,31 +680,48 @@ where
///
/// If you were to "zoom" to a certain part of the world you may want to choose different
/// bounds.
///
/// This is a fluent setter method which must be chained or used as it consumes self
#[must_use = "method moves the value of self and returns the modified value"]
pub fn y_bounds(mut self, bounds: [f64; 2]) -> Canvas<'a, F> {
self.y_bounds = bounds;
self
}
/// Store the closure that will be used to draw to the Canvas
/// Store the closure that will be used to draw to the [`Canvas`]
///
/// This is a fluent setter method which must be chained or used as it consumes self
#[must_use = "method moves the value of self and returns the modified value"]
pub fn paint(mut self, f: F) -> Canvas<'a, F> {
self.paint_func = Some(f);
self
}
/// Change the background color of the canvas
/// Change the background [`Color`] of the entire canvas
///
/// This is a fluent setter method which must be chained or used as it consumes self
#[must_use = "method moves the value of self and returns the modified value"]
pub fn background_color(mut self, color: Color) -> Canvas<'a, F> {
self.background_color = color;
self
}
/// Change the type of points used to draw the shapes. By default the braille patterns are used
/// as they provide a more fine grained result but you might want to use the simple dot or
/// block instead if the targeted terminal does not support those symbols.
/// Change the type of points used to draw the shapes.
///
/// The HalfBlock marker is useful when you want to draw shapes with a higher resolution than a
/// CharGrid but lower than a BrailleGrid. This grid type supports a foreground and background
/// color for each terminal cell. This allows for more flexibility than the BrailleGrid which
/// only supports a single foreground color for each 2x4 dots cell.
/// By default the [`Braille`] patterns are used as they provide a more fine grained result,
/// but you might want to use the simple [`Dot`] or [`Block`] instead if the targeted terminal
/// does not support those symbols.
///
/// The [`HalfBlock`] marker is useful when you want to draw shapes with a higher resolution
/// than with a grid of characters (e.g. with [`Block`] or [`Dot`]) but lower than with
/// [`Braille`]. This grid type supports a foreground and background color for each terminal
/// cell. This allows for more flexibility than the BrailleGrid which only supports a single
/// foreground color for each 2x4 dots cell.
///
/// [`Braille`]: crate::symbols::Marker::Braille
/// [`HalfBlock`]: crate::symbols::Marker::HalfBlock
/// [`Dot`]: crate::symbols::Marker::Dot
/// [`Block`]: crate::symbols::Marker::Block
///
/// # Examples
///
@ -671,12 +731,15 @@ where
/// Canvas::default()
/// .marker(symbols::Marker::Braille)
/// .paint(|ctx| {});
///
/// Canvas::default()
/// .marker(symbols::Marker::HalfBlock)
/// .paint(|ctx| {});
///
/// Canvas::default()
/// .marker(symbols::Marker::Dot)
/// .paint(|ctx| {});
///
/// Canvas::default()
/// .marker(symbols::Marker::Block)
/// .paint(|ctx| {});

View file

@ -3,12 +3,16 @@ use crate::{
widgets::canvas::{Painter, Shape},
};
/// Shape to draw a circle with a given center and radius and with the given color
/// A circle with a given center and radius and with a given color
#[derive(Debug, Default, Clone, PartialEq)]
pub struct Circle {
/// `x` coordinate of the circle's center
pub x: f64,
/// `y` coordinate of the circle's center
pub y: f64,
/// Radius of the circle
pub radius: f64,
/// Color of the circle
pub color: Color,
}

View file

@ -3,18 +3,23 @@ use crate::{
widgets::canvas::{Painter, Shape},
};
/// Shape to draw a line from (x1, y1) to (x2, y2) with the given color
/// A line from `(x1, y1)` to `(x2, y2)` with the given color
#[derive(Debug, Default, Clone, PartialEq)]
pub struct Line {
/// `x` of the starting point
pub x1: f64,
/// `y` of the starting point
pub y1: f64,
/// `x` of the ending point
pub x2: f64,
/// `y` of the ending point
pub y2: f64,
/// Color of the line
pub color: Color,
}
impl Line {
/// Create a new line from (x1, y1) to (x2, y2) with the given color
/// Create a new line from `(x1, y1)` to `(x2, y2)` with the given color
pub fn new(x1: f64, y1: f64, x2: f64, y2: f64, color: Color) -> Self {
Self {
x1,

View file

@ -8,10 +8,21 @@ use crate::{
},
};
/// Defines how many points are going to be used to draw a [`Map`].
///
/// You generally want a [high](MapResolution::High) resolution map.
#[derive(Debug, Default, Display, EnumString, Clone, Copy, Eq, PartialEq, Hash)]
pub enum MapResolution {
/// A lesser resolution for the [`Map`] [`Shape`].
///
/// Contains about 1000 points.
#[default]
Low,
/// A higher resolution for the [`Map`] [`Shape`].
///
/// Contains about 5000 points, you likely want to use [`Marker::Braille`] with this.
///
/// [`Marker::Braille`]: (crate::symbols::Marker::Braille)
High,
}
@ -24,10 +35,18 @@ impl MapResolution {
}
}
/// Shape to draw a world map with the given resolution and color
/// A world map
///
/// A world map can be rendered with different [resolutions](MapResolution) and [colors](Color).
#[derive(Debug, Default, Clone, Eq, PartialEq, Hash)]
pub struct Map {
/// The resolution of the map.
///
/// This is the number of points used to draw the map.
pub resolution: MapResolution,
/// Map color
///
/// This is the color of the points of the map.
pub color: Color,
}

View file

@ -3,10 +3,12 @@ use crate::{
widgets::canvas::{Painter, Shape},
};
/// A shape to draw a group of points with the given color
/// A group of points with a given color
#[derive(Debug, Default, Clone, PartialEq)]
pub struct Points<'a> {
/// List of points to draw
pub coords: &'a [(f64, f64)],
/// Color of the points
pub color: Color,
}

View file

@ -3,13 +3,25 @@ use crate::{
widgets::canvas::{Line, Painter, Shape},
};
/// Shape to draw a rectangle from a `Rect` with the given color
/// A rectangle to draw on a [`Canvas`](super::Canvas)
///
/// Sizes used here are **not** in terminal cell. This is much more similar to the
/// mathematic coordinate system.
#[derive(Debug, Default, Clone, PartialEq)]
pub struct Rectangle {
/// The `x` position of the rectangle.
///
/// The rectangle is positioned from its bottom left corner.
pub x: f64,
/// The `y` position of the rectangle.
///
/// The rectangle is positioned from its bottom left corner.
pub y: f64,
/// The width of the rectangle.
pub width: f64,
/// The height of the rectangle.
pub height: f64,
/// The color of the rectangle.
pub color: Color,
}

View file

@ -1,4 +1,3 @@
#![warn(missing_docs)]
use std::cmp::max;
use strum::{Display, EnumString};

View file

@ -1,5 +1,3 @@
#![deny(missing_docs)]
use crate::{prelude::*, widgets::Block};
/// A widget to display a progress bar.

View file

@ -1,4 +1,3 @@
#![warn(missing_docs)]
use strum::{Display, EnumString};
use unicode_width::UnicodeWidthStr;

View file

@ -1,4 +1,3 @@
#![warn(missing_docs)]
use std::iter;
use strum::{Display, EnumString};

View file

@ -1,4 +1,3 @@
#![warn(missing_docs)]
use std::cmp::min;
use strum::{Display, EnumString};

View file

@ -1,5 +1,3 @@
#![warn(missing_docs)]
use strum::{Display, EnumString};
mod cell;

View file

@ -1,4 +1,3 @@
#![deny(missing_docs)]
use crate::{prelude::*, widgets::Block};
const DEFAULT_HIGHLIGHT_STYLE: Style = Style::new().add_modifier(Modifier::REVERSED);