mirror of
https://github.com/slint-ui/slint.git
synced 2025-10-01 06:11:16 +00:00
parent
3ddc3c6ce5
commit
ce34ff87d0
12 changed files with 224 additions and 73 deletions
|
@ -19,6 +19,7 @@ All notable changes to this project will be documented in this file.
|
||||||
- `z` property on items
|
- `z` property on items
|
||||||
- Mouse wheel work on the Flickable and derivatives
|
- Mouse wheel work on the Flickable and derivatives
|
||||||
- One can now omit the type of a two way binding property
|
- One can now omit the type of a two way binding property
|
||||||
|
- One can declare callback aliases
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
|
|
|
@ -224,6 +224,8 @@ fn to_eval_value<'cx>(
|
||||||
Type::Enumeration(_) => todo!(),
|
Type::Enumeration(_) => todo!(),
|
||||||
Type::Invalid
|
Type::Invalid
|
||||||
| Type::Void
|
| Type::Void
|
||||||
|
| Type::InferredProperty
|
||||||
|
| Type::InferredCallback
|
||||||
| Type::Builtin(_)
|
| Type::Builtin(_)
|
||||||
| Type::Native(_)
|
| Type::Native(_)
|
||||||
| Type::Function { .. }
|
| Type::Function { .. }
|
||||||
|
|
|
@ -358,6 +358,16 @@ Example := Rectangle {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Callback aliases
|
||||||
|
|
||||||
|
It is possible to declare callback aliases in a similar way to two-way bindings:
|
||||||
|
|
||||||
|
```60
|
||||||
|
Example := Rectangle {
|
||||||
|
callback clicked <=> area.clicked;
|
||||||
|
area := TouchArea {}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
## Expressions
|
## Expressions
|
||||||
|
|
||||||
|
|
|
@ -659,6 +659,12 @@ fn generate_component(
|
||||||
let mut init = vec!["[[maybe_unused]] auto self = this;".into()];
|
let mut init = vec!["[[maybe_unused]] auto self = this;".into()];
|
||||||
|
|
||||||
for (cpp_name, property_decl) in component.root_element.borrow().property_declarations.iter() {
|
for (cpp_name, property_decl) in component.root_element.borrow().property_declarations.iter() {
|
||||||
|
let access = if let Some(alias) = &property_decl.is_alias {
|
||||||
|
access_named_reference(alias, component, "this")
|
||||||
|
} else {
|
||||||
|
format!("this->{}", cpp_name)
|
||||||
|
};
|
||||||
|
|
||||||
let ty = if let Type::Callback { args, return_type } = &property_decl.property_type {
|
let ty = if let Type::Callback { args, return_type } = &property_decl.property_type {
|
||||||
let param_types =
|
let param_types =
|
||||||
args.iter().map(|t| get_cpp_type(t, property_decl, diag)).collect::<Vec<_>>();
|
args.iter().map(|t| get_cpp_type(t, property_decl, diag)).collect::<Vec<_>>();
|
||||||
|
@ -668,7 +674,7 @@ fn generate_component(
|
||||||
if property_decl.expose_in_public_api && is_root {
|
if property_decl.expose_in_public_api && is_root {
|
||||||
let callback_emitter = vec![format!(
|
let callback_emitter = vec![format!(
|
||||||
"return {}.call({});",
|
"return {}.call({});",
|
||||||
cpp_name,
|
access,
|
||||||
(0..args.len()).map(|i| format!("arg_{}", i)).join(", ")
|
(0..args.len()).map(|i| format!("arg_{}", i)).join(", ")
|
||||||
)];
|
)];
|
||||||
component_struct.members.push((
|
component_struct.members.push((
|
||||||
|
@ -696,7 +702,7 @@ fn generate_component(
|
||||||
signature: "(Functor && callback_handler) const".into(),
|
signature: "(Functor && callback_handler) const".into(),
|
||||||
statements: Some(vec![format!(
|
statements: Some(vec![format!(
|
||||||
"{}.set_handler(std::forward<Functor>(callback_handler));",
|
"{}.set_handler(std::forward<Functor>(callback_handler));",
|
||||||
cpp_name
|
access
|
||||||
)]),
|
)]),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}),
|
}),
|
||||||
|
@ -707,12 +713,6 @@ fn generate_component(
|
||||||
let cpp_type = get_cpp_type(&property_decl.property_type, property_decl, diag);
|
let cpp_type = get_cpp_type(&property_decl.property_type, property_decl, diag);
|
||||||
|
|
||||||
if property_decl.expose_in_public_api && is_root {
|
if property_decl.expose_in_public_api && is_root {
|
||||||
let access = if let Some(alias) = &property_decl.is_alias {
|
|
||||||
access_named_reference(alias, component, "this")
|
|
||||||
} else {
|
|
||||||
format!("this->{}", cpp_name)
|
|
||||||
};
|
|
||||||
|
|
||||||
let prop_getter: Vec<String> = vec![format!("return {}.get();", access)];
|
let prop_getter: Vec<String> = vec![format!("return {}.get();", access)];
|
||||||
component_struct.members.push((
|
component_struct.members.push((
|
||||||
Access::Public,
|
Access::Public,
|
||||||
|
|
|
@ -280,8 +280,13 @@ fn generate_component(
|
||||||
let mut property_and_callback_accessors: Vec<TokenStream> = vec![];
|
let mut property_and_callback_accessors: Vec<TokenStream> = vec![];
|
||||||
for (prop_name, property_decl) in component.root_element.borrow().property_declarations.iter() {
|
for (prop_name, property_decl) in component.root_element.borrow().property_declarations.iter() {
|
||||||
let prop_ident = format_ident!("{}", prop_name);
|
let prop_ident = format_ident!("{}", prop_name);
|
||||||
|
let prop = if let Some(alias) = &property_decl.is_alias {
|
||||||
|
access_named_reference(alias, component, quote!(_self))
|
||||||
|
} else {
|
||||||
|
quote!(#inner_component_id::FIELD_OFFSETS.#prop_ident.apply_pin(_self))
|
||||||
|
};
|
||||||
|
|
||||||
if let Type::Callback { args, return_type } = &property_decl.property_type {
|
if let Type::Callback { args, return_type } = &property_decl.property_type {
|
||||||
declared_callbacks.push(prop_ident.clone());
|
|
||||||
let callback_args = args
|
let callback_args = args
|
||||||
.iter()
|
.iter()
|
||||||
.map(|a| get_rust_type(a, &property_decl.type_node(), diag))
|
.map(|a| get_rust_type(a, &property_decl.type_node(), diag))
|
||||||
|
@ -295,16 +300,13 @@ fn generate_component(
|
||||||
.map(|i| format_ident!("arg_{}", i))
|
.map(|i| format_ident!("arg_{}", i))
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
let caller_ident = format_ident!("invoke_{}", prop_name);
|
let caller_ident = format_ident!("invoke_{}", prop_name);
|
||||||
property_and_callback_accessors.push(
|
property_and_callback_accessors.push(quote!(
|
||||||
quote!(
|
#[allow(dead_code)]
|
||||||
#[allow(dead_code)]
|
pub fn #caller_ident(&self, #(#args_name : #callback_args,)*) -> #return_type {
|
||||||
pub fn #caller_ident(&self, #(#args_name : #callback_args,)*) -> #return_type {
|
let _self = vtable::VRc::as_pin_ref(&self.0);
|
||||||
let _self = vtable::VRc::as_pin_ref(&self.0);
|
#prop.call(&(#(#args_name,)*))
|
||||||
#inner_component_id::FIELD_OFFSETS.#prop_ident.apply_pin(_self).call(&(#(#args_name,)*))
|
}
|
||||||
}
|
));
|
||||||
)
|
|
||||||
,
|
|
||||||
);
|
|
||||||
|
|
||||||
let on_ident = format_ident!("on_{}", prop_name);
|
let on_ident = format_ident!("on_{}", prop_name);
|
||||||
let args_index =
|
let args_index =
|
||||||
|
@ -315,7 +317,7 @@ fn generate_component(
|
||||||
pub fn #on_ident(&self, f: impl Fn(#(#callback_args),*) -> #return_type + 'static) {
|
pub fn #on_ident(&self, f: impl Fn(#(#callback_args),*) -> #return_type + 'static) {
|
||||||
let _self = vtable::VRc::as_pin_ref(&self.0);
|
let _self = vtable::VRc::as_pin_ref(&self.0);
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
#inner_component_id::FIELD_OFFSETS.#prop_ident.apply_pin(_self).set_handler(
|
#prop.set_handler(
|
||||||
// FIXME: why do i need to clone here?
|
// FIXME: why do i need to clone here?
|
||||||
move |args| f(#(args.#args_index.clone()),*)
|
move |args| f(#(args.#args_index.clone()),*)
|
||||||
)
|
)
|
||||||
|
@ -324,8 +326,11 @@ fn generate_component(
|
||||||
,
|
,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
declared_callbacks_types.push(callback_args);
|
if property_decl.is_alias.is_none() {
|
||||||
declared_callbacks_ret.push(return_type);
|
declared_callbacks.push(prop_ident.clone());
|
||||||
|
declared_callbacks_types.push(callback_args);
|
||||||
|
declared_callbacks_ret.push(return_type);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
let rust_property_type =
|
let rust_property_type =
|
||||||
get_rust_type(&property_decl.property_type, &property_decl.type_node(), diag);
|
get_rust_type(&property_decl.property_type, &property_decl.type_node(), diag);
|
||||||
|
@ -333,12 +338,6 @@ fn generate_component(
|
||||||
let getter_ident = format_ident!("get_{}", prop_name);
|
let getter_ident = format_ident!("get_{}", prop_name);
|
||||||
let setter_ident = format_ident!("set_{}", prop_name);
|
let setter_ident = format_ident!("set_{}", prop_name);
|
||||||
|
|
||||||
let prop = if let Some(alias) = &property_decl.is_alias {
|
|
||||||
access_named_reference(alias, component, quote!(_self))
|
|
||||||
} else {
|
|
||||||
quote!(#inner_component_id::FIELD_OFFSETS.#prop_ident.apply_pin(_self))
|
|
||||||
};
|
|
||||||
|
|
||||||
property_and_callback_accessors.push(quote!(
|
property_and_callback_accessors.push(quote!(
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub fn #getter_ident(&self) -> #rust_property_type {
|
pub fn #getter_ident(&self) -> #rust_property_type {
|
||||||
|
|
|
@ -638,7 +638,7 @@ impl Element {
|
||||||
let unresolved_name = unwrap_or_continue!(identifier_text(&con_node); diag);
|
let unresolved_name = unwrap_or_continue!(identifier_text(&con_node); diag);
|
||||||
let PropertyLookupResult { resolved_name, property_type } =
|
let PropertyLookupResult { resolved_name, property_type } =
|
||||||
r.lookup_property(&unresolved_name);
|
r.lookup_property(&unresolved_name);
|
||||||
if let Type::Callback { args, .. } = property_type {
|
if let Type::Callback { args, .. } = &property_type {
|
||||||
let num_arg = con_node.DeclaredIdentifier().count();
|
let num_arg = con_node.DeclaredIdentifier().count();
|
||||||
if num_arg > args.len() {
|
if num_arg > args.len() {
|
||||||
diag.push_error(
|
diag.push_error(
|
||||||
|
@ -651,23 +651,26 @@ impl Element {
|
||||||
&con_node.child_token(SyntaxKind::Identifier).unwrap(),
|
&con_node.child_token(SyntaxKind::Identifier).unwrap(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if r.bindings
|
} else if property_type == Type::InferredCallback {
|
||||||
.insert(
|
// argument matching will happen later
|
||||||
resolved_name.into_owned(),
|
|
||||||
BindingExpression::new_uncompiled(con_node.clone().into()),
|
|
||||||
)
|
|
||||||
.is_some()
|
|
||||||
{
|
|
||||||
diag.push_error(
|
|
||||||
"Duplicated callback".into(),
|
|
||||||
&con_node.child_token(SyntaxKind::Identifier).unwrap(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
diag.push_error(
|
diag.push_error(
|
||||||
format!("'{}' is not a callback in {}", unresolved_name, r.base_type),
|
format!("'{}' is not a callback in {}", unresolved_name, r.base_type),
|
||||||
&con_node.child_token(SyntaxKind::Identifier).unwrap(),
|
&con_node.child_token(SyntaxKind::Identifier).unwrap(),
|
||||||
);
|
);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if r.bindings
|
||||||
|
.insert(
|
||||||
|
resolved_name.into_owned(),
|
||||||
|
BindingExpression::new_uncompiled(con_node.clone().into()),
|
||||||
|
)
|
||||||
|
.is_some()
|
||||||
|
{
|
||||||
|
diag.push_error(
|
||||||
|
"Duplicated callback".into(),
|
||||||
|
&con_node.child_token(SyntaxKind::Identifier).unwrap(),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -326,7 +326,6 @@ fn parse_callback_declaration(p: &mut impl Parser) {
|
||||||
|
|
||||||
if p.test(SyntaxKind::DoubleArrow) {
|
if p.test(SyntaxKind::DoubleArrow) {
|
||||||
let mut p = p.start_node(SyntaxKind::TwoWayBinding);
|
let mut p = p.start_node(SyntaxKind::TwoWayBinding);
|
||||||
p.consume();
|
|
||||||
parse_expression(&mut *p);
|
parse_expression(&mut *p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -241,7 +241,7 @@ impl Expression {
|
||||||
Expression::TwoWayBinding(n, None)
|
Expression::TwoWayBinding(n, None)
|
||||||
}
|
}
|
||||||
Expression::CallbackReference(n) => {
|
Expression::CallbackReference(n) => {
|
||||||
if ctx.property_type != Type::InferredCallback {
|
if ctx.property_type != Type::InferredCallback && ty != ctx.property_type {
|
||||||
ctx.diag.push_error("Cannot bind to a callback".into(), &node);
|
ctx.diag.push_error("Cannot bind to a callback".into(), &node);
|
||||||
Expression::Invalid
|
Expression::Invalid
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -8,6 +8,11 @@
|
||||||
Please contact info@sixtyfps.io for more information.
|
Please contact info@sixtyfps.io for more information.
|
||||||
LICENSE END */
|
LICENSE END */
|
||||||
|
|
||||||
|
Sub := Rectangle {
|
||||||
|
callback compute(int) -> int;
|
||||||
|
callback compute_alias <=> compute;
|
||||||
|
}
|
||||||
|
|
||||||
Xxx := Rectangle {
|
Xxx := Rectangle {
|
||||||
|
|
||||||
foo := Rectangle {
|
foo := Rectangle {
|
||||||
|
@ -26,4 +31,12 @@ Xxx := Rectangle {
|
||||||
// ^^error{The expression in a two way binding must be a property reference}
|
// ^^error{The expression in a two way binding must be a property reference}
|
||||||
callback loop2 <=> loop3;
|
callback loop2 <=> loop3;
|
||||||
|
|
||||||
|
Sub {
|
||||||
|
compute_alias(a, b, c) => {
|
||||||
|
debug(b); // FIXME: one should actually check that the connection has the right amount of arguments
|
||||||
|
// ^error{Unknown unqualified identifier 'b'}
|
||||||
|
return "hello";
|
||||||
|
// ^error{Cannot convert string to int}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -439,9 +439,38 @@ impl<'id> ComponentDescription<'id> {
|
||||||
if !core::ptr::eq((&self.ct) as *const _, component.get_vtable() as *const _) {
|
if !core::ptr::eq((&self.ct) as *const _, component.get_vtable() as *const _) {
|
||||||
return Err(());
|
return Err(());
|
||||||
}
|
}
|
||||||
let x = self.custom_callbacks.get(name).ok_or(())?;
|
if let Some(alias) = self
|
||||||
let sig = x.apply(unsafe { &*(component.as_ptr() as *const dynamic_type::Instance) });
|
.original
|
||||||
sig.set_handler(handler);
|
.root_element
|
||||||
|
.borrow()
|
||||||
|
.property_declarations
|
||||||
|
.get(name)
|
||||||
|
.and_then(|d| d.is_alias.as_ref())
|
||||||
|
{
|
||||||
|
generativity::make_guard!(guard);
|
||||||
|
// Safety: we just verified that the component has the right vtable
|
||||||
|
let c = unsafe { InstanceRef::from_pin_ref(component, guard) };
|
||||||
|
generativity::make_guard!(guard);
|
||||||
|
let element = alias.element();
|
||||||
|
let enclosing_component = eval::enclosing_component_for_element(&element, c, guard);
|
||||||
|
let component_type = enclosing_component.component_type;
|
||||||
|
let item_info = &component_type.items[element.borrow().id.as_str()];
|
||||||
|
let item = unsafe { item_info.item_from_component(enclosing_component.as_ptr()) };
|
||||||
|
|
||||||
|
if let Some(callback) = item_info.rtti.callbacks.get(alias.name()) {
|
||||||
|
callback.set_handler(item, handler)
|
||||||
|
} else if let Some(callback_offset) = component_type.custom_callbacks.get(alias.name())
|
||||||
|
{
|
||||||
|
let callback = callback_offset.apply(&*enclosing_component.instance);
|
||||||
|
callback.set_handler(handler)
|
||||||
|
} else {
|
||||||
|
return Err(());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let x = self.custom_callbacks.get(name).ok_or(())?;
|
||||||
|
let sig = x.apply(unsafe { &*(component.as_ptr() as *const dynamic_type::Instance) });
|
||||||
|
sig.set_handler(handler);
|
||||||
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -458,9 +487,31 @@ impl<'id> ComponentDescription<'id> {
|
||||||
if !core::ptr::eq((&self.ct) as *const _, component.get_vtable() as *const _) {
|
if !core::ptr::eq((&self.ct) as *const _, component.get_vtable() as *const _) {
|
||||||
return Err(());
|
return Err(());
|
||||||
}
|
}
|
||||||
let x = self.custom_callbacks.get(name).ok_or(())?;
|
generativity::make_guard!(guard);
|
||||||
let sig = x.apply(unsafe { &*(component.as_ptr() as *const dynamic_type::Instance) });
|
// Safety: we just verified that the component has the right vtable
|
||||||
Ok(sig.call(args))
|
let c = unsafe { InstanceRef::from_pin_ref(component, guard) };
|
||||||
|
if let Some(alias) = self
|
||||||
|
.original
|
||||||
|
.root_element
|
||||||
|
.borrow()
|
||||||
|
.property_declarations
|
||||||
|
.get(name)
|
||||||
|
.and_then(|d| d.is_alias.as_ref())
|
||||||
|
{
|
||||||
|
Ok(eval::invoke_callback(
|
||||||
|
eval::ComponentInstance::InstanceRef(c),
|
||||||
|
&alias.element(),
|
||||||
|
alias.name(),
|
||||||
|
args,
|
||||||
|
))
|
||||||
|
} else {
|
||||||
|
Ok(eval::invoke_callback(
|
||||||
|
eval::ComponentInstance::InstanceRef(c),
|
||||||
|
&self.original.root_element,
|
||||||
|
name,
|
||||||
|
args,
|
||||||
|
))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -193,30 +193,8 @@ pub fn eval_expression(e: &Expression, local_context: &mut EvalLocalContext) ->
|
||||||
}
|
}
|
||||||
Expression::FunctionCall { function, arguments, source_location: _ } => match &**function {
|
Expression::FunctionCall { function, arguments, source_location: _ } => match &**function {
|
||||||
Expression::CallbackReference(nr) => {
|
Expression::CallbackReference(nr) => {
|
||||||
let element = nr.element();
|
let args = arguments.iter().map(|e| eval_expression(e, local_context)).collect::<Vec<_>>();
|
||||||
generativity::make_guard!(guard);
|
invoke_callback(local_context.component_instance, &nr.element(), nr.name(), &args)
|
||||||
match enclosing_component_instance_for_element(&element, local_context.component_instance, guard) {
|
|
||||||
ComponentInstance::InstanceRef(enclosing_component) => {
|
|
||||||
let component_type = enclosing_component.component_type;
|
|
||||||
let item_info = &component_type.items[element.borrow().id.as_str()];
|
|
||||||
let item = unsafe { item_info.item_from_component(enclosing_component.as_ptr()) };
|
|
||||||
let args = arguments.iter().map(|e| eval_expression(e, local_context)).collect::<Vec<_>>();
|
|
||||||
|
|
||||||
if let Some(callback) = item_info.rtti.callbacks.get(nr.name()) {
|
|
||||||
callback.call(item, args.as_slice())
|
|
||||||
} else if let Some(callback_offset) = component_type.custom_callbacks.get(nr.name())
|
|
||||||
{
|
|
||||||
let callback = callback_offset.apply(&*enclosing_component.instance);
|
|
||||||
callback.call(args.as_slice())
|
|
||||||
} else {
|
|
||||||
panic!("unkown callback {}", nr.name())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ComponentInstance::GlobalComponent(global) => {
|
|
||||||
let args = arguments.iter().map(|e| eval_expression(e, local_context));
|
|
||||||
global.as_ref().invoke_callback(nr.name(), args.collect::<Vec<_>>().as_slice())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Expression::BuiltinFunctionReference(BuiltinFunction::GetWindowScaleFactor, _) => {
|
Expression::BuiltinFunctionReference(BuiltinFunction::GetWindowScaleFactor, _) => {
|
||||||
match local_context.component_instance {
|
match local_context.component_instance {
|
||||||
|
@ -720,6 +698,35 @@ pub fn store_property(
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn invoke_callback(
|
||||||
|
component_instance: ComponentInstance,
|
||||||
|
element: &ElementRc,
|
||||||
|
callback_name: &str,
|
||||||
|
args: &[Value],
|
||||||
|
) -> Value {
|
||||||
|
generativity::make_guard!(guard);
|
||||||
|
match enclosing_component_instance_for_element(element, component_instance, guard) {
|
||||||
|
ComponentInstance::InstanceRef(enclosing_component) => {
|
||||||
|
let component_type = enclosing_component.component_type;
|
||||||
|
let item_info = &component_type.items[element.borrow().id.as_str()];
|
||||||
|
let item = unsafe { item_info.item_from_component(enclosing_component.as_ptr()) };
|
||||||
|
|
||||||
|
if let Some(callback) = item_info.rtti.callbacks.get(callback_name) {
|
||||||
|
callback.call(item, args)
|
||||||
|
} else if let Some(callback_offset) = component_type.custom_callbacks.get(callback_name)
|
||||||
|
{
|
||||||
|
let callback = callback_offset.apply(&*enclosing_component.instance);
|
||||||
|
callback.call(args)
|
||||||
|
} else {
|
||||||
|
panic!("unkown callback {}", callback_name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ComponentInstance::GlobalComponent(global) => {
|
||||||
|
global.as_ref().invoke_callback(callback_name, args)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn root_component_instance<'a, 'old_id, 'new_id>(
|
fn root_component_instance<'a, 'old_id, 'new_id>(
|
||||||
component: InstanceRef<'a, 'old_id>,
|
component: InstanceRef<'a, 'old_id>,
|
||||||
guard: generativity::Guard<'new_id>,
|
guard: generativity::Guard<'new_id>,
|
||||||
|
|
66
tests/cases/callbacks/callback_alias.60
Normal file
66
tests/cases/callbacks/callback_alias.60
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
/* LICENSE BEGIN
|
||||||
|
This file is part of the SixtyFPS Project -- https://sixtyfps.io
|
||||||
|
Copyright (c) 2020 Olivier Goffart <olivier.goffart@sixtyfps.io>
|
||||||
|
Copyright (c) 2020 Simon Hausmann <simon.hausmann@sixtyfps.io>
|
||||||
|
|
||||||
|
SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
This file is also available under commercial licensing terms.
|
||||||
|
Please contact info@sixtyfps.io for more information.
|
||||||
|
LICENSE END */
|
||||||
|
|
||||||
|
Foo := Rectangle {
|
||||||
|
callback hallo_alias <=> xxx.hallo;
|
||||||
|
callback clicked <=> are.clicked;
|
||||||
|
xxx := Rectangle {
|
||||||
|
callback hallo(int) -> int;
|
||||||
|
hallo(a) => { return a + 88; }
|
||||||
|
}
|
||||||
|
|
||||||
|
are := TouchArea { }
|
||||||
|
}
|
||||||
|
|
||||||
|
TestCase := Rectangle {
|
||||||
|
|
||||||
|
callback foo1_alias <=> foo1.hallo_alias;
|
||||||
|
callback foo2_alias <=> foo2.hallo_alias;
|
||||||
|
|
||||||
|
callback foo1_clicked <=> foo1.clicked;
|
||||||
|
|
||||||
|
callback call_foo2(int) -> int;
|
||||||
|
call_foo2(a) => { return foo2.hallo_alias(a); }
|
||||||
|
|
||||||
|
foo1 := Foo {
|
||||||
|
hallo_alias(a) => { return a + 22; }
|
||||||
|
}
|
||||||
|
|
||||||
|
foo2 := Foo {
|
||||||
|
clicked => { debug(42) }
|
||||||
|
}
|
||||||
|
|
||||||
|
property <bool> test: foo1_alias(100) == 122 && foo2_alias(100) == 188;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
```rust
|
||||||
|
let instance = TestCase::new();
|
||||||
|
assert_eq!(instance.invoke_foo1_alias(100), 122);
|
||||||
|
assert_eq!(instance.invoke_foo2_alias(100), 188);
|
||||||
|
assert_eq!(instance.invoke_call_foo2(100), 188);
|
||||||
|
```
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
auto handle = TestCase::create();
|
||||||
|
const TestCase &instance = *handle;
|
||||||
|
assert_eq(instance.invoke_foo1_alias(100), 122);
|
||||||
|
assert_eq(instance.invoke_foo2_alias(100), 188);
|
||||||
|
assert_eq(instance.invoke_call_foo2(100), 188);
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
```js
|
||||||
|
var instance = new sixtyfps.TestCase();
|
||||||
|
assert.equal(instance.foo1_alias(100), 122);
|
||||||
|
assert.equal(instance.foo2_alias(100), 188);
|
||||||
|
assert.equal(instance.call_foo2(100), 188);
|
||||||
|
```
|
||||||
|
*/
|
Loading…
Add table
Add a link
Reference in a new issue