diff options
35 files changed, 288 insertions, 160 deletions
@@ -19,6 +19,8 @@ members = [      "core",      "native",      "web", +    "wgpu", +    "winit",  ]  [target.'cfg(not(target_arch = "wasm32"))'.dependencies] diff --git a/core/src/background.rs b/core/src/background.rs new file mode 100644 index 00000000..59b67a2c --- /dev/null +++ b/core/src/background.rs @@ -0,0 +1,7 @@ +use crate::Color; + +#[derive(Debug, Clone, Copy, PartialEq)] +pub enum Background { +    Color(Color), +    // TODO: Add gradient and image variants +} diff --git a/core/src/color.rs b/core/src/color.rs index 2b64c78d..79910dd8 100644 --- a/core/src/color.rs +++ b/core/src/color.rs @@ -17,6 +17,14 @@ impl Color {          a: 1.0,      }; +    /// The white color. +    pub const WHITE: Color = Color { +        r: 1.0, +        g: 1.0, +        b: 1.0, +        a: 1.0, +    }; +      pub fn into_linear(self) -> [f32; 4] {          // As described in:          // https://en.wikipedia.org/wiki/SRGB#The_reverse_transformation diff --git a/core/src/lib.rs b/core/src/lib.rs index 1f43b2b7..877a8f85 100644 --- a/core/src/lib.rs +++ b/core/src/lib.rs @@ -1,6 +1,7 @@  pub mod widget;  mod align; +mod background;  mod color;  mod justify;  mod length; @@ -9,6 +10,7 @@ mod rectangle;  mod vector;  pub use align::Align; +pub use background::Background;  pub use color::Color;  pub use justify::Justify;  pub use length::Length; diff --git a/core/src/widget/button.rs b/core/src/widget/button.rs index b98bb443..a57f2dd8 100644 --- a/core/src/widget/button.rs +++ b/core/src/widget/button.rs @@ -5,68 +5,58 @@  //! [`Button`]: struct.Button.html  //! [`State`]: struct.State.html -use crate::{Align, Length}; +use crate::{Align, Background, Length};  /// A generic widget that produces a message when clicked. -/// -/// # Example -/// -/// ``` -/// use iced_core::{button, Button}; -/// -/// pub enum Message { -///     ButtonClicked, -/// } -/// -/// let state = &mut button::State::new(); -/// -/// Button::new(state, "Click me!") -///     .on_press(Message::ButtonClicked); -/// ``` -/// -///  -pub struct Button<'a, Message> { +pub struct Button<'a, Message, Element> {      /// The current state of the button      pub state: &'a mut State, -    /// The label of the button -    pub label: String, +    pub content: Element,      /// The message to produce when the button is pressed      pub on_press: Option<Message>, -    pub class: Class, -      pub width: Length, +    pub padding: u16, + +    pub background: Option<Background>, + +    pub border_radius: u16, +      pub align_self: Option<Align>,  } -impl<'a, Message> std::fmt::Debug for Button<'a, Message> +impl<'a, Message, Element> std::fmt::Debug for Button<'a, Message, Element>  where      Message: std::fmt::Debug,  {      fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {          f.debug_struct("Button")              .field("state", &self.state) -            .field("label", &self.label)              .field("on_press", &self.on_press)              .finish()      }  } -impl<'a, Message> Button<'a, Message> { +impl<'a, Message, Element> Button<'a, Message, Element> {      /// Creates a new [`Button`] with some local [`State`] and the given label.      ///      /// [`Button`]: struct.Button.html      /// [`State`]: struct.State.html -    pub fn new(state: &'a mut State, label: &str) -> Self { +    pub fn new<E>(state: &'a mut State, content: E) -> Self +    where +        E: Into<Element>, +    {          Button {              state, -            label: String::from(label), +            content: content.into(),              on_press: None, -            class: Class::Primary,              width: Length::Shrink, +            padding: 0, +            background: None, +            border_radius: 0,              align_self: None,          }      } @@ -79,6 +69,21 @@ impl<'a, Message> Button<'a, Message> {          self      } +    pub fn padding(mut self, padding: u16) -> Self { +        self.padding = padding; +        self +    } + +    pub fn background(mut self, background: Background) -> Self { +        self.background = Some(background); +        self +    } + +    pub fn border_radius(mut self, border_radius: u16) -> Self { +        self.border_radius = border_radius; +        self +    } +      /// Sets the alignment of the [`Button`] itself.      ///      /// This is useful if you want to override the default alignment given by @@ -90,16 +95,6 @@ impl<'a, Message> Button<'a, Message> {          self      } -    /// Sets the [`Class`] of the [`Button`]. -    /// -    /// -    /// [`Button`]: struct.Button.html -    /// [`Class`]: enum.Class.html -    pub fn class(mut self, class: Class) -> Self { -        self.class = class; -        self -    } -      /// Sets the message that will be produced when the [`Button`] is pressed.      ///      /// [`Button`]: struct.Button.html @@ -133,26 +128,3 @@ impl State {          self.is_pressed      }  } - -/// The type of a [`Button`]. -/// -///  -/// -/// [`Button`]: struct.Button.html -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub enum Class { -    /// The [`Button`] performs the main action. -    /// -    /// [`Button`]: struct.Button.html -    Primary, - -    /// The [`Button`] performs an alternative action. -    /// -    /// [`Button`]: struct.Button.html -    Secondary, - -    /// The [`Button`] performs a productive action. -    /// -    /// [`Button`]: struct.Button.html -    Positive, -} diff --git a/core/src/widget/text.rs b/core/src/widget/text.rs index 427d9471..cd94dbb2 100644 --- a/core/src/widget/text.rs +++ b/core/src/widget/text.rs @@ -1,5 +1,5 @@  //! Write some text for your users to read. -use crate::{Color, Length}; +use crate::{Align, Color, Length};  /// A paragraph of text.  /// diff --git a/examples/tour.rs b/examples/tour.rs index 5f24eb87..96590c0e 100644 --- a/examples/tour.rs +++ b/examples/tour.rs @@ -1,7 +1,7 @@  use iced::{ -    button, slider, text::HorizontalAlignment, Align, Button, Checkbox, Color, -    Column, Element, Image, Justify, Length, Radio, Row, Slider, Text, -    UserInterface, +    button, slider, text::HorizontalAlignment, Align, Background, Button, +    Checkbox, Color, Column, Element, Image, Justify, Length, Radio, Row, +    Slider, Text, UserInterface,  };  pub fn main() { @@ -59,9 +59,8 @@ impl UserInterface for Tour {          if steps.has_previous() {              controls = controls.push( -                Button::new(back_button, "Back") -                    .on_press(Message::BackPressed) -                    .class(button::Class::Secondary), +                secondary_button(back_button, "Back") +                    .on_press(Message::BackPressed),              );          } @@ -69,7 +68,8 @@ impl UserInterface for Tour {          if steps.can_continue() {              controls = controls.push( -                Button::new(next_button, "Next").on_press(Message::NextPressed), +                primary_button(next_button, "Next") +                    .on_press(Message::NextPressed),              );          } @@ -546,6 +546,44 @@ impl<'a> Step {      }  } +fn button<'a, Message>( +    state: &'a mut button::State, +    label: &str, +) -> Button<'a, Message> { +    Button::new( +        state, +        Text::new(label) +            .color(Color::WHITE) +            .horizontal_alignment(HorizontalAlignment::Center), +    ) +    .padding(10) +    .border_radius(10) +} + +fn primary_button<'a, Message>( +    state: &'a mut button::State, +    label: &str, +) -> Button<'a, Message> { +    button(state, label).background(Background::Color(Color { +        r: 0.3, +        g: 0.3, +        b: 0.8, +        a: 1.0, +    })) +} + +fn secondary_button<'a, Message>( +    state: &'a mut button::State, +    label: &str, +) -> Button<'a, Message> { +    button(state, label).background(Background::Color(Color { +        r: 0.8, +        g: 0.8, +        b: 0.8, +        a: 1.0, +    })) +} +  #[derive(Debug, Clone, Copy, PartialEq, Eq)]  pub enum Language {      Rust, diff --git a/native/src/element.rs b/native/src/element.rs index 417e3463..cf96b7ea 100644 --- a/native/src/element.rs +++ b/native/src/element.rs @@ -41,6 +41,10 @@ where          }      } +    pub fn node(&self, renderer: &Renderer) -> Node { +        self.widget.node(renderer) +    } +      pub fn draw(          &self,          renderer: &mut Renderer, @@ -97,22 +101,22 @@ where      ///      /// ```      /// # mod counter { -    /// #     use iced_native::{button, Button}; +    /// #     use iced_native::{text, Text};      /// #      /// #     #[derive(Debug, Clone, Copy)]      /// #     pub enum Message {} -    /// #     pub struct Counter(button::State); +    /// #     pub struct Counter;      /// #      /// #     impl Counter { -    /// #         pub fn view(&mut self) -> Button<Message> { -    /// #             Button::new(&mut self.0, "_") +    /// #         pub fn view(&mut self) -> Text { +    /// #             Text::new("")      /// #         }      /// #     }      /// # }      /// #      /// # mod iced_wgpu {      /// #     use iced_native::{ -    /// #         button, row, Button, Node, Point, Rectangle, Style, Layout, Row +    /// #         text, row, Text, Node, Point, Rectangle, Style, Layout, Row      /// #     };      /// #     pub struct Renderer;      /// # @@ -127,16 +131,15 @@ where      /// #         ) {}      /// #     }      /// # -    /// #     impl button::Renderer for Renderer { -    /// #         fn node<Message>(&self, _button: &Button<'_, Message>) -> Node { +    /// #     impl text::Renderer for Renderer { +    /// #         fn node(&self, _text: &Text) -> Node {      /// #             Node::new(Style::default())      /// #         }      /// # -    /// #         fn draw<Message>( +    /// #         fn draw(      /// #             &mut self, -    /// #             _button: &Button<'_, Message>, +    /// #             _text: &Text,      /// #             _layout: Layout<'_>, -    /// #             _cursor_position: Point,      /// #         ) {}      /// #     }      /// # } @@ -289,7 +292,7 @@ where      A: Copy,      Renderer: crate::Renderer,  { -    fn node(&self, renderer: &mut Renderer) -> Node { +    fn node(&self, renderer: &Renderer) -> Node {          self.widget.node(renderer)      } @@ -359,7 +362,7 @@ impl<'a, Message, Renderer> Widget<Message, Renderer>  where      Renderer: crate::Renderer + renderer::Debugger,  { -    fn node(&self, renderer: &mut Renderer) -> Node { +    fn node(&self, renderer: &Renderer) -> Node {          self.element.widget.node(renderer)      } diff --git a/native/src/lib.rs b/native/src/lib.rs index 6067f49d..18ce3a37 100644 --- a/native/src/lib.rs +++ b/native/src/lib.rs @@ -89,14 +89,14 @@  //! #     impl button::Renderer for Renderer {  //! #         fn node<Message>(  //! #             &self, -//! #             _button: &Button<'_, Message> +//! #             _button: &Button<'_, Message, Self>  //! #         ) -> Node {  //! #             Node::new(Style::default())  //! #         }  //! #  //! #         fn draw<Message>(  //! #             &mut self, -//! #             _button: &Button<'_, Message>, +//! #             _button: &Button<'_, Message, Self>,  //! #             _layout: Layout<'_>,  //! #             _cursor_position: Point,  //! #         ) {} @@ -125,7 +125,7 @@  //!             .push(  //!                 // The increment button. We tell it to produce an  //!                 // `IncrementPressed` message when pressed -//!                 Button::new(&mut self.increment_button, "+") +//!                 Button::new(&mut self.increment_button, Text::new("+"))  //!                     .on_press(Message::IncrementPressed),  //!             )  //!             .push( @@ -135,7 +135,7 @@  //!             .push(  //!                 // The decrement button. We tell it to produce a  //!                 // `DecrementPressed` message when pressed -//!                 Button::new(&mut self.decrement_button, "-") +//!                 Button::new(&mut self.decrement_button, Text::new("-"))  //!                     .on_press(Message::DecrementPressed),  //!             )  //!     } @@ -212,7 +212,9 @@ mod user_interface;  pub(crate) use iced_core::Vector; -pub use iced_core::{Align, Color, Justify, Length, Point, Rectangle}; +pub use iced_core::{ +    Align, Background, Color, Justify, Length, Point, Rectangle, +};  #[doc(no_inline)]  pub use stretch::{geometry::Size, number::Number}; diff --git a/native/src/style.rs b/native/src/style.rs index b1c49fd4..70a7ff74 100644 --- a/native/src/style.rs +++ b/native/src/style.rs @@ -74,12 +74,12 @@ impl Style {          self      } -    pub(crate) fn align_items(mut self, align: Align) -> Self { +    pub fn align_items(mut self, align: Align) -> Self {          self.0.align_items = into_align_items(align);          self      } -    pub(crate) fn justify_content(mut self, justify: Justify) -> Self { +    pub fn justify_content(mut self, justify: Justify) -> Self {          self.0.justify_content = into_justify_content(justify);          self      } diff --git a/native/src/widget.rs b/native/src/widget.rs index eff098a6..b7181c1b 100644 --- a/native/src/widget.rs +++ b/native/src/widget.rs @@ -67,7 +67,7 @@ where      /// [`Node`]: ../struct.Node.html      /// [`Widget`]: trait.Widget.html      /// [`Layout`]: ../struct.Layout.html -    fn node(&self, renderer: &mut Renderer) -> Node; +    fn node(&self, renderer: &Renderer) -> Node;      /// Draws the [`Widget`] using the associated `Renderer`.      /// diff --git a/native/src/widget/button.rs b/native/src/widget/button.rs index 5ae4e045..1f881660 100644 --- a/native/src/widget/button.rs +++ b/native/src/widget/button.rs @@ -10,14 +10,18 @@ use crate::input::{mouse, ButtonState};  use crate::{Element, Event, Hasher, Layout, Node, Point, Widget};  use std::hash::Hash; -pub use iced_core::button::*; +pub use iced_core::button::State; -impl<'a, Message, Renderer> Widget<Message, Renderer> for Button<'a, Message> +pub type Button<'a, Message, Renderer> = +    iced_core::Button<'a, Message, Element<'a, Message, Renderer>>; + +impl<'a, Message, Renderer> Widget<Message, Renderer> +    for Button<'a, Message, Renderer>  where      Renderer: self::Renderer,      Message: Copy + std::fmt::Debug,  { -    fn node(&self, renderer: &mut Renderer) -> Node { +    fn node(&self, renderer: &Renderer) -> Node {          renderer.node(&self)      } @@ -68,9 +72,9 @@ where      }      fn hash_layout(&self, state: &mut Hasher) { -        self.label.hash(state);          self.width.hash(state);          self.align_self.hash(state); +        self.content.hash_layout(state);      }  } @@ -81,31 +85,33 @@ where  ///  /// [`Button`]: struct.Button.html  /// [renderer]: ../../renderer/index.html -pub trait Renderer: crate::Renderer { +pub trait Renderer: crate::Renderer + Sized {      /// Creates a [`Node`] for the provided [`Button`].      ///      /// [`Node`]: ../../struct.Node.html      /// [`Button`]: struct.Button.html -    fn node<Message>(&self, button: &Button<'_, Message>) -> Node; +    fn node<Message>(&self, button: &Button<'_, Message, Self>) -> Node;      /// Draws a [`Button`].      ///      /// [`Button`]: struct.Button.html      fn draw<Message>(          &mut self, -        button: &Button<'_, Message>, +        button: &Button<'_, Message, Self>,          layout: Layout<'_>,          cursor_position: Point,      ) -> Self::Primitive;  } -impl<'a, Message, Renderer> From<Button<'a, Message>> +impl<'a, Message, Renderer> From<Button<'a, Message, Renderer>>      for Element<'a, Message, Renderer>  where -    Renderer: self::Renderer, +    Renderer: 'static + self::Renderer,      Message: 'static + Copy + std::fmt::Debug,  { -    fn from(button: Button<'a, Message>) -> Element<'a, Message, Renderer> { +    fn from( +        button: Button<'a, Message, Renderer>, +    ) -> Element<'a, Message, Renderer> {          Element::new(button)      }  } diff --git a/native/src/widget/checkbox.rs b/native/src/widget/checkbox.rs index 1954305a..c069bfdc 100644 --- a/native/src/widget/checkbox.rs +++ b/native/src/widget/checkbox.rs @@ -10,7 +10,7 @@ impl<Message, Renderer> Widget<Message, Renderer> for Checkbox<Message>  where      Renderer: self::Renderer,  { -    fn node(&self, renderer: &mut Renderer) -> Node { +    fn node(&self, renderer: &Renderer) -> Node {          renderer.node(&self)      } @@ -64,7 +64,7 @@ pub trait Renderer: crate::Renderer {      ///      /// [`Node`]: ../../struct.Node.html      /// [`Checkbox`]: struct.Checkbox.html -    fn node<Message>(&mut self, checkbox: &Checkbox<Message>) -> Node; +    fn node<Message>(&self, checkbox: &Checkbox<Message>) -> Node;      /// Draws a [`Checkbox`].      /// diff --git a/native/src/widget/column.rs b/native/src/widget/column.rs index 6228d711..7e10e662 100644 --- a/native/src/widget/column.rs +++ b/native/src/widget/column.rs @@ -11,7 +11,7 @@ impl<'a, Message, Renderer> Widget<Message, Renderer>  where      Renderer: self::Renderer,  { -    fn node(&self, renderer: &mut Renderer) -> Node { +    fn node(&self, renderer: &Renderer) -> Node {          let mut children: Vec<Node> = self              .children              .iter() diff --git a/native/src/widget/image.rs b/native/src/widget/image.rs index 2bce36c2..5197d5b1 100644 --- a/native/src/widget/image.rs +++ b/native/src/widget/image.rs @@ -11,7 +11,7 @@ where      Renderer: self::Renderer<I>,      I: Clone,  { -    fn node(&self, renderer: &mut Renderer) -> Node { +    fn node(&self, renderer: &Renderer) -> Node {          renderer.node(&self)      } @@ -45,7 +45,7 @@ pub trait Renderer<I>: crate::Renderer {      ///      /// [`Node`]: ../../struct.Node.html      /// [`Image`]: struct.Image.html -    fn node(&mut self, image: &Image<I>) -> Node; +    fn node(&self, image: &Image<I>) -> Node;      /// Draws an [`Image`].      /// diff --git a/native/src/widget/radio.rs b/native/src/widget/radio.rs index 1bc052aa..22308f81 100644 --- a/native/src/widget/radio.rs +++ b/native/src/widget/radio.rs @@ -11,7 +11,7 @@ where      Renderer: self::Renderer,      Message: Copy + std::fmt::Debug,  { -    fn node(&self, renderer: &mut Renderer) -> Node { +    fn node(&self, renderer: &Renderer) -> Node {          renderer.node(&self)      } @@ -61,7 +61,7 @@ pub trait Renderer: crate::Renderer {      ///      /// [`Node`]: ../../struct.Node.html      /// [`Radio`]: struct.Radio.html -    fn node<Message>(&mut self, radio: &Radio<Message>) -> Node; +    fn node<Message>(&self, radio: &Radio<Message>) -> Node;      /// Draws a [`Radio`] button.      /// diff --git a/native/src/widget/row.rs b/native/src/widget/row.rs index 9d023210..b1d4a5b2 100644 --- a/native/src/widget/row.rs +++ b/native/src/widget/row.rs @@ -11,7 +11,7 @@ impl<'a, Message, Renderer> Widget<Message, Renderer>  where      Renderer: self::Renderer,  { -    fn node(&self, renderer: &mut Renderer) -> Node { +    fn node(&self, renderer: &Renderer) -> Node {          let mut children: Vec<Node> = self              .children              .iter() diff --git a/native/src/widget/slider.rs b/native/src/widget/slider.rs index 77095cb7..643efdf4 100644 --- a/native/src/widget/slider.rs +++ b/native/src/widget/slider.rs @@ -15,7 +15,7 @@ impl<'a, Message, Renderer> Widget<Message, Renderer> for Slider<'a, Message>  where      Renderer: self::Renderer,  { -    fn node(&self, renderer: &mut Renderer) -> Node { +    fn node(&self, renderer: &Renderer) -> Node {          renderer.node(&self)      } diff --git a/native/src/widget/text.rs b/native/src/widget/text.rs index a032b4fc..62f2d7b7 100644 --- a/native/src/widget/text.rs +++ b/native/src/widget/text.rs @@ -9,7 +9,7 @@ impl<Message, Renderer> Widget<Message, Renderer> for Text  where      Renderer: self::Renderer,  { -    fn node(&self, renderer: &mut Renderer) -> Node { +    fn node(&self, renderer: &Renderer) -> Node {          renderer.node(&self)      } @@ -1,12 +1,13 @@  pub use iced_wgpu::{Primitive, Renderer};  pub use iced_winit::{ -    button, slider, text, winit, Align, Button, Checkbox, Color, Image, +    button, slider, text, winit, Align, Background, Checkbox, Color, Image,      Justify, Length, Radio, Slider, Text,  };  pub type Element<'a, Message> = iced_winit::Element<'a, Message, Renderer>;  pub type Row<'a, Message> = iced_winit::Row<'a, Message, Renderer>;  pub type Column<'a, Message> = iced_winit::Column<'a, Message, Renderer>; +pub type Button<'a, Message> = iced_winit::Button<'a, Message, Renderer>;  pub trait UserInterface {      type Message; diff --git a/web/src/element.rs b/web/src/element.rs index 8270d8db..a2b78c69 100644 --- a/web/src/element.rs +++ b/web/src/element.rs @@ -14,6 +14,14 @@ impl<'a, Message> Element<'a, Message> {          }      } +    pub fn node<'b>( +        &self, +        bump: &'b bumpalo::Bump, +        bus: &Bus<Message>, +    ) -> dodrio::Node<'b> { +        self.widget.node(bump, bus) +    } +      pub fn explain(self, _color: Color) -> Element<'a, Message> {          self      } diff --git a/web/src/widget/button.rs b/web/src/widget/button.rs index 23a4165a..257034a7 100644 --- a/web/src/widget/button.rs +++ b/web/src/widget/button.rs @@ -2,7 +2,10 @@ use crate::{Bus, Element, Widget};  use dodrio::bumpalo; -pub use iced_core::button::*; +pub use iced_core::button::State; + +pub type Button<'a, Message> = +    iced_core::Button<'a, Message, Element<'a, Message>>;  impl<'a, Message> Widget<Message> for Button<'a, Message>  where @@ -15,9 +18,8 @@ where      ) -> dodrio::Node<'b> {          use dodrio::builder::*; -        let label = bumpalo::format!(in bump, "{}", self.label); - -        let mut node = button(bump).children(vec![text(label.into_bump_str())]); +        let mut node = +            button(bump).children(vec![self.content.node(bump, bus)]);          if let Some(on_press) = self.on_press {              let event_bus = bus.clone(); diff --git a/wgpu/src/lib.rs b/wgpu/src/lib.rs index 33d8f5ed..8f8d50e9 100644 --- a/wgpu/src/lib.rs +++ b/wgpu/src/lib.rs @@ -8,5 +8,5 @@ pub(crate) use quad::Quad;  pub(crate) use transformation::Transformation;  pub use mouse_cursor::MouseCursor; -pub use primitive::{Background, Primitive}; +pub use primitive::Primitive;  pub use renderer::{Renderer, Target}; diff --git a/wgpu/src/primitive.rs b/wgpu/src/primitive.rs index f6730a1f..b664689b 100644 --- a/wgpu/src/primitive.rs +++ b/wgpu/src/primitive.rs @@ -1,4 +1,4 @@ -use iced_native::{Color, Rectangle}; +use iced_native::{text, Background, Color, Rectangle};  #[derive(Debug, Clone)]  pub enum Primitive { @@ -9,16 +9,14 @@ pub enum Primitive {      Text {          content: String,          bounds: Rectangle, +        color: Color,          size: f32, +        horizontal_alignment: text::HorizontalAlignment, +        vertical_alignment: text::VerticalAlignment,      },      Quad {          bounds: Rectangle,          background: Background, +        border_radius: u16,      },  } - -#[derive(Debug, Clone, Copy, PartialEq)] -pub enum Background { -    Color(Color), -    // TODO: Add gradient and image variants -} diff --git a/wgpu/src/quad.rs b/wgpu/src/quad.rs index d0126bbd..adb294f0 100644 --- a/wgpu/src/quad.rs +++ b/wgpu/src/quad.rs @@ -123,6 +123,11 @@ impl Pipeline {                                  format: wgpu::VertexFormat::Float4,                                  offset: 4 * (2 + 2),                              }, +                            wgpu::VertexAttributeDescriptor { +                                shader_location: 4, +                                format: wgpu::VertexFormat::Uint, +                                offset: 4 * (2 + 2 + 4), +                            },                          ],                      },                  ], @@ -262,6 +267,7 @@ pub struct Quad {      pub position: [f32; 2],      pub scale: [f32; 2],      pub color: [f32; 4], +    pub border_radius: u32,  }  impl Quad { diff --git a/wgpu/src/renderer.rs b/wgpu/src/renderer.rs index 9883943b..ae5692e3 100644 --- a/wgpu/src/renderer.rs +++ b/wgpu/src/renderer.rs @@ -1,5 +1,7 @@ -use crate::{quad, Background, Primitive, Quad, Transformation}; -use iced_native::{renderer::Debugger, Color, Layout, Point, Widget}; +use crate::{quad, Primitive, Quad, Transformation}; +use iced_native::{ +    renderer::Debugger, Background, Color, Layout, Point, Widget, +};  use raw_window_handle::HasRawWindowHandle;  use wgpu::{ @@ -159,20 +161,74 @@ impl Renderer {                  content,                  bounds,                  size, -            } => self.glyph_brush.borrow_mut().queue(Section { -                text: &content, -                screen_position: (bounds.x, bounds.y), -                bounds: (bounds.width, bounds.height), -                scale: wgpu_glyph::Scale { x: *size, y: *size }, -                ..Default::default() -            }), -            Primitive::Quad { bounds, background } => { +                color, +                horizontal_alignment, +                vertical_alignment, +            } => { +                let x = match horizontal_alignment { +                    iced_native::text::HorizontalAlignment::Left => bounds.x, +                    iced_native::text::HorizontalAlignment::Center => { +                        bounds.x + bounds.width / 2.0 +                    } +                    iced_native::text::HorizontalAlignment::Right => { +                        bounds.x + bounds.width +                    } +                }; + +                let y = match vertical_alignment { +                    iced_native::text::VerticalAlignment::Top => bounds.y, +                    iced_native::text::VerticalAlignment::Center => { +                        bounds.y + bounds.height / 2.0 +                    } +                    iced_native::text::VerticalAlignment::Bottom => { +                        bounds.y + bounds.height +                    } +                }; + +                self.glyph_brush.borrow_mut().queue(Section { +                    text: &content, +                    screen_position: (x, y), +                    bounds: (bounds.width, bounds.height), +                    scale: wgpu_glyph::Scale { x: *size, y: *size }, +                    color: color.into_linear(), +                    layout: wgpu_glyph::Layout::default() +                        .h_align(match horizontal_alignment { +                            iced_native::text::HorizontalAlignment::Left => { +                                wgpu_glyph::HorizontalAlign::Left +                            } +                            iced_native::text::HorizontalAlignment::Center => { +                                wgpu_glyph::HorizontalAlign::Center +                            } +                            iced_native::text::HorizontalAlignment::Right => { +                                wgpu_glyph::HorizontalAlign::Right +                            } +                        }) +                        .v_align(match vertical_alignment { +                            iced_native::text::VerticalAlignment::Top => { +                                wgpu_glyph::VerticalAlign::Top +                            } +                            iced_native::text::VerticalAlignment::Center => { +                                wgpu_glyph::VerticalAlign::Center +                            } +                            iced_native::text::VerticalAlignment::Bottom => { +                                wgpu_glyph::VerticalAlign::Bottom +                            } +                        }), +                    ..Default::default() +                }) +            } +            Primitive::Quad { +                bounds, +                background, +                border_radius, +            } => {                  self.quads.push(Quad {                      position: [bounds.x, bounds.y],                      scale: [bounds.width, bounds.height],                      color: match background {                          Background::Color(color) => color.into_linear(),                      }, +                    border_radius: u32::from(*border_radius),                  });              }          } diff --git a/wgpu/src/renderer/button.rs b/wgpu/src/renderer/button.rs index f75b44f7..00fcd0eb 100644 --- a/wgpu/src/renderer/button.rs +++ b/wgpu/src/renderer/button.rs @@ -1,22 +1,26 @@ -use crate::{Background, Primitive, Renderer}; -use iced_native::{button, Button, Color, Layout, Length, Node, Point, Style}; +use crate::{Primitive, Renderer}; +use iced_native::{ +    button, Align, Background, Button, Color, Layout, Length, Node, Point, +    Style, +};  impl button::Renderer for Renderer { -    fn node<Message>(&self, button: &Button<Message>) -> Node { +    fn node<Message>(&self, button: &Button<Message, Self>) -> Node {          let style = Style::default()              .width(button.width) -            .min_height(Length::Units(30)) +            .padding(button.padding)              .min_width(Length::Units(100)) -            .align_self(button.align_self); +            .align_self(button.align_self) +            .align_items(Align::Stretch); -        Node::new(style) +        Node::with_children(style, vec![button.content.node(self)])      }      fn draw<Message>(          &mut self, -        button: &Button<Message>, +        button: &Button<Message, Self>,          layout: Layout<'_>, -        _cursor_position: Point, +        cursor_position: Point,      ) -> Self::Primitive {          let bounds = layout.bounds(); @@ -24,18 +28,21 @@ impl button::Renderer for Renderer {              primitives: vec![                  Primitive::Quad {                      bounds, -                    background: Background::Color(Color { -                        r: 0.8, -                        b: 0.8, -                        g: 0.8, -                        a: 1.0, -                    }), -                }, -                Primitive::Text { -                    content: button.label.clone(), -                    size: 20.0, -                    bounds: layout.bounds(), +                    background: button.background.unwrap_or(Background::Color( +                        Color { +                            r: 0.8, +                            b: 0.8, +                            g: 0.8, +                            a: 1.0, +                        }, +                    )), +                    border_radius: button.border_radius,                  }, +                button.content.draw( +                    self, +                    layout.children().next().unwrap(), +                    cursor_position, +                ),              ],          }      } diff --git a/wgpu/src/renderer/checkbox.rs b/wgpu/src/renderer/checkbox.rs index c94a2157..16d5734f 100644 --- a/wgpu/src/renderer/checkbox.rs +++ b/wgpu/src/renderer/checkbox.rs @@ -2,7 +2,7 @@ use crate::{Primitive, Renderer};  use iced_native::{checkbox, Checkbox, Layout, Node, Point, Style};  impl checkbox::Renderer for Renderer { -    fn node<Message>(&mut self, _checkbox: &Checkbox<Message>) -> Node { +    fn node<Message>(&self, _checkbox: &Checkbox<Message>) -> Node {          Node::new(Style::default())      } diff --git a/wgpu/src/renderer/image.rs b/wgpu/src/renderer/image.rs index 6ff39d30..bacc430d 100644 --- a/wgpu/src/renderer/image.rs +++ b/wgpu/src/renderer/image.rs @@ -2,7 +2,7 @@ use crate::{Primitive, Renderer};  use iced_native::{image, Image, Layout, Node, Style};  impl image::Renderer<&str> for Renderer { -    fn node(&mut self, _image: &Image<&str>) -> Node { +    fn node(&self, _image: &Image<&str>) -> Node {          Node::new(Style::default())      } diff --git a/wgpu/src/renderer/radio.rs b/wgpu/src/renderer/radio.rs index ce419ae0..fdc0a0fc 100644 --- a/wgpu/src/renderer/radio.rs +++ b/wgpu/src/renderer/radio.rs @@ -2,7 +2,7 @@ use crate::{Primitive, Renderer};  use iced_native::{radio, Layout, Node, Point, Radio, Style};  impl radio::Renderer for Renderer { -    fn node<Message>(&mut self, _checkbox: &Radio<Message>) -> Node { +    fn node<Message>(&self, _checkbox: &Radio<Message>) -> Node {          Node::new(Style::default())      } diff --git a/wgpu/src/renderer/text.rs b/wgpu/src/renderer/text.rs index 4434cc22..c89c0b3e 100644 --- a/wgpu/src/renderer/text.rs +++ b/wgpu/src/renderer/text.rs @@ -1,5 +1,5 @@  use crate::{Primitive, Renderer}; -use iced_native::{text, Layout, Node, Style, Text}; +use iced_native::{text, Color, Layout, Node, Style, Text};  use wgpu_glyph::{GlyphCruncher, Section}; @@ -72,6 +72,9 @@ impl text::Renderer for Renderer {              content: text.content.clone(),              size: f32::from(text.size.unwrap_or(20)),              bounds: layout.bounds(), +            color: text.color.unwrap_or(Color::BLACK), +            horizontal_alignment: text.horizontal_alignment, +            vertical_alignment: text.vertical_alignment,          }      }  } diff --git a/wgpu/src/shader/quad.frag b/wgpu/src/shader/quad.frag index 1fc28bc1..987744db 100644 --- a/wgpu/src/shader/quad.frag +++ b/wgpu/src/shader/quad.frag @@ -3,6 +3,7 @@  layout(location = 0) in vec4 v_Color;  layout(location = 1) in vec2 v_Pos;  layout(location = 2) in vec2 v_Scale; +layout(location = 3) in flat uint v_BorderRadius;  layout(location = 0) out vec4 o_Color; @@ -26,8 +27,11 @@ float rounded(in vec2 frag_coord, in vec2 position, in vec2 size, float radius,  }  void main() { -    o_Color = vec4( -        v_Color.xyz, -        v_Color.w * rounded(gl_FragCoord.xy, v_Pos, v_Scale, 5.0, 1.0) -    ); +    float radius_alpha = 1.0; + +    if(v_BorderRadius > 0.0) { +        radius_alpha = rounded(gl_FragCoord.xy, v_Pos, v_Scale, v_BorderRadius, 1.0); +    } + +    o_Color = vec4(v_Color.xyz, v_Color.w * radius_alpha);  } diff --git a/wgpu/src/shader/quad.frag.spv b/wgpu/src/shader/quad.frag.spv Binary files differindex 19733ecf..063287b3 100644 --- a/wgpu/src/shader/quad.frag.spv +++ b/wgpu/src/shader/quad.frag.spv diff --git a/wgpu/src/shader/quad.vert b/wgpu/src/shader/quad.vert index 87f6cc53..b7c5cf3e 100644 --- a/wgpu/src/shader/quad.vert +++ b/wgpu/src/shader/quad.vert @@ -4,6 +4,7 @@ layout(location = 0) in vec2 v_Pos;  layout(location = 1) in vec2 i_Pos;  layout(location = 2) in vec2 i_Scale;  layout(location = 3) in vec4 i_Color; +layout(location = 4) in uint i_BorderRadius;  layout (set = 0, binding = 0) uniform Globals {      mat4 u_Transform; @@ -12,6 +13,7 @@ layout (set = 0, binding = 0) uniform Globals {  layout(location = 0) out vec4 o_Color;  layout(location = 1) out vec2 o_Pos;  layout(location = 2) out vec2 o_Scale; +layout(location = 3) out uint o_BorderRadius;  void main() {      mat4 i_Transform = mat4( @@ -24,6 +26,7 @@ void main() {      o_Color = i_Color;      o_Pos = i_Pos;      o_Scale = i_Scale; +    o_BorderRadius = i_BorderRadius;      gl_Position = u_Transform * i_Transform * vec4(v_Pos, 0.0, 1.0);  } diff --git a/wgpu/src/shader/quad.vert.spv b/wgpu/src/shader/quad.vert.spv Binary files differindex 0d13df6c..f62a160c 100644 --- a/wgpu/src/shader/quad.vert.spv +++ b/wgpu/src/shader/quad.vert.spv  | 
