From 719c073fc67c87d6b2da1bc01b74751d3f5e59f0 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Fri, 25 Oct 2019 03:47:34 +0200 Subject: Draft `Scrollable` widget (no clipping yet!) --- wgpu/src/renderer/scrollable.rs | 70 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 wgpu/src/renderer/scrollable.rs (limited to 'wgpu/src/renderer/scrollable.rs') diff --git a/wgpu/src/renderer/scrollable.rs b/wgpu/src/renderer/scrollable.rs new file mode 100644 index 00000000..14ff9ff4 --- /dev/null +++ b/wgpu/src/renderer/scrollable.rs @@ -0,0 +1,70 @@ +use crate::{Primitive, Renderer}; +use iced_native::{ + scrollable, Background, Color, Layout, Point, Rectangle, Scrollable, Widget, +}; + +impl scrollable::Renderer for Renderer { + fn draw( + &mut self, + scrollable: &Scrollable<'_, Message, Self>, + layout: Layout<'_>, + cursor_position: Point, + ) -> Self::Output { + let bounds = layout.bounds(); + let is_mouse_over = bounds.contains(cursor_position); + + let content = layout.children().next().unwrap(); + let content_bounds = content.bounds(); + + let cursor_position = if bounds.contains(cursor_position) { + Point::new( + cursor_position.x, + cursor_position.y + scrollable.state.offset as f32, + ) + } else { + Point::new(cursor_position.x, -1.0) + }; + + let (content, mouse_cursor) = + scrollable.content.draw(self, content, cursor_position); + + let primitive = Primitive::Scrollable { + bounds, + offset: scrollable.state.offset, + content: Box::new(content), + }; + + ( + Primitive::Group { + primitives: if is_mouse_over + && content_bounds.height > bounds.height + { + let ratio = bounds.height / content_bounds.height; + let scrollbar_height = bounds.height * ratio; + let y_offset = scrollable.state.offset as f32 * ratio; + + let scrollbar = Primitive::Quad { + bounds: Rectangle { + x: bounds.x + bounds.width - 12.0, + y: bounds.y + y_offset, + width: 10.0, + height: scrollbar_height, + }, + background: Background::Color(Color { + r: 0.0, + g: 0.0, + b: 0.0, + a: 0.5, + }), + border_radius: 5, + }; + + vec![primitive, scrollbar] + } else { + vec![primitive] + }, + }, + mouse_cursor, + ) + } +} -- cgit From 09bd2c46c06eba72da40852d82a52e7353cc9e9b Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Sun, 27 Oct 2019 01:24:08 +0200 Subject: Expose scrollable offset properly --- wgpu/src/renderer/scrollable.rs | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'wgpu/src/renderer/scrollable.rs') diff --git a/wgpu/src/renderer/scrollable.rs b/wgpu/src/renderer/scrollable.rs index 14ff9ff4..5b93a765 100644 --- a/wgpu/src/renderer/scrollable.rs +++ b/wgpu/src/renderer/scrollable.rs @@ -16,11 +16,10 @@ impl scrollable::Renderer for Renderer { let content = layout.children().next().unwrap(); let content_bounds = content.bounds(); + let offset = scrollable.state.offset(bounds, content_bounds); + let cursor_position = if bounds.contains(cursor_position) { - Point::new( - cursor_position.x, - cursor_position.y + scrollable.state.offset as f32, - ) + Point::new(cursor_position.x, cursor_position.y + offset as f32) } else { Point::new(cursor_position.x, -1.0) }; @@ -30,7 +29,7 @@ impl scrollable::Renderer for Renderer { let primitive = Primitive::Scrollable { bounds, - offset: scrollable.state.offset, + offset, content: Box::new(content), }; @@ -41,7 +40,7 @@ impl scrollable::Renderer for Renderer { { let ratio = bounds.height / content_bounds.height; let scrollbar_height = bounds.height * ratio; - let y_offset = scrollable.state.offset as f32 * ratio; + let y_offset = offset as f32 * ratio; let scrollbar = Primitive::Quad { bounds: Rectangle { -- cgit From be488ac73837c9a741d900617840ee5c4ed74d61 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Tue, 29 Oct 2019 02:00:17 +0100 Subject: Draw scrollbar on top of scrollable content --- wgpu/src/renderer/scrollable.rs | 51 +++++++++++++++++++---------------------- 1 file changed, 24 insertions(+), 27 deletions(-) (limited to 'wgpu/src/renderer/scrollable.rs') diff --git a/wgpu/src/renderer/scrollable.rs b/wgpu/src/renderer/scrollable.rs index 5b93a765..43dddeed 100644 --- a/wgpu/src/renderer/scrollable.rs +++ b/wgpu/src/renderer/scrollable.rs @@ -34,34 +34,31 @@ impl scrollable::Renderer for Renderer { }; ( - Primitive::Group { - primitives: if is_mouse_over - && content_bounds.height > bounds.height - { - let ratio = bounds.height / content_bounds.height; - let scrollbar_height = bounds.height * ratio; - let y_offset = offset as f32 * ratio; + if is_mouse_over && content_bounds.height > bounds.height { + let ratio = bounds.height / content_bounds.height; + let scrollbar_height = bounds.height * ratio; + let y_offset = offset as f32 * ratio; - let scrollbar = Primitive::Quad { - bounds: Rectangle { - x: bounds.x + bounds.width - 12.0, - y: bounds.y + y_offset, - width: 10.0, - height: scrollbar_height, - }, - background: Background::Color(Color { - r: 0.0, - g: 0.0, - b: 0.0, - a: 0.5, - }), - border_radius: 5, - }; - - vec![primitive, scrollbar] - } else { - vec![primitive] - }, + let scrollbar = Primitive::Quad { + bounds: Rectangle { + x: bounds.x + bounds.width - 12.0, + y: bounds.y + y_offset, + width: 10.0, + height: scrollbar_height, + }, + background: Background::Color(Color { + r: 0.0, + g: 0.0, + b: 0.0, + a: 0.7, + }), + border_radius: 5, + }; + Primitive::Group { + primitives: vec![primitive, scrollbar], + } + } else { + primitive }, mouse_cursor, ) -- cgit From a3c55f75174f9bc87f80d7fe6236a71138d2fd77 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Tue, 29 Oct 2019 02:13:22 +0100 Subject: Stop leaking impl details in scrollable `Renderer` --- wgpu/src/renderer/scrollable.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'wgpu/src/renderer/scrollable.rs') diff --git a/wgpu/src/renderer/scrollable.rs b/wgpu/src/renderer/scrollable.rs index 43dddeed..1327e577 100644 --- a/wgpu/src/renderer/scrollable.rs +++ b/wgpu/src/renderer/scrollable.rs @@ -7,13 +7,11 @@ impl scrollable::Renderer for Renderer { fn draw( &mut self, scrollable: &Scrollable<'_, Message, Self>, - layout: Layout<'_>, + bounds: Rectangle, + content: Layout<'_>, cursor_position: Point, ) -> Self::Output { - let bounds = layout.bounds(); let is_mouse_over = bounds.contains(cursor_position); - - let content = layout.children().next().unwrap(); let content_bounds = content.bounds(); let offset = scrollable.state.offset(bounds, content_bounds); -- cgit From 29588f604af66fb4911f791c0c402fccd30ba64b Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Tue, 29 Oct 2019 05:09:54 +0100 Subject: Implement scrollbar interactions! :tada: --- wgpu/src/renderer/scrollable.rs | 87 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 78 insertions(+), 9 deletions(-) (limited to 'wgpu/src/renderer/scrollable.rs') diff --git a/wgpu/src/renderer/scrollable.rs b/wgpu/src/renderer/scrollable.rs index 1327e577..7f8a7db6 100644 --- a/wgpu/src/renderer/scrollable.rs +++ b/wgpu/src/renderer/scrollable.rs @@ -1,9 +1,33 @@ use crate::{Primitive, Renderer}; use iced_native::{ - scrollable, Background, Color, Layout, Point, Rectangle, Scrollable, Widget, + scrollable, Background, Color, Layout, MouseCursor, Point, Rectangle, + Scrollable, Widget, }; +const SCROLLBAR_WIDTH: u16 = 10; +const SCROLLBAR_MARGIN: u16 = 10; + +fn scrollbar_bounds(bounds: Rectangle) -> Rectangle { + Rectangle { + x: bounds.x + bounds.width + - f32::from(SCROLLBAR_WIDTH + 2 * SCROLLBAR_MARGIN), + y: bounds.y, + width: f32::from(SCROLLBAR_WIDTH + 2 * SCROLLBAR_MARGIN), + height: bounds.height, + } +} + impl scrollable::Renderer for Renderer { + fn is_mouse_over_scrollbar( + &self, + bounds: Rectangle, + content_bounds: Rectangle, + cursor_position: Point, + ) -> bool { + content_bounds.height > bounds.height + && scrollbar_bounds(bounds).contains(cursor_position) + } + fn draw( &mut self, scrollable: &Scrollable<'_, Message, Self>, @@ -15,8 +39,15 @@ impl scrollable::Renderer for Renderer { 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 bounds.contains(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) @@ -32,16 +63,19 @@ impl scrollable::Renderer for Renderer { }; ( - if is_mouse_over && content_bounds.height > bounds.height { + if is_content_overflowing + && (is_mouse_over || scrollable.state.is_scrollbar_grabbed()) + { let ratio = bounds.height / content_bounds.height; let scrollbar_height = bounds.height * ratio; let y_offset = offset as f32 * ratio; let scrollbar = Primitive::Quad { bounds: Rectangle { - x: bounds.x + bounds.width - 12.0, - y: bounds.y + y_offset, - width: 10.0, + x: scrollbar_bounds.x + f32::from(SCROLLBAR_MARGIN), + y: scrollbar_bounds.y + y_offset, + width: scrollbar_bounds.width + - f32::from(2 * SCROLLBAR_MARGIN), height: scrollbar_height, }, background: Background::Color(Color { @@ -52,13 +86,48 @@ impl scrollable::Renderer for Renderer { }), border_radius: 5, }; - Primitive::Group { - primitives: vec![primitive, scrollbar], + + if is_mouse_over_scrollbar + || scrollable.state.is_scrollbar_grabbed() + { + let scrollbar_background = Primitive::Quad { + bounds: Rectangle { + x: scrollbar_bounds.x + f32::from(SCROLLBAR_MARGIN), + width: scrollbar_bounds.width + - f32::from(2 * SCROLLBAR_MARGIN), + ..scrollbar_bounds + }, + background: Background::Color(Color { + r: 0.0, + g: 0.0, + b: 0.0, + a: 0.3, + }), + border_radius: 5, + }; + + Primitive::Group { + primitives: vec![ + primitive, + scrollbar_background, + scrollbar, + ], + } + } else { + Primitive::Group { + primitives: vec![primitive, scrollbar], + } } } else { primitive }, - mouse_cursor, + if is_mouse_over_scrollbar + || scrollable.state.is_scrollbar_grabbed() + { + MouseCursor::Idle + } else { + mouse_cursor + }, ) } } -- cgit From 85916c9e8710ee90cbf37d384acbb6d208ff1da3 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Tue, 29 Oct 2019 19:50:34 +0100 Subject: Rename `Primitive::Scrollable` to `Clip` --- wgpu/src/renderer/scrollable.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'wgpu/src/renderer/scrollable.rs') diff --git a/wgpu/src/renderer/scrollable.rs b/wgpu/src/renderer/scrollable.rs index 7f8a7db6..7bce3a68 100644 --- a/wgpu/src/renderer/scrollable.rs +++ b/wgpu/src/renderer/scrollable.rs @@ -56,7 +56,7 @@ impl scrollable::Renderer for Renderer { let (content, mouse_cursor) = scrollable.content.draw(self, content, cursor_position); - let primitive = Primitive::Scrollable { + let primitive = Primitive::Clip { bounds, offset, content: Box::new(content), -- cgit From 58d04cadef020412375f2adc5fd96bfa10ec4692 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Sat, 2 Nov 2019 01:42:51 +0100 Subject: Add scrollable section to `tour` --- wgpu/src/renderer/scrollable.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'wgpu/src/renderer/scrollable.rs') diff --git a/wgpu/src/renderer/scrollable.rs b/wgpu/src/renderer/scrollable.rs index 7bce3a68..e812a7e1 100644 --- a/wgpu/src/renderer/scrollable.rs +++ b/wgpu/src/renderer/scrollable.rs @@ -5,7 +5,7 @@ use iced_native::{ }; const SCROLLBAR_WIDTH: u16 = 10; -const SCROLLBAR_MARGIN: u16 = 10; +const SCROLLBAR_MARGIN: u16 = 2; fn scrollbar_bounds(bounds: Rectangle) -> Rectangle { Rectangle { -- cgit