Skip to content

Commit

Permalink
feat: enter to delete list #376
Browse files Browse the repository at this point in the history
  • Loading branch information
Hufe921 committed Dec 27, 2023
1 parent 56ea7d8 commit f542739
Show file tree
Hide file tree
Showing 5 changed files with 167 additions and 81 deletions.
29 changes: 1 addition & 28 deletions src/editor/core/command/CommandAdapt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -559,34 +559,7 @@ export class CommandAdapt {
public list(listType: ListType | null, listStyle?: ListStyle) {
const isReadonly = this.draw.isReadonly()
if (isReadonly) return
const { startIndex, endIndex } = this.range.getRange()
if (!~startIndex && !~endIndex) return
// 需要改变的元素列表
const changeElementList = this.range.getRangeParagraphElementList()
if (!changeElementList || !changeElementList.length) return
// 如果包含列表则设置为取消列表
const isUnsetList = changeElementList.find(
el => el.listType === listType && el.listStyle === listStyle
)
// 设置值
const listId = getUUID()
changeElementList.forEach(el => {
if (!isUnsetList && listType) {
el.listId = listId
el.listType = listType
el.listStyle = listStyle
} else {
if (el.listId) {
delete el.listId
delete el.listType
delete el.listStyle
}
}
})
// 光标定位
const isSetCursor = startIndex === endIndex
const curIndex = isSetCursor ? endIndex : startIndex
this.draw.render({ curIndex, isSetCursor })
this.draw.getListParticle().setList(listType, listStyle)
}

public rowFlex(payload: RowFlex) {
Expand Down
75 changes: 75 additions & 0 deletions src/editor/core/draw/particle/ListParticle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,13 @@ import { DeepRequired } from '../../../interface/Common'
import { IEditorOption } from '../../../interface/Editor'
import { IElement, IElementPosition } from '../../../interface/Element'
import { IRow } from '../../../interface/Row'
import { getUUID } from '../../../utils'
import { RangeManager } from '../../range/RangeManager'
import { Draw } from '../Draw'

export class ListParticle {
private draw: Draw
private range: RangeManager
private options: DeepRequired<IEditorOption>

// 非递增样式直接返回默认值
Expand All @@ -18,9 +22,80 @@ export class ListParticle {
private readonly LIST_GAP = 10

constructor(draw: Draw) {
this.draw = draw
this.range = draw.getRange()
this.options = draw.getOptions()
}

public setList(listType: ListType | null, listStyle?: ListStyle) {
const isReadonly = this.draw.isReadonly()
if (isReadonly) return
const { startIndex, endIndex } = this.range.getRange()
if (!~startIndex && !~endIndex) return
// 需要改变的元素列表
const changeElementList = this.range.getRangeParagraphElementList()
if (!changeElementList || !changeElementList.length) return
// 如果包含列表则设置为取消列表
const isUnsetList = changeElementList.find(
el => el.listType === listType && el.listStyle === listStyle
)
if (isUnsetList || !listType) {
this.unsetList()
return
}
// 设置值
const listId = getUUID()
changeElementList.forEach(el => {
el.listId = listId
el.listType = listType
el.listStyle = listStyle
})
// 光标定位
const isSetCursor = startIndex === endIndex
const curIndex = isSetCursor ? endIndex : startIndex
this.draw.render({ curIndex, isSetCursor })
}

public unsetList() {
const isReadonly = this.draw.isReadonly()
if (isReadonly) return
const { startIndex, endIndex } = this.range.getRange()
if (!~startIndex && !~endIndex) return
// 需要改变的元素列表
const changeElementList = this.range
.getRangeParagraphElementList()
?.filter(el => el.listId)
if (!changeElementList || !changeElementList.length) return
// 如果列表最后字符不是换行符则需插入换行符
const elementList = this.draw.getElementList()
const endElement = elementList[endIndex]
if (endElement.listId) {
let start = endIndex + 1
while (start < elementList.length) {
const element = elementList[start]
if (element.value === ZERO && !element.listWrap) break
if (element.listId !== endElement.listId) {
this.draw.spliceElementList(elementList, start, 0, {
value: ZERO
})
break
}
start++
}
}
// 取消设置
changeElementList.forEach(el => {
delete el.listId
delete el.listType
delete el.listStyle
delete el.listWrap
})
// 光标定位
const isSetCursor = startIndex === endIndex
const curIndex = isSetCursor ? endIndex : startIndex
this.draw.render({ curIndex, isSetCursor })
}

public computeListStyle(
ctx: CanvasRenderingContext2D,
elementList: IElement[]
Expand Down
70 changes: 70 additions & 0 deletions src/editor/core/event/handlers/keydown/enter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import { ZERO } from '../../../../dataset/constant/Common'
import { IElement } from '../../../../interface/Element'
import { formatElementContext } from '../../../../utils/element'
import { CanvasEvent } from '../../CanvasEvent'

export function enter(evt: KeyboardEvent, host: CanvasEvent) {
const draw = host.getDraw()
const isReadonly = draw.isReadonly()
const control = draw.getControl()
if (isReadonly || control.isPartRangeInControlOutside()) return
const rangeManager = draw.getRange()
const { startIndex, endIndex } = rangeManager.getRange()
const isCollapsed = rangeManager.getIsCollapsed()
const elementList = draw.getElementList()
const startElement = elementList[startIndex]
const endElement = elementList[endIndex]
// 最后一个列表项行首回车取消列表设置
if (
isCollapsed &&
endElement.listId &&
endElement.value === ZERO &&
elementList[endIndex + 1]?.listId !== endElement.listId
) {
draw.getListParticle().unsetList()
return
}
// 列表块内换行
const enterText: IElement = {
value: ZERO
}
if (evt.shiftKey && startElement.listId) {
enterText.listWrap = true
}
// 标题结尾处回车无需格式化
if (
!(
endElement.titleId &&
endElement.titleId !== elementList[endIndex + 1]?.titleId
)
) {
formatElementContext(elementList, [enterText], startIndex)
}
// 控件或文档插入换行元素
const activeControl = control.getActiveControl()
let curIndex: number
if (activeControl && !control.isRangInPostfix()) {
curIndex = control.setValue([enterText])
} else {
const position = draw.getPosition()
const cursorPosition = position.getCursorPosition()
if (!cursorPosition) return
const { index } = cursorPosition
if (isCollapsed) {
draw.spliceElementList(elementList, index + 1, 0, enterText)
} else {
draw.spliceElementList(
elementList,
startIndex + 1,
endIndex - startIndex,
enterText
)
}
curIndex = index + 1
}
if (~curIndex) {
rangeManager.setRange(curIndex, curIndex)
draw.render({ curIndex })
}
evt.preventDefault()
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import { EditorMode, EditorZone } from '../../..'
import { ZERO } from '../../../dataset/constant/Common'
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 { 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 { enter } from './enter'

export function keydown(evt: KeyboardEvent, host: CanvasEvent) {
if (host.isComposing) return
Expand Down Expand Up @@ -85,46 +86,7 @@ export function keydown(evt: KeyboardEvent, host: CanvasEvent) {
rangeManager.setRange(curIndex, curIndex)
draw.render({ curIndex })
} else if (evt.key === KeyMap.Enter) {
if (isReadonly || control.isPartRangeInControlOutside()) return
const enterText: IElement = {
value: ZERO
}
const startElement = elementList[startIndex]
const endElement = elementList[endIndex]
// 列表块内换行
if (evt.shiftKey && startElement.listId) {
enterText.listWrap = true
}
// 标题结尾处回车无需格式化
if (
!(
endElement.titleId &&
endElement.titleId !== elementList[endIndex + 1]?.titleId
)
) {
formatElementContext(elementList, [enterText], startIndex)
}
let curIndex: number
if (activeControl && !control.isRangInPostfix()) {
curIndex = control.setValue([enterText])
} else {
if (isCollapsed) {
draw.spliceElementList(elementList, index + 1, 0, enterText)
} else {
draw.spliceElementList(
elementList,
startIndex + 1,
endIndex - startIndex,
enterText
)
}
curIndex = index + 1
}
if (~curIndex) {
rangeManager.setRange(curIndex, curIndex)
draw.render({ curIndex })
}
evt.preventDefault()
enter(evt, host)
} else if (evt.key === KeyMap.Left) {
if (isReadonly) return
if (index > 0) {
Expand Down
14 changes: 10 additions & 4 deletions src/editor/core/range/RangeManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -154,9 +154,12 @@ export class RangeManager {
if (!rowArray.includes(rowNo)) {
rowArray.unshift(rowNo)
}
const element = elementList[start]
const preElement = elementList[start - 1]
if (
positionList[start]?.value === ZERO ||
elementList[start].titleId !== elementList[start - 1]?.titleId
(element.value === ZERO && !element.listWrap) ||
element.listId !== preElement?.listId ||
element.titleId !== preElement?.titleId
) {
break
}
Expand All @@ -181,9 +184,12 @@ export class RangeManager {
// 向下查找
let end = endIndex
while (end < positionList.length) {
const element = elementList[end]
const nextElement = elementList[end + 1]
if (
positionList[end].value === ZERO ||
elementList[end].titleId !== elementList[end + 1]?.titleId
(element.value === ZERO && !element.listWrap) ||
element.listId !== nextElement?.listId ||
element.titleId !== nextElement?.titleId
) {
break
}
Expand Down

0 comments on commit f542739

Please sign in to comment.