2022-05-14 01:47:55 +02:00
|
|
|
use iced::executor;
|
2022-09-29 10:52:58 -07:00
|
|
|
use iced::widget::canvas::{
|
|
|
|
|
Cache, Cursor, Geometry, LineCap, Path, Stroke, StrokeStyle,
|
|
|
|
|
};
|
2022-07-27 06:49:20 +02:00
|
|
|
use iced::widget::{canvas, container};
|
2020-02-12 03:47:36 +01:00
|
|
|
use iced::{
|
2022-07-27 06:49:20 +02:00
|
|
|
Application, Color, Command, Element, Length, Point, Rectangle, Settings,
|
|
|
|
|
Subscription, Theme, Vector,
|
2020-02-12 03:47:36 +01:00
|
|
|
};
|
|
|
|
|
|
2020-09-08 00:35:17 +02:00
|
|
|
pub fn main() -> iced::Result {
|
2020-02-15 10:08:27 +01:00
|
|
|
Clock::run(Settings {
|
2020-02-18 09:54:24 +01:00
|
|
|
antialiasing: true,
|
2020-02-15 10:08:27 +01:00
|
|
|
..Settings::default()
|
|
|
|
|
})
|
2020-02-12 03:47:36 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct Clock {
|
2022-01-12 20:16:33 +07:00
|
|
|
now: time::OffsetDateTime,
|
2020-04-28 06:24:12 +02:00
|
|
|
clock: Cache,
|
2020-02-12 03:47:36 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Debug, Clone, Copy)]
|
|
|
|
|
enum Message {
|
2022-01-12 20:16:33 +07:00
|
|
|
Tick(time::OffsetDateTime),
|
2020-02-12 03:47:36 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Application for Clock {
|
2022-09-29 10:52:58 -07:00
|
|
|
type Executor = executor::Default;
|
2020-02-12 03:47:36 +01:00
|
|
|
type Message = Message;
|
2022-05-14 01:47:55 +02:00
|
|
|
type Theme = Theme;
|
2020-03-30 18:00:15 +02:00
|
|
|
type Flags = ();
|
2020-02-12 03:47:36 +01:00
|
|
|
|
2020-03-30 18:00:15 +02:00
|
|
|
fn new(_flags: ()) -> (Self, Command<Message>) {
|
2020-02-12 03:47:36 +01:00
|
|
|
(
|
|
|
|
|
Clock {
|
2022-01-12 20:16:33 +07:00
|
|
|
now: time::OffsetDateTime::now_local()
|
|
|
|
|
.unwrap_or_else(|_| time::OffsetDateTime::now_utc()),
|
2020-04-08 23:07:42 +01:00
|
|
|
clock: Default::default(),
|
2020-02-12 03:47:36 +01:00
|
|
|
},
|
|
|
|
|
Command::none(),
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn title(&self) -> String {
|
|
|
|
|
String::from("Clock - Iced")
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-01 19:21:49 +07:00
|
|
|
fn update(&mut self, message: Message) -> Command<Message> {
|
2020-02-12 03:47:36 +01:00
|
|
|
match message {
|
2020-02-12 04:00:13 +01:00
|
|
|
Message::Tick(local_time) => {
|
2020-04-30 05:37:44 +02:00
|
|
|
let now = local_time;
|
2020-02-12 04:00:13 +01:00
|
|
|
|
|
|
|
|
if now != self.now {
|
|
|
|
|
self.now = now;
|
|
|
|
|
self.clock.clear();
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-02-12 03:47:36 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Command::none()
|
|
|
|
|
}
|
|
|
|
|
|
2022-07-27 06:49:20 +02:00
|
|
|
fn view(&self) -> Element<Message> {
|
|
|
|
|
let canvas = canvas(self as &Self)
|
|
|
|
|
.width(Length::Fill)
|
|
|
|
|
.height(Length::Fill);
|
2020-02-12 08:49:42 +01:00
|
|
|
|
2022-07-27 06:49:20 +02:00
|
|
|
container(canvas)
|
2020-02-12 03:47:36 +01:00
|
|
|
.width(Length::Fill)
|
|
|
|
|
.height(Length::Fill)
|
2020-03-31 01:19:28 +02:00
|
|
|
.padding(20)
|
2020-02-12 03:47:36 +01:00
|
|
|
.into()
|
|
|
|
|
}
|
2022-09-29 10:52:58 -07:00
|
|
|
|
|
|
|
|
fn subscription(&self) -> Subscription<Message> {
|
|
|
|
|
iced::time::every(std::time::Duration::from_millis(500)).map(|_| {
|
|
|
|
|
Message::Tick(
|
|
|
|
|
time::OffsetDateTime::now_local()
|
|
|
|
|
.unwrap_or_else(|_| time::OffsetDateTime::now_utc()),
|
|
|
|
|
)
|
|
|
|
|
})
|
|
|
|
|
}
|
2020-02-12 03:47:36 +01:00
|
|
|
}
|
|
|
|
|
|
2022-03-18 22:13:52 +07:00
|
|
|
impl<Message> canvas::Program<Message> for Clock {
|
2022-07-27 06:49:20 +02:00
|
|
|
type State = ();
|
|
|
|
|
|
2022-06-07 05:24:43 +02:00
|
|
|
fn draw(
|
|
|
|
|
&self,
|
2022-07-27 06:49:20 +02:00
|
|
|
_state: &Self::State,
|
2022-06-07 05:24:43 +02:00
|
|
|
_theme: &Theme,
|
|
|
|
|
bounds: Rectangle,
|
|
|
|
|
_cursor: Cursor,
|
|
|
|
|
) -> Vec<Geometry> {
|
2020-04-29 04:25:49 +02:00
|
|
|
let clock = self.clock.draw(bounds.size(), |frame| {
|
2020-04-28 06:24:12 +02:00
|
|
|
let center = frame.center();
|
|
|
|
|
let radius = frame.width().min(frame.height()) / 2.0;
|
2020-04-14 06:54:12 +02:00
|
|
|
|
2020-04-28 06:24:12 +02:00
|
|
|
let background = Path::circle(center, radius);
|
|
|
|
|
frame.fill(&background, Color::from_rgb8(0x12, 0x93, 0xD8));
|
2020-02-12 03:47:36 +01:00
|
|
|
|
2020-04-28 06:24:12 +02:00
|
|
|
let short_hand =
|
|
|
|
|
Path::line(Point::ORIGIN, Point::new(0.0, -0.5 * radius));
|
2020-02-12 03:47:36 +01:00
|
|
|
|
2020-04-28 06:24:12 +02:00
|
|
|
let long_hand =
|
|
|
|
|
Path::line(Point::ORIGIN, Point::new(0.0, -0.8 * radius));
|
2020-02-12 03:47:36 +01:00
|
|
|
|
2022-09-29 10:52:58 -07:00
|
|
|
let width = radius / 100.0;
|
|
|
|
|
|
|
|
|
|
let thin_stroke = || -> Stroke {
|
|
|
|
|
Stroke {
|
|
|
|
|
width,
|
|
|
|
|
style: StrokeStyle::Solid(Color::WHITE),
|
|
|
|
|
line_cap: LineCap::Round,
|
|
|
|
|
..Stroke::default()
|
|
|
|
|
}
|
2020-04-28 06:24:12 +02:00
|
|
|
};
|
2020-02-12 03:47:36 +01:00
|
|
|
|
2022-09-29 10:52:58 -07:00
|
|
|
let wide_stroke = || -> Stroke {
|
|
|
|
|
Stroke {
|
|
|
|
|
width: width * 3.0,
|
|
|
|
|
style: StrokeStyle::Solid(Color::WHITE),
|
|
|
|
|
line_cap: LineCap::Round,
|
|
|
|
|
..Stroke::default()
|
|
|
|
|
}
|
2020-04-28 06:24:12 +02:00
|
|
|
};
|
2020-02-12 03:47:36 +01:00
|
|
|
|
2020-04-28 06:24:12 +02:00
|
|
|
frame.translate(Vector::new(center.x, center.y));
|
2020-02-12 03:47:36 +01:00
|
|
|
|
2020-04-28 06:24:12 +02:00
|
|
|
frame.with_save(|frame| {
|
|
|
|
|
frame.rotate(hand_rotation(self.now.hour(), 12));
|
2022-09-29 10:52:58 -07:00
|
|
|
frame.stroke(&short_hand, wide_stroke());
|
2020-04-28 06:24:12 +02:00
|
|
|
});
|
2020-02-12 03:47:36 +01:00
|
|
|
|
2020-04-28 06:24:12 +02:00
|
|
|
frame.with_save(|frame| {
|
|
|
|
|
frame.rotate(hand_rotation(self.now.minute(), 60));
|
2022-09-29 10:52:58 -07:00
|
|
|
frame.stroke(&long_hand, wide_stroke());
|
2020-04-28 06:24:12 +02:00
|
|
|
});
|
2020-02-12 03:47:36 +01:00
|
|
|
|
2020-04-28 06:24:12 +02:00
|
|
|
frame.with_save(|frame| {
|
|
|
|
|
frame.rotate(hand_rotation(self.now.second(), 60));
|
2022-09-29 10:52:58 -07:00
|
|
|
frame.stroke(&long_hand, thin_stroke());
|
2020-04-28 06:24:12 +02:00
|
|
|
})
|
2020-02-12 06:41:24 +01:00
|
|
|
});
|
2020-02-12 03:47:36 +01:00
|
|
|
|
2020-04-28 06:24:12 +02:00
|
|
|
vec![clock]
|
2020-02-12 03:47:36 +01:00
|
|
|
}
|
|
|
|
|
}
|
2020-02-12 08:49:42 +01:00
|
|
|
|
2022-01-12 20:16:33 +07:00
|
|
|
fn hand_rotation(n: u8, total: u8) -> f32 {
|
2020-04-14 07:08:24 +02:00
|
|
|
let turns = n as f32 / total as f32;
|
|
|
|
|
|
|
|
|
|
2.0 * std::f32::consts::PI * turns
|
|
|
|
|
}
|