diff options
author | 2020-05-28 21:52:34 +0200 | |
---|---|---|
committer | 2020-05-28 21:52:34 +0200 | |
commit | d3db055583f4cbef1441fd66d07da70424bd1200 (patch) | |
tree | 9f695bd26f688a5aaf3b8fa687a0e3ff096ffe11 /wgpu/src/widget | |
parent | ead4186870d1b46015986f702dd63382498060fc (diff) | |
parent | 709ed1f3f7ad8cf67a176763e394aaae4e808e93 (diff) | |
download | iced-d3db055583f4cbef1441fd66d07da70424bd1200.tar.gz iced-d3db055583f4cbef1441fd66d07da70424bd1200.tar.bz2 iced-d3db055583f4cbef1441fd66d07da70424bd1200.zip |
Merge pull request #354 from hecrj/feature/glow-renderer
OpenGL renderer and backend-agnostic graphics subcrate
Diffstat (limited to 'wgpu/src/widget')
-rw-r--r-- | wgpu/src/widget/button.rs | 2 | ||||
-rw-r--r-- | wgpu/src/widget/canvas.rs | 226 | ||||
-rw-r--r-- | wgpu/src/widget/canvas/cache.rs | 108 | ||||
-rw-r--r-- | wgpu/src/widget/canvas/cursor.rs | 72 | ||||
-rw-r--r-- | wgpu/src/widget/canvas/event.rs | 10 | ||||
-rw-r--r-- | wgpu/src/widget/canvas/fill.rs | 20 | ||||
-rw-r--r-- | wgpu/src/widget/canvas/frame.rs | 367 | ||||
-rw-r--r-- | wgpu/src/widget/canvas/geometry.rs | 34 | ||||
-rw-r--r-- | wgpu/src/widget/canvas/path.rs | 79 | ||||
-rw-r--r-- | wgpu/src/widget/canvas/path/arc.rs | 44 | ||||
-rw-r--r-- | wgpu/src/widget/canvas/path/builder.rs | 180 | ||||
-rw-r--r-- | wgpu/src/widget/canvas/program.rs | 85 | ||||
-rw-r--r-- | wgpu/src/widget/canvas/stroke.rs | 115 | ||||
-rw-r--r-- | wgpu/src/widget/canvas/text.rs | 49 | ||||
-rw-r--r-- | wgpu/src/widget/checkbox.rs | 2 | ||||
-rw-r--r-- | wgpu/src/widget/container.rs | 2 | ||||
-rw-r--r-- | wgpu/src/widget/progress_bar.rs | 2 | ||||
-rw-r--r-- | wgpu/src/widget/radio.rs | 2 | ||||
-rw-r--r-- | wgpu/src/widget/scrollable.rs | 2 | ||||
-rw-r--r-- | wgpu/src/widget/slider.rs | 2 | ||||
-rw-r--r-- | wgpu/src/widget/text.rs | 7 | ||||
-rw-r--r-- | wgpu/src/widget/text_input.rs | 2 |
22 files changed, 9 insertions, 1403 deletions
diff --git a/wgpu/src/widget/button.rs b/wgpu/src/widget/button.rs index b738c55e..fee7a7f8 100644 --- a/wgpu/src/widget/button.rs +++ b/wgpu/src/widget/button.rs @@ -6,8 +6,8 @@ //! [`State`]: struct.State.html use crate::Renderer; +pub use iced_graphics::button::{Style, StyleSheet}; pub use iced_native::button::State; -pub use iced_style::button::{Style, StyleSheet}; /// A widget that produces a message when clicked. /// diff --git a/wgpu/src/widget/canvas.rs b/wgpu/src/widget/canvas.rs index 2fc10ea0..bef34857 100644 --- a/wgpu/src/widget/canvas.rs +++ b/wgpu/src/widget/canvas.rs @@ -6,228 +6,4 @@ //! //! [`Canvas`]: struct.Canvas.html //! [`Frame`]: struct.Frame.html -use crate::{Defaults, Primitive, Renderer}; - -use iced_native::{ - layout, mouse, Clipboard, Element, Hasher, Layout, Length, Point, Size, - Vector, Widget, -}; -use std::hash::Hash; -use std::marker::PhantomData; - -pub mod path; - -mod cache; -mod cursor; -mod event; -mod fill; -mod frame; -mod geometry; -mod program; -mod stroke; -mod text; - -pub use cache::Cache; -pub use cursor::Cursor; -pub use event::Event; -pub use fill::Fill; -pub use frame::Frame; -pub use geometry::Geometry; -pub use path::Path; -pub use program::Program; -pub use stroke::{LineCap, LineJoin, Stroke}; -pub use text::Text; - -/// A widget capable of drawing 2D graphics. -/// -/// [`Canvas`]: struct.Canvas.html -/// -/// # Examples -/// The repository has a couple of [examples] showcasing how to use a -/// [`Canvas`]: -/// -/// - [`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/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: -/// -/// ```no_run -/// # mod iced { -/// # pub use iced_wgpu::canvas; -/// # pub use iced_native::{Color, Rectangle}; -/// # } -/// use iced::canvas::{self, Canvas, Cursor, Fill, Frame, Geometry, Path, Program}; -/// use iced::{Color, Rectangle}; -/// -/// // 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 { -/// fn draw(&self, bounds: Rectangle, _cursor: Cursor) -> Vec<Geometry>{ -/// // We prepare a new `Frame` -/// let mut frame = Frame::new(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, Fill::Color(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<Message, P: Program<Message>> { - width: Length, - height: Length, - program: P, - phantom: PhantomData<Message>, -} - -impl<Message, P: Program<Message>> Canvas<Message, P> { - const DEFAULT_SIZE: u16 = 100; - - /// Creates a new [`Canvas`]. - /// - /// [`Canvas`]: struct.Canvas.html - pub fn new(program: P) -> Self { - Canvas { - width: Length::Units(Self::DEFAULT_SIZE), - height: Length::Units(Self::DEFAULT_SIZE), - program, - phantom: PhantomData, - } - } - - /// Sets the width of the [`Canvas`]. - /// - /// [`Canvas`]: struct.Canvas.html - pub fn width(mut self, width: Length) -> Self { - self.width = width; - self - } - - /// Sets the height of the [`Canvas`]. - /// - /// [`Canvas`]: struct.Canvas.html - pub fn height(mut self, height: Length) -> Self { - self.height = height; - self - } -} - -impl<Message, P: Program<Message>> Widget<Message, Renderer> - for Canvas<Message, P> -{ - 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, - event: iced_native::Event, - layout: Layout<'_>, - cursor_position: Point, - messages: &mut Vec<Message>, - _renderer: &Renderer, - _clipboard: Option<&dyn Clipboard>, - ) { - let bounds = layout.bounds(); - - let canvas_event = match event { - iced_native::Event::Mouse(mouse_event) => { - Some(Event::Mouse(mouse_event)) - } - _ => None, - }; - - let cursor = Cursor::from_window_position(cursor_position); - - if let Some(canvas_event) = canvas_event { - if let Some(message) = - self.program.update(canvas_event, bounds, cursor) - { - messages.push(message); - } - } - } - - fn draw( - &self, - _renderer: &mut Renderer, - _defaults: &Defaults, - layout: Layout<'_>, - cursor_position: Point, - ) -> (Primitive, mouse::Interaction) { - let bounds = layout.bounds(); - let translation = Vector::new(bounds.x, bounds.y); - let cursor = Cursor::from_window_position(cursor_position); - - ( - Primitive::Translate { - translation, - content: Box::new(Primitive::Group { - primitives: self - .program - .draw(bounds, cursor) - .into_iter() - .map(Geometry::into_primitive) - .collect(), - }), - }, - self.program.mouse_interaction(bounds, cursor), - ) - } - - fn hash_layout(&self, state: &mut Hasher) { - struct Marker; - std::any::TypeId::of::<Marker>().hash(state); - - self.width.hash(state); - self.height.hash(state); - } -} - -impl<'a, Message, P: Program<Message> + 'a> From<Canvas<Message, P>> - for Element<'a, Message, Renderer> -where - Message: 'static, -{ - fn from(canvas: Canvas<Message, P>) -> Element<'a, Message, Renderer> { - Element::new(canvas) - } -} +pub use iced_graphics::canvas::*; diff --git a/wgpu/src/widget/canvas/cache.rs b/wgpu/src/widget/canvas/cache.rs deleted file mode 100644 index 4b28d164..00000000 --- a/wgpu/src/widget/canvas/cache.rs +++ /dev/null @@ -1,108 +0,0 @@ -use crate::{ - canvas::{Frame, Geometry}, - Primitive, -}; - -use iced_native::Size; -use std::{cell::RefCell, sync::Arc}; - -enum State { - Empty, - Filled { - bounds: Size, - primitive: Arc<Primitive>, - }, -} - -impl Default for State { - fn default() -> Self { - State::Empty - } -} -/// 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>, -} - -impl Cache { - /// Creates a new empty [`Cache`]. - /// - /// [`Cache`]: struct.Cache.html - pub fn new() -> Self { - Cache { - state: Default::default(), - } - } - - /// Clears the [`Cache`], forcing a redraw the next time it is used. - /// - /// [`Cache`]: struct.Cache.html - pub fn clear(&mut self) { - *self.state.borrow_mut() = State::Empty; - } - - /// 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: cached_bounds, - primitive, - } = self.state.borrow().deref() - { - if *cached_bounds == bounds { - return Geometry::from_primitive(Primitive::Cached { - cache: primitive.clone(), - }); - } - } - - let mut frame = Frame::new(bounds); - draw_fn(&mut frame); - - let primitive = { - let geometry = frame.into_geometry(); - - Arc::new(geometry.into_primitive()) - }; - - *self.state.borrow_mut() = State::Filled { - bounds, - primitive: primitive.clone(), - }; - - Geometry::from_primitive(Primitive::Cached { cache: primitive }) - } -} - -impl std::fmt::Debug for State { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - State::Empty => write!(f, "Empty"), - State::Filled { primitive, bounds } => f - .debug_struct("Filled") - .field("primitive", primitive) - .field("bounds", bounds) - .finish(), - } - } -} diff --git a/wgpu/src/widget/canvas/cursor.rs b/wgpu/src/widget/canvas/cursor.rs deleted file mode 100644 index 456760ea..00000000 --- a/wgpu/src/widget/canvas/cursor.rs +++ /dev/null @@ -1,72 +0,0 @@ -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, -} - -impl Cursor { - // TODO: Remove this once this type is used in `iced_native` to encode - // proper cursor availability - pub(crate) fn from_window_position(position: Point) -> Self { - if position.x < 0.0 || position.y < 0.0 { - Cursor::Unavailable - } else { - Cursor::Available(position) - } - } - - /// 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), - Cursor::Unavailable => None, - } - } - - /// 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()) - } else { - None - } - } - - /// 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) => { - Some(Point::new(position.x - origin.x, position.y - origin.y)) - } - Cursor::Unavailable => None, - } - } - - /// 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), - Cursor::Unavailable => false, - } - } -} diff --git a/wgpu/src/widget/canvas/event.rs b/wgpu/src/widget/canvas/event.rs deleted file mode 100644 index ad11f51e..00000000 --- a/wgpu/src/widget/canvas/event.rs +++ /dev/null @@ -1,10 +0,0 @@ -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), -} diff --git a/wgpu/src/widget/canvas/fill.rs b/wgpu/src/widget/canvas/fill.rs deleted file mode 100644 index a2010e45..00000000 --- a/wgpu/src/widget/canvas/fill.rs +++ /dev/null @@ -1,20 +0,0 @@ -use iced_native::Color; - -/// The style used to fill geometry. -#[derive(Debug, Clone, Copy)] -pub enum Fill { - /// Fill with a color. - Color(Color), -} - -impl Default for Fill { - fn default() -> Fill { - Fill::Color(Color::BLACK) - } -} - -impl From<Color> for Fill { - fn from(color: Color) -> Fill { - Fill::Color(color) - } -} diff --git a/wgpu/src/widget/canvas/frame.rs b/wgpu/src/widget/canvas/frame.rs deleted file mode 100644 index 5262ab4e..00000000 --- a/wgpu/src/widget/canvas/frame.rs +++ /dev/null @@ -1,367 +0,0 @@ -use iced_native::{Point, Rectangle, Size, Vector}; - -use crate::{ - canvas::{Fill, Geometry, Path, Stroke, Text}, - triangle, Primitive, -}; - -/// The frame of a [`Canvas`]. -/// -/// [`Canvas`]: struct.Canvas.html -#[derive(Debug)] -pub struct Frame { - size: Size, - buffers: lyon::tessellation::VertexBuffers<triangle::Vertex2D, u32>, - primitives: Vec<Primitive>, - transforms: Transforms, -} - -#[derive(Debug)] -struct Transforms { - previous: Vec<Transform>, - current: Transform, -} - -#[derive(Debug, Clone, Copy)] -struct Transform { - raw: lyon::math::Transform, - is_identity: bool, -} - -impl Frame { - /// Creates a new empty [`Frame`] with the given dimensions. - /// - /// The default coordinate system of a [`Frame`] has its origin at the - /// top-left corner of its bounds. - /// - /// [`Frame`]: struct.Frame.html - pub fn new(size: Size) -> Frame { - Frame { - size, - buffers: lyon::tessellation::VertexBuffers::new(), - primitives: Vec::new(), - transforms: Transforms { - previous: Vec::new(), - current: Transform { - raw: lyon::math::Transform::identity(), - is_identity: true, - }, - }, - } - } - - /// Returns the width of the [`Frame`]. - /// - /// [`Frame`]: struct.Frame.html - #[inline] - pub fn width(&self) -> f32 { - self.size.width - } - - /// Returns the width of the [`Frame`]. - /// - /// [`Frame`]: struct.Frame.html - #[inline] - pub fn height(&self) -> f32 { - self.size.height - } - - /// Returns the dimensions of the [`Frame`]. - /// - /// [`Frame`]: struct.Frame.html - #[inline] - pub fn size(&self) -> Size { - self.size - } - - /// Returns the coordinate of the center of the [`Frame`]. - /// - /// [`Frame`]: struct.Frame.html - #[inline] - pub fn center(&self) -> Point { - Point::new(self.size.width / 2.0, self.size.height / 2.0) - } - - /// Draws the given [`Path`] on the [`Frame`] by filling it with the - /// provided style. - /// - /// [`Path`]: path/struct.Path.html - /// [`Frame`]: struct.Frame.html - pub fn fill(&mut self, path: &Path, fill: impl Into<Fill>) { - use lyon::tessellation::{ - BuffersBuilder, FillOptions, FillTessellator, - }; - - let mut buffers = BuffersBuilder::new( - &mut self.buffers, - FillVertex(match fill.into() { - Fill::Color(color) => color.into_linear(), - }), - ); - - let mut tessellator = FillTessellator::new(); - - let result = if self.transforms.current.is_identity { - tessellator.tessellate_path( - path.raw(), - &FillOptions::default(), - &mut buffers, - ) - } else { - let path = path.transformed(&self.transforms.current.raw); - - tessellator.tessellate_path( - path.raw(), - &FillOptions::default(), - &mut buffers, - ) - }; - - let _ = result.expect("Tessellate path"); - } - - /// Draws an axis-aligned rectangle given its top-left corner coordinate and - /// its `Size` on the [`Frame`] by filling it with the provided style. - /// - /// [`Frame`]: struct.Frame.html - pub fn fill_rectangle( - &mut self, - top_left: Point, - size: Size, - fill: impl Into<Fill>, - ) { - use lyon::tessellation::{BuffersBuilder, FillOptions}; - - let mut buffers = BuffersBuilder::new( - &mut self.buffers, - FillVertex(match fill.into() { - Fill::Color(color) => color.into_linear(), - }), - ); - - let top_left = - self.transforms.current.raw.transform_point( - lyon::math::Point::new(top_left.x, top_left.y), - ); - - let size = - self.transforms.current.raw.transform_vector( - lyon::math::Vector::new(size.width, size.height), - ); - - let _ = lyon::tessellation::basic_shapes::fill_rectangle( - &lyon::math::Rect::new(top_left, size.into()), - &FillOptions::default(), - &mut buffers, - ) - .expect("Fill rectangle"); - } - - /// Draws the stroke of the given [`Path`] on the [`Frame`] with the - /// provided style. - /// - /// [`Path`]: path/struct.Path.html - /// [`Frame`]: struct.Frame.html - pub fn stroke(&mut self, path: &Path, stroke: impl Into<Stroke>) { - use lyon::tessellation::{ - BuffersBuilder, StrokeOptions, StrokeTessellator, - }; - - let stroke = stroke.into(); - - let mut buffers = BuffersBuilder::new( - &mut self.buffers, - StrokeVertex(stroke.color.into_linear()), - ); - - let mut tessellator = StrokeTessellator::new(); - - let mut options = StrokeOptions::default(); - options.line_width = stroke.width; - options.start_cap = stroke.line_cap.into(); - options.end_cap = stroke.line_cap.into(); - options.line_join = stroke.line_join.into(); - - let result = if self.transforms.current.is_identity { - tessellator.tessellate_path(path.raw(), &options, &mut buffers) - } else { - let path = path.transformed(&self.transforms.current.raw); - - tessellator.tessellate_path(path.raw(), &options, &mut buffers) - }; - - let _ = result.expect("Stroke path"); - } - - /// Draws the characters of the given [`Text`] on the [`Frame`], filling - /// them with the given color. - /// - /// __Warning:__ Text currently does not work well with rotations and scale - /// transforms! The position will be correctly transformed, but the - /// resulting glyphs will not be rotated or scaled properly. - /// - /// Additionally, all text will be rendered on top of all the layers of - /// a [`Canvas`]. Therefore, it is currently only meant to be used for - /// overlays, which is the most common use case. - /// - /// Support for vectorial text is planned, and should address all these - /// limitations. - /// - /// [`Text`]: struct.Text.html - /// [`Frame`]: struct.Frame.html - /// [`Canvas`]: struct.Canvas.html - pub fn fill_text(&mut self, text: impl Into<Text>) { - use std::f32; - - let text = text.into(); - - let position = if self.transforms.current.is_identity { - text.position - } else { - let transformed = self.transforms.current.raw.transform_point( - lyon::math::Point::new(text.position.x, text.position.y), - ); - - Point::new(transformed.x, transformed.y) - }; - - // TODO: Use vectorial text instead of primitive - self.primitives.push(Primitive::Text { - content: text.content, - bounds: Rectangle { - x: position.x, - y: position.y, - width: f32::INFINITY, - height: f32::INFINITY, - }, - color: text.color, - size: text.size, - font: text.font, - horizontal_alignment: text.horizontal_alignment, - vertical_alignment: text.vertical_alignment, - }); - } - - /// Stores the current transform of the [`Frame`] and executes the given - /// drawing operations, restoring the transform afterwards. - /// - /// This method is useful to compose transforms and perform drawing - /// operations in different coordinate systems. - /// - /// [`Frame`]: struct.Frame.html - #[inline] - pub fn with_save(&mut self, f: impl FnOnce(&mut Frame)) { - self.transforms.previous.push(self.transforms.current); - - f(self); - - self.transforms.current = self.transforms.previous.pop().unwrap(); - } - - /// Applies a translation to the current transform of the [`Frame`]. - /// - /// [`Frame`]: struct.Frame.html - #[inline] - pub fn translate(&mut self, translation: Vector) { - self.transforms.current.raw = self - .transforms - .current - .raw - .pre_translate(lyon::math::Vector::new( - translation.x, - translation.y, - )); - self.transforms.current.is_identity = false; - } - - /// Applies a rotation to the current transform of the [`Frame`]. - /// - /// [`Frame`]: struct.Frame.html - #[inline] - pub fn rotate(&mut self, angle: f32) { - self.transforms.current.raw = self - .transforms - .current - .raw - .pre_rotate(lyon::math::Angle::radians(-angle)); - self.transforms.current.is_identity = false; - } - - /// Applies a scaling to the current transform of the [`Frame`]. - /// - /// [`Frame`]: struct.Frame.html - #[inline] - pub fn scale(&mut self, scale: f32) { - self.transforms.current.raw = - self.transforms.current.raw.pre_scale(scale, scale); - self.transforms.current.is_identity = false; - } - - /// Produces the [`Geometry`] representing everything drawn on the [`Frame`]. - /// - /// [`Frame`]: struct.Frame.html - /// [`Geometry`]: struct.Geometry.html - pub fn into_geometry(mut self) -> Geometry { - if !self.buffers.indices.is_empty() { - self.primitives.push(Primitive::Mesh2D { - size: self.size, - buffers: triangle::Mesh2D { - vertices: self.buffers.vertices, - indices: self.buffers.indices, - }, - }); - } - - Geometry::from_primitive(Primitive::Group { - primitives: self.primitives, - }) - } -} - -struct FillVertex([f32; 4]); - -impl lyon::tessellation::BasicVertexConstructor<triangle::Vertex2D> - for FillVertex -{ - fn new_vertex( - &mut self, - position: lyon::math::Point, - ) -> triangle::Vertex2D { - triangle::Vertex2D { - position: [position.x, position.y], - color: self.0, - } - } -} - -impl lyon::tessellation::FillVertexConstructor<triangle::Vertex2D> - for FillVertex -{ - fn new_vertex( - &mut self, - position: lyon::math::Point, - _attributes: lyon::tessellation::FillAttributes<'_>, - ) -> triangle::Vertex2D { - triangle::Vertex2D { - position: [position.x, position.y], - color: self.0, - } - } -} - -struct StrokeVertex([f32; 4]); - -impl lyon::tessellation::StrokeVertexConstructor<triangle::Vertex2D> - for StrokeVertex -{ - fn new_vertex( - &mut self, - position: lyon::math::Point, - _attributes: lyon::tessellation::StrokeAttributes<'_, '_>, - ) -> triangle::Vertex2D { - triangle::Vertex2D { - position: [position.x, position.y], - color: self.0, - } - } -} diff --git a/wgpu/src/widget/canvas/geometry.rs b/wgpu/src/widget/canvas/geometry.rs deleted file mode 100644 index 4cadee39..00000000 --- a/wgpu/src/widget/canvas/geometry.rs +++ /dev/null @@ -1,34 +0,0 @@ -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); - -impl Geometry { - pub(crate) fn from_primitive(primitive: Primitive) -> Self { - 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 - } -} - -impl From<Geometry> for Primitive { - fn from(geometry: Geometry) -> Primitive { - geometry.0 - } -} diff --git a/wgpu/src/widget/canvas/path.rs b/wgpu/src/widget/canvas/path.rs deleted file mode 100644 index c26bf187..00000000 --- a/wgpu/src/widget/canvas/path.rs +++ /dev/null @@ -1,79 +0,0 @@ -//! Build different kinds of 2D shapes. -pub mod arc; - -mod builder; - -#[doc(no_inline)] -pub use arc::Arc; -pub use builder::Builder; - -use iced_native::{Point, Size}; - -/// An immutable set of points that may or may not be connected. -/// -/// A single [`Path`] can represent different kinds of 2D shapes! -/// -/// [`Path`]: struct.Path.html -#[derive(Debug, Clone)] -pub struct Path { - raw: lyon::path::Path, -} - -impl Path { - /// Creates a new [`Path`] with the provided closure. - /// - /// Use the [`Builder`] to configure your [`Path`]. - /// - /// [`Path`]: struct.Path.html - /// [`Builder`]: struct.Builder.html - pub fn new(f: impl FnOnce(&mut Builder)) -> Self { - let mut builder = Builder::new(); - - // TODO: Make it pure instead of side-effect-based (?) - f(&mut builder); - - builder.build() - } - - /// Creates a new [`Path`] representing a line segment given its starting - /// and end points. - /// - /// [`Path`]: struct.Path.html - pub fn line(from: Point, to: Point) -> Self { - Self::new(|p| { - p.move_to(from); - p.line_to(to); - }) - } - - /// Creates a new [`Path`] representing a rectangle given its top-left - /// corner coordinate and its `Size`. - /// - /// [`Path`]: struct.Path.html - pub fn rectangle(top_left: Point, size: Size) -> Self { - Self::new(|p| p.rectangle(top_left, size)) - } - - /// Creates a new [`Path`] representing a circle given its center - /// coordinate and its radius. - /// - /// [`Path`]: struct.Path.html - pub fn circle(center: Point, radius: f32) -> Self { - Self::new(|p| p.circle(center, radius)) - } - - #[inline] - pub(crate) fn raw(&self) -> &lyon::path::Path { - &self.raw - } - - #[inline] - pub(crate) fn transformed( - &self, - transform: &lyon::math::Transform, - ) -> Path { - Path { - raw: self.raw.transformed(transform), - } - } -} diff --git a/wgpu/src/widget/canvas/path/arc.rs b/wgpu/src/widget/canvas/path/arc.rs deleted file mode 100644 index 343191f1..00000000 --- a/wgpu/src/widget/canvas/path/arc.rs +++ /dev/null @@ -1,44 +0,0 @@ -//! Build and draw curves. -use iced_native::{Point, Vector}; - -/// A segment of a differentiable curve. -#[derive(Debug, Clone, Copy)] -pub struct Arc { - /// The center of the arc. - pub center: Point, - /// The radius of the arc. - pub radius: f32, - /// The start of the segment's angle, clockwise rotation. - pub start_angle: f32, - /// The end of the segment's angle, clockwise rotation. - pub end_angle: f32, -} - -/// An elliptical [`Arc`]. -/// -/// [`Arc`]: struct.Arc.html -#[derive(Debug, Clone, Copy)] -pub struct Elliptical { - /// The center of the arc. - pub center: Point, - /// The radii of the arc's ellipse, defining its axes. - pub radii: Vector, - /// The rotation of the arc's ellipse. - pub rotation: f32, - /// The start of the segment's angle, clockwise rotation. - pub start_angle: f32, - /// The end of the segment's angle, clockwise rotation. - pub end_angle: f32, -} - -impl From<Arc> for Elliptical { - fn from(arc: Arc) -> Elliptical { - Elliptical { - center: arc.center, - radii: Vector::new(arc.radius, arc.radius), - rotation: 0.0, - start_angle: arc.start_angle, - end_angle: arc.end_angle, - } - } -} diff --git a/wgpu/src/widget/canvas/path/builder.rs b/wgpu/src/widget/canvas/path/builder.rs deleted file mode 100644 index 6511fa52..00000000 --- a/wgpu/src/widget/canvas/path/builder.rs +++ /dev/null @@ -1,180 +0,0 @@ -use crate::canvas::path::{arc, Arc, Path}; - -use iced_native::{Point, Size}; -use lyon::path::builder::{Build, FlatPathBuilder, PathBuilder, SvgBuilder}; - -/// A [`Path`] builder. -/// -/// Once a [`Path`] is built, it can no longer be mutated. -/// -/// [`Path`]: struct.Path.html -#[allow(missing_debug_implementations)] -pub struct Builder { - raw: lyon::path::builder::SvgPathBuilder<lyon::path::Builder>, -} - -impl Builder { - /// Creates a new [`Builder`]. - /// - /// [`Builder`]: struct.Builder.html - pub fn new() -> Builder { - Builder { - raw: lyon::path::Path::builder().with_svg(), - } - } - - /// Moves the starting point of a new sub-path to the given `Point`. - #[inline] - pub fn move_to(&mut self, point: Point) { - let _ = self.raw.move_to(lyon::math::Point::new(point.x, point.y)); - } - - /// Connects the last point in the [`Path`] to the given `Point` with a - /// straight line. - /// - /// [`Path`]: struct.Path.html - #[inline] - pub fn line_to(&mut self, point: Point) { - let _ = self.raw.line_to(lyon::math::Point::new(point.x, point.y)); - } - - /// Adds an [`Arc`] to the [`Path`] from `start_angle` to `end_angle` in - /// a clockwise direction. - /// - /// [`Arc`]: struct.Arc.html - /// [`Path`]: struct.Path.html - #[inline] - pub fn arc(&mut self, arc: Arc) { - self.ellipse(arc.into()); - } - - /// Adds a circular arc to the [`Path`] with the given control points and - /// radius. - /// - /// The arc is connected to the previous point by a straight line, if - /// necessary. - /// - /// [`Path`]: struct.Path.html - pub fn arc_to(&mut self, a: Point, b: Point, radius: f32) { - use lyon::{math, path}; - - let a = math::Point::new(a.x, a.y); - - if self.raw.current_position() != a { - let _ = self.raw.line_to(a); - } - - let _ = self.raw.arc_to( - math::Vector::new(radius, radius), - math::Angle::radians(0.0), - path::ArcFlags::default(), - math::Point::new(b.x, b.y), - ); - } - - /// Adds an [`Ellipse`] to the [`Path`] using a clockwise direction. - /// - /// [`Ellipse`]: struct.Arc.html - /// [`Path`]: struct.Path.html - pub fn ellipse(&mut self, arc: arc::Elliptical) { - use lyon::{geom, math}; - - let arc = geom::Arc { - center: math::Point::new(arc.center.x, arc.center.y), - radii: math::Vector::new(arc.radii.x, arc.radii.y), - x_rotation: math::Angle::radians(arc.rotation), - start_angle: math::Angle::radians(arc.start_angle), - sweep_angle: math::Angle::radians(arc.end_angle), - }; - - let _ = self.raw.move_to(arc.sample(0.0)); - - arc.for_each_quadratic_bezier(&mut |curve| { - let _ = self.raw.quadratic_bezier_to(curve.ctrl, curve.to); - }); - } - - /// Adds a cubic Bézier curve to the [`Path`] given its two control points - /// and its end point. - /// - /// [`Path`]: struct.Path.html - #[inline] - pub fn bezier_curve_to( - &mut self, - control_a: Point, - control_b: Point, - to: Point, - ) { - use lyon::math; - - let _ = self.raw.cubic_bezier_to( - math::Point::new(control_a.x, control_a.y), - math::Point::new(control_b.x, control_b.y), - math::Point::new(to.x, to.y), - ); - } - - /// Adds a quadratic Bézier curve to the [`Path`] given its control point - /// and its end point. - /// - /// [`Path`]: struct.Path.html - #[inline] - pub fn quadratic_curve_to(&mut self, control: Point, to: Point) { - use lyon::math; - - let _ = self.raw.quadratic_bezier_to( - math::Point::new(control.x, control.y), - math::Point::new(to.x, to.y), - ); - } - - /// Adds a rectangle to the [`Path`] given its top-left corner coordinate - /// and its `Size`. - /// - /// [`Path`]: struct.Path.html - #[inline] - pub fn rectangle(&mut self, top_left: Point, size: Size) { - self.move_to(top_left); - self.line_to(Point::new(top_left.x + size.width, top_left.y)); - self.line_to(Point::new( - top_left.x + size.width, - top_left.y + size.height, - )); - self.line_to(Point::new(top_left.x, top_left.y + size.height)); - self.close(); - } - - /// Adds a circle to the [`Path`] given its center coordinate and its - /// radius. - /// - /// [`Path`]: struct.Path.html - #[inline] - pub fn circle(&mut self, center: Point, radius: f32) { - self.arc(Arc { - center, - radius, - start_angle: 0.0, - end_angle: 2.0 * std::f32::consts::PI, - }); - } - - /// Closes the current sub-path in the [`Path`] with a straight line to - /// the starting point. - /// - /// [`Path`]: struct.Path.html - #[inline] - pub fn close(&mut self) { - self.raw.close() - } - - /// Builds the [`Path`] of this [`Builder`]. - /// - /// [`Path`]: struct.Path.html - /// [`Builder`]: struct.Builder.html - #[inline] - pub fn build(self) -> Path { - Path { - raw: self.raw.build(), - } - } -} diff --git a/wgpu/src/widget/canvas/program.rs b/wgpu/src/widget/canvas/program.rs deleted file mode 100644 index 725d9d72..00000000 --- a/wgpu/src/widget/canvas/program.rs +++ /dev/null @@ -1,85 +0,0 @@ -use crate::canvas::{Cursor, Event, Geometry}; -use iced_native::{mouse, 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, - _bounds: Rectangle, - _cursor: Cursor, - ) -> Option<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 current mouse interaction of the [`Program`]. - /// - /// The interaction 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_interaction( - &self, - _bounds: Rectangle, - _cursor: Cursor, - ) -> mouse::Interaction { - mouse::Interaction::default() - } -} - -impl<T, Message> Program<Message> for &mut T -where - T: Program<Message>, -{ - fn update( - &mut self, - event: Event, - bounds: Rectangle, - cursor: Cursor, - ) -> Option<Message> { - T::update(self, event, bounds, cursor) - } - - fn draw(&self, bounds: Rectangle, cursor: Cursor) -> Vec<Geometry> { - T::draw(self, bounds, cursor) - } - - fn mouse_interaction( - &self, - bounds: Rectangle, - cursor: Cursor, - ) -> mouse::Interaction { - T::mouse_interaction(self, bounds, cursor) - } -} diff --git a/wgpu/src/widget/canvas/stroke.rs b/wgpu/src/widget/canvas/stroke.rs deleted file mode 100644 index 5b6fc56a..00000000 --- a/wgpu/src/widget/canvas/stroke.rs +++ /dev/null @@ -1,115 +0,0 @@ -use iced_native::Color; - -/// The style of a stroke. -#[derive(Debug, Clone, Copy)] -pub struct Stroke { - /// The color of the stroke. - pub color: Color, - /// The distance between the two edges of the stroke. - pub width: f32, - /// The shape to be used at the end of open subpaths when they are stroked. - pub line_cap: LineCap, - /// The shape to be used at the corners of paths or basic shapes when they - /// are stroked. - pub line_join: LineJoin, -} - -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 } - } -} - -impl Default for Stroke { - fn default() -> Stroke { - Stroke { - color: Color::BLACK, - width: 1.0, - line_cap: LineCap::default(), - line_join: LineJoin::default(), - } - } -} - -/// The shape used at the end of open subpaths when they are stroked. -#[derive(Debug, Clone, Copy)] -pub enum LineCap { - /// The stroke for each sub-path does not extend beyond its two endpoints. - Butt, - /// At the end of each sub-path, the shape representing the stroke will be - /// extended by a square. - Square, - /// At the end of each sub-path, the shape representing the stroke will be - /// extended by a semicircle. - Round, -} - -impl Default for LineCap { - fn default() -> LineCap { - LineCap::Butt - } -} - -impl From<LineCap> for lyon::tessellation::LineCap { - fn from(line_cap: LineCap) -> lyon::tessellation::LineCap { - match line_cap { - LineCap::Butt => lyon::tessellation::LineCap::Butt, - LineCap::Square => lyon::tessellation::LineCap::Square, - LineCap::Round => lyon::tessellation::LineCap::Round, - } - } -} - -/// The shape used at the corners of paths or basic shapes when they are -/// stroked. -#[derive(Debug, Clone, Copy)] -pub enum LineJoin { - /// A sharp corner. - Miter, - /// A round corner. - Round, - /// A bevelled corner. - Bevel, -} - -impl Default for LineJoin { - fn default() -> LineJoin { - LineJoin::Miter - } -} - -impl From<LineJoin> for lyon::tessellation::LineJoin { - fn from(line_join: LineJoin) -> lyon::tessellation::LineJoin { - match line_join { - LineJoin::Miter => lyon::tessellation::LineJoin::Miter, - LineJoin::Round => lyon::tessellation::LineJoin::Round, - LineJoin::Bevel => lyon::tessellation::LineJoin::Bevel, - } - } -} diff --git a/wgpu/src/widget/canvas/text.rs b/wgpu/src/widget/canvas/text.rs deleted file mode 100644 index c4cae30e..00000000 --- a/wgpu/src/widget/canvas/text.rs +++ /dev/null @@ -1,49 +0,0 @@ -use iced_native::{Color, Font, HorizontalAlignment, Point, VerticalAlignment}; - -/// A bunch of text that can be drawn to a canvas -#[derive(Debug, Clone)] -pub struct Text { - /// The contents of the text - pub content: String, - /// The position where to begin drawing the text (top-left corner coordinates) - pub position: Point, - /// The color of the text - pub color: Color, - /// The size of the text - pub size: f32, - /// The font of the text - pub font: Font, - /// The horizontal alignment of the text - pub horizontal_alignment: HorizontalAlignment, - /// The vertical alignment of the text - pub vertical_alignment: VerticalAlignment, -} - -impl Default for Text { - fn default() -> Text { - Text { - content: String::new(), - position: Point::ORIGIN, - color: Color::BLACK, - size: 16.0, - font: Font::Default, - horizontal_alignment: HorizontalAlignment::Left, - vertical_alignment: VerticalAlignment::Top, - } - } -} - -impl From<String> for Text { - fn from(content: String) -> Text { - Text { - content, - ..Default::default() - } - } -} - -impl From<&str> for Text { - fn from(content: &str) -> Text { - String::from(content).into() - } -} diff --git a/wgpu/src/widget/checkbox.rs b/wgpu/src/widget/checkbox.rs index da0d7a84..d27d77cc 100644 --- a/wgpu/src/widget/checkbox.rs +++ b/wgpu/src/widget/checkbox.rs @@ -1,7 +1,7 @@ //! Show toggle controls using checkboxes. use crate::Renderer; -pub use iced_style::checkbox::{Style, StyleSheet}; +pub use iced_graphics::checkbox::{Style, StyleSheet}; /// A box that can be checked. /// diff --git a/wgpu/src/widget/container.rs b/wgpu/src/widget/container.rs index 9a93a246..bc26cef2 100644 --- a/wgpu/src/widget/container.rs +++ b/wgpu/src/widget/container.rs @@ -1,7 +1,7 @@ //! Decorate content and apply alignment. use crate::Renderer; -pub use iced_style::container::{Style, StyleSheet}; +pub use iced_graphics::container::{Style, StyleSheet}; /// An element decorating some content. /// diff --git a/wgpu/src/widget/progress_bar.rs b/wgpu/src/widget/progress_bar.rs index 770bcea8..a636a3a6 100644 --- a/wgpu/src/widget/progress_bar.rs +++ b/wgpu/src/widget/progress_bar.rs @@ -6,7 +6,7 @@ //! [`ProgressBar`]: type.ProgressBar.html use crate::Renderer; -pub use iced_style::progress_bar::{Style, StyleSheet}; +pub use iced_graphics::progress_bar::{Style, StyleSheet}; /// A bar that displays progress. /// diff --git a/wgpu/src/widget/radio.rs b/wgpu/src/widget/radio.rs index 6e5cf042..0b843d1f 100644 --- a/wgpu/src/widget/radio.rs +++ b/wgpu/src/widget/radio.rs @@ -1,7 +1,7 @@ //! Create choices using radio buttons. use crate::Renderer; -pub use iced_style::radio::{Style, StyleSheet}; +pub use iced_graphics::radio::{Style, StyleSheet}; /// A circular button representing a choice. /// diff --git a/wgpu/src/widget/scrollable.rs b/wgpu/src/widget/scrollable.rs index 1d236105..fabb4318 100644 --- a/wgpu/src/widget/scrollable.rs +++ b/wgpu/src/widget/scrollable.rs @@ -1,8 +1,8 @@ //! Navigate an endless amount of content with a scrollbar. use crate::Renderer; +pub use iced_graphics::scrollable::{Scrollbar, Scroller, StyleSheet}; pub use iced_native::scrollable::State; -pub use iced_style::scrollable::{Scrollbar, Scroller, StyleSheet}; /// A widget that can vertically display an infinite amount of content /// with a scrollbar. diff --git a/wgpu/src/widget/slider.rs b/wgpu/src/widget/slider.rs index 4e47978f..cf036829 100644 --- a/wgpu/src/widget/slider.rs +++ b/wgpu/src/widget/slider.rs @@ -6,8 +6,8 @@ //! [`State`]: struct.State.html use crate::Renderer; +pub use iced_graphics::slider::{Handle, HandleShape, Style, StyleSheet}; pub use iced_native::slider::State; -pub use iced_style::slider::{Handle, HandleShape, Style, StyleSheet}; /// An horizontal bar and a handle that selects a single value from a range of /// values. diff --git a/wgpu/src/widget/text.rs b/wgpu/src/widget/text.rs deleted file mode 100644 index 1053ea97..00000000 --- a/wgpu/src/widget/text.rs +++ /dev/null @@ -1,7 +0,0 @@ -//! Write some text for your users to read. -use crate::Renderer; - -/// A paragraph of text. -/// -/// This is an alias of an `iced_native` text with an `iced_wgpu::Renderer`. -pub type Text = iced_native::Text<Renderer>; diff --git a/wgpu/src/widget/text_input.rs b/wgpu/src/widget/text_input.rs index 260fe3a6..1da3fbe6 100644 --- a/wgpu/src/widget/text_input.rs +++ b/wgpu/src/widget/text_input.rs @@ -6,8 +6,8 @@ //! [`State`]: struct.State.html use crate::Renderer; +pub use iced_graphics::text_input::{Style, StyleSheet}; pub use iced_native::text_input::State; -pub use iced_style::text_input::{Style, StyleSheet}; /// A field that can be filled with text. /// |