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}