feat: enter to delete list #376
This commit is contained in:
@@ -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) {
|
||||
|
||||
@@ -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>
|
||||
|
||||
// 非递增样式直接返回默认值
|
||||
@@ -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[]
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
+11
-49
@@ -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
|
||||
@@ -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) {
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user