Validate children component type

This commit is contained in:
Exidex 2023-12-10 19:25:00 +01:00
parent 95bae1df93
commit 5ae0928591
7 changed files with 120 additions and 34 deletions

View file

@ -114,7 +114,7 @@ fn main() -> anyhow::Result<()> {
output.push_str("\n");
output.push_str("fn append_component_widget_child(parent: &ComponentWidgetWrapper, child: ComponentWidgetWrapper) {\n");
output.push_str("fn append_component_widget_child(parent: &ComponentWidgetWrapper, child: ComponentWidgetWrapper) -> anyhow::Result<()> {\n");
output.push_str(" let mut parent = parent.get_mut();\n");
output.push_str(" match *parent {\n");
output.push_str(" ComponentWidget::TextPart { .. } => panic!(\"text part cannot be a parent\"),\n");
@ -126,16 +126,33 @@ fn main() -> anyhow::Result<()> {
if has_children {
output.push_str(&format!(" ComponentWidget::{} {{ ref mut children, .. }} => {{\n", name));
output.push_str(" match get_component_widget_type_internal(&child) {\n");
match component.children() {
Children::Members { members } => {
for member in members {
output.push_str(&format!(" (\"gauntlet:{}\", _) => (),\n", member.component_internal_name()));
}
}
Children::String => {
output.push_str(&format!(" (\"gauntlet:___text_part___\", _) => (),\n"));
}
Children::None => {}
}
output.push_str(&format!(" (_, name) => Err(anyhow::anyhow!(\"{} cannot have {{}} child\", name))?\n", name));
output.push_str(" };\n");
output.push_str(" children.push(child)\n");
output.push_str(" }\n");
} else {
output.push_str(&format!(" ComponentWidget::{} {{ .. }} => {{\n", name));
output.push_str(&format!(" panic!(\"{} cannot be a parent\")\n", internal_name));
output.push_str(&format!(" Err(anyhow::anyhow!(\"{} cannot have children\"))?\n", name));
output.push_str(" }\n");
}
}
output.push_str(" }\n");
output.push_str(" };\n");
output.push_str(" Ok(())\n");
output.push_str("}\n");
output.push_str("\n");
@ -158,7 +175,7 @@ fn main() -> anyhow::Result<()> {
output.push_str("\n");
output.push_str("fn get_component_widget_children(widget: &ComponentWidgetWrapper) -> Vec<ComponentWidgetWrapper> {\n");
output.push_str("fn get_component_widget_children(widget: &ComponentWidgetWrapper) -> anyhow::Result<Vec<ComponentWidgetWrapper>> {\n");
output.push_str(" let widget = widget.get();\n");
output.push_str(" let children = match *widget {\n");
output.push_str(" ComponentWidget::TextPart { .. } => panic!(\"text part cannot have children\"),\n");
@ -174,18 +191,18 @@ fn main() -> anyhow::Result<()> {
output.push_str(" }\n");
} else {
output.push_str(&format!(" ComponentWidget::{} {{ .. }} => {{\n", name));
output.push_str(&format!(" panic!(\"{} cannot have children\")\n", internal_name));
output.push_str(&format!(" Err(anyhow::anyhow!(\"{} cannot have children\"))?\n", name));
output.push_str(" }\n");
}
}
output.push_str(" };\n");
output.push_str(" children.iter().cloned().collect()\n");
output.push_str(" Ok(children.iter().cloned().collect())\n");
output.push_str("}\n");
output.push_str("\n");
output.push_str("fn set_component_widget_children(widget: &ComponentWidgetWrapper, new_children: Vec<ComponentWidgetWrapper>) {\n");
output.push_str("fn set_component_widget_children(widget: &ComponentWidgetWrapper, new_children: Vec<ComponentWidgetWrapper>) -> anyhow::Result<()> {\n");
output.push_str(" let mut widget = widget.get_mut();\n");
output.push_str(" match *widget {\n");
output.push_str(" ComponentWidget::TextPart { .. } => panic!(\"text part cannot have children\"),\n");
@ -197,16 +214,35 @@ fn main() -> anyhow::Result<()> {
if has_children {
output.push_str(&format!(" ComponentWidget::{} {{ ref mut children, .. }} => {{\n", name));
output.push_str(" for new_child in &new_children {\n");
output.push_str(" match get_component_widget_type_internal(new_child) {\n");
match component.children() {
Children::Members { members } => {
for member in members {
output.push_str(&format!(" (\"gauntlet:{}\", _) => (),\n", member.component_internal_name()));
}
}
Children::String => {
output.push_str(&format!(" (\"gauntlet:___text_part___\", _) => (),\n"));
}
Children::None => {}
}
output.push_str(&format!(" (_, name) => Err(anyhow::anyhow!(\"{} cannot have {{}} child\", name))?\n", name));
output.push_str(" };\n");
output.push_str(" }\n");
output.push_str(" *children = new_children\n");
output.push_str(" }\n");
} else {
output.push_str(&format!(" ComponentWidget::{} {{ .. }} => {{\n", name));
output.push_str(&format!(" panic!(\"{} cannot have children\")\n", internal_name));
output.push_str(&format!(" Err(anyhow::anyhow!(\"{} cannot have children\"))?\n", internal_name));
output.push_str(" }\n");
}
}
output.push_str(" }\n");
output.push_str(" };\n");
output.push_str(" Ok(())\n");
output.push_str("}\n");
output.push_str("\n");
@ -228,6 +264,23 @@ fn main() -> anyhow::Result<()> {
output.push_str("\n");
output.push_str("fn get_component_widget_type_internal(widget: &ComponentWidgetWrapper) -> (&str, &str) {\n");
output.push_str(" let widget = widget.get();\n");
output.push_str(" match *widget {\n");
output.push_str(" ComponentWidget::TextPart { .. } => (\"gauntlet:___text_part___\", \"TextPart\"),\n");
for component in &components {
let name = component.name();
let internal_name = component.internal_name();
output.push_str(&format!(" ComponentWidget::{} {{ .. }} => (\"gauntlet:{}\", \"{}\"),\n", name, internal_name, name));
}
output.push_str(" }\n");
output.push_str("}\n");
output.push_str("\n");
output.push_str("fn parse_optional_string(properties: &HashMap<String, NativeUiPropertyValue>, name: &str) -> anyhow::Result<Option<String>> {\n");
output.push_str(" match properties.get(name) {\n");
output.push_str(" None => Ok(None),\n");

View file

@ -49,9 +49,14 @@ impl DbusClient {
Ok(widget)
}
fn append_child(&mut self, plugin_id: &str, parent: DBusUiWidget, child: DBusUiWidget) -> Result<()> {
async fn append_child(&mut self, plugin_id: &str, parent: DBusUiWidget, child: DBusUiWidget) -> Result<()> {
let data = NativeUiRequestData::AppendChild { parent: parent.into(), child: child.into() };
self.context_tx.send((PluginId::from_string(plugin_id), data));
let input = (PluginId::from_string(plugin_id), data);
match self.context_tx.send_receive(input).await {
NativeUiResponseData::AppendChild { result } => result?,
value @ _ => panic!("unsupported response type {:?}", value),
};
Ok(())
}
@ -73,10 +78,15 @@ impl DbusClient {
Ok(widget)
}
fn replace_container_children(&self, plugin_id: &str, container: DBusUiWidget, new_children: Vec<DBusUiWidget>) -> Result<()> {
async fn replace_container_children(&self, plugin_id: &str, container: DBusUiWidget, new_children: Vec<DBusUiWidget>) -> Result<()> {
let new_children = new_children.into_iter().map(|child| child.into()).collect();
let data = NativeUiRequestData::ReplaceContainerChildren { container: container.into(), new_children };
self.context_tx.send((PluginId::from_string(plugin_id), data));
let data = (PluginId::from_string(plugin_id), data);
match self.context_tx.send_receive(data).await {
NativeUiResponseData::ReplaceContainerChildren { result } => result?,
value @ _ => panic!("unsupported response type {:?}", value),
};
Ok(())
}

View file

@ -28,6 +28,12 @@ pub enum NativeUiResponseData {
CloneInstance {
widget: anyhow::Result<NativeUiWidget>
},
AppendChild {
result: anyhow::Result<()>
},
ReplaceContainerChildren {
result: anyhow::Result<()>
},
}
#[derive(Debug)]

View file

@ -325,7 +325,11 @@ async fn request_loop(
responder.respond(response)
}
NativeUiRequestData::AppendChild { parent, child } => {
client_context.append_child(&plugin_id, parent, child);
let result = client_context.append_child(&plugin_id, parent, child);
let response = NativeUiResponseData::AppendChild { result };
responder.respond(response)
}
NativeUiRequestData::CloneInstance {
widget,
@ -340,7 +344,11 @@ async fn request_loop(
responder.respond(response)
}
NativeUiRequestData::ReplaceContainerChildren { container, new_children } => {
client_context.replace_container_children(&plugin_id, container, new_children);
let result = client_context.replace_container_children(&plugin_id, container, new_children);
let response = NativeUiResponseData::AppendChild { result };
responder.respond(response)
}
}
}

View file

@ -65,7 +65,7 @@ impl PluginViewContainer {
NativeUiWidget {
widget_id: self.root_id,
widget_type: "___root___".to_owned()
widget_type: "gauntlet:___root___".to_owned()
}
}
@ -78,7 +78,7 @@ impl PluginViewContainer {
fn create_text_instance(&mut self, text: &str) -> anyhow::Result<NativeUiWidget> {
tracing::trace!("create_text_instance is called. text: {:?}", text);
let widget = self.create_native_widget("text", |id| ComponentWidgetWrapper::text_part(id, text));
let widget = self.create_native_widget("gauntlet:___text_part___", |id| ComponentWidgetWrapper::text_part(id, text));
tracing::trace!("create_text_instance is returned. widget: {:?}", widget);
widget
}
@ -92,9 +92,7 @@ impl PluginViewContainer {
if keep_children {
let new_widget_builtin = self.get_builtin_widget(new_widget.clone());
if new_widget_builtin.can_have_children() {
new_widget_builtin.set_children(widget.get_children());
}
new_widget_builtin.set_children(widget.get_children()?)?;
}
tracing::trace!("clone_instance is returned. widget: {:?}", widget);
@ -102,15 +100,15 @@ impl PluginViewContainer {
Ok(new_widget)
}
fn append_child(&mut self, parent: NativeUiWidget, child: NativeUiWidget) {
fn append_child(&mut self, parent: NativeUiWidget, child: NativeUiWidget) -> anyhow::Result<()> {
tracing::trace!("append_child is called. parent: {:?}, child: {:?}", parent, child);
let parent = self.get_builtin_widget(parent);
let child = self.get_builtin_widget(child);
parent.append_child(child);
parent.append_child(child)
}
fn replace_container_children(&mut self, container: NativeUiWidget, new_children: Vec<NativeUiWidget>) {
fn replace_container_children(&mut self, container: NativeUiWidget, new_children: Vec<NativeUiWidget>) -> anyhow::Result<()> {
tracing::trace!("replace_container_children is called. container: {:?}, new_children: {:?}", container, new_children);
let container = self.get_builtin_widget(container);
@ -118,7 +116,7 @@ impl PluginViewContainer {
.map(|child| self.get_builtin_widget(child))
.collect();
container.set_children(children);
container.set_children(children)
}
}
@ -180,7 +178,7 @@ impl ClientContext {
self.get_view_container_mut(plugin_id).create_text_instance(text)
}
pub fn append_child(&mut self, plugin_id: &PluginId, parent: NativeUiWidget, child: NativeUiWidget) {
pub fn append_child(&mut self, plugin_id: &PluginId, parent: NativeUiWidget, child: NativeUiWidget) -> anyhow::Result<()> {
self.get_view_container_mut(plugin_id).append_child(parent, child)
}
@ -188,7 +186,7 @@ impl ClientContext {
self.get_view_container_mut(plugin_id).clone_instance(widget, widget_type, new_props, keep_children)
}
pub fn replace_container_children(&mut self, plugin_id: &PluginId, container: NativeUiWidget, new_children: Vec<NativeUiWidget>) {
pub fn replace_container_children(&mut self, plugin_id: &PluginId, container: NativeUiWidget, new_children: Vec<NativeUiWidget>) -> anyhow::Result<()> {
self.get_view_container_mut(plugin_id).replace_container_children(container, new_children)
}
}

View file

@ -137,19 +137,15 @@ impl ComponentWidgetWrapper {
}
}
pub fn append_child(&self, child: ComponentWidgetWrapper) {
append_component_widget_child(&self, child);
pub fn append_child(&self, child: ComponentWidgetWrapper) -> anyhow::Result<()> {
append_component_widget_child(&self, child)
}
pub fn can_have_children(&self) -> bool {
can_component_widget_have_children(&self)
}
pub fn get_children(&self) -> Vec<ComponentWidgetWrapper> {
pub fn get_children(&self) -> anyhow::Result<Vec<ComponentWidgetWrapper>> {
get_component_widget_children(&self)
}
pub fn set_children(&self, new_children: Vec<ComponentWidgetWrapper>) {
pub fn set_children(&self, new_children: Vec<ComponentWidgetWrapper>) -> anyhow::Result<()> {
set_component_widget_children(&self, new_children)
}

View file

@ -111,10 +111,24 @@ pub enum Children {
pub struct ChildrenMember {
#[serde(rename = "memberName")]
member_name: String,
#[serde(rename = "componentInternalName")]
component_internal_name: String,
#[serde(rename = "componentName")]
component_name: ComponentName,
}
impl ChildrenMember {
pub fn member_name(&self) -> &str {
&self.member_name
}
pub fn component_internal_name(&self) -> &str {
&self.component_internal_name
}
pub fn component_name(&self) -> &ComponentName {
&self.component_name
}
}
fn children_members(members: Vec<ChildrenMember>) -> Children {
Children::Members {
@ -133,6 +147,7 @@ fn children_none() -> Children {
fn member(member_name: impl ToString, component: &Component) -> ChildrenMember {
ChildrenMember {
member_name: member_name.to_string(),
component_internal_name: component.internal_name.clone(),
component_name: component.name.clone()
}
}