diff --git a/pax-compiler/src/lib.rs b/pax-compiler/src/lib.rs index dc81c3e20..c42770963 100644 --- a/pax-compiler/src/lib.rs +++ b/pax-compiler/src/lib.rs @@ -581,8 +581,6 @@ fn recurse_generate_render_nodes_literal( }) .collect(); - const DEFAULT_PROPERTY_LITERAL: &str = "PropertyLiteral::new(Default::default())"; - //pull inline event binding and store into map let events = generate_bound_events(tnd.settings.clone()); let args = if tnd.type_id == parsing::TYPE_ID_REPEAT { @@ -616,7 +614,7 @@ fn recurse_generate_render_nodes_literal( primitive_instance_import_path: Some("RepeatInstance".into()), properties_coproduct_variant: "None".to_string(), component_properties_struct: "None".to_string(), - properties: vec![], + defined_properties: vec![], common_properties_literal, children_literal, slot_index_literal: "None".to_string(), @@ -649,7 +647,7 @@ fn recurse_generate_render_nodes_literal( primitive_instance_import_path: Some("ConditionalInstance".into()), properties_coproduct_variant: "None".to_string(), component_properties_struct: "None".to_string(), - properties: vec![], + defined_properties: vec![], common_properties_literal, children_literal, slot_index_literal: "None".to_string(), @@ -685,7 +683,7 @@ fn recurse_generate_render_nodes_literal( primitive_instance_import_path: Some("SlotInstance".into()), properties_coproduct_variant: "None".to_string(), component_properties_struct: "None".to_string(), - properties: vec![], + defined_properties: vec![], common_properties_literal, children_literal, slot_index_literal: format!("Some(Box::new(PropertyExpression::new({})))", id), @@ -716,7 +714,7 @@ fn recurse_generate_render_nodes_literal( // stage for any `Properties` that are bound to something other than an expression / literal) // Tuple of property_id, RIL literal string (e.g. `PropertyLiteral::new(...`_ - let property_ril_tuples: Vec<(String, String)> = component_for_current_node + let property_ril_tuples: Vec<Option<(String, String)>> = component_for_current_node .get_property_definitions(rngc.type_table) .iter() .map(|pd| { @@ -727,42 +725,53 @@ fn recurse_generate_render_nodes_literal( { match &matched_setting.1 { ValueDefinition::LiteralValue(lv) => { - format!("PropertyLiteral::new({})", lv) + Some(format!("PropertyLiteral::new({})", lv)) } ValueDefinition::Expression(_, id) | ValueDefinition::Identifier(_, id) => { - format!( + Some(format!( "PropertyExpression::new({})", id.expect("Tried to use expression but it wasn't compiled") - ) + )) } ValueDefinition::Block(block) => { - format!( + Some(format!( "PropertyLiteral::new({})", recurse_literal_block( block.clone(), pd.get_type_definition(&rngc.type_table), host_crate_info ) - ) + )) } _ => { panic!("Incorrect value bound to inline setting") } } } else { - DEFAULT_PROPERTY_LITERAL.to_string() + None } } else { //no inline attributes at all; everything will be default - DEFAULT_PROPERTY_LITERAL.to_string() + None } }; - (pd.name.clone(), ril_literal_string) + + if let Some(ril_literal_string) = ril_literal_string { + Some((pd.name.clone(), ril_literal_string)) + } else { + None + } }) .collect(); + let defined_properties: Vec<(String, String)> = property_ril_tuples + .iter() + .filter_map(|p| p.as_ref()) + .cloned() + .collect(); + let identifiers_and_types = pax_runtime_api::CommonProperties::get_property_identifiers(); fn default_common_property_value(identifier: &str) -> String { @@ -841,7 +850,7 @@ fn recurse_generate_render_nodes_literal( .clone(), properties_coproduct_variant: component_for_current_node.type_id_escaped.to_string(), component_properties_struct: component_for_current_node.pascal_identifier.to_string(), - properties: property_ril_tuples, + defined_properties, common_properties_literal, children_literal, slot_index_literal: "None".to_string(), diff --git a/pax-compiler/src/templating.rs b/pax-compiler/src/templating.rs index ce2bfa87d..f67f73231 100644 --- a/pax-compiler/src/templating.rs +++ b/pax-compiler/src/templating.rs @@ -4,7 +4,8 @@ use serde_derive::{Deserialize, Serialize}; #[allow(unused_imports)] use serde_json; use std::collections::HashMap; -use tera::Tera; +use tera::{Tera, Context}; + use crate::manifest::{ExpressionSpec, PropertyDefinition}; @@ -56,7 +57,7 @@ pub struct TemplateArgsCodegenCartridgeRenderNodeLiteral { pub primitive_instance_import_path: Option<String>, pub properties_coproduct_variant: String, pub component_properties_struct: String, - pub properties: Vec<(String, String)>, + pub defined_properties: Vec<(String, String)>, //0: property id (e.g. "width"), 1: property value literal RIL (e.g. "None" or "Some(Rc::new(...))" pub common_properties_literal: Vec<(String, String)>, pub children_literal: Vec<String>, @@ -134,10 +135,14 @@ pub fn press_template_codegen_cartridge_render_node_literal( .unwrap() .contents_utf8() .unwrap(); - Tera::one_off( - template.into(), - &tera::Context::from_serialize(args).unwrap(), - false, + + let mut tera = Tera::default(); + tera.add_raw_template("cartridge-render-node-literal", template).unwrap(); + + tera.render( + "cartridge-render-node-literal", + &Context::from_serialize(args).unwrap(), ) - .unwrap() + .unwrap() } + diff --git a/pax-compiler/templates/cartridge-render-node-literal.tera b/pax-compiler/templates/cartridge-render-node-literal.tera index dbd47d7a1..4f760daba 100644 --- a/pax-compiler/templates/cartridge-render-node-literal.tera +++ b/pax-compiler/templates/cartridge-render-node-literal.tera @@ -12,11 +12,17 @@ instantiate_{{ snake_case_type_id }}( Rc::clone(&instance_registry), }, properties: PropertiesCoproduct::{{ properties_coproduct_variant }} {% if properties_coproduct_variant != "None" %} - ( {{component_properties_struct}} { - {% for property in properties %} - {{ property.0 }}: Box::new( {{ property.1 }} ), - {% endfor %} - }) + ( + { + let mut cps = {{component_properties_struct}}::default(); + + {% for property in defined_properties %} + cps.{{ property.0 }} = Box::new( {{ property.1 }} ); + {% endfor %} + + cps + } + ) {% endif %}, handler_registry: Some(Rc::new(RefCell::new({ #[allow(unused_mut)] diff --git a/pax-example/src/website_desktop.pax b/pax-example/src/website_desktop.pax index 21a016cb4..15f4eeb50 100644 --- a/pax-example/src/website_desktop.pax +++ b/pax-example/src/website_desktop.pax @@ -22,7 +22,7 @@ // Scrolling content pane <Scroller width=100% height=100% size_inner_pane_x=100% size_inner_pane_y=5000px scroll_enabled_x=false scroll_enabled_y=true> - <Stacker cells=5 direction=StackerDirection::Vertical gutter=0px> + <Stacker cells=5 direction=StackerDirection::Vertical> <Group> <Frame id=f1> <Stacker cells=2 direction=StackerDirection::Vertical gutter=20px sizes={[Option::Some(70%), Option::None]} > diff --git a/pax-example/src/website_mobile.pax b/pax-example/src/website_mobile.pax index e3b51911d..25868ca95 100644 --- a/pax-example/src/website_mobile.pax +++ b/pax-example/src/website_mobile.pax @@ -20,7 +20,7 @@ // Scrolling content pane <Scroller width=100% height=100% size_inner_pane_x=100% size_inner_pane_y=500% scroll_enabled_x=false scroll_enabled_y=true> - <Stacker cells=5 direction=StackerDirection::Vertical gutter=0px> + <Stacker cells=5 direction=StackerDirection::Vertical > <Frame id=f0> <Frame id=f1> <Stacker cells=2 direction=StackerDirection::Vertical gutter=10px sizes={[Option::Some(70%), Option::None]} > @@ -37,7 +37,7 @@ </Frame> <Frame id=f0> <Frame id=f2> - <Stacker cells=3 direction=StackerDirection::Vertical gutter=0px sizes={[Option::None, Option::Some(40%), Option::None]}> + <Stacker cells=3 direction=StackerDirection::Vertical sizes={[Option::None, Option::Some(40%), Option::None]}> <Text text="BUILD CREATIVELY" class=h2/> <Text text="Pax renders in the same coordinate space as a tool like Photoshop or Figma, with the addition of responsive positioning & sizing, as well as a fine-grained animation engine." class=p2 /> <Text text="Create and compose custom components into apps. Write application logic in Rust, while describing content & style in Pax’s declarative UI language." class=p2 /> diff --git a/pax-std/src/stacker.rs b/pax-std/src/stacker.rs index 7499b950e..370c67d66 100644 --- a/pax-std/src/stacker.rs +++ b/pax-std/src/stacker.rs @@ -3,13 +3,15 @@ use crate::types::{StackerCell, StackerDirection}; use pax_lang::api::numeric::Numeric; use pax_lang::api::{Property, Size, Transform2D}; use pax_lang::*; -use pax_runtime_api::RuntimeContext; +use pax_runtime_api::{RuntimeContext, PropertyLiteral}; + /// Stacker lays out a series of nodes either /// vertically or horizontally (i.e. a single row or column) with a specified gutter in between /// each node. `Stacker`s can be stacked inside of each other, horizontally /// and vertically, along with `Transform.align` and `Transform.anchor` to compose any rectilinear 2D layout. #[derive(Pax)] +#[custom(Default)] #[inlined( for (cell_spec, i) in self._cell_specs { <Frame @@ -37,6 +39,18 @@ pub struct Stacker { pub sizes: Property<Vec<Option<Size>>>, } +impl Default for Stacker { + fn default() -> Self { + Self { + cells: Box::new(PropertyLiteral::new(1.into())), + direction: Box::new(PropertyLiteral::new(StackerDirection::Horizontal)), + _cell_specs: Box::new(PropertyLiteral::new(vec![])), + gutter: Box::new(PropertyLiteral::new(Size::Pixels(Numeric::Integer(0)))), + sizes: Box::new(PropertyLiteral::new(vec![])), + } + } +} + impl Stacker { pub fn handle_will_render(&mut self, ctx: RuntimeContext) { let cells = self.cells.get().get_as_float();