|
|
|
@ -11,15 +11,15 @@ use crate::{
|
|
|
|
|
|
|
|
|
|
use heapless::{String, Vec};
|
|
|
|
|
|
|
|
|
|
use super::{common::display_left, scrollbar::SCROLLBAR_SPACE, theme, title::Title, ScrollBar};
|
|
|
|
|
use super::{common::display_left, scrollbar::SCROLLBAR_SPACE, theme, ScrollBar};
|
|
|
|
|
|
|
|
|
|
const WORDS_PER_PAGE: usize = 3;
|
|
|
|
|
const EXTRA_LINE_HEIGHT: i16 = 2;
|
|
|
|
|
const NUMBER_X_OFFSET: i16 = 5;
|
|
|
|
|
const NUMBER_WORD_OFFSET: i16 = 20;
|
|
|
|
|
const NUMBER_X_OFFSET: i16 = 0;
|
|
|
|
|
const WORD_X_OFFSET: i16 = 25;
|
|
|
|
|
const NUMBER_FONT: Font = Font::DEMIBOLD;
|
|
|
|
|
const WORD_FONT: Font = Font::BIG;
|
|
|
|
|
const INFO_TOP_OFFSET: i16 = 15;
|
|
|
|
|
const INFO_TOP_OFFSET: i16 = 20;
|
|
|
|
|
const MAX_WORDS: usize = 33; // super-shamir has 33 words, all other have less
|
|
|
|
|
|
|
|
|
|
/// Showing the given share words.
|
|
|
|
@ -28,7 +28,6 @@ where
|
|
|
|
|
T: StringType,
|
|
|
|
|
{
|
|
|
|
|
area: Rect,
|
|
|
|
|
title: Child<Title<T>>,
|
|
|
|
|
scrollbar: Child<ScrollBar>,
|
|
|
|
|
share_words: Vec<T, MAX_WORDS>,
|
|
|
|
|
page_index: usize,
|
|
|
|
@ -38,10 +37,9 @@ impl<T> ShareWords<T>
|
|
|
|
|
where
|
|
|
|
|
T: StringType + Clone,
|
|
|
|
|
{
|
|
|
|
|
pub fn new(title: T, share_words: Vec<T, MAX_WORDS>) -> Self {
|
|
|
|
|
pub fn new(share_words: Vec<T, MAX_WORDS>) -> Self {
|
|
|
|
|
let mut instance = Self {
|
|
|
|
|
area: Rect::zero(),
|
|
|
|
|
title: Child::new(Title::new(title)),
|
|
|
|
|
scrollbar: Child::new(ScrollBar::to_be_filled_later()),
|
|
|
|
|
share_words,
|
|
|
|
|
page_index: 0,
|
|
|
|
@ -53,15 +51,7 @@ where
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn word_index(&self) -> usize {
|
|
|
|
|
(self.page_index - 2) * WORDS_PER_PAGE
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn is_entry_page(&self) -> bool {
|
|
|
|
|
self.page_index == 0
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn is_second_page(&self) -> bool {
|
|
|
|
|
self.page_index == 1
|
|
|
|
|
self.page_index * WORDS_PER_PAGE
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn is_final_page(&self) -> bool {
|
|
|
|
@ -74,36 +64,13 @@ where
|
|
|
|
|
} else {
|
|
|
|
|
self.share_words.len() / WORDS_PER_PAGE + 1
|
|
|
|
|
};
|
|
|
|
|
// Two pages before the words, one after it
|
|
|
|
|
2 + word_screens + 1
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn get_first_text(&self) -> String<100> {
|
|
|
|
|
build_string!(
|
|
|
|
|
100,
|
|
|
|
|
"Write down all ",
|
|
|
|
|
inttostr!(self.share_words.len() as u8),
|
|
|
|
|
" words in order."
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Display the first page with user information.
|
|
|
|
|
fn paint_entry_page(&mut self) {
|
|
|
|
|
self.render_text_on_screen(&self.get_first_text(), Font::MONO);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn get_second_text(&self) -> String<100> {
|
|
|
|
|
build_string!(100, "Do NOT make digital copies!")
|
|
|
|
|
// One page after the words
|
|
|
|
|
word_screens + 1
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Display the second page with user information.
|
|
|
|
|
fn paint_second_page(&mut self) {
|
|
|
|
|
self.render_text_on_screen(&self.get_second_text(), Font::MONO);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn get_final_text(&self) -> String<100> {
|
|
|
|
|
fn get_final_text(&self) -> String<50> {
|
|
|
|
|
build_string!(
|
|
|
|
|
100,
|
|
|
|
|
50,
|
|
|
|
|
"I wrote down all ",
|
|
|
|
|
inttostr!(self.share_words.len() as u8),
|
|
|
|
|
" words in order."
|
|
|
|
@ -112,15 +79,10 @@ where
|
|
|
|
|
|
|
|
|
|
/// Display the final page with user confirmation.
|
|
|
|
|
fn paint_final_page(&mut self) {
|
|
|
|
|
self.render_text_on_screen(&self.get_final_text(), Font::MONO);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Shows text in the main screen area.
|
|
|
|
|
fn render_text_on_screen(&self, text: &str, font: Font) {
|
|
|
|
|
text_multiline(
|
|
|
|
|
self.area.split_top(INFO_TOP_OFFSET).1,
|
|
|
|
|
text,
|
|
|
|
|
font,
|
|
|
|
|
&self.get_final_text(),
|
|
|
|
|
Font::NORMAL,
|
|
|
|
|
theme::FG,
|
|
|
|
|
theme::BG,
|
|
|
|
|
Alignment::Start,
|
|
|
|
@ -138,9 +100,10 @@ where
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
let word = &self.share_words[index];
|
|
|
|
|
let baseline = self.area.top_left() + Offset::new(NUMBER_X_OFFSET, y_offset);
|
|
|
|
|
display_left(baseline, &inttostr!(index as u8 + 1), NUMBER_FONT);
|
|
|
|
|
display_left(baseline + Offset::x(NUMBER_WORD_OFFSET), &word, WORD_FONT);
|
|
|
|
|
let baseline = self.area.top_left() + Offset::y(y_offset);
|
|
|
|
|
let ordinal = build_string!(5, inttostr!(index as u8 + 1), ".");
|
|
|
|
|
display_left(baseline + Offset::x(NUMBER_X_OFFSET), &ordinal, NUMBER_FONT);
|
|
|
|
|
display_left(baseline + Offset::x(WORD_X_OFFSET), &word, WORD_FONT);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -152,12 +115,11 @@ where
|
|
|
|
|
type Msg = Never;
|
|
|
|
|
|
|
|
|
|
fn place(&mut self, bounds: Rect) -> Rect {
|
|
|
|
|
let (title_area, _) = bounds.split_top(theme::FONT_HEADER.line_height());
|
|
|
|
|
let (top_area, _) = bounds.split_top(theme::FONT_HEADER.line_height());
|
|
|
|
|
|
|
|
|
|
let (title_area, scrollbar_area) =
|
|
|
|
|
title_area.split_right(self.scrollbar.inner().overall_width() + SCROLLBAR_SPACE);
|
|
|
|
|
let (_, scrollbar_area) =
|
|
|
|
|
top_area.split_right(self.scrollbar.inner().overall_width() + SCROLLBAR_SPACE);
|
|
|
|
|
|
|
|
|
|
self.title.place(title_area);
|
|
|
|
|
self.scrollbar.place(scrollbar_area);
|
|
|
|
|
|
|
|
|
|
self.area = bounds;
|
|
|
|
@ -165,7 +127,6 @@ where
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn event(&mut self, ctx: &mut EventCtx, event: Event) -> Option<Self::Msg> {
|
|
|
|
|
self.title.event(ctx, event);
|
|
|
|
|
self.scrollbar.event(ctx, event);
|
|
|
|
|
None
|
|
|
|
|
}
|
|
|
|
@ -174,12 +135,7 @@ where
|
|
|
|
|
// Showing scrollbar in all cases
|
|
|
|
|
// Individual pages are responsible for not colliding with it
|
|
|
|
|
self.scrollbar.paint();
|
|
|
|
|
if self.is_entry_page() {
|
|
|
|
|
self.title.paint();
|
|
|
|
|
self.paint_entry_page();
|
|
|
|
|
} else if self.is_second_page() {
|
|
|
|
|
self.paint_second_page();
|
|
|
|
|
} else if self.is_final_page() {
|
|
|
|
|
if self.is_final_page() {
|
|
|
|
|
self.paint_final_page();
|
|
|
|
|
} else {
|
|
|
|
|
self.paint_words();
|
|
|
|
@ -211,19 +167,10 @@ where
|
|
|
|
|
{
|
|
|
|
|
fn trace(&self, t: &mut dyn crate::trace::Tracer) {
|
|
|
|
|
t.component("ShareWords");
|
|
|
|
|
let content = if self.is_entry_page() {
|
|
|
|
|
build_string!(
|
|
|
|
|
100,
|
|
|
|
|
self.title.inner().get_text(),
|
|
|
|
|
"\n",
|
|
|
|
|
&self.get_first_text()
|
|
|
|
|
)
|
|
|
|
|
} else if self.is_second_page() {
|
|
|
|
|
self.get_second_text()
|
|
|
|
|
} else if self.is_final_page() {
|
|
|
|
|
let content = if self.is_final_page() {
|
|
|
|
|
self.get_final_text()
|
|
|
|
|
} else {
|
|
|
|
|
let mut content = String::<100>::new();
|
|
|
|
|
let mut content = String::<50>::new();
|
|
|
|
|
for i in 0..WORDS_PER_PAGE {
|
|
|
|
|
let index = self.word_index() + i;
|
|
|
|
|
if index >= self.share_words.len() {
|
|
|
|
@ -231,7 +178,7 @@ where
|
|
|
|
|
}
|
|
|
|
|
let word = &self.share_words[index];
|
|
|
|
|
let current_line =
|
|
|
|
|
build_string!(20, inttostr!(index as u8 + 1), " ", word.as_ref(), "\n");
|
|
|
|
|
build_string!(50, inttostr!(index as u8 + 1), ". ", word.as_ref(), "\n");
|
|
|
|
|
unwrap!(content.push_str(¤t_line));
|
|
|
|
|
}
|
|
|
|
|
content
|
|
|
|
|