use core::convert::Infallible;
use embedded_graphics::{
Drawable, Pixel,
draw_target::DrawTarget,
geometry::{OriginDimensions, Size},
pixelcolor::Rgb565,
prelude::{Point, Primitive, RgbColor},
primitives::Rectangle,
};
use faststep::{
ChildView, DisplayPort, FsTheme, I18n, ListDataSource, ListDelegate, ListRow, ListSelection,
ListView, Localized, TouchEvent, TouchPhase, UiCanvas, UiSystem, UiView, ViewEnvironment,
ViewEvent, ViewKind, ViewRedraw, ViewRegistration,
};
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
enum DemoViewId {
DevicesList,
AlertOverlay,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
enum DemoMessage {
DeviceTapped(u8),
}
struct RootView {
list: ListView<DeviceDataSource, DeviceDelegate>,
}
impl RootView {
fn new() -> Self {
Self {
list: ListView::new(DeviceDataSource, DeviceDelegate),
}
}
}
impl UiView<'static, DemoViewId, DemoMessage, 2> for RootView {
fn configure(&mut self, registration: &mut ViewRegistration<'static, DemoViewId, 2>) {
registration.set_title(Localized::new("root.title", "Devices"));
registration.set_clips_to_bounds(true);
let list_frame = registration.frame();
let _ = registration.add_child(
ChildView::new(DemoViewId::DevicesList, list_frame)
.with_kind(ViewKind::List)
.with_title(Localized::new("devices.title", "Devices")),
);
let _ = registration.add_child(
ChildView::new(
DemoViewId::AlertOverlay,
Rectangle::new(Point::new(16, 16), Size::new(0, 0)),
)
.with_kind(ViewKind::AlertHost)
.with_hidden(true)
.with_alpha(0),
);
}
fn update(
&mut self,
dt_ms: u32,
registration: &ViewRegistration<'static, DemoViewId, 2>,
_env: &ViewEnvironment<'_, 'static>,
) -> ViewEvent<DemoMessage> {
let list = registration.children()[0].frame;
ViewEvent::redraw(self.list.tick(dt_ms, list))
}
fn handle_touch(
&mut self,
touch: TouchEvent,
registration: &ViewRegistration<'static, DemoViewId, 2>,
_env: &ViewEnvironment<'_, 'static>,
) -> ViewEvent<DemoMessage> {
self.list
.handle_touch(touch, registration.children()[0].frame)
.into_view_event()
}
fn draw<D>(
&self,
display: &mut D,
registration: &ViewRegistration<'static, DemoViewId, 2>,
env: &ViewEnvironment<'_, 'static>,
) where
D: DrawTarget<Color = Rgb565>,
{
self.list
.draw(display, registration.children()[0].frame, env);
}
}
struct DeviceDataSource;
impl ListDataSource for DeviceDataSource {
type ItemId = u8;
fn item_count(&self) -> usize {
3
}
fn item_id(&self, index: usize) -> Self::ItemId {
index as u8
}
fn item_height(&self, index: usize) -> u32 {
match index {
0 => 64,
1 => 88,
_ => 72,
}
}
}
struct DeviceDelegate;
impl ListDelegate<'static, u8> for DeviceDelegate {
type Message = DemoMessage;
fn draw_row<D>(&self, display: &mut D, row: ListRow<u8>, _env: &ViewEnvironment<'_, 'static>)
where
D: DrawTarget<Color = Rgb565>,
{
let color = if row.state.highlighted {
Rgb565::WHITE
} else {
match row.item.id {
0 => Rgb565::RED,
1 => Rgb565::GREEN,
_ => Rgb565::BLUE,
}
};
row.item
.frame
.into_styled(embedded_graphics::primitives::PrimitiveStyle::with_fill(
color,
))
.draw(display)
.ok();
}
fn did_select_item(&mut self, selection: ListSelection<u8>) -> Option<Self::Message> {
Some(DemoMessage::DeviceTapped(selection.id))
}
}
struct NullDisplay {
bounds: Rectangle,
}
impl NullDisplay {
fn new(bounds: Rectangle) -> Self {
Self { bounds }
}
}
struct NullCanvas {
size: Size,
}
impl OriginDimensions for NullCanvas {
fn size(&self) -> Size {
self.size
}
}
impl DrawTarget for NullCanvas {
type Color = Rgb565;
type Error = Infallible;
fn draw_iter<I>(&mut self, _pixels: I) -> Result<(), Self::Error>
where
I: IntoIterator<Item = Pixel<Self::Color>>,
{
Ok(())
}
}
impl UiCanvas for NullCanvas {
fn dim_rect(&mut self, _area: Rectangle, _alpha: u8) {}
}
impl DisplayPort for NullDisplay {
type Canvas = NullCanvas;
type Error = Infallible;
fn bounds(&self) -> Rectangle {
self.bounds
}
fn draw_frame<F>(&mut self, draw: F) -> Result<(), Self::Error>
where
F: FnOnce(&mut Self::Canvas),
{
let mut canvas = NullCanvas {
size: self.bounds.size,
};
draw(&mut canvas);
Ok(())
}
}
fn main() {
let bounds = Rectangle::new(Point::zero(), Size::new(320, 240));
let mut system = UiSystem::new(
NullDisplay::new(bounds),
RootView::new(),
FsTheme::default(),
I18n::new("en", "en", &[]),
);
let redraw = system.update(16).redraw;
let _ = system.draw_redraw(redraw);
let _ = system.handle_touch(TouchEvent::new(Point::new(24, 24), TouchPhase::Start, 1));
let _ = system.handle_touch(TouchEvent::new(Point::new(24, 24), TouchPhase::End, 2));
let _ = system.draw();
let _ = system.registration();
let _ = ViewRedraw::Full;
}