Working multitouch example

This commit is contained in:
Artur Sapek 2022-04-13 19:08:53 -06:00 committed by Héctor Ramón Jiménez
parent 4a3c3e2a18
commit fe17641d46
No known key found for this signature in database
GPG key ID: 140CC052C94F138E
4 changed files with 179 additions and 0 deletions

View file

@ -72,6 +72,7 @@ members = [
"examples/geometry", "examples/geometry",
"examples/integration_opengl", "examples/integration_opengl",
"examples/integration_wgpu", "examples/integration_wgpu",
"examples/multitouch",
"examples/pane_grid", "examples/pane_grid",
"examples/pick_list", "examples/pick_list",
"examples/pokedex", "examples/pokedex",

View file

@ -204,6 +204,7 @@ fn view_controls<'a>(
mod grid { mod grid {
use crate::Preset; use crate::Preset;
use iced::touch;
use iced::widget::canvas; use iced::widget::canvas;
use iced::widget::canvas::event::{self, Event}; use iced::widget::canvas::event::{self, Event};
use iced::widget::canvas::{ use iced::widget::canvas::{
@ -423,6 +424,22 @@ mod grid {
}; };
match event { match event {
Event::Touch(touch_event) => match touch_event {
touch::Event::FingerMoved { .. } => {
let message = {
*interaction = if is_populated {
Interaction::Erasing
} else {
Interaction::Drawing
};
populate.or(unpopulate)
};
(event::Status::Captured, message)
}
_ => (event::Status::Ignored, None),
},
Event::Mouse(mouse_event) => match mouse_event { Event::Mouse(mouse_event) => match mouse_event {
mouse::Event::ButtonPressed(button) => { mouse::Event::ButtonPressed(button) => {
let message = match button { let message = match button {

View file

@ -0,0 +1,11 @@
[package]
name = "multitouch"
version = "0.1.0"
authors = ["Artur Sapek <artur@kraken.com>"]
edition = "2021"
publish = false
[dependencies]
iced = { path = "../..", features = ["canvas", "tokio", "debug"] }
tokio = { version = "1.0", features = ["sync"] }
env_logger = "0.9"

View file

@ -0,0 +1,150 @@
//! This example shows how to use touch events in `Canvas` to draw
//! a circle around each fingertip. This only works on touch-enabled
//! computers like Microsoft Surface.
use iced::widget::canvas::event;
use iced::widget::canvas::{self, Canvas, Cursor, Geometry, Path, Stroke};
use iced::{
executor, touch, window, Application, Color, Command, Element, Length,
Point, Rectangle, Settings, Subscription, Theme,
};
use std::collections::HashMap;
pub fn main() -> iced::Result {
env_logger::builder().format_timestamp(None).init();
Multitouch::run(Settings {
antialiasing: true,
window: window::Settings {
position: window::Position::Centered,
..window::Settings::default()
},
..Settings::default()
})
}
struct Multitouch {
state: State,
}
#[derive(Debug)]
struct State {
cache: canvas::Cache,
fingers: HashMap<touch::Finger, Point>,
}
impl State {
fn new() -> Self {
Self {
cache: canvas::Cache::new(),
fingers: HashMap::new(),
}
}
}
#[derive(Debug)]
enum Message {
FingerPressed { id: touch::Finger, position: Point },
FingerLifted { id: touch::Finger },
}
impl Application for Multitouch {
type Executor = executor::Default;
type Message = Message;
type Theme = Theme;
type Flags = ();
fn new(_flags: ()) -> (Self, Command<Message>) {
(
Multitouch {
state: State::new(),
},
Command::none(),
)
}
fn title(&self) -> String {
String::from("Multitouch - Iced")
}
fn update(&mut self, message: Message) -> Command<Message> {
match message {
Message::FingerPressed { id, position } => {
self.state.fingers.insert(id, position.clone());
self.state.cache.clear();
}
Message::FingerLifted { id } => {
self.state.fingers.remove(&id);
self.state.cache.clear();
}
}
Command::none()
}
fn subscription(&self) -> Subscription<Message> {
Subscription::none()
}
fn view(&self) -> Element<Message> {
Canvas::new(&self.state)
.width(Length::Fill)
.height(Length::Fill)
.into()
}
}
impl<'a> canvas::Program<Message> for State {
type State = ();
fn update(
&self,
_state: &mut Self::State,
event: event::Event,
_bounds: Rectangle,
_cursor: Cursor,
) -> (event::Status, Option<Message>) {
match event {
event::Event::Touch(touch_event) => match touch_event {
touch::Event::FingerPressed { id, position }
| touch::Event::FingerMoved { id, position } => (
event::Status::Captured,
Some(Message::FingerPressed { id, position }),
),
touch::Event::FingerLifted { id, .. }
| touch::Event::FingerLost { id, .. } => (
event::Status::Captured,
Some(Message::FingerLifted { id }),
),
},
_ => (event::Status::Ignored, None),
}
}
fn draw(
&self,
_state: &Self::State,
_theme: &Theme,
bounds: Rectangle,
_cursor: Cursor,
) -> Vec<Geometry> {
let fingerweb = self.cache.draw(bounds.size(), |frame| {
for finger in &self.fingers {
dbg!(&finger);
let circle = Path::new(|p| p.circle(*finger.1, 50.0));
frame.stroke(
&circle,
Stroke {
color: Color::BLACK,
width: 3.0,
..Stroke::default()
},
);
}
});
vec![fingerweb]
}
}