1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2024-12-23 06:48:16 +00:00

chore(core/rust): wireframe rendering for ui debugging

[no changelog]
This commit is contained in:
Martin Milata 2022-01-14 16:37:16 +01:00
parent 10650af1fa
commit 5378492ea9
13 changed files with 111 additions and 35 deletions

View File

@ -17,6 +17,7 @@ static void _librust_qstrs(void) {
MP_QSTR_timer;
MP_QSTR_paint;
MP_QSTR_trace;
MP_QSTR_bounds;
MP_QSTR_title;
MP_QSTR_action;

View File

@ -2,11 +2,11 @@ use core::mem;
use heapless::Vec;
use crate::time::Duration;
#[cfg(feature = "model_t1")]
use crate::ui::model_t1::event::ButtonEvent;
#[cfg(feature = "model_tt")]
use crate::ui::model_tt::event::TouchEvent;
use crate::{time::Duration, ui::geometry::Rect};
/// Type used by components that do not return any messages.
///
@ -20,6 +20,7 @@ pub trait Component {
type Msg;
fn event(&mut self, ctx: &mut EventCtx, event: Event) -> Option<Self::Msg>;
fn paint(&mut self);
fn bounds(&self, _sink: &mut dyn FnMut(Rect)) {}
}
/// Components should always avoid unnecessary overpaint to prevent obvious
@ -95,6 +96,10 @@ where
self.component.paint();
}
}
fn bounds(&self, sink: &mut dyn FnMut(Rect)) {
self.component.bounds(sink)
}
}
#[cfg(feature = "ui_debug")]

View File

@ -1,4 +1,5 @@
use super::{Component, Event, EventCtx};
use crate::ui::geometry::Rect;
pub struct Map<T, F> {
inner: T,
@ -25,6 +26,10 @@ where
fn paint(&mut self) {
self.inner.paint()
}
fn bounds(&self, sink: &mut dyn FnMut(Rect)) {
self.inner.bounds(sink);
}
}
#[cfg(feature = "ui_debug")]

View File

@ -4,7 +4,7 @@ use crate::ui::{
};
pub struct Pad {
area: Rect,
pub area: Rect,
color: Color,
clear: bool,
}

View File

@ -120,6 +120,10 @@ where
fn paint(&mut self) {
self.layout_content(&mut TextRenderer);
}
fn bounds(&self, sink: &mut dyn FnMut(Rect)) {
sink(self.layout.bounds)
}
}
#[cfg(feature = "ui_debug")]

View File

@ -120,6 +120,13 @@ where
char_offset = 0;
}
}
fn bounds(&self, sink: &mut dyn FnMut(Rect)) {
sink(self.area);
for paragraph in self.list.iter().skip(self.offset.par).take(self.visible) {
sink(paragraph.layout.bounds)
}
}
}
impl<T> Dimensions for Paragraphs<T> {
@ -144,13 +151,6 @@ where
}
t.close();
}
fn bounds(&self, sink: &dyn Fn(Rect)) {
sink(self.area);
for paragraph in self.list.iter().skip(self.offset.par).take(self.visible) {
paragraph.bounds(sink);
}
}
}
pub struct Paragraph<T> {

View File

@ -18,6 +18,11 @@ where
self.0.paint();
self.1.paint();
}
fn bounds(&self, sink: &mut dyn FnMut(Rect)) {
self.0.bounds(sink);
self.1.bounds(sink);
}
}
impl<T, A, B, C> Component for (A, B, C)
@ -40,6 +45,12 @@ where
self.1.paint();
self.2.paint();
}
fn bounds(&self, sink: &mut dyn FnMut(Rect)) {
self.0.bounds(sink);
self.1.bounds(sink);
self.2.bounds(sink);
}
}
#[cfg(feature = "ui_debug")]
@ -54,11 +65,6 @@ where
t.field("1", &self.1);
t.close();
}
fn bounds(&self, sink: &dyn Fn(Rect)) {
self.0.bounds(sink);
self.1.bounds(sink);
}
}
#[cfg(feature = "ui_debug")]
@ -75,10 +81,4 @@ where
t.field("2", &self.2);
t.close();
}
fn bounds(&self, sink: &dyn Fn(Rect)) {
self.0.bounds(sink);
self.1.bounds(sink);
self.2.bounds(sink);
}
}

View File

@ -13,7 +13,10 @@ use crate::{
typ::Type,
},
time::Duration,
ui::component::{Child, Component, Event, EventCtx, Never, PageMsg, TimerToken},
ui::{
component::{Child, Component, Event, EventCtx, Never, PageMsg, TimerToken},
geometry::Rect,
},
util,
};
@ -48,6 +51,7 @@ where
pub trait ObjComponent {
fn obj_event(&mut self, ctx: &mut EventCtx, event: Event) -> Result<Obj, Error>;
fn obj_paint(&mut self);
fn obj_bounds(&self, sink: &mut dyn FnMut(Rect));
}
impl<T> ObjComponent for Child<T>
@ -65,6 +69,10 @@ where
fn obj_paint(&mut self) {
self.paint();
}
fn obj_bounds(&self, sink: &mut dyn FnMut(Rect)) {
self.bounds(sink)
}
}
#[cfg(feature = "ui_debug")]
@ -209,6 +217,22 @@ impl LayoutObj {
.trace(&mut CallbackTracer(callback));
}
#[cfg(feature = "ui_debug")]
fn obj_bounds(&self) {
use crate::ui::display;
// Sink for `Trace::bounds` that draws the boundaries using pseudorandom color.
fn wireframe(r: Rect) {
let w = r.width() as u16;
let h = r.height() as u16;
let color = display::Color::from_u16(w.rotate_right(w.into()).wrapping_add(h * 8));
display::rect_stroke(r, color)
}
wireframe(display::screen());
self.inner.borrow().root.obj_bounds(&mut wireframe);
}
fn obj_type() -> &'static Type {
static TYPE: Type = obj_type! {
name: Qstr::MP_QSTR_Layout,
@ -219,6 +243,7 @@ impl LayoutObj {
Qstr::MP_QSTR_timer => obj_fn_2!(ui_layout_timer).as_obj(),
Qstr::MP_QSTR_paint => obj_fn_1!(ui_layout_paint).as_obj(),
Qstr::MP_QSTR_trace => obj_fn_2!(ui_layout_trace).as_obj(),
Qstr::MP_QSTR_bounds => obj_fn_1!(ui_layout_bounds).as_obj(),
}),
};
&TYPE
@ -384,3 +409,18 @@ extern "C" fn ui_layout_trace(this: Obj, callback: Obj) -> Obj {
extern "C" fn ui_layout_trace(_this: Obj, _callback: Obj) -> Obj {
Obj::const_none()
}
#[cfg(feature = "ui_debug")]
extern "C" fn ui_layout_bounds(this: Obj) -> Obj {
let block = || {
let this: Gc<LayoutObj> = this.try_into()?;
this.obj_bounds();
Ok(Obj::const_none())
};
unsafe { util::try_or_raise(block) }
}
#[cfg(not(feature = "ui_debug"))]
extern "C" fn ui_layout_bounds(_this: Obj) -> Obj {
Obj::const_none()
}

View File

@ -209,6 +209,10 @@ where
}
}
}
fn bounds(&self, sink: &mut dyn FnMut(Rect)) {
sink(self.area)
}
}
#[cfg(feature = "ui_debug")]

View File

@ -96,6 +96,17 @@ where
self.cancel.paint();
self.confirm.paint();
}
fn bounds(&self, sink: &mut dyn FnMut(Rect)) {
sink(self.pad.area);
if self.loader.is_animating() {
self.loader.bounds(sink)
} else {
self.content.bounds(sink)
}
self.cancel.bounds(sink);
self.confirm.bounds(sink);
}
}
#[cfg(feature = "ui_debug")]

View File

@ -57,6 +57,12 @@ where
self.left.paint();
self.right.paint();
}
fn bounds(&self, sink: &mut dyn FnMut(Rect)) {
self.content.bounds(sink);
self.left.bounds(sink);
self.right.bounds(sink);
}
}
pub struct DialogLayout {

View File

@ -58,6 +58,11 @@ where
);
self.content.paint();
}
fn bounds(&self, sink: &mut dyn FnMut(Rect)) {
sink(self.area);
self.content.bounds(sink);
}
}
#[cfg(feature = "ui_debug")]
@ -72,9 +77,4 @@ where
t.field("content", &self.content);
t.close();
}
fn bounds(&self, sink: &dyn Fn(Rect)) {
sink(self.area);
self.content.bounds(sink);
}
}

View File

@ -148,6 +148,15 @@ where
display::fade_backlight(val);
}
}
fn bounds(&self, sink: &mut dyn FnMut(Rect)) {
sink(self.scrollbar.area);
sink(self.pad.area);
self.content.bounds(sink);
if !self.scrollbar.has_next_page() {
self.buttons.bounds(sink);
}
}
}
#[cfg(feature = "ui_debug")]
@ -163,15 +172,6 @@ where
t.field("content", &self.content);
t.close();
}
fn bounds(&self, sink: &dyn Fn(Rect)) {
sink(self.scrollbar.area);
sink(self.pad.area);
self.content.bounds(sink);
if !self.scrollbar.has_next_page() {
self.buttons.bounds(sink);
}
}
}
pub struct ScrollBar {