mirror of
https://github.com/project-gauntlet/gauntlet.git
synced 2025-12-23 10:35:53 +00:00
Validate children component type
This commit is contained in:
parent
95bae1df93
commit
5ae0928591
7 changed files with 120 additions and 34 deletions
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -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(())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,6 +28,12 @@ pub enum NativeUiResponseData {
|
|||
CloneInstance {
|
||||
widget: anyhow::Result<NativeUiWidget>
|
||||
},
|
||||
AppendChild {
|
||||
result: anyhow::Result<()>
|
||||
},
|
||||
ReplaceContainerChildren {
|
||||
result: anyhow::Result<()>
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
@ -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)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue