mirror of
https://github.com/slint-ui/slint.git
synced 2025-10-01 22:31:14 +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
|
### 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
|
```js
|
||||||
// connect to a signal
|
// connect to a signal
|
||||||
component.clicked = function() { console.log("hello"); }
|
component.clicked.setHandler(function() { console.log("hello"); })
|
||||||
// emit a signal
|
// emit a signal
|
||||||
component.clicked();
|
component.clicked();
|
||||||
```
|
```
|
||||||
|
|
|
@ -49,6 +49,14 @@ class Component {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @hidden
|
||||||
|
*/
|
||||||
|
interface Signal {
|
||||||
|
(): any;
|
||||||
|
setHandler(cb: any): void;
|
||||||
|
}
|
||||||
|
|
||||||
require.extensions['.60'] =
|
require.extensions['.60'] =
|
||||||
function (module, filename) {
|
function (module, filename) {
|
||||||
var c = native.load(filename);
|
var c = native.load(filename);
|
||||||
|
@ -64,7 +72,11 @@ require.extensions['.60'] =
|
||||||
});
|
});
|
||||||
c.signals().forEach((x: string) => {
|
c.signals().forEach((x: string) => {
|
||||||
Object.defineProperty(ret, x, {
|
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,
|
enumerable: true,
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
@ -187,8 +199,8 @@ class ArrayModel<T> implements Model<T> {
|
||||||
* the model, starting at the specified index. This is equivalent to calling
|
* the model, starting at the specified index. This is equivalent to calling
|
||||||
* Array.slice() on the array and notifying the run-time about the removed
|
* Array.slice() on the array and notifying the run-time about the removed
|
||||||
* rows.
|
* rows.
|
||||||
* @param index
|
* @param index
|
||||||
* @param size
|
* @param size
|
||||||
*/
|
*/
|
||||||
remove(index: number, size: number) {
|
remove(index: number, size: number) {
|
||||||
let r = this.a.splice(index, size);
|
let r = this.a.splice(index, size);
|
||||||
|
|
|
@ -83,6 +83,28 @@ fn load(mut cx: FunctionContext) -> JsResult<JsValue> {
|
||||||
Ok(obj.as_value(&mut cx))
|
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>(
|
fn create<'cx>(
|
||||||
cx: &mut CallContext<'cx, impl neon::object::This>,
|
cx: &mut CallContext<'cx, impl neon::object::This>,
|
||||||
component_type: Rc<sixtyfps_interpreter::ComponentDescription>,
|
component_type: Rc<sixtyfps_interpreter::ComponentDescription>,
|
||||||
|
@ -103,28 +125,12 @@ fn create<'cx>(
|
||||||
})?
|
})?
|
||||||
.clone();
|
.clone();
|
||||||
if let Type::Signal { .. } = ty {
|
if let Type::Signal { .. } = ty {
|
||||||
let _fun = value.downcast_or_throw::<JsFunction, _>(cx)?;
|
let fun = value.downcast_or_throw::<JsFunction, _>(cx)?;
|
||||||
let fun_idx = persistent_context.allocate(cx, value);
|
|
||||||
component_type
|
component_type
|
||||||
.set_signal_handler(
|
.set_signal_handler(
|
||||||
component.borrow(),
|
component.borrow(),
|
||||||
prop_name.as_str(),
|
prop_name.as_str(),
|
||||||
Box::new(move |args| {
|
make_signal_handler(cx, &persistent_context, fun),
|
||||||
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();
|
|
||||||
})
|
|
||||||
}),
|
|
||||||
)
|
)
|
||||||
.or_else(|_| cx.throw_error(format!("Cannot set signal")))?;
|
.or_else(|_| cx.throw_error(format!("Cannot set signal")))?;
|
||||||
} else {
|
} else {
|
||||||
|
@ -412,6 +418,23 @@ declare_types! {
|
||||||
Ok(JsUndefined::new().as_value(&mut cx))
|
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) {
|
method send_mouse_click(mut cx) {
|
||||||
let x = cx.argument::<JsNumber>(0)?.value() as f32;
|
let x = cx.argument::<JsNumber>(0)?.value() as f32;
|
||||||
let y = cx.argument::<JsNumber>(1)?.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(e.toString(), "Error: test_signal expect 1 arguments, but 0 where provided");
|
||||||
}
|
}
|
||||||
assert.equal(instance.signal_emission_count, 0);
|
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