1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2025-02-24 13:22:05 +00:00

fix(core/ui): style update: frame and corner button

[no changelog]
This commit is contained in:
Martin Milata 2023-03-13 23:09:51 +01:00
parent 670cbd7a1d
commit afe965687f
6 changed files with 153 additions and 213 deletions

View File

@ -7,13 +7,13 @@ use crate::{
text::paragraphs::{ text::paragraphs::{
Paragraph, ParagraphSource, ParagraphStrType, ParagraphVecShort, Paragraphs, VecExt, Paragraph, ParagraphSource, ParagraphStrType, ParagraphVecShort, Paragraphs, VecExt,
}, },
Component, Event, EventCtx, Never, Paginate, Qr, Component, Event, EventCtx, Paginate, Qr,
}, },
geometry::Rect, geometry::Rect,
}, },
}; };
use super::{theme, Frame}; use super::{theme, Frame, FrameMsg};
const MAX_XPUBS: usize = 16; const MAX_XPUBS: usize = 16;
@ -57,18 +57,21 @@ where
"RECEIVE ADDRESS".into(), "RECEIVE ADDRESS".into(),
Qr::new(qr_address, case_sensitive)?.with_border(7), Qr::new(qr_address, case_sensitive)?.with_border(7),
) )
.with_cancel_button()
.with_border(theme::borders_horizontal_scroll()), .with_border(theme::borders_horizontal_scroll()),
details: Frame::left_aligned( details: Frame::left_aligned(
theme::label_title(), theme::label_title(),
"RECEIVING TO".into(), "RECEIVING TO".into(),
para.into_paragraphs(), para.into_paragraphs(),
) )
.with_cancel_button()
.with_border(theme::borders_horizontal_scroll()), .with_border(theme::borders_horizontal_scroll()),
xpub_view: Frame::left_aligned( xpub_view: Frame::left_aligned(
theme::label_title(), theme::label_title(),
" \n ".into(), " \n ".into(),
Paragraph::new(&theme::TEXT_MONO, "".into()).into_paragraphs(), Paragraph::new(&theme::TEXT_MONO, "".into()).into_paragraphs(),
) )
.with_cancel_button()
.with_border(theme::borders_horizontal_scroll()), .with_border(theme::borders_horizontal_scroll()),
xpubs: Vec::new(), xpubs: Vec::new(),
xpub_page_count: Vec::new(), xpub_page_count: Vec::new(),
@ -142,7 +145,7 @@ impl<T> Component for AddressDetails<T>
where where
T: ParagraphStrType + Clone, T: ParagraphStrType + Clone,
{ {
type Msg = Never; type Msg = ();
fn place(&mut self, bounds: Rect) -> Rect { fn place(&mut self, bounds: Rect) -> Rect {
self.qr_code.place(bounds); self.qr_code.place(bounds);
@ -159,10 +162,14 @@ 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> {
match self.current_page { let msg = match self.current_page {
0 => self.qr_code.event(ctx, event), 0 => self.qr_code.event(ctx, event),
1 => self.details.event(ctx, event), 1 => self.details.event(ctx, event),
_ => self.xpub_view.event(ctx, event), _ => self.xpub_view.event(ctx, event),
};
match msg {
Some(FrameMsg::Button(_)) => Some(()),
_ => None,
} }
} }

View File

@ -2,8 +2,7 @@ use crate::{
time::Duration, time::Duration,
ui::{ ui::{
component::{ component::{
Component, ComponentExt, Event, EventCtx, FixedHeightBar, Floating, Map, Paginate, Component, ComponentExt, Event, EventCtx, FixedHeightBar, Map, Split, TimerToken,
Split, TimerToken,
}, },
display::{self, toif::Icon, Color, Font}, display::{self, toif::Icon, Color, Font},
event::TouchEvent, event::TouchEvent,
@ -514,6 +513,7 @@ type CancelInfoConfirm<T, F0, F1, F2> =
type CancelConfirm<T, F0, F1> = FixedHeightBar<Split<Map<Button<T>, F0>, Map<Button<T>, F1>>>; type CancelConfirm<T, F0, F1> = FixedHeightBar<Split<Map<Button<T>, F0>, Map<Button<T>, F1>>>;
#[derive(Clone, Copy)]
pub enum CancelInfoConfirmMsg { pub enum CancelInfoConfirmMsg {
Cancelled, Cancelled,
Info, Info,
@ -582,89 +582,3 @@ impl IconText {
} }
} }
} }
pub struct FloatingButton<T> {
inner: T,
button: Floating<Button<&'static str>>,
}
pub enum FloatingButtonMsg<T> {
ButtonClicked,
Content(T),
}
impl<T> FloatingButton<T>
where
T: Component,
{
pub const fn top_right_corner(icon: Icon, inner: T) -> Self {
Self {
inner,
button: Floating::top_right(
theme::CORNER_BUTTON_SIDE,
theme::CORNER_BUTTON_SPACING,
Button::with_icon(icon)
.with_expanded_touch_area(Insets::uniform(theme::CORNER_BUTTON_SPACING))
.styled(theme::button_moreinfo()),
),
}
}
pub fn inner(&self) -> &T {
&self.inner
}
}
impl<T> Component for FloatingButton<T>
where
T: Component,
{
type Msg = FloatingButtonMsg<T::Msg>;
fn place(&mut self, bounds: Rect) -> Rect {
self.button.place(bounds);
self.inner.place(bounds)
}
fn event(&mut self, ctx: &mut EventCtx, event: Event) -> Option<Self::Msg> {
if let Some(ButtonMsg::Clicked) = self.button.event(ctx, event) {
return Some(FloatingButtonMsg::ButtonClicked);
}
self.inner.event(ctx, event).map(FloatingButtonMsg::Content)
}
fn paint(&mut self) {
self.inner.paint();
self.button.paint();
}
fn bounds(&self, sink: &mut dyn FnMut(Rect)) {
self.inner.bounds(sink);
self.button.bounds(sink);
}
}
impl<T> Paginate for FloatingButton<T>
where
T: Paginate,
{
fn page_count(&mut self) -> usize {
self.inner.page_count()
}
fn change_page(&mut self, to_page: usize) {
self.inner.change_page(to_page)
}
}
#[cfg(feature = "ui_debug")]
impl<T> crate::trace::Trace for FloatingButton<T>
where
T: Component + crate::trace::Trace,
{
fn trace(&self, t: &mut dyn crate::trace::Tracer) {
t.open("FloatingButton");
t.field("inner", self.inner());
t.close();
}
}

View File

@ -3,16 +3,24 @@ use crate::ui::{
component::{ component::{
base::ComponentExt, label::Label, text::TextStyle, Child, Component, Event, EventCtx, base::ComponentExt, label::Label, text::TextStyle, Child, Component, Event, EventCtx,
}, },
display::{self, Color, Font}, display::{self, Color, Font, Icon},
geometry::{Alignment, Insets, Offset, Rect}, geometry::{Alignment, Insets, Offset, Rect},
model_tt::component::{Button, ButtonMsg, CancelInfoConfirmMsg},
}; };
pub struct Frame<T, U> { pub struct Frame<T, U> {
border: Insets, border: Insets,
title: Child<Label<U>>, title: Child<Label<U>>,
button: Option<Child<Button<&'static str>>>,
button_msg: CancelInfoConfirmMsg,
content: Child<T>, content: Child<T>,
} }
pub enum FrameMsg<T> {
Content(T),
Button(CancelInfoConfirmMsg),
}
impl<T, U> Frame<T, U> impl<T, U> Frame<T, U>
where where
T: Component, T: Component,
@ -21,7 +29,9 @@ 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)),
border: theme::borders_scroll(), border: theme::borders(),
button: None,
button_msg: CancelInfoConfirmMsg::Cancelled,
content: Child::new(content), content: Child::new(content),
} }
} }
@ -43,6 +53,35 @@ where
self self
} }
fn with_button(mut self, icon: Icon, msg: CancelInfoConfirmMsg) -> Self {
let touch_area = Insets {
left: self.border.left * 4,
bottom: self.border.bottom * 4,
..self.border
};
self.button = Some(Child::new(
Button::with_icon(icon)
.with_expanded_touch_area(touch_area)
.styled(theme::button_moreinfo()),
));
self.button_msg = msg;
self
}
pub fn with_cancel_button(self) -> Self {
self.with_button(
Icon::new(theme::ICON_CORNER_CANCEL),
CancelInfoConfirmMsg::Cancelled,
)
}
pub fn with_info_button(self) -> Self {
self.with_button(
Icon::new(theme::ICON_CORNER_INFO),
CancelInfoConfirmMsg::Info,
)
}
pub fn inner(&self) -> &T { pub fn inner(&self) -> &T {
self.content.inner() self.content.inner()
} }
@ -71,31 +110,51 @@ where
T: Component, T: Component,
U: AsRef<str>, U: AsRef<str>,
{ {
type Msg = T::Msg; type Msg = FrameMsg<T::Msg>;
fn place(&mut self, bounds: Rect) -> Rect { fn place(&mut self, bounds: Rect) -> Rect {
const TITLE_SPACE: i16 = theme::BUTTON_SPACING; const TITLE_SPACE: i16 = theme::BUTTON_SPACING;
let bounds = bounds.inset(self.border); let bounds = bounds.inset(self.border);
let title_area = bounds.inset(Insets::sides(theme::CONTENT_BORDER)); if let Some(b) = &mut self.button {
let button_side = theme::CORNER_BUTTON_SIDE;
let (title_area, button_area) = bounds.split_right(button_side);
let (button_area, _) = button_area.split_top(button_side);
b.place(button_area);
let title_area = self.title.place(title_area); let title_area = self.title.place(title_area);
let title_height = title_area.height();
let height = title_area.height().max(button_side);
if title_height < button_side {
self.title
.place(title_area.translate(Offset::y((button_side - title_height) / 2)));
}
let content_area = bounds.inset(Insets::top(height + TITLE_SPACE));
self.content.place(content_area);
} else {
let title_area = self.title.place(bounds);
let content_area = bounds.inset(Insets::top(title_area.height() + TITLE_SPACE)); let content_area = bounds.inset(Insets::top(title_area.height() + TITLE_SPACE));
self.content.place(content_area); self.content.place(content_area);
}
bounds bounds
} }
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.content.event(ctx, event) if let Some(ButtonMsg::Clicked) = self.button.event(ctx, event) {
return Some(FrameMsg::Button(self.button_msg));
}
self.content.event(ctx, event).map(FrameMsg::Content)
} }
fn paint(&mut self) { fn paint(&mut self) {
self.title.paint(); self.title.paint();
self.button.paint();
self.content.paint(); self.content.paint();
} }
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.button.bounds(sink);
self.content.bounds(sink); self.content.bounds(sink);
} }
} }
@ -109,6 +168,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(b) = &self.button {
t.field("button", b);
}
t.field("content", &self.content); t.field("content", &self.content);
t.close(); t.close();
} }
@ -150,7 +212,7 @@ where
display::text_center( display::text_center(
area.center() + Offset::y((font.text_max_height() - font.text_baseline()) / 2), area.center() + Offset::y((font.text_max_height() - font.text_baseline()) / 2),
title, title,
Font::BOLD, font,
theme::FG, theme::FG,
color, color,
); );

View File

@ -22,11 +22,11 @@ mod welcome_screen;
pub use address_details::AddressDetails; pub use address_details::AddressDetails;
pub use button::{ pub use button::{
Button, ButtonContent, ButtonMsg, ButtonStyle, ButtonStyleSheet, CancelConfirmMsg, Button, ButtonContent, ButtonMsg, ButtonStyle, ButtonStyleSheet, CancelConfirmMsg,
CancelInfoConfirmMsg, FloatingButton, FloatingButtonMsg, IconText, SelectWordMsg, CancelInfoConfirmMsg, IconText, SelectWordMsg,
}; };
pub use dialog::{Dialog, DialogMsg, IconDialog}; pub use dialog::{Dialog, DialogMsg, IconDialog};
pub use fido::{FidoConfirm, FidoMsg}; pub use fido::{FidoConfirm, FidoMsg};
pub use frame::{Frame, NotificationFrame}; pub use frame::{Frame, FrameMsg, NotificationFrame};
pub use hold_to_confirm::{HoldToConfirm, HoldToConfirmMsg}; pub use hold_to_confirm::{HoldToConfirm, HoldToConfirmMsg};
#[cfg(feature = "dma2d")] #[cfg(feature = "dma2d")]
pub use homescreen::{Homescreen, HomescreenMsg, Lockscreen}; pub use homescreen::{Homescreen, HomescreenMsg, Lockscreen};

View File

@ -46,13 +46,12 @@ use crate::{
use super::{ use super::{
component::{ component::{
AddressDetails, Bip39Input, Button, ButtonMsg, ButtonStyleSheet, CancelConfirmMsg, AddressDetails, Bip39Input, Button, ButtonMsg, ButtonStyleSheet, CancelConfirmMsg,
CancelInfoConfirmMsg, Dialog, DialogMsg, FidoConfirm, FidoMsg, FloatingButton, CancelInfoConfirmMsg, Dialog, DialogMsg, FidoConfirm, FidoMsg, Frame, FrameMsg,
FloatingButtonMsg, Frame, HoldToConfirm, HoldToConfirmMsg, Homescreen, HomescreenMsg, HoldToConfirm, HoldToConfirmMsg, Homescreen, HomescreenMsg, HorizontalPage, IconDialog,
HorizontalPage, IconDialog, Lockscreen, MnemonicInput, MnemonicKeyboard, Lockscreen, MnemonicInput, MnemonicKeyboard, MnemonicKeyboardMsg, NotificationFrame,
MnemonicKeyboardMsg, NotificationFrame, NumberInputDialog, NumberInputDialogMsg, NumberInputDialog, NumberInputDialogMsg, PassphraseKeyboard, PassphraseKeyboardMsg,
PassphraseKeyboard, PassphraseKeyboardMsg, PinKeyboard, PinKeyboardMsg, Progress, PinKeyboard, PinKeyboardMsg, Progress, SelectWordCount, SelectWordCountMsg, SelectWordMsg,
SelectWordCount, SelectWordCountMsg, SelectWordMsg, Slip39Input, SwipeHoldPage, SwipePage, Slip39Input, SwipeHoldPage, SwipePage, WelcomeScreen,
WelcomeScreen,
}, },
constant, theme, constant, theme,
}; };
@ -200,7 +199,10 @@ where
U: AsRef<str>, U: AsRef<str>,
{ {
fn msg_try_into_obj(&self, msg: Self::Msg) -> Result<Obj, Error> { fn msg_try_into_obj(&self, msg: Self::Msg) -> Result<Obj, Error> {
self.inner().msg_try_into_obj(msg) match msg {
FrameMsg::Content(c) => self.inner().msg_try_into_obj(c),
FrameMsg::Button(b) => b.try_into(),
}
} }
} }
@ -340,18 +342,6 @@ impl ComponentMsgObj for Qr {
} }
} }
impl<T> ComponentMsgObj for FloatingButton<T>
where
T: ComponentMsgObj,
{
fn msg_try_into_obj(&self, msg: Self::Msg) -> Result<Obj, Error> {
match msg {
FloatingButtonMsg::ButtonClicked => Ok(INFO.as_obj()),
FloatingButtonMsg::Content(c) => self.inner().msg_try_into_obj(c),
}
}
}
impl<T> ComponentMsgObj for HorizontalPage<T> impl<T> ComponentMsgObj for HorizontalPage<T>
where where
T: ComponentMsgObj + Paginate, T: ComponentMsgObj + Paginate,
@ -371,7 +361,7 @@ where
T: ParagraphStrType + Clone, T: ParagraphStrType + Clone,
{ {
fn msg_try_into_obj(&self, _msg: Self::Msg) -> Result<Obj, Error> { fn msg_try_into_obj(&self, _msg: Self::Msg) -> Result<Obj, Error> {
unreachable!(); Ok(CANCELLED.as_obj())
} }
} }
@ -508,16 +498,16 @@ extern "C" fn new_confirm_address(n_args: usize, args: *const Obj, kwargs: *mut
.into_paragraphs(); .into_paragraphs();
let buttons = Button::cancel_confirm_text(None, Some("CONFIRM")); let buttons = Button::cancel_confirm_text(None, Some("CONFIRM"));
let obj = LayoutObj::new(FloatingButton::top_right_corner( let obj = LayoutObj::new(
Icon::new(theme::ICON_CORNER_INFO),
Frame::left_aligned( Frame::left_aligned(
theme::label_title(), theme::label_title(),
title, title,
SwipePage::new(paragraphs, buttons, theme::BG) SwipePage::new(paragraphs, buttons, theme::BG)
.with_swipe_left() .with_swipe_left()
.with_cancel_on_first_page(), .with_cancel_on_first_page(),
), )
))?; .with_info_button(),
)?;
Ok(obj.into()) Ok(obj.into())
}; };
unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) } unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) }
@ -572,14 +562,11 @@ extern "C" fn new_confirm_homescreen(n_args: usize, args: *const Obj, kwargs: *m
}; };
let buttons = Button::cancel_confirm_text(None, Some("CONFIRM")); let buttons = Button::cancel_confirm_text(None, Some("CONFIRM"));
let obj = LayoutObj::new( let obj = LayoutObj::new(Frame::centered(
Frame::centered(
theme::label_title(), theme::label_title(),
title, title,
Dialog::new(painter::jpeg_painter(buffer_func, size, 1), buttons), Dialog::new(painter::jpeg_painter(buffer_func, size, 1), buttons),
) ))?;
.with_border(theme::borders()),
)?;
Ok(obj.into()) Ok(obj.into())
}; };
@ -606,14 +593,11 @@ extern "C" fn new_confirm_reset_device(n_args: usize, args: *const Obj, kwargs:
Button::with_text(button).styled(theme::button_confirm()), Button::with_text(button).styled(theme::button_confirm()),
true, true,
); );
let obj = LayoutObj::new( let obj = LayoutObj::new(Frame::left_aligned(
Frame::left_aligned(
theme::label_title(), theme::label_title(),
title, title,
Dialog::new(paragraphs, buttons), Dialog::new(paragraphs, buttons),
) ))?;
.with_border(theme::borders()),
)?;
Ok(obj.into()) Ok(obj.into())
}; };
unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) } unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) }
@ -632,14 +616,11 @@ extern "C" fn new_show_qr(n_args: usize, args: *const Obj, kwargs: *mut Map) ->
false, false,
); );
let obj = LayoutObj::new( let obj = LayoutObj::new(Frame::left_aligned(
Frame::left_aligned(
theme::label_title(), theme::label_title(),
title, title,
Dialog::new(Qr::new(address, case_sensitive)?.with_border(4), buttons), Dialog::new(Qr::new(address, case_sensitive)?.with_border(4), buttons),
) ))?;
.with_border(theme::borders()),
)?;
Ok(obj.into()) Ok(obj.into())
}; };
unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) } unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) }
@ -663,13 +644,7 @@ extern "C" fn new_show_address_details(n_args: usize, args: *const Obj, kwargs:
ad.add_xpub(xtitle, text)?; ad.add_xpub(xtitle, text)?;
} }
let obj = LayoutObj::new( let obj = LayoutObj::new(HorizontalPage::new(ad, theme::BG).with_swipe_right_to_go_back())?;
HorizontalPage::new(
FloatingButton::top_right_corner(Icon::new(theme::ICON_CORNER_CANCEL), ad),
theme::BG,
)
.with_swipe_right_to_go_back(),
)?;
Ok(obj.into()) Ok(obj.into())
}; };
unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) } unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) }
@ -889,9 +864,7 @@ extern "C" fn new_confirm_fido(n_args: usize, args: *const Obj, kwargs: *mut Map
let fido_page = FidoConfirm::new(app_name, get_page, page_count, icon, controls); let fido_page = FidoConfirm::new(app_name, get_page, page_count, icon, controls);
let obj = LayoutObj::new( let obj = LayoutObj::new(Frame::centered(theme::label_title(), title, fido_page))?;
Frame::centered(theme::label_title(), title, fido_page).with_border(theme::borders()),
)?;
Ok(obj.into()) Ok(obj.into())
}; };
unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) } unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) }
@ -1043,14 +1016,11 @@ extern "C" fn new_confirm_with_info(n_args: usize, args: *const Obj, kwargs: *mu
let buttons = Button::cancel_info_confirm(button, info_button); let buttons = Button::cancel_info_confirm(button, info_button);
let obj = LayoutObj::new( let obj = LayoutObj::new(Frame::left_aligned(
Frame::left_aligned(
theme::label_title(), theme::label_title(),
title, title,
Dialog::new(paragraphs.into_paragraphs(), buttons), Dialog::new(paragraphs.into_paragraphs(), buttons),
) ))?;
.with_border(theme::borders()),
)?;
Ok(obj.into()) Ok(obj.into())
}; };
unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) } unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) }
@ -1216,14 +1186,11 @@ extern "C" fn new_request_number(n_args: usize, args: *const Obj, kwargs: *mut M
.unwrap() .unwrap()
}; };
let obj = LayoutObj::new( let obj = LayoutObj::new(Frame::left_aligned(
Frame::left_aligned(
theme::label_title(), theme::label_title(),
title, title,
NumberInputDialog::new(min_count, max_count, count, callback), NumberInputDialog::new(min_count, max_count, count, callback),
) ))?;
.with_border(theme::borders()),
)?;
Ok(obj.into()) Ok(obj.into())
}; };
unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) } unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) }
@ -1249,8 +1216,7 @@ extern "C" fn new_show_checklist(n_args: usize, args: *const Obj, kwargs: *mut M
paragraphs.add(Paragraph::new(style, text)); paragraphs.add(Paragraph::new(style, text));
} }
let obj = LayoutObj::new( let obj = LayoutObj::new(Frame::left_aligned(
Frame::left_aligned(
theme::label_title(), theme::label_title(),
title, title,
Dialog::new( Dialog::new(
@ -1266,9 +1232,7 @@ extern "C" fn new_show_checklist(n_args: usize, args: *const Obj, kwargs: *mut M
(matches!(msg, ButtonMsg::Clicked)).then(|| CancelConfirmMsg::Confirmed) (matches!(msg, ButtonMsg::Clicked)).then(|| CancelConfirmMsg::Confirmed)
})), })),
), ),
) ))?;
.with_border(theme::borders()),
)?;
Ok(obj.into()) Ok(obj.into())
}; };
unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) } unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) }
@ -1346,14 +1310,11 @@ extern "C" fn new_select_word_count(n_args: usize, args: *const Obj, kwargs: *mu
.centered(), .centered(),
); );
let obj = LayoutObj::new( let obj = LayoutObj::new(Frame::left_aligned(
Frame::left_aligned(
theme::label_title(), theme::label_title(),
title, title,
Dialog::new(paragraphs, SelectWordCount::new()), Dialog::new(paragraphs, SelectWordCount::new()),
) ))?;
.with_border(theme::borders()),
)?;
Ok(obj.into()) Ok(obj.into())
}; };
unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) } unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) }

View File

@ -553,22 +553,18 @@ pub const fn button_bar<T>(inner: T) -> FixedHeightBar<T> {
} }
/// +----------+ /// +----------+
/// | 13 | /// | 6 |
/// | +----+ | /// | +----+ |
/// |10| |10| /// | 6| | 6|
/// | +----+ | /// | +----+ |
/// | 14 | /// | 6 |
/// +----------+ /// +----------+
pub const fn borders() -> Insets { pub const fn borders() -> Insets {
Insets::new(6, 6, 6, 6) Insets::new(6, 6, 6, 6)
} }
pub const fn borders_scroll() -> Insets {
Insets::new(6, 6, 6, 6)
}
pub const fn borders_horizontal_scroll() -> Insets { pub const fn borders_horizontal_scroll() -> Insets {
Insets::new(13, 10, 0, 10) Insets::new(6, 6, 0, 6)
} }
pub const fn borders_notification() -> Insets { pub const fn borders_notification() -> Insets {