Skip to main content

three_consumer_probe/
three_consumer_probe.rs

1use operad::{
2    layout, root_style, AccessibilityAction, AccessibilityMeta, AccessibilityRole,
3    ApproxTextMeasurer, ColorRgba, InputBehavior, ScrollAxes, StrokeStyle, TextStyle, UiDocument,
4    UiInputEvent, UiNode, UiPoint, UiSize, UiVisual,
5};
6
7fn main() -> Result<(), String> {
8    let probes = [
9        ("game_overlay", build_game_overlay()),
10        ("tool_panel", build_tool_panel()),
11        ("timeline_editor", build_timeline_editor()),
12    ];
13
14    for (name, mut document) in probes {
15        document
16            .compute_layout(UiSize::new(800.0, 600.0), &mut ApproxTextMeasurer)
17            .map_err(|error| format!("{name} layout failed: {error}"))?;
18        let warnings = document.audit_layout();
19        if !warnings.is_empty() {
20            return Err(format!(
21                "{name} should have no basic layout audit warnings: {warnings:#?}"
22            ));
23        }
24        if document.paint_list().is_empty() {
25            return Err(format!("{name} should produce renderer-neutral paint"));
26        }
27        println!("{name}: {} paint items", document.paint_list().items.len());
28    }
29    Ok(())
30}
31
32fn build_game_overlay() -> UiDocument {
33    let mut document = UiDocument::new(root_style(800.0, 600.0));
34    let hotbar = document.add_child(
35        document.root(),
36        UiNode::container(
37            "game.hotbar",
38            layout::clipped_node_style(layout::with_margin_bottom(
39                layout::with_auto_horizontal_margin(layout::with_size(
40                    layout::centered_row(),
41                    layout::px(360.0),
42                    layout::px(64.0),
43                )),
44                18.0,
45            ))
46            .with_z_index(10),
47        )
48        .with_visual(UiVisual::panel(
49            ColorRgba::new(20, 24, 31, 230),
50            Some(StrokeStyle::new(ColorRgba::new(96, 113, 139, 255), 1.0)),
51            6.0,
52        )),
53    );
54
55    for slot in 0..8 {
56        document.add_child(
57            hotbar,
58            UiNode::container(
59                format!("game.hotbar.slot.{slot}"),
60                layout::node_style(layout::with_margin_all(layout::fixed(36.0, 36.0), 4.0)),
61            )
62            .with_input(InputBehavior::BUTTON)
63            .with_accessibility(
64                AccessibilityMeta::new(AccessibilityRole::Button)
65                    .label(format!("Hotbar slot {}", slot + 1))
66                    .focusable()
67                    .action(AccessibilityAction::new("activate", "Activate")),
68            )
69            .with_visual(UiVisual::panel(
70                ColorRgba::new(40, 49, 62, 255),
71                Some(StrokeStyle::new(ColorRgba::new(105, 124, 153, 255), 1.0)),
72                4.0,
73            )),
74        );
75    }
76
77    document
78}
79
80fn build_tool_panel() -> UiDocument {
81    let mut document = UiDocument::new(root_style(800.0, 600.0));
82    let panel = document.add_child(
83        document.root(),
84        UiNode::container(
85            "tool.sidebar.modules",
86            layout::clipped_node_style(layout::with_size(
87                layout::column(),
88                layout::px(260.0),
89                layout::px(220.0),
90            )),
91        )
92        .with_scroll(ScrollAxes::VERTICAL)
93        .with_visual(UiVisual::panel(
94            ColorRgba::new(28, 33, 39, 255),
95            Some(StrokeStyle::new(ColorRgba::new(74, 85, 104, 255), 1.0)),
96            4.0,
97        )),
98    );
99
100    for row in 0..12 {
101        let label = format!("Layer module {}", row + 1);
102        document.add_child(
103            panel,
104            UiNode::text(
105                format!("tool.module.{row}"),
106                label.clone(),
107                TextStyle::default(),
108                layout::size(layout::percent(1.0), layout::px(32.0)),
109            )
110            .with_input(InputBehavior::BUTTON)
111            .with_accessibility(
112                AccessibilityMeta::new(AccessibilityRole::Button)
113                    .label(label)
114                    .focusable()
115                    .action(AccessibilityAction::new("activate", "Activate")),
116            ),
117        );
118    }
119
120    document.handle_input(UiInputEvent::wheel(
121        UiPoint::new(12.0, 12.0),
122        UiPoint::new(0.0, 24.0),
123    ));
124
125    document
126}
127
128fn build_timeline_editor() -> UiDocument {
129    let mut document = UiDocument::new(root_style(800.0, 600.0));
130    let shell = document.add_child(
131        document.root(),
132        UiNode::container(
133            "timeline.shell",
134            layout::clipped_node_style(layout::with_size(
135                layout::column(),
136                layout::percent(1.0),
137                layout::percent(1.0),
138            )),
139        ),
140    );
141
142    document.add_child(
143        shell,
144        UiNode::text(
145            "timeline.transport",
146            "Transport",
147            TextStyle::default(),
148            layout::size(layout::percent(1.0), layout::px(32.0)),
149        )
150        .with_visual(UiVisual::panel(
151            ColorRgba::new(30, 36, 44, 255),
152            Some(StrokeStyle::new(ColorRgba::new(84, 96, 115, 255), 1.0)),
153            0.0,
154        )),
155    );
156    document.add_child(
157        shell,
158        UiNode::canvas(
159            "timeline.editor",
160            "timeline.editor.display_list_surface",
161            layout::size(layout::percent(1.0), layout::px(260.0)),
162        )
163        .with_accessibility(
164            AccessibilityMeta::new(AccessibilityRole::EditorSurface)
165                .label("Timeline editor")
166                .focusable(),
167        )
168        .with_visual(UiVisual::panel(
169            ColorRgba::new(16, 19, 23, 255),
170            Some(StrokeStyle::new(ColorRgba::new(64, 75, 92, 255), 1.0)),
171            0.0,
172        )),
173    );
174
175    document
176}