Make iced_core::Button customizable

Now it supports:
  - Any kind of content
  - Custom border radius
  - Custom background
This commit is contained in:
Héctor Ramón Jiménez 2019-10-08 03:13:41 +02:00
parent a0234d5bce
commit 10e10e5e06
35 changed files with 288 additions and 160 deletions

View file

@ -19,6 +19,8 @@ members = [
"core",
"native",
"web",
"wgpu",
"winit",
]
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]

7
core/src/background.rs Normal file
View file

@ -0,0 +1,7 @@
use crate::Color;
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum Background {
Color(Color),
// TODO: Add gradient and image variants
}

View file

@ -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

View file

@ -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;

View file

@ -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);
/// ```
///
/// ![Button drawn by Coffee's renderer](https://github.com/hecrj/coffee/blob/bda9818f823dfcb8a7ad0ff4940b4d4b387b5208/images/ui/button.png?raw=true)
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`].
///
/// ![Different buttons drawn by the built-in renderer in Coffee](https://github.com/hecrj/coffee/blob/bda9818f823dfcb8a7ad0ff4940b4d4b387b5208/images/ui/button_classes.png?raw=true)
///
/// [`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,
}

View file

@ -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.
///

View file

@ -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,

View file

@ -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)
}

View file

@ -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};

View file

@ -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
}

View file

@ -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`.
///

View file

@ -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)
}
}

View file

@ -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`].
///

View file

@ -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()

View file

@ -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`].
///

View file

@ -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.
///

View file

@ -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()

View file

@ -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)
}

View file

@ -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)
}

View file

@ -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;

View file

@ -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
}

View file

@ -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();

View file

@ -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};

View file

@ -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
}

View file

@ -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 {

View file

@ -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),
});
}
}

View file

@ -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,
),
],
}
}

View file

@ -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())
}

View file

@ -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())
}

View file

@ -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())
}

View file

@ -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,
}
}
}

View file

@ -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);
}

Binary file not shown.

View file

@ -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);
}

Binary file not shown.