diff options
| author | 2020-01-11 00:40:27 +0100 | |
|---|---|---|
| committer | 2020-01-11 00:40:27 +0100 | |
| commit | e879982cfdf0c6a1c6781a9bc46e0a77839de88f (patch) | |
| tree | 02e9ed892bc178dd4134d6590f375276fe10317f /examples | |
| parent | dd5edbc6ee791c7c4323ff4f02c21bc470d0a537 (diff) | |
| download | iced-e879982cfdf0c6a1c6781a9bc46e0a77839de88f.tar.gz iced-e879982cfdf0c6a1c6781a9bc46e0a77839de88f.tar.bz2 iced-e879982cfdf0c6a1c6781a9bc46e0a77839de88f.zip | |
Improve state guarantees in `bezier_tool`
Diffstat (limited to '')
| -rw-r--r-- | examples/bezier_tool.rs | 141 | 
1 files changed, 84 insertions, 57 deletions
| diff --git a/examples/bezier_tool.rs b/examples/bezier_tool.rs index 6f99ebe2..fbf5879b 100644 --- a/examples/bezier_tool.rs +++ b/examples/bezier_tool.rs @@ -25,26 +25,41 @@ mod bezier {      use std::sync::Arc;      pub struct Bezier<'a, Message> { -        pending_points: &'a [Point], +        state: &'a mut State, +        curves: &'a [Curve],          // [from, to, ctrl] -        bezier_points: &'a [[Point; 3]], -        on_click: Box<dyn Fn(Point) -> Message>, +        on_click: Box<dyn Fn(Curve) -> Message>, +    } + +    #[derive(Debug, Clone, Copy)] +    pub struct Curve { +        from: Point, +        to: Point, +        control: Point, +    } + +    #[derive(Default)] +    pub struct State { +        pending: Option<Pending>, +    } + +    enum Pending { +        One { from: Point }, +        Two { from: Point, to: Point },      }      impl<'a, Message> Bezier<'a, Message> {          pub fn new<F>( -            bezier_points: &'a [[Point; 3]], -            pending_points: &'a [Point], +            state: &'a mut State, +            curves: &'a [Curve],              on_click: F,          ) -> Self          where -            F: 'static + Fn(Point) -> Message, +            F: 'static + Fn(Curve) -> Message,          { -            assert!(pending_points.len() < 3); -              Self { -                bezier_points, -                pending_points, +                state, +                curves,                  on_click: Box::new(on_click),              }          } @@ -102,40 +117,40 @@ mod bezier {              )              .unwrap(); -            for pts in self.bezier_points { +            for curve in self.curves {                  path_builder.move_to(lyon::math::Point::new( -                    pts[0].x + bounds.x, -                    pts[0].y + bounds.y, +                    curve.from.x + bounds.x, +                    curve.from.y + bounds.y,                  ));                  path_builder.quadratic_bezier_to(                      lyon::math::Point::new( -                        pts[2].x + bounds.x, -                        pts[2].y + bounds.y, +                        curve.control.x + bounds.x, +                        curve.control.y + bounds.y,                      ),                      lyon::math::Point::new( -                        pts[1].x + bounds.x, -                        pts[1].y + bounds.y, +                        curve.to.x + bounds.x, +                        curve.to.y + bounds.y,                      ),                  );              } -            match self.pending_points.len() { -                0 => {} -                1 => { +            match self.state.pending { +                None => {} +                Some(Pending::One { from }) => {                      path_builder.move_to(lyon::math::Point::new( -                        self.pending_points[0].x + bounds.x, -                        self.pending_points[0].y + bounds.y, +                        from.x + bounds.x, +                        from.y + bounds.y,                      ));                      path_builder.line_to(lyon::math::Point::new(                          cursor_position.x,                          cursor_position.y,                      ));                  } -                2 => { +                Some(Pending::Two { from, to }) => {                      path_builder.move_to(lyon::math::Point::new( -                        self.pending_points[0].x + bounds.x, -                        self.pending_points[0].y + bounds.y, +                        from.x + bounds.x, +                        from.y + bounds.y,                      ));                      path_builder.quadratic_bezier_to(                          lyon::math::Point::new( @@ -143,14 +158,11 @@ mod bezier {                              cursor_position.y,                          ),                          lyon::math::Point::new( -                            self.pending_points[1].x + bounds.x, -                            self.pending_points[1].y + bounds.y, +                            to.x + bounds.x, +                            to.y + bounds.y,                          ),                      );                  } -                _ => { -                    unreachable!(); -                }              }              let mut tessellator = StrokeTessellator::new(); @@ -197,18 +209,42 @@ mod bezier {              _clipboard: Option<&dyn Clipboard>,          ) {              let bounds = layout.bounds(); -            match event { -                Event::Mouse(input::mouse::Event::Input { state, .. }) => { -                    if state == input::ButtonState::Pressed -                        && bounds.contains(cursor_position) -                    { -                        messages.push((self.on_click)(Point::new( + +            if bounds.contains(cursor_position) { +                match event { +                    Event::Mouse(input::mouse::Event::Input { +                        state: input::ButtonState::Pressed, +                        .. +                    }) => { +                        let new_point = Point::new(                              cursor_position.x - bounds.x,                              cursor_position.y - bounds.y, -                        ))); +                        ); + +                        match self.state.pending { +                            None => { +                                self.state.pending = +                                    Some(Pending::One { from: new_point }); +                            } +                            Some(Pending::One { from }) => { +                                self.state.pending = Some(Pending::Two { +                                    from, +                                    to: new_point, +                                }); +                            } +                            Some(Pending::Two { from, to }) => { +                                self.state.pending = None; + +                                messages.push((self.on_click)(Curve { +                                    from, +                                    to, +                                    control: new_point, +                                })); +                            } +                        }                      } +                    _ => {}                  } -                _ => {}              }          }      } @@ -228,7 +264,6 @@ use iced::{      button, Align, Button, Color, Column, Container, Element, Length, Sandbox,      Settings, Text,  }; -use iced_native::Point;  pub fn main() {      Example::run(Settings::default()) @@ -236,14 +271,14 @@ pub fn main() {  #[derive(Default)]  struct Example { -    bezier_points: Vec<[Point; 3]>, -    pending_points: Vec<Point>, +    bezier: bezier::State, +    curves: Vec<bezier::Curve>,      button_state: button::State,  }  #[derive(Debug, Clone, Copy)]  enum Message { -    AddPoint(Point), +    AddCurve(bezier::Curve),      Clear,  } @@ -260,20 +295,12 @@ impl Sandbox for Example {      fn update(&mut self, message: Message) {          match message { -            Message::AddPoint(point) => { -                self.pending_points.push(point); -                if self.pending_points.len() == 3 { -                    self.bezier_points.push([ -                        self.pending_points[0], -                        self.pending_points[1], -                        self.pending_points[2], -                    ]); -                    self.pending_points.clear(); -                } +            Message::AddCurve(curve) => { +                self.curves.push(curve);              }              Message::Clear => { -                self.bezier_points.clear(); -                self.pending_points.clear(); +                self.bezier = bezier::State::default(); +                self.curves.clear();              }          }      } @@ -289,9 +316,9 @@ impl Sandbox for Example {                      .size(50),              )              .push(Bezier::new( -                self.bezier_points.as_slice(), -                self.pending_points.as_slice(), -                Message::AddPoint, +                &mut self.bezier, +                self.curves.as_slice(), +                Message::AddCurve,              ))              .push(                  Button::new(&mut self.button_state, Text::new("Clear")) | 
