mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-21 14:58:11 +08:00
Partial implementation of the WindowDom system
This commit is contained in:
@@ -0,0 +1,12 @@
|
|||||||
|
<window:main>
|
||||||
|
<col width="100%" height="100%">
|
||||||
|
</col>
|
||||||
|
</window:main>
|
||||||
|
|
||||||
|
|
||||||
|
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
|
||||||
@@ -45,7 +45,7 @@ pub type NodeOrDefTree = rctree::Node<LayoutComponentNodeOrDefinition>;
|
|||||||
|
|
||||||
// ====================================================================================================
|
// ====================================================================================================
|
||||||
|
|
||||||
/// 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)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub enum LayoutComponentNode {
|
pub enum LayoutComponentNode {
|
||||||
Tag(LayoutComponentTag),
|
Tag(LayoutComponentTag),
|
||||||
@@ -81,19 +81,19 @@ pub struct LayoutComponentDefinition {
|
|||||||
/// Name of the component in "namespace:name" format
|
/// Name of the component in "namespace:name" format
|
||||||
pub name: (String, String),
|
pub name: (String, String),
|
||||||
/// User-defined attribute parameters, which are prefixed with ':'
|
/// User-defined attribute parameters, which are prefixed with ':'
|
||||||
pub user_attributes: Vec<VariableParameter>,
|
pub parameters: Vec<VariableParameter>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LayoutComponentDefinition {
|
impl LayoutComponentDefinition {
|
||||||
/// Construct a definition for a layout component given its name in "namespace:name" format with an empty set of parameters
|
/// 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 {
|
pub fn new(name: (String, String)) -> Self {
|
||||||
let user_attributes = vec![];
|
let parameters = vec![];
|
||||||
Self { name, user_attributes }
|
Self { name, parameters }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add a parameter definition (with its name, types, and default value) to this component definition
|
/// Add a parameter definition (with its name, types, and default value) to this component definition
|
||||||
pub fn add_parameter(&mut self, parameter: VariableParameter) {
|
pub fn add_parameter(&mut self, parameter: VariableParameter) {
|
||||||
self.user_attributes.push(parameter);
|
self.parameters.push(parameter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+11
-10
@@ -7,15 +7,15 @@ use std::collections::HashSet;
|
|||||||
use std::fs;
|
use std::fs;
|
||||||
use std::io;
|
use std::io;
|
||||||
|
|
||||||
pub struct LayoutSystem {
|
pub struct LayoutSystem<'a> {
|
||||||
windows: Vec<WindowDom>,
|
windows: Vec<WindowDom<'a>>,
|
||||||
loaded_components: ResourceCache<FlatComponent>,
|
loaded_components: ResourceCache<FlatComponent>,
|
||||||
attribute_parser: AttributeParser,
|
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
|
/// 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 {
|
Self {
|
||||||
windows: vec![],
|
windows: vec![],
|
||||||
loaded_components: ResourceCache::new(),
|
loaded_components: ResourceCache::new(),
|
||||||
@@ -24,17 +24,18 @@ impl LayoutSystem {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Load and construct a new window from a layout component
|
/// 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
|
// Preload the component and its dependencies
|
||||||
self.preload_component(name)
|
self.preload_component(name)
|
||||||
.expect(&format!("Failure loading layout component '{}'", Self::component_name(name))[..]);
|
.expect(&format!("Failure loading layout component '{}'", Self::component_name(name))[..]);
|
||||||
|
|
||||||
// Get the now-loaded component
|
// Get the now-loaded component
|
||||||
let window_root_component_name = Self::component_name(name);
|
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
|
// 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);
|
self.windows.push(new_window);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -67,7 +68,7 @@ impl LayoutSystem {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Go through each parameter attribute and preload any default values of layouts
|
// 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() {
|
for default in definition.type_sequence_default.iter() {
|
||||||
if let TypeValue::Layout(layouts) = default {
|
if let TypeValue::Layout(layouts) = default {
|
||||||
for layout in layouts {
|
for layout in layouts {
|
||||||
@@ -175,7 +176,7 @@ impl LayoutSystem {
|
|||||||
}).collect::<Vec<_>>();
|
}).collect::<Vec<_>>();
|
||||||
cloned_tag.set_content(children);
|
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)
|
Some(cloned_tag)
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
@@ -338,7 +339,7 @@ impl LayoutSystem {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Get a string in `namespace:name` format (or just `name` for primitives) given a namespace and component name
|
/// 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;
|
let (namespace, file) = name;
|
||||||
if namespace.len() > 0 {
|
if namespace.len() > 0 {
|
||||||
format!("{}:{}", namespace, file)
|
format!("{}:{}", namespace, file)
|
||||||
|
|||||||
+100
-4
@@ -1,9 +1,105 @@
|
|||||||
use crate::layout_abstract_syntax::*;
|
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<DomNode>,
|
||||||
|
loaded_components: &'a ResourceCache<FlatComponent>,
|
||||||
|
}
|
||||||
|
|
||||||
impl WindowDom {
|
impl<'a> WindowDom<'a> {
|
||||||
pub fn new(root_component: &FlatComponent) -> WindowDom {
|
pub fn new(root_component: &str, window_size: (u32, u32), loaded_components: &'a ResourceCache<FlatComponent>) -> WindowDom<'a> {
|
||||||
Self {}
|
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<AttributeArg>,
|
||||||
|
loaded_components: &'a ResourceCache<FlatComponent>,
|
||||||
|
) -> rctree::Node<DomNode> {
|
||||||
|
// 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::<Vec<_>>();
|
||||||
|
|
||||||
|
// 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<String, Vec<TypeValueOrArgument>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DomNode {
|
||||||
|
pub fn new(cache_name: String, layout_attributes: LayoutAttributes, variable_bindings: HashMap<String, Vec<TypeValueOrArgument>>) -> Self {
|
||||||
|
Self {
|
||||||
|
cache_name,
|
||||||
|
layout_attributes,
|
||||||
|
variable_bindings,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from_component(component: &FlatComponent, layout_attributes: &LayoutAttributes, parameters: &Vec<AttributeArg>) -> 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::<Vec<_>>(),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.collect::<HashMap<_, _>>();
|
||||||
|
// 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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user