From fe17641d46b47f60fc2baa68bb7a0c4e137aa628 Mon Sep 17 00:00:00 2001 From: Artur Sapek Date: Wed, 13 Apr 2022 19:08:53 -0600 Subject: Working multitouch example --- examples/game_of_life/src/main.rs | 17 +++++ examples/multitouch/Cargo.toml | 11 +++ examples/multitouch/src/main.rs | 150 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 178 insertions(+) create mode 100644 examples/multitouch/Cargo.toml create mode 100644 examples/multitouch/src/main.rs (limited to 'examples') diff --git a/examples/game_of_life/src/main.rs b/examples/game_of_life/src/main.rs index a2030275..971ad4d7 100644 --- a/examples/game_of_life/src/main.rs +++ b/examples/game_of_life/src/main.rs @@ -204,6 +204,7 @@ fn view_controls<'a>( mod grid { use crate::Preset; + use iced::touch; use iced::widget::canvas; use iced::widget::canvas::event::{self, Event}; use iced::widget::canvas::{ @@ -423,6 +424,22 @@ mod grid { }; 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 { mouse::Event::ButtonPressed(button) => { let message = match button { diff --git a/examples/multitouch/Cargo.toml b/examples/multitouch/Cargo.toml new file mode 100644 index 00000000..ecd4760c --- /dev/null +++ b/examples/multitouch/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "multitouch" +version = "0.1.0" +authors = ["Artur Sapek "] +edition = "2021" +publish = false + +[dependencies] +iced = { path = "../..", features = ["canvas", "tokio", "debug"] } +tokio = { version = "1.0", features = ["sync"] } +env_logger = "0.9" diff --git a/examples/multitouch/src/main.rs b/examples/multitouch/src/main.rs new file mode 100644 index 00000000..f1d2f216 --- /dev/null +++ b/examples/multitouch/src/main.rs @@ -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, +} + +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) { + ( + Multitouch { + state: State::new(), + }, + Command::none(), + ) + } + + fn title(&self) -> String { + String::from("Multitouch - Iced") + } + + fn update(&mut self, message: Message) -> Command { + 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 { + Subscription::none() + } + + fn view(&self) -> Element { + Canvas::new(&self.state) + .width(Length::Fill) + .height(Length::Fill) + .into() + } +} + +impl<'a> canvas::Program for State { + type State = (); + + fn update( + &self, + _state: &mut Self::State, + event: event::Event, + _bounds: Rectangle, + _cursor: Cursor, + ) -> (event::Status, Option) { + 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 { + 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] + } +} -- cgit