zng_wgt_rule_line/
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 zng_wgt::{margin, prelude::*};
13use zng_wgt_access::{AccessRole, access_role};
14
15#[widget($crate::RuleLine)]
17pub struct RuleLine(WidgetBase);
18impl RuleLine {
19 fn widget_intrinsic(&mut self) {
20 self.widget_builder().push_build_action(on_build);
21
22 widget_set! {
23 self;
24 access_role = AccessRole::Separator;
25 }
26 }
27
28 widget_impl! {
29 pub margin(margin: impl IntoVar<SideOffsets>);
31 }
32}
33
34#[property(CONTEXT, capture, default(LineOrientation::Horizontal), widget_impl(RuleLine))]
36pub fn orientation(orientation: impl IntoVar<LineOrientation>) {}
37
38#[property(CONTEXT, capture, default(rgb(0, 0, 0)), widget_impl(RuleLine))]
40pub fn color(color: impl IntoVar<Rgba>) {}
41
42#[property(CONTEXT, capture, default(1), widget_impl(RuleLine))]
44pub fn stroke_thickness(thickness: impl IntoVar<Length>) {}
45
46#[property(CONTEXT, capture, default(Length::Default), widget_impl(RuleLine))]
52pub fn length(length: impl IntoVar<Length>) {}
53
54#[property(CONTEXT, capture, default(LineStyle::Solid), widget_impl(RuleLine))]
56pub fn line_style(style: impl IntoVar<LineStyle>) {}
57
58fn on_build(wgt: &mut WidgetBuilding) {
59 let mut bounds = PxSize::zero();
60
61 let orientation = wgt
62 .capture_var(property_id!(orientation))
63 .unwrap_or_else(|| LineOrientation::Horizontal.into_var().boxed());
64
65 let length = wgt
66 .capture_var(property_id!(length))
67 .unwrap_or_else(|| LocalVar(Length::Default).boxed());
68
69 let stroke_thickness = wgt
70 .capture_var(property_id!(stroke_thickness))
71 .unwrap_or_else(|| LocalVar(Length::from(1)).boxed());
72
73 let color = wgt
74 .capture_var(property_id!(color))
75 .unwrap_or_else(|| LocalVar(rgb(0, 0, 0)).boxed());
76
77 let style = wgt
78 .capture_var(property_id!(line_style))
79 .unwrap_or_else(|| LineStyle::Solid.into_var().boxed());
80
81 wgt.set_child(match_node_leaf(move |op| match op {
82 UiNodeOp::Init => {
83 WIDGET
84 .sub_var_layout(&stroke_thickness)
85 .sub_var_layout(&orientation)
86 .sub_var_layout(&length)
87 .sub_var_render(&color)
88 .sub_var_render(&style);
89 }
90 UiNodeOp::Measure { desired_size, .. } => {
91 let metrics = LAYOUT.metrics();
92 let default_stroke = Dip::new(1).to_px(metrics.scale_factor());
93
94 *desired_size = match orientation.get() {
95 LineOrientation::Horizontal => PxSize::new(
96 length.layout_dft_x(metrics.constraints().x.fill()),
97 stroke_thickness.layout_dft_y(default_stroke),
98 ),
99 LineOrientation::Vertical => PxSize::new(
100 stroke_thickness.layout_dft_x(default_stroke),
101 length.layout_dft_y(metrics.constraints().y.fill()),
102 ),
103 };
104 }
105 UiNodeOp::Layout { final_size, .. } => {
106 let metrics = LAYOUT.metrics();
107 let default_stroke = Dip::new(1).to_px(metrics.scale_factor());
108
109 let b = match orientation.get() {
110 LineOrientation::Horizontal => PxSize::new(
111 length.layout_dft_x(metrics.constraints().x.fill()),
112 stroke_thickness.layout_dft_y(default_stroke),
113 ),
114 LineOrientation::Vertical => PxSize::new(
115 stroke_thickness.layout_dft_x(default_stroke),
116 length.layout_dft_y(metrics.constraints().y.fill()),
117 ),
118 };
119
120 if b != bounds {
121 bounds = b;
122 WIDGET.render();
123 }
124
125 *final_size = b;
126 }
127 UiNodeOp::Render { frame } => {
128 let bounds = PxRect::from_size(bounds);
129 let orientation = orientation.get();
130 let color = color.get();
131 let style = style.get();
132 frame.push_line(bounds, orientation, color, style);
133 }
134 _ => {}
135 }));
136}
137
138pub mod hr {
140 use zng_wgt::prelude::*;
141
142 #[widget($crate::hr::Hr)]
144 pub struct Hr(super::RuleLine);
145 impl Hr {
146 fn widget_intrinsic(&mut self) {
147 widget_set! {
148 self;
149 orientation = LineOrientation::Horizontal;
150 color = COLOR_VAR;
151 stroke_thickness = STROKE_THICKNESS_VAR;
152 line_style = LINE_STYLE_VAR;
153 margin = MARGIN_VAR;
154 }
155 }
156 }
157
158 context_var! {
159 pub static COLOR_VAR: Rgba = zng_wgt_text::FONT_COLOR_VAR.map(|c| c.with_alpha(30.pct()));
163
164 pub static STROKE_THICKNESS_VAR: Length = 1.dip();
166
167 pub static LINE_STYLE_VAR: LineStyle = LineStyle::Solid;
169
170 pub static MARGIN_VAR: SideOffsets = (4, 0);
174 }
175
176 #[property(CONTEXT, default(COLOR_VAR))]
178 pub fn color(child: impl UiNode, color: impl IntoVar<Rgba>) -> impl UiNode {
179 with_context_var(child, COLOR_VAR, color)
180 }
181
182 #[property(CONTEXT, default(STROKE_THICKNESS_VAR))]
184 pub fn stroke_thickness(child: impl UiNode, thickness: impl IntoVar<Length>) -> impl UiNode {
185 with_context_var(child, STROKE_THICKNESS_VAR, thickness)
186 }
187
188 #[property(CONTEXT, default(LINE_STYLE_VAR))]
190 pub fn line_style(child: impl UiNode, style: impl IntoVar<LineStyle>) -> impl UiNode {
191 with_context_var(child, LINE_STYLE_VAR, style)
192 }
193
194 #[property(CONTEXT, default(MARGIN_VAR))]
196 pub fn margin(child: impl UiNode, margin: impl IntoVar<SideOffsets>) -> impl UiNode {
197 with_context_var(child, MARGIN_VAR, margin)
198 }
199}
200
201pub mod vr {
203 use zng_wgt::prelude::*;
204
205 #[widget($crate::vr::Vr)]
207 pub struct Vr(super::RuleLine);
208 impl Vr {
209 fn widget_intrinsic(&mut self) {
210 widget_set! {
211 self;
212 orientation = LineOrientation::Vertical;
213 color = COLOR_VAR;
214 stroke_thickness = STROKE_THICKNESS_VAR;
215 line_style = LINE_STYLE_VAR;
216 margin = MARGIN_VAR;
217 }
218 }
219 }
220
221 context_var! {
222 pub static COLOR_VAR: Rgba = zng_wgt_text::FONT_COLOR_VAR.map(|c| c.with_alpha(30.pct()));
226
227 pub static STROKE_THICKNESS_VAR: Length = 1.dip();
229
230 pub static LINE_STYLE_VAR: LineStyle = LineStyle::Solid;
232
233 pub static MARGIN_VAR: SideOffsets = (0, 4);
237 }
238
239 #[property(CONTEXT, default(COLOR_VAR))]
241 pub fn color(child: impl UiNode, color: impl IntoVar<Rgba>) -> impl UiNode {
242 with_context_var(child, COLOR_VAR, color)
243 }
244
245 #[property(CONTEXT, default(STROKE_THICKNESS_VAR))]
247 pub fn stroke_thickness(child: impl UiNode, thickness: impl IntoVar<Length>) -> impl UiNode {
248 with_context_var(child, STROKE_THICKNESS_VAR, thickness)
249 }
250
251 #[property(CONTEXT, default(LINE_STYLE_VAR))]
253 pub fn line_style(child: impl UiNode, style: impl IntoVar<LineStyle>) -> impl UiNode {
254 with_context_var(child, LINE_STYLE_VAR, style)
255 }
256
257 #[property(CONTEXT, default(MARGIN_VAR))]
259 pub fn margin(child: impl UiNode, margin: impl IntoVar<SideOffsets>) -> impl UiNode {
260 with_context_var(child, MARGIN_VAR, margin)
261 }
262}