Skip to content

Commit ebe4ae2

Browse files
committed
Bind string editor fields through Rml data
1 parent 193389a commit ebe4ae2

1 file changed

Lines changed: 43 additions & 15 deletions

File tree

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

Lines changed: 43 additions & 15 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_blur, on_enter, on_pointer, ChangeQueue, Field, FieldValue,
@@ -16,6 +19,7 @@ pub(crate) struct StringField {
1619
display_elem: Option<u64>,
1720
edit_elem: Option<u64>,
1821
editing: bool,
22+
display_value: Option<RmlDataVariable<'static, String>>,
1923
}
2024

2125
impl StringField {
@@ -29,6 +33,7 @@ impl StringField {
2933
display_elem: None,
3034
edit_elem: None,
3135
editing: false,
36+
display_value: None,
3237
}
3338
}
3439

@@ -37,14 +42,34 @@ impl StringField {
3742
self
3843
}
3944

40-
fn button_rml(&self) -> String {
45+
fn binding_name(&self) -> String {
4146
format!(
42-
r#"<span class="field-button-title">{title}:</span><span class="field-button-value">{value}</span>"#,
43-
title = escape_rml(self.title.trim_end_matches(':')),
44-
value = escape_rml(&self.value),
47+
"field_{}_display",
48+
self.name
49+
.chars()
50+
.map(|character| if character.is_ascii_alphanumeric() {
51+
character
52+
} else {
53+
'_'
54+
})
55+
.collect::<String>(),
4556
)
4657
}
4758

59+
fn display_markup(&self) -> String {
60+
self.display_value
61+
.as_ref()
62+
.map(|_| format!("{{{{ {} }}}}", self.binding_name()))
63+
.unwrap_or_else(|| escape_rml(&self.value))
64+
}
65+
66+
fn sync_display_value(&self) -> Result<(), Error> {
67+
if let Some(value) = &self.display_value {
68+
value.set(self.value.clone())?;
69+
}
70+
Ok(())
71+
}
72+
4873
fn show_edit(&mut self, interface: &NativeInterfaceRef) {
4974
self.editing = true;
5075
let rml = interface.rml_ui();
@@ -61,11 +86,10 @@ impl StringField {
6186

6287
fn show_display(&mut self, interface: &NativeInterfaceRef) {
6388
self.editing = false;
64-
let markup = self.button_rml();
6589
let rml = interface.rml_ui();
6690
if let Some(element) = self.display_elem {
6791
let _ = rml.element_set_class(element, "hidden", false);
68-
let _ = rml.element_set_inner_rml(element, &markup);
92+
let _ = self.sync_display_value();
6993
}
7094
if let Some(element) = self.edit_elem {
7195
let _ = rml.element_set_class(element, "hidden", true);
@@ -82,18 +106,24 @@ impl Field for StringField {
82106
self.tooltip.as_deref()
83107
}
84108

109+
fn prepare_data_model(&mut self, model: &RmlDataModel<'static>) -> Result<(), Error> {
110+
self.display_value = Some(model.bind(&self.binding_name(), self.value.clone())?);
111+
Ok(())
112+
}
113+
85114
fn generate_rml(&self) -> String {
86115
format!(
87116
concat!(
88117
r#"<div class="field-row">"#,
89-
r#"<button id="field-{n}" class="field-composite-button field-string-button" style="width: {width}px;">{button}</button>"#,
90-
r#"<input type="text" id="field-{n}-input" class="field-input field-string-input hidden" style="width: {width}px;" value="{value}"/>"#,
118+
r#"<button id="field-{n}" class="field-composite-button field-string-button" style="width: {width}px;"><span class="field-button-title">{title}:</span><span class="field-button-value">{value}</span></button>"#,
119+
r#"<input type="text" id="field-{n}-input" class="field-input field-string-input hidden" style="width: {width}px;" value="{input_value}"/>"#,
91120
r#"</div>"#,
92121
),
93122
n = self.name,
94123
width = self.width,
95-
button = self.button_rml(),
96-
value = escape_rml(&self.value),
124+
title = escape_rml(self.title.trim_end_matches(':')),
125+
value = self.display_markup(),
126+
input_value = escape_rml(&self.value),
97127
)
98128
}
99129

@@ -128,10 +158,8 @@ impl Field for StringField {
128158
}
129159

130160
fn write_to_dom(&self, interface: &NativeInterfaceRef) -> Result<(), Error> {
131-
if let Some(element) = self.display_elem {
132-
interface
133-
.rml_ui()
134-
.element_set_inner_rml(element, &self.button_rml())?;
161+
if self.display_elem.is_some() {
162+
self.sync_display_value()?;
135163
}
136164
if let Some(element) = self.edit_elem {
137165
interface

0 commit comments

Comments
 (0)