mirror of
https://github.com/trezor/trezor-firmware.git
synced 2025-08-05 13:26:57 +00:00
fixup! refactor(core): integrate new drawing library
This commit is contained in:
parent
434b272f44
commit
6602bd9b86
@ -61,7 +61,7 @@ pub trait Component {
|
||||
/// the `Child` wrapper.
|
||||
fn paint(&mut self);
|
||||
|
||||
fn render(&mut self, _target: &mut impl Renderer);
|
||||
fn render<'s>(&'s self, _target: &mut impl Renderer<'s>);
|
||||
|
||||
#[cfg(feature = "ui_bounds")]
|
||||
/// Report current paint bounds of this component. Used for debugging.
|
||||
@ -156,7 +156,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
fn render(&mut self, target: &mut impl Renderer) {
|
||||
fn render<'s>(&'s self, target: &mut impl Renderer<'s>) {
|
||||
self.component.render(target);
|
||||
}
|
||||
|
||||
@ -260,7 +260,7 @@ where
|
||||
self.inner.paint();
|
||||
}
|
||||
|
||||
fn render(&mut self, target: &mut impl Renderer) {
|
||||
fn render<'s>(&'s self, target: &mut impl Renderer<'s>) {
|
||||
self.inner.render(target);
|
||||
}
|
||||
|
||||
@ -302,7 +302,7 @@ where
|
||||
self.1.paint();
|
||||
}
|
||||
|
||||
fn render(&mut self, target: &mut impl Renderer) {
|
||||
fn render<'s>(&'s self, target: &mut impl Renderer<'s>) {
|
||||
self.0.render(target);
|
||||
self.1.render(target);
|
||||
}
|
||||
@ -356,7 +356,7 @@ where
|
||||
self.2.paint();
|
||||
}
|
||||
|
||||
fn render(&mut self, target: &mut impl Renderer) {
|
||||
fn render<'s>(&'s self, target: &mut impl Renderer<'s>) {
|
||||
self.0.render(target);
|
||||
self.1.render(target);
|
||||
self.2.render(target);
|
||||
@ -389,8 +389,8 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
fn render(&mut self, target: &mut impl Renderer) {
|
||||
if let Some(ref mut c) = self {
|
||||
fn render<'s>(&'s self, target: &mut impl Renderer<'s>) {
|
||||
if let Some(ref c) = self {
|
||||
c.render(target)
|
||||
}
|
||||
}
|
||||
|
@ -42,7 +42,7 @@ where
|
||||
self.inner.paint()
|
||||
}
|
||||
|
||||
fn render(&mut self, target: &mut impl Renderer) {
|
||||
fn render<'s>(&'s self, target: &mut impl Renderer<'s>) {
|
||||
self.inner.render(target);
|
||||
}
|
||||
|
||||
|
@ -57,7 +57,7 @@ impl Component for Connect {
|
||||
});
|
||||
}
|
||||
|
||||
fn render(&mut self, target: &mut impl Renderer) {
|
||||
fn render<'s>(&'s self, target: &mut impl Renderer<'s>) {
|
||||
let font = Font::NORMAL;
|
||||
|
||||
self.bg.render(target);
|
||||
|
@ -16,7 +16,7 @@ impl Component for Empty {
|
||||
|
||||
fn paint(&mut self) {}
|
||||
|
||||
fn render(&mut self, _target: &mut impl Renderer) {}
|
||||
fn render<'s>(&'s self, _target: &mut impl Renderer<'s>) {}
|
||||
}
|
||||
|
||||
#[cfg(feature = "ui_debug")]
|
||||
|
@ -50,7 +50,7 @@ impl Component for Image {
|
||||
self.draw(self.area.center(), Alignment2D::CENTER);
|
||||
}
|
||||
|
||||
fn render(&mut self, target: &mut impl Renderer) {
|
||||
fn render<'s>(&'s self, target: &mut impl Renderer<'s>) {
|
||||
shape::ToifImage::new(self.area.center(), self.toif)
|
||||
.with_align(Alignment2D::CENTER)
|
||||
.render(target);
|
||||
@ -138,7 +138,7 @@ impl Component for BlendedImage {
|
||||
self.paint_image();
|
||||
}
|
||||
|
||||
fn render(&mut self, target: &mut impl Renderer) {
|
||||
fn render<'s>(&'s self, target: &mut impl Renderer<'s>) {
|
||||
shape::ToifImage::new(self.bg_top_left, self.bg.toif)
|
||||
.with_fg(self.bg_color)
|
||||
.render(target);
|
||||
|
@ -120,7 +120,7 @@ where
|
||||
self.layout.render_text(self.text.as_ref());
|
||||
}
|
||||
|
||||
fn render(&mut self, target: &mut impl Renderer) {
|
||||
fn render<'s>(&'s self, target: &mut impl Renderer<'s>) {
|
||||
self.layout.render_text2(self.text.as_ref(), target);
|
||||
}
|
||||
|
||||
|
@ -31,7 +31,7 @@ where
|
||||
self.inner.paint()
|
||||
}
|
||||
|
||||
fn render(&mut self, target: &mut impl Renderer) {
|
||||
fn render<'s>(&'s self, target: &mut impl Renderer<'s>) {
|
||||
self.inner.render(target);
|
||||
}
|
||||
|
||||
|
@ -132,7 +132,7 @@ where
|
||||
);
|
||||
}
|
||||
|
||||
pub fn render_anim(&mut self, target: &mut impl Renderer, offset: i16) {
|
||||
pub fn render_anim<'s>(&'s self, target: &mut impl Renderer<'s>, offset: i16) {
|
||||
target.in_window(self.area, &mut |target| {
|
||||
let text_height = self.font.text_height();
|
||||
let pos = self.area.top_left() + Offset::new(offset, text_height - 1);
|
||||
@ -237,7 +237,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
fn render(&mut self, target: &mut impl Renderer) {
|
||||
fn render<'s>(&'s self, target: &mut impl Renderer<'s>) {
|
||||
let now = Instant::now();
|
||||
|
||||
match self.state {
|
||||
|
@ -95,7 +95,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
fn render(&mut self, target: &mut impl Renderer) {
|
||||
fn render<'s>(&'s self, target: &mut impl Renderer<'s>) {
|
||||
self.pad.render(target);
|
||||
if self.visible {
|
||||
self.inner.render(target);
|
||||
|
@ -55,7 +55,7 @@ impl Pad {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn render(&mut self, target: &mut impl Renderer) {
|
||||
pub fn render<'s>(&'s self, target: &mut impl Renderer<'s>) {
|
||||
shape::Bar::new(self.area)
|
||||
.with_bg(self.color)
|
||||
.render(target);
|
||||
|
@ -41,7 +41,7 @@ where
|
||||
(self.func)(self.area);
|
||||
}
|
||||
|
||||
fn render(&mut self, target: &mut impl Renderer) {
|
||||
fn render<'s>(&'s self, target: &mut impl Renderer<'s>) {
|
||||
let area = self.area;
|
||||
shape::Bar::new(area)
|
||||
.with_thickness(1)
|
||||
|
@ -65,7 +65,7 @@ where
|
||||
self.inner.paint()
|
||||
}
|
||||
|
||||
fn render(&mut self, target: &mut impl Renderer) {
|
||||
fn render<'s>(&'s self, target: &mut impl Renderer<'s>) {
|
||||
self.inner.render(target);
|
||||
}
|
||||
}
|
||||
@ -112,7 +112,7 @@ where
|
||||
self.inner.paint()
|
||||
}
|
||||
|
||||
fn render(&mut self, target: &mut impl Renderer) {
|
||||
fn render<'s>(&'s self, target: &mut impl Renderer<'s>) {
|
||||
self.inner.render(target);
|
||||
}
|
||||
}
|
||||
@ -188,7 +188,7 @@ where
|
||||
self.inner.paint()
|
||||
}
|
||||
|
||||
fn render(&mut self, target: &mut impl Renderer) {
|
||||
fn render<'s>(&'s self, target: &mut impl Renderer<'s>) {
|
||||
self.inner.render(target);
|
||||
}
|
||||
}
|
||||
@ -283,7 +283,7 @@ where
|
||||
self.second.paint();
|
||||
}
|
||||
|
||||
fn render(&mut self, target: &mut impl Renderer) {
|
||||
fn render<'s>(&'s self, target: &mut impl Renderer<'s>) {
|
||||
self.first.render(target);
|
||||
self.second.render(target);
|
||||
}
|
||||
|
@ -143,7 +143,7 @@ impl Component for Qr {
|
||||
Self::draw(&qr, area, self.border, scale);
|
||||
}
|
||||
|
||||
fn render(&mut self, target: &mut impl Renderer) {
|
||||
fn render<'s>(&'s self, target: &mut impl Renderer<'s>) {
|
||||
let mut outbuffer = [0u8; QR_MAX_VERSION.buffer_len()];
|
||||
let mut tempbuffer = [0u8; QR_MAX_VERSION.buffer_len()];
|
||||
|
||||
|
@ -140,8 +140,8 @@ impl<T: StringType + Clone> Component for FormattedText<T> {
|
||||
self.layout_content(&mut TextRenderer);
|
||||
}
|
||||
|
||||
fn render(&mut self, target: &mut impl Renderer) {
|
||||
self.layout_content(&mut TextRenderer2(target));
|
||||
fn render<'s>(&'s self, target: &mut impl Renderer<'s>) {
|
||||
self.layout_content(&mut TextRenderer2::new(target));
|
||||
}
|
||||
|
||||
#[cfg(feature = "ui_bounds")]
|
||||
|
@ -238,8 +238,12 @@ impl TextLayout {
|
||||
}
|
||||
|
||||
/// Draw as much text as possible on the current screen.
|
||||
pub fn render_text2(&self, text: &str, target: &mut impl Renderer) -> LayoutFit {
|
||||
self.layout_text(text, &mut self.initial_cursor(), &mut TextRenderer2(target))
|
||||
pub fn render_text2<'s>(&self, text: &str, target: &mut impl Renderer<'s>) -> LayoutFit {
|
||||
self.layout_text(
|
||||
text,
|
||||
&mut self.initial_cursor(),
|
||||
&mut TextRenderer2::new(target),
|
||||
)
|
||||
}
|
||||
|
||||
/// Loop through the `text` and try to fit it on the current screen,
|
||||
@ -537,13 +541,22 @@ impl LayoutSink for TextRenderer {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct TextRenderer2<'a, R>(pub &'a mut R)
|
||||
pub struct TextRenderer2<'a, 's, R>(pub &'a mut R, core::marker::PhantomData<&'s ()>)
|
||||
where
|
||||
R: Renderer;
|
||||
R: Renderer<'s>;
|
||||
|
||||
impl<'a, R> LayoutSink for TextRenderer2<'a, R>
|
||||
impl<'a, 's, R> TextRenderer2<'a, 's, R>
|
||||
where
|
||||
R: Renderer,
|
||||
R: Renderer<'s>,
|
||||
{
|
||||
pub fn new(target: &'a mut R) -> Self {
|
||||
Self(target, core::marker::PhantomData)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 's, R> LayoutSink for TextRenderer2<'a, 's, R>
|
||||
where
|
||||
R: Renderer<'s>,
|
||||
{
|
||||
fn text(&mut self, cursor: Point, layout: &TextLayout, text: &str) {
|
||||
shape::Text::new(cursor, text)
|
||||
|
@ -190,7 +190,7 @@ where
|
||||
)
|
||||
}
|
||||
|
||||
fn render(&mut self, target: &mut impl Renderer) {
|
||||
fn render<'s>(&'s self, target: &mut impl Renderer<'s>) {
|
||||
Self::foreach_visible(
|
||||
&self.source,
|
||||
&self.visible,
|
||||
@ -620,12 +620,12 @@ impl<T> Checklist<T> {
|
||||
);
|
||||
}
|
||||
|
||||
fn render_icon(
|
||||
fn render_icon<'s>(
|
||||
&self,
|
||||
layout: &TextLayout,
|
||||
icon: Icon,
|
||||
offset: Offset,
|
||||
target: &mut impl Renderer,
|
||||
target: &mut impl Renderer<'s>,
|
||||
) {
|
||||
let top_left = Point::new(self.area.x0, layout.bounds.y0);
|
||||
shape::ToifImage::new(top_left + offset, icon.toif)
|
||||
@ -671,7 +671,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
fn render(&mut self, target: &mut impl Renderer) {
|
||||
fn render<'s>(&'s self, target: &mut impl Renderer<'s>) {
|
||||
self.paragraphs.render(target);
|
||||
|
||||
let current_visible = self.current.saturating_sub(self.paragraphs.offset.par);
|
||||
|
@ -45,8 +45,8 @@ pub fn text_multiline(
|
||||
///
|
||||
/// If it fits, returns the rest of the area.
|
||||
/// If it does not fit, returns `None`.
|
||||
pub fn text_multiline2(
|
||||
target: &mut impl Renderer,
|
||||
pub fn text_multiline2<'s>(
|
||||
target: &mut impl Renderer<'s>,
|
||||
area: Rect,
|
||||
text: TString<'_>,
|
||||
font: Font,
|
||||
@ -97,8 +97,8 @@ pub fn text_multiline_bottom(
|
||||
|
||||
/// Same as `text_multiline` above, but aligns the text to the bottom of the
|
||||
/// area.
|
||||
pub fn text_multiline_bottom2(
|
||||
target: &mut impl Renderer,
|
||||
pub fn text_multiline_bottom2<'s>(
|
||||
target: &mut impl Renderer<'s>,
|
||||
area: Rect,
|
||||
text: TString<'_>,
|
||||
font: Font,
|
||||
|
@ -46,7 +46,7 @@ impl Component for Timeout {
|
||||
|
||||
fn paint(&mut self) {}
|
||||
|
||||
fn render(&mut self, _target: &mut impl Renderer) {}
|
||||
fn render<'s>(&'s self, _target: &mut impl Renderer<'s>) {}
|
||||
}
|
||||
|
||||
#[cfg(feature = "ui_debug")]
|
||||
|
@ -14,7 +14,6 @@ use crate::{
|
||||
},
|
||||
};
|
||||
|
||||
#[cfg(not(feature = "new_rendering"))]
|
||||
pub fn jpeg(data: &[u8], pos: Point, scale: u8) {
|
||||
let mut buffer = BufferJpegWork::get_cleared();
|
||||
let pool = buffer.buffer.as_mut_slice();
|
||||
|
@ -105,7 +105,7 @@ impl<'a> Component for Intro<'a> {
|
||||
self.buttons.paint();
|
||||
}
|
||||
|
||||
fn render(&mut self, target: &mut impl Renderer) {
|
||||
fn render<'s>(&'s self, target: &mut impl Renderer<'s>) {
|
||||
self.bg.render(target);
|
||||
self.title.render(target);
|
||||
|
||||
|
@ -73,7 +73,7 @@ impl Choice for MenuChoice {
|
||||
);
|
||||
}
|
||||
|
||||
fn render_center(&self, target: &mut impl Renderer, _area: Rect, _inverse: bool) {
|
||||
fn render_center<'s>(&self, target: &mut impl Renderer<'s>, _area: Rect, _inverse: bool) {
|
||||
// Icon on top and two lines of text below
|
||||
shape::ToifImage::new(SCREEN_CENTER + Offset::y(-20), self.icon.toif)
|
||||
.with_align(Alignment2D::CENTER)
|
||||
@ -186,7 +186,7 @@ impl Component for Menu {
|
||||
self.choice_page.paint();
|
||||
}
|
||||
|
||||
fn render(&mut self, target: &mut impl Renderer) {
|
||||
fn render<'s>(&'s self, target: &mut impl Renderer<'s>) {
|
||||
self.pad.render(target);
|
||||
self.choice_page.render(target);
|
||||
}
|
||||
|
@ -60,7 +60,7 @@ impl Component for Welcome {
|
||||
);
|
||||
}
|
||||
|
||||
fn render(&mut self, target: &mut impl Renderer) {
|
||||
fn render<'s>(&'s self, target: &mut impl Renderer<'s>) {
|
||||
self.bg.render(target);
|
||||
|
||||
let top_center = self.bg.area.top_center();
|
||||
|
@ -257,7 +257,7 @@ impl Component for AddressDetails {
|
||||
}
|
||||
}
|
||||
|
||||
fn render(&mut self, target: &mut impl Renderer) {
|
||||
fn render<'s>(&'s self, target: &mut impl Renderer<'s>) {
|
||||
self.pad.render(target);
|
||||
self.buttons.render(target);
|
||||
match self.current_page {
|
||||
|
@ -229,8 +229,8 @@ where
|
||||
self.buttons.paint();
|
||||
}
|
||||
|
||||
fn render(&mut self, target: &mut impl Renderer) {
|
||||
self.bg.paint();
|
||||
fn render<'s>(&'s self, target: &mut impl Renderer<'s>) {
|
||||
self.bg.render(target);
|
||||
|
||||
let mut display_top_left = |text: TString<'static>| {
|
||||
text.map(|t| {
|
||||
|
@ -268,7 +268,7 @@ impl Component for Button {
|
||||
}
|
||||
}
|
||||
|
||||
fn render(&mut self, target: &mut impl Renderer) {
|
||||
fn render<'s>(&'s self, target: &mut impl Renderer<'s>) {
|
||||
let style = self.style();
|
||||
let fg_color = style.text_color;
|
||||
let bg_color = fg_color.negate();
|
||||
|
@ -95,7 +95,7 @@ impl ButtonType {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn render(&mut self, target: &mut impl Renderer) {
|
||||
pub fn render<'s>(&'s self, target: &mut impl Renderer<'s>) {
|
||||
match self {
|
||||
Self::Button(button) => {
|
||||
button.render(target);
|
||||
@ -167,7 +167,7 @@ impl ButtonContainer {
|
||||
self.button_type.paint();
|
||||
}
|
||||
|
||||
pub fn render(&mut self, target: &mut impl Renderer) {
|
||||
pub fn render<'s>(&'s self, target: &mut impl Renderer<'s>) {
|
||||
self.button_type.render(target);
|
||||
}
|
||||
|
||||
@ -592,7 +592,7 @@ impl Component for ButtonController {
|
||||
self.right_btn.paint();
|
||||
}
|
||||
|
||||
fn render(&mut self, target: &mut impl Renderer) {
|
||||
fn render<'s>(&'s self, target: &mut impl Renderer<'s>) {
|
||||
self.pad.render(target);
|
||||
self.left_btn.render(target);
|
||||
self.middle_btn.render(target);
|
||||
@ -778,7 +778,7 @@ impl Component for AutomaticMover {
|
||||
|
||||
fn paint(&mut self) {}
|
||||
|
||||
fn render(&mut self, _target: &mut impl Renderer) {}
|
||||
fn render<'s>(&'s self, _target: &mut impl Renderer<'s>) {}
|
||||
|
||||
fn event(&mut self, ctx: &mut EventCtx, event: Event) -> Option<Self::Msg> {
|
||||
// Moving automatically only when we receive a TimerToken that we have
|
||||
|
@ -111,7 +111,7 @@ where
|
||||
common::display_left(baseline, &self.text, self.font);
|
||||
}
|
||||
|
||||
fn render_left(&self, target: &mut impl Renderer) {
|
||||
fn render_left<'s>(&'s self, target: &mut impl Renderer<'s>) {
|
||||
let baseline = Point::new(self.pad.area.x0, self.y_baseline());
|
||||
shape::Text::new(baseline, &self.text.as_ref())
|
||||
.with_font(self.font)
|
||||
@ -123,7 +123,7 @@ where
|
||||
common::display_center(baseline, &self.text, self.font);
|
||||
}
|
||||
|
||||
fn render_center(&self, target: &mut impl Renderer) {
|
||||
fn render_center<'s>(&'s self, target: &mut impl Renderer<'s>) {
|
||||
let baseline = Point::new(self.pad.area.bottom_center().x, self.y_baseline());
|
||||
shape::Text::new(baseline, &self.text.as_ref())
|
||||
.with_align(Alignment::Center)
|
||||
@ -136,7 +136,7 @@ where
|
||||
common::display_right(baseline, &self.text, self.font);
|
||||
}
|
||||
|
||||
fn render_right(&self, target: &mut impl Renderer) {
|
||||
fn render_right<'s>(&'s self, target: &mut impl Renderer<'s>) {
|
||||
let baseline = Point::new(self.pad.area.x1, self.y_baseline());
|
||||
shape::Text::new(baseline, &self.text.as_ref())
|
||||
.with_align(Alignment::End)
|
||||
@ -201,7 +201,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
fn render(&mut self, target: &mut impl Renderer) {
|
||||
fn render<'s>(&'s self, target: &mut impl Renderer<'s>) {
|
||||
self.pad.render(target);
|
||||
if self.show_content {
|
||||
// In the case text cannot fit, show ellipsis and its right part
|
||||
|
@ -136,7 +136,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
fn render(&mut self, target: &mut impl Renderer) {
|
||||
fn render<'s>(&'s self, target: &mut impl Renderer<'s>) {
|
||||
// TOP
|
||||
let center = self.area.center() + Offset::y(self.loader_y_offset);
|
||||
|
||||
|
@ -99,7 +99,7 @@ impl<T: AsRef<str>> Component for ErrorScreen<T> {
|
||||
self.footer.paint();
|
||||
}
|
||||
|
||||
fn render(&mut self, target: &mut impl Renderer) {
|
||||
fn render<'s>(&'s self, target: &mut impl Renderer<'s>) {
|
||||
self.bg.render(target);
|
||||
|
||||
if self.show_icons {
|
||||
|
@ -310,7 +310,7 @@ where
|
||||
self.current_page.paint();
|
||||
}
|
||||
|
||||
fn render(&mut self, target: &mut impl Renderer) {
|
||||
fn render<'s>(&'s self, target: &mut impl Renderer<'s>) {
|
||||
self.pad.render(target);
|
||||
// Scrollbars are painted only with a title and when requested
|
||||
if self.title.is_some() {
|
||||
|
@ -133,8 +133,7 @@ where
|
||||
self.formatted.paint();
|
||||
}
|
||||
|
||||
pub fn render(&mut self, target: &mut impl Renderer) {
|
||||
self.change_page(self.current_page);
|
||||
pub fn render<'s>(&'s self, target: &mut impl Renderer<'s>) {
|
||||
self.formatted.render(target);
|
||||
}
|
||||
|
||||
|
@ -85,7 +85,7 @@ where
|
||||
self.content.paint();
|
||||
}
|
||||
|
||||
fn render(&mut self, target: &mut impl Renderer) {
|
||||
fn render<'s>(&'s self, target: &mut impl Renderer<'s>) {
|
||||
self.title.render(target);
|
||||
self.content.render(target);
|
||||
}
|
||||
@ -211,7 +211,7 @@ where
|
||||
self.content.paint();
|
||||
}
|
||||
|
||||
fn render(&mut self, target: &mut impl Renderer) {
|
||||
fn render<'s>(&'s self, target: &mut impl Renderer<'s>) {
|
||||
self.title.render(target);
|
||||
self.scrollbar.render(target);
|
||||
self.content.render(target);
|
||||
|
@ -124,7 +124,7 @@ impl Component for HoldToConfirm {
|
||||
self.loader.paint();
|
||||
}
|
||||
|
||||
fn render(&mut self, target: &mut impl Renderer) {
|
||||
fn render<'s>(&'s self, target: &mut impl Renderer<'s>) {
|
||||
self.loader.render(target);
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,10 @@
|
||||
use crate::{
|
||||
error::Error,
|
||||
micropython::buffer::StrBuffer,
|
||||
micropython::{
|
||||
buffer::{get_buffer, StrBuffer},
|
||||
gc::Gc,
|
||||
obj::Obj,
|
||||
},
|
||||
strutil::StringType,
|
||||
translations::TR,
|
||||
trezorhal::usb::usb_configured,
|
||||
@ -50,7 +54,7 @@ fn paint_default_image() {
|
||||
);
|
||||
}
|
||||
|
||||
fn render_default_image(target: &mut impl Renderer) {
|
||||
fn render_default_image<'s>(target: &mut impl Renderer<'s>) {
|
||||
shape::ToifImage::new(
|
||||
TOP_CENTER + Offset::y(LOGO_ICON_TOP_MARGIN),
|
||||
theme::ICON_LOGO.toif,
|
||||
@ -74,6 +78,7 @@ where
|
||||
// always painted, so we need to always paint the label too
|
||||
label: Label<T>,
|
||||
notification: Option<(T, u8)>,
|
||||
custom_image: Option<Gc<[u8]>>,
|
||||
/// Used for HTC functionality to lock device from homescreen
|
||||
invisible_buttons: Child<ButtonController>,
|
||||
/// Holds the loader component
|
||||
@ -97,6 +102,7 @@ where
|
||||
Self {
|
||||
label: Label::centered(label, theme::TEXT_BIG),
|
||||
notification,
|
||||
custom_image: get_user_custom_image().ok(),
|
||||
invisible_buttons: Child::new(ButtonController::new(invisible_btn_layout)),
|
||||
loader,
|
||||
show_loader: false,
|
||||
@ -105,8 +111,8 @@ where
|
||||
}
|
||||
|
||||
fn paint_homescreen_image(&self) {
|
||||
let homescreen_bytes = get_user_custom_image().ok();
|
||||
let homescreen = homescreen_bytes
|
||||
let homescreen = self
|
||||
.custom_image
|
||||
.as_ref()
|
||||
.and_then(|data| Toif::new(data.as_ref()).ok())
|
||||
.filter(check_homescreen_format);
|
||||
@ -117,17 +123,17 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
fn render_homescreen_image(&self, target: &mut impl Renderer) {
|
||||
let homescreen_bytes = get_user_custom_image().ok();
|
||||
let homescreen = homescreen_bytes
|
||||
fn render_homescreen_image<'s>(&'s self, target: &mut impl Renderer<'s>) {
|
||||
let homescreen = self
|
||||
.custom_image
|
||||
.as_ref()
|
||||
.and_then(|data| Toif::new(data.as_ref()).ok())
|
||||
.filter(check_homescreen_format);
|
||||
if let Some(toif) = homescreen {
|
||||
/*shape::ToifImage::new(TOP_CENTER, toif)
|
||||
shape::ToifImage::new(TOP_CENTER, toif)
|
||||
.with_align(Alignment2D::TOP_CENTER)
|
||||
.with_fg(theme::FG)
|
||||
.render(target);*/ // !@# lifetime problem
|
||||
.render(target);
|
||||
} else {
|
||||
render_default_image(target);
|
||||
}
|
||||
@ -164,7 +170,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
fn render_notification(&self, target: &mut impl Renderer) {
|
||||
fn render_notification<'s>(&'s self, target: &mut impl Renderer<'s>) {
|
||||
let baseline = TOP_CENTER + Offset::y(NOTIFICATION_FONT.line_height());
|
||||
if !usb_configured() {
|
||||
shape::Bar::new(AREA.split_top(NOTIFICATION_HEIGHT).0)
|
||||
@ -217,12 +223,12 @@ where
|
||||
self.label.paint();
|
||||
}
|
||||
|
||||
fn render_label(&mut self, target: &mut impl Renderer) {
|
||||
fn render_label<'s>(&'s self, target: &mut impl Renderer<'s>) {
|
||||
// paint black background to place the label
|
||||
let mut outset = Insets::uniform(LABEL_OUTSET);
|
||||
// the margin at top is bigger (caused by text-height vs line-height?)
|
||||
// compensate by shrinking the outset
|
||||
outset.top -= 2;
|
||||
outset.top -= 5;
|
||||
shape::Bar::new(self.label.text_area().outset(outset))
|
||||
.with_bg(theme::BG)
|
||||
.render(target);
|
||||
@ -321,19 +327,11 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
fn render(&mut self, target: &mut impl Renderer) {
|
||||
fn render<'s>(&'s self, target: &mut impl Renderer<'s>) {
|
||||
// Redraw the whole screen when the screen changes (loader vs homescreen)
|
||||
if self.show_loader {
|
||||
if !matches!(self.current_screen, CurrentScreen::Loader) {
|
||||
// display::clear(); !@# what's this??
|
||||
self.current_screen = CurrentScreen::Loader;
|
||||
}
|
||||
self.loader.render(target);
|
||||
} else {
|
||||
if !matches!(self.current_screen, CurrentScreen::Homescreen) {
|
||||
// display::clear(); !@# what's this??
|
||||
self.current_screen = CurrentScreen::Homescreen;
|
||||
}
|
||||
// Painting the homescreen image first, as the notification and label
|
||||
// should be "on top of it"
|
||||
self.render_homescreen_image(target);
|
||||
@ -426,7 +424,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
fn render(&mut self, target: &mut impl Renderer) {
|
||||
fn render<'s>(&'s self, target: &mut impl Renderer<'s>) {
|
||||
if self.screensaver {
|
||||
// keep screen blank
|
||||
return;
|
||||
@ -451,33 +449,32 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ConfirmHomescreen<T, F>
|
||||
pub struct ConfirmHomescreen<T>
|
||||
where
|
||||
T: StringType,
|
||||
{
|
||||
title: Child<Label<T>>,
|
||||
buffer_func: F,
|
||||
image: Obj,
|
||||
buttons: Child<ButtonController>,
|
||||
}
|
||||
|
||||
impl<T, F> ConfirmHomescreen<T, F>
|
||||
impl<T> ConfirmHomescreen<T>
|
||||
where
|
||||
T: StringType + Clone,
|
||||
{
|
||||
pub fn new(title: T, buffer_func: F) -> Self {
|
||||
pub fn new(title: T, image: Obj) -> Self {
|
||||
let btn_layout = ButtonLayout::cancel_none_text(TR::buttons__change.into());
|
||||
ConfirmHomescreen {
|
||||
title: Child::new(Label::centered(title, theme::TEXT_BOLD)),
|
||||
buffer_func,
|
||||
image,
|
||||
buttons: Child::new(ButtonController::new(btn_layout)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T, F> Component for ConfirmHomescreen<T, F>
|
||||
impl<'a, T> Component for ConfirmHomescreen<T>
|
||||
where
|
||||
T: StringType + Clone,
|
||||
F: Fn() -> &'a [u8],
|
||||
{
|
||||
type Msg = CancelConfirmMsg;
|
||||
|
||||
@ -504,11 +501,13 @@ where
|
||||
|
||||
fn paint(&mut self) {
|
||||
// Drawing the image full-screen first and then other things on top
|
||||
let buffer = (self.buffer_func)();
|
||||
if buffer.is_empty() {
|
||||
// SAFETY: We expect no existing mutable reference. Resulting reference is
|
||||
// discarded before returning to micropython.
|
||||
let image_data = unwrap!(unsafe { get_buffer(self.image) });
|
||||
if image_data.is_empty() {
|
||||
paint_default_image();
|
||||
} else {
|
||||
let toif_data = unwrap!(Toif::new(buffer));
|
||||
let toif_data = unwrap!(Toif::new(image_data));
|
||||
toif_data.draw(TOP_CENTER, Alignment2D::TOP_CENTER, theme::FG, theme::BG);
|
||||
};
|
||||
// Need to make all the title background black, so the title text is well
|
||||
@ -519,16 +518,18 @@ where
|
||||
self.buttons.paint();
|
||||
}
|
||||
|
||||
fn render(&mut self, target: &mut impl Renderer) {
|
||||
fn render<'s>(&'s self, target: &mut impl Renderer<'s>) {
|
||||
// Drawing the image full-screen first and then other things on top
|
||||
let buffer = (self.buffer_func)();
|
||||
if buffer.is_empty() {
|
||||
// SAFETY: We expect no existing mutable reference. Resulting reference is
|
||||
// discarded before returning to micropython.
|
||||
let image_data = unwrap!(unsafe { get_buffer(self.image) });
|
||||
if image_data.is_empty() {
|
||||
render_default_image(target);
|
||||
} else {
|
||||
/*let toif_data = unwrap!(Toif::new(buffer));
|
||||
let toif_data = unwrap!(Toif::new(image_data));
|
||||
shape::ToifImage::new(TOP_CENTER, toif_data)
|
||||
.with_fg(theme::FG)
|
||||
.render(target);*/ // !@# lifetime problem
|
||||
.render(target);
|
||||
};
|
||||
// Need to make all the title background black, so the title text is well
|
||||
// visible
|
||||
@ -572,7 +573,7 @@ where
|
||||
}
|
||||
|
||||
#[cfg(feature = "ui_debug")]
|
||||
impl<T, F> crate::trace::Trace for ConfirmHomescreen<T, F>
|
||||
impl<T> crate::trace::Trace for ConfirmHomescreen<T>
|
||||
where
|
||||
T: StringType,
|
||||
{
|
||||
|
@ -16,7 +16,7 @@ pub trait Choice {
|
||||
// and therefore has a default implementation.
|
||||
fn paint_center(&self, area: Rect, inverse: bool);
|
||||
|
||||
fn render_center(&self, target: &mut impl Renderer, _area: Rect, _inverse: bool);
|
||||
fn render_center<'s>(&self, target: &mut impl Renderer<'s>, _area: Rect, _inverse: bool);
|
||||
|
||||
fn width_center(&self) -> i16 {
|
||||
0
|
||||
@ -24,7 +24,7 @@ pub trait Choice {
|
||||
|
||||
fn paint_side(&self, _area: Rect) {}
|
||||
|
||||
fn render_side(&self, _target: &mut impl Renderer, _area: Rect) {}
|
||||
fn render_side<'s>(&self, _target: &mut impl Renderer<'s>, _area: Rect) {}
|
||||
|
||||
fn width_side(&self) -> i16 {
|
||||
0
|
||||
@ -257,11 +257,11 @@ where
|
||||
|
||||
/// Display current, previous and next choices according to
|
||||
/// the current ChoiceItem.
|
||||
fn render_choices(&mut self, target: &mut impl Renderer) {
|
||||
fn render_choices<'s>(&'s self, target: &mut impl Renderer<'s>) {
|
||||
// Getting the row area for the choices - so that displaying
|
||||
// items in the used font will show them in the middle vertically.
|
||||
let area_height_half = self.pad.area.height() / 2;
|
||||
let font_size_half = theme::FONT_CHOICE_ITEMS.text_height() / 2;
|
||||
let font_size_half = theme::FONT_CHOICE_ITEMS.visible_text_height("Ay") / 2;
|
||||
let center_row_area = self
|
||||
.pad
|
||||
.area
|
||||
@ -341,14 +341,9 @@ where
|
||||
}
|
||||
|
||||
/// Display the current choice in the middle.
|
||||
fn show_current_choice2(&mut self, target: &mut impl Renderer, area: Rect) {
|
||||
fn show_current_choice2<'s>(&'s self, target: &mut impl Renderer<'s>, area: Rect) {
|
||||
self.get_current_item()
|
||||
.render_center(target, area, self.inverse_selected_item);
|
||||
|
||||
// Color inversion is just one-time thing.
|
||||
if self.inverse_selected_item {
|
||||
self.inverse_selected_item = false;
|
||||
}
|
||||
}
|
||||
|
||||
/// Display all the choices fitting on the left side.
|
||||
@ -395,7 +390,7 @@ where
|
||||
|
||||
/// Display all the choices fitting on the left side.
|
||||
/// Going as far as possible.
|
||||
fn show_left_choices2(&self, target: &mut impl Renderer, area: Rect) {
|
||||
fn show_left_choices2<'s>(&'s self, target: &mut impl Renderer<'s>, area: Rect) {
|
||||
// NOTE: page index can get negative here, so having it as i16 instead of usize
|
||||
let mut page_index = self.page_counter as i16 - 1;
|
||||
let mut current_area = area.split_right(self.items_distance).0;
|
||||
@ -478,7 +473,7 @@ where
|
||||
|
||||
/// Display all the choices fitting on the right side.
|
||||
/// Going as far as possible.
|
||||
fn show_right_choices2(&self, target: &mut impl Renderer, area: Rect) {
|
||||
fn show_right_choices2<'s>(&'s self, target: &mut impl Renderer<'s>, area: Rect) {
|
||||
let mut page_index = self.page_counter + 1;
|
||||
let mut current_area = area.split_left(self.items_distance).1;
|
||||
while current_area.width() > 0 {
|
||||
@ -624,7 +619,6 @@ where
|
||||
}
|
||||
|
||||
fn event(&mut self, ctx: &mut EventCtx, event: Event) -> Option<Self::Msg> {
|
||||
|
||||
// Cancel highlighting of the current choice.
|
||||
// The Highlighting is started by pressing the middle button and
|
||||
// canceled immediately when any other event is processed
|
||||
@ -728,7 +722,7 @@ where
|
||||
self.paint_choices();
|
||||
}
|
||||
|
||||
fn render(&mut self, target: &mut impl Renderer) {
|
||||
fn render<'s>(&'s self, target: &mut impl Renderer<'s>) {
|
||||
self.pad.render(target);
|
||||
self.buttons.render(target);
|
||||
self.render_choices(target);
|
||||
|
@ -111,12 +111,12 @@ impl Choice for ChoiceItem {
|
||||
|
||||
/// Painting the item as the main choice in the middle.
|
||||
/// Showing both the icon and text, if the icon is available.
|
||||
fn render_center(&self, target: &mut impl Renderer, area: Rect, inverse: bool) {
|
||||
fn render_center<'s>(&self, target: &mut impl Renderer<'s>, area: Rect, inverse: bool) {
|
||||
let width = text_icon_width(Some(self.text.as_ref()), self.icon, self.font);
|
||||
render_rounded_highlight(
|
||||
target,
|
||||
area,
|
||||
Offset::new(width, self.font.text_height()),
|
||||
Offset::new(width, self.font.visible_text_height("Ay")),
|
||||
inverse,
|
||||
);
|
||||
render_text_icon(
|
||||
@ -149,7 +149,7 @@ impl Choice for ChoiceItem {
|
||||
}
|
||||
|
||||
/// Painting smaller version of the item on the side.
|
||||
fn render_side(&self, target: &mut impl Renderer, area: Rect) {
|
||||
fn render_side<'s>(&self, target: &mut impl Renderer<'s>, area: Rect) {
|
||||
let width = text_icon_width(self.side_text(), self.icon, self.font);
|
||||
render_text_icon(
|
||||
target,
|
||||
@ -188,7 +188,12 @@ fn paint_rounded_highlight(area: Rect, size: Offset, inverse: bool) {
|
||||
}
|
||||
}
|
||||
|
||||
fn render_rounded_highlight(target: &mut impl Renderer, area: Rect, size: Offset, inverse: bool) {
|
||||
fn render_rounded_highlight<'s>(
|
||||
target: &mut impl Renderer<'s>,
|
||||
area: Rect,
|
||||
size: Offset,
|
||||
inverse: bool,
|
||||
) {
|
||||
let bound = theme::BUTTON_OUTLINE;
|
||||
let left_bottom = area.bottom_center() + Offset::new(-size.x / 2 - bound, bound + 1);
|
||||
let x_size = size.x + 2 * bound;
|
||||
@ -257,8 +262,8 @@ fn paint_text_icon(
|
||||
}
|
||||
}
|
||||
|
||||
fn render_text_icon(
|
||||
target: &mut impl Renderer,
|
||||
fn render_text_icon<'s>(
|
||||
target: &mut impl Renderer<'s>,
|
||||
area: Rect,
|
||||
width: i16,
|
||||
text: Option<&str>,
|
||||
@ -270,7 +275,7 @@ fn render_text_icon(
|
||||
|
||||
let mut baseline = area.bottom_center() - Offset::x(width / 2);
|
||||
if let Some(icon) = icon {
|
||||
let height_diff = font.text_height() - icon.toif.height();
|
||||
let height_diff = font.visible_text_height("Ay") - icon.toif.height();
|
||||
let vertical_offset = Offset::y(-height_diff / 2);
|
||||
shape::ToifImage::new(baseline + vertical_offset, icon.toif)
|
||||
.with_align(Alignment2D::BOTTOM_LEFT)
|
||||
|
@ -83,7 +83,7 @@ impl Component for NumberInput {
|
||||
self.choice_page.paint();
|
||||
}
|
||||
|
||||
fn render(&mut self, target: &mut impl Renderer) {
|
||||
fn render<'s>(&'s self, target: &mut impl Renderer<'s>) {
|
||||
self.choice_page.render(target);
|
||||
}
|
||||
}
|
||||
|
@ -450,7 +450,7 @@ impl Component for PassphraseEntry {
|
||||
self.choice_page.paint();
|
||||
}
|
||||
|
||||
fn render(&mut self, target: &mut impl Renderer) {
|
||||
fn render<'s>(&'s self, target: &mut impl Renderer<'s>) {
|
||||
self.passphrase_dots.render(target);
|
||||
self.choice_page.render(target);
|
||||
}
|
||||
|
@ -331,7 +331,7 @@ where
|
||||
self.choice_page.paint();
|
||||
}
|
||||
|
||||
fn render(&mut self, target: &mut impl Renderer) {
|
||||
fn render<'s>(&'s self, target: &mut impl Renderer<'s>) {
|
||||
self.header_line.render(target);
|
||||
self.pin_line.render(target);
|
||||
self.choice_page.render(target);
|
||||
|
@ -117,7 +117,7 @@ impl Component for SimpleChoice {
|
||||
self.choice_page.paint();
|
||||
}
|
||||
|
||||
fn render(&mut self, target: &mut impl Renderer) {
|
||||
fn render<'s>(&'s self, target: &mut impl Renderer<'s>) {
|
||||
self.choice_page.render(target);
|
||||
}
|
||||
}
|
||||
|
@ -312,7 +312,7 @@ impl Component for WordlistEntry {
|
||||
self.choice_page.paint();
|
||||
}
|
||||
|
||||
fn render(&mut self, target: &mut impl Renderer) {
|
||||
fn render<'s>(&'s self, target: &mut impl Renderer<'s>) {
|
||||
self.chosen_letters.render(target);
|
||||
self.choice_page.render(target);
|
||||
}
|
||||
|
@ -167,7 +167,12 @@ impl Loader {
|
||||
);
|
||||
}
|
||||
|
||||
pub fn render_loader(&mut self, target: &mut impl Renderer, style: &LoaderStyle, done: i32) {
|
||||
pub fn render_loader<'s>(
|
||||
&'s self,
|
||||
target: &mut impl Renderer<'s>,
|
||||
style: &LoaderStyle,
|
||||
done: i32,
|
||||
) {
|
||||
let width = self.area.width();
|
||||
// NOTE: need to calculate this in `i32`, it would overflow using `i16`
|
||||
let split_point = (((width as i32 + 1) * done) / (display::LOADER_MAX as i32)) as i16;
|
||||
@ -266,7 +271,7 @@ impl Component for Loader {
|
||||
}
|
||||
}
|
||||
|
||||
fn render(&mut self, target: &mut impl Renderer) {
|
||||
fn render<'s>(&'s self, target: &mut impl Renderer<'s>) {
|
||||
// TODO: Consider passing the current instant along with the event -- that way,
|
||||
// we could synchronize painting across the component tree. Also could be useful
|
||||
// in automated tests.
|
||||
@ -397,7 +402,7 @@ where
|
||||
self.loader.paint();
|
||||
}
|
||||
|
||||
fn render(&mut self, target: &mut impl Renderer) {
|
||||
fn render<'s>(&'s self, target: &mut impl Renderer<'s>) {
|
||||
self.loader.render(target);
|
||||
}
|
||||
}
|
||||
|
@ -217,7 +217,7 @@ where
|
||||
self.buttons.paint();
|
||||
}
|
||||
|
||||
fn render(&mut self, target: &mut impl Renderer) {
|
||||
fn render<'s>(&'s self, target: &mut impl Renderer<'s>) {
|
||||
self.pad.render(target);
|
||||
self.content.render(target);
|
||||
self.buttons.render(target);
|
||||
|
@ -185,7 +185,7 @@ where
|
||||
self.description.paint();
|
||||
}
|
||||
|
||||
fn render(&mut self, target: &mut impl Renderer) {
|
||||
fn render<'s>(&'s self, target: &mut impl Renderer<'s>) {
|
||||
self.title.render(target);
|
||||
|
||||
let area = constant::screen();
|
||||
|
@ -110,7 +110,7 @@ impl<'a> Component for ResultScreen<'a> {
|
||||
self.message_bottom.paint();
|
||||
}
|
||||
|
||||
fn render(&mut self, target: &mut impl Renderer) {
|
||||
fn render<'s>(&'s self, target: &mut impl Renderer<'s>) {
|
||||
self.bg.render(target);
|
||||
self.small_pad.render(target);
|
||||
|
||||
|
@ -108,7 +108,7 @@ impl ScrollBar {
|
||||
/// Create a (seemingly circular) dot given its top left point.
|
||||
/// Make it full when it is active, otherwise paint just the perimeter and
|
||||
/// leave center empty.
|
||||
fn render_dot(&self, target: &mut impl Renderer, dot_type: &DotType, top_right: Point) {
|
||||
fn render_dot<'s>(&self, target: &mut impl Renderer<'s>, dot_type: &DotType, top_right: Point) {
|
||||
let full_square =
|
||||
Rect::from_top_right_and_size(top_right, Offset::uniform(Self::MAX_DOT_SIZE));
|
||||
|
||||
@ -234,7 +234,7 @@ impl ScrollBar {
|
||||
}
|
||||
}
|
||||
|
||||
fn render_horizontal(&mut self, target: &mut impl Renderer) {
|
||||
fn render_horizontal<'s>(&'s self, target: &mut impl Renderer<'s>) {
|
||||
let mut top_right = self.pad.area.top_right();
|
||||
for dot in self.get_drawable_dots().iter().rev() {
|
||||
self.render_dot(target, dot, top_right);
|
||||
@ -274,7 +274,7 @@ impl Component for ScrollBar {
|
||||
}
|
||||
|
||||
/// Displaying one dot for each page.
|
||||
fn render(&mut self, target: &mut impl Renderer) {
|
||||
fn render<'s>(&'s self, target: &mut impl Renderer<'s>) {
|
||||
// Not showing the scrollbar dot when there is only one page
|
||||
if self.page_count <= 1 {
|
||||
return;
|
||||
|
@ -99,7 +99,7 @@ where
|
||||
}
|
||||
|
||||
/// Display the final page with user confirmation.
|
||||
fn render_final_page(&mut self, target: &mut impl Renderer) {
|
||||
fn render_final_page<'s>(&'s self, target: &mut impl Renderer<'s>) {
|
||||
let final_text = self.get_final_text();
|
||||
text_multiline2(
|
||||
target,
|
||||
@ -131,7 +131,7 @@ where
|
||||
}
|
||||
|
||||
/// Display current set of recovery words.
|
||||
fn render_words(&mut self, target: &mut impl Renderer) {
|
||||
fn render_words<'s>(&'s self, target: &mut impl Renderer<'s>) {
|
||||
let mut y_offset = 0;
|
||||
// Showing the word index and the words itself
|
||||
for i in 0..WORDS_PER_PAGE {
|
||||
@ -191,7 +191,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
fn render(&mut self, target: &mut impl Renderer) {
|
||||
fn render<'s>(&'s self, target: &mut impl Renderer<'s>) {
|
||||
// Showing scrollbar in all cases
|
||||
// Individual pages are responsible for not colliding with it
|
||||
self.scrollbar.render(target);
|
||||
|
@ -79,7 +79,7 @@ where
|
||||
self.buttons.paint();
|
||||
}
|
||||
|
||||
fn render(&mut self, target: &mut impl Renderer) {
|
||||
fn render<'s>(&'s self, target: &mut impl Renderer<'s>) {
|
||||
self.content.render(target);
|
||||
self.buttons.render(target);
|
||||
}
|
||||
|
@ -72,7 +72,7 @@ where
|
||||
}
|
||||
|
||||
/// Display title/header at the top left of the given area.
|
||||
pub fn render_header_left(target: &mut impl Renderer, title: &T, area: Rect) {
|
||||
pub fn render_header_left<'s>(target: &mut impl Renderer<'s>, title: &T, area: Rect) {
|
||||
let text_height = theme::FONT_HEADER.text_height();
|
||||
let title_baseline = area.top_left() + Offset::y(text_height - 1);
|
||||
shape::Text::new(title_baseline, title.as_ref())
|
||||
@ -95,7 +95,7 @@ where
|
||||
}
|
||||
|
||||
/// Display title/header centered at the top of the given area.
|
||||
pub fn render_header_centered(target: &mut impl Renderer, title: &T, area: Rect) {
|
||||
pub fn render_header_centered<'s>(target: &mut impl Renderer<'s>, title: &T, area: Rect) {
|
||||
let text_height = theme::FONT_HEADER.text_height();
|
||||
let title_baseline = area.top_center() + Offset::y(text_height - 1);
|
||||
shape::Text::new(title_baseline, title.as_ref())
|
||||
@ -140,7 +140,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
fn render(&mut self, target: &mut impl Renderer) {
|
||||
fn render<'s>(&'s self, target: &mut impl Renderer<'s>) {
|
||||
if self.needs_marquee {
|
||||
self.marquee.render(target);
|
||||
} else if self.centered {
|
||||
|
@ -55,7 +55,7 @@ impl Component for WelcomeScreen {
|
||||
);
|
||||
}
|
||||
|
||||
fn render(&mut self, target: &mut impl Renderer) {
|
||||
fn render<'s>(&'s self, target: &mut impl Renderer<'s>) {
|
||||
shape::ToifImage::new(
|
||||
self.area.bottom_center() - Offset::y(5),
|
||||
theme::ICON_DEVICE_NAME.toif,
|
||||
|
@ -44,13 +44,13 @@ impl HorizontalLine {
|
||||
Self { step, ..self }
|
||||
}
|
||||
|
||||
pub fn render(self, renderer: &mut impl Renderer) {
|
||||
pub fn render<'s>(self, renderer: &mut impl Renderer<'s>) {
|
||||
renderer.render_shape(self);
|
||||
}
|
||||
}
|
||||
|
||||
impl Shape for HorizontalLine {
|
||||
fn bounds(&self, _cache: &DrawingCache) -> Rect {
|
||||
impl<'s> Shape<'s> for HorizontalLine {
|
||||
fn bounds(&self, _cache: &DrawingCache<'s>) -> Rect {
|
||||
let size = Offset::new(self.length, self.thickness as i16);
|
||||
Rect::from_top_left_and_size(self.pos, size)
|
||||
}
|
||||
@ -77,8 +77,8 @@ impl Shape for HorizontalLine {
|
||||
}
|
||||
}
|
||||
|
||||
impl ShapeClone for HorizontalLine {
|
||||
fn clone_at_bump<'alloc, T>(self, bump: &'alloc T) -> Option<&'alloc mut dyn Shape>
|
||||
impl<'s> ShapeClone<'s> for HorizontalLine {
|
||||
fn clone_at_bump<'alloc, T>(self, bump: &'alloc T) -> Option<&'alloc mut dyn Shape<'s>>
|
||||
where
|
||||
T: LocalAllocLeakExt<'alloc>,
|
||||
{
|
||||
|
@ -77,13 +77,13 @@ impl LoaderCircular {
|
||||
Rect::from_top_left_and_size(pt, Offset::uniform(self.scale))
|
||||
}
|
||||
|
||||
pub fn render(self, renderer: &mut impl Renderer) {
|
||||
pub fn render<'s>(self, renderer: &mut impl Renderer<'s>) {
|
||||
renderer.render_shape(self);
|
||||
}
|
||||
}
|
||||
|
||||
impl Shape for LoaderCircular {
|
||||
fn bounds(&self, _cache: &DrawingCache) -> Rect {
|
||||
impl<'s> Shape<'s> for LoaderCircular {
|
||||
fn bounds(&self, _cache: &DrawingCache<'s>) -> Rect {
|
||||
let cells = self.cells();
|
||||
|
||||
if cells.is_empty() {
|
||||
@ -106,7 +106,7 @@ impl Shape for LoaderCircular {
|
||||
}
|
||||
}
|
||||
|
||||
impl ShapeClone for LoaderCircular {
|
||||
impl ShapeClone<'_> for LoaderCircular {
|
||||
fn clone_at_bump<'alloc, T>(self, bump: &'alloc T) -> Option<&'alloc mut dyn Shape>
|
||||
where
|
||||
T: LocalAllocLeakExt<'alloc>,
|
||||
|
@ -48,12 +48,12 @@ impl LoaderSmall {
|
||||
Self { color, ..self }
|
||||
}
|
||||
|
||||
pub fn render(self, renderer: &mut impl Renderer) {
|
||||
pub fn render<'s>(self, renderer: &mut impl Renderer<'s>) {
|
||||
renderer.render_shape(self);
|
||||
}
|
||||
}
|
||||
|
||||
impl Shape for LoaderSmall {
|
||||
impl Shape<'_> for LoaderSmall {
|
||||
fn bounds(&self, _cache: &DrawingCache) -> Rect {
|
||||
Rect::from_top_left_and_size(self.pos, Offset::uniform(1)).expand(RADIUS + 1)
|
||||
}
|
||||
@ -78,7 +78,7 @@ impl Shape for LoaderSmall {
|
||||
}
|
||||
}
|
||||
|
||||
impl ShapeClone for LoaderSmall {
|
||||
impl ShapeClone<'_> for LoaderSmall {
|
||||
fn clone_at_bump<'alloc, T>(self, bump: &'alloc T) -> Option<&'alloc mut dyn Shape>
|
||||
where
|
||||
T: LocalAllocLeakExt<'alloc>,
|
||||
|
@ -52,7 +52,7 @@ impl LoaderStarry {
|
||||
Self { color, ..self }
|
||||
}
|
||||
|
||||
pub fn render(self, renderer: &mut impl Renderer) {
|
||||
pub fn render<'s>(self, renderer: &mut impl Renderer<'s>) {
|
||||
renderer.render_shape(self);
|
||||
}
|
||||
|
||||
@ -72,7 +72,7 @@ impl LoaderStarry {
|
||||
}
|
||||
}
|
||||
|
||||
impl Shape for LoaderStarry {
|
||||
impl Shape<'_> for LoaderStarry {
|
||||
fn bounds(&self, _cache: &DrawingCache) -> Rect {
|
||||
Rect::from_top_left_and_size(self.pos, Offset::uniform(1)).expand(RADIUS + STAR_LARGE)
|
||||
}
|
||||
@ -95,7 +95,7 @@ impl Shape for LoaderStarry {
|
||||
}
|
||||
}
|
||||
|
||||
impl ShapeClone for LoaderStarry {
|
||||
impl ShapeClone<'_> for LoaderStarry {
|
||||
fn clone_at_bump<'alloc, T>(self, bump: &'alloc T) -> Option<&'alloc mut dyn Shape>
|
||||
where
|
||||
T: LocalAllocLeakExt<'alloc>,
|
||||
|
@ -234,10 +234,9 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T, F> ComponentMsgObj for ConfirmHomescreen<T, F>
|
||||
impl<'a, T> ComponentMsgObj for ConfirmHomescreen<T>
|
||||
where
|
||||
T: StringType + Clone,
|
||||
F: Fn() -> &'a [u8],
|
||||
{
|
||||
fn msg_try_into_obj(&self, msg: Self::Msg) -> Result<Obj, Error> {
|
||||
match msg {
|
||||
@ -422,15 +421,8 @@ extern "C" fn new_confirm_properties(n_args: usize, args: *const Obj, kwargs: *m
|
||||
extern "C" fn new_confirm_homescreen(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
|
||||
let block = move |_args: &[Obj], kwargs: &Map| {
|
||||
let title: StrBuffer = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?;
|
||||
let data: Obj = kwargs.get(Qstr::MP_QSTR_image)?;
|
||||
|
||||
// Layout needs to hold the Obj to play nice with GC. Obj is resolved to &[u8]
|
||||
// in every paint pass.
|
||||
// SAFETY: We expect no existing mutable reference. Resulting reference is
|
||||
// discarded before returning to micropython.
|
||||
let buffer_func = move || unsafe { unwrap!(get_buffer(data)) };
|
||||
|
||||
let obj = LayoutObj::new(ConfirmHomescreen::new(title, buffer_func))?;
|
||||
let image: Obj = kwargs.get(Qstr::MP_QSTR_image)?;
|
||||
let obj = LayoutObj::new(ConfirmHomescreen::new(title, image))?;
|
||||
Ok(obj.into())
|
||||
};
|
||||
|
||||
|
@ -103,7 +103,7 @@ impl<'a> Component for Intro<'a> {
|
||||
self.menu.paint();
|
||||
}
|
||||
|
||||
fn render(&mut self, target: &mut impl Renderer) {
|
||||
fn render<'s>(&'s self, target: &mut impl Renderer<'s>) {
|
||||
self.bg.render(target);
|
||||
self.title.render(target);
|
||||
self.text.render(target);
|
||||
|
@ -109,7 +109,7 @@ impl Component for Menu {
|
||||
self.reset.paint();
|
||||
}
|
||||
|
||||
fn render(&mut self, target: &mut impl Renderer) {
|
||||
fn render<'s>(&'s self, target: &mut impl Renderer<'s>) {
|
||||
self.bg.render(target);
|
||||
self.title.render(target);
|
||||
self.close.render(target);
|
||||
|
@ -59,8 +59,9 @@ impl Component for Welcome {
|
||||
);
|
||||
}
|
||||
|
||||
fn render(&mut self, target: &mut impl Renderer) {
|
||||
fn render<'s>(&'s self, target: &mut impl Renderer<'s>) {
|
||||
self.bg.render(target);
|
||||
|
||||
shape::Text::new(screen().top_center() + Offset::y(102), "Get started with")
|
||||
.with_align(Alignment::Center)
|
||||
.with_font(Font::NORMAL)
|
||||
|
@ -188,7 +188,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
fn render(&mut self, target: &mut impl Renderer) {
|
||||
fn render<'s>(&'s self, target: &mut impl Renderer<'s>) {
|
||||
match self.current_page {
|
||||
0 => self.qr_code.render(target),
|
||||
1 => self.details.render(target),
|
||||
|
@ -236,11 +236,11 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
fn render(&mut self, target: &mut impl Renderer) {
|
||||
fn render<'s>(&'s self, target: &mut impl Renderer<'s>) {
|
||||
self.bg.render(target);
|
||||
self.content_pad.render(target);
|
||||
|
||||
if let Some(info) = self.info.as_mut() {
|
||||
if let Some(info) = self.info.as_ref() {
|
||||
if self.show_info {
|
||||
info.close_button.render(target);
|
||||
info.title.render(target);
|
||||
@ -259,7 +259,7 @@ where
|
||||
self.alert.render(target);
|
||||
self.left_button.render(target);
|
||||
self.right_button.render(target);
|
||||
match &mut self.title {
|
||||
match &self.title {
|
||||
ConfirmTitle::Text(label) => label.render(target),
|
||||
ConfirmTitle::Icon(icon) => {
|
||||
shape::ToifImage::new(Point::new(screen().center().x, ICON_TOP), icon.toif)
|
||||
|
@ -191,7 +191,7 @@ impl<T> Button<T> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn render_background(&self, target: &mut impl Renderer, style: &ButtonStyle) {
|
||||
pub fn render_background<'s>(&self, target: &mut impl Renderer<'s>, style: &ButtonStyle) {
|
||||
match &self.content {
|
||||
ButtonContent::IconBlend(_, _, _) => {}
|
||||
_ => shape::Bar::new(self.area)
|
||||
@ -244,7 +244,7 @@ impl<T> Button<T> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn render_content(&self, target: &mut impl Renderer, style: &ButtonStyle)
|
||||
pub fn render_content<'s>(&self, target: &mut impl Renderer<'s>, style: &ButtonStyle)
|
||||
where
|
||||
T: AsRef<str>,
|
||||
{
|
||||
@ -375,7 +375,7 @@ where
|
||||
self.paint_content(style);
|
||||
}
|
||||
|
||||
fn render(&mut self, target: &mut impl Renderer) {
|
||||
fn render<'s>(&'s self, target: &mut impl Renderer<'s>) {
|
||||
let style = self.style();
|
||||
self.render_background(target, style);
|
||||
self.render_content(target, style);
|
||||
|
@ -134,7 +134,7 @@ where
|
||||
self.label.paint();
|
||||
}
|
||||
|
||||
fn render(&mut self, target: &mut impl Renderer) {
|
||||
fn render<'s>(&'s self, target: &mut impl Renderer<'s>) {
|
||||
self.content.render(target);
|
||||
|
||||
let center = constant::screen().center() + Offset::y(LOADER_OFFSET);
|
||||
|
@ -72,7 +72,7 @@ where
|
||||
self.controls.paint();
|
||||
}
|
||||
|
||||
fn render(&mut self, target: &mut impl Renderer) {
|
||||
fn render<'s>(&'s self, target: &mut impl Renderer<'s>) {
|
||||
self.content.render(target);
|
||||
self.controls.render(target);
|
||||
}
|
||||
@ -204,7 +204,7 @@ where
|
||||
self.controls.paint();
|
||||
}
|
||||
|
||||
fn render(&mut self, target: &mut impl Renderer) {
|
||||
fn render<'s>(&'s self, target: &mut impl Renderer<'s>) {
|
||||
self.image.render(target);
|
||||
self.paragraphs.render(target);
|
||||
self.controls.render(target);
|
||||
|
@ -89,7 +89,7 @@ impl<T: AsRef<str>> Component for ErrorScreen<'_, T> {
|
||||
self.footer.paint();
|
||||
}
|
||||
|
||||
fn render(&mut self, target: &mut impl Renderer) {
|
||||
fn render<'s>(&'s self, target: &mut impl Renderer<'s>) {
|
||||
self.bg.render(target);
|
||||
|
||||
let icon = ICON_WARNING40;
|
||||
|
@ -195,7 +195,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
fn render(&mut self, target: &mut impl Renderer) {
|
||||
fn render<'s>(&'s self, target: &mut impl Renderer<'s>) {
|
||||
self.icon.render(target);
|
||||
self.controls.render(target);
|
||||
self.app_name.render(target);
|
||||
@ -204,8 +204,6 @@ where
|
||||
self.scrollbar.render(target);
|
||||
}
|
||||
|
||||
let current_account = (self.get_account)(self.active_page());
|
||||
|
||||
// Erasing the old text content before writing the new one.
|
||||
let account_name_area = self.account_name.area();
|
||||
let real_area = account_name_area
|
||||
@ -215,15 +213,13 @@ where
|
||||
// Account name is optional.
|
||||
// Showing it only if it differs from app name.
|
||||
// (Dummy requests usually have some text as both app_name and account_name.)
|
||||
if !current_account.as_ref().is_empty()
|
||||
&& current_account.as_ref() != self.app_name.text().as_ref()
|
||||
{
|
||||
self.account_name.set_text(current_account);
|
||||
let account_name = self.account_name.text().as_ref();
|
||||
let app_name = self.app_name.text().as_ref();
|
||||
if !account_name.is_empty() && account_name != app_name {
|
||||
self.account_name.render(target);
|
||||
}
|
||||
|
||||
if self.fade {
|
||||
self.fade = false;
|
||||
if self.fade.take() {
|
||||
// Note that this is blocking and takes some time.
|
||||
display::fade_backlight(theme::BACKLIGHT_NORMAL);
|
||||
}
|
||||
|
@ -170,7 +170,7 @@ where
|
||||
self.content.paint();
|
||||
}
|
||||
|
||||
fn render(&mut self, target: &mut impl Renderer) {
|
||||
fn render<'s>(&'s self, target: &mut impl Renderer<'s>) {
|
||||
self.title.render(target);
|
||||
self.subtitle.render(target);
|
||||
self.button.render(target);
|
||||
|
@ -123,7 +123,7 @@ impl Homescreen {
|
||||
self.loader.paint()
|
||||
}
|
||||
|
||||
fn render_loader(&mut self, target: &mut impl Renderer) {
|
||||
fn render_loader<'s>(&'s self, target: &mut impl Renderer<'s>) {
|
||||
TR::progress__locking_device.map_translated(|t| {
|
||||
shape::Text::new(TOP_CENTER + Offset::y(HOLD_Y), t)
|
||||
.with_align(Alignment::Center)
|
||||
@ -267,13 +267,13 @@ impl Component for Homescreen {
|
||||
}
|
||||
}
|
||||
|
||||
fn render(&mut self, target: &mut impl Renderer) {
|
||||
fn render<'s>(&'s self, target: &mut impl Renderer<'s>) {
|
||||
self.pad.render(target);
|
||||
if self.loader.is_animating() || self.loader.is_completely_grown(Instant::now()) {
|
||||
self.render_loader(target);
|
||||
} else {
|
||||
let img_data = match self.custom_image {
|
||||
Some(ref img) => IMAGE_HOMESCREEN, //img.as_ref(), !@# solve lifetime problem
|
||||
Some(ref img) => img.as_ref(),
|
||||
None => IMAGE_HOMESCREEN,
|
||||
};
|
||||
|
||||
@ -458,9 +458,9 @@ impl Component for Lockscreen {
|
||||
}
|
||||
}
|
||||
|
||||
fn render(&mut self, target: &mut impl Renderer) {
|
||||
fn render<'s>(&'s self, target: &mut impl Renderer<'s>) {
|
||||
let img_data = match self.custom_image {
|
||||
Some(ref img) => IMAGE_HOMESCREEN, //img.as_ref(), !@# solve lifetime problem
|
||||
Some(ref img) => img.as_ref(),
|
||||
None => IMAGE_HOMESCREEN,
|
||||
};
|
||||
|
||||
|
@ -156,7 +156,7 @@ impl Component for Bip39Input {
|
||||
}
|
||||
}
|
||||
|
||||
fn render(&mut self, target: &mut impl Renderer) {
|
||||
fn render<'s>(&'s self, target: &mut impl Renderer<'s>) {
|
||||
let area = self.button.area();
|
||||
let style = self.button.style();
|
||||
|
||||
|
@ -131,8 +131,8 @@ pub fn paint_pending_marker(text_baseline: Point, text: &str, font: Font, color:
|
||||
}
|
||||
|
||||
/// Create a visible "underscoring" of the last letter of a text.
|
||||
pub fn render_pending_marker(
|
||||
target: &mut impl Renderer,
|
||||
pub fn render_pending_marker<'s>(
|
||||
target: &mut impl Renderer<'s>,
|
||||
text_baseline: Point,
|
||||
text: &str,
|
||||
font: Font,
|
||||
|
@ -183,12 +183,12 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
fn render(&mut self, target: &mut impl Renderer) {
|
||||
fn render<'s>(&'s self, target: &mut impl Renderer<'s>) {
|
||||
self.prompt.render(target);
|
||||
self.input.render(target);
|
||||
self.back.render(target);
|
||||
|
||||
for btn in &mut self.keys {
|
||||
for btn in &self.keys {
|
||||
btn.render(target);
|
||||
}
|
||||
}
|
||||
|
@ -298,16 +298,15 @@ impl Component for PassphraseKeyboard {
|
||||
}
|
||||
}
|
||||
|
||||
fn render(&mut self, target: &mut impl Renderer) {
|
||||
fn render<'s>(&'s self, target: &mut impl Renderer<'s>) {
|
||||
self.input.render(target);
|
||||
self.scrollbar.render(target);
|
||||
self.confirm.render(target);
|
||||
self.back.render(target);
|
||||
for btn in &mut self.keys {
|
||||
for btn in &self.keys {
|
||||
btn.render(target);
|
||||
}
|
||||
if self.fade {
|
||||
self.fade = false;
|
||||
if self.fade.take() {
|
||||
// Note that this is blocking and takes some time.
|
||||
display::fade_backlight(theme::BACKLIGHT_NORMAL);
|
||||
}
|
||||
@ -393,7 +392,7 @@ impl Component for Input {
|
||||
}
|
||||
}
|
||||
|
||||
fn render(&mut self, target: &mut impl Renderer) {
|
||||
fn render<'s>(&'s self, target: &mut impl Renderer<'s>) {
|
||||
let style = theme::label_keyboard();
|
||||
|
||||
let text_baseline = self.area.top_left() + Offset::y(style.text_font.text_height())
|
||||
|
@ -269,11 +269,11 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
fn render(&mut self, target: &mut impl Renderer) {
|
||||
fn render<'s>(&'s self, target: &mut impl Renderer<'s>) {
|
||||
self.erase_btn.render(target);
|
||||
self.textbox_pad.render(target);
|
||||
if self.textbox.inner().is_empty() {
|
||||
if let Some(ref mut w) = self.major_warning {
|
||||
if let Some(ref w) = self.major_warning {
|
||||
w.render(target);
|
||||
} else {
|
||||
self.major_prompt.render(target);
|
||||
@ -284,7 +284,7 @@ where
|
||||
self.textbox.render(target);
|
||||
}
|
||||
self.confirm_btn.render(target);
|
||||
for btn in &mut self.digit_btns {
|
||||
for btn in &self.digit_btns {
|
||||
btn.render(target);
|
||||
}
|
||||
}
|
||||
@ -389,7 +389,7 @@ impl PinDots {
|
||||
}
|
||||
}
|
||||
|
||||
fn render_digits(&self, area: Rect, target: &mut impl Renderer) {
|
||||
fn render_digits<'s>(&self, area: Rect, target: &mut impl Renderer<'s>) {
|
||||
let center = area.center() + Offset::y(Font::MONO.text_height() / 2);
|
||||
let right = center + Offset::x(Font::MONO.text_width("0") * (MAX_VISIBLE_DOTS as i16) / 2);
|
||||
let digits = self.digits.len();
|
||||
@ -454,7 +454,7 @@ impl PinDots {
|
||||
}
|
||||
}
|
||||
|
||||
fn render_dots(&self, area: Rect, target: &mut impl Renderer) {
|
||||
fn render_dots<'s>(&self, area: Rect, target: &mut impl Renderer<'s>) {
|
||||
let mut cursor = self.size().snap(area.center(), Alignment2D::CENTER);
|
||||
|
||||
let digits = self.digits.len();
|
||||
@ -533,7 +533,7 @@ impl Component for PinDots {
|
||||
}
|
||||
}
|
||||
|
||||
fn render(&mut self, target: &mut impl Renderer) {
|
||||
fn render<'s>(&'s self, target: &mut impl Renderer<'s>) {
|
||||
let dot_area = self.area.inset(HEADER_PADDING);
|
||||
self.pad.render(target);
|
||||
if self.display_digits {
|
||||
|
@ -187,7 +187,7 @@ impl Component for Slip39Input {
|
||||
}
|
||||
}
|
||||
|
||||
fn render(&mut self, target: &mut impl Renderer) {
|
||||
fn render<'s>(&'s self, target: &mut impl Renderer<'s>) {
|
||||
let area = self.button.area();
|
||||
let style = self.button.style();
|
||||
|
||||
|
@ -58,8 +58,8 @@ impl Component for SelectWordCount {
|
||||
}
|
||||
}
|
||||
|
||||
fn render(&mut self, target: &mut impl Renderer) {
|
||||
for btn in self.button.iter_mut() {
|
||||
fn render<'s>(&'s self, target: &mut impl Renderer<'s>) {
|
||||
for btn in self.button.iter() {
|
||||
btn.render(target)
|
||||
}
|
||||
}
|
||||
|
@ -209,7 +209,7 @@ impl Component for Loader {
|
||||
}
|
||||
}
|
||||
|
||||
fn render(&mut self, target: &mut impl Renderer) {
|
||||
fn render<'s>(&'s self, target: &mut impl Renderer<'s>) {
|
||||
// TODO: Consider passing the current instant along with the event -- that way,
|
||||
// we could synchronize painting across the component tree. Also could be useful
|
||||
// in automated tests.
|
||||
@ -250,7 +250,7 @@ impl Component for Loader {
|
||||
if let Some((icon, color)) = style.icon {
|
||||
shape::ToifImage::new(center, icon.toif)
|
||||
.with_align(Alignment2D::CENTER)
|
||||
.with_bg(color)
|
||||
.with_fg(color)
|
||||
.render(target);
|
||||
}
|
||||
}
|
||||
|
@ -124,7 +124,7 @@ where
|
||||
self.confirm_button.paint();
|
||||
}
|
||||
|
||||
fn render(&mut self, target: &mut impl Renderer) {
|
||||
fn render<'s>(&'s self, target: &mut impl Renderer<'s>) {
|
||||
self.input.render(target);
|
||||
self.paragraphs_pad.render(target);
|
||||
self.paragraphs.render(target);
|
||||
@ -240,7 +240,7 @@ impl Component for NumberInput {
|
||||
self.inc.paint();
|
||||
}
|
||||
|
||||
fn render(&mut self, target: &mut impl Renderer) {
|
||||
fn render<'s>(&'s self, target: &mut impl Renderer<'s>) {
|
||||
let mut buf = [0u8; 10];
|
||||
|
||||
if let Some(text) = strutil::format_i64(self.value as i64, &mut buf) {
|
||||
|
@ -18,6 +18,8 @@ use super::{
|
||||
SwipeDirection,
|
||||
};
|
||||
|
||||
use core::cell::Cell;
|
||||
|
||||
/// Allows pagination of inner component. Shows scroll bar, confirm & cancel
|
||||
/// buttons. Optionally handles hold-to-confirm with loader.
|
||||
pub struct ButtonPage<T, U> {
|
||||
@ -41,7 +43,7 @@ pub struct ButtonPage<T, U> {
|
||||
/// Whether to pass-through right swipe to parent component.
|
||||
swipe_right: bool,
|
||||
/// Fade to given backlight level on next paint().
|
||||
fade: Option<u16>,
|
||||
fade: Cell<Option<u16>>,
|
||||
}
|
||||
|
||||
impl<T> ButtonPage<T, StrBuffer>
|
||||
@ -77,7 +79,7 @@ where
|
||||
cancel_from_any_page: false,
|
||||
swipe_left: false,
|
||||
swipe_right: false,
|
||||
fade: None,
|
||||
fade: Cell::new(None),
|
||||
}
|
||||
}
|
||||
|
||||
@ -157,7 +159,7 @@ where
|
||||
|
||||
// Swipe has dimmed the screen, so fade back to normal backlight after the next
|
||||
// paint.
|
||||
self.fade = Some(theme::BACKLIGHT_NORMAL);
|
||||
self.fade.set(Some(theme::BACKLIGHT_NORMAL));
|
||||
}
|
||||
|
||||
fn is_cancel_visible(&self) -> bool {
|
||||
@ -413,7 +415,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
fn render(&mut self, target: &mut impl Renderer) {
|
||||
fn render<'s>(&'s self, target: &mut impl Renderer<'s>) {
|
||||
self.pad.render(target);
|
||||
match &self.loader {
|
||||
Some(l) if l.is_animating() => self.loader.render(target),
|
||||
|
@ -123,7 +123,7 @@ where
|
||||
self.description.paint();
|
||||
}
|
||||
|
||||
fn render(&mut self, target: &mut impl Renderer) {
|
||||
fn render<'s>(&'s self, target: &mut impl Renderer<'s>) {
|
||||
self.title.render(target);
|
||||
|
||||
let center = constant::screen().center() + Offset::y(self.loader_y_offset);
|
||||
|
@ -92,7 +92,7 @@ impl<T: AsRef<str>> Component for ResultFooter<'_, T> {
|
||||
self.text.paint();
|
||||
}
|
||||
|
||||
fn render(&mut self, target: &mut impl Renderer) {
|
||||
fn render<'s>(&'s self, target: &mut impl Renderer<'s>) {
|
||||
// divider line
|
||||
let bar = Rect::from_center_and_size(
|
||||
Point::new(self.area.center().x, self.area.y0),
|
||||
@ -181,7 +181,7 @@ impl<'a, T: StringType> Component for ResultScreen<'a, T> {
|
||||
self.footer.paint();
|
||||
}
|
||||
|
||||
fn render(&mut self, target: &mut impl Renderer) {
|
||||
fn render<'s>(&'s self, target: &mut impl Renderer<'s>) {
|
||||
self.bg.render(target);
|
||||
self.footer_pad.render(target);
|
||||
|
||||
|
@ -124,7 +124,7 @@ impl Component for ScrollBar {
|
||||
}
|
||||
}
|
||||
|
||||
fn render(&mut self, target: &mut impl Renderer) {
|
||||
fn render<'s>(&'s self, target: &mut impl Renderer<'s>) {
|
||||
fn dotsize(distance: usize, nhidden: usize) -> Icon {
|
||||
match (nhidden.saturating_sub(distance)).min(2 - distance) {
|
||||
0 => theme::DOT_INACTIVE,
|
||||
|
@ -166,7 +166,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
fn render(&mut self, target: &mut impl Renderer) {
|
||||
fn render<'s>(&'s self, target: &mut impl Renderer<'s>) {
|
||||
self.pad.render(target);
|
||||
self.content.render(target);
|
||||
if self.scrollbar.has_pages() {
|
||||
|
@ -161,5 +161,5 @@ impl Component for Swipe {
|
||||
|
||||
fn paint(&mut self) {}
|
||||
|
||||
fn render(&mut self, _target: &mut impl Renderer) {}
|
||||
fn render<'s>(&'s self, _target: &mut impl Renderer<'s>) {}
|
||||
}
|
||||
|
@ -71,7 +71,7 @@ impl Component for WelcomeScreen {
|
||||
);
|
||||
}
|
||||
|
||||
fn render(&mut self, target: &mut impl Renderer) {
|
||||
fn render<'s>(&'s self, target: &mut impl Renderer<'s>) {
|
||||
let logo = if self.empty_lock {
|
||||
theme::ICON_LOGO_EMPTY
|
||||
} else {
|
||||
|
Loading…
Reference in New Issue
Block a user