1
//! Native list view widget with column headers, row selection, and sorting indicators.
2

            
3
use alloc::vec::Vec;
4

            
5
use 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)] // widget/render module pulls in the css property/value types it builds with
16
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
};
27
use azul_css::css::BoxOrStatic;
28

            
29
use crate::callbacks::{Callback, CallbackInfo};
30

            
31
const STRING_16146701490593874959: AzString = AzString::from_const_str("system:ui");
32
const STYLE_BACKGROUND_CONTENT_661302523448178568_ITEMS: &[StyleBackgroundContent] =
33
    &[StyleBackgroundContent::Color(ColorU {
34
        r: 209,
35
        g: 232,
36
        b: 255,
37
        a: 255,
38
    })];
39
const STYLE_BACKGROUND_CONTENT_2444935983575427872_ITEMS: &[StyleBackgroundContent] =
40
    &[StyleBackgroundContent::Color(ColorU {
41
        r: 252,
42
        g: 252,
43
        b: 252,
44
        a: 255,
45
    })];
46
const STYLE_BACKGROUND_CONTENT_3010057533077499049_ITEMS: &[StyleBackgroundContent] =
47
    &[StyleBackgroundContent::Color(ColorU {
48
        r: 229,
49
        g: 243,
50
        b: 251,
51
        a: 255,
52
    })];
53
const STYLE_BACKGROUND_CONTENT_3839348353894170136_ITEMS: &[StyleBackgroundContent] =
54
    &[StyleBackgroundContent::Color(ColorU {
55
        r: 249,
56
        g: 250,
57
        b: 251,
58
        a: 255,
59
    })];
60
const 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
    })];
71
const 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
    })];
82
const STYLE_BACKGROUND_CONTENT_11062356617965867290_ITEMS: &[StyleBackgroundContent] =
83
    &[StyleBackgroundContent::Color(ColorU {
84
        r: 240,
85
        g: 240,
86
        b: 240,
87
        a: 255,
88
    })];
89
const STYLE_BACKGROUND_CONTENT_11098930083828139815_ITEMS: &[StyleBackgroundContent] =
90
    &[StyleBackgroundContent::Color(ColorU {
91
        r: 184,
92
        g: 224,
93
        b: 243,
94
        a: 255,
95
    })];
96
const STYLE_TRANSFORM_6162542744002865382_ITEMS: &[StyleTransform] =
97
    &[StyleTransform::Translate(StyleTransformTranslate2D {
98
        x: PixelValue::const_px(7),
99
        y: PixelValue::const_px(0),
100
    })];
101
const STYLE_TRANSFORM_16978981723642914576_ITEMS: &[StyleTransform] =
102
    &[StyleTransform::Rotate(AngleValue::const_deg(45))];
103
const 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
];
110
const STYLE_FONT_FAMILY_8122988506401935406_ITEMS: &[StyleFontFamily] =
111
    &[StyleFontFamily::System(STRING_16146701490593874959)];
112
const 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
];
150
const 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

            
189
const CSS_MATCH_1085706216385961159_PROPERTIES: &[CssPropertyWithConditions] = &[
190
    // .__azul_native-list-header-arrow-down
191
    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
];
224
const CSS_MATCH_1085706216385961159: CssPropertyWithConditionsVec =
225
    CssPropertyWithConditionsVec::from_const_slice(CSS_MATCH_1085706216385961159_PROPERTIES);
226

            
227
const CSS_MATCH_12498280255863106397_PROPERTIES: &[CssPropertyWithConditions] = &[
228
    // .__azul_native-list-header-item:hover
229
    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
    // .__azul_native-list-header-item:active
255
    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
    // .__azul_native-list-header-item
433
    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
];
470
const CSS_MATCH_12498280255863106397: CssPropertyWithConditionsVec =
471
    CssPropertyWithConditionsVec::from_const_slice(CSS_MATCH_12498280255863106397_PROPERTIES);
472

            
473
const CSS_MATCH_12980082330151137475_PROPERTIES: &[CssPropertyWithConditions] = &[
474
    // .__azul_native-list-rows-row-cell
475
    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
];
494
const CSS_MATCH_12980082330151137475: CssPropertyWithConditionsVec =
495
    CssPropertyWithConditionsVec::from_const_slice(CSS_MATCH_12980082330151137475_PROPERTIES);
496

            
497
const CSS_MATCH_13758717721055992976_PROPERTIES: &[CssPropertyWithConditions] = &[
498
    // .__azul_native-list-header-arrow-down-inner
499
    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
];
515
const CSS_MATCH_13758717721055992976: CssPropertyWithConditionsVec =
516
    CssPropertyWithConditionsVec::from_const_slice(CSS_MATCH_13758717721055992976_PROPERTIES);
517

            
518
const CSS_MATCH_15295293133676720691_PROPERTIES: &[CssPropertyWithConditions] = &[
519
    // .__azul_native-list-header-dragwidth-drag
520
    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
];
527
const CSS_MATCH_15295293133676720691: CssPropertyWithConditionsVec =
528
    CssPropertyWithConditionsVec::from_const_slice(CSS_MATCH_15295293133676720691_PROPERTIES);
529

            
530
const CSS_MATCH_15315949193378715186_PROPERTIES: &[CssPropertyWithConditions] = &[
531
    // .__azul_native-list-header
532
    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
];
544
const CSS_MATCH_15315949193378715186: CssPropertyWithConditionsVec =
545
    CssPropertyWithConditionsVec::from_const_slice(CSS_MATCH_15315949193378715186_PROPERTIES);
546

            
547
const CSS_MATCH_15673486787900743642_PROPERTIES: &[CssPropertyWithConditions] = &[
548
    // .__azul_native-list-header .__azul_native-list-header-item p
549
    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
];
579
const CSS_MATCH_15673486787900743642: CssPropertyWithConditionsVec =
580
    CssPropertyWithConditionsVec::from_const_slice(CSS_MATCH_15673486787900743642_PROPERTIES);
581

            
582
const CSS_MATCH_1574792189506859253_PROPERTIES: &[CssPropertyWithConditions] = &[
583
    // .__azul_native-list-header-arrow-down-inner-deco
584
    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
];
686
const CSS_MATCH_1574792189506859253: CssPropertyWithConditionsVec =
687
    CssPropertyWithConditionsVec::from_const_slice(CSS_MATCH_1574792189506859253_PROPERTIES);
688

            
689
const CSS_MATCH_17553577885456905601_PROPERTIES: &[CssPropertyWithConditions] = &[
690
    // .__azul_native_list-container
691
    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
];
702
const CSS_MATCH_17553577885456905601: CssPropertyWithConditionsVec =
703
    CssPropertyWithConditionsVec::from_const_slice(CSS_MATCH_17553577885456905601_PROPERTIES);
704

            
705
const CSS_MATCH_2883986488332352590_PROPERTIES: &[CssPropertyWithConditions] = &[
706
    // body
707
    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
];
733
const CSS_MATCH_2883986488332352590: CssPropertyWithConditionsVec =
734
    CssPropertyWithConditionsVec::from_const_slice(CSS_MATCH_2883986488332352590_PROPERTIES);
735

            
736
const CSS_MATCH_4852927511892172364_PROPERTIES: &[CssPropertyWithConditions] = &[
737
    // .__azul_native-list-rows
738
    CssPropertyWithConditions::simple(CssProperty::FlexDirection(LayoutFlexDirectionValue::Exact(
739
        LayoutFlexDirection::Column,
740
    ))),
741
];
742
const CSS_MATCH_4852927511892172364: CssPropertyWithConditionsVec =
743
    CssPropertyWithConditionsVec::from_const_slice(CSS_MATCH_4852927511892172364_PROPERTIES);
744

            
745
const CSS_MATCH_6002662151290653203_PROPERTIES: &[CssPropertyWithConditions] = &[
746
    // .__azul_native-list-header-dragwidth
747
    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
];
759
const CSS_MATCH_6002662151290653203: CssPropertyWithConditionsVec =
760
    CssPropertyWithConditionsVec::from_const_slice(CSS_MATCH_6002662151290653203_PROPERTIES);
761

            
762
const CSS_MATCH_6827198030119836081_PROPERTIES: &[CssPropertyWithConditions] = &[
763
    // .__azul_native-list-rows-row.selected
764
    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
    // .__azul_native-list-rows-row:hover
850
    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
    // .__azul_native-list-rows-row
936
    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(
        StyleBorderTopStyleValue::Exact(StyleBorderTopStyle {
            inner: BorderStyle::Solid,
        }),
    )),
    CssPropertyWithConditions::simple(CssProperty::BorderBottomColor(
        StyleBorderBottomColorValue::Exact(StyleBorderBottomColor {
            inner: ColorU {
                r: 255,
                g: 255,
                b: 255,
                a: 0,
            },
        }),
    )),
    CssPropertyWithConditions::simple(CssProperty::BorderLeftColor(
        StyleBorderLeftColorValue::Exact(StyleBorderLeftColor {
            inner: ColorU {
                r: 255,
                g: 255,
                b: 255,
                a: 0,
            },
        }),
    )),
    CssPropertyWithConditions::simple(CssProperty::BorderRightColor(
        StyleBorderRightColorValue::Exact(StyleBorderRightColor {
            inner: ColorU {
                r: 255,
                g: 255,
                b: 255,
                a: 0,
            },
        }),
    )),
    CssPropertyWithConditions::simple(CssProperty::BorderTopColor(
        StyleBorderTopColorValue::Exact(StyleBorderTopColor {
            inner: ColorU {
                r: 255,
                g: 255,
                b: 255,
                a: 0,
            },
        }),
    )),
];
const CSS_MATCH_6827198030119836081: CssPropertyWithConditionsVec =
    CssPropertyWithConditionsVec::from_const_slice(CSS_MATCH_6827198030119836081_PROPERTIES);
const CSS_MATCH_7894335449545988724_PROPERTIES: &[CssPropertyWithConditions] = &[
    // .__azul_native-list-rows-row.focused
    CssPropertyWithConditions::on_focus(CssProperty::BorderBottomWidth(
        LayoutBorderBottomWidthValue::Exact(LayoutBorderBottomWidth {
            inner: PixelValue::const_px(1),
        }),
    )),
    CssPropertyWithConditions::on_focus(CssProperty::BorderLeftWidth(
        LayoutBorderLeftWidthValue::Exact(LayoutBorderLeftWidth {
            inner: PixelValue::const_px(1),
        }),
    )),
    CssPropertyWithConditions::on_focus(CssProperty::BorderRightWidth(
        LayoutBorderRightWidthValue::Exact(LayoutBorderRightWidth {
            inner: PixelValue::const_px(1),
        }),
    )),
    CssPropertyWithConditions::on_focus(CssProperty::BorderTopWidth(
        LayoutBorderTopWidthValue::Exact(LayoutBorderTopWidth {
            inner: PixelValue::const_px(1),
        }),
    )),
    CssPropertyWithConditions::on_focus(CssProperty::BorderBottomStyle(
        StyleBorderBottomStyleValue::Exact(StyleBorderBottomStyle {
            inner: BorderStyle::Solid,
        }),
    )),
    CssPropertyWithConditions::on_focus(CssProperty::BorderLeftStyle(
        StyleBorderLeftStyleValue::Exact(StyleBorderLeftStyle {
            inner: BorderStyle::Solid,
        }),
    )),
    CssPropertyWithConditions::on_focus(CssProperty::BorderRightStyle(
        StyleBorderRightStyleValue::Exact(StyleBorderRightStyle {
            inner: BorderStyle::Solid,
        }),
    )),
    CssPropertyWithConditions::on_focus(CssProperty::BorderTopStyle(
        StyleBorderTopStyleValue::Exact(StyleBorderTopStyle {
            inner: BorderStyle::Solid,
        }),
    )),
    CssPropertyWithConditions::on_focus(CssProperty::BorderBottomColor(
        StyleBorderBottomColorValue::Exact(StyleBorderBottomColor {
            inner: ColorU {
                r: 38,
                g: 160,
                b: 218,
                a: 255,
            },
        }),
    )),
    CssPropertyWithConditions::on_focus(CssProperty::BorderLeftColor(
        StyleBorderLeftColorValue::Exact(StyleBorderLeftColor {
            inner: ColorU {
                r: 38,
                g: 160,
                b: 218,
                a: 255,
            },
        }),
    )),
    CssPropertyWithConditions::on_focus(CssProperty::BorderRightColor(
        StyleBorderRightColorValue::Exact(StyleBorderRightColor {
            inner: ColorU {
                r: 38,
                g: 160,
                b: 218,
                a: 255,
            },
        }),
    )),
    CssPropertyWithConditions::on_focus(CssProperty::BorderTopColor(
        StyleBorderTopColorValue::Exact(StyleBorderTopColor {
            inner: ColorU {
                r: 38,
                g: 160,
                b: 218,
                a: 255,
            },
        }),
    )),
    CssPropertyWithConditions::on_focus(CssProperty::BackgroundContent(
        StyleBackgroundContentVecValue::Exact(StyleBackgroundContentVec::from_const_slice(
            STYLE_BACKGROUND_CONTENT_11098930083828139815_ITEMS,
        )),
    )),
    // .__azul_native-list-rows-row:hover
    CssPropertyWithConditions::on_hover(CssProperty::BorderBottomWidth(
        LayoutBorderBottomWidthValue::Exact(LayoutBorderBottomWidth {
            inner: PixelValue::const_px(1),
        }),
    )),
    CssPropertyWithConditions::on_hover(CssProperty::BorderLeftWidth(
        LayoutBorderLeftWidthValue::Exact(LayoutBorderLeftWidth {
            inner: PixelValue::const_px(1),
        }),
    )),
    CssPropertyWithConditions::on_hover(CssProperty::BorderRightWidth(
        LayoutBorderRightWidthValue::Exact(LayoutBorderRightWidth {
            inner: PixelValue::const_px(1),
        }),
    )),
    CssPropertyWithConditions::on_hover(CssProperty::BorderTopWidth(
        LayoutBorderTopWidthValue::Exact(LayoutBorderTopWidth {
            inner: PixelValue::const_px(1),
        }),
    )),
    CssPropertyWithConditions::on_hover(CssProperty::BorderBottomStyle(
        StyleBorderBottomStyleValue::Exact(StyleBorderBottomStyle {
            inner: BorderStyle::Solid,
        }),
    )),
    CssPropertyWithConditions::on_hover(CssProperty::BorderLeftStyle(
        StyleBorderLeftStyleValue::Exact(StyleBorderLeftStyle {
            inner: BorderStyle::Solid,
        }),
    )),
    CssPropertyWithConditions::on_hover(CssProperty::BorderRightStyle(
        StyleBorderRightStyleValue::Exact(StyleBorderRightStyle {
            inner: BorderStyle::Solid,
        }),
    )),
    CssPropertyWithConditions::on_hover(CssProperty::BorderTopStyle(
        StyleBorderTopStyleValue::Exact(StyleBorderTopStyle {
            inner: BorderStyle::Solid,
        }),
    )),
    CssPropertyWithConditions::on_hover(CssProperty::BorderBottomColor(
        StyleBorderBottomColorValue::Exact(StyleBorderBottomColor {
            inner: ColorU {
                r: 101,
                g: 181,
                b: 220,
                a: 255,
            },
        }),
    )),
    CssPropertyWithConditions::on_hover(CssProperty::BorderLeftColor(
        StyleBorderLeftColorValue::Exact(StyleBorderLeftColor {
            inner: ColorU {
                r: 101,
                g: 181,
                b: 220,
                a: 255,
            },
        }),
    )),
    CssPropertyWithConditions::on_hover(CssProperty::BorderRightColor(
        StyleBorderRightColorValue::Exact(StyleBorderRightColor {
            inner: ColorU {
                r: 101,
                g: 181,
                b: 220,
                a: 255,
            },
        }),
    )),
    CssPropertyWithConditions::on_hover(CssProperty::BorderTopColor(
        StyleBorderTopColorValue::Exact(StyleBorderTopColor {
            inner: ColorU {
                r: 101,
                g: 181,
                b: 220,
                a: 255,
            },
        }),
    )),
    CssPropertyWithConditions::on_hover(CssProperty::BackgroundContent(
        StyleBackgroundContentVecValue::Exact(StyleBackgroundContentVec::from_const_slice(
            STYLE_BACKGROUND_CONTENT_3010057533077499049_ITEMS,
        )),
    )),
    // .__azul_native-list-rows-row
    CssPropertyWithConditions::simple(CssProperty::PaddingRight(LayoutPaddingRightValue::Exact(
        LayoutPaddingRight {
            inner: PixelValue::const_px(0),
        },
    ))),
    CssPropertyWithConditions::simple(CssProperty::PaddingLeft(LayoutPaddingLeftValue::Exact(
        LayoutPaddingLeft {
            inner: PixelValue::const_px(0),
        },
    ))),
    CssPropertyWithConditions::simple(CssProperty::PaddingBottom(LayoutPaddingBottomValue::Exact(
        LayoutPaddingBottom {
            inner: PixelValue::const_px(2),
        },
    ))),
    CssPropertyWithConditions::simple(CssProperty::PaddingTop(LayoutPaddingTopValue::Exact(
        LayoutPaddingTop {
            inner: PixelValue::const_px(2),
        },
    ))),
    CssPropertyWithConditions::simple(CssProperty::FlexGrow(LayoutFlexGrowValue::Exact(
        LayoutFlexGrow {
            inner: FloatValue::const_new(1),
        },
    ))),
    CssPropertyWithConditions::simple(CssProperty::FlexDirection(LayoutFlexDirectionValue::Exact(
        LayoutFlexDirection::Row,
    ))),
    CssPropertyWithConditions::simple(CssProperty::BorderBottomWidth(
        LayoutBorderBottomWidthValue::Exact(LayoutBorderBottomWidth {
            inner: PixelValue::const_px(1),
        }),
    )),
    CssPropertyWithConditions::simple(CssProperty::BorderLeftWidth(
        LayoutBorderLeftWidthValue::Exact(LayoutBorderLeftWidth {
            inner: PixelValue::const_px(1),
        }),
    )),
    CssPropertyWithConditions::simple(CssProperty::BorderRightWidth(
        LayoutBorderRightWidthValue::Exact(LayoutBorderRightWidth {
            inner: PixelValue::const_px(1),
        }),
    )),
    CssPropertyWithConditions::simple(CssProperty::BorderTopWidth(
        LayoutBorderTopWidthValue::Exact(LayoutBorderTopWidth {
            inner: PixelValue::const_px(1),
        }),
    )),
    CssPropertyWithConditions::simple(CssProperty::BorderBottomStyle(
        StyleBorderBottomStyleValue::Exact(StyleBorderBottomStyle {
            inner: BorderStyle::Solid,
        }),
    )),
    CssPropertyWithConditions::simple(CssProperty::BorderLeftStyle(
        StyleBorderLeftStyleValue::Exact(StyleBorderLeftStyle {
            inner: BorderStyle::Solid,
        }),
    )),
    CssPropertyWithConditions::simple(CssProperty::BorderRightStyle(
        StyleBorderRightStyleValue::Exact(StyleBorderRightStyle {
            inner: BorderStyle::Solid,
        }),
    )),
    CssPropertyWithConditions::simple(CssProperty::BorderTopStyle(
        StyleBorderTopStyleValue::Exact(StyleBorderTopStyle {
            inner: BorderStyle::Solid,
        }),
    )),
    CssPropertyWithConditions::simple(CssProperty::BorderBottomColor(
        StyleBorderBottomColorValue::Exact(StyleBorderBottomColor {
            inner: ColorU {
                r: 255,
                g: 255,
                b: 255,
                a: 0,
            },
        }),
    )),
    CssPropertyWithConditions::simple(CssProperty::BorderLeftColor(
        StyleBorderLeftColorValue::Exact(StyleBorderLeftColor {
            inner: ColorU {
                r: 255,
                g: 255,
                b: 255,
                a: 0,
            },
        }),
    )),
    CssPropertyWithConditions::simple(CssProperty::BorderRightColor(
        StyleBorderRightColorValue::Exact(StyleBorderRightColor {
            inner: ColorU {
                r: 255,
                g: 255,
                b: 255,
                a: 0,
            },
        }),
    )),
    CssPropertyWithConditions::simple(CssProperty::BorderTopColor(
        StyleBorderTopColorValue::Exact(StyleBorderTopColor {
            inner: ColorU {
                r: 255,
                g: 255,
                b: 255,
                a: 0,
            },
        }),
    )),
];
const CSS_MATCH_7894335449545988724: CssPropertyWithConditionsVec =
    CssPropertyWithConditionsVec::from_const_slice(CSS_MATCH_7894335449545988724_PROPERTIES);
const IDS_AND_CLASSES_790316832563530605: &[IdOrClass] = &[Class(AzString::from_const_str(
    "__azul_native-list-rows-row",
))];
const ROW_CLASS: IdOrClassVec = IdOrClassVec::from_const_slice(IDS_AND_CLASSES_790316832563530605);
const IDS_AND_CLASSES_3034181810805097699: &[IdOrClass] = &[Class(AzString::from_const_str(
    "__azul_native-list-rows-row-cell",
))];
const CELL_CLASS: IdOrClassVec =
    IdOrClassVec::from_const_slice(IDS_AND_CLASSES_3034181810805097699);
const IDS_AND_CLASSES_6012478019077291002: &[IdOrClass] =
    &[Class(AzString::from_const_str("__azul_native-list-rows"))];
const ROW_CONTAINER_CLASS: IdOrClassVec =
    IdOrClassVec::from_const_slice(IDS_AND_CLASSES_6012478019077291002);
const IDS_AND_CLASSES_10742579426112804392: &[IdOrClass] =
    &[Class(AzString::from_const_str("__azul_native-list-header"))];
const HEADER_CONTAINER_CLASS: IdOrClassVec =
    IdOrClassVec::from_const_slice(IDS_AND_CLASSES_10742579426112804392);
const IDS_AND_CLASSES_9205819539370539587: &[IdOrClass] = &[Class(AzString::from_const_str(
    "__azul_native_list-container",
))];
const LIST_VIEW_CONTAINER_CLASS: IdOrClassVec =
    IdOrClassVec::from_const_slice(IDS_AND_CLASSES_9205819539370539587);
const IDS_AND_CLASSES_18330792117162403422: &[IdOrClass] = &[Class(AzString::from_const_str(
    "__azul_native-list-header-item",
))];
const COLUMN_NAME_CLASS: IdOrClassVec =
    IdOrClassVec::from_const_slice(IDS_AND_CLASSES_18330792117162403422);
pub type ListViewOnLazyLoadScrollCallbackType =
    extern "C" fn(RefAny, CallbackInfo, ListViewState) -> Update;
impl_widget_callback!(
    ListViewOnLazyLoadScroll,
    OptionListViewOnLazyLoadScroll,
    ListViewOnLazyLoadScrollCallback,
    ListViewOnLazyLoadScrollCallbackType
);
azul_core::impl_managed_callback! {
    wrapper:        ListViewOnLazyLoadScrollCallback,
    info_ty:        CallbackInfo,
    return_ty:      Update,
    default_ret:    Update::DoNothing,
    invoker_static: LIST_VIEW_ON_LAZY_LOAD_SCROLL_INVOKER,
    invoker_ty:     AzListViewOnLazyLoadScrollCallbackInvoker,
    thunk_fn:       az_list_view_on_lazy_load_scroll_callback_thunk,
    setter_fn:      AzApp_setListViewOnLazyLoadScrollCallbackInvoker,
    from_handle_fn: AzListViewOnLazyLoadScrollCallback_createFromHostHandle,
    extra_args:     [ state: ListViewState ],
}
pub type ListViewOnColumnClickCallbackType =
    extern "C" fn(RefAny, CallbackInfo, ListViewState, column_clicked: usize) -> Update;
impl_widget_callback!(
    ListViewOnColumnClick,
    OptionListViewOnColumnClick,
    ListViewOnColumnClickCallback,
    ListViewOnColumnClickCallbackType
);
azul_core::impl_managed_callback! {
    wrapper:        ListViewOnColumnClickCallback,
    info_ty:        CallbackInfo,
    return_ty:      Update,
    default_ret:    Update::DoNothing,
    invoker_static: LIST_VIEW_ON_COLUMN_CLICK_INVOKER,
    invoker_ty:     AzListViewOnColumnClickCallbackInvoker,
    thunk_fn:       az_list_view_on_column_click_callback_thunk,
    setter_fn:      AzApp_setListViewOnColumnClickCallbackInvoker,
    from_handle_fn: AzListViewOnColumnClickCallback_createFromHostHandle,
    extra_args:     [ state: ListViewState, column_clicked: usize ],
}
pub type ListViewOnRowClickCallbackType =
    extern "C" fn(RefAny, CallbackInfo, ListViewState, row_clicked: usize) -> Update;
impl_widget_callback!(
    ListViewOnRowClick,
    OptionListViewOnRowClick,
    ListViewOnRowClickCallback,
    ListViewOnRowClickCallbackType
);
azul_core::impl_managed_callback! {
    wrapper:        ListViewOnRowClickCallback,
    info_ty:        CallbackInfo,
    return_ty:      Update,
    default_ret:    Update::DoNothing,
    invoker_static: LIST_VIEW_ON_ROW_CLICK_INVOKER,
    invoker_ty:     AzListViewOnRowClickCallbackInvoker,
    thunk_fn:       az_list_view_on_row_click_callback_thunk,
    setter_fn:      AzApp_setListViewOnRowClickCallbackInvoker,
    from_handle_fn: AzListViewOnRowClickCallback_createFromHostHandle,
    extra_args:     [ state: ListViewState, row_clicked: usize ],
}
/// State of the `ListView`, but without row data
#[derive(Debug, Clone)]
#[repr(C)]
pub struct ListViewState {
    /// Copy of the current column names
    pub columns: StringVec,
    /// Which column the rows are currently sorted by
    pub sorted_by: OptionUsize,
    /// Row count of rows currently loaded in the DOM
    pub current_row_count: usize,
    /// Y-offset currently applied to the rows
    pub scroll_offset: PixelValueNoPercent,
    /// Current position where the user has scrolled the `ListView` to
    pub current_scroll_position: LogicalPosition,
    /// Current height of the row container
    pub current_content_height: LogicalSize,
}
/// List view, optionally able to lazy-load data
#[derive(Debug, Clone)]
#[repr(C)]
pub struct ListView {
    /// Column names
    pub columns: StringVec,
    /// Currently rendered rows. Note that the `ListView` does not
    /// have to render all rows at once, usually you'd only render
    /// the top 100 rows
    pub rows: ListViewRowVec,
    /// Which column is the list view sorted by (default = None)?
    pub sorted_by: OptionUsize,
    /// Offset to add to the rows used when layouting row positions
    /// during lazy-loaded scrolling. Also affects the scroll position
    pub scroll_offset: PixelValueNoPercent,
    /// Height of the content, if not all rows are loaded
    pub content_height: OptionPixelValueNoPercent,
    /// Context menu for the columns (usually opens a context menu
    /// to select which columns to show)
    pub column_context_menu: OptionMenu,
    /// Indicates that this `ListView` is being lazily loaded, allows
    /// control over what happens when the user scrolls the `ListView`.
    pub on_lazy_load_scroll: OptionListViewOnLazyLoadScroll,
    /// What to do when the user left-clicks the column
    /// (usually used for storing which column to sort by)
    pub on_column_click: OptionListViewOnColumnClick,
    /// What to do when the user left-clicks a row
    /// (usually used for selecting the row depending on the state)
    pub on_row_click: OptionListViewOnRowClick,
}
impl Default for ListView {
49
    fn default() -> Self {
49
        Self {
49
            columns: StringVec::from_const_slice(&[]),
49
            rows: ListViewRowVec::from_const_slice(&[]),
49
            sorted_by: None.into(),
49
            scroll_offset: PixelValueNoPercent {
49
                inner: PixelValue::const_px(0),
49
            },
49
            content_height: None.into(),
49
            column_context_menu: None.into(),
49
            on_lazy_load_scroll: None.into(),
49
            on_column_click: None.into(),
49
            on_row_click: None.into(),
49
        }
49
    }
}
/// Row of the `ListView`
#[derive(Debug, Clone)]
#[repr(C)]
pub struct ListViewRow {
    /// Each cell is an opaque Dom object
    pub cells: DomVec,
    /// Height of the row, if known beforehand
    pub height: OptionPixelValueNoPercent,
}
impl_option!(ListViewRow, OptionListViewRow, copy = false, [Debug, Clone]);
impl_vec!(ListViewRow, ListViewRowVec, ListViewRowVecDestructor, ListViewRowVecDestructorType, ListViewRowVecSlice, OptionListViewRow);
impl_vec_clone!(ListViewRow, ListViewRowVec, ListViewRowVecDestructor);
impl_vec_mut!(ListViewRow, ListViewRowVec);
impl_vec_debug!(ListViewRow, ListViewRowVec);
impl ListView {
16
    #[must_use] pub fn create(columns: StringVec) -> Self {
16
        Self {
16
            columns,
16
            ..Default::default()
16
        }
16
    }
    #[must_use]
3
    pub fn swap_with_default(&mut self) -> Self {
3
        let mut m = Self::default();
3
        core::mem::swap(&mut m, self);
3
        m
3
    }
3
    #[must_use] pub fn with_columns(mut self, columns: StringVec) -> Self {
3
        self.set_columns(columns);
3
        self
3
    }
5
    pub fn set_columns(&mut self, columns: StringVec) {
5
        self.columns = columns;
5
    }
9
    #[must_use] pub fn with_rows(mut self, rows: ListViewRowVec) -> Self {
9
        self.set_rows(rows);
9
        self
9
    }
10
    pub fn set_rows(&mut self, rows: ListViewRowVec) {
10
        self.rows = rows;
10
    }
    /// The half-open range `[first, last)` of row indices visible in a
    /// vertically-scrolled, fixed-row-height list — the windowing core for
    /// virtualizing a long `ListView` (render only these rows instead of all of
    /// them, the way the `MapWidget`'s `VirtualView` renders only visible tiles).
    /// `scroll_y` is pixels scrolled past the top, `viewport_height` the visible
    /// height; one extra row is included so a row straddling the bottom edge
    /// still renders. Returns `(0, 0)` for degenerate input (no rows, a
    /// non-positive/non-finite height, or non-finite scroll), and an empty range
    /// `(total, total)` once scrolled past the end.
    #[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)] // bounded layout/render numeric cast
123
    #[must_use] pub fn visible_row_range(
123
        scroll_y: f32,
123
        viewport_height: f32,
123
        row_height: f32,
123
        total_rows: usize,
123
    ) -> (usize, usize) {
123
        if total_rows == 0
120
            || !row_height.is_finite()
116
            || row_height <= 0.0
112
            || !viewport_height.is_finite()
109
            || viewport_height <= 0.0
106
            || !scroll_y.is_finite()
        {
21
            return (0, 0);
102
        }
102
        let first = (scroll_y.max(0.0) / row_height).floor() as usize;
102
        if first >= total_rows {
8
            return (total_rows, total_rows);
94
        }
        // Saturating: a sub-pixel `row_height` makes `viewport_height / row_height`
        // astronomically large, whose `as usize` cast saturates to `usize::MAX`, so
        // `+ 1` (and `first + visible`) would overflow. The `.min(total_rows)` clamp
        // makes the saturated value harmless.
94
        let visible = ((viewport_height / row_height).ceil() as usize).saturating_add(1);
94
        let last = first.saturating_add(visible).min(total_rows);
94
        (first, last)
123
    }
6
    #[must_use] pub const fn with_sorted_by(mut self, sorted_by: OptionUsize) -> Self {
6
        self.set_sorted_by(sorted_by);
6
        self
6
    }
8
    pub const fn set_sorted_by(&mut self, sorted_by: OptionUsize) {
8
        self.sorted_by = sorted_by;
8
    }
15
    #[must_use] pub const fn with_scroll_offset(mut self, scroll_offset: PixelValueNoPercent) -> Self {
15
        self.set_scroll_offset(scroll_offset);
15
        self
15
    }
17
    pub const fn set_scroll_offset(&mut self, scroll_offset: PixelValueNoPercent) {
17
        self.scroll_offset = scroll_offset;
17
    }
2
    #[must_use] pub fn with_content_height(mut self, content_height: PixelValueNoPercent) -> Self {
2
        self.set_content_height(content_height);
2
        self
2
    }
7
    pub fn set_content_height(&mut self, content_height: PixelValueNoPercent) {
7
        self.content_height = Some(content_height).into();
7
    }
2
    #[must_use] pub fn with_column_context_menu(mut self, context_menu: Menu) -> Self {
2
        self.set_column_context_menu(context_menu);
2
        self
2
    }
4
    pub fn set_column_context_menu(&mut self, column_context_menu: Menu) {
4
        self.column_context_menu = Some(column_context_menu).into();
4
    }
    #[must_use]
3
    pub fn with_on_column_click<C: Into<ListViewOnColumnClickCallback>>(
3
        mut self,
3
        refany: RefAny,
3
        on_column_click: C,
3
    ) -> Self {
3
        self.set_on_column_click(refany, on_column_click);
3
        self
3
    }
3
    pub fn set_on_column_click<C: Into<ListViewOnColumnClickCallback>>(
3
        &mut self,
3
        refany: RefAny,
3
        on_column_click: C,
3
    ) {
3
        self.on_column_click = Some(ListViewOnColumnClick {
3
            refany,
3
            callback: on_column_click.into(),
3
        })
3
        .into();
3
    }
    #[must_use]
5
    pub fn with_on_row_click<C: Into<ListViewOnRowClickCallback>>(
5
        mut self,
5
        refany: RefAny,
5
        on_row_click: C,
5
    ) -> Self {
5
        self.set_on_row_click(refany, on_row_click);
5
        self
5
    }
8
    pub fn set_on_row_click<C: Into<ListViewOnRowClickCallback>>(
8
        &mut self,
8
        refany: RefAny,
8
        on_row_click: C,
8
    ) {
8
        self.on_row_click = Some(ListViewOnRowClick {
8
            refany,
8
            callback: on_row_click.into(),
8
        })
8
        .into();
8
    }
19
    #[must_use] pub fn dom(self) -> Dom {
        // Snapshot the state handed to row/column click callbacks. Runtime-only
        // fields (scroll position / content height) aren't known at build time,
        // so they default to zero; columns/sorted_by/row-count/scroll-offset are.
19
        let state = ListViewState {
19
            columns: self.columns.clone(),
19
            sorted_by: self.sorted_by,
19
            current_row_count: self.rows.as_ref().len(),
19
            scroll_offset: self.scroll_offset,
19
            current_scroll_position: LogicalPosition::zero(),
19
            current_content_height: LogicalSize::zero(),
19
        };
19
        let on_column_click = self.on_column_click.clone();
19
        let on_row_click = self.on_row_click.clone();
19
        Dom::create_div()
19
            .with_css_props(CSS_MATCH_17553577885456905601)
19
            .with_ids_and_classes(LIST_VIEW_CONTAINER_CLASS)
19
            .with_children(DomVec::from_vec(vec![
                // header
19
                Dom::create_div()
19
                    .with_css_props(CSS_MATCH_15315949193378715186)
19
                    .with_ids_and_classes(HEADER_CONTAINER_CLASS)
19
                    .with_children(
19
                        self.columns
19
                            .iter()
19
                            .enumerate()
95
                            .map(|(col_index, col)| {
95
                                let col_dom = Dom::create_div()
95
                                    .with_css_props(CSS_MATCH_12498280255863106397)
95
                                    .with_ids_and_classes(COLUMN_NAME_CLASS)
95
                                    .with_child({
95
                                        Dom::create_p_with_text(col.clone())
95
                                            .with_css_props(CSS_MATCH_15673486787900743642)
                                    });
                                // Wire the click only when the app set a handler.
95
                                match &on_column_click {
3
                                    OptionListViewOnColumnClick::Some(_) => col_dom.with_callbacks(
3
                                        vec![CoreCallbackData {
3
                                            event: EventFilter::Hover(HoverEventFilter::MouseUp),
3
                                            refany: RefAny::new(ColumnClickData {
3
                                                col_index,
3
                                                state: state.clone(),
3
                                                on_column_click: on_column_click.clone(),
3
                                            }),
3
                                            callback: CoreCallback {
3
                                                cb: on_list_view_column_click as usize,
3
                                                ctx: OptionRefAny::None,
3
                                            },
3
                                        }]
3
                                        .into(),
                                    ),
92
                                    OptionListViewOnColumnClick::None => col_dom,
                                }
95
                            })
19
                            .collect::<Vec<_>>()
19
                            .into(),
                    ),
                // rows
19
                Dom::create_div()
19
                    .with_css_props(CSS_MATCH_4852927511892172364)
19
                    .with_ids_and_classes(ROW_CONTAINER_CLASS)
19
                    .with_children(
19
                        self.rows
19
                            .into_iter()
19
                            .enumerate()
77
                            .map(|(row_index, row)| {
77
                                let row_dom = Dom::create_div()
77
                                    .with_css_props(CSS_MATCH_7894335449545988724)
77
                                    .with_ids_and_classes(ROW_CLASS)
77
                                    .with_tab_index(TabIndex::Auto)
77
                                    .with_children(
77
                                        row.cells
77
                                            .as_ref()
77
                                            .iter()
4118
                                            .map(|cell| {
4118
                                                Dom::create_div()
4118
                                                    .with_css_props(CSS_MATCH_12980082330151137475)
4118
                                                    .with_ids_and_classes(CELL_CLASS)
4118
                                                    .with_child(cell.clone())
4118
                                            })
77
                                            .collect::<Vec<_>>()
77
                                            .into(),
                                    );
77
                                match &on_row_click {
70
                                    OptionListViewOnRowClick::Some(_) => row_dom.with_callbacks(
70
                                        vec![CoreCallbackData {
70
                                            event: EventFilter::Hover(HoverEventFilter::MouseUp),
70
                                            refany: RefAny::new(RowClickData {
70
                                                row_index,
70
                                                state: state.clone(),
70
                                                on_row_click: on_row_click.clone(),
70
                                            }),
70
                                            callback: CoreCallback {
70
                                                cb: on_list_view_row_click as usize,
70
                                                ctx: OptionRefAny::None,
70
                                            },
70
                                        }]
70
                                        .into(),
                                    ),
7
                                    OptionListViewOnRowClick::None => row_dom,
                                }
77
                            })
19
                            .collect::<Vec<_>>()
19
                            .into(),
                    ),
            ]))
19
    }
}
/// Per-row data carried to the internal `MouseUp` handler (the row index plus a
/// snapshot of the list state and the app's `on_row_click` hook).
struct RowClickData {
    row_index: usize,
    state: ListViewState,
    on_row_click: OptionListViewOnRowClick,
}
/// Per-column equivalent of [`RowClickData`].
struct ColumnClickData {
    col_index: usize,
    state: ListViewState,
    on_column_click: OptionListViewOnColumnClick,
}
/// `MouseUp` on a row → invoke the app's `on_row_click(state, row_index)`.
extern "C" fn on_list_view_row_click(mut refany: RefAny, info: CallbackInfo) -> Update {
    let Some(data) = refany.downcast_ref::<RowClickData>() else {
        return Update::DoNothing;
    };
    match data.on_row_click.as_ref() {
        Some(ListViewOnRowClick { refany: user_data, callback }) => {
            (callback.cb)(user_data.clone(), info, data.state.clone(), data.row_index)
        }
        None => Update::DoNothing,
    }
}
/// `MouseUp` on a column header → invoke the app's `on_column_click(state, col_index)`.
extern "C" fn on_list_view_column_click(mut refany: RefAny, info: CallbackInfo) -> Update {
    let Some(data) = refany.downcast_ref::<ColumnClickData>() else {
        return Update::DoNothing;
    };
    match data.on_column_click.as_ref() {
        Some(ListViewOnColumnClick { refany: user_data, callback }) => {
            (callback.cb)(user_data.clone(), info, data.state.clone(), data.col_index)
        }
        None => Update::DoNothing,
    }
}
#[cfg(test)]
mod list_view_click_tests {
    use super::*;
    /// The windowing core for `ListView` virtualization: only the visible rows
    /// (+1 straddling the bottom) are in range, the range tracks scroll, clamps
    /// to the row count, and degenerate input yields an empty range.
    #[test]
1
    fn visible_row_range_windows_correctly() {
        // 100 rows x 20px, 200px viewport → 10 full rows + 1 partial.
1
        assert_eq!(ListView::visible_row_range(0.0, 200.0, 20.0, 100), (0, 11));
        // Scrolled 50px → first row = floor(50/20) = 2.
1
        assert_eq!(ListView::visible_row_range(50.0, 200.0, 20.0, 100), (2, 13));
        // Near the end → clamped to the row count.
1
        assert_eq!(ListView::visible_row_range(1900.0, 200.0, 20.0, 100), (95, 100));
        // Scrolled past the end → empty range at the tail.
1
        assert_eq!(ListView::visible_row_range(5000.0, 200.0, 20.0, 100), (100, 100));
        // Degenerate inputs → empty.
1
        assert_eq!(ListView::visible_row_range(0.0, 200.0, 20.0, 0), (0, 0));
1
        assert_eq!(ListView::visible_row_range(0.0, 200.0, 0.0, 100), (0, 0));
1
        assert_eq!(ListView::visible_row_range(f32::NAN, 200.0, 20.0, 100), (0, 0));
1
    }
    extern "C" fn noop_row(_: RefAny, _: CallbackInfo, _: ListViewState, _: usize) -> Update {
        Update::DoNothing
    }
3
    fn empty_row() -> ListViewRow {
3
        ListViewRow {
3
            cells: DomVec::from_const_slice(&[]),
3
            height: None.into(),
3
        }
3
    }
    /// Rows must carry a click callback exactly when `on_row_click` is set —
    /// previously `dom()` wired nothing, so the hook was dead.
    #[test]
    #[allow(clippy::field_reassign_with_default)] // struct built incrementally / test setup; a struct literal is not clearer here
1
    fn rows_get_a_click_callback_only_when_on_row_click_is_set() {
1
        let mut lv = ListView::default();
1
        lv.rows = ListViewRowVec::from_vec(vec![empty_row(), empty_row()]);
1
        let on_row_click: ListViewOnRowClickCallbackType = noop_row;
1
        lv.set_on_row_click(RefAny::new(()), on_row_click);
1
        let dom = lv.dom();
        // children = [header, rows]; each row div carries the MouseUp callback.
1
        let rows = dom.children.as_ref()[1].children.as_ref();
1
        assert_eq!(rows.len(), 2);
3
        for row in rows {
2
            assert_eq!(
2
                row.root.callbacks.as_ref().len(),
                1,
                "row must carry the click callback when on_row_click is set"
            );
        }
        // Without the hook → no callbacks (opt-in, no wasted dispatch).
1
        let mut bare = ListView::default();
1
        bare.rows = ListViewRowVec::from_vec(vec![empty_row()]);
1
        let dom2 = bare.dom();
1
        let rows2 = dom2.children.as_ref()[1].children.as_ref();
1
        assert_eq!(rows2.len(), 1);
1
        assert!(
1
            rows2[0].root.callbacks.as_ref().is_empty(),
            "no callback when on_row_click is unset"
        );
1
    }
}
#[cfg(test)]
#[allow(clippy::float_cmp)] // exact float compares are deliberate here (saturation / identity checks)
mod autotest_generated {
    use azul_core::{
        dom::NodeType,
        menu::{MenuItem, MenuItemVec},
    };
    use super::*;
    // ------------------------------------------------------------------
    // Helpers
    // ------------------------------------------------------------------
    fn cols(names: &[&str]) -> StringVec {
        StringVec::from_vec(names.iter().map(|s| AzString::from(*s)).collect::<Vec<_>>())
    }
    /// A row with `n` text cells (`n == 0` is allowed and deliberately used).
    fn row_with(n: usize) -> ListViewRow {
        ListViewRow {
            cells: DomVec::from_vec(
                (0..n)
                    .map(|i| Dom::create_text_do_not_use_without_block_level_wrapper(format!("c{i}")))
                    .collect::<Vec<_>>(),
            ),
            height: None.into(),
        }
    }
    fn px(v: f32) -> PixelValueNoPercent {
        PixelValueNoPercent {
            inner: PixelValue::px(v),
        }
    }
    extern "C" fn noop_row_cb(_: RefAny, _: CallbackInfo, _: ListViewState, _: usize) -> Update {
        Update::DoNothing
    }
    extern "C" fn noop_col_cb(_: RefAny, _: CallbackInfo, _: ListViewState, _: usize) -> Update {
        Update::DoNothing
    }
    /// The `[header, rows]` container pair every `ListView` DOM is built from.
    fn header_and_rows(dom: &Dom) -> (&Dom, &Dom) {
        let ch = dom.children.as_ref();
        assert_eq!(ch.len(), 2, "list view DOM = [header, rows]");
        (&ch[0], &ch[1])
    }
    /// The text of a text node, looking through the `<p>` block wrapper the
    /// label convention mandates (`p > text`).
    fn text_of(dom: &Dom) -> &str {
        match &dom.root.node_type {
            NodeType::Text(s) => s.as_ref().as_str(),
            NodeType::P => match dom.children.as_ref() {
                [only] => text_of(only),
                _ => panic!("a label <p> must wrap exactly one text node"),
            },
            _ => panic!("expected a text node"),
        }
    }
    // ------------------------------------------------------------------
    // `visible_row_range` — numeric core (zero / negative / NaN / limits)
    // ------------------------------------------------------------------
    /// Every degenerate input documented as "empty" really returns `(0, 0)`,
    /// including `-0.0` (which must count as non-positive, not as a valid height).
    #[test]
    fn visible_row_range_zero_and_degenerate_inputs_are_empty() {
        assert_eq!(ListView::visible_row_range(0.0, 100.0, 10.0, 0), (0, 0));
        assert_eq!(ListView::visible_row_range(0.0, 100.0, 0.0, 5), (0, 0));
        assert_eq!(ListView::visible_row_range(0.0, 100.0, -0.0, 5), (0, 0));
        assert_eq!(ListView::visible_row_range(0.0, 100.0, -10.0, 5), (0, 0));
        assert_eq!(ListView::visible_row_range(0.0, 0.0, 10.0, 5), (0, 0));
        assert_eq!(ListView::visible_row_range(0.0, -0.0, 10.0, 5), (0, 0));
        assert_eq!(ListView::visible_row_range(0.0, -100.0, 10.0, 5), (0, 0));
        assert_eq!(ListView::visible_row_range(0.0, 0.0, 0.0, 0), (0, 0));
    }
    /// A negative scroll offset (rubber-band / over-scroll) must clamp to the
    /// top window rather than wrapping through the `as usize` cast.
    #[test]
    fn visible_row_range_negative_scroll_clamps_to_the_top_window() {
        let top = ListView::visible_row_range(0.0, 200.0, 20.0, 100);
        assert_eq!(top, (0, 11), "10 full rows + 1 straddling the bottom edge");
        for s in [-0.0_f32, -1.0, -0.5, -1e9, -f32::MAX, -f32::MIN_POSITIVE] {
            assert_eq!(
                ListView::visible_row_range(s, 200.0, 20.0, 100),
                top,
                "negative scroll {s} must clamp to the top window"
            );
        }
    }
    /// NaN / ±inf in any float argument yields the documented empty range — no
    /// panic, no garbage index out of the float→int cast.
    #[test]
    fn visible_row_range_nan_and_infinite_inputs_are_empty() {
        for b in [f32::NAN, f32::INFINITY, f32::NEG_INFINITY] {
            assert_eq!(
                ListView::visible_row_range(b, 200.0, 20.0, 100),
                (0, 0),
                "scroll_y = {b}"
            );
            assert_eq!(
                ListView::visible_row_range(0.0, b, 20.0, 100),
                (0, 0),
                "viewport_height = {b}"
            );
            assert_eq!(
                ListView::visible_row_range(0.0, 200.0, b, 100),
                (0, 0),
                "row_height = {b}"
            );
        }
        // All-NaN with the largest possible row count is still empty.
        assert_eq!(
            ListView::visible_row_range(f32::NAN, f32::NAN, f32::NAN, usize::MAX),
            (0, 0)
        );
    }
    /// Scrolling past the end returns the empty tail range, and a `scroll_y`
    /// large enough to saturate the `as usize` cast takes the same path.
    #[test]
    fn visible_row_range_past_the_end_is_an_empty_tail_range() {
        // 10 rows x 20px = 200px of content; scrolling exactly to the end.
        assert_eq!(
            ListView::visible_row_range(200.0, 100.0, 20.0, 10),
            (10, 10)
        );
        assert_eq!(
            ListView::visible_row_range(1e9, 200.0, 20.0, 100),
            (100, 100)
        );
        // f32::MAX / 20 overflows usize; the saturating cast keeps it >= total.
        assert_eq!(
            ListView::visible_row_range(f32::MAX, 200.0, 20.0, 100),
            (100, 100)
        );
        // ... one float ULP before the end is still a live window.
        let (first, last) = ListView::visible_row_range(199.0, 100.0, 20.0, 10);
        assert!(first < last, "just before the end the range is non-empty");
        assert_eq!(last, 10, "and clamps to the row count");
    }
    /// A huge `total_rows` must not make the window huge — only the viewport
    /// decides how many rows are returned.
    #[test]
    fn visible_row_range_window_size_is_bounded_by_the_viewport_not_the_row_count() {
        for total in [1_usize, 2, 1000, u32::MAX as usize, usize::MAX] {
            let (first, last) = ListView::visible_row_range(0.0, 200.0, 20.0, total);
            assert_eq!(first, 0);
            assert_eq!(
                last,
                11.min(total),
                "window stays viewport-sized for total_rows = {total}"
            );
        }
    }
    /// Property: whatever the inputs, the returned window is well-ordered,
    /// clamped to the row count, and actually covers the visible strip.
    #[test]
    fn visible_row_range_window_always_covers_the_viewport() {
        let total = 1000_usize;
        for &h in &[1.0_f32, 7.5, 20.0, 33.3] {
            for &vp in &[1.0_f32, 17.0, 200.0, 999.0] {
                for &s in &[0.0_f32, 0.1, 19.0, 123.456, 5000.0] {
                    let (first, last) = ListView::visible_row_range(s, vp, h, total);
                    assert!(first <= last, "well-ordered range for ({s}, {vp}, {h})");
                    assert!(last <= total, "range clamps to the row count");
                    if first == last {
                        continue; // empty tail range: nothing to cover
                    }
                    let top = first as f32 * h;
                    let bottom = last as f32 * h;
                    assert!(top <= s, "window starts at or above scroll {s} (top {top})");
                    let needed = (s + vp).min(total as f32 * h);
                    assert!(
                        bottom >= needed,
                        "window bottom {bottom} must reach {needed} for ({s}, {vp}, {h})"
                    );
                }
            }
        }
    }
    /// KNOWN BUG — pinned deliberately, do NOT weaken to make it pass.
    ///
    /// `visible_row_range` computes `(viewport_height / row_height).ceil() as
    /// usize + 1` and then `first + visible`. The float→int cast *saturates* to
    /// `usize::MAX`, so the `+ 1` (and the later addition) overflow and panic
    /// under the default dev/test `overflow-checks`. Both inputs below are
    /// finite, positive and pass every existing guard. Expected safe behaviour
    /// is to saturate and clamp to `total_rows`, as the doc comment promises.
    #[test]
    fn visible_row_range_does_not_overflow_on_extreme_but_finite_input() {
        // Sub-pixel row height (degenerate zoom): 1000 / 1e-30 = 1e33, which
        // saturates the cast to usize::MAX -> `+ 1` overflows.
        assert_eq!(ListView::visible_row_range(0.0, 1000.0, 1e-30, 10), (0, 10));
        // `first + visible` overflows even when neither term alone saturates:
        // ~1e19 + ~1e19 > usize::MAX (~1.84e19).
        let (first, last) = ListView::visible_row_range(1.0e19, 1.0e19, 1.0, usize::MAX);
        assert!(first > 0, "a huge scroll lands deep in the list");
        assert_eq!(last, usize::MAX, "the window must clamp to the row count");
    }
    // ------------------------------------------------------------------
    // Constructors / setters — round-trip + invariants
    // ------------------------------------------------------------------
    #[test]
    fn create_sets_columns_and_leaves_everything_else_default() {
        let lv = ListView::create(cols(&["a", "b", "c"]));
        assert_eq!(lv.columns.len(), 3);
        assert_eq!(lv.columns.as_ref()[1].as_str(), "b");
        assert!(lv.rows.is_empty());
        assert!(lv.sorted_by.is_none());
        assert!(lv.content_height.is_none());
        assert!(lv.column_context_menu.is_none());
        assert!(lv.on_lazy_load_scroll.is_none());
        assert!(lv.on_column_click.is_none());
        assert!(lv.on_row_click.is_none());
        assert_eq!(lv.scroll_offset, PixelValueNoPercent::zero());
        // An empty column list is accepted, not rejected or defaulted.
        let empty = ListView::create(StringVec::from_const_slice(&[]));
        assert!(empty.columns.is_empty());
    }
    #[test]
    fn with_and_set_columns_replace_rather_than_append() {
        let b = cols(&["x", "y"]);
        let lv = ListView::default()
            .with_columns(cols(&["one"]))
            .with_columns(b.clone());
        assert_eq!(lv.columns, b, "the last write wins");
        let mut m = ListView::default();
        m.set_columns(b.clone());
        assert_eq!(m.columns, b);
        m.set_columns(StringVec::from_const_slice(&[]));
        assert!(m.columns.is_empty(), "columns can be cleared again");
    }
    /// Column names are opaque payload: empty strings, interior NULs, astral /
    /// ZWJ / RTL / combining sequences and very long strings must survive the
    /// builder *and* the DOM build byte-for-byte.
    #[test]
    fn columns_round_trip_unicode_and_pathological_strings() {
        let names: Vec<String> = vec![
            String::new(),
            "\u{0}".to_string(),
            "🦀👨‍👩‍👧‍👦".to_string(),
            "مرحبا بالعالم".to_string(),
            "e\u{301}\u{301}\u{301}".to_string(),
            "\u{feff}leading BOM".to_string(),
            "line\nbreak\ttab".to_string(),
            "x".repeat(10_000),
        ];
        let sv = StringVec::from_vec(
            names
                .iter()
                .map(|s| AzString::from(s.clone()))
                .collect::<Vec<_>>(),
        );
        let lv = ListView::default().with_columns(sv);
        assert_eq!(lv.columns.len(), names.len());
        for (got, want) in lv.columns.iter().zip(names.iter()) {
            assert_eq!(got.as_str(), want.as_str(), "column name must round-trip");
        }
        let dom = lv.dom();
        let (header, _) = header_and_rows(&dom);
        let hdr = header.children.as_ref();
        assert_eq!(hdr.len(), names.len());
        for (col, want) in hdr.iter().zip(names.iter()) {
            let text = col.children.as_ref();
            assert_eq!(text.len(), 1, "each header cell holds one text node");
            assert_eq!(text_of(&text[0]), want.as_str());
        }
    }
    #[test]
    fn with_and_set_rows_round_trip_including_empty_and_ragged_rows() {
        let lv = ListView::default().with_rows(ListViewRowVec::from_vec(vec![
            row_with(0),
            row_with(1),
            row_with(5),
        ]));
        assert_eq!(lv.rows.len(), 3);
        assert_eq!(lv.rows.as_ref()[0].cells.len(), 0);
        assert_eq!(lv.rows.as_ref()[2].cells.len(), 5);
        let mut m = ListView::default().with_rows(ListViewRowVec::from_vec(vec![row_with(2)]));
        m.set_rows(ListViewRowVec::from_const_slice(&[]));
        assert!(m.rows.is_empty(), "rows can be cleared again");
    }
    /// `sorted_by` is a raw column index with no validation — an out-of-range
    /// value is stored verbatim and must not break the DOM build.
    #[test]
    fn sorted_by_is_stored_verbatim_even_when_out_of_range() {
        for v in [None, Some(0_usize), Some(2), Some(usize::MAX)] {
            let lv = ListView::create(cols(&["a", "b"])).with_sorted_by(v.into());
            assert_eq!(
                lv.sorted_by.as_ref().copied(),
                v,
                "sorted_by is not validated against the column count"
            );
            let dom = lv.dom();
            let (header, _) = header_and_rows(&dom);
            assert_eq!(header.children.as_ref().len(), 2);
        }
        let mut m = ListView::default();
        m.set_sorted_by(Some(7_usize).into());
        assert_eq!(m.sorted_by.as_ref().copied(), Some(7));
        m.set_sorted_by(None.into());
        assert!(m.sorted_by.is_none(), "sorted_by can be reset to None");
    }
    /// The fixed-point `PixelValue` encoding saturates (NaN -> 0, ±inf -> the
    /// isize limits) instead of trapping, and the setter stores the value bit
    /// for bit.
    #[test]
    fn scroll_offset_round_trips_extreme_and_non_finite_values() {
        for v in [
            0.0_f32,
            -0.0,
            1.0,
            -1.0,
            0.001,
            -12345.678,
            f32::MAX,
            f32::MIN,
            f32::MIN_POSITIVE,
            f32::NAN,
            f32::INFINITY,
            f32::NEG_INFINITY,
        ] {
            let p = px(v);
            let lv = ListView::default().with_scroll_offset(p);
            assert_eq!(lv.scroll_offset, p, "scroll_offset stored verbatim ({v})");
            let got = lv.scroll_offset.inner.number.get();
            assert!(
                got.is_finite(),
                "encoded offset stays finite for {v} (got {got})"
            );
        }
        assert_eq!(px(f32::NAN).inner.number.get(), 0.0, "NaN saturates to 0");
        assert!(px(f32::INFINITY).inner.number.get() > 0.0);
        assert!(px(f32::NEG_INFINITY).inner.number.get() < 0.0);
        let mut m = ListView::default();
        m.set_scroll_offset(px(5.0));
        m.set_scroll_offset(px(-5.0));
        assert_eq!(m.scroll_offset, px(-5.0), "the last write wins");
    }
    /// `PixelValueNoPercent` does not actually reject a `%` metric — the setter
    /// takes whatever it is handed. Pinned so a future validation change is a
    /// deliberate decision, not a silent one.
    #[test]
    fn scroll_offset_accepts_a_percent_metric_despite_the_type_name() {
        let percent = PixelValueNoPercent {
            inner: PixelValue::percent(50.0),
        };
        let lv = ListView::default().with_scroll_offset(percent);
        assert_eq!(lv.scroll_offset, percent);
        assert_eq!(lv.scroll_offset.inner.metric, SizeMetric::Percent);
    }
    #[test]
    fn content_height_wraps_in_some_and_has_no_clearing_setter() {
        let mut m = ListView::default();
        assert!(m.content_height.is_none(), "unset by default");
        for v in [0.0_f32, -1.0, f32::MAX, f32::NAN, f32::NEG_INFINITY] {
            let p = px(v);
            m.set_content_height(p);
            assert_eq!(m.content_height.as_ref(), Some(&p), "stores {v} verbatim");
            assert!(m
                .content_height
                .as_ref()
                .expect("just set")
                .inner
                .number
                .get()
                .is_finite());
        }
        assert!(
            m.content_height.is_some(),
            "Some() is sticky — no unset API"
        );
        let lv = ListView::default().with_content_height(px(42.0));
        assert_eq!(lv.content_height.as_ref(), Some(&px(42.0)));
    }
    #[test]
    fn column_context_menu_is_stored_and_replaced() {
        let mut m = ListView::default();
        assert!(m.column_context_menu.is_none());
        let empty_menu = Menu::create(MenuItemVec::from_const_slice(&[]));
        m.set_column_context_menu(empty_menu.clone());
        assert_eq!(
            m.column_context_menu.as_ref(),
            Some(&empty_menu),
            "an empty menu is accepted, not silently dropped"
        );
        let full = Menu::create(MenuItemVec::from_vec(vec![MenuItem::Separator; 256]));
        m.set_column_context_menu(full.clone());
        assert_eq!(
            m.column_context_menu.as_ref(),
            Some(&full),
            "last write wins"
        );
        assert!(
            m.column_context_menu.is_some(),
            "there is no way to unset it"
        );
        let lv = ListView::default().with_column_context_menu(full.clone());
        assert_eq!(lv.column_context_menu.as_ref(), Some(&full));
        // The menu is metadata only — it must not alter the DOM shape.
        let dom = lv.dom();
        let (header, rows) = header_and_rows(&dom);
        assert!(header.children.as_ref().is_empty());
        assert!(rows.children.as_ref().is_empty());
    }
    #[test]
    fn click_hook_setters_replace_rather_than_accumulate() {
        let rcb: ListViewOnRowClickCallbackType = noop_row_cb;
        let ccb: ListViewOnColumnClickCallbackType = noop_col_cb;
        let mut m = ListView::default();
        assert!(m.on_row_click.is_none());
        assert!(m.on_column_click.is_none());
        m.set_on_row_click(RefAny::new(1_u32), rcb);
        m.set_on_row_click(RefAny::new(2_u32), rcb);
        assert!(m.on_row_click.is_some());
        let mut payload = m.on_row_click.as_ref().expect("just set").refany.clone();
        assert_eq!(
            *payload.downcast_ref::<u32>().expect("u32 payload"),
            2,
            "the second registration replaces the first"
        );
        let lv = ListView::default()
            .with_on_row_click(RefAny::new(()), rcb)
            .with_on_column_click(RefAny::new(()), ccb);
        assert!(lv.on_row_click.is_some());
        assert!(lv.on_column_click.is_some());
        assert!(
            lv.on_lazy_load_scroll.is_none(),
            "unrelated hooks stay unset"
        );
    }
    // ------------------------------------------------------------------
    // `swap_with_default`
    // ------------------------------------------------------------------
    #[test]
    fn swap_with_default_moves_state_out_and_leaves_a_pristine_default() {
        let rcb: ListViewOnRowClickCallbackType = noop_row_cb;
        let mut lv = ListView::create(cols(&["a", "b"]))
            .with_rows(ListViewRowVec::from_vec(vec![row_with(1)]))
            .with_sorted_by(Some(1_usize).into())
            .with_scroll_offset(px(9.0))
            .with_content_height(px(1000.0))
            .with_column_context_menu(Menu::create(MenuItemVec::from_const_slice(&[])))
            .with_on_row_click(RefAny::new(()), rcb);
        let taken = lv.swap_with_default();
        assert_eq!(taken.columns.len(), 2);
        assert_eq!(taken.rows.len(), 1);
        assert_eq!(taken.sorted_by.as_ref().copied(), Some(1));
        assert_eq!(taken.scroll_offset, px(9.0));
        assert!(taken.content_height.is_some());
        assert!(taken.column_context_menu.is_some());
        assert!(taken.on_row_click.is_some());
        assert!(lv.columns.is_empty());
        assert!(lv.rows.is_empty());
        assert!(lv.sorted_by.is_none());
        assert_eq!(lv.scroll_offset, PixelValueNoPercent::zero());
        assert!(lv.content_height.is_none());
        assert!(lv.column_context_menu.is_none());
        assert!(lv.on_row_click.is_none());
        assert!(lv.on_column_click.is_none());
        assert!(lv.on_lazy_load_scroll.is_none());
        // Repeated swaps of an already-default value are a no-op, not a
        // double-free of the moved-out heap buffers.
        let again = lv.swap_with_default();
        assert!(again.columns.is_empty() && again.rows.is_empty());
        let third = lv.swap_with_default();
        assert!(third.columns.is_empty() && third.rows.is_empty());
        drop(taken);
    }
    // ------------------------------------------------------------------
    // `dom()` — shape + callback wiring
    // ------------------------------------------------------------------
    #[test]
    fn dom_shape_matches_the_column_and_row_counts() {
        let empty = ListView::default().dom();
        let (h, r) = header_and_rows(&empty);
        assert!(h.children.as_ref().is_empty());
        assert!(r.children.as_ref().is_empty());
        // Columns without rows and rows without columns are both legal.
        let no_rows = ListView::create(cols(&["a", "b"])).dom();
        let (h, r) = header_and_rows(&no_rows);
        assert_eq!(h.children.as_ref().len(), 2);
        assert!(r.children.as_ref().is_empty());
        let no_cols = ListView::default()
            .with_rows(ListViewRowVec::from_vec(vec![row_with(3)]))
            .dom();
        let (h, r) = header_and_rows(&no_cols);
        assert!(h.children.as_ref().is_empty());
        assert_eq!(r.children.as_ref().len(), 1);
        assert_eq!(
            r.children.as_ref()[0].children.as_ref().len(),
            3,
            "cells are rendered even with no matching column headers"
        );
        // Ragged rows keep their own cell counts (no padding to the column count).
        let ragged = ListView::create(cols(&["a", "b", "c"]))
            .with_rows(ListViewRowVec::from_vec(vec![
                row_with(0),
                row_with(1),
                row_with(3),
                row_with(7),
            ]))
            .dom();
        let (h, r) = header_and_rows(&ragged);
        assert_eq!(h.children.as_ref().len(), 3);
        let rows = r.children.as_ref();
        assert_eq!(rows.len(), 4);
        for (row, want) in rows.iter().zip([0_usize, 1, 3, 7]) {
            assert_eq!(row.children.as_ref().len(), want);
            for cell in row.children.as_ref() {
                assert_eq!(cell.children.as_ref().len(), 1, "one child per cell");
            }
        }
    }
    /// The wired-in `MouseUp` handler must receive the *right* index and a
    /// faithful snapshot of the list state — this exercises the exact
    /// `downcast_ref` path `on_list_view_{row,column}_click` take.
    #[test]
    fn dom_wires_click_payloads_with_the_right_index_and_state_snapshot() {
        let rcb: ListViewOnRowClickCallbackType = noop_row_cb;
        let ccb: ListViewOnColumnClickCallbackType = noop_col_cb;
        let lv = ListView::create(cols(&["c0", "c1"]))
            .with_rows(ListViewRowVec::from_vec(vec![
                row_with(2),
                row_with(2),
                row_with(2),
            ]))
            .with_sorted_by(Some(1_usize).into())
            .with_scroll_offset(px(-17.5))
            .with_on_row_click(RefAny::new(()), rcb)
            .with_on_column_click(RefAny::new(()), ccb);
        let dom = lv.dom();
        let (header, rows) = header_and_rows(&dom);
        for (i, col) in header.children.as_ref().iter().enumerate() {
            let cbs = col.root.callbacks.as_ref();
            assert_eq!(cbs.len(), 1);
            assert!(matches!(
                cbs[0].event,
                EventFilter::Hover(HoverEventFilter::MouseUp)
            ));
            assert_eq!(cbs[0].callback.cb, on_list_view_column_click as usize);
            let mut any = cbs[0].refany.clone();
            let data = any
                .downcast_ref::<ColumnClickData>()
                .expect("ColumnClickData payload");
            assert_eq!(data.col_index, i, "each header carries its own index");
            assert_eq!(data.state.current_row_count, 3);
            assert_eq!(data.state.columns.len(), 2);
            assert_eq!(data.state.sorted_by.as_ref().copied(), Some(1));
            assert_eq!(data.state.scroll_offset, px(-17.5));
            assert!(data.on_column_click.is_some());
        }
        for (i, row) in rows.children.as_ref().iter().enumerate() {
            let cbs = row.root.callbacks.as_ref();
            assert_eq!(cbs.len(), 1);
            assert!(matches!(
                cbs[0].event,
                EventFilter::Hover(HoverEventFilter::MouseUp)
            ));
            assert_eq!(cbs[0].callback.cb, on_list_view_row_click as usize);
            let mut any = cbs[0].refany.clone();
            let data = any
                .downcast_ref::<RowClickData>()
                .expect("RowClickData payload");
            assert_eq!(data.row_index, i, "each row carries its own index");
            assert_eq!(data.state.current_row_count, 3);
            assert!(data.on_row_click.is_some());
        }
    }
    /// Row and column hooks are wired independently — setting one must not
    /// attach a dispatcher to the other.
    #[test]
    fn click_callbacks_are_wired_per_hook_and_only_when_set() {
        let rcb: ListViewOnRowClickCallbackType = noop_row_cb;
        let ccb: ListViewOnColumnClickCallbackType = noop_col_cb;
        let bare = ListView::create(cols(&["a", "b"])).dom();
        let (h, _) = header_and_rows(&bare);
        for col in h.children.as_ref() {
            assert!(
                col.root.callbacks.as_ref().is_empty(),
                "no hook, no dispatch"
            );
        }
        let row_only = ListView::create(cols(&["a"]))
            .with_rows(ListViewRowVec::from_vec(vec![row_with(1)]))
            .with_on_row_click(RefAny::new(()), rcb)
            .dom();
        let (h, r) = header_and_rows(&row_only);
        assert!(h.children.as_ref()[0].root.callbacks.as_ref().is_empty());
        assert_eq!(r.children.as_ref()[0].root.callbacks.as_ref().len(), 1);
        let col_only = ListView::create(cols(&["a"]))
            .with_rows(ListViewRowVec::from_vec(vec![row_with(1)]))
            .with_on_column_click(RefAny::new(()), ccb)
            .dom();
        let (h, r) = header_and_rows(&col_only);
        assert_eq!(h.children.as_ref()[0].root.callbacks.as_ref().len(), 1);
        assert!(r.children.as_ref()[0].root.callbacks.as_ref().is_empty());
    }
    /// A wrong-typed payload must make the internal handlers bail out rather
    /// than reinterpreting foreign memory. `CallbackInfo` cannot be built here
    /// without the full `LayoutWindow` harness, so this pins the guard that
    /// runs *before* any `CallbackInfo` use: the `downcast_ref` type check.
    #[test]
    fn click_handler_payload_downcast_rejects_foreign_types() {
        let mut wrong = RefAny::new(0_u64);
        assert!(
            wrong.downcast_ref::<RowClickData>().is_none(),
            "handler must not accept a foreign payload type"
        );
        assert!(wrong.downcast_ref::<ColumnClickData>().is_none());
        // ... and a RowClickData payload is not mistaken for a ColumnClickData.
        let mut row_payload = RefAny::new(RowClickData {
            row_index: 0,
            state: ListViewState {
                columns: StringVec::from_const_slice(&[]),
                sorted_by: None.into(),
                current_row_count: 0,
                scroll_offset: PixelValueNoPercent::zero(),
                current_scroll_position: LogicalPosition::zero(),
                current_content_height: LogicalSize::zero(),
            },
            on_row_click: None.into(),
        });
        assert!(row_payload.downcast_ref::<ColumnClickData>().is_none());
        assert!(row_payload.downcast_ref::<RowClickData>().is_some());
    }
    #[test]
    fn dom_survives_a_large_column_and_row_count() {
        const N_COLS: usize = 64;
        const N_ROWS: usize = 64;
        let rcb: ListViewOnRowClickCallbackType = noop_row_cb;
        let names = (0..N_COLS)
            .map(|i| AzString::from(format!("col{i}")))
            .collect::<Vec<_>>();
        let rows = (0..N_ROWS).map(|_| row_with(N_COLS)).collect::<Vec<_>>();
        let dom = ListView::create(StringVec::from_vec(names))
            .with_rows(ListViewRowVec::from_vec(rows))
            .with_on_row_click(RefAny::new(()), rcb)
            .dom();
        let (h, r) = header_and_rows(&dom);
        assert_eq!(h.children.as_ref().len(), N_COLS);
        assert_eq!(r.children.as_ref().len(), N_ROWS);
        for row in r.children.as_ref() {
            assert_eq!(row.children.as_ref().len(), N_COLS);
            assert_eq!(row.root.callbacks.as_ref().len(), 1);
        }
    }
}