mirror of
https://github.com/slint-ui/slint.git
synced 2025-11-13 17:25:27 +00:00
live-preview: Refactor Api between backend and UI
Only push basic information over the boundary in a model. The values themselves now need to be queried via `Api`. Pros: * Slint tracks the properties automatically, no more Property change tracker! Cons: * Live preview is less useful now as we can not yet provide function call results via ourr data API.
This commit is contained in:
parent
fd0f6e822a
commit
f96ce07287
5 changed files with 252 additions and 460 deletions
|
|
@ -16,7 +16,7 @@ use lsp_types::Url;
|
||||||
use slint::PlatformError;
|
use slint::PlatformError;
|
||||||
use slint_interpreter::{ComponentDefinition, ComponentHandle, ComponentInstance};
|
use slint_interpreter::{ComponentDefinition, ComponentHandle, ComponentInstance};
|
||||||
use std::borrow::BorrowMut;
|
use std::borrow::BorrowMut;
|
||||||
use std::cell::{OnceCell, RefCell};
|
use std::cell::RefCell;
|
||||||
use std::collections::{HashMap, HashSet};
|
use std::collections::{HashMap, HashSet};
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
@ -126,9 +126,6 @@ struct PreviewState {
|
||||||
workspace_edit_sent: bool,
|
workspace_edit_sent: bool,
|
||||||
known_components: Vec<ComponentInformation>,
|
known_components: Vec<ComponentInformation>,
|
||||||
preview_loading_delay_timer: Option<slint::Timer>,
|
preview_loading_delay_timer: Option<slint::Timer>,
|
||||||
property_change_tracker: OnceCell<
|
|
||||||
std::pin::Pin<Box<i_slint_core::properties::PropertyTracker<PreviewDataDirtyHandler>>>,
|
|
||||||
>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PreviewState {
|
impl PreviewState {
|
||||||
|
|
@ -935,40 +932,6 @@ fn extract_resources(
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
struct PreviewDataDirtyHandler {}
|
|
||||||
|
|
||||||
impl i_slint_core::properties::PropertyDirtyHandler for PreviewDataDirtyHandler {
|
|
||||||
fn notify(self: std::pin::Pin<&Self>) {
|
|
||||||
PREVIEW_STATE.with(|preview_state| {
|
|
||||||
let mut preview_state = preview_state.borrow_mut();
|
|
||||||
|
|
||||||
let preview_data = &track_preview_data(&mut preview_state);
|
|
||||||
|
|
||||||
if let Some(ui) = &preview_state.ui {
|
|
||||||
ui::ui_set_preview_data(ui, preview_data);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn track_preview_data(
|
|
||||||
preview_state: &mut std::cell::RefMut<PreviewState>,
|
|
||||||
) -> HashMap<preview_data::PropertyContainer, Vec<preview_data::PreviewData>> {
|
|
||||||
let Some(component_instance) = preview_state.component_instance() else {
|
|
||||||
return Default::default();
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut tracker = preview_state.property_change_tracker.get_or_init(move || {
|
|
||||||
Box::pin(i_slint_core::properties::PropertyTracker::new_with_dirty_handler(
|
|
||||||
PreviewDataDirtyHandler {},
|
|
||||||
))
|
|
||||||
});
|
|
||||||
|
|
||||||
tracker.borrow_mut().as_ref().evaluate_as_dependency_root(|| {
|
|
||||||
preview_data::query_preview_data_properties_and_callbacks(&component_instance)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fn finish_parsing(preview_url: &Url) {
|
fn finish_parsing(preview_url: &Url) {
|
||||||
set_status_text("");
|
set_status_text("");
|
||||||
|
|
||||||
|
|
@ -1039,12 +1002,17 @@ fn finish_parsing(preview_url: &Url) {
|
||||||
|
|
||||||
preview_state.document_cache.borrow_mut().replace(Some(Rc::new(document_cache)));
|
preview_state.document_cache.borrow_mut().replace(Some(Rc::new(document_cache)));
|
||||||
|
|
||||||
let preview_data = track_preview_data(&mut preview_state);
|
let preview_data = preview_state
|
||||||
|
.component_instance()
|
||||||
|
.map(|component_instance| {
|
||||||
|
preview_data::query_preview_data_properties_and_callbacks(&component_instance)
|
||||||
|
})
|
||||||
|
.unwrap_or_default();
|
||||||
|
|
||||||
if let Some(ui) = &preview_state.ui {
|
if let Some(ui) = &preview_state.ui {
|
||||||
ui::ui_set_uses_widgets(ui, uses_widgets);
|
ui::ui_set_uses_widgets(ui, uses_widgets);
|
||||||
ui::ui_set_known_components(ui, &preview_state.known_components, index);
|
ui::ui_set_known_components(ui, &preview_state.known_components, index);
|
||||||
ui::ui_set_preview_data(ui, &preview_data);
|
ui::ui_set_preview_data(ui, preview_data);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -67,6 +67,46 @@ impl PreviewData {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_preview_data(
|
||||||
|
component_instance: &ComponentInstance,
|
||||||
|
container: PropertyContainer,
|
||||||
|
property_name: String,
|
||||||
|
) -> Option<PreviewData> {
|
||||||
|
fn find_preview_data(
|
||||||
|
property_name: &str,
|
||||||
|
mut it: impl Iterator<
|
||||||
|
Item = (
|
||||||
|
String,
|
||||||
|
(
|
||||||
|
i_slint_compiler::langtype::Type,
|
||||||
|
i_slint_compiler::object_tree::PropertyVisibility,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
>,
|
||||||
|
value_query: &dyn Fn(&str) -> Option<slint_interpreter::Value>,
|
||||||
|
) -> Option<PreviewData> {
|
||||||
|
it.find(|(name, (_, _))| name == property_name).map(|(name, (ty, visibility))| {
|
||||||
|
let value = value_query(&name);
|
||||||
|
|
||||||
|
PreviewData { name, ty, visibility, value }
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
let definition = &component_instance.definition();
|
||||||
|
match &container {
|
||||||
|
PropertyContainer::Main => {
|
||||||
|
find_preview_data(&property_name, &mut definition.properties_and_callbacks(), &|name| {
|
||||||
|
component_instance.get_property(name).ok()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
PropertyContainer::Global(g) => find_preview_data(
|
||||||
|
&property_name,
|
||||||
|
&mut definition.global_properties_and_callbacks(g)?,
|
||||||
|
&|name| component_instance.get_global_property(g, name).ok(),
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn query_preview_data_properties_and_callbacks(
|
pub fn query_preview_data_properties_and_callbacks(
|
||||||
component_instance: &ComponentInstance,
|
component_instance: &ComponentInstance,
|
||||||
) -> HashMap<PropertyContainer, Vec<PreviewData>> {
|
) -> HashMap<PropertyContainer, Vec<PreviewData>> {
|
||||||
|
|
@ -147,38 +187,6 @@ fn find_component_properties_and_callbacks<'a>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_preview_data(
|
|
||||||
component_instance: &ComponentInstance,
|
|
||||||
container: PropertyContainer,
|
|
||||||
property_name: String,
|
|
||||||
values: Vec<Vec<String>>,
|
|
||||||
) -> Result<(), String> {
|
|
||||||
let definition = &component_instance.definition();
|
|
||||||
|
|
||||||
let (_, (ty, _)) = find_component_properties_and_callbacks(definition, &container)?
|
|
||||||
.find(|(name, (_, _))| name == &property_name)
|
|
||||||
.ok_or_else(|| {
|
|
||||||
format!("Property name {property_name} not found on component {container}")
|
|
||||||
})?;
|
|
||||||
|
|
||||||
if values.len() == 1 && values[0].len() == 1 {
|
|
||||||
let json_value: serde_json::Value = serde_json::from_str(&values[0][0])
|
|
||||||
.map_err(|e| format!("Failed to read value as JSON: {e}"))?;
|
|
||||||
let value = slint_interpreter::json::value_from_json(&ty, &json_value)?;
|
|
||||||
|
|
||||||
match &container {
|
|
||||||
PropertyContainer::Main => component_instance
|
|
||||||
.set_property(&property_name, value)
|
|
||||||
.map_err(|e| format!("Failed to set property: {e}"))?,
|
|
||||||
PropertyContainer::Global(g) => component_instance
|
|
||||||
.set_global_property(g, &property_name, value)
|
|
||||||
.map_err(|e| format!("Failed to set global property: {e}"))?,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_json_preview_data(
|
pub fn set_json_preview_data(
|
||||||
component_instance: &ComponentInstance,
|
component_instance: &ComponentInstance,
|
||||||
container: PropertyContainer,
|
container: PropertyContainer,
|
||||||
|
|
|
||||||
|
|
@ -97,7 +97,7 @@ pub fn create_ui(style: String, experimental: bool) -> Result<PreviewUi, Platfor
|
||||||
api.on_set_color_binding(super::set_color_binding);
|
api.on_set_color_binding(super::set_color_binding);
|
||||||
api.on_property_declaration_ranges(super::property_declaration_ranges);
|
api.on_property_declaration_ranges(super::property_declaration_ranges);
|
||||||
|
|
||||||
api.on_set_preview_data(set_preview_data);
|
api.on_get_property_value(get_property_value);
|
||||||
api.on_set_json_preview_data(set_json_preview_data);
|
api.on_set_json_preview_data(set_json_preview_data);
|
||||||
|
|
||||||
api.on_string_to_code(string_to_code);
|
api.on_string_to_code(string_to_code);
|
||||||
|
|
@ -794,16 +794,12 @@ fn update_grouped_properties(
|
||||||
to_do.push(Op::Remove(c_index));
|
to_do.push(Op::Remove(c_index));
|
||||||
cp = c_it.next();
|
cp = c_it.next();
|
||||||
}
|
}
|
||||||
(Some(c), Some(n)) => {
|
(Some(c), Some(n)) => match c.name.cmp(&n.name) {
|
||||||
if c.name < n.name {
|
std::cmp::Ordering::Less => {
|
||||||
to_do.push(Op::Remove(c_index));
|
to_do.push(Op::Remove(c_index));
|
||||||
cp = c_it.next();
|
cp = c_it.next();
|
||||||
} else if c.name > n.name {
|
}
|
||||||
to_do.push(Op::Insert((c_index, n_index)));
|
std::cmp::Ordering::Equal => {
|
||||||
c_index += 1;
|
|
||||||
n_index += 1;
|
|
||||||
np = n_it.next();
|
|
||||||
} else {
|
|
||||||
if !is_equal_property(c, n) {
|
if !is_equal_property(c, n) {
|
||||||
to_do.push(Op::Copy((c_index, n_index)));
|
to_do.push(Op::Copy((c_index, n_index)));
|
||||||
}
|
}
|
||||||
|
|
@ -812,7 +808,13 @@ fn update_grouped_properties(
|
||||||
cp = c_it.next();
|
cp = c_it.next();
|
||||||
np = n_it.next();
|
np = n_it.next();
|
||||||
}
|
}
|
||||||
|
std::cmp::Ordering::Greater => {
|
||||||
|
to_do.push(Op::Insert((c_index, n_index)));
|
||||||
|
c_index += 1;
|
||||||
|
n_index += 1;
|
||||||
|
np = n_it.next();
|
||||||
}
|
}
|
||||||
|
},
|
||||||
(None, Some(_)) => {
|
(None, Some(_)) => {
|
||||||
to_do.push(Op::PushBack(n_index));
|
to_do.push(Op::PushBack(n_index));
|
||||||
n_index += 1;
|
n_index += 1;
|
||||||
|
|
@ -1030,51 +1032,44 @@ fn map_value_and_type(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn map_preview_data_property(rp: &preview_data::PreviewData) -> Option<PreviewData> {
|
fn map_preview_data_to_property_value(
|
||||||
if !rp.is_property() {
|
preview_data: &preview_data::PreviewData,
|
||||||
|
) -> Option<PropertyValue> {
|
||||||
|
let mut mapping = ValueMapping::default();
|
||||||
|
map_value_and_type(&preview_data.ty, &preview_data.value, &mut mapping);
|
||||||
|
mapping.array_values.first().and_then(|av| av.first()).cloned()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn map_preview_data_property(preview_data: &preview_data::PreviewData) -> Option<PreviewData> {
|
||||||
|
if !preview_data.is_property() {
|
||||||
return None;
|
return None;
|
||||||
};
|
};
|
||||||
|
|
||||||
let has_getter = rp.has_getter();
|
let has_getter = preview_data.has_getter();
|
||||||
let has_setter = rp.has_setter();
|
let has_setter = preview_data.has_setter();
|
||||||
|
|
||||||
let mut mapping = ValueMapping::default();
|
let mut mapping = ValueMapping::default();
|
||||||
map_value_and_type(&rp.ty, &rp.value, &mut mapping);
|
map_value_and_type(&preview_data.ty, &preview_data.value, &mut mapping);
|
||||||
|
|
||||||
let array_values = mapping
|
|
||||||
.array_values
|
|
||||||
.drain(..)
|
|
||||||
.map(|v| Rc::new(slint::VecModel::from(v)).into())
|
|
||||||
.collect::<Vec<slint::ModelRc<_>>>();
|
|
||||||
let array_values = Rc::new(slint::VecModel::from(array_values)).into();
|
|
||||||
|
|
||||||
Some(PreviewData {
|
Some(PreviewData {
|
||||||
name: rp.name.clone().into(),
|
name: preview_data.name.clone().into(),
|
||||||
has_getter,
|
has_getter,
|
||||||
has_setter,
|
has_setter,
|
||||||
prefer_json: mapping.is_too_complex,
|
kind: if mapping.is_too_complex { PreviewDataKind::Json } else { PreviewDataKind::Value },
|
||||||
is_array: mapping.is_array,
|
|
||||||
header: Rc::new(VecModel::from(
|
|
||||||
mapping.header.drain(..).map(slint::SharedString::from).collect::<Vec<_>>(),
|
|
||||||
))
|
|
||||||
.into(),
|
|
||||||
array_values,
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn ui_set_preview_data(
|
pub fn ui_set_preview_data(
|
||||||
ui: &PreviewUi,
|
ui: &PreviewUi,
|
||||||
preview_data: &HashMap<preview_data::PropertyContainer, Vec<preview_data::PreviewData>>,
|
preview_data: HashMap<preview_data::PropertyContainer, Vec<preview_data::PreviewData>>,
|
||||||
) {
|
) {
|
||||||
let mut result: Vec<PropertyContainer> = vec![];
|
|
||||||
|
|
||||||
fn fill_container(
|
fn fill_container(
|
||||||
container_name: String,
|
container_name: String,
|
||||||
container_id: String,
|
container_id: String,
|
||||||
properties: &[preview_data::PreviewData],
|
properties: &[preview_data::PreviewData],
|
||||||
) -> Option<PropertyContainer> {
|
) -> Option<PropertyContainer> {
|
||||||
let properties =
|
let properties =
|
||||||
properties.iter().filter_map(|rp| map_preview_data_property(rp)).collect::<Vec<_>>();
|
properties.iter().filter_map(map_preview_data_property).collect::<Vec<_>>();
|
||||||
|
|
||||||
(!properties.is_empty()).then(|| PropertyContainer {
|
(!properties.is_empty()).then(|| PropertyContainer {
|
||||||
container_name: container_name.into(),
|
container_name: container_name.into(),
|
||||||
|
|
@ -1083,11 +1078,14 @@ pub fn ui_set_preview_data(
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let mut result: Vec<PropertyContainer> = vec![];
|
||||||
|
|
||||||
if let Some(main) = preview_data.get(&preview_data::PropertyContainer::Main) {
|
if let Some(main) = preview_data.get(&preview_data::PropertyContainer::Main) {
|
||||||
if let Some(c) = fill_container("<MAIN>".to_string(), String::new(), main) {
|
if let Some(c) = fill_container("<MAIN>".to_string(), String::new(), main) {
|
||||||
result.push(c)
|
result.push(c)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for component_key in
|
for component_key in
|
||||||
preview_data.keys().filter(|k| **k != preview_data::PropertyContainer::Main)
|
preview_data.keys().filter(|k| **k != preview_data::PropertyContainer::Main)
|
||||||
{
|
{
|
||||||
|
|
@ -1101,85 +1099,31 @@ pub fn ui_set_preview_data(
|
||||||
|
|
||||||
let api = ui.global::<Api>();
|
let api = ui.global::<Api>();
|
||||||
|
|
||||||
let mut old_model = api.get_preview_data();
|
let old_model = api.get_preview_data();
|
||||||
|
|
||||||
fn update_model(
|
fn update_model(
|
||||||
old_model: &mut slint::ModelRc<PropertyContainer>,
|
old_model: &slint::ModelRc<PropertyContainer>,
|
||||||
new_model: Vec<PropertyContainer>,
|
new_model: &[PropertyContainer],
|
||||||
) -> Option<slint::ModelRc<PropertyContainer>> {
|
) -> bool {
|
||||||
// The structure should never change as the API between business logic and UI should be pretty
|
|
||||||
// fixed.
|
|
||||||
|
|
||||||
fn m(model: Vec<PropertyContainer>) -> Option<slint::ModelRc<PropertyContainer>> {
|
|
||||||
Some(Rc::new(VecModel::from(model)).into())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn is_semantic_equal(o: &PreviewData, n: &PreviewData) -> bool {
|
|
||||||
if o.name != n.name
|
|
||||||
|| o.has_getter != n.has_getter
|
|
||||||
|| o.has_setter != n.has_setter
|
|
||||||
|| o.is_array != n.is_array
|
|
||||||
|| o.prefer_json != n.prefer_json
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if o.header.row_count() != n.header.row_count() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
for (oh, nh) in o.header.iter().zip(n.header.iter()) {
|
|
||||||
if oh != nh {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if o.array_values.row_count() != n.array_values.row_count() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
for (oav, nav) in o.array_values.iter().zip(n.array_values.iter()) {
|
|
||||||
if oav.row_count() != nav.row_count() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (oavv, navv) in oav.iter().zip(nav.iter()) {
|
|
||||||
if oavv != navv {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
true
|
|
||||||
}
|
|
||||||
|
|
||||||
if old_model.row_count() != new_model.len() {
|
if old_model.row_count() != new_model.len() {
|
||||||
return m(new_model);
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (oc, nc) in old_model.iter().zip(new_model.iter()) {
|
for (oc, nc) in old_model.iter().zip(new_model.iter()) {
|
||||||
if oc.container_name != nc.container_name
|
if oc.container_name != nc.container_name
|
||||||
|| oc.container_id != nc.container_id
|
|| oc.container_id != nc.container_id
|
||||||
|| oc.properties.row_count() != nc.properties.row_count()
|
|| oc.properties.row_count() != nc.properties.row_count()
|
||||||
|
|| oc.properties.iter().zip(nc.properties.iter()).any(|(o, n)| o != n)
|
||||||
{
|
{
|
||||||
return m(new_model);
|
return true;
|
||||||
}
|
|
||||||
|
|
||||||
let mut to_replace = oc
|
|
||||||
.properties
|
|
||||||
.iter()
|
|
||||||
.zip(nc.properties.iter())
|
|
||||||
.enumerate()
|
|
||||||
.filter_map(|(i, (o, n))| (!is_semantic_equal(&o, &n)).then_some((i, n)))
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
|
|
||||||
for (i, n) in to_replace.drain(..) {
|
|
||||||
oc.properties.set_row_data(i, n);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
None
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(m) = update_model(&mut old_model, result) {
|
if update_model(&old_model, &result) {
|
||||||
api.set_preview_data(m);
|
api.set_preview_data(Rc::new(VecModel::from(result)).into());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1191,60 +1135,45 @@ fn to_property_container(container: slint::SharedString) -> preview_data::Proper
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_preview_data(
|
fn get_property_value(container: SharedString, property_name: SharedString) -> PropertyValue {
|
||||||
container: SharedString,
|
preview::component_instance()
|
||||||
property_name: SharedString,
|
.and_then(|component_instance| {
|
||||||
model: slint::ModelRc<slint::ModelRc<PropertyValue>>,
|
preview_data::get_preview_data(
|
||||||
) -> bool {
|
|
||||||
if model.row_count() == 0 || property_name.is_empty() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
let values = model
|
|
||||||
.iter()
|
|
||||||
.map(|r| {
|
|
||||||
r.iter()
|
|
||||||
.map(|c| if c.was_edited { c.edited_value.to_string() } else { c.code.to_string() })
|
|
||||||
.collect::<Vec<_>>()
|
|
||||||
})
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
|
|
||||||
if let Some(component_instance) = preview::component_instance() {
|
|
||||||
preview_data::set_preview_data(
|
|
||||||
&component_instance,
|
&component_instance,
|
||||||
to_property_container(container),
|
to_property_container(container),
|
||||||
property_name.to_string(),
|
property_name.to_string(),
|
||||||
values,
|
|
||||||
)
|
)
|
||||||
.is_ok()
|
})
|
||||||
} else {
|
.and_then(|pd| map_preview_data_to_property_value(&pd))
|
||||||
false
|
.unwrap_or_else(Default::default)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_json_preview_data(
|
fn set_json_preview_data(
|
||||||
container: SharedString,
|
container: SharedString,
|
||||||
property_name: SharedString,
|
property_name: SharedString,
|
||||||
json_string: SharedString,
|
json_string: SharedString,
|
||||||
) {
|
) -> bool {
|
||||||
let property_name = (!property_name.is_empty()).then_some(property_name.to_string());
|
let property_name = (!property_name.is_empty()).then_some(property_name.to_string());
|
||||||
|
|
||||||
let Ok(json) = serde_json::from_str::<serde_json::Value>(&json_string.to_string()) else {
|
let Ok(json) = serde_json::from_str::<serde_json::Value>(json_string.as_ref()) else {
|
||||||
return;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
if property_name.is_none() && !json.is_object() {
|
if property_name.is_none() && !json.is_object() {
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(component_instance) = preview::component_instance() {
|
preview::component_instance()
|
||||||
let _ = preview_data::set_json_preview_data(
|
.and_then(|component_instance| {
|
||||||
|
preview_data::set_json_preview_data(
|
||||||
&component_instance,
|
&component_instance,
|
||||||
to_property_container(container),
|
to_property_container(container),
|
||||||
property_name,
|
property_name,
|
||||||
json,
|
json,
|
||||||
);
|
)
|
||||||
};
|
.ok()
|
||||||
|
})
|
||||||
|
.is_some()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_properties(
|
fn update_properties(
|
||||||
|
|
@ -1309,7 +1238,7 @@ mod tests {
|
||||||
|
|
||||||
use i_slint_core::model::Model;
|
use i_slint_core::model::Model;
|
||||||
|
|
||||||
use super::{map_preview_data_property, PropertyInformation, PropertyValue, PropertyValueKind};
|
use super::{PropertyInformation, PropertyValue, PropertyValueKind};
|
||||||
|
|
||||||
fn properties_at_position(
|
fn properties_at_position(
|
||||||
source: &str,
|
source: &str,
|
||||||
|
|
@ -1945,46 +1874,23 @@ export component Tester {{
|
||||||
type_def: &str,
|
type_def: &str,
|
||||||
type_name: &str,
|
type_name: &str,
|
||||||
code: &str,
|
code: &str,
|
||||||
expected: super::PreviewData,
|
expected_data: super::PreviewData,
|
||||||
|
expected_value: super::PropertyValue,
|
||||||
) {
|
) {
|
||||||
let rp = generate_preview_data(visibility, type_def, type_name, code);
|
let raw_data = generate_preview_data(visibility, type_def, type_name, code);
|
||||||
|
|
||||||
let rp = map_preview_data_property(&rp).unwrap();
|
let rp = super::map_preview_data_property(&raw_data).unwrap();
|
||||||
|
|
||||||
eprintln!("*** Validating PreviewData: Received: {rp:?}");
|
eprintln!("*** Validating PreviewData: Received: {rp:?}");
|
||||||
eprintln!("*** Validating PreviewData: Expected: {expected:?}");
|
eprintln!("*** Validating PreviewData: Expected: {expected_data:?}");
|
||||||
|
|
||||||
assert_eq!(rp.name, expected.name);
|
assert_eq!(rp.name, expected_data.name);
|
||||||
assert_eq!(rp.has_getter, expected.has_getter);
|
assert_eq!(rp.has_getter, expected_data.has_getter);
|
||||||
assert_eq!(rp.has_setter, expected.has_setter);
|
assert_eq!(rp.has_setter, expected_data.has_setter);
|
||||||
assert_eq!(rp.is_array, expected.is_array);
|
assert_eq!(rp.kind, expected_data.kind);
|
||||||
assert_eq!(rp.prefer_json, expected.prefer_json);
|
|
||||||
|
|
||||||
eprintln!("*** Basic properties all match, looking at values next...");
|
let pv = super::map_preview_data_to_property_value(&raw_data).unwrap();
|
||||||
|
compare_pv(&pv, &expected_value);
|
||||||
eprintln!("*** Headers: Received:");
|
|
||||||
for h in rp.header.iter() {
|
|
||||||
eprintln!("*** {h}.");
|
|
||||||
}
|
|
||||||
eprintln!("*** Headers: Expected:");
|
|
||||||
for h in expected.header.iter() {
|
|
||||||
eprintln!("*** {h}.");
|
|
||||||
}
|
|
||||||
|
|
||||||
assert_eq!(rp.header.row_count(), expected.header.row_count());
|
|
||||||
for (r, e) in rp.header.iter().zip(expected.header.iter()) {
|
|
||||||
assert_eq!(r, e);
|
|
||||||
}
|
|
||||||
|
|
||||||
eprintln!("*** Values all match, looking at array_values next...");
|
|
||||||
|
|
||||||
assert_eq!(rp.array_values.row_count(), expected.array_values.row_count());
|
|
||||||
for (rr, er) in rp.array_values.iter().zip(expected.array_values.iter()) {
|
|
||||||
assert_eq!(rr.row_count(), er.row_count());
|
|
||||||
for (e, r) in rr.iter().zip(er.iter()) {
|
|
||||||
compare_pv(&r, &e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
@ -1997,18 +1903,14 @@ export component Tester {{
|
||||||
super::PreviewData {
|
super::PreviewData {
|
||||||
name: "test".into(),
|
name: "test".into(),
|
||||||
has_setter: true,
|
has_setter: true,
|
||||||
header: std::rc::Rc::new(slint::VecModel::from(vec!["".into()])).into(),
|
kind: super::PreviewDataKind::Value,
|
||||||
array_values: std::rc::Rc::new(slint::VecModel::from(vec![std::rc::Rc::new(
|
..Default::default()
|
||||||
slint::VecModel::from(vec![super::PropertyValue {
|
},
|
||||||
|
super::PropertyValue {
|
||||||
code: "\"Test\"".into(),
|
code: "\"Test\"".into(),
|
||||||
kind: super::PropertyValueKind::String,
|
kind: super::PropertyValueKind::String,
|
||||||
value_string: "Test".into(),
|
value_string: "Test".into(),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}]),
|
|
||||||
)
|
|
||||||
.into()]))
|
|
||||||
.into(),
|
|
||||||
..Default::default()
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -2023,9 +1925,10 @@ export component Tester {{
|
||||||
super::PreviewData {
|
super::PreviewData {
|
||||||
name: "test".into(),
|
name: "test".into(),
|
||||||
has_setter: true,
|
has_setter: true,
|
||||||
header: std::rc::Rc::new(slint::VecModel::from(vec!["".into()])).into(),
|
kind: super::PreviewDataKind::Value,
|
||||||
array_values: std::rc::Rc::new(slint::VecModel::from(vec![std::rc::Rc::new(
|
..Default::default()
|
||||||
slint::VecModel::from(vec![super::PropertyValue {
|
},
|
||||||
|
super::PropertyValue {
|
||||||
code: "100".into(),
|
code: "100".into(),
|
||||||
kind: super::PropertyValueKind::Float,
|
kind: super::PropertyValueKind::Float,
|
||||||
value_float: 100.0,
|
value_float: 100.0,
|
||||||
|
|
@ -2041,11 +1944,6 @@ export component Tester {{
|
||||||
]))
|
]))
|
||||||
.into(),
|
.into(),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}]),
|
|
||||||
)
|
|
||||||
.into()]))
|
|
||||||
.into(),
|
|
||||||
..Default::default()
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -2060,9 +1958,10 @@ export component Tester {{
|
||||||
super::PreviewData {
|
super::PreviewData {
|
||||||
name: "test".into(),
|
name: "test".into(),
|
||||||
has_setter: true,
|
has_setter: true,
|
||||||
header: std::rc::Rc::new(slint::VecModel::from(vec!["".into()])).into(),
|
kind: super::PreviewDataKind::Value,
|
||||||
array_values: std::rc::Rc::new(slint::VecModel::from(vec![std::rc::Rc::new(
|
..Default::default()
|
||||||
slint::VecModel::from(vec![super::PropertyValue {
|
},
|
||||||
|
super::PropertyValue {
|
||||||
code: "100000".into(),
|
code: "100000".into(),
|
||||||
kind: super::PropertyValueKind::Float,
|
kind: super::PropertyValueKind::Float,
|
||||||
value_float: 100000.0,
|
value_float: 100000.0,
|
||||||
|
|
@ -2074,11 +1973,6 @@ export component Tester {{
|
||||||
.into(),
|
.into(),
|
||||||
default_selection: 1,
|
default_selection: 1,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}]),
|
|
||||||
)
|
|
||||||
.into()]))
|
|
||||||
.into(),
|
|
||||||
..Default::default()
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -2093,9 +1987,10 @@ export component Tester {{
|
||||||
super::PreviewData {
|
super::PreviewData {
|
||||||
name: "test".into(),
|
name: "test".into(),
|
||||||
has_setter: true,
|
has_setter: true,
|
||||||
header: std::rc::Rc::new(slint::VecModel::from(vec!["".into()])).into(),
|
kind: super::PreviewDataKind::Value,
|
||||||
array_values: std::rc::Rc::new(slint::VecModel::from(vec![std::rc::Rc::new(
|
..Default::default()
|
||||||
slint::VecModel::from(vec![super::PropertyValue {
|
},
|
||||||
|
super::PropertyValue {
|
||||||
code: "36000".into(),
|
code: "36000".into(),
|
||||||
kind: super::PropertyValueKind::Float,
|
kind: super::PropertyValueKind::Float,
|
||||||
value_float: 36000.0,
|
value_float: 36000.0,
|
||||||
|
|
@ -2108,11 +2003,6 @@ export component Tester {{
|
||||||
]))
|
]))
|
||||||
.into(),
|
.into(),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}]),
|
|
||||||
)
|
|
||||||
.into()]))
|
|
||||||
.into(),
|
|
||||||
..Default::default()
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -2127,20 +2017,15 @@ export component Tester {{
|
||||||
super::PreviewData {
|
super::PreviewData {
|
||||||
name: "test".into(),
|
name: "test".into(),
|
||||||
has_setter: true,
|
has_setter: true,
|
||||||
header: std::rc::Rc::new(slint::VecModel::from(vec!["".into()])).into(),
|
kind: super::PreviewDataKind::Value,
|
||||||
array_values: std::rc::Rc::new(slint::VecModel::from(vec![std::rc::Rc::new(
|
..Default::default()
|
||||||
slint::VecModel::from(vec![super::PropertyValue {
|
},
|
||||||
|
super::PropertyValue {
|
||||||
code: "10".into(),
|
code: "10".into(),
|
||||||
kind: super::PropertyValueKind::Float,
|
kind: super::PropertyValueKind::Float,
|
||||||
value_float: 10.0,
|
value_float: 10.0,
|
||||||
value_string: "10%".into(),
|
value_string: "10%".into(),
|
||||||
visual_items: std::rc::Rc::new(slint::VecModel::from(vec!["%".into()]))
|
visual_items: std::rc::Rc::new(slint::VecModel::from(vec!["%".into()])).into(),
|
||||||
.into(),
|
|
||||||
..Default::default()
|
|
||||||
}]),
|
|
||||||
)
|
|
||||||
.into()]))
|
|
||||||
.into(),
|
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
@ -2156,9 +2041,10 @@ export component Tester {{
|
||||||
super::PreviewData {
|
super::PreviewData {
|
||||||
name: "test".into(),
|
name: "test".into(),
|
||||||
has_setter: true,
|
has_setter: true,
|
||||||
header: std::rc::Rc::new(slint::VecModel::from(vec!["".into()])).into(),
|
kind: super::PreviewDataKind::Value,
|
||||||
array_values: std::rc::Rc::new(slint::VecModel::from(vec![std::rc::Rc::new(
|
..Default::default()
|
||||||
slint::VecModel::from(vec![super::PropertyValue {
|
},
|
||||||
|
super::PropertyValue {
|
||||||
code: "\"#aabbccff\"".into(),
|
code: "\"#aabbccff\"".into(),
|
||||||
kind: super::PropertyValueKind::Color,
|
kind: super::PropertyValueKind::Color,
|
||||||
value_string: "#aabbccff".into(),
|
value_string: "#aabbccff".into(),
|
||||||
|
|
@ -2166,11 +2052,6 @@ export component Tester {{
|
||||||
0xff, 0xaa, 0xbb, 0xcc,
|
0xff, 0xaa, 0xbb, 0xcc,
|
||||||
)),
|
)),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}]),
|
|
||||||
)
|
|
||||||
.into()]))
|
|
||||||
.into(),
|
|
||||||
..Default::default()
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -2185,19 +2066,15 @@ export component Tester {{
|
||||||
super::PreviewData {
|
super::PreviewData {
|
||||||
name: "test".into(),
|
name: "test".into(),
|
||||||
has_setter: true,
|
has_setter: true,
|
||||||
header: std::rc::Rc::new(slint::VecModel::from(vec!["".into()])).into(),
|
kind: super::PreviewDataKind::Value,
|
||||||
array_values: std::rc::Rc::new(slint::VecModel::from(vec![std::rc::Rc::new(
|
..Default::default()
|
||||||
slint::VecModel::from(vec![super::PropertyValue {
|
},
|
||||||
|
super::PropertyValue {
|
||||||
code: "12".into(),
|
code: "12".into(),
|
||||||
kind: super::PropertyValueKind::Integer,
|
kind: super::PropertyValueKind::Integer,
|
||||||
value_string: "12".into(),
|
value_string: "12".into(),
|
||||||
value_int: 12,
|
value_int: 12,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}]),
|
|
||||||
)
|
|
||||||
.into()]))
|
|
||||||
.into(),
|
|
||||||
..Default::default()
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -2212,19 +2089,15 @@ export component Tester {{
|
||||||
super::PreviewData {
|
super::PreviewData {
|
||||||
name: "test".into(),
|
name: "test".into(),
|
||||||
has_getter: true,
|
has_getter: true,
|
||||||
header: std::rc::Rc::new(slint::VecModel::from(vec!["".into()])).into(),
|
kind: super::PreviewDataKind::Value,
|
||||||
array_values: std::rc::Rc::new(slint::VecModel::from(vec![std::rc::Rc::new(
|
..Default::default()
|
||||||
slint::VecModel::from(vec![super::PropertyValue {
|
},
|
||||||
|
super::PropertyValue {
|
||||||
code: "true".into(),
|
code: "true".into(),
|
||||||
kind: super::PropertyValueKind::Boolean,
|
kind: super::PropertyValueKind::Boolean,
|
||||||
value_string: "true".into(),
|
value_string: "true".into(),
|
||||||
value_bool: true,
|
value_bool: true,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}]),
|
|
||||||
)
|
|
||||||
.into()]))
|
|
||||||
.into(),
|
|
||||||
..Default::default()
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -2240,19 +2113,15 @@ export component Tester {{
|
||||||
name: "test".into(),
|
name: "test".into(),
|
||||||
has_getter: true,
|
has_getter: true,
|
||||||
has_setter: true,
|
has_setter: true,
|
||||||
header: std::rc::Rc::new(slint::VecModel::from(vec!["".into()])).into(),
|
kind: super::PreviewDataKind::Value,
|
||||||
array_values: std::rc::Rc::new(slint::VecModel::from(vec![std::rc::Rc::new(
|
..Default::default()
|
||||||
slint::VecModel::from(vec![super::PropertyValue {
|
},
|
||||||
|
super::PropertyValue {
|
||||||
code: "false".into(),
|
code: "false".into(),
|
||||||
kind: super::PropertyValueKind::Boolean,
|
kind: super::PropertyValueKind::Boolean,
|
||||||
value_string: "false".into(),
|
value_string: "false".into(),
|
||||||
value_bool: false,
|
value_bool: false,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}]),
|
|
||||||
)
|
|
||||||
.into()]))
|
|
||||||
.into(),
|
|
||||||
..Default::default()
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -2270,16 +2139,13 @@ export component Tester {{
|
||||||
name: "test".into(),
|
name: "test".into(),
|
||||||
has_getter: true,
|
has_getter: true,
|
||||||
has_setter: true,
|
has_setter: true,
|
||||||
prefer_json: true,
|
kind: super::PreviewDataKind::Json,
|
||||||
header: std::rc::Rc::new(slint::VecModel::from(vec!["".into()])).into(),
|
|
||||||
array_values: std::rc::Rc::new(slint::VecModel::from(vec![std::rc::Rc::new(
|
|
||||||
slint::VecModel::from(vec![super::PropertyValue {
|
|
||||||
kind: super::PropertyValueKind::Code,
|
|
||||||
code: "{\n \"first\": [\n \"first of a kind\",\n \"second of a kind\"\n ]\n}".into(),
|
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
])).into(),
|
super::PropertyValue {
|
||||||
]))
|
kind: super::PropertyValueKind::Code,
|
||||||
|
code:
|
||||||
|
"{\n \"first\": [\n \"first of a kind\",\n \"second of a kind\"\n ]\n}"
|
||||||
.into(),
|
.into(),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -166,14 +166,16 @@ export struct PropertyGroup {
|
||||||
properties: [PropertyInformation],
|
properties: [PropertyInformation],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export enum PreviewDataKind {
|
||||||
|
Value,
|
||||||
|
Json,
|
||||||
|
}
|
||||||
|
|
||||||
export struct PreviewData {
|
export struct PreviewData {
|
||||||
name: string,
|
name: string,
|
||||||
has-getter: bool,
|
has-getter: bool,
|
||||||
has-setter: bool,
|
has-setter: bool,
|
||||||
is-array: bool,
|
kind: PreviewDataKind,
|
||||||
prefer-json: bool,
|
|
||||||
header: [string], // "Simple" values + table headers
|
|
||||||
array-values: [[PropertyValue]], // The "Table values"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Information on exported components and their properties
|
/// Information on exported components and their properties
|
||||||
|
|
@ -406,54 +408,7 @@ export global Api {
|
||||||
|
|
||||||
// ## preview data
|
// ## preview data
|
||||||
|
|
||||||
in-out property <[PropertyContainer]> preview-data: [
|
in-out property <[PropertyContainer]> preview-data;
|
||||||
{
|
|
||||||
container-name: "Fruits",
|
|
||||||
properties: [
|
|
||||||
{
|
|
||||||
name: "AppleSetter",
|
|
||||||
has-getter: false,
|
|
||||||
has-setter: true,
|
|
||||||
is-array: false,
|
|
||||||
prefer-json: false,
|
|
||||||
header: [ "" ],
|
|
||||||
array-values: [[{
|
|
||||||
kind: PropertyValueKind.boolean,
|
|
||||||
value-bool: true,
|
|
||||||
}]],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "BananaGetter",
|
|
||||||
has-getter: true,
|
|
||||||
has-setter: true,
|
|
||||||
is-array: false,
|
|
||||||
prefer-json: true,
|
|
||||||
header: [ "fruit" ],
|
|
||||||
array-values: [[{
|
|
||||||
kind: PropertyValueKind.code,
|
|
||||||
code: "{\n json: true\n}"
|
|
||||||
}]]
|
|
||||||
},
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
container-name: "Vegetables",
|
|
||||||
properties: [
|
|
||||||
{
|
|
||||||
name: "Cucumber",
|
|
||||||
has-getter: true,
|
|
||||||
has-setter: true,
|
|
||||||
is-array: false,
|
|
||||||
prefer-json: false,
|
|
||||||
header: [ "" ],
|
|
||||||
array-values: [[{
|
|
||||||
kind: PropertyValueKind.string,
|
|
||||||
value-string: "a green banana",
|
|
||||||
}]],
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
// # Callbacks
|
// # Callbacks
|
||||||
|
|
||||||
|
|
@ -517,8 +472,9 @@ export global Api {
|
||||||
pure callback string-to-code(value: string, is_translatable: bool, tr_context: string, tr_plural: string, tr_plural_expression: string) -> string;
|
pure callback string-to-code(value: string, is_translatable: bool, tr_context: string, tr_plural: string, tr_plural_expression: string) -> string;
|
||||||
|
|
||||||
// ## preview data
|
// ## preview data
|
||||||
callback set-preview-data(component: string, name: string, raw-json-array-values: [[PropertyValue]]) -> bool;
|
pure callback get-property-value(component: string, name: string) -> PropertyValue;
|
||||||
callback set-json-preview-data(component: string, name: string, json-value: string);
|
|
||||||
|
callback set-json-preview-data(component: string, name: string, json-value: string) -> bool;
|
||||||
|
|
||||||
// Get the property declaration/definition ranges
|
// Get the property declaration/definition ranges
|
||||||
callback property-declaration-ranges(property-name: string) -> PropertyDeclaration;
|
callback property-declaration-ranges(property-name: string) -> PropertyDeclaration;
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
import { Button, CheckBox, ComboBox, LineEdit, Palette, Slider, TextEdit } from "std-widgets.slint";
|
import { Button, CheckBox, ComboBox, LineEdit, Palette, Slider, TextEdit } from "std-widgets.slint";
|
||||||
|
|
||||||
import { Api, ColorData, ElementInformation, PreviewData, PropertyContainer, PropertyInformation, PropertyValue, PropertyValueKind } from "../api.slint";
|
import { Api, ColorData, ElementInformation, PreviewData, PreviewDataKind, PropertyContainer, PropertyInformation, PropertyValue, PropertyValueKind } from "../api.slint";
|
||||||
import { BodyStrongText } from "../components/body-strong-text.slint";
|
import { BodyStrongText } from "../components/body-strong-text.slint";
|
||||||
import { BodyText } from "../components/body-text.slint";
|
import { BodyText } from "../components/body-text.slint";
|
||||||
import { StateLayer } from "../components/state-layer.slint";
|
import { StateLayer } from "../components/state-layer.slint";
|
||||||
|
|
@ -889,6 +889,12 @@ export component PreviewDataPropertyValueWidget inherits VerticalLayout {
|
||||||
in property <PreviewData> preview-data;
|
in property <PreviewData> preview-data;
|
||||||
in property <string> property-container-name;
|
in property <string> property-container-name;
|
||||||
|
|
||||||
|
private property <PropertyValue> value: Api.get-property-value(root.property-container-name, root.preview-data.name);
|
||||||
|
|
||||||
|
changed value => {
|
||||||
|
debug("\{self.property-container-name}.\{self.preview-data.name}: VALUE CHANGED TO \{self.value.code}");
|
||||||
|
}
|
||||||
|
|
||||||
callback edit-in-spreadsheet(rp: PropertyContainer);
|
callback edit-in-spreadsheet(rp: PropertyContainer);
|
||||||
|
|
||||||
function reset-action() {
|
function reset-action() {
|
||||||
|
|
@ -896,32 +902,20 @@ export component PreviewDataPropertyValueWidget inherits VerticalLayout {
|
||||||
}
|
}
|
||||||
|
|
||||||
function set-code-binding(text: string) -> bool {
|
function set-code-binding(text: string) -> bool {
|
||||||
root.value.was-edited = true;
|
return(Api.set-json-preview-data(root.property-container-name, root.preview-data.name, text));
|
||||||
root.value.edited-value = text;
|
|
||||||
|
|
||||||
root.array-values[0][0] = root.value;
|
|
||||||
|
|
||||||
return(Api.set-preview-data(root.property-container-name, root.preview-data.name, self.array-values));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private property <bool> is-simple: preview-data.header.length == 1 && !preview-data.is-array && !preview-data.prefer-json;
|
if root.preview-data.kind == PreviewDataKind.Value && value.kind == PropertyValueKind.code: CodeWidget {
|
||||||
private property <bool> show-json: preview-data.prefer-json;
|
|
||||||
|
|
||||||
private property <[[PropertyValue]]> array-values: preview-data.array-values;
|
|
||||||
|
|
||||||
property <PropertyValue> value: root.preview-data.array-values[0][0];
|
|
||||||
|
|
||||||
if is-simple && value.kind == PropertyValueKind.code: CodeWidget {
|
|
||||||
enabled: root.preview-data.has-setter;
|
enabled: root.preview-data.has-setter;
|
||||||
property-name: root.preview-data.name;
|
property-name: root.preview-data.name;
|
||||||
property-value: value;
|
property-value <=> root.value;
|
||||||
has-code-action: false;
|
has-code-action: false;
|
||||||
|
|
||||||
reset-action() => {
|
reset-action() => {
|
||||||
root.reset-action();
|
root.reset-action();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if is-simple && value.kind != PropertyValueKind.code: PropertyValueWidget {
|
if root.preview-data.kind == PreviewDataKind.Value && value.kind != PropertyValueKind.code: PropertyValueWidget {
|
||||||
property-value <=> root.value;
|
property-value <=> root.value;
|
||||||
property-name: root.preview-data.name;
|
property-name: root.preview-data.name;
|
||||||
enabled: root.preview-data.has-setter;
|
enabled: root.preview-data.has-setter;
|
||||||
|
|
@ -951,10 +945,10 @@ export component PreviewDataPropertyValueWidget inherits VerticalLayout {
|
||||||
return(root.set-code-binding(is_translated ? "\"\{text}\"" : text));
|
return(root.set-code-binding(is_translated ? "\"\{text}\"" : text));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if show-json: EditJsonWidget {
|
if root.preview-data.kind == PreviewDataKind.Json: EditJsonWidget {
|
||||||
enabled: root.preview-data.has-setter;
|
enabled: root.preview-data.has-setter;
|
||||||
property-name: root.preview-data.name;
|
property-name: root.preview-data.name;
|
||||||
property-value: value;
|
property-value <=> root.value;
|
||||||
|
|
||||||
set-code-binding(text) => {
|
set-code-binding(text) => {
|
||||||
root.set-code-binding(text);
|
root.set-code-binding(text);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue