Touch support for `PaneGrid` and `PickList` (#650)

* touch events properly parsed and converted to logical size, button working

* scrolling with a nice touch

* fixed application state level touch cursor. panel_grid is touchable now.

* format glicthes fixes

* format glitches

* tight format

* fixed pane grid

* fixing with upstream

* Remove unused `touch` module from `iced_core`

* Remove unused `crate::text` import in `iced_native`

* Remove redundant match branch in `iced_winit`

* Keep removed line break in `UserInterface::update`

* Compute `text_size` only when bounds contains cursor in `overlay::menu`

Co-authored-by: Héctor Ramón Jiménez <hector0193@gmail.com>
This commit is contained in:
anunge 2021-02-12 21:52:20 +02:00 committed by GitHub
parent 2f10a1f2a2
commit 9e453843b2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 93 additions and 71 deletions

View File

@ -6,6 +6,7 @@ use crate::mouse;
use crate::overlay; use crate::overlay;
use crate::scrollable; use crate::scrollable;
use crate::text; use crate::text;
use crate::touch;
use crate::{ use crate::{
Clipboard, Container, Element, Hasher, Layout, Length, Point, Rectangle, Clipboard, Container, Element, Hasher, Layout, Length, Point, Rectangle,
Scrollable, Size, Vector, Widget, Scrollable, Size, Vector, Widget,
@ -337,10 +338,11 @@ where
} }
Event::Mouse(mouse::Event::CursorMoved { .. }) => { Event::Mouse(mouse::Event::CursorMoved { .. }) => {
let bounds = layout.bounds(); let bounds = layout.bounds();
let text_size =
self.text_size.unwrap_or(renderer.default_size());
if bounds.contains(cursor_position) { if bounds.contains(cursor_position) {
let text_size =
self.text_size.unwrap_or(renderer.default_size());
*self.hovered_option = Some( *self.hovered_option = Some(
((cursor_position.y - bounds.y) ((cursor_position.y - bounds.y)
/ f32::from(text_size + self.padding * 2)) / f32::from(text_size + self.padding * 2))
@ -348,6 +350,26 @@ where
); );
} }
} }
Event::Touch(touch::Event::FingerPressed { .. }) => {
let bounds = layout.bounds();
if bounds.contains(cursor_position) {
let text_size =
self.text_size.unwrap_or(renderer.default_size());
*self.hovered_option = Some(
((cursor_position.y - bounds.y)
/ f32::from(text_size + self.padding * 2))
as usize,
);
if let Some(index) = *self.hovered_option {
if let Some(option) = self.options.get(index) {
*self.last_selection = Some(option.clone());
}
}
}
}
_ => {} _ => {}
} }

View File

@ -33,6 +33,7 @@ use crate::layout;
use crate::mouse; use crate::mouse;
use crate::overlay; use crate::overlay;
use crate::row; use crate::row;
use crate::touch;
use crate::{ use crate::{
Clipboard, Element, Hasher, Layout, Length, Point, Rectangle, Size, Vector, Clipboard, Element, Hasher, Layout, Length, Point, Rectangle, Size, Vector,
Widget, Widget,
@ -368,42 +369,34 @@ where
let mut event_status = event::Status::Ignored; let mut event_status = event::Status::Ignored;
match event { match event {
Event::Mouse(mouse_event) => match mouse_event { Event::Mouse(mouse::Event::ButtonPressed(mouse::Button::Left))
mouse::Event::ButtonPressed(mouse::Button::Left) => { | Event::Touch(touch::Event::FingerPressed { .. }) => {
let bounds = layout.bounds(); let bounds = layout.bounds();
if bounds.contains(cursor_position) { if bounds.contains(cursor_position) {
event_status = event::Status::Captured; event_status = event::Status::Captured;
match self.on_resize { match self.on_resize {
Some((leeway, _)) => { Some((leeway, _)) => {
let relative_cursor = Point::new( let relative_cursor = Point::new(
cursor_position.x - bounds.x, cursor_position.x - bounds.x,
cursor_position.y - bounds.y, cursor_position.y - bounds.y,
); );
let splits = self.state.split_regions( let splits = self.state.split_regions(
f32::from(self.spacing), f32::from(self.spacing),
Size::new(bounds.width, bounds.height), Size::new(bounds.width, bounds.height),
); );
let clicked_split = hovered_split( let clicked_split = hovered_split(
splits.iter(), splits.iter(),
f32::from(self.spacing + leeway), f32::from(self.spacing + leeway),
relative_cursor, relative_cursor,
); );
if let Some((split, axis, _)) = clicked_split { if let Some((split, axis, _)) = clicked_split {
self.state.pick_split(&split, axis); self.state.pick_split(&split, axis);
} else { } else {
self.click_pane(
layout,
cursor_position,
messages,
);
}
}
None => {
self.click_pane( self.click_pane(
layout, layout,
cursor_position, cursor_position,
@ -411,47 +404,51 @@ where
); );
} }
} }
} None => {
} self.click_pane(layout, cursor_position, messages);
mouse::Event::ButtonReleased(mouse::Button::Left) => {
if let Some((pane, _)) = self.state.picked_pane() {
if let Some(on_drag) = &self.on_drag {
let mut dropped_region = self
.elements
.iter()
.zip(layout.children())
.filter(|(_, layout)| {
layout.bounds().contains(cursor_position)
});
let event = match dropped_region.next() {
Some(((target, _), _)) if pane != *target => {
DragEvent::Dropped {
pane,
target: *target,
}
}
_ => DragEvent::Canceled { pane },
};
messages.push(on_drag(event));
} }
self.state.idle();
event_status = event::Status::Captured;
} else if self.state.picked_split().is_some() {
self.state.idle();
event_status = event::Status::Captured;
} }
} }
mouse::Event::CursorMoved { .. } => { }
event_status = Event::Mouse(mouse::Event::ButtonReleased(mouse::Button::Left))
self.trigger_resize(layout, cursor_position, messages); | Event::Touch(touch::Event::FingerLifted { .. })
| Event::Touch(touch::Event::FingerLost { .. }) => {
if let Some((pane, _)) = self.state.picked_pane() {
if let Some(on_drag) = &self.on_drag {
let mut dropped_region =
self.elements.iter().zip(layout.children()).filter(
|(_, layout)| {
layout.bounds().contains(cursor_position)
},
);
let event = match dropped_region.next() {
Some(((target, _), _)) if pane != *target => {
DragEvent::Dropped {
pane,
target: *target,
}
}
_ => DragEvent::Canceled { pane },
};
messages.push(on_drag(event));
}
self.state.idle();
event_status = event::Status::Captured;
} else if self.state.picked_split().is_some() {
self.state.idle();
event_status = event::Status::Captured;
} }
_ => {} }
}, Event::Mouse(mouse::Event::CursorMoved { .. })
| Event::Touch(touch::Event::FingerMoved { .. }) => {
event_status =
self.trigger_resize(layout, cursor_position, messages);
}
_ => {} _ => {}
} }

View File

@ -6,6 +6,7 @@ use crate::overlay;
use crate::overlay::menu::{self, Menu}; use crate::overlay::menu::{self, Menu};
use crate::scrollable; use crate::scrollable;
use crate::text; use crate::text;
use crate::touch;
use crate::{ use crate::{
Clipboard, Element, Hasher, Layout, Length, Point, Rectangle, Size, Widget, Clipboard, Element, Hasher, Layout, Length, Point, Rectangle, Size, Widget,
}; };
@ -214,7 +215,8 @@ where
_clipboard: Option<&dyn Clipboard>, _clipboard: Option<&dyn Clipboard>,
) -> event::Status { ) -> event::Status {
match event { match event {
Event::Mouse(mouse::Event::ButtonPressed(mouse::Button::Left)) => { Event::Mouse(mouse::Event::ButtonPressed(mouse::Button::Left))
| Event::Touch(touch::Event::FingerPressed { .. }) => {
let event_status = if *self.is_open { let event_status = if *self.is_open {
// TODO: Encode cursor availability in the type system // TODO: Encode cursor availability in the type system
*self.is_open = *self.is_open =

View File

@ -19,6 +19,7 @@ impl Pipeline {
let default_font = default_font.map(|slice| slice.to_vec()); let default_font = default_font.map(|slice| slice.to_vec());
// TODO: Font customization // TODO: Font customization
#[cfg(not(target_os = "ios"))]
#[cfg(feature = "default_system_font")] #[cfg(feature = "default_system_font")]
let default_font = { let default_font = {
default_font.or_else(|| { default_font.or_else(|| {