diff options
Diffstat (limited to 'src/widget/canvas.rs')
-rw-r--r-- | src/widget/canvas.rs | 238 |
1 files changed, 0 insertions, 238 deletions
diff --git a/src/widget/canvas.rs b/src/widget/canvas.rs deleted file mode 100644 index bc5995c6..00000000 --- a/src/widget/canvas.rs +++ /dev/null @@ -1,238 +0,0 @@ -//! Draw 2D graphics for your users. -pub mod event; - -mod cursor; -mod program; - -pub use cursor::Cursor; -pub use event::Event; -pub use program::Program; - -pub use iced_renderer::geometry::*; - -use crate::{Length, Point, Rectangle, Size, Vector}; - -use iced_native::layout::{self, Layout}; -use iced_native::mouse; -use iced_native::renderer; -use iced_native::widget::tree::{self, Tree}; -use iced_native::{Clipboard, Element, Shell, Widget}; - -use std::marker::PhantomData; - -/// A widget capable of drawing 2D graphics. -/// -/// ## Drawing a simple circle -/// If you want to get a quick overview, here's how we can draw a simple circle: -/// -/// ```no_run -/// use iced::widget::canvas::{self, Canvas, Cursor, Fill, Frame, Geometry, Path, Program}; -/// use iced::{Color, Rectangle, Theme, Renderer}; -/// -/// // First, we define the data we need for drawing -/// #[derive(Debug)] -/// struct Circle { -/// radius: f32, -/// } -/// -/// // Then, we implement the `Program` trait -/// impl Program<()> for Circle { -/// type State = (); -/// -/// fn draw(&self, _state: &(), renderer: &Renderer, _theme: &Theme, bounds: Rectangle, _cursor: Cursor) -> Vec<Geometry>{ -/// // We prepare a new `Frame` -/// let mut frame = Frame::new(renderer, bounds.size()); -/// -/// // We create a `Path` representing a simple circle -/// let circle = Path::circle(frame.center(), self.radius); -/// -/// // And fill it with some color -/// frame.fill(&circle, Color::BLACK); -/// -/// // Finally, we produce the geometry -/// vec![frame.into_geometry()] -/// } -/// } -/// -/// // Finally, we simply use our `Circle` to create the `Canvas`! -/// let canvas = Canvas::new(Circle { radius: 50.0 }); -/// ``` -#[derive(Debug)] -pub struct Canvas<P, Message, Renderer = crate::Renderer> -where - Renderer: iced_renderer::geometry::Renderer, - P: Program<Message, Renderer>, -{ - width: Length, - height: Length, - program: P, - message_: PhantomData<Message>, - theme_: PhantomData<Renderer>, -} - -impl<P, Message, Renderer> Canvas<P, Message, Renderer> -where - Renderer: iced_renderer::geometry::Renderer, - P: Program<Message, Renderer>, -{ - const DEFAULT_SIZE: f32 = 100.0; - - /// Creates a new [`Canvas`]. - pub fn new(program: P) -> Self { - Canvas { - width: Length::Fixed(Self::DEFAULT_SIZE), - height: Length::Fixed(Self::DEFAULT_SIZE), - program, - message_: PhantomData, - theme_: PhantomData, - } - } - - /// Sets the width of the [`Canvas`]. - pub fn width(mut self, width: impl Into<Length>) -> Self { - self.width = width.into(); - self - } - - /// Sets the height of the [`Canvas`]. - pub fn height(mut self, height: impl Into<Length>) -> Self { - self.height = height.into(); - self - } -} - -impl<P, Message, Renderer> Widget<Message, Renderer> - for Canvas<P, Message, Renderer> -where - Renderer: iced_renderer::geometry::Renderer, - P: Program<Message, Renderer>, -{ - fn tag(&self) -> tree::Tag { - struct Tag<T>(T); - tree::Tag::of::<Tag<P::State>>() - } - - fn state(&self) -> tree::State { - tree::State::new(P::State::default()) - } - - fn width(&self) -> Length { - self.width - } - - fn height(&self) -> Length { - self.height - } - - fn layout( - &self, - _renderer: &Renderer, - limits: &layout::Limits, - ) -> layout::Node { - let limits = limits.width(self.width).height(self.height); - let size = limits.resolve(Size::ZERO); - - layout::Node::new(size) - } - - fn on_event( - &mut self, - tree: &mut Tree, - event: iced_native::Event, - layout: Layout<'_>, - cursor_position: Point, - _renderer: &Renderer, - _clipboard: &mut dyn Clipboard, - shell: &mut Shell<'_, Message>, - ) -> event::Status { - let bounds = layout.bounds(); - - let canvas_event = match event { - iced_native::Event::Mouse(mouse_event) => { - Some(Event::Mouse(mouse_event)) - } - iced_native::Event::Touch(touch_event) => { - Some(Event::Touch(touch_event)) - } - iced_native::Event::Keyboard(keyboard_event) => { - Some(Event::Keyboard(keyboard_event)) - } - _ => None, - }; - - let cursor = Cursor::from_window_position(cursor_position); - - if let Some(canvas_event) = canvas_event { - let state = tree.state.downcast_mut::<P::State>(); - - let (event_status, message) = - self.program.update(state, canvas_event, bounds, cursor); - - if let Some(message) = message { - shell.publish(message); - } - - return event_status; - } - - event::Status::Ignored - } - - fn mouse_interaction( - &self, - tree: &Tree, - layout: Layout<'_>, - cursor_position: Point, - _viewport: &Rectangle, - _renderer: &Renderer, - ) -> mouse::Interaction { - let bounds = layout.bounds(); - let cursor = Cursor::from_window_position(cursor_position); - let state = tree.state.downcast_ref::<P::State>(); - - self.program.mouse_interaction(state, bounds, cursor) - } - - fn draw( - &self, - tree: &Tree, - renderer: &mut Renderer, - theme: &Renderer::Theme, - _style: &renderer::Style, - layout: Layout<'_>, - cursor_position: Point, - _viewport: &Rectangle, - ) { - let bounds = layout.bounds(); - - if bounds.width < 1.0 || bounds.height < 1.0 { - return; - } - - let cursor = Cursor::from_window_position(cursor_position); - let state = tree.state.downcast_ref::<P::State>(); - - renderer.with_translation( - Vector::new(bounds.x, bounds.y), - |renderer| { - renderer.draw( - self.program.draw(state, renderer, theme, bounds, cursor), - ); - }, - ); - } -} - -impl<'a, P, Message, Renderer> From<Canvas<P, Message, Renderer>> - for Element<'a, Message, Renderer> -where - Message: 'a, - Renderer: 'a + iced_renderer::geometry::Renderer, - P: Program<Message, Renderer> + 'a, -{ - fn from( - canvas: Canvas<P, Message, Renderer>, - ) -> Element<'a, Message, Renderer> { - Element::new(canvas) - } -} |