master
Dustin Swan 1 day ago
parent 59dc90cfa5
commit a39c80fc74
Signed by: dustinswan
GPG Key ID: 30D46587E2100467

@ -1,6 +1,6 @@
import type { Value } from './types'; import type { Value, UIValue } from './types';
import { valueToUI } from './valueToUI'; import { valueToUI } from './valueToUI';
import { render, hitTest, hitTestTextInput } from './ui'; import { render, hitTest } from './ui';
import { evaluate } from './interpreter'; import { evaluate } from './interpreter';
import { CGError } from './error'; import { CGError } from './error';
@ -23,7 +23,6 @@ export function runApp(app: App, canvas: HTMLCanvasElement, source: string) {
// Focus tracking // Focus tracking
let focusedComponentKey: string | null = null; let focusedComponentKey: string | null = null;
let focusableComponents: Map<string, { x: number, y: number, w: number, h: number }> = new Map();
function setFocus(componentKey: string | null) { function setFocus(componentKey: string | null) {
if (focusedComponentKey === componentKey) return; if (focusedComponentKey === componentKey) return;
@ -135,7 +134,7 @@ export function runApp(app: App, canvas: HTMLCanvasElement, source: string) {
case 'column': { case 'column': {
return { return {
...ui, ...ui,
children: ui.children.map((child, i) => children: ui.children.map((child: UIValue, i: number) =>
expandStateful(child, [...path, i]) expandStateful(child, [...path, i])
) )
} }
@ -237,14 +236,6 @@ export function runApp(app: App, canvas: HTMLCanvasElement, source: string) {
const x = e.clientX - rect.left; const x = e.clientX - rect.left;
const y = e.clientY - rect.top; const y = e.clientY - rect.top;
// Text Inputs
const hitTextInput = hitTestTextInput(x, y);
if (hitTextInput) {
rerender();
return;
}
const hitResult = hitTest(x, y); const hitResult = hitTest(x, y);
if (hitResult) { if (hitResult) {
const { event, relativeX, relativeY } = hitResult; const { event, relativeX, relativeY } = hitResult;

@ -8,12 +8,12 @@ function e(str: string) {
console.log(str); console.log(str);
const tokens = tokenize(str); const tokens = tokenize(str);
console.log(tokens); console.log(tokens);
const p = new Parser(tokens); const p = new Parser(tokens, str);
const ast = p.parse(); const ast = p.parse();
console.log(ast); console.log(ast);
console.log(prettyPrint(ast)); console.log(prettyPrint(ast));
const env: Env = new Map(); const env: Env = new Map();
console.log(evaluate(ast, env)); console.log(evaluate(ast, env, str));
} }
e('add1 = (x \\ x + 1); add1 3'); e('add1 = (x \\ x + 1); add1 3');
@ -49,4 +49,3 @@ fib = n \\ n
[ fib 10, factorial 5 ]; [ fib 10, factorial 5 ];
`); `);

@ -57,7 +57,6 @@ export type UIValue =
| { kind: 'opacity', child: UIValue, opacity: number } | { kind: 'opacity', child: UIValue, opacity: number }
| { kind: 'clip', child: UIValue, w: number, h: number } | { kind: 'clip', child: UIValue, w: number, h: number }
| { kind: 'stack', children: UIValue[] } | { kind: 'stack', children: UIValue[] }
| { kind: 'text-input', value: string, placeholder: string, x: number, y: number, w: number, h: number, focused: boolean, onInput: Value, onSubmit: Value }
| { kind: 'stateful', key: string, focusable: boolean, init: Value, update: Value, view: Value } | { kind: 'stateful', key: string, focusable: boolean, init: Value, update: Value, view: Value }
export type Value = IntValue | FloatValue | StringValue | Closure | ListValue | RecordValue | ConstructorValue | NativeFunction; export type Value = IntValue | FloatValue | StringValue | Closure | ListValue | RecordValue | ConstructorValue | NativeFunction;

@ -4,8 +4,8 @@ button = config \
event = config.event, event = config.event,
child = Stack { child = Stack {
children = [ children = [
Rect { w = 100, h = 40, color = config.theme.colors.primary }, Rect { w = 100, h = 40, color = "#eee" },
Text { content = config.label, x = 10, y = 25, color = config.theme.colors.bg } Text { content = config.label, x = 10, y = 25, color = "#222" }
] ]
} }
}; };

@ -126,38 +126,6 @@ function renderUI(ui: UIValue, ctx: CanvasRenderingContext2D, x: number, y: numb
} }
break; break;
} }
case 'text-input': {
ctx.fillStyle = ui.value ? '#000000' : '#999999';
ctx.font = '16px "SF Mono", "Monaco", "Menlo", "Consolas", "Courier New", monospace';
ctx.fillText(
ui.value || ui.placeholder,
x + ui.x + 8,
y + ui.y + ui.h / 2 + 6
);
// Draw cursor
if (ui.focused) {
const textWidth = ctx.measureText(ui.value).width;
ctx.fillStyle = '#000000';
ctx.fillRect(x + ui.x + 8 + textWidth, y + ui.y + 8, 2, ui.h - 16);
}
textInputRegions.push({
x: x + ui.x,
y: y + ui.y,
width: ui.w,
height: ui.h,
inputConstructor: ui.onInput,
submitConstructor: ui.onSubmit
});
if (ui.focused && focusedInput && (ui.onInput as any).name === (focusedInput as any).name) {
currentInputValue = ui.value;
}
break;
}
} }
} }
@ -223,8 +191,8 @@ function measure(ui: UIValue): { width: number, height: number } {
return { width: maxWidth, height: maxHeight }; return { width: maxWidth, height: maxHeight };
} }
case 'text-input': case 'stateful':
return { width: ui.w, height: ui.h }; throw new Error('Stateful components cannot be measured');
} }
} }

@ -113,30 +113,6 @@ export function valueToUI(value: Value): UIValue {
return { kind: 'stack', children: children.elements.map(valueToUI) }; return { kind: 'stack', children: children.elements.map(valueToUI) };
} }
case 'TextInput': {
const { value, placeholder, x, y, w, h, focused, onInput, onSubmit } = fields;
if (value.kind !== 'string' || placeholder.kind !== 'string' ||
x.kind !== 'int' || y.kind !== 'int' || w.kind !== 'int' || h.kind !== 'int' ||
onInput.kind !== 'constructor' || onSubmit.kind !== 'constructor')
throw new Error('Invalid TextInput fields');
const isFocused = focused.kind === 'constructor' && focused.name === 'True';
return {
kind: 'text-input',
value: value.value,
placeholder: placeholder.value,
x: x.value,
y: y.value,
w: w.value,
h: h.value,
focused: isFocused,
onInput: onInput,
onSubmit: onSubmit
};
}
case 'Stateful': { case 'Stateful': {
const { key, focusable, init, update, view } = fields; const { key, focusable, init, update, view } = fields;

Loading…
Cancel
Save