diff --git a/core/embed/rust/src/ui/model_t1/component/title.rs b/core/embed/rust/src/ui/model_t1/component/frame.rs similarity index 88% rename from core/embed/rust/src/ui/model_t1/component/title.rs rename to core/embed/rust/src/ui/model_t1/component/frame.rs index 83fe0cbbab..0635af4349 100644 --- a/core/embed/rust/src/ui/model_t1/component/title.rs +++ b/core/embed/rust/src/ui/model_t1/component/frame.rs @@ -5,13 +5,13 @@ use crate::ui::{ geometry::{Offset, Rect}, }; -pub struct Title<T, U> { +pub struct Frame<T, U> { area: Rect, title: U, content: Child<T>, } -impl<T: Component, U: AsRef<[u8]>> Title<T, U> { +impl<T: Component, U: AsRef<[u8]>> Frame<T, U> { pub fn new(area: Rect, title: U, content: impl FnOnce(Rect) -> T) -> Self { let (title_area, content_area) = Self::areas(area); Self { @@ -32,7 +32,7 @@ impl<T: Component, U: AsRef<[u8]>> Title<T, U> { } } -impl<T: Component, U: AsRef<[u8]>> Component for Title<T, U> { +impl<T: Component, U: AsRef<[u8]>> Component for Frame<T, U> { type Msg = T::Msg; fn event(&mut self, ctx: &mut EventCtx, event: Event) -> Option<Self::Msg> { @@ -53,13 +53,13 @@ impl<T: Component, U: AsRef<[u8]>> Component for Title<T, U> { } #[cfg(feature = "ui_debug")] -impl<T, U> crate::trace::Trace for Title<T, U> +impl<T, U> crate::trace::Trace for Frame<T, U> where T: crate::trace::Trace, U: crate::trace::Trace + AsRef<[u8]>, { fn trace(&self, t: &mut dyn crate::trace::Tracer) { - t.open("Title"); + t.open("Frame"); t.field("title", &self.title); t.field("content", &self.content); t.close(); diff --git a/core/embed/rust/src/ui/model_t1/component/mod.rs b/core/embed/rust/src/ui/model_t1/component/mod.rs index 9e614d6794..ec817cc8ed 100644 --- a/core/embed/rust/src/ui/model_t1/component/mod.rs +++ b/core/embed/rust/src/ui/model_t1/component/mod.rs @@ -1,11 +1,11 @@ mod button; mod dialog; +mod frame; mod page; -mod title; use super::{event, theme}; pub use button::{Button, ButtonContent, ButtonMsg, ButtonPos, ButtonStyle, ButtonStyleSheet}; pub use dialog::{Dialog, DialogMsg}; +pub use frame::Frame; pub use page::ButtonPage; -pub use title::Title; diff --git a/core/embed/rust/src/ui/model_t1/layout.rs b/core/embed/rust/src/ui/model_t1/layout.rs index 535ca19134..9133c54237 100644 --- a/core/embed/rust/src/ui/model_t1/layout.rs +++ b/core/embed/rust/src/ui/model_t1/layout.rs @@ -12,7 +12,7 @@ use crate::{ }; use super::{ - component::{Button, ButtonPage, Title}, + component::{Button, ButtonPage, Frame}, theme, }; @@ -56,7 +56,7 @@ extern "C" fn ui_layout_new_confirm_action( let right = verb .map(|label| |area, pos| Button::with_text(area, pos, label, theme::button_default())); - let obj = LayoutObj::new(Child::new(Title::new(display::screen(), title, |area| { + let obj = LayoutObj::new(Child::new(Frame::new(display::screen(), title, |area| { ButtonPage::new( area, |area| { @@ -84,7 +84,7 @@ extern "C" fn ui_layout_new_confirm_text( let description: Option<Buffer> = kwargs.get(Qstr::MP_QSTR_description)?.try_into_option()?; - let obj = LayoutObj::new(Child::new(Title::new(display::screen(), title, |area| { + let obj = LayoutObj::new(Child::new(Frame::new(display::screen(), title, |area| { ButtonPage::new( area, |area| { @@ -194,7 +194,7 @@ arameters! > left:<Button text:Left > right:<Button text:Right > >"# #[test] fn trace_layout_title() { - let layout = Child::new(Title::new(display::screen(), "Please confirm", |area| { + let layout = Child::new(Frame::new(display::screen(), "Please confirm", |area| { Dialog::new( area, |area| { @@ -210,7 +210,7 @@ arameters! > left:<Button text:Left > right:<Button text:Right > >"# })); assert_eq!( trace(&layout), - r#"<Title title:Please confirm content:<Dialog content:<Text content:Testing text layout, + r#"<Frame title:Please confirm content:<Dialog content:<Text content:Testing text layout, with some text, and some more text. And p- arameters! > left:<Button text:Left > right:<Button text:Right > > >"# diff --git a/core/embed/rust/src/ui/model_tt/component/frame.rs b/core/embed/rust/src/ui/model_tt/component/frame.rs new file mode 100644 index 0000000000..98b1134990 --- /dev/null +++ b/core/embed/rust/src/ui/model_tt/component/frame.rs @@ -0,0 +1,80 @@ +use super::theme; +use crate::ui::{ + component::{Child, Component, ComponentExt, Event, EventCtx}, + display, + geometry::Rect, +}; + +pub struct Frame<T, U> { + area: Rect, + title: U, + content: Child<T>, +} + +impl<T, U> Frame<T, U> +where + T: Component, + U: AsRef<[u8]>, +{ + pub fn new(area: Rect, title: U, content: impl FnOnce(Rect) -> T) -> Self { + let (title_area, content_area) = Self::areas(area); + Self { + area: title_area, + title, + content: content(content_area).into_child(), + } + } + + fn areas(area: Rect) -> (Rect, Rect) { + const HEADER_SPACE: i32 = 14; + let header_height = theme::FONT_BOLD.line_height() - theme::CONTENT_BORDER; + + let (header_area, content_area) = area.hsplit(header_height); + let (_space, header_area) = header_area.vsplit(theme::CONTENT_BORDER); + let (_space, content_area) = content_area.hsplit(HEADER_SPACE); + + (header_area, content_area) + } +} + +impl<T, U> Component for Frame<T, U> +where + T: Component, + U: AsRef<[u8]>, +{ + type Msg = T::Msg; + + fn event(&mut self, ctx: &mut EventCtx, event: Event) -> Option<Self::Msg> { + self.content.event(ctx, event) + } + + fn paint(&mut self) { + display::text( + self.area.bottom_left(), + self.title.as_ref(), + theme::FONT_BOLD, + theme::GREY_LIGHT, + theme::BG, + ); + self.content.paint(); + } +} + +#[cfg(feature = "ui_debug")] +impl<T, U> crate::trace::Trace for Frame<T, U> +where + T: crate::trace::Trace, + U: crate::trace::Trace + AsRef<[u8]>, +{ + fn trace(&self, t: &mut dyn crate::trace::Tracer) { + t.open("Frame"); + t.field("title", &self.title); + t.field("content", &self.content); + t.close(); + } + + fn bounds(&self, sink: &dyn Fn(Rect)) { + sink(self.area); + self.content.bounds(sink); + } +} diff --git a/core/embed/rust/src/ui/model_tt/component/mod.rs b/core/embed/rust/src/ui/model_tt/component/mod.rs index 47c86bdbb7..a94437b9a9 100644 --- a/core/embed/rust/src/ui/model_tt/component/mod.rs +++ b/core/embed/rust/src/ui/model_tt/component/mod.rs @@ -1,6 +1,7 @@ mod button; mod confirm; mod dialog; +mod frame; mod loader; mod page; mod passphrase; @@ -10,6 +11,7 @@ mod swipe; pub use button::{Button, ButtonContent, ButtonMsg, ButtonStyle, ButtonStyleSheet}; pub use confirm::{HoldToConfirm, HoldToConfirmMsg}; pub use dialog::{Dialog, DialogLayout, DialogMsg}; +pub use frame::Frame; pub use loader::{Loader, LoaderMsg, LoaderStyle, LoaderStyleSheet}; pub use page::SwipePage; pub use swipe::{Swipe, SwipeDirection};