diff options
| author | 2022-10-07 16:58:45 -0700 | |
|---|---|---|
| committer | 2022-10-07 16:58:45 -0700 | |
| commit | aabc4e87b51af8025910681dc427260254877e4c (patch) | |
| tree | 44dc50e04e58c15871cc56d22221dc43685d1d58 /examples/multitouch/src | |
| parent | 7a124476b1f609019bb0fdfa1254236af2d2a49e (diff) | |
| parent | 77c838011fe6f8f567389d5994584a1a1b8420c5 (diff) | |
| download | iced-aabc4e87b51af8025910681dc427260254877e4c.tar.gz iced-aabc4e87b51af8025910681dc427260254877e4c.tar.bz2 iced-aabc4e87b51af8025910681dc427260254877e4c.zip | |
Merge branch 'master' into fear/linear-gradients
Diffstat (limited to '')
| -rw-r--r-- | examples/multitouch/src/main.rs | 199 | 
1 files changed, 199 insertions, 0 deletions
| diff --git a/examples/multitouch/src/main.rs b/examples/multitouch/src/main.rs new file mode 100644 index 00000000..0345ceb7 --- /dev/null +++ b/examples/multitouch/src/main.rs @@ -0,0 +1,199 @@ +//! 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, 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); +                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 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| { +            if self.fingers.len() < 2 { +                return; +            } + +            // Collect tuples of (id, point); +            let mut zones: Vec<(u64, Point)> = +                self.fingers.iter().map(|(id, pt)| (id.0, *pt)).collect(); + +            // Sort by ID +            zones.sort_by(|a, b| a.0.partial_cmp(&b.0).unwrap()); + +            // Generate sorted list of points +            let vpoints: Vec<(f64, f64)> = zones +                .iter() +                .map(|(_, p)| (f64::from(p.x), f64::from(p.y))) +                .collect(); + +            let diagram: voronator::VoronoiDiagram< +                voronator::delaunator::Point, +            > = voronator::VoronoiDiagram::from_tuple( +                &(0.0, 0.0), +                &(700.0, 700.0), +                &vpoints, +            ) +            .expect("Generate Voronoi diagram"); + +            for (cell, zone) in diagram.cells().iter().zip(zones) { +                let mut builder = canvas::path::Builder::new(); + +                for (index, p) in cell.points().iter().enumerate() { +                    let p = Point::new(p.x as f32, p.y as f32); + +                    match index { +                        0 => builder.move_to(p), +                        _ => builder.line_to(p), +                    } +                } + +                let path = builder.build(); + +                let color_r = (10 % zone.0) as f32 / 20.0; +                let color_g = (10 % (zone.0 + 8)) as f32 / 20.0; +                let color_b = (10 % (zone.0 + 3)) as f32 / 20.0; + +                frame.fill( +                    &path, +                    Color { +                        r: color_r, +                        g: color_g, +                        b: color_b, +                        a: 1.0, +                    }, +                ); + +                frame.stroke( +                    &path, +                    Stroke { +                        color: Color::BLACK, +                        width: 3.0, +                        ..Stroke::default() +                    }, +                ); +            } +        }); + +        vec![fingerweb] +    } +} | 
