mirror of
https://github.com/trezor/trezor-firmware.git
synced 2025-01-03 03:50:58 +00:00
feat(core/ui): frames with title and subtitle
[no changelog]
This commit is contained in:
parent
331bba9b70
commit
229c81fa7e
@ -57,6 +57,10 @@ where
|
|||||||
self.layout.bounds
|
self.layout.bounds
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn alignment(&self) -> Alignment {
|
||||||
|
self.layout.align
|
||||||
|
}
|
||||||
|
|
||||||
pub fn max_size(&self) -> Offset {
|
pub fn max_size(&self) -> Offset {
|
||||||
let font = self.font();
|
let font = self.font();
|
||||||
Offset::new(font.text_width(self.text.as_ref()), font.text_max_height())
|
Offset::new(font.text_width(self.text.as_ref()), font.text_max_height())
|
||||||
|
@ -11,6 +11,7 @@ use crate::ui::{
|
|||||||
pub struct Frame<T, U> {
|
pub struct Frame<T, U> {
|
||||||
border: Insets,
|
border: Insets,
|
||||||
title: Child<Label<U>>,
|
title: Child<Label<U>>,
|
||||||
|
subtitle: Option<Child<Label<U>>>,
|
||||||
button: Option<Child<Button<&'static str>>>,
|
button: Option<Child<Button<&'static str>>>,
|
||||||
button_msg: CancelInfoConfirmMsg,
|
button_msg: CancelInfoConfirmMsg,
|
||||||
content: Child<T>,
|
content: Child<T>,
|
||||||
@ -29,6 +30,7 @@ where
|
|||||||
pub fn new(style: TextStyle, alignment: Alignment, title: U, content: T) -> Self {
|
pub fn new(style: TextStyle, alignment: Alignment, title: U, content: T) -> Self {
|
||||||
Self {
|
Self {
|
||||||
title: Child::new(Label::new(title, alignment, style)),
|
title: Child::new(Label::new(title, alignment, style)),
|
||||||
|
subtitle: None,
|
||||||
border: theme::borders(),
|
border: theme::borders(),
|
||||||
button: None,
|
button: None,
|
||||||
button_msg: CancelInfoConfirmMsg::Cancelled,
|
button_msg: CancelInfoConfirmMsg::Cancelled,
|
||||||
@ -53,6 +55,15 @@ where
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn with_subtitle(mut self, style: TextStyle, subtitle: U) -> Self {
|
||||||
|
self.subtitle = Some(Child::new(Label::new(
|
||||||
|
subtitle,
|
||||||
|
self.title.inner().alignment(),
|
||||||
|
style,
|
||||||
|
)));
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
fn with_button(mut self, icon: Icon, msg: CancelInfoConfirmMsg) -> Self {
|
fn with_button(mut self, icon: Icon, msg: CancelInfoConfirmMsg) -> Self {
|
||||||
let touch_area = Insets {
|
let touch_area = Insets {
|
||||||
left: self.border.left * 4,
|
left: self.border.left * 4,
|
||||||
@ -118,21 +129,29 @@ where
|
|||||||
let bounds = bounds.inset(self.border);
|
let bounds = bounds.inset(self.border);
|
||||||
if let Some(b) = &mut self.button {
|
if let Some(b) = &mut self.button {
|
||||||
let button_side = theme::CORNER_BUTTON_SIDE;
|
let button_side = theme::CORNER_BUTTON_SIDE;
|
||||||
let (title_area, button_area) = bounds.split_right(button_side);
|
let (header_area, button_area) = bounds.split_right(button_side);
|
||||||
let (button_area, _) = button_area.split_top(button_side);
|
let (button_area, _) = button_area.split_top(button_side);
|
||||||
b.place(button_area);
|
b.place(button_area);
|
||||||
let title_area = self.title.place(title_area);
|
let title_area = self.title.place(header_area);
|
||||||
let title_height = title_area.height();
|
let remaining = header_area.inset(Insets::top(title_area.height()));
|
||||||
let height = title_area.height().max(button_side);
|
let subtitle_area = self.subtitle.place(remaining);
|
||||||
|
|
||||||
|
let title_height = title_area.height() + subtitle_area.height();
|
||||||
|
let header_height = title_height.max(button_side);
|
||||||
if title_height < button_side {
|
if title_height < button_side {
|
||||||
self.title
|
self.title
|
||||||
.place(title_area.translate(Offset::y((button_side - title_height) / 2)));
|
.place(title_area.translate(Offset::y((button_side - title_height) / 2)));
|
||||||
|
self.subtitle
|
||||||
|
.place(subtitle_area.translate(Offset::y((button_side - title_height) / 2)));
|
||||||
}
|
}
|
||||||
let content_area = bounds.inset(Insets::top(height + TITLE_SPACE));
|
let content_area = bounds.inset(Insets::top(header_height + TITLE_SPACE));
|
||||||
self.content.place(content_area);
|
self.content.place(content_area);
|
||||||
} else {
|
} else {
|
||||||
let title_area = self.title.place(bounds);
|
let title_area = self.title.place(bounds);
|
||||||
let content_area = bounds.inset(Insets::top(title_area.height() + TITLE_SPACE));
|
let remaining = bounds.inset(Insets::top(title_area.height()));
|
||||||
|
let subtitle_area = self.subtitle.place(remaining);
|
||||||
|
let remaining = remaining.inset(Insets::top(subtitle_area.height()));
|
||||||
|
let content_area = remaining.inset(Insets::top(TITLE_SPACE));
|
||||||
self.content.place(content_area);
|
self.content.place(content_area);
|
||||||
}
|
}
|
||||||
bounds
|
bounds
|
||||||
@ -140,6 +159,7 @@ where
|
|||||||
|
|
||||||
fn event(&mut self, ctx: &mut EventCtx, event: Event) -> Option<Self::Msg> {
|
fn event(&mut self, ctx: &mut EventCtx, event: Event) -> Option<Self::Msg> {
|
||||||
self.title.event(ctx, event);
|
self.title.event(ctx, event);
|
||||||
|
self.subtitle.event(ctx, event);
|
||||||
if let Some(ButtonMsg::Clicked) = self.button.event(ctx, event) {
|
if let Some(ButtonMsg::Clicked) = self.button.event(ctx, event) {
|
||||||
return Some(FrameMsg::Button(self.button_msg));
|
return Some(FrameMsg::Button(self.button_msg));
|
||||||
}
|
}
|
||||||
@ -148,6 +168,7 @@ where
|
|||||||
|
|
||||||
fn paint(&mut self) {
|
fn paint(&mut self) {
|
||||||
self.title.paint();
|
self.title.paint();
|
||||||
|
self.subtitle.paint();
|
||||||
self.button.paint();
|
self.button.paint();
|
||||||
self.content.paint();
|
self.content.paint();
|
||||||
}
|
}
|
||||||
@ -155,6 +176,7 @@ where
|
|||||||
#[cfg(feature = "ui_bounds")]
|
#[cfg(feature = "ui_bounds")]
|
||||||
fn bounds(&self, sink: &mut dyn FnMut(Rect)) {
|
fn bounds(&self, sink: &mut dyn FnMut(Rect)) {
|
||||||
self.title.bounds(sink);
|
self.title.bounds(sink);
|
||||||
|
self.subtitle.bounds(sink);
|
||||||
self.button.bounds(sink);
|
self.button.bounds(sink);
|
||||||
self.content.bounds(sink);
|
self.content.bounds(sink);
|
||||||
}
|
}
|
||||||
@ -169,6 +191,9 @@ where
|
|||||||
fn trace(&self, t: &mut dyn crate::trace::Tracer) {
|
fn trace(&self, t: &mut dyn crate::trace::Tracer) {
|
||||||
t.open("Frame");
|
t.open("Frame");
|
||||||
t.field("title", &self.title);
|
t.field("title", &self.title);
|
||||||
|
if let Some(s) = &self.subtitle {
|
||||||
|
t.field("subtitle", s);
|
||||||
|
}
|
||||||
if let Some(b) = &self.button {
|
if let Some(b) = &self.button {
|
||||||
t.field("button", b);
|
t.field("button", b);
|
||||||
}
|
}
|
||||||
|
@ -150,6 +150,10 @@ pub const fn label_title() -> TextStyle {
|
|||||||
TextStyle::new(Font::BOLD, GREY_LIGHT, BG, GREY_LIGHT, GREY_LIGHT)
|
TextStyle::new(Font::BOLD, GREY_LIGHT, BG, GREY_LIGHT, GREY_LIGHT)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub const fn label_subtitle() -> TextStyle {
|
||||||
|
TextStyle::new(Font::NORMAL, GREY_LIGHT, BG, GREY_LIGHT, GREY_LIGHT)
|
||||||
|
}
|
||||||
|
|
||||||
pub const fn label_coinjoin_progress() -> TextStyle {
|
pub const fn label_coinjoin_progress() -> TextStyle {
|
||||||
TextStyle::new(Font::BOLD, FG, YELLOW, FG, FG)
|
TextStyle::new(Font::BOLD, FG, YELLOW, FG, FG)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user