use wrap_render::WrapRender;
use crate::prelude::*;
#[derive(Default, Clone)]
pub struct ClipBoundary {
pub clip_boundary: bool,
}
impl Declare for ClipBoundary {
type Builder = FatObj<()>;
#[inline]
fn declarer() -> Self::Builder { FatObj::new(()) }
}
impl_compose_child_for_wrap_render!(ClipBoundary);
impl WrapRender for ClipBoundary {
fn perform_layout(&self, clamp: BoxClamp, host: &dyn Render, ctx: &mut LayoutCtx) -> Size {
host.perform_layout(clamp, ctx)
}
fn size_affected_by_child(&self, host: &dyn Render) -> bool { host.size_affected_by_child() }
fn paint(&self, host: &dyn Render, ctx: &mut PaintingCtx) {
if self.clip_boundary {
let rect = Rect::from_size(
ctx
.box_size()
.expect("impossible without size in painting stage"),
);
let path = if let Some(radius) = Provider::of::<Radius>(ctx) {
Path::rect_round(&rect, &radius)
} else {
Path::rect(&rect)
};
ctx.box_painter().clip(path.into());
}
host.paint(ctx)
}
fn visual_box(&self, _: &dyn Render, ctx: &mut VisualCtx) -> Option<Rect> {
let clip_rect = Rect::from_size(ctx.box_size()?);
ctx.clip(clip_rect);
Some(clip_rect)
}
fn hit_test(&self, host: &dyn Render, ctx: &mut HitTestCtx, pos: Point) -> HitTest {
let mut hit = host.hit_test(ctx, pos);
hit.can_hit_child &= ctx.box_hit_test(pos);
hit
}
#[inline]
fn wrapper_dirty_phase(&self) -> DirtyPhase { DirtyPhase::Layout }
}
#[cfg(test)]
mod tests {
use ribir_dev_helper::*;
use super::*;
use crate::{reset_test_env, test_helper::*};
#[test]
#[cfg(not(target_arch = "wasm32"))]
fn clip_boundary() {
reset_test_env!();
let size = Size::new(40., 40.);
assert_widget_eq_image!(
WidgetTester::new(fn_widget! {
@MockBox {
clip_boundary: true,
radius: Radius::all(20.),
size: size,
@MockBox {
background: Color::GRAY,
size: size,
}
}
})
.with_wnd_size(size)
.with_comparison(0.00015),
"clip_boundary"
);
}
}