1use crate::{Application, Expr, ExprKind, Node, Prop};
9use bern_protocol::Value;
10
11impl Application {
12 pub fn on_platform(&self, platform: &str) -> Application {
17 let mut app = self.with_menu_bar(platform == "macos");
18 if app.style.corners.is_empty() {
19 return app;
20 }
21 let style = std::mem::take(&mut app.style);
22 let radius = |name: &str, radius: f64| style.corner(name, platform).unwrap_or(radius);
23 for component in &mut app.components {
24 resolve_node(&mut component.body, &radius);
25 }
26 for window in &mut app.windows.windows {
27 resolve_node(&mut window.content, &radius);
28 }
29 app.style = style;
30 app
31 }
32}
33
34fn resolve_node(node: &mut Node, radius: &impl Fn(&str, f64) -> f64) {
35 match node {
36 Node::Element(element) => {
37 for prop in element.props.values_mut() {
38 let Prop::Expr { expr } = prop else {
39 continue;
40 };
41 if let ExprKind::Corner {
43 name,
44 radius: value,
45 } = &expr.kind
46 {
47 *prop = Prop::Number {
48 value: radius(name, *value),
49 };
50 continue;
51 }
52 resolve_expr(expr, radius);
53 }
54 for child in &mut element.children {
55 resolve_node(child, radius);
56 }
57 }
58 Node::Component(_) => {}
59 Node::If(node) => {
60 for (_, body) in &mut node.branches {
61 for child in body {
62 resolve_node(child, radius);
63 }
64 }
65 for child in &mut node.otherwise {
66 resolve_node(child, radius);
67 }
68 }
69 Node::IfLet(node) => {
70 for child in node.then.iter_mut().chain(&mut node.otherwise) {
71 resolve_node(child, radius);
72 }
73 }
74 Node::Match(node) => {
75 for arm in &mut node.arms {
76 for child in &mut arm.body {
77 resolve_node(child, radius);
78 }
79 }
80 }
81 }
82}
83
84fn resolve_expr(expr: &mut Expr, radius: &impl Fn(&str, f64) -> f64) {
85 match &mut expr.kind {
86 ExprKind::Corner {
87 name,
88 radius: value,
89 } => {
90 expr.kind = ExprKind::Literal {
91 value: Value::Float(radius(name, *value)),
92 };
93 }
94 ExprKind::Literal { .. } | ExprKind::Binding { .. } => {}
95 ExprKind::Variant { fields, .. } => {
96 for field in fields {
97 resolve_expr(field, radius);
98 }
99 }
100 ExprKind::Not { expr } | ExprKind::Neg { expr } => resolve_expr(expr, radius),
101 ExprKind::Binary { lhs, rhs, .. } => {
102 resolve_expr(lhs, radius);
103 resolve_expr(rhs, radius);
104 }
105 ExprKind::If {
106 cond,
107 then,
108 otherwise,
109 } => {
110 resolve_expr(cond, radius);
111 resolve_expr(then, radius);
112 resolve_expr(otherwise, radius);
113 }
114 }
115}