1#![feature(type_alias_impl_trait, impl_trait_in_assoc_type)]
2
3use std::time::Duration;
4
5use nuit::{clone, Alignment, Animation, Bind, Button, Circle, ForEach, Frame, HStack, Rectangle, State, Text, VStack, Vec2, View, ViewExt, ZStack};
6
7#[derive(Bind)]
8struct AnimationsView<const COUNT: usize> {
9 animations: [Animation; COUNT],
10 flips: State<[bool; COUNT]>,
11}
12
13impl<const COUNT: usize> AnimationsView<COUNT> {
14 pub fn new(animations: [Animation; COUNT]) -> Self {
15 Self {
16 animations,
17 flips: State::new(animations.map(|_| false)),
18 }
19 }
20}
21
22impl<const COUNT: usize> View for AnimationsView<COUNT> {
23 type Body = impl View;
24
25 fn body(&self) -> Self::Body {
26 let animations = self.animations;
27 let flips = self.flips.clone();
28 let width = 200.0;
29 let radius = 10.0;
30 let inner_width = width - 2.0 * radius;
31
32 VStack::new((
33 VStack::new(
34 ForEach::with_index_id(animations, |i, animation| {
35 let factor = if flips.get()[i] { 1.0 } else { -1.0 };
36 HStack::new((
37 Text::new(format!("{}", animation))
38 .frame_with(Alignment::Trailing, Frame::with_width(100)),
39 ZStack::new((
40 Rectangle::new()
41 .frame(Frame::exact(inner_width, 2)),
42 Circle::new()
43 .frame(2.0 * radius)
44 .offset(Vec2::with_x(factor * inner_width / 2.0))
45 ))
46 .frame(Frame::with_width(width)),
47 Button::with_text("Flip", clone!(flips => move || {
48 let mut value = flips.get();
49 value[i] = !value[i];
50 flips.set_with(animation, value);
51 })),
52 ))
53 })
54 ),
55 ))
56 }
57}
58
59fn main() {
60 let duration = Duration::from_secs(4);
61 nuit::run_app(AnimationsView::new([
62 Animation::linear(duration),
63 Animation::ease_in(duration),
64 Animation::ease_out(duration),
65 Animation::ease_in_out(duration),
66 ]));
67}