From 77e6e111e0f655487076ce0e4605fd3b143e0320 Mon Sep 17 00:00:00 2001 From: 13r0ck Date: Mon, 10 May 2021 14:29:35 -0600 Subject: [PATCH 1/6] add scrolling to pick_lists --- native/src/widget/pick_list.rs | 68 ++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) diff --git a/native/src/widget/pick_list.rs b/native/src/widget/pick_list.rs index 046d57791a..eba1525338 100644 --- a/native/src/widget/pick_list.rs +++ b/native/src/widget/pick_list.rs @@ -25,6 +25,7 @@ where on_selected: Box Message>, options: Cow<'a, [T]>, selected: Option, + on_change: Option, width: Length, padding: u16, text_size: Option, @@ -82,6 +83,7 @@ where on_selected: Box::new(on_selected), options: options.into(), selected, + on_change: None, width: Length::Shrink, text_size: None, padding: Renderer::DEFAULT_PADDING, @@ -114,6 +116,12 @@ where self } + /// Sets the message sent when [`PickList`] selection changes + pub fn on_change(mut self, msg: Message) -> Self { + self.on_change = Some(msg); + self + } + /// Sets the style of the [`PickList`]. pub fn style( mut self, @@ -247,6 +255,66 @@ where event_status } } + Event::Mouse(mouse::Event::WheelScrolled { delta }) + if layout.bounds().contains(cursor_position) + && !*self.is_open => + { + let y = match delta { + mouse::ScrollDelta::Lines { y, .. } + | mouse::ScrollDelta::Pixels { y, .. } => y, + }; + + if y.is_sign_negative() { + if let Some(selected) = self.selected.as_ref() { + let i = self + .options + .iter() + .position(|option| option == selected) + .unwrap_or(0) + + 1; + if i < self.options.len() { + messages.push((self.on_selected)( + self.options[i].clone(), + )); + if let Some(msg) = self.on_change.take() { + messages.push(msg) + } + } + } else { + messages + .push((self.on_selected)(self.options[0].clone())); + if let Some(msg) = self.on_change.take() { + messages.push(msg) + } + } + } else { + if let Some(selected) = self.selected.as_ref() { + let i = self + .options + .iter() + .position(|option| option == selected) + .unwrap_or(0); + if i != 0 { + messages.push((self.on_selected)( + self.options[i - 1].clone(), + )); + if let Some(msg) = self.on_change.take() { + messages.push(msg) + } + } + } else { + messages.push((self.on_selected)( + self.options[self.options.len() - 1].clone(), + )); + if let Some(msg) = self.on_change.take() { + messages.push(msg) + } + } + } + + return event::Status::Captured; + } + _ => event::Status::Ignored, } } From 8f319d7c6fde1efb1e88a15ed19ce93aef3d26c4 Mon Sep 17 00:00:00 2001 From: 13r0ck Date: Mon, 10 May 2021 16:05:50 -0600 Subject: [PATCH 2/6] Improve performance using iters --- native/src/widget/pick_list.rs | 31 ++++++++----------------------- 1 file changed, 8 insertions(+), 23 deletions(-) diff --git a/native/src/widget/pick_list.rs b/native/src/widget/pick_list.rs index eba1525338..f2f6ba2d7a 100644 --- a/native/src/widget/pick_list.rs +++ b/native/src/widget/pick_list.rs @@ -265,19 +265,11 @@ where }; if y.is_sign_negative() { + let mut options_iter = self.options.iter(); if let Some(selected) = self.selected.as_ref() { - let i = self - .options - .iter() - .position(|option| option == selected) - .unwrap_or(0) - + 1; - if i < self.options.len() { - messages.push((self.on_selected)( - self.options[i].clone(), - )); - if let Some(msg) = self.on_change.take() { - messages.push(msg) + if let Some(_) = options_iter.position(|o| o == selected) { + if let Some(prev_val) = options_iter.next() { + messages.push((self.on_selected)(prev_val.clone())); } } } else { @@ -288,18 +280,11 @@ where } } } else { + let mut options_iter = self.options.iter().rev(); if let Some(selected) = self.selected.as_ref() { - let i = self - .options - .iter() - .position(|option| option == selected) - .unwrap_or(0); - if i != 0 { - messages.push((self.on_selected)( - self.options[i - 1].clone(), - )); - if let Some(msg) = self.on_change.take() { - messages.push(msg) + if let Some(_) = options_iter.position(|o| o == selected) { + if let Some(next_val) = options_iter.next() { + messages.push((self.on_selected)(next_val.clone())); } } } else { From 3a9ad8997039631ff633abe7333faad9a2f1c042 Mon Sep 17 00:00:00 2001 From: 13r0ck Date: Mon, 10 May 2021 16:06:39 -0600 Subject: [PATCH 3/6] cargo fmt --- native/src/widget/pick_list.rs | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/native/src/widget/pick_list.rs b/native/src/widget/pick_list.rs index f2f6ba2d7a..fcb1550307 100644 --- a/native/src/widget/pick_list.rs +++ b/native/src/widget/pick_list.rs @@ -267,24 +267,30 @@ where if y.is_sign_negative() { let mut options_iter = self.options.iter(); if let Some(selected) = self.selected.as_ref() { - if let Some(_) = options_iter.position(|o| o == selected) { + if let Some(_) = + options_iter.position(|o| o == selected) + { if let Some(prev_val) = options_iter.next() { - messages.push((self.on_selected)(prev_val.clone())); + messages + .push((self.on_selected)(prev_val.clone())); } } } else { messages .push((self.on_selected)(self.options[0].clone())); - if let Some(msg) = self.on_change.take() { - messages.push(msg) - } + if let Some(msg) = self.on_change.take() { + messages.push(msg) + } } } else { let mut options_iter = self.options.iter().rev(); if let Some(selected) = self.selected.as_ref() { - if let Some(_) = options_iter.position(|o| o == selected) { + if let Some(_) = + options_iter.position(|o| o == selected) + { if let Some(next_val) = options_iter.next() { - messages.push((self.on_selected)(next_val.clone())); + messages + .push((self.on_selected)(next_val.clone())); } } } else { From fbfb28b8d46a56de206cfd84c978f1902effc4f3 Mon Sep 17 00:00:00 2001 From: 13r0ck Date: Tue, 25 May 2021 08:23:04 -0600 Subject: [PATCH 4/6] Remove redundant 'on_change' --- native/src/widget/pick_list.rs | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/native/src/widget/pick_list.rs b/native/src/widget/pick_list.rs index fcb1550307..71c167a646 100644 --- a/native/src/widget/pick_list.rs +++ b/native/src/widget/pick_list.rs @@ -25,7 +25,6 @@ where on_selected: Box Message>, options: Cow<'a, [T]>, selected: Option, - on_change: Option, width: Length, padding: u16, text_size: Option, @@ -83,7 +82,6 @@ where on_selected: Box::new(on_selected), options: options.into(), selected, - on_change: None, width: Length::Shrink, text_size: None, padding: Renderer::DEFAULT_PADDING, @@ -116,12 +114,6 @@ where self } - /// Sets the message sent when [`PickList`] selection changes - pub fn on_change(mut self, msg: Message) -> Self { - self.on_change = Some(msg); - self - } - /// Sets the style of the [`PickList`]. pub fn style( mut self, @@ -278,9 +270,6 @@ where } else { messages .push((self.on_selected)(self.options[0].clone())); - if let Some(msg) = self.on_change.take() { - messages.push(msg) - } } } else { let mut options_iter = self.options.iter().rev(); @@ -297,9 +286,6 @@ where messages.push((self.on_selected)( self.options[self.options.len() - 1].clone(), )); - if let Some(msg) = self.on_change.take() { - messages.push(msg) - } } } From 6069e90c9b1b44c405706e08b608ae39dae0b1f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A9ctor=20Ram=C3=B3n=20Jim=C3=A9nez?= Date: Thu, 22 Jul 2021 21:15:35 +0700 Subject: [PATCH 5/6] Abstract and improve scroll logic in `PickList` --- native/src/widget/pick_list.rs | 46 ++++++++++++++++------------------ 1 file changed, 21 insertions(+), 25 deletions(-) diff --git a/native/src/widget/pick_list.rs b/native/src/widget/pick_list.rs index 71c167a646..667c9f18a5 100644 --- a/native/src/widget/pick_list.rs +++ b/native/src/widget/pick_list.rs @@ -256,37 +256,33 @@ where | mouse::ScrollDelta::Pixels { y, .. } => y, }; - if y.is_sign_negative() { - let mut options_iter = self.options.iter(); + fn find_next<'a, T: PartialEq>( + selected: &'a T, + mut options: impl Iterator, + ) -> Option<&'a T> { + let _ = options.find(|&option| option == selected); + + options.next() + } + + let next_option = if y < 0.0 { if let Some(selected) = self.selected.as_ref() { - if let Some(_) = - options_iter.position(|o| o == selected) - { - if let Some(prev_val) = options_iter.next() { - messages - .push((self.on_selected)(prev_val.clone())); - } - } + find_next(selected, self.options.iter()) } else { - messages - .push((self.on_selected)(self.options[0].clone())); + self.options.first() } - } else { - let mut options_iter = self.options.iter().rev(); + } else if y > 0.0 { if let Some(selected) = self.selected.as_ref() { - if let Some(_) = - options_iter.position(|o| o == selected) - { - if let Some(next_val) = options_iter.next() { - messages - .push((self.on_selected)(next_val.clone())); - } - } + find_next(selected, self.options.iter().rev()) } else { - messages.push((self.on_selected)( - self.options[self.options.len() - 1].clone(), - )); + self.options.last() } + } else { + None + }; + + if let Some(next_option) = next_option { + messages.push((self.on_selected)(next_option.clone())); } return event::Status::Captured; From 46aab24d91eb083a2f030094e33f98ba8e0dad7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A9ctor=20Ram=C3=B3n=20Jim=C3=A9nez?= Date: Thu, 22 Jul 2021 21:28:21 +0700 Subject: [PATCH 6/6] Enable scroll selection for `PickList` only when scroll is discrete --- native/src/widget/pick_list.rs | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/native/src/widget/pick_list.rs b/native/src/widget/pick_list.rs index 667c9f18a5..ddd0d0a299 100644 --- a/native/src/widget/pick_list.rs +++ b/native/src/widget/pick_list.rs @@ -247,15 +247,11 @@ where event_status } } - Event::Mouse(mouse::Event::WheelScrolled { delta }) - if layout.bounds().contains(cursor_position) - && !*self.is_open => + Event::Mouse(mouse::Event::WheelScrolled { + delta: mouse::ScrollDelta::Lines { y, .. }, + }) if layout.bounds().contains(cursor_position) + && !*self.is_open => { - let y = match delta { - mouse::ScrollDelta::Lines { y, .. } - | mouse::ScrollDelta::Pixels { y, .. } => y, - }; - fn find_next<'a, T: PartialEq>( selected: &'a T, mut options: impl Iterator,