From 5eec3a8867f4fbd54e2e28e5d984c2ca7ec0fea4 Mon Sep 17 00:00:00 2001 From: Friz64 Date: Mon, 25 Nov 2019 20:27:15 +0100 Subject: First implementation --- examples/tour.rs | 2 +- native/src/renderer/null.rs | 9 ++-- native/src/widget.rs | 2 +- native/src/widget/scrollable.rs | 73 ++++++++++++++++++++--------- wgpu/src/renderer/widget/scrollable.rs | 84 ++++++++++++++++++++++++---------- 5 files changed, 119 insertions(+), 51 deletions(-) diff --git a/examples/tour.rs b/examples/tour.rs index 0121c3bd..6b366957 100644 --- a/examples/tour.rs +++ b/examples/tour.rs @@ -145,7 +145,7 @@ impl Steps { Step::Debugger, Step::End, ], - current: 0, + current: 6, } } diff --git a/native/src/renderer/null.rs b/native/src/renderer/null.rs index 182f033a..c8852ad1 100644 --- a/native/src/renderer/null.rs +++ b/native/src/renderer/null.rs @@ -1,7 +1,7 @@ use crate::{ button, checkbox, column, radio, row, scrollable, text, text_input, Background, Color, Element, Font, HorizontalAlignment, Layout, Point, - Rectangle, Renderer, Size, VerticalAlignment, + Rectangle, Renderer, ScrollbarGrab, Size, VerticalAlignment, }; /// A renderer that does nothing. @@ -61,13 +61,14 @@ impl text::Renderer for Null { } impl scrollable::Renderer for Null { - fn is_mouse_over_scrollbar( + fn scrollbar_grab( &self, _bounds: Rectangle, _content_bounds: Rectangle, + _offset: u32, _cursor_position: Point, - ) -> bool { - false + ) -> Option { + None } fn draw( diff --git a/native/src/widget.rs b/native/src/widget.rs index 71dcdc0d..a2d3aa12 100644 --- a/native/src/widget.rs +++ b/native/src/widget.rs @@ -47,7 +47,7 @@ pub use radio::Radio; #[doc(no_inline)] pub use row::Row; #[doc(no_inline)] -pub use scrollable::Scrollable; +pub use scrollable::{Scrollable, ScrollbarGrab}; #[doc(no_inline)] pub use slider::Slider; #[doc(no_inline)] diff --git a/native/src/widget/scrollable.rs b/native/src/widget/scrollable.rs index 678d837a..fed7f54e 100644 --- a/native/src/widget/scrollable.rs +++ b/native/src/widget/scrollable.rs @@ -150,9 +150,11 @@ where let content = layout.children().next().unwrap(); let content_bounds = content.bounds(); - let is_mouse_over_scrollbar = renderer.is_mouse_over_scrollbar( + let offset = self.state.offset(bounds, content_bounds); + let scrollbar_grab = renderer.scrollbar_grab( bounds, content_bounds, + offset, cursor_position, ); @@ -174,25 +176,45 @@ where } } - if self.state.is_scrollbar_grabbed() || is_mouse_over_scrollbar { + if self.state.currently_grabbed() || scrollbar_grab.is_some() { match event { Event::Mouse(mouse::Event::Input { button: mouse::Button::Left, state, }) => match state { ButtonState::Pressed => { - self.state.scroll_to( - cursor_position.y / (bounds.y + bounds.height), + let (scrollbar_grab, scroller_bounds) = + scrollbar_grab.unwrap(); + + let scroller_grabbed_at = match scrollbar_grab { + ScrollbarGrab::Background => 0.5, + ScrollbarGrab::Scroller => { + (cursor_position.y - scroller_bounds.y) + / scroller_bounds.height + } + }; + + let scroll_percentage = (cursor_position.y + - (scroller_bounds.height * scroller_grabbed_at)) + / (bounds.height + - (scroller_bounds.height + * scroller_grabbed_at)); + + dbg!((scroll_percentage, scroller_grabbed_at)); + /*self.state.scroll_to( + scroll_percentage, bounds, content_bounds, - ); + );*/ - self.state.scrollbar_grabbed_at = Some(cursor_position); + self.state.scroller_grabbed_at = + Some(scroller_grabbed_at); } ButtonState::Released => { - self.state.scrollbar_grabbed_at = None; + self.state.scroller_grabbed_at = None; } }, + /* TODO: Implement dragging to scroll Event::Mouse(mouse::Event::CursorMoved { .. }) => { if let Some(scrollbar_grabbed_at) = self.state.scrollbar_grabbed_at @@ -209,13 +231,13 @@ where self.state.scrollbar_grabbed_at = Some(cursor_position); } } + */ _ => {} } } let cursor_position = if is_mouse_over - && !(is_mouse_over_scrollbar - || self.state.scrollbar_grabbed_at.is_some()) + && !(scrollbar_grab.is_some() || self.state.currently_grabbed()) { Point::new( cursor_position.x, @@ -251,11 +273,9 @@ where let offset = self.state.offset(bounds, content_bounds); let is_mouse_over = bounds.contains(cursor_position); - let is_mouse_over_scrollbar = renderer.is_mouse_over_scrollbar( - bounds, - content_bounds, - cursor_position, - ); + let is_mouse_over_scrollbar = renderer + .scrollbar_grab(bounds, content_bounds, offset, cursor_position) + .is_some(); let content = { let cursor_position = if is_mouse_over && !is_mouse_over_scrollbar { @@ -294,7 +314,7 @@ where /// [`Scrollable`]: struct.Scrollable.html #[derive(Debug, Clone, Copy, Default)] pub struct State { - scrollbar_grabbed_at: Option, + scroller_grabbed_at: Option, offset: f32, } @@ -357,11 +377,20 @@ impl State { } /// Returns whether the scrollbar is currently grabbed or not. - pub fn is_scrollbar_grabbed(&self) -> bool { - self.scrollbar_grabbed_at.is_some() + pub fn currently_grabbed(&self) -> bool { + self.scroller_grabbed_at.is_some() } } +#[derive(Debug, Clone, Copy)] +/// What the mouse is grabbing on the scrollbar +pub enum ScrollbarGrab { + /// The mouse is grabbing the background + Background, + /// The mouse is grabbing the scroller + Scroller, +} + /// The renderer of a [`Scrollable`]. /// /// Your [renderer] will need to implement this trait before being @@ -370,16 +399,18 @@ impl State { /// [`Scrollable`]: struct.Scrollable.html /// [renderer]: ../../renderer/index.html pub trait Renderer: crate::Renderer + Sized { - /// Returns whether the mouse is over the scrollbar given the bounds of - /// the [`Scrollable`] and its contents. + /// Returns what part of the scrollbar is being grabbed by the mouse + /// given the bounds of the [`Scrollable`] and its contents together + /// with the current scroller bounds. /// /// [`Scrollable`]: struct.Scrollable.html - fn is_mouse_over_scrollbar( + fn scrollbar_grab( &self, bounds: Rectangle, content_bounds: Rectangle, + offset: u32, cursor_position: Point, - ) -> bool; + ) -> Option<(ScrollbarGrab, Rectangle)>; /// Draws the [`Scrollable`]. /// diff --git a/wgpu/src/renderer/widget/scrollable.rs b/wgpu/src/renderer/widget/scrollable.rs index 58dc3df9..d069b799 100644 --- a/wgpu/src/renderer/widget/scrollable.rs +++ b/wgpu/src/renderer/widget/scrollable.rs @@ -1,12 +1,13 @@ use crate::{Primitive, Renderer}; use iced_native::{ - scrollable, Background, MouseCursor, Point, Rectangle, Vector, + scrollable, Background, MouseCursor, Point, Rectangle, ScrollbarGrab, + Vector, }; const SCROLLBAR_WIDTH: u16 = 10; const SCROLLBAR_MARGIN: u16 = 2; -fn scrollbar_bounds(bounds: Rectangle) -> Rectangle { +fn background_bounds(bounds: Rectangle) -> Rectangle { Rectangle { x: bounds.x + bounds.width - f32::from(SCROLLBAR_WIDTH + 2 * SCROLLBAR_MARGIN), @@ -16,15 +17,53 @@ fn scrollbar_bounds(bounds: Rectangle) -> Rectangle { } } +fn scroller_bounds( + bounds: Rectangle, + content_bounds: Rectangle, + background_bounds: Rectangle, + offset: u32, +) -> Rectangle { + let ratio = bounds.height / content_bounds.height; + let scrollbar_height = bounds.height * ratio; + let y_offset = offset as f32 * ratio; + + Rectangle { + x: background_bounds.x + f32::from(SCROLLBAR_MARGIN), + y: background_bounds.y + y_offset, + width: background_bounds.width - f32::from(2 * SCROLLBAR_MARGIN), + height: scrollbar_height, + } +} + impl scrollable::Renderer for Renderer { - fn is_mouse_over_scrollbar( + fn scrollbar_grab( &self, bounds: Rectangle, content_bounds: Rectangle, + offset: u32, cursor_position: Point, - ) -> bool { - content_bounds.height > bounds.height - && scrollbar_bounds(bounds).contains(cursor_position) + ) -> Option<(ScrollbarGrab, Rectangle)> { + let background_bounds = background_bounds(bounds); + if content_bounds.height > bounds.height + && background_bounds.contains(cursor_position) + { + let scroller_bounds = scroller_bounds( + bounds, + content_bounds, + background_bounds, + offset, + ); + + let scrollbar_grab = if scroller_bounds.contains(cursor_position) { + ScrollbarGrab::Scroller + } else { + ScrollbarGrab::Background + }; + + Some((scrollbar_grab, scroller_bounds)) + } else { + None + } } fn draw( @@ -38,7 +77,7 @@ impl scrollable::Renderer for Renderer { (content, mouse_cursor): Self::Output, ) -> Self::Output { let is_content_overflowing = content_bounds.height > bounds.height; - let scrollbar_bounds = scrollbar_bounds(bounds); + let background_bounds = background_bounds(bounds); let clip = Primitive::Clip { bounds, @@ -48,31 +87,28 @@ impl scrollable::Renderer for Renderer { ( if is_content_overflowing - && (is_mouse_over || state.is_scrollbar_grabbed()) + && (is_mouse_over || state.currently_grabbed()) { - let ratio = bounds.height / content_bounds.height; - let scrollbar_height = bounds.height * ratio; - let y_offset = offset as f32 * ratio; - + let scroller_bounds = scroller_bounds( + bounds, + content_bounds, + background_bounds, + offset, + ); let scrollbar = Primitive::Quad { - bounds: Rectangle { - 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, - }, + bounds: scroller_bounds, background: Background::Color([0.0, 0.0, 0.0, 0.7].into()), border_radius: 5, }; - if is_mouse_over_scrollbar || state.is_scrollbar_grabbed() { + if is_mouse_over_scrollbar || state.currently_grabbed() { let scrollbar_background = Primitive::Quad { bounds: Rectangle { - x: scrollbar_bounds.x + f32::from(SCROLLBAR_MARGIN), - width: scrollbar_bounds.width + x: background_bounds.x + + f32::from(SCROLLBAR_MARGIN), + width: background_bounds.width - f32::from(2 * SCROLLBAR_MARGIN), - ..scrollbar_bounds + ..background_bounds }, background: Background::Color( [0.0, 0.0, 0.0, 0.3].into(), @@ -91,7 +127,7 @@ impl scrollable::Renderer for Renderer { } else { clip }, - if is_mouse_over_scrollbar || state.is_scrollbar_grabbed() { + if is_mouse_over_scrollbar || state.currently_grabbed() { MouseCursor::Idle } else { mouse_cursor -- cgit From f8fac432c665e57267243a9ee3920208b2724e6e Mon Sep 17 00:00:00 2001 From: Friz64 Date: Sat, 30 Nov 2019 17:30:42 +0100 Subject: Finalize work --- examples/tour.rs | 2 +- native/src/widget/scrollable.rs | 69 ++++++++++++++++++++-------------- wgpu/src/renderer/widget/scrollable.rs | 32 +++++++++------- 3 files changed, 60 insertions(+), 43 deletions(-) diff --git a/examples/tour.rs b/examples/tour.rs index 6b366957..0121c3bd 100644 --- a/examples/tour.rs +++ b/examples/tour.rs @@ -145,7 +145,7 @@ impl Steps { Step::Debugger, Step::End, ], - current: 6, + current: 0, } } diff --git a/native/src/widget/scrollable.rs b/native/src/widget/scrollable.rs index fed7f54e..17a1363e 100644 --- a/native/src/widget/scrollable.rs +++ b/native/src/widget/scrollable.rs @@ -151,10 +151,13 @@ where let content_bounds = content.bounds(); let offset = self.state.offset(bounds, content_bounds); + let (background_bounds, scroller_bounds) = + renderer.scrollbar_bounds(bounds, content_bounds, offset); let scrollbar_grab = renderer.scrollbar_grab( bounds, content_bounds, - offset, + background_bounds, + scroller_bounds, cursor_position, ); @@ -183,10 +186,8 @@ where state, }) => match state { ButtonState::Pressed => { - let (scrollbar_grab, scroller_bounds) = - scrollbar_grab.unwrap(); - - let scroller_grabbed_at = match scrollbar_grab { + let scroller_grabbed_at = match scrollbar_grab.unwrap() + { ScrollbarGrab::Background => 0.5, ScrollbarGrab::Scroller => { (cursor_position.y - scroller_bounds.y) @@ -194,18 +195,15 @@ where } }; - let scroll_percentage = (cursor_position.y - - (scroller_bounds.height * scroller_grabbed_at)) - / (bounds.height - - (scroller_bounds.height - * scroller_grabbed_at)); + let scroll_percentage = (cursor_position.y + bounds.y + - scroller_bounds.height * scroller_grabbed_at) + / (bounds.height - scroller_bounds.height); - dbg!((scroll_percentage, scroller_grabbed_at)); - /*self.state.scroll_to( + self.state.scroll_to( scroll_percentage, bounds, content_bounds, - );*/ + ); self.state.scroller_grabbed_at = Some(scroller_grabbed_at); @@ -214,24 +212,21 @@ where self.state.scroller_grabbed_at = None; } }, - /* TODO: Implement dragging to scroll Event::Mouse(mouse::Event::CursorMoved { .. }) => { - if let Some(scrollbar_grabbed_at) = - self.state.scrollbar_grabbed_at + if let Some(scroller_grabbed_at) = + self.state.scroller_grabbed_at { - let ratio = content_bounds.height / bounds.height; - let delta = scrollbar_grabbed_at.y - cursor_position.y; + let scroll_percentage = (cursor_position.y + bounds.y + - scroller_bounds.height * scroller_grabbed_at) + / (bounds.height - scroller_bounds.height); - self.state.scroll( - delta * ratio, + self.state.scroll_to( + scroll_percentage, bounds, content_bounds, ); - - self.state.scrollbar_grabbed_at = Some(cursor_position); } } - */ _ => {} } } @@ -273,8 +268,16 @@ where let offset = self.state.offset(bounds, content_bounds); let is_mouse_over = bounds.contains(cursor_position); + let (background_bounds, scroller_bounds) = + renderer.scrollbar_bounds(bounds, content_bounds, offset); let is_mouse_over_scrollbar = renderer - .scrollbar_grab(bounds, content_bounds, offset, cursor_position) + .scrollbar_grab( + bounds, + content_bounds, + background_bounds, + scroller_bounds, + cursor_position, + ) .is_some(); let content = { @@ -399,18 +402,28 @@ pub enum ScrollbarGrab { /// [`Scrollable`]: struct.Scrollable.html /// [renderer]: ../../renderer/index.html pub trait Renderer: crate::Renderer + Sized { + /// Returns the bounds of the scrollbar + /// - Background + /// - Movable Scroller + fn scrollbar_bounds( + &self, + bounds: Rectangle, + content_bounds: Rectangle, + offset: u32, + ) -> (Rectangle, Rectangle); + /// Returns what part of the scrollbar is being grabbed by the mouse - /// given the bounds of the [`Scrollable`] and its contents together - /// with the current scroller bounds. + /// given the bounds of the [`Scrollable`] and its contents. /// /// [`Scrollable`]: struct.Scrollable.html fn scrollbar_grab( &self, bounds: Rectangle, content_bounds: Rectangle, - offset: u32, + background_bounds: Rectangle, + scroller_bounds: Rectangle, cursor_position: Point, - ) -> Option<(ScrollbarGrab, Rectangle)>; + ) -> Option; /// Draws the [`Scrollable`]. /// diff --git a/wgpu/src/renderer/widget/scrollable.rs b/wgpu/src/renderer/widget/scrollable.rs index d069b799..175fac11 100644 --- a/wgpu/src/renderer/widget/scrollable.rs +++ b/wgpu/src/renderer/widget/scrollable.rs @@ -36,31 +36,35 @@ fn scroller_bounds( } impl scrollable::Renderer for Renderer { - fn scrollbar_grab( + fn scrollbar_bounds( &self, bounds: Rectangle, content_bounds: Rectangle, offset: u32, - cursor_position: Point, - ) -> Option<(ScrollbarGrab, Rectangle)> { + ) -> (Rectangle, Rectangle) { let background_bounds = background_bounds(bounds); + let scroller_bounds = + scroller_bounds(bounds, content_bounds, background_bounds, offset); + + (background_bounds, scroller_bounds) + } + + fn scrollbar_grab( + &self, + bounds: Rectangle, + content_bounds: Rectangle, + background_bounds: Rectangle, + scroller_bounds: Rectangle, + cursor_position: Point, + ) -> Option { if content_bounds.height > bounds.height && background_bounds.contains(cursor_position) { - let scroller_bounds = scroller_bounds( - bounds, - content_bounds, - background_bounds, - offset, - ); - - let scrollbar_grab = if scroller_bounds.contains(cursor_position) { + Some(if scroller_bounds.contains(cursor_position) { ScrollbarGrab::Scroller } else { ScrollbarGrab::Background - }; - - Some((scrollbar_grab, scroller_bounds)) + }) } else { None } -- cgit From c12ba14ddad40e8f0e656ae0f8a43c87f0b5907f Mon Sep 17 00:00:00 2001 From: Friz64 Date: Sat, 30 Nov 2019 17:49:42 +0100 Subject: Move scrolling percentage logic to separate function --- native/src/widget/scrollable.rs | 33 +++++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/native/src/widget/scrollable.rs b/native/src/widget/scrollable.rs index 17a1363e..ab1a203b 100644 --- a/native/src/widget/scrollable.rs +++ b/native/src/widget/scrollable.rs @@ -102,6 +102,17 @@ impl<'a, Message, Renderer> Scrollable<'a, Message, Renderer> { } } +fn scroll_percentage( + bounds: Rectangle, + scroller_bounds: Rectangle, + scroller_grabbed_at: f32, + cursor_position: Point, +) -> f32 { + (cursor_position.y + bounds.y + - scroller_bounds.height * scroller_grabbed_at) + / (bounds.height - scroller_bounds.height) +} + impl<'a, Message, Renderer> Widget for Scrollable<'a, Message, Renderer> where @@ -195,12 +206,13 @@ where } }; - let scroll_percentage = (cursor_position.y + bounds.y - - scroller_bounds.height * scroller_grabbed_at) - / (bounds.height - scroller_bounds.height); - self.state.scroll_to( - scroll_percentage, + scroll_percentage( + bounds, + scroller_bounds, + scroller_grabbed_at, + cursor_position, + ), bounds, content_bounds, ); @@ -216,12 +228,13 @@ where if let Some(scroller_grabbed_at) = self.state.scroller_grabbed_at { - let scroll_percentage = (cursor_position.y + bounds.y - - scroller_bounds.height * scroller_grabbed_at) - / (bounds.height - scroller_bounds.height); - self.state.scroll_to( - scroll_percentage, + scroll_percentage( + bounds, + scroller_bounds, + scroller_grabbed_at, + cursor_position, + ), bounds, content_bounds, ); -- cgit From 9a733bb3c89e15ada05fc90efb71eeae12b8c9c1 Mon Sep 17 00:00:00 2001 From: Friz64 Date: Sat, 30 Nov 2019 18:16:01 +0100 Subject: Support null renderer --- native/src/renderer/null.rs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/native/src/renderer/null.rs b/native/src/renderer/null.rs index c8852ad1..c06d1dfa 100644 --- a/native/src/renderer/null.rs +++ b/native/src/renderer/null.rs @@ -61,11 +61,21 @@ impl text::Renderer for Null { } impl scrollable::Renderer for Null { - fn scrollbar_grab( + fn scrollbar_bounds( &self, _bounds: Rectangle, _content_bounds: Rectangle, _offset: u32, + ) -> (Rectangle, Rectangle) { + Default::default() + } + + fn scrollbar_grab( + &self, + _bounds: Rectangle, + _content_bounds: Rectangle, + _background_bounds: Rectangle, + _scroller_bounds: Rectangle, _cursor_position: Point, ) -> Option { None -- cgit From 6943041e0fad65927a741e316509bf07bdaa2f61 Mon Sep 17 00:00:00 2001 From: Friz64 Date: Mon, 2 Dec 2019 18:51:34 +0100 Subject: Address suggestions --- examples/tour.rs | 2 +- native/src/renderer/null.rs | 23 +++---- native/src/widget.rs | 2 +- native/src/widget/scrollable.rs | 108 ++++++++++++++++++++------------- wgpu/src/renderer/widget/scrollable.rs | 102 +++++++++---------------------- 5 files changed, 105 insertions(+), 132 deletions(-) diff --git a/examples/tour.rs b/examples/tour.rs index 0121c3bd..6b366957 100644 --- a/examples/tour.rs +++ b/examples/tour.rs @@ -145,7 +145,7 @@ impl Steps { Step::Debugger, Step::End, ], - current: 0, + current: 6, } } diff --git a/native/src/renderer/null.rs b/native/src/renderer/null.rs index c06d1dfa..2ce150c0 100644 --- a/native/src/renderer/null.rs +++ b/native/src/renderer/null.rs @@ -1,7 +1,7 @@ use crate::{ button, checkbox, column, radio, row, scrollable, text, text_input, Background, Color, Element, Font, HorizontalAlignment, Layout, Point, - Rectangle, Renderer, ScrollbarGrab, Size, VerticalAlignment, + Rectangle, Renderer, Size, VerticalAlignment, }; /// A renderer that does nothing. @@ -61,24 +61,17 @@ impl text::Renderer for Null { } impl scrollable::Renderer for Null { - fn scrollbar_bounds( - &self, - _bounds: Rectangle, - _content_bounds: Rectangle, - _offset: u32, - ) -> (Rectangle, Rectangle) { + fn scrollbar_bounds(_bounds: Rectangle) -> Rectangle { Default::default() } - fn scrollbar_grab( - &self, + fn scroller_bounds( _bounds: Rectangle, _content_bounds: Rectangle, - _background_bounds: Rectangle, - _scroller_bounds: Rectangle, - _cursor_position: Point, - ) -> Option { - None + _scrollbar_bounds: Rectangle, + _offset: u32, + ) -> Rectangle { + Default::default() } fn draw( @@ -88,6 +81,8 @@ impl scrollable::Renderer for Null { _content_bounds: Rectangle, _is_mouse_over: bool, _is_mouse_over_scrollbar: bool, + _scrollbar_bounds: Rectangle, + _scroller_bounds: Rectangle, _offset: u32, _content: Self::Output, ) { diff --git a/native/src/widget.rs b/native/src/widget.rs index a2d3aa12..71dcdc0d 100644 --- a/native/src/widget.rs +++ b/native/src/widget.rs @@ -47,7 +47,7 @@ pub use radio::Radio; #[doc(no_inline)] pub use row::Row; #[doc(no_inline)] -pub use scrollable::{Scrollable, ScrollbarGrab}; +pub use scrollable::Scrollable; #[doc(no_inline)] pub use slider::Slider; #[doc(no_inline)] diff --git a/native/src/widget/scrollable.rs b/native/src/widget/scrollable.rs index ab1a203b..b48ae492 100644 --- a/native/src/widget/scrollable.rs +++ b/native/src/widget/scrollable.rs @@ -162,12 +162,17 @@ where let content_bounds = content.bounds(); let offset = self.state.offset(bounds, content_bounds); - let (background_bounds, scroller_bounds) = - renderer.scrollbar_bounds(bounds, content_bounds, offset); - let scrollbar_grab = renderer.scrollbar_grab( + let scrollbar_bounds = Renderer::scrollbar_bounds(bounds); + let scroller_bounds = Renderer::scroller_bounds( bounds, content_bounds, - background_bounds, + scrollbar_bounds, + offset, + ); + let scrollbar_grab = ScrollbarItem::from_cursor_position( + bounds, + content_bounds, + scrollbar_bounds, scroller_bounds, cursor_position, ); @@ -190,7 +195,7 @@ where } } - if self.state.currently_grabbed() || scrollbar_grab.is_some() { + if self.state.is_scroller_grabbed() || scrollbar_grab.is_some() { match event { Event::Mouse(mouse::Event::Input { button: mouse::Button::Left, @@ -199,8 +204,8 @@ where ButtonState::Pressed => { let scroller_grabbed_at = match scrollbar_grab.unwrap() { - ScrollbarGrab::Background => 0.5, - ScrollbarGrab::Scroller => { + ScrollbarItem::Background => 0.5, + ScrollbarItem::Scroller => { (cursor_position.y - scroller_bounds.y) / scroller_bounds.height } @@ -245,7 +250,7 @@ where } let cursor_position = if is_mouse_over - && !(scrollbar_grab.is_some() || self.state.currently_grabbed()) + && !(scrollbar_grab.is_some() || self.state.is_scroller_grabbed()) { Point::new( cursor_position.x, @@ -281,17 +286,21 @@ where let offset = self.state.offset(bounds, content_bounds); let is_mouse_over = bounds.contains(cursor_position); - let (background_bounds, scroller_bounds) = - renderer.scrollbar_bounds(bounds, content_bounds, offset); - let is_mouse_over_scrollbar = renderer - .scrollbar_grab( - bounds, - content_bounds, - background_bounds, - scroller_bounds, - cursor_position, - ) - .is_some(); + let scrollbar_bounds = Renderer::scrollbar_bounds(bounds); + let scroller_bounds = Renderer::scroller_bounds( + bounds, + content_bounds, + scrollbar_bounds, + offset, + ); + let is_mouse_over_scrollbar = ScrollbarItem::from_cursor_position( + bounds, + content_bounds, + scrollbar_bounds, + scroller_bounds, + cursor_position, + ) + .is_some(); let content = { let cursor_position = if is_mouse_over && !is_mouse_over_scrollbar { @@ -310,6 +319,8 @@ where content_layout.bounds(), is_mouse_over, is_mouse_over_scrollbar, + scrollbar_bounds, + scroller_bounds, offset, content, ) @@ -392,21 +403,41 @@ impl State { self.offset.min(hidden_content as f32) as u32 } - /// Returns whether the scrollbar is currently grabbed or not. - pub fn currently_grabbed(&self) -> bool { + /// Returns whether the scroller is currently grabbed or not. + pub fn is_scroller_grabbed(&self) -> bool { self.scroller_grabbed_at.is_some() } } #[derive(Debug, Clone, Copy)] -/// What the mouse is grabbing on the scrollbar -pub enum ScrollbarGrab { - /// The mouse is grabbing the background +enum ScrollbarItem { Background, - /// The mouse is grabbing the scroller Scroller, } +impl ScrollbarItem { + /// `None` means the cursor is not over any item + fn from_cursor_position( + bounds: Rectangle, + content_bounds: Rectangle, + scrollbar_bounds: Rectangle, + scroller_bounds: Rectangle, + cursor_position: Point, + ) -> Option { + if content_bounds.height > bounds.height + && scrollbar_bounds.contains(cursor_position) + { + Some(if scroller_bounds.contains(cursor_position) { + ScrollbarItem::Scroller + } else { + ScrollbarItem::Background + }) + } else { + None + } + } +} + /// The renderer of a [`Scrollable`]. /// /// Your [renderer] will need to implement this trait before being @@ -416,27 +447,16 @@ pub enum ScrollbarGrab { /// [renderer]: ../../renderer/index.html pub trait Renderer: crate::Renderer + Sized { /// Returns the bounds of the scrollbar - /// - Background - /// - Movable Scroller - fn scrollbar_bounds( - &self, - bounds: Rectangle, - content_bounds: Rectangle, - offset: u32, - ) -> (Rectangle, Rectangle); + fn scrollbar_bounds(bounds: Rectangle) -> Rectangle; - /// Returns what part of the scrollbar is being grabbed by the mouse - /// given the bounds of the [`Scrollable`] and its contents. - /// - /// [`Scrollable`]: struct.Scrollable.html - fn scrollbar_grab( - &self, + /// Returns the bounds of the scroller + /// "The part that you can drag around with your mouse to scroll" + fn scroller_bounds( bounds: Rectangle, content_bounds: Rectangle, - background_bounds: Rectangle, - scroller_bounds: Rectangle, - cursor_position: Point, - ) -> Option; + scrollbar_bounds: Rectangle, + offset: u32, + ) -> Rectangle; /// Draws the [`Scrollable`]. /// @@ -457,6 +477,8 @@ pub trait Renderer: crate::Renderer + Sized { content_bounds: Rectangle, is_mouse_over: bool, is_mouse_over_scrollbar: bool, + scrollbar_bounds: Rectangle, + scroller_bounds: Rectangle, offset: u32, content: Self::Output, ) -> Self::Output; diff --git a/wgpu/src/renderer/widget/scrollable.rs b/wgpu/src/renderer/widget/scrollable.rs index 175fac11..b83cee1b 100644 --- a/wgpu/src/renderer/widget/scrollable.rs +++ b/wgpu/src/renderer/widget/scrollable.rs @@ -1,72 +1,34 @@ use crate::{Primitive, Renderer}; -use iced_native::{ - scrollable, Background, MouseCursor, Point, Rectangle, ScrollbarGrab, - Vector, -}; +use iced_native::{scrollable, Background, MouseCursor, Rectangle, Vector}; const SCROLLBAR_WIDTH: u16 = 10; const SCROLLBAR_MARGIN: u16 = 2; -fn background_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, - } -} - -fn scroller_bounds( - bounds: Rectangle, - content_bounds: Rectangle, - background_bounds: Rectangle, - offset: u32, -) -> Rectangle { - let ratio = bounds.height / content_bounds.height; - let scrollbar_height = bounds.height * ratio; - let y_offset = offset as f32 * ratio; - - Rectangle { - x: background_bounds.x + f32::from(SCROLLBAR_MARGIN), - y: background_bounds.y + y_offset, - width: background_bounds.width - f32::from(2 * SCROLLBAR_MARGIN), - height: scrollbar_height, - } -} - impl scrollable::Renderer for Renderer { - fn scrollbar_bounds( - &self, - bounds: Rectangle, - content_bounds: Rectangle, - offset: u32, - ) -> (Rectangle, Rectangle) { - let background_bounds = background_bounds(bounds); - let scroller_bounds = - scroller_bounds(bounds, content_bounds, background_bounds, offset); - - (background_bounds, scroller_bounds) + 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, + } } - fn scrollbar_grab( - &self, + fn scroller_bounds( bounds: Rectangle, content_bounds: Rectangle, - background_bounds: Rectangle, - scroller_bounds: Rectangle, - cursor_position: Point, - ) -> Option { - if content_bounds.height > bounds.height - && background_bounds.contains(cursor_position) - { - Some(if scroller_bounds.contains(cursor_position) { - ScrollbarGrab::Scroller - } else { - ScrollbarGrab::Background - }) - } else { - None + scrollbar_bounds: Rectangle, + offset: u32, + ) -> Rectangle { + let ratio = bounds.height / content_bounds.height; + let scrollbar_height = bounds.height * ratio; + let y_offset = offset as f32 * ratio; + Rectangle { + 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, } } @@ -77,11 +39,12 @@ impl scrollable::Renderer for Renderer { content_bounds: Rectangle, is_mouse_over: bool, is_mouse_over_scrollbar: bool, + scrollbar_bounds: Rectangle, + scroller_bounds: Rectangle, offset: u32, (content, mouse_cursor): Self::Output, ) -> Self::Output { let is_content_overflowing = content_bounds.height > bounds.height; - let background_bounds = background_bounds(bounds); let clip = Primitive::Clip { bounds, @@ -91,28 +54,21 @@ impl scrollable::Renderer for Renderer { ( if is_content_overflowing - && (is_mouse_over || state.currently_grabbed()) + && (is_mouse_over || state.is_scroller_grabbed()) { - let scroller_bounds = scroller_bounds( - bounds, - content_bounds, - background_bounds, - offset, - ); let scrollbar = Primitive::Quad { bounds: scroller_bounds, background: Background::Color([0.0, 0.0, 0.0, 0.7].into()), border_radius: 5, }; - if is_mouse_over_scrollbar || state.currently_grabbed() { + if is_mouse_over_scrollbar || state.is_scroller_grabbed() { let scrollbar_background = Primitive::Quad { bounds: Rectangle { - x: background_bounds.x - + f32::from(SCROLLBAR_MARGIN), - width: background_bounds.width + x: scrollbar_bounds.x + f32::from(SCROLLBAR_MARGIN), + width: scrollbar_bounds.width - f32::from(2 * SCROLLBAR_MARGIN), - ..background_bounds + ..scrollbar_bounds }, background: Background::Color( [0.0, 0.0, 0.0, 0.3].into(), @@ -131,7 +87,7 @@ impl scrollable::Renderer for Renderer { } else { clip }, - if is_mouse_over_scrollbar || state.currently_grabbed() { + if is_mouse_over_scrollbar || state.is_scroller_grabbed() { MouseCursor::Idle } else { mouse_cursor -- cgit From 6b25b4df2219460882f3d3c57da03d2e930e9d82 Mon Sep 17 00:00:00 2001 From: Friz64 Date: Mon, 2 Dec 2019 18:58:25 +0100 Subject: Reset tour start to 0 --- examples/tour.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/tour.rs b/examples/tour.rs index 6b366957..0121c3bd 100644 --- a/examples/tour.rs +++ b/examples/tour.rs @@ -145,7 +145,7 @@ impl Steps { Step::Debugger, Step::End, ], - current: 6, + current: 0, } } -- cgit From 31e3b6fbcb06bd5e1e5773a7c2febd0cb0092819 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Tue, 3 Dec 2019 06:48:29 +0100 Subject: Unify logic by introducing `scrollable::Scrollbar` --- native/src/renderer/null.rs | 15 +-- native/src/widget/scrollable.rs | 215 ++++++++++++++++----------------- wgpu/src/renderer/widget/scrollable.rs | 110 +++++++++-------- 3 files changed, 169 insertions(+), 171 deletions(-) diff --git a/native/src/renderer/null.rs b/native/src/renderer/null.rs index 2ce150c0..da0e5159 100644 --- a/native/src/renderer/null.rs +++ b/native/src/renderer/null.rs @@ -61,17 +61,13 @@ impl text::Renderer for Null { } impl scrollable::Renderer for Null { - fn scrollbar_bounds(_bounds: Rectangle) -> Rectangle { - Default::default() - } - - fn scroller_bounds( + fn scrollbar( + &self, _bounds: Rectangle, _content_bounds: Rectangle, - _scrollbar_bounds: Rectangle, _offset: u32, - ) -> Rectangle { - Default::default() + ) -> Option { + None } fn draw( @@ -81,8 +77,7 @@ impl scrollable::Renderer for Null { _content_bounds: Rectangle, _is_mouse_over: bool, _is_mouse_over_scrollbar: bool, - _scrollbar_bounds: Rectangle, - _scroller_bounds: Rectangle, + _scrollbar: Option, _offset: u32, _content: Self::Output, ) { diff --git a/native/src/widget/scrollable.rs b/native/src/widget/scrollable.rs index b48ae492..7753c2d2 100644 --- a/native/src/widget/scrollable.rs +++ b/native/src/widget/scrollable.rs @@ -102,17 +102,6 @@ impl<'a, Message, Renderer> Scrollable<'a, Message, Renderer> { } } -fn scroll_percentage( - bounds: Rectangle, - scroller_bounds: Rectangle, - scroller_grabbed_at: f32, - cursor_position: Point, -) -> f32 { - (cursor_position.y + bounds.y - - scroller_bounds.height * scroller_grabbed_at) - / (bounds.height - scroller_bounds.height) -} - impl<'a, Message, Renderer> Widget for Scrollable<'a, Message, Renderer> where @@ -161,22 +150,6 @@ where let content = layout.children().next().unwrap(); let content_bounds = content.bounds(); - let offset = self.state.offset(bounds, content_bounds); - let scrollbar_bounds = Renderer::scrollbar_bounds(bounds); - let scroller_bounds = Renderer::scroller_bounds( - bounds, - content_bounds, - scrollbar_bounds, - offset, - ); - let scrollbar_grab = ScrollbarItem::from_cursor_position( - bounds, - content_bounds, - scrollbar_bounds, - scroller_bounds, - cursor_position, - ); - // TODO: Event capture. Nested scrollables should capture scroll events. if is_mouse_over { match event { @@ -195,48 +168,27 @@ where } } - if self.state.is_scroller_grabbed() || scrollbar_grab.is_some() { + let offset = self.state.offset(bounds, content_bounds); + let scrollbar = renderer.scrollbar(bounds, content_bounds, offset); + let is_mouse_over_scrollbar = scrollbar + .as_ref() + .map(|scrollbar| scrollbar.is_mouse_over(cursor_position)) + .unwrap_or(false); + + if self.state.is_scroller_grabbed() { match event { Event::Mouse(mouse::Event::Input { button: mouse::Button::Left, - state, - }) => match state { - ButtonState::Pressed => { - let scroller_grabbed_at = match scrollbar_grab.unwrap() - { - ScrollbarItem::Background => 0.5, - ScrollbarItem::Scroller => { - (cursor_position.y - scroller_bounds.y) - / scroller_bounds.height - } - }; - - self.state.scroll_to( - scroll_percentage( - bounds, - scroller_bounds, - scroller_grabbed_at, - cursor_position, - ), - bounds, - content_bounds, - ); - - self.state.scroller_grabbed_at = - Some(scroller_grabbed_at); - } - ButtonState::Released => { - self.state.scroller_grabbed_at = None; - } - }, + state: ButtonState::Released, + }) => { + self.state.scroller_grabbed_at = None; + } Event::Mouse(mouse::Event::CursorMoved { .. }) => { - if let Some(scroller_grabbed_at) = - self.state.scroller_grabbed_at + if let (Some(scrollbar), Some(scroller_grabbed_at)) = + (scrollbar, self.state.scroller_grabbed_at) { self.state.scroll_to( - scroll_percentage( - bounds, - scroller_bounds, + scrollbar.scroll_percentage( scroller_grabbed_at, cursor_position, ), @@ -247,11 +199,35 @@ where } _ => {} } + } else if is_mouse_over_scrollbar { + match event { + Event::Mouse(mouse::Event::Input { + button: mouse::Button::Left, + state: ButtonState::Pressed, + }) => { + if let Some(scrollbar) = scrollbar { + if let Some(scroller_grabbed_at) = + scrollbar.grab_scroller(cursor_position) + { + self.state.scroll_to( + scrollbar.scroll_percentage( + scroller_grabbed_at, + cursor_position, + ), + bounds, + content_bounds, + ); + + self.state.scroller_grabbed_at = + Some(scroller_grabbed_at); + } + } + } + _ => {} + } } - let cursor_position = if is_mouse_over - && !(scrollbar_grab.is_some() || self.state.is_scroller_grabbed()) - { + let cursor_position = if is_mouse_over && !is_mouse_over_scrollbar { Point::new( cursor_position.x, cursor_position.y @@ -284,23 +260,13 @@ where let content_layout = layout.children().next().unwrap(); let content_bounds = content_layout.bounds(); let offset = self.state.offset(bounds, content_bounds); + let scrollbar = renderer.scrollbar(bounds, content_bounds, offset); let is_mouse_over = bounds.contains(cursor_position); - let scrollbar_bounds = Renderer::scrollbar_bounds(bounds); - let scroller_bounds = Renderer::scroller_bounds( - bounds, - content_bounds, - scrollbar_bounds, - offset, - ); - let is_mouse_over_scrollbar = ScrollbarItem::from_cursor_position( - bounds, - content_bounds, - scrollbar_bounds, - scroller_bounds, - cursor_position, - ) - .is_some(); + let is_mouse_over_scrollbar = scrollbar + .as_ref() + .map(|scrollbar| scrollbar.is_mouse_over(cursor_position)) + .unwrap_or(false); let content = { let cursor_position = if is_mouse_over && !is_mouse_over_scrollbar { @@ -319,8 +285,7 @@ where content_layout.bounds(), is_mouse_over, is_mouse_over_scrollbar, - scrollbar_bounds, - scroller_bounds, + scrollbar, offset, content, ) @@ -409,33 +374,60 @@ impl State { } } -#[derive(Debug, Clone, Copy)] -enum ScrollbarItem { - Background, - Scroller, +/// The scrollbar of a [`Scrollable`]. +/// +/// [`Scrollable`]: struct.Scrollable.html +#[derive(Debug)] +pub struct Scrollbar { + /// The bounds of the [`Scrollbar`]. + /// + /// [`Scrollbar`]: struct.Scrollbar.html + pub bounds: Rectangle, + + /// The bounds of the [`Scroller`]. + /// + /// [`Scroller`]: struct.Scroller.html + pub scroller: Scroller, } -impl ScrollbarItem { - /// `None` means the cursor is not over any item - fn from_cursor_position( - bounds: Rectangle, - content_bounds: Rectangle, - scrollbar_bounds: Rectangle, - scroller_bounds: Rectangle, - cursor_position: Point, - ) -> Option { - if content_bounds.height > bounds.height - && scrollbar_bounds.contains(cursor_position) - { - Some(if scroller_bounds.contains(cursor_position) { - ScrollbarItem::Scroller +impl Scrollbar { + fn is_mouse_over(&self, cursor_position: Point) -> bool { + self.bounds.contains(cursor_position) + } + + fn grab_scroller(&self, cursor_position: Point) -> Option { + if self.bounds.contains(cursor_position) { + Some(if self.scroller.bounds.contains(cursor_position) { + (cursor_position.y - self.scroller.bounds.y) + / self.scroller.bounds.height } else { - ScrollbarItem::Background + 0.5 }) } else { None } } + + fn scroll_percentage( + &self, + grabbed_at: f32, + cursor_position: Point, + ) -> f32 { + (cursor_position.y + self.bounds.y + - self.scroller.bounds.height * grabbed_at) + / (self.bounds.height - self.scroller.bounds.height) + } +} + +/// The handle of a [`Scrollbar`]. +/// +/// [`Scrollbar`]: struct.Scrollbar.html +#[derive(Debug, Clone, Copy)] +pub struct Scroller { + /// The bounds of the [`Scroller`]. + /// + /// [`Scroller`]: struct.Scrollbar.html + pub bounds: Rectangle, } /// The renderer of a [`Scrollable`]. @@ -446,17 +438,17 @@ impl ScrollbarItem { /// [`Scrollable`]: struct.Scrollable.html /// [renderer]: ../../renderer/index.html pub trait Renderer: crate::Renderer + Sized { - /// Returns the bounds of the scrollbar - fn scrollbar_bounds(bounds: Rectangle) -> Rectangle; - - /// Returns the bounds of the scroller - /// "The part that you can drag around with your mouse to scroll" - fn scroller_bounds( + /// Returns the [`Scrollbar`] given the bounds and content bounds of a + /// [`Scrollable`]. + /// + /// [`Scrollbar`]: struct.Scrollbar.html + /// [`Scrollable`]: struct.Scrollable.html + fn scrollbar( + &self, bounds: Rectangle, content_bounds: Rectangle, - scrollbar_bounds: Rectangle, offset: u32, - ) -> Rectangle; + ) -> Option; /// Draws the [`Scrollable`]. /// @@ -477,8 +469,7 @@ pub trait Renderer: crate::Renderer + Sized { content_bounds: Rectangle, is_mouse_over: bool, is_mouse_over_scrollbar: bool, - scrollbar_bounds: Rectangle, - scroller_bounds: Rectangle, + scrollbar: Option, offset: u32, content: Self::Output, ) -> Self::Output; diff --git a/wgpu/src/renderer/widget/scrollable.rs b/wgpu/src/renderer/widget/scrollable.rs index b83cee1b..6ef57185 100644 --- a/wgpu/src/renderer/widget/scrollable.rs +++ b/wgpu/src/renderer/widget/scrollable.rs @@ -5,30 +5,40 @@ const SCROLLBAR_WIDTH: u16 = 10; const SCROLLBAR_MARGIN: u16 = 2; impl scrollable::Renderer for Renderer { - 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, - } - } - - fn scroller_bounds( + fn scrollbar( + &self, bounds: Rectangle, content_bounds: Rectangle, - scrollbar_bounds: Rectangle, offset: u32, - ) -> Rectangle { - let ratio = bounds.height / content_bounds.height; - let scrollbar_height = bounds.height * ratio; - let y_offset = offset as f32 * ratio; - Rectangle { - 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, + ) -> Option { + if content_bounds.height > bounds.height { + let scrollbar_bounds = 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, + }; + + let ratio = bounds.height / content_bounds.height; + let scrollbar_height = bounds.height * ratio; + let y_offset = offset as f32 * ratio; + + let scroller_bounds = Rectangle { + 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, + }; + + Some(scrollable::Scrollbar { + bounds: scrollbar_bounds, + scroller: scrollable::Scroller { + bounds: scroller_bounds, + }, + }) + } else { + None } } @@ -36,16 +46,13 @@ impl scrollable::Renderer for Renderer { &mut self, state: &scrollable::State, bounds: Rectangle, - content_bounds: Rectangle, + _content_bounds: Rectangle, is_mouse_over: bool, is_mouse_over_scrollbar: bool, - scrollbar_bounds: Rectangle, - scroller_bounds: Rectangle, + scrollbar: Option, offset: u32, (content, mouse_cursor): Self::Output, ) -> Self::Output { - let is_content_overflowing = content_bounds.height > bounds.height; - let clip = Primitive::Clip { bounds, offset: Vector::new(0, offset), @@ -53,36 +60,41 @@ impl scrollable::Renderer for Renderer { }; ( - if is_content_overflowing - && (is_mouse_over || state.is_scroller_grabbed()) - { - let scrollbar = Primitive::Quad { - bounds: scroller_bounds, - background: Background::Color([0.0, 0.0, 0.0, 0.7].into()), - border_radius: 5, - }; - - if is_mouse_over_scrollbar || state.is_scroller_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 - }, + if let Some(scrollbar) = scrollbar { + if is_mouse_over || state.is_scroller_grabbed() { + let scroller = Primitive::Quad { + bounds: scrollbar.scroller.bounds, background: Background::Color( - [0.0, 0.0, 0.0, 0.3].into(), + [0.0, 0.0, 0.0, 0.7].into(), ), border_radius: 5, }; - Primitive::Group { - primitives: vec![clip, scrollbar_background, scrollbar], + if is_mouse_over_scrollbar || state.is_scroller_grabbed() { + let scrollbar = 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( + [0.0, 0.0, 0.0, 0.3].into(), + ), + border_radius: 5, + }; + + Primitive::Group { + primitives: vec![clip, scrollbar, scroller], + } + } else { + Primitive::Group { + primitives: vec![clip, scroller], + } } } else { - Primitive::Group { - primitives: vec![clip, scrollbar], - } + clip } } else { clip -- cgit From 2cd517c09998f2dd4c8b15ba3b014d9904f957fd Mon Sep 17 00:00:00 2001 From: Friz64 Date: Tue, 3 Dec 2019 15:19:59 +0100 Subject: Correct documentation oversight --- native/src/widget/scrollable.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/native/src/widget/scrollable.rs b/native/src/widget/scrollable.rs index 7753c2d2..3c2625b7 100644 --- a/native/src/widget/scrollable.rs +++ b/native/src/widget/scrollable.rs @@ -454,12 +454,15 @@ pub trait Renderer: crate::Renderer + Sized { /// /// It receives: /// - the [`State`] of the [`Scrollable`] - /// - the bounds of the [`Scrollable`] + /// - the bounds of the [`Scrollable`] widget + /// - the bounds of the [`Scrollable`] content /// - whether the mouse is over the [`Scrollable`] or not - /// - whether the mouse is over the scrollbar or not + /// - whether the mouse is over the [`Scrollbar`] or not + /// - a optional [`Scrollbar`] to be rendered /// - the scrolling offset /// - the drawn content /// + /// [`Scrollbar`]: struct.Scrollbar.html /// [`Scrollable`]: struct.Scrollable.html /// [`State`]: struct.State.html fn draw( -- cgit