Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Textbox styling pass #120

Merged
merged 3 commits into from
Feb 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 10 additions & 3 deletions examples/src/playground/src/lib.pax
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,14 @@
align_multiline: TextAlignHorizontal::Center
}
/>
<Textbox y=70% anchor_y=50% x=100px width=50% height=30px text={self.textbox_text} @textbox_change=self.textbox_change/>
<Textbox id=text
background={Color::rgba(0.0, 1.0, 0.0, 1.0)}
border_radius=100.0
stroke={
color: {Color::rgba(1.0, 0.0, 1.0, 1.0)}
width: 10px
}
y=70% anchor_y=50% x=100px width=50% height=30px text={self.textbox_text} @textbox_input=self.textbox_input/>
<Checkbox class=small y=50% anchor_y=50% x={50% - 100px} anchor_x=100% checked={self.checked} @checkbox_change=self.checkbox_change/>

<Image class=small class=centered path="assets/images/pax-logo-light.png"/>
Expand Down Expand Up @@ -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
}
}
}
}
2 changes: 1 addition & 1 deletion examples/src/playground/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -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<string>) {
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(){
Expand Down
57 changes: 38 additions & 19 deletions pax-chassis-web/interface/src/classes/native-element-pool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down Expand Up @@ -240,6 +240,23 @@ export class NativeElementPool {
console.assert(leaf !== undefined);
let textbox = leaf.firstChild;

applyTextTyle(textbox, textbox, patch.style);

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) {
Expand Down Expand Up @@ -591,7 +608,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) {

Expand All @@ -601,23 +634,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";
Expand All @@ -637,3 +654,5 @@ function applyTextTyle(textContainer: HTMLDivElement, textElem: HTMLDivElement,
}
}
}


2 changes: 1 addition & 1 deletion pax-chassis-web/interface/src/classes/text.ts
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,7 @@ export function getAlignItems(verticalAlignment: string): string {
}
}

class ColorGroup {
export class ColorGroup {
Hsla?: number[];
Rgba?: number[];
Rgb?: number[];
Expand Down
2 changes: 1 addition & 1 deletion pax-chassis-web/interface/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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"];
Expand Down
5 changes: 5 additions & 0 deletions pax-message/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,11 @@ pub struct TextboxPatch {
pub size_x: Option<f64>,
pub size_y: Option<f64>,
pub text: Option<String>,
pub background: Option<ColorVariantMessage>,
pub stroke_color: Option<ColorVariantMessage>,
pub stroke_width: Option<f64>,
pub border_radius: Option<f64>,
pub style: Option<TextStyleMessage>,
}

#[cfg_attr(debug_assertions, derive(Debug))]
Expand Down
6 changes: 6 additions & 0 deletions pax-runtime/src/expressions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use crate::api::{
// via calls to `read()`
pub struct PropertyExpression<T: Default> {
pub id: usize,
pub has_been_evaluted: bool,
pub cached_value: T,
pub transition_manager: TransitionManager<T>,
}
Expand All @@ -22,12 +23,16 @@ impl<T: Default> PropertyExpression<T> {
id,
cached_value: Default::default(),
transition_manager: TransitionManager::new(),
has_been_evaluted: false,
}
}
}

impl<T: Default + Clone> PropertyInstance<T> for PropertyExpression<T> {
fn get(&self) -> &T {
if !self.has_been_evaluted {
panic!("expression width id {:?} has'nt been evaluated", self.id)
}
&self.cached_value
}

Expand All @@ -41,6 +46,7 @@ impl<T: Default + Clone> PropertyInstance<T> for PropertyExpression<T> {

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 <T: PropertyInstance> implementations
Expand Down
10 changes: 10 additions & 0 deletions pax-std/pax-std-primitives/src/rectangle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
53 changes: 48 additions & 5 deletions pax-std/pax-std-primitives/src/textbox.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,24 @@ impl InstanceNode for TextboxInstance {

fn update(self: Rc<Self>, expanded_node: &Rc<ExpandedNode>, 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);
});
}

Expand Down Expand Up @@ -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));
Expand Down
Empty file removed pax-std/src/forms/text-box.rs
Empty file.
8 changes: 8 additions & 0 deletions pax-std/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,13 @@ 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;

#[pax]
#[primitive("pax_std_primitives::frame::FrameInstance")]
Expand Down Expand Up @@ -78,6 +82,10 @@ pub mod primitives {
#[primitive("pax_std_primitives::textbox::TextboxInstance")]
pub struct Textbox {
pub text: Property<StringBox>,
pub background: Property<Color>,
pub stroke: Property<Stroke>,
pub border_radius: Property<Numeric>,
pub style: Property<TextStyle>,
}

#[pax]
Expand Down
2 changes: 2 additions & 0 deletions pax-std/src/types/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,7 @@ impl Default for Color {
}
}
}

impl Into<ColorVariantMessage> for &Color {
fn into(self) -> ColorVariantMessage {
match self.color_variant {
Expand All @@ -213,6 +214,7 @@ impl Into<ColorVariantMessage> for &Color {
}
}
}

impl PartialEq<ColorVariantMessage> for Color {
fn eq(&self, other: &ColorVariantMessage) -> bool {
match self.color_variant {
Expand Down
Loading