feat(core/rust): special shape erase button

[no changelog]
pull/2569/head
tychovrahe 1 year ago committed by TychoVrahe
parent f1a3f289bf
commit 38548f02f2

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

@ -79,7 +79,6 @@ impl BlendedImage {
}
}
#[cfg(feature = "dma2d")]
fn paint_image(&self) {
display::icon_over_icon(
None,
@ -88,17 +87,6 @@ impl BlendedImage {
self.area_color,
);
}
#[cfg(not(feature = "dma2d"))]
fn paint_image(&self) {
display::icon_top_left(self.bg_top_left, self.bg, self.bg_color, self.area_color);
display::icon_top_left(
self.bg_top_left + self.fg_offset,
self.fg,
self.fg_color,
self.bg_color,
);
}
}
impl Component for BlendedImage {

@ -748,6 +748,27 @@ pub fn icon_over_icon(
dma2d_wait_for_transfer();
}
#[cfg(not(feature = "dma2d"))]
pub fn icon_over_icon(
bg_area: Option<Rect>,
bg: (&[u8], Offset, Color),
fg: (&[u8], Offset, Color),
bg_color: Color,
) {
let (data_bg, offset_bg, color_icon_bg) = bg;
let (data_fg, offset_fg, color_icon_fg) = fg;
let pos_bg = if let Some(area) = bg_area {
rect_fill(area, bg_color);
area.top_left() + offset_bg
} else {
Point::from(offset_bg)
};
icon_top_left(pos_bg, data_bg, color_icon_bg, bg_color);
icon_top_left(pos_bg + offset_fg, data_fg, color_icon_fg, color_icon_bg);
}
/// Gets a color of a pixel on `p` coordinates of rounded rectangle with corner
/// radius 2
fn rect_rounded2_get_pixel(

@ -6,7 +6,6 @@ use crate::{
Child, Component, ComponentExt, Event, EventCtx, Label, Pad,
},
constant::screen,
display::Font,
geometry::{Alignment, Insets, LinearPlacement, Point, Rect},
model_tr::{
component::{Button, ButtonMsg, ButtonPos, ResultAnim, ResultAnimMsg},

@ -52,6 +52,10 @@ impl<T> Button<T> {
Self::new(ButtonContent::Icon(image))
}
pub fn with_icon_blend(bg: &'static [u8], fg: &'static [u8], fg_offset: Offset) -> Self {
Self::new(ButtonContent::IconBlend(bg, fg, fg_offset))
}
pub fn empty() -> Self {
Self::new(ButtonContent::Empty)
}
@ -141,29 +145,34 @@ impl<T> Button<T> {
}
pub fn paint_background(&self, style: &ButtonStyle) {
if style.border_width > 0 {
// Paint the border and a smaller background on top of it.
display::rect_fill_rounded(
self.area,
style.border_color,
style.background_color,
style.border_radius,
);
display::rect_fill_rounded(
self.area.inset(Insets::uniform(style.border_width)),
style.button_color,
style.border_color,
style.border_radius,
);
} else {
// We do not need to draw an explicit border in this case, just a
// bigger background.
display::rect_fill_rounded(
self.area,
style.button_color,
style.background_color,
style.border_radius,
);
match &self.content {
ButtonContent::IconBlend(_, _, _) => {}
_ => {
if style.border_width > 0 {
// Paint the border and a smaller background on top of it.
display::rect_fill_rounded(
self.area,
style.border_color,
style.background_color,
style.border_radius,
);
display::rect_fill_rounded(
self.area.inset(Insets::uniform(style.border_width)),
style.button_color,
style.border_color,
style.border_radius,
);
} else {
// We do not need to draw an explicit border in this case, just a
// bigger background.
display::rect_fill_rounded(
self.area,
style.button_color,
style.background_color,
style.border_radius,
);
}
}
}
}
@ -196,6 +205,12 @@ impl<T> Button<T> {
style.button_color,
);
}
ButtonContent::IconBlend(bg, fg, offset) => display::icon_over_icon(
Some(self.area),
(bg, Offset::zero(), style.button_color),
(fg, *offset, style.text_color),
style.background_color,
),
}
}
}
@ -300,6 +315,7 @@ where
ButtonContent::Empty => {}
ButtonContent::Text(text) => t.field("text", text),
ButtonContent::Icon(_) => t.symbol("icon"),
ButtonContent::IconBlend(_, _, _) => t.symbol("icon"),
}
t.close();
}
@ -318,6 +334,7 @@ pub enum ButtonContent<T> {
Empty,
Text(T),
Icon(&'static [u8]),
IconBlend(&'static [u8], &'static [u8], Offset),
}
#[derive(PartialEq, Eq)]

@ -2,7 +2,7 @@ use core::ops::Deref;
use crate::ui::{
component::{maybe::paint_overlapping, Child, Component, Event, EventCtx, Label, Maybe},
geometry::{Alignment, Grid, Rect},
geometry::{Alignment, Grid, Offset, Rect},
model_tt::{
component::{Button, ButtonMsg},
theme,
@ -39,7 +39,12 @@ where
)),
back: Child::new(Maybe::hidden(
theme::BG,
Button::with_icon(theme::ICON_BACK).styled(theme::button_clear()),
Button::with_icon_blend(
theme::IMAGE_BG_BACK_BTN_TALL,
theme::ICON_BACK,
Offset::new(30, 17),
)
.styled(theme::button_clear()),
)),
input: Child::new(Maybe::hidden(theme::BG, input)),
keys: T::keys().map(Button::with_text).map(Child::new),

@ -4,7 +4,10 @@ use crate::ui::{
geometry::{Grid, Insets, Offset, Rect},
model_tt::component::{
button::{Button, ButtonContent, ButtonMsg::Clicked},
keyboard::common::{paint_pending_marker, MultiTapKeyboard, TextBox, HEADER_PADDING_SIDE},
keyboard::common::{
paint_pending_marker, MultiTapKeyboard, TextBox, HEADER_HEIGHT, HEADER_PADDING_BOTTOM,
HEADER_PADDING_SIDE,
},
swipe::{Swipe, SwipeDirection},
theme, ScrollBar,
},
@ -46,10 +49,14 @@ impl PassphraseKeyboard {
confirm: Button::with_icon(theme::ICON_CONFIRM)
.styled(theme::button_confirm())
.into_child(),
back: Button::with_icon(theme::ICON_BACK)
.styled(theme::button_reset())
.initially_enabled(false)
.into_child(),
back: Button::with_icon_blend(
theme::IMAGE_BG_BACK_BTN,
theme::ICON_BACK,
Offset::new(30, 12),
)
.styled(theme::button_reset())
.initially_enabled(false)
.into_child(),
keys: KEYBOARD.map(|page| {
page.map(|text| {
if text == " " {
@ -70,6 +77,7 @@ impl PassphraseKeyboard {
ButtonContent::Text(text) => text,
ButtonContent::Icon(_) => " ",
ButtonContent::Empty => "",
ButtonContent::IconBlend(_, _, _) => "",
}
}
@ -135,17 +143,16 @@ impl Component for PassphraseKeyboard {
fn place(&mut self, bounds: Rect) -> Rect {
let bounds = bounds.inset(theme::borders());
let input_area = Grid::new(bounds, 5, 1)
.with_spacing(theme::KEYBOARD_SPACING)
.row_col(0, 0);
let (input_area, key_grid_area) = bounds.split_top(HEADER_HEIGHT + HEADER_PADDING_BOTTOM);
let (input_area, scroll_area) = input_area.split_bottom(ScrollBar::DOT_SIZE);
let input_area =
input_area.inset(Insets::new(0, HEADER_PADDING_SIDE, 2, HEADER_PADDING_SIDE));
let (input_area, scroll_area) =
input_area.split_bottom(ScrollBar::DOT_SIZE + theme::KEYBOARD_SPACING);
let (scroll_area, _) = scroll_area.split_top(ScrollBar::DOT_SIZE);
let input_area = input_area.inset(Insets::sides(HEADER_PADDING_SIDE));
let key_grid = Grid::new(bounds, 5, 3).with_spacing(theme::KEYBOARD_SPACING);
let confirm_btn_area = key_grid.cell(14);
let back_btn_area = key_grid.cell(12);
let key_grid = Grid::new(key_grid_area, 4, 3).with_spacing(theme::KEYBOARD_SPACING);
let confirm_btn_area = key_grid.cell(11);
let back_btn_area = key_grid.cell(9);
self.page_swipe.place(bounds);
self.input.place(input_area);
@ -162,10 +169,10 @@ impl Component for PassphraseKeyboard {
// from the second row.
let area = key_grid.cell(if key < 9 {
// The grid has 3 columns, and we skip the first row.
key + 3
key
} else {
// For the last key (the "0" position) we skip one cell.
key + 1 + 3
key + 1
});
btn.place(area);
}
@ -280,10 +287,11 @@ impl Component for Input {
}
fn paint(&mut self) {
const TEXT_OFFSET: Offset = Offset::y(8);
let style = theme::label_default();
let mut text_baseline = self.area.bottom_left() - TEXT_OFFSET;
let mut text_baseline = self.area.top_left() + Offset::y(style.text_font.text_height())
- Offset::y(style.text_font.text_baseline());
let text = self.textbox.content();
// Preparing the new text to be displayed.

@ -70,10 +70,14 @@ where
allow_cancel: bool,
) -> Self {
// Control buttons.
let erase_btn = Button::with_icon(theme::ICON_BACK)
.styled(theme::button_reset())
.with_long_press(ERASE_HOLD_DURATION)
.initially_enabled(false);
let erase_btn = Button::with_icon_blend(
theme::IMAGE_BG_BACK_BTN,
theme::ICON_BACK,
Offset::new(30, 12),
)
.styled(theme::button_reset())
.with_long_press(ERASE_HOLD_DURATION)
.initially_enabled(false);
let erase_btn = Maybe::hidden(theme::BG, erase_btn).into_child();
let cancel_btn = Button::with_icon(theme::ICON_CANCEL).styled(theme::button_cancel());

@ -65,6 +65,8 @@ pub const IMAGE_FG_ERROR: &[u8] = include_res!("model_tt/res/error_fg.toif");
pub const IMAGE_FG_INFO: &[u8] = include_res!("model_tt/res/info_fg.toif");
pub const IMAGE_BG_CIRCLE: &[u8] = include_res!("model_tt/res/circle.toif");
pub const IMAGE_BG_TRIANGLE: &[u8] = include_res!("model_tt/res/triangle.toif");
pub const IMAGE_BG_BACK_BTN: &[u8] = include_res!("model_tt/res/back_btn.toif");
pub const IMAGE_BG_BACK_BTN_TALL: &[u8] = include_res!("model_tt/res/back_btn_tall.toif");
// Scrollbar/PIN dots.
pub const DOT_ACTIVE: &[u8] = include_res!("model_tt/res/scroll-active.toif");
@ -229,7 +231,7 @@ pub fn button_reset() -> ButtonStyleSheet {
},
disabled: &ButtonStyle {
font: Font::BOLD,
text_color: GREY_LIGHT,
text_color: FG,
button_color: YELLOW,
background_color: BG,
border_color: BG,

@ -1646,10 +1646,10 @@
"TT_test_session_id_and_passphrase.py::test_multiple_passphrases": "7f73c410413a655054ab7fcc95d9da528bd082a89cda3ee981c4c48b566e6660",
"TT_test_session_id_and_passphrase.py::test_multiple_sessions": "f03b50df7f4a161078fa903c44f37272961b70358d4014d30a12888e1fd2caf1",
"TT_test_session_id_and_passphrase.py::test_passphrase_ack_mismatch": "95a40f79fa7ffceb10e89b513c203b4937112b8d764cdba3c1df538355dc129c",
"TT_test_session_id_and_passphrase.py::test_passphrase_always_on_device": "ea3049463b15861f70fab2d4a56fc5efd75b6e6464b9f81e19478e9f8ef48f8e",
"TT_test_session_id_and_passphrase.py::test_passphrase_always_on_device": "d2302e826a90ac2aaec7f7bcf9794fe1ffa077f04d9566ce4edbd53975caee16",
"TT_test_session_id_and_passphrase.py::test_passphrase_length": "928b70f715015cb291bcd9890190dc53a4a31a7965d7b7eadfa5ec2e7a3a47a1",
"TT_test_session_id_and_passphrase.py::test_passphrase_missing": "95a40f79fa7ffceb10e89b513c203b4937112b8d764cdba3c1df538355dc129c",
"TT_test_session_id_and_passphrase.py::test_passphrase_on_device": "9e9111f802d024580996acb984e520d68b0b61efaec50173f8755770586fd7bd",
"TT_test_session_id_and_passphrase.py::test_passphrase_on_device": "3425b0aa0fb34c5fb40dadd63533701ba93b752b9218d8cce72cc9c9e24c0236",
"TT_test_session_id_and_passphrase.py::test_session_enable_passphrase": "9c96dc98e60e7b3a16d7f328f92a001e8c6727902e6912100fc45b3dabee612c",
"TT_test_session_id_and_passphrase.py::test_session_with_passphrase": "a7046b2ffe82d6b5194ad34d17d0fa2e16bfa29ab8df798dc38d2b40de01c434",
"TT_tezos-test_getaddress.py::test_tezos_get_address": "d5c6a3fcb7bf58d62be0eb6d3d51fa17ebeadfb8ec3359f11e5b3771bb33e4f4",

Loading…
Cancel
Save