Skip to content

Commit

Permalink
long lines support in code editor
Browse files Browse the repository at this point in the history
  • Loading branch information
goldbuick committed Dec 18, 2024
1 parent 82e4286 commit cdbe994
Show file tree
Hide file tree
Showing 4 changed files with 105 additions and 37 deletions.
9 changes: 8 additions & 1 deletion zss/gadget/components/tape/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ import { createContext } from 'react'
import { MODEM_SHARED_VALUE } from 'zss/device/modem'
import { DRAW_CHAR_HEIGHT, DRAW_CHAR_WIDTH } from 'zss/gadget/data/types'
import { MAYBE, ispresent } from 'zss/mapping/types'
import { COLOR } from 'zss/words/types'
import { WRITE_TEXT_CONTEXT, textformatreadedges } from 'zss/words/textformat'
import { COLOR } from 'zss/words/types'

// deco
export const BKG_PTRN = 250
Expand Down Expand Up @@ -112,6 +112,13 @@ export function splitcoderows(code: string): EDITOR_CODE_ROW[] {
})
}

export function findmaxwidthinrows(rows: EDITOR_CODE_ROW[]): number {
return rows.reduce((maxwidth, row) => {
const width = row.code.length
return width > maxwidth ? width : maxwidth
}, 0)
}

export function findcursorinrows(cursor: number, rows: EDITOR_CODE_ROW[]) {
for (let i = 0; i < rows.length; ++i) {
if (cursor <= rows[i].end) {
Expand Down
74 changes: 57 additions & 17 deletions zss/gadget/components/tape/editor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,12 @@ import { ispresent } from 'zss/mapping/types'
import { textformatreadedges } from 'zss/words/textformat'
import { useShallow } from 'zustand/react/shallow'

import { findcursorinrows, sharedtosynced, splitcoderows } from './common'
import {
findcursorinrows,
findmaxwidthinrows,
sharedtosynced,
splitcoderows,
} from './common'
import { BackPlate } from './elements/backplate'
import { EditorFrame } from './elements/editorframe'
import { EditorInput } from './elements/editorinput'
Expand Down Expand Up @@ -36,40 +41,75 @@ export function TapeEditor() {
const strvalue = ispresent(value) ? value.toJSON() : ''
const rows = splitcoderows(strvalue)
const ycursor = findcursorinrows(tapeeditor.cursor, rows)
const xcursor = tapeeditor.cursor - rows[ycursor].start
// figure out longest line of code
const maxwidth = findmaxwidthinrows(rows)

// measure edges once
const props = {
rows,
xcursor,
ycursor,
codepage,
xoffset: tapeeditor.xscroll,
yoffset: tapeeditor.yscroll,
codepage,
ycursor,
rows,
}

const maxscroll = rows.length - 4
const chunkstep = 32
const xmaxscroll = (Math.round(maxwidth / chunkstep) + 1) * chunkstep
const ymaxscroll = rows.length

useEffect(() => {
let xscroll = tapeeditor.xscroll
const xdelta = xcursor - xscroll
const xwidth = edge.width - 3

let xstep = Math.round(clamp(Math.abs(xdelta) * 0.5, 1, chunkstep))
if (xstep < 8) {
xstep = 1
}
if (xdelta > xwidth - 8) {
xscroll += xstep
}
if (xdelta < 8) {
xscroll -= xstep
}

let yscroll = tapeeditor.yscroll
const delta = ycursor - tapeeditor.yscroll
const bottom = edge.height - 8
const maxstep = Math.round(bottom * 0.75)
let step = clamp(Math.round(Math.abs(delta) * 0.25), 1, maxstep)
if (step < 8) {
step = 1
const ydelta = ycursor - yscroll
const yheight = edge.height - 4
const ymaxstep = Math.round(yheight * 0.5)

let ystep = Math.round(clamp(Math.abs(ydelta) * 0.25, 1, ymaxstep))
if (ystep < 8) {
ystep = 1
}
if (delta > bottom) {
yscroll += step
if (ydelta > yheight - 4) {
yscroll += ystep
}
if (delta < 4) {
yscroll -= step
if (ydelta < 4) {
yscroll -= ystep
}

// update
setTimeout(
() =>
useTapeEditor.setState({
yscroll: Math.round(clamp(yscroll, 0, maxscroll)),
xscroll: Math.round(clamp(xscroll, 0, xmaxscroll)),
yscroll: Math.round(clamp(yscroll, 0, ymaxscroll)),
}),
16,
)
}, [ycursor, tapeeditor.yscroll, maxscroll, edge.height])
}, [
xcursor,
xmaxscroll,
tapeeditor.xscroll,
ycursor,
ymaxscroll,
tapeeditor.yscroll,
edge.width,
edge.height,
])

return (
<>
Expand Down
23 changes: 18 additions & 5 deletions zss/gadget/components/tape/elements/editorinput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,18 @@ import { UserInput, modsfromevent } from '../../userinput'
import { EDITOR_CODE_ROW, sharedtosynced } from '../common'

type TextinputProps = {
xcursor: number
ycursor: number
xoffset: number
yoffset: number
rows: EDITOR_CODE_ROW[]
codepage: MAYBE<MODEM_SHARED_STRING>
}

export function EditorInput({
xcursor,
ycursor,
xoffset,
yoffset,
rows,
codepage,
Expand All @@ -41,19 +45,28 @@ export function EditorInput({
const strvalue = ispresent(value) ? value.toJSON() : ''
const rowsend = rows.length - 1

// translate index to x, y
const xcursor = tapeeditor.cursor - rows[ycursor].start

// draw cursor
const xblink = xcursor + 1
const xblink = xcursor + 1 - xoffset
const yblink = ycursor + 2 - yoffset
if (ispresent(codepage)) {
const moving =
blinkdelta.current?.x !== xblink || blinkdelta.current?.y !== yblink
if (blink || moving) {
const x = edge.left + xblink
const y = edge.top + yblink
applystrtoindex(x + y * context.width, String.fromCharCode(221), context)
// visibility clip
if (
y > edge.top + 1 &&
y < edge.bottom &&
x > edge.left &&
x < edge.right
) {
applystrtoindex(
x + y * context.width,
String.fromCharCode(221),
context,
)
}
}
}
blinkdelta.current = { x: xblink, y: yblink }
Expand Down
36 changes: 22 additions & 14 deletions zss/gadget/components/tape/elements/editorrows.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,8 @@ export function EditorRows({
}

// render lines
const left = edge.left + 1 - xoffset
setupeditoritem(false, false, 0, -yoffset, context, 1, 2, 1)
const left = edge.left + 1
setupeditoritem(false, false, -xoffset, -yoffset, context, 1, 2, 1)
for (let i = 0; i < rows.length; ++i) {
if (context.y <= edge.top + 1) {
++context.y
Expand All @@ -75,24 +75,32 @@ export function EditorRows({
const text = row.code.replaceAll('\n', '')

// render
context.x = left
context.x = left - xoffset
context.iseven = context.y % 2 === 0
context.active.bg = active ? BG_ACTIVE : BG
context.disablewrap = true
writeplaintext(`${text}`, context, false)
writeplaintext(`${text} `, context, false)

// render selection
if (hasselection && row.start <= ii2 && row.end >= ii1) {
const index = left + context.y * context.width
const start = Math.max(0, ii1 - row.start)
const end = Math.min(row.end - row.start, ii2 - row.start)
applycolortoindexes(
index + start,
index + end,
FG_SELECTED,
BG_SELECTED,
context,
)
const maybestart = Math.max(row.start, ii1) - row.start - xoffset
const maybeend = Math.min(row.end, ii2) - row.start - xoffset

// start of drawn line
const right = edge.width - 3
const index = 1 + context.y * context.width
const start = Math.max(0, maybestart)
const end = Math.min(right, maybeend)

if (start <= right && end >= left) {
applycolortoindexes(
index + start,
index + end,
FG_SELECTED,
BG_SELECTED,
context,
)
}
}

// next line
Expand Down

0 comments on commit cdbe994

Please sign in to comment.