From 4d9839fc192d53e36b973f8c4d8db59124e7f29e Mon Sep 17 00:00:00 2001
From: Per Lindgren <per.lindgren@ltu.se>
Date: Sun, 26 Jan 2020 01:39:36 +0100
Subject: [PATCH] dail now works

---
 examples/dial_test.rs | 93 +++++++++++++++++++++++++++++++++++++++++++
 src/dial.rs           | 83 ++++++++++++++++++++++++++++++++++++++
 src/lib.rs            |  3 ++
 src/main.rs           | 28 -------------
 4 files changed, 179 insertions(+), 28 deletions(-)
 create mode 100644 examples/dial_test.rs
 create mode 100644 src/dial.rs
 create mode 100644 src/lib.rs
 delete mode 100644 src/main.rs

diff --git a/examples/dial_test.rs b/examples/dial_test.rs
new file mode 100644
index 0000000..40ec480
--- /dev/null
+++ b/examples/dial_test.rs
@@ -0,0 +1,93 @@
+// Copyright 2019 The xi-editor Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//! An example of an animating widget.
+
+use std::f64::consts::PI;
+
+use druid::kurbo::{BezPath, Line};
+use druid::widget::{Flex, Label, WidgetExt};
+use druid::{
+    AppLauncher, BoxConstraints, Color, Data, Env, Event, EventCtx, LayoutCtx, Lens, LensWrap,
+    LinearGradient, PaintCtx, PlatformError, Point, RenderContext, Size, UnitPoint, UpdateCtx,
+    Vec2, WheelEvent, Widget, WindowDesc,
+};
+
+use log::info;
+
+use druid_widgets::*;
+
+#[derive(Clone, Data, Lens)]
+struct DialData {
+    value: f64,
+}
+
+fn build_app() -> impl Widget<(DialData)> {
+    let solid = Color::rgb8(0x3a, 0x3a, 0x3a);
+    let gradient = LinearGradient::new(
+        UnitPoint::TOP_LEFT,
+        UnitPoint::BOTTOM_RIGHT,
+        (Color::rgb8(0x11, 0x11, 0x11), Color::rgb8(0xbb, 0xbb, 0xbb)),
+    );
+
+    Flex::column()
+        .with_child(
+            Flex::row()
+                .with_child(
+                    Label::new("top left")
+                        .background(solid.clone())
+                        .padding(10.0),
+                    1.0,
+                )
+                .with_child(
+                    LensWrap::new(Dial::new(Size::new(100.0, 100.0)), DialData::value)
+                        .background(solid.clone())
+                        .padding(10.0),
+                    0.0,
+                )
+                .with_child(
+                    Label::new("top right")
+                        .background(solid.clone())
+                        .padding(10.0),
+                    1.0,
+                ),
+            0.0, // vertical
+        )
+        .with_child(
+            Flex::row()
+                .with_child(
+                    Label::new("bottom left")
+                        .background(gradient.clone())
+                        .rounded(10.0)
+                        .padding(10.0),
+                    0.0,
+                )
+                .with_child(
+                    Label::new("bottom right")
+                        .border(solid.clone(), 4.0)
+                        .rounded(10.0)
+                        .padding(10.0),
+                    1.0,
+                ),
+            1.0,
+        )
+}
+
+fn main() -> Result<(), PlatformError> {
+    AppLauncher::with_window(WindowDesc::new(build_app))
+        .use_simple_logger()
+        .launch(DialData { value: 0.0 })?;
+
+    Ok(())
+}
diff --git a/src/dial.rs b/src/dial.rs
new file mode 100644
index 0000000..b9a3444
--- /dev/null
+++ b/src/dial.rs
@@ -0,0 +1,83 @@
+use std::f64::consts::PI;
+
+use druid::kurbo::{BezPath, Line};
+use druid::widget::{Align, Flex, Label, WidgetExt};
+use druid::{
+    AppLauncher, BoxConstraints, Color, Data, Env, Event, EventCtx, LayoutCtx, LinearGradient,
+    PaintCtx, PlatformError, Point, RenderContext, Size, UnitPoint, UpdateCtx, Vec2, WheelEvent,
+    Widget, WindowDesc,
+};
+use log::info;
+use std::convert::From;
+#[derive(Debug, Clone, Default)]
+pub struct Dial {
+    // properties for the Dial
+    value: f64,
+    size: Size,
+}
+
+impl Dial {
+    pub fn new(size: Size) -> impl Widget<f64> {
+        Self { value: 0.0, size }
+    }
+}
+
+impl Widget<f64> for Dial {
+    fn event(&mut self, ctx: &mut EventCtx, event: &Event, data: &mut f64, _env: &Env) {
+        match event {
+            Event::Wheel(w) => {
+                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;
+                };
+
+                // set data
+                // maybe we can get scroll wheel direction from Env/Preferences
+                *data = *data - delta;
+                *data = f64::min(1.0, f64::max(0.0, *data));
+
+                ctx.invalidate();
+            }
+            _ => (),
+        }
+    }
+
+    fn update(&mut self, ctx: &mut UpdateCtx, _old_data: Option<&f64>, _data: &f64, _env: &Env) {
+        ctx.invalidate();
+    }
+    fn layout(
+        &mut self,
+        _layout_ctx: &mut LayoutCtx,
+        bc: &BoxConstraints,
+        _data: &f64,
+        _env: &Env,
+    ) -> Size {
+        bc.constrain(self.size)
+    }
+
+    fn paint(&mut self, paint_ctx: &mut PaintCtx, data: &f64, _env: &Env) {
+        info!("dial paint");
+        // for 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(data * 2.0 * 0.75 * PI + 2.0 * PI * 0.375),
+        );
+        paint_ctx.stroke(path, &Color::WHITE, 1.0);
+    }
+}
diff --git a/src/lib.rs b/src/lib.rs
new file mode 100644
index 0000000..d39bf79
--- /dev/null
+++ b/src/lib.rs
@@ -0,0 +1,3 @@
+mod dial;
+
+pub use dial::*;
diff --git a/src/main.rs b/src/main.rs
deleted file mode 100644
index 7864487..0000000
--- a/src/main.rs
+++ /dev/null
@@ -1,28 +0,0 @@
-use druid::widget::{Align, Button, Flex, Label, Padding, WidgetExt};
-use druid::{AppLauncher, LocalizedString, Widget, WindowDesc};
-
-use log::info;
-fn main() {
-    let main_window = WindowDesc::new(ui_builder);
-    let data = 0_u32;
-    AppLauncher::with_window(main_window)
-        .use_simple_logger()
-        .launch(data)
-        .expect("launch failed");
-}
-
-fn ui_builder() -> impl Widget<u32> {
-    // The label text will be computed dynamically based on the current locale and count
-    let text =
-        LocalizedString::new("hello-counter").with_arg("count", |data: &u32, _env| (*data).into());
-    let label = Label::new(text).padding(5.0).center();
-    let button = Button::new("increment", |_ctx, data, _env| {
-        *data += 1;
-        info!("Button Pressed");
-    })
-    .padding(5.0);
-
-    Flex::column()
-        .with_child(label, 1.0)
-        .with_child(button, 1.0)
-}
-- 
GitLab