diff --git a/dom_pseudocode.xml b/dom_pseudocode.xml
new file mode 100644
index 000000000..f07b20fad
--- /dev/null
+++ b/dom_pseudocode.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+Start with the given root component
+For each child_component:
+ Get the component of the associated child_component tag
+ Create a DomNode for this component
+ Give this DomNode its width and height and other layout attributes
+ Recursively load its children
\ No newline at end of file
diff --git a/src/layout_abstract_syntax.rs b/src/layout_abstract_syntax.rs
index 66fd7231c..f825fd3ac 100644
--- a/src/layout_abstract_syntax.rs
+++ b/src/layout_abstract_syntax.rs
@@ -45,7 +45,7 @@ pub type NodeOrDefTree = rctree::Node;
// ====================================================================================================
-/// Representation of an XML node with either another XML tag (`LayoutComponentTag`) or a text node (just a `String`)
+/// Representation of an XML node with either another XML tag (`LayoutComponentTag`) or a text node (a vector of alternating `TemplateStringSegment::String`s and `TemplateStringSegment::Argument`s)
#[derive(Debug, Clone, PartialEq)]
pub enum LayoutComponentNode {
Tag(LayoutComponentTag),
@@ -81,19 +81,19 @@ pub struct LayoutComponentDefinition {
/// Name of the component in "namespace:name" format
pub name: (String, String),
/// User-defined attribute parameters, which are prefixed with ':'
- pub user_attributes: Vec,
+ pub parameters: Vec,
}
impl LayoutComponentDefinition {
/// Construct a definition for a layout component given its name in "namespace:name" format with an empty set of parameters
pub fn new(name: (String, String)) -> Self {
- let user_attributes = vec![];
- Self { name, user_attributes }
+ let parameters = vec![];
+ Self { name, parameters }
}
/// Add a parameter definition (with its name, types, and default value) to this component definition
pub fn add_parameter(&mut self, parameter: VariableParameter) {
- self.user_attributes.push(parameter);
+ self.parameters.push(parameter);
}
}
diff --git a/src/layout_system.rs b/src/layout_system.rs
index 825e27c5d..92feb84c2 100644
--- a/src/layout_system.rs
+++ b/src/layout_system.rs
@@ -7,15 +7,15 @@ use std::collections::HashSet;
use std::fs;
use std::io;
-pub struct LayoutSystem {
- windows: Vec,
+pub struct LayoutSystem<'a> {
+ windows: Vec>,
loaded_components: ResourceCache,
attribute_parser: AttributeParser,
}
-impl LayoutSystem {
+impl<'a> LayoutSystem<'a> {
/// Construct the `LayoutSystem` with zero windows, an empty cache of component XML layouts, and an `AttributeParser` with its regex parsers
- pub fn new() -> LayoutSystem {
+ pub fn new() -> Self {
Self {
windows: vec![],
loaded_components: ResourceCache::new(),
@@ -24,17 +24,18 @@ impl LayoutSystem {
}
/// Load and construct a new window from a layout component
- pub fn add_window(&mut self, name: (&str, &str)) {
+ pub fn add_window(&'a mut self, name: (&str, &str)) {
// Preload the component and its dependencies
self.preload_component(name)
.expect(&format!("Failure loading layout component '{}'", Self::component_name(name))[..]);
// Get the now-loaded component
let window_root_component_name = Self::component_name(name);
- let window_root_component = self.loaded_components.get(&window_root_component_name[..]).unwrap();
+ // let window_root_component = self.loaded_components.get(&window_root_component_name[..]).unwrap();
+ // println!("FC: {:#?}", window_root_component);
// Construct the window and save it
- let new_window = WindowDom::new(window_root_component);
+ let new_window = WindowDom::new(&window_root_component_name[..], (1920, 1080), &self.loaded_components);
self.windows.push(new_window);
}
@@ -67,7 +68,7 @@ impl LayoutSystem {
}
// Go through each parameter attribute and preload any default values of layouts
- for definition in &component.own_info.user_attributes {
+ for definition in &component.own_info.parameters {
for default in definition.type_sequence_default.iter() {
if let TypeValue::Layout(layouts) = default {
for layout in layouts {
@@ -175,7 +176,7 @@ impl LayoutSystem {
}).collect::>();
cloned_tag.set_content(children);
- // Return this LayoutComponentTag within the component's root definition tag
+ // Return this `LayoutComponentTag` within the component's root definition tag
Some(cloned_tag)
})
.collect::>();
@@ -338,7 +339,7 @@ impl LayoutSystem {
}
/// Get a string in `namespace:name` format (or just `name` for primitives) given a namespace and component name
- fn component_name(name: (&str, &str)) -> String {
+ pub fn component_name(name: (&str, &str)) -> String {
let (namespace, file) = name;
if namespace.len() > 0 {
format!("{}:{}", namespace, file)
diff --git a/src/window_dom.rs b/src/window_dom.rs
index 9a9de4ccf..e4ec35b14 100644
--- a/src/window_dom.rs
+++ b/src/window_dom.rs
@@ -1,9 +1,105 @@
use crate::layout_abstract_syntax::*;
+use crate::layout_abstract_types::*;
+use crate::{layout_system::*, resource_cache::ResourceCache};
+use std::collections::HashMap;
-pub struct WindowDom {}
+pub struct WindowDom<'a> {
+ pub dom: rctree::Node,
+ loaded_components: &'a ResourceCache,
+}
-impl WindowDom {
- pub fn new(root_component: &FlatComponent) -> WindowDom {
- Self {}
+impl<'a> WindowDom<'a> {
+ pub fn new(root_component: &str, window_size: (u32, u32), loaded_components: &'a ResourceCache) -> WindowDom<'a> {
+ let mut layout_attributes = LayoutAttributes::default();
+ layout_attributes.width = Dimension::AbsolutePx(window_size.0 as f64);
+ layout_attributes.height = Dimension::AbsolutePx(window_size.1 as f64);
+
+ let dom = Self::build_dom_from_component(root_component, &layout_attributes, &vec![], loaded_components);
+ Self { dom, loaded_components }
+ }
+
+ fn build_dom_from_component(
+ root_component: &str,
+ layout_attributes: &LayoutAttributes,
+ parameters: &Vec,
+ loaded_components: &'a ResourceCache,
+ ) -> rctree::Node {
+ // Instantiate the DOM node and put it in a tree node
+ let component = loaded_components.get(root_component).unwrap();
+ let dom_node = DomNode::from_component(component, layout_attributes, parameters);
+ let mut tree = rctree::Node::new(dom_node);
+
+ // Recursively build the child `DomNode` tree node instances
+ let child_nodes = component
+ .child_components
+ .iter()
+ .map(|child| {
+ // Get the child name used as the component cache key
+ let (namespace, name) = &child.name;
+ let component_name = LayoutSystem::component_name((namespace, name));
+
+ // Recursively build the child `DomNode` component instance
+ Self::build_dom_from_component(&component_name[..], &child.layout_arguments, &child.user_arguments, loaded_components)
+ })
+ .collect::>();
+
+ // Append each child `DomNode` tree node
+ for child in child_nodes {
+ tree.append(child);
+ }
+
+ // Return the tree that has been recursively built with sibling and child components
+ tree
+ }
+}
+
+pub struct DomNode {
+ pub cache_name: String,
+ pub layout_attributes: LayoutAttributes,
+ pub variable_bindings: HashMap>,
+}
+
+impl DomNode {
+ pub fn new(cache_name: String, layout_attributes: LayoutAttributes, variable_bindings: HashMap>) -> Self {
+ Self {
+ cache_name,
+ layout_attributes,
+ variable_bindings,
+ }
+ }
+
+ pub fn from_component(component: &FlatComponent, layout_attributes: &LayoutAttributes, parameters: &Vec) -> Self {
+ // Cached name of the loaded component
+ let (namespace, name) = &component.own_info.name;
+ let cache_name = LayoutSystem::component_name((&namespace[..], &name[..]));
+
+ // Every VARIABLE_NAME binding defined as a parameter on this component
+ let mut variable_bindings = component
+ .own_info
+ .parameters
+ .iter()
+ .map(|parameter| {
+ (
+ // HashMap key is the parameter name
+ parameter.name.clone(),
+ // HashMap value is the parameter's defined default value
+ parameter
+ .type_sequence_default
+ .iter()
+ .map(|value| TypeValueOrArgument::TypeValue(value.clone()))
+ .collect::>(),
+ )
+ })
+ .collect::>();
+ // Overwrite the defaults for given parameters
+ for parameter in parameters {
+ if !variable_bindings.contains_key(¶meter.name[..]) {
+ panic!("Invalid argument {} given to the {} component", parameter.name, cache_name);
+ }
+
+ variable_bindings.insert(parameter.name.clone(), parameter.value.clone());
+ }
+
+ Self::new(cache_name, layout_attributes.clone(), variable_bindings)
}
}