From 9f0ebf6d1ae52b274568a37760352dbcb9ad8294 Mon Sep 17 00:00:00 2001 From: Martin Milata Date: Fri, 6 May 2022 21:14:00 +0200 Subject: [PATCH] refactor(core/rust/ui): arbitrary controls for Dialog component [no changelog] --- core/embed/rust/src/ui/component/base.rs | 33 +++++++++++ .../rust/src/ui/model_tt/component/confirm.rs | 5 +- .../rust/src/ui/model_tt/component/dialog.rs | 59 ++++++++----------- core/embed/rust/src/ui/model_tt/layout.rs | 20 ++++--- 4 files changed, 72 insertions(+), 45 deletions(-) diff --git a/core/embed/rust/src/ui/component/base.rs b/core/embed/rust/src/ui/component/base.rs index 94224e445..cfbad3404 100644 --- a/core/embed/rust/src/ui/component/base.rs +++ b/core/embed/rust/src/ui/component/base.rs @@ -210,6 +210,39 @@ where } } +impl Component for Option +where + T: Component, +{ + type Msg = T::Msg; + + fn event(&mut self, ctx: &mut EventCtx, event: Event) -> Option { + match self { + Some(ref mut c) => c.event(ctx, event), + _ => None, + } + } + + fn paint(&mut self) { + if let Some(ref mut c) = self { + c.paint() + } + } + + fn place(&mut self, bounds: Rect) -> Rect { + match self { + Some(ref mut c) => c.place(bounds), + _ => bounds.with_size(Offset::zero()), + } + } + + fn bounds(&self, sink: &mut dyn FnMut(Rect)) { + if let Some(ref c) = self { + c.bounds(sink) + } + } +} + pub trait ComponentExt: Sized { fn map(self, func: F) -> Map; fn into_child(self) -> Child; diff --git a/core/embed/rust/src/ui/model_tt/component/confirm.rs b/core/embed/rust/src/ui/model_tt/component/confirm.rs index 6c7224ca5..623e710c9 100644 --- a/core/embed/rust/src/ui/model_tt/component/confirm.rs +++ b/core/embed/rust/src/ui/model_tt/component/confirm.rs @@ -52,8 +52,9 @@ where let layout = DialogLayout::middle(bounds); self.loader.place(layout.content); self.content.place(layout.content); - self.cancel.place(layout.left); - self.confirm.place(layout.right); + let (left, right) = layout.controls.split_left(layout.controls.size().x); + self.cancel.place(left); + self.confirm.place(right); bounds } diff --git a/core/embed/rust/src/ui/model_tt/component/dialog.rs b/core/embed/rust/src/ui/model_tt/component/dialog.rs index 21d000c04..534167a73 100644 --- a/core/embed/rust/src/ui/model_tt/component/dialog.rs +++ b/core/embed/rust/src/ui/model_tt/component/dialog.rs @@ -3,29 +3,27 @@ use crate::ui::{ geometry::{Grid, Rect}, }; -pub enum DialogMsg { +use super::{theme, Button}; + +pub enum DialogMsg { Content(T), - Left(L), - Right(R), + Controls(U), } -pub struct Dialog { +pub struct Dialog { content: Child, - left: Child, - right: Child, + controls: Child, } -impl Dialog +impl Dialog where T: Component, - L: Component, - R: Component, + U: Component, { - pub fn new(content: T, left: L, right: R) -> Self { + pub fn new(content: T, controls: U) -> Self { Self { content: Child::new(content), - left: Child::new(left), - right: Child::new(right), + controls: Child::new(controls), } } @@ -34,19 +32,17 @@ where } } -impl Component for Dialog +impl Component for Dialog where T: Component, - L: Component, - R: Component, + U: Component, { - type Msg = DialogMsg; + type Msg = DialogMsg; fn place(&mut self, bounds: Rect) -> Rect { let layout = DialogLayout::middle(bounds); self.content.place(layout.content); - self.left.place(layout.left); - self.right.place(layout.right); + self.controls.place(layout.controls); bounds } @@ -54,55 +50,48 @@ where self.content .event(ctx, event) .map(Self::Msg::Content) - .or_else(|| self.left.event(ctx, event).map(Self::Msg::Left)) - .or_else(|| self.right.event(ctx, event).map(Self::Msg::Right)) + .or_else(|| self.controls.event(ctx, event).map(Self::Msg::Controls)) } fn paint(&mut self) { self.content.paint(); - self.left.paint(); - self.right.paint(); + self.controls.paint(); } fn bounds(&self, sink: &mut dyn FnMut(Rect)) { self.content.bounds(sink); - self.left.bounds(sink); - self.right.bounds(sink); + self.controls.bounds(sink); } } pub struct DialogLayout { pub content: Rect, - pub left: Rect, - pub right: Rect, + pub controls: Rect, } impl DialogLayout { pub fn middle(area: Rect) -> Self { - let grid = Grid::new(area, 5, 2); + let grid = Grid::new(area, 5, 1); Self { content: Rect::new( grid.row_col(0, 0).top_left(), - grid.row_col(3, 1).bottom_right(), + grid.row_col(3, 0).bottom_right(), ), - left: grid.row_col(4, 0), - right: grid.row_col(4, 1), + controls: grid.row_col(4, 0), } } } #[cfg(feature = "ui_debug")] -impl crate::trace::Trace for Dialog +impl crate::trace::Trace for Dialog where T: crate::trace::Trace, - L: crate::trace::Trace, - R: crate::trace::Trace, + U: crate::trace::Trace, { fn trace(&self, t: &mut dyn crate::trace::Tracer) { t.open("Dialog"); t.field("content", &self.content); - t.field("left", &self.left); - t.field("right", &self.right); + t.field("controls", &self.controls); t.close(); } } diff --git a/core/embed/rust/src/ui/model_tt/layout.rs b/core/embed/rust/src/ui/model_tt/layout.rs index 3cbf99046..2a5f5957d 100644 --- a/core/embed/rust/src/ui/model_tt/layout.rs +++ b/core/embed/rust/src/ui/model_tt/layout.rs @@ -26,17 +26,16 @@ use super::{ theme, }; -impl ComponentMsgObj for Dialog, Button> +impl ComponentMsgObj for Dialog where T: ComponentMsgObj, - U: AsRef, + U: Component, { fn msg_try_into_obj(&self, msg: Self::Msg) -> Result { match msg { DialogMsg::Content(c) => Ok(self.inner().msg_try_into_obj(c)?), - DialogMsg::Left(ButtonMsg::Clicked) => Ok(CANCELLED.as_obj()), - DialogMsg::Right(ButtonMsg::Clicked) => Ok(CONFIRMED.as_obj()), - _ => Ok(Obj::const_none()), + DialogMsg::Controls(false) => Ok(CANCELLED.as_obj()), + DialogMsg::Controls(true) => Ok(CONFIRMED.as_obj()), } } } @@ -283,18 +282,23 @@ mod tests { #[test] fn trace_example_layout() { + let buttons = Button::left_right( + Button::with_text("Left"), + |msg| (matches!(msg, ButtonMsg::Clicked)).then(|| false), + Button::with_text("Right"), + |msg| (matches!(msg, ButtonMsg::Clicked)).then(|| true), + ); let mut layout = Dialog::new( FormattedText::new::( "Testing text layout, with some text, and some more text. And {param}", ) .with("param", "parameters!"), - Button::with_text("Left"), - Button::with_text("Right"), + buttons, ); layout.place(SCREEN); assert_eq!( trace(&layout), - " left: