Skip to main content

sequoia_seq/
bindings.rs

1use std::cell::Cell;
2use std::collections::HashMap;
3use std::rc::Rc;
4
5use sequoia_async::Resource;
6use sequoia_reactive::{I18n, Memo, Signal};
7
8#[derive(Clone, Copy, Debug, PartialEq, Eq)]
9pub enum PropType {
10    Str,
11    Bool,
12    Int,
13    Float,
14}
15
16impl PropType {
17    pub fn from_seq(name: &str) -> Option<Self> {
18        match name {
19            "String" => Some(Self::Str),
20            "Bool" => Some(Self::Bool),
21            "Int" => Some(Self::Int),
22            "Float" => Some(Self::Float),
23            _ => None,
24        }
25    }
26
27    pub fn seq_name(self) -> &'static str {
28        match self {
29            Self::Str => "String",
30            Self::Bool => "Bool",
31            Self::Int => "Int",
32            Self::Float => "Float",
33        }
34    }
35}
36
37#[derive(Clone, Copy, Debug, PartialEq, Eq)]
38pub enum ActionSig {
39    A0,
40
41    Int,
42
43    Float,
44
45    Str,
46
47    Bool,
48
49    Point,
50
51    PointNamed,
52
53    Wheel,
54
55    Pinch,
56}
57
58#[derive(Clone)]
59pub enum FieldSignal {
60    Str(Signal<String>),
61
62    Bool(Signal<bool>),
63
64    Int(Signal<i64>),
65
66    Float(Signal<f64>),
67}
68
69pub trait SeqRow {
70    fn id(&self) -> i64;
71
72    fn fields(&self) -> Vec<(String, FieldSignal)>;
73}
74
75#[derive(Clone)]
76pub struct SeqRowData {
77    pub id: i64,
78
79    pub fields: HashMap<String, FieldSignal>,
80}
81
82pub(crate) type RowsFn = std::rc::Rc<dyn Fn() -> Vec<SeqRowData>>;
83
84pub(crate) type PointNamedAction = Rc<dyn Fn(f64, f64, String)>;
85
86pub(crate) type WheelAction = Rc<dyn Fn(f64, f64, f64)>;
87
88pub(crate) type PinchAction = Rc<dyn Fn(f64, f64, f64)>;
89
90impl SeqRowData {
91    fn snapshot<R: SeqRow>(row: &R) -> Self {
92        Self {
93            id: row.id(),
94            fields: row.fields().into_iter().collect(),
95        }
96    }
97}
98
99#[derive(Clone, Default)]
100pub struct HostBindings {
101    strings: HashMap<String, Signal<String>>,
102    bools: HashMap<String, Signal<bool>>,
103    ints: HashMap<String, Signal<i64>>,
104    floats: HashMap<String, Signal<f64>>,
105    memo_strings: HashMap<String, Memo<String>>,
106    memo_bools: HashMap<String, Memo<bool>>,
107    memo_ints: HashMap<String, Memo<i64>>,
108    memo_floats: HashMap<String, Memo<f64>>,
109    env_strings: HashMap<String, Signal<String>>,
110    env_bools: HashMap<String, Signal<bool>>,
111    env_ints: HashMap<String, Signal<i64>>,
112    env_floats: HashMap<String, Signal<f64>>,
113    i18n: Option<I18n>,
114    resources: HashMap<String, Resource<String>>,
115    rows: HashMap<String, RowsFn>,
116    actions0: HashMap<String, Rc<dyn Fn()>>,
117    actions_int: HashMap<String, Rc<dyn Fn(i64)>>,
118    actions_float: HashMap<String, Rc<dyn Fn(f64)>>,
119    actions_str: HashMap<String, Rc<dyn Fn(String)>>,
120    actions_bool: HashMap<String, Rc<dyn Fn(bool)>>,
121    actions_point: HashMap<String, Rc<dyn Fn(f64, f64)>>,
122    actions_point_named: HashMap<String, PointNamedAction>,
123    actions_wheel: HashMap<String, WheelAction>,
124    actions_pinch: HashMap<String, PinchAction>,
125
126    tick_angles: HashMap<String, Rc<Cell<f32>>>,
127
128    seq: Option<Rc<crate::eval::SeqRuntime>>,
129}
130
131impl HostBindings {
132    pub fn new() -> Self {
133        Self::default()
134    }
135
136    #[must_use]
137    pub(crate) fn with_seq(mut self, rt: Rc<crate::eval::SeqRuntime>) -> Self {
138        self.seq = Some(rt);
139        self
140    }
141
142    pub(crate) fn get_seq(&self) -> Option<Rc<crate::eval::SeqRuntime>> {
143        self.seq.clone()
144    }
145
146    pub fn prop_str(mut self, name: impl Into<String>, sig: Signal<String>) -> Self {
147        self.strings.insert(name.into(), sig);
148        self
149    }
150
151    pub fn prop_bool(mut self, name: impl Into<String>, sig: Signal<bool>) -> Self {
152        self.bools.insert(name.into(), sig);
153        self
154    }
155
156    pub fn prop_int(mut self, name: impl Into<String>, sig: Signal<i64>) -> Self {
157        self.ints.insert(name.into(), sig);
158        self
159    }
160
161    pub fn prop_float(mut self, name: impl Into<String>, sig: Signal<f64>) -> Self {
162        self.floats.insert(name.into(), sig);
163        self
164    }
165
166    pub fn tick_angle(mut self, name: impl Into<String>, angle: Rc<Cell<f32>>) -> Self {
167        self.tick_angles.insert(name.into(), angle);
168        self
169    }
170
171    pub fn memo_str(mut self, name: impl Into<String>, memo: Memo<String>) -> Self {
172        self.memo_strings.insert(name.into(), memo);
173        self
174    }
175
176    pub fn memo_bool(mut self, name: impl Into<String>, memo: Memo<bool>) -> Self {
177        self.memo_bools.insert(name.into(), memo);
178        self
179    }
180
181    pub fn memo_int(mut self, name: impl Into<String>, memo: Memo<i64>) -> Self {
182        self.memo_ints.insert(name.into(), memo);
183        self
184    }
185
186    pub fn memo_float(mut self, name: impl Into<String>, memo: Memo<f64>) -> Self {
187        self.memo_floats.insert(name.into(), memo);
188        self
189    }
190
191    pub fn env_str(mut self, name: impl Into<String>, sig: Signal<String>) -> Self {
192        self.env_strings.insert(name.into(), sig);
193        self
194    }
195
196    pub fn env_bool(mut self, name: impl Into<String>, sig: Signal<bool>) -> Self {
197        self.env_bools.insert(name.into(), sig);
198        self
199    }
200
201    pub fn env_int(mut self, name: impl Into<String>, sig: Signal<i64>) -> Self {
202        self.env_ints.insert(name.into(), sig);
203        self
204    }
205
206    pub fn env_float(mut self, name: impl Into<String>, sig: Signal<f64>) -> Self {
207        self.env_floats.insert(name.into(), sig);
208        self
209    }
210
211    pub fn i18n(mut self, i18n: I18n) -> Self {
212        self.i18n = Some(i18n);
213        self
214    }
215
216    pub fn resource(mut self, name: impl Into<String>, res: Resource<String>) -> Self {
217        self.resources.insert(name.into(), res);
218        self
219    }
220
221    pub fn on(mut self, name: impl Into<String>, f: impl Fn() + 'static) -> Self {
222        self.actions0.insert(name.into(), Rc::new(f));
223        self
224    }
225
226    pub fn on_int(mut self, name: impl Into<String>, f: impl Fn(i64) + 'static) -> Self {
227        self.actions_int.insert(name.into(), Rc::new(f));
228        self
229    }
230
231    pub fn on_float(mut self, name: impl Into<String>, f: impl Fn(f64) + 'static) -> Self {
232        self.actions_float.insert(name.into(), Rc::new(f));
233        self
234    }
235
236    pub fn on_str(mut self, name: impl Into<String>, f: impl Fn(String) + 'static) -> Self {
237        self.actions_str.insert(name.into(), Rc::new(f));
238        self
239    }
240
241    pub fn on_bool(mut self, name: impl Into<String>, f: impl Fn(bool) + 'static) -> Self {
242        self.actions_bool.insert(name.into(), Rc::new(f));
243        self
244    }
245
246    pub fn on_point(mut self, name: impl Into<String>, f: impl Fn(f64, f64) + 'static) -> Self {
247        self.actions_point.insert(name.into(), Rc::new(f));
248        self
249    }
250
251    pub fn on_point_named(
252        mut self,
253        name: impl Into<String>,
254        f: impl Fn(f64, f64, String) + 'static,
255    ) -> Self {
256        self.actions_point_named.insert(name.into(), Rc::new(f));
257        self
258    }
259
260    pub fn rows<R>(mut self, name: impl Into<String>, sig: Signal<Vec<R>>) -> Self
261    where
262        R: SeqRow + Clone + PartialEq + 'static,
263    {
264        self.rows.insert(
265            name.into(),
266            Rc::new(move || sig.get().iter().map(SeqRowData::snapshot).collect()),
267        );
268        self
269    }
270
271    pub(crate) fn prop_type(&self, name: &str) -> Option<PropType> {
272        if self.strings.contains_key(name) || self.memo_strings.contains_key(name) {
273            Some(PropType::Str)
274        } else if self.bools.contains_key(name) || self.memo_bools.contains_key(name) {
275            Some(PropType::Bool)
276        } else if self.ints.contains_key(name) || self.memo_ints.contains_key(name) {
277            Some(PropType::Int)
278        } else if self.floats.contains_key(name) || self.memo_floats.contains_key(name) {
279            Some(PropType::Float)
280        } else {
281            None
282        }
283    }
284
285    pub(crate) fn get_str(&self, name: &str) -> Option<Signal<String>> {
286        self.strings.get(name).cloned()
287    }
288
289    pub(crate) fn get_bool(&self, name: &str) -> Option<Signal<bool>> {
290        self.bools.get(name).cloned()
291    }
292
293    pub(crate) fn get_int(&self, name: &str) -> Option<Signal<i64>> {
294        self.ints.get(name).cloned()
295    }
296
297    pub(crate) fn get_float(&self, name: &str) -> Option<Signal<f64>> {
298        self.floats.get(name).cloned()
299    }
300
301    pub(crate) fn get_tick_angle(&self, name: &str) -> Option<Rc<Cell<f32>>> {
302        self.tick_angles.get(name).cloned()
303    }
304
305    pub(crate) fn get_memo_str(&self, name: &str) -> Option<Memo<String>> {
306        self.memo_strings.get(name).cloned()
307    }
308
309    pub(crate) fn get_memo_bool(&self, name: &str) -> Option<Memo<bool>> {
310        self.memo_bools.get(name).cloned()
311    }
312
313    pub(crate) fn get_memo_int(&self, name: &str) -> Option<Memo<i64>> {
314        self.memo_ints.get(name).cloned()
315    }
316
317    pub(crate) fn get_memo_float(&self, name: &str) -> Option<Memo<f64>> {
318        self.memo_floats.get(name).cloned()
319    }
320
321    pub(crate) fn get_env_str(&self, name: &str) -> Option<Signal<String>> {
322        self.env_strings.get(name).cloned()
323    }
324
325    pub(crate) fn get_env_bool(&self, name: &str) -> Option<Signal<bool>> {
326        self.env_bools.get(name).cloned()
327    }
328
329    pub(crate) fn get_env_int(&self, name: &str) -> Option<Signal<i64>> {
330        self.env_ints.get(name).cloned()
331    }
332
333    pub(crate) fn get_env_float(&self, name: &str) -> Option<Signal<f64>> {
334        self.env_floats.get(name).cloned()
335    }
336
337    pub(crate) fn get_i18n(&self) -> Option<I18n> {
338        self.i18n.clone()
339    }
340
341    pub(crate) fn get_resource(&self, name: &str) -> Option<Resource<String>> {
342        self.resources.get(name).cloned()
343    }
344
345    pub(crate) fn get_rows(&self, name: &str) -> Option<RowsFn> {
346        self.rows.get(name).cloned()
347    }
348
349    pub(crate) fn action_sig(&self, name: &str) -> Option<ActionSig> {
350        if self.actions0.contains_key(name) {
351            Some(ActionSig::A0)
352        } else if self.actions_int.contains_key(name) {
353            Some(ActionSig::Int)
354        } else if self.actions_float.contains_key(name) {
355            Some(ActionSig::Float)
356        } else if self.actions_str.contains_key(name) {
357            Some(ActionSig::Str)
358        } else if self.actions_bool.contains_key(name) {
359            Some(ActionSig::Bool)
360        } else if self.actions_point.contains_key(name) {
361            Some(ActionSig::Point)
362        } else if self.actions_point_named.contains_key(name) {
363            Some(ActionSig::PointNamed)
364        } else if self.actions_wheel.contains_key(name) {
365            Some(ActionSig::Wheel)
366        } else if self.actions_pinch.contains_key(name) {
367            Some(ActionSig::Pinch)
368        } else {
369            None
370        }
371    }
372
373    pub(crate) fn get_action0(&self, name: &str) -> Option<Rc<dyn Fn()>> {
374        self.actions0.get(name).cloned()
375    }
376
377    pub(crate) fn get_action_int(&self, name: &str) -> Option<Rc<dyn Fn(i64)>> {
378        self.actions_int.get(name).cloned()
379    }
380
381    pub(crate) fn get_action_float(&self, name: &str) -> Option<Rc<dyn Fn(f64)>> {
382        self.actions_float.get(name).cloned()
383    }
384
385    pub(crate) fn get_action_str(&self, name: &str) -> Option<Rc<dyn Fn(String)>> {
386        self.actions_str.get(name).cloned()
387    }
388
389    pub(crate) fn get_action_bool(&self, name: &str) -> Option<Rc<dyn Fn(bool)>> {
390        self.actions_bool.get(name).cloned()
391    }
392
393    pub(crate) fn get_action_point(&self, name: &str) -> Option<Rc<dyn Fn(f64, f64)>> {
394        self.actions_point.get(name).cloned()
395    }
396
397    pub(crate) fn get_action_point_named(&self, name: &str) -> Option<PointNamedAction> {
398        self.actions_point_named.get(name).cloned()
399    }
400
401    pub(crate) fn get_action_wheel(&self, name: &str) -> Option<WheelAction> {
402        self.actions_wheel.get(name).cloned()
403    }
404
405    pub(crate) fn get_action_pinch(&self, name: &str) -> Option<PinchAction> {
406        self.actions_pinch.get(name).cloned()
407    }
408
409    pub fn on_wheel(
410        mut self,
411        name: impl Into<String>,
412        f: impl Fn(f64, f64, f64) + 'static,
413    ) -> Self {
414        self.actions_wheel.insert(name.into(), Rc::new(f));
415        self
416    }
417
418    pub fn on_pinch(
419        mut self,
420        name: impl Into<String>,
421        f: impl Fn(f64, f64, f64) + 'static,
422    ) -> Self {
423        self.actions_pinch.insert(name.into(), Rc::new(f));
424        self
425    }
426}