1use alloc::vec::Vec;
4
5use azul_core::{
6 callbacks::{CoreCallback, CoreCallbackData, Update},
7 dom::{
8 Dom, DomVec, EventFilter, HoverEventFilter, IdOrClass, IdOrClass::Class, IdOrClassVec,
9 TabIndex,
10 },
11 geom::{LogicalPosition, LogicalSize},
12 menu::{Menu, OptionMenu},
13 refany::{OptionRefAny, RefAny},
14};
15#[allow(clippy::wildcard_imports)] use azul_css::{
17 corety::OptionUsize,
18 dynamic_selector::{CssPropertyWithConditions, CssPropertyWithConditionsVec},
19 props::{
20 basic::*,
21 layout::*,
22 property::{CssProperty, *},
23 style::*,
24 },
25 *,
26};
27use azul_css::css::BoxOrStatic;
28
29use crate::callbacks::{Callback, CallbackInfo};
30
31const STRING_16146701490593874959: AzString = AzString::from_const_str("system:ui");
32const STYLE_BACKGROUND_CONTENT_661302523448178568_ITEMS: &[StyleBackgroundContent] =
33 &[StyleBackgroundContent::Color(ColorU {
34 r: 209,
35 g: 232,
36 b: 255,
37 a: 255,
38 })];
39const STYLE_BACKGROUND_CONTENT_2444935983575427872_ITEMS: &[StyleBackgroundContent] =
40 &[StyleBackgroundContent::Color(ColorU {
41 r: 252,
42 g: 252,
43 b: 252,
44 a: 255,
45 })];
46const STYLE_BACKGROUND_CONTENT_3010057533077499049_ITEMS: &[StyleBackgroundContent] =
47 &[StyleBackgroundContent::Color(ColorU {
48 r: 229,
49 g: 243,
50 b: 251,
51 a: 255,
52 })];
53const STYLE_BACKGROUND_CONTENT_3839348353894170136_ITEMS: &[StyleBackgroundContent] =
54 &[StyleBackgroundContent::Color(ColorU {
55 r: 249,
56 g: 250,
57 b: 251,
58 a: 255,
59 })];
60const STYLE_BACKGROUND_CONTENT_6112684430356720596_ITEMS: &[StyleBackgroundContent] =
61 &[StyleBackgroundContent::LinearGradient(LinearGradient {
62 direction: Direction::FromTo(DirectionCorners {
63 dir_from: DirectionCorner::Top,
64 dir_to: DirectionCorner::Bottom,
65 }),
66 extend_mode: ExtendMode::Clamp,
67 stops: NormalizedLinearColorStopVec::from_const_slice(
68 LINEAR_COLOR_STOP_10827796861537038040_ITEMS,
69 ),
70 })];
71const STYLE_BACKGROUND_CONTENT_7422581697888665934_ITEMS: &[StyleBackgroundContent] =
72 &[StyleBackgroundContent::LinearGradient(LinearGradient {
73 direction: Direction::FromTo(DirectionCorners {
74 dir_from: DirectionCorner::Top,
75 dir_to: DirectionCorner::Bottom,
76 }),
77 extend_mode: ExtendMode::Clamp,
78 stops: NormalizedLinearColorStopVec::from_const_slice(
79 LINEAR_COLOR_STOP_513857305091467054_ITEMS,
80 ),
81 })];
82const STYLE_BACKGROUND_CONTENT_11062356617965867290_ITEMS: &[StyleBackgroundContent] =
83 &[StyleBackgroundContent::Color(ColorU {
84 r: 240,
85 g: 240,
86 b: 240,
87 a: 255,
88 })];
89const STYLE_BACKGROUND_CONTENT_11098930083828139815_ITEMS: &[StyleBackgroundContent] =
90 &[StyleBackgroundContent::Color(ColorU {
91 r: 184,
92 g: 224,
93 b: 243,
94 a: 255,
95 })];
96const STYLE_TRANSFORM_6162542744002865382_ITEMS: &[StyleTransform] =
97 &[StyleTransform::Translate(StyleTransformTranslate2D {
98 x: PixelValue::const_px(7),
99 y: PixelValue::const_px(0),
100 })];
101const STYLE_TRANSFORM_16978981723642914576_ITEMS: &[StyleTransform] =
102 &[StyleTransform::Rotate(AngleValue::const_deg(45))];
103const STYLE_TRANSFORM_17732691695785266054_ITEMS: &[StyleTransform] = &[
104 StyleTransform::Rotate(AngleValue::const_deg(315)),
105 StyleTransform::Translate(StyleTransformTranslate2D {
106 x: PixelValue::const_px(0),
107 y: PixelValue::const_px(2),
108 }),
109];
110const STYLE_FONT_FAMILY_8122988506401935406_ITEMS: &[StyleFontFamily] =
111 &[StyleFontFamily::System(STRING_16146701490593874959)];
112const LINEAR_COLOR_STOP_513857305091467054_ITEMS: &[NormalizedLinearColorStop] = &[
113 NormalizedLinearColorStop {
114 offset: PercentageValue::const_new(0),
115 color: ColorOrSystem::color(ColorU {
116 r: 255,
117 g: 255,
118 b: 255,
119 a: 255,
120 }),
121 },
122 NormalizedLinearColorStop {
123 offset: PercentageValue::const_new(50),
124 color: ColorOrSystem::color(ColorU {
125 r: 255,
126 g: 255,
127 b: 255,
128 a: 255,
129 }),
130 },
131 NormalizedLinearColorStop {
132 offset: PercentageValue::const_new(51),
133 color: ColorOrSystem::color(ColorU {
134 r: 247,
135 g: 248,
136 b: 250,
137 a: 255,
138 }),
139 },
140 NormalizedLinearColorStop {
141 offset: PercentageValue::const_new(100),
142 color: ColorOrSystem::color(ColorU {
143 r: 243,
144 g: 244,
145 b: 246,
146 a: 255,
147 }),
148 },
149];
150const LINEAR_COLOR_STOP_10827796861537038040_ITEMS: &[NormalizedLinearColorStop] = &[
151 NormalizedLinearColorStop {
152 offset: PercentageValue::const_new(0),
153 color: ColorOrSystem::color(ColorU {
154 r: 247,
155 g: 252,
156 b: 254,
157 a: 255,
158 }),
159 },
160 NormalizedLinearColorStop {
161 offset: PercentageValue::const_new(50),
162 color: ColorOrSystem::color(ColorU {
163 r: 247,
164 g: 252,
165 b: 254,
166 a: 255,
167 }),
168 },
169 NormalizedLinearColorStop {
170 offset: PercentageValue::const_new(51),
171 color: ColorOrSystem::color(ColorU {
172 r: 232,
173 g: 246,
174 b: 254,
175 a: 255,
176 }),
177 },
178 NormalizedLinearColorStop {
179 offset: PercentageValue::const_new(100),
180 color: ColorOrSystem::color(ColorU {
181 r: 206,
182 g: 231,
183 b: 244,
184 a: 255,
185 }),
186 },
187];
188
189const CSS_MATCH_1085706216385961159_PROPERTIES: &[CssPropertyWithConditions] = &[
190 CssPropertyWithConditions::simple(CssProperty::Transform(StyleTransformVecValue::Exact(
192 StyleTransformVec::from_const_slice(STYLE_TRANSFORM_6162542744002865382_ITEMS),
193 ))),
194 CssPropertyWithConditions::simple(CssProperty::Position(LayoutPositionValue::Exact(
195 LayoutPosition::Absolute,
196 ))),
197 CssPropertyWithConditions::simple(CssProperty::PaddingRight(LayoutPaddingRightValue::Exact(
198 LayoutPaddingRight {
199 inner: PixelValue::const_px(3),
200 },
201 ))),
202 CssPropertyWithConditions::simple(CssProperty::PaddingLeft(LayoutPaddingLeftValue::Exact(
203 LayoutPaddingLeft {
204 inner: PixelValue::const_px(3),
205 },
206 ))),
207 CssPropertyWithConditions::simple(CssProperty::PaddingBottom(LayoutPaddingBottomValue::Exact(
208 LayoutPaddingBottom {
209 inner: PixelValue::const_px(3),
210 },
211 ))),
212 CssPropertyWithConditions::simple(CssProperty::PaddingTop(LayoutPaddingTopValue::Exact(
213 LayoutPaddingTop {
214 inner: PixelValue::const_px(3),
215 },
216 ))),
217 CssPropertyWithConditions::simple(CssProperty::JustifyContent(
218 LayoutJustifyContentValue::Exact(LayoutJustifyContent::Center),
219 )),
220 CssPropertyWithConditions::simple(CssProperty::FlexDirection(LayoutFlexDirectionValue::Exact(
221 LayoutFlexDirection::Row,
222 ))),
223];
224const CSS_MATCH_1085706216385961159: CssPropertyWithConditionsVec =
225 CssPropertyWithConditionsVec::from_const_slice(CSS_MATCH_1085706216385961159_PROPERTIES);
226
227const CSS_MATCH_12498280255863106397_PROPERTIES: &[CssPropertyWithConditions] = &[
228 CssPropertyWithConditions::on_hover(CssProperty::BorderBottomWidth(
230 LayoutBorderBottomWidthValue::Exact(LayoutBorderBottomWidth {
231 inner: PixelValue::const_px(1),
232 }),
233 )),
234 CssPropertyWithConditions::on_hover(CssProperty::BorderBottomStyle(
235 StyleBorderBottomStyleValue::Exact(StyleBorderBottomStyle {
236 inner: BorderStyle::Solid,
237 }),
238 )),
239 CssPropertyWithConditions::on_hover(CssProperty::BorderBottomColor(
240 StyleBorderBottomColorValue::Exact(StyleBorderBottomColor {
241 inner: ColorU {
242 r: 154,
243 g: 223,
244 b: 254,
245 a: 255,
246 },
247 }),
248 )),
249 CssPropertyWithConditions::on_hover(CssProperty::BackgroundContent(
250 StyleBackgroundContentVecValue::Exact(StyleBackgroundContentVec::from_const_slice(
251 STYLE_BACKGROUND_CONTENT_6112684430356720596_ITEMS,
252 )),
253 )),
254 CssPropertyWithConditions::on_active(CssProperty::BoxShadowBottom(StyleBoxShadowValue::Exact(BoxOrStatic::Static(&
256 StyleBoxShadow {
257 offset_x: PixelValueNoPercent {
258 inner: PixelValue::const_px(0),
259 },
260 offset_y: PixelValueNoPercent {
261 inner: PixelValue::const_px(0),
262 },
263 color: ColorU {
264 r: 206,
265 g: 231,
266 b: 244,
267 a: 255,
268 },
269 blur_radius: PixelValueNoPercent {
270 inner: PixelValue::const_px(5),
271 },
272 spread_radius: PixelValueNoPercent {
273 inner: PixelValue::const_px(0),
274 },
275 clip_mode: BoxShadowClipMode::Inset,
276 },
277 )))),
278 CssPropertyWithConditions::on_active(CssProperty::BoxShadowTop(StyleBoxShadowValue::Exact(BoxOrStatic::Static(&
279 StyleBoxShadow {
280 offset_x: PixelValueNoPercent {
281 inner: PixelValue::const_px(0),
282 },
283 offset_y: PixelValueNoPercent {
284 inner: PixelValue::const_px(0),
285 },
286 color: ColorU {
287 r: 206,
288 g: 231,
289 b: 244,
290 a: 255,
291 },
292 blur_radius: PixelValueNoPercent {
293 inner: PixelValue::const_px(5),
294 },
295 spread_radius: PixelValueNoPercent {
296 inner: PixelValue::const_px(0),
297 },
298 clip_mode: BoxShadowClipMode::Inset,
299 },
300 )))),
301 CssPropertyWithConditions::on_active(CssProperty::BoxShadowRight(StyleBoxShadowValue::Exact(BoxOrStatic::Static(&
302 StyleBoxShadow {
303 offset_x: PixelValueNoPercent {
304 inner: PixelValue::const_px(0),
305 },
306 offset_y: PixelValueNoPercent {
307 inner: PixelValue::const_px(0),
308 },
309 color: ColorU {
310 r: 206,
311 g: 231,
312 b: 244,
313 a: 255,
314 },
315 blur_radius: PixelValueNoPercent {
316 inner: PixelValue::const_px(5),
317 },
318 spread_radius: PixelValueNoPercent {
319 inner: PixelValue::const_px(0),
320 },
321 clip_mode: BoxShadowClipMode::Inset,
322 },
323 )))),
324 CssPropertyWithConditions::on_active(CssProperty::BoxShadowLeft(StyleBoxShadowValue::Exact(BoxOrStatic::Static(&
325 StyleBoxShadow {
326 offset_x: PixelValueNoPercent {
327 inner: PixelValue::const_px(0),
328 },
329 offset_y: PixelValueNoPercent {
330 inner: PixelValue::const_px(0),
331 },
332 color: ColorU {
333 r: 206,
334 g: 231,
335 b: 244,
336 a: 255,
337 },
338 blur_radius: PixelValueNoPercent {
339 inner: PixelValue::const_px(5),
340 },
341 spread_radius: PixelValueNoPercent {
342 inner: PixelValue::const_px(0),
343 },
344 clip_mode: BoxShadowClipMode::Inset,
345 },
346 )))),
347 CssPropertyWithConditions::on_active(CssProperty::BorderBottomWidth(
348 LayoutBorderBottomWidthValue::Exact(LayoutBorderBottomWidth {
349 inner: PixelValue::const_px(1),
350 }),
351 )),
352 CssPropertyWithConditions::on_active(CssProperty::BorderLeftWidth(
353 LayoutBorderLeftWidthValue::Exact(LayoutBorderLeftWidth {
354 inner: PixelValue::const_px(1),
355 }),
356 )),
357 CssPropertyWithConditions::on_active(CssProperty::BorderRightWidth(
358 LayoutBorderRightWidthValue::Exact(LayoutBorderRightWidth {
359 inner: PixelValue::const_px(1),
360 }),
361 )),
362 CssPropertyWithConditions::on_active(CssProperty::BorderTopWidth(
363 LayoutBorderTopWidthValue::Exact(LayoutBorderTopWidth {
364 inner: PixelValue::const_px(1),
365 }),
366 )),
367 CssPropertyWithConditions::on_active(CssProperty::BorderBottomStyle(
368 StyleBorderBottomStyleValue::Exact(StyleBorderBottomStyle {
369 inner: BorderStyle::Solid,
370 }),
371 )),
372 CssPropertyWithConditions::on_active(CssProperty::BorderLeftStyle(
373 StyleBorderLeftStyleValue::Exact(StyleBorderLeftStyle {
374 inner: BorderStyle::Solid,
375 }),
376 )),
377 CssPropertyWithConditions::on_active(CssProperty::BorderRightStyle(
378 StyleBorderRightStyleValue::Exact(StyleBorderRightStyle {
379 inner: BorderStyle::Solid,
380 }),
381 )),
382 CssPropertyWithConditions::on_active(CssProperty::BorderTopStyle(
383 StyleBorderTopStyleValue::Exact(StyleBorderTopStyle {
384 inner: BorderStyle::Solid,
385 }),
386 )),
387 CssPropertyWithConditions::on_active(CssProperty::BorderBottomColor(
388 StyleBorderBottomColorValue::Exact(StyleBorderBottomColor {
389 inner: ColorU {
390 r: 194,
391 g: 205,
392 b: 219,
393 a: 255,
394 },
395 }),
396 )),
397 CssPropertyWithConditions::on_active(CssProperty::BorderLeftColor(
398 StyleBorderLeftColorValue::Exact(StyleBorderLeftColor {
399 inner: ColorU {
400 r: 194,
401 g: 205,
402 b: 219,
403 a: 255,
404 },
405 }),
406 )),
407 CssPropertyWithConditions::on_active(CssProperty::BorderRightColor(
408 StyleBorderRightColorValue::Exact(StyleBorderRightColor {
409 inner: ColorU {
410 r: 194,
411 g: 205,
412 b: 219,
413 a: 255,
414 },
415 }),
416 )),
417 CssPropertyWithConditions::on_active(CssProperty::BorderTopColor(
418 StyleBorderTopColorValue::Exact(StyleBorderTopColor {
419 inner: ColorU {
420 r: 194,
421 g: 205,
422 b: 219,
423 a: 255,
424 },
425 }),
426 )),
427 CssPropertyWithConditions::on_active(CssProperty::BackgroundContent(
428 StyleBackgroundContentVecValue::Exact(StyleBackgroundContentVec::from_const_slice(
429 STYLE_BACKGROUND_CONTENT_3839348353894170136_ITEMS,
430 )),
431 )),
432 CssPropertyWithConditions::simple(CssProperty::Position(LayoutPositionValue::Exact(
434 LayoutPosition::Relative,
435 ))),
436 CssPropertyWithConditions::simple(CssProperty::PaddingLeft(LayoutPaddingLeftValue::Exact(
437 LayoutPaddingLeft {
438 inner: PixelValue::const_px(7),
439 },
440 ))),
441 CssPropertyWithConditions::simple(CssProperty::MinWidth(LayoutMinWidthValue::Exact(
442 LayoutMinWidth {
443 inner: PixelValue::const_px(100),
444 },
445 ))),
446 CssPropertyWithConditions::simple(CssProperty::FlexDirection(LayoutFlexDirectionValue::Exact(
447 LayoutFlexDirection::Column,
448 ))),
449 CssPropertyWithConditions::simple(CssProperty::BorderRightWidth(
450 LayoutBorderRightWidthValue::Exact(LayoutBorderRightWidth {
451 inner: PixelValue::const_px(1),
452 }),
453 )),
454 CssPropertyWithConditions::simple(CssProperty::BorderRightStyle(
455 StyleBorderRightStyleValue::Exact(StyleBorderRightStyle {
456 inner: BorderStyle::Solid,
457 }),
458 )),
459 CssPropertyWithConditions::simple(CssProperty::BorderRightColor(
460 StyleBorderRightColorValue::Exact(StyleBorderRightColor {
461 inner: ColorU {
462 r: 243,
463 g: 244,
464 b: 246,
465 a: 255,
466 },
467 }),
468 )),
469];
470const CSS_MATCH_12498280255863106397: CssPropertyWithConditionsVec =
471 CssPropertyWithConditionsVec::from_const_slice(CSS_MATCH_12498280255863106397_PROPERTIES);
472
473const CSS_MATCH_12980082330151137475_PROPERTIES: &[CssPropertyWithConditions] = &[
474 CssPropertyWithConditions::simple(CssProperty::PaddingLeft(LayoutPaddingLeftValue::Exact(
476 LayoutPaddingLeft {
477 inner: PixelValue::const_px(7),
478 },
479 ))),
480 CssPropertyWithConditions::simple(CssProperty::MinWidth(LayoutMinWidthValue::Exact(
481 LayoutMinWidth {
482 inner: PixelValue::const_px(100),
483 },
484 ))),
485 CssPropertyWithConditions::simple(CssProperty::FontSize(StyleFontSizeValue::Exact(
486 StyleFontSize {
487 inner: PixelValue::const_px(11),
488 },
489 ))),
490 CssPropertyWithConditions::simple(CssProperty::FontFamily(StyleFontFamilyVecValue::Exact(
491 StyleFontFamilyVec::from_const_slice(STYLE_FONT_FAMILY_8122988506401935406_ITEMS),
492 ))),
493];
494const CSS_MATCH_12980082330151137475: CssPropertyWithConditionsVec =
495 CssPropertyWithConditionsVec::from_const_slice(CSS_MATCH_12980082330151137475_PROPERTIES);
496
497const CSS_MATCH_13758717721055992976_PROPERTIES: &[CssPropertyWithConditions] = &[
498 CssPropertyWithConditions::simple(CssProperty::Width(LayoutWidthValue::Exact(
500 LayoutWidth::Px(PixelValue::const_px(6)),
501 ))),
502 CssPropertyWithConditions::simple(CssProperty::Transform(StyleTransformVecValue::Exact(
503 StyleTransformVec::from_const_slice(STYLE_TRANSFORM_16978981723642914576_ITEMS),
504 ))),
505 CssPropertyWithConditions::simple(CssProperty::OverflowY(LayoutOverflowValue::Exact(
506 LayoutOverflow::Hidden,
507 ))),
508 CssPropertyWithConditions::simple(CssProperty::OverflowX(LayoutOverflowValue::Exact(
509 LayoutOverflow::Hidden,
510 ))),
511 CssPropertyWithConditions::simple(CssProperty::Height(LayoutHeightValue::Exact(
512 LayoutHeight::Px(PixelValue::const_px(6)),
513 ))),
514];
515const CSS_MATCH_13758717721055992976: CssPropertyWithConditionsVec =
516 CssPropertyWithConditionsVec::from_const_slice(CSS_MATCH_13758717721055992976_PROPERTIES);
517
518const CSS_MATCH_15295293133676720691_PROPERTIES: &[CssPropertyWithConditions] = &[
519 CssPropertyWithConditions::simple(CssProperty::Width(LayoutWidthValue::Exact(
521 LayoutWidth::Px(PixelValue::const_px(2)),
522 ))),
523 CssPropertyWithConditions::simple(CssProperty::Position(LayoutPositionValue::Exact(
524 LayoutPosition::Absolute,
525 ))),
526];
527const CSS_MATCH_15295293133676720691: CssPropertyWithConditionsVec =
528 CssPropertyWithConditionsVec::from_const_slice(CSS_MATCH_15295293133676720691_PROPERTIES);
529
530const CSS_MATCH_15315949193378715186_PROPERTIES: &[CssPropertyWithConditions] = &[
531 CssPropertyWithConditions::simple(CssProperty::Height(LayoutHeightValue::Exact(
533 LayoutHeight::Px(PixelValue::const_px(25)),
534 ))),
535 CssPropertyWithConditions::simple(CssProperty::FlexDirection(LayoutFlexDirectionValue::Exact(
536 LayoutFlexDirection::Row,
537 ))),
538 CssPropertyWithConditions::simple(CssProperty::BackgroundContent(
539 StyleBackgroundContentVecValue::Exact(StyleBackgroundContentVec::from_const_slice(
540 STYLE_BACKGROUND_CONTENT_7422581697888665934_ITEMS,
541 )),
542 )),
543];
544const CSS_MATCH_15315949193378715186: CssPropertyWithConditionsVec =
545 CssPropertyWithConditionsVec::from_const_slice(CSS_MATCH_15315949193378715186_PROPERTIES);
546
547const CSS_MATCH_15673486787900743642_PROPERTIES: &[CssPropertyWithConditions] = &[
548 CssPropertyWithConditions::simple(CssProperty::FontSize(StyleFontSizeValue::Exact(
550 StyleFontSize {
551 inner: PixelValue::const_px(11),
552 },
553 ))),
554 CssPropertyWithConditions::simple(CssProperty::FontFamily(StyleFontFamilyVecValue::Exact(
555 StyleFontFamilyVec::from_const_slice(STYLE_FONT_FAMILY_8122988506401935406_ITEMS),
556 ))),
557 CssPropertyWithConditions::simple(CssProperty::FlexGrow(LayoutFlexGrowValue::Exact(
558 LayoutFlexGrow {
559 inner: FloatValue::const_new(1),
560 },
561 ))),
562 CssPropertyWithConditions::simple(CssProperty::FlexDirection(LayoutFlexDirectionValue::Exact(
563 LayoutFlexDirection::Column,
564 ))),
565 CssPropertyWithConditions::simple(CssProperty::TextColor(StyleTextColorValue::Exact(
566 StyleTextColor {
567 inner: ColorU {
568 r: 0,
569 g: 0,
570 b: 0,
571 a: 255,
572 },
573 },
574 ))),
575 CssPropertyWithConditions::simple(CssProperty::AlignItems(LayoutAlignItemsValue::Exact(
576 LayoutAlignItems::Center,
577 ))),
578];
579const CSS_MATCH_15673486787900743642: CssPropertyWithConditionsVec =
580 CssPropertyWithConditionsVec::from_const_slice(CSS_MATCH_15673486787900743642_PROPERTIES);
581
582const CSS_MATCH_1574792189506859253_PROPERTIES: &[CssPropertyWithConditions] = &[
583 CssPropertyWithConditions::simple(CssProperty::Width(LayoutWidthValue::Exact(
585 LayoutWidth::Px(PixelValue::const_px(12)),
586 ))),
587 CssPropertyWithConditions::simple(CssProperty::Transform(StyleTransformVecValue::Exact(
588 StyleTransformVec::from_const_slice(STYLE_TRANSFORM_17732691695785266054_ITEMS),
589 ))),
590 CssPropertyWithConditions::simple(CssProperty::Height(LayoutHeightValue::Exact(
591 LayoutHeight::Px(PixelValue::const_px(12)),
592 ))),
593 CssPropertyWithConditions::simple(CssProperty::BoxShadowBottom(StyleBoxShadowValue::Exact(BoxOrStatic::Static(&
594 StyleBoxShadow {
595 offset_x: PixelValueNoPercent {
596 inner: PixelValue::const_px(3),
597 },
598 offset_y: PixelValueNoPercent {
599 inner: PixelValue::const_px(3),
600 },
601 color: ColorU {
602 r: 60,
603 g: 94,
604 b: 114,
605 a: 255,
606 },
607 blur_radius: PixelValueNoPercent {
608 inner: PixelValue::const_px(10),
609 },
610 spread_radius: PixelValueNoPercent {
611 inner: PixelValue::const_px(0),
612 },
613 clip_mode: BoxShadowClipMode::Inset,
614 },
615 )))),
616 CssPropertyWithConditions::simple(CssProperty::BoxShadowTop(StyleBoxShadowValue::Exact(BoxOrStatic::Static(&
617 StyleBoxShadow {
618 offset_x: PixelValueNoPercent {
619 inner: PixelValue::const_px(3),
620 },
621 offset_y: PixelValueNoPercent {
622 inner: PixelValue::const_px(3),
623 },
624 color: ColorU {
625 r: 60,
626 g: 94,
627 b: 114,
628 a: 255,
629 },
630 blur_radius: PixelValueNoPercent {
631 inner: PixelValue::const_px(10),
632 },
633 spread_radius: PixelValueNoPercent {
634 inner: PixelValue::const_px(0),
635 },
636 clip_mode: BoxShadowClipMode::Inset,
637 },
638 )))),
639 CssPropertyWithConditions::simple(CssProperty::BoxShadowRight(StyleBoxShadowValue::Exact(BoxOrStatic::Static(&
640 StyleBoxShadow {
641 offset_x: PixelValueNoPercent {
642 inner: PixelValue::const_px(3),
643 },
644 offset_y: PixelValueNoPercent {
645 inner: PixelValue::const_px(3),
646 },
647 color: ColorU {
648 r: 60,
649 g: 94,
650 b: 114,
651 a: 255,
652 },
653 blur_radius: PixelValueNoPercent {
654 inner: PixelValue::const_px(10),
655 },
656 spread_radius: PixelValueNoPercent {
657 inner: PixelValue::const_px(0),
658 },
659 clip_mode: BoxShadowClipMode::Inset,
660 },
661 )))),
662 CssPropertyWithConditions::simple(CssProperty::BoxShadowLeft(StyleBoxShadowValue::Exact(BoxOrStatic::Static(&
663 StyleBoxShadow {
664 offset_x: PixelValueNoPercent {
665 inner: PixelValue::const_px(3),
666 },
667 offset_y: PixelValueNoPercent {
668 inner: PixelValue::const_px(3),
669 },
670 color: ColorU {
671 r: 60,
672 g: 94,
673 b: 114,
674 a: 255,
675 },
676 blur_radius: PixelValueNoPercent {
677 inner: PixelValue::const_px(10),
678 },
679 spread_radius: PixelValueNoPercent {
680 inner: PixelValue::const_px(0),
681 },
682 clip_mode: BoxShadowClipMode::Inset,
683 },
684 )))),
685];
686const CSS_MATCH_1574792189506859253: CssPropertyWithConditionsVec =
687 CssPropertyWithConditionsVec::from_const_slice(CSS_MATCH_1574792189506859253_PROPERTIES);
688
689const CSS_MATCH_17553577885456905601_PROPERTIES: &[CssPropertyWithConditions] = &[
690 CssPropertyWithConditions::simple(CssProperty::FlexGrow(LayoutFlexGrowValue::Exact(
692 LayoutFlexGrow {
693 inner: FloatValue::const_new(1),
694 },
695 ))),
696 CssPropertyWithConditions::simple(CssProperty::BackgroundContent(
697 StyleBackgroundContentVecValue::Exact(StyleBackgroundContentVec::from_const_slice(
698 STYLE_BACKGROUND_CONTENT_2444935983575427872_ITEMS,
699 )),
700 )),
701];
702const CSS_MATCH_17553577885456905601: CssPropertyWithConditionsVec =
703 CssPropertyWithConditionsVec::from_const_slice(CSS_MATCH_17553577885456905601_PROPERTIES);
704
705const CSS_MATCH_2883986488332352590_PROPERTIES: &[CssPropertyWithConditions] = &[
706 CssPropertyWithConditions::simple(CssProperty::PaddingRight(LayoutPaddingRightValue::Exact(
708 LayoutPaddingRight {
709 inner: PixelValue::const_px(5),
710 },
711 ))),
712 CssPropertyWithConditions::simple(CssProperty::PaddingLeft(LayoutPaddingLeftValue::Exact(
713 LayoutPaddingLeft {
714 inner: PixelValue::const_px(5),
715 },
716 ))),
717 CssPropertyWithConditions::simple(CssProperty::PaddingBottom(LayoutPaddingBottomValue::Exact(
718 LayoutPaddingBottom {
719 inner: PixelValue::const_px(5),
720 },
721 ))),
722 CssPropertyWithConditions::simple(CssProperty::PaddingTop(LayoutPaddingTopValue::Exact(
723 LayoutPaddingTop {
724 inner: PixelValue::const_px(5),
725 },
726 ))),
727 CssPropertyWithConditions::simple(CssProperty::BackgroundContent(
728 StyleBackgroundContentVecValue::Exact(StyleBackgroundContentVec::from_const_slice(
729 STYLE_BACKGROUND_CONTENT_11062356617965867290_ITEMS,
730 )),
731 )),
732];
733const CSS_MATCH_2883986488332352590: CssPropertyWithConditionsVec =
734 CssPropertyWithConditionsVec::from_const_slice(CSS_MATCH_2883986488332352590_PROPERTIES);
735
736const CSS_MATCH_4852927511892172364_PROPERTIES: &[CssPropertyWithConditions] = &[
737 CssPropertyWithConditions::simple(CssProperty::FlexDirection(LayoutFlexDirectionValue::Exact(
739 LayoutFlexDirection::Column,
740 ))),
741];
742const CSS_MATCH_4852927511892172364: CssPropertyWithConditionsVec =
743 CssPropertyWithConditionsVec::from_const_slice(CSS_MATCH_4852927511892172364_PROPERTIES);
744
745const CSS_MATCH_6002662151290653203_PROPERTIES: &[CssPropertyWithConditions] = &[
746 CssPropertyWithConditions::simple(CssProperty::Width(LayoutWidthValue::Exact(
748 LayoutWidth::Px(PixelValue::const_px(0)),
749 ))),
750 CssPropertyWithConditions::simple(CssProperty::Position(LayoutPositionValue::Exact(
751 LayoutPosition::Relative,
752 ))),
753 CssPropertyWithConditions::simple(CssProperty::FlexGrow(LayoutFlexGrowValue::Exact(
754 LayoutFlexGrow {
755 inner: FloatValue::const_new(1),
756 },
757 ))),
758];
759const CSS_MATCH_6002662151290653203: CssPropertyWithConditionsVec =
760 CssPropertyWithConditionsVec::from_const_slice(CSS_MATCH_6002662151290653203_PROPERTIES);
761
762const CSS_MATCH_6827198030119836081_PROPERTIES: &[CssPropertyWithConditions] = &[
763 CssPropertyWithConditions::simple(CssProperty::BorderBottomWidth(
765 LayoutBorderBottomWidthValue::Exact(LayoutBorderBottomWidth {
766 inner: PixelValue::const_px(1),
767 }),
768 )),
769 CssPropertyWithConditions::simple(CssProperty::BorderLeftWidth(
770 LayoutBorderLeftWidthValue::Exact(LayoutBorderLeftWidth {
771 inner: PixelValue::const_px(1),
772 }),
773 )),
774 CssPropertyWithConditions::simple(CssProperty::BorderRightWidth(
775 LayoutBorderRightWidthValue::Exact(LayoutBorderRightWidth {
776 inner: PixelValue::const_px(1),
777 }),
778 )),
779 CssPropertyWithConditions::simple(CssProperty::BorderTopWidth(
780 LayoutBorderTopWidthValue::Exact(LayoutBorderTopWidth {
781 inner: PixelValue::const_px(1),
782 }),
783 )),
784 CssPropertyWithConditions::simple(CssProperty::BorderBottomStyle(
785 StyleBorderBottomStyleValue::Exact(StyleBorderBottomStyle {
786 inner: BorderStyle::Solid,
787 }),
788 )),
789 CssPropertyWithConditions::simple(CssProperty::BorderLeftStyle(
790 StyleBorderLeftStyleValue::Exact(StyleBorderLeftStyle {
791 inner: BorderStyle::Solid,
792 }),
793 )),
794 CssPropertyWithConditions::simple(CssProperty::BorderRightStyle(
795 StyleBorderRightStyleValue::Exact(StyleBorderRightStyle {
796 inner: BorderStyle::Solid,
797 }),
798 )),
799 CssPropertyWithConditions::simple(CssProperty::BorderTopStyle(
800 StyleBorderTopStyleValue::Exact(StyleBorderTopStyle {
801 inner: BorderStyle::Solid,
802 }),
803 )),
804 CssPropertyWithConditions::simple(CssProperty::BorderBottomColor(
805 StyleBorderBottomColorValue::Exact(StyleBorderBottomColor {
806 inner: ColorU {
807 r: 102,
808 g: 167,
809 b: 232,
810 a: 255,
811 },
812 }),
813 )),
814 CssPropertyWithConditions::simple(CssProperty::BorderLeftColor(
815 StyleBorderLeftColorValue::Exact(StyleBorderLeftColor {
816 inner: ColorU {
817 r: 102,
818 g: 167,
819 b: 232,
820 a: 255,
821 },
822 }),
823 )),
824 CssPropertyWithConditions::simple(CssProperty::BorderRightColor(
825 StyleBorderRightColorValue::Exact(StyleBorderRightColor {
826 inner: ColorU {
827 r: 102,
828 g: 167,
829 b: 232,
830 a: 255,
831 },
832 }),
833 )),
834 CssPropertyWithConditions::simple(CssProperty::BorderTopColor(
835 StyleBorderTopColorValue::Exact(StyleBorderTopColor {
836 inner: ColorU {
837 r: 102,
838 g: 167,
839 b: 232,
840 a: 255,
841 },
842 }),
843 )),
844 CssPropertyWithConditions::simple(CssProperty::BackgroundContent(
845 StyleBackgroundContentVecValue::Exact(StyleBackgroundContentVec::from_const_slice(
846 STYLE_BACKGROUND_CONTENT_661302523448178568_ITEMS,
847 )),
848 )),
849 CssPropertyWithConditions::on_hover(CssProperty::BorderBottomWidth(
851 LayoutBorderBottomWidthValue::Exact(LayoutBorderBottomWidth {
852 inner: PixelValue::const_px(1),
853 }),
854 )),
855 CssPropertyWithConditions::on_hover(CssProperty::BorderLeftWidth(
856 LayoutBorderLeftWidthValue::Exact(LayoutBorderLeftWidth {
857 inner: PixelValue::const_px(1),
858 }),
859 )),
860 CssPropertyWithConditions::on_hover(CssProperty::BorderRightWidth(
861 LayoutBorderRightWidthValue::Exact(LayoutBorderRightWidth {
862 inner: PixelValue::const_px(1),
863 }),
864 )),
865 CssPropertyWithConditions::on_hover(CssProperty::BorderTopWidth(
866 LayoutBorderTopWidthValue::Exact(LayoutBorderTopWidth {
867 inner: PixelValue::const_px(1),
868 }),
869 )),
870 CssPropertyWithConditions::on_hover(CssProperty::BorderBottomStyle(
871 StyleBorderBottomStyleValue::Exact(StyleBorderBottomStyle {
872 inner: BorderStyle::Solid,
873 }),
874 )),
875 CssPropertyWithConditions::on_hover(CssProperty::BorderLeftStyle(
876 StyleBorderLeftStyleValue::Exact(StyleBorderLeftStyle {
877 inner: BorderStyle::Solid,
878 }),
879 )),
880 CssPropertyWithConditions::on_hover(CssProperty::BorderRightStyle(
881 StyleBorderRightStyleValue::Exact(StyleBorderRightStyle {
882 inner: BorderStyle::Solid,
883 }),
884 )),
885 CssPropertyWithConditions::on_hover(CssProperty::BorderTopStyle(
886 StyleBorderTopStyleValue::Exact(StyleBorderTopStyle {
887 inner: BorderStyle::Solid,
888 }),
889 )),
890 CssPropertyWithConditions::on_hover(CssProperty::BorderBottomColor(
891 StyleBorderBottomColorValue::Exact(StyleBorderBottomColor {
892 inner: ColorU {
893 r: 101,
894 g: 181,
895 b: 220,
896 a: 255,
897 },
898 }),
899 )),
900 CssPropertyWithConditions::on_hover(CssProperty::BorderLeftColor(
901 StyleBorderLeftColorValue::Exact(StyleBorderLeftColor {
902 inner: ColorU {
903 r: 101,
904 g: 181,
905 b: 220,
906 a: 255,
907 },
908 }),
909 )),
910 CssPropertyWithConditions::on_hover(CssProperty::BorderRightColor(
911 StyleBorderRightColorValue::Exact(StyleBorderRightColor {
912 inner: ColorU {
913 r: 101,
914 g: 181,
915 b: 220,
916 a: 255,
917 },
918 }),
919 )),
920 CssPropertyWithConditions::on_hover(CssProperty::BorderTopColor(
921 StyleBorderTopColorValue::Exact(StyleBorderTopColor {
922 inner: ColorU {
923 r: 101,
924 g: 181,
925 b: 220,
926 a: 255,
927 },
928 }),
929 )),
930 CssPropertyWithConditions::on_hover(CssProperty::BackgroundContent(
931 StyleBackgroundContentVecValue::Exact(StyleBackgroundContentVec::from_const_slice(
932 STYLE_BACKGROUND_CONTENT_3010057533077499049_ITEMS,
933 )),
934 )),
935 CssPropertyWithConditions::simple(CssProperty::PaddingRight(LayoutPaddingRightValue::Exact(
937 LayoutPaddingRight {
938 inner: PixelValue::const_px(0),
939 },
940 ))),
941 CssPropertyWithConditions::simple(CssProperty::PaddingLeft(LayoutPaddingLeftValue::Exact(
942 LayoutPaddingLeft {
943 inner: PixelValue::const_px(0),
944 },
945 ))),
946 CssPropertyWithConditions::simple(CssProperty::PaddingBottom(LayoutPaddingBottomValue::Exact(
947 LayoutPaddingBottom {
948 inner: PixelValue::const_px(2),
949 },
950 ))),
951 CssPropertyWithConditions::simple(CssProperty::PaddingTop(LayoutPaddingTopValue::Exact(
952 LayoutPaddingTop {
953 inner: PixelValue::const_px(2),
954 },
955 ))),
956 CssPropertyWithConditions::simple(CssProperty::FlexGrow(LayoutFlexGrowValue::Exact(
957 LayoutFlexGrow {
958 inner: FloatValue::const_new(1),
959 },
960 ))),
961 CssPropertyWithConditions::simple(CssProperty::FlexDirection(LayoutFlexDirectionValue::Exact(
962 LayoutFlexDirection::Row,
963 ))),
964 CssPropertyWithConditions::simple(CssProperty::BorderBottomWidth(
965 LayoutBorderBottomWidthValue::Exact(LayoutBorderBottomWidth {
966 inner: PixelValue::const_px(1),
967 }),
968 )),
969 CssPropertyWithConditions::simple(CssProperty::BorderLeftWidth(
970 LayoutBorderLeftWidthValue::Exact(LayoutBorderLeftWidth {
971 inner: PixelValue::const_px(1),
972 }),
973 )),
974 CssPropertyWithConditions::simple(CssProperty::BorderRightWidth(
975 LayoutBorderRightWidthValue::Exact(LayoutBorderRightWidth {
976 inner: PixelValue::const_px(1),
977 }),
978 )),
979 CssPropertyWithConditions::simple(CssProperty::BorderTopWidth(
980 LayoutBorderTopWidthValue::Exact(LayoutBorderTopWidth {
981 inner: PixelValue::const_px(1),
982 }),
983 )),
984 CssPropertyWithConditions::simple(CssProperty::BorderBottomStyle(
985 StyleBorderBottomStyleValue::Exact(StyleBorderBottomStyle {
986 inner: BorderStyle::Solid,
987 }),
988 )),
989 CssPropertyWithConditions::simple(CssProperty::BorderLeftStyle(
990 StyleBorderLeftStyleValue::Exact(StyleBorderLeftStyle {
991 inner: BorderStyle::Solid,
992 }),
993 )),
994 CssPropertyWithConditions::simple(CssProperty::BorderRightStyle(
995 StyleBorderRightStyleValue::Exact(StyleBorderRightStyle {
996 inner: BorderStyle::Solid,
997 }),
998 )),
999 CssPropertyWithConditions::simple(CssProperty::BorderTopStyle(
1000 StyleBorderTopStyleValue::Exact(StyleBorderTopStyle {
1001 inner: BorderStyle::Solid,
1002 }),
1003 )),
1004 CssPropertyWithConditions::simple(CssProperty::BorderBottomColor(
1005 StyleBorderBottomColorValue::Exact(StyleBorderBottomColor {
1006 inner: ColorU {
1007 r: 255,
1008 g: 255,
1009 b: 255,
1010 a: 0,
1011 },
1012 }),
1013 )),
1014 CssPropertyWithConditions::simple(CssProperty::BorderLeftColor(
1015 StyleBorderLeftColorValue::Exact(StyleBorderLeftColor {
1016 inner: ColorU {
1017 r: 255,
1018 g: 255,
1019 b: 255,
1020 a: 0,
1021 },
1022 }),
1023 )),
1024 CssPropertyWithConditions::simple(CssProperty::BorderRightColor(
1025 StyleBorderRightColorValue::Exact(StyleBorderRightColor {
1026 inner: ColorU {
1027 r: 255,
1028 g: 255,
1029 b: 255,
1030 a: 0,
1031 },
1032 }),
1033 )),
1034 CssPropertyWithConditions::simple(CssProperty::BorderTopColor(
1035 StyleBorderTopColorValue::Exact(StyleBorderTopColor {
1036 inner: ColorU {
1037 r: 255,
1038 g: 255,
1039 b: 255,
1040 a: 0,
1041 },
1042 }),
1043 )),
1044];
1045const CSS_MATCH_6827198030119836081: CssPropertyWithConditionsVec =
1046 CssPropertyWithConditionsVec::from_const_slice(CSS_MATCH_6827198030119836081_PROPERTIES);
1047
1048const CSS_MATCH_7894335449545988724_PROPERTIES: &[CssPropertyWithConditions] = &[
1049 CssPropertyWithConditions::on_focus(CssProperty::BorderBottomWidth(
1051 LayoutBorderBottomWidthValue::Exact(LayoutBorderBottomWidth {
1052 inner: PixelValue::const_px(1),
1053 }),
1054 )),
1055 CssPropertyWithConditions::on_focus(CssProperty::BorderLeftWidth(
1056 LayoutBorderLeftWidthValue::Exact(LayoutBorderLeftWidth {
1057 inner: PixelValue::const_px(1),
1058 }),
1059 )),
1060 CssPropertyWithConditions::on_focus(CssProperty::BorderRightWidth(
1061 LayoutBorderRightWidthValue::Exact(LayoutBorderRightWidth {
1062 inner: PixelValue::const_px(1),
1063 }),
1064 )),
1065 CssPropertyWithConditions::on_focus(CssProperty::BorderTopWidth(
1066 LayoutBorderTopWidthValue::Exact(LayoutBorderTopWidth {
1067 inner: PixelValue::const_px(1),
1068 }),
1069 )),
1070 CssPropertyWithConditions::on_focus(CssProperty::BorderBottomStyle(
1071 StyleBorderBottomStyleValue::Exact(StyleBorderBottomStyle {
1072 inner: BorderStyle::Solid,
1073 }),
1074 )),
1075 CssPropertyWithConditions::on_focus(CssProperty::BorderLeftStyle(
1076 StyleBorderLeftStyleValue::Exact(StyleBorderLeftStyle {
1077 inner: BorderStyle::Solid,
1078 }),
1079 )),
1080 CssPropertyWithConditions::on_focus(CssProperty::BorderRightStyle(
1081 StyleBorderRightStyleValue::Exact(StyleBorderRightStyle {
1082 inner: BorderStyle::Solid,
1083 }),
1084 )),
1085 CssPropertyWithConditions::on_focus(CssProperty::BorderTopStyle(
1086 StyleBorderTopStyleValue::Exact(StyleBorderTopStyle {
1087 inner: BorderStyle::Solid,
1088 }),
1089 )),
1090 CssPropertyWithConditions::on_focus(CssProperty::BorderBottomColor(
1091 StyleBorderBottomColorValue::Exact(StyleBorderBottomColor {
1092 inner: ColorU {
1093 r: 38,
1094 g: 160,
1095 b: 218,
1096 a: 255,
1097 },
1098 }),
1099 )),
1100 CssPropertyWithConditions::on_focus(CssProperty::BorderLeftColor(
1101 StyleBorderLeftColorValue::Exact(StyleBorderLeftColor {
1102 inner: ColorU {
1103 r: 38,
1104 g: 160,
1105 b: 218,
1106 a: 255,
1107 },
1108 }),
1109 )),
1110 CssPropertyWithConditions::on_focus(CssProperty::BorderRightColor(
1111 StyleBorderRightColorValue::Exact(StyleBorderRightColor {
1112 inner: ColorU {
1113 r: 38,
1114 g: 160,
1115 b: 218,
1116 a: 255,
1117 },
1118 }),
1119 )),
1120 CssPropertyWithConditions::on_focus(CssProperty::BorderTopColor(
1121 StyleBorderTopColorValue::Exact(StyleBorderTopColor {
1122 inner: ColorU {
1123 r: 38,
1124 g: 160,
1125 b: 218,
1126 a: 255,
1127 },
1128 }),
1129 )),
1130 CssPropertyWithConditions::on_focus(CssProperty::BackgroundContent(
1131 StyleBackgroundContentVecValue::Exact(StyleBackgroundContentVec::from_const_slice(
1132 STYLE_BACKGROUND_CONTENT_11098930083828139815_ITEMS,
1133 )),
1134 )),
1135 CssPropertyWithConditions::on_hover(CssProperty::BorderBottomWidth(
1137 LayoutBorderBottomWidthValue::Exact(LayoutBorderBottomWidth {
1138 inner: PixelValue::const_px(1),
1139 }),
1140 )),
1141 CssPropertyWithConditions::on_hover(CssProperty::BorderLeftWidth(
1142 LayoutBorderLeftWidthValue::Exact(LayoutBorderLeftWidth {
1143 inner: PixelValue::const_px(1),
1144 }),
1145 )),
1146 CssPropertyWithConditions::on_hover(CssProperty::BorderRightWidth(
1147 LayoutBorderRightWidthValue::Exact(LayoutBorderRightWidth {
1148 inner: PixelValue::const_px(1),
1149 }),
1150 )),
1151 CssPropertyWithConditions::on_hover(CssProperty::BorderTopWidth(
1152 LayoutBorderTopWidthValue::Exact(LayoutBorderTopWidth {
1153 inner: PixelValue::const_px(1),
1154 }),
1155 )),
1156 CssPropertyWithConditions::on_hover(CssProperty::BorderBottomStyle(
1157 StyleBorderBottomStyleValue::Exact(StyleBorderBottomStyle {
1158 inner: BorderStyle::Solid,
1159 }),
1160 )),
1161 CssPropertyWithConditions::on_hover(CssProperty::BorderLeftStyle(
1162 StyleBorderLeftStyleValue::Exact(StyleBorderLeftStyle {
1163 inner: BorderStyle::Solid,
1164 }),
1165 )),
1166 CssPropertyWithConditions::on_hover(CssProperty::BorderRightStyle(
1167 StyleBorderRightStyleValue::Exact(StyleBorderRightStyle {
1168 inner: BorderStyle::Solid,
1169 }),
1170 )),
1171 CssPropertyWithConditions::on_hover(CssProperty::BorderTopStyle(
1172 StyleBorderTopStyleValue::Exact(StyleBorderTopStyle {
1173 inner: BorderStyle::Solid,
1174 }),
1175 )),
1176 CssPropertyWithConditions::on_hover(CssProperty::BorderBottomColor(
1177 StyleBorderBottomColorValue::Exact(StyleBorderBottomColor {
1178 inner: ColorU {
1179 r: 101,
1180 g: 181,
1181 b: 220,
1182 a: 255,
1183 },
1184 }),
1185 )),
1186 CssPropertyWithConditions::on_hover(CssProperty::BorderLeftColor(
1187 StyleBorderLeftColorValue::Exact(StyleBorderLeftColor {
1188 inner: ColorU {
1189 r: 101,
1190 g: 181,
1191 b: 220,
1192 a: 255,
1193 },
1194 }),
1195 )),
1196 CssPropertyWithConditions::on_hover(CssProperty::BorderRightColor(
1197 StyleBorderRightColorValue::Exact(StyleBorderRightColor {
1198 inner: ColorU {
1199 r: 101,
1200 g: 181,
1201 b: 220,
1202 a: 255,
1203 },
1204 }),
1205 )),
1206 CssPropertyWithConditions::on_hover(CssProperty::BorderTopColor(
1207 StyleBorderTopColorValue::Exact(StyleBorderTopColor {
1208 inner: ColorU {
1209 r: 101,
1210 g: 181,
1211 b: 220,
1212 a: 255,
1213 },
1214 }),
1215 )),
1216 CssPropertyWithConditions::on_hover(CssProperty::BackgroundContent(
1217 StyleBackgroundContentVecValue::Exact(StyleBackgroundContentVec::from_const_slice(
1218 STYLE_BACKGROUND_CONTENT_3010057533077499049_ITEMS,
1219 )),
1220 )),
1221 CssPropertyWithConditions::simple(CssProperty::PaddingRight(LayoutPaddingRightValue::Exact(
1223 LayoutPaddingRight {
1224 inner: PixelValue::const_px(0),
1225 },
1226 ))),
1227 CssPropertyWithConditions::simple(CssProperty::PaddingLeft(LayoutPaddingLeftValue::Exact(
1228 LayoutPaddingLeft {
1229 inner: PixelValue::const_px(0),
1230 },
1231 ))),
1232 CssPropertyWithConditions::simple(CssProperty::PaddingBottom(LayoutPaddingBottomValue::Exact(
1233 LayoutPaddingBottom {
1234 inner: PixelValue::const_px(2),
1235 },
1236 ))),
1237 CssPropertyWithConditions::simple(CssProperty::PaddingTop(LayoutPaddingTopValue::Exact(
1238 LayoutPaddingTop {
1239 inner: PixelValue::const_px(2),
1240 },
1241 ))),
1242 CssPropertyWithConditions::simple(CssProperty::FlexGrow(LayoutFlexGrowValue::Exact(
1243 LayoutFlexGrow {
1244 inner: FloatValue::const_new(1),
1245 },
1246 ))),
1247 CssPropertyWithConditions::simple(CssProperty::FlexDirection(LayoutFlexDirectionValue::Exact(
1248 LayoutFlexDirection::Row,
1249 ))),
1250 CssPropertyWithConditions::simple(CssProperty::BorderBottomWidth(
1251 LayoutBorderBottomWidthValue::Exact(LayoutBorderBottomWidth {
1252 inner: PixelValue::const_px(1),
1253 }),
1254 )),
1255 CssPropertyWithConditions::simple(CssProperty::BorderLeftWidth(
1256 LayoutBorderLeftWidthValue::Exact(LayoutBorderLeftWidth {
1257 inner: PixelValue::const_px(1),
1258 }),
1259 )),
1260 CssPropertyWithConditions::simple(CssProperty::BorderRightWidth(
1261 LayoutBorderRightWidthValue::Exact(LayoutBorderRightWidth {
1262 inner: PixelValue::const_px(1),
1263 }),
1264 )),
1265 CssPropertyWithConditions::simple(CssProperty::BorderTopWidth(
1266 LayoutBorderTopWidthValue::Exact(LayoutBorderTopWidth {
1267 inner: PixelValue::const_px(1),
1268 }),
1269 )),
1270 CssPropertyWithConditions::simple(CssProperty::BorderBottomStyle(
1271 StyleBorderBottomStyleValue::Exact(StyleBorderBottomStyle {
1272 inner: BorderStyle::Solid,
1273 }),
1274 )),
1275 CssPropertyWithConditions::simple(CssProperty::BorderLeftStyle(
1276 StyleBorderLeftStyleValue::Exact(StyleBorderLeftStyle {
1277 inner: BorderStyle::Solid,
1278 }),
1279 )),
1280 CssPropertyWithConditions::simple(CssProperty::BorderRightStyle(
1281 StyleBorderRightStyleValue::Exact(StyleBorderRightStyle {
1282 inner: BorderStyle::Solid,
1283 }),
1284 )),
1285 CssPropertyWithConditions::simple(CssProperty::BorderTopStyle(
1286 StyleBorderTopStyleValue::Exact(StyleBorderTopStyle {
1287 inner: BorderStyle::Solid,
1288 }),
1289 )),
1290 CssPropertyWithConditions::simple(CssProperty::BorderBottomColor(
1291 StyleBorderBottomColorValue::Exact(StyleBorderBottomColor {
1292 inner: ColorU {
1293 r: 255,
1294 g: 255,
1295 b: 255,
1296 a: 0,
1297 },
1298 }),
1299 )),
1300 CssPropertyWithConditions::simple(CssProperty::BorderLeftColor(
1301 StyleBorderLeftColorValue::Exact(StyleBorderLeftColor {
1302 inner: ColorU {
1303 r: 255,
1304 g: 255,
1305 b: 255,
1306 a: 0,
1307 },
1308 }),
1309 )),
1310 CssPropertyWithConditions::simple(CssProperty::BorderRightColor(
1311 StyleBorderRightColorValue::Exact(StyleBorderRightColor {
1312 inner: ColorU {
1313 r: 255,
1314 g: 255,
1315 b: 255,
1316 a: 0,
1317 },
1318 }),
1319 )),
1320 CssPropertyWithConditions::simple(CssProperty::BorderTopColor(
1321 StyleBorderTopColorValue::Exact(StyleBorderTopColor {
1322 inner: ColorU {
1323 r: 255,
1324 g: 255,
1325 b: 255,
1326 a: 0,
1327 },
1328 }),
1329 )),
1330];
1331const CSS_MATCH_7894335449545988724: CssPropertyWithConditionsVec =
1332 CssPropertyWithConditionsVec::from_const_slice(CSS_MATCH_7894335449545988724_PROPERTIES);
1333
1334const IDS_AND_CLASSES_790316832563530605: &[IdOrClass] = &[Class(AzString::from_const_str(
1335 "__azul_native-list-rows-row",
1336))];
1337const ROW_CLASS: IdOrClassVec = IdOrClassVec::from_const_slice(IDS_AND_CLASSES_790316832563530605);
1338
1339const IDS_AND_CLASSES_3034181810805097699: &[IdOrClass] = &[Class(AzString::from_const_str(
1340 "__azul_native-list-rows-row-cell",
1341))];
1342const CELL_CLASS: IdOrClassVec =
1343 IdOrClassVec::from_const_slice(IDS_AND_CLASSES_3034181810805097699);
1344
1345const IDS_AND_CLASSES_6012478019077291002: &[IdOrClass] =
1346 &[Class(AzString::from_const_str("__azul_native-list-rows"))];
1347const ROW_CONTAINER_CLASS: IdOrClassVec =
1348 IdOrClassVec::from_const_slice(IDS_AND_CLASSES_6012478019077291002);
1349
1350const IDS_AND_CLASSES_10742579426112804392: &[IdOrClass] =
1351 &[Class(AzString::from_const_str("__azul_native-list-header"))];
1352const HEADER_CONTAINER_CLASS: IdOrClassVec =
1353 IdOrClassVec::from_const_slice(IDS_AND_CLASSES_10742579426112804392);
1354
1355const IDS_AND_CLASSES_9205819539370539587: &[IdOrClass] = &[Class(AzString::from_const_str(
1356 "__azul_native_list-container",
1357))];
1358const LIST_VIEW_CONTAINER_CLASS: IdOrClassVec =
1359 IdOrClassVec::from_const_slice(IDS_AND_CLASSES_9205819539370539587);
1360
1361const IDS_AND_CLASSES_18330792117162403422: &[IdOrClass] = &[Class(AzString::from_const_str(
1362 "__azul_native-list-header-item",
1363))];
1364const COLUMN_NAME_CLASS: IdOrClassVec =
1365 IdOrClassVec::from_const_slice(IDS_AND_CLASSES_18330792117162403422);
1366
1367pub type ListViewOnLazyLoadScrollCallbackType =
1368 extern "C" fn(RefAny, CallbackInfo, ListViewState) -> Update;
1369impl_widget_callback!(
1370 ListViewOnLazyLoadScroll,
1371 OptionListViewOnLazyLoadScroll,
1372 ListViewOnLazyLoadScrollCallback,
1373 ListViewOnLazyLoadScrollCallbackType
1374);
1375
1376azul_core::impl_managed_callback! {
1377 wrapper: ListViewOnLazyLoadScrollCallback,
1378 info_ty: CallbackInfo,
1379 return_ty: Update,
1380 default_ret: Update::DoNothing,
1381 invoker_static: LIST_VIEW_ON_LAZY_LOAD_SCROLL_INVOKER,
1382 invoker_ty: AzListViewOnLazyLoadScrollCallbackInvoker,
1383 thunk_fn: az_list_view_on_lazy_load_scroll_callback_thunk,
1384 setter_fn: AzApp_setListViewOnLazyLoadScrollCallbackInvoker,
1385 from_handle_fn: AzListViewOnLazyLoadScrollCallback_createFromHostHandle,
1386 extra_args: [ state: ListViewState ],
1387}
1388
1389pub type ListViewOnColumnClickCallbackType =
1390 extern "C" fn(RefAny, CallbackInfo, ListViewState, column_clicked: usize) -> Update;
1391impl_widget_callback!(
1392 ListViewOnColumnClick,
1393 OptionListViewOnColumnClick,
1394 ListViewOnColumnClickCallback,
1395 ListViewOnColumnClickCallbackType
1396);
1397
1398azul_core::impl_managed_callback! {
1399 wrapper: ListViewOnColumnClickCallback,
1400 info_ty: CallbackInfo,
1401 return_ty: Update,
1402 default_ret: Update::DoNothing,
1403 invoker_static: LIST_VIEW_ON_COLUMN_CLICK_INVOKER,
1404 invoker_ty: AzListViewOnColumnClickCallbackInvoker,
1405 thunk_fn: az_list_view_on_column_click_callback_thunk,
1406 setter_fn: AzApp_setListViewOnColumnClickCallbackInvoker,
1407 from_handle_fn: AzListViewOnColumnClickCallback_createFromHostHandle,
1408 extra_args: [ state: ListViewState, column_clicked: usize ],
1409}
1410
1411pub type ListViewOnRowClickCallbackType =
1412 extern "C" fn(RefAny, CallbackInfo, ListViewState, row_clicked: usize) -> Update;
1413impl_widget_callback!(
1414 ListViewOnRowClick,
1415 OptionListViewOnRowClick,
1416 ListViewOnRowClickCallback,
1417 ListViewOnRowClickCallbackType
1418);
1419
1420azul_core::impl_managed_callback! {
1421 wrapper: ListViewOnRowClickCallback,
1422 info_ty: CallbackInfo,
1423 return_ty: Update,
1424 default_ret: Update::DoNothing,
1425 invoker_static: LIST_VIEW_ON_ROW_CLICK_INVOKER,
1426 invoker_ty: AzListViewOnRowClickCallbackInvoker,
1427 thunk_fn: az_list_view_on_row_click_callback_thunk,
1428 setter_fn: AzApp_setListViewOnRowClickCallbackInvoker,
1429 from_handle_fn: AzListViewOnRowClickCallback_createFromHostHandle,
1430 extra_args: [ state: ListViewState, row_clicked: usize ],
1431}
1432
1433#[derive(Debug, Clone)]
1435#[repr(C)]
1436pub struct ListViewState {
1437 pub columns: StringVec,
1439 pub sorted_by: OptionUsize,
1441 pub current_row_count: usize,
1443 pub scroll_offset: PixelValueNoPercent,
1445 pub current_scroll_position: LogicalPosition,
1447 pub current_content_height: LogicalSize,
1449}
1450
1451#[derive(Debug, Clone)]
1453#[repr(C)]
1454pub struct ListView {
1455 pub columns: StringVec,
1457 pub rows: ListViewRowVec,
1461 pub sorted_by: OptionUsize,
1463 pub scroll_offset: PixelValueNoPercent,
1466 pub content_height: OptionPixelValueNoPercent,
1468 pub column_context_menu: OptionMenu,
1471 pub on_lazy_load_scroll: OptionListViewOnLazyLoadScroll,
1474 pub on_column_click: OptionListViewOnColumnClick,
1477 pub on_row_click: OptionListViewOnRowClick,
1480}
1481
1482impl Default for ListView {
1483 fn default() -> Self {
1484 Self {
1485 columns: StringVec::from_const_slice(&[]),
1486 rows: ListViewRowVec::from_const_slice(&[]),
1487 sorted_by: None.into(),
1488 scroll_offset: PixelValueNoPercent {
1489 inner: PixelValue::const_px(0),
1490 },
1491 content_height: None.into(),
1492 column_context_menu: None.into(),
1493 on_lazy_load_scroll: None.into(),
1494 on_column_click: None.into(),
1495 on_row_click: None.into(),
1496 }
1497 }
1498}
1499
1500#[derive(Debug, Clone)]
1502#[repr(C)]
1503pub struct ListViewRow {
1504 pub cells: DomVec,
1506 pub height: OptionPixelValueNoPercent,
1508}
1509
1510impl_option!(ListViewRow, OptionListViewRow, copy = false, [Debug, Clone]);
1511impl_vec!(ListViewRow, ListViewRowVec, ListViewRowVecDestructor, ListViewRowVecDestructorType, ListViewRowVecSlice, OptionListViewRow);
1512impl_vec_clone!(ListViewRow, ListViewRowVec, ListViewRowVecDestructor);
1513impl_vec_mut!(ListViewRow, ListViewRowVec);
1514impl_vec_debug!(ListViewRow, ListViewRowVec);
1515
1516impl ListView {
1517 #[must_use] pub fn create(columns: StringVec) -> Self {
1518 Self {
1519 columns,
1520 ..Default::default()
1521 }
1522 }
1523
1524 #[must_use]
1525 pub fn swap_with_default(&mut self) -> Self {
1526 let mut m = Self::default();
1527 core::mem::swap(&mut m, self);
1528 m
1529 }
1530
1531 #[must_use] pub fn with_columns(mut self, columns: StringVec) -> Self {
1532 self.set_columns(columns);
1533 self
1534 }
1535
1536 pub fn set_columns(&mut self, columns: StringVec) {
1537 self.columns = columns;
1538 }
1539
1540 #[must_use] pub fn with_rows(mut self, rows: ListViewRowVec) -> Self {
1541 self.set_rows(rows);
1542 self
1543 }
1544
1545 pub fn set_rows(&mut self, rows: ListViewRowVec) {
1546 self.rows = rows;
1547 }
1548
1549 #[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)] #[must_use] pub fn visible_row_range(
1560 scroll_y: f32,
1561 viewport_height: f32,
1562 row_height: f32,
1563 total_rows: usize,
1564 ) -> (usize, usize) {
1565 if total_rows == 0
1566 || !row_height.is_finite()
1567 || row_height <= 0.0
1568 || !viewport_height.is_finite()
1569 || viewport_height <= 0.0
1570 || !scroll_y.is_finite()
1571 {
1572 return (0, 0);
1573 }
1574 let first = (scroll_y.max(0.0) / row_height).floor() as usize;
1575 if first >= total_rows {
1576 return (total_rows, total_rows);
1577 }
1578 let visible = ((viewport_height / row_height).ceil() as usize).saturating_add(1);
1583 let last = first.saturating_add(visible).min(total_rows);
1584 (first, last)
1585 }
1586
1587 #[must_use] pub const fn with_sorted_by(mut self, sorted_by: OptionUsize) -> Self {
1588 self.set_sorted_by(sorted_by);
1589 self
1590 }
1591
1592 pub const fn set_sorted_by(&mut self, sorted_by: OptionUsize) {
1593 self.sorted_by = sorted_by;
1594 }
1595
1596 #[must_use] pub const fn with_scroll_offset(mut self, scroll_offset: PixelValueNoPercent) -> Self {
1597 self.set_scroll_offset(scroll_offset);
1598 self
1599 }
1600
1601 pub const fn set_scroll_offset(&mut self, scroll_offset: PixelValueNoPercent) {
1602 self.scroll_offset = scroll_offset;
1603 }
1604
1605 #[must_use] pub fn with_content_height(mut self, content_height: PixelValueNoPercent) -> Self {
1606 self.set_content_height(content_height);
1607 self
1608 }
1609
1610 pub fn set_content_height(&mut self, content_height: PixelValueNoPercent) {
1611 self.content_height = Some(content_height).into();
1612 }
1613
1614 #[must_use] pub fn with_column_context_menu(mut self, context_menu: Menu) -> Self {
1615 self.set_column_context_menu(context_menu);
1616 self
1617 }
1618
1619 pub fn set_column_context_menu(&mut self, column_context_menu: Menu) {
1620 self.column_context_menu = Some(column_context_menu).into();
1621 }
1622
1623 #[must_use]
1624 pub fn with_on_column_click<C: Into<ListViewOnColumnClickCallback>>(
1625 mut self,
1626 refany: RefAny,
1627 on_column_click: C,
1628 ) -> Self {
1629 self.set_on_column_click(refany, on_column_click);
1630 self
1631 }
1632
1633 pub fn set_on_column_click<C: Into<ListViewOnColumnClickCallback>>(
1634 &mut self,
1635 refany: RefAny,
1636 on_column_click: C,
1637 ) {
1638 self.on_column_click = Some(ListViewOnColumnClick {
1639 refany,
1640 callback: on_column_click.into(),
1641 })
1642 .into();
1643 }
1644
1645 #[must_use]
1646 pub fn with_on_row_click<C: Into<ListViewOnRowClickCallback>>(
1647 mut self,
1648 refany: RefAny,
1649 on_row_click: C,
1650 ) -> Self {
1651 self.set_on_row_click(refany, on_row_click);
1652 self
1653 }
1654
1655 pub fn set_on_row_click<C: Into<ListViewOnRowClickCallback>>(
1656 &mut self,
1657 refany: RefAny,
1658 on_row_click: C,
1659 ) {
1660 self.on_row_click = Some(ListViewOnRowClick {
1661 refany,
1662 callback: on_row_click.into(),
1663 })
1664 .into();
1665 }
1666
1667 #[must_use] pub fn dom(self) -> Dom {
1668 let state = ListViewState {
1672 columns: self.columns.clone(),
1673 sorted_by: self.sorted_by,
1674 current_row_count: self.rows.as_ref().len(),
1675 scroll_offset: self.scroll_offset,
1676 current_scroll_position: LogicalPosition::zero(),
1677 current_content_height: LogicalSize::zero(),
1678 };
1679 let on_column_click = self.on_column_click.clone();
1680 let on_row_click = self.on_row_click.clone();
1681
1682 Dom::create_div()
1683 .with_css_props(CSS_MATCH_17553577885456905601)
1684 .with_ids_and_classes(LIST_VIEW_CONTAINER_CLASS)
1685 .with_children(DomVec::from_vec(vec![
1686 Dom::create_div()
1688 .with_css_props(CSS_MATCH_15315949193378715186)
1689 .with_ids_and_classes(HEADER_CONTAINER_CLASS)
1690 .with_children(
1691 self.columns
1692 .iter()
1693 .enumerate()
1694 .map(|(col_index, col)| {
1695 let col_dom = Dom::create_div()
1696 .with_css_props(CSS_MATCH_12498280255863106397)
1697 .with_ids_and_classes(COLUMN_NAME_CLASS)
1698 .with_child({
1699 Dom::create_text(col.clone())
1700 .with_css_props(CSS_MATCH_15673486787900743642)
1701 });
1702 match &on_column_click {
1704 OptionListViewOnColumnClick::Some(_) => col_dom.with_callbacks(
1705 vec![CoreCallbackData {
1706 event: EventFilter::Hover(HoverEventFilter::MouseUp),
1707 refany: RefAny::new(ColumnClickData {
1708 col_index,
1709 state: state.clone(),
1710 on_column_click: on_column_click.clone(),
1711 }),
1712 callback: CoreCallback {
1713 cb: on_list_view_column_click as usize,
1714 ctx: OptionRefAny::None,
1715 },
1716 }]
1717 .into(),
1718 ),
1719 OptionListViewOnColumnClick::None => col_dom,
1720 }
1721 })
1722 .collect::<Vec<_>>()
1723 .into(),
1724 ),
1725 Dom::create_div()
1727 .with_css_props(CSS_MATCH_4852927511892172364)
1728 .with_ids_and_classes(ROW_CONTAINER_CLASS)
1729 .with_children(
1730 self.rows
1731 .into_iter()
1732 .enumerate()
1733 .map(|(row_index, row)| {
1734 let row_dom = Dom::create_div()
1735 .with_css_props(CSS_MATCH_7894335449545988724)
1736 .with_ids_and_classes(ROW_CLASS)
1737 .with_tab_index(TabIndex::Auto)
1738 .with_children(
1739 row.cells
1740 .as_ref()
1741 .iter()
1742 .map(|cell| {
1743 Dom::create_div()
1744 .with_css_props(CSS_MATCH_12980082330151137475)
1745 .with_ids_and_classes(CELL_CLASS)
1746 .with_child(cell.clone())
1747 })
1748 .collect::<Vec<_>>()
1749 .into(),
1750 );
1751 match &on_row_click {
1752 OptionListViewOnRowClick::Some(_) => row_dom.with_callbacks(
1753 vec![CoreCallbackData {
1754 event: EventFilter::Hover(HoverEventFilter::MouseUp),
1755 refany: RefAny::new(RowClickData {
1756 row_index,
1757 state: state.clone(),
1758 on_row_click: on_row_click.clone(),
1759 }),
1760 callback: CoreCallback {
1761 cb: on_list_view_row_click as usize,
1762 ctx: OptionRefAny::None,
1763 },
1764 }]
1765 .into(),
1766 ),
1767 OptionListViewOnRowClick::None => row_dom,
1768 }
1769 })
1770 .collect::<Vec<_>>()
1771 .into(),
1772 ),
1773 ]))
1774 }
1775}
1776
1777struct RowClickData {
1780 row_index: usize,
1781 state: ListViewState,
1782 on_row_click: OptionListViewOnRowClick,
1783}
1784
1785struct ColumnClickData {
1787 col_index: usize,
1788 state: ListViewState,
1789 on_column_click: OptionListViewOnColumnClick,
1790}
1791
1792extern "C" fn on_list_view_row_click(mut refany: RefAny, info: CallbackInfo) -> Update {
1794 let Some(data) = refany.downcast_ref::<RowClickData>() else {
1795 return Update::DoNothing;
1796 };
1797 match data.on_row_click.as_ref() {
1798 Some(ListViewOnRowClick { refany: user_data, callback }) => {
1799 (callback.cb)(user_data.clone(), info, data.state.clone(), data.row_index)
1800 }
1801 None => Update::DoNothing,
1802 }
1803}
1804
1805extern "C" fn on_list_view_column_click(mut refany: RefAny, info: CallbackInfo) -> Update {
1807 let Some(data) = refany.downcast_ref::<ColumnClickData>() else {
1808 return Update::DoNothing;
1809 };
1810 match data.on_column_click.as_ref() {
1811 Some(ListViewOnColumnClick { refany: user_data, callback }) => {
1812 (callback.cb)(user_data.clone(), info, data.state.clone(), data.col_index)
1813 }
1814 None => Update::DoNothing,
1815 }
1816}
1817
1818#[cfg(test)]
1819mod list_view_click_tests {
1820 use super::*;
1821
1822 #[test]
1826 fn visible_row_range_windows_correctly() {
1827 assert_eq!(ListView::visible_row_range(0.0, 200.0, 20.0, 100), (0, 11));
1829 assert_eq!(ListView::visible_row_range(50.0, 200.0, 20.0, 100), (2, 13));
1831 assert_eq!(ListView::visible_row_range(1900.0, 200.0, 20.0, 100), (95, 100));
1833 assert_eq!(ListView::visible_row_range(5000.0, 200.0, 20.0, 100), (100, 100));
1835 assert_eq!(ListView::visible_row_range(0.0, 200.0, 20.0, 0), (0, 0));
1837 assert_eq!(ListView::visible_row_range(0.0, 200.0, 0.0, 100), (0, 0));
1838 assert_eq!(ListView::visible_row_range(f32::NAN, 200.0, 20.0, 100), (0, 0));
1839 }
1840
1841 extern "C" fn noop_row(_: RefAny, _: CallbackInfo, _: ListViewState, _: usize) -> Update {
1842 Update::DoNothing
1843 }
1844
1845 fn empty_row() -> ListViewRow {
1846 ListViewRow {
1847 cells: DomVec::from_const_slice(&[]),
1848 height: None.into(),
1849 }
1850 }
1851
1852 #[test]
1855 #[allow(clippy::field_reassign_with_default)] fn rows_get_a_click_callback_only_when_on_row_click_is_set() {
1857 let mut lv = ListView::default();
1858 lv.rows = ListViewRowVec::from_vec(vec![empty_row(), empty_row()]);
1859 let on_row_click: ListViewOnRowClickCallbackType = noop_row;
1860 lv.set_on_row_click(RefAny::new(()), on_row_click);
1861 let dom = lv.dom();
1862 let rows = dom.children.as_ref()[1].children.as_ref();
1864 assert_eq!(rows.len(), 2);
1865 for row in rows {
1866 assert_eq!(
1867 row.root.callbacks.as_ref().len(),
1868 1,
1869 "row must carry the click callback when on_row_click is set"
1870 );
1871 }
1872
1873 let mut bare = ListView::default();
1875 bare.rows = ListViewRowVec::from_vec(vec![empty_row()]);
1876 let dom2 = bare.dom();
1877 let rows2 = dom2.children.as_ref()[1].children.as_ref();
1878 assert_eq!(rows2.len(), 1);
1879 assert!(
1880 rows2[0].root.callbacks.as_ref().is_empty(),
1881 "no callback when on_row_click is unset"
1882 );
1883 }
1884}
1885
1886#[cfg(test)]
1887#[allow(clippy::float_cmp)] mod autotest_generated {
1889 use azul_core::{
1890 dom::NodeType,
1891 menu::{MenuItem, MenuItemVec},
1892 };
1893
1894 use super::*;
1895
1896 fn cols(names: &[&str]) -> StringVec {
1901 StringVec::from_vec(names.iter().map(|s| AzString::from(*s)).collect::<Vec<_>>())
1902 }
1903
1904 fn row_with(n: usize) -> ListViewRow {
1906 ListViewRow {
1907 cells: DomVec::from_vec(
1908 (0..n)
1909 .map(|i| Dom::create_text(format!("c{i}")))
1910 .collect::<Vec<_>>(),
1911 ),
1912 height: None.into(),
1913 }
1914 }
1915
1916 fn px(v: f32) -> PixelValueNoPercent {
1917 PixelValueNoPercent {
1918 inner: PixelValue::px(v),
1919 }
1920 }
1921
1922 extern "C" fn noop_row_cb(_: RefAny, _: CallbackInfo, _: ListViewState, _: usize) -> Update {
1923 Update::DoNothing
1924 }
1925
1926 extern "C" fn noop_col_cb(_: RefAny, _: CallbackInfo, _: ListViewState, _: usize) -> Update {
1927 Update::DoNothing
1928 }
1929
1930 fn header_and_rows(dom: &Dom) -> (&Dom, &Dom) {
1932 let ch = dom.children.as_ref();
1933 assert_eq!(ch.len(), 2, "list view DOM = [header, rows]");
1934 (&ch[0], &ch[1])
1935 }
1936
1937 fn text_of(dom: &Dom) -> &str {
1938 match &dom.root.node_type {
1939 NodeType::Text(s) => s.as_ref().as_str(),
1940 _ => panic!("expected a text node"),
1941 }
1942 }
1943
1944 #[test]
1951 fn visible_row_range_zero_and_degenerate_inputs_are_empty() {
1952 assert_eq!(ListView::visible_row_range(0.0, 100.0, 10.0, 0), (0, 0));
1953 assert_eq!(ListView::visible_row_range(0.0, 100.0, 0.0, 5), (0, 0));
1954 assert_eq!(ListView::visible_row_range(0.0, 100.0, -0.0, 5), (0, 0));
1955 assert_eq!(ListView::visible_row_range(0.0, 100.0, -10.0, 5), (0, 0));
1956 assert_eq!(ListView::visible_row_range(0.0, 0.0, 10.0, 5), (0, 0));
1957 assert_eq!(ListView::visible_row_range(0.0, -0.0, 10.0, 5), (0, 0));
1958 assert_eq!(ListView::visible_row_range(0.0, -100.0, 10.0, 5), (0, 0));
1959 assert_eq!(ListView::visible_row_range(0.0, 0.0, 0.0, 0), (0, 0));
1960 }
1961
1962 #[test]
1965 fn visible_row_range_negative_scroll_clamps_to_the_top_window() {
1966 let top = ListView::visible_row_range(0.0, 200.0, 20.0, 100);
1967 assert_eq!(top, (0, 11), "10 full rows + 1 straddling the bottom edge");
1968 for s in [-0.0_f32, -1.0, -0.5, -1e9, -f32::MAX, -f32::MIN_POSITIVE] {
1969 assert_eq!(
1970 ListView::visible_row_range(s, 200.0, 20.0, 100),
1971 top,
1972 "negative scroll {s} must clamp to the top window"
1973 );
1974 }
1975 }
1976
1977 #[test]
1980 fn visible_row_range_nan_and_infinite_inputs_are_empty() {
1981 for b in [f32::NAN, f32::INFINITY, f32::NEG_INFINITY] {
1982 assert_eq!(
1983 ListView::visible_row_range(b, 200.0, 20.0, 100),
1984 (0, 0),
1985 "scroll_y = {b}"
1986 );
1987 assert_eq!(
1988 ListView::visible_row_range(0.0, b, 20.0, 100),
1989 (0, 0),
1990 "viewport_height = {b}"
1991 );
1992 assert_eq!(
1993 ListView::visible_row_range(0.0, 200.0, b, 100),
1994 (0, 0),
1995 "row_height = {b}"
1996 );
1997 }
1998 assert_eq!(
2000 ListView::visible_row_range(f32::NAN, f32::NAN, f32::NAN, usize::MAX),
2001 (0, 0)
2002 );
2003 }
2004
2005 #[test]
2008 fn visible_row_range_past_the_end_is_an_empty_tail_range() {
2009 assert_eq!(
2011 ListView::visible_row_range(200.0, 100.0, 20.0, 10),
2012 (10, 10)
2013 );
2014 assert_eq!(
2015 ListView::visible_row_range(1e9, 200.0, 20.0, 100),
2016 (100, 100)
2017 );
2018 assert_eq!(
2020 ListView::visible_row_range(f32::MAX, 200.0, 20.0, 100),
2021 (100, 100)
2022 );
2023 let (first, last) = ListView::visible_row_range(199.0, 100.0, 20.0, 10);
2025 assert!(first < last, "just before the end the range is non-empty");
2026 assert_eq!(last, 10, "and clamps to the row count");
2027 }
2028
2029 #[test]
2032 fn visible_row_range_window_size_is_bounded_by_the_viewport_not_the_row_count() {
2033 for total in [1_usize, 2, 1000, u32::MAX as usize, usize::MAX] {
2034 let (first, last) = ListView::visible_row_range(0.0, 200.0, 20.0, total);
2035 assert_eq!(first, 0);
2036 assert_eq!(
2037 last,
2038 11.min(total),
2039 "window stays viewport-sized for total_rows = {total}"
2040 );
2041 }
2042 }
2043
2044 #[test]
2047 fn visible_row_range_window_always_covers_the_viewport() {
2048 let total = 1000_usize;
2049 for &h in &[1.0_f32, 7.5, 20.0, 33.3] {
2050 for &vp in &[1.0_f32, 17.0, 200.0, 999.0] {
2051 for &s in &[0.0_f32, 0.1, 19.0, 123.456, 5000.0] {
2052 let (first, last) = ListView::visible_row_range(s, vp, h, total);
2053 assert!(first <= last, "well-ordered range for ({s}, {vp}, {h})");
2054 assert!(last <= total, "range clamps to the row count");
2055 if first == last {
2056 continue; }
2058 let top = first as f32 * h;
2059 let bottom = last as f32 * h;
2060 assert!(top <= s, "window starts at or above scroll {s} (top {top})");
2061 let needed = (s + vp).min(total as f32 * h);
2062 assert!(
2063 bottom >= needed,
2064 "window bottom {bottom} must reach {needed} for ({s}, {vp}, {h})"
2065 );
2066 }
2067 }
2068 }
2069 }
2070
2071 #[test]
2080 fn visible_row_range_does_not_overflow_on_extreme_but_finite_input() {
2081 assert_eq!(ListView::visible_row_range(0.0, 1000.0, 1e-30, 10), (0, 10));
2084
2085 let (first, last) = ListView::visible_row_range(1.0e19, 1.0e19, 1.0, usize::MAX);
2088 assert!(first > 0, "a huge scroll lands deep in the list");
2089 assert_eq!(last, usize::MAX, "the window must clamp to the row count");
2090 }
2091
2092 #[test]
2097 fn create_sets_columns_and_leaves_everything_else_default() {
2098 let lv = ListView::create(cols(&["a", "b", "c"]));
2099 assert_eq!(lv.columns.len(), 3);
2100 assert_eq!(lv.columns.as_ref()[1].as_str(), "b");
2101 assert!(lv.rows.is_empty());
2102 assert!(lv.sorted_by.is_none());
2103 assert!(lv.content_height.is_none());
2104 assert!(lv.column_context_menu.is_none());
2105 assert!(lv.on_lazy_load_scroll.is_none());
2106 assert!(lv.on_column_click.is_none());
2107 assert!(lv.on_row_click.is_none());
2108 assert_eq!(lv.scroll_offset, PixelValueNoPercent::zero());
2109
2110 let empty = ListView::create(StringVec::from_const_slice(&[]));
2112 assert!(empty.columns.is_empty());
2113 }
2114
2115 #[test]
2116 fn with_and_set_columns_replace_rather_than_append() {
2117 let b = cols(&["x", "y"]);
2118 let lv = ListView::default()
2119 .with_columns(cols(&["one"]))
2120 .with_columns(b.clone());
2121 assert_eq!(lv.columns, b, "the last write wins");
2122
2123 let mut m = ListView::default();
2124 m.set_columns(b.clone());
2125 assert_eq!(m.columns, b);
2126 m.set_columns(StringVec::from_const_slice(&[]));
2127 assert!(m.columns.is_empty(), "columns can be cleared again");
2128 }
2129
2130 #[test]
2134 fn columns_round_trip_unicode_and_pathological_strings() {
2135 let names: Vec<String> = vec![
2136 String::new(),
2137 "\u{0}".to_string(),
2138 "๐ฆ๐จโ๐ฉโ๐งโ๐ฆ".to_string(),
2139 "ู
ุฑุญุจุง ุจุงูุนุงูู
".to_string(),
2140 "e\u{301}\u{301}\u{301}".to_string(),
2141 "\u{feff}leading BOM".to_string(),
2142 "line\nbreak\ttab".to_string(),
2143 "x".repeat(10_000),
2144 ];
2145 let sv = StringVec::from_vec(
2146 names
2147 .iter()
2148 .map(|s| AzString::from(s.clone()))
2149 .collect::<Vec<_>>(),
2150 );
2151 let lv = ListView::default().with_columns(sv);
2152 assert_eq!(lv.columns.len(), names.len());
2153 for (got, want) in lv.columns.iter().zip(names.iter()) {
2154 assert_eq!(got.as_str(), want.as_str(), "column name must round-trip");
2155 }
2156
2157 let dom = lv.dom();
2158 let (header, _) = header_and_rows(&dom);
2159 let hdr = header.children.as_ref();
2160 assert_eq!(hdr.len(), names.len());
2161 for (col, want) in hdr.iter().zip(names.iter()) {
2162 let text = col.children.as_ref();
2163 assert_eq!(text.len(), 1, "each header cell holds one text node");
2164 assert_eq!(text_of(&text[0]), want.as_str());
2165 }
2166 }
2167
2168 #[test]
2169 fn with_and_set_rows_round_trip_including_empty_and_ragged_rows() {
2170 let lv = ListView::default().with_rows(ListViewRowVec::from_vec(vec![
2171 row_with(0),
2172 row_with(1),
2173 row_with(5),
2174 ]));
2175 assert_eq!(lv.rows.len(), 3);
2176 assert_eq!(lv.rows.as_ref()[0].cells.len(), 0);
2177 assert_eq!(lv.rows.as_ref()[2].cells.len(), 5);
2178
2179 let mut m = ListView::default().with_rows(ListViewRowVec::from_vec(vec![row_with(2)]));
2180 m.set_rows(ListViewRowVec::from_const_slice(&[]));
2181 assert!(m.rows.is_empty(), "rows can be cleared again");
2182 }
2183
2184 #[test]
2187 fn sorted_by_is_stored_verbatim_even_when_out_of_range() {
2188 for v in [None, Some(0_usize), Some(2), Some(usize::MAX)] {
2189 let lv = ListView::create(cols(&["a", "b"])).with_sorted_by(v.into());
2190 assert_eq!(
2191 lv.sorted_by.as_ref().copied(),
2192 v,
2193 "sorted_by is not validated against the column count"
2194 );
2195 let dom = lv.dom();
2196 let (header, _) = header_and_rows(&dom);
2197 assert_eq!(header.children.as_ref().len(), 2);
2198 }
2199
2200 let mut m = ListView::default();
2201 m.set_sorted_by(Some(7_usize).into());
2202 assert_eq!(m.sorted_by.as_ref().copied(), Some(7));
2203 m.set_sorted_by(None.into());
2204 assert!(m.sorted_by.is_none(), "sorted_by can be reset to None");
2205 }
2206
2207 #[test]
2211 fn scroll_offset_round_trips_extreme_and_non_finite_values() {
2212 for v in [
2213 0.0_f32,
2214 -0.0,
2215 1.0,
2216 -1.0,
2217 0.001,
2218 -12345.678,
2219 f32::MAX,
2220 f32::MIN,
2221 f32::MIN_POSITIVE,
2222 f32::NAN,
2223 f32::INFINITY,
2224 f32::NEG_INFINITY,
2225 ] {
2226 let p = px(v);
2227 let lv = ListView::default().with_scroll_offset(p);
2228 assert_eq!(lv.scroll_offset, p, "scroll_offset stored verbatim ({v})");
2229 let got = lv.scroll_offset.inner.number.get();
2230 assert!(
2231 got.is_finite(),
2232 "encoded offset stays finite for {v} (got {got})"
2233 );
2234 }
2235
2236 assert_eq!(px(f32::NAN).inner.number.get(), 0.0, "NaN saturates to 0");
2237 assert!(px(f32::INFINITY).inner.number.get() > 0.0);
2238 assert!(px(f32::NEG_INFINITY).inner.number.get() < 0.0);
2239
2240 let mut m = ListView::default();
2241 m.set_scroll_offset(px(5.0));
2242 m.set_scroll_offset(px(-5.0));
2243 assert_eq!(m.scroll_offset, px(-5.0), "the last write wins");
2244 }
2245
2246 #[test]
2250 fn scroll_offset_accepts_a_percent_metric_despite_the_type_name() {
2251 let percent = PixelValueNoPercent {
2252 inner: PixelValue::percent(50.0),
2253 };
2254 let lv = ListView::default().with_scroll_offset(percent);
2255 assert_eq!(lv.scroll_offset, percent);
2256 assert_eq!(lv.scroll_offset.inner.metric, SizeMetric::Percent);
2257 }
2258
2259 #[test]
2260 fn content_height_wraps_in_some_and_has_no_clearing_setter() {
2261 let mut m = ListView::default();
2262 assert!(m.content_height.is_none(), "unset by default");
2263 for v in [0.0_f32, -1.0, f32::MAX, f32::NAN, f32::NEG_INFINITY] {
2264 let p = px(v);
2265 m.set_content_height(p);
2266 assert_eq!(m.content_height.as_ref(), Some(&p), "stores {v} verbatim");
2267 assert!(m
2268 .content_height
2269 .as_ref()
2270 .expect("just set")
2271 .inner
2272 .number
2273 .get()
2274 .is_finite());
2275 }
2276 assert!(
2277 m.content_height.is_some(),
2278 "Some() is sticky โ no unset API"
2279 );
2280
2281 let lv = ListView::default().with_content_height(px(42.0));
2282 assert_eq!(lv.content_height.as_ref(), Some(&px(42.0)));
2283 }
2284
2285 #[test]
2286 fn column_context_menu_is_stored_and_replaced() {
2287 let mut m = ListView::default();
2288 assert!(m.column_context_menu.is_none());
2289
2290 let empty_menu = Menu::create(MenuItemVec::from_const_slice(&[]));
2291 m.set_column_context_menu(empty_menu.clone());
2292 assert_eq!(
2293 m.column_context_menu.as_ref(),
2294 Some(&empty_menu),
2295 "an empty menu is accepted, not silently dropped"
2296 );
2297
2298 let full = Menu::create(MenuItemVec::from_vec(vec![MenuItem::Separator; 256]));
2299 m.set_column_context_menu(full.clone());
2300 assert_eq!(
2301 m.column_context_menu.as_ref(),
2302 Some(&full),
2303 "last write wins"
2304 );
2305 assert!(
2306 m.column_context_menu.is_some(),
2307 "there is no way to unset it"
2308 );
2309
2310 let lv = ListView::default().with_column_context_menu(full.clone());
2311 assert_eq!(lv.column_context_menu.as_ref(), Some(&full));
2312 let dom = lv.dom();
2314 let (header, rows) = header_and_rows(&dom);
2315 assert!(header.children.as_ref().is_empty());
2316 assert!(rows.children.as_ref().is_empty());
2317 }
2318
2319 #[test]
2320 fn click_hook_setters_replace_rather_than_accumulate() {
2321 let rcb: ListViewOnRowClickCallbackType = noop_row_cb;
2322 let ccb: ListViewOnColumnClickCallbackType = noop_col_cb;
2323
2324 let mut m = ListView::default();
2325 assert!(m.on_row_click.is_none());
2326 assert!(m.on_column_click.is_none());
2327 m.set_on_row_click(RefAny::new(1_u32), rcb);
2328 m.set_on_row_click(RefAny::new(2_u32), rcb);
2329 assert!(m.on_row_click.is_some());
2330 let mut payload = m.on_row_click.as_ref().expect("just set").refany.clone();
2331 assert_eq!(
2332 *payload.downcast_ref::<u32>().expect("u32 payload"),
2333 2,
2334 "the second registration replaces the first"
2335 );
2336
2337 let lv = ListView::default()
2338 .with_on_row_click(RefAny::new(()), rcb)
2339 .with_on_column_click(RefAny::new(()), ccb);
2340 assert!(lv.on_row_click.is_some());
2341 assert!(lv.on_column_click.is_some());
2342 assert!(
2343 lv.on_lazy_load_scroll.is_none(),
2344 "unrelated hooks stay unset"
2345 );
2346 }
2347
2348 #[test]
2353 fn swap_with_default_moves_state_out_and_leaves_a_pristine_default() {
2354 let rcb: ListViewOnRowClickCallbackType = noop_row_cb;
2355 let mut lv = ListView::create(cols(&["a", "b"]))
2356 .with_rows(ListViewRowVec::from_vec(vec![row_with(1)]))
2357 .with_sorted_by(Some(1_usize).into())
2358 .with_scroll_offset(px(9.0))
2359 .with_content_height(px(1000.0))
2360 .with_column_context_menu(Menu::create(MenuItemVec::from_const_slice(&[])))
2361 .with_on_row_click(RefAny::new(()), rcb);
2362
2363 let taken = lv.swap_with_default();
2364 assert_eq!(taken.columns.len(), 2);
2365 assert_eq!(taken.rows.len(), 1);
2366 assert_eq!(taken.sorted_by.as_ref().copied(), Some(1));
2367 assert_eq!(taken.scroll_offset, px(9.0));
2368 assert!(taken.content_height.is_some());
2369 assert!(taken.column_context_menu.is_some());
2370 assert!(taken.on_row_click.is_some());
2371
2372 assert!(lv.columns.is_empty());
2373 assert!(lv.rows.is_empty());
2374 assert!(lv.sorted_by.is_none());
2375 assert_eq!(lv.scroll_offset, PixelValueNoPercent::zero());
2376 assert!(lv.content_height.is_none());
2377 assert!(lv.column_context_menu.is_none());
2378 assert!(lv.on_row_click.is_none());
2379 assert!(lv.on_column_click.is_none());
2380 assert!(lv.on_lazy_load_scroll.is_none());
2381
2382 let again = lv.swap_with_default();
2385 assert!(again.columns.is_empty() && again.rows.is_empty());
2386 let third = lv.swap_with_default();
2387 assert!(third.columns.is_empty() && third.rows.is_empty());
2388 drop(taken);
2389 }
2390
2391 #[test]
2396 fn dom_shape_matches_the_column_and_row_counts() {
2397 let empty = ListView::default().dom();
2398 let (h, r) = header_and_rows(&empty);
2399 assert!(h.children.as_ref().is_empty());
2400 assert!(r.children.as_ref().is_empty());
2401
2402 let no_rows = ListView::create(cols(&["a", "b"])).dom();
2404 let (h, r) = header_and_rows(&no_rows);
2405 assert_eq!(h.children.as_ref().len(), 2);
2406 assert!(r.children.as_ref().is_empty());
2407
2408 let no_cols = ListView::default()
2409 .with_rows(ListViewRowVec::from_vec(vec![row_with(3)]))
2410 .dom();
2411 let (h, r) = header_and_rows(&no_cols);
2412 assert!(h.children.as_ref().is_empty());
2413 assert_eq!(r.children.as_ref().len(), 1);
2414 assert_eq!(
2415 r.children.as_ref()[0].children.as_ref().len(),
2416 3,
2417 "cells are rendered even with no matching column headers"
2418 );
2419
2420 let ragged = ListView::create(cols(&["a", "b", "c"]))
2422 .with_rows(ListViewRowVec::from_vec(vec![
2423 row_with(0),
2424 row_with(1),
2425 row_with(3),
2426 row_with(7),
2427 ]))
2428 .dom();
2429 let (h, r) = header_and_rows(&ragged);
2430 assert_eq!(h.children.as_ref().len(), 3);
2431 let rows = r.children.as_ref();
2432 assert_eq!(rows.len(), 4);
2433 for (row, want) in rows.iter().zip([0_usize, 1, 3, 7]) {
2434 assert_eq!(row.children.as_ref().len(), want);
2435 for cell in row.children.as_ref() {
2436 assert_eq!(cell.children.as_ref().len(), 1, "one child per cell");
2437 }
2438 }
2439 }
2440
2441 #[test]
2445 fn dom_wires_click_payloads_with_the_right_index_and_state_snapshot() {
2446 let rcb: ListViewOnRowClickCallbackType = noop_row_cb;
2447 let ccb: ListViewOnColumnClickCallbackType = noop_col_cb;
2448 let lv = ListView::create(cols(&["c0", "c1"]))
2449 .with_rows(ListViewRowVec::from_vec(vec![
2450 row_with(2),
2451 row_with(2),
2452 row_with(2),
2453 ]))
2454 .with_sorted_by(Some(1_usize).into())
2455 .with_scroll_offset(px(-17.5))
2456 .with_on_row_click(RefAny::new(()), rcb)
2457 .with_on_column_click(RefAny::new(()), ccb);
2458
2459 let dom = lv.dom();
2460 let (header, rows) = header_and_rows(&dom);
2461
2462 for (i, col) in header.children.as_ref().iter().enumerate() {
2463 let cbs = col.root.callbacks.as_ref();
2464 assert_eq!(cbs.len(), 1);
2465 assert!(matches!(
2466 cbs[0].event,
2467 EventFilter::Hover(HoverEventFilter::MouseUp)
2468 ));
2469 assert_eq!(cbs[0].callback.cb, on_list_view_column_click as usize);
2470 let mut any = cbs[0].refany.clone();
2471 let data = any
2472 .downcast_ref::<ColumnClickData>()
2473 .expect("ColumnClickData payload");
2474 assert_eq!(data.col_index, i, "each header carries its own index");
2475 assert_eq!(data.state.current_row_count, 3);
2476 assert_eq!(data.state.columns.len(), 2);
2477 assert_eq!(data.state.sorted_by.as_ref().copied(), Some(1));
2478 assert_eq!(data.state.scroll_offset, px(-17.5));
2479 assert!(data.on_column_click.is_some());
2480 }
2481
2482 for (i, row) in rows.children.as_ref().iter().enumerate() {
2483 let cbs = row.root.callbacks.as_ref();
2484 assert_eq!(cbs.len(), 1);
2485 assert!(matches!(
2486 cbs[0].event,
2487 EventFilter::Hover(HoverEventFilter::MouseUp)
2488 ));
2489 assert_eq!(cbs[0].callback.cb, on_list_view_row_click as usize);
2490 let mut any = cbs[0].refany.clone();
2491 let data = any
2492 .downcast_ref::<RowClickData>()
2493 .expect("RowClickData payload");
2494 assert_eq!(data.row_index, i, "each row carries its own index");
2495 assert_eq!(data.state.current_row_count, 3);
2496 assert!(data.on_row_click.is_some());
2497 }
2498 }
2499
2500 #[test]
2503 fn click_callbacks_are_wired_per_hook_and_only_when_set() {
2504 let rcb: ListViewOnRowClickCallbackType = noop_row_cb;
2505 let ccb: ListViewOnColumnClickCallbackType = noop_col_cb;
2506
2507 let bare = ListView::create(cols(&["a", "b"])).dom();
2508 let (h, _) = header_and_rows(&bare);
2509 for col in h.children.as_ref() {
2510 assert!(
2511 col.root.callbacks.as_ref().is_empty(),
2512 "no hook, no dispatch"
2513 );
2514 }
2515
2516 let row_only = ListView::create(cols(&["a"]))
2517 .with_rows(ListViewRowVec::from_vec(vec![row_with(1)]))
2518 .with_on_row_click(RefAny::new(()), rcb)
2519 .dom();
2520 let (h, r) = header_and_rows(&row_only);
2521 assert!(h.children.as_ref()[0].root.callbacks.as_ref().is_empty());
2522 assert_eq!(r.children.as_ref()[0].root.callbacks.as_ref().len(), 1);
2523
2524 let col_only = ListView::create(cols(&["a"]))
2525 .with_rows(ListViewRowVec::from_vec(vec![row_with(1)]))
2526 .with_on_column_click(RefAny::new(()), ccb)
2527 .dom();
2528 let (h, r) = header_and_rows(&col_only);
2529 assert_eq!(h.children.as_ref()[0].root.callbacks.as_ref().len(), 1);
2530 assert!(r.children.as_ref()[0].root.callbacks.as_ref().is_empty());
2531 }
2532
2533 #[test]
2538 fn click_handler_payload_downcast_rejects_foreign_types() {
2539 let mut wrong = RefAny::new(0_u64);
2540 assert!(
2541 wrong.downcast_ref::<RowClickData>().is_none(),
2542 "handler must not accept a foreign payload type"
2543 );
2544 assert!(wrong.downcast_ref::<ColumnClickData>().is_none());
2545
2546 let mut row_payload = RefAny::new(RowClickData {
2548 row_index: 0,
2549 state: ListViewState {
2550 columns: StringVec::from_const_slice(&[]),
2551 sorted_by: None.into(),
2552 current_row_count: 0,
2553 scroll_offset: PixelValueNoPercent::zero(),
2554 current_scroll_position: LogicalPosition::zero(),
2555 current_content_height: LogicalSize::zero(),
2556 },
2557 on_row_click: None.into(),
2558 });
2559 assert!(row_payload.downcast_ref::<ColumnClickData>().is_none());
2560 assert!(row_payload.downcast_ref::<RowClickData>().is_some());
2561 }
2562
2563 #[test]
2564 fn dom_survives_a_large_column_and_row_count() {
2565 const N_COLS: usize = 64;
2566 const N_ROWS: usize = 64;
2567 let rcb: ListViewOnRowClickCallbackType = noop_row_cb;
2568 let names = (0..N_COLS)
2569 .map(|i| AzString::from(format!("col{i}")))
2570 .collect::<Vec<_>>();
2571 let rows = (0..N_ROWS).map(|_| row_with(N_COLS)).collect::<Vec<_>>();
2572 let dom = ListView::create(StringVec::from_vec(names))
2573 .with_rows(ListViewRowVec::from_vec(rows))
2574 .with_on_row_click(RefAny::new(()), rcb)
2575 .dom();
2576
2577 let (h, r) = header_and_rows(&dom);
2578 assert_eq!(h.children.as_ref().len(), N_COLS);
2579 assert_eq!(r.children.as_ref().len(), N_ROWS);
2580 for row in r.children.as_ref() {
2581 assert_eq!(row.children.as_ref().len(), N_COLS);
2582 assert_eq!(row.root.callbacks.as_ref().len(), 1);
2583 }
2584 }
2585}