parent
5052594789
commit
5a9c2a1363
After Width: | Height: | Size: 383 B |
@ -0,0 +1,60 @@
|
||||
use crate::{
|
||||
time::Duration,
|
||||
ui::{
|
||||
component::{Component, Event, EventCtx, TimerToken},
|
||||
geometry::Rect,
|
||||
},
|
||||
};
|
||||
|
||||
pub struct Timeout {
|
||||
time_ms: u32,
|
||||
timer: Option<TimerToken>,
|
||||
}
|
||||
|
||||
pub enum TimeoutMsg {
|
||||
TimedOut,
|
||||
}
|
||||
|
||||
impl Timeout {
|
||||
pub fn new(time_ms: u32) -> Self {
|
||||
Self {
|
||||
time_ms,
|
||||
timer: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Component for Timeout {
|
||||
type Msg = TimeoutMsg;
|
||||
|
||||
fn place(&mut self, _bounds: Rect) -> Rect {
|
||||
Rect::zero()
|
||||
}
|
||||
|
||||
fn event(&mut self, ctx: &mut EventCtx, event: Event) -> Option<Self::Msg> {
|
||||
match event {
|
||||
// Set up timer.
|
||||
Event::Attach => {
|
||||
self.timer = Some(ctx.request_timer(Duration::from_millis(self.time_ms)));
|
||||
None
|
||||
}
|
||||
// Fire.
|
||||
Event::Timer(token) if Some(token) == self.timer => {
|
||||
self.timer = None;
|
||||
Some(TimeoutMsg::TimedOut)
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn paint(&mut self) {}
|
||||
}
|
||||
|
||||
#[cfg(feature = "ui_debug")]
|
||||
impl crate::trace::Trace for Timeout {
|
||||
fn trace(&self, t: &mut dyn crate::trace::Tracer) {
|
||||
t.open("Timeout");
|
||||
t.int(self.time_ms as i64);
|
||||
t.close();
|
||||
}
|
||||
}
|
@ -1,2 +1,3 @@
|
||||
pub mod obj;
|
||||
pub mod result;
|
||||
pub mod util;
|
||||
|
@ -0,0 +1,23 @@
|
||||
use crate::{
|
||||
error::Error,
|
||||
micropython::{
|
||||
iter::{Iter, IterBuf},
|
||||
obj::Obj,
|
||||
},
|
||||
};
|
||||
use cstr_core::cstr;
|
||||
use heapless::Vec;
|
||||
|
||||
pub fn iter_into_array<T, const N: usize>(iterable: Obj) -> Result<[T; N], Error>
|
||||
where
|
||||
T: TryFrom<Obj, Error = Error>,
|
||||
{
|
||||
let err = Error::ValueError(cstr!("Invalid iterable length"));
|
||||
let mut vec = Vec::<T, N>::new();
|
||||
let mut iter_buf = IterBuf::new();
|
||||
for item in Iter::try_from_obj_with_buf(iterable, &mut iter_buf)? {
|
||||
vec.push(item.try_into()?).map_err(|_| err)?;
|
||||
}
|
||||
// Returns error if array.len() != N
|
||||
vec.into_array().map_err(|_| err)
|
||||
}
|
@ -0,0 +1,73 @@
|
||||
use crate::ui::{
|
||||
component::{Component, Event, EventCtx},
|
||||
geometry::{Grid, GridCellSpan, Rect},
|
||||
model_tt::{
|
||||
component::button::{Button, ButtonMsg},
|
||||
theme,
|
||||
},
|
||||
};
|
||||
|
||||
const NUMBERS: [u32; 5] = [12, 18, 20, 24, 33];
|
||||
const LABELS: [&str; 5] = ["12", "18", "20", "24", "33"];
|
||||
const CELLS: [(usize, usize); 5] = [(0, 0), (0, 2), (0, 4), (1, 1), (1, 3)];
|
||||
|
||||
pub struct SelectWordCount {
|
||||
button: [Button<&'static str>; NUMBERS.len()],
|
||||
}
|
||||
|
||||
pub enum SelectWordCountMsg {
|
||||
Selected(u32),
|
||||
}
|
||||
|
||||
impl SelectWordCount {
|
||||
pub fn new() -> Self {
|
||||
SelectWordCount {
|
||||
button: LABELS.map(Button::with_text),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Component for SelectWordCount {
|
||||
type Msg = SelectWordCountMsg;
|
||||
|
||||
fn place(&mut self, bounds: Rect) -> Rect {
|
||||
let (_, bounds) = bounds.split_bottom(theme::button_rows(2));
|
||||
let grid = Grid::new(bounds, 2, 6).with_spacing(theme::BUTTON_SPACING);
|
||||
for (btn, (x, y)) in self.button.iter_mut().zip(CELLS) {
|
||||
btn.place(grid.cells(GridCellSpan {
|
||||
from: (x, y),
|
||||
to: (x, y + 1),
|
||||
}));
|
||||
}
|
||||
bounds
|
||||
}
|
||||
|
||||
fn event(&mut self, ctx: &mut EventCtx, event: Event) -> Option<Self::Msg> {
|
||||
for (i, btn) in self.button.iter_mut().enumerate() {
|
||||
if let Some(ButtonMsg::Clicked) = btn.event(ctx, event) {
|
||||
return Some(SelectWordCountMsg::Selected(NUMBERS[i]));
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
fn paint(&mut self) {
|
||||
for btn in self.button.iter_mut() {
|
||||
btn.paint()
|
||||
}
|
||||
}
|
||||
|
||||
fn bounds(&self, sink: &mut dyn FnMut(Rect)) {
|
||||
for btn in self.button.iter() {
|
||||
btn.bounds(sink)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "ui_debug")]
|
||||
impl crate::trace::Trace for SelectWordCount {
|
||||
fn trace(&self, t: &mut dyn crate::trace::Tracer) {
|
||||
t.open("SelectWordCount");
|
||||
t.close();
|
||||
}
|
||||
}
|
Binary file not shown.
Loading…
Reference in new issue