You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
201 lines
5.3 KiB
201 lines
5.3 KiB
use core::mem;
|
|
|
|
use crate::{
|
|
strutil::StringType,
|
|
translations::TR,
|
|
ui::{
|
|
component::{
|
|
base::Never,
|
|
text::util::{
|
|
text_multiline, text_multiline2, text_multiline_bottom, text_multiline_bottom2,
|
|
},
|
|
Component, Event, EventCtx,
|
|
},
|
|
display::{self, Font},
|
|
geometry::{Alignment, Insets, Offset, Rect},
|
|
model_tr::cshape,
|
|
shape,
|
|
shape::Renderer,
|
|
util::animation_disabled,
|
|
},
|
|
};
|
|
|
|
use super::theme;
|
|
|
|
const FOOTER_TEXT_MARGIN: i16 = 8;
|
|
const LOADER_OFFSET: i16 = -15;
|
|
const LOADER_SPEED: u16 = 10;
|
|
|
|
pub struct CoinJoinProgress<T> {
|
|
value: u16,
|
|
loader_y_offset: i16,
|
|
text: T,
|
|
area: Rect,
|
|
indeterminate: bool,
|
|
}
|
|
|
|
impl<T> CoinJoinProgress<T>
|
|
where
|
|
T: StringType,
|
|
{
|
|
pub fn new(text: T, indeterminate: bool) -> Self {
|
|
Self {
|
|
value: 0,
|
|
loader_y_offset: LOADER_OFFSET,
|
|
text,
|
|
area: Rect::zero(),
|
|
indeterminate,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl<T> Component for CoinJoinProgress<T>
|
|
where
|
|
T: StringType,
|
|
{
|
|
type Msg = Never;
|
|
|
|
fn place(&mut self, bounds: Rect) -> Rect {
|
|
self.area = bounds;
|
|
bounds
|
|
}
|
|
|
|
fn event(&mut self, ctx: &mut EventCtx, event: Event) -> Option<Self::Msg> {
|
|
if animation_disabled() {
|
|
return None;
|
|
}
|
|
|
|
// Indeterminate needs to request frames to animate.
|
|
// Determinate ones are receiving Event::Progress events.
|
|
if self.indeterminate {
|
|
match event {
|
|
Event::Attach => {
|
|
ctx.request_anim_frame();
|
|
}
|
|
Event::Timer(EventCtx::ANIM_FRAME_TIMER) => {
|
|
self.value = (self.value + LOADER_SPEED) % 1000;
|
|
ctx.request_anim_frame();
|
|
ctx.request_paint();
|
|
}
|
|
_ => {}
|
|
}
|
|
} else if let Event::Progress(new_value, _new_description) = event {
|
|
if mem::replace(&mut self.value, new_value) != new_value {
|
|
ctx.request_paint();
|
|
}
|
|
}
|
|
|
|
None
|
|
}
|
|
|
|
fn paint(&mut self) {
|
|
// TOP
|
|
if self.indeterminate {
|
|
text_multiline(
|
|
self.area,
|
|
TR::coinjoin__title_progress.into(),
|
|
Font::BOLD,
|
|
theme::FG,
|
|
theme::BG,
|
|
Alignment::Center,
|
|
);
|
|
display::loader::loader_small_indeterminate(
|
|
self.value,
|
|
self.loader_y_offset,
|
|
theme::FG,
|
|
theme::BG,
|
|
);
|
|
} else {
|
|
display::loader(
|
|
self.value,
|
|
self.loader_y_offset,
|
|
theme::FG,
|
|
theme::BG,
|
|
Some((theme::ICON_TICK_FAT, theme::FG)),
|
|
);
|
|
}
|
|
|
|
// BOTTOM
|
|
let top_rest = text_multiline_bottom(
|
|
self.area,
|
|
TR::coinjoin__do_not_disconnect.into(),
|
|
Font::BOLD,
|
|
theme::FG,
|
|
theme::BG,
|
|
Alignment::Center,
|
|
);
|
|
if let Some(rest) = top_rest {
|
|
text_multiline_bottom(
|
|
rest.inset(Insets::bottom(FOOTER_TEXT_MARGIN)),
|
|
self.text.as_ref().into(),
|
|
Font::NORMAL,
|
|
theme::FG,
|
|
theme::BG,
|
|
Alignment::Center,
|
|
);
|
|
}
|
|
}
|
|
|
|
fn render<'s>(&'s self, target: &mut impl Renderer<'s>) {
|
|
// TOP
|
|
let center = self.area.center() + Offset::y(self.loader_y_offset);
|
|
|
|
if self.indeterminate {
|
|
text_multiline2(
|
|
target,
|
|
self.area,
|
|
TR::coinjoin__title_progress.into(),
|
|
Font::BOLD,
|
|
theme::FG,
|
|
theme::BG,
|
|
Alignment::Center,
|
|
);
|
|
cshape::LoaderSmall::new(center, self.value)
|
|
.with_color(theme::FG)
|
|
.render(target);
|
|
} else {
|
|
cshape::LoaderCircular::new(center, self.value)
|
|
.with_color(theme::FG)
|
|
.render(target);
|
|
shape::ToifImage::new(center, theme::ICON_TICK_FAT.toif)
|
|
.with_fg(theme::FG)
|
|
.render(target);
|
|
}
|
|
|
|
// BOTTOM
|
|
let top_rest = text_multiline_bottom2(
|
|
target,
|
|
self.area,
|
|
TR::coinjoin__do_not_disconnect.into(),
|
|
Font::BOLD,
|
|
theme::FG,
|
|
theme::BG,
|
|
Alignment::Center,
|
|
);
|
|
if let Some(rest) = top_rest {
|
|
text_multiline_bottom2(
|
|
target,
|
|
rest.inset(Insets::bottom(FOOTER_TEXT_MARGIN)),
|
|
self.text.as_ref().into(),
|
|
Font::NORMAL,
|
|
theme::FG,
|
|
theme::BG,
|
|
Alignment::Center,
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
#[cfg(feature = "ui_debug")]
|
|
impl<T> crate::trace::Trace for CoinJoinProgress<T>
|
|
where
|
|
T: StringType,
|
|
{
|
|
fn trace(&self, t: &mut dyn crate::trace::Tracer) {
|
|
t.component("CoinJoinProgress");
|
|
t.string("header", TR::coinjoin__title_progress.into());
|
|
t.string("text", self.text.as_ref().into());
|
|
t.string("footer", TR::coinjoin__do_not_disconnect.into());
|
|
}
|
|
}
|