diff options
-rw-r--r-- | examples/combo_box/src/main.rs | 20 | ||||
-rw-r--r-- | widget/src/combo_box.rs | 42 | ||||
-rw-r--r-- | widget/src/overlay/menu.rs | 23 | ||||
-rw-r--r-- | widget/src/pick_list.rs | 1 |
4 files changed, 63 insertions, 23 deletions
diff --git a/examples/combo_box/src/main.rs b/examples/combo_box/src/main.rs index 22d05132..2e6f95d5 100644 --- a/examples/combo_box/src/main.rs +++ b/examples/combo_box/src/main.rs @@ -15,9 +15,9 @@ struct Example { #[derive(Debug, Clone, Copy)] enum Message { - LanguageSelected(Language), - LanguagePreview(Language), - LanguageBlurred, + Selected(Language), + OptionHovered(Language), + Closed, } impl Sandbox for Example { @@ -37,15 +37,15 @@ impl Sandbox for Example { fn update(&mut self, message: Message) { match message { - Message::LanguageSelected(language) => { + Message::Selected(language) => { self.selected_language = Some(language); self.text = language.hello().to_string(); self.languages.unfocus(); } - Message::LanguagePreview(language) => { + Message::OptionHovered(language) => { self.text = language.hello().to_string(); } - Message::LanguageBlurred => { + Message::Closed => { self.text = self .selected_language .map(|language| language.hello().to_string()) @@ -59,17 +59,17 @@ impl Sandbox for Example { &self.languages, "Type a language...", self.selected_language.as_ref(), - Message::LanguageSelected, + Message::Selected, ) - .on_selection(Message::LanguagePreview) - .on_blur(Message::LanguageBlurred) + .on_option_hovered(Message::OptionHovered) + .on_close(Message::Closed) .width(250); let content = column![ + text(&self.text), "What is your language?", combo_box, vertical_space(150), - text(&self.text), ] .width(Length::Fill) .align_items(Alignment::Center) diff --git a/widget/src/combo_box.rs b/widget/src/combo_box.rs index 91a91c32..14fe2528 100644 --- a/widget/src/combo_box.rs +++ b/widget/src/combo_box.rs @@ -32,8 +32,8 @@ where font: Option<Renderer::Font>, selection: text_input::Value, on_selected: Box<dyn Fn(T) -> Message>, - on_selection: Option<Box<dyn Fn(T) -> Message>>, - on_blur: Option<Message>, + on_option_hovered: Option<Box<dyn Fn(T) -> Message>>, + on_close: Option<Message>, on_input: Option<Box<dyn Fn(String) -> Message>>, menu_style: <Renderer::Theme as menu::StyleSheet>::Style, padding: Padding, @@ -66,9 +66,9 @@ where font: None, selection: text_input::Value::new(&selection), on_selected: Box::new(on_selected), - on_selection: None, + on_option_hovered: None, on_input: None, - on_blur: None, + on_close: None, menu_style: Default::default(), padding: text_input::DEFAULT_PADDING, size: None, @@ -87,18 +87,18 @@ where /// Sets the message that will be produced when an option of the /// [`ComboBox`] is hovered using the arrow keys. - pub fn on_selection( + pub fn on_option_hovered( mut self, on_selection: impl Fn(T) -> Message + 'static, ) -> Self { - self.on_selection = Some(Box::new(on_selection)); + self.on_option_hovered = Some(Box::new(on_selection)); self } /// Sets the message that will be produced when the outside area /// of the [`ComboBox`] is pressed. - pub fn on_blur(mut self, message: Message) -> Self { - self.on_blur = Some(message); + pub fn on_close(mut self, message: Message) -> Self { + self.on_close = Some(message); self } @@ -424,6 +424,7 @@ where // Then finally react to them here for message in local_messages { let TextInputEvent::TextChanged(new_value) = message; + if let Some(on_input) = &self.on_input { shell.publish((on_input)(new_value.clone())); published_message_to_shell = true; @@ -451,6 +452,20 @@ where if self.state.is_focused() { self.state.with_inner(|state| { + if !started_focused { + if let Some(on_option_hovered) = &mut self.on_option_hovered + { + let hovered_option = menu.hovered_option.unwrap_or(0); + + if let Some(option) = + state.filtered_options.options.get(hovered_option) + { + shell.publish(on_option_hovered(option.clone())); + published_message_to_shell = true; + } + } + } + if let Event::Keyboard(keyboard::Event::KeyPressed { key_code, .. @@ -475,7 +490,9 @@ where menu.hovered_option = Some(0); } - if let Some(on_selection) = &mut self.on_selection { + if let Some(on_selection) = + &mut self.on_option_hovered + { if let Some(option) = menu.hovered_option.and_then(|index| { state @@ -507,7 +524,9 @@ where menu.hovered_option = Some(0); } - if let Some(on_selection) = &mut self.on_selection { + if let Some(on_selection) = + &mut self.on_option_hovered + { if let Some(option) = menu.hovered_option.and_then(|index| { state @@ -566,7 +585,7 @@ where && !self.state.is_focused() && !published_message_to_shell { - if let Some(message) = self.on_blur.take() { + if let Some(message) = self.on_close.take() { shell.publish(message); } } @@ -637,6 +656,7 @@ where &filtered_options.options, hovered_option, |x| (self.on_selected)(x), + self.on_option_hovered.as_deref(), ) .width(bounds.width) .padding(self.padding) diff --git a/widget/src/overlay/menu.rs b/widget/src/overlay/menu.rs index 72662422..f7bdeef6 100644 --- a/widget/src/overlay/menu.rs +++ b/widget/src/overlay/menu.rs @@ -28,6 +28,7 @@ where options: &'a [T], hovered_option: &'a mut Option<usize>, on_selected: Box<dyn FnMut(T) -> Message + 'a>, + on_option_hovered: Option<&'a dyn Fn(T) -> Message>, width: f32, padding: Padding, text_size: Option<f32>, @@ -52,12 +53,14 @@ where options: &'a [T], hovered_option: &'a mut Option<usize>, on_selected: impl FnMut(T) -> Message + 'a, + on_option_hovered: Option<&'a dyn Fn(T) -> Message>, ) -> Self { Menu { state, options, hovered_option, on_selected: Box::new(on_selected), + on_option_hovered, width: 0.0, padding: Padding::ZERO, text_size: None, @@ -187,6 +190,7 @@ where options, hovered_option, on_selected, + on_option_hovered, width, padding, font, @@ -200,6 +204,7 @@ where options, hovered_option, on_selected, + on_option_hovered, font, text_size, text_line_height, @@ -321,6 +326,7 @@ where options: &'a [T], hovered_option: &'a mut Option<usize>, on_selected: Box<dyn FnMut(T) -> Message + 'a>, + on_option_hovered: Option<&'a dyn Fn(T) -> Message>, padding: Padding, text_size: Option<f32>, text_line_height: text::LineHeight, @@ -405,8 +411,21 @@ where self.text_line_height.to_absolute(Pixels(text_size)), ) + self.padding.vertical(); - *self.hovered_option = - Some((cursor_position.y / option_height) as usize); + let new_hovered_option = + (cursor_position.y / option_height) as usize; + + if let Some(on_option_hovered) = self.on_option_hovered { + if *self.hovered_option != Some(new_hovered_option) { + if let Some(option) = + self.options.get(new_hovered_option) + { + shell + .publish(on_option_hovered(option.clone())); + } + } + } + + *self.hovered_option = Some(new_hovered_option); } } Event::Touch(touch::Event::FingerPressed { .. }) => { diff --git a/widget/src/pick_list.rs b/widget/src/pick_list.rs index d99ada10..0a1e2a99 100644 --- a/widget/src/pick_list.rs +++ b/widget/src/pick_list.rs @@ -566,6 +566,7 @@ where (on_selected)(option) }, + None, ) .width(bounds.width) .padding(padding) |