summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--examples/custom_widget.rs3
-rw-r--r--examples/pokedex.rs30
-rw-r--r--examples/stopwatch.rs45
-rw-r--r--examples/todos.rs111
-rw-r--r--examples/tour.rs60
-rw-r--r--native/src/element.rs10
-rw-r--r--native/src/lib.rs2
-rw-r--r--native/src/renderer.rs9
-rw-r--r--native/src/renderer/debugger.rs1
-rw-r--r--native/src/renderer/null.rs30
-rw-r--r--native/src/renderer/windowed.rs3
-rw-r--r--native/src/user_interface.rs58
-rw-r--r--native/src/widget.rs1
-rw-r--r--native/src/widget/button.rs66
-rw-r--r--native/src/widget/checkbox.rs2
-rw-r--r--native/src/widget/column.rs4
-rw-r--r--native/src/widget/container.rs50
-rw-r--r--native/src/widget/image.rs1
-rw-r--r--native/src/widget/radio.rs2
-rw-r--r--native/src/widget/row.rs4
-rw-r--r--native/src/widget/scrollable.rs8
-rw-r--r--native/src/widget/slider.rs1
-rw-r--r--native/src/widget/svg.rs1
-rw-r--r--native/src/widget/text.rs3
-rw-r--r--native/src/widget/text_input.rs1
-rw-r--r--src/lib.rs2
-rw-r--r--src/native.rs18
-rw-r--r--src/settings.rs18
-rw-r--r--wgpu/src/defaults.rs27
-rw-r--r--wgpu/src/lib.rs16
-rw-r--r--wgpu/src/renderer.rs31
-rw-r--r--wgpu/src/renderer/widget.rs1
-rw-r--r--wgpu/src/renderer/widget/button.rs49
-rw-r--r--wgpu/src/renderer/widget/column.rs3
-rw-r--r--wgpu/src/renderer/widget/container.rs46
-rw-r--r--wgpu/src/renderer/widget/row.rs3
-rw-r--r--wgpu/src/renderer/widget/text.rs3
-rw-r--r--wgpu/src/widget.rs2
-rw-r--r--wgpu/src/widget/button.rs90
-rw-r--r--wgpu/src/widget/container.rs37
-rw-r--r--winit/src/application.rs12
-rw-r--r--winit/src/settings/mod.rs15
42 files changed, 635 insertions, 244 deletions
diff --git a/examples/custom_widget.rs b/examples/custom_widget.rs
index cf2f7792..ca562ead 100644
--- a/examples/custom_widget.rs
+++ b/examples/custom_widget.rs
@@ -13,7 +13,7 @@ mod circle {
layout, Background, Color, Element, Hasher, Layout, Length,
MouseCursor, Point, Size, Widget,
};
- use iced_wgpu::{Primitive, Renderer};
+ use iced_wgpu::{Defaults, Primitive, Renderer};
pub struct Circle {
radius: u16,
@@ -54,6 +54,7 @@ mod circle {
fn draw(
&self,
_renderer: &mut Renderer,
+ _defaults: &Defaults,
layout: Layout<'_>,
_cursor_position: Point,
) -> (Primitive, MouseCursor) {
diff --git a/examples/pokedex.rs b/examples/pokedex.rs
index 2d595ec4..35d38251 100644
--- a/examples/pokedex.rs
+++ b/examples/pokedex.rs
@@ -1,6 +1,6 @@
use iced::{
- button, image, Align, Application, Button, Color, Column, Command,
- Container, Element, Image, Length, Row, Settings, Text,
+ button, image, Align, Application, Button, Column, Command, Container,
+ Element, Image, Length, Row, Settings, Text,
};
pub fn main() {
@@ -219,8 +219,28 @@ impl From<surf::Exception> for Error {
}
fn button<'a>(state: &'a mut button::State, text: &str) -> Button<'a, Message> {
- Button::new(state, Text::new(text).color(Color::WHITE))
- .background(Color::from_rgb(0.11, 0.42, 0.87))
- .border_radius(10)
+ Button::new(state, Text::new(text))
.padding(10)
+ .style(style::Button::Primary)
+}
+
+mod style {
+ use iced::{button, Background, Color};
+
+ pub enum Button {
+ Primary,
+ }
+
+ impl button::StyleSheet for Button {
+ fn active(&self) -> button::Style {
+ button::Style {
+ background: Some(Background::Color(match self {
+ Button::Primary => Color::from_rgb(0.11, 0.42, 0.87),
+ })),
+ border_radius: 12,
+ shadow_offset: 1.0,
+ text_color: Color::WHITE,
+ }
+ }
+ }
}
diff --git a/examples/stopwatch.rs b/examples/stopwatch.rs
index 7a7f0793..99746609 100644
--- a/examples/stopwatch.rs
+++ b/examples/stopwatch.rs
@@ -1,7 +1,6 @@
use iced::{
- button, Align, Application, Background, Button, Color, Column, Command,
- Container, Element, HorizontalAlignment, Length, Row, Settings,
- Subscription, Text,
+ button, Align, Application, Button, Column, Command, Container, Element,
+ HorizontalAlignment, Length, Row, Settings, Subscription, Text,
};
use std::time::{Duration, Instant};
@@ -99,30 +98,29 @@ impl Application for Stopwatch {
.width(Length::Shrink)
.size(40);
- let button = |state, label, color: [f32; 3]| {
+ let button = |state, label, style| {
Button::new(
state,
Text::new(label)
- .color(Color::WHITE)
.horizontal_alignment(HorizontalAlignment::Center),
)
.min_width(80)
- .background(Background::Color(color.into()))
- .border_radius(10)
.padding(10)
+ .style(style)
};
let toggle_button = {
let (label, color) = match self.state {
- State::Idle => ("Start", [0.11, 0.42, 0.87]),
- State::Ticking { .. } => ("Stop", [0.9, 0.4, 0.4]),
+ State::Idle => ("Start", style::Button::Primary),
+ State::Ticking { .. } => ("Stop", style::Button::Destructive),
};
button(&mut self.toggle, label, color).on_press(Message::Toggle)
};
- let reset_button = button(&mut self.reset, "Reset", [0.7, 0.7, 0.7])
- .on_press(Message::Reset);
+ let reset_button =
+ button(&mut self.reset, "Reset", style::Button::Secondary)
+ .on_press(Message::Reset);
let controls = Row::new()
.width(Length::Shrink)
@@ -180,3 +178,28 @@ mod time {
}
}
}
+
+mod style {
+ use iced::{button, Background, Color};
+
+ pub enum Button {
+ Primary,
+ Secondary,
+ Destructive,
+ }
+
+ impl button::StyleSheet for Button {
+ fn active(&self) -> button::Style {
+ button::Style {
+ background: Some(Background::Color(match self {
+ Button::Primary => Color::from_rgb(0.11, 0.42, 0.87),
+ Button::Secondary => Color::from_rgb(0.5, 0.5, 0.5),
+ Button::Destructive => Color::from_rgb(0.8, 0.2, 0.2),
+ })),
+ border_radius: 12,
+ shadow_offset: 1.0,
+ text_color: Color::WHITE,
+ }
+ }
+ }
+}
diff --git a/examples/todos.rs b/examples/todos.rs
index 42e88f65..ca20183f 100644
--- a/examples/todos.rs
+++ b/examples/todos.rs
@@ -1,7 +1,7 @@
use iced::{
button, scrollable, text_input, Align, Application, Button, Checkbox,
- Color, Column, Command, Container, Element, Font, HorizontalAlignment,
- Length, Row, Scrollable, Settings, Text, TextInput,
+ Column, Command, Container, Element, Font, HorizontalAlignment, Length,
+ Row, Scrollable, Settings, Text, TextInput,
};
use serde::{Deserialize, Serialize};
@@ -291,12 +291,10 @@ impl Task {
.align_items(Align::Center)
.push(checkbox)
.push(
- Button::new(
- edit_button,
- edit_icon().color([0.5, 0.5, 0.5]),
- )
- .on_press(TaskMessage::Edit)
- .padding(10),
+ Button::new(edit_button, edit_icon())
+ .on_press(TaskMessage::Edit)
+ .padding(10)
+ .style(style::Button::Icon),
)
.into()
}
@@ -320,19 +318,13 @@ impl Task {
.push(
Button::new(
delete_button,
- Row::new()
- .spacing(10)
- .push(delete_icon().color(Color::WHITE))
- .push(
- Text::new("Delete")
- .width(Length::Shrink)
- .color(Color::WHITE),
- ),
+ Row::new().spacing(10).push(delete_icon()).push(
+ Text::new("Delete").width(Length::Shrink),
+ ),
)
.on_press(TaskMessage::Delete)
.padding(10)
- .border_radius(5)
- .background(Color::from_rgb(0.8, 0.2, 0.2)),
+ .style(style::Button::Destructive),
)
.into()
}
@@ -359,17 +351,12 @@ impl Controls {
let filter_button = |state, label, filter, current_filter| {
let label = Text::new(label).size(16).width(Length::Shrink);
- let button = if filter == current_filter {
- Button::new(state, label.color(Color::WHITE))
- .background(Color::from_rgb(0.2, 0.2, 0.7))
- } else {
- Button::new(state, label)
- };
-
- button
- .on_press(Message::FilterChanged(filter))
- .padding(8)
- .border_radius(10)
+ let button =
+ Button::new(state, label).style(style::Button::Filter {
+ selected: filter == current_filter,
+ });
+
+ button.on_press(Message::FilterChanged(filter)).padding(8)
};
Row::new()
@@ -562,3 +549,69 @@ impl SavedState {
Ok(())
}
}
+
+mod style {
+ use iced::{button, Background, Color};
+
+ pub enum Button {
+ Filter { selected: bool },
+ Icon,
+ Destructive,
+ }
+
+ impl button::StyleSheet for Button {
+ fn active(&self) -> button::Style {
+ match self {
+ Button::Filter { selected } => {
+ if *selected {
+ button::Style {
+ background: Some(Background::Color(
+ Color::from_rgb(0.2, 0.2, 0.7),
+ )),
+ border_radius: 10,
+ shadow_offset: 0.0,
+ text_color: Color::WHITE,
+ }
+ } else {
+ button::Style {
+ background: None,
+ border_radius: 0,
+ shadow_offset: 0.0,
+ text_color: Color::BLACK,
+ }
+ }
+ }
+ Button::Icon => button::Style {
+ background: None,
+ border_radius: 0,
+ shadow_offset: 0.0,
+ text_color: Color::from_rgb(0.5, 0.5, 0.5),
+ },
+ Button::Destructive => button::Style {
+ background: Some(Background::Color(Color::from_rgb(
+ 0.8, 0.2, 0.2,
+ ))),
+ border_radius: 5,
+ shadow_offset: 1.0,
+ text_color: Color::WHITE,
+ },
+ }
+ }
+
+ fn hovered(&self) -> button::Style {
+ let active = self.active();
+
+ button::Style {
+ text_color: match self {
+ Button::Icon => Color::from_rgb(0.2, 0.2, 0.7),
+ Button::Filter { selected } if !selected => {
+ Color::from_rgb(0.2, 0.2, 0.7)
+ }
+ _ => active.text_color,
+ },
+ shadow_offset: active.shadow_offset + 1.0,
+ ..active
+ }
+ }
+ }
+}
diff --git a/examples/tour.rs b/examples/tour.rs
index 91b75296..c7f866e8 100644
--- a/examples/tour.rs
+++ b/examples/tour.rs
@@ -62,8 +62,9 @@ impl Sandbox for Tour {
if steps.has_previous() {
controls = controls.push(
- secondary_button(back_button, "Back")
- .on_press(Message::BackPressed),
+ button(back_button, "Back")
+ .on_press(Message::BackPressed)
+ .style(style::Button::Secondary),
);
}
@@ -71,8 +72,9 @@ impl Sandbox for Tour {
if steps.can_continue() {
controls = controls.push(
- primary_button(next_button, "Next")
- .on_press(Message::NextPressed),
+ button(next_button, "Next")
+ .on_press(Message::NextPressed)
+ .style(style::Button::Primary),
);
}
@@ -692,29 +694,12 @@ fn button<'a, Message>(
) -> Button<'a, Message> {
Button::new(
state,
- Text::new(label)
- .color(Color::WHITE)
- .horizontal_alignment(HorizontalAlignment::Center),
+ Text::new(label).horizontal_alignment(HorizontalAlignment::Center),
)
.padding(12)
- .border_radius(12)
.min_width(100)
}
-fn primary_button<'a, Message>(
- state: &'a mut button::State,
- label: &str,
-) -> Button<'a, Message> {
- button(state, label).background(Color::from_rgb(0.11, 0.42, 0.87))
-}
-
-fn secondary_button<'a, Message>(
- state: &'a mut button::State,
- label: &str,
-) -> Button<'a, Message> {
- button(state, label).background(Color::from_rgb(0.4, 0.4, 0.4))
-}
-
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Language {
Rust,
@@ -757,6 +742,37 @@ pub enum Layout {
Column,
}
+mod style {
+ use iced::{button, Background, Color};
+
+ pub enum Button {
+ Primary,
+ Secondary,
+ }
+
+ impl button::StyleSheet for Button {
+ fn active(&self) -> button::Style {
+ button::Style {
+ background: Some(Background::Color(match self {
+ Button::Primary => Color::from_rgb(0.11, 0.42, 0.87),
+ Button::Secondary => Color::from_rgb(0.5, 0.5, 0.5),
+ })),
+ border_radius: 12,
+ shadow_offset: 1.0,
+ text_color: Color::from_rgb8(0xEE, 0xEE, 0xEE),
+ }
+ }
+
+ fn hovered(&self) -> button::Style {
+ button::Style {
+ text_color: Color::WHITE,
+ shadow_offset: 2.0,
+ ..self.active()
+ }
+ }
+ }
+}
+
// This should be gracefully handled by Iced in the future. Probably using our
// own proc macro, or maybe the whole process is streamlined by `wasm-pack` at
// some point.
diff --git a/native/src/element.rs b/native/src/element.rs
index 63d2de0c..9b5adb9c 100644
--- a/native/src/element.rs
+++ b/native/src/element.rs
@@ -235,10 +235,12 @@ where
pub fn draw(
&self,
renderer: &mut Renderer,
+ defaults: &Renderer::Defaults,
layout: Layout<'_>,
cursor_position: Point,
) -> Renderer::Output {
- self.widget.draw(renderer, layout, cursor_position)
+ self.widget
+ .draw(renderer, defaults, layout, cursor_position)
}
pub(crate) fn hash_layout(&self, state: &mut Hasher) {
@@ -316,10 +318,12 @@ where
fn draw(
&self,
renderer: &mut Renderer,
+ defaults: &Renderer::Defaults,
layout: Layout<'_>,
cursor_position: Point,
) -> Renderer::Output {
- self.widget.draw(renderer, layout, cursor_position)
+ self.widget
+ .draw(renderer, defaults, layout, cursor_position)
}
fn hash_layout(&self, state: &mut Hasher) {
@@ -384,10 +388,12 @@ where
fn draw(
&self,
renderer: &mut Renderer,
+ defaults: &Renderer::Defaults,
layout: Layout<'_>,
cursor_position: Point,
) -> Renderer::Output {
renderer.explain(
+ defaults,
self.element.widget.as_ref(),
layout,
cursor_position,
diff --git a/native/src/lib.rs b/native/src/lib.rs
index 8dcacb2b..9d237196 100644
--- a/native/src/lib.rs
+++ b/native/src/lib.rs
@@ -34,7 +34,7 @@
//! [`Windowed`]: renderer/trait.Windowed.html
//! [`UserInterface`]: struct.UserInterface.html
//! [renderer]: renderer/index.html
-#![deny(missing_docs)]
+//#![deny(missing_docs)]
#![deny(missing_debug_implementations)]
#![deny(unused_results)]
#![deny(unsafe_code)]
diff --git a/native/src/renderer.rs b/native/src/renderer.rs
index 7a68ada4..90cec6c8 100644
--- a/native/src/renderer.rs
+++ b/native/src/renderer.rs
@@ -21,14 +21,15 @@
//! [`checkbox::Renderer`]: ../widget/checkbox/trait.Renderer.html
mod debugger;
-#[cfg(debug_assertions)]
-mod null;
mod windowed;
pub use debugger::Debugger;
+pub use windowed::{Target, Windowed};
+
+#[cfg(debug_assertions)]
+mod null;
#[cfg(debug_assertions)]
pub use null::Null;
-pub use windowed::{Target, Windowed};
use crate::{layout, Element};
@@ -43,6 +44,8 @@ pub trait Renderer: Sized {
/// [`Renderer`]: trait.Renderer.html
type Output;
+ type Defaults: Default;
+
/// Lays out the elements of a user interface.
///
/// You should override this if you need to perform any operations before or
diff --git a/native/src/renderer/debugger.rs b/native/src/renderer/debugger.rs
index 4cc50661..30f3d9a0 100644
--- a/native/src/renderer/debugger.rs
+++ b/native/src/renderer/debugger.rs
@@ -17,6 +17,7 @@ pub trait Debugger: super::Renderer {
/// [`Element::explain`]: struct.Element.html#method.explain
fn explain<Message>(
&mut self,
+ defaults: &Self::Defaults,
widget: &dyn Widget<Message, Self>,
layout: Layout<'_>,
cursor_position: Point,
diff --git a/native/src/renderer/null.rs b/native/src/renderer/null.rs
index 43076d61..56d7e472 100644
--- a/native/src/renderer/null.rs
+++ b/native/src/renderer/null.rs
@@ -1,20 +1,30 @@
use crate::{
- button, checkbox, column, radio, row, scrollable, text, text_input,
- Background, Color, Element, Font, HorizontalAlignment, Layout, Point,
- Rectangle, Renderer, Size, VerticalAlignment,
+ button, checkbox, column, radio, row, scrollable, text, text_input, Color,
+ Element, Font, HorizontalAlignment, Layout, Point, Rectangle, Renderer,
+ Size, VerticalAlignment,
};
/// A renderer that does nothing.
+///
+/// It can be useful if you are writing tests!
#[derive(Debug, Clone, Copy)]
pub struct Null;
+impl Null {
+ pub fn new() -> Null {
+ Null
+ }
+}
+
impl Renderer for Null {
type Output = ();
+ type Defaults = ();
}
impl column::Renderer for Null {
fn draw<Message>(
&mut self,
+ _defaults: &Self::Defaults,
_content: &[Element<'_, Message, Self>],
_layout: Layout<'_>,
_cursor_position: Point,
@@ -25,6 +35,7 @@ impl column::Renderer for Null {
impl row::Renderer for Null {
fn draw<Message>(
&mut self,
+ _defaults: &Self::Defaults,
_content: &[Element<'_, Message, Self>],
_layout: Layout<'_>,
_cursor_position: Point,
@@ -49,6 +60,7 @@ impl text::Renderer for Null {
fn draw(
&mut self,
+ _defaults: &Self::Defaults,
_bounds: Rectangle,
_content: &str,
_size: u16,
@@ -117,14 +129,18 @@ impl text_input::Renderer for Null {
}
impl button::Renderer for Null {
- fn draw(
+ type Style = ();
+
+ fn draw<Message>(
&mut self,
+ _defaults: &Self::Defaults,
_bounds: Rectangle,
_cursor_position: Point,
+ _is_disabled: bool,
_is_pressed: bool,
- _background: Option<Background>,
- _border_radius: u16,
- _content: Self::Output,
+ _style: &Self::Style,
+ _content: &Element<'_, Message, Self>,
+ _content_layout: Layout<'_>,
) -> Self::Output {
}
}
diff --git a/native/src/renderer/windowed.rs b/native/src/renderer/windowed.rs
index 813a03f2..89f80bbe 100644
--- a/native/src/renderer/windowed.rs
+++ b/native/src/renderer/windowed.rs
@@ -1,4 +1,4 @@
-use crate::MouseCursor;
+use crate::{Color, MouseCursor};
use raw_window_handle::HasRawWindowHandle;
@@ -19,6 +19,7 @@ pub trait Windowed: super::Renderer + Sized {
/// top of the GUI on most scenarios.
fn draw<T: AsRef<str>>(
&mut self,
+ clear_color: Color,
output: &Self::Output,
overlay: &[T],
target: &mut Self::Target,
diff --git a/native/src/user_interface.rs b/native/src/user_interface.rs
index 07b936a9..970bf0c1 100644
--- a/native/src/user_interface.rs
+++ b/native/src/user_interface.rs
@@ -43,24 +43,7 @@ where
/// use iced_wgpu::Renderer;
///
/// # mod iced_wgpu {
- /// # pub struct Renderer;
- /// #
- /// # impl Renderer {
- /// # pub fn new() -> Self { Renderer }
- /// # }
- /// #
- /// # impl iced_native::Renderer for Renderer { type Output = (); }
- /// #
- /// # impl iced_native::column::Renderer for Renderer {
- /// # fn draw<Message>(
- /// # &mut self,
- /// # _children: &[iced_native::Element<'_, Message, Self>],
- /// # _layout: iced_native::Layout<'_>,
- /// # _cursor_position: iced_native::Point,
- /// # ) -> Self::Output {
- /// # ()
- /// # }
- /// # }
+ /// # pub use iced_native::renderer::Null as Renderer;
/// # }
/// #
/// # use iced_native::Column;
@@ -139,24 +122,7 @@ where
/// use iced_wgpu::Renderer;
///
/// # mod iced_wgpu {
- /// # pub struct Renderer;
- /// #
- /// # impl Renderer {
- /// # pub fn new() -> Self { Renderer }
- /// # }
- /// #
- /// # impl iced_native::Renderer for Renderer { type Output = (); }
- /// #
- /// # impl iced_native::column::Renderer for Renderer {
- /// # fn draw<Message>(
- /// # &mut self,
- /// # _children: &[iced_native::Element<'_, Message, Self>],
- /// # _layout: iced_native::Layout<'_>,
- /// # _cursor_position: iced_native::Point,
- /// # ) -> Self::Output {
- /// # ()
- /// # }
- /// # }
+ /// # pub use iced_native::renderer::Null as Renderer;
/// # }
/// #
/// # use iced_native::Column;
@@ -241,24 +207,7 @@ where
/// use iced_wgpu::Renderer;
///
/// # mod iced_wgpu {
- /// # pub struct Renderer;
- /// #
- /// # impl Renderer {
- /// # pub fn new() -> Self { Renderer }
- /// # }
- /// #
- /// # impl iced_native::Renderer for Renderer { type Output = (); }
- /// #
- /// # impl iced_native::column::Renderer for Renderer {
- /// # fn draw<Message>(
- /// # &mut self,
- /// # _children: &[iced_native::Element<'_, Message, Self>],
- /// # _layout: iced_native::Layout<'_>,
- /// # _cursor_position: iced_native::Point,
- /// # ) -> Self::Output {
- /// # ()
- /// # }
- /// # }
+ /// # pub use iced_native::renderer::Null as Renderer;
/// # }
/// #
/// # use iced_native::Column;
@@ -304,6 +253,7 @@ where
pub fn draw(&self, renderer: &mut Renderer) -> Renderer::Output {
self.root.widget.draw(
renderer,
+ &Renderer::Defaults::default(),
Layout::new(&self.layout),
self.cursor_position,
)
diff --git a/native/src/widget.rs b/native/src/widget.rs
index dcc99645..536d9e94 100644
--- a/native/src/widget.rs
+++ b/native/src/widget.rs
@@ -104,6 +104,7 @@ where
fn draw(
&self,
renderer: &mut Renderer,
+ defaults: &Renderer::Defaults,
layout: Layout<'_>,
cursor_position: Point,
) -> Renderer::Output;
diff --git a/native/src/widget/button.rs b/native/src/widget/button.rs
index 2881105f..75ef2693 100644
--- a/native/src/widget/button.rs
+++ b/native/src/widget/button.rs
@@ -6,8 +6,8 @@
//! [`State`]: struct.State.html
use crate::{
input::{mouse, ButtonState},
- layout, Background, Clipboard, Element, Event, Hasher, Layout, Length,
- Point, Rectangle, Widget,
+ layout, Clipboard, Element, Event, Hasher, Layout, Length, Point,
+ Rectangle, Widget,
};
use std::hash::Hash;
@@ -28,7 +28,7 @@ use std::hash::Hash;
/// .on_press(Message::ButtonPressed);
/// ```
#[allow(missing_debug_implementations)]
-pub struct Button<'a, Message, Renderer> {
+pub struct Button<'a, Message, Renderer: self::Renderer> {
state: &'a mut State,
content: Element<'a, Message, Renderer>,
on_press: Option<Message>,
@@ -37,11 +37,13 @@ pub struct Button<'a, Message, Renderer> {
min_width: u32,
min_height: u32,
padding: u16,
- background: Option<Background>,
- border_radius: u16,
+ style: Renderer::Style,
}
-impl<'a, Message, Renderer> Button<'a, Message, Renderer> {
+impl<'a, Message, Renderer> Button<'a, Message, Renderer>
+where
+ Renderer: self::Renderer,
+{
/// Creates a new [`Button`] with some local [`State`] and the given
/// content.
///
@@ -60,8 +62,7 @@ impl<'a, Message, Renderer> Button<'a, Message, Renderer> {
min_width: 0,
min_height: 0,
padding: 0,
- background: None,
- border_radius: 0,
+ style: Renderer::Style::default(),
}
}
@@ -105,23 +106,6 @@ impl<'a, Message, Renderer> Button<'a, Message, Renderer> {
self
}
- /// Sets the [`Background`] of the [`Button`].
- ///
- /// [`Button`]: struct.Button.html
- /// [`Background`]: ../../struct.Background.html
- pub fn background<T: Into<Background>>(mut self, background: T) -> Self {
- self.background = Some(background.into());
- self
- }
-
- /// Sets the border radius of the [`Button`].
- ///
- /// [`Button`]: struct.Button.html
- pub fn border_radius(mut self, border_radius: u16) -> Self {
- self.border_radius = border_radius;
- self
- }
-
/// Sets the message that will be produced when the [`Button`] is pressed.
///
/// [`Button`]: struct.Button.html
@@ -129,6 +113,11 @@ impl<'a, Message, Renderer> Button<'a, Message, Renderer> {
self.on_press = Some(msg);
self
}
+
+ pub fn style(mut self, style: impl Into<Renderer::Style>) -> Self {
+ self.style = style.into();
+ self
+ }
}
/// The local state of a [`Button`].
@@ -227,22 +216,19 @@ where
fn draw(
&self,
renderer: &mut Renderer,
+ defaults: &Renderer::Defaults,
layout: Layout<'_>,
cursor_position: Point,
) -> Renderer::Output {
- let content = self.content.draw(
- renderer,
- layout.children().next().unwrap(),
- cursor_position,
- );
-
renderer.draw(
+ defaults,
layout.bounds(),
cursor_position,
+ self.on_press.is_none(),
self.state.is_pressed,
- self.background,
- self.border_radius,
- content,
+ &self.style,
+ &self.content,
+ layout.children().next().unwrap(),
)
}
@@ -260,17 +246,21 @@ where
/// [`Button`]: struct.Button.html
/// [renderer]: ../../renderer/index.html
pub trait Renderer: crate::Renderer + Sized {
+ type Style: Default;
+
/// Draws a [`Button`].
///
/// [`Button`]: struct.Button.html
- fn draw(
+ fn draw<Message>(
&mut self,
+ defaults: &Self::Defaults,
bounds: Rectangle,
cursor_position: Point,
+ is_disabled: bool,
is_pressed: bool,
- background: Option<Background>,
- border_radius: u16,
- content: Self::Output,
+ style: &Self::Style,
+ content: &Element<'_, Message, Self>,
+ content_layout: Layout<'_>,
) -> Self::Output;
}
diff --git a/native/src/widget/checkbox.rs b/native/src/widget/checkbox.rs
index 0dcac712..87a7f629 100644
--- a/native/src/widget/checkbox.rs
+++ b/native/src/widget/checkbox.rs
@@ -134,6 +134,7 @@ where
fn draw(
&self,
renderer: &mut Renderer,
+ defaults: &Renderer::Defaults,
layout: Layout<'_>,
cursor_position: Point,
) -> Renderer::Output {
@@ -146,6 +147,7 @@ where
let label = text::Renderer::draw(
renderer,
+ defaults,
label_layout.bounds(),
&self.label,
text::Renderer::default_size(renderer),
diff --git a/native/src/widget/column.rs b/native/src/widget/column.rs
index 4b5d631c..3418d4b0 100644
--- a/native/src/widget/column.rs
+++ b/native/src/widget/column.rs
@@ -173,10 +173,11 @@ where
fn draw(
&self,
renderer: &mut Renderer,
+ defaults: &Renderer::Defaults,
layout: Layout<'_>,
cursor_position: Point,
) -> Renderer::Output {
- renderer.draw(&self.children, layout, cursor_position)
+ renderer.draw(defaults, &self.children, layout, cursor_position)
}
fn hash_layout(&self, state: &mut Hasher) {
@@ -213,6 +214,7 @@ pub trait Renderer: crate::Renderer + Sized {
/// [`Layout`]: ../layout/struct.Layout.html
fn draw<Message>(
&mut self,
+ defaults: &Self::Defaults,
content: &[Element<'_, Message, Self>],
layout: Layout<'_>,
cursor_position: Point,
diff --git a/native/src/widget/container.rs b/native/src/widget/container.rs
index 74f0e0ef..75c2d6b3 100644
--- a/native/src/widget/container.rs
+++ b/native/src/widget/container.rs
@@ -3,7 +3,7 @@ use std::hash::Hash;
use crate::{
layout, Align, Clipboard, Element, Event, Hasher, Layout, Length, Point,
- Widget,
+ Rectangle, Widget,
};
use std::u32;
@@ -12,17 +12,21 @@ use std::u32;
///
/// It is normally used for alignment purposes.
#[allow(missing_debug_implementations)]
-pub struct Container<'a, Message, Renderer> {
+pub struct Container<'a, Message, Renderer: self::Renderer> {
width: Length,
height: Length,
max_width: u32,
max_height: u32,
horizontal_alignment: Align,
vertical_alignment: Align,
+ style: Renderer::Style,
content: Element<'a, Message, Renderer>,
}
-impl<'a, Message, Renderer> Container<'a, Message, Renderer> {
+impl<'a, Message, Renderer> Container<'a, Message, Renderer>
+where
+ Renderer: self::Renderer,
+{
/// Creates an empty [`Container`].
///
/// [`Container`]: struct.Container.html
@@ -37,6 +41,7 @@ impl<'a, Message, Renderer> Container<'a, Message, Renderer> {
max_height: u32::MAX,
horizontal_alignment: Align::Start,
vertical_alignment: Align::Start,
+ style: Renderer::Style::default(),
content: content.into(),
}
}
@@ -78,7 +83,6 @@ impl<'a, Message, Renderer> Container<'a, Message, Renderer> {
/// [`Container`]: struct.Container.html
pub fn center_x(mut self) -> Self {
self.horizontal_alignment = Align::Center;
-
self
}
@@ -87,7 +91,14 @@ impl<'a, Message, Renderer> Container<'a, Message, Renderer> {
/// [`Container`]: struct.Container.html
pub fn center_y(mut self) -> Self {
self.vertical_alignment = Align::Center;
+ self
+ }
+ /// Sets the style the [`Container`].
+ ///
+ /// [`Container`]: struct.Container.html
+ pub fn style(mut self, style: impl Into<Renderer::Style>) -> Self {
+ self.style = style.into();
self
}
}
@@ -95,7 +106,7 @@ impl<'a, Message, Renderer> Container<'a, Message, Renderer> {
impl<'a, Message, Renderer> Widget<Message, Renderer>
for Container<'a, Message, Renderer>
where
- Renderer: crate::Renderer,
+ Renderer: self::Renderer,
{
fn width(&self) -> Length {
self.width
@@ -147,13 +158,17 @@ where
fn draw(
&self,
renderer: &mut Renderer,
+ defaults: &Renderer::Defaults,
layout: Layout<'_>,
cursor_position: Point,
) -> Renderer::Output {
- self.content.draw(
- renderer,
- layout.children().next().unwrap(),
+ renderer.draw(
+ defaults,
+ layout.bounds(),
cursor_position,
+ &self.style,
+ &self.content,
+ layout.children().next().unwrap(),
)
}
@@ -168,10 +183,27 @@ where
}
}
+pub trait Renderer: crate::Renderer {
+ type Style: Default;
+
+ /// Draws a [`Container`].
+ ///
+ /// [`Container`]: struct.Container.html
+ fn draw<Message>(
+ &mut self,
+ defaults: &Self::Defaults,
+ bounds: Rectangle,
+ cursor_position: Point,
+ style: &Self::Style,
+ content: &Element<'_, Message, Self>,
+ content_layout: Layout<'_>,
+ ) -> Self::Output;
+}
+
impl<'a, Message, Renderer> From<Container<'a, Message, Renderer>>
for Element<'a, Message, Renderer>
where
- Renderer: 'a + crate::Renderer,
+ Renderer: 'a + self::Renderer,
Message: 'static,
{
fn from(
diff --git a/native/src/widget/image.rs b/native/src/widget/image.rs
index 20375822..1efe4570 100644
--- a/native/src/widget/image.rs
+++ b/native/src/widget/image.rs
@@ -95,6 +95,7 @@ where
fn draw(
&self,
renderer: &mut Renderer,
+ _defaults: &Renderer::Defaults,
layout: Layout<'_>,
_cursor_position: Point,
) -> Renderer::Output {
diff --git a/native/src/widget/radio.rs b/native/src/widget/radio.rs
index a9995b86..6ac00770 100644
--- a/native/src/widget/radio.rs
+++ b/native/src/widget/radio.rs
@@ -131,6 +131,7 @@ where
fn draw(
&self,
renderer: &mut Renderer,
+ defaults: &Renderer::Defaults,
layout: Layout<'_>,
cursor_position: Point,
) -> Renderer::Output {
@@ -143,6 +144,7 @@ where
let label = text::Renderer::draw(
renderer,
+ defaults,
label_layout.bounds(),
&self.label,
text::Renderer::default_size(renderer),
diff --git a/native/src/widget/row.rs b/native/src/widget/row.rs
index 3de65deb..76cca3d0 100644
--- a/native/src/widget/row.rs
+++ b/native/src/widget/row.rs
@@ -174,10 +174,11 @@ where
fn draw(
&self,
renderer: &mut Renderer,
+ defaults: &Renderer::Defaults,
layout: Layout<'_>,
cursor_position: Point,
) -> Renderer::Output {
- renderer.draw(&self.children, layout, cursor_position)
+ renderer.draw(defaults, &self.children, layout, cursor_position)
}
fn hash_layout(&self, state: &mut Hasher) {
@@ -215,6 +216,7 @@ pub trait Renderer: crate::Renderer + Sized {
/// [`Layout`]: ../layout/struct.Layout.html
fn draw<Message>(
&mut self,
+ defaults: &Self::Defaults,
children: &[Element<'_, Message, Self>],
layout: Layout<'_>,
cursor_position: Point,
diff --git a/native/src/widget/scrollable.rs b/native/src/widget/scrollable.rs
index 9fa602d5..9df09b14 100644
--- a/native/src/widget/scrollable.rs
+++ b/native/src/widget/scrollable.rs
@@ -255,6 +255,7 @@ where
fn draw(
&self,
renderer: &mut Renderer,
+ defaults: &Renderer::Defaults,
layout: Layout<'_>,
cursor_position: Point,
) -> Renderer::Output {
@@ -277,7 +278,12 @@ where
Point::new(cursor_position.x, -1.0)
};
- self.content.draw(renderer, content_layout, cursor_position)
+ self.content.draw(
+ renderer,
+ defaults,
+ content_layout,
+ cursor_position,
+ )
};
self::Renderer::draw(
diff --git a/native/src/widget/slider.rs b/native/src/widget/slider.rs
index f446f7e8..ea66a347 100644
--- a/native/src/widget/slider.rs
+++ b/native/src/widget/slider.rs
@@ -178,6 +178,7 @@ where
fn draw(
&self,
renderer: &mut Renderer,
+ _defaults: &Renderer::Defaults,
layout: Layout<'_>,
cursor_position: Point,
) -> Renderer::Output {
diff --git a/native/src/widget/svg.rs b/native/src/widget/svg.rs
index 9580f195..f6202f72 100644
--- a/native/src/widget/svg.rs
+++ b/native/src/widget/svg.rs
@@ -91,6 +91,7 @@ where
fn draw(
&self,
renderer: &mut Renderer,
+ _defaults: &Renderer::Defaults,
layout: Layout<'_>,
_cursor_position: Point,
) -> Renderer::Output {
diff --git a/native/src/widget/text.rs b/native/src/widget/text.rs
index cf9c9565..3a3db3cd 100644
--- a/native/src/widget/text.rs
+++ b/native/src/widget/text.rs
@@ -146,10 +146,12 @@ where
fn draw(
&self,
renderer: &mut Renderer,
+ defaults: &Renderer::Defaults,
layout: Layout<'_>,
_cursor_position: Point,
) -> Renderer::Output {
renderer.draw(
+ defaults,
layout.bounds(),
&self.content,
self.size.unwrap_or(renderer.default_size()),
@@ -209,6 +211,7 @@ pub trait Renderer: crate::Renderer {
/// [`VerticalAlignment`]: enum.VerticalAlignment.html
fn draw(
&mut self,
+ defaults: &Self::Defaults,
bounds: Rectangle,
content: &str,
size: u16,
diff --git a/native/src/widget/text_input.rs b/native/src/widget/text_input.rs
index 1d1c32a2..e2114f00 100644
--- a/native/src/widget/text_input.rs
+++ b/native/src/widget/text_input.rs
@@ -343,6 +343,7 @@ where
fn draw(
&self,
renderer: &mut Renderer,
+ _defaults: &Renderer::Defaults,
layout: Layout<'_>,
cursor_position: Point,
) -> Renderer::Output {
diff --git a/src/lib.rs b/src/lib.rs
index 1ef11378..579ff43d 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -174,7 +174,7 @@
//! [documentation]: https://docs.rs/iced
//! [examples]: https://github.com/hecrj/iced/tree/master/examples
//! [`Application`]: trait.Application.html
-#![deny(missing_docs)]
+//#![deny(missing_docs)]
#![deny(missing_debug_implementations)]
#![deny(unused_results)]
#![deny(unsafe_code)]
diff --git a/src/native.rs b/src/native.rs
index cf48a391..d5c9349a 100644
--- a/src/native.rs
+++ b/src/native.rs
@@ -22,23 +22,7 @@ pub mod widget {
//!
//! [`TextInput`]: text_input/struct.TextInput.html
//! [`text_input::State`]: text_input/struct.State.html
- pub mod button {
- //! Allow your users to perform actions by pressing a button.
- //!
- //! A [`Button`] has some local [`State`].
- //!
- //! [`Button`]: type.Button.html
- //! [`State`]: struct.State.html
-
- /// A widget that produces a message when clicked.
- ///
- /// This is an alias of an `iced_native` button with a default
- /// `Renderer`.
- pub type Button<'a, Message> =
- iced_winit::Button<'a, Message, iced_wgpu::Renderer>;
-
- pub use iced_winit::button::State;
- }
+ pub use iced_wgpu::button;
pub mod scrollable {
//! Navigate an endless amount of content with a scrollbar.
diff --git a/src/settings.rs b/src/settings.rs
index 62a1a614..4ae18a14 100644
--- a/src/settings.rs
+++ b/src/settings.rs
@@ -1,7 +1,8 @@
//! Configure your application.
+use crate::Color;
/// The settings of an application.
-#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
+#[derive(Debug, Clone, Copy, PartialEq)]
pub struct Settings {
/// The [`Window`] settings.
///
@@ -9,6 +10,20 @@ pub struct Settings {
///
/// [`Window`]: struct.Window.html
pub window: Window,
+
+ /// The default background [`Color`] of the application
+ ///
+ /// [`Color`]: ../struct.Color.html
+ pub background: Color,
+}
+
+impl Default for Settings {
+ fn default() -> Settings {
+ Settings {
+ window: Window::default(),
+ background: Color::WHITE,
+ }
+ }
}
/// The window settings of an application.
@@ -44,6 +59,7 @@ impl From<Settings> for iced_winit::Settings {
decorations: settings.window.decorations,
platform_specific: Default::default(),
},
+ background: settings.background,
}
}
}
diff --git a/wgpu/src/defaults.rs b/wgpu/src/defaults.rs
new file mode 100644
index 00000000..8de8258b
--- /dev/null
+++ b/wgpu/src/defaults.rs
@@ -0,0 +1,27 @@
+use iced_native::Color;
+
+#[derive(Debug, Clone, Copy)]
+pub struct Defaults {
+ pub text: Text,
+}
+
+impl Default for Defaults {
+ fn default() -> Defaults {
+ Defaults {
+ text: Text::default(),
+ }
+ }
+}
+
+#[derive(Debug, Clone, Copy)]
+pub struct Text {
+ pub color: Color,
+}
+
+impl Default for Text {
+ fn default() -> Text {
+ Text {
+ color: Color::BLACK,
+ }
+ }
+}
diff --git a/wgpu/src/lib.rs b/wgpu/src/lib.rs
index 9f9ed8db..786b6872 100644
--- a/wgpu/src/lib.rs
+++ b/wgpu/src/lib.rs
@@ -19,11 +19,14 @@
//! [`wgpu`]: https://github.com/gfx-rs/wgpu-rs
//! [WebGPU API]: https://gpuweb.github.io/gpuweb/
//! [`wgpu_glyph`]: https://github.com/hecrj/wgpu_glyph
-#![deny(missing_docs)]
+//#![deny(missing_docs)]
#![deny(missing_debug_implementations)]
#![deny(unused_results)]
#![deny(unsafe_code)]
#![deny(rust_2018_idioms)]
+pub mod defaults;
+pub mod widget;
+
mod image;
mod primitive;
mod quad;
@@ -31,9 +34,12 @@ mod renderer;
mod text;
mod transformation;
-pub(crate) use crate::image::Image;
-pub(crate) use quad::Quad;
-pub(crate) use transformation::Transformation;
-
+pub use defaults::Defaults;
pub use primitive::Primitive;
pub use renderer::{Renderer, Target};
+#[doc(no_inline)]
+pub use widget::*;
+
+pub(crate) use self::image::Image;
+pub(crate) use quad::Quad;
+pub(crate) use transformation::Transformation;
diff --git a/wgpu/src/renderer.rs b/wgpu/src/renderer.rs
index 365ef1ef..1b143d90 100644
--- a/wgpu/src/renderer.rs
+++ b/wgpu/src/renderer.rs
@@ -1,4 +1,6 @@
-use crate::{image, quad, text, Image, Primitive, Quad, Transformation};
+use crate::{
+ image, quad, text, Defaults, Image, Primitive, Quad, Transformation,
+};
use iced_native::{
renderer::{Debugger, Windowed},
Background, Color, Layout, MouseCursor, Point, Rectangle, Vector, Widget,
@@ -22,7 +24,7 @@ pub struct Renderer {
device: Device,
queue: Queue,
quad_pipeline: quad::Pipeline,
- image_pipeline: crate::image::Pipeline,
+ image_pipeline: image::Pipeline,
text_pipeline: text::Pipeline,
}
@@ -63,7 +65,7 @@ impl Renderer {
let text_pipeline = text::Pipeline::new(&mut device);
let quad_pipeline = quad::Pipeline::new(&mut device);
- let image_pipeline = crate::image::Pipeline::new(&mut device);
+ let image_pipeline = image::Pipeline::new(&mut device);
Self {
device,
@@ -76,6 +78,7 @@ impl Renderer {
fn draw<T: AsRef<str>>(
&mut self,
+ clear_color: Color,
(primitive, mouse_cursor): &(Primitive, MouseCursor),
overlay: &[T],
target: &mut Target,
@@ -97,11 +100,15 @@ impl Renderer {
resolve_target: None,
load_op: wgpu::LoadOp::Clear,
store_op: wgpu::StoreOp::Store,
- clear_color: wgpu::Color {
- r: 1.0,
- g: 1.0,
- b: 1.0,
- a: 1.0,
+ clear_color: {
+ let [r, g, b, a] = clear_color.into_linear();
+
+ wgpu::Color {
+ r: f64::from(r),
+ g: f64::from(g),
+ b: f64::from(b),
+ a: f64::from(a),
+ }
},
}],
depth_stencil_attachment: None,
@@ -406,6 +413,7 @@ impl Renderer {
impl iced_native::Renderer for Renderer {
type Output = (Primitive, MouseCursor);
+ type Defaults = Defaults;
fn layout<'a, Message>(
&mut self,
@@ -428,24 +436,27 @@ impl Windowed for Renderer {
fn draw<T: AsRef<str>>(
&mut self,
+ clear_color: Color,
output: &Self::Output,
overlay: &[T],
target: &mut Target,
) -> MouseCursor {
- self.draw(output, overlay, target)
+ self.draw(clear_color, output, overlay, target)
}
}
impl Debugger for Renderer {
fn explain<Message>(
&mut self,
+ defaults: &Defaults,
widget: &dyn Widget<Message, Self>,
layout: Layout<'_>,
cursor_position: Point,
color: Color,
) -> Self::Output {
let mut primitives = Vec::new();
- let (primitive, cursor) = widget.draw(self, layout, cursor_position);
+ let (primitive, cursor) =
+ widget.draw(self, defaults, layout, cursor_position);
explain_layout(layout, color, &mut primitives);
primitives.push(primitive);
diff --git a/wgpu/src/renderer/widget.rs b/wgpu/src/renderer/widget.rs
index f82631d5..daf35cbe 100644
--- a/wgpu/src/renderer/widget.rs
+++ b/wgpu/src/renderer/widget.rs
@@ -1,6 +1,7 @@
mod button;
mod checkbox;
mod column;
+mod container;
mod image;
mod radio;
mod row;
diff --git a/wgpu/src/renderer/widget/button.rs b/wgpu/src/renderer/widget/button.rs
index 86963053..4fbd90d7 100644
--- a/wgpu/src/renderer/widget/button.rs
+++ b/wgpu/src/renderer/widget/button.rs
@@ -1,50 +1,67 @@
-use crate::{Primitive, Renderer};
-use iced_native::{button, Background, MouseCursor, Point, Rectangle};
+use crate::{button::StyleSheet, defaults, Defaults, Primitive, Renderer};
+use iced_native::{Background, Element, Layout, MouseCursor, Point, Rectangle};
-impl button::Renderer for Renderer {
- fn draw(
+impl iced_native::button::Renderer for Renderer {
+ type Style = Box<dyn StyleSheet>;
+
+ fn draw<Message>(
&mut self,
+ defaults: &Defaults,
bounds: Rectangle,
cursor_position: Point,
+ is_disabled: bool,
is_pressed: bool,
- background: Option<Background>,
- border_radius: u16,
- (content, _): Self::Output,
+ style: &Box<dyn StyleSheet>,
+ content: &Element<'_, Message, Self>,
+ content_layout: Layout<'_>,
) -> Self::Output {
let is_mouse_over = bounds.contains(cursor_position);
// TODO: Render proper shadows
- // TODO: Make hovering and pressed styles configurable
- let shadow_offset = if is_mouse_over {
+ let styling = if is_disabled {
+ style.disabled()
+ } else if is_mouse_over {
if is_pressed {
- 0.0
+ style.pressed()
} else {
- 2.0
+ style.hovered()
}
} else {
- 1.0
+ style.active()
};
+ let (content, _) = content.draw(
+ self,
+ &Defaults {
+ text: defaults::Text {
+ color: styling.text_color,
+ },
+ ..*defaults
+ },
+ content_layout,
+ cursor_position,
+ );
+
(
- match background {
+ match styling.background {
None => content,
Some(background) => Primitive::Group {
primitives: vec![
Primitive::Quad {
bounds: Rectangle {
x: bounds.x + 1.0,
- y: bounds.y + shadow_offset,
+ y: bounds.y + styling.shadow_offset,
..bounds
},
background: Background::Color(
[0.0, 0.0, 0.0, 0.5].into(),
),
- border_radius,
+ border_radius: styling.border_radius,
},
Primitive::Quad {
bounds,
background,
- border_radius,
+ border_radius: styling.border_radius,
},
content,
],
diff --git a/wgpu/src/renderer/widget/column.rs b/wgpu/src/renderer/widget/column.rs
index 6c31af90..95a7463a 100644
--- a/wgpu/src/renderer/widget/column.rs
+++ b/wgpu/src/renderer/widget/column.rs
@@ -4,6 +4,7 @@ use iced_native::{column, Element, Layout, MouseCursor, Point};
impl column::Renderer for Renderer {
fn draw<Message>(
&mut self,
+ defaults: &Self::Defaults,
content: &[Element<'_, Message, Self>],
layout: Layout<'_>,
cursor_position: Point,
@@ -17,7 +18,7 @@ impl column::Renderer for Renderer {
.zip(layout.children())
.map(|(child, layout)| {
let (primitive, new_mouse_cursor) =
- child.draw(self, layout, cursor_position);
+ child.draw(self, defaults, layout, cursor_position);
if new_mouse_cursor > mouse_cursor {
mouse_cursor = new_mouse_cursor;
diff --git a/wgpu/src/renderer/widget/container.rs b/wgpu/src/renderer/widget/container.rs
new file mode 100644
index 00000000..29c709f8
--- /dev/null
+++ b/wgpu/src/renderer/widget/container.rs
@@ -0,0 +1,46 @@
+use crate::{container, defaults, Defaults, Primitive, Renderer};
+use iced_native::{Element, Layout, Point, Rectangle};
+
+impl iced_native::container::Renderer for Renderer {
+ type Style = Box<dyn container::StyleSheet>;
+
+ fn draw<Message>(
+ &mut self,
+ defaults: &Defaults,
+ bounds: Rectangle,
+ cursor_position: Point,
+ style_sheet: &Self::Style,
+ content: &Element<'_, Message, Self>,
+ content_layout: Layout<'_>,
+ ) -> Self::Output {
+ let style = style_sheet.style();
+
+ let defaults = Defaults {
+ text: defaults::Text {
+ color: style.text_color.unwrap_or(defaults.text.color),
+ },
+ ..*defaults
+ };
+
+ let (content, mouse_cursor) =
+ content.draw(self, &defaults, content_layout, cursor_position);
+
+ match style.background {
+ Some(background) => {
+ let quad = Primitive::Quad {
+ bounds,
+ background,
+ border_radius: style.border_radius,
+ };
+
+ (
+ Primitive::Group {
+ primitives: vec![quad, content],
+ },
+ mouse_cursor,
+ )
+ }
+ None => (content, mouse_cursor),
+ }
+ }
+}
diff --git a/wgpu/src/renderer/widget/row.rs b/wgpu/src/renderer/widget/row.rs
index f082dc61..bd9f1a04 100644
--- a/wgpu/src/renderer/widget/row.rs
+++ b/wgpu/src/renderer/widget/row.rs
@@ -4,6 +4,7 @@ use iced_native::{row, Element, Layout, MouseCursor, Point};
impl row::Renderer for Renderer {
fn draw<Message>(
&mut self,
+ defaults: &Self::Defaults,
children: &[Element<'_, Message, Self>],
layout: Layout<'_>,
cursor_position: Point,
@@ -17,7 +18,7 @@ impl row::Renderer for Renderer {
.zip(layout.children())
.map(|(child, layout)| {
let (primitive, new_mouse_cursor) =
- child.draw(self, layout, cursor_position);
+ child.draw(self, defaults, layout, cursor_position);
if new_mouse_cursor > mouse_cursor {
mouse_cursor = new_mouse_cursor;
diff --git a/wgpu/src/renderer/widget/text.rs b/wgpu/src/renderer/widget/text.rs
index 08a162ba..d61c5523 100644
--- a/wgpu/src/renderer/widget/text.rs
+++ b/wgpu/src/renderer/widget/text.rs
@@ -27,6 +27,7 @@ impl text::Renderer for Renderer {
fn draw(
&mut self,
+ defaults: &Self::Defaults,
bounds: Rectangle,
content: &str,
size: u16,
@@ -40,7 +41,7 @@ impl text::Renderer for Renderer {
content: content.to_string(),
size: f32::from(size),
bounds,
- color: color.unwrap_or(Color::BLACK),
+ color: color.unwrap_or(defaults.text.color),
font,
horizontal_alignment,
vertical_alignment,
diff --git a/wgpu/src/widget.rs b/wgpu/src/widget.rs
new file mode 100644
index 00000000..c6f34301
--- /dev/null
+++ b/wgpu/src/widget.rs
@@ -0,0 +1,2 @@
+pub mod button;
+pub mod container;
diff --git a/wgpu/src/widget/button.rs b/wgpu/src/widget/button.rs
new file mode 100644
index 00000000..2c4e174f
--- /dev/null
+++ b/wgpu/src/widget/button.rs
@@ -0,0 +1,90 @@
+//! Allow your users to perform actions by pressing a button.
+//!
+//! A [`Button`] has some local [`State`].
+//!
+//! [`Button`]: type.Button.html
+//! [`State`]: struct.State.html
+use crate::Renderer;
+use iced_native::{Background, Color};
+
+pub use iced_native::button::State;
+
+/// A widget that produces a message when clicked.
+///
+/// This is an alias of an `iced_native` button with an `iced_wgpu::Renderer`.
+pub type Button<'a, Message> = iced_native::Button<'a, Message, Renderer>;
+
+#[derive(Debug)]
+pub struct Style {
+ pub shadow_offset: f32,
+ pub background: Option<Background>,
+ pub border_radius: u16,
+ pub text_color: Color,
+}
+
+pub trait StyleSheet {
+ fn active(&self) -> Style;
+
+ fn hovered(&self) -> Style {
+ let active = self.active();
+
+ Style {
+ shadow_offset: active.shadow_offset + 1.0,
+ ..active
+ }
+ }
+
+ fn pressed(&self) -> Style {
+ Style {
+ shadow_offset: 0.0,
+ ..self.active()
+ }
+ }
+
+ fn disabled(&self) -> Style {
+ let active = self.active();
+
+ Style {
+ shadow_offset: 0.0,
+ background: active.background.map(|background| match background {
+ Background::Color(color) => Background::Color(Color {
+ a: color.a * 0.5,
+ ..color
+ }),
+ }),
+ text_color: Color {
+ a: active.text_color.a * 0.5,
+ ..active.text_color
+ },
+ ..active
+ }
+ }
+}
+
+struct Default;
+
+impl StyleSheet for Default {
+ fn active(&self) -> Style {
+ Style {
+ shadow_offset: 1.0,
+ background: Some(Background::Color([0.5, 0.5, 0.5].into())),
+ border_radius: 5,
+ text_color: Color::BLACK,
+ }
+ }
+}
+
+impl std::default::Default for Box<dyn StyleSheet> {
+ fn default() -> Self {
+ Box::new(Default)
+ }
+}
+
+impl<T> From<T> for Box<dyn StyleSheet>
+where
+ T: 'static + StyleSheet,
+{
+ fn from(style: T) -> Self {
+ Box::new(style)
+ }
+}
diff --git a/wgpu/src/widget/container.rs b/wgpu/src/widget/container.rs
new file mode 100644
index 00000000..1fc0ec98
--- /dev/null
+++ b/wgpu/src/widget/container.rs
@@ -0,0 +1,37 @@
+use iced_native::{Background, Color};
+
+#[derive(Debug, Clone, Copy)]
+pub struct Style {
+ pub text_color: Option<Color>,
+ pub background: Option<Background>,
+ pub border_radius: u16,
+}
+
+pub trait StyleSheet {
+ fn style(&self) -> Style {
+ Style {
+ text_color: None,
+ background: None,
+ border_radius: 0,
+ }
+ }
+}
+
+struct Default;
+
+impl StyleSheet for Default {}
+
+impl std::default::Default for Box<dyn StyleSheet> {
+ fn default() -> Self {
+ Box::new(Default)
+ }
+}
+
+impl<T> From<T> for Box<dyn StyleSheet>
+where
+ T: 'static + StyleSheet,
+{
+ fn from(style: T) -> Self {
+ Box::new(style)
+ }
+}
diff --git a/winit/src/application.rs b/winit/src/application.rs
index a8612b1a..02fa3780 100644
--- a/winit/src/application.rs
+++ b/winit/src/application.rs
@@ -1,5 +1,5 @@
use crate::{
- conversion,
+ container, conversion,
input::{keyboard, mouse},
renderer::{Target, Windowed},
subscription, Cache, Clipboard, Command, Container, Debug, Element, Event,
@@ -18,7 +18,7 @@ pub trait Application: Sized {
/// The renderer to use to draw the [`Application`].
///
/// [`Application`]: trait.Application.html
- type Renderer: Windowed;
+ type Renderer: Windowed + container::Renderer;
/// The type of __messages__ your [`Application`] will produce.
///
@@ -279,8 +279,12 @@ pub trait Application: Sized {
resized = false;
}
- let new_mouse_cursor =
- renderer.draw(&primitive, &debug.overlay(), &mut target);
+ let new_mouse_cursor = renderer.draw(
+ settings.background,
+ &primitive,
+ &debug.overlay(),
+ &mut target,
+ );
debug.render_finished();
diff --git a/winit/src/settings/mod.rs b/winit/src/settings/mod.rs
index 58e3d879..0384df32 100644
--- a/winit/src/settings/mod.rs
+++ b/winit/src/settings/mod.rs
@@ -1,4 +1,5 @@
//! Configure your application.
+use crate::Color;
#[cfg(target_os = "windows")]
#[path = "windows.rs"]
@@ -10,12 +11,24 @@ mod platform;
pub use platform::PlatformSpecific;
/// The settings of an application.
-#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
+#[derive(Debug, Clone, Copy, PartialEq)]
pub struct Settings {
/// The [`Window`] settings
///
/// [`Window`]: struct.Window.html
pub window: Window,
+
+ /// The default background color of the application
+ pub background: Color,
+}
+
+impl Default for Settings {
+ fn default() -> Settings {
+ Settings {
+ window: Window::default(),
+ background: Color::WHITE,
+ }
+ }
}
/// The window settings of an application.