zng_wgt_checkerboard/
lib.rs
1#![doc(html_favicon_url = "https://raw.githubusercontent.com/zng-ui/zng/main/examples/image/res/zng-logo-icon.png")]
2#![doc(html_logo_url = "https://raw.githubusercontent.com/zng-ui/zng/main/examples/image/res/zng-logo.png")]
3#![doc = include_str!(concat!("../", std::env!("CARGO_PKG_README")))]
9#![warn(unused_extern_crates)]
10#![warn(missing_docs)]
11
12use std::ops;
13
14use zng_color::COLOR_SCHEME_VAR;
15use zng_wgt::prelude::{
16 gradient::{RenderExtendMode, RenderGradientStop},
17 *,
18};
19
20#[widget($crate::Checkerboard)]
24pub struct Checkerboard(WidgetBase);
25impl Checkerboard {
26 fn widget_intrinsic(&mut self) {
27 self.widget_builder().push_build_action(|wgt| wgt.set_child(self::node()));
28 }
29}
30
31#[derive(Debug, Clone, PartialEq, Hash, serde::Serialize, serde::Deserialize)]
35pub struct Colors(pub [LightDark; 2]);
36impl ops::Deref for Colors {
37 type Target = [LightDark; 2];
38
39 fn deref(&self) -> &Self::Target {
40 &self.0
41 }
42}
43impl_from_and_into_var! {
44 fn from<C: Into<LightDark>>([c0, c1]: [C; 2]) -> Colors {
45 Colors([c0.into(), c1.into()])
46 }
47 fn from<C0: Into<LightDark>, C1: Into<LightDark>>((c0, c1): (C0, C1)) -> Colors {
48 Colors([c0.into(), c1.into()])
49 }
50}
51
52context_var! {
53 pub static COLORS_VAR: Colors = [
55 light_dark(rgb(202, 202, 204), rgb(20, 20, 20)),
56 light_dark(rgb(253, 253, 253), rgb(40, 40, 40)),
57 ];
58
59 pub static ORIGIN_VAR: Point = Point::zero();
63
64 pub static SIZE_VAR: Size = 10;
68}
69
70#[property(CONTEXT, default(COLORS_VAR), widget_impl(Checkerboard))]
77pub fn colors(child: impl UiNode, colors: impl IntoVar<Colors>) -> impl UiNode {
78 with_context_var(child, COLORS_VAR, colors)
79}
80
81#[property(CONTEXT, default(SIZE_VAR), widget_impl(Checkerboard))]
85pub fn cb_size(child: impl UiNode, size: impl IntoVar<Size>) -> impl UiNode {
86 with_context_var(child, SIZE_VAR, size)
87}
88
89#[property(CONTEXT, default(ORIGIN_VAR), widget_impl(Checkerboard))]
95pub fn cb_origin(child: impl UiNode, offset: impl IntoVar<Point>) -> impl UiNode {
96 with_context_var(child, ORIGIN_VAR, offset)
97}
98
99pub fn node() -> impl UiNode {
103 let mut render_size = PxSize::zero();
104 let mut tile_origin = PxPoint::zero();
105 let mut tile_size = PxSize::zero();
106
107 match_node_leaf(move |op| match op {
108 UiNodeOp::Init => {
109 WIDGET
110 .sub_var_render(&COLORS_VAR)
111 .sub_var_render(&COLOR_SCHEME_VAR)
112 .sub_var_layout(&SIZE_VAR)
113 .sub_var_layout(&ORIGIN_VAR);
114 }
115 UiNodeOp::Measure { desired_size, .. } => {
116 *desired_size = LAYOUT.constraints().fill_size();
117 }
118 UiNodeOp::Layout { final_size, .. } => {
119 *final_size = LAYOUT.constraints().fill_size();
120 if *final_size != render_size {
121 render_size = *final_size;
122 WIDGET.render();
123 }
124
125 let mut ts = SIZE_VAR.layout_dft(PxSize::splat(Px(4)));
126 let to = LAYOUT.with_constraints(PxConstraints2d::new_exact_size(ts), || ORIGIN_VAR.layout());
127
128 ts *= 2.fct();
130
131 if tile_origin != to || tile_size != ts {
132 tile_origin = to;
133 tile_size = ts;
134
135 WIDGET.render();
136 }
137 }
138 UiNodeOp::Render { frame } => {
139 let [c0, c1] = COLORS_VAR.get().0;
140 let sch = COLOR_SCHEME_VAR.get();
141 let colors = [c0[sch], c1[sch]];
142
143 frame.push_conic_gradient(
144 PxRect::from_size(render_size),
145 tile_size.to_vector().to_point() / 2.fct(),
146 0.rad(),
147 &[
148 RenderGradientStop {
149 color: colors[0],
150 offset: 0.0,
151 },
152 RenderGradientStop {
153 color: colors[0],
154 offset: 0.25,
155 },
156 RenderGradientStop {
157 color: colors[1],
158 offset: 0.25,
159 },
160 RenderGradientStop {
161 color: colors[1],
162 offset: 0.5,
163 },
164 RenderGradientStop {
165 color: colors[0],
166 offset: 0.5,
167 },
168 RenderGradientStop {
169 color: colors[0],
170 offset: 0.75,
171 },
172 RenderGradientStop {
173 color: colors[1],
174 offset: 0.75,
175 },
176 RenderGradientStop {
177 color: colors[1],
178 offset: 1.0,
179 },
180 ],
181 RenderExtendMode::Repeat,
182 tile_origin,
183 tile_size,
184 PxSize::zero(),
185 );
186 }
187 _ => {}
188 })
189}