You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
93 lines
4.0 KiB
TypeScript
93 lines
4.0 KiB
TypeScript
import { Dataspace, Turn, Dataflow } from '@syndicate-lang/core';
|
|
import { boot as bootHtml, template, Anchor } from '@syndicate-lang/html';
|
|
|
|
message type Key(key: string);
|
|
message type Mouse(what: string, x: number, y: number);
|
|
assertion type Status(status: string);
|
|
|
|
Dataspace.boot(ds => {
|
|
bootHtml(ds);
|
|
at ds {
|
|
spawn named 'input-driver' {
|
|
const container = document.getElementById('container')!;
|
|
const facet = Turn.activeFacet;
|
|
facet.preventInertCheck();
|
|
const sendMouseEvent = (what: string) => (e: PointerEvent) => facet.turn(() => {
|
|
const { left, top } = container.getBoundingClientRect();
|
|
send message Mouse(what, e.clientX - left, e.clientY - top);
|
|
});
|
|
container.addEventListener('pointerdown', sendMouseEvent('down'));
|
|
container.addEventListener('pointermove', sendMouseEvent('move'));
|
|
container.addEventListener('pointerup', sendMouseEvent('up'));
|
|
container.addEventListener('keydown', (e) => facet.turn(() => {
|
|
send message Key(e.key);
|
|
}));
|
|
}
|
|
|
|
const WIDTH = 50;
|
|
const HEIGHT = 50;
|
|
|
|
function dragBehaviour(x: Dataflow.Field<number>, y: Dataflow.Field<number>)
|
|
{
|
|
const inBounds = (dx: number, dy: number) =>
|
|
dx >= 0 && dy >= 0 && dx < WIDTH && dy < HEIGHT;
|
|
|
|
function awaitClick(status: string) {
|
|
assert Status(status);
|
|
on message Mouse('down', $dX: number, $dY: number) => {
|
|
if (inBounds(dX - x.value, dY - y.value)) {
|
|
stop {
|
|
react {
|
|
assert Status('Intermediate');
|
|
const [oX, oY] = [x.value, y.value];
|
|
stop on message Mouse('up', _, _) => react {
|
|
awaitClick('Clicked!');
|
|
}
|
|
stop on message Key('Escape') => react {
|
|
awaitClick('Cancelled!');
|
|
}
|
|
stop on message Mouse('move', $nX: number, $nY: number) => react {
|
|
assert Status('Dragging');
|
|
stop on message Mouse('up', _, _) => react {
|
|
awaitClick('Dragged!');
|
|
}
|
|
stop on message Key('Escape') => react {
|
|
[x.value, y.value] = [oX, oY];
|
|
awaitClick('Cancelled!');
|
|
}
|
|
[x.value, y.value] = [oX + nX - dX, oY + nY - dY];
|
|
on message Mouse('move', $nX: number, $nY: number) => {
|
|
[x.value, y.value] = [oX + nX - dX, oY + nY - dY];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
react {
|
|
awaitClick('Waiting');
|
|
}
|
|
}
|
|
|
|
spawn named 'model' {
|
|
const ui = new Anchor();
|
|
field x: number = 24;
|
|
field y: number = 24;
|
|
assert ui.html('#container',
|
|
template`<div class="square"
|
|
style="left: ${x.value}px;
|
|
top: ${y.value}px;
|
|
width: ${WIDTH}px;
|
|
height: ${HEIGHT}px;"></div>`);
|
|
dragBehaviour(x, y);
|
|
}
|
|
|
|
spawn named 'status' {
|
|
const ui = new Anchor();
|
|
during Status($s: string) => assert ui.html('#status', template`${s}`);
|
|
}
|
|
}
|
|
});
|