From b623f280ed43b04cef16a82de4cdf13497b5d63e Mon Sep 17 00:00:00 2001 From: Cory Forsstrom Date: Fri, 14 Apr 2023 13:32:44 -0700 Subject: Add `scroll_to` operation for absolute scroll --- examples/scrollable/src/main.rs | 4 +-- native/src/widget/operation/scrollable.rs | 50 +++++++++++++++++++++++++++- native/src/widget/scrollable.rs | 55 +++++++++++++++++++++---------- src/widget.rs | 4 +-- 4 files changed, 90 insertions(+), 23 deletions(-) diff --git a/examples/scrollable/src/main.rs b/examples/scrollable/src/main.rs index 2e99b1ac..be8d0f52 100644 --- a/examples/scrollable/src/main.rs +++ b/examples/scrollable/src/main.rs @@ -36,7 +36,7 @@ enum Message { ScrollerWidthChanged(u16), ScrollToBeginning, ScrollToEnd, - Scrolled(scrollable::RelativeOffset), + Scrolled(scrollable::CurrentOffset), } impl Application for ScrollableDemo { @@ -105,7 +105,7 @@ impl Application for ScrollableDemo { ) } Message::Scrolled(offset) => { - self.current_scroll_offset = offset; + self.current_scroll_offset = offset.relative; Command::none() } diff --git a/native/src/widget/operation/scrollable.rs b/native/src/widget/operation/scrollable.rs index 3b20631f..62f4c91e 100644 --- a/native/src/widget/operation/scrollable.rs +++ b/native/src/widget/operation/scrollable.rs @@ -5,6 +5,9 @@ use crate::widget::{Id, Operation}; pub trait Scrollable { /// Snaps the scroll of the widget to the given `percentage` along the horizontal & vertical axis. fn snap_to(&mut self, offset: RelativeOffset); + + /// Scroll the widget to the given [`AbsoluteOffset`] along the horizontal & vertical axis. + fn scroll_to(&mut self, offset: AbsoluteOffset); } /// Produces an [`Operation`] that snaps the widget with the given [`Id`] to @@ -34,7 +37,52 @@ pub fn snap_to(target: Id, offset: RelativeOffset) -> impl Operation { SnapTo { target, offset } } -/// The amount of offset in each direction of a [`Scrollable`]. +/// Produces an [`Operation`] that scrolls the widget with the given [`Id`] to +/// the provided [`AbsoluteOffset`]. +pub fn scroll_to(target: Id, offset: AbsoluteOffset) -> impl Operation { + struct ScrollTo { + target: Id, + offset: AbsoluteOffset, + } + + impl Operation for ScrollTo { + fn container( + &mut self, + _id: Option<&Id>, + operate_on_children: &mut dyn FnMut(&mut dyn Operation), + ) { + operate_on_children(self) + } + + fn scrollable(&mut self, state: &mut dyn Scrollable, id: Option<&Id>) { + if Some(&self.target) == id { + state.scroll_to(self.offset); + } + } + } + + ScrollTo { target, offset } +} + +/// The current absolute & relative offset of a [`Scrollable`] +#[derive(Debug, Clone, Copy, PartialEq, Default)] +pub struct CurrentOffset { + /// The [`AbsoluteOffset`] of a [`Scrollable`] + pub absolute: AbsoluteOffset, + /// The [`RelativeOffset`] of a [`Scrollable`] + pub relative: RelativeOffset, +} + +/// The amount of absolute offset in each direction of a [`Scrollable`]. +#[derive(Debug, Clone, Copy, PartialEq, Default)] +pub struct AbsoluteOffset { + /// The amount of horizontal offset + pub x: f32, + /// The amount of vertical offset + pub y: f32, +} + +/// The amount of relative offset in each direction of a [`Scrollable`]. /// /// A value of `0.0` means start, while `1.0` means end. #[derive(Debug, Clone, Copy, PartialEq, Default)] diff --git a/native/src/widget/scrollable.rs b/native/src/widget/scrollable.rs index 78dcdca2..eedddfd0 100644 --- a/native/src/widget/scrollable.rs +++ b/native/src/widget/scrollable.rs @@ -15,7 +15,9 @@ use crate::{ }; pub use iced_style::scrollable::StyleSheet; -pub use operation::scrollable::RelativeOffset; +pub use operation::scrollable::{ + AbsoluteOffset, CurrentOffset, RelativeOffset, +}; pub mod style { //! The styles of a [`Scrollable`]. @@ -38,7 +40,7 @@ where vertical: Properties, horizontal: Option, content: Element<'a, Message, Renderer>, - on_scroll: Option Message + 'a>>, + on_scroll: Option Message + 'a>>, style: ::Style, } @@ -93,11 +95,10 @@ where /// Sets a function to call when the [`Scrollable`] is scrolled. /// - /// The function takes the new relative x & y offset of the [`Scrollable`] - /// (e.g. `0` means beginning, while `1` means end). + /// The function takes the [`CurrentOffset`] of the [`Scrollable`] pub fn on_scroll( mut self, - f: impl Fn(RelativeOffset) -> Message + 'a, + f: impl Fn(CurrentOffset) -> Message + 'a, ) -> Self { self.on_scroll = Some(Box::new(f)); self @@ -436,7 +437,7 @@ pub fn update( shell: &mut Shell<'_, Message>, vertical: &Properties, horizontal: Option<&Properties>, - on_scroll: &Option Message + '_>>, + on_scroll: &Option Message + '_>>, update_content: impl FnOnce( Event, Layout<'_>, @@ -896,7 +897,7 @@ pub fn draw( fn notify_on_scroll( state: &mut State, - on_scroll: &Option Message + '_>>, + on_scroll: &Option Message + '_>>, bounds: Rectangle, content_bounds: Rectangle, shell: &mut Shell<'_, Message>, @@ -908,31 +909,39 @@ fn notify_on_scroll( return; } - let x = state.offset_x.absolute(bounds.width, content_bounds.width) - / (content_bounds.width - bounds.width); + let absolute_x = + state.offset_x.absolute(bounds.width, content_bounds.width); + let relative_x = absolute_x / (content_bounds.width - bounds.width); - let y = state + let absolute_y = state .offset_y - .absolute(bounds.height, content_bounds.height) - / (content_bounds.height - bounds.height); + .absolute(bounds.height, content_bounds.height); + let relative_y = absolute_y / (content_bounds.height - bounds.height); - let new_offset = RelativeOffset { x, y }; + let absolute = AbsoluteOffset { + x: absolute_x, + y: absolute_y, + }; + let relative = RelativeOffset { + x: relative_x, + y: relative_y, + }; // Don't publish redundant offsets to shell - if let Some(prev_offset) = state.last_notified { + if let Some(prev_relative) = state.last_notified { let unchanged = |a: f32, b: f32| { (a - b).abs() <= f32::EPSILON || (a.is_nan() && b.is_nan()) }; - if unchanged(prev_offset.x, new_offset.x) - && unchanged(prev_offset.y, new_offset.y) + if unchanged(prev_relative.x, relative.x) + && unchanged(prev_relative.y, relative.y) { return; } } - shell.publish(on_scroll(new_offset)); - state.last_notified = Some(new_offset); + shell.publish(on_scroll(CurrentOffset { absolute, relative })); + state.last_notified = Some(relative); } } @@ -966,6 +975,10 @@ impl operation::Scrollable for State { fn snap_to(&mut self, offset: RelativeOffset) { State::snap_to(self, offset); } + + fn scroll_to(&mut self, offset: AbsoluteOffset) { + State::scroll_to(self, offset) + } } #[derive(Debug, Clone, Copy)] @@ -1052,6 +1065,12 @@ impl State { self.offset_y = Offset::Relative(offset.y.clamp(0.0, 1.0)); } + /// Scroll to the provided [`AbsoluteOffset`]. + pub fn scroll_to(&mut self, offset: AbsoluteOffset) { + self.offset_x = Offset::Absolute(offset.x.max(0.0)); + self.offset_y = Offset::Absolute(offset.y.max(0.0)); + } + /// Unsnaps the current scroll position, if snapped, given the bounds of the /// [`Scrollable`] and its contents. pub fn unsnap(&mut self, bounds: Rectangle, content_bounds: Rectangle) { diff --git a/src/widget.rs b/src/widget.rs index 44027811..87e82f47 100644 --- a/src/widget.rs +++ b/src/widget.rs @@ -109,8 +109,8 @@ pub mod radio { pub mod scrollable { //! Navigate an endless amount of content with a scrollbar. pub use iced_native::widget::scrollable::{ - snap_to, style::Scrollbar, style::Scroller, Id, Properties, - RelativeOffset, StyleSheet, + snap_to, style::Scrollbar, style::Scroller, AbsoluteOffset, + CurrentOffset, Id, Properties, RelativeOffset, StyleSheet, }; /// A widget that can vertically display an infinite amount of content -- cgit From 6ad5e03d71db3dee174ac6512dceccc80e3a70a8 Mon Sep 17 00:00:00 2001 From: Cory Forsstrom Date: Mon, 17 Apr 2023 13:55:40 -0700 Subject: Add scrollable `Viewport` --- examples/scrollable/src/main.rs | 6 +- native/src/widget/operation/scrollable.rs | 9 --- native/src/widget/scrollable.rs | 94 ++++++++++++++++++------------- src/widget.rs | 4 +- 4 files changed, 61 insertions(+), 52 deletions(-) diff --git a/examples/scrollable/src/main.rs b/examples/scrollable/src/main.rs index be8d0f52..97344c94 100644 --- a/examples/scrollable/src/main.rs +++ b/examples/scrollable/src/main.rs @@ -36,7 +36,7 @@ enum Message { ScrollerWidthChanged(u16), ScrollToBeginning, ScrollToEnd, - Scrolled(scrollable::CurrentOffset), + Scrolled(scrollable::Viewport), } impl Application for ScrollableDemo { @@ -104,8 +104,8 @@ impl Application for ScrollableDemo { self.current_scroll_offset, ) } - Message::Scrolled(offset) => { - self.current_scroll_offset = offset.relative; + Message::Scrolled(viewport) => { + self.current_scroll_offset = viewport.relative_offset(); Command::none() } diff --git a/native/src/widget/operation/scrollable.rs b/native/src/widget/operation/scrollable.rs index 62f4c91e..f947344d 100644 --- a/native/src/widget/operation/scrollable.rs +++ b/native/src/widget/operation/scrollable.rs @@ -64,15 +64,6 @@ pub fn scroll_to(target: Id, offset: AbsoluteOffset) -> impl Operation { ScrollTo { target, offset } } -/// The current absolute & relative offset of a [`Scrollable`] -#[derive(Debug, Clone, Copy, PartialEq, Default)] -pub struct CurrentOffset { - /// The [`AbsoluteOffset`] of a [`Scrollable`] - pub absolute: AbsoluteOffset, - /// The [`RelativeOffset`] of a [`Scrollable`] - pub relative: RelativeOffset, -} - /// The amount of absolute offset in each direction of a [`Scrollable`]. #[derive(Debug, Clone, Copy, PartialEq, Default)] pub struct AbsoluteOffset { diff --git a/native/src/widget/scrollable.rs b/native/src/widget/scrollable.rs index eedddfd0..c66a166b 100644 --- a/native/src/widget/scrollable.rs +++ b/native/src/widget/scrollable.rs @@ -15,9 +15,7 @@ use crate::{ }; pub use iced_style::scrollable::StyleSheet; -pub use operation::scrollable::{ - AbsoluteOffset, CurrentOffset, RelativeOffset, -}; +pub use operation::scrollable::{AbsoluteOffset, RelativeOffset}; pub mod style { //! The styles of a [`Scrollable`]. @@ -40,7 +38,7 @@ where vertical: Properties, horizontal: Option, content: Element<'a, Message, Renderer>, - on_scroll: Option Message + 'a>>, + on_scroll: Option Message + 'a>>, style: ::Style, } @@ -95,11 +93,8 @@ where /// Sets a function to call when the [`Scrollable`] is scrolled. /// - /// The function takes the [`CurrentOffset`] of the [`Scrollable`] - pub fn on_scroll( - mut self, - f: impl Fn(CurrentOffset) -> Message + 'a, - ) -> Self { + /// The function takes the [`Viewport`] of the [`Scrollable`] + pub fn on_scroll(mut self, f: impl Fn(Viewport) -> Message + 'a) -> Self { self.on_scroll = Some(Box::new(f)); self } @@ -437,7 +432,7 @@ pub fn update( shell: &mut Shell<'_, Message>, vertical: &Properties, horizontal: Option<&Properties>, - on_scroll: &Option Message + '_>>, + on_scroll: &Option Message + '_>>, update_content: impl FnOnce( Event, Layout<'_>, @@ -897,7 +892,7 @@ pub fn draw( fn notify_on_scroll( state: &mut State, - on_scroll: &Option Message + '_>>, + on_scroll: &Option Message + '_>>, bounds: Rectangle, content_bounds: Rectangle, shell: &mut Shell<'_, Message>, @@ -909,39 +904,29 @@ fn notify_on_scroll( return; } - let absolute_x = - state.offset_x.absolute(bounds.width, content_bounds.width); - let relative_x = absolute_x / (content_bounds.width - bounds.width); - - let absolute_y = state - .offset_y - .absolute(bounds.height, content_bounds.height); - let relative_y = absolute_y / (content_bounds.height - bounds.height); - - let absolute = AbsoluteOffset { - x: absolute_x, - y: absolute_y, - }; - let relative = RelativeOffset { - x: relative_x, - y: relative_y, + let viewport = Viewport { + offset_x: state.offset_x, + offset_y: state.offset_y, + bounds, + content_bounds, }; - // Don't publish redundant offsets to shell - if let Some(prev_relative) = state.last_notified { + // Don't publish redundant viewports to shell + if let Some(last_notified) = state.last_notified { + let prev = last_notified.relative_offset(); + let curr = viewport.relative_offset(); + let unchanged = |a: f32, b: f32| { (a - b).abs() <= f32::EPSILON || (a.is_nan() && b.is_nan()) }; - if unchanged(prev_relative.x, relative.x) - && unchanged(prev_relative.y, relative.y) - { + if unchanged(prev.x, curr.x) && unchanged(prev.y, curr.y) { return; } } - shell.publish(on_scroll(CurrentOffset { absolute, relative })); - state.last_notified = Some(relative); + shell.publish(on_scroll(viewport)); + state.last_notified = Some(viewport); } } @@ -954,7 +939,7 @@ pub struct State { offset_x: Offset, x_scroller_grabbed_at: Option, keyboard_modifiers: keyboard::Modifiers, - last_notified: Option, + last_notified: Option, } impl Default for State { @@ -988,18 +973,51 @@ enum Offset { } impl Offset { - fn absolute(self, window: f32, content: f32) -> f32 { + fn absolute(self, viewport: f32, content: f32) -> f32 { match self { Offset::Absolute(absolute) => { - absolute.min((content - window).max(0.0)) + absolute.min((content - viewport).max(0.0)) } Offset::Relative(percentage) => { - ((content - window) * percentage).max(0.0) + ((content - viewport) * percentage).max(0.0) } } } } +/// The current [`Viewport`] of the [`Scrollable`]. +#[derive(Debug, Clone, Copy)] +pub struct Viewport { + offset_x: Offset, + offset_y: Offset, + bounds: Rectangle, + content_bounds: Rectangle, +} + +impl Viewport { + /// Returns the [`AbsoluteOffset`] of the current [`Viewport`]. + pub fn absolute_offset(&self) -> AbsoluteOffset { + let x = self + .offset_x + .absolute(self.bounds.width, self.content_bounds.width); + let y = self + .offset_y + .absolute(self.bounds.height, self.content_bounds.height); + + AbsoluteOffset { x, y } + } + + /// Returns the [`RelativeOffset`] of the current [`Viewport`]. + pub fn relative_offset(&self) -> RelativeOffset { + let AbsoluteOffset { x, y } = self.absolute_offset(); + + let x = x / (self.content_bounds.width - self.bounds.width); + let y = y / (self.content_bounds.height - self.bounds.height); + + RelativeOffset { x, y } + } +} + impl State { /// Creates a new [`State`] with the scrollbar(s) at the beginning. pub fn new() -> Self { diff --git a/src/widget.rs b/src/widget.rs index 87e82f47..38995a45 100644 --- a/src/widget.rs +++ b/src/widget.rs @@ -109,8 +109,8 @@ pub mod radio { pub mod scrollable { //! Navigate an endless amount of content with a scrollbar. pub use iced_native::widget::scrollable::{ - snap_to, style::Scrollbar, style::Scroller, AbsoluteOffset, - CurrentOffset, Id, Properties, RelativeOffset, StyleSheet, + snap_to, style::Scrollbar, style::Scroller, AbsoluteOffset, Id, + Properties, RelativeOffset, StyleSheet, Viewport, }; /// A widget that can vertically display an infinite amount of content -- cgit From 07dfebfec00b29ef84a1624ac942bb433628eff6 Mon Sep 17 00:00:00 2001 From: Cory Forsstrom Date: Mon, 17 Apr 2023 18:11:50 -0700 Subject: Invalidate responsive layout when layout is called --- lazy/src/responsive.rs | 51 +++++++++++++++++++++++++------------------------- 1 file changed, 26 insertions(+), 25 deletions(-) diff --git a/lazy/src/responsive.rs b/lazy/src/responsive.rs index 57c07de1..cdeec2ad 100644 --- a/lazy/src/responsive.rs +++ b/lazy/src/responsive.rs @@ -41,7 +41,7 @@ where view: Box::new(view), content: RefCell::new(Content { size: Size::ZERO, - layout: layout::Node::new(Size::ZERO), + layout: None, element: Element::new(horizontal_space(0)), }), } @@ -50,7 +50,7 @@ where struct Content<'a, Message, Renderer> { size: Size, - layout: layout::Node, + layout: Option, element: Element<'a, Message, Renderer>, } @@ -58,10 +58,21 @@ impl<'a, Message, Renderer> Content<'a, Message, Renderer> where Renderer: iced_native::Renderer, { + fn layout(&mut self, renderer: &Renderer) -> layout::Node { + if self.layout.is_none() { + self.layout = + Some(self.element.as_widget().layout( + renderer, + &layout::Limits::new(Size::ZERO, self.size), + )); + } + + self.layout.clone().unwrap() + } + fn update( &mut self, tree: &mut Tree, - renderer: &Renderer, new_size: Size, view: &dyn Fn(Size) -> Element<'a, Message, Renderer>, ) { @@ -73,11 +84,6 @@ where self.size = new_size; tree.diff(&self.element); - - self.layout = self - .element - .as_widget() - .layout(renderer, &layout::Limits::new(Size::ZERO, self.size)); } fn resolve( @@ -96,12 +102,12 @@ where where R: Deref, { - self.update(tree, renderer.deref(), layout.bounds().size(), view); + self.update(tree, layout.bounds().size(), view); - let content_layout = Layout::with_offset( - layout.position() - Point::ORIGIN, - &self.layout, - ); + let node = self.layout(renderer.deref()); + + let content_layout = + Layout::with_offset(layout.position() - Point::ORIGIN, &node); f(tree, renderer, content_layout, &mut self.element) } @@ -139,6 +145,8 @@ where _renderer: &Renderer, limits: &layout::Limits, ) -> layout::Node { + let _ = self.content.borrow_mut().layout.take(); + layout::Node::new(limits.max()) } @@ -272,22 +280,15 @@ where tree: state.tree.borrow_mut(), types: PhantomData, overlay_builder: |content: &mut RefMut>, tree| { - content.update( - tree, - renderer, - layout.bounds().size(), - &self.view, - ); + content.update(tree, layout.bounds().size(), &self.view); + + let node = content.layout(renderer); - let Content { - element, - layout: content_layout, - .. - } = content.deref_mut(); + let Content { element, .. } = content.deref_mut(); let content_layout = Layout::with_offset( layout.bounds().position() - Point::ORIGIN, - content_layout, + &node, ); element -- cgit From ac7b77f59c720bdb618057df0435fa1170d9c84a Mon Sep 17 00:00:00 2001 From: Cory Forsstrom Date: Mon, 17 Apr 2023 18:40:41 -0700 Subject: Only invalidate layout if children layout is invalid --- lazy/src/responsive.rs | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/lazy/src/responsive.rs b/lazy/src/responsive.rs index cdeec2ad..2f097ff5 100644 --- a/lazy/src/responsive.rs +++ b/lazy/src/responsive.rs @@ -145,8 +145,6 @@ where _renderer: &Renderer, limits: &layout::Limits, ) -> layout::Node { - let _ = self.content.borrow_mut().layout.take(); - layout::Node::new(limits.max()) } @@ -186,7 +184,10 @@ where let state = tree.state.downcast_mut::(); let mut content = self.content.borrow_mut(); - content.resolve( + let mut local_messages = vec![]; + let mut local_shell = Shell::new(&mut local_messages); + + let status = content.resolve( &mut state.tree.borrow_mut(), renderer, layout, @@ -199,10 +200,18 @@ where cursor_position, renderer, clipboard, - shell, + &mut local_shell, ) }, - ) + ); + + if local_shell.is_layout_invalid() { + let _ = content.layout.take(); + } + + shell.merge(local_shell, std::convert::identity); + + status } fn draw( -- cgit From f42fb6af54ea6057a8476704c6756b59c3f3d631 Mon Sep 17 00:00:00 2001 From: Cory Forsstrom Date: Mon, 17 Apr 2023 19:04:27 -0700 Subject: Update lazy/src/responsive.rs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Héctor Ramón --- lazy/src/responsive.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lazy/src/responsive.rs b/lazy/src/responsive.rs index 2f097ff5..88ed6312 100644 --- a/lazy/src/responsive.rs +++ b/lazy/src/responsive.rs @@ -206,7 +206,7 @@ where ); if local_shell.is_layout_invalid() { - let _ = content.layout.take(); + content.layout = None; } shell.merge(local_shell, std::convert::identity); -- cgit From 399a22e61d8b3c265be636aab3645aba62dd5c89 Mon Sep 17 00:00:00 2001 From: Casper Rogild Storm Date: Thu, 20 Apr 2023 12:17:11 +0200 Subject: Centered icon vertically --- native/src/widget/text_input.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/native/src/widget/text_input.rs b/native/src/widget/text_input.rs index 8627aa98..6113cf94 100644 --- a/native/src/widget/text_input.rs +++ b/native/src/widget/text_input.rs @@ -970,9 +970,12 @@ pub fn draw( size: icon.size.unwrap_or_else(|| renderer.default_size()), font: icon.font.clone(), color: appearance.icon_color, - bounds: icon_layout.bounds(), + bounds: Rectangle { + y: text_bounds.center_y(), + ..icon_layout.bounds() + }, horizontal_alignment: alignment::Horizontal::Left, - vertical_alignment: alignment::Vertical::Top, + vertical_alignment: alignment::Vertical::Center, }); } -- cgit From 2e9129582a88ee0758c215847b0ec49baab79f11 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Thu, 20 Apr 2023 15:25:37 +0200 Subject: Fix sliders drawing out of their bounds --- native/src/widget/slider.rs | 4 ++-- native/src/widget/vertical_slider.rs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/native/src/widget/slider.rs b/native/src/widget/slider.rs index ba467834..cfb0a8fe 100644 --- a/native/src/widget/slider.rs +++ b/native/src/widget/slider.rs @@ -391,7 +391,7 @@ pub fn draw( let offset = if range_start >= range_end { 0.0 } else { - (bounds.width - handle_width / 2.0) * (value - range_start) + (bounds.width - handle_width) * (value - range_start) / (range_end - range_start) }; @@ -417,7 +417,7 @@ pub fn draw( bounds: Rectangle { x: bounds.x + offset + handle_width / 2.0, y: rail_y - style.rail.width / 2.0, - width: bounds.width - offset, + width: bounds.width - offset - handle_width / 2.0, height: style.rail.width, }, border_radius: Default::default(), diff --git a/native/src/widget/vertical_slider.rs b/native/src/widget/vertical_slider.rs index 5af69676..cb2de480 100644 --- a/native/src/widget/vertical_slider.rs +++ b/native/src/widget/vertical_slider.rs @@ -384,7 +384,7 @@ pub fn draw( let offset = if range_start >= range_end { 0.0 } else { - (bounds.height - handle_width / 2.0) * (value - range_end) + (bounds.height - handle_width) * (value - range_end) / (range_start - range_end) }; @@ -411,7 +411,7 @@ pub fn draw( x: rail_x - style.rail.width / 2.0, y: bounds.y + offset + handle_width / 2.0, width: style.rail.width, - height: bounds.height - offset, + height: bounds.height - offset - handle_width / 2.0, }, border_radius: Default::default(), border_width: 0.0, -- cgit From 477d9bd6ad0f6653f270e624eb4d31683779dc0a Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Thu, 20 Apr 2023 15:26:26 +0200 Subject: Bump version of `iced_native` :tada: --- native/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/native/Cargo.toml b/native/Cargo.toml index 869c1bb0..d0ec403d 100644 --- a/native/Cargo.toml +++ b/native/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "iced_native" -version = "0.10.1" +version = "0.10.2" authors = ["Héctor Ramón Jiménez "] edition = "2021" description = "A renderer-agnostic library for native GUIs" -- cgit From 2155d0af1f76b12cd05a1b8dba1afc1e5ecdefe5 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Thu, 20 Apr 2023 15:31:15 +0200 Subject: Bump version of `iced_native` :tada: --- native/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/native/Cargo.toml b/native/Cargo.toml index d0ec403d..5ba06b67 100644 --- a/native/Cargo.toml +++ b/native/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "iced_native" -version = "0.10.2" +version = "0.10.3" authors = ["Héctor Ramón Jiménez "] edition = "2021" description = "A renderer-agnostic library for native GUIs" -- cgit From 8a711408de26c53cf6b18045ea19c677e8edbd95 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Thu, 20 Apr 2023 15:48:34 +0200 Subject: Compare absolute offsets as well in `notify_on_scroll` --- native/src/widget/scrollable.rs | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/native/src/widget/scrollable.rs b/native/src/widget/scrollable.rs index c66a166b..c9ad5947 100644 --- a/native/src/widget/scrollable.rs +++ b/native/src/widget/scrollable.rs @@ -913,14 +913,21 @@ fn notify_on_scroll( // Don't publish redundant viewports to shell if let Some(last_notified) = state.last_notified { - let prev = last_notified.relative_offset(); - let curr = viewport.relative_offset(); + let last_relative_offset = last_notified.relative_offset(); + let current_relative_offset = viewport.relative_offset(); + + let last_absolute_offset = last_notified.absolute_offset(); + let current_absolute_offset = viewport.absolute_offset(); let unchanged = |a: f32, b: f32| { (a - b).abs() <= f32::EPSILON || (a.is_nan() && b.is_nan()) }; - if unchanged(prev.x, curr.x) && unchanged(prev.y, curr.y) { + if unchanged(last_relative_offset.x, current_relative_offset.x) + && unchanged(last_relative_offset.y, current_relative_offset.y) + && unchanged(last_absolute_offset.x, current_absolute_offset.x) + && unchanged(last_absolute_offset.y, current_absolute_offset.y) + { return; } } -- cgit From a38bf092a88a2d59a11d7bc428c7c242840d7d6d Mon Sep 17 00:00:00 2001 From: Cory Forsstrom Date: Thu, 20 Apr 2023 13:34:38 -0700 Subject: Export scroll_to helper --- native/src/widget/scrollable.rs | 9 +++++++++ src/widget.rs | 4 ++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/native/src/widget/scrollable.rs b/native/src/widget/scrollable.rs index c9ad5947..e35a4f96 100644 --- a/native/src/widget/scrollable.rs +++ b/native/src/widget/scrollable.rs @@ -392,6 +392,15 @@ pub fn snap_to( Command::widget(operation::scrollable::snap_to(id.0, offset)) } +/// Produces a [`Command`] that scrolls the [`Scrollable`] with the given [`Id`] +/// to the provided [`AbsoluteOffset`] along the x & y axis. +pub fn scroll_to( + id: Id, + offset: AbsoluteOffset, +) -> Command { + Command::widget(operation::scrollable::scroll_to(id.0, offset)) +} + /// Computes the layout of a [`Scrollable`]. pub fn layout( renderer: &Renderer, diff --git a/src/widget.rs b/src/widget.rs index 38995a45..1163904d 100644 --- a/src/widget.rs +++ b/src/widget.rs @@ -109,8 +109,8 @@ pub mod radio { pub mod scrollable { //! Navigate an endless amount of content with a scrollbar. pub use iced_native::widget::scrollable::{ - snap_to, style::Scrollbar, style::Scroller, AbsoluteOffset, Id, - Properties, RelativeOffset, StyleSheet, Viewport, + scroll_to, snap_to, style::Scrollbar, style::Scroller, AbsoluteOffset, + Id, Properties, RelativeOffset, StyleSheet, Viewport, }; /// A widget that can vertically display an infinite amount of content -- cgit From 8122904ca46b73ceda54bd73bd68cf4138d22f1b Mon Sep 17 00:00:00 2001 From: David Huculak Date: Thu, 20 Apr 2023 21:28:47 -0400 Subject: wgpu 0.16 --- examples/integration_wgpu/src/main.rs | 3 +-- wgpu/Cargo.toml | 4 ++-- wgpu/src/image/atlas.rs | 4 ++-- wgpu/src/window/compositor.rs | 2 +- 4 files changed, 6 insertions(+), 7 deletions(-) diff --git a/examples/integration_wgpu/src/main.rs b/examples/integration_wgpu/src/main.rs index 3ac458b3..7b9f4d4c 100644 --- a/examples/integration_wgpu/src/main.rs +++ b/examples/integration_wgpu/src/main.rs @@ -72,7 +72,6 @@ pub fn main() -> Result<(), Box> { backends: backend, ..Default::default() }); - let surface = unsafe { instance.create_surface(&window) }?; let (format, (device, queue)) = futures::executor::block_on(async { @@ -99,7 +98,7 @@ pub fn main() -> Result<(), Box> { capabilities .formats .iter() - .filter(|format| format.describe().srgb) + .filter(|format| format.is_srgb()) .copied() .next() .or_else(|| capabilities.formats.first().copied()) diff --git a/wgpu/Cargo.toml b/wgpu/Cargo.toml index 3478ef59..1ce07e0a 100644 --- a/wgpu/Cargo.toml +++ b/wgpu/Cargo.toml @@ -28,8 +28,8 @@ spirv = ["wgpu/spirv"] webgl = ["wgpu/webgl"] [dependencies] -wgpu = "0.15" -wgpu_glyph = "0.19" +wgpu = "0.16" +wgpu_glyph = "0.20" glyph_brush = "0.7" raw-window-handle = "0.5" log = "0.4" diff --git a/wgpu/src/image/atlas.rs b/wgpu/src/image/atlas.rs index 82504147..1384949a 100644 --- a/wgpu/src/image/atlas.rs +++ b/wgpu/src/image/atlas.rs @@ -209,8 +209,8 @@ impl Atlas { buffer, layout: wgpu::ImageDataLayout { offset: offset as u64, - bytes_per_row: NonZeroU32::new(4 * image_width + padding), - rows_per_image: NonZeroU32::new(image_height), + bytes_per_row: Some(4 * image_width + padding), + rows_per_image: Some(image_height), }, }, wgpu::ImageCopyTexture { diff --git a/wgpu/src/window/compositor.rs b/wgpu/src/window/compositor.rs index d4a59471..8969ad6c 100644 --- a/wgpu/src/window/compositor.rs +++ b/wgpu/src/window/compositor.rs @@ -71,7 +71,7 @@ impl Compositor { capabilities .formats .iter() - .filter(|format| format.describe().srgb) + .filter(|format| format.is_srgb()) .copied() .next() .or_else(|| { -- cgit From cbb2ba38faadc52b9523918a2fbc2e2a78de9087 Mon Sep 17 00:00:00 2001 From: David Huculak Date: Thu, 20 Apr 2023 21:38:52 -0400 Subject: remove unused import --- wgpu/src/image/atlas.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/wgpu/src/image/atlas.rs b/wgpu/src/image/atlas.rs index 1384949a..a0fdf146 100644 --- a/wgpu/src/image/atlas.rs +++ b/wgpu/src/image/atlas.rs @@ -15,8 +15,6 @@ pub const SIZE: u32 = 2048; use iced_graphics::image; use iced_graphics::Size; -use std::num::NonZeroU32; - #[derive(Debug)] pub struct Atlas { texture: wgpu::Texture, -- cgit From 3f0c226b74c6d0271e550161b6542e652c1875ca Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Fri, 21 Apr 2023 21:36:30 +0200 Subject: Use point-free notation --- examples/integration_wgpu/src/main.rs | 2 +- wgpu/src/window/compositor.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/integration_wgpu/src/main.rs b/examples/integration_wgpu/src/main.rs index 7b9f4d4c..f5fe7636 100644 --- a/examples/integration_wgpu/src/main.rs +++ b/examples/integration_wgpu/src/main.rs @@ -98,8 +98,8 @@ pub fn main() -> Result<(), Box> { capabilities .formats .iter() - .filter(|format| format.is_srgb()) .copied() + .filter(wgpu::TextureFormat::is_srgb) .next() .or_else(|| capabilities.formats.first().copied()) .expect("Get preferred format"), diff --git a/wgpu/src/window/compositor.rs b/wgpu/src/window/compositor.rs index 8969ad6c..3c51768a 100644 --- a/wgpu/src/window/compositor.rs +++ b/wgpu/src/window/compositor.rs @@ -71,8 +71,8 @@ impl Compositor { capabilities .formats .iter() - .filter(|format| format.is_srgb()) .copied() + .filter(wgpu::TextureFormat::is_srgb) .next() .or_else(|| { log::warn!("No sRGB format found!"); -- cgit From ecc1a4509ab25611397386c9f9c85fe7b269fda3 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Fri, 21 Apr 2023 21:40:43 +0200 Subject: Avoid cloning `layout::Node` in `Responsive` widget --- lazy/src/responsive.rs | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/lazy/src/responsive.rs b/lazy/src/responsive.rs index 88ed6312..d87815f6 100644 --- a/lazy/src/responsive.rs +++ b/lazy/src/responsive.rs @@ -58,7 +58,7 @@ impl<'a, Message, Renderer> Content<'a, Message, Renderer> where Renderer: iced_native::Renderer, { - fn layout(&mut self, renderer: &Renderer) -> layout::Node { + fn layout(&mut self, renderer: &Renderer) { if self.layout.is_none() { self.layout = Some(self.element.as_widget().layout( @@ -66,8 +66,6 @@ where &layout::Limits::new(Size::ZERO, self.size), )); } - - self.layout.clone().unwrap() } fn update( @@ -103,11 +101,12 @@ where R: Deref, { self.update(tree, layout.bounds().size(), view); + self.layout(renderer.deref()); - let node = self.layout(renderer.deref()); - - let content_layout = - Layout::with_offset(layout.position() - Point::ORIGIN, &node); + let content_layout = Layout::with_offset( + layout.position() - Point::ORIGIN, + self.layout.as_ref().unwrap(), + ); f(tree, renderer, content_layout, &mut self.element) } @@ -290,14 +289,17 @@ where types: PhantomData, overlay_builder: |content: &mut RefMut>, tree| { content.update(tree, layout.bounds().size(), &self.view); + content.layout(renderer); - let node = content.layout(renderer); - - let Content { element, .. } = content.deref_mut(); + let Content { + element, + layout: content_layout_node, + .. + } = content.deref_mut(); let content_layout = Layout::with_offset( layout.bounds().position() - Point::ORIGIN, - &node, + content_layout_node.as_ref().unwrap(), ); element -- cgit From cc20baad6f422271f052cf68474a4aee40dcdc82 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Fri, 21 Apr 2023 21:46:02 +0200 Subject: Use `find(..)` instead of `filter(..).next()` --- examples/integration_wgpu/src/main.rs | 3 +-- wgpu/src/window/compositor.rs | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/examples/integration_wgpu/src/main.rs b/examples/integration_wgpu/src/main.rs index f5fe7636..15901db8 100644 --- a/examples/integration_wgpu/src/main.rs +++ b/examples/integration_wgpu/src/main.rs @@ -99,8 +99,7 @@ pub fn main() -> Result<(), Box> { .formats .iter() .copied() - .filter(wgpu::TextureFormat::is_srgb) - .next() + .find(wgpu::TextureFormat::is_srgb) .or_else(|| capabilities.formats.first().copied()) .expect("Get preferred format"), adapter diff --git a/wgpu/src/window/compositor.rs b/wgpu/src/window/compositor.rs index 3c51768a..53af19bf 100644 --- a/wgpu/src/window/compositor.rs +++ b/wgpu/src/window/compositor.rs @@ -72,8 +72,7 @@ impl Compositor { .formats .iter() .copied() - .filter(wgpu::TextureFormat::is_srgb) - .next() + .find(wgpu::TextureFormat::is_srgb) .or_else(|| { log::warn!("No sRGB format found!"); -- cgit From dcc9a7073449a7cecafb913c0a27ecb3bd66bab1 Mon Sep 17 00:00:00 2001 From: Carlos Pizarro Date: Fri, 28 Apr 2023 08:36:14 -0400 Subject: Fix small typo on `ROADMAP.md` Link works properly now --- ROADMAP.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ROADMAP.md b/ROADMAP.md index c30c591b..f1893664 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -49,7 +49,7 @@ As a first approach, we could expose the underlying renderer directly here, and In the long run, we could expose a renderer-agnostic abstraction to perform the drawing. [#32]: https://github.com/iced-rs/iced/issues/32 -[#343] https://github.com/iced-rs/iced/issues/343 +[#343]: https://github.com/iced-rs/iced/issues/343 ### Text shaping and font fallback ([#33]) [`wgpu_glyph`] uses [`glyph_brush`], which in turn uses [`rusttype`]. While the current implementation is able to layout text quite nicely, it does not perform any [text shaping]. -- cgit