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) {
|
public list(listType: ListType | null, listStyle?: ListStyle) {
|
||||||
const isReadonly = this.draw.isReadonly()
|
const isReadonly = this.draw.isReadonly()
|
||||||
if (isReadonly) return
|
if (isReadonly) return
|
||||||
const { startIndex, endIndex } = this.range.getRange()
|
this.draw.getListParticle().setList(listType, listStyle)
|
||||||
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 })
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public rowFlex(payload: RowFlex) {
|
public rowFlex(payload: RowFlex) {
|
||||||
|
|||||||
@@ -7,9 +7,13 @@ import { DeepRequired } from '../../../interface/Common'
|
|||||||
import { IEditorOption } from '../../../interface/Editor'
|
import { IEditorOption } from '../../../interface/Editor'
|
||||||
import { IElement, IElementPosition } from '../../../interface/Element'
|
import { IElement, IElementPosition } from '../../../interface/Element'
|
||||||
import { IRow } from '../../../interface/Row'
|
import { IRow } from '../../../interface/Row'
|
||||||
|
import { getUUID } from '../../../utils'
|
||||||
|
import { RangeManager } from '../../range/RangeManager'
|
||||||
import { Draw } from '../Draw'
|
import { Draw } from '../Draw'
|
||||||
|
|
||||||
export class ListParticle {
|
export class ListParticle {
|
||||||
|
private draw: Draw
|
||||||
|
private range: RangeManager
|
||||||
private options: DeepRequired<IEditorOption>
|
private options: DeepRequired<IEditorOption>
|
||||||
|
|
||||||
// 非递增样式直接返回默认值
|
// 非递增样式直接返回默认值
|
||||||
@@ -18,9 +22,80 @@ export class ListParticle {
|
|||||||
private readonly LIST_GAP = 10
|
private readonly LIST_GAP = 10
|
||||||
|
|
||||||
constructor(draw: Draw) {
|
constructor(draw: Draw) {
|
||||||
|
this.draw = draw
|
||||||
|
this.range = draw.getRange()
|
||||||
this.options = draw.getOptions()
|
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(
|
public computeListStyle(
|
||||||
ctx: CanvasRenderingContext2D,
|
ctx: CanvasRenderingContext2D,
|
||||||
elementList: IElement[]
|
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 { ZERO } from '../../../dataset/constant/Common'
|
import { EditorMode, EditorZone } from '../../../../dataset/enum/Editor'
|
||||||
import { ElementType } from '../../../dataset/enum/Element'
|
import { ElementType } from '../../../../dataset/enum/Element'
|
||||||
import { KeyMap } from '../../../dataset/enum/KeyMap'
|
import { KeyMap } from '../../../../dataset/enum/KeyMap'
|
||||||
import { MoveDirection } from '../../../dataset/enum/Observer'
|
import { MoveDirection } from '../../../../dataset/enum/Observer'
|
||||||
import { IElement, IElementPosition } from '../../../interface/Element'
|
import { IElement, IElementPosition } from '../../../../interface/Element'
|
||||||
import { formatElementContext } from '../../../utils/element'
|
import { formatElementContext } from '../../../../utils/element'
|
||||||
import { isMod } from '../../../utils/hotkey'
|
import { isMod } from '../../../../utils/hotkey'
|
||||||
import { CanvasEvent } from '../CanvasEvent'
|
import { CanvasEvent } from '../../CanvasEvent'
|
||||||
|
import { enter } from './enter'
|
||||||
|
|
||||||
export function keydown(evt: KeyboardEvent, host: CanvasEvent) {
|
export function keydown(evt: KeyboardEvent, host: CanvasEvent) {
|
||||||
if (host.isComposing) return
|
if (host.isComposing) return
|
||||||
@@ -85,46 +86,7 @@ export function keydown(evt: KeyboardEvent, host: CanvasEvent) {
|
|||||||
rangeManager.setRange(curIndex, curIndex)
|
rangeManager.setRange(curIndex, curIndex)
|
||||||
draw.render({ curIndex })
|
draw.render({ curIndex })
|
||||||
} else if (evt.key === KeyMap.Enter) {
|
} else if (evt.key === KeyMap.Enter) {
|
||||||
if (isReadonly || control.isPartRangeInControlOutside()) return
|
enter(evt, host)
|
||||||
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()
|
|
||||||
} else if (evt.key === KeyMap.Left) {
|
} else if (evt.key === KeyMap.Left) {
|
||||||
if (isReadonly) return
|
if (isReadonly) return
|
||||||
if (index > 0) {
|
if (index > 0) {
|
||||||
@@ -154,9 +154,12 @@ export class RangeManager {
|
|||||||
if (!rowArray.includes(rowNo)) {
|
if (!rowArray.includes(rowNo)) {
|
||||||
rowArray.unshift(rowNo)
|
rowArray.unshift(rowNo)
|
||||||
}
|
}
|
||||||
|
const element = elementList[start]
|
||||||
|
const preElement = elementList[start - 1]
|
||||||
if (
|
if (
|
||||||
positionList[start]?.value === ZERO ||
|
(element.value === ZERO && !element.listWrap) ||
|
||||||
elementList[start].titleId !== elementList[start - 1]?.titleId
|
element.listId !== preElement?.listId ||
|
||||||
|
element.titleId !== preElement?.titleId
|
||||||
) {
|
) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -181,9 +184,12 @@ export class RangeManager {
|
|||||||
// 向下查找
|
// 向下查找
|
||||||
let end = endIndex
|
let end = endIndex
|
||||||
while (end < positionList.length) {
|
while (end < positionList.length) {
|
||||||
|
const element = elementList[end]
|
||||||
|
const nextElement = elementList[end + 1]
|
||||||
if (
|
if (
|
||||||
positionList[end].value === ZERO ||
|
(element.value === ZERO && !element.listWrap) ||
|
||||||
elementList[end].titleId !== elementList[end + 1]?.titleId
|
element.listId !== nextElement?.listId ||
|
||||||
|
element.titleId !== nextElement?.titleId
|
||||||
) {
|
) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user