mirror of
https://github.com/slint-ui/slint.git
synced 2025-11-24 13:21:43 +00:00
The README.md contains the warning that used to be in lib.rs. Add README.md files to all internal crates ... pointing to the official public crate to use instead. Rename internal crates fixup: README files fixup rename
148 lines
5.1 KiB
Rust
148 lines
5.1 KiB
Rust
// Copyright © SixtyFPS GmbH <info@sixtyfps.io>
|
|
// SPDX-License-Identifier: (GPL-3.0-only OR LicenseRef-SixtyFPS-commercial)
|
|
|
|
use i_slint_compiler::langtype::Type;
|
|
use i_slint_core::model::Model;
|
|
use neon::prelude::*;
|
|
use std::cell::Cell;
|
|
use std::rc::{Rc, Weak};
|
|
|
|
/// Model coming from JS
|
|
pub struct JsModel {
|
|
notify: i_slint_core::model::ModelNotify,
|
|
/// The index of the value in the PersistentContext
|
|
value_index: u32,
|
|
data_type: Type,
|
|
}
|
|
|
|
impl JsModel {
|
|
pub fn new<'cx>(
|
|
obj: Handle<'cx, JsObject>,
|
|
data_type: Type,
|
|
cx: &mut impl Context<'cx>,
|
|
persistent_context: &crate::persistent_context::PersistentContext<'cx>,
|
|
) -> NeonResult<Rc<Self>> {
|
|
let val = obj.as_value(cx);
|
|
let model = Rc::new(JsModel {
|
|
notify: Default::default(),
|
|
value_index: persistent_context.allocate(cx, val),
|
|
data_type,
|
|
});
|
|
|
|
let mut notify = SlintModelNotify::new::<_, JsValue, _>(cx, std::iter::empty())?;
|
|
cx.borrow_mut(&mut notify, |mut notify| notify.0 = Rc::downgrade(&model));
|
|
let notify = notify.as_value(cx);
|
|
obj.set(cx, "notify", notify)?;
|
|
|
|
Ok(model)
|
|
}
|
|
|
|
pub fn get_object<'cx>(
|
|
&self,
|
|
cx: &mut impl Context<'cx>,
|
|
persistent_context: &crate::persistent_context::PersistentContext<'cx>,
|
|
) -> JsResult<'cx, JsObject> {
|
|
persistent_context.get(cx, self.value_index)?.downcast_or_throw(cx)
|
|
}
|
|
}
|
|
|
|
impl Model for JsModel {
|
|
type Data = slint_interpreter::Value;
|
|
|
|
fn row_count(&self) -> usize {
|
|
let r = Cell::new(0usize);
|
|
crate::run_with_global_context(&|cx, persistent_context| {
|
|
let obj = self.get_object(cx, persistent_context).unwrap();
|
|
let _ = obj
|
|
.get(cx, "rowCount")
|
|
.ok()
|
|
.and_then(|func| func.downcast::<JsFunction>().ok())
|
|
.and_then(|func| func.call(cx, obj, std::iter::empty::<Handle<JsValue>>()).ok())
|
|
.and_then(|res| res.downcast::<JsNumber>().ok())
|
|
.map(|num| r.set(num.value() as _));
|
|
});
|
|
r.get()
|
|
}
|
|
|
|
fn row_data(&self, row: usize) -> Option<Self::Data> {
|
|
if row >= self.row_count() {
|
|
None
|
|
} else {
|
|
let r = Cell::new(slint_interpreter::Value::default());
|
|
crate::run_with_global_context(&|cx, persistent_context| {
|
|
let row = JsNumber::new(cx, row as f64);
|
|
let obj = self.get_object(cx, persistent_context).unwrap();
|
|
let _ = obj
|
|
.get(cx, "rowData")
|
|
.ok()
|
|
.and_then(|func| func.downcast::<JsFunction>().ok())
|
|
.and_then(|func| func.call(cx, obj, std::iter::once(row)).ok())
|
|
.and_then(|res| {
|
|
crate::to_eval_value(res, self.data_type.clone(), cx, persistent_context)
|
|
.ok()
|
|
})
|
|
.map(|res| r.set(res));
|
|
});
|
|
Some(r.into_inner())
|
|
}
|
|
}
|
|
|
|
fn model_tracker(&self) -> &dyn i_slint_core::model::ModelTracker {
|
|
&self.notify
|
|
}
|
|
|
|
fn set_row_data(&self, row: usize, data: Self::Data) {
|
|
crate::run_with_global_context(&|cx, persistent_context| {
|
|
let row = JsNumber::new(cx, row as f64).as_value(cx);
|
|
let data = crate::to_js_value(data.clone(), cx, persistent_context).unwrap();
|
|
let obj = self.get_object(cx, persistent_context).unwrap();
|
|
let _ = obj
|
|
.get(cx, "setRowData")
|
|
.ok()
|
|
.and_then(|func| func.downcast::<JsFunction>().ok())
|
|
.and_then(|func| func.call(cx, obj, [row, data].iter().cloned()).ok());
|
|
});
|
|
}
|
|
|
|
fn as_any(&self) -> &dyn core::any::Any {
|
|
self
|
|
}
|
|
}
|
|
|
|
struct WrappedJsModel(Weak<JsModel>);
|
|
|
|
declare_types! {
|
|
class SlintModelNotify for WrappedJsModel {
|
|
init(_) {
|
|
Ok(WrappedJsModel(Weak::default()))
|
|
}
|
|
method rowDataChanged(mut cx) {
|
|
let this = cx.this();
|
|
let row = cx.argument::<JsNumber>(0)?.value() as usize;
|
|
if let Some(model) = cx.borrow(&this, |x| x.0.upgrade()) {
|
|
model.notify.row_changed(row)
|
|
}
|
|
Ok(JsUndefined::new().as_value(&mut cx))
|
|
}
|
|
method rowAdded(mut cx) {
|
|
let this = cx.this();
|
|
let row = cx.argument::<JsNumber>(0)?.value() as usize;
|
|
let count = cx.argument::<JsNumber>(1)?.value() as usize;
|
|
if let Some(model) = cx.borrow(&this, |x| x.0.upgrade()) {
|
|
model.notify.row_added(row, count)
|
|
}
|
|
Ok(JsUndefined::new().as_value(&mut cx))
|
|
}
|
|
method rowRemoved(mut cx) {
|
|
let this = cx.this();
|
|
let row = cx.argument::<JsNumber>(0)?.value() as usize;
|
|
let count = cx.argument::<JsNumber>(1)?.value() as usize;
|
|
if let Some(model) = cx.borrow(&this, |x| x.0.upgrade()) {
|
|
model.notify.row_removed(row, count)
|
|
}
|
|
Ok(JsUndefined::new().as_value(&mut cx))
|
|
}
|
|
|
|
}
|
|
|
|
}
|