mirror of
https://github.com/slint-ui/slint.git
synced 2025-09-30 05:44:52 +00:00
Some refactoring of the rust generated code
Always use a Pin<Rc> for the component. (This is required to support repeater within repeater as well anyway) Do not use the context within the binding. We can get along by simply capturing a weak pointer to the component
This commit is contained in:
parent
1a0d053889
commit
ab7ae9f3e2
15 changed files with 74 additions and 73 deletions
|
@ -20,7 +20,7 @@ sixtyfps::sixtyfps!{
|
|||
}
|
||||
fn main() {
|
||||
# return; // Don't run a window in an example
|
||||
HelloWorld::default().run()
|
||||
HelloWorld::new().run()
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -56,7 +56,7 @@ Then in your main file
|
|||
```ignore
|
||||
sixtyfps::include_modules!();
|
||||
fn main() {
|
||||
HelloWorld::default().run()
|
||||
HelloWorld::new().run()
|
||||
}
|
||||
```
|
||||
*/
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
use core::cell::RefCell;
|
||||
use core::pin::Pin;
|
||||
use std::rc::Rc;
|
||||
|
||||
/// Component that can be instantiated by a repeater.
|
||||
pub trait RepeatedComponent: sixtyfps_corelib::abi::datastructures::Component {
|
||||
|
@ -11,9 +13,14 @@ pub trait RepeatedComponent: sixtyfps_corelib::abi::datastructures::Component {
|
|||
|
||||
/// This field is put in a component when using the `for` syntax
|
||||
/// It helps instantiating the components `C`
|
||||
#[derive(Default)]
|
||||
pub struct Repeater<C> {
|
||||
components: RefCell<Vec<core::pin::Pin<Box<C>>>>,
|
||||
components: RefCell<Vec<Pin<Rc<C>>>>,
|
||||
}
|
||||
|
||||
impl<C> Default for Repeater<C> {
|
||||
fn default() -> Self {
|
||||
Repeater { components: Default::default() }
|
||||
}
|
||||
}
|
||||
|
||||
impl<Data, C> Repeater<C>
|
||||
|
@ -21,7 +28,7 @@ where
|
|||
C: RepeatedComponent<Data = Data>,
|
||||
{
|
||||
/// Called when the model is changed
|
||||
pub fn update_model<'a>(&self, data: impl Iterator<Item = Data>, init: impl Fn() -> C)
|
||||
pub fn update_model<'a>(&self, data: impl Iterator<Item = Data>, init: impl Fn() -> Pin<Rc<C>>)
|
||||
where
|
||||
Data: 'a,
|
||||
{
|
||||
|
@ -29,7 +36,7 @@ where
|
|||
for (i, d) in data.enumerate() {
|
||||
let c = init();
|
||||
c.update(i, d);
|
||||
self.components.borrow_mut().push(Box::pin(c));
|
||||
self.components.borrow_mut().push(c);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -127,7 +127,7 @@ Hello := Rectangle {
|
|||
}
|
||||
|
||||
fn main() {
|
||||
let mut app = Hello::default();
|
||||
let app = Hello::new();
|
||||
app.plus_clicked.set_handler(|context, ()| {
|
||||
let app = context.get_component::<Hello>().unwrap();
|
||||
let counter = Hello::field_offsets().counter.apply_pin(app);
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
sixtyfps::include_modules!();
|
||||
|
||||
fn main() {
|
||||
let mut app = Hello::default();
|
||||
let app = Hello::new();
|
||||
|
||||
app.plus_clicked.set_handler(|context, ()| {
|
||||
let app = context.get_component::<Hello>().unwrap();
|
||||
|
|
|
@ -10,5 +10,5 @@ pub fn wasm_main() {
|
|||
#[cfg(debug_assertions)]
|
||||
console_error_panic_hook::set_once();
|
||||
|
||||
Hello::default().run();
|
||||
Hello::new().run();
|
||||
}
|
||||
|
|
|
@ -115,7 +115,6 @@ pub fn generate(component: &Rc<Component>, diag: &mut Diagnostics) -> Option<Tok
|
|||
let mut repeated_dynmodel_names = Vec::new();
|
||||
let mut repeated_visit_branch = Vec::new();
|
||||
let mut init = Vec::new();
|
||||
let mut init_repeaters = Vec::new();
|
||||
super::build_array_helper(component, |item_rc, children_index| {
|
||||
let item = item_rc.borrow();
|
||||
if let Some(repeated) = &item.repeated {
|
||||
|
@ -166,11 +165,9 @@ pub fn generate(component: &Rc<Component>, diag: &mut Diagnostics) -> Option<Tok
|
|||
}
|
||||
|
||||
if repeated.model.is_constant() {
|
||||
init_repeaters.push(quote! {
|
||||
init.push(quote! {
|
||||
self_pinned.#repeater_id.update_model(#model, || {
|
||||
let mut new_comp = #rep_component_id::default();
|
||||
new_comp.parent = self_pinned.self_weak.get().unwrap().clone();
|
||||
new_comp
|
||||
#rep_component_id::new(self_pinned.self_weak.get().unwrap().clone())
|
||||
});
|
||||
});
|
||||
repeated_visit_branch.push(quote!(
|
||||
|
@ -189,9 +186,7 @@ pub fn generate(component: &Rc<Component>, diag: &mut Diagnostics) -> Option<Tok
|
|||
);
|
||||
let context = &context;
|
||||
self_pinned.#repeater_id.update_model(#model, || {
|
||||
let mut new_comp = #rep_component_id::default();
|
||||
new_comp.parent = self_pinned.self_weak.get().unwrap().clone();
|
||||
new_comp
|
||||
#rep_component_id::new(self_pinned.self_weak.get().unwrap().clone())
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -231,38 +226,37 @@ pub fn generate(component: &Rc<Component>, diag: &mut Diagnostics) -> Option<Tok
|
|||
|
||||
if matches!(item.lookup_property(k.as_str()), Type::Signal) {
|
||||
init.push(quote!(
|
||||
self_.#rust_property.set_handler(|context, ()| {
|
||||
self_pinned.#rust_property.set_handler(|context, ()| {
|
||||
let _self = context.get_component::<#component_id>().unwrap();
|
||||
#tokens_for_expression;
|
||||
});
|
||||
));
|
||||
} else {
|
||||
if binding_expression.is_constant() {
|
||||
let setter = property_set_value_tokens(
|
||||
let setter = if binding_expression.is_constant() {
|
||||
property_set_value_tokens(
|
||||
component,
|
||||
&item_rc,
|
||||
k,
|
||||
quote!((#tokens_for_expression) as _),
|
||||
);
|
||||
init.push(quote!(
|
||||
self_.#rust_property.#setter;
|
||||
));
|
||||
)
|
||||
} else {
|
||||
let setter = property_set_binding_tokens(
|
||||
property_set_binding_tokens(
|
||||
component,
|
||||
&item_rc,
|
||||
k,
|
||||
quote!(
|
||||
|context| {
|
||||
let _self = context.get_component::<#component_id>().unwrap();
|
||||
quote!({
|
||||
let self_weak = sixtyfps::re_exports::WeakPin::downgrade(self_pinned.clone());
|
||||
move |context| {
|
||||
let self_pinned = self_weak.upgrade().unwrap();
|
||||
let _self = self_pinned.as_ref();
|
||||
(#tokens_for_expression) as _
|
||||
}
|
||||
),
|
||||
);
|
||||
init.push(quote!(
|
||||
self_.#rust_property.#setter;
|
||||
));
|
||||
}
|
||||
}),
|
||||
)
|
||||
};
|
||||
init.push(quote!(
|
||||
self_pinned.#rust_property.#setter;
|
||||
));
|
||||
}
|
||||
}
|
||||
item_names.push(field_name);
|
||||
|
@ -312,15 +306,10 @@ pub fn generate(component: &Rc<Component>, diag: &mut Diagnostics) -> Option<Tok
|
|||
));
|
||||
} else {
|
||||
property_and_signal_accessors.push(quote! {
|
||||
fn run(self) {
|
||||
fn run(self : core::pin::Pin<std::rc::Rc<Self>>) {
|
||||
use sixtyfps::re_exports::*;
|
||||
let window = sixtyfps::create_window();
|
||||
let self_pinned = Rc::pin(self);
|
||||
self_pinned.self_weak.set(WeakPin::downgrade(self_pinned.clone()))
|
||||
.map_err(|_|())
|
||||
.expect("Can only be pinned once");
|
||||
#(#init_repeaters)*
|
||||
window.run(VRef::new_pin(self_pinned.as_ref()));
|
||||
window.run(VRef::new_pin(self.as_ref()));
|
||||
}
|
||||
});
|
||||
};
|
||||
|
@ -349,25 +338,6 @@ pub fn generate(component: &Rc<Component>, diag: &mut Diagnostics) -> Option<Tok
|
|||
#(parent : sixtyfps::re_exports::WeakPin<#parent_component_type>,)*
|
||||
}
|
||||
|
||||
impl ::core::default::Default for #component_id {
|
||||
fn default() -> Self {
|
||||
#![allow(unused)]
|
||||
use sixtyfps::re_exports::*;
|
||||
ComponentVTable_static!(static VT for #component_id);
|
||||
let mut self_ = Self {
|
||||
#(#item_names : ::core::default::Default::default(),)*
|
||||
#(#declared_property_vars : ::core::default::Default::default(),)*
|
||||
#(#declared_signals : ::core::default::Default::default(),)*
|
||||
#(#repeated_element_names : ::core::default::Default::default(),)*
|
||||
#(#repeated_dynmodel_names : ::core::default::Default::default(),)*
|
||||
self_weak : ::core::default::Default::default(),
|
||||
#(parent : sixtyfps::re_exports::WeakPin::<#parent_component_type>::default(),)*
|
||||
};
|
||||
#(#init)*
|
||||
self_
|
||||
}
|
||||
|
||||
}
|
||||
impl sixtyfps::re_exports::Component for #component_id {
|
||||
fn visit_children_item(self: ::core::pin::Pin<&Self>, index: isize, visitor: sixtyfps::re_exports::ItemVisitorRefMut) {
|
||||
use sixtyfps::re_exports::*;
|
||||
|
@ -386,6 +356,27 @@ pub fn generate(component: &Rc<Component>, diag: &mut Diagnostics) -> Option<Tok
|
|||
}
|
||||
|
||||
impl #component_id{
|
||||
fn new(#(parent: sixtyfps::re_exports::WeakPin::<#parent_component_type>)*)
|
||||
-> core::pin::Pin<std::rc::Rc<Self>>
|
||||
{
|
||||
#![allow(unused)]
|
||||
use sixtyfps::re_exports::*;
|
||||
ComponentVTable_static!(static VT for #component_id);
|
||||
let mut self_ = Self {
|
||||
#(#item_names : ::core::default::Default::default(),)*
|
||||
#(#declared_property_vars : ::core::default::Default::default(),)*
|
||||
#(#declared_signals : ::core::default::Default::default(),)*
|
||||
#(#repeated_element_names : ::core::default::Default::default(),)*
|
||||
#(#repeated_dynmodel_names : ::core::default::Default::default(),)*
|
||||
self_weak : ::core::default::Default::default(),
|
||||
#(parent : parent as sixtyfps::re_exports::WeakPin::<#parent_component_type>,)*
|
||||
};
|
||||
let self_pinned = std::rc::Rc::pin(self_);
|
||||
self_pinned.self_weak.set(WeakPin::downgrade(self_pinned.clone())).map_err(|_|())
|
||||
.expect("Can only be pinned once");
|
||||
#(#init)*
|
||||
self_pinned
|
||||
}
|
||||
#(#property_and_signal_accessors)*
|
||||
}
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@ but then it should also be renamed everywhere, including in the language grammar
|
|||
*/
|
||||
|
||||
use super::properties::EvaluationContext;
|
||||
use core::cell::Cell;
|
||||
|
||||
/// A Signal that can be connected to a handler.
|
||||
///
|
||||
|
@ -15,7 +16,7 @@ use super::properties::EvaluationContext;
|
|||
#[repr(C)]
|
||||
pub struct Signal<Arg> {
|
||||
/// FIXME: Box<dyn> is a fat object and we probaly want to put an erased type in there
|
||||
handler: Option<Box<dyn Fn(&EvaluationContext, Arg)>>,
|
||||
handler: Cell<Option<Box<dyn Fn(&EvaluationContext, Arg)>>>,
|
||||
}
|
||||
|
||||
impl<Arg> Signal<Arg> {
|
||||
|
@ -23,16 +24,18 @@ impl<Arg> Signal<Arg> {
|
|||
///
|
||||
/// The constext must be a context corresponding to the component in which the signal is contained.
|
||||
pub fn emit(&self, context: &EvaluationContext, a: Arg) {
|
||||
if let Some(h) = &self.handler {
|
||||
if let Some(h) = self.handler.take() {
|
||||
h(context, a);
|
||||
assert!(self.handler.take().is_none(), "Signal Handler set while emitted");
|
||||
self.handler.set(Some(h))
|
||||
}
|
||||
}
|
||||
|
||||
/// Set an handler to be called when the signal is emited
|
||||
///
|
||||
/// There can only be one single handler per signal.
|
||||
pub fn set_handler(&mut self, f: impl Fn(&EvaluationContext, Arg) + 'static) {
|
||||
self.handler = Some(Box::new(f));
|
||||
pub fn set_handler(&self, f: impl Fn(&EvaluationContext, Arg) + 'static) {
|
||||
self.handler.set(Some(Box::new(f)));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -57,7 +60,7 @@ fn signal_simple_test() {
|
|||
fn compute_layout(self: Pin<&Self>, _: &crate::EvaluationContext) {}
|
||||
}
|
||||
use crate::abi::datastructures::ComponentVTable;
|
||||
let mut c = Component::default();
|
||||
let c = Component::default();
|
||||
c.clicked.set_handler(|c, ()| unsafe {
|
||||
(*(c.component.as_ptr() as *const Component)).pressed.set(true)
|
||||
});
|
||||
|
|
|
@ -18,7 +18,7 @@ assert(instance.get_t4() == 3 + - 5 - 8 - -9 * - - - 120);
|
|||
|
||||
|
||||
```rust
|
||||
let instance = Box::pin(TestCase::default());
|
||||
let instance = TestCase::new();
|
||||
let instance = instance.as_ref();
|
||||
assert_eq!(instance.get_t1(), 4 + 3 * 2 + 2 - 50 - 2);
|
||||
assert_eq!(instance.get_t2(), 500 / 2 * 30 - 1);
|
||||
|
|
|
@ -11,7 +11,7 @@ assert(!instance.get_falsevar());
|
|||
|
||||
|
||||
```rust
|
||||
let instance = Box::pin(TestCase::default());
|
||||
let instance = TestCase::new();
|
||||
let instance = instance.as_ref();
|
||||
assert!(instance.get_truevar(), 1);
|
||||
assert!(!instance.get_falsevar(), 1);
|
||||
|
|
|
@ -21,7 +21,7 @@ assert(instance.get_s1() == "123");
|
|||
|
||||
|
||||
```rust
|
||||
let instance = Box::pin(TestCase::default());
|
||||
let instance = TestCase::new();
|
||||
let instance = instance.as_ref();
|
||||
instance.set_condition(true);
|
||||
assert_eq!(instance.get_s1(), "abc");
|
||||
|
|
|
@ -27,7 +27,7 @@ assert(t.get_b1() != t.get_r5());
|
|||
|
||||
|
||||
```rust
|
||||
let t = Box::pin(Test::default());
|
||||
let t = Test::new();
|
||||
let t = t.as_ref();
|
||||
assert_eq!(t.get_r1(), t.get_r2());
|
||||
assert_eq!(t.get_r1(), t.get_r3());
|
||||
|
|
|
@ -58,7 +58,7 @@ assert(instance.get_t6() == true);
|
|||
|
||||
|
||||
```rust
|
||||
let instance = Box::pin(TestCase::default());
|
||||
let instance = TestCase::new();
|
||||
let instance = instance.as_ref();
|
||||
|
||||
assert_eq!(instance.get_t1(), true);
|
||||
|
|
|
@ -20,7 +20,7 @@ assert(instance.get_test_value2() == 3);
|
|||
|
||||
|
||||
```rust
|
||||
let instance = Box::pin(TestCase::default());
|
||||
let instance = TestCase::new();
|
||||
let instance = instance.as_ref();
|
||||
instance.set_condition(true);
|
||||
assert_eq!(instance.get_test_value(), 1);
|
||||
|
|
|
@ -14,7 +14,7 @@ assert(instance.get_signal_emission_count() == 1);
|
|||
|
||||
|
||||
```rust
|
||||
let instance = Box::pin(TestCase::default());
|
||||
let instance = TestCase::new();
|
||||
let instance = instance.as_ref();
|
||||
instance.set_signal_emission_count(0);
|
||||
assert_eq!(instance.get_signal_emission_count(), 0);
|
||||
|
|
|
@ -8,7 +8,7 @@ TestCase instance;
|
|||
```
|
||||
|
||||
```rust
|
||||
TestCase::default();
|
||||
TestCase::new();
|
||||
```
|
||||
|
||||
```js
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue