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:
parent
10650af1fa
commit
5378492ea9
@ -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;
|
||||
|
@ -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")]
|
||||
|
@ -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")]
|
||||
|
@ -4,7 +4,7 @@ use crate::ui::{
|
||||
};
|
||||
|
||||
pub struct Pad {
|
||||
area: Rect,
|
||||
pub area: Rect,
|
||||
color: Color,
|
||||
clear: bool,
|
||||
}
|
||||
|
@ -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")]
|
||||
|
@ -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> {
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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()
|
||||
}
|
||||
|
@ -209,6 +209,10 @@ where
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn bounds(&self, sink: &mut dyn FnMut(Rect)) {
|
||||
sink(self.area)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "ui_debug")]
|
||||
|
@ -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")]
|
||||
|
@ -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 {
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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 {
|
||||
|
Loading…
Reference in New Issue
Block a user