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

Native UI: Textbox #85

Merged
merged 2 commits into from
Jan 18, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
4 changes: 3 additions & 1 deletion examples/src/playground/src/lib.pax
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<Text width=50% height=50% text="Text Properties Test 1 LONG long LONG long long long"
<Text width=50% height=50% text={self.textbox_text}
style = {
font: {Font::system("Times New Roman", FontStyle::Normal, FontWeight::Bold)},
fill: {self.color},
Expand All @@ -8,7 +8,9 @@
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/>
<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"/>
<Button class=small y=50% anchor_y=50% x={50% + 150px} label="Test!!!" style = {
font: {Font::system("Times New Roman", FontStyle::Normal, FontWeight::Bold)},
Expand Down
5 changes: 5 additions & 0 deletions examples/src/playground/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ pub struct Example {
pub checked: Property<bool>,
pub align_vertical: Property<TextAlignVertical>,
pub color: Property<Color>,
pub textbox_text: Property<String>,
}

impl Example {
Expand Down Expand Up @@ -55,6 +56,10 @@ impl Example {
}
}

pub fn textbox_change(&mut self, ctx: &NodeContext, args: ArgsTextboxChange) {
self.textbox_text.set(args.text);
}

pub fn button_click(&mut self, ctx: &NodeContext, args: ArgsButtonClick) {
self.color
.set(Color::rgba(1.0.into(), 0.3.into(), 0.6.into(), 1.0.into()));
Expand Down
105 changes: 105 additions & 0 deletions pax-chassis-web/interface/public/pax-chassis-web-interface.js
Original file line number Diff line number Diff line change
Expand Up @@ -744,6 +744,69 @@ var Pax = (() => {
parent.removeChild(oldNode);
}
}
textboxCreate(patch) {
const textbox = this.objectManager.getFromPool(INPUT);
textbox.type = "text";
textbox.addEventListener("input", (_event) => {
let message = {
"FormTextboxChange": {
"id_chain": patch.idChain,
"text": textbox.value
}
};
this.chassis.interrupt(JSON.stringify(message), void 0);
textbox.value = textbox.fixed_text_value;
});
let runningChain = this.objectManager.getFromPool(DIV);
runningChain.appendChild(textbox);
runningChain.setAttribute("class", NATIVE_LEAF_CLASS);
runningChain.setAttribute("id_chain", String(patch.idChain));
let scroller_id;
if (patch.scrollerIds != null) {
let length = patch.scrollerIds.length;
if (length != 0) {
scroller_id = patch.scrollerIds[length - 1];
}
}
if (patch.idChain != void 0 && patch.zIndex != void 0) {
_NativeElementPool.addNativeElement(
runningChain,
this.baseOcclusionContext,
this.scrollers,
patch.idChain,
scroller_id,
patch.zIndex
);
}
this.textNodes[patch.idChain] = runningChain;
}
textboxUpdate(patch) {
window.textNodes = this.textNodes;
let leaf = this.textNodes[patch.id_chain];
console.assert(leaf !== void 0);
let textbox = leaf.firstChild;
if (patch.text != null) {
textbox.value = patch.text;
textbox.fixed_text_value = textbox.value;
}
if (patch.size_x != null) {
textbox.style.width = patch.size_x - 1 + "px";
}
if (patch.size_y != null) {
textbox.style.height = patch.size_y + "px";
}
if (patch.transform != null) {
leaf.style.transform = packAffineCoeffsIntoMatrix3DString(patch.transform);
}
}
textboxDelete(id_chain) {
console.log("textbox deleted");
let oldNode = this.textNodes[id_chain];
if (oldNode) {
let parent = oldNode.parentElement;
parent.removeChild(oldNode);
}
}
buttonCreate(patch) {
console.assert(patch.idChain != null);
console.assert(patch.clippingIds != null);
Expand Down Expand Up @@ -1283,6 +1346,27 @@ var Pax = (() => {
}
};

// src/classes/messages/textbox-update-patch.ts
var TextboxUpdatePatch = class {
constructor(objectManager2) {
this.objectManager = objectManager2;
}
fromPatch(jsonMessage) {
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"];
}
cleanUp() {
this.id_chain = [];
this.size_x = 0;
this.size_y = 0;
this.transform = [];
this.text = "";
}
};

// src/pools/supported-objects.ts
var OBJECT = "Object";
var ARRAY2 = "Array";
Expand All @@ -1297,6 +1381,7 @@ var Pax = (() => {
var SCROLLER_UPDATE_PATCH = "Scroller Update Patch";
var TEXT_UPDATE_PATCH = "Text Update Patch";
var CHECKBOX_UPDATE_PATCH = "Checkbox Update Patch";
var TEXTBOX_UPDATE_PATCH = "Textbox Update Patch";
var BUTTON_UPDATE_PATCH = "Button Update Patch";
var LAYER = "LAYER";
var OCCLUSION_CONTEXT = "Occlusion Context";
Expand Down Expand Up @@ -1398,6 +1483,13 @@ var Pax = (() => {
patch.cleanUp();
}
},
{
name: TEXTBOX_UPDATE_PATCH,
factory: (objectManager2) => new TextboxUpdatePatch(objectManager2),
cleanUp: (patch) => {
patch.cleanUp();
}
},
{
name: BUTTON_UPDATE_PATCH,
factory: (objectManager2) => new ButtonUpdatePatch(objectManager2),
Expand Down Expand Up @@ -1787,6 +1879,19 @@ var Pax = (() => {
} else if (unwrapped_msg["CheckboxDelete"]) {
let msg = unwrapped_msg["CheckboxDelete"];
nativePool.checkboxDelete(msg);
} else if (unwrapped_msg["TextboxCreate"]) {
let msg = unwrapped_msg["TextboxCreate"];
let patch = objectManager2.getFromPool(ANY_CREATE_PATCH);
patch.fromPatch(msg);
nativePool.textboxCreate(patch);
} else if (unwrapped_msg["TextboxUpdate"]) {
let msg = unwrapped_msg["TextboxUpdate"];
let patch = objectManager2.getFromPool(TEXTBOX_UPDATE_PATCH, objectManager2);
patch.fromPatch(msg);
nativePool.textboxUpdate(patch);
} else if (unwrapped_msg["TextboxDelete"]) {
let msg = unwrapped_msg["TextboxDelete"];
nativePool.textboxDelete(msg);
} else if (unwrapped_msg["TextCreate"]) {
let msg = unwrapped_msg["TextCreate"];
let patch = objectManager2.getFromPool(ANY_CREATE_PATCH);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import {ObjectManager} from "../../pools/object-manager";

export class TextboxUpdatePatch {
public id_chain?: number[];
public size_x?: number;
public size_y?: number;
public transform?: number[];
public text?: string;
objectManager: ObjectManager;

constructor(objectManager: ObjectManager) {
this.objectManager = objectManager;
}

fromPatch(jsonMessage: any) {
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"];
}

cleanUp(){
this.id_chain = [];
this.size_x = 0;
this.size_y = 0;
this.transform = [];
this.text = "";
}
}
76 changes: 76 additions & 0 deletions pax-chassis-web/interface/src/classes/native-element-pool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {arrayToKey, packAffineCoeffsIntoMatrix3DString, readImageToByteBuffer} f
import {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";

export class NativeElementPool {
private canvases: Map<string, HTMLCanvasElement>;
Expand Down Expand Up @@ -182,6 +183,81 @@ export class NativeElementPool {
}
}

textboxCreate(patch: AnyCreatePatch) {
const textbox = this.objectManager.getFromPool(INPUT) as HTMLInputElement;
textbox.type = "text";
textbox.addEventListener("input", (_event) => {
let message = {
"FormTextboxChange": {
"id_chain": patch.idChain!,
"text": textbox.value,
}
}
this.chassis!.interrupt(JSON.stringify(message), undefined);
// @ts-ignore
textbox.value = textbox.fixed_text_value;
});

let runningChain: HTMLDivElement = this.objectManager.getFromPool(DIV);
runningChain.appendChild(textbox);
runningChain.setAttribute("class", NATIVE_LEAF_CLASS)
runningChain.setAttribute("id_chain", String(patch.idChain));
let scroller_id;
if(patch.scrollerIds != null){
let length = patch.scrollerIds.length;
if(length != 0) {
scroller_id = patch.scrollerIds[length-1];
}
}
if(patch.idChain != undefined && patch.zIndex != undefined){
NativeElementPool.addNativeElement(runningChain, this.baseOcclusionContext,
this.scrollers, patch.idChain, scroller_id, patch.zIndex);
}
// @ts-ignore
this.textNodes[patch.idChain] = runningChain;

}


textboxUpdate(patch: TextboxUpdatePatch) {
//@ts-ignore
window.textNodes = this.textNodes;
// @ts-ignore
let leaf = this.textNodes[patch.id_chain];
console.assert(leaf !== undefined);
let textbox = leaf.firstChild;


// Apply the content
if (patch.text != null) {
textbox.value = patch.text;
// @ts-ignore
textbox.fixed_text_value = textbox.value;
}

// Handle size_x and size_y
if (patch.size_x != null) {
textbox.style.width = patch.size_x - 1 + "px";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we have the -1 here?

}
if (patch.size_y != null) {
textbox.style.height = patch.size_y + "px";
}
// Handle transform
if (patch.transform != null) {
leaf.style.transform = packAffineCoeffsIntoMatrix3DString(patch.transform);
}
}

textboxDelete(id_chain: number[]) {
console.log("textbox deleted");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we can clean this up now

// @ts-ignore
let oldNode = this.textNodes[id_chain];
if (oldNode){
let parent = oldNode.parentElement;
parent.removeChild(oldNode);
}
}

buttonCreate(patch: AnyCreatePatch) {
console.assert(patch.idChain != null);
console.assert(patch.clippingIds != null);
Expand Down
15 changes: 15 additions & 0 deletions pax-chassis-web/interface/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
FRAME_UPDATE_PATCH,
IMAGE_LOAD_PATCH, OCCLUSION_UPDATE_PATCH, SCROLLER_UPDATE_PATCH,
SUPPORTED_OBJECTS,
TEXTBOX_UPDATE_PATCH,
TEXT_UPDATE_PATCH
} from "./pools/supported-objects";
import {NativeElementPool} from "./classes/native-element-pool";
Expand All @@ -22,6 +23,7 @@ import {setupEventListeners} from "./events/listeners";
import "./styles/pax-web.css";
import { OcclusionUpdatePatch } from "./classes/messages/occlusion-update-patch";
import { ButtonUpdatePatch } from "./classes/messages/button-update-patch";
import { TextboxUpdatePatch } from "./classes/messages/textbox-update-patch";

let objectManager = new ObjectManager(SUPPORTED_OBJECTS);
let messages : any[];
Expand Down Expand Up @@ -150,6 +152,19 @@ export function processMessages(messages: any[], chassis: PaxChassisWeb, objectM
}else if (unwrapped_msg["CheckboxDelete"]) {
let msg = unwrapped_msg["CheckboxDelete"];
nativePool.checkboxDelete(msg)
} else if(unwrapped_msg["TextboxCreate"]) {
let msg = unwrapped_msg["TextboxCreate"]
let patch: AnyCreatePatch = objectManager.getFromPool(ANY_CREATE_PATCH);
patch.fromPatch(msg);
nativePool.textboxCreate(patch);
} else if (unwrapped_msg["TextboxUpdate"]){
let msg = unwrapped_msg["TextboxUpdate"]
let patch: TextboxUpdatePatch = objectManager.getFromPool(TEXTBOX_UPDATE_PATCH, objectManager);
patch.fromPatch(msg);
nativePool.textboxUpdate(patch);
}else if (unwrapped_msg["TextboxDelete"]) {
let msg = unwrapped_msg["TextboxDelete"];
nativePool.textboxDelete(msg)
} else if(unwrapped_msg["TextCreate"]) {
let msg = unwrapped_msg["TextCreate"]
let patch: AnyCreatePatch = objectManager.getFromPool(ANY_CREATE_PATCH);
Expand Down
7 changes: 7 additions & 0 deletions pax-chassis-web/interface/src/pools/supported-objects.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {Font, TextStyle} from "../classes/text";
import { CheckboxUpdatePatch } from "../classes/messages/checkbox-update-patch";
import { OcclusionUpdatePatch } from "../classes/messages/occlusion-update-patch";
import { ButtonUpdatePatch } from "../classes/messages/button-update-patch";
import { TextboxUpdatePatch } from "../classes/messages/textbox-update-patch";

export const OBJECT = "Object";
export const ARRAY = "Array";
Expand All @@ -26,6 +27,7 @@ export const IMAGE_LOAD_PATCH = "IMAGE LOAD PATCH";
export const SCROLLER_UPDATE_PATCH = "Scroller Update Patch";
export const TEXT_UPDATE_PATCH = "Text Update Patch";
export const CHECKBOX_UPDATE_PATCH = "Checkbox Update Patch";
export const TEXTBOX_UPDATE_PATCH = "Textbox Update Patch";
export const BUTTON_UPDATE_PATCH = "Button Update Patch";

export const LAYER = "LAYER";
Expand Down Expand Up @@ -125,6 +127,11 @@ export let SUPPORTED_OBJECTS = [{
factory: (objectManager: ObjectManager) => new CheckboxUpdatePatch(objectManager),
cleanUp: (patch: CheckboxUpdatePatch) => {patch.cleanUp()},
},
{
name: TEXTBOX_UPDATE_PATCH,
factory: (objectManager: ObjectManager) => new TextboxUpdatePatch(objectManager),
cleanUp: (patch: CheckboxUpdatePatch) => {patch.cleanUp()},
},
{
name: BUTTON_UPDATE_PATCH,
factory: (objectManager: ObjectManager) => new ButtonUpdatePatch(objectManager),
Expand Down
7 changes: 7 additions & 0 deletions pax-chassis-web/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use js_sys::Uint8Array;
use pax_core::ExpressionTable;
use pax_runtime_api::ArgsButtonClick;
use pax_runtime_api::ArgsCheckboxChange;
use pax_runtime_api::ArgsTextboxChange;
use pax_runtime_api::RenderContext;
use std::cell::RefCell;
use std::collections::HashMap;
Expand Down Expand Up @@ -149,6 +150,12 @@ impl PaxChassisWeb {
.expect("button node exists in engine");
node.dispatch_button_click(ArgsButtonClick {}, globals);
}
NativeInterrupt::FormTextboxChange(args) => {
let node = engine
.get_expanded_node(args.id_chain[0])
.expect("textbox node exists in engine");
node.dispatch_textbox_change(ArgsTextboxChange { text: args.text }, globals);
}
NativeInterrupt::FormCheckboxToggle(args) => {
let node = engine
.get_expanded_node(args.id_chain[0])
Expand Down
Loading