refactor: keydown event code structure

pr675
Hufe921 2 years ago
parent 83f37edbca
commit 0ff6c2fd1f

@ -24,6 +24,7 @@
"rowspan",
"TEXTLIKE",
"trlist",
"updown",
"vite",
"vitepress",
"Yahei"

@ -0,0 +1,60 @@
import { ZERO } from '../../../../dataset/constant/Common'
import { CanvasEvent } from '../../CanvasEvent'
export function backspace(evt: KeyboardEvent, host: CanvasEvent) {
const draw = host.getDraw()
const isReadonly = draw.isReadonly()
if (isReadonly) return
// 控件整体性验证
const control = draw.getControl()
const activeControl = control.getActiveControl()
if (control.isPartRangeInControlOutside()) return
const rangeManager = draw.getRange()
let curIndex: number | null
if (activeControl) {
// 光标在控件内
curIndex = control.keydown(evt)
} else {
// 普通元素删除
const position = draw.getPosition()
const cursorPosition = position.getCursorPosition()
if (!cursorPosition) return
const { index } = cursorPosition
const { startIndex, endIndex } = rangeManager.getRange()
const isCollapsed = rangeManager.getIsCollapsed()
const elementList = draw.getElementList()
// 判断是否允许删除
if (isCollapsed && index === 0) {
const firstElement = elementList[index]
if (firstElement.value === ZERO) {
// 取消首字符列表设置
if (firstElement.listId) {
draw.getListParticle().unsetList()
}
evt.preventDefault()
return
}
}
// 清空当前行对齐方式
const startElement = elementList[startIndex]
if (isCollapsed && startElement.rowFlex && startElement.value === ZERO) {
const rowList = draw.getRowList()
const positionList = position.getPositionList()
const rowNo = positionList[startIndex].rowNo
const rowFlexElementList = rowList[rowNo].elementList
rowFlexElementList.forEach(element => {
delete element.rowFlex
})
}
if (!isCollapsed) {
draw.spliceElementList(elementList, startIndex + 1, endIndex - startIndex)
} else {
draw.spliceElementList(elementList, index, 1)
}
curIndex = isCollapsed ? index - 1 : startIndex
}
if (curIndex === null) return
draw.getGlobalEvent().setCanvasEventAbility()
rangeManager.setRange(curIndex, curIndex)
draw.render({ curIndex })
}

@ -0,0 +1,39 @@
import { CanvasEvent } from '../../CanvasEvent'
export function del(evt: KeyboardEvent, host: CanvasEvent) {
const draw = host.getDraw()
const isReadonly = draw.isReadonly()
if (isReadonly) return
// 控件整体性验证
const control = draw.getControl()
const activeControl = control.getActiveControl()
if (control.isPartRangeInControlOutside()) return
const rangeManager = draw.getRange()
const { startIndex, endIndex } = rangeManager.getRange()
const elementList = draw.getElementList()
let curIndex: number | null
if (activeControl) {
// 光标在控件内
curIndex = control.keydown(evt)
} else if (elementList[endIndex + 1]?.controlId) {
// 光标在控件前
curIndex = control.removeControl(endIndex + 1)
} else {
// 普通元素
const position = draw.getPosition()
const cursorPosition = position.getCursorPosition()
if (!cursorPosition) return
const { index } = cursorPosition
const isCollapsed = rangeManager.getIsCollapsed()
if (!isCollapsed) {
draw.spliceElementList(elementList, startIndex + 1, endIndex - startIndex)
} else {
draw.spliceElementList(elementList, index + 1, 1)
}
curIndex = isCollapsed ? index : startIndex
}
if (curIndex === null) return
draw.getGlobalEvent().setCanvasEventAbility()
rangeManager.setRange(curIndex, curIndex)
draw.render({ curIndex })
}

@ -1,99 +1,23 @@
import { ZERO } from '../../../../dataset/constant/Common'
import { EditorMode, EditorZone } from '../../../../dataset/enum/Editor'
import { ElementType } from '../../../../dataset/enum/Element'
import { KeyMap } from '../../../../dataset/enum/KeyMap'
import { MoveDirection } from '../../../../dataset/enum/Observer'
import { IElement, IElementPosition } from '../../../../interface/Element'
import { formatElementContext } from '../../../../utils/element'
import { isMod } from '../../../../utils/hotkey'
import { CanvasEvent } from '../../CanvasEvent'
import { backspace } from './backspace'
import { del } from './delete'
import { enter } from './enter'
import { left } from './left'
import { right } from './right'
import { tab } from './tab'
import { updown } from './updown'
export function keydown(evt: KeyboardEvent, host: CanvasEvent) {
if (host.isComposing) return
const draw = host.getDraw()
const position = draw.getPosition()
const cursorPosition = position.getCursorPosition()
if (!cursorPosition) return
const isReadonly = draw.isReadonly()
const historyManager = draw.getHistoryManager()
const elementList = draw.getElementList()
const positionList = position.getPositionList()
const { index } = cursorPosition
const rangeManager = draw.getRange()
const { startIndex, endIndex } = rangeManager.getRange()
const isCollapsed = startIndex === endIndex
// 当前激活控件
const control = draw.getControl()
const activeControl = control.getActiveControl()
// 键盘事件逻辑分发
if (evt.key === KeyMap.Backspace) {
if (isReadonly || control.isPartRangeInControlOutside()) return
let curIndex: number | null
if (activeControl) {
curIndex = control.keydown(evt)
} else {
// 判断是否允许删除
if (isCollapsed && index === 0) {
const firstElement = elementList[index]
if (firstElement.value === ZERO) {
// 取消首字符列表设置
if (firstElement.listId) {
draw.getListParticle().unsetList()
}
evt.preventDefault()
return
}
}
// 清空当前行对齐方式
const startElement = elementList[startIndex]
if (isCollapsed && startElement.rowFlex && startElement.value === ZERO) {
const rowList = draw.getRowList()
const rowNo = positionList[startIndex].rowNo
const rowFlexElementList = rowList[rowNo].elementList
rowFlexElementList.forEach(element => {
delete element.rowFlex
})
}
if (!isCollapsed) {
draw.spliceElementList(
elementList,
startIndex + 1,
endIndex - startIndex
)
} else {
draw.spliceElementList(elementList, index, 1)
}
curIndex = isCollapsed ? index - 1 : startIndex
}
if (curIndex === null) return
draw.getGlobalEvent().setCanvasEventAbility()
rangeManager.setRange(curIndex, curIndex)
draw.render({ curIndex })
backspace(evt, host)
} else if (evt.key === KeyMap.Delete) {
if (isReadonly || control.isPartRangeInControlOutside()) return
let curIndex: number | null
if (activeControl) {
curIndex = control.keydown(evt)
} else if (elementList[endIndex + 1]?.controlId) {
curIndex = control.removeControl(endIndex + 1)
} else {
if (!isCollapsed) {
draw.spliceElementList(
elementList,
startIndex + 1,
endIndex - startIndex
)
} else {
draw.spliceElementList(elementList, index + 1, 1)
}
curIndex = isCollapsed ? index : startIndex
}
if (curIndex === null) return
draw.getGlobalEvent().setCanvasEventAbility()
rangeManager.setRange(curIndex, curIndex)
draw.render({ curIndex })
del(evt, host)
} else if (evt.key === KeyMap.Enter) {
enter(evt, host)
} else if (evt.key === KeyMap.Left) {
@ -101,124 +25,14 @@ export function keydown(evt: KeyboardEvent, host: CanvasEvent) {
} else if (evt.key === KeyMap.Right) {
right(evt, host)
} else if (evt.key === KeyMap.Up || evt.key === KeyMap.Down) {
if (isReadonly) return
let anchorPosition: IElementPosition = cursorPosition
// 扩大选区时,判断移动光标点
if (evt.shiftKey) {
if (startIndex === cursorPosition.index) {
anchorPosition = positionList[endIndex]
} else {
anchorPosition = positionList[startIndex]
}
}
const {
index,
rowNo,
rowIndex,
coordinate: {
leftTop: [curLeftX],
rightTop: [curRightX]
}
} = anchorPosition
// 向上时在首行、向下时在尾行则忽略
const isUp = evt.key === KeyMap.Up
if (
(isUp && rowIndex === 0) ||
(!isUp && rowIndex === draw.getRowCount() - 1)
) {
return
}
// 查找下一行位置列表
const probablePosition: IElementPosition[] = []
if (isUp) {
let p = index - 1
while (p > 0) {
const position = positionList[p]
p--
if (position.rowNo === rowNo) continue
if (
probablePosition[0] &&
probablePosition[0].rowNo !== position.rowNo
) {
break
}
probablePosition.unshift(position)
}
} else {
let p = index + 1
while (p < positionList.length) {
const position = positionList[p]
p++
if (position.rowNo === rowNo) continue
if (
probablePosition[0] &&
probablePosition[0].rowNo !== position.rowNo
) {
break
}
probablePosition.push(position)
}
}
// 查找下一行位置:第一个存在交叉宽度的元素位置
let nextIndex = 0
for (let p = 0; p < probablePosition.length; p++) {
const nextPosition = probablePosition[p]
const {
coordinate: {
leftTop: [nextLeftX],
rightTop: [nextRightX]
}
} = nextPosition
if (p === probablePosition.length - 1) {
nextIndex = nextPosition.index
}
if (curRightX <= nextLeftX || curLeftX >= nextRightX) continue
nextIndex = nextPosition.index
break
}
if (!nextIndex) return
// shift则缩放选区
let anchorStartIndex = nextIndex
let anchorEndIndex = nextIndex
if (evt.shiftKey) {
if (startIndex !== endIndex) {
if (startIndex === cursorPosition.index) {
anchorStartIndex = startIndex
} else {
anchorEndIndex = endIndex
}
} else {
if (isUp) {
anchorEndIndex = endIndex
} else {
anchorStartIndex = startIndex
}
}
}
if (anchorStartIndex > anchorEndIndex) {
// prettier-ignore
[anchorStartIndex, anchorEndIndex] = [anchorEndIndex, anchorStartIndex]
}
rangeManager.setRange(anchorStartIndex, anchorEndIndex)
const isCollapsed = anchorStartIndex === anchorEndIndex
draw.render({
curIndex: isCollapsed ? anchorStartIndex : undefined,
isSetCursor: isCollapsed,
isSubmitHistory: false,
isCompute: false
})
// 将光标移动到可视范围内
draw.getCursor().moveCursorToVisible({
cursorPosition: positionList[isUp ? anchorStartIndex : anchorEndIndex],
direction: isUp ? MoveDirection.UP : MoveDirection.DOWN
})
updown(evt, host)
} else if (isMod(evt) && evt.key === KeyMap.Z) {
if (isReadonly && draw.getMode() !== EditorMode.FORM) return
historyManager.undo()
if (draw.isReadonly() && draw.getMode() !== EditorMode.FORM) return
draw.getHistoryManager().undo()
evt.preventDefault()
} else if (isMod(evt) && evt.key === KeyMap.Y) {
if (isReadonly && draw.getMode() !== EditorMode.FORM) return
historyManager.redo()
if (draw.isReadonly() && draw.getMode() !== EditorMode.FORM) return
draw.getHistoryManager().redo()
evt.preventDefault()
} else if (isMod(evt) && evt.key === KeyMap.C) {
host.copy()
@ -230,7 +44,7 @@ export function keydown(evt: KeyboardEvent, host: CanvasEvent) {
host.selectAll()
evt.preventDefault()
} else if (isMod(evt) && evt.key === KeyMap.S) {
if (isReadonly) return
if (draw.isReadonly()) return
const listener = draw.getListener()
if (listener.saved) {
listener.saved(draw.getValue())
@ -250,12 +64,6 @@ export function keydown(evt: KeyboardEvent, host: CanvasEvent) {
}
evt.preventDefault()
} else if (evt.key === KeyMap.TAB) {
const tabElement: IElement = {
type: ElementType.TAB,
value: ''
}
formatElementContext(elementList, [tabElement], startIndex)
draw.insertElementList([tabElement])
evt.preventDefault()
tab(evt, host)
}
}

@ -0,0 +1,20 @@
import { ElementType } from '../../../../dataset/enum/Element'
import { IElement } from '../../../../interface/Element'
import { formatElementContext } from '../../../../utils/element'
import { CanvasEvent } from '../../CanvasEvent'
export function tab(evt: KeyboardEvent, host: CanvasEvent) {
const draw = host.getDraw()
const isReadonly = draw.isReadonly()
if (isReadonly) return
const tabElement: IElement = {
type: ElementType.TAB,
value: ''
}
const rangeManager = draw.getRange()
const { startIndex } = rangeManager.getRange()
const elementList = draw.getElementList()
formatElementContext(elementList, [tabElement], startIndex)
draw.insertElementList([tabElement])
evt.preventDefault()
}

@ -0,0 +1,120 @@
import { KeyMap } from '../../../../dataset/enum/KeyMap'
import { MoveDirection } from '../../../../dataset/enum/Observer'
import { IElementPosition } from '../../../../interface/Element'
import { CanvasEvent } from '../../CanvasEvent'
export function updown(evt: KeyboardEvent, host: CanvasEvent) {
const draw = host.getDraw()
const isReadonly = draw.isReadonly()
if (isReadonly) return
const position = draw.getPosition()
const cursorPosition = position.getCursorPosition()
if (!cursorPosition) return
const rangeManager = draw.getRange()
const { startIndex, endIndex } = rangeManager.getRange()
const positionList = position.getPositionList()
let anchorPosition: IElementPosition = cursorPosition
// 扩大选区时,判断移动光标点
if (evt.shiftKey) {
if (startIndex === cursorPosition.index) {
anchorPosition = positionList[endIndex]
} else {
anchorPosition = positionList[startIndex]
}
}
const {
index,
rowNo,
rowIndex,
coordinate: {
leftTop: [curLeftX],
rightTop: [curRightX]
}
} = anchorPosition
// 向上时在首行、向下时在尾行则忽略
const isUp = evt.key === KeyMap.Up
if (
(isUp && rowIndex === 0) ||
(!isUp && rowIndex === draw.getRowCount() - 1)
) {
return
}
// 查找下一行位置列表
const probablePosition: IElementPosition[] = []
if (isUp) {
let p = index - 1
while (p > 0) {
const position = positionList[p]
p--
if (position.rowNo === rowNo) continue
if (probablePosition[0] && probablePosition[0].rowNo !== position.rowNo) {
break
}
probablePosition.unshift(position)
}
} else {
let p = index + 1
while (p < positionList.length) {
const position = positionList[p]
p++
if (position.rowNo === rowNo) continue
if (probablePosition[0] && probablePosition[0].rowNo !== position.rowNo) {
break
}
probablePosition.push(position)
}
}
// 查找下一行位置:第一个存在交叉宽度的元素位置
let nextIndex = 0
for (let p = 0; p < probablePosition.length; p++) {
const nextPosition = probablePosition[p]
const {
coordinate: {
leftTop: [nextLeftX],
rightTop: [nextRightX]
}
} = nextPosition
if (p === probablePosition.length - 1) {
nextIndex = nextPosition.index
}
if (curRightX <= nextLeftX || curLeftX >= nextRightX) continue
nextIndex = nextPosition.index
break
}
if (!nextIndex) return
// shift则缩放选区
let anchorStartIndex = nextIndex
let anchorEndIndex = nextIndex
if (evt.shiftKey) {
if (startIndex !== endIndex) {
if (startIndex === cursorPosition.index) {
anchorStartIndex = startIndex
} else {
anchorEndIndex = endIndex
}
} else {
if (isUp) {
anchorEndIndex = endIndex
} else {
anchorStartIndex = startIndex
}
}
}
if (anchorStartIndex > anchorEndIndex) {
// prettier-ignore
[anchorStartIndex, anchorEndIndex] = [anchorEndIndex, anchorStartIndex]
}
rangeManager.setRange(anchorStartIndex, anchorEndIndex)
const isCollapsed = anchorStartIndex === anchorEndIndex
draw.render({
curIndex: isCollapsed ? anchorStartIndex : undefined,
isSetCursor: isCollapsed,
isSubmitHistory: false,
isCompute: false
})
// 将光标移动到可视范围内
draw.getCursor().moveCursorToVisible({
cursorPosition: positionList[isUp ? anchorStartIndex : anchorEndIndex],
direction: isUp ? MoveDirection.UP : MoveDirection.DOWN
})
}
Loading…
Cancel
Save