mirror of
https://github.com/trezor/trezor-firmware.git
synced 2024-12-19 12:58:13 +00:00
refactor(core/mercury): remove unnecessary Child
[no changelog]
This commit is contained in:
parent
1212a7319a
commit
888e384f79
@ -6,9 +6,7 @@ use crate::{
|
||||
strutil::TString,
|
||||
translations::TR,
|
||||
ui::{
|
||||
component::{
|
||||
base::Never, Bar, Child, Component, ComponentExt, Empty, Event, EventCtx, Label, Split,
|
||||
},
|
||||
component::{base::Never, Bar, Component, Empty, Event, EventCtx, Label, Split},
|
||||
display::loader::{loader_circular_uncompress, LoaderDimensions},
|
||||
geometry::{Insets, Offset, Rect},
|
||||
model_mercury::constant,
|
||||
@ -30,7 +28,7 @@ const LOADER_SPEED: u16 = 5;
|
||||
pub struct CoinJoinProgress<U> {
|
||||
value: u16,
|
||||
indeterminate: bool,
|
||||
content: Child<Frame<Split<Empty, U>>>,
|
||||
content: Frame<Split<Empty, U>>,
|
||||
// Label is not a child since circular loader paints large black rectangle which overlaps it.
|
||||
// To work around this, draw label every time loader is drawn.
|
||||
label: Label<'static>,
|
||||
@ -65,8 +63,7 @@ where
|
||||
content: Frame::centered(
|
||||
TR::coinjoin__title_progress.into(),
|
||||
Split::bottom(RECTANGLE_HEIGHT, 0, Empty, inner),
|
||||
)
|
||||
.into_child(),
|
||||
),
|
||||
label: Label::centered(text, theme::TEXT_NORMAL),
|
||||
})
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
use crate::{
|
||||
strutil::TString,
|
||||
ui::{
|
||||
component::{Child, Component, Event, EventCtx, Label, Never, Pad},
|
||||
component::{Component, Event, EventCtx, Label, Never, Pad},
|
||||
constant::screen,
|
||||
geometry::{Alignment2D, Point, Rect},
|
||||
shape,
|
||||
@ -26,9 +26,9 @@ const STYLE: &ResultStyle = &super::theme::RESULT_ERROR;
|
||||
|
||||
pub struct ErrorScreen<'a> {
|
||||
bg: Pad,
|
||||
title: Child<Label<'a>>,
|
||||
message: Child<Label<'a>>,
|
||||
footer: Child<ResultFooter<'a>>,
|
||||
title: Label<'a>,
|
||||
message: Label<'a>,
|
||||
footer: ResultFooter<'a>,
|
||||
}
|
||||
|
||||
impl<'a> ErrorScreen<'a> {
|
||||
@ -42,9 +42,9 @@ impl<'a> ErrorScreen<'a> {
|
||||
|
||||
Self {
|
||||
bg: Pad::with_background(FATAL_ERROR_COLOR).with_clear(),
|
||||
title: Child::new(title),
|
||||
message: Child::new(message),
|
||||
footer: Child::new(footer),
|
||||
title,
|
||||
message,
|
||||
footer,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +1,7 @@
|
||||
use crate::{
|
||||
strutil::TString,
|
||||
ui::{
|
||||
component::{
|
||||
image::Image, Child, Component, Event, EventCtx, Label, Swipe, SwipeDirection,
|
||||
},
|
||||
component::{image::Image, Component, Event, EventCtx, Label, Swipe, SwipeDirection},
|
||||
display,
|
||||
geometry::{Insets, Rect},
|
||||
model_mercury::component::{fido_icons::get_fido_icon_data, theme, ScrollBar},
|
||||
@ -30,7 +28,7 @@ pub struct FidoConfirm<F: Fn(usize) -> TString<'static>, U> {
|
||||
page_swipe: Swipe,
|
||||
app_name: Label<'static>,
|
||||
account_name: Label<'static>,
|
||||
icon: Child<Image>,
|
||||
icon: Image,
|
||||
/// Function/closure that will return appropriate page on demand.
|
||||
get_account: F,
|
||||
scrollbar: ScrollBar,
|
||||
@ -79,7 +77,7 @@ where
|
||||
app_name: Label::centered(app_name, theme::TEXT_DEMIBOLD),
|
||||
account_name: Label::centered(current_account, theme::TEXT_DEMIBOLD),
|
||||
page_swipe,
|
||||
icon: Child::new(Image::new(icon_data)),
|
||||
icon: Image::new(icon_data),
|
||||
get_account,
|
||||
scrollbar,
|
||||
fade: Cell::new(false),
|
||||
|
@ -2,7 +2,7 @@ use crate::{
|
||||
strutil::TString,
|
||||
ui::{
|
||||
component::{
|
||||
maybe::paint_overlapping, Child, Component, Event, EventCtx, Label, Maybe, Swipe,
|
||||
maybe::paint_overlapping, Component, Event, EventCtx, Label, Maybe, Swipe,
|
||||
SwipeDirection,
|
||||
},
|
||||
geometry::{Alignment, Grid, Insets, Rect},
|
||||
@ -24,17 +24,17 @@ pub enum MnemonicKeyboardMsg {
|
||||
|
||||
pub struct MnemonicKeyboard<T> {
|
||||
/// Initial prompt, displayed on empty input.
|
||||
prompt: Child<Maybe<Label<'static>>>,
|
||||
prompt: Maybe<Label<'static>>,
|
||||
/// Delete a char button.
|
||||
erase: Child<Maybe<Button>>,
|
||||
erase: Maybe<Button>,
|
||||
/// Go to previous word button
|
||||
back: Child<Maybe<Button>>,
|
||||
back: Maybe<Button>,
|
||||
/// Input area, acting as the auto-complete and confirm button.
|
||||
input: Child<Maybe<T>>,
|
||||
input: Maybe<T>,
|
||||
/// Area with keypads - used for rounded overlay
|
||||
keypad_area: Rect,
|
||||
/// Key buttons.
|
||||
keys: [Child<Button>; MNEMONIC_KEY_COUNT],
|
||||
keys: [Button; MNEMONIC_KEY_COUNT],
|
||||
/// Swipe controller - allowing for going to the previous word.
|
||||
swipe: Swipe,
|
||||
/// Whether going back is allowed (is not on the very first word).
|
||||
@ -56,26 +56,20 @@ where
|
||||
.styled(theme::button_default())
|
||||
.with_expanded_touch_area(Insets::right(BACK_BUTTON_RIGHT_EXPAND));
|
||||
Self {
|
||||
prompt: Child::new(Maybe::new(
|
||||
prompt: Maybe::new(
|
||||
theme::BG,
|
||||
Label::centered(prompt, theme::TEXT_MAIN_GREY_LIGHT).vertically_centered(),
|
||||
prompt_visible,
|
||||
)),
|
||||
erase: Child::new(Maybe::new(theme::BG, erase_btn, !prompt_visible)),
|
||||
back: Child::new(Maybe::new(
|
||||
theme::BG,
|
||||
back_btn,
|
||||
prompt_visible && can_go_back,
|
||||
)),
|
||||
input: Child::new(Maybe::new(theme::BG, input, !prompt_visible)),
|
||||
),
|
||||
erase: Maybe::new(theme::BG, erase_btn, !prompt_visible),
|
||||
back: Maybe::new(theme::BG, back_btn, prompt_visible && can_go_back),
|
||||
input: Maybe::new(theme::BG, input, !prompt_visible),
|
||||
keypad_area: Rect::zero(),
|
||||
keys: T::keys()
|
||||
.map(|t| {
|
||||
Button::with_text(t.into())
|
||||
.styled(theme::button_keyboard())
|
||||
.with_text_align(Alignment::Center)
|
||||
})
|
||||
.map(Child::new),
|
||||
keys: T::keys().map(|t| {
|
||||
Button::with_text(t.into())
|
||||
.styled(theme::button_keyboard())
|
||||
.with_text_align(Alignment::Center)
|
||||
}),
|
||||
swipe: Swipe::new().right(),
|
||||
can_go_back,
|
||||
}
|
||||
@ -90,32 +84,23 @@ where
|
||||
/// completion mask and the pending key.
|
||||
fn toggle_key_buttons(&mut self, ctx: &mut EventCtx) {
|
||||
for (key, btn) in self.keys.iter_mut().enumerate() {
|
||||
let enabled = self
|
||||
.input
|
||||
.inner()
|
||||
.inner()
|
||||
.can_key_press_lead_to_a_valid_word(key);
|
||||
btn.mutate(ctx, |ctx, b| b.enable_if(ctx, enabled));
|
||||
let enabled = self.input.inner().can_key_press_lead_to_a_valid_word(key);
|
||||
btn.enable_if(ctx, enabled);
|
||||
}
|
||||
}
|
||||
|
||||
/// After edit operations, we need to either show or hide the prompt, the
|
||||
/// input, the erase button and the back button.
|
||||
fn toggle_prompt_or_input(&mut self, ctx: &mut EventCtx) {
|
||||
let prompt_visible = self.input.inner().inner().is_empty();
|
||||
self.prompt
|
||||
.mutate(ctx, |ctx, p| p.show_if(ctx, prompt_visible));
|
||||
self.input
|
||||
.mutate(ctx, |ctx, i| i.show_if(ctx, !prompt_visible));
|
||||
self.erase
|
||||
.mutate(ctx, |ctx, b| b.show_if(ctx, !prompt_visible));
|
||||
self.back.mutate(ctx, |ctx, b| {
|
||||
b.show_if(ctx, prompt_visible && self.can_go_back)
|
||||
});
|
||||
let prompt_visible = self.input.inner().is_empty();
|
||||
self.prompt.show_if(ctx, prompt_visible);
|
||||
self.input.show_if(ctx, !prompt_visible);
|
||||
self.erase.show_if(ctx, !prompt_visible);
|
||||
self.back.show_if(ctx, prompt_visible && self.can_go_back);
|
||||
}
|
||||
|
||||
pub fn mnemonic(&self) -> Option<&'static str> {
|
||||
self.input.inner().inner().mnemonic()
|
||||
self.input.inner().mnemonic()
|
||||
}
|
||||
}
|
||||
|
||||
@ -181,14 +166,12 @@ where
|
||||
|
||||
match self.erase.event(ctx, event) {
|
||||
Some(ButtonMsg::Clicked) => {
|
||||
self.input
|
||||
.mutate(ctx, |ctx, i| i.inner_mut().on_backspace_click(ctx));
|
||||
self.input.inner_mut().on_backspace_click(ctx);
|
||||
self.on_input_change(ctx);
|
||||
return None;
|
||||
}
|
||||
Some(ButtonMsg::LongPressed) => {
|
||||
self.input
|
||||
.mutate(ctx, |ctx, i| i.inner_mut().on_backspace_long_press(ctx));
|
||||
self.input.inner_mut().on_backspace_long_press(ctx);
|
||||
self.on_input_change(ctx);
|
||||
return None;
|
||||
}
|
||||
@ -196,8 +179,7 @@ where
|
||||
}
|
||||
for (key, btn) in self.keys.iter_mut().enumerate() {
|
||||
if let Some(ButtonMsg::Clicked) = btn.event(ctx, event) {
|
||||
self.input
|
||||
.mutate(ctx, |ctx, i| i.inner_mut().on_key_click(ctx, key));
|
||||
self.input.inner_mut().on_key_click(ctx, key);
|
||||
self.on_input_change(ctx);
|
||||
return None;
|
||||
}
|
||||
@ -213,7 +195,7 @@ where
|
||||
}
|
||||
|
||||
fn render<'s>(&'s self, target: &mut impl Renderer<'s>) {
|
||||
if self.input.inner().inner().is_empty() {
|
||||
if self.input.inner().is_empty() {
|
||||
self.prompt.render(target);
|
||||
if self.can_go_back {
|
||||
self.back.render(target);
|
||||
|
@ -3,8 +3,8 @@ use crate::{
|
||||
translations::TR,
|
||||
ui::{
|
||||
component::{
|
||||
base::ComponentExt, text::common::TextBox, Child, Component, Event, EventCtx, Label,
|
||||
Maybe, Never, Swipe, SwipeDirection,
|
||||
base::ComponentExt, text::common::TextBox, Component, Event, EventCtx, Label, Maybe,
|
||||
Never, Swipe, SwipeDirection,
|
||||
},
|
||||
display,
|
||||
geometry::{Alignment, Grid, Insets, Offset, Rect},
|
||||
@ -75,14 +75,14 @@ impl From<KeyboardLayout> for ButtonContent {
|
||||
|
||||
pub struct PassphraseKeyboard {
|
||||
page_swipe: Swipe,
|
||||
input: Child<Input>,
|
||||
input_prompt: Child<Label<'static>>,
|
||||
erase_btn: Child<Maybe<Button>>,
|
||||
cancel_btn: Child<Maybe<Button>>,
|
||||
confirm_btn: Child<Button>,
|
||||
next_btn: Child<Button>,
|
||||
input: Input,
|
||||
input_prompt: Label<'static>,
|
||||
erase_btn: Maybe<Button>,
|
||||
cancel_btn: Maybe<Button>,
|
||||
confirm_btn: Button,
|
||||
next_btn: Button,
|
||||
keypad_area: Rect,
|
||||
keys: [Child<Button>; KEY_COUNT],
|
||||
keys: [Button; KEY_COUNT],
|
||||
active_layout: KeyboardLayout,
|
||||
fade: Cell<bool>,
|
||||
}
|
||||
@ -105,43 +105,38 @@ impl PassphraseKeyboard {
|
||||
|
||||
let confirm_btn = Button::with_icon(theme::ICON_SIMPLE_CHECKMARK24)
|
||||
.styled(theme::button_passphrase_confirm())
|
||||
.with_radius(15)
|
||||
.into_child();
|
||||
.with_radius(15);
|
||||
|
||||
let next_btn = Button::new(active_layout.next().into())
|
||||
.styled(theme::button_passphrase_next())
|
||||
.with_text_align(Alignment::Center)
|
||||
.into_child();
|
||||
.with_text_align(Alignment::Center);
|
||||
|
||||
let erase_btn = Button::with_icon(theme::ICON_DELETE)
|
||||
.styled(theme::button_keyboard_erase())
|
||||
.with_long_press(theme::ERASE_HOLD_DURATION)
|
||||
.initially_enabled(false);
|
||||
let erase_btn = Maybe::hidden(theme::BG, erase_btn).into_child();
|
||||
let erase_btn = Maybe::hidden(theme::BG, erase_btn);
|
||||
|
||||
let cancel_btn =
|
||||
Button::with_icon(theme::ICON_CLOSE).styled(theme::button_keyboard_cancel());
|
||||
let cancel_btn = Maybe::visible(theme::BG, cancel_btn).into_child();
|
||||
let cancel_btn = Maybe::visible(theme::BG, cancel_btn);
|
||||
|
||||
Self {
|
||||
page_swipe: Swipe::horizontal(),
|
||||
input: Input::new().into_child(),
|
||||
input: Input::new(),
|
||||
input_prompt: Label::left_aligned(
|
||||
TString::from_translation(TR::passphrase__title_enter),
|
||||
theme::label_keyboard(),
|
||||
)
|
||||
.into_child(),
|
||||
),
|
||||
erase_btn,
|
||||
cancel_btn,
|
||||
confirm_btn,
|
||||
next_btn,
|
||||
keypad_area: Rect::zero(),
|
||||
keys: KEYBOARD[active_layout.to_usize().unwrap()].map(|text| {
|
||||
Child::new(
|
||||
Button::new(Self::key_content(text))
|
||||
.styled(theme::button_keyboard())
|
||||
.with_text_align(Alignment::Center),
|
||||
)
|
||||
Button::new(Self::key_content(text))
|
||||
.styled(theme::button_keyboard())
|
||||
.with_text_align(Alignment::Center)
|
||||
}),
|
||||
active_layout,
|
||||
fade: Cell::new(false),
|
||||
@ -174,8 +169,7 @@ impl PassphraseKeyboard {
|
||||
_ => self.active_layout,
|
||||
};
|
||||
// Clear the pending state.
|
||||
self.input
|
||||
.mutate(ctx, |ctx, i| i.multi_tap.clear_pending_state(ctx));
|
||||
self.input.multi_tap.clear_pending_state(ctx);
|
||||
// Update keys.
|
||||
self.replace_keys_contents(ctx);
|
||||
// Reset backlight to normal level on next paint.
|
||||
@ -186,13 +180,12 @@ impl PassphraseKeyboard {
|
||||
}
|
||||
|
||||
fn replace_keys_contents(&mut self, ctx: &mut EventCtx) {
|
||||
self.next_btn.mutate(ctx, |ctx, b| {
|
||||
b.set_content(ctx, self.active_layout.next().into());
|
||||
});
|
||||
self.next_btn
|
||||
.set_content(ctx, self.active_layout.next().into());
|
||||
for (i, btn) in self.keys.iter_mut().enumerate() {
|
||||
let text = KEYBOARD[self.active_layout.to_usize().unwrap()][i];
|
||||
let content = Self::key_content(text);
|
||||
btn.mutate(ctx, |ctx, b| b.set_content(ctx, content));
|
||||
btn.set_content(ctx, content);
|
||||
btn.request_complete_repaint(ctx);
|
||||
}
|
||||
}
|
||||
@ -201,15 +194,11 @@ impl PassphraseKeyboard {
|
||||
fn after_edit(&mut self, ctx: &mut EventCtx) {
|
||||
// When the input is empty, enable cancel button. Otherwise show erase and
|
||||
// confirm button.
|
||||
let is_empty = self.input.inner().textbox.is_empty();
|
||||
self.erase_btn.mutate(ctx, |ctx, btn| {
|
||||
btn.show_if(ctx, !is_empty);
|
||||
btn.inner_mut().enable_if(ctx, !is_empty);
|
||||
});
|
||||
self.cancel_btn.mutate(ctx, |ctx, btn| {
|
||||
btn.show_if(ctx, is_empty);
|
||||
btn.inner_mut().enable_if(ctx, is_empty);
|
||||
});
|
||||
let is_empty = self.input.textbox.is_empty();
|
||||
self.erase_btn.show_if(ctx, !is_empty);
|
||||
self.erase_btn.inner_mut().enable_if(ctx, !is_empty);
|
||||
self.cancel_btn.show_if(ctx, is_empty);
|
||||
self.cancel_btn.inner_mut().enable_if(ctx, is_empty);
|
||||
|
||||
self.update_input_btns_state(ctx);
|
||||
}
|
||||
@ -218,13 +207,11 @@ impl PassphraseKeyboard {
|
||||
fn update_input_btns_state(&mut self, ctx: &mut EventCtx) {
|
||||
let active_states = self.get_buttons_active_states();
|
||||
for (key, btn) in self.keys.iter_mut().enumerate() {
|
||||
btn.mutate(ctx, |ctx, b| {
|
||||
if active_states[key] {
|
||||
b.enable(ctx);
|
||||
} else {
|
||||
b.disable(ctx);
|
||||
}
|
||||
});
|
||||
if active_states[key] {
|
||||
btn.enable(ctx);
|
||||
} else {
|
||||
btn.disable(ctx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -241,9 +228,9 @@ impl PassphraseKeyboard {
|
||||
/// We should disable the input when the passphrase has reached maximum
|
||||
/// length and we are not cycling through the characters.
|
||||
fn is_button_active(&self, key: usize) -> bool {
|
||||
let textbox_not_full = self.input.inner().textbox.len() < MAX_LENGTH;
|
||||
let textbox_not_full = self.input.textbox.len() < MAX_LENGTH;
|
||||
let key_is_pending = {
|
||||
if let Some(pending) = self.input.inner().multi_tap.pending_key() {
|
||||
if let Some(pending) = self.input.multi_tap.pending_key() {
|
||||
pending == key
|
||||
} else {
|
||||
false
|
||||
@ -253,7 +240,7 @@ impl PassphraseKeyboard {
|
||||
}
|
||||
|
||||
pub fn passphrase(&self) -> &str {
|
||||
self.input.inner().textbox.content()
|
||||
self.input.textbox.content()
|
||||
}
|
||||
}
|
||||
|
||||
@ -307,9 +294,8 @@ impl Component for PassphraseKeyboard {
|
||||
}
|
||||
|
||||
fn event(&mut self, ctx: &mut EventCtx, event: Event) -> Option<Self::Msg> {
|
||||
if self.input.inner().multi_tap.is_timeout_event(event) {
|
||||
self.input
|
||||
.mutate(ctx, |ctx, i| i.multi_tap.clear_pending_state(ctx));
|
||||
if self.input.multi_tap.is_timeout_event(event) {
|
||||
self.input.multi_tap.clear_pending_state(ctx);
|
||||
return None;
|
||||
}
|
||||
if let Some(swipe) = self.page_swipe.event(ctx, event) {
|
||||
@ -331,18 +317,14 @@ impl Component for PassphraseKeyboard {
|
||||
|
||||
match self.erase_btn.event(ctx, event) {
|
||||
Some(ButtonMsg::Clicked) => {
|
||||
self.input.mutate(ctx, |ctx, i| {
|
||||
i.multi_tap.clear_pending_state(ctx);
|
||||
i.textbox.delete_last(ctx);
|
||||
});
|
||||
self.input.multi_tap.clear_pending_state(ctx);
|
||||
self.input.textbox.delete_last(ctx);
|
||||
self.after_edit(ctx);
|
||||
return None;
|
||||
}
|
||||
Some(ButtonMsg::LongPressed) => {
|
||||
self.input.mutate(ctx, |ctx, i| {
|
||||
i.multi_tap.clear_pending_state(ctx);
|
||||
i.textbox.clear(ctx);
|
||||
});
|
||||
self.input.multi_tap.clear_pending_state(ctx);
|
||||
self.input.textbox.clear(ctx);
|
||||
self.after_edit(ctx);
|
||||
return None;
|
||||
}
|
||||
@ -362,11 +344,9 @@ impl Component for PassphraseKeyboard {
|
||||
if let Some(ButtonMsg::Clicked) = btn.event(ctx, event) {
|
||||
// Key button was clicked. If this button is pending, let's cycle the pending
|
||||
// character in textbox. If not, let's just append the first character.
|
||||
let text = Self::key_text(btn.inner().content());
|
||||
self.input.mutate(ctx, |ctx, i| {
|
||||
let edit = text.map(|c| i.multi_tap.click_key(ctx, key, c));
|
||||
i.textbox.apply(ctx, edit);
|
||||
});
|
||||
let text = Self::key_text(btn.content());
|
||||
let edit = text.map(|c| self.input.multi_tap.click_key(ctx, key, c));
|
||||
self.input.textbox.apply(ctx, edit);
|
||||
self.after_edit(ctx);
|
||||
return None;
|
||||
}
|
||||
@ -383,7 +363,7 @@ impl Component for PassphraseKeyboard {
|
||||
self.next_btn.render(target);
|
||||
self.erase_btn.render(target);
|
||||
self.confirm_btn.render(target);
|
||||
if self.input.inner().textbox.is_empty() {
|
||||
if self.input.textbox.is_empty() {
|
||||
self.cancel_btn.render(target);
|
||||
// FIXME: when prompt fixed in Figma
|
||||
// self.input_prompt.render(target);
|
||||
|
@ -8,7 +8,7 @@ use crate::{
|
||||
component::{
|
||||
base::{AttachType, ComponentExt},
|
||||
text::TextStyle,
|
||||
Child, Component, Event, EventCtx, Label, Never, Pad, SwipeDirection, TimerToken,
|
||||
Component, Event, EventCtx, Label, Never, Pad, SwipeDirection, TimerToken,
|
||||
},
|
||||
display::Font,
|
||||
event::TouchEvent,
|
||||
@ -246,12 +246,12 @@ pub struct PinKeyboard<'a> {
|
||||
allow_cancel: bool,
|
||||
show_erase: bool,
|
||||
show_cancel: bool,
|
||||
major_prompt: Child<Label<'a>>,
|
||||
minor_prompt: Child<Label<'a>>,
|
||||
major_warning: Option<Child<Label<'a>>>,
|
||||
major_prompt: Label<'a>,
|
||||
minor_prompt: Label<'a>,
|
||||
major_warning: Option<Label<'a>>,
|
||||
keypad_area: Rect,
|
||||
textbox_area: Rect,
|
||||
textbox: Child<PinDots>,
|
||||
textbox: PinDots,
|
||||
erase_btn: Button,
|
||||
cancel_btn: Button,
|
||||
confirm_btn: Button,
|
||||
@ -282,15 +282,13 @@ impl<'a> PinKeyboard<'a> {
|
||||
allow_cancel,
|
||||
show_erase: false,
|
||||
show_cancel: allow_cancel,
|
||||
major_prompt: Label::left_aligned(major_prompt, theme::label_keyboard()).into_child(),
|
||||
minor_prompt: Label::right_aligned(minor_prompt, theme::label_keyboard_minor())
|
||||
.into_child(),
|
||||
major_warning: major_warning.map(|text| {
|
||||
Label::left_aligned(text, theme::label_keyboard_warning()).into_child()
|
||||
}),
|
||||
major_prompt: Label::left_aligned(major_prompt, theme::label_keyboard()),
|
||||
minor_prompt: Label::right_aligned(minor_prompt, theme::label_keyboard_minor()),
|
||||
major_warning: major_warning
|
||||
.map(|text| Label::left_aligned(text, theme::label_keyboard_warning())),
|
||||
keypad_area: Rect::zero(),
|
||||
textbox_area: Rect::zero(),
|
||||
textbox: PinDots::new(theme::label_default()).into_child(),
|
||||
textbox: PinDots::new(theme::label_default()),
|
||||
erase_btn,
|
||||
cancel_btn,
|
||||
confirm_btn: Button::with_icon(theme::ICON_SIMPLE_CHECKMARK24)
|
||||
@ -318,8 +316,8 @@ impl<'a> PinKeyboard<'a> {
|
||||
}
|
||||
|
||||
fn pin_modified(&mut self, ctx: &mut EventCtx) {
|
||||
let is_full = self.textbox.inner().is_full();
|
||||
let is_empty = self.textbox.inner().is_empty();
|
||||
let is_full = self.textbox.is_full();
|
||||
let is_empty = self.textbox.is_empty();
|
||||
|
||||
self.textbox.request_complete_repaint(ctx);
|
||||
|
||||
@ -343,7 +341,7 @@ impl<'a> PinKeyboard<'a> {
|
||||
}
|
||||
|
||||
pub fn pin(&self) -> &str {
|
||||
self.textbox.inner().pin()
|
||||
self.textbox.pin()
|
||||
}
|
||||
|
||||
fn get_button_alpha(&self, x: usize, y: usize, attach_time: f32, close_time: f32) -> u8 {
|
||||
@ -454,12 +452,12 @@ impl Component for PinKeyboard<'_> {
|
||||
}
|
||||
match self.erase_btn.event(ctx, event) {
|
||||
Some(ButtonMsg::Clicked) => {
|
||||
self.textbox.mutate(ctx, |ctx, t| t.pop(ctx));
|
||||
self.textbox.pop(ctx);
|
||||
self.pin_modified(ctx);
|
||||
return None;
|
||||
}
|
||||
Some(ButtonMsg::LongPressed) => {
|
||||
self.textbox.mutate(ctx, |ctx, t| t.clear(ctx));
|
||||
self.textbox.clear(ctx);
|
||||
self.pin_modified(ctx);
|
||||
return None;
|
||||
}
|
||||
@ -469,7 +467,7 @@ impl Component for PinKeyboard<'_> {
|
||||
if let Some(Clicked) = btn.0.event(ctx, event) {
|
||||
if let ButtonContent::Text(text) = btn.0.content() {
|
||||
text.map(|text| {
|
||||
self.textbox.mutate(ctx, |ctx, t| t.push(ctx, text));
|
||||
self.textbox.push(ctx, text);
|
||||
});
|
||||
self.pin_modified(ctx);
|
||||
return None;
|
||||
@ -493,7 +491,7 @@ impl Component for PinKeyboard<'_> {
|
||||
self.erase_btn.render_with_alpha(target, erase_alpha);
|
||||
}
|
||||
|
||||
if self.textbox.inner().is_empty() {
|
||||
if self.textbox.is_empty() {
|
||||
if let Some(ref w) = self.major_warning {
|
||||
w.render(target);
|
||||
} else {
|
||||
@ -710,7 +708,7 @@ impl crate::trace::Trace for PinKeyboard<'_> {
|
||||
}
|
||||
}
|
||||
t.string("digits_order", digits_order.as_str().into());
|
||||
t.string("pin", self.textbox.inner().pin().into());
|
||||
t.bool("display_digits", self.textbox.inner().display_digits);
|
||||
t.string("pin", self.textbox.pin().into());
|
||||
t.bool("display_digits", self.textbox.display_digits);
|
||||
}
|
||||
}
|
||||
|
@ -3,9 +3,8 @@ use crate::{
|
||||
strutil::{self, TString},
|
||||
ui::{
|
||||
component::{
|
||||
base::ComponentExt,
|
||||
text::paragraphs::{Paragraph, Paragraphs},
|
||||
Child, Component, Event, EventCtx, Pad, SwipeDirection,
|
||||
Component, Event, EventCtx, Pad, SwipeDirection,
|
||||
},
|
||||
display::Font,
|
||||
event::SwipeEvent,
|
||||
@ -23,8 +22,8 @@ pub enum NumberInputDialogMsg {
|
||||
|
||||
pub struct NumberInputDialog {
|
||||
area: Rect,
|
||||
input: Child<NumberInput>,
|
||||
paragraphs: Child<Paragraphs<Paragraph<'static>>>,
|
||||
input: NumberInput,
|
||||
paragraphs: Paragraphs<Paragraph<'static>>,
|
||||
paragraphs_pad: Pad,
|
||||
}
|
||||
|
||||
@ -32,15 +31,14 @@ impl NumberInputDialog {
|
||||
pub fn new(min: u32, max: u32, init_value: u32, text: TString<'static>) -> Result<Self, Error> {
|
||||
Ok(Self {
|
||||
area: Rect::zero(),
|
||||
input: NumberInput::new(min, max, init_value).into_child(),
|
||||
paragraphs: Paragraphs::new(Paragraph::new(&theme::TEXT_MAIN_GREY_LIGHT, text))
|
||||
.into_child(),
|
||||
input: NumberInput::new(min, max, init_value),
|
||||
paragraphs: Paragraphs::new(Paragraph::new(&theme::TEXT_MAIN_GREY_LIGHT, text)),
|
||||
paragraphs_pad: Pad::with_background(theme::BG),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn value(&self) -> u32 {
|
||||
self.input.inner().value
|
||||
self.input.value
|
||||
}
|
||||
}
|
||||
|
||||
@ -69,7 +67,7 @@ impl Component for NumberInputDialog {
|
||||
}
|
||||
|
||||
if let Event::Swipe(SwipeEvent::End(SwipeDirection::Up)) = event {
|
||||
return Some(NumberInputDialogMsg::Confirmed(self.input.inner().value));
|
||||
return Some(NumberInputDialogMsg::Confirmed(self.input.value));
|
||||
}
|
||||
self.paragraphs.event(ctx, event);
|
||||
None
|
||||
@ -101,8 +99,8 @@ pub enum NumberInputMsg {
|
||||
|
||||
pub struct NumberInput {
|
||||
area: Rect,
|
||||
dec: Child<Button>,
|
||||
inc: Child<Button>,
|
||||
dec: Button,
|
||||
inc: Button,
|
||||
min: u32,
|
||||
max: u32,
|
||||
value: u32,
|
||||
@ -110,12 +108,8 @@ pub struct NumberInput {
|
||||
|
||||
impl NumberInput {
|
||||
pub fn new(min: u32, max: u32, value: u32) -> Self {
|
||||
let dec = Button::with_icon(theme::ICON_MINUS)
|
||||
.styled(theme::button_counter())
|
||||
.into_child();
|
||||
let inc = Button::with_icon(theme::ICON_PLUS)
|
||||
.styled(theme::button_counter())
|
||||
.into_child();
|
||||
let dec = Button::with_icon(theme::ICON_MINUS).styled(theme::button_counter());
|
||||
let inc = Button::with_icon(theme::ICON_PLUS).styled(theme::button_counter());
|
||||
let value = value.clamp(min, max);
|
||||
Self {
|
||||
area: Rect::zero(),
|
||||
@ -150,10 +144,8 @@ impl Component for NumberInput {
|
||||
changed = true;
|
||||
};
|
||||
if changed {
|
||||
self.dec
|
||||
.mutate(ctx, |ctx, btn| btn.enable_if(ctx, self.value > self.min));
|
||||
self.inc
|
||||
.mutate(ctx, |ctx, btn| btn.enable_if(ctx, self.value < self.max));
|
||||
self.dec.enable_if(ctx, self.value > self.min);
|
||||
self.inc.enable_if(ctx, self.value < self.max);
|
||||
ctx.request_paint();
|
||||
return Some(NumberInputMsg::Changed(self.value));
|
||||
}
|
||||
|
@ -3,7 +3,7 @@ use crate::{
|
||||
strutil::{ShortString, TString},
|
||||
translations::TR,
|
||||
ui::{
|
||||
component::{base::ComponentExt, Child, Component, Event, EventCtx},
|
||||
component::{Component, Event, EventCtx},
|
||||
constant::screen,
|
||||
display,
|
||||
event::TouchEvent,
|
||||
@ -18,7 +18,7 @@ pub enum NumberInputSliderDialogMsg {
|
||||
|
||||
pub struct NumberInputSliderDialog {
|
||||
area: Rect,
|
||||
input: Child<NumberInputSlider>,
|
||||
input: NumberInputSlider,
|
||||
footer: Footer<'static>,
|
||||
min: u16,
|
||||
max: u16,
|
||||
@ -30,7 +30,7 @@ impl NumberInputSliderDialog {
|
||||
pub fn new(min: u16, max: u16, init_value: u16) -> Self {
|
||||
Self {
|
||||
area: Rect::zero(),
|
||||
input: NumberInputSlider::new(min, max, init_value).into_child(),
|
||||
input: NumberInputSlider::new(min, max, init_value),
|
||||
footer: Footer::new::<TString<'static>>(
|
||||
TR::instructions__swipe_horizontally.into(),
|
||||
Some(TR::setting__adjust.into()),
|
||||
@ -43,7 +43,7 @@ impl NumberInputSliderDialog {
|
||||
}
|
||||
|
||||
pub fn value(&self) -> u16 {
|
||||
self.input.inner().value
|
||||
self.input.value
|
||||
}
|
||||
}
|
||||
|
||||
@ -79,7 +79,7 @@ impl Component for NumberInputSliderDialog {
|
||||
if let Some(value) = self.input.event(ctx, event) {
|
||||
self.val = value;
|
||||
|
||||
if self.val == self.init_val || self.input.inner().touching {
|
||||
if self.val == self.init_val || self.input.touching {
|
||||
self.footer
|
||||
.update_instruction(ctx, TR::instructions__swipe_horizontally);
|
||||
self.footer.update_description(ctx, TR::setting__adjust);
|
||||
|
@ -4,10 +4,9 @@ use crate::{
|
||||
strutil::TString,
|
||||
ui::{
|
||||
component::{
|
||||
base::ComponentExt,
|
||||
paginated::Paginate,
|
||||
text::paragraphs::{Paragraph, Paragraphs},
|
||||
Child, Component, Event, EventCtx, Label, Never, Pad,
|
||||
Component, Event, EventCtx, Label, Never, Pad,
|
||||
},
|
||||
display::{self, Font, LOADER_MAX},
|
||||
geometry::{Insets, Offset, Rect},
|
||||
@ -23,11 +22,11 @@ use crate::{
|
||||
use super::theme;
|
||||
|
||||
pub struct Progress {
|
||||
title: Child<Label<'static>>,
|
||||
title: Label<'static>,
|
||||
value: u16,
|
||||
loader_y_offset: i16,
|
||||
indeterminate: bool,
|
||||
description: Child<Paragraphs<Paragraph<'static>>>,
|
||||
description: Paragraphs<Paragraph<'static>>,
|
||||
description_pad: Pad,
|
||||
}
|
||||
|
||||
@ -40,14 +39,13 @@ impl Progress {
|
||||
description: TString<'static>,
|
||||
) -> Self {
|
||||
Self {
|
||||
title: Label::centered(title, theme::label_progress()).into_child(),
|
||||
title: Label::centered(title, theme::label_progress()),
|
||||
value: 0,
|
||||
loader_y_offset: 0,
|
||||
indeterminate,
|
||||
description: Paragraphs::new(
|
||||
Paragraph::new(&theme::TEXT_NORMAL, description).centered(),
|
||||
)
|
||||
.into_child(),
|
||||
),
|
||||
description_pad: Pad::with_background(theme::BG),
|
||||
}
|
||||
}
|
||||
@ -60,10 +58,9 @@ impl Component for Progress {
|
||||
let description_lines = 1 + self
|
||||
.description
|
||||
.inner()
|
||||
.inner()
|
||||
.content()
|
||||
.map(|t| t.chars().filter(|c| *c == '\n').count() as i16);
|
||||
let (title, rest) = Self::AREA.split_top(self.title.inner().max_size().y);
|
||||
let (title, rest) = Self::AREA.split_top(self.title.max_size().y);
|
||||
let (loader, description) =
|
||||
rest.split_bottom(Font::NORMAL.line_height() * description_lines);
|
||||
let loader = loader.inset(Insets::top(theme::CONTENT_BORDER));
|
||||
@ -80,14 +77,12 @@ impl Component for Progress {
|
||||
if !animation_disabled() {
|
||||
ctx.request_paint();
|
||||
}
|
||||
self.description.mutate(ctx, |ctx, para| {
|
||||
if para.inner_mut().content() != &new_description {
|
||||
para.inner_mut().update(new_description);
|
||||
para.change_page(0); // Recompute bounding box.
|
||||
ctx.request_paint();
|
||||
self.description_pad.clear();
|
||||
}
|
||||
});
|
||||
if self.description.inner_mut().content() != &new_description {
|
||||
self.description.inner_mut().update(new_description);
|
||||
self.description.change_page(0); // Recompute bounding box.
|
||||
ctx.request_paint();
|
||||
self.description_pad.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
None
|
||||
|
@ -1,7 +1,7 @@
|
||||
use crate::{
|
||||
strutil::TString,
|
||||
ui::{
|
||||
component::{text::TextStyle, Child, Component, Event, EventCtx, Label, Never, Pad},
|
||||
component::{text::TextStyle, Component, Event, EventCtx, Label, Never, Pad},
|
||||
constant::screen,
|
||||
display::{self, Color, Font, Icon},
|
||||
geometry::{Alignment2D, Insets, Offset, Point, Rect},
|
||||
@ -117,8 +117,8 @@ pub struct ResultScreen<'a> {
|
||||
footer_pad: Pad,
|
||||
style: &'a ResultStyle,
|
||||
icon: Icon,
|
||||
message: Child<Label<'a>>,
|
||||
footer: Child<ResultFooter<'a>>,
|
||||
message: Label<'a>,
|
||||
footer: ResultFooter<'a>,
|
||||
}
|
||||
|
||||
impl<'a> ResultScreen<'a> {
|
||||
@ -134,8 +134,8 @@ impl<'a> ResultScreen<'a> {
|
||||
footer_pad: Pad::with_background(style.bg_color),
|
||||
style,
|
||||
icon,
|
||||
message: Child::new(Label::centered(message, style.message_style())),
|
||||
footer: Child::new(ResultFooter::new(footer, style)),
|
||||
message: Label::centered(message, style.message_style()),
|
||||
footer: ResultFooter::new(footer, style),
|
||||
};
|
||||
|
||||
if complete_draw {
|
||||
|
Loading…
Reference in New Issue
Block a user