[go: up one dir, main page]

Struct Canvas

Source
pub struct Canvas<'a, F>
where F: Fn(&mut Context<'_>),
{ /* private fields */ }
Expand description

The Canvas widget provides a means to draw shapes (Lines, Rectangles, Circles, etc.) on a grid.

By default the grid is made of Braille patterns but you may change the marker to use a different set of symbols. If your terminal or font does not support this unicode block, you will see unicode replacement characters (�) instead of braille dots. The Braille patterns provide a more fine grained result (2x4 dots) but you might want to use a simple dot, block, or bar instead by calling the marker method if your target environment does not support those symbols,

See Unicode Braille Patterns for more info.

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.

The Canvas widget is used by calling the Canvas::paint method and passing a closure that will be used to draw on the canvas. The closure will be passed a Context object that can be used to draw shapes on the canvas.

The Context object provides a Context::draw method that can be used to draw shapes on the canvas. The Context::layer method can be used to save the current state of the canvas and start a new layer. This is useful if you want to draw multiple shapes on the canvas in specific order. The Context object also provides a Context::print method that can be used to print text on the canvas. Note that the text is always printed on top of the canvas and is not affected by the layers.

§Examples

use ratatui::{
    style::Color,
    widgets::{
        canvas::{Canvas, Line, Map, MapResolution, Rectangle},
        Block,
    },
};

Canvas::default()
    .block(Block::bordered().title("Canvas"))
    .x_bounds([-180.0, 180.0])
    .y_bounds([-90.0, 90.0])
    .paint(|ctx| {
        ctx.draw(&Map {
            resolution: MapResolution::High,
            color: Color::White,
        });
        ctx.layer();
        ctx.draw(&Line {
            x1: 0.0,
            y1: 10.0,
            x2: 10.0,
            y2: 10.0,
            color: Color::White,
        });
        ctx.draw(&Rectangle {
            x: 10.0,
            y: 20.0,
            width: 10.0,
            height: 10.0,
            color: Color::Red,
        });
    });

Implementations§

Source§

impl<'a, F> Canvas<'a, F>
where F: Fn(&mut Context<'_>),

Source

pub fn block(self, block: Block<'a>) -> Self

Wraps the canvas with a custom Block widget.

This is a fluent setter method which must be chained or used as it consumes self

Examples found in repository?
examples/canvas.rs (line 178)
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 (lines 116-120)
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 const fn x_bounds(self, bounds: [f64; 2]) -> 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

Examples found in repository?
examples/canvas.rs (line 187)
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 124)
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 const fn y_bounds(self, bounds: [f64; 2]) -> 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

Examples found in repository?
examples/canvas.rs (line 188)
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 125)
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 paint(self, f: F) -> Self

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

Examples found in repository?
examples/canvas.rs (lines 180-186)
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 (lines 126-145)
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 const fn background_color(self, color: Color) -> Self

Change the background Color of the entire canvas

This is a fluent setter method which must be chained or used as it consumes self

Examples found in repository?
examples/demo2/tabs/traceroute.rs (line 115)
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 const fn marker(self, marker: Marker) -> 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.

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.

§Examples
use ratatui::{symbols, widgets::canvas::Canvas};

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| {});
Examples found in repository?
examples/canvas.rs (line 179)
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 121)
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}

Trait Implementations§

Source§

impl<'a, F> Clone for Canvas<'a, F>
where F: Fn(&mut Context<'_>) + Clone,

Source§

fn clone(&self) -> Canvas<'a, F>

Returns a copy of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl<'a, F> Debug for Canvas<'a, F>
where F: Fn(&mut Context<'_>) + Debug,

Source§

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

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

impl<'a, F> Default for Canvas<'a, F>
where F: Fn(&mut Context<'_>),

Source§

fn default() -> Self

Returns the “default value” for a type. Read more
Source§

impl<'a, F> PartialEq for Canvas<'a, F>
where F: Fn(&mut Context<'_>) + PartialEq,

Source§

fn eq(&self, other: &Canvas<'a, F>) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl<F> Widget for Canvas<'_, F>
where F: Fn(&mut Context<'_>),

Source§

fn render(self, area: Rect, buf: &mut Buffer)

Draws the current state of the widget in the given buffer. That is the only method required to implement a custom widget.
Source§

impl<F> WidgetRef for Canvas<'_, F>
where F: Fn(&mut Context<'_>),

Source§

fn render_ref(&self, area: Rect, buf: &mut Buffer)

Available on crate feature unstable-widget-ref only.
Draws the current state of the widget in the given buffer. That is the only method required to implement a custom widget.
Source§

impl<'a, F> StructuralPartialEq for Canvas<'a, F>
where F: Fn(&mut Context<'_>),

Auto Trait Implementations§

§

impl<'a, F> Freeze for Canvas<'a, F>
where F: Freeze,

§

impl<'a, F> RefUnwindSafe for Canvas<'a, F>
where F: RefUnwindSafe,

§

impl<'a, F> Send for Canvas<'a, F>
where F: Send,

§

impl<'a, F> Sync for Canvas<'a, F>
where F: Sync,

§

impl<'a, F> Unpin for Canvas<'a, F>
where F: Unpin,

§

impl<'a, F> UnwindSafe for Canvas<'a, F>
where F: UnwindSafe,

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> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
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> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
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.