mirror of
https://github.com/slint-ui/slint.git
synced 2025-10-02 14:51:15 +00:00
Node: Add setHandler features on signals
This commit is contained in:
parent
c50b9d73d3
commit
ac6d4007ab
4 changed files with 73 additions and 23 deletions
|
@ -70,11 +70,12 @@ console.log(component.counter);
|
|||
|
||||
### Signals
|
||||
|
||||
The signals are also exposed as property that can be called
|
||||
The signals are also exposed as property that have a setHandler function, and that can can be called.
|
||||
|
||||
|
||||
```js
|
||||
// connect to a signal
|
||||
component.clicked = function() { console.log("hello"); }
|
||||
component.clicked.setHandler(function() { console.log("hello"); })
|
||||
// emit a signal
|
||||
component.clicked();
|
||||
```
|
||||
|
|
|
@ -49,6 +49,14 @@ class Component {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @hidden
|
||||
*/
|
||||
interface Signal {
|
||||
(): any;
|
||||
setHandler(cb: any): void;
|
||||
}
|
||||
|
||||
require.extensions['.60'] =
|
||||
function (module, filename) {
|
||||
var c = native.load(filename);
|
||||
|
@ -64,7 +72,11 @@ require.extensions['.60'] =
|
|||
});
|
||||
c.signals().forEach((x: string) => {
|
||||
Object.defineProperty(ret, x, {
|
||||
get() { return function () { comp.emit_signal(x, [...arguments]); } },
|
||||
get() {
|
||||
let signal = function () { comp.emit_signal(x, [...arguments]); } as Signal;
|
||||
signal.setHandler = function (callback) { comp.connect_signal(x, callback) };
|
||||
return signal;
|
||||
},
|
||||
enumerable: true,
|
||||
})
|
||||
});
|
||||
|
|
|
@ -83,6 +83,28 @@ fn load(mut cx: FunctionContext) -> JsResult<JsValue> {
|
|||
Ok(obj.as_value(&mut cx))
|
||||
}
|
||||
|
||||
fn make_signal_handler<'cx>(
|
||||
cx: &mut impl Context<'cx>,
|
||||
persistent_context: &persistent_context::PersistentContext<'cx>,
|
||||
fun: Handle<'cx, JsFunction>,
|
||||
) -> Box<dyn Fn(&[sixtyfps_interpreter::Value])> {
|
||||
let fun_value = fun.as_value(cx);
|
||||
let fun_idx = persistent_context.allocate(cx, fun_value);
|
||||
Box::new(move |args| {
|
||||
let args = args.iter().cloned().collect::<Vec<_>>();
|
||||
run_with_global_contect(&move |cx, persistent_context| {
|
||||
let args = args.iter().map(|a| to_js_value(a.clone(), cx).unwrap()).collect::<Vec<_>>();
|
||||
persistent_context
|
||||
.get(cx, fun_idx)
|
||||
.unwrap()
|
||||
.downcast::<JsFunction>()
|
||||
.unwrap()
|
||||
.call::<_, _, JsValue, _>(cx, JsUndefined::new(), args)
|
||||
.unwrap();
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
fn create<'cx>(
|
||||
cx: &mut CallContext<'cx, impl neon::object::This>,
|
||||
component_type: Rc<sixtyfps_interpreter::ComponentDescription>,
|
||||
|
@ -103,28 +125,12 @@ fn create<'cx>(
|
|||
})?
|
||||
.clone();
|
||||
if let Type::Signal { .. } = ty {
|
||||
let _fun = value.downcast_or_throw::<JsFunction, _>(cx)?;
|
||||
let fun_idx = persistent_context.allocate(cx, value);
|
||||
let fun = value.downcast_or_throw::<JsFunction, _>(cx)?;
|
||||
component_type
|
||||
.set_signal_handler(
|
||||
component.borrow(),
|
||||
prop_name.as_str(),
|
||||
Box::new(move |args| {
|
||||
let args = args.iter().cloned().collect::<Vec<_>>();
|
||||
run_with_global_contect(&move |cx, persistent_context| {
|
||||
let args = args
|
||||
.iter()
|
||||
.map(|a| to_js_value(a.clone(), cx).unwrap())
|
||||
.collect::<Vec<_>>();
|
||||
persistent_context
|
||||
.get(cx, fun_idx)
|
||||
.unwrap()
|
||||
.downcast::<JsFunction>()
|
||||
.unwrap()
|
||||
.call::<_, _, JsValue, _>(cx, JsUndefined::new(), args)
|
||||
.unwrap();
|
||||
})
|
||||
}),
|
||||
make_signal_handler(cx, &persistent_context, fun),
|
||||
)
|
||||
.or_else(|_| cx.throw_error(format!("Cannot set signal")))?;
|
||||
} else {
|
||||
|
@ -412,6 +418,23 @@ declare_types! {
|
|||
Ok(JsUndefined::new().as_value(&mut cx))
|
||||
}
|
||||
|
||||
method connect_signal(mut cx) {
|
||||
let signal_name = cx.argument::<JsString>(0)?.value();
|
||||
let handler = cx.argument::<JsFunction>(1)?;
|
||||
let this = cx.this();
|
||||
let persistent_context =
|
||||
persistent_context::PersistentContext::from_object(&mut cx, this.downcast().unwrap())?;
|
||||
let lock = cx.lock();
|
||||
let x = this.borrow(&lock).0.clone();
|
||||
let component = x.ok_or(()).or_else(|()| cx.throw_error("Invalid type"))?;
|
||||
component.description().set_signal_handler(
|
||||
component.borrow(),
|
||||
signal_name.as_str(),
|
||||
make_signal_handler(&mut cx, &persistent_context, handler)
|
||||
).or_else(|_| cx.throw_error(format!("Cannot set signal")))?;
|
||||
Ok(JsUndefined::new().as_value(&mut cx))
|
||||
}
|
||||
|
||||
method send_mouse_click(mut cx) {
|
||||
let x = cx.argument::<JsNumber>(0)?.value() as f32;
|
||||
let y = cx.argument::<JsNumber>(1)?.value() as f32;
|
||||
|
|
|
@ -88,7 +88,21 @@ try {
|
|||
assert.equal(e.toString(), "Error: test_signal expect 1 arguments, but 0 where provided");
|
||||
}
|
||||
assert.equal(instance.signal_emission_count, 0);
|
||||
|
||||
|
||||
/// also test setHandler
|
||||
instance.test_signal2.setHandler(function(a) {
|
||||
signal_3_emited += 100;
|
||||
signal_3_string_value = a;
|
||||
});
|
||||
instance.test_signal2("salùt")
|
||||
assert.equal(signal_3_emited, 101);
|
||||
assert.equal(signal_3_string_value, "salùt");
|
||||
assert.equal(signal_3_int_value, 55); // same as before
|
||||
|
||||
```
|
||||
|
||||
|
||||
|
||||
*/
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue