Struct Context

Source
pub struct Context<'a> { /* private fields */ }
Expand description

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.

Implementations§

Source§

impl<'a> Context<'a>

Source

pub fn new( width: u16, height: u16, x_bounds: [f64; 2], y_bounds: [f64; 2], marker: Marker, ) -> Self

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 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 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 example, if you want to draw a map of the world, you might want to use the following bounds:

use ratatui::{symbols, widgets::canvas::Context};

let ctx = Context::new(
    100,
    100,
    [-180.0, 180.0],
    [-90.0, 90.0],
    symbols::Marker::Braille,
);
Source

pub fn draw<S>(&mut self, shape: &S)
where S: Shape,

Draw the given Shape in this context

Examples found in repository?
examples/canvas.rs (lines 181-184)
176    fn map_canvas(&self) -> impl Widget + '_ {
177        Canvas::default()
178            .block(Block::bordered().title("World"))
179            .marker(self.marker)
180            .paint(|ctx| {
181                ctx.draw(&Map {
182                    color: Color::Green,
183                    resolution: MapResolution::High,
184                });
185                ctx.print(self.x, -self.y, "You are here".yellow());
186            })
187            .x_bounds([-180.0, 180.0])
188            .y_bounds([-90.0, 90.0])
189    }
190
191    fn draw_canvas(&self, area: Rect) -> impl Widget + '_ {
192        Canvas::default()
193            .block(Block::bordered().title("Draw here"))
194            .marker(self.marker)
195            .x_bounds([0.0, f64::from(area.width)])
196            .y_bounds([0.0, f64::from(area.height)])
197            .paint(move |ctx| {
198                let points = self
199                    .points
200                    .iter()
201                    .map(|p| {
202                        (
203                            f64::from(p.x) - f64::from(area.left()),
204                            f64::from(area.bottom()) - f64::from(p.y),
205                        )
206                    })
207                    .collect_vec();
208                ctx.draw(&Points {
209                    coords: &points,
210                    color: Color::White,
211                });
212            })
213    }
214
215    fn pong_canvas(&self) -> impl Widget + '_ {
216        Canvas::default()
217            .block(Block::bordered().title("Pong"))
218            .marker(self.marker)
219            .paint(|ctx| {
220                ctx.draw(&self.ball);
221            })
222            .x_bounds([10.0, 210.0])
223            .y_bounds([10.0, 110.0])
224    }
225
226    fn boxes_canvas(&self, area: Rect) -> impl Widget {
227        let left = 0.0;
228        let right = f64::from(area.width);
229        let bottom = 0.0;
230        let top = f64::from(area.height).mul_add(2.0, -4.0);
231        Canvas::default()
232            .block(Block::bordered().title("Rects"))
233            .marker(self.marker)
234            .x_bounds([left, right])
235            .y_bounds([bottom, top])
236            .paint(|ctx| {
237                for i in 0..=11 {
238                    ctx.draw(&Rectangle {
239                        x: f64::from(i * i + 3 * i) / 2.0 + 2.0,
240                        y: 2.0,
241                        width: f64::from(i),
242                        height: f64::from(i),
243                        color: Color::Red,
244                    });
245                    ctx.draw(&Rectangle {
246                        x: f64::from(i * i + 3 * i) / 2.0 + 2.0,
247                        y: 21.0,
248                        width: f64::from(i),
249                        height: f64::from(i),
250                        color: Color::Blue,
251                    });
252                }
253                for i in 0..100 {
254                    if i % 10 != 0 {
255                        ctx.print(f64::from(i) + 1.0, 0.0, format!("{i}", i = i % 10));
256                    }
257                    if i % 2 == 0 && i % 10 != 0 {
258                        ctx.print(0.0, f64::from(i), format!("{i}", i = i % 10));
259                    }
260                }
261            })
262    }
More examples
Hide additional examples
examples/demo2/tabs/traceroute.rs (line 127)
107fn render_map(selected_row: usize, area: Rect, buf: &mut Buffer) {
108    let theme = THEME.traceroute.map;
109    let path: Option<(&Hop, &Hop)> = HOPS.iter().tuple_windows().nth(selected_row);
110    let map = Map {
111        resolution: MapResolution::High,
112        color: theme.color,
113    };
114    Canvas::default()
115        .background_color(theme.background_color)
116        .block(
117            Block::new()
118                .padding(Padding::new(1, 0, 1, 0))
119                .style(theme.style),
120        )
121        .marker(Marker::HalfBlock)
122        // picked to show Australia for the demo as it's the most interesting part of the map
123        // (and the only part with hops ;))
124        .x_bounds([112.0, 155.0])
125        .y_bounds([-46.0, -11.0])
126        .paint(|context| {
127            context.draw(&map);
128            if let Some(path) = path {
129                context.draw(&canvas::Line::new(
130                    path.0.location.0,
131                    path.0.location.1,
132                    path.1.location.0,
133                    path.1.location.1,
134                    theme.path,
135                ));
136                context.draw(&Points {
137                    color: theme.source,
138                    coords: &[path.0.location], // sydney
139                });
140                context.draw(&Points {
141                    color: theme.destination,
142                    coords: &[path.1.location], // perth
143                });
144            }
145        })
146        .render(area, buf);
147}
Source

pub fn layer(&mut self)

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.

Source

pub fn print<T>(&mut self, x: f64, y: f64, line: T)
where T: Into<TextLine<'a>>,

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.

Examples found in repository?
examples/canvas.rs (line 185)
176    fn map_canvas(&self) -> impl Widget + '_ {
177        Canvas::default()
178            .block(Block::bordered().title("World"))
179            .marker(self.marker)
180            .paint(|ctx| {
181                ctx.draw(&Map {
182                    color: Color::Green,
183                    resolution: MapResolution::High,
184                });
185                ctx.print(self.x, -self.y, "You are here".yellow());
186            })
187            .x_bounds([-180.0, 180.0])
188            .y_bounds([-90.0, 90.0])
189    }
190
191    fn draw_canvas(&self, area: Rect) -> impl Widget + '_ {
192        Canvas::default()
193            .block(Block::bordered().title("Draw here"))
194            .marker(self.marker)
195            .x_bounds([0.0, f64::from(area.width)])
196            .y_bounds([0.0, f64::from(area.height)])
197            .paint(move |ctx| {
198                let points = self
199                    .points
200                    .iter()
201                    .map(|p| {
202                        (
203                            f64::from(p.x) - f64::from(area.left()),
204                            f64::from(area.bottom()) - f64::from(p.y),
205                        )
206                    })
207                    .collect_vec();
208                ctx.draw(&Points {
209                    coords: &points,
210                    color: Color::White,
211                });
212            })
213    }
214
215    fn pong_canvas(&self) -> impl Widget + '_ {
216        Canvas::default()
217            .block(Block::bordered().title("Pong"))
218            .marker(self.marker)
219            .paint(|ctx| {
220                ctx.draw(&self.ball);
221            })
222            .x_bounds([10.0, 210.0])
223            .y_bounds([10.0, 110.0])
224    }
225
226    fn boxes_canvas(&self, area: Rect) -> impl Widget {
227        let left = 0.0;
228        let right = f64::from(area.width);
229        let bottom = 0.0;
230        let top = f64::from(area.height).mul_add(2.0, -4.0);
231        Canvas::default()
232            .block(Block::bordered().title("Rects"))
233            .marker(self.marker)
234            .x_bounds([left, right])
235            .y_bounds([bottom, top])
236            .paint(|ctx| {
237                for i in 0..=11 {
238                    ctx.draw(&Rectangle {
239                        x: f64::from(i * i + 3 * i) / 2.0 + 2.0,
240                        y: 2.0,
241                        width: f64::from(i),
242                        height: f64::from(i),
243                        color: Color::Red,
244                    });
245                    ctx.draw(&Rectangle {
246                        x: f64::from(i * i + 3 * i) / 2.0 + 2.0,
247                        y: 21.0,
248                        width: f64::from(i),
249                        height: f64::from(i),
250                        color: Color::Blue,
251                    });
252                }
253                for i in 0..100 {
254                    if i % 10 != 0 {
255                        ctx.print(f64::from(i) + 1.0, 0.0, format!("{i}", i = i % 10));
256                    }
257                    if i % 2 == 0 && i % 10 != 0 {
258                        ctx.print(0.0, f64::from(i), format!("{i}", i = i % 10));
259                    }
260                }
261            })
262    }

Trait Implementations§

Source§

impl<'a> Debug for Context<'a>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<'a, 'b> From<&'a mut Context<'b>> for Painter<'a, 'b>

Source§

fn from(context: &'a mut Context<'b>) -> Self

Converts to this type from the input type.

Auto Trait Implementations§

§

impl<'a> Freeze for Context<'a>

§

impl<'a> !RefUnwindSafe for Context<'a>

§

impl<'a> !Send for Context<'a>

§

impl<'a> !Sync for Context<'a>

§

impl<'a> Unpin for Context<'a>

§

impl<'a> !UnwindSafe for Context<'a>

Blanket Implementations§

Source§

impl<S, D, Swp, Dwp, T> AdaptInto<D, Swp, Dwp, T> for S
where T: Real + Zero + Arithmetics + Clone, Swp: WhitePoint<T>, Dwp: WhitePoint<T>, D: AdaptFrom<S, Swp, Dwp, T>,

Source§

fn adapt_into_using<M>(self, method: M) -> D
where M: TransformMatrix<T>,

Convert the source color to the destination color using the specified method.
Source§

fn adapt_into(self) -> D

Convert the source color to the destination color using the bradford method by default.
Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T, C> ArraysFrom<C> for T
where C: IntoArrays<T>,

Source§

fn arrays_from(colors: C) -> T

Cast a collection of colors into a collection of arrays.
Source§

impl<T, C> ArraysInto<C> for T
where C: FromArrays<T>,

Source§

fn arrays_into(self) -> C

Cast this collection of arrays into a collection of colors.
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<WpParam, T, U> Cam16IntoUnclamped<WpParam, T> for U
where T: FromCam16Unclamped<WpParam, U>,

Source§

type Scalar = <T as FromCam16Unclamped<WpParam, U>>::Scalar

The number type that’s used in parameters when converting.
Source§

fn cam16_into_unclamped( self, parameters: BakedParameters<WpParam, <U as Cam16IntoUnclamped<WpParam, T>>::Scalar>, ) -> T

Converts self into C, using the provided parameters.
Source§

impl<T, C> ComponentsFrom<C> for T
where C: IntoComponents<T>,

Source§

fn components_from(colors: C) -> T

Cast a collection of colors into a collection of color components.
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> FromAngle<T> for T

Source§

fn from_angle(angle: T) -> T

Performs a conversion from angle.
Source§

impl<T, U> FromStimulus<U> for T
where U: IntoStimulus<T>,

Source§

fn from_stimulus(other: U) -> T

Converts other into Self, while performing the appropriate scaling, rounding and clamping.
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> IntoAngle<U> for T
where U: FromAngle<T>,

Source§

fn into_angle(self) -> U

Performs a conversion into T.
Source§

impl<WpParam, T, U> IntoCam16Unclamped<WpParam, T> for U
where T: Cam16FromUnclamped<WpParam, U>,

Source§

type Scalar = <T as Cam16FromUnclamped<WpParam, U>>::Scalar

The number type that’s used in parameters when converting.
Source§

fn into_cam16_unclamped( self, parameters: BakedParameters<WpParam, <U as IntoCam16Unclamped<WpParam, T>>::Scalar>, ) -> T

Converts self into C, using the provided parameters.
Source§

impl<T, U> IntoColor<U> for T
where U: FromColor<T>,

Source§

fn into_color(self) -> U

Convert into T with values clamped to the color defined bounds Read more
Source§

impl<T, U> IntoColorUnclamped<U> for T
where U: FromColorUnclamped<T>,

Source§

fn into_color_unclamped(self) -> U

Convert into T. The resulting color might be invalid in its color space Read more
Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> IntoStimulus<T> for T

Source§

fn into_stimulus(self) -> T

Converts self into T, while performing the appropriate scaling, rounding and clamping.
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, C> TryComponentsInto<C> for T
where C: TryFromComponents<T>,

Source§

type Error = <C as TryFromComponents<T>>::Error

The error for when try_into_colors fails to cast.
Source§

fn try_components_into(self) -> Result<C, <T as TryComponentsInto<C>>::Error>

Try to cast this collection of color components into a collection of colors. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T, U> TryIntoColor<U> for T
where U: TryFromColor<T>,

Source§

fn try_into_color(self) -> Result<U, OutOfBounds<U>>

Convert into T, returning ok if the color is inside of its defined range, otherwise an OutOfBounds error is returned which contains the unclamped color. Read more
Source§

impl<C, U> UintsFrom<C> for U
where C: IntoUints<U>,

Source§

fn uints_from(colors: C) -> U

Cast a collection of colors into a collection of unsigned integers.
Source§

impl<C, U> UintsInto<C> for U
where C: FromUints<U>,

Source§

fn uints_into(self) -> C

Cast this collection of unsigned integers into a collection of colors.