From d881d71d7db7084e13d6d826fc32a4a197db1ebf Mon Sep 17 00:00:00 2001 From: Samuel Selleck Date: Mon, 26 Feb 2024 10:24:11 -0800 Subject: [PATCH 1/3] partial --- pax-message/src/lib.rs | 11 +++++++++++ pax-std/src/forms/text-box.rs | 0 pax-std/src/lib.rs | 6 ++++++ 3 files changed, 17 insertions(+) delete mode 100644 pax-std/src/forms/text-box.rs diff --git a/pax-message/src/lib.rs b/pax-message/src/lib.rs index a347a0858..6abb34d88 100644 --- a/pax-message/src/lib.rs +++ b/pax-message/src/lib.rs @@ -333,6 +333,10 @@ pub struct TextboxPatch { pub size_x: Option, pub size_y: Option, pub text: Option, + pub background: Option, + pub stroke: Option, + pub border_radius: Option, + pub style: Option, } #[cfg_attr(debug_assertions, derive(Debug))] @@ -405,6 +409,13 @@ pub enum ColorVariantMessage { Rgb([f64; 3]), } +#[cfg_attr(debug_assertions, derive(Debug))] +#[derive(Serialize, Clone, PartialEq)] +#[repr(C)] +pub struct StrokeMessage { + color: Option, +} + impl Default for ColorVariantMessage { fn default() -> Self { ColorVariantMessage::Rgba([1.0, 0.5, 0.0, 1.0]) diff --git a/pax-std/src/forms/text-box.rs b/pax-std/src/forms/text-box.rs deleted file mode 100644 index e69de29bb..000000000 diff --git a/pax-std/src/lib.rs b/pax-std/src/lib.rs index c20010d78..cd2796926 100644 --- a/pax-std/src/lib.rs +++ b/pax-std/src/lib.rs @@ -14,7 +14,9 @@ pub mod primitives { use pax_runtime::api::StringBox; use crate::types::text::TextStyle; + use crate::types::Fill; use crate::types::PathSegment; + use crate::types::Stroke; #[pax] #[primitive("pax_std_primitives::frame::FrameInstance")] @@ -78,6 +80,10 @@ pub mod primitives { #[primitive("pax_std_primitives::textbox::TextboxInstance")] pub struct Textbox { pub text: Property, + pub background: Property, + pub stroke: Property, + pub border_radius: Property, + pub text_style: Property, } #[pax] From 725a4c85fbda9c8bdbfc3fcc27a802b4ce7b8110 Mon Sep 17 00:00:00 2001 From: Samuel Selleck Date: Mon, 26 Feb 2024 20:27:20 -0800 Subject: [PATCH 2/3] first pass texbox styling done --- examples/src/playground/src/lib.pax | 13 ++++- examples/src/playground/src/lib.rs | 2 +- .../classes/messages/textbox-update-patch.ts | 19 +++++- .../src/classes/native-element-pool.ts | 58 +++++++++++++------ pax-chassis-web/interface/src/classes/text.ts | 2 +- pax-chassis-web/interface/src/index.ts | 2 +- pax-message/src/lib.rs | 10 +--- pax-runtime/src/expressions.rs | 6 ++ pax-std/pax-std-primitives/src/rectangle.rs | 10 ++++ pax-std/pax-std-primitives/src/textbox.rs | 53 +++++++++++++++-- pax-std/src/lib.rs | 8 ++- pax-std/src/types/mod.rs | 2 + 12 files changed, 143 insertions(+), 42 deletions(-) diff --git a/examples/src/playground/src/lib.pax b/examples/src/playground/src/lib.pax index 3c108a80b..732a1ff00 100644 --- a/examples/src/playground/src/lib.pax +++ b/examples/src/playground/src/lib.pax @@ -8,7 +8,14 @@ align_multiline: TextAlignHorizontal::Center } /> - + @@ -43,10 +50,10 @@ style: { font: {Font::system("Times New Roman", FontStyle::Normal, FontWeight::Bold)}, font_size: 32px, - fill: {Color::rgba(1.0, 1.0, 1.0, 1.0)}, + fill: {Color::rgba(1.0, 0.0, 1.0, 1.0)}, align_vertical: TextAlignVertical::Center, align_horizontal: TextAlignHorizontal::Center, align_multiline: TextAlignHorizontal::Center } - } + } } diff --git a/examples/src/playground/src/lib.rs b/examples/src/playground/src/lib.rs index af3a455ec..50e35fc9b 100644 --- a/examples/src/playground/src/lib.rs +++ b/examples/src/playground/src/lib.rs @@ -56,7 +56,7 @@ impl Example { } } - pub fn textbox_change(&mut self, ctx: &NodeContext, args: ArgsTextboxChange) { + pub fn textbox_input(&mut self, ctx: &NodeContext, args: ArgsTextboxInput) { self.textbox_text.set(args.text); } diff --git a/pax-chassis-web/interface/src/classes/messages/textbox-update-patch.ts b/pax-chassis-web/interface/src/classes/messages/textbox-update-patch.ts index 2292633e1..22df61ad5 100644 --- a/pax-chassis-web/interface/src/classes/messages/textbox-update-patch.ts +++ b/pax-chassis-web/interface/src/classes/messages/textbox-update-patch.ts @@ -1,23 +1,40 @@ import {ObjectManager} from "../../pools/object-manager"; +import { TEXT_STYLE } from "../../pools/supported-objects"; +import { TextStyle } from "../text"; export class TextboxUpdatePatch { public id_chain?: number[]; public size_x?: number; public size_y?: number; + public stroke_width?: number; + public stroke_color?: ColorGroup; + public background?: ColorGroup; + public border_radius: number; public transform?: number[]; public text?: string; objectManager: ObjectManager; + public style?: TextStyle; constructor(objectManager: ObjectManager) { this.objectManager = objectManager; } - fromPatch(jsonMessage: any) { + fromPatch(jsonMessage: any, registeredFontFaces: Set) { this.id_chain = jsonMessage["id_chain"]; this.size_x = jsonMessage["size_x"]; this.size_y = jsonMessage["size_y"]; this.transform = jsonMessage["transform"]; this.text = jsonMessage["text"]; + this.stroke_color = jsonMessage["stroke_color"]; + this.stroke_width = jsonMessage["stroke_width"]; + this.background = jsonMessage["background"]; + this.border_radius = jsonMessage["border_radius"]; + const styleMessage = jsonMessage["style"]; + + if (styleMessage) { + this.style = this.objectManager.getFromPool(TEXT_STYLE, this.objectManager); + this.style.build(styleMessage, registeredFontFaces) + } } cleanUp(){ diff --git a/pax-chassis-web/interface/src/classes/native-element-pool.ts b/pax-chassis-web/interface/src/classes/native-element-pool.ts index 4f5c52a61..ea0fd1c40 100644 --- a/pax-chassis-web/interface/src/classes/native-element-pool.ts +++ b/pax-chassis-web/interface/src/classes/native-element-pool.ts @@ -14,7 +14,7 @@ import {OcclusionContext} from "./occlusion-context"; import {ObjectManager} from "../pools/object-manager"; import {INPUT, BUTTON, DIV, OBJECT, OCCLUSION_CONTEXT, SCROLLER} from "../pools/supported-objects"; import {arrayToKey, packAffineCoeffsIntoMatrix3DString, readImageToByteBuffer} from "../utils/helpers"; -import {TextStyle, getAlignItems, getJustifyContent, getTextAlign} from "./text"; +import {ColorGroup, TextStyle, getAlignItems, getJustifyContent, getTextAlign} from "./text"; import type {PaxChassisWeb} from "../types/pax-chassis-web"; import { CheckboxUpdatePatch } from "./messages/checkbox-update-patch"; import { TextboxUpdatePatch } from "./messages/textbox-update-patch"; @@ -240,6 +240,24 @@ export class NativeElementPool { console.assert(leaf !== undefined); let textbox = leaf.firstChild; + applyTextTyle(textbox, textbox, patch.style); + console.log(patch); + + if (patch.background) { + textbox.style.background = toCssColor(patch.background); + } + + if (patch.border_radius) { + textbox.style["border-radius"] = patch.border_radius + "px"; + } + + if (patch.stroke_color) { + textbox.style["border-color"] = toCssColor(patch.stroke_color); + } + + if (patch.stroke_width) { + textbox.style["border-width"] = patch.stroke_width + "px"; + } // Apply the content if (patch.text != null) { @@ -591,7 +609,23 @@ export class NativeElementPool { } - +function toCssColor(color: ColorGroup): string { + if (color.Rgba != null) { + let p = color.Rgba; + return `rgba(${p[0] * 255},${p[1] * 255},${p[2] * 255},${p[3] * 255})`; + } else if (color.Hsla != null) { + let p = color.Hsla; + return `hsla(${p[0] * 255},${p[1] * 255},${p[2] * 255},${p[3] * 255})`; + } else if (color.Rgb != null) { + let p = color.Rgb; + return `rgb(${p[0] * 255},${p[1] * 255},${p[2] * 255})`; + } else if (color.Hsl != null) { + let p = color.Hsl; + return `hsl(${p[0] * 255},${p[1] * 255},${p[2] * 255})`; + } else { + throw new TypeError("Unsupported Color Format"); + } +} function applyTextTyle(textContainer: HTMLDivElement, textElem: HTMLDivElement, style: TextStyle | undefined) { @@ -601,23 +635,7 @@ function applyTextTyle(textContainer: HTMLDivElement, textElem: HTMLDivElement, style.font.applyFontToDiv(textContainer); } if (style.fill) { - let newValue = ""; - if (style.fill.Rgba != null) { - let p = style.fill.Rgba; - newValue = `rgba(${p[0] * 255},${p[1] * 255},${p[2] * 255},${p[3] * 255})`; - } else if (style.fill.Hsla != null) { - let p = style.fill.Hsla; - newValue = `hsla(${p[0] * 255},${p[1] * 255},${p[2] * 255},${p[3] * 255})`; - } else if (style.fill.Rgb != null) { - let p = style.fill.Rgb; - newValue = `rgb(${p[0] * 255},${p[1] * 255},${p[2] * 255})`; - } else if (style.fill.Hsl != null) { - let p = style.fill.Hsl; - newValue = `hsl(${p[0] * 255},${p[1] * 255},${p[2] * 255})`; - } else { - throw new TypeError("Unsupported Color Format"); - } - textElem.style.color = newValue; + textElem.style.color = toCssColor(style.fill); } if (style.font_size) { textElem.style.fontSize = style.font_size + "px"; @@ -637,3 +655,5 @@ function applyTextTyle(textContainer: HTMLDivElement, textElem: HTMLDivElement, } } } + + diff --git a/pax-chassis-web/interface/src/classes/text.ts b/pax-chassis-web/interface/src/classes/text.ts index bc47ce793..e79ceb9bd 100644 --- a/pax-chassis-web/interface/src/classes/text.ts +++ b/pax-chassis-web/interface/src/classes/text.ts @@ -245,7 +245,7 @@ export function getAlignItems(verticalAlignment: string): string { } } -class ColorGroup { +export class ColorGroup { Hsla?: number[]; Rgba?: number[]; Rgb?: number[]; diff --git a/pax-chassis-web/interface/src/index.ts b/pax-chassis-web/interface/src/index.ts index 1949dc189..dc5b341e2 100644 --- a/pax-chassis-web/interface/src/index.ts +++ b/pax-chassis-web/interface/src/index.ts @@ -161,7 +161,7 @@ export function processMessages(messages: any[], chassis: PaxChassisWeb, objectM } else if (unwrapped_msg["TextboxUpdate"]){ let msg = unwrapped_msg["TextboxUpdate"] let patch: TextboxUpdatePatch = objectManager.getFromPool(TEXTBOX_UPDATE_PATCH, objectManager); - patch.fromPatch(msg); + patch.fromPatch(msg, nativePool.registeredFontFaces); nativePool.textboxUpdate(patch); }else if (unwrapped_msg["TextboxDelete"]) { let msg = unwrapped_msg["TextboxDelete"]; diff --git a/pax-message/src/lib.rs b/pax-message/src/lib.rs index 6abb34d88..8d1584bf9 100644 --- a/pax-message/src/lib.rs +++ b/pax-message/src/lib.rs @@ -334,7 +334,8 @@ pub struct TextboxPatch { pub size_y: Option, pub text: Option, pub background: Option, - pub stroke: Option, + pub stroke_color: Option, + pub stroke_width: Option, pub border_radius: Option, pub style: Option, } @@ -409,13 +410,6 @@ pub enum ColorVariantMessage { Rgb([f64; 3]), } -#[cfg_attr(debug_assertions, derive(Debug))] -#[derive(Serialize, Clone, PartialEq)] -#[repr(C)] -pub struct StrokeMessage { - color: Option, -} - impl Default for ColorVariantMessage { fn default() -> Self { ColorVariantMessage::Rgba([1.0, 0.5, 0.0, 1.0]) diff --git a/pax-runtime/src/expressions.rs b/pax-runtime/src/expressions.rs index 36d5de361..4609d0eed 100644 --- a/pax-runtime/src/expressions.rs +++ b/pax-runtime/src/expressions.rs @@ -12,6 +12,7 @@ use crate::api::{ // via calls to `read()` pub struct PropertyExpression { pub id: usize, + pub has_been_evaluted: bool, pub cached_value: T, pub transition_manager: TransitionManager, } @@ -22,12 +23,16 @@ impl PropertyExpression { id, cached_value: Default::default(), transition_manager: TransitionManager::new(), + has_been_evaluted: false, } } } impl PropertyInstance for PropertyExpression { fn get(&self) -> &T { + if !self.has_been_evaluted { + panic!("expression width id {:?} has'nt been evaluated", self.id) + } &self.cached_value } @@ -41,6 +46,7 @@ impl PropertyInstance for PropertyExpression { fn set(&mut self, value: T) { self.cached_value = value; + self.has_been_evaluted = true; } //FUTURE: when trait fields land, DRY this implementation vs. other implementations diff --git a/pax-std/pax-std-primitives/src/rectangle.rs b/pax-std/pax-std-primitives/src/rectangle.rs index df9cf1283..ac96798a8 100644 --- a/pax-std/pax-std-primitives/src/rectangle.rs +++ b/pax-std/pax-std-primitives/src/rectangle.rs @@ -39,6 +39,16 @@ impl InstanceNode for RectangleInstance { &expanded_node.stack, &mut properties.stroke, ); + handle_vtable_update( + context.expression_table(), + &expanded_node.stack, + &mut properties.stroke.get_mut().color, + ); + handle_vtable_update( + context.expression_table(), + &expanded_node.stack, + &mut properties.stroke.get_mut().width, + ); handle_vtable_update( context.expression_table(), &expanded_node.stack, diff --git a/pax-std/pax-std-primitives/src/textbox.rs b/pax-std/pax-std-primitives/src/textbox.rs index a0eec2c76..2927613da 100644 --- a/pax-std/pax-std-primitives/src/textbox.rs +++ b/pax-std/pax-std-primitives/src/textbox.rs @@ -40,11 +40,24 @@ impl InstanceNode for TextboxInstance { fn update(self: Rc, expanded_node: &Rc, context: &mut RuntimeContext) { expanded_node.with_properties_unwrapped(|properties: &mut Textbox| { - handle_vtable_update( - context.expression_table(), - &expanded_node.stack, - &mut properties.text, - ); + let tbl = context.expression_table(); + let stk = &expanded_node.stack; + handle_vtable_update(tbl, stk, &mut properties.text); + handle_vtable_update(tbl, stk, &mut properties.stroke); + handle_vtable_update(tbl, stk, &mut properties.stroke.get_mut().color); + handle_vtable_update(tbl, stk, &mut properties.stroke.get_mut().width); + handle_vtable_update(tbl, stk, &mut properties.border_radius); + handle_vtable_update(tbl, stk, &mut properties.background); + // Style + handle_vtable_update(tbl, stk, &mut properties.style); + let stl = properties.style.get_mut(); + handle_vtable_update(tbl, stk, &mut stl.fill); + handle_vtable_update(tbl, stk, &mut stl.font); + handle_vtable_update(tbl, stk, &mut stl.font_size); + handle_vtable_update(tbl, stk, &mut stl.underline); + handle_vtable_update(tbl, stk, &mut stl.align_vertical); + handle_vtable_update(tbl, stk, &mut stl.align_horizontal); + handle_vtable_update(tbl, stk, &mut stl.align_multiline); }); } @@ -83,6 +96,36 @@ impl InstanceNode for TextboxInstance { &mut patch.transform, computed_tab.transform.coeffs().to_vec(), ), + patch_if_needed( + &mut old_state.style, + &mut patch.style, + properties.style.get().into(), + ), + patch_if_needed( + &mut old_state.stroke_color, + &mut patch.stroke_color, + properties.stroke.get().color.get().into(), + ), + patch_if_needed( + &mut old_state.stroke_width, + &mut patch.stroke_width, + properties + .stroke + .get() + .width + .get() + .get_pixels(computed_tab.bounds.0), + ), + patch_if_needed( + &mut old_state.background, + &mut patch.background, + properties.background.get().into(), + ), + patch_if_needed( + &mut old_state.border_radius, + &mut patch.border_radius, + properties.border_radius.get().get_as_float(), + ), ]; if updates.into_iter().any(|v| v == true) { context.enqueue_native_message(pax_message::NativeMessage::TextboxUpdate(patch)); diff --git a/pax-std/src/lib.rs b/pax-std/src/lib.rs index cd2796926..8f6eece34 100644 --- a/pax-std/src/lib.rs +++ b/pax-std/src/lib.rs @@ -12,8 +12,10 @@ pub mod primitives { use pax_runtime::api::Property; use pax_runtime::api::Size; use pax_runtime::api::StringBox; + use pax_runtime::numeric::Numeric; use crate::types::text::TextStyle; + use crate::types::Color; use crate::types::Fill; use crate::types::PathSegment; use crate::types::Stroke; @@ -80,10 +82,10 @@ pub mod primitives { #[primitive("pax_std_primitives::textbox::TextboxInstance")] pub struct Textbox { pub text: Property, - pub background: Property, + pub background: Property, pub stroke: Property, - pub border_radius: Property, - pub text_style: Property, + pub border_radius: Property, + pub style: Property, } #[pax] diff --git a/pax-std/src/types/mod.rs b/pax-std/src/types/mod.rs index dc25c8388..2f9f59823 100644 --- a/pax-std/src/types/mod.rs +++ b/pax-std/src/types/mod.rs @@ -203,6 +203,7 @@ impl Default for Color { } } } + impl Into for &Color { fn into(self) -> ColorVariantMessage { match self.color_variant { @@ -213,6 +214,7 @@ impl Into for &Color { } } } + impl PartialEq for Color { fn eq(&self, other: &ColorVariantMessage) -> bool { match self.color_variant { From a7e2d5788eca1851784545662a2761b240bd96b5 Mon Sep 17 00:00:00 2001 From: Samuel Selleck Date: Mon, 26 Feb 2024 20:46:49 -0800 Subject: [PATCH 3/3] cleanup --- pax-chassis-web/interface/src/classes/native-element-pool.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/pax-chassis-web/interface/src/classes/native-element-pool.ts b/pax-chassis-web/interface/src/classes/native-element-pool.ts index ea0fd1c40..8c90cc81d 100644 --- a/pax-chassis-web/interface/src/classes/native-element-pool.ts +++ b/pax-chassis-web/interface/src/classes/native-element-pool.ts @@ -241,7 +241,6 @@ export class NativeElementPool { let textbox = leaf.firstChild; applyTextTyle(textbox, textbox, patch.style); - console.log(patch); if (patch.background) { textbox.style.background = toCssColor(patch.background);