summaryrefslogtreecommitdiffstats
path: root/wgpu
diff options
context:
space:
mode:
Diffstat (limited to 'wgpu')
-rw-r--r--wgpu/src/image.rs10
-rw-r--r--wgpu/src/lib.rs26
-rw-r--r--wgpu/src/primitive.rs32
-rw-r--r--wgpu/src/quad.rs1
-rw-r--r--wgpu/src/renderer.rs36
-rw-r--r--wgpu/src/renderer/target.rs10
-rw-r--r--wgpu/src/renderer/widget/button.rs52
-rw-r--r--wgpu/src/renderer/widget/checkbox.rs62
-rw-r--r--wgpu/src/renderer/widget/column.rs7
-rw-r--r--wgpu/src/renderer/widget/image.rs29
-rw-r--r--wgpu/src/renderer/widget/radio.rs62
-rw-r--r--wgpu/src/renderer/widget/row.rs7
-rw-r--r--wgpu/src/renderer/widget/scrollable.rs42
-rw-r--r--wgpu/src/renderer/widget/slider.rs35
-rw-r--r--wgpu/src/renderer/widget/text.rs53
-rw-r--r--wgpu/src/renderer/widget/text_input.rs35
-rw-r--r--wgpu/src/text.rs12
17 files changed, 225 insertions, 286 deletions
diff --git a/wgpu/src/image.rs b/wgpu/src/image.rs
index 75cfa166..96c9ab6d 100644
--- a/wgpu/src/image.rs
+++ b/wgpu/src/image.rs
@@ -1,11 +1,9 @@
use crate::Transformation;
use iced_native::Rectangle;
-use std::cell::RefCell;
-use std::collections::HashMap;
-use std::mem;
-use std::rc::Rc;
+use std::{cell::RefCell, collections::HashMap, mem, rc::Rc};
+#[derive(Debug)]
pub struct Pipeline {
cache: RefCell<HashMap<String, Memory>>,
@@ -207,7 +205,8 @@ impl Pipeline {
if !self.cache.borrow().contains_key(path) {
let image = image::open(path).expect("Load image").to_bgra();
- self.cache
+ let _ = self
+ .cache
.borrow_mut()
.insert(path.to_string(), Memory::Host { image });
}
@@ -308,6 +307,7 @@ impl Pipeline {
}
}
+#[derive(Debug)]
enum Memory {
Host {
image: image::ImageBuffer<image::Bgra<u8>, Vec<u8>>,
diff --git a/wgpu/src/lib.rs b/wgpu/src/lib.rs
index d770f872..9f9ed8db 100644
--- a/wgpu/src/lib.rs
+++ b/wgpu/src/lib.rs
@@ -1,3 +1,29 @@
+//! A [`wgpu`] renderer for [`iced_native`].
+//!
+//! ![`iced_wgpu` crate graph](https://github.com/hecrj/iced/blob/cae26cb7bc627f4a5b3bcf1cd023a0c552e8c65e/docs/graphs/wgpu.png?raw=true)
+//!
+//! For now, it is the default renderer of [Iced] in native platforms.
+//!
+//! [`wgpu`] supports most modern graphics backends: Vulkan, Metal, DX11, and
+//! DX12 (OpenGL and WebGL are still WIP). Additionally, it will support the
+//! incoming [WebGPU API].
+//!
+//! Currently, `iced_wgpu` supports the following primitives:
+//! - Text, which is rendered using [`wgpu_glyph`]. No shaping at all.
+//! - Quads or rectangles, with rounded borders and a solid background color.
+//! - Images, lazily loaded from the filesystem.
+//! - Clip areas, useful to implement scrollables or hide overflowing content.
+//!
+//! [Iced]: https://github.com/hecrj/iced
+//! [`iced_native`]: https://github.com/hecrj/iced/tree/master/native
+//! [`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_debug_implementations)]
+#![deny(unused_results)]
+#![deny(unsafe_code)]
+#![deny(rust_2018_idioms)]
mod image;
mod primitive;
mod quad;
diff --git a/wgpu/src/primitive.rs b/wgpu/src/primitive.rs
index b9f1ca6f..9efd74f6 100644
--- a/wgpu/src/primitive.rs
+++ b/wgpu/src/primitive.rs
@@ -1,32 +1,58 @@
-use iced_native::{text, Background, Color, Font, Rectangle, Vector};
+use iced_native::{
+ Background, Color, Font, HorizontalAlignment, Rectangle, Vector,
+ VerticalAlignment,
+};
+/// A rendering primitive.
#[derive(Debug, Clone)]
pub enum Primitive {
+ /// An empty primitive
None,
+ /// A group of primitives
Group {
+ /// The primitives of the group
primitives: Vec<Primitive>,
},
+ /// A text primitive
Text {
+ /// The contents of the text
content: String,
+ /// The bounds of the text
bounds: Rectangle,
+ /// The color of the text
color: Color,
+ /// The size of the text
size: f32,
+ /// The font of the text
font: Font,
- horizontal_alignment: text::HorizontalAlignment,
- vertical_alignment: text::VerticalAlignment,
+ /// The horizontal alignment of the text
+ horizontal_alignment: HorizontalAlignment,
+ /// The vertical alignment of the text
+ vertical_alignment: VerticalAlignment,
},
+ /// A quad primitive
Quad {
+ /// The bounds of the quad
bounds: Rectangle,
+ /// The background of the quad
background: Background,
+ /// The border radius of the quad
border_radius: u16,
},
+ /// An image primitive
Image {
+ /// The path of the image
path: String,
+ /// The bounds of the image
bounds: Rectangle,
},
+ /// A clip primitive
Clip {
+ /// The bounds of the clip
bounds: Rectangle,
+ /// The offset transformation of the clip
offset: Vector<u32>,
+ /// The content of the clip
content: Box<Primitive>,
},
}
diff --git a/wgpu/src/quad.rs b/wgpu/src/quad.rs
index 4356f8af..3d797758 100644
--- a/wgpu/src/quad.rs
+++ b/wgpu/src/quad.rs
@@ -3,6 +3,7 @@ use iced_native::Rectangle;
use std::mem;
+#[derive(Debug)]
pub struct Pipeline {
pipeline: wgpu::RenderPipeline,
constants: wgpu::BindGroup,
diff --git a/wgpu/src/renderer.rs b/wgpu/src/renderer.rs
index 52764248..f27a4b8a 100644
--- a/wgpu/src/renderer.rs
+++ b/wgpu/src/renderer.rs
@@ -1,7 +1,7 @@
use crate::{quad, text, Image, Primitive, Quad, Transformation};
use iced_native::{
- renderer::Debugger, renderer::Windowed, Background, Color, Layout,
- MouseCursor, Point, Rectangle, Vector, Widget,
+ renderer::{Debugger, Windowed},
+ Background, Color, Layout, MouseCursor, Point, Rectangle, Vector, Widget,
};
use wgpu::{
@@ -14,6 +14,10 @@ mod widget;
pub use target::Target;
+/// A [`wgpu`] renderer.
+///
+/// [`wgpu`]: https://github.com/gfx-rs/wgpu-rs
+#[derive(Debug)]
pub struct Renderer {
device: Device,
queue: Queue,
@@ -22,7 +26,7 @@ pub struct Renderer {
text_pipeline: text::Pipeline,
}
-pub struct Layer<'a> {
+struct Layer<'a> {
bounds: Rectangle<u32>,
offset: Vector<u32>,
quads: Vec<Quad>,
@@ -152,21 +156,21 @@ impl Renderer {
vertical_alignment,
} => {
let x = match horizontal_alignment {
- iced_native::text::HorizontalAlignment::Left => bounds.x,
- iced_native::text::HorizontalAlignment::Center => {
+ iced_native::HorizontalAlignment::Left => bounds.x,
+ iced_native::HorizontalAlignment::Center => {
bounds.x + bounds.width / 2.0
}
- iced_native::text::HorizontalAlignment::Right => {
+ iced_native::HorizontalAlignment::Right => {
bounds.x + bounds.width
}
};
let y = match vertical_alignment {
- iced_native::text::VerticalAlignment::Top => bounds.y,
- iced_native::text::VerticalAlignment::Center => {
+ iced_native::VerticalAlignment::Top => bounds.y,
+ iced_native::VerticalAlignment::Center => {
bounds.y + bounds.height / 2.0
}
- iced_native::text::VerticalAlignment::Bottom => {
+ iced_native::VerticalAlignment::Bottom => {
bounds.y + bounds.height
}
};
@@ -183,24 +187,24 @@ impl Renderer {
font_id: self.text_pipeline.find_font(*font),
layout: wgpu_glyph::Layout::default()
.h_align(match horizontal_alignment {
- iced_native::text::HorizontalAlignment::Left => {
+ iced_native::HorizontalAlignment::Left => {
wgpu_glyph::HorizontalAlign::Left
}
- iced_native::text::HorizontalAlignment::Center => {
+ iced_native::HorizontalAlignment::Center => {
wgpu_glyph::HorizontalAlign::Center
}
- iced_native::text::HorizontalAlignment::Right => {
+ iced_native::HorizontalAlignment::Right => {
wgpu_glyph::HorizontalAlign::Right
}
})
.v_align(match vertical_alignment {
- iced_native::text::VerticalAlignment::Top => {
+ iced_native::VerticalAlignment::Top => {
wgpu_glyph::VerticalAlign::Top
}
- iced_native::text::VerticalAlignment::Center => {
+ iced_native::VerticalAlignment::Center => {
wgpu_glyph::VerticalAlign::Center
}
- iced_native::text::VerticalAlignment::Bottom => {
+ iced_native::VerticalAlignment::Bottom => {
wgpu_glyph::VerticalAlign::Bottom
}
}),
@@ -304,7 +308,7 @@ impl Renderer {
&mut self,
dpi: f32,
transformation: Transformation,
- layer: &Layer,
+ layer: &Layer<'_>,
encoder: &mut wgpu::CommandEncoder,
target: &wgpu::TextureView,
) {
diff --git a/wgpu/src/renderer/target.rs b/wgpu/src/renderer/target.rs
index eeeb629a..569f3c62 100644
--- a/wgpu/src/renderer/target.rs
+++ b/wgpu/src/renderer/target.rs
@@ -2,6 +2,8 @@ use crate::{Renderer, Transformation};
use raw_window_handle::HasRawWindowHandle;
+/// A rendering target.
+#[derive(Debug)]
pub struct Target {
surface: wgpu::Surface,
width: u16,
@@ -12,19 +14,19 @@ pub struct Target {
}
impl Target {
- pub fn dimensions(&self) -> (u16, u16) {
+ pub(crate) fn dimensions(&self) -> (u16, u16) {
(self.width, self.height)
}
- pub fn dpi(&self) -> f32 {
+ pub(crate) fn dpi(&self) -> f32 {
self.dpi
}
- pub fn transformation(&self) -> Transformation {
+ pub(crate) fn transformation(&self) -> Transformation {
self.transformation
}
- pub fn next_frame(&mut self) -> wgpu::SwapChainOutput {
+ pub(crate) fn next_frame(&mut self) -> wgpu::SwapChainOutput<'_> {
self.swap_chain.get_next_texture()
}
}
diff --git a/wgpu/src/renderer/widget/button.rs b/wgpu/src/renderer/widget/button.rs
index a19c7d86..86963053 100644
--- a/wgpu/src/renderer/widget/button.rs
+++ b/wgpu/src/renderer/widget/button.rs
@@ -1,52 +1,22 @@
use crate::{Primitive, Renderer};
-use iced_native::{
- button, layout, Background, Button, Layout, Length, MouseCursor, Point,
- Rectangle,
-};
+use iced_native::{button, Background, MouseCursor, Point, Rectangle};
impl button::Renderer for Renderer {
- fn layout<Message>(
- &self,
- button: &Button<Message, Self>,
- limits: &layout::Limits,
- ) -> layout::Node {
- let padding = f32::from(button.padding);
- let limits = limits
- .min_width(button.min_width)
- .width(button.width)
- .height(Length::Shrink)
- .pad(padding);
-
- let mut content = button.content.layout(self, &limits);
-
- content.bounds.x = padding;
- content.bounds.y = padding;
-
- let size = limits.resolve(content.size()).pad(padding);
-
- layout::Node::with_children(size, vec![content])
- }
-
- fn draw<Message>(
+ fn draw(
&mut self,
- button: &Button<Message, Self>,
- layout: Layout<'_>,
+ bounds: Rectangle,
cursor_position: Point,
+ is_pressed: bool,
+ background: Option<Background>,
+ border_radius: u16,
+ (content, _): Self::Output,
) -> Self::Output {
- let bounds = layout.bounds();
-
- let (content, _) = button.content.draw(
- self,
- layout.children().next().unwrap(),
- cursor_position,
- );
-
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 {
- if button.state.is_pressed {
+ if is_pressed {
0.0
} else {
2.0
@@ -56,7 +26,7 @@ impl button::Renderer for Renderer {
};
(
- match button.background {
+ match background {
None => content,
Some(background) => Primitive::Group {
primitives: vec![
@@ -69,12 +39,12 @@ impl button::Renderer for Renderer {
background: Background::Color(
[0.0, 0.0, 0.0, 0.5].into(),
),
- border_radius: button.border_radius,
+ border_radius,
},
Primitive::Quad {
bounds,
background,
- border_radius: button.border_radius,
+ border_radius,
},
content,
],
diff --git a/wgpu/src/renderer/widget/checkbox.rs b/wgpu/src/renderer/widget/checkbox.rs
index aedb821c..54b4b1cc 100644
--- a/wgpu/src/renderer/widget/checkbox.rs
+++ b/wgpu/src/renderer/widget/checkbox.rs
@@ -1,63 +1,35 @@
use crate::{Primitive, Renderer};
use iced_native::{
- checkbox, layout, text, text::HorizontalAlignment, text::VerticalAlignment,
- Align, Background, Checkbox, Column, Layout, Length, MouseCursor, Point,
- Rectangle, Row, Text, Widget,
+ checkbox, Background, HorizontalAlignment, MouseCursor, Rectangle,
+ VerticalAlignment,
};
const SIZE: f32 = 28.0;
impl checkbox::Renderer for Renderer {
- fn layout<Message>(
- &self,
- checkbox: &Checkbox<Message>,
- limits: &layout::Limits,
- ) -> layout::Node {
- Row::<(), Self>::new()
- .spacing(15)
- .align_items(Align::Center)
- .push(
- Column::new()
- .width(Length::Units(SIZE as u16))
- .height(Length::Units(SIZE as u16)),
- )
- .push(Text::new(&checkbox.label))
- .layout(self, limits)
+ fn default_size(&self) -> u32 {
+ SIZE as u32
}
- fn draw<Message>(
+ fn draw(
&mut self,
- checkbox: &Checkbox<Message>,
- layout: Layout<'_>,
- cursor_position: Point,
+ bounds: Rectangle,
+ is_checked: bool,
+ is_mouse_over: bool,
+ (label, _): Self::Output,
) -> Self::Output {
- let bounds = layout.bounds();
- let mut children = layout.children();
-
- let checkbox_layout = children.next().unwrap();
- let label_layout = children.next().unwrap();
- let checkbox_bounds = checkbox_layout.bounds();
-
- let (label, _) = text::Renderer::draw(
- self,
- &Text::new(&checkbox.label),
- label_layout,
- );
-
- let is_mouse_over = bounds.contains(cursor_position);
-
let (checkbox_border, checkbox_box) = (
Primitive::Quad {
- bounds: checkbox_bounds,
+ bounds,
background: Background::Color([0.6, 0.6, 0.6].into()),
border_radius: 6,
},
Primitive::Quad {
bounds: Rectangle {
- x: checkbox_bounds.x + 1.0,
- y: checkbox_bounds.y + 1.0,
- width: checkbox_bounds.width - 2.0,
- height: checkbox_bounds.height - 2.0,
+ x: bounds.x + 1.0,
+ y: bounds.y + 1.0,
+ width: bounds.width - 2.0,
+ height: bounds.height - 2.0,
},
background: Background::Color(
if is_mouse_over {
@@ -73,12 +45,12 @@ impl checkbox::Renderer for Renderer {
(
Primitive::Group {
- primitives: if checkbox.is_checked {
+ primitives: if is_checked {
let check = Primitive::Text {
content: crate::text::CHECKMARK_ICON.to_string(),
font: crate::text::BUILTIN_ICONS,
- size: checkbox_bounds.height * 0.7,
- bounds: checkbox_bounds,
+ size: bounds.height * 0.7,
+ bounds: bounds,
color: [0.3, 0.3, 0.3].into(),
horizontal_alignment: HorizontalAlignment::Center,
vertical_alignment: VerticalAlignment::Center,
diff --git a/wgpu/src/renderer/widget/column.rs b/wgpu/src/renderer/widget/column.rs
index cac6da77..6c31af90 100644
--- a/wgpu/src/renderer/widget/column.rs
+++ b/wgpu/src/renderer/widget/column.rs
@@ -1,10 +1,10 @@
use crate::{Primitive, Renderer};
-use iced_native::{column, Column, Layout, MouseCursor, Point};
+use iced_native::{column, Element, Layout, MouseCursor, Point};
impl column::Renderer for Renderer {
fn draw<Message>(
&mut self,
- column: &Column<'_, Message, Self>,
+ content: &[Element<'_, Message, Self>],
layout: Layout<'_>,
cursor_position: Point,
) -> Self::Output {
@@ -12,8 +12,7 @@ impl column::Renderer for Renderer {
(
Primitive::Group {
- primitives: column
- .children
+ primitives: content
.iter()
.zip(layout.children())
.map(|(child, layout)| {
diff --git a/wgpu/src/renderer/widget/image.rs b/wgpu/src/renderer/widget/image.rs
index 0afb11e3..0006dde1 100644
--- a/wgpu/src/renderer/widget/image.rs
+++ b/wgpu/src/renderer/widget/image.rs
@@ -1,34 +1,15 @@
use crate::{Primitive, Renderer};
-use iced_native::{image, layout, Image, Layout, Length, MouseCursor, Size};
+use iced_native::{image, Layout, MouseCursor};
impl image::Renderer for Renderer {
- fn layout(&self, image: &Image, limits: &layout::Limits) -> layout::Node {
- let (width, height) = self.image_pipeline.dimensions(&image.path);
-
- let aspect_ratio = width as f32 / height as f32;
-
- // TODO: Deal with additional cases
- let (width, height) = match (image.width, image.height) {
- (Length::Units(width), _) => (
- image.width,
- Length::Units((width as f32 / aspect_ratio).round() as u16),
- ),
- (_, _) => {
- (Length::Units(width as u16), Length::Units(height as u16))
- }
- };
-
- let mut size = limits.width(width).height(height).resolve(Size::ZERO);
-
- size.height = size.width / aspect_ratio;
-
- layout::Node::new(size)
+ fn dimensions(&self, path: &str) -> (u32, u32) {
+ self.image_pipeline.dimensions(path)
}
- fn draw(&mut self, image: &Image, layout: Layout<'_>) -> Self::Output {
+ fn draw(&mut self, path: &str, layout: Layout<'_>) -> Self::Output {
(
Primitive::Image {
- path: image.path.clone(),
+ path: String::from(path),
bounds: layout.bounds(),
},
MouseCursor::OutOfBounds,
diff --git a/wgpu/src/renderer/widget/radio.rs b/wgpu/src/renderer/widget/radio.rs
index 1f17ba28..3c00a4c2 100644
--- a/wgpu/src/renderer/widget/radio.rs
+++ b/wgpu/src/renderer/widget/radio.rs
@@ -1,59 +1,33 @@
use crate::{Primitive, Renderer};
-use iced_native::{
- layout, radio, text, Align, Background, Column, Layout, Length,
- MouseCursor, Point, Radio, Rectangle, Row, Text, Widget,
-};
+use iced_native::{radio, Background, MouseCursor, Rectangle};
const SIZE: f32 = 28.0;
const DOT_SIZE: f32 = SIZE / 2.0;
impl radio::Renderer for Renderer {
- fn layout<Message>(
- &self,
- radio: &Radio<Message>,
- limits: &layout::Limits,
- ) -> layout::Node {
- Row::<(), Self>::new()
- .spacing(15)
- .align_items(Align::Center)
- .push(
- Column::new()
- .width(Length::Units(SIZE as u16))
- .height(Length::Units(SIZE as u16)),
- )
- .push(Text::new(&radio.label))
- .layout(self, limits)
+ fn default_size(&self) -> u32 {
+ SIZE as u32
}
- fn draw<Message>(
+ fn draw(
&mut self,
- radio: &Radio<Message>,
- layout: Layout<'_>,
- cursor_position: Point,
+ bounds: Rectangle,
+ is_selected: bool,
+ is_mouse_over: bool,
+ (label, _): Self::Output,
) -> Self::Output {
- let bounds = layout.bounds();
- let mut children = layout.children();
-
- let radio_bounds = children.next().unwrap().bounds();
- let label_layout = children.next().unwrap();
-
- let (label, _) =
- text::Renderer::draw(self, &Text::new(&radio.label), label_layout);
-
- let is_mouse_over = bounds.contains(cursor_position);
-
let (radio_border, radio_box) = (
Primitive::Quad {
- bounds: radio_bounds,
+ bounds,
background: Background::Color([0.6, 0.6, 0.6].into()),
border_radius: (SIZE / 2.0) as u16,
},
Primitive::Quad {
bounds: Rectangle {
- x: radio_bounds.x + 1.0,
- y: radio_bounds.y + 1.0,
- width: radio_bounds.width - 2.0,
- height: radio_bounds.height - 2.0,
+ x: bounds.x + 1.0,
+ y: bounds.y + 1.0,
+ width: bounds.width - 2.0,
+ height: bounds.height - 2.0,
},
background: Background::Color(
if is_mouse_over {
@@ -69,13 +43,13 @@ impl radio::Renderer for Renderer {
(
Primitive::Group {
- primitives: if radio.is_selected {
+ primitives: if is_selected {
let radio_circle = Primitive::Quad {
bounds: Rectangle {
- x: radio_bounds.x + DOT_SIZE / 2.0,
- y: radio_bounds.y + DOT_SIZE / 2.0,
- width: radio_bounds.width - DOT_SIZE,
- height: radio_bounds.height - DOT_SIZE,
+ x: bounds.x + DOT_SIZE / 2.0,
+ y: bounds.y + DOT_SIZE / 2.0,
+ width: bounds.width - DOT_SIZE,
+ height: bounds.height - DOT_SIZE,
},
background: Background::Color([0.3, 0.3, 0.3].into()),
border_radius: (DOT_SIZE / 2.0) as u16,
diff --git a/wgpu/src/renderer/widget/row.rs b/wgpu/src/renderer/widget/row.rs
index bbfef9a1..f082dc61 100644
--- a/wgpu/src/renderer/widget/row.rs
+++ b/wgpu/src/renderer/widget/row.rs
@@ -1,10 +1,10 @@
use crate::{Primitive, Renderer};
-use iced_native::{row, Layout, MouseCursor, Point, Row};
+use iced_native::{row, Element, Layout, MouseCursor, Point};
impl row::Renderer for Renderer {
fn draw<Message>(
&mut self,
- row: &Row<'_, Message, Self>,
+ children: &[Element<'_, Message, Self>],
layout: Layout<'_>,
cursor_position: Point,
) -> Self::Output {
@@ -12,8 +12,7 @@ impl row::Renderer for Renderer {
(
Primitive::Group {
- primitives: row
- .children
+ primitives: children
.iter()
.zip(layout.children())
.map(|(child, layout)| {
diff --git a/wgpu/src/renderer/widget/scrollable.rs b/wgpu/src/renderer/widget/scrollable.rs
index dd6ebcc1..58dc3df9 100644
--- a/wgpu/src/renderer/widget/scrollable.rs
+++ b/wgpu/src/renderer/widget/scrollable.rs
@@ -1,7 +1,6 @@
use crate::{Primitive, Renderer};
use iced_native::{
- scrollable, Background, Layout, MouseCursor, Point, Rectangle, Scrollable,
- Vector, Widget,
+ scrollable, Background, MouseCursor, Point, Rectangle, Vector,
};
const SCROLLBAR_WIDTH: u16 = 10;
@@ -28,33 +27,18 @@ impl scrollable::Renderer for Renderer {
&& scrollbar_bounds(bounds).contains(cursor_position)
}
- fn draw<Message>(
+ fn draw(
&mut self,
- scrollable: &Scrollable<'_, Message, Self>,
+ state: &scrollable::State,
bounds: Rectangle,
- content: Layout<'_>,
- cursor_position: Point,
+ content_bounds: Rectangle,
+ is_mouse_over: bool,
+ is_mouse_over_scrollbar: bool,
+ offset: u32,
+ (content, mouse_cursor): Self::Output,
) -> Self::Output {
- let is_mouse_over = bounds.contains(cursor_position);
- let content_bounds = content.bounds();
-
- let offset = scrollable.state.offset(bounds, content_bounds);
let is_content_overflowing = content_bounds.height > bounds.height;
let scrollbar_bounds = scrollbar_bounds(bounds);
- let is_mouse_over_scrollbar = self.is_mouse_over_scrollbar(
- bounds,
- content_bounds,
- cursor_position,
- );
-
- let cursor_position = if is_mouse_over && !is_mouse_over_scrollbar {
- Point::new(cursor_position.x, cursor_position.y + offset as f32)
- } else {
- Point::new(cursor_position.x, -1.0)
- };
-
- let (content, mouse_cursor) =
- scrollable.content.draw(self, content, cursor_position);
let clip = Primitive::Clip {
bounds,
@@ -64,7 +48,7 @@ impl scrollable::Renderer for Renderer {
(
if is_content_overflowing
- && (is_mouse_over || scrollable.state.is_scrollbar_grabbed())
+ && (is_mouse_over || state.is_scrollbar_grabbed())
{
let ratio = bounds.height / content_bounds.height;
let scrollbar_height = bounds.height * ratio;
@@ -82,9 +66,7 @@ impl scrollable::Renderer for Renderer {
border_radius: 5,
};
- if is_mouse_over_scrollbar
- || scrollable.state.is_scrollbar_grabbed()
- {
+ if is_mouse_over_scrollbar || state.is_scrollbar_grabbed() {
let scrollbar_background = Primitive::Quad {
bounds: Rectangle {
x: scrollbar_bounds.x + f32::from(SCROLLBAR_MARGIN),
@@ -109,9 +91,7 @@ impl scrollable::Renderer for Renderer {
} else {
clip
},
- if is_mouse_over_scrollbar
- || scrollable.state.is_scrollbar_grabbed()
- {
+ if is_mouse_over_scrollbar || state.is_scrollbar_grabbed() {
MouseCursor::Idle
} else {
mouse_cursor
diff --git a/wgpu/src/renderer/widget/slider.rs b/wgpu/src/renderer/widget/slider.rs
index 98065bc9..f561be0a 100644
--- a/wgpu/src/renderer/widget/slider.rs
+++ b/wgpu/src/renderer/widget/slider.rs
@@ -1,32 +1,22 @@
use crate::{Primitive, Renderer};
-use iced_native::{
- layout, slider, Background, Color, Layout, Length, MouseCursor, Point,
- Rectangle, Size, Slider,
-};
+use iced_native::{slider, Background, Color, MouseCursor, Point, Rectangle};
const HANDLE_WIDTH: f32 = 8.0;
const HANDLE_HEIGHT: f32 = 22.0;
impl slider::Renderer for Renderer {
- fn layout<Message>(
- &self,
- slider: &Slider<Message>,
- limits: &layout::Limits,
- ) -> layout::Node {
- let limits = limits.width(slider.width).height(Length::Units(30));
- let size = limits.resolve(Size::ZERO);
-
- layout::Node::new(size)
+ fn height(&self) -> u32 {
+ 30
}
- fn draw<Message>(
+ fn draw(
&mut self,
- slider: &Slider<Message>,
- layout: Layout<'_>,
+ bounds: Rectangle,
cursor_position: Point,
+ range: std::ops::RangeInclusive<f32>,
+ value: f32,
+ is_dragging: bool,
) -> Self::Output {
- let bounds = layout.bounds();
-
let is_mouse_over = bounds.contains(cursor_position);
let rail_y = bounds.y + (bounds.height / 2.0).round();
@@ -54,11 +44,10 @@ impl slider::Renderer for Renderer {
},
);
- let (range_start, range_end) = slider.range.clone().into_inner();
+ let (range_start, range_end) = range.into_inner();
let handle_offset = (bounds.width - HANDLE_WIDTH)
- * ((slider.value - range_start)
- / (range_end - range_start).max(1.0));
+ * ((value - range_start) / (range_end - range_start).max(1.0));
let (handle_border, handle) = (
Primitive::Quad {
@@ -79,7 +68,7 @@ impl slider::Renderer for Renderer {
height: HANDLE_HEIGHT,
},
background: Background::Color(
- if slider.state.is_dragging() {
+ if is_dragging {
[0.85, 0.85, 0.85]
} else if is_mouse_over {
[0.90, 0.90, 0.90]
@@ -96,7 +85,7 @@ impl slider::Renderer for Renderer {
Primitive::Group {
primitives: vec![rail_top, rail_bottom, handle_border, handle],
},
- if slider.state.is_dragging() {
+ if is_dragging {
MouseCursor::Grabbing
} else if is_mouse_over {
MouseCursor::Grab
diff --git a/wgpu/src/renderer/widget/text.rs b/wgpu/src/renderer/widget/text.rs
index a8ead70b..08a162ba 100644
--- a/wgpu/src/renderer/widget/text.rs
+++ b/wgpu/src/renderer/widget/text.rs
@@ -1,5 +1,8 @@
use crate::{Primitive, Renderer};
-use iced_native::{layout, text, Color, Layout, MouseCursor, Size, Text};
+use iced_native::{
+ text, Color, Font, HorizontalAlignment, MouseCursor, Rectangle, Size,
+ VerticalAlignment,
+};
use std::f32;
@@ -7,30 +10,40 @@ use std::f32;
const DEFAULT_TEXT_SIZE: f32 = 20.0;
impl text::Renderer for Renderer {
- fn layout(&self, text: &Text, limits: &layout::Limits) -> layout::Node {
- let limits = limits.width(text.width).height(text.height);
- let size = text.size.map(f32::from).unwrap_or(DEFAULT_TEXT_SIZE);
- let bounds = limits.max();
-
- let (width, height) =
- self.text_pipeline
- .measure(&text.content, size, text.font, bounds);
-
- let size = limits.resolve(Size::new(width, height));
+ fn default_size(&self) -> u16 {
+ DEFAULT_TEXT_SIZE as u16
+ }
- layout::Node::new(size)
+ fn measure(
+ &self,
+ content: &str,
+ size: u16,
+ font: Font,
+ bounds: Size,
+ ) -> (f32, f32) {
+ self.text_pipeline
+ .measure(content, f32::from(size), font, bounds)
}
- fn draw(&mut self, text: &Text, layout: Layout<'_>) -> Self::Output {
+ fn draw(
+ &mut self,
+ bounds: Rectangle,
+ content: &str,
+ size: u16,
+ font: Font,
+ color: Option<Color>,
+ horizontal_alignment: HorizontalAlignment,
+ vertical_alignment: VerticalAlignment,
+ ) -> Self::Output {
(
Primitive::Text {
- content: text.content.clone(),
- size: text.size.map(f32::from).unwrap_or(DEFAULT_TEXT_SIZE),
- bounds: layout.bounds(),
- color: text.color.unwrap_or(Color::BLACK),
- font: text.font,
- horizontal_alignment: text.horizontal_alignment,
- vertical_alignment: text.vertical_alignment,
+ content: content.to_string(),
+ size: f32::from(size),
+ bounds,
+ color: color.unwrap_or(Color::BLACK),
+ font,
+ horizontal_alignment,
+ vertical_alignment,
},
MouseCursor::OutOfBounds,
)
diff --git a/wgpu/src/renderer/widget/text_input.rs b/wgpu/src/renderer/widget/text_input.rs
index 855e945c..9ed3b415 100644
--- a/wgpu/src/renderer/widget/text_input.rs
+++ b/wgpu/src/renderer/widget/text_input.rs
@@ -1,8 +1,8 @@
use crate::{Primitive, Renderer};
use iced_native::{
- text::HorizontalAlignment, text::VerticalAlignment, text_input, Background,
- Color, Font, MouseCursor, Point, Rectangle, Size, TextInput, Vector,
+ text_input, Background, Color, Font, HorizontalAlignment, MouseCursor,
+ Point, Rectangle, Size, Vector, VerticalAlignment,
};
use std::f32;
@@ -12,19 +12,22 @@ impl text_input::Renderer for Renderer {
20
}
- fn draw<Message>(
+ fn draw(
&mut self,
- text_input: &TextInput<Message>,
bounds: Rectangle,
text_bounds: Rectangle,
cursor_position: Point,
+ size: u16,
+ placeholder: &str,
+ value: &text_input::Value,
+ state: &text_input::State,
) -> Self::Output {
let is_mouse_over = bounds.contains(cursor_position);
let border = Primitive::Quad {
bounds,
background: Background::Color(
- if is_mouse_over || text_input.state.is_focused {
+ if is_mouse_over || state.is_focused() {
[0.5, 0.5, 0.5]
} else {
[0.7, 0.7, 0.7]
@@ -45,12 +48,12 @@ impl text_input::Renderer for Renderer {
border_radius: 5,
};
- let size = f32::from(text_input.size.unwrap_or(self.default_size()));
- let text = text_input.value.to_string();
+ let size = f32::from(size);
+ let text = value.to_string();
- let value = Primitive::Text {
+ let text_value = Primitive::Text {
content: if text.is_empty() {
- text_input.placeholder.clone()
+ placeholder.to_string()
} else {
text.clone()
},
@@ -70,14 +73,12 @@ impl text_input::Renderer for Renderer {
vertical_alignment: VerticalAlignment::Center,
};
- let (contents_primitive, offset) = if text_input.state.is_focused {
- let text_before_cursor = &text_input
- .value
- .until(text_input.state.cursor_position(&text_input.value))
- .to_string();
+ let (contents_primitive, offset) = if state.is_focused() {
+ let text_before_cursor =
+ value.until(state.cursor_position(value)).to_string();
let (mut text_value_width, _) = self.text_pipeline.measure(
- text_before_cursor,
+ &text_before_cursor,
size,
Font::Default,
Size::new(f32::INFINITY, text_bounds.height),
@@ -104,7 +105,7 @@ impl text_input::Renderer for Renderer {
(
Primitive::Group {
- primitives: vec![value, cursor],
+ primitives: vec![text_value, cursor],
},
Vector::new(
((text_value_width + 5.0) - text_bounds.width).max(0.0)
@@ -113,7 +114,7 @@ impl text_input::Renderer for Renderer {
),
)
} else {
- (value, Vector::new(0, 0))
+ (text_value, Vector::new(0, 0))
};
let contents = Primitive::Clip {
diff --git a/wgpu/src/text.rs b/wgpu/src/text.rs
index da070f5c..bf37abe5 100644
--- a/wgpu/src/text.rs
+++ b/wgpu/src/text.rs
@@ -2,8 +2,7 @@ mod font;
use crate::Transformation;
-use std::cell::RefCell;
-use std::collections::HashMap;
+use std::{cell::RefCell, collections::HashMap};
pub const BUILTIN_ICONS: iced_native::Font = iced_native::Font::External {
name: "iced_wgpu icons",
@@ -12,6 +11,7 @@ pub const BUILTIN_ICONS: iced_native::Font = iced_native::Font::External {
pub const CHECKMARK_ICON: char = '\u{F00C}';
+#[derive(Debug)]
pub struct Pipeline {
draw_brush: RefCell<wgpu_glyph::GlyphBrush<'static, ()>>,
draw_font_map: RefCell<HashMap<String, wgpu_glyph::FontId>>,
@@ -56,7 +56,7 @@ impl Pipeline {
wgpu_glyph::FontId(0)
}
- pub fn queue(&mut self, section: wgpu_glyph::Section) {
+ pub fn queue(&mut self, section: wgpu_glyph::Section<'_>) {
self.draw_brush.borrow_mut().queue(section);
}
@@ -134,7 +134,8 @@ impl Pipeline {
// it uses a lifetimed `GlyphCalculatorGuard` with side-effects on drop.
// This makes stuff quite inconvenient. A manual method for trimming the
// cache would make our lives easier.
- self.measure_brush
+ let _ = self
+ .measure_brush
.borrow_mut()
.process_queued(|_, _| {}, |_| {})
.expect("Trim text measurements");
@@ -154,7 +155,8 @@ impl Pipeline {
let font_id =
self.draw_brush.borrow_mut().add_font_bytes(bytes);
- self.draw_font_map
+ let _ = self
+ .draw_font_map
.borrow_mut()
.insert(String::from(name), font_id);