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
|
||||
//! [WebGPU API]: https://gpuweb.github.io/gpuweb/
|
||||
//! [`wgpu_glyph`]: https://github.com/hecrj/wgpu_glyph
|
||||
//#![deny(missing_docs)]
|
||||
#![deny(missing_docs)]
|
||||
#![deny(missing_debug_implementations)]
|
||||
#![deny(unused_results)]
|
||||
#![forbid(unsafe_code)]
|
||||
|
@ -48,12 +48,15 @@ pub use text::Text;
|
||||
///
|
||||
/// - [`clock`], an application that uses the [`Canvas`] widget to draw a clock
|
||||
/// 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
|
||||
/// and showcasing how to compose different transforms.
|
||||
///
|
||||
/// [examples]: https://github.com/hecrj/iced/tree/0.1/examples
|
||||
/// [`clock`]: https://github.com/hecrj/iced/tree/0.1/examples/clock
|
||||
/// [`solar_system`]: https://github.com/hecrj/iced/tree/0.1/examples/solar_system
|
||||
/// [examples]: https://github.com/hecrj/iced/tree/master/examples
|
||||
/// [`clock`]: https://github.com/hecrj/iced/tree/master/examples/clock
|
||||
/// [`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
|
||||
/// 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 });
|
||||
/// ```
|
||||
#[derive(Debug)]
|
||||
|
@ -19,13 +19,14 @@ impl Default for State {
|
||||
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
|
||||
/// change or it is explicitly cleared.
|
||||
///
|
||||
/// [`Layer`]: ../trait.Layer.html
|
||||
/// [`Cache`]: struct.Cache.html
|
||||
/// [`Geometry`]: struct.Geometry.html
|
||||
#[derive(Debug, Default)]
|
||||
pub struct Cache {
|
||||
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) {
|
||||
*self.state.borrow_mut() = State::Empty;
|
||||
}
|
||||
|
||||
pub fn draw(
|
||||
&self,
|
||||
new_bounds: Size,
|
||||
draw_fn: impl Fn(&mut Frame),
|
||||
) -> Geometry {
|
||||
/// Draws [`Geometry`] using the provided closure and stores it in the
|
||||
/// [`Cache`].
|
||||
///
|
||||
/// The closure will only be called when
|
||||
/// - 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;
|
||||
|
||||
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 {
|
||||
cache: primitive.clone(),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
let mut frame = Frame::new(new_bounds);
|
||||
let mut frame = Frame::new(bounds);
|
||||
draw_fn(&mut frame);
|
||||
|
||||
let primitive = {
|
||||
@ -74,7 +86,7 @@ impl Cache {
|
||||
};
|
||||
|
||||
*self.state.borrow_mut() = State::Filled {
|
||||
bounds: new_bounds,
|
||||
bounds,
|
||||
primitive: primitive.clone(),
|
||||
};
|
||||
|
||||
|
@ -1,8 +1,12 @@
|
||||
use iced_native::{Point, Rectangle};
|
||||
|
||||
/// The mouse cursor state.
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
pub enum Cursor {
|
||||
/// The cursor has a defined position.
|
||||
Available(Point),
|
||||
|
||||
/// The cursor is currently unavailable (i.e. out of bounds or busy).
|
||||
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> {
|
||||
match self {
|
||||
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> {
|
||||
if self.is_over(bounds) {
|
||||
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> {
|
||||
match self {
|
||||
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 {
|
||||
match self {
|
||||
Cursor::Available(position) => bounds.contains(*position),
|
||||
|
@ -1,6 +1,10 @@
|
||||
use iced_native::mouse;
|
||||
|
||||
/// A [`Canvas`] event.
|
||||
///
|
||||
/// [`Canvas`]: struct.Event.html
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
pub enum Event {
|
||||
/// A mouse event.
|
||||
Mouse(mouse::Event),
|
||||
}
|
||||
|
@ -1,5 +1,13 @@
|
||||
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)]
|
||||
pub struct Geometry(Primitive);
|
||||
|
||||
@ -8,6 +16,12 @@ impl Geometry {
|
||||
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 {
|
||||
self.0
|
||||
}
|
||||
|
@ -1,7 +1,27 @@
|
||||
use crate::canvas::{Cursor, Event, Geometry};
|
||||
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> {
|
||||
/// 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(
|
||||
&mut self,
|
||||
_event: Event,
|
||||
@ -11,8 +31,24 @@ pub trait Program<Message> {
|
||||
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>;
|
||||
|
||||
/// 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 {
|
||||
MouseCursor::default()
|
||||
}
|
||||
|
@ -15,18 +15,32 @@ pub struct Stroke {
|
||||
}
|
||||
|
||||
impl Stroke {
|
||||
/// Sets the color of the [`Stroke`].
|
||||
///
|
||||
/// [`Stroke`]: struct.Stroke.html
|
||||
pub fn with_color(self, color: Color) -> Stroke {
|
||||
Stroke { color, ..self }
|
||||
}
|
||||
|
||||
/// Sets the width of the [`Stroke`].
|
||||
///
|
||||
/// [`Stroke`]: struct.Stroke.html
|
||||
pub fn with_width(self, width: f32) -> Stroke {
|
||||
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 {
|
||||
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 {
|
||||
Stroke { line_join, ..self }
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user