1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2025-07-24 07:28:34 +00:00

perf(core/eckhart): constructing MenuItems

- self-referential builder pattern is easier on the stack memory usage
than consuming builder pattern
- store ButtonStyleSheet as a static ref
This commit is contained in:
obrusvit 2025-05-21 11:48:06 +02:00 committed by Vít Obrusník
parent bd89e13493
commit d73f0dc79d

View File

@ -70,26 +70,30 @@ pub enum DeviceMenuMsg {
struct MenuItem {
text: TString<'static>,
subtext: Option<(TString<'static>, Option<TextStyle>)>,
stylesheet: ButtonStyleSheet,
stylesheet: &'static ButtonStyleSheet,
action: Option<Action>,
}
const MENU_ITEM_TITLE_STYLE_SHEET: &ButtonStyleSheet = &theme::menu_item_title();
impl MenuItem {
pub fn new(text: TString<'static>, action: Option<Action>) -> Self {
Self {
text,
subtext: None,
stylesheet: theme::menu_item_title(),
stylesheet: MENU_ITEM_TITLE_STYLE_SHEET,
action,
}
}
pub fn with_subtext(mut self, subtext: Option<(TString<'static>, Option<TextStyle>)>) -> Self {
pub fn with_subtext(
&mut self,
subtext: Option<(TString<'static>, Option<TextStyle>)>,
) -> &mut Self {
self.subtext = subtext;
self
}
pub fn with_stylesheet(mut self, stylesheet: ButtonStyleSheet) -> Self {
pub fn with_stylesheet(&mut self, stylesheet: &'static ButtonStyleSheet) -> &mut Self {
self.stylesheet = stylesheet;
self
}
@ -221,12 +225,13 @@ impl<'a> DeviceMenuScreen<'a> {
) -> usize {
let mut items: Vec<MenuItem, SHORT_MENU_ITEMS> = Vec::new();
for (device, idx) in paired_devices.iter().zip(paired_device_indices) {
unwrap!(items.push(
MenuItem::new(*device, Some(Action::GoTo(idx))).with_subtext(Some((
"Connected".into(),
Some(Button::SUBTEXT_STYLE_GREEN)
))) // TODO: this should be a boolean feature of the device
));
let mut item_device = MenuItem::new(*device, Some(Action::GoTo(idx)));
// TODO: this should be a boolean feature of the device
item_device.with_subtext(Some((
"Connected".into(),
Some(Button::SUBTEXT_STYLE_GREEN),
)));
unwrap!(items.push(item_device));
}
let submenu_index = self.add_submenu(Submenu::new("Manage paired devices".into(), items));
@ -235,16 +240,15 @@ impl<'a> DeviceMenuScreen<'a> {
fn add_pair_and_connect_menu(&mut self, manage_devices_index: usize) -> usize {
let mut items: Vec<MenuItem, SHORT_MENU_ITEMS> = Vec::new();
unwrap!(items.push(
MenuItem::new(
"Manage paired devices".into(),
Some(Action::GoTo(manage_devices_index)),
)
.with_subtext(Some((
"1 device connected".into(),
Some(Button::SUBTEXT_STYLE_GREEN)
)))
));
let mut manage_paired_item = MenuItem::new(
"Manage paired devices".into(),
Some(Action::GoTo(manage_devices_index)),
);
manage_paired_item.with_subtext(Some((
"1 device connected".into(),
Some(Button::SUBTEXT_STYLE_GREEN),
)));
unwrap!(items.push(manage_paired_item));
unwrap!(items.push(MenuItem::new(
"Pair new device".into(),
Some(Action::Return(DeviceMenuMsg::DevicePair)),
@ -291,22 +295,21 @@ impl<'a> DeviceMenuScreen<'a> {
auto_lock_delay: TString<'static>,
) -> usize {
let mut items: Vec<MenuItem, SHORT_MENU_ITEMS> = Vec::new();
unwrap!(
items.push(MenuItem::new("Name".into(), None).with_subtext(Some((device_name, None))))
);
let mut item_device_name = MenuItem::new("Name".into(), None);
item_device_name.with_subtext(Some((device_name, None)));
unwrap!(items.push(item_device_name));
unwrap!(items.push(MenuItem::new(
"Screen brightness".into(),
Some(Action::Return(DeviceMenuMsg::ScreenBrightness)),
)));
if has_pin() {
unwrap!(items.push(
MenuItem::new(
"Auto-lock delay".into(),
Some(Action::Return(DeviceMenuMsg::AutoLockDelay)),
)
.with_subtext(Some((auto_lock_delay, None)))
));
let mut autolock_delay_item = MenuItem::new(
"Auto-lock delay".into(),
Some(Action::Return(DeviceMenuMsg::AutoLockDelay)),
);
autolock_delay_item.with_subtext(Some((auto_lock_delay, None)));
unwrap!(items.push(autolock_delay_item));
}
unwrap!(items.push(MenuItem::new(
@ -326,25 +329,23 @@ impl<'a> DeviceMenuScreen<'a> {
) -> usize {
let mut items: Vec<MenuItem, SHORT_MENU_ITEMS> = Vec::new();
if failed_backup {
unwrap!(items.push(
MenuItem::new(
"Backup failed".into(),
Some(Action::Return(DeviceMenuMsg::BackupFailed)),
)
.with_subtext(Some(("Review".into(), None)))
.with_stylesheet(theme::menu_item_title_red()),
));
let mut item_backup_failed = MenuItem::new(
"Backup failed".into(),
Some(Action::Return(DeviceMenuMsg::BackupFailed)),
);
item_backup_failed.with_subtext(Some(("Review".into(), None)));
item_backup_failed.with_stylesheet(MENU_ITEM_TITLE_STYLE_SHEET);
unwrap!(items.push(item_backup_failed));
}
unwrap!(items.push(
MenuItem::new(
"Pair & connect".into(),
Some(Action::GoTo(pair_and_connect_index)),
)
.with_subtext(Some((
"1 device connected".into(),
Some(Button::SUBTEXT_STYLE_GREEN)
)))
));
let mut item_pair_and_connect = MenuItem::new(
"Pair & connect".into(),
Some(Action::GoTo(pair_and_connect_index)),
);
item_pair_and_connect.with_subtext(Some((
"1 device connected".into(),
Some(Button::SUBTEXT_STYLE_GREEN),
)));
unwrap!(items.push(item_pair_and_connect));
unwrap!(items.push(MenuItem::new(
"Settings".into(),
Some(Action::GoTo(settings_index)),
@ -379,12 +380,12 @@ impl<'a> DeviceMenuScreen<'a> {
let button = if let Some((subtext, subtext_style)) = item.subtext {
Button::new_menu_item_with_subtext(
item.text,
item.stylesheet,
*item.stylesheet,
subtext,
subtext_style,
)
} else {
Button::new_menu_item(item.text, item.stylesheet)
Button::new_menu_item(item.text, *item.stylesheet)
};
menu.item(button);
}