Write documentation for the new canvas
API
This commit is contained in:
parent
1501a93915
commit
d4c4198f72
@ -20,7 +20,7 @@
|
|||||||
//! [`wgpu`]: https://github.com/gfx-rs/wgpu-rs
|
//! [`wgpu`]: https://github.com/gfx-rs/wgpu-rs
|
||||||
//! [WebGPU API]: https://gpuweb.github.io/gpuweb/
|
//! [WebGPU API]: https://gpuweb.github.io/gpuweb/
|
||||||
//! [`wgpu_glyph`]: https://github.com/hecrj/wgpu_glyph
|
//! [`wgpu_glyph`]: https://github.com/hecrj/wgpu_glyph
|
||||||
//#![deny(missing_docs)]
|
#![deny(missing_docs)]
|
||||||
#![deny(missing_debug_implementations)]
|
#![deny(missing_debug_implementations)]
|
||||||
#![deny(unused_results)]
|
#![deny(unused_results)]
|
||||||
#![forbid(unsafe_code)]
|
#![forbid(unsafe_code)]
|
||||||
|
@ -48,12 +48,15 @@ pub use text::Text;
|
|||||||
///
|
///
|
||||||
/// - [`clock`], an application that uses the [`Canvas`] widget to draw a clock
|
/// - [`clock`], an application that uses the [`Canvas`] widget to draw a clock
|
||||||
/// and its hands to display the current time.
|
/// and its hands to display the current time.
|
||||||
|
/// - [`game_of_life`], an interactive version of the Game of Life, invented by
|
||||||
|
/// John Conway.
|
||||||
/// - [`solar_system`], an animated solar system drawn using the [`Canvas`] widget
|
/// - [`solar_system`], an animated solar system drawn using the [`Canvas`] widget
|
||||||
/// and showcasing how to compose different transforms.
|
/// and showcasing how to compose different transforms.
|
||||||
///
|
///
|
||||||
/// [examples]: https://github.com/hecrj/iced/tree/0.1/examples
|
/// [examples]: https://github.com/hecrj/iced/tree/master/examples
|
||||||
/// [`clock`]: https://github.com/hecrj/iced/tree/0.1/examples/clock
|
/// [`clock`]: https://github.com/hecrj/iced/tree/master/examples/clock
|
||||||
/// [`solar_system`]: https://github.com/hecrj/iced/tree/0.1/examples/solar_system
|
/// [`game_of_life`]: https://github.com/hecrj/iced/tree/master/examples/game_of_life
|
||||||
|
/// [`solar_system`]: https://github.com/hecrj/iced/tree/master/examples/solar_system
|
||||||
///
|
///
|
||||||
/// ## Drawing a simple circle
|
/// ## Drawing a simple circle
|
||||||
/// If you want to get a quick overview, here's how we can draw a simple circle:
|
/// If you want to get a quick overview, here's how we can draw a simple circle:
|
||||||
@ -89,7 +92,7 @@ pub use text::Text;
|
|||||||
/// }
|
/// }
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// // Finally, we simply use our `Cache` to create the `Canvas`!
|
/// // Finally, we simply use our `Circle` to create the `Canvas`!
|
||||||
/// let canvas = Canvas::new(Circle { radius: 50.0 });
|
/// let canvas = Canvas::new(Circle { radius: 50.0 });
|
||||||
/// ```
|
/// ```
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -19,13 +19,14 @@ impl Default for State {
|
|||||||
State::Empty
|
State::Empty
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/// A simple cache that stores generated geometry to avoid recomputation.
|
/// A simple cache that stores generated [`Geometry`] to avoid recomputation.
|
||||||
///
|
///
|
||||||
/// A [`Cache`] will not redraw its geometry unless the dimensions of its layer
|
/// A [`Cache`] will not redraw its geometry unless the dimensions of its layer
|
||||||
/// change or it is explicitly cleared.
|
/// change or it is explicitly cleared.
|
||||||
///
|
///
|
||||||
/// [`Layer`]: ../trait.Layer.html
|
/// [`Layer`]: ../trait.Layer.html
|
||||||
/// [`Cache`]: struct.Cache.html
|
/// [`Cache`]: struct.Cache.html
|
||||||
|
/// [`Geometry`]: struct.Geometry.html
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
pub struct Cache {
|
pub struct Cache {
|
||||||
state: RefCell<State>,
|
state: RefCell<State>,
|
||||||
@ -41,30 +42,41 @@ impl Cache {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Clears the cache, forcing a redraw the next time it is used.
|
/// Clears the [`Cache`], forcing a redraw the next time it is used.
|
||||||
///
|
///
|
||||||
/// [`Cached`]: struct.Cached.html
|
/// [`Cache`]: struct.Cache.html
|
||||||
pub fn clear(&mut self) {
|
pub fn clear(&mut self) {
|
||||||
*self.state.borrow_mut() = State::Empty;
|
*self.state.borrow_mut() = State::Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn draw(
|
/// Draws [`Geometry`] using the provided closure and stores it in the
|
||||||
&self,
|
/// [`Cache`].
|
||||||
new_bounds: Size,
|
///
|
||||||
draw_fn: impl Fn(&mut Frame),
|
/// The closure will only be called when
|
||||||
) -> Geometry {
|
/// - the bounds have changed since the previous draw call.
|
||||||
|
/// - the [`Cache`] is empty or has been explicitly cleared.
|
||||||
|
///
|
||||||
|
/// Otherwise, the previously stored [`Geometry`] will be returned. The
|
||||||
|
/// [`Cache`] is not cleared in this case. In other words, it will keep
|
||||||
|
/// returning the stored [`Geometry`] if needed.
|
||||||
|
///
|
||||||
|
/// [`Cache`]: struct.Cache.html
|
||||||
|
pub fn draw(&self, bounds: Size, draw_fn: impl Fn(&mut Frame)) -> Geometry {
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
|
|
||||||
if let State::Filled { bounds, primitive } = self.state.borrow().deref()
|
if let State::Filled {
|
||||||
|
bounds: cached_bounds,
|
||||||
|
primitive,
|
||||||
|
} = self.state.borrow().deref()
|
||||||
{
|
{
|
||||||
if *bounds == new_bounds {
|
if *cached_bounds == bounds {
|
||||||
return Geometry::from_primitive(Primitive::Cached {
|
return Geometry::from_primitive(Primitive::Cached {
|
||||||
cache: primitive.clone(),
|
cache: primitive.clone(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut frame = Frame::new(new_bounds);
|
let mut frame = Frame::new(bounds);
|
||||||
draw_fn(&mut frame);
|
draw_fn(&mut frame);
|
||||||
|
|
||||||
let primitive = {
|
let primitive = {
|
||||||
@ -74,7 +86,7 @@ impl Cache {
|
|||||||
};
|
};
|
||||||
|
|
||||||
*self.state.borrow_mut() = State::Filled {
|
*self.state.borrow_mut() = State::Filled {
|
||||||
bounds: new_bounds,
|
bounds,
|
||||||
primitive: primitive.clone(),
|
primitive: primitive.clone(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,8 +1,12 @@
|
|||||||
use iced_native::{Point, Rectangle};
|
use iced_native::{Point, Rectangle};
|
||||||
|
|
||||||
|
/// The mouse cursor state.
|
||||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||||
pub enum Cursor {
|
pub enum Cursor {
|
||||||
|
/// The cursor has a defined position.
|
||||||
Available(Point),
|
Available(Point),
|
||||||
|
|
||||||
|
/// The cursor is currently unavailable (i.e. out of bounds or busy).
|
||||||
Unavailable,
|
Unavailable,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -17,6 +21,9 @@ impl Cursor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the absolute position of the [`Cursor`], if available.
|
||||||
|
///
|
||||||
|
/// [`Cursor`]: enum.Cursor.html
|
||||||
pub fn position(&self) -> Option<Point> {
|
pub fn position(&self) -> Option<Point> {
|
||||||
match self {
|
match self {
|
||||||
Cursor::Available(position) => Some(*position),
|
Cursor::Available(position) => Some(*position),
|
||||||
@ -24,6 +31,13 @@ impl Cursor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the relative position of the [`Cursor`] inside the given bounds,
|
||||||
|
/// if available.
|
||||||
|
///
|
||||||
|
/// If the [`Cursor`] is not over the provided bounds, this method will
|
||||||
|
/// return `None`.
|
||||||
|
///
|
||||||
|
/// [`Cursor`]: enum.Cursor.html
|
||||||
pub fn position_in(&self, bounds: &Rectangle) -> Option<Point> {
|
pub fn position_in(&self, bounds: &Rectangle) -> Option<Point> {
|
||||||
if self.is_over(bounds) {
|
if self.is_over(bounds) {
|
||||||
self.position_from(bounds.position())
|
self.position_from(bounds.position())
|
||||||
@ -32,6 +46,10 @@ impl Cursor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the relative position of the [`Cursor`] from the given origin,
|
||||||
|
/// if available.
|
||||||
|
///
|
||||||
|
/// [`Cursor`]: enum.Cursor.html
|
||||||
pub fn position_from(&self, origin: Point) -> Option<Point> {
|
pub fn position_from(&self, origin: Point) -> Option<Point> {
|
||||||
match self {
|
match self {
|
||||||
Cursor::Available(position) => {
|
Cursor::Available(position) => {
|
||||||
@ -41,6 +59,10 @@ impl Cursor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns whether the [`Cursor`] is currently over the provided bounds
|
||||||
|
/// or not.
|
||||||
|
///
|
||||||
|
/// [`Cursor`]: enum.Cursor.html
|
||||||
pub fn is_over(&self, bounds: &Rectangle) -> bool {
|
pub fn is_over(&self, bounds: &Rectangle) -> bool {
|
||||||
match self {
|
match self {
|
||||||
Cursor::Available(position) => bounds.contains(*position),
|
Cursor::Available(position) => bounds.contains(*position),
|
||||||
|
@ -1,6 +1,10 @@
|
|||||||
use iced_native::mouse;
|
use iced_native::mouse;
|
||||||
|
|
||||||
|
/// A [`Canvas`] event.
|
||||||
|
///
|
||||||
|
/// [`Canvas`]: struct.Event.html
|
||||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||||
pub enum Event {
|
pub enum Event {
|
||||||
|
/// A mouse event.
|
||||||
Mouse(mouse::Event),
|
Mouse(mouse::Event),
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,13 @@
|
|||||||
use crate::Primitive;
|
use crate::Primitive;
|
||||||
|
|
||||||
|
/// A bunch of shapes that can be drawn.
|
||||||
|
///
|
||||||
|
/// [`Geometry`] can be easily generated with a [`Frame`] or stored in a
|
||||||
|
/// [`Cache`].
|
||||||
|
///
|
||||||
|
/// [`Geometry`]: struct.Geometry.html
|
||||||
|
/// [`Frame`]: struct.Frame.html
|
||||||
|
/// [`Cache`]: struct.Cache.html
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct Geometry(Primitive);
|
pub struct Geometry(Primitive);
|
||||||
|
|
||||||
@ -8,6 +16,12 @@ impl Geometry {
|
|||||||
Self(primitive)
|
Self(primitive)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Turns the [`Geometry`] into a [`Primitive`].
|
||||||
|
///
|
||||||
|
/// This can be useful if you are building a custom widget.
|
||||||
|
///
|
||||||
|
/// [`Geometry`]: struct.Geometry.html
|
||||||
|
/// [`Primitive`]: ../enum.Primitive.html
|
||||||
pub fn into_primitive(self) -> Primitive {
|
pub fn into_primitive(self) -> Primitive {
|
||||||
self.0
|
self.0
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,27 @@
|
|||||||
use crate::canvas::{Cursor, Event, Geometry};
|
use crate::canvas::{Cursor, Event, Geometry};
|
||||||
use iced_native::{MouseCursor, Rectangle};
|
use iced_native::{MouseCursor, Rectangle};
|
||||||
|
|
||||||
|
/// The state and logic of a [`Canvas`].
|
||||||
|
///
|
||||||
|
/// A [`Program`] can mutate internal state and produce messages for an
|
||||||
|
/// application.
|
||||||
|
///
|
||||||
|
/// [`Canvas`]: struct.Canvas.html
|
||||||
|
/// [`Program`]: trait.Program.html
|
||||||
pub trait Program<Message> {
|
pub trait Program<Message> {
|
||||||
|
/// Updates the state of the [`Program`].
|
||||||
|
///
|
||||||
|
/// When a [`Program`] is used in a [`Canvas`], the runtime will call this
|
||||||
|
/// method for each [`Event`].
|
||||||
|
///
|
||||||
|
/// This method can optionally return a `Message` to notify an application
|
||||||
|
/// of any meaningful interactions.
|
||||||
|
///
|
||||||
|
/// By default, this method does and returns nothing.
|
||||||
|
///
|
||||||
|
/// [`Program`]: trait.Program.html
|
||||||
|
/// [`Canvas`]: struct.Canvas.html
|
||||||
|
/// [`Event`]: enum.Event.html
|
||||||
fn update(
|
fn update(
|
||||||
&mut self,
|
&mut self,
|
||||||
_event: Event,
|
_event: Event,
|
||||||
@ -11,8 +31,24 @@ pub trait Program<Message> {
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Draws the state of the [`Program`], producing a bunch of [`Geometry`].
|
||||||
|
///
|
||||||
|
/// [`Geometry`] can be easily generated with a [`Frame`] or stored in a
|
||||||
|
/// [`Cache`].
|
||||||
|
///
|
||||||
|
/// [`Program`]: trait.Program.html
|
||||||
|
/// [`Geometry`]: struct.Geometry.html
|
||||||
|
/// [`Frame`]: struct.Frame.html
|
||||||
|
/// [`Cache`]: struct.Cache.html
|
||||||
fn draw(&self, bounds: Rectangle, cursor: Cursor) -> Vec<Geometry>;
|
fn draw(&self, bounds: Rectangle, cursor: Cursor) -> Vec<Geometry>;
|
||||||
|
|
||||||
|
/// Returns the mouse cursor state of the [`Program`].
|
||||||
|
///
|
||||||
|
/// The mouse cursor returned will be in effect even if the cursor position
|
||||||
|
/// is out of bounds of the program's [`Canvas`].
|
||||||
|
///
|
||||||
|
/// [`Program`]: trait.Program.html
|
||||||
|
/// [`Canvas`]: struct.Canvas.html
|
||||||
fn mouse_cursor(&self, _bounds: Rectangle, _cursor: Cursor) -> MouseCursor {
|
fn mouse_cursor(&self, _bounds: Rectangle, _cursor: Cursor) -> MouseCursor {
|
||||||
MouseCursor::default()
|
MouseCursor::default()
|
||||||
}
|
}
|
||||||
|
@ -15,18 +15,32 @@ pub struct Stroke {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Stroke {
|
impl Stroke {
|
||||||
|
/// Sets the color of the [`Stroke`].
|
||||||
|
///
|
||||||
|
/// [`Stroke`]: struct.Stroke.html
|
||||||
pub fn with_color(self, color: Color) -> Stroke {
|
pub fn with_color(self, color: Color) -> Stroke {
|
||||||
Stroke { color, ..self }
|
Stroke { color, ..self }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Sets the width of the [`Stroke`].
|
||||||
|
///
|
||||||
|
/// [`Stroke`]: struct.Stroke.html
|
||||||
pub fn with_width(self, width: f32) -> Stroke {
|
pub fn with_width(self, width: f32) -> Stroke {
|
||||||
Stroke { width, ..self }
|
Stroke { width, ..self }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Sets the [`LineCap`] of the [`Stroke`].
|
||||||
|
///
|
||||||
|
/// [`LineCap`]: enum.LineCap.html
|
||||||
|
/// [`Stroke`]: struct.Stroke.html
|
||||||
pub fn with_line_cap(self, line_cap: LineCap) -> Stroke {
|
pub fn with_line_cap(self, line_cap: LineCap) -> Stroke {
|
||||||
Stroke { line_cap, ..self }
|
Stroke { line_cap, ..self }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Sets the [`LineJoin`] of the [`Stroke`].
|
||||||
|
///
|
||||||
|
/// [`LineJoin`]: enum.LineJoin.html
|
||||||
|
/// [`Stroke`]: struct.Stroke.html
|
||||||
pub fn with_line_join(self, line_join: LineJoin) -> Stroke {
|
pub fn with_line_join(self, line_join: LineJoin) -> Stroke {
|
||||||
Stroke { line_join, ..self }
|
Stroke { line_join, ..self }
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user