Published
Edited
Jan 17, 2020
Importers
Insert cell
md`# WASM Controls`
Insert cell
new BigInt64Array([BigInt(4), BigInt(5)])
Insert cell
mutable tObj = ({value: [ BigInt(4), new BigInt64Array([BigInt(4), BigInt(5)])], type: { firsti32: "i32", firstArrayi32: "i32[]"}})
Insert cell
addType = ({
value: [ "label1", "uint16", new dT.BN(0), new dT.BN(0)],
type: { label:"string", "Component":"enum:types", "x1 from T[x1][x2]":"uint8", "x2 from T[x1][x2]":"uint8"}
})
Insert cell
{
yield html `<div id="control3" style="height:500px;"><div id="control2" style="width:50%;"></div><div id="control1" style="width:50%;"></div></div>`
showControl(tObj, "control1", {
gui: {align: 'left'},
onChange: (typed) => {
console.log('onChange', typed);
},
buttons: []
})
showControl(addType, "control2", {
gui: {align: 'right'},
onChange: (typed) => {
},
buttons: []
})
}
Insert cell
function showControl(vObj, divId, options = {}) {
let div = document.getElementById(divId)
div.innerHTML=""
const DEFAULT_OPTS = {
align: 'left',
theme: {
name: "YoRHa",

colors: {
menuBarBackground: '#CCC8B1',
menuBarText: '#454138',
panelBackground: '#fff', //'#CCC8B1',

componentBackground: '#BAB5A1',
componentBackgroundHover: '#877F6E',
componentForeground: '#454138',
componentActive: '#978F7E',

textPrimary: '#454138',
textSecondary: '#454138',
textHover: '#CCC8B1',
textActive: '#CCC8B1',
},

//Optional
font: {
fontFamily: `Roboto Condensed, helvetica, sans-serif`,
fontSize: '14px',
//fontWeight: '100'
},
},
root: div,
open: true,
barMode: "none",
panelMode: "inner",
width: "50%",
opacity: 0.90,
}

let lastObj = Object.assign({}, vObj);

const onChangeSubTyped = (typed) => {
lastObj = Object.assign({}, typed);
options.onChange(typed);
}

const onReinitialize = () => {
showControl(lastObj, divId, options);
}

const guiOptions = Object.assign({}, DEFAULT_OPTS, options.gui || {});
let gui = new guify(guiOptions);
const features = options.buttons || [];

if (options.randomize) {
features.push({ type: "button", label: "Randomize", action: () => {
vObj=dT.t.apply(vObj, "random");
showControl(vObj, divId, options);
if (options.onChange) {
lastObj = Object.assign({}, vObj);
options.onChange(vObj);
}
}});
}

if (options.live) {
features.push({ type: "checkbox", label: "Every Change", initial: false});
}

if (options.toast) {
features.push({ type: "button", label: "Toast", action:() => {gui.Toast('Possible error!');}});
}

const component = gui.Register(features);

return dT.t.apply(vObj, "showControl", "", {
onChange: onChangeSubTyped,
onReinitialize,
args: [gui],
});
}
Insert cell
function createBtn(text, onclick) {
const btn = document.createElement('button');
btn.innerText = text;
btn.onclick = onclick;
btn.style.backgroundColor = "rgb(186, 181, 161)";
btn.style.padding = "2px";
return btn;
}
Insert cell
function guiRegister(typed, gui, guiOptions, options = {}, getContainer) {
const component = gui.Register(guiOptions);
const {arrOptions, onChange} = options;

if (arrOptions) {
const container = getContainer ? getContainer(component) : component.container.children[0];

if (arrOptions.remove) {
const removeBtn = createBtn('-', () => {
console.log('remove');
component.Remove();
if (onChange) onChange(null);
});
container.appendChild(removeBtn);
}
if (arrOptions.add) {
const addBtn = createBtn('+', () => {
console.log('add', typed);
// arrOptions.add(arrOptions.index + 1);
const newElem = JSON.parse(JSON.stringify(typed));
// newArrayElem.value = newArrayElem.value;
if (onChange) onChange(newElem, arrOptions.index + 1);
});
container.appendChild(addBtn);
}
}
return component;
}
Insert cell
function dTControlsExtend(dT) {

dT.controls.bn.showControl = function(typed, folder, options = {}) {
const {onChange, args} = options;
const [gui] = args;
const guiOptions = {
type: 'range', label: typed.name+":"+typed.type,
min: dT.controls[typed.type].min().toNumber(),
max: dT.controls[typed.type].max().toNumber(), step: 1 ,
folder: folder,
initial: typed.value.toNumber(),
onChange: (data) => {
typed.value = new dT.BN(data)
if (onChange) onChange(typed);
}
}

const component = guiRegister(typed, gui, guiOptions, options);
console.log('component dT.controls["bn"]', component);

return typed
}

dT.controls.bbn.showControl = function(typed, folder, options = {}) {
const {onChange, args} = options;
const [gui] = args;
const guiOptions = {
type: 'text', label: typed.name+":"+typed.type,
folder: folder,
initial: "0x"+typed.value.toString(16),
onChange: (data) => {
console.log(data);
if (data.substring(0, 2) === '0x') {
typed.value = new dT.BN(data.substring(2), 16)
} else {
// TODO: fix type checking in UI
typed.value = new dT.BN(parseInt(data));
}
console.log(typed);
if (onChange) onChange(typed);
}
}
const component = guiRegister(typed, gui, guiOptions, options);
console.log('component dT.controls["bbn"]', component);

return typed
}

dT.controls.string.showControl = function(typed, folder, options = {}) {
const {onChange, args} = options;
const [gui] = args;
const guiOptions = {
type: 'text', label: typed.name+":"+typed.type,
folder: folder,
initial: typed.value,
onChange: (data) => {
console.log(data);
typed.value = data
console.log(typed);
if (onChange) onChange(typed);
}
}

const component = guiRegister(typed, gui, guiOptions, options);
console.log('dT.controls["string"]', component);

return typed
}

dT.controls.natural.showControl = function(typed, folder, options = {}) {
const {onChange, args} = options;
const [gui] = args;
const guiOptions = {
type: 'range', label: typed.name+":"+typed.type,
min: dT.controls[typed.type].min(),
max: dT.controls[typed.type].max(),
step: 1,
folder: folder,
initial: typed.value,
onChange: (data) => {
typed.value = data;
if (onChange) onChange(typed);
}
}
const component = guiRegister(typed, gui, guiOptions, options);
console.log('dT.controls["natural"]', component);

return typed
}

dT.enums.controls.showControl = function(typed, folder, options = {}) {
const {onChange, args} = options;
const [gui] = args;
const guiOptions = {
type: 'select', label: typed.name+":"+typed.type,
options: dT.enum_choices[typed.type.substring(5)],
folder: folder,
initial: typed.value,
onChange: (data) => {
console.log(data);
typed.value = data
console.log(typed);
if (onChange) onChange(typed);
}
}
const component = guiRegister(typed, gui, guiOptions, options);
console.log('dT.enums.controls', component);

return typed
}

dT.controls.tuple.showControl = function(typed, folder, options = {}) {
const {onChange, args} = options;
const [gui] = args;
let fold1 = folder+"."+typed.name
const guiOptions = {
type: 'folder',
label: fold1,
folder: folder,
open: true
}
const getContainer = comp => comp.container;
const component = guiRegister(typed, gui, guiOptions, options, getContainer);

return fold1
}

dT.controls.array.showControl = function(typed, folder, options = {}) {
const {onChange, args, arrOptions} = options;
const [gui] = args;
let fold1 = folder+".$."+typed.name
const guiOptions = {
type: 'folder',
label: fold1,
folder: folder,
open: true
}
const component = gui.Register(guiOptions);

// Add sub-element in array at index 0
if (arrOptions.addInner) {
const addElemBtn = createBtn('+', () => {
arrOptions.addInner(0);
});
component.container.insertBefore(addElemBtn, component.container.children[1]);
}

// If array is part of another array, remove array button
if (arrOptions.remove) {
const removeBtn = createBtn('-', () => {
component.Remove();
if (onChange) onChange(null);
});
component.container.appendChild(removeBtn);
}

// If array is part of another array, add another array after it
if (arrOptions.add) {
const addBtn = createBtn('+', () => {
const newArrayElem = Object.assign({}, typed);
newArrayElem.value = [newArrayElem.value[0]];
if (onChange) onChange(newArrayElem, arrOptions.index + 1);
});
component.container.appendChild(addBtn);
}

return fold1
}

dT.controls.bool.showControl = function(typed, folder, options = {}) {
const {onChange, args} = options;
const [gui] = args;
const guiOptions = {
type: 'checkbox', label: typed.name,
folder: folder,
initial: typed.value.gt(new dT.BN(0)),
onChange: (data) => {
console.log(data);
typed.value = data
console.log(typed);
if (onChange) onChange(typed);
}
}
const component = guiRegister(typed, gui, guiOptions, options);

return typed
}

dT.controls.jsfunction.showControl = function(typed, folder, options = {}) {
const {onChange, args} = options;
const [gui] = args;
const guiOptions = {
type: 'button', label: typed.name,
folder: folder,
action: typed.value
}
const component = guiRegister(typed, gui, guiOptions, options);

return typed
}


//wasm
dT.controls.u32.showControl = function(typed, folder, options = {}) {
const {onChange, args} = options;
const [gui] = args;
const guiOptions = {
type: 'range', label: typed.name+":"+typed.type,
min: dT.controls[typed.type].min().toString(10),
max: dT.controls[typed.type].max().toString(10), step: 1 ,
folder: folder,
initial: typed.value.toString(10),
onChange: (data) => {
typed.value = BigInt(data)
if (onChange) onChange(typed);
}
}

const component = guiRegister(typed, gui, guiOptions, options);
console.log('component dT.controls["bn"]', component);

return typed
}
dT.controls.i32.showControl = function(typed, folder, options = {}) {
const {onChange, args} = options;
const [gui] = args;
const guiOptions = {
type: 'text', label: typed.name+":"+typed.type,
folder: folder,
initial: typed.value,
onChange: (data) => {
console.log(data);
typed.value = BigInt(data)
console.log(typed);
if (onChange) onChange(typed);
}
}

const component = guiRegister(typed, gui, guiOptions, options);
console.log('dT.controls["string"]', component);

return typed
}
dT.controls.i64.showControl = dT.controls.i32.showControl
dT.controls.u64.showControl = dT.controls.u32.showControl
dT.controls.f32.showControl = function(typed, folder, options = {}) {
const {onChange, args} = options;
const [gui] = args;
const guiOptions = {
type: 'text', label: typed.name+":"+typed.type,
folder: folder,
initial: typed.value,
onChange: (data) => {
console.log(data);
typed.value = Float32Array([data]);
console.log(typed);
if (onChange) onChange(typed);
}
}

const component = guiRegister(typed, gui, guiOptions, options);
console.log('dT.controls["string"]', component);

return typed
}
dT.controls.f64.showControl = dT.controls.f32.showControl
dT.t.extendTypes();
return dT;
}
Insert cell
import {dT as dtype} from '@khron/dtype-for-wasm';
Insert cell
dT = dTControlsExtend(dtype);
Insert cell
guify = require('guify@0.12.0/lib/guify.min.js');
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more