diff --git a/src/counter.cg b/src/counter.cg index 6acacf1..3a33850 100644 --- a/src/counter.cg +++ b/src/counter.cg @@ -8,7 +8,7 @@ view = count \ children = [ Text({ content = str(count), x = 0, y = 20 }), Clickable { - event = "increment", + event = Increment, child = Rect { w = 100, h = 40, color = "blue" } } ] diff --git a/src/runtime.ts b/src/runtime.ts index ca148ef..7295062 100644 --- a/src/runtime.ts +++ b/src/runtime.ts @@ -74,9 +74,26 @@ export function runApp(app: App, canvas: HTMLCanvasElement) { } - const event = hitTest(x, y); - if (event) { - handleEvent(event); + const hitResult = hitTest(x, y); + 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); + } } }); diff --git a/src/textinput-test.cg b/src/textinput-test.cg index 62911e2..48f2f9e 100644 --- a/src/textinput-test.cg +++ b/src/textinput-test.cg @@ -1,21 +1,31 @@ routeKeyToFocused = state event \ (state.focusedInput == "email" | True \ - newInputState = textInput2.update state.email event; + newInputState = textInput.update state.email event; state.{ email = newInputState } | False \ - newInputState = textInput2.update state.password event; + newInputState = textInput.update state.password event; state.{ password = newInputState }); init = { focusedInput = "email", - email = textInput2.init "", - password = textInput2.init "" + email = textInput.init "", + password = textInput.init "" }; update = state event \ event - | FocusEmail \ state.{ focusedInput = "email" } - | FocusPassword \ state.{ focusedInput = "password" } + | FocusEmail coords \ ( + 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 | ArrowRight \ routeKeyToFocused state ArrowRight | Backspace \ routeKeyToFocused state Backspace @@ -29,13 +39,13 @@ view = state viewport \ child = Column { gap = 10, children = [ - textInput2.view state.email { + textInput.view state.email { focused = state.focusedInput == "email", onFocus = FocusEmail, w = 300, h = 40 }, - textInput2.view state.password { + textInput.view state.password { focused = state.focusedInput == "password", onFocus = FocusPassword, w = 300, diff --git a/src/ui-components.cg b/src/ui-components.cg index a2f4819..dca77fb 100644 --- a/src/ui-components.cg +++ b/src/ui-components.cg @@ -33,7 +33,23 @@ calcScrollOffset = text cursorPos scrollOffset inputWidth \ | True \ cursorX - inputWidth + 20 | 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 = text \ { text = text, cursorPos = 0, scrollOffset = 0 }, @@ -65,6 +81,12 @@ textInput2 = { { 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, view = state config \ diff --git a/src/ui.ts b/src/ui.ts index 8d87eeb..7bd3d11 100644 --- a/src/ui.ts +++ b/src/ui.ts @@ -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) { if (x >= region.x && x < region.x + region.width && 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;