diff --git a/docs b/docs index 8569b289a..c748d9031 160000 --- a/docs +++ b/docs @@ -1 +1 @@ -Subproject commit 8569b289aa1d9015bc88b3d2d5b5f8f88496c89e +Subproject commit c748d9031b40f1854fc65179b61693f69a7280f0 diff --git a/examples/src/fireworks/src/lib.rs b/examples/src/fireworks/src/lib.rs index 72697f760..50296077e 100644 --- a/examples/src/fireworks/src/lib.rs +++ b/examples/src/fireworks/src/lib.rs @@ -1,3 +1,4 @@ +#![allow(unused_imports)] use pax_lang::api::{ArgsClick, ArgsWheel, EasingCurve, NodeContext}; use pax_lang::*; use pax_std::primitives::{Ellipse, Frame, Group, Path, Rectangle, Text}; @@ -13,13 +14,13 @@ pub struct Fireworks { const ROTATION_COEFFICIENT: f64 = 0.00010; impl Fireworks { - pub fn handle_scroll(&mut self, ctx: &NodeContext, args: ArgsWheel) { + pub fn handle_scroll(&mut self, _ctx: &NodeContext, args: ArgsWheel) { let old_t = self.rotation.get(); let new_t = old_t - args.delta_y * ROTATION_COEFFICIENT; self.rotation.set(f64::max(0.0, new_t)); } - pub fn handle_pre_render(&mut self, ctx: &NodeContext) { + pub fn handle_pre_render(&mut self, _ctx: &NodeContext) { let old_ticks = self.ticks.get(); self.ticks.set(old_ticks + 1); } diff --git a/pax-chassis-web/interface/src/index.ts b/pax-chassis-web/interface/src/index.ts index 7d15a706a..ad0069330 100644 --- a/pax-chassis-web/interface/src/index.ts +++ b/pax-chassis-web/interface/src/index.ts @@ -61,7 +61,7 @@ async function loadWasmModule(extensionlessUrl: string): Promise<{ chassis: PaxC const wasmBinary = await fetch(`${extensionlessUrl}_bg.wasm`); const wasmArrayBuffer = await wasmBinary.arrayBuffer(); - let _io = glueCodeModule.initSync(wasmArrayBuffer); + let _io = await glueCodeModule.default(wasmArrayBuffer); let chassis = glueCodeModule.PaxChassisWeb.new(); let get_latest_memory = glueCodeModule.wasm_memory; diff --git a/pax-chassis-web/interface/src/types/pax-chassis-web.d.ts b/pax-chassis-web/interface/src/types/pax-chassis-web.d.ts index 0d0815e31..df54f87f9 100644 --- a/pax-chassis-web/interface/src/types/pax-chassis-web.d.ts +++ b/pax-chassis-web/interface/src/types/pax-chassis-web.d.ts @@ -97,4 +97,4 @@ export function initSync(module: SyncInitInput): InitOutput; * * @returns {Promise} */ -export default function __wbg_init (module_or_path?: InitInput | Promise): Promise; +export default function __wbg_init (module_or_path?: InitInput | Promise): Promise; \ No newline at end of file diff --git a/pax-chassis-web/package-lock.json b/pax-chassis-web/package-lock.json index 820a7188d..06ce343a7 100644 --- a/pax-chassis-web/package-lock.json +++ b/pax-chassis-web/package-lock.json @@ -2,5 +2,408 @@ "name": "pax-chassis-web", "lockfileVersion": 3, "requires": true, - "packages": {} + "packages": { + "": { + "dependencies": { + "snarkdown": "^2.0.0" + }, + "devDependencies": { + "esbuild": "0.19.8" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.19.8", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.19.8.tgz", + "integrity": "sha512-31E2lxlGM1KEfivQl8Yf5aYU/mflz9g06H6S15ITUFQueMFtFjESRMoDSkvMo8thYvLBax+VKTPlpnx+sPicOA==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.19.8", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.19.8.tgz", + "integrity": "sha512-B8JbS61bEunhfx8kasogFENgQfr/dIp+ggYXwTqdbMAgGDhRa3AaPpQMuQU0rNxDLECj6FhDzk1cF9WHMVwrtA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.19.8", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.19.8.tgz", + "integrity": "sha512-rdqqYfRIn4jWOp+lzQttYMa2Xar3OK9Yt2fhOhzFXqg0rVWEfSclJvZq5fZslnz6ypHvVf3CT7qyf0A5pM682A==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.19.8", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.19.8.tgz", + "integrity": "sha512-RQw9DemMbIq35Bprbboyf8SmOr4UXsRVxJ97LgB55VKKeJOOdvsIPy0nFyF2l8U+h4PtBx/1kRf0BelOYCiQcw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.19.8", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.19.8.tgz", + "integrity": "sha512-3sur80OT9YdeZwIVgERAysAbwncom7b4bCI2XKLjMfPymTud7e/oY4y+ci1XVp5TfQp/bppn7xLw1n/oSQY3/Q==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.19.8", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.19.8.tgz", + "integrity": "sha512-WAnPJSDattvS/XtPCTj1tPoTxERjcTpH6HsMr6ujTT+X6rylVe8ggxk8pVxzf5U1wh5sPODpawNicF5ta/9Tmw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.19.8", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.19.8.tgz", + "integrity": "sha512-ICvZyOplIjmmhjd6mxi+zxSdpPTKFfyPPQMQTK/w+8eNK6WV01AjIztJALDtwNNfFhfZLux0tZLC+U9nSyA5Zg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.19.8", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.19.8.tgz", + "integrity": "sha512-H4vmI5PYqSvosPaTJuEppU9oz1dq2A7Mr2vyg5TF9Ga+3+MGgBdGzcyBP7qK9MrwFQZlvNyJrvz6GuCaj3OukQ==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.19.8", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.19.8.tgz", + "integrity": "sha512-z1zMZivxDLHWnyGOctT9JP70h0beY54xDDDJt4VpTX+iwA77IFsE1vCXWmprajJGa+ZYSqkSbRQ4eyLCpCmiCQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.19.8", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.19.8.tgz", + "integrity": "sha512-1a8suQiFJmZz1khm/rDglOc8lavtzEMRo0v6WhPgxkrjcU0LkHj+TwBrALwoz/OtMExvsqbbMI0ChyelKabSvQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.19.8", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.19.8.tgz", + "integrity": "sha512-fHZWS2JJxnXt1uYJsDv9+b60WCc2RlvVAy1F76qOLtXRO+H4mjt3Tr6MJ5l7Q78X8KgCFudnTuiQRBhULUyBKQ==", + "cpu": [ + "loong64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.19.8", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.19.8.tgz", + "integrity": "sha512-Wy/z0EL5qZYLX66dVnEg9riiwls5IYnziwuju2oUiuxVc+/edvqXa04qNtbrs0Ukatg5HEzqT94Zs7J207dN5Q==", + "cpu": [ + "mips64el" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.19.8", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.19.8.tgz", + "integrity": "sha512-ETaW6245wK23YIEufhMQ3HSeHO7NgsLx8gygBVldRHKhOlD1oNeNy/P67mIh1zPn2Hr2HLieQrt6tWrVwuqrxg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.19.8", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.19.8.tgz", + "integrity": "sha512-T2DRQk55SgoleTP+DtPlMrxi/5r9AeFgkhkZ/B0ap99zmxtxdOixOMI570VjdRCs9pE4Wdkz7JYrsPvsl7eESg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.19.8", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.19.8.tgz", + "integrity": "sha512-NPxbdmmo3Bk7mbNeHmcCd7R7fptJaczPYBaELk6NcXxy7HLNyWwCyDJ/Xx+/YcNH7Im5dHdx9gZ5xIwyliQCbg==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.19.8", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.19.8.tgz", + "integrity": "sha512-lytMAVOM3b1gPypL2TRmZ5rnXl7+6IIk8uB3eLsV1JwcizuolblXRrc5ShPrO9ls/b+RTp+E6gbsuLWHWi2zGg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.19.8", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.19.8.tgz", + "integrity": "sha512-hvWVo2VsXz/8NVt1UhLzxwAfo5sioj92uo0bCfLibB0xlOmimU/DeAEsQILlBQvkhrGjamP0/el5HU76HAitGw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.19.8", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.19.8.tgz", + "integrity": "sha512-/7Y7u77rdvmGTxR83PgaSvSBJCC2L3Kb1M/+dmSIvRvQPXXCuC97QAwMugBNG0yGcbEGfFBH7ojPzAOxfGNkwQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.19.8", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.19.8.tgz", + "integrity": "sha512-9Lc4s7Oi98GqFA4HzA/W2JHIYfnXbUYgekUP/Sm4BG9sfLjyv6GKKHKKVs83SMicBF2JwAX6A1PuOLMqpD001w==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.19.8", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.19.8.tgz", + "integrity": "sha512-rq6WzBGjSzihI9deW3fC2Gqiak68+b7qo5/3kmB6Gvbh/NYPA0sJhrnp7wgV4bNwjqM+R2AApXGxMO7ZoGhIJg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.19.8", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.19.8.tgz", + "integrity": "sha512-AIAbverbg5jMvJznYiGhrd3sumfwWs8572mIJL5NQjJa06P8KfCPWZQ0NwZbPQnbQi9OWSZhFVSUWjjIrn4hSw==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.19.8", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.19.8.tgz", + "integrity": "sha512-bfZ0cQ1uZs2PqpulNL5j/3w+GDhP36k1K5c38QdQg+Swy51jFZWWeIkteNsufkQxp986wnqRRsb/bHbY1WQ7TA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild": { + "version": "0.19.8", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.19.8.tgz", + "integrity": "sha512-l7iffQpT2OrZfH2rXIp7/FkmaeZM0vxbxN9KfiCwGYuZqzMg/JdvX26R31Zxn/Pxvsrg3Y9N6XTcnknqDyyv4w==", + "dev": true, + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/android-arm": "0.19.8", + "@esbuild/android-arm64": "0.19.8", + "@esbuild/android-x64": "0.19.8", + "@esbuild/darwin-arm64": "0.19.8", + "@esbuild/darwin-x64": "0.19.8", + "@esbuild/freebsd-arm64": "0.19.8", + "@esbuild/freebsd-x64": "0.19.8", + "@esbuild/linux-arm": "0.19.8", + "@esbuild/linux-arm64": "0.19.8", + "@esbuild/linux-ia32": "0.19.8", + "@esbuild/linux-loong64": "0.19.8", + "@esbuild/linux-mips64el": "0.19.8", + "@esbuild/linux-ppc64": "0.19.8", + "@esbuild/linux-riscv64": "0.19.8", + "@esbuild/linux-s390x": "0.19.8", + "@esbuild/linux-x64": "0.19.8", + "@esbuild/netbsd-x64": "0.19.8", + "@esbuild/openbsd-x64": "0.19.8", + "@esbuild/sunos-x64": "0.19.8", + "@esbuild/win32-arm64": "0.19.8", + "@esbuild/win32-ia32": "0.19.8", + "@esbuild/win32-x64": "0.19.8" + } + }, + "node_modules/snarkdown": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/snarkdown/-/snarkdown-2.0.0.tgz", + "integrity": "sha512-MgL/7k/AZdXCTJiNgrO7chgDqaB9FGM/1Tvlcenenb7div6obaDATzs16JhFyHHBGodHT3B7RzRc5qk8pFhg3A==" + } + } } diff --git a/pax-chassis-web/src/lib.rs b/pax-chassis-web/src/lib.rs index c7dbd1690..1947d9d9a 100644 --- a/pax-chassis-web/src/lib.rs +++ b/pax-chassis-web/src/lib.rs @@ -66,7 +66,7 @@ pub struct PaxChassisWeb { drawing_contexts: Renderer>, engine: Rc>, #[cfg(feature = "designtime")] - _designtime: Rc>, + definition_to_instance_traverser: pax_cartridge::DefinitionToInstanceTraverser, } #[wasm_bindgen] @@ -86,19 +86,21 @@ impl PaxChassisWeb { #[cfg(feature = "designtime")] { - let designtime = Rc::new(RefCell::new(pax_cartridge::instantiate_designtime_manager())); + let mut definition_to_instance_traverser = + pax_cartridge::DefinitionToInstanceTraverser::new(); + let main_component_instance = definition_to_instance_traverser.get_main_component(); let engine = pax_core::PaxEngine::new_with_designtime( main_component_instance, expression_table, pax_runtime_api::PlatformSpecificLogger::Web(log_wrapper), (width, height), - designtime.clone(), + definition_to_instance_traverser.get_designtime_manager(), ); let engine_container: Rc> = Rc::new(RefCell::new(engine)); Self { engine: engine_container, drawing_contexts: Renderer::new(), - _designtime: designtime, + definition_to_instance_traverser, } } #[cfg(not(feature = "designtime"))] diff --git a/pax-compiler/Cargo.toml b/pax-compiler/Cargo.toml index a3677f607..a320e6f62 100644 --- a/pax-compiler/Cargo.toml +++ b/pax-compiler/Cargo.toml @@ -16,7 +16,7 @@ include = [ [features] -default = ["console_error_panic_hook","json"] +default = ["console_error_panic_hook","json", "pax-manifest/parsing"] json = ["serde_json"] [lib] diff --git a/pax-compiler/src/building/mod.rs b/pax-compiler/src/building/mod.rs index e7f4dfc1c..f4e12b5da 100644 --- a/pax-compiler/src/building/mod.rs +++ b/pax-compiler/src/building/mod.rs @@ -5,7 +5,7 @@ use flate2::read::GzDecoder; use libc::EXIT_FAILURE; -use pax_manifest::PaxManifest; +use pax_manifest::{HostCrateInfo, PaxManifest}; use std::{ collections::HashMap, fs, @@ -19,7 +19,7 @@ use tar::Archive; use crate::{ errors::source_map::SourceMap, - helpers::{copy_dir_recursively, HostCrateInfo, ALL_PKGS, DIR_IGNORE_LIST_MACOS, PKG_DIR_NAME}, + helpers::{copy_dir_recursively, ALL_PKGS, DIR_IGNORE_LIST_MACOS, PKG_DIR_NAME}, RunContext, RunTarget, }; @@ -85,27 +85,44 @@ pub fn build_chassis_with_cartridge( Ok(()) } -pub fn update_property_prefixes_in_place( +pub fn update_type_id_prefixes_in_place( manifest: &mut PaxManifest, host_crate_info: &HostCrateInfo, ) { + manifest.main_component_type_id = + host_crate_info.fully_qualify_path(&manifest.main_component_type_id); let mut updated_type_table = HashMap::new(); manifest.type_table.iter_mut().for_each(|t| { t.1.type_id_escaped = t.1.type_id_escaped.replace("{PREFIX}", ""); - t.1.type_id = - t.1.type_id - .replace("{PREFIX}", &host_crate_info.import_prefix); + t.1.type_id = host_crate_info.fully_qualify_path(&t.1.type_id); + if let Some(inner) = &t.1.inner_iterable_type_id { + t.1.inner_iterable_type_id = Some(host_crate_info.fully_qualify_path(&inner)); + } t.1.property_definitions.iter_mut().for_each(|pd| { - pd.type_id = pd - .type_id - .replace("{PREFIX}", &host_crate_info.import_prefix); + pd.type_id = host_crate_info.fully_qualify_path(&pd.type_id); + pd.type_id_escaped = pd.type_id_escaped.replace("{PREFIX}", ""); }); - updated_type_table.insert( - t.0.replace("{PREFIX}", &host_crate_info.import_prefix), - t.1.clone(), - ); + updated_type_table.insert(host_crate_info.fully_qualify_path(&t.0), t.1.clone()); }); std::mem::swap(&mut manifest.type_table, &mut updated_type_table); + + let mut updated_component_table = HashMap::new(); + manifest.components.iter_mut().for_each(|c| { + c.1.type_id = host_crate_info.fully_qualify_path(&c.1.type_id); + c.1.type_id_escaped = c.1.type_id_escaped.replace("{PREFIX}", ""); + + let mut updated_template_table = HashMap::new(); + if let Some(template) = c.1.template.as_mut() { + template.iter_mut().for_each(|t| { + t.1.type_id = host_crate_info.fully_qualify_path(&t.1.type_id); + updated_template_table.insert(t.0.clone(), t.1.clone()); + }); + c.1.template = Some(updated_template_table); + } + + updated_component_table.insert(host_crate_info.fully_qualify_path(&c.0), c.1.clone()); + }); + std::mem::swap(&mut manifest.components, &mut updated_component_table); } /// Clone all dependencies to `.pax/pkg`. Similar in spirit to the Cargo package cache, diff --git a/pax-compiler/src/cartridge_generation/mod.rs b/pax-compiler/src/cartridge_generation/mod.rs index 3e0a3cb5d..78b8cd6e9 100644 --- a/pax-compiler/src/cartridge_generation/mod.rs +++ b/pax-compiler/src/cartridge_generation/mod.rs @@ -3,8 +3,7 @@ //! The `code_generation` module provides structures and functions for generating Pax Cartridges //! from Pax Manifests. The `generate_and_overwrite_cartridge` function is the main entrypoint. -use crate::helpers::{HostCrateInfo, PKG_DIR_NAME}; -use crate::parsing; +use crate::helpers::PKG_DIR_NAME; use itertools::Itertools; use pax_runtime_api::CommonProperties; use std::borrow::Borrow; @@ -13,7 +12,7 @@ use std::fs; use std::str::FromStr; use pax_manifest::{ - escape_identifier, ComponentDefinition, ExpressionSpec, HandlersBlockElement, + escape_identifier, ComponentDefinition, ExpressionSpec, HandlersBlockElement, HostCrateInfo, LiteralBlockDefinition, MappedString, PaxManifest, SettingElement, TemplateNodeDefinition, Token, TypeDefinition, TypeTable, ValueDefinition, }; @@ -30,15 +29,6 @@ use self::templating::{ pub mod templating; -#[cfg(feature = "designtime")] -use pax_designtime::cartridge_generation::{ - press_template_codegen_designtime_cartridge, TemplateArgsCodegenDesigntimeCartridge, -}; -#[cfg(feature = "designtime")] -fn press_designtime_template() -> String { - press_template_codegen_designtime_cartridge(TemplateArgsCodegenDesigntimeCartridge {}) -} - pub fn generate_and_overwrite_cartridge( pax_dir: &PathBuf, manifest: &PaxManifest, @@ -90,7 +80,7 @@ pub fn generate_and_overwrite_cartridge( .collect(); imports.append( - &mut crate::helpers::IMPORTS_BUILTINS + &mut pax_manifest::IMPORTS_BUILTINS .into_iter() .map(|ib| ib.to_string()) .collect::>(), @@ -128,9 +118,15 @@ pub fn generate_and_overwrite_cartridge( #[cfg(feature = "designtime")] { - let path = target_dir.join("initial_manifest.json"); + // things I need to pass to press_design_template + // host crate info + // manifest + let path = target_dir.join(pax_designtime::INITIAL_MANIFEST_FILE_NAME); fs::write(path.clone(), serde_json::to_string(manifest).unwrap()).unwrap(); - generated_lib_rs += &press_designtime_template(); + generated_lib_rs += &pax_designtime::cartridge_generation::generate_designtime_cartridge( + manifest, + host_crate_info, + ); } // Re: formatting the generated Rust code, see prior art at `_format_generated_lib_rs` @@ -156,7 +152,7 @@ fn generate_cartridge_render_nodes_literal( .filter(|child_id| { let tnd_map = rngc.active_component_definition.template.as_ref().unwrap(); let active_tnd = &tnd_map[*child_id]; - active_tnd.type_id != parsing::TYPE_ID_COMMENT + active_tnd.type_id != pax_manifest::TYPE_ID_COMMENT }) .map(|child_id| { let tnd_map = rngc.active_component_definition.template.as_ref().unwrap(); @@ -297,7 +293,7 @@ fn recurse_generate_render_nodes_literal( .filter(|child_id| { let tnd_map = rngc.active_component_definition.template.as_ref().unwrap(); let active_tnd = &tnd_map[*child_id]; - active_tnd.type_id != parsing::TYPE_ID_COMMENT + active_tnd.type_id != pax_manifest::TYPE_ID_COMMENT }) .map(|child_id| { let active_tnd = &rngc.active_component_definition.template.as_ref().unwrap()[child_id]; @@ -312,7 +308,7 @@ fn recurse_generate_render_nodes_literal( //in the context of cartridge-render-node-literal so `"()"` is suitable const CONTROL_FLOW_STUBBED_PROPERTIES_TYPE: &str = "()"; - let args = if tnd.type_id == parsing::TYPE_ID_REPEAT { + let args = if tnd.type_id == pax_manifest::TYPE_ID_REPEAT { // Repeat let rsd = tnd .control_flow_settings @@ -382,7 +378,7 @@ fn recurse_generate_render_nodes_literal( fully_qualified_properties_type: CONTROL_FLOW_STUBBED_PROPERTIES_TYPE.to_string(), containing_component_struct, } - } else if tnd.type_id == parsing::TYPE_ID_IF { + } else if tnd.type_id == pax_manifest::TYPE_ID_IF { // If let id = tnd .control_flow_settings @@ -437,7 +433,7 @@ fn recurse_generate_render_nodes_literal( fully_qualified_properties_type: CONTROL_FLOW_STUBBED_PROPERTIES_TYPE.to_string(), containing_component_struct, } - } else if tnd.type_id == parsing::TYPE_ID_SLOT { + } else if tnd.type_id == pax_manifest::TYPE_ID_SLOT { // Slot let id = tnd .control_flow_settings @@ -502,6 +498,9 @@ 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(...`_ + if let None = rngc.components.get(&tnd.type_id) { + panic!("Component {} not found in components map", tnd.type_id); + } let component_for_current_node = rngc.components.get(&tnd.type_id).unwrap(); let fully_qualified_properties_type = host_crate_info.fully_qualify_path(&component_for_current_node.type_id); diff --git a/pax-compiler/src/expressions.rs b/pax-compiler/src/expressions.rs index f1060de3d..50825b319 100644 --- a/pax-compiler/src/expressions.rs +++ b/pax-compiler/src/expressions.rs @@ -1,8 +1,8 @@ use pax_manifest::{ escape_identifier, ComponentDefinition, ControlFlowRepeatPredicateDefinition, ExpressionSpec, - ExpressionSpecInvocation, PaxManifest, PropertyDefinition, PropertyDefinitionFlags, - SettingElement, SettingsBlockElement, TemplateNodeDefinition, Token, TypeDefinition, TypeTable, - ValueDefinition, + ExpressionSpecInvocation, HostCrateInfo, PaxManifest, PropertyDefinition, + PropertyDefinitionFlags, SettingElement, TemplateNodeDefinition, Token, TypeDefinition, + TypeTable, ValueDefinition, }; use std::collections::HashMap; use std::ops::RangeFrom; @@ -10,7 +10,6 @@ use std::slice::IterMut; use crate::errors::source_map::SourceMap; use crate::errors::PaxTemplateError; -use crate::helpers::HostCrateInfo; use color_eyre::eyre; use color_eyre::eyre::Report; use lazy_static::lazy_static; @@ -64,109 +63,6 @@ pub fn compile_all_expressions<'a>( Ok(()) } -fn pull_matched_identifiers_from_inline( - inline_settings: &Option>, - s: String, -) -> Vec { - let mut ret = Vec::new(); - if let Some(val) = inline_settings { - let matched_settings = val.iter().filter(|e| match e { - SettingElement::Setting(token, _) => token.token_value == s.as_str(), - _ => false, - }); - for e in matched_settings { - if let SettingElement::Setting(_, value) = e { - match value { - ValueDefinition::Identifier(s, _) => ret.push(s.clone()), - _ => {} - }; - } - } - } - ret -} - -fn pull_settings_with_selector( - settings: &Option>, - selector: String, -) -> Option> { - settings.as_ref().and_then(|val| { - let mut merged_setting = Vec::new(); - for settings_value in val.iter() { - match settings_value { - SettingsBlockElement::SelectorBlock(token, value) => { - if token.token_value == selector { - merged_setting.extend(value.elements.clone()); - } - } - _ => {} - } - } - (!merged_setting.is_empty()).then(|| merged_setting) - }) -} - -fn merge_inline_settings_with_settings_block( - inline_settings: &Option>, - settings_block: &Option>, -) -> Option> { - // collect id settings - let ids = pull_matched_identifiers_from_inline(&inline_settings, "id".to_string()); - - let mut id_settings = Vec::new(); - if ids.len() == 1 { - if let Some(settings) = - pull_settings_with_selector(&settings_block, format!("#{}", ids[0].token_value)) - { - id_settings.extend(settings.clone()); - } - } else if ids.len() > 1 { - panic!("Specified more than one id inline!"); - } - - // collect all class settings - let classes = pull_matched_identifiers_from_inline(&inline_settings, "class".to_string()); - - let mut class_settings = Vec::new(); - for class in classes { - if let Some(settings) = - pull_settings_with_selector(&settings_block, format!(".{}", class.token_value)) - { - class_settings.extend(settings.clone()); - } - } - - let mut map = HashMap::new(); - - // Iterate in reverse order of priority (class, then id, then inline) - for e in class_settings.into_iter() { - if let SettingElement::Setting(key, _) = e.clone() { - map.insert(key, e); - } - } - - for e in id_settings.into_iter() { - if let SettingElement::Setting(key, _) = e.clone() { - map.insert(key, e); - } - } - - if let Some(inline) = inline_settings.clone() { - for e in inline.into_iter() { - if let SettingElement::Setting(key, _) = e.clone() { - map.insert(key, e); - } - } - } - let merged: Vec = map.values().cloned().collect(); - - if merged.len() > 0 { - Some(merged) - } else { - None - } -} - fn recurse_compile_literal_block<'a>( settings_pairs: &mut IterMut, ctx: &mut ExpressionCompilationContext, @@ -279,8 +175,10 @@ fn recurse_compile_expressions<'a>( let cloned_settings_block = ctx.component_def.settings.clone(); let cloned_inline_settings = ctx.active_node_def.settings.clone(); - let mut merged_settings = - merge_inline_settings_with_settings_block(&cloned_inline_settings, &cloned_settings_block); + let mut merged_settings = PaxManifest::merge_inline_settings_with_settings_block( + &cloned_inline_settings, + &cloned_settings_block, + ); let mut cloned_control_flow_settings = ctx.active_node_def.control_flow_settings.clone(); if let Some(ref mut inline_settings) = merged_settings { @@ -413,8 +311,10 @@ fn recurse_compile_expressions<'a>( is_repeat_source_range, is_repeat_source_iterable, is_property_wrapped: true, + is_enum: false, }, type_id: iterable_type.type_id.clone(), + type_id_escaped: iterable_type.type_id_escaped.clone(), }; let scope: HashMap = HashMap::from([ @@ -429,12 +329,14 @@ fn recurse_compile_expressions<'a>( let elem_property_definition = PropertyDefinition { name: format!("{}", elem_id.token_value), type_id: iterable_type.type_id, + type_id_escaped: iterable_type.type_id_escaped, flags: PropertyDefinitionFlags { is_binding_repeat_elem: true, is_binding_repeat_i: false, is_repeat_source_range: is_repeat_source_range.clone(), is_repeat_source_iterable: is_repeat_source_iterable.clone(), is_property_wrapped: true, + is_enum: false, }, }; @@ -446,6 +348,7 @@ fn recurse_compile_expressions<'a>( is_repeat_source_range, is_repeat_source_iterable, is_property_wrapped: true, + is_enum: false, }; incremented = true; diff --git a/pax-compiler/src/helpers.rs b/pax-compiler/src/helpers.rs index d012a06a5..d805a5abf 100644 --- a/pax-compiler/src/helpers.rs +++ b/pax-compiler/src/helpers.rs @@ -1,8 +1,8 @@ use colored::{ColoredString, Colorize}; use include_dir::{include_dir, Dir}; use lazy_static::lazy_static; +use pax_manifest::HostCrateInfo; use pax_runtime_api::serde::Deserialize; -use std::collections::HashSet; use std::fs; use std::path::{Path, PathBuf}; use std::process::Command; @@ -283,60 +283,6 @@ pub fn copy_dir_recursively( Ok(()) } -/// Pulled from host Cargo.toml -pub struct HostCrateInfo { - /// for example: `pax-example` - pub name: String, - /// for example: `pax_example` - pub identifier: String, - /// for example: `some_crate::pax_reexports`, - pub import_prefix: String, -} - -pub const IMPORTS_BUILTINS: [&str; 28] = [ - "std::any::Any", - "std::cell::RefCell", - "std::collections::HashMap", - "std::collections::VecDeque", - "std::ops::Deref", - "std::rc::Rc", - "pax_core::RepeatItem", - "pax_core::RepeatProperties", - "pax_core::ConditionalProperties", - "pax_core::SlotProperties", - "pax_core::get_numeric_from_wrapped_properties", - "pax_runtime_api::PropertyInstance", - "pax_runtime_api::PropertyLiteral", - "pax_runtime_api::CommonProperties", - "pax_core::ComponentInstance", - "pax_core::InstanceNodePtr", - "pax_core::PropertyExpression", - "pax_core::InstanceNodePtrList", - "pax_core::ExpressionContext", - "pax_core::PaxEngine", - "pax_core::InstanceNode", - "pax_core::HandlerRegistry", - "pax_core::InstantiationArgs", - "pax_core::ConditionalInstance", - "pax_core::SlotInstance", - "pax_core::properties::RuntimePropertiesStackFrame", - "pax_core::repeat::RepeatInstance", - "piet_common::RenderContext", -]; - -impl<'a> HostCrateInfo { - pub fn fully_qualify_path(&self, path: &str) -> String { - #[allow(non_snake_case)] - let IMPORT_PREFIX = format!("{}::pax_reexports::", self.identifier); - let imports_builtins_set: HashSet<&str> = IMPORTS_BUILTINS.into_iter().collect(); - if !imports_builtins_set.contains(path) { - IMPORT_PREFIX.clone() + &path.replace("crate::", "") - } else { - "".to_string() - } - } -} - pub fn get_host_crate_info(cargo_toml_path: &Path) -> HostCrateInfo { let existing_cargo_toml = toml_edit::Document::from_str( &fs::read_to_string(fs::canonicalize(cargo_toml_path).unwrap()).unwrap(), diff --git a/pax-compiler/src/lib.rs b/pax-compiler/src/lib.rs index 82fe941a0..096bea41b 100644 --- a/pax-compiler/src/lib.rs +++ b/pax-compiler/src/lib.rs @@ -10,7 +10,6 @@ //! extern crate core; - mod building; mod cartridge_generation; pub mod errors; @@ -34,7 +33,7 @@ use std::sync::{Arc, Mutex}; use std::os::unix::process::CommandExt; use crate::building::{ - build_chassis_with_cartridge, clone_all_to_pkg_dir, update_property_prefixes_in_place, + build_chassis_with_cartridge, clone_all_to_pkg_dir, update_type_id_prefixes_in_place, }; use crate::cartridge_generation::generate_and_overwrite_cartridge; @@ -139,10 +138,9 @@ pub fn perform_build(ctx: &RunContext) -> eyre::Result<(), Report> { let out = String::from_utf8(output.stdout).unwrap(); let mut manifest: PaxManifest = serde_json::from_str(&out).expect(&format!("Malformed JSON from parser: {}", &out)); - let host_cargo_toml_path = Path::new(&ctx.path).join("Cargo.toml"); let host_crate_info = get_host_crate_info(&host_cargo_toml_path); - update_property_prefixes_in_place(&mut manifest, &host_crate_info); + update_type_id_prefixes_in_place(&mut manifest, &host_crate_info); let mut source_map = SourceMap::new(); diff --git a/pax-compiler/src/parsing.rs b/pax-compiler/src/parsing.rs index 8d7e48cc2..da14e2b05 100644 --- a/pax-compiler/src/parsing.rs +++ b/pax-compiler/src/parsing.rs @@ -3,7 +3,7 @@ use std::collections::{HashMap, HashSet}; use std::rc::Rc; use itertools::{Itertools, MultiPeek}; -use pax_manifest::escape_identifier; +use pax_manifest::{escape_identifier, TYPE_ID_COMMENT, TYPE_ID_IF, TYPE_ID_REPEAT, TYPE_ID_SLOT}; use std::ops::RangeFrom; use pax_manifest::{ @@ -356,11 +356,6 @@ struct TemplateNodeParseContext { pub uid_gen: MultiPeek>, } -pub static TYPE_ID_IF: &str = "IF"; -pub static TYPE_ID_REPEAT: &str = "REPEAT"; -pub static TYPE_ID_SLOT: &str = "SLOT"; -pub static TYPE_ID_COMMENT: &str = "COMMENT"; - fn recurse_visit_tag_pairs_for_template( ctx: &mut TemplateNodeParseContext, any_tag_pair: Pair, @@ -1494,16 +1489,6 @@ impl Reflectable for pax_runtime_api::Numeric { } } -impl Reflectable for pax_runtime_api::SizePixels { - fn get_import_path() -> String { - "pax_lang::api::SizePixels".to_string() - } - - fn get_self_pascal_identifier() -> String { - "SizePixels".to_string() - } -} - impl Reflectable for kurbo::Point { fn get_import_path() -> String { "kurbo::Point".to_string() diff --git a/pax-compiler/templates/cartridge_generation/cartridge-component-factory.tera b/pax-compiler/templates/cartridge_generation/cartridge-component-factory.tera index 10a295c31..531cbbbfa 100644 --- a/pax-compiler/templates/cartridge_generation/cartridge-component-factory.tera +++ b/pax-compiler/templates/cartridge_generation/cartridge-component-factory.tera @@ -43,7 +43,6 @@ pub fn instantiate_main_component() -> Rc { }))), children: None, component_template: Some(vec![{{render_nodes_literal}}]), - scroller_args: None, compute_properties_fn: Some(Box::new(|node, table, globals|{ let props = &node.properties; let properties = &mut props.as_ref().borrow_mut(); diff --git a/pax-compiler/templates/cartridge_generation/cartridge-render-node-literal.tera b/pax-compiler/templates/cartridge_generation/cartridge-render-node-literal.tera index fe132e0b8..7046f8104 100644 --- a/pax-compiler/templates/cartridge_generation/cartridge-render-node-literal.tera +++ b/pax-compiler/templates/cartridge_generation/cartridge-render-node-literal.tera @@ -77,6 +77,5 @@ instantiate_{{ snake_case_type_id }}( {% endfor %} ]), component_template: None, - scroller_args: None, compute_properties_fn: None, }) diff --git a/pax-core/src/constants.rs b/pax-core/src/constants.rs new file mode 100644 index 000000000..9393e827e --- /dev/null +++ b/pax-core/src/constants.rs @@ -0,0 +1,22 @@ +pub const SCROLL_HANDLERS: &str = "scroll"; +pub const CLAP_HANDLERS: &str = "clap"; +pub const TOUCH_START_HANDLERS: &str = "touch_start"; +pub const TOUCH_MOVE_HANDLERS: &str = "touch_move"; +pub const TOUCH_END_HANDLERS: &str = "touch_end"; +pub const KEY_DOWN_HANDLERS: &str = "key_down"; +pub const KEY_UP_HANDLERS: &str = "key_up"; +pub const KEY_PRESS_HANDLERS: &str = "key_press"; +pub const CHECKBOX_CHANGE_HANDLERS: &str = "checkbox_change"; +pub const BUTTON_CLICK_HANDLERS: &str = "button_click"; +pub const TEXTBOX_CHANGE_HANDLERS: &str = "textbox_change"; +pub const CLICK_HANDLERS: &str = "click"; +pub const MOUSE_DOWN_HANDLERS: &str = "mouse_down"; +pub const MOUSE_UP_HANDLERS: &str = "mouse_up"; +pub const MOUSE_MOVE_HANDLERS: &str = "mouse_move"; +pub const MOUSE_OVER_HANDLERS: &str = "mouse_over"; +pub const MOUSE_OUT_HANDLERS: &str = "mouse_out"; +pub const DOUBLE_CLICK_HANDLERS: &str = "double_click"; +pub const CONTEXT_MENU_HANDLERS: &str = "context_menu"; +pub const WHEEL_HANDLERS: &str = "wheel"; +pub const PRE_RENDER_HANDLERS: &str = "pre_render"; +pub const MOUNT_HANDLERS: &str = "mount"; diff --git a/pax-core/src/engine/expanded_node.rs b/pax-core/src/engine/expanded_node.rs index e5a076328..c12332e92 100644 --- a/pax-core/src/engine/expanded_node.rs +++ b/pax-core/src/engine/expanded_node.rs @@ -1,3 +1,11 @@ +#[cfg(feature = "designtime")] +use crate::constants::{ + BUTTON_CLICK_HANDLERS, CHECKBOX_CHANGE_HANDLERS, CLAP_HANDLERS, CLICK_HANDLERS, + CONTEXT_MENU_HANDLERS, DOUBLE_CLICK_HANDLERS, KEY_DOWN_HANDLERS, KEY_PRESS_HANDLERS, + KEY_UP_HANDLERS, MOUSE_DOWN_HANDLERS, MOUSE_MOVE_HANDLERS, MOUSE_OUT_HANDLERS, + MOUSE_OVER_HANDLERS, MOUSE_UP_HANDLERS, SCROLL_HANDLERS, TEXTBOX_CHANGE_HANDLERS, + TOUCH_END_HANDLERS, TOUCH_MOVE_HANDLERS, TOUCH_START_HANDLERS, WHEEL_HANDLERS, +}; use crate::Globals; use core::fmt; use std::any::Any; @@ -81,10 +89,9 @@ pub struct ExpandedNode { } macro_rules! dispatch_event_handler { - ($fn_name:ident, $arg_type:ty, $handler_field:ident) => { + ($fn_name:ident, $arg_type:ty, $handler_field:ident, $handler_key:ident) => { pub fn $fn_name(&self, args: $arg_type, globals: &Globals) { if let Some(registry) = self.instance_node.base().get_handler_registry() { - let handlers = &(*registry).borrow().$handler_field; let component_properties = if let Some(cc) = self.containing_component.upgrade() { Rc::clone(&cc.properties) } else { @@ -110,9 +117,31 @@ macro_rules! dispatch_event_handler { #[cfg(feature = "designtime")] designtime: globals.designtime.clone(), }; - handlers.iter().for_each(|handler| { - handler(Rc::clone(&component_properties), &context, args.clone()); - }); + + let borrowed_registry = &(*registry).borrow(); + + #[cfg(not(feature = "designtime"))] + { + let handlers = &borrowed_registry.$handler_field; + handlers.iter().for_each(|handler| { + handler(Rc::clone(&component_properties), &context, args.clone()); + }); + } + #[cfg(feature = "designtime")] + { + let handlers = if let Some(hs) = borrowed_registry.handlers.get($handler_key) { + hs + } else { + return; + }; + handlers.iter().for_each(|handler| { + handler( + Rc::clone(&component_properties), + &context, + Some(Box::new(args.clone()) as Box), + ); + }); + } } if let Some(parent) = &self.parent_expanded_node.borrow().upgrade() { @@ -245,8 +274,26 @@ impl ExpandedNode { self.instance_node.handle_native_patches(self, context); } if let Some(ref registry) = self.instance_node.base().handler_registry { - for handler in ®istry.borrow().pre_render_handlers { - handler(Rc::clone(&self.properties), &self.get_node_context(context)) + #[cfg(feature = "designtime")] + { + for handler in registry + .borrow() + .handlers + .get("pre_render") + .unwrap_or(&Vec::new()) + { + handler( + Rc::clone(&self.properties), + &self.get_node_context(context), + None, + ) + } + } + #[cfg(not(feature = "designtime"))] + { + for handler in ®istry.borrow().pre_render_handlers { + handler(Rc::clone(&self.properties), &self.get_node_context(context)) + } } } for child in self.children.borrow().iter() { @@ -260,8 +307,26 @@ impl ExpandedNode { context.lookup.insert(self.id_chain[0], Rc::clone(&self)); self.instance_node.handle_mount(&self, context); if let Some(ref registry) = self.instance_node.base().handler_registry { - for handler in ®istry.borrow().mount_handlers { - handler(Rc::clone(&self.properties), &self.get_node_context(context)) + #[cfg(feature = "designtime")] + { + for handler in registry + .borrow() + .handlers + .get("mount") + .unwrap_or(&Vec::new()) + { + handler( + Rc::clone(&self.properties), + &self.get_node_context(context), + None, + ) + } + } + #[cfg(not(feature = "designtime"))] + { + for handler in ®istry.borrow().mount_handlers { + handler(Rc::clone(&self.properties), &self.get_node_context(context)) + } } } } @@ -421,47 +486,107 @@ impl ExpandedNode { } } - dispatch_event_handler!(dispatch_scroll, ArgsScroll, scroll_handlers); - dispatch_event_handler!(dispatch_clap, ArgsClap, clap_handlers); - dispatch_event_handler!(dispatch_touch_start, ArgsTouchStart, touch_start_handlers); + dispatch_event_handler!( + dispatch_scroll, + ArgsScroll, + scroll_handlers, + SCROLL_HANDLERS + ); + dispatch_event_handler!(dispatch_clap, ArgsClap, clap_handlers, CLAP_HANDLERS); + dispatch_event_handler!( + dispatch_touch_start, + ArgsTouchStart, + touch_start_handlers, + TOUCH_START_HANDLERS + ); - dispatch_event_handler!(dispatch_touch_move, ArgsTouchMove, touch_move_handlers); - dispatch_event_handler!(dispatch_touch_end, ArgsTouchEnd, touch_end_handlers); - dispatch_event_handler!(dispatch_key_down, ArgsKeyDown, key_down_handlers); - dispatch_event_handler!(dispatch_key_up, ArgsKeyUp, key_up_handlers); - dispatch_event_handler!(dispatch_key_press, ArgsKeyPress, key_press_handlers); + dispatch_event_handler!( + dispatch_touch_move, + ArgsTouchMove, + touch_move_handlers, + TOUCH_MOVE_HANDLERS + ); + dispatch_event_handler!( + dispatch_touch_end, + ArgsTouchEnd, + touch_end_handlers, + TOUCH_END_HANDLERS + ); + dispatch_event_handler!( + dispatch_key_down, + ArgsKeyDown, + key_down_handlers, + KEY_DOWN_HANDLERS + ); + dispatch_event_handler!(dispatch_key_up, ArgsKeyUp, key_up_handlers, KEY_UP_HANDLERS); + dispatch_event_handler!( + dispatch_key_press, + ArgsKeyPress, + key_press_handlers, + KEY_PRESS_HANDLERS + ); dispatch_event_handler!( dispatch_checkbox_change, ArgsCheckboxChange, - checkbox_change_handlers + checkbox_change_handlers, + CHECKBOX_CHANGE_HANDLERS ); dispatch_event_handler!( dispatch_textbox_change, ArgsTextboxChange, - textbox_change_handlers + textbox_change_handlers, + TEXTBOX_CHANGE_HANDLERS ); dispatch_event_handler!( dispatch_button_click, ArgsButtonClick, - button_click_handlers + button_click_handlers, + BUTTON_CLICK_HANDLERS + ); + dispatch_event_handler!( + dispatch_mouse_down, + ArgsMouseDown, + mouse_down_handlers, + MOUSE_DOWN_HANDLERS + ); + dispatch_event_handler!( + dispatch_mouse_up, + ArgsMouseUp, + mouse_up_handlers, + MOUSE_UP_HANDLERS + ); + dispatch_event_handler!( + dispatch_mouse_move, + ArgsMouseMove, + mouse_move_handlers, + MOUSE_MOVE_HANDLERS + ); + dispatch_event_handler!( + dispatch_mouse_over, + ArgsMouseOver, + mouse_over_handlers, + MOUSE_OVER_HANDLERS + ); + dispatch_event_handler!( + dispatch_mouse_out, + ArgsMouseOut, + mouse_out_handlers, + MOUSE_OUT_HANDLERS ); - dispatch_event_handler!(dispatch_mouse_down, ArgsMouseDown, mouse_down_handlers); - dispatch_event_handler!(dispatch_mouse_up, ArgsMouseUp, mouse_up_handlers); - dispatch_event_handler!(dispatch_mouse_move, ArgsMouseMove, mouse_move_handlers); - dispatch_event_handler!(dispatch_mouse_over, ArgsMouseOver, mouse_over_handlers); - dispatch_event_handler!(dispatch_mouse_out, ArgsMouseOut, mouse_out_handlers); dispatch_event_handler!( dispatch_double_click, ArgsDoubleClick, - double_click_handlers + double_click_handlers, + DOUBLE_CLICK_HANDLERS ); dispatch_event_handler!( dispatch_context_menu, ArgsContextMenu, - context_menu_handlers + context_menu_handlers, + CONTEXT_MENU_HANDLERS ); - dispatch_event_handler!(dispatch_click, ArgsClick, click_handlers); - dispatch_event_handler!(dispatch_wheel, ArgsWheel, wheel_handlers); + dispatch_event_handler!(dispatch_click, ArgsClick, click_handlers, CLICK_HANDLERS); + dispatch_event_handler!(dispatch_wheel, ArgsWheel, wheel_handlers, WHEEL_HANDLERS); } /// Properties that are currently re-computed each frame before rendering. diff --git a/pax-core/src/engine.rs b/pax-core/src/engine/mod.rs similarity index 97% rename from pax-core/src/engine.rs rename to pax-core/src/engine/mod.rs index 1375495a2..eab720c11 100644 --- a/pax-core/src/engine.rs +++ b/pax-core/src/engine/mod.rs @@ -102,6 +102,9 @@ pub struct HandlerRegistry { pub pre_render_handlers: Vec>, &NodeContext)>, pub tick_handlers: Vec>, &NodeContext)>, pub mount_handlers: Vec>, &NodeContext)>, + #[cfg(feature = "designtime")] + pub handlers: + HashMap>, &NodeContext, Option>)>>, } impl Default for HandlerRegistry { @@ -130,6 +133,8 @@ impl Default for HandlerRegistry { button_click_handlers: Vec::new(), textbox_change_handlers: Vec::new(), tick_handlers: Vec::new(), + #[cfg(feature = "designtime")] + handlers: HashMap::new(), } } } @@ -341,6 +346,11 @@ impl PaxEngine { } } + #[cfg(feature = "designtime")] + pub fn update_root_node(&mut self, main_component_instance: Rc) { + self.root_node = ExpandedNode::root(main_component_instance, &mut self.runtime_context); + } + // NOTES: this is the order of different things being computed in recurse-expand-nodes // - expanded_node instantiated from instance_node. diff --git a/pax-core/src/lib.rs b/pax-core/src/lib.rs index bc8a19516..6487b5851 100644 --- a/pax-core/src/lib.rs +++ b/pax-core/src/lib.rs @@ -3,6 +3,7 @@ pub use piet::{Color, Error, StrokeStyle}; pub mod component; pub mod conditional; +pub mod constants; pub mod declarative_macros; pub mod engine; pub mod expressions; diff --git a/pax-core/src/rendering.rs b/pax-core/src/rendering.rs index be092f577..d3bed924f 100644 --- a/pax-core/src/rendering.rs +++ b/pax-core/src/rendering.rs @@ -9,7 +9,7 @@ use kurbo::Affine; use pax_runtime_api::{CommonProperties, RenderContext}; use piet::{Color, StrokeStyle}; -use pax_runtime_api::{ArgsScroll, Layer, PropertyInstance, Size}; +use pax_runtime_api::{ArgsScroll, Layer, Size}; use crate::{ExpandedNode, ExpressionTable, Globals, HandlerRegistry, RuntimeContext}; @@ -18,18 +18,12 @@ use crate::{ExpandedNode, ExpressionTable, Globals, HandlerRegistry, RuntimeCont pub type InstanceNodePtr = Rc; pub type InstanceNodePtrList = Vec; -pub struct ScrollerArgs { - pub size_inner_pane: [Box>; 2], - pub axes_enabled: [Box>; 2], -} - pub struct InstantiationArgs { pub prototypical_common_properties_factory: Box Rc>>, pub prototypical_properties_factory: Box Rc>>, pub handler_registry: Option>>, pub children: Option, pub component_template: Option, - pub scroller_args: Option, ///used by Component instances, specifically to unwrap dyn Any properties ///and recurse into descendant property computation diff --git a/pax-macro/src/lib.rs b/pax-macro/src/lib.rs index e8a7fa820..4d1666520 100644 --- a/pax-macro/src/lib.rs +++ b/pax-macro/src/lib.rs @@ -211,7 +211,6 @@ fn get_static_property_definitions_from_tokens(data: &Data) -> Vec Vec Vec { <% } %> let property_type_id = <%= spd.root_scoped_resolvable_type %>::get_type_id(); + let escaped_property_type_id = pax_manifest::escape_identifier(property_type_id.clone()); let mut flags = pax_manifest::PropertyDefinitionFlags::default(); flags.is_property_wrapped = <%= spd.is_property_wrapped %>; + flags.is_enum = <%= spd.is_enum %>; property_definitions.push(pax_manifest::PropertyDefinition { name: "<%= spd.field_name %>".to_string(), type_id: property_type_id, - flags: pax_manifest::PropertyDefinitionFlags::default(), + type_id_escaped: escaped_property_type_id, + flags, }); <% } %> diff --git a/pax-manifest/Cargo.toml b/pax-manifest/Cargo.toml index 6f5d64344..1e2f98e4a 100644 --- a/pax-manifest/Cargo.toml +++ b/pax-manifest/Cargo.toml @@ -10,13 +10,14 @@ description = "Definition container for an entire Pax cartridge" [features] default = ["json"] -json = ["serde_json"] +json = ["serde","serde_json"] parsing = ["pest", "pest_derive"] [lib] [dependencies] serde_json = { version = "1.0.95", optional = true } +serde = { version="1.0.95", features=["derive"], optional=true} pax-message = {path="../pax-message", version="0.11.3"} pest = { version="2.7.6", optional=true} pest_derive = {version="2.7.6", optional=true} diff --git a/pax-manifest/src/cartridge_generation/mod.rs b/pax-manifest/src/cartridge_generation/mod.rs new file mode 100644 index 000000000..547bcbff8 --- /dev/null +++ b/pax-manifest/src/cartridge_generation/mod.rs @@ -0,0 +1,406 @@ +use serde::{Deserialize, Serialize}; +use std::collections::HashMap; + +use crate::{ + HandlersBlockElement, PaxManifest, PropertyDefinition, SettingElement, SettingsBlockElement, + TemplateNodeDefinition, Token, ValueDefinition, +}; + +#[derive(Serialize, Debug)] +pub struct ComponentInfo { + pub type_id: String, + pub pascal_identifier: String, + pub primitive_instance_import_path: Option, + pub properties: Vec, + pub handlers: Vec, +} + +#[derive(Serialize, Debug)] +pub struct PropertyInfo { + pub name: String, + pub property_type: PropertyDefinition, +} + +#[derive(Serialize, Debug)] +pub struct HandlerInfo { + pub name: String, + pub args_type: Option, +} + +impl PaxManifest { + pub fn get_component_handlers(&self, type_id: &str) -> Vec<(String, Vec)> { + let mut handlers = Vec::new(); + if let Some(component) = self.components.get(type_id) { + if let Some(component_handlers) = &component.handlers { + for handler in component_handlers { + if let HandlersBlockElement::Handler(key, values) = handler { + handlers.push(( + key.token_value.clone(), + values + .iter() + .map(|v| self.clean_handler(v.raw_value.clone())) + .collect(), + )); + } + } + } + } + handlers + } + + pub fn event_to_args_map(&self) -> HashMap> { + let mut map = HashMap::new(); + map.insert("scroll".to_string(), Some("ArgsScroll".to_string())); + map.insert("clap".to_string(), Some("ArgsClap".to_string())); + map.insert( + "touch_start".to_string(), + Some("ArgsTouchStart".to_string()), + ); + map.insert("touch_move".to_string(), Some("ArgsTouchMove".to_string())); + map.insert("touch_end".to_string(), Some("ArgsTouchEnd".to_string())); + map.insert("key_down".to_string(), Some("ArgsKeyDown".to_string())); + map.insert("key_up".to_string(), Some("ArgsKeyUp".to_string())); + map.insert("key_press".to_string(), Some("ArgsKeyPress".to_string())); + map.insert( + "checkbox_change".to_string(), + Some("ArgsCheckboxChange".to_string()), + ); + map.insert( + "button_click".to_string(), + Some("ArgsButtonClick".to_string()), + ); + map.insert( + "textbox_change".to_string(), + Some("ArgsTextboxChange".to_string()), + ); + map.insert("click".to_string(), Some("ArgsClick".to_string())); + map.insert("mouse_down".to_string(), Some("ArgsMouseDown".to_string())); + map.insert("mouse_up".to_string(), Some("ArgsMouseUp".to_string())); + map.insert("mouse_move".to_string(), Some("ArgsMouseMove".to_string())); + map.insert("mouse_over".to_string(), Some("ArgsMouseOver".to_string())); + map.insert("mouse_out".to_string(), Some("ArgsMouseOut".to_string())); + map.insert( + "double_click".to_string(), + Some("ArgsDoubleClick".to_string()), + ); + map.insert( + "context_menu".to_string(), + Some("ArgsContextMenu".to_string()), + ); + map.insert("wheel".to_string(), Some("ArgsWheel".to_string())); + map.insert("pre_render".to_string(), None); + map.insert("mount".to_string(), None); + map + } + + fn clean_handler(&self, handler: String) -> String { + handler.replace("self.", "") + } + + pub fn generate_codegen_component_info(&self) -> Vec { + let mut component_infos = Vec::new(); + let event_map = self.event_to_args_map(); + + // get all the properties for this commonent type + for (type_id, component) in &self.components { + // No need to generate helpers on simple types + if component.is_struct_only_component { + continue; + } + + let mut properties = Vec::new(); + for property in &self.type_table[type_id].property_definitions { + properties.push(PropertyInfo { + name: property.name.clone(), + property_type: property.clone(), + }); + } + + let mut handler_data = Vec::new(); + + // pull all handlers from the component settings + if let Some(handlers) = &component.handlers { + for handler in handlers { + if let HandlersBlockElement::Handler(key, values) = handler { + for value in values { + let args_type = event_map.get(key.token_value.as_str()).unwrap(); + handler_data.push(HandlerInfo { + name: self.clean_handler(value.raw_value.clone()), + args_type: args_type.clone(), + }); + } + } + } + } + + // pull all handlers from the template inline settings + if let Some(template) = &component.template { + for (id, tnd) in template { + if id > &0 { + if let Some(settings) = &tnd.settings { + for setting in settings { + if let SettingElement::Setting(key, value) = setting { + if let ValueDefinition::EventBindingTarget(e) = value { + let args_type = event_map + .get(key.token_value.as_str()) + .expect("Unsupported event"); + handler_data.push(HandlerInfo { + name: self.clean_handler(e.raw_value.clone()), + args_type: args_type.clone(), + }); + } + } + } + } + } + } + } + + component_infos.push(ComponentInfo { + type_id: component.type_id.clone(), + pascal_identifier: component.pascal_identifier.clone(), + primitive_instance_import_path: component.primitive_instance_import_path.clone(), + properties, + handlers: handler_data, + }); + } + component_infos + } + + pub fn get_inline_properties( + &self, + containing_component_type_id: &str, + tnd: &TemplateNodeDefinition, + ) -> HashMap { + let component = self.components.get(containing_component_type_id).unwrap(); + let settings = + Self::merge_inline_settings_with_settings_block(&tnd.settings, &component.settings); + let mut map = HashMap::new(); + if let Some(settings) = &settings { + for setting in settings { + if let SettingElement::Setting(key, value) = setting { + match value { + ValueDefinition::LiteralValue(_) + | ValueDefinition::Block(_) + | ValueDefinition::Expression(_, _) + | ValueDefinition::Identifier(_, _) => { + map.insert(key.token_value.clone(), value.clone()); + } + _ => {} + } + } + } + } + map + } + + pub fn get_inline_common_properties( + &self, + containing_component_type_id: &str, + tnd: &TemplateNodeDefinition, + ) -> HashMap { + let component = self.components.get(containing_component_type_id).unwrap(); + let settings = + Self::merge_inline_settings_with_settings_block(&tnd.settings, &component.settings); + let mut map = HashMap::new(); + if let Some(settings) = &settings { + for setting in settings { + if let SettingElement::Setting(key, value) = setting { + match value { + ValueDefinition::LiteralValue(_) + | ValueDefinition::Block(_) + | ValueDefinition::Expression(_, _) + | ValueDefinition::Identifier(_, _) => { + if CommonProperty::get_common_properties().contains(&key.token_value) { + map.insert(key.token_value.clone(), value.clone()); + } + } + _ => {} + } + } + } + } + map + } + + pub fn get_inline_event_handlers(&self, tnd: &TemplateNodeDefinition) -> Vec<(String, String)> { + let mut handlers = Vec::new(); + if let Some(settings) = &tnd.settings { + for setting in settings { + if let SettingElement::Setting(key, value) = setting { + match value { + ValueDefinition::EventBindingTarget(e) => { + handlers.push(( + key.token_value.clone(), + self.clean_handler(e.raw_value.clone()), + )); + } + _ => {} + } + } + } + } + handlers + } + + fn pull_matched_identifiers_from_inline( + inline_settings: &Option>, + s: String, + ) -> Vec { + let mut ret = Vec::new(); + if let Some(val) = inline_settings { + let matched_settings = val.iter().filter(|e| match e { + SettingElement::Setting(token, _) => token.token_value == s.as_str(), + _ => false, + }); + for e in matched_settings { + if let SettingElement::Setting(_, value) = e { + match value { + ValueDefinition::Identifier(s, _) => ret.push(s.clone()), + _ => {} + }; + } + } + } + ret + } + + fn pull_settings_with_selector( + settings: &Option>, + selector: String, + ) -> Option> { + settings.as_ref().and_then(|val| { + let mut merged_setting = Vec::new(); + for settings_value in val.iter() { + match settings_value { + SettingsBlockElement::SelectorBlock(token, value) => { + if token.token_value == selector { + merged_setting.extend(value.elements.clone()); + } + } + _ => {} + } + } + (!merged_setting.is_empty()).then(|| merged_setting) + }) + } + + pub fn merge_inline_settings_with_settings_block( + inline_settings: &Option>, + settings_block: &Option>, + ) -> Option> { + // collect id settings + let ids = Self::pull_matched_identifiers_from_inline(&inline_settings, "id".to_string()); + + let mut id_settings = Vec::new(); + if ids.len() == 1 { + if let Some(settings) = Self::pull_settings_with_selector( + &settings_block, + format!("#{}", ids[0].token_value), + ) { + id_settings.extend(settings.clone()); + } + } else if ids.len() > 1 { + panic!("Specified more than one id inline!"); + } + + // collect all class settings + let classes = + Self::pull_matched_identifiers_from_inline(&inline_settings, "class".to_string()); + + let mut class_settings = Vec::new(); + for class in classes { + if let Some(settings) = Self::pull_settings_with_selector( + &settings_block, + format!(".{}", class.token_value), + ) { + class_settings.extend(settings.clone()); + } + } + + let mut map = HashMap::new(); + + // Iterate in reverse order of priority (class, then id, then inline) + for e in class_settings.into_iter() { + if let SettingElement::Setting(key, _) = e.clone() { + map.insert(key, e); + } + } + + for e in id_settings.into_iter() { + if let SettingElement::Setting(key, _) = e.clone() { + map.insert(key, e); + } + } + + if let Some(inline) = inline_settings.clone() { + for e in inline.into_iter() { + if let SettingElement::Setting(key, _) = e.clone() { + map.insert(key, e); + } + } + } + let merged: Vec = map.values().cloned().collect(); + + if merged.len() > 0 { + Some(merged) + } else { + None + } + } +} + +#[derive(Serialize, Deserialize)] +pub struct CommonProperty { + name: String, + property_type: String, + is_optional: bool, +} + +impl CommonProperty { + pub fn get_common_properties() -> Vec { + vec![ + "x".to_string(), + "y".to_string(), + "scale_x".to_string(), + "scale_y".to_string(), + "skew_x".to_string(), + "skew_y".to_string(), + "anchor_x".to_string(), + "anchor_y".to_string(), + "rotate".to_string(), + "transform".to_string(), + "width".to_string(), + "height".to_string(), + ] + } + + pub fn get_property_types() -> Vec<(String, String)> { + vec![ + ("x".to_string(), "Size".to_string()), + ("y".to_string(), "Size".to_string()), + ("scale_x".to_string(), "Size".to_string()), + ("scale_y".to_string(), "Size".to_string()), + ("skew_x".to_string(), "Numeric".to_string()), + ("skew_y".to_string(), "Numeric".to_string()), + ("anchor_x".to_string(), "Size".to_string()), + ("anchor_y".to_string(), "Size".to_string()), + ("rotate".to_string(), "Rotation".to_string()), + ("transform".to_string(), "Transform2D".to_string()), + ("width".to_string(), "Size".to_string()), + ("height".to_string(), "Size".to_string()), + ] + } + + pub fn get_as_common_property() -> Vec { + let mut common_properties = Vec::new(); + for (name, property_type) in CommonProperty::get_property_types() { + common_properties.push(CommonProperty { + name: name.clone(), + property_type, + is_optional: (name != "transform" && name != "width" && name != "height"), + }); + } + common_properties + } +} diff --git a/pax-manifest/src/lib.rs b/pax-manifest/src/lib.rs index c0b220897..b06e29be0 100644 --- a/pax-manifest/src/lib.rs +++ b/pax-manifest/src/lib.rs @@ -1,4 +1,4 @@ -use std::collections::HashMap; +use std::collections::{HashMap, HashSet}; use std::hash::Hasher; use std::{cmp::Ordering, hash::Hash}; @@ -9,6 +9,14 @@ use serde_json; #[cfg(feature = "parsing")] pub mod utils; +#[cfg(feature = "parsing")] +pub mod cartridge_generation; + +pub static TYPE_ID_IF: &str = "IF"; +pub static TYPE_ID_REPEAT: &str = "REPEAT"; +pub static TYPE_ID_SLOT: &str = "SLOT"; +pub static TYPE_ID_COMMENT: &str = "COMMENT"; + /// Definition container for an entire Pax cartridge #[derive(Serialize, Deserialize)] #[serde(crate = "pax_message::serde")] @@ -237,10 +245,16 @@ pub struct PropertyDefinition { /// Statically known type_id for this Property's associated TypeDefinition pub type_id: String, + + /// Pascalized type_id, used for enum identifiers + pub type_id_escaped: String, } impl PropertyDefinition { pub fn get_type_definition<'a>(&'a self, tt: &'a TypeTable) -> &TypeDefinition { + if let None = tt.get(&self.type_id) { + panic!("TypeTable does not contain type_id: {}", &self.type_id); + } tt.get(&self.type_id).unwrap() } @@ -282,6 +296,9 @@ pub struct PropertyDefinitionFlags { /// This distinction affects our ability to dirty-watch a particular property, and /// has implications on codegen pub is_property_wrapped: bool, + + /// Describes whether this property is an enum variant property + pub is_enum: bool, } /// Describes static metadata surrounding a property, for example @@ -294,6 +311,7 @@ impl PropertyDefinition { name: symbol_name.to_string(), flags: PropertyDefinitionFlags::default(), type_id: type_name.to_string(), + type_id_escaped: escape_identifier(type_name.to_string()), } } } @@ -629,3 +647,72 @@ pub fn escape_identifier(input: String) -> String { .replace("#", "HASH") .replace("-", "HYPH") } + +/// Pulled from host Cargo.toml +pub struct HostCrateInfo { + /// for example: `pax-example` + pub name: String, + /// for example: `pax_example` + pub identifier: String, + /// for example: `some_crate::pax_reexports`, + pub import_prefix: String, +} + +pub const IMPORTS_BUILTINS: [&str; 28] = [ + "std::any::Any", + "std::cell::RefCell", + "std::collections::HashMap", + "std::collections::VecDeque", + "std::ops::Deref", + "std::rc::Rc", + "pax_core::RepeatItem", + "pax_core::RepeatProperties", + "pax_core::ConditionalProperties", + "pax_core::SlotProperties", + "pax_core::get_numeric_from_wrapped_properties", + "pax_runtime_api::PropertyInstance", + "pax_runtime_api::PropertyLiteral", + "pax_runtime_api::CommonProperties", + "pax_core::ComponentInstance", + "pax_core::InstanceNodePtr", + "pax_core::PropertyExpression", + "pax_core::InstanceNodePtrList", + "pax_core::ExpressionContext", + "pax_core::PaxEngine", + "pax_core::InstanceNode", + "pax_core::HandlerRegistry", + "pax_core::InstantiationArgs", + "pax_core::ConditionalInstance", + "pax_core::SlotInstance", + "pax_core::properties::RuntimePropertiesStackFrame", + "pax_core::repeat::RepeatInstance", + "piet_common::RenderContext", +]; + +impl<'a> HostCrateInfo { + pub fn fully_qualify_path(&self, path: &str) -> String { + let ret = path.replace("crate::", "").to_string(); + #[allow(non_snake_case)] + let IMPORT_PREFIX = format!("{}::pax_reexports::", self.identifier); + let imports_builtins_set: HashSet<&str> = IMPORTS_BUILTINS.into_iter().collect(); + let mut primitives_set: HashSet<&str> = SUPPORTED_NUMERIC_PRIMITIVES + .into_iter() + .chain(SUPPORTED_NONNUMERIC_PRIMITIVES.into_iter()) + .collect(); + primitives_set.insert(TYPE_ID_IF); + primitives_set.insert(TYPE_ID_REPEAT); + primitives_set.insert(TYPE_ID_SLOT); + primitives_set.insert(TYPE_ID_COMMENT); + if primitives_set.contains(path) || path.contains("pax_reexports") { + ret.to_string() + } else if !imports_builtins_set.contains(path) { + if path.contains("{PREFIX}") { + ret.replace("{PREFIX}", &IMPORT_PREFIX) + } else { + IMPORT_PREFIX.clone() + ret.as_str() + } + } else { + "".to_string() + } + } +} diff --git a/pax-runtime-api/Cargo.toml b/pax-runtime-api/Cargo.toml index 44c5d4779..a7cf6e99c 100644 --- a/pax-runtime-api/Cargo.toml +++ b/pax-runtime-api/Cargo.toml @@ -18,3 +18,5 @@ lazy_static = "1.4.0" mut_static = "5.0.0" uuid = {version = "0.8", features = ["v4", "wasm-bindgen"]} pax-message = {version="0.11.3", path="../pax-message"} +serde = {version="1.0.196", features=["derive"]} + diff --git a/pax-runtime-api/src/lib.rs b/pax-runtime-api/src/lib.rs index 4a441f6ee..fbc15803a 100644 --- a/pax-runtime-api/src/lib.rs +++ b/pax-runtime-api/src/lib.rs @@ -14,12 +14,12 @@ pub use crate::numeric::Numeric; use kurbo::BezPath; use mut_static::MutStatic; pub use pax_message::serde; -use pax_message::serde::{Deserialize, Serialize}; use pax_message::{ModifierKeyMessage, MouseButtonMessage, TouchMessage}; use piet::PaintBrush; #[cfg(feature = "designtime")] use pax_designtime::DesigntimeManager; +use serde::{Deserialize, Serialize}; #[cfg(feature = "designtime")] use std::rc::Rc; @@ -438,6 +438,17 @@ impl Size { } } } + + /// Returns the pixel value + /// Panics if wrapped type is not pixels. + pub fn expect_pixels(&self) -> Numeric { + match &self { + Size::Pixels(val) => val.clone(), + _ => { + panic!("Percentage value expected but stored value was not a percentage.") + } + } + } } pub enum Axis { @@ -465,6 +476,14 @@ impl Size { } } +#[cfg_attr(debug_assertions, derive(Debug))] +#[derive(Default, Serialize, Deserialize)] +pub struct CommonProperty { + name: String, + property_type: String, + optional: bool, +} + // Struct containing fields shared by all RenderNodes. // Each property here is special-cased by the compiler when parsing element properties (e.g. ``) // Retrieved via #get_common_properties @@ -519,10 +538,21 @@ impl CommonProperties { ("height".to_string(), "Size".to_string()), ] } + + pub fn get_as_common_property() -> Vec { + Self::get_property_identifiers() + .iter() + .map(|id| CommonProperty { + name: id.0.to_string(), + property_type: id.1.to_string(), + optional: (id.0 == "transform" || id.0 == "width" || id.0 == "height"), + }) + .collect() + } } #[cfg_attr(debug_assertions, derive(Debug))] -#[derive(Clone)] +#[derive(Clone, Deserialize)] pub enum Rotation { Radians(Numeric), Degrees(Numeric), @@ -647,44 +677,6 @@ impl Default for Size { } } -impl From for SizePixels { - fn from(value: Size) -> Self { - match value { - Size::Pixels(x) => SizePixels(x), - _ => { - panic!("Non-pixel Size cannot be coerced into SizePixels"); - } - } - } -} - -#[derive(Copy, Clone, Serialize, Deserialize)] -#[serde(crate = "crate::serde")] -#[cfg_attr(debug_assertions, derive(Debug))] -pub struct SizePixels(pub Numeric); - -impl Default for SizePixels { - fn default() -> Self { - Self(Numeric::Float(150.0)) - } -} -impl From<&SizePixels> for f64 { - fn from(value: &SizePixels) -> Self { - value.0.get_as_float() - } -} - -impl PartialEq for SizePixels { - fn eq(&self, other: &Numeric) -> bool { - self.0 == *other - } -} -impl PartialEq for Numeric { - fn eq(&self, other: &SizePixels) -> bool { - other.0 == *self - } -} - /// Coproduct for storing various kinds of function pointer, /// needed to achieve compatibility with various native bridge mechanisms pub enum PlatformSpecificLogger { @@ -756,7 +748,7 @@ impl Mul for Size { /// to be offset either by a pixel or percentage-of-element-size /// for each of (x,y) #[cfg_attr(debug_assertions, derive(Debug))] -#[derive(Default, Clone)] +#[derive(Default, Clone, Deserialize)] pub struct Transform2D { /// Keeps track of a linked list of previous Transform2Ds, assembled e.g. via multiplication pub previous: Option>, diff --git a/pax-runtime-api/src/numeric.rs b/pax-runtime-api/src/numeric.rs index 665556319..7f1c4dca7 100644 --- a/pax-runtime-api/src/numeric.rs +++ b/pax-runtime-api/src/numeric.rs @@ -1,4 +1,4 @@ -use crate::serde::{Deserialize, Serialize}; +use serde::{Deserialize, Serialize}; use crate::Interpolatable; use std::cmp::Ordering; diff --git a/pax-std/Cargo.toml b/pax-std/Cargo.toml index 08a0a7856..0b584c46a 100644 --- a/pax-std/Cargo.toml +++ b/pax-std/Cargo.toml @@ -23,6 +23,7 @@ pax-compiler = {path="../pax-compiler", optional = true, version="0.11.3"} serde_json = {version="1.0.95", optional = true} pax-runtime-api = {version="0.11.3", path="../pax-runtime-api"} pax-manifest = {path = "../pax-manifest", version="0.11.3"} +serde = { version = "1.0.159", features=["derive"]} [features] parser = ["pax-lang/parser", "dep:pax-compiler", "dep:serde_json"] diff --git a/pax-std/pax-std-primitives/src/ellipse.rs b/pax-std/pax-std-primitives/src/ellipse.rs index b8dca9d65..0cc23f735 100644 --- a/pax-std/pax-std-primitives/src/ellipse.rs +++ b/pax-std/pax-std-primitives/src/ellipse.rs @@ -61,7 +61,7 @@ impl InstanceNode for EllipseInstance { rc.fill(&layer_id, transformed_bez_path, &color.into()); //hack to address "phantom stroke" bug on Web - let width: f64 = *&properties.stroke.get().width.get().into(); + let width: f64 = *&properties.stroke.get().width.get().expect_pixels().into(); if width > f64::EPSILON { rc.stroke( &layer_id, diff --git a/pax-std/pax-std-primitives/src/path.rs b/pax-std/pax-std-primitives/src/path.rs index 64387de37..e6c78da9f 100644 --- a/pax-std/pax-std-primitives/src/path.rs +++ b/pax-std/pax-std-primitives/src/path.rs @@ -84,7 +84,7 @@ impl InstanceNode for PathInstance { &layer_id, duplicate_transformed_bez_path, &properties.stroke.get().color.get().to_piet_color().into(), - properties.stroke.get().width.get().into(), + properties.stroke.get().width.get().expect_pixels().into(), ); }); } diff --git a/pax-std/pax-std-primitives/src/rectangle.rs b/pax-std/pax-std-primitives/src/rectangle.rs index b4fb83aa7..fc7c756ea 100644 --- a/pax-std/pax-std-primitives/src/rectangle.rs +++ b/pax-std/pax-std-primitives/src/rectangle.rs @@ -111,7 +111,7 @@ impl InstanceNode for RectangleInstance { } //hack to address "phantom stroke" bug on Web - let width: f64 = *&properties.stroke.get().width.get().into(); + let width: f64 = *&properties.stroke.get().width.get().expect_pixels().into(); if width > f64::EPSILON { rc.stroke( &layer_id, diff --git a/pax-std/src/types/mod.rs b/pax-std/src/types/mod.rs index 0827ed21c..c0f93733f 100644 --- a/pax-std/src/types/mod.rs +++ b/pax-std/src/types/mod.rs @@ -3,8 +3,8 @@ pub mod text; use crate::primitives::Path; pub use kurbo::RoundedRectRadii; use pax_lang::api::numeric::Numeric; +use pax_lang::api::PropertyLiteral; pub use pax_lang::api::Size; -use pax_lang::api::{PropertyLiteral, SizePixels}; use pax_lang::*; use pax_message::ColorVariantMessage; use piet::UnitPoint; @@ -14,14 +14,14 @@ use piet::UnitPoint; #[cfg_attr(debug_assertions, derive(Debug))] pub struct Stroke { pub color: Property, - pub width: Property, + pub width: Property, } impl Default for Stroke { fn default() -> Self { Self { color: Default::default(), - width: Box::new(PropertyLiteral::new(SizePixels(0.0.into()))), + width: Box::new(PropertyLiteral::new(Size::Pixels(0.0.into()))), } } } @@ -63,7 +63,7 @@ pub enum Fill { #[cfg_attr(debug_assertions, derive(Debug))] #[pax] -#[custom(Default, Imports)] +#[custom(Imports)] pub struct LinearGradient { pub start: (Size, Size), pub end: (Size, Size), @@ -72,7 +72,7 @@ pub struct LinearGradient { #[cfg_attr(debug_assertions, derive(Debug))] #[pax] -#[custom(Default, Imports)] +#[custom(Imports)] pub struct RadialGradient { pub end: (Size, Size), pub start: (Size, Size), @@ -84,8 +84,8 @@ pub struct RadialGradient { #[pax] #[custom(Imports)] pub struct GradientStop { - position: Size, - color: Color, + pub position: Size, + pub color: Color, } impl GradientStop { diff --git a/pax-std/src/types/text.rs b/pax-std/src/types/text.rs index 6d7d25e64..0334f9ae7 100644 --- a/pax-std/src/types/text.rs +++ b/pax-std/src/types/text.rs @@ -1,6 +1,6 @@ use crate::types::Color; -use api::StringBox; -use pax_lang::api::{Numeric, Property, PropertyLiteral, SizePixels}; +use api::{Size, StringBox}; +use pax_lang::api::{Numeric, Property, PropertyLiteral}; use pax_lang::*; use pax_message::{ ColorVariantMessage, FontPatch, FontStyleMessage, FontWeightMessage, LocalFontMessage, @@ -13,7 +13,7 @@ use pax_message::{ #[cfg_attr(debug_assertions, derive(Debug))] pub struct TextStyle { pub font: Property, - pub font_size: Property, + pub font_size: Property, pub fill: Property, pub underline: Property, pub align_multiline: Property, @@ -25,7 +25,7 @@ impl Default for TextStyle { fn default() -> Self { Self { font: Box::new(PropertyLiteral::new(Font::default())), - font_size: Box::new(PropertyLiteral::new(SizePixels(Numeric::Float(20.0)))), + font_size: Box::new(PropertyLiteral::new(Size::Pixels(Numeric::Float(20.0)))), fill: Box::new(PropertyLiteral::new(Color::rgba( Numeric::Float(0.0), Numeric::Float(0.0), @@ -44,7 +44,7 @@ impl<'a> Into for &'a TextStyle { fn into(self) -> TextStyleMessage { TextStyleMessage { font: Some(self.font.get().clone().into()), - font_size: Some(f64::from(&self.font_size.get().clone())), + font_size: Some(f64::from(self.font_size.get().expect_pixels())), fill: Some(Into::::into(self.fill.get())), underline: Some(self.underline.get().clone()), align_multiline: Some(Into::::into( @@ -68,7 +68,7 @@ impl PartialEq for TextStyle { .map_or(false, |font| self.font.get().eq(font)); let font_size_equal = other.font_size.map_or(false, |size| { - Numeric::Float(size) == self.font_size.get().clone() + Numeric::Float(size) == self.font_size.get().expect_pixels().clone() }); let fill_equal = other diff --git a/scripts/release.py b/scripts/release.py index 7a2461eb7..87e488d85 100755 --- a/scripts/release.py +++ b/scripts/release.py @@ -61,6 +61,29 @@ doc = tomlkit.parse(file.read()) PACKAGE_NAMES[doc['package']['name']] = elem + +def update_pax_designtime_cargo_toml(pax_designtime_dir, new_version): + """ + Update the pax-designtime Cargo.toml file to set new version numbers for dependencies. + :param pax_designtime_dir: Directory of the pax-designtime crate. + :param new_version: The new version to set for the dependencies. + """ + cargo_toml_path = os.path.join(pax_designtime_dir, 'Cargo.toml') + with open(cargo_toml_path, 'r') as file: + doc = tomlkit.parse(file.read()) + + # Check and update dependencies + if 'dependencies' in doc: + for dep in doc['dependencies']: + if dep in PACKAGE_NAMES: + dep_table = doc['dependencies'][dep] + if isinstance(dep_table, tomlkit.items.InlineTable): + dep_table['version'] = new_version + + with open(cargo_toml_path, 'w') as file: + file.write(tomlkit.dumps(doc)) + + def update_crate_versions_in_examples(new_version, package_names, examples_dir): """ Update the crate versions in all Cargo.toml files within the examples directory. @@ -144,6 +167,9 @@ def dfs(node): EXAMPLES_DIR = "examples/src" update_crate_versions_in_examples(NEW_VERSION, PACKAGE_NAMES, EXAMPLES_DIR) +# Update the pax-designtime crate version +update_pax_designtime_cargo_toml('../pax-designtime', NEW_VERSION) + # Set to keep track of already published packages published = set()