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