We have Refs! Emit and Update event to update refs in the 'store'.
This commit is contained in:
parent
a39c80fc74
commit
1af838126e
6 changed files with 119 additions and 20 deletions
|
|
@ -472,5 +472,39 @@ export const builtins: { [name: string]: NativeFunction } = {
|
|||
console.log(`[DEBUG] ${l}: `, value);
|
||||
return value;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
'store': {
|
||||
kind: 'native',
|
||||
name: 'store',
|
||||
arity: 1,
|
||||
fn: (initialValue) => {
|
||||
return { kind: 'ref', value: initialValue };
|
||||
}
|
||||
},
|
||||
|
||||
'get': {
|
||||
kind: 'native',
|
||||
name: 'get',
|
||||
arity: 1,
|
||||
fn: (ref) => {
|
||||
if (ref.kind !== 'ref')
|
||||
throw new Error('get expects a Ref');
|
||||
|
||||
return ref.value;
|
||||
}
|
||||
},
|
||||
|
||||
'update': {
|
||||
kind: 'native',
|
||||
name: 'update',
|
||||
arity: 2,
|
||||
fn: (ref, transformFn) => {
|
||||
return {
|
||||
kind: 'constructor',
|
||||
name: 'Update',
|
||||
args: [ref, transformFn]
|
||||
};
|
||||
}
|
||||
},
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,13 +11,18 @@ import designTokensCode from './design-tokens.cg?raw';
|
|||
import uiComponentsCode from './ui-components.cg?raw';
|
||||
|
||||
import textInputCode from './textinput-test.cg?raw';
|
||||
import refTest from './test-ref.cg?raw';
|
||||
// import testCode from './test.cg?raw';
|
||||
// import counterApp from './counter.cg?raw';
|
||||
|
||||
const canvas = document.createElement('canvas') as HTMLCanvasElement;
|
||||
document.body.appendChild(canvas);
|
||||
|
||||
const cgCode = stdlibCode + '\n' + designTokensCode + '\n' + uiComponentsCode + '\n' + textInputCode;
|
||||
const cgCode = stdlibCode + '\n' +
|
||||
designTokensCode + '\n' +
|
||||
uiComponentsCode + '\n' +
|
||||
textInputCode + '\n'
|
||||
// refTest + '\n';
|
||||
|
||||
try {
|
||||
const tokens = tokenize(cgCode);
|
||||
|
|
|
|||
|
|
@ -77,6 +77,9 @@ export function runApp(app: App, canvas: HTMLCanvasElement, source: string) {
|
|||
handleEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
rerender();
|
||||
|
||||
} catch(error) {
|
||||
if (error instanceof CGError) {
|
||||
console.error(error.format());
|
||||
|
|
@ -120,7 +123,7 @@ export function runApp(app: App, canvas: HTMLCanvasElement, source: string) {
|
|||
child: viewUI,
|
||||
event: {
|
||||
kind: 'constructor',
|
||||
name: 'Focus',
|
||||
name: 'FocusAndClick',
|
||||
args: [{ kind: 'string', value: fullKey }]
|
||||
}
|
||||
};
|
||||
|
|
@ -201,9 +204,41 @@ export function runApp(app: App, canvas: HTMLCanvasElement, source: string) {
|
|||
}
|
||||
|
||||
function handleEvent(event: Value) {
|
||||
if (event.kind === 'constructor' && event.name === 'Focus') {
|
||||
if (event.args.length > 0 && event.args[0].kind === 'string') {
|
||||
setFocus(event.args[0].value);
|
||||
if (event.kind === 'constructor' && event.name === 'FocusAndClick') {
|
||||
if (event.args.length === 2 && event.args[0].kind === 'string') {
|
||||
const componentKey = event.args[0].value;
|
||||
const coords = event.args[1];
|
||||
|
||||
setFocus(componentKey);
|
||||
|
||||
handleComponentEvent(componentKey, {
|
||||
kind: 'constructor',
|
||||
name: 'Clicked',
|
||||
args: [coords]
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (event.kind === 'constructor' && event.name === 'Update') {
|
||||
if (event.args.length === 2) {
|
||||
const ref = event.args[0];
|
||||
const transformFn = event.args[1];
|
||||
|
||||
if (ref.kind !== 'ref')
|
||||
throw new Error('Update event expects a Ref')
|
||||
|
||||
if (transformFn.kind !== 'closure')
|
||||
throw new Error('Update event expects a Ref')
|
||||
|
||||
const callEnv = new Map(transformFn.env);
|
||||
callEnv.set(transformFn.params[0], ref.value);
|
||||
const newValue = evaluate(transformFn.body, callEnv, source);
|
||||
|
||||
ref.value = newValue;
|
||||
|
||||
rerender();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
@ -240,19 +275,22 @@ export function runApp(app: App, canvas: HTMLCanvasElement, source: string) {
|
|||
if (hitResult) {
|
||||
const { event, relativeX, relativeY } = hitResult;
|
||||
|
||||
if (event.kind === 'constructor' && event.name === 'Focus') {
|
||||
if (event.kind === 'constructor' && (event.name === 'Focus' || event.name === 'Update')) {
|
||||
handleEvent(event);
|
||||
} else if (event.kind === 'constructor') {
|
||||
} else if (event.kind === 'constructor' && event.name === 'FocusAndClick') {
|
||||
const eventWithCoords: Value = {
|
||||
kind: 'constructor',
|
||||
name: event.name,
|
||||
args: [{
|
||||
kind: 'record',
|
||||
fields: {
|
||||
x: { kind: 'int', value: Math.floor(relativeX) },
|
||||
y: { kind: 'int', value: Math.floor(relativeY) },
|
||||
args: [
|
||||
event.args[0],
|
||||
{
|
||||
kind: 'record',
|
||||
fields: {
|
||||
x: { kind: 'int', value: Math.floor(relativeX) },
|
||||
y: { kind: 'int', value: Math.floor(relativeY) },
|
||||
}
|
||||
}
|
||||
}]
|
||||
]
|
||||
};
|
||||
handleEvent(eventWithCoords);
|
||||
} else {
|
||||
|
|
|
|||
17
src/test-ref.cg
Normal file
17
src/test-ref.cg
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
counter = store 0;
|
||||
|
||||
view = state viewport \
|
||||
currentCount = get counter;
|
||||
|
||||
Column {
|
||||
gap = 10,
|
||||
children = [
|
||||
Text { content = str currentCount, x = 30, y = 30 },
|
||||
Clickable {
|
||||
event = update counter (n \ n + 1),
|
||||
child = Rect { w = 100, h = 40, color = "blue" }
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
{ init = {}, update = state event \ state, view = view }
|
||||
|
|
@ -46,6 +46,11 @@ export type NativeFunction = {
|
|||
fn: (...args: Value[]) => Value
|
||||
}
|
||||
|
||||
export type RefValue = {
|
||||
kind: 'ref'
|
||||
value: Value
|
||||
}
|
||||
|
||||
export type UIValue =
|
||||
| { kind: 'rect', w: number, h: number, color: string, radius?: number }
|
||||
| { kind: 'text', content: string, x: number, y: number }
|
||||
|
|
@ -59,4 +64,4 @@ export type UIValue =
|
|||
| { kind: 'stack', children: UIValue[] }
|
||||
| { 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 | RefValue;
|
||||
|
|
|
|||
|
|
@ -68,14 +68,15 @@ textInput = config \ Stateful {
|
|||
newCursorPos = max 0 (state.cursorPos - 1);
|
||||
newScroll = calcScrollOffset state.text newCursorPos state.scrollOffset 284;
|
||||
newState = state.{ text = state.text, cursorPos = newCursorPos, scrollOffset = newScroll };
|
||||
return { state = newState, emit = [] }
|
||||
_ = debug "ArrowLeft" [];
|
||||
{ state = newState, emit = [] }
|
||||
)
|
||||
|
||||
| ArrowRight \ (
|
||||
newCursorPos = min (len state.text) (state.cursorPos + 1);
|
||||
newScroll = calcScrollOffset state.text newCursorPos state.scrollOffset 284;
|
||||
newState = state.{ text = state.text, cursorPos = newCursorPos, scrollOffset = newScroll };
|
||||
return { state = newState, emit = [] }
|
||||
{ state = newState, emit = [] }
|
||||
)
|
||||
|
||||
| Backspace \ (
|
||||
|
|
@ -86,19 +87,18 @@ textInput = config \ Stateful {
|
|||
{ state = newState, emit = [config.onChange newText] }
|
||||
)
|
||||
|
||||
| Char c \ (
|
||||
| Char c \
|
||||
_ = debug c;
|
||||
newText = insertChar state.text state.cursorPos c;
|
||||
newCursorPos = state.cursorPos + 1;
|
||||
newScroll = calcScrollOffset newText newCursorPos state.scrollOffset 284;
|
||||
newState = state.{ text = newText, cursorPos = newCursorPos, scrollOffset = newScroll };
|
||||
{ state = newState, emit = [config.onChange newText] }
|
||||
)
|
||||
|
||||
| Clicked coords \ (
|
||||
newCursorPos = findCursorPos state.text coords.x state.scrollOffset 8;
|
||||
newScroll = calcScrollOffset state.text newCursorPos state.scrollOffset 284;
|
||||
newSatte = state.{ text = state.text, cursorPos = newCursorPos, scrollOffset = newScroll };
|
||||
newState = state.{ text = state.text, cursorPos = newCursorPos, scrollOffset = newScroll };
|
||||
{ state = newState, emit = [] }
|
||||
)
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue