diff --git a/examples/draw.rs b/examples/draw.rs index 9d410a40b788dfd86c60b6212bea448548ded616..c0551c6d72a1c42a149bdfb9608167f00a3a35fa 100644 --- a/examples/draw.rs +++ b/examples/draw.rs @@ -20,7 +20,8 @@ use druid::kurbo::{BezPath, Line}; use druid::widget::{Flex, Label, WidgetExt}; use druid::{ AppLauncher, BoxConstraints, Color, Env, Event, EventCtx, LayoutCtx, LinearGradient, PaintCtx, - PlatformError, Point, RenderContext, Size, UnitPoint, UpdateCtx, Vec2, Widget, WindowDesc, + PlatformError, Point, RenderContext, Size, UnitPoint, UpdateCtx, Vec2, WheelEvent, Widget, + WindowDesc, }; use log::info; @@ -32,7 +33,6 @@ enum MouseState { struct DrawWidget { state: MouseState, points: Vec<Point>, - t: f64, } impl Widget<()> for DrawWidget { @@ -42,7 +42,6 @@ impl Widget<()> for DrawWidget { info!("down: pos {:?}", m.pos); //info!("down: pos {:?}, pos_rel {:?}", m.pos); self.state = MouseState::Down; - self.t = 0.0; self.points.push(m.pos); ctx.invalidate(); } @@ -55,11 +54,8 @@ impl Widget<()> for DrawWidget { Event::MouseUp(m) => { info!("up:pos {:?}", m.pos); self.state = MouseState::Up; - self.t = 0.0; } - - Event::AnimFrame(interval) => {} - _ => (), + _ => {} } } @@ -94,6 +90,91 @@ impl Widget<()> for DrawWidget { } } +#[derive(Debug)] +struct DialWidget { + size: Size, + down_pos: Option<Point>, + cur_pos: Point, + value: f64, // in range 0.0..= 1.0 +} + +impl Widget<()> for DialWidget { + fn event(&mut self, ctx: &mut EventCtx, event: &Event, _data: &mut (), _env: &Env) { + match event { + Event::MouseDown(m) => { + info!("down: pos {:?}", m.pos); + //info!("down: pos {:?}, pos_rel {:?}", m.pos); + self.down_pos = Some(m.pos); + } + Event::MouseMoved(m) => match self.down_pos { + Some(down_pos) => { + self.cur_pos = m.pos; + info!("down_pos {:?}, cur_pos {:?}", down_pos, m.pos); + } + _ => {} + }, + Event::MouseUp(m) => { + info!("up:pos {:?}", m.pos); + + self.value = self.value + 1.0; + } + Event::Wheel(w) => { + info!("Event {:?}", w.delta); + let mut delta = w.delta.y / (120 * 10) as f64; // 1% for my machine + if w.mods.shift { + delta = delta / 10.0; + }; + if w.mods.ctrl { + delta = delta / 10.0; + }; + + self.value -= delta; + self.value = f64::max(0.0, f64::min(1.0, self.value)); + ctx.invalidate(); + } + _ => (), + } + } + + fn update(&mut self, ctx: &mut UpdateCtx, _old_data: Option<&()>, _data: &(), env: &Env) { + //info!("update {:?}", env.get()); + ctx.invalidate(); + } + + fn layout( + &mut self, + _layout_ctx: &mut LayoutCtx, + bc: &BoxConstraints, + _data: &(), + _env: &Env, + ) -> Size { + bc.constrain(self.size) // size of dial + } + + fn paint(&mut self, paint_ctx: &mut PaintCtx, _data: &(), _env: &Env) { + info!("dial paint"); + // far some reason origin (0,0) seems not to point to the border not the interior + let center = Point::new(self.size.width / 2.0, self.size.height / 2.0); + let diameter = 0.8 * self.size.width / 2.0; + let mut path = BezPath::new(); + let ambit0 = center + diameter * Vec2::from_angle(0.0); + path.move_to(ambit0); + for v in (0..360).step_by(10) { + let ambit = center + diameter * Vec2::from_angle(v as f64 / 360.0 * 2.0 * PI); + path.line_to(ambit); + } + path.close_path(); + paint_ctx.stroke(path, &Color::WHITE, 1.0); + + let mut path = BezPath::new(); + path.move_to(center); + path.line_to( + center + diameter * Vec2::from_angle(self.value * 2.0 * 0.75 * PI + 2.0 * PI * 0.375), + ); + paint_ctx.stroke(path, &Color::WHITE, 1.0); + } +} + fn build_app() -> impl Widget<()> { let solid = Color::rgb8(0x3a, 0x3a, 0x3a); let gradient = LinearGradient::new( @@ -106,16 +187,20 @@ fn build_app() -> impl Widget<()> { .with_child( Flex::row() .with_child( - Label::new("top left") - .border(gradient.clone(), 4.0) - .padding(10.0), - 1.0, // horizontal + DialWidget { + size: Size::new(100.0, 100.0), + down_pos: None, + cur_pos: Point::new(0.0, 0.0), + value: 0.0, + } + .border(gradient.clone(), 4.0) + .padding(10.0), + 0.0, // horizontal ) .with_child( DrawWidget { state: MouseState::Up, points: Vec::new(), - t: 0.0, } .border(gradient.clone(), 4.0) .padding(10.0),