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

[no changelog]
pull/2266/head
Martin Milata 2 years ago
parent 168389a7b3
commit c257a8a687

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

@ -1,6 +1,6 @@
use crate::ui::{
component::{Component, ComponentExt, Event, EventCtx, Pad},
display::Color,
display::{self, Color},
geometry::Rect,
};
@ -98,3 +98,48 @@ where
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()
}
}

@ -26,6 +26,18 @@ impl Pad {
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) {
if self.clear {
self.clear = false;

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

Loading…
Cancel
Save