refactor(core/rust): model-agnostic Paginated

[no changelog]
pull/2116/head
Martin Milata 2 years ago committed by matejcik
parent c236dfc814
commit 7f224ab36d

@ -5,6 +5,7 @@ pub mod empty;
pub mod label;
pub mod map;
pub mod pad;
pub mod paginated;
pub mod text;
pub mod tuple;
@ -12,6 +13,7 @@ pub use base::{Child, Component, ComponentExt, Event, EventCtx, Never, TimerToke
pub use empty::Empty;
pub use label::{Label, LabelStyle};
pub use pad::Pad;
pub use paginated::{Paginate, Paginated};
pub use text::{
formatted::FormattedText,
layout::{LineBreaking, PageBreaking, TextLayout},

@ -3,48 +3,61 @@ use crate::ui::{
text::layout::{LayoutFit, TextNoOp},
Component, ComponentExt, Event, EventCtx, FormattedText, Pad,
},
display,
display::Color,
geometry::Rect,
};
use super::{
page::{Page, PageMsg},
theme,
};
pub trait Page {
type Content;
fn new(area: Rect, page: Self::Content, page_count: usize, active_page: usize) -> Self;
fn inner_mut(&mut self) -> &mut Self::Content;
fn page_count(&self) -> usize;
fn active_page(&self) -> usize;
fn fade_after_next_paint(&mut self);
}
pub struct Paginated<T> {
page: Page<T>,
pub enum PageMsg<T> {
Content(T),
ChangePage(usize),
}
pub struct Paginated<P> {
page: P,
pad: Pad,
fade_after_next_paint: Option<i32>,
}
impl<T> Paginated<T>
impl<P> Paginated<P>
where
T: Paginate,
P: Page,
P::Content: Paginate,
{
pub fn new(area: Rect, mut content: T) -> Self {
pub fn new(area: Rect, content: impl FnOnce(Rect) -> P::Content, background: Color) -> Self {
let active_page = 0;
let mut content = content(area);
let page_count = content.page_count();
Self {
page: Page::new(area, content, page_count, active_page),
pad: Pad::with_background(area, theme::BG),
fade_after_next_paint: None,
page: P::new(area, content, page_count, active_page),
pad: Pad::with_background(area, background),
}
}
}
impl<T> Component for Paginated<T>
impl<P> Component for Paginated<P>
where
T: Paginate,
T: Component,
P: Page,
P: Component<Msg = PageMsg<<<P as Page>::Content as Component>::Msg>>,
P::Content: Paginate,
P::Content: Component,
{
type Msg = T::Msg;
type Msg = <<P as Page>::Content as Component>::Msg;
fn event(&mut self, ctx: &mut EventCtx, event: Event) -> Option<Self::Msg> {
self.page.event(ctx, event).and_then(|msg| match msg {
PageMsg::Content(c) => Some(c),
PageMsg::ChangePage(page) => {
self.fade_after_next_paint = Some(theme::BACKLIGHT_NORMAL);
self.page.fade_after_next_paint();
self.page.inner_mut().change_page(page);
self.page.inner_mut().request_complete_repaint(ctx);
self.pad.clear();
@ -56,16 +69,14 @@ where
fn paint(&mut self) {
self.pad.paint();
self.page.paint();
if let Some(val) = self.fade_after_next_paint.take() {
display::fade_backlight(val);
}
}
}
#[cfg(feature = "ui_debug")]
impl<T> crate::trace::Trace for Paginated<T>
impl<P> crate::trace::Trace for Paginated<P>
where
T: crate::trace::Trace,
P: Page + crate::trace::Trace,
P::Content: crate::trace::Trace,
{
fn trace(&self, t: &mut dyn crate::trace::Tracer) {
self.page.trace(t);

@ -3,7 +3,6 @@ mod confirm;
mod dialog;
mod loader;
mod page;
mod paginated;
mod passphrase;
mod pin;
mod swipe;
@ -12,7 +11,7 @@ pub use button::{Button, ButtonContent, ButtonMsg, ButtonStyle, ButtonStyleSheet
pub use confirm::{HoldToConfirm, HoldToConfirmMsg};
pub use dialog::{Dialog, DialogLayout, DialogMsg};
pub use loader::{Loader, LoaderMsg, LoaderStyle, LoaderStyleSheet};
pub use paginated::{Paginate, Paginated};
pub use page::SwipePage;
pub use swipe::{Swipe, SwipeDirection};
use super::{event, theme};

@ -1,24 +1,32 @@
use crate::ui::{
component::{Component, Event, EventCtx, Never},
component::{
paginated::{Page, PageMsg},
Component, Event, EventCtx, Never,
},
display,
geometry::{Offset, Point, Rect},
};
use super::{theme, Swipe, SwipeDirection};
pub enum PageMsg<T> {
Content(T),
ChangePage(usize),
}
pub struct Page<T> {
pub struct SwipePage<T> {
swipe: Swipe,
scrollbar: ScrollBar,
page: T,
fade: Option<i32>,
}
impl<T> Page<T> {
pub fn new(area: Rect, page: T, page_count: usize, active_page: usize) -> Self {
impl<T> SwipePage<T> {
fn setup_swipe(scrollbar: &ScrollBar, swipe: &mut Swipe) {
swipe.allow_up = scrollbar.has_next_page();
swipe.allow_down = scrollbar.has_previous_page();
}
}
impl<T> Page for SwipePage<T> {
type Content = T;
fn new(area: Rect, page: T, page_count: usize, active_page: usize) -> Self {
let scrollbar = ScrollBar::vertical_right(area, page_count, active_page);
let mut swipe = Swipe::new(area);
Self::setup_swipe(&scrollbar, &mut swipe);
@ -26,28 +34,28 @@ impl<T> Page<T> {
swipe,
scrollbar,
page,
fade: None,
}
}
fn setup_swipe(scrollbar: &ScrollBar, swipe: &mut Swipe) {
swipe.allow_up = scrollbar.has_next_page();
swipe.allow_down = scrollbar.has_previous_page();
}
pub fn inner_mut(&mut self) -> &mut T {
fn inner_mut(&mut self) -> &mut T {
&mut self.page
}
pub fn page_count(&self) -> usize {
fn page_count(&self) -> usize {
self.scrollbar.page_count
}
pub fn active_page(&self) -> usize {
fn active_page(&self) -> usize {
self.scrollbar.active_page
}
fn fade_after_next_paint(&mut self) {
self.fade = Some(theme::BACKLIGHT_NORMAL);
}
}
impl<T: Component> Component for Page<T> {
impl<T: Component> Component for SwipePage<T> {
type Msg = PageMsg<T::Msg>;
fn event(&mut self, ctx: &mut EventCtx, event: Event) -> Option<Self::Msg> {
@ -79,16 +87,19 @@ impl<T: Component> Component for Page<T> {
fn paint(&mut self) {
self.page.paint();
self.scrollbar.paint();
if let Some(val) = self.fade.take() {
display::fade_backlight(val);
}
}
}
#[cfg(feature = "ui_debug")]
impl<T> crate::trace::Trace for Page<T>
impl<T> crate::trace::Trace for SwipePage<T>
where
T: crate::trace::Trace,
{
fn trace(&self, t: &mut dyn crate::trace::Tracer) {
t.open("Page");
t.open("SwipePage");
t.field("active_page", &self.active_page());
t.field("page_count", &self.page_count());
t.field("content", &self.page);

Loading…
Cancel
Save