Returning coords with Clickable event. Usinsg them to position cursor when clicking in a textfield

master
Dustin Swan 2 days ago
parent 787e071fbd
commit 9f078aaeef
Signed by: dustinswan
GPG Key ID: 30D46587E2100467

@ -8,7 +8,7 @@ view = count \
children = [ children = [
Text({ content = str(count), x = 0, y = 20 }), Text({ content = str(count), x = 0, y = 20 }),
Clickable { Clickable {
event = "increment", event = Increment,
child = Rect { w = 100, h = 40, color = "blue" } child = Rect { w = 100, h = 40, color = "blue" }
} }
] ]

@ -74,10 +74,27 @@ export function runApp(app: App, canvas: HTMLCanvasElement) {
} }
const event = hitTest(x, y); const hitResult = hitTest(x, y);
if (event) { if (hitResult) {
const { event, relativeX, relativeY } = hitResult;
if (event.kind === 'constructor') {
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) },
}
}]
};
handleEvent(eventWithCoords);
} else {
handleEvent(event); handleEvent(event);
} }
}
}); });
window.addEventListener('keydown', (e) => { window.addEventListener('keydown', (e) => {

@ -1,21 +1,31 @@
routeKeyToFocused = state event \ routeKeyToFocused = state event \
(state.focusedInput == "email" (state.focusedInput == "email"
| True \ | True \
newInputState = textInput2.update state.email event; newInputState = textInput.update state.email event;
state.{ email = newInputState } state.{ email = newInputState }
| False \ | False \
newInputState = textInput2.update state.password event; newInputState = textInput.update state.password event;
state.{ password = newInputState }); state.{ password = newInputState });
init = { init = {
focusedInput = "email", focusedInput = "email",
email = textInput2.init "", email = textInput.init "",
password = textInput2.init "" password = textInput.init ""
}; };
update = state event \ event update = state event \ event
| FocusEmail \ state.{ focusedInput = "email" } | FocusEmail coords \ (
| FocusPassword \ state.{ focusedInput = "password" } newState = state.{ focusedInput = "email" };
newInputState = textInput.update state.email (Clicked coords);
newState.{ email = newInputState }
)
| FocusPassword coords \ (
newState = state.{ focusedInput = "password" };
newInputState = textInput.update state.password (Clicked coords);
newState.{ password = newInputState }
)
| ArrowLeft \ routeKeyToFocused state ArrowLeft | ArrowLeft \ routeKeyToFocused state ArrowLeft
| ArrowRight \ routeKeyToFocused state ArrowRight | ArrowRight \ routeKeyToFocused state ArrowRight
| Backspace \ routeKeyToFocused state Backspace | Backspace \ routeKeyToFocused state Backspace
@ -29,13 +39,13 @@ view = state viewport \
child = Column { child = Column {
gap = 10, gap = 10,
children = [ children = [
textInput2.view state.email { textInput.view state.email {
focused = state.focusedInput == "email", focused = state.focusedInput == "email",
onFocus = FocusEmail, onFocus = FocusEmail,
w = 300, w = 300,
h = 40 h = 40
}, },
textInput2.view state.password { textInput.view state.password {
focused = state.focusedInput == "password", focused = state.focusedInput == "password",
onFocus = FocusPassword, onFocus = FocusPassword,
w = 300, w = 300,

@ -33,7 +33,23 @@ calcScrollOffset = text cursorPos scrollOffset inputWidth \
| True \ cursorX - inputWidth + 20 | True \ cursorX - inputWidth + 20
| False \ scrollOffset)); | False \ scrollOffset));
textInput2 = { findPosHelper = text targetX index \
(index >= len text)
| True \ len text
| False \ (
widthSoFar = measureText (slice text 0 index);
widthNext = measureText (slice text 0 (index + 1));
midpoint = (widthSoFar + widthNext) / 2;
(targetX < midpoint
| True \ index
| False \ findPosHelper text targetX (index + 1))
);
findCursorPos = text clickX scrollOffset inputPadding \
adjustedX = clickX + scrollOffset - inputPadding;
findPosHelper text adjustedX 0;
textInput = {
# init : String \ State # init : String \ State
init = text \ { text = text, cursorPos = 0, scrollOffset = 0 }, init = text \ { text = text, cursorPos = 0, scrollOffset = 0 },
@ -65,6 +81,12 @@ textInput2 = {
{ text = newText, cursorPos = newCursorPos, scrollOffset = newScroll } { text = newText, cursorPos = newCursorPos, scrollOffset = newScroll }
) )
| Clicked coords \ (
newCursorPos = findCursorPos state.text coords.x state.scrollOffset 8;
newScroll = calcScrollOffset state.text newCursorPos state.scrollOffset 284;
{ text = state.text, cursorPos = newCursorPos, scrollOffset = newScroll }
)
| _ \ state, | _ \ state,
view = state config \ view = state config \

@ -228,11 +228,15 @@ function measure(ui: UIValue): { width: number, height: number } {
} }
} }
export function hitTest(x: number, y: number): Value | null { export function hitTest(x: number, y: number): { event: Value, relativeX: number, relativeY: number } | null {
for (const region of clickRegions) { for (const region of clickRegions) {
if (x >= region.x && x < region.x + region.width && if (x >= region.x && x < region.x + region.width &&
y >= region.y && y < region.y + region.height) { y >= region.y && y < region.y + region.height) {
return region.event; return {
event: region.event,
relativeX: x - region.x,
relativeY: y - region.y,
};
} }
} }
return null; return null;

Loading…
Cancel
Save