mirror of
https://github.com/trezor/trezor-firmware.git
synced 2024-12-24 15:28:10 +00:00
refactor(core): extract non-generic code from SwipeContent
[no changelog]
This commit is contained in:
parent
df018a2af8
commit
a700ff8dff
@ -2,6 +2,7 @@ use crate::{
|
|||||||
time::{Duration, Stopwatch},
|
time::{Duration, Stopwatch},
|
||||||
ui::{
|
ui::{
|
||||||
component::{base::AttachType, Component, Event, EventCtx, SwipeDirection},
|
component::{base::AttachType, Component, Event, EventCtx, SwipeDirection},
|
||||||
|
constant::screen,
|
||||||
display::Color,
|
display::Color,
|
||||||
event::SwipeEvent,
|
event::SwipeEvent,
|
||||||
geometry::{Offset, Rect},
|
geometry::{Offset, Rect},
|
||||||
@ -15,10 +16,21 @@ use crate::{
|
|||||||
#[derive(Default, Clone)]
|
#[derive(Default, Clone)]
|
||||||
struct AttachAnimation {
|
struct AttachAnimation {
|
||||||
pub timer: Stopwatch,
|
pub timer: Stopwatch,
|
||||||
|
pub attach_type: Option<AttachType>,
|
||||||
|
pub show_attach_anim: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AttachAnimation {
|
impl AttachAnimation {
|
||||||
const DURATION_MS: u32 = 500;
|
const DURATION_MS: u32 = 500;
|
||||||
|
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
timer: Stopwatch::new_stopped(),
|
||||||
|
attach_type: None,
|
||||||
|
show_attach_anim: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn is_active(&self) -> bool {
|
pub fn is_active(&self) -> bool {
|
||||||
if animation_disabled() {
|
if animation_disabled() {
|
||||||
return false;
|
return false;
|
||||||
@ -36,7 +48,7 @@ impl AttachAnimation {
|
|||||||
self.timer.elapsed().to_millis() as f32 / 1000.0
|
self.timer.elapsed().to_millis() as f32 / 1000.0
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_offset(&self, t: f32, attach_type: Option<AttachType>) -> Offset {
|
pub fn get_offset(&self, t: f32) -> Offset {
|
||||||
let value = pareen::constant(0.0).seq_ease_in(
|
let value = pareen::constant(0.0).seq_ease_in(
|
||||||
0.0,
|
0.0,
|
||||||
easer::functions::Linear,
|
easer::functions::Linear,
|
||||||
@ -44,7 +56,7 @@ impl AttachAnimation {
|
|||||||
pareen::constant(1.0),
|
pareen::constant(1.0),
|
||||||
);
|
);
|
||||||
|
|
||||||
match attach_type {
|
match self.attach_type {
|
||||||
Some(AttachType::Initial) => {
|
Some(AttachType::Initial) => {
|
||||||
Offset::lerp(Offset::new(0, -20), Offset::zero(), value.eval(t))
|
Offset::lerp(Offset::new(0, -20), Offset::zero(), value.eval(t))
|
||||||
}
|
}
|
||||||
@ -61,14 +73,14 @@ impl AttachAnimation {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_opacity(&self, t: f32, attach_type: Option<AttachType>) -> u8 {
|
pub fn get_opacity(&self, t: f32) -> u8 {
|
||||||
let value = pareen::constant(0.0).seq_ease_in_out(
|
let value = pareen::constant(0.0).seq_ease_in_out(
|
||||||
0.0,
|
0.0,
|
||||||
easer::functions::Cubic,
|
easer::functions::Cubic,
|
||||||
0.2,
|
0.2,
|
||||||
pareen::constant(1.0),
|
pareen::constant(1.0),
|
||||||
);
|
);
|
||||||
match attach_type {
|
match self.attach_type {
|
||||||
Some(AttachType::Initial)
|
Some(AttachType::Initial)
|
||||||
| Some(AttachType::Swipe(SwipeDirection::Up))
|
| Some(AttachType::Swipe(SwipeDirection::Up))
|
||||||
| Some(AttachType::Swipe(SwipeDirection::Down)) => {}
|
| Some(AttachType::Swipe(SwipeDirection::Down)) => {}
|
||||||
@ -86,62 +98,99 @@ impl AttachAnimation {
|
|||||||
pub fn reset(&mut self) {
|
pub fn reset(&mut self) {
|
||||||
self.timer = Stopwatch::new_stopped();
|
self.timer = Stopwatch::new_stopped();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
pub struct SwipeContent<T> {
|
pub fn lazy_start(&mut self, ctx: &mut EventCtx, event: Event, animate: bool) -> bool {
|
||||||
inner: T,
|
|
||||||
bounds: Rect,
|
|
||||||
progress: i16,
|
|
||||||
dir: SwipeDirection,
|
|
||||||
attach_animation: AttachAnimation,
|
|
||||||
attach_type: Option<AttachType>,
|
|
||||||
show_attach_anim: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: Component> SwipeContent<T> {
|
|
||||||
pub fn new(inner: T) -> Self {
|
|
||||||
Self {
|
|
||||||
inner,
|
|
||||||
bounds: Rect::zero(),
|
|
||||||
progress: 0,
|
|
||||||
dir: SwipeDirection::Up,
|
|
||||||
attach_animation: AttachAnimation::default(),
|
|
||||||
attach_type: None,
|
|
||||||
show_attach_anim: true,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn with_no_attach_anim(mut self) -> Self {
|
|
||||||
self.show_attach_anim = false;
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn inner(&self) -> &T {
|
|
||||||
&self.inner
|
|
||||||
}
|
|
||||||
|
|
||||||
fn process_event(&mut self, ctx: &mut EventCtx, event: Event, animate: bool) -> Option<T::Msg> {
|
|
||||||
if let Event::Attach(attach_type) = event {
|
if let Event::Attach(attach_type) = event {
|
||||||
self.progress = 0;
|
|
||||||
if self.show_attach_anim && animate {
|
if self.show_attach_anim && animate {
|
||||||
self.attach_type = Some(attach_type);
|
self.attach_type = Some(attach_type);
|
||||||
} else {
|
} else {
|
||||||
self.attach_type = None;
|
self.attach_type = None;
|
||||||
}
|
}
|
||||||
self.attach_animation.reset();
|
self.reset();
|
||||||
ctx.request_anim_frame();
|
ctx.request_anim_frame();
|
||||||
}
|
}
|
||||||
if let Event::Timer(EventCtx::ANIM_FRAME_TIMER) = event {
|
if let Event::Timer(EventCtx::ANIM_FRAME_TIMER) = event {
|
||||||
if !animation_disabled() {
|
if !animation_disabled() {
|
||||||
if !self.attach_animation.timer.is_running() {
|
if !self.timer.is_running() {
|
||||||
self.attach_animation.timer.start();
|
self.timer.start();
|
||||||
}
|
}
|
||||||
if self.attach_animation.is_active() {
|
if self.is_active() {
|
||||||
ctx.request_anim_frame();
|
ctx.request_anim_frame();
|
||||||
ctx.request_paint();
|
ctx.request_paint();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
match event {
|
||||||
|
Event::Touch(_) => !self.is_active(),
|
||||||
|
_ => true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct SwipeContext {
|
||||||
|
progress: i16,
|
||||||
|
dir: SwipeDirection,
|
||||||
|
attach_animation: AttachAnimation,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SwipeContext {
|
||||||
|
fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
progress: 0,
|
||||||
|
dir: SwipeDirection::Up,
|
||||||
|
attach_animation: AttachAnimation::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_params(&self, bounds: Rect) -> (Offset, Rect, u8) {
|
||||||
|
let progress = self.progress as f32 / 1000.0;
|
||||||
|
|
||||||
|
let shift = pareen::constant(0.0).seq_ease_out(
|
||||||
|
0.0,
|
||||||
|
easer::functions::Cubic,
|
||||||
|
1.0,
|
||||||
|
pareen::constant(1.0),
|
||||||
|
);
|
||||||
|
|
||||||
|
let y_offset = i16::lerp(0, 50, shift.eval(progress));
|
||||||
|
|
||||||
|
let mut offset = Offset::zero();
|
||||||
|
let mut clip = bounds;
|
||||||
|
let mut mask = 0;
|
||||||
|
|
||||||
|
if self.progress > 0 {
|
||||||
|
match self.dir {
|
||||||
|
SwipeDirection::Up => {
|
||||||
|
offset = Offset::y(-y_offset);
|
||||||
|
mask = u8::lerp(0, 255, shift.eval(progress));
|
||||||
|
}
|
||||||
|
SwipeDirection::Down => {
|
||||||
|
offset = Offset::y(y_offset);
|
||||||
|
clip = screen();
|
||||||
|
mask = u8::lerp(0, 255, shift.eval(progress));
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let t = self.attach_animation.eval();
|
||||||
|
let opacity = self.attach_animation.get_opacity(t);
|
||||||
|
offset = self.attach_animation.get_offset(t);
|
||||||
|
mask = 255 - opacity;
|
||||||
|
|
||||||
|
if offset.x == 0 && offset.y == 0 {
|
||||||
|
clip = screen();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
(offset, clip, mask)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn process_event(&mut self, ctx: &mut EventCtx, event: Event, animate: bool) -> bool {
|
||||||
|
let inner_event = self.attach_animation.lazy_start(ctx, event, animate);
|
||||||
|
|
||||||
|
if let Event::Attach(_) = event {
|
||||||
|
self.progress = 0;
|
||||||
|
}
|
||||||
|
|
||||||
if let Event::Swipe(SwipeEvent::Move(dir, progress)) = event {
|
if let Event::Swipe(SwipeEvent::Move(dir, progress)) = event {
|
||||||
match dir {
|
match dir {
|
||||||
@ -156,15 +205,41 @@ impl<T: Component> SwipeContent<T> {
|
|||||||
ctx.request_paint();
|
ctx.request_paint();
|
||||||
}
|
}
|
||||||
|
|
||||||
match event {
|
inner_event
|
||||||
Event::Touch(_) => {
|
}
|
||||||
if self.attach_animation.is_active() {
|
}
|
||||||
None
|
|
||||||
} else {
|
pub struct SwipeContent<T> {
|
||||||
|
inner: T,
|
||||||
|
bounds: Rect,
|
||||||
|
swipe_context: SwipeContext,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Component> SwipeContent<T> {
|
||||||
|
pub fn new(inner: T) -> Self {
|
||||||
|
Self {
|
||||||
|
inner,
|
||||||
|
bounds: Rect::zero(),
|
||||||
|
swipe_context: SwipeContext::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_no_attach_anim(mut self) -> Self {
|
||||||
|
self.swipe_context.attach_animation.show_attach_anim = false;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn inner(&self) -> &T {
|
||||||
|
&self.inner
|
||||||
|
}
|
||||||
|
|
||||||
|
fn process_event(&mut self, ctx: &mut EventCtx, event: Event, animate: bool) -> Option<T::Msg> {
|
||||||
|
let inner_event = self.swipe_context.process_event(ctx, event, animate);
|
||||||
|
|
||||||
|
if inner_event {
|
||||||
self.inner.event(ctx, event)
|
self.inner.event(ctx, event)
|
||||||
}
|
} else {
|
||||||
}
|
None
|
||||||
_ => self.inner.event(ctx, event),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -186,24 +261,9 @@ impl<T: Component> Component for SwipeContent<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn render<'s>(&'s self, target: &mut impl Renderer<'s>) {
|
fn render<'s>(&'s self, target: &mut impl Renderer<'s>) {
|
||||||
let progress = self.progress as f32 / 1000.0;
|
let (offset, clip, mask) = self.swipe_context.get_params(self.bounds);
|
||||||
|
|
||||||
let shift = pareen::constant(0.0).seq_ease_out(
|
target.in_clip(clip, &|target| {
|
||||||
0.0,
|
|
||||||
easer::functions::Cubic,
|
|
||||||
1.0,
|
|
||||||
pareen::constant(1.0),
|
|
||||||
);
|
|
||||||
|
|
||||||
let offset = i16::lerp(0, 50, shift.eval(progress));
|
|
||||||
|
|
||||||
let mask = u8::lerp(0, 255, shift.eval(progress));
|
|
||||||
|
|
||||||
if self.progress > 0 {
|
|
||||||
match self.dir {
|
|
||||||
SwipeDirection::Up => {
|
|
||||||
let offset = Offset::y(-offset);
|
|
||||||
target.in_clip(self.bounds, &|target| {
|
|
||||||
target.with_origin(offset, &|target| {
|
target.with_origin(offset, &|target| {
|
||||||
self.inner.render(target);
|
self.inner.render(target);
|
||||||
shape::Bar::new(self.bounds)
|
shape::Bar::new(self.bounds)
|
||||||
@ -214,47 +274,6 @@ impl<T: Component> Component for SwipeContent<T> {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
SwipeDirection::Down => {
|
|
||||||
let offset = Offset::y(offset);
|
|
||||||
target.with_origin(offset, &|target| {
|
|
||||||
self.inner.render(target);
|
|
||||||
shape::Bar::new(self.bounds)
|
|
||||||
.with_alpha(mask)
|
|
||||||
.with_fg(Color::black())
|
|
||||||
.with_bg(Color::black())
|
|
||||||
.render(target);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
let t = self.attach_animation.eval();
|
|
||||||
let offset = self.attach_animation.get_offset(t, self.attach_type);
|
|
||||||
let opacity = self.attach_animation.get_opacity(t, self.attach_type);
|
|
||||||
|
|
||||||
if offset.x != 0 || offset.y != 0 {
|
|
||||||
target.in_clip(self.bounds, &|target| {
|
|
||||||
target.with_origin(offset, &|target| {
|
|
||||||
self.inner.render(target);
|
|
||||||
shape::Bar::new(self.bounds)
|
|
||||||
.with_alpha(255 - opacity)
|
|
||||||
.with_fg(Color::black())
|
|
||||||
.with_bg(Color::black())
|
|
||||||
.render(target);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
// some components draw outside their bounds during animations
|
|
||||||
// let them do that unless we are animating here
|
|
||||||
self.inner.render(target);
|
|
||||||
shape::Bar::new(self.bounds)
|
|
||||||
.with_alpha(255 - opacity)
|
|
||||||
.with_fg(Color::black())
|
|
||||||
.with_bg(Color::black())
|
|
||||||
.render(target);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "ui_debug")]
|
#[cfg(feature = "ui_debug")]
|
||||||
@ -305,7 +324,7 @@ where
|
|||||||
let is_swipe_up = matches!(attach_type, AttachType::Swipe(SwipeDirection::Up));
|
let is_swipe_up = matches!(attach_type, AttachType::Swipe(SwipeDirection::Up));
|
||||||
let is_swipe_down = matches!(attach_type, AttachType::Swipe(SwipeDirection::Down));
|
let is_swipe_down = matches!(attach_type, AttachType::Swipe(SwipeDirection::Down));
|
||||||
|
|
||||||
if !self.content.show_attach_anim {
|
if !self.content.swipe_context.attach_animation.show_attach_anim {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user