pub struct Context<'a> { /* private fields */ }
Expand description
Implementations§
Source§impl<'a> Context<'a>
impl<'a> Context<'a>
Sourcepub fn new(
width: u16,
height: u16,
x_bounds: [f64; 2],
y_bounds: [f64; 2],
marker: Marker,
) -> Self
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,
);
Sourcepub fn draw<S>(&mut self, shape: &S)where
S: Shape,
pub fn draw<S>(&mut self, shape: &S)where
S: Shape,
Draw the given Shape
in this context
Examples found in repository?
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
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}
Sourcepub fn layer(&mut self)
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.
Sourcepub fn print<T>(&mut self, x: f64, y: f64, line: T)
pub fn print<T>(&mut self, x: f64, y: f64, line: T)
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?
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§
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 Swhere
T: Real + Zero + Arithmetics + Clone,
Swp: WhitePoint<T>,
Dwp: WhitePoint<T>,
D: AdaptFrom<S, Swp, Dwp, T>,
impl<S, D, Swp, Dwp, T> AdaptInto<D, Swp, Dwp, T> for Swhere
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) -> Dwhere
M: TransformMatrix<T>,
fn adapt_into_using<M>(self, method: M) -> Dwhere
M: TransformMatrix<T>,
Source§fn adapt_into(self) -> D
fn adapt_into(self) -> D
Source§impl<T, C> ArraysFrom<C> for Twhere
C: IntoArrays<T>,
impl<T, C> ArraysFrom<C> for Twhere
C: IntoArrays<T>,
Source§fn arrays_from(colors: C) -> T
fn arrays_from(colors: C) -> T
Source§impl<T, C> ArraysInto<C> for Twhere
C: FromArrays<T>,
impl<T, C> ArraysInto<C> for Twhere
C: FromArrays<T>,
Source§fn arrays_into(self) -> C
fn arrays_into(self) -> C
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<WpParam, T, U> Cam16IntoUnclamped<WpParam, T> for Uwhere
T: FromCam16Unclamped<WpParam, U>,
impl<WpParam, T, U> Cam16IntoUnclamped<WpParam, T> for Uwhere
T: FromCam16Unclamped<WpParam, U>,
Source§type Scalar = <T as FromCam16Unclamped<WpParam, U>>::Scalar
type Scalar = <T as FromCam16Unclamped<WpParam, U>>::Scalar
parameters
when converting.Source§fn cam16_into_unclamped(
self,
parameters: BakedParameters<WpParam, <U as Cam16IntoUnclamped<WpParam, T>>::Scalar>,
) -> T
fn cam16_into_unclamped( self, parameters: BakedParameters<WpParam, <U as Cam16IntoUnclamped<WpParam, T>>::Scalar>, ) -> T
self
into C
, using the provided parameters.Source§impl<T, C> ComponentsFrom<C> for Twhere
C: IntoComponents<T>,
impl<T, C> ComponentsFrom<C> for Twhere
C: IntoComponents<T>,
Source§fn components_from(colors: C) -> T
fn components_from(colors: C) -> T
Source§impl<T> FromAngle<T> for T
impl<T> FromAngle<T> for T
Source§fn from_angle(angle: T) -> T
fn from_angle(angle: T) -> T
angle
.Source§impl<T, U> FromStimulus<U> for Twhere
U: IntoStimulus<T>,
impl<T, U> FromStimulus<U> for Twhere
U: IntoStimulus<T>,
Source§fn from_stimulus(other: U) -> T
fn from_stimulus(other: U) -> T
other
into Self
, while performing the appropriate scaling,
rounding and clamping.Source§impl<T, U> IntoAngle<U> for Twhere
U: FromAngle<T>,
impl<T, U> IntoAngle<U> for Twhere
U: FromAngle<T>,
Source§fn into_angle(self) -> U
fn into_angle(self) -> U
T
.Source§impl<WpParam, T, U> IntoCam16Unclamped<WpParam, T> for Uwhere
T: Cam16FromUnclamped<WpParam, U>,
impl<WpParam, T, U> IntoCam16Unclamped<WpParam, T> for Uwhere
T: Cam16FromUnclamped<WpParam, U>,
Source§type Scalar = <T as Cam16FromUnclamped<WpParam, U>>::Scalar
type Scalar = <T as Cam16FromUnclamped<WpParam, U>>::Scalar
parameters
when converting.Source§fn into_cam16_unclamped(
self,
parameters: BakedParameters<WpParam, <U as IntoCam16Unclamped<WpParam, T>>::Scalar>,
) -> T
fn into_cam16_unclamped( self, parameters: BakedParameters<WpParam, <U as IntoCam16Unclamped<WpParam, T>>::Scalar>, ) -> T
self
into C
, using the provided parameters.Source§impl<T, U> IntoColor<U> for Twhere
U: FromColor<T>,
impl<T, U> IntoColor<U> for Twhere
U: FromColor<T>,
Source§fn into_color(self) -> U
fn into_color(self) -> U
Source§impl<T, U> IntoColorUnclamped<U> for Twhere
U: FromColorUnclamped<T>,
impl<T, U> IntoColorUnclamped<U> for Twhere
U: FromColorUnclamped<T>,
Source§fn into_color_unclamped(self) -> U
fn into_color_unclamped(self) -> U
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
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 moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
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 moreSource§impl<T> IntoStimulus<T> for T
impl<T> IntoStimulus<T> for T
Source§fn into_stimulus(self) -> T
fn into_stimulus(self) -> T
self
into T
, while performing the appropriate scaling,
rounding and clamping.Source§impl<T, C> TryComponentsInto<C> for Twhere
C: TryFromComponents<T>,
impl<T, C> TryComponentsInto<C> for Twhere
C: TryFromComponents<T>,
Source§type Error = <C as TryFromComponents<T>>::Error
type Error = <C as TryFromComponents<T>>::Error
try_into_colors
fails to cast.Source§fn try_components_into(self) -> Result<C, <T as TryComponentsInto<C>>::Error>
fn try_components_into(self) -> Result<C, <T as TryComponentsInto<C>>::Error>
Source§impl<T, U> TryIntoColor<U> for Twhere
U: TryFromColor<T>,
impl<T, U> TryIntoColor<U> for Twhere
U: TryFromColor<T>,
Source§fn try_into_color(self) -> Result<U, OutOfBounds<U>>
fn try_into_color(self) -> Result<U, OutOfBounds<U>>
OutOfBounds
error is returned which contains
the unclamped color. Read more