Adding Clip ui primitive. text boxes looking... well, still awful but getting there
This commit is contained in:
parent
4626616b14
commit
787e071fbd
4 changed files with 49 additions and 19 deletions
|
|
@ -55,6 +55,7 @@ export type UIValue =
|
|||
| { kind: 'padding', child: UIValue, amount: number }
|
||||
| { kind: 'positioned', x: number, y: number, child: UIValue }
|
||||
| { kind: 'opacity', child: UIValue, opacity: number }
|
||||
| { kind: 'clip', child: UIValue, w: number, h: number }
|
||||
| { 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 }
|
||||
|
||||
|
|
|
|||
|
|
@ -72,27 +72,31 @@ textInput2 = {
|
|||
cursorX = measureText textBeforeCursor;
|
||||
padding = 8;
|
||||
|
||||
Clickable {
|
||||
event = config.onFocus,
|
||||
child =
|
||||
Stack {
|
||||
children = [
|
||||
Rect { w = config.w, h = config.h, color = "rgba(240,240,240,0.9)", radius = 4 },
|
||||
Clip {
|
||||
w = config.w,
|
||||
h = config.h,
|
||||
child = Clickable {
|
||||
event = config.onFocus,
|
||||
child =
|
||||
Stack {
|
||||
children = [
|
||||
Rect { w = config.w, h = config.h, color = "rgba(240,240,240,0.9)", radius = 4 },
|
||||
|
||||
Positioned {
|
||||
x = 8 - state.scrollOffset,
|
||||
y = 8,
|
||||
child = Text { content = state.text, x = 0, y = 17 }
|
||||
},
|
||||
Positioned {
|
||||
x = 8 - state.scrollOffset,
|
||||
y = 8,
|
||||
child = Text { content = state.text, x = 0, y = 17 }
|
||||
},
|
||||
|
||||
(config.focused
|
||||
| True \ Positioned {
|
||||
x = 8 + cursorX - state.scrollOffset,
|
||||
y = 8,
|
||||
child = Rect { w = 2, h = 24, color = "black" }
|
||||
}
|
||||
| _ \ Rect { w = 0, h = 0, color = "transparent" })
|
||||
]
|
||||
(config.focused
|
||||
| True \ Positioned {
|
||||
x = 8 + cursorX - state.scrollOffset,
|
||||
y = 8,
|
||||
child = Rect { w = 2, h = 24, color = "black" }
|
||||
}
|
||||
| _ \ Rect { w = 0, h = 0, color = "transparent" })
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
|||
16
src/ui.ts
16
src/ui.ts
|
|
@ -110,6 +110,16 @@ function renderUI(ui: UIValue, ctx: CanvasRenderingContext2D, x: number, y: numb
|
|||
break;
|
||||
}
|
||||
|
||||
case 'clip': {
|
||||
ctx.save();
|
||||
ctx.beginPath();
|
||||
ctx.rect(x, y, ui.w, ui.h);
|
||||
ctx.clip();
|
||||
renderUI(ui.child, ctx, x, y);
|
||||
ctx.restore();
|
||||
break;
|
||||
}
|
||||
|
||||
case 'stack': {
|
||||
for (const child of ui.children) {
|
||||
renderUI(child, ctx, x, y);
|
||||
|
|
@ -184,6 +194,12 @@ function measure(ui: UIValue): { width: number, height: number } {
|
|||
case 'clickable':
|
||||
return measure(ui.child);
|
||||
|
||||
case 'opacity':
|
||||
return measure(ui.child);
|
||||
|
||||
case 'clip':
|
||||
return { width: ui.w, height: ui.h };
|
||||
|
||||
case 'padding': {
|
||||
const childSize = measure(ui.child);
|
||||
return {
|
||||
|
|
|
|||
|
|
@ -95,6 +95,15 @@ export function valueToUI(value: Value): UIValue {
|
|||
return { kind: 'opacity', opacity: opacity.value, child: valueToUI(child) };
|
||||
}
|
||||
|
||||
case 'Clip': {
|
||||
const { child, w, h } = fields;
|
||||
|
||||
if (w.kind !== 'int' || h.kind !== 'int')
|
||||
throw new Error('Invalid Clip fields');
|
||||
|
||||
return { kind: 'clip', w: w.value, h: h.value, child: valueToUI(child) };
|
||||
}
|
||||
|
||||
case 'Stack': {
|
||||
const children = fields.children;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue