1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2024-12-23 14:58:09 +00:00

fix(core/ui/rust): painting of overlapping Maybe<T> components

[no changelog]
This commit is contained in:
Martin Milata 2022-04-25 17:54:56 +02:00
parent 168389a7b3
commit c257a8a687
4 changed files with 86 additions and 6 deletions

View File

@ -4,7 +4,11 @@ use heapless::Vec;
use crate::{ use crate::{
time::Duration, time::Duration,
ui::{component::Map, geometry::Rect}, ui::{
component::{maybe::PaintOverlapping, Map},
display::Color,
geometry::Rect,
},
}; };
#[cfg(feature = "buttons")] #[cfg(feature = "buttons")]
@ -136,6 +140,22 @@ where
} }
} }
impl<T> PaintOverlapping for Child<T>
where
T: PaintOverlapping,
{
fn cleared_area(&self) -> Option<(Rect, Color)> {
self.component.cleared_area()
}
fn paint_overlapping(&mut self) {
if self.marked_for_paint {
self.marked_for_paint = false;
self.component.paint_overlapping()
}
}
}
#[cfg(feature = "ui_debug")] #[cfg(feature = "ui_debug")]
impl<T> crate::trace::Trace for Child<T> impl<T> crate::trace::Trace for Child<T>
where where
@ -167,6 +187,11 @@ where
self.0.paint(); self.0.paint();
self.1.paint(); self.1.paint();
} }
fn bounds(&self, sink: &mut dyn FnMut(Rect)) {
self.0.bounds(sink);
self.1.bounds(sink);
}
} }
#[cfg(feature = "ui_debug")] #[cfg(feature = "ui_debug")]

View File

@ -1,6 +1,6 @@
use crate::ui::{ use crate::ui::{
component::{Component, ComponentExt, Event, EventCtx, Pad}, component::{Component, ComponentExt, Event, EventCtx, Pad},
display::Color, display::{self, Color},
geometry::Rect, geometry::Rect,
}; };
@ -98,3 +98,48 @@ where
self.inner.bounds(sink); self.inner.bounds(sink);
} }
} }
pub trait PaintOverlapping {
/// Return area that would be cleared during regular paint, along with
/// background color, or None if clearing isn't requested.
fn cleared_area(&self) -> Option<(Rect, Color)>;
/// Paint the component but do not clear background beforehand.
fn paint_overlapping(&mut self);
}
impl<T> PaintOverlapping for Maybe<T>
where
T: Component,
{
fn cleared_area(&self) -> Option<(Rect, Color)> {
self.pad.will_paint()
}
fn paint_overlapping(&mut self) {
self.pad.cancel_clear();
self.paint()
}
}
/// Paint multiple Maybe<T> components, correctly handling clearing of
/// background in the case the areas overlap, i.e. clear the combined area first
/// and then paint over it.
pub fn paint_overlapping(components: &mut [&mut dyn PaintOverlapping]) {
let mut area = Rect::zero();
let mut color = Color::rgb(0, 0, 0);
for component in components.iter() {
if let Some((clear_area, clear_color)) = component.cleared_area() {
area = area.union(clear_area);
color = clear_color;
}
}
if area != Rect::zero() {
display::rect_fill(area, color)
}
for component in components.iter_mut() {
component.paint_overlapping()
}
}

View File

@ -26,6 +26,18 @@ impl Pad {
self.clear = true; self.clear = true;
} }
pub fn cancel_clear(&mut self) {
self.clear = false;
}
pub fn will_paint(&self) -> Option<(Rect, Color)> {
if self.clear {
Some((self.area, self.color))
} else {
None
}
}
pub fn paint(&mut self) { pub fn paint(&mut self) {
if self.clear { if self.clear {
self.clear = false; self.clear = false;

View File

@ -1,7 +1,7 @@
use core::ops::Deref; use core::ops::Deref;
use crate::ui::{ use crate::ui::{
component::{Child, Component, Event, EventCtx, Label, Maybe}, component::{maybe::paint_overlapping, Child, Component, Event, EventCtx, Label, Maybe},
geometry::{Alignment, Grid, Rect}, geometry::{Alignment, Grid, Rect},
model_tt::{ model_tt::{
component::{Button, ButtonMsg}, component::{Button, ButtonMsg},
@ -139,9 +139,7 @@ where
} }
fn paint(&mut self) { fn paint(&mut self) {
self.prompt.paint(); paint_overlapping(&mut [&mut self.prompt, &mut self.input, &mut self.back]);
self.input.paint();
self.back.paint();
for btn in &mut self.keys { for btn in &mut self.keys {
btn.paint(); btn.paint();
} }