From 018c1a666641e572a55f635b53f7c81f13d2bff5 Mon Sep 17 00:00:00 2001 From: Tobias Hunger Date: Thu, 27 Jan 2022 19:10:16 +0100 Subject: [PATCH] Rename ModelHandle to SharedModel This patch is mostly a rename now, but also contains a few small cleanups. SharedModel implements the Model trait itself and gracefully falls back to an empty model is no Model was provided. This allows for some small simplifications. Also make sure to use the same comparision for SharedModels everywhere. This fixes the last remaining clippy errors we had. --- CHANGELOG.md | 1 + api/sixtyfps-node/native/lib.rs | 9 +- api/sixtyfps-rs/lib.rs | 4 +- api/sixtyfps-rs/migration.md | 3 + .../rust/src/main_game_logic_in_rust.rs | 2 +- .../tutorial/rust/src/main_tiles_from_rust.rs | 2 +- examples/imagefilter/main.rs | 2 +- examples/memory/main.rs | 4 +- examples/printerdemo/rust/main.rs | 2 +- examples/slide_puzzle/main.rs | 2 +- examples/todo/rust/main.rs | 2 +- sixtyfps_compiler/generator/rust.rs | 10 +- sixtyfps_runtime/corelib/model.rs | 108 ++++++++---------- sixtyfps_runtime/interpreter/api.rs | 16 +-- .../interpreter/dynamic_component.rs | 4 +- sixtyfps_runtime/interpreter/eval.rs | 8 +- sixtyfps_runtime/interpreter/ffi.rs | 4 +- tests/cases/crashes/layout_deleted_item.60 | 2 +- tests/cases/models/array.60 | 2 +- tests/cases/models/model.60 | 2 +- tests/cases/models/write_to_model.60 | 2 +- tools/viewer/main.rs | 9 +- 22 files changed, 88 insertions(+), 112 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8403c5db2..7510b8a69 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,7 @@ as well as the [Rust migration guide for the `sixtyfps` crate](api/sixtyfps-rs/m - In Rust and C++, `sixtyfps::Image::size()` now returns an integer size type. - `sixtyfps::interpreter::CallCallbackError` was renamed to `sixtyfps::interpreter::InvokeCallbackError` - Some deprecation warning in .60 became hard errors + - Replace `ModelHandle` with `ModelRc` ### Added diff --git a/api/sixtyfps-node/native/lib.rs b/api/sixtyfps-node/native/lib.rs index e2f3782cd..62eb9fbbd 100644 --- a/api/sixtyfps-node/native/lib.rs +++ b/api/sixtyfps-node/native/lib.rs @@ -5,7 +5,7 @@ use core::cell::RefCell; use neon::prelude::*; use rand::RngCore; use sixtyfps_compilerlib::langtype::Type; -use sixtyfps_corelib::model::{Model, ModelHandle}; +use sixtyfps_corelib::model::{Model, ModelRc}; use sixtyfps_corelib::window::WindowHandleAccess; use sixtyfps_corelib::{ImageInner, SharedVector}; use std::rc::Rc; @@ -182,21 +182,20 @@ fn to_eval_value<'cx>( Type::Array(a) => match val.downcast::() { Ok(arr) => { let vec = arr.to_vec(cx)?; - Ok(Value::Model(ModelHandle::new(Rc::new( + Ok(Value::Model(ModelRc::new(Rc::new( sixtyfps_corelib::model::SharedVectorModel::from( vec.into_iter() .map(|i| to_eval_value(i, (*a).clone(), cx, persistent_context)) .collect::, _>>()?, ), - ) - as Rc>))) + )))) } Err(_) => { let obj = val.downcast_or_throw::(cx)?; obj.get(cx, "rowCount")?.downcast_or_throw::(cx)?; obj.get(cx, "rowData")?.downcast_or_throw::(cx)?; let m = js_model::JsModel::new(obj, *a, cx, persistent_context)?; - Ok(Value::Model(ModelHandle::new(m))) + Ok(Value::Model(ModelRc::new(m))) } }, Type::Image => { diff --git a/api/sixtyfps-rs/lib.rs b/api/sixtyfps-rs/lib.rs index fb15e3aae..09f73d5c8 100644 --- a/api/sixtyfps-rs/lib.rs +++ b/api/sixtyfps-rs/lib.rs @@ -181,7 +181,7 @@ The follow table summarizes the entire mapping: | `duration` | `i64` | At run-time, durations are always represented as signed 64-bit integers with millisecond precision. | | `angle` | `f32` | The value in degrees | | structure | `struct` of the same name | | -| array | [`ModelHandle`] | | +| array | [`ModelRc`] | | For user defined structures in the .60, an extra struct is generated. For example, if the `.60` contains @@ -233,7 +233,7 @@ pub use sixtyfps_corelib::graphics::{ Brush, Color, Image, LoadImageError, Rgb8Pixel, Rgba8Pixel, RgbaColor, SharedPixelBuffer, }; pub use sixtyfps_corelib::model::{ - Model, ModelHandle, ModelNotify, ModelPeer, ModelTracker, StandardListViewItem, VecModel, + Model, ModelNotify, ModelPeer, ModelRc, ModelTracker, StandardListViewItem, VecModel, }; pub use sixtyfps_corelib::sharedvector::SharedVector; pub use sixtyfps_corelib::string::SharedString; diff --git a/api/sixtyfps-rs/migration.md b/api/sixtyfps-rs/migration.md index 35d40273f..b65f71677 100644 --- a/api/sixtyfps-rs/migration.md +++ b/api/sixtyfps-rs/migration.md @@ -62,3 +62,6 @@ fn model_tracker(&self) -> &dyn ModelTracker { } ``` +#### Minor changes to `Model` + +`ModelRc` replaces `ModelHandle`. diff --git a/docs/tutorial/rust/src/main_game_logic_in_rust.rs b/docs/tutorial/rust/src/main_game_logic_in_rust.rs index 735648a88..f6f79f267 100644 --- a/docs/tutorial/rust/src/main_game_logic_in_rust.rs +++ b/docs/tutorial/rust/src/main_game_logic_in_rust.rs @@ -20,7 +20,7 @@ fn main() { // ANCHOR: game_logic // Assign the shuffled Vec to the model property let tiles_model = std::rc::Rc::new(sixtyfps::VecModel::from(tiles)); - main_window.set_memory_tiles(sixtyfps::ModelHandle::new(tiles_model.clone())); + main_window.set_memory_tiles(sixtyfps::ModelRc::new(tiles_model.clone())); let main_window_weak = main_window.as_weak(); main_window.on_check_if_pair_solved(move || { diff --git a/docs/tutorial/rust/src/main_tiles_from_rust.rs b/docs/tutorial/rust/src/main_tiles_from_rust.rs index 6f2f5b449..18238215c 100644 --- a/docs/tutorial/rust/src/main_tiles_from_rust.rs +++ b/docs/tutorial/rust/src/main_tiles_from_rust.rs @@ -20,7 +20,7 @@ fn main() { // Assign the shuffled Vec to the model property let tiles_model = std::rc::Rc::new(sixtyfps::VecModel::from(tiles)); - main_window.set_memory_tiles(sixtyfps::ModelHandle::new(tiles_model)); + main_window.set_memory_tiles(sixtyfps::ModelRc::new(tiles_model)); main_window.run(); } diff --git a/examples/imagefilter/main.rs b/examples/imagefilter/main.rs index 147e4f409..7b9ba2812 100644 --- a/examples/imagefilter/main.rs +++ b/examples/imagefilter/main.rs @@ -140,7 +140,7 @@ pub fn main() { ]); let filters = Rc::new(filters); - main_window.set_filters(sixtyfps::ModelHandle::new(filters.clone())); + main_window.set_filters(sixtyfps::ModelRc::new(filters.clone())); main_window.on_filter_image(move |filter_index| { let filter_fn = filters.0[filter_index as usize].apply_function; diff --git a/examples/memory/main.rs b/examples/memory/main.rs index 9a35a0944..0ccfa8aad 100644 --- a/examples/memory/main.rs +++ b/examples/memory/main.rs @@ -1,7 +1,7 @@ // Copyright © SixtyFPS GmbH // SPDX-License-Identifier: (GPL-3.0-only OR LicenseRef-SixtyFPS-commercial) -use sixtyfps::{Model, ModelHandle, Timer, VecModel}; +use sixtyfps::{Model, ModelRc, Timer, VecModel}; use std::rc::Rc; use std::time::Duration; @@ -30,7 +30,7 @@ pub fn main() { let tiles_model = Rc::new(VecModel::from(tiles)); - main_window.set_memory_tiles(ModelHandle::new(tiles_model.clone())); + main_window.set_memory_tiles(ModelRc::new(tiles_model.clone())); let main_window_weak = main_window.as_weak(); diff --git a/examples/printerdemo/rust/main.rs b/examples/printerdemo/rust/main.rs index 6018fb76e..8ffa457bf 100644 --- a/examples/printerdemo/rust/main.rs +++ b/examples/printerdemo/rust/main.rs @@ -59,7 +59,7 @@ pub fn main() { }); main_window .global::() - .set_printer_queue(sixtyfps::ModelHandle::new(printer_queue.data.clone())); + .set_printer_queue(sixtyfps::ModelRc::new(printer_queue.data.clone())); main_window.on_quit(move || { #[cfg(not(target_arch = "wasm32"))] diff --git a/examples/slide_puzzle/main.rs b/examples/slide_puzzle/main.rs index 55f09f9eb..912839f96 100644 --- a/examples/slide_puzzle/main.rs +++ b/examples/slide_puzzle/main.rs @@ -180,7 +180,7 @@ pub fn main() { finished: false, })); state.borrow_mut().randomize(); - main_window.set_pieces(sixtyfps::ModelHandle::new(state.borrow().pieces.clone())); + main_window.set_pieces(sixtyfps::ModelRc::new(state.borrow().pieces.clone())); let state_copy = state.clone(); main_window.on_piece_clicked(move |p| { diff --git a/examples/todo/rust/main.rs b/examples/todo/rust/main.rs index e9f30647e..80b7f52fe 100644 --- a/examples/todo/rust/main.rs +++ b/examples/todo/rust/main.rs @@ -45,7 +45,7 @@ pub fn main() { } }); - main_window.set_todo_model(sixtyfps::ModelHandle::new(todo_model)); + main_window.set_todo_model(sixtyfps::ModelRc::new(todo_model)); main_window.run(); } diff --git a/sixtyfps_compiler/generator/rust.rs b/sixtyfps_compiler/generator/rust.rs index 264b9e95c..d59aa677c 100644 --- a/sixtyfps_compiler/generator/rust.rs +++ b/sixtyfps_compiler/generator/rust.rs @@ -78,7 +78,7 @@ fn rust_type(ty: &Type) -> Option { Type::Struct { name: Some(name), .. } => Some(struct_name_to_tokens(name)), Type::Array(o) => { let inner = rust_type(o)?; - Some(quote!(sixtyfps::re_exports::ModelHandle<#inner>)) + Some(quote!(sixtyfps::re_exports::ModelRc<#inner>)) } Type::Enumeration(e) => { let e = ident(&e.name); @@ -536,7 +536,7 @@ fn generate_sub_component( let mut model = compile_expression(&repeated.model, &ctx); if repeated.model.ty(&ctx) == Type::Bool { - model = quote!(sixtyfps::re_exports::ModelHandle::new(sixtyfps::re_exports::Rc::::new(#model))) + model = quote!(sixtyfps::re_exports::ModelRc::new(sixtyfps::re_exports::Rc::::new(#model))) } init.push(quote! { @@ -1273,7 +1273,7 @@ fn compile_expression(expr: &Expression, ctx: &EvaluationContext) -> TokenStream )) } (Type::Float32, Type::Model) | (Type::Int32, Type::Model) => { - quote!(sixtyfps::re_exports::ModelHandle::new(sixtyfps::re_exports::Rc::::new(#f as usize))) + quote!(sixtyfps::re_exports::ModelRc::new(sixtyfps::re_exports::Rc::::new(#f as usize))) } (Type::Float32, Type::Color) => { quote!(sixtyfps::re_exports::Color::from_argb_encoded(#f as u32)) @@ -1446,7 +1446,7 @@ fn compile_expression(expr: &Expression, ctx: &EvaluationContext) -> TokenStream let base_e = compile_expression(array, ctx); let index_e = compile_expression(index, ctx); let value_e = compile_expression(value, ctx); - quote!((#base_e).set_row_data(#index_e as usize, #value_e as _);) + quote!((#base_e).set_row_data(#index_e as usize, #value_e as _)) } Expression::BinaryExpression { lhs, rhs, op } => { let (conv1, conv2) = match crate::expression_tree::operator_class(*op) { @@ -1536,7 +1536,7 @@ fn compile_expression(expr: &Expression, ctx: &EvaluationContext) -> TokenStream let val = values.iter().map(|e| compile_expression(e, ctx)); if *as_model { let rust_element_ty = rust_type(element_ty).unwrap(); - quote!(sixtyfps::re_exports::ModelHandle::new( + quote!(sixtyfps::re_exports::ModelRc::new( sixtyfps::re_exports::Rc::new(sixtyfps::re_exports::VecModel::<#rust_element_ty>::from( sixtyfps::re_exports::vec![#(#val as _),*] )) diff --git a/sixtyfps_runtime/corelib/model.rs b/sixtyfps_runtime/corelib/model.rs index b9a93251a..8481c0fb5 100644 --- a/sixtyfps_runtime/corelib/model.rs +++ b/sixtyfps_runtime/corelib/model.rs @@ -239,14 +239,14 @@ pub trait Model { /// Return something that can be downcast'ed (typically self) /// - /// This is useful to get back to the actual model from a ModelHandle stored + /// This is useful to get back to the actual model from a `ModelRc` stored /// in a component. /// /// ``` /// # use sixtyfps_corelib::model::*; /// # use std::rc::Rc; /// let vec_model = Rc::new(VecModel::from(vec![1i32, 2, 3])); - /// let handle = ModelHandle::from(vec_model as Rc>); + /// let handle = ModelRc::new(vec_model as Rc>); /// // later: /// handle.as_any().downcast_ref::>().unwrap().push(4); /// assert_eq!(handle.row_data(3).unwrap(), 4); @@ -305,11 +305,11 @@ pub struct VecModel { impl VecModel { /// Allocate a new model from a slice - pub fn from_slice(slice: &[T]) -> ModelHandle + pub fn from_slice(slice: &[T]) -> ModelRc where T: Clone, { - ModelHandle(Some(Rc::::new(slice.to_vec().into()))) + ModelRc::new(Rc::::new(slice.to_vec().into())) } /// Add a row at the end of the model @@ -462,56 +462,49 @@ impl Model for bool { } } -/// Properties of type array in the .60 language are represented as -/// an [`Option`] of an [`Rc`] of something implemented the [`Model`] trait +/// Properties of type Array in the .60 language are represented as +/// a `ModelRc` that implements the `Model` trait. #[derive(derive_more::Deref, derive_more::DerefMut, derive_more::From, derive_more::Into)] -pub struct ModelHandle(pub Option>>); +pub struct ModelRc(Option>>); -impl core::fmt::Debug for ModelHandle { - fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { - write!(f, "ModelHandle({:?})", self.0.as_ref().map(|_| "dyn Model")) +impl core::fmt::Debug for ModelRc { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "ModelRc(dyn Model)") } } -impl Clone for ModelHandle { +impl Clone for ModelRc { fn clone(&self) -> Self { Self(self.0.clone()) } } -impl Default for ModelHandle { + +impl Default for ModelRc { fn default() -> Self { Self(None) } } -impl core::cmp::PartialEq for ModelHandle { +impl core::cmp::PartialEq for ModelRc { fn eq(&self, other: &Self) -> bool { match (&self.0, &other.0) { (None, None) => true, - (None, Some(_)) => false, - (Some(_), None) => false, (Some(a), Some(b)) => core::ptr::eq( (&**a) as *const dyn Model as *const u8, (&**b) as *const dyn Model as *const u8, ), + _ => false, } } } -impl From>> for ModelHandle { - fn from(x: Rc>) -> Self { - Self(Some(x)) - } -} - -impl ModelHandle { - /// Create a new handle wrapping the given model +impl ModelRc { pub fn new(model: Rc>) -> Self { Self(Some(model)) } } -impl Model for ModelHandle { +impl Model for ModelRc { type Data = T; fn row_count(&self) -> usize { @@ -524,7 +517,7 @@ impl Model for ModelHandle { fn set_row_data(&self, row: usize, data: Self::Data) { if let Some(model) = self.0.as_ref() { - model.set_row_data(row, data) + model.set_row_data(row, data); } } @@ -656,7 +649,7 @@ impl ErasedRepeater for Repeater { pub struct Repeater { inner: RefCell>, #[pin] - model: Property>, + model: Property>, #[pin] is_dirty: Property, /// Only used for the list view to track if the scrollbar has changed and item needs to be layed out again. @@ -694,24 +687,22 @@ impl PinnedDrop for Repeater { } impl Repeater { - fn model(self: Pin<&Self>) -> ModelHandle { - // Safety: Repeater does not implement drop and never let access model as mutable + fn model(self: Pin<&Self>) -> ModelRc { + // Safety: Repeater does not implement drop and never allows access to model as mutable let model = self.project_ref().model; if model.is_dirty() { *self.inner.borrow_mut() = RepeaterInner::default(); self.is_dirty.set(true); - if let ModelHandle(Some(m)) = model.get() { - let peer = self.peer.get_or_init(|| { - //Safety: we will reset it when we Drop the Repeater - Rc::pin(DependencyNode::new( - self.get_ref() as &dyn ErasedRepeater as *const dyn ErasedRepeater - )) - }); + let m = model.get(); + let peer = self.peer.get_or_init(|| { + //Safety: we will reset it when we Drop the Repeater + Rc::pin(DependencyNode::new( + self.get_ref() as &dyn ErasedRepeater as *const dyn ErasedRepeater + )) + }); - m.model_tracker() - .attach_peer(ModelPeer { inner: PinWeak::downgrade(peer.clone()) }); - } + m.model_tracker().attach_peer(ModelPeer { inner: PinWeak::downgrade(peer.clone()) }); } model.get() } @@ -719,12 +710,9 @@ impl Repeater { /// Call this function to make sure that the model is updated. /// The init function is the function to create a component pub fn ensure_updated(self: Pin<&Self>, init: impl Fn() -> ComponentRc) { - if let ModelHandle(Some(model)) = self.model() { - if self.project_ref().is_dirty.get() { - self.ensure_updated_impl(init, &model, model.row_count()); - } - } else { - self.inner.borrow_mut().components.clear(); + let model = self.model(); + if self.project_ref().is_dirty.get() { + self.ensure_updated_impl(init, &model, model.row_count()); } } @@ -732,7 +720,7 @@ impl Repeater { fn ensure_updated_impl( self: Pin<&Self>, init: impl Fn() -> ComponentRc, - model: &Rc>, + model: &ModelRc, count: usize, ) -> bool { let mut inner = self.inner.borrow_mut(); @@ -769,11 +757,7 @@ impl Repeater { viewport_y.set(0.); }; - let model = if let ModelHandle(Some(model)) = self.model() { - model - } else { - return empty_model(); - }; + let model = self.model(); let row_count = model.row_count(); if row_count == 0 { return empty_model(); @@ -785,8 +769,7 @@ impl Repeater { let geometry_updated = listview_geometry_tracker .evaluate_if_dirty(|| { // Fetch the model again to make sure that it is a dependency of this geometry tracker. - // invariant: model existence was checked earlier, so unwrap() should be safe. - let model = self.model().0.unwrap(); + let model = self.model(); // Also register a dependency to "is_dirty" let _ = self.project_ref().is_dirty.get(); @@ -904,14 +887,13 @@ impl Repeater { /// Sets the data directly in the model pub fn model_set_row_data(self: Pin<&Self>, row: usize, data: C::Data) { - if let ModelHandle(Some(model)) = self.model() { - model.set_row_data(row, data); - if let Some(c) = self.inner.borrow_mut().components.get_mut(row) { - if c.0 == RepeatedComponentState::Dirty { - if let Some(comp) = c.1.as_ref() { - comp.update(row, model.row_data(row).unwrap()); - c.0 = RepeatedComponentState::Clean; - } + let model = self.model(); + model.set_row_data(row, data); + if let Some(c) = self.inner.borrow_mut().components.get_mut(row) { + if c.0 == RepeatedComponentState::Dirty { + if let Some(comp) = c.1.as_ref() { + comp.update(row, model.row_data(row).unwrap()); + c.0 = RepeatedComponentState::Clean; } } } @@ -920,7 +902,7 @@ impl Repeater { impl Repeater { /// Set the model binding - pub fn set_model_binding(&self, binding: impl Fn() -> ModelHandle + 'static) { + pub fn set_model_binding(&self, binding: impl Fn() -> ModelRc + 'static) { self.model.set_binding(binding); } @@ -991,7 +973,7 @@ pub struct StandardListViewItem { #[test] fn test_tracking_model_handle() { let model: Rc> = Rc::new(Default::default()); - let handle = ModelHandle::new(model.clone()); + let handle = ModelRc::new(model.clone()); let tracker = Box::pin(crate::properties::PropertyTracker::default()); assert_eq!( tracker.as_ref().evaluate(|| { @@ -1028,7 +1010,7 @@ fn test_tracking_model_handle() { #[test] fn test_data_tracking() { let model: Rc> = Rc::new(VecModel::from(vec![0, 1, 2, 3, 4])); - let handle = ModelHandle::new(model.clone()); + let handle = ModelRc::new(model.clone()); let tracker = Box::pin(crate::properties::PropertyTracker::default()); assert_eq!( tracker.as_ref().evaluate(|| { diff --git a/sixtyfps_runtime/interpreter/api.rs b/sixtyfps_runtime/interpreter/api.rs index 1ce5fc49c..3e9f481cb 100644 --- a/sixtyfps_runtime/interpreter/api.rs +++ b/sixtyfps_runtime/interpreter/api.rs @@ -4,7 +4,7 @@ use core::convert::TryInto; use sixtyfps_compilerlib::langtype::Type as LangType; use sixtyfps_corelib::graphics::Image; -use sixtyfps_corelib::model::{Model, ModelHandle}; +use sixtyfps_corelib::model::{Model, ModelRc}; use sixtyfps_corelib::{Brush, PathData, SharedString, SharedVector}; use std::borrow::Cow; use std::collections::HashMap; @@ -92,7 +92,7 @@ pub enum Value { /// Correspond to the `image` type in .60 Image(Image), /// A model (that includes array in .60) - Model(ModelHandle), + Model(ModelRc), /// An object Struct(Struct), /// Correspond to `brush` or `color` type in .60. For color, this is then a [`Brush::SolidColor`] @@ -144,11 +144,7 @@ impl PartialEq for Value { Value::Image(lhs) => matches!(other, Value::Image(rhs) if lhs == rhs), Value::Model(lhs) => { if let Value::Model(rhs) = other { - match (&lhs.0, &rhs.0) { - (None, None) => true, - (None, Some(_)) | (Some(_), None) => false, - (Some(a), Some(b)) => Rc::ptr_eq(a, b), - } + lhs == rhs } else { false } @@ -1364,13 +1360,13 @@ fn component_definition_model_properties() { let instance = comp_def.create(); - let int_model = Value::Model(ModelHandle::new(Rc::new(VecModel::from_slice(&[ + let int_model = Value::Model(ModelRc::new(Rc::new(VecModel::from_slice(&[ Value::Number(14.), Value::Number(15.), Value::Number(16.), ])))); - let empty_model = Value::Model(ModelHandle::new(Rc::new(VecModel::::default()))); - let model_with_string = Value::Model(ModelHandle::new(Rc::new(VecModel::from_slice(&[ + let empty_model = Value::Model(ModelRc::new(Rc::new(VecModel::::default()))); + let model_with_string = Value::Model(ModelRc::new(Rc::new(VecModel::from_slice(&[ Value::Number(1000.), Value::String("foo".into()), Value::Number(1111.), diff --git a/sixtyfps_runtime/interpreter/dynamic_component.rs b/sixtyfps_runtime/interpreter/dynamic_component.rs index db27eda6c..3640334b0 100644 --- a/sixtyfps_runtime/interpreter/dynamic_component.rs +++ b/sixtyfps_runtime/interpreter/dynamic_component.rs @@ -1355,9 +1355,7 @@ pub fn instantiate( InstanceRef::from_pin_ref(c, guard) }), ); - sixtyfps_corelib::model::ModelHandle(Some(Rc::new( - crate::value_model::ValueModel::new(m), - ))) + sixtyfps_corelib::model::ModelRc::new(Rc::new(crate::value_model::ValueModel::new(m))) }); } diff --git a/sixtyfps_runtime/interpreter/eval.rs b/sixtyfps_runtime/interpreter/eval.rs index b37b589e8..491887a83 100644 --- a/sixtyfps_runtime/interpreter/eval.rs +++ b/sixtyfps_runtime/interpreter/eval.rs @@ -7,7 +7,7 @@ use core::convert::TryInto; use core::pin::Pin; use corelib::graphics::{GradientStop, LinearGradientBrush, PathElement}; use corelib::items::{ItemRef, PropertyAnimation}; -use corelib::model::{Model, ModelHandle}; +use corelib::model::{Model, ModelRc}; use corelib::rtti::AnimatedBindingKind; use corelib::window::{WindowHandleAccess, WindowRc}; use corelib::{Brush, Color, PathData, SharedString, SharedVector}; @@ -568,10 +568,10 @@ pub fn eval_expression(expression: &Expression, local_context: &mut EvalLocalCon } } Expression::Array { values, .. } => Value::Model( - ModelHandle::new(Rc::new(corelib::model::SharedVectorModel::from( + ModelRc::new(Rc::new(corelib::model::SharedVectorModel::from( values.iter().map(|e| eval_expression(e, local_context)).collect::>() - )) as Rc>) - ), + ) + ))), Expression::Struct { values, .. } => Value::Struct( values .iter() diff --git a/sixtyfps_runtime/interpreter/ffi.rs b/sixtyfps_runtime/interpreter/ffi.rs index d5b39bbcc..6eb0d762a 100644 --- a/sixtyfps_runtime/interpreter/ffi.rs +++ b/sixtyfps_runtime/interpreter/ffi.rs @@ -85,7 +85,7 @@ pub unsafe extern "C" fn sixtyfps_interpreter_value_new_array_model( let vec = std::mem::transmute::, SharedVector>(a.clone()); std::ptr::write( val as *mut Value, - Value::Model(ModelHandle::new(Rc::new(SharedVectorModel::::from(vec)))), + Value::Model(ModelRc::new(Rc::new(SharedVectorModel::::from(vec)))), ) } @@ -121,7 +121,7 @@ pub unsafe extern "C" fn sixtyfps_interpreter_value_new_model( ) { std::ptr::write( val as *mut Value, - Value::Model(ModelHandle::new(Rc::new(ModelAdaptorWrapper(model)))), + Value::Model(ModelRc::new(Rc::new(ModelAdaptorWrapper(model)))), ) } diff --git a/tests/cases/crashes/layout_deleted_item.60 b/tests/cases/crashes/layout_deleted_item.60 index 07f67e468..d87096a04 100644 --- a/tests/cases/crashes/layout_deleted_item.60 +++ b/tests/cases/crashes/layout_deleted_item.60 @@ -52,7 +52,7 @@ assert(!instance.get_hover()); use sixtyfps::Model; let instance = TestCase::new(); let vec_model = std::rc::Rc::new(sixtyfps::VecModel::from(vec![1i32, 2i32])); -instance.set_model(sixtyfps::ModelHandle::from(vec_model.clone() as std::rc::Rc>)); +instance.set_model(sixtyfps::ModelRc::new(vec_model.clone() as std::rc::Rc>)); instance.on_clicked(move || dbg!(vec_model.remove(vec_model.row_count() - 1))); sixtyfps::testing::send_mouse_click(&instance, 95., 5.); assert_eq!(instance.get_model().row_count(), 1); diff --git a/tests/cases/models/array.60 b/tests/cases/models/array.60 index d9fca6abc..66f2c0c83 100644 --- a/tests/cases/models/array.60 +++ b/tests/cases/models/array.60 @@ -43,7 +43,7 @@ assert_eq!(instance.get_n(), 4); assert_eq!(instance.get_third_int(), 3); let model: std::rc::Rc> = std::rc::Rc::new(vec![1, 2, 3, 4, 5, 6, 7].into()); -instance.set_ints(sixtyfps::ModelHandle::new(model.clone())); +instance.set_ints(sixtyfps::ModelRc::new(model.clone())); assert_eq!(instance.get_num_ints(), 7); assert_eq!(instance.get_third_int(), 3); model.push(8); diff --git a/tests/cases/models/model.60 b/tests/cases/models/model.60 index 5f8378fed..9d634296d 100644 --- a/tests/cases/models/model.60 +++ b/tests/cases/models/model.60 @@ -62,7 +62,7 @@ let another_model = std::rc::Rc::new(sixtyfps::VecModel::::from( ("a3".into(), "world".into(), 333.), ])); -instance.set_model(sixtyfps::ModelHandle::new(another_model.clone())); +instance.set_model(sixtyfps::ModelRc::new(another_model.clone())); sixtyfps::testing::send_mouse_click(&instance, 25., 5.); assert_eq!(instance.get_clicked_score(), 333000); diff --git a/tests/cases/models/write_to_model.60 b/tests/cases/models/write_to_model.60 index 78801d4a5..18fb0c487 100644 --- a/tests/cases/models/write_to_model.60 +++ b/tests/cases/models/write_to_model.60 @@ -61,7 +61,7 @@ let another_model = std::rc::Rc::new(sixtyfps::VecModel::::from( ("a3".into(), "world".into(), 333.), ])); -instance.set_model(sixtyfps::ModelHandle::new(another_model.clone())); +instance.set_model(sixtyfps::ModelRc::new(another_model.clone())); sixtyfps::testing::send_mouse_click(&instance, 25., 5.); assert_eq!(instance.get_clicked_score(), 336); diff --git a/tools/viewer/main.rs b/tools/viewer/main.rs index dff91e7c6..1a23a5035 100644 --- a/tools/viewer/main.rs +++ b/tools/viewer/main.rs @@ -3,7 +3,7 @@ #![doc = include_str!("README.md")] -use sixtyfps_corelib::model::{Model, ModelHandle}; +use sixtyfps_corelib::model::{Model, ModelRc}; use sixtyfps_corelib::SharedVector; use sixtyfps_interpreter::{ComponentInstance, SharedString, Value}; use std::future::Future; @@ -268,12 +268,9 @@ fn load_data(instance: &ComponentInstance, data_path: &std::path::Path) -> Resul } serde_json::Value::String(s) => SharedString::from(s.as_str()).into(), serde_json::Value::Array(array) => sixtyfps_interpreter::Value::Model( - ModelHandle::new(Rc::new(sixtyfps_corelib::model::SharedVectorModel::from( + ModelRc::new(Rc::new(sixtyfps_corelib::model::SharedVectorModel::from( array.iter().map(from_json).collect::>(), - )) - as Rc< - dyn sixtyfps_corelib::model::Model, - >), + ))), ), serde_json::Value::Object(obj) => obj .iter()