Skip to content

Commit ae92459

Browse files
committed
Bind asset editor fields through Rml data
1 parent ebe4ae2 commit ae92459

1 file changed

Lines changed: 44 additions & 17 deletions

File tree

‎native/src/sbc/panels/fields/asset.rs‎

Lines changed: 44 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
use spring_native::prelude::{Error, NativeInterfaceRef};
1+
use spring_native::{
2+
prelude::{Error, NativeInterfaceRef},
3+
RmlDataModel, RmlDataVariable,
4+
};
25

36
use crate::sbc::panels::field::{
47
element_by_id, escape_rml, on_pointer, ChangeQueue, Field, FieldValue, InteractionQueue,
@@ -14,6 +17,7 @@ pub(crate) struct AssetField {
1417
root: String,
1518
extensions: Vec<String>,
1619
element: Option<u64>,
20+
display_value: Option<RmlDataVariable<'static, String>>,
1721
}
1822

1923
impl AssetField {
@@ -26,6 +30,7 @@ impl AssetField {
2630
extensions: Vec::new(),
2731
tooltip: None,
2832
element: None,
33+
display_value: None,
2934
}
3035
}
3136

@@ -39,20 +44,38 @@ impl AssetField {
3944
self
4045
}
4146

42-
fn button_rml(&self) -> String {
43-
// Show just the file name; the full VFS path does not fit the button.
44-
let shown = self
45-
.value
47+
fn display_text(&self) -> String {
48+
self.value
4649
.rsplit('/')
4750
.next()
48-
.filter(|s| !s.is_empty())
49-
.unwrap_or("(none)");
51+
.filter(|value| !value.is_empty())
52+
.unwrap_or("(none)")
53+
.to_string()
54+
}
55+
56+
fn binding_name(&self) -> String {
5057
format!(
51-
r#"<span class="field-button-title">{title}:</span><span class="field-button-value">{shown}</span>"#,
52-
title = escape_rml(self.title.trim_end_matches(':')),
53-
shown = escape_rml(shown),
58+
"field_{}_display",
59+
self.name
60+
.chars()
61+
.map(|character| if character.is_ascii_alphanumeric() { character } else { '_' })
62+
.collect::<String>(),
5463
)
5564
}
65+
66+
fn display_markup(&self) -> String {
67+
self.display_value
68+
.as_ref()
69+
.map(|_| format!("{{{{ {} }}}}", self.binding_name()))
70+
.unwrap_or_else(|| escape_rml(&self.display_text()))
71+
}
72+
73+
fn sync_display_value(&self) -> Result<(), Error> {
74+
if let Some(value) = &self.display_value {
75+
value.set(self.display_text())?;
76+
}
77+
Ok(())
78+
}
5679
}
5780

5881
impl Field for AssetField {
@@ -64,11 +87,17 @@ impl Field for AssetField {
6487
self.tooltip.as_deref()
6588
}
6689

90+
fn prepare_data_model(&mut self, model: &RmlDataModel<'static>) -> Result<(), Error> {
91+
self.display_value = Some(model.bind(&self.binding_name(), self.display_text())?);
92+
Ok(())
93+
}
94+
6795
fn generate_rml(&self) -> String {
6896
format!(
69-
r#"<div class="field-row"><button id="field-{n}" class="field-composite-button field-asset-button">{button}</button></div>"#,
97+
r#"<div class="field-row"><button id="field-{n}" class="field-composite-button field-asset-button"><span class="field-button-title">{title}:</span><span class="field-button-value">{value}</span></button></div>"#,
7098
n = self.name,
71-
button = self.button_rml(),
99+
title = escape_rml(self.title.trim_end_matches(':')),
100+
value = self.display_markup(),
72101
)
73102
}
74103

@@ -90,11 +119,9 @@ impl Field for AssetField {
90119
Ok(FieldValue::Text(self.value.clone()))
91120
}
92121

93-
fn write_to_dom(&self, interface: &NativeInterfaceRef) -> Result<(), Error> {
94-
if let Some(e) = self.element {
95-
interface
96-
.rml_ui()
97-
.element_set_inner_rml(e, &self.button_rml())?;
122+
fn write_to_dom(&self, _interface: &NativeInterfaceRef) -> Result<(), Error> {
123+
if self.element.is_some() {
124+
self.sync_display_value()?;
98125
}
99126
Ok(())
100127
}

0 commit comments

Comments
 (0)