Skip to main content

uikit_root/
uikit_root.rs

1use core::convert::Infallible;
2
3use embedded_graphics::{
4    Drawable, Pixel,
5    draw_target::DrawTarget,
6    geometry::{OriginDimensions, Size},
7    pixelcolor::Rgb565,
8    prelude::{Point, Primitive, RgbColor},
9    primitives::Rectangle,
10};
11
12use faststep::{
13    ChildView, DisplayPort, FsTheme, I18n, ListDataSource, ListDelegate, ListRow, ListSelection,
14    ListView, Localized, TouchEvent, TouchPhase, UiCanvas, UiSystem, UiView, ViewEnvironment,
15    ViewEvent, ViewKind, ViewRedraw, ViewRegistration,
16};
17
18#[derive(Clone, Copy, Debug, PartialEq, Eq)]
19enum DemoViewId {
20    DevicesList,
21    AlertOverlay,
22}
23
24#[derive(Clone, Copy, Debug, PartialEq, Eq)]
25enum DemoMessage {
26    DeviceTapped(u8),
27}
28
29struct RootView {
30    list: ListView<DeviceDataSource, DeviceDelegate>,
31}
32
33impl RootView {
34    fn new() -> Self {
35        Self {
36            list: ListView::new(DeviceDataSource, DeviceDelegate),
37        }
38    }
39}
40
41impl UiView<'static, DemoViewId, DemoMessage, 2> for RootView {
42    fn configure(&mut self, registration: &mut ViewRegistration<'static, DemoViewId, 2>) {
43        registration.set_title(Localized::new("root.title", "Devices"));
44        registration.set_clips_to_bounds(true);
45        let list_frame = registration.frame();
46        let _ = registration.add_child(
47            ChildView::new(DemoViewId::DevicesList, list_frame)
48                .with_kind(ViewKind::List)
49                .with_title(Localized::new("devices.title", "Devices")),
50        );
51        let _ = registration.add_child(
52            ChildView::new(
53                DemoViewId::AlertOverlay,
54                Rectangle::new(Point::new(16, 16), Size::new(0, 0)),
55            )
56            .with_kind(ViewKind::AlertHost)
57            .with_hidden(true)
58            .with_alpha(0),
59        );
60    }
61
62    fn update(
63        &mut self,
64        dt_ms: u32,
65        registration: &ViewRegistration<'static, DemoViewId, 2>,
66        _env: &ViewEnvironment<'_, 'static>,
67    ) -> ViewEvent<DemoMessage> {
68        let list = registration.children()[0].frame;
69        ViewEvent::redraw(self.list.tick(dt_ms, list))
70    }
71
72    fn handle_touch(
73        &mut self,
74        touch: TouchEvent,
75        registration: &ViewRegistration<'static, DemoViewId, 2>,
76        _env: &ViewEnvironment<'_, 'static>,
77    ) -> ViewEvent<DemoMessage> {
78        self.list
79            .handle_touch(touch, registration.children()[0].frame)
80            .into_view_event()
81    }
82
83    fn draw<D>(
84        &self,
85        display: &mut D,
86        registration: &ViewRegistration<'static, DemoViewId, 2>,
87        env: &ViewEnvironment<'_, 'static>,
88    ) where
89        D: DrawTarget<Color = Rgb565>,
90    {
91        self.list
92            .draw(display, registration.children()[0].frame, env);
93    }
94}
95
96struct DeviceDataSource;
97
98impl ListDataSource for DeviceDataSource {
99    type ItemId = u8;
100
101    fn item_count(&self) -> usize {
102        3
103    }
104
105    fn item_id(&self, index: usize) -> Self::ItemId {
106        index as u8
107    }
108
109    fn item_height(&self, index: usize) -> u32 {
110        match index {
111            0 => 64,
112            1 => 88,
113            _ => 72,
114        }
115    }
116}
117
118struct DeviceDelegate;
119
120impl ListDelegate<'static, u8> for DeviceDelegate {
121    type Message = DemoMessage;
122
123    fn draw_row<D>(&self, display: &mut D, row: ListRow<u8>, _env: &ViewEnvironment<'_, 'static>)
124    where
125        D: DrawTarget<Color = Rgb565>,
126    {
127        let color = if row.state.highlighted {
128            Rgb565::WHITE
129        } else {
130            match row.item.id {
131                0 => Rgb565::RED,
132                1 => Rgb565::GREEN,
133                _ => Rgb565::BLUE,
134            }
135        };
136        row.item
137            .frame
138            .into_styled(embedded_graphics::primitives::PrimitiveStyle::with_fill(
139                color,
140            ))
141            .draw(display)
142            .ok();
143    }
144
145    fn did_select_item(&mut self, selection: ListSelection<u8>) -> Option<Self::Message> {
146        Some(DemoMessage::DeviceTapped(selection.id))
147    }
148}
149
150struct NullDisplay {
151    bounds: Rectangle,
152}
153
154impl NullDisplay {
155    fn new(bounds: Rectangle) -> Self {
156        Self { bounds }
157    }
158}
159
160struct NullCanvas {
161    size: Size,
162}
163
164impl OriginDimensions for NullCanvas {
165    fn size(&self) -> Size {
166        self.size
167    }
168}
169
170impl DrawTarget for NullCanvas {
171    type Color = Rgb565;
172    type Error = Infallible;
173
174    fn draw_iter<I>(&mut self, _pixels: I) -> Result<(), Self::Error>
175    where
176        I: IntoIterator<Item = Pixel<Self::Color>>,
177    {
178        Ok(())
179    }
180}
181
182impl UiCanvas for NullCanvas {
183    fn dim_rect(&mut self, _area: Rectangle, _alpha: u8) {}
184}
185
186impl DisplayPort for NullDisplay {
187    type Canvas = NullCanvas;
188    type Error = Infallible;
189
190    fn bounds(&self) -> Rectangle {
191        self.bounds
192    }
193
194    fn draw_frame<F>(&mut self, draw: F) -> Result<(), Self::Error>
195    where
196        F: FnOnce(&mut Self::Canvas),
197    {
198        let mut canvas = NullCanvas {
199            size: self.bounds.size,
200        };
201        draw(&mut canvas);
202        Ok(())
203    }
204}
205
206fn main() {
207    let bounds = Rectangle::new(Point::zero(), Size::new(320, 240));
208    let mut system = UiSystem::new(
209        NullDisplay::new(bounds),
210        RootView::new(),
211        FsTheme::default(),
212        I18n::new("en", "en", &[]),
213    );
214
215    let redraw = system.update(16).redraw;
216    let _ = system.draw_redraw(redraw);
217    let _ = system.handle_touch(TouchEvent::new(Point::new(24, 24), TouchPhase::Start, 1));
218    let _ = system.handle_touch(TouchEvent::new(Point::new(24, 24), TouchPhase::End, 2));
219    let _ = system.draw();
220    let _ = system.registration();
221    let _ = ViewRedraw::Full;
222}