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 |