diff options
| author | 2020-03-24 19:08:21 +0100 | |
|---|---|---|
| committer | 2020-03-24 19:08:21 +0100 | |
| commit | e77fa175aa0eaf62be4ebafbd8e0dbc5df18f006 (patch) | |
| tree | 78608f77c6db3ff1e61a58008bd54d114f32352c /wgpu/src/widget | |
| parent | 7cb1452d29ddfdcd29fd7ecc7c96a79ea2681fce (diff) | |
| parent | fd7d9622e333a0a2cd5c2e8e6cc38cc09d7981e4 (diff) | |
| download | iced-e77fa175aa0eaf62be4ebafbd8e0dbc5df18f006.tar.gz iced-e77fa175aa0eaf62be4ebafbd8e0dbc5df18f006.tar.bz2 iced-e77fa175aa0eaf62be4ebafbd8e0dbc5df18f006.zip | |
Merge branch 'master' into feature/text-selection
Diffstat (limited to '')
| -rw-r--r-- | wgpu/src/widget.rs | 3 | ||||
| -rw-r--r-- | wgpu/src/widget/canvas.rs | 6 | ||||
| -rw-r--r-- | wgpu/src/widget/canvas/frame.rs | 71 | ||||
| -rw-r--r-- | wgpu/src/widget/canvas/layer.rs | 14 | ||||
| -rw-r--r-- | wgpu/src/widget/canvas/layer/cache.rs | 34 | ||||
| -rw-r--r-- | wgpu/src/widget/canvas/text.rs | 34 | ||||
| -rw-r--r-- | wgpu/src/widget/pane_grid.rs | 17 | 
7 files changed, 150 insertions, 29 deletions
| diff --git a/wgpu/src/widget.rs b/wgpu/src/widget.rs index 73cce7e2..b39f2d91 100644 --- a/wgpu/src/widget.rs +++ b/wgpu/src/widget.rs @@ -10,6 +10,7 @@  pub mod button;  pub mod checkbox;  pub mod container; +pub mod pane_grid;  pub mod progress_bar;  pub mod radio;  pub mod scrollable; @@ -23,6 +24,8 @@ pub use checkbox::Checkbox;  #[doc(no_inline)]  pub use container::Container;  #[doc(no_inline)] +pub use pane_grid::PaneGrid; +#[doc(no_inline)]  pub use progress_bar::ProgressBar;  #[doc(no_inline)]  pub use radio::Radio; diff --git a/wgpu/src/widget/canvas.rs b/wgpu/src/widget/canvas.rs index 38c1ce62..3a9605c9 100644 --- a/wgpu/src/widget/canvas.rs +++ b/wgpu/src/widget/canvas.rs @@ -20,6 +20,7 @@ mod drawable;  mod fill;  mod frame;  mod stroke; +mod text;  pub use drawable::Drawable;  pub use fill::Fill; @@ -27,6 +28,7 @@ pub use frame::Frame;  pub use layer::Layer;  pub use path::Path;  pub use stroke::{LineCap, LineJoin, Stroke}; +pub use text::Text;  /// A widget capable of drawing 2D graphics.  /// @@ -121,9 +123,9 @@ impl<'a, Message> Widget<Message, Renderer> for Canvas<'a> {                  primitives: self                      .layers                      .iter() -                    .map(|layer| Primitive::Mesh2D { +                    .map(|layer| Primitive::Cached {                          origin, -                        buffers: layer.draw(size), +                        cache: layer.draw(size),                      })                      .collect(),              }, diff --git a/wgpu/src/widget/canvas/frame.rs b/wgpu/src/widget/canvas/frame.rs index fa6d8c0a..7d7ce06a 100644 --- a/wgpu/src/widget/canvas/frame.rs +++ b/wgpu/src/widget/canvas/frame.rs @@ -1,8 +1,8 @@ -use iced_native::{Point, Size, Vector}; +use iced_native::{Point, Rectangle, Size, Vector};  use crate::{ -    canvas::{Fill, Path, Stroke}, -    triangle, +    canvas::{Fill, Path, Stroke, Text}, +    triangle, Primitive,  };  /// The frame of a [`Canvas`]. @@ -13,6 +13,7 @@ pub struct Frame {      width: f32,      height: f32,      buffers: lyon::tessellation::VertexBuffers<triangle::Vertex2D, u32>, +    primitives: Vec<Primitive>,      transforms: Transforms,  } @@ -40,6 +41,7 @@ impl Frame {              width,              height,              buffers: lyon::tessellation::VertexBuffers::new(), +            primitives: Vec::new(),              transforms: Transforms {                  previous: Vec::new(),                  current: Transform { @@ -154,6 +156,52 @@ impl Frame {          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 +    pub fn fill_text(&mut self, text: Text) { +        use std::f32; + +        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.      /// @@ -209,13 +257,20 @@ impl Frame {          self.transforms.current.is_identity = false;      } -    /// Produces the geometry that has been drawn on the [`Frame`]. +    /// Produces the primitive representing everything drawn on the [`Frame`].      ///      /// [`Frame`]: struct.Frame.html -    pub fn into_mesh(self) -> triangle::Mesh2D { -        triangle::Mesh2D { -            vertices: self.buffers.vertices, -            indices: self.buffers.indices, +    pub fn into_primitive(mut self) -> Primitive { +        self.primitives.push(Primitive::Mesh2D { +            origin: Point::ORIGIN, +            buffers: triangle::Mesh2D { +                vertices: self.buffers.vertices, +                indices: self.buffers.indices, +            }, +        }); + +        Primitive::Group { +            primitives: self.primitives,          }      }  } diff --git a/wgpu/src/widget/canvas/layer.rs b/wgpu/src/widget/canvas/layer.rs index 82d647bb..a46b7fb1 100644 --- a/wgpu/src/widget/canvas/layer.rs +++ b/wgpu/src/widget/canvas/layer.rs @@ -3,23 +3,23 @@ mod cache;  pub use cache::Cache; -use crate::triangle; - +use crate::Primitive;  use iced_native::Size; +  use std::sync::Arc;  /// A layer that can be presented at a [`Canvas`].  ///  /// [`Canvas`]: ../struct.Canvas.html  pub trait Layer: std::fmt::Debug { -    /// Draws the [`Layer`] in the given bounds and produces [`Mesh2D`] as a -    /// result. +    /// Draws the [`Layer`] in the given bounds and produces a [`Primitive`] as +    /// a result.      /// -    /// The [`Layer`] may choose to store the produced [`Mesh2D`] locally and +    /// The [`Layer`] may choose to store the produced [`Primitive`] locally and      /// only recompute it when the bounds change, its contents change, or is      /// otherwise explicitly cleared by other means.      ///      /// [`Layer`]: trait.Layer.html -    /// [`Mesh2D`]: ../../../triangle/struct.Mesh2D.html -    fn draw(&self, bounds: Size) -> Arc<triangle::Mesh2D>; +    /// [`Primitive`]: ../../../enum.Primitive.html +    fn draw(&self, bounds: Size) -> Arc<Primitive>;  } diff --git a/wgpu/src/widget/canvas/layer/cache.rs b/wgpu/src/widget/canvas/layer/cache.rs index 3071cce0..f7002459 100644 --- a/wgpu/src/widget/canvas/layer/cache.rs +++ b/wgpu/src/widget/canvas/layer/cache.rs @@ -1,12 +1,10 @@  use crate::{      canvas::{Drawable, Frame, Layer}, -    triangle, +    Primitive,  };  use iced_native::Size; -use std::cell::RefCell; -use std::marker::PhantomData; -use std::sync::Arc; +use std::{cell::RefCell, marker::PhantomData, sync::Arc};  /// A simple cache that stores generated geometry to avoid recomputation.  /// @@ -21,12 +19,11 @@ pub struct Cache<T: Drawable> {      state: RefCell<State>,  } -#[derive(Debug)]  enum State {      Empty,      Filled { -        mesh: Arc<triangle::Mesh2D>,          bounds: Size, +        primitive: Arc<Primitive>,      },  } @@ -75,27 +72,40 @@ impl<'a, T> Layer for Bind<'a, T>  where      T: Drawable + std::fmt::Debug,  { -    fn draw(&self, current_bounds: Size) -> Arc<triangle::Mesh2D> { +    fn draw(&self, current_bounds: Size) -> Arc<Primitive> {          use std::ops::Deref; -        if let State::Filled { mesh, bounds } = +        if let State::Filled { bounds, primitive } =              self.cache.state.borrow().deref()          {              if *bounds == current_bounds { -                return mesh.clone(); +                return primitive.clone();              }          }          let mut frame = Frame::new(current_bounds.width, current_bounds.height);          self.input.draw(&mut frame); -        let mesh = Arc::new(frame.into_mesh()); +        let primitive = Arc::new(frame.into_primitive());          *self.cache.state.borrow_mut() = State::Filled { -            mesh: mesh.clone(),              bounds: current_bounds, +            primitive: primitive.clone(),          }; -        mesh +        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/text.rs b/wgpu/src/widget/canvas/text.rs new file mode 100644 index 00000000..d1cf1a0f --- /dev/null +++ b/wgpu/src/widget/canvas/text.rs @@ -0,0 +1,34 @@ +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, +        } +    } +} diff --git a/wgpu/src/widget/pane_grid.rs b/wgpu/src/widget/pane_grid.rs new file mode 100644 index 00000000..7bc2f7c5 --- /dev/null +++ b/wgpu/src/widget/pane_grid.rs @@ -0,0 +1,17 @@ +//! Let your users split regions of your application and organize layout dynamically. +//! +//! [](https://gfycat.com/mixedflatjellyfish) +use crate::Renderer; + +pub use iced_native::pane_grid::{ +    Axis, Direction, DragEvent, Focus, KeyPressEvent, Pane, ResizeEvent, Split, +    State, +}; + +/// A collection of panes distributed using either vertical or horizontal splits +/// to completely fill the space available. +/// +/// [](https://gfycat.com/mixedflatjellyfish) +/// +/// This is an alias of an `iced_native` pane grid with an `iced_wgpu::Renderer`. +pub type PaneGrid<'a, Message> = iced_native::PaneGrid<'a, Message, Renderer>; | 
