feat:text control delete

pr675
Hufe921 4 years ago
parent 3602093d59
commit 6243a8e4ca

@ -1,6 +1,7 @@
import { ControlComponent, ControlType } from '../../../dataset/enum/Control' import { ControlComponent, ControlType } from '../../../dataset/enum/Control'
import { ElementType } from '../../../dataset/enum/Element' import { ElementType } from '../../../dataset/enum/Element'
import { IControlInitOption, IControlInitResult, IControlInstance } from '../../../interface/Control' import { IControlInitOption, IControlInitResult, IControlInstance } from '../../../interface/Control'
import { IEditorOption } from '../../../interface/Editor'
import { IElement } from '../../../interface/Element' import { IElement } from '../../../interface/Element'
import { RangeManager } from '../../range/RangeManager' import { RangeManager } from '../../range/RangeManager'
import { Draw } from '../Draw' import { Draw } from '../Draw'
@ -14,14 +15,20 @@ export class Control {
private draw: Draw private draw: Draw
private range: RangeManager private range: RangeManager
private options: Required<IEditorOption>
private activeControl: IControlInstance | null private activeControl: IControlInstance | null
constructor(draw: Draw) { constructor(draw: Draw) {
this.draw = draw this.draw = draw
this.range = draw.getRange() this.range = draw.getRange()
this.options = draw.getOptions()
this.activeControl = null this.activeControl = null
} }
public getOptions(): Required<IEditorOption> {
return this.options
}
public getElementList(): IElement[] { public getElementList(): IElement[] {
return this.draw.getElementList() return this.draw.getElementList()
} }
@ -146,4 +153,11 @@ export class Control {
return this.activeControl.setValue(data) return this.activeControl.setValue(data)
} }
public keydown(evt: KeyboardEvent): number {
if (!this.activeControl) {
throw new Error('active control is null')
}
return this.activeControl.keydown(evt)
}
} }

@ -1,5 +1,7 @@
import { ControlComponent } from '../../../../dataset/enum/Control' import { ControlComponent } from '../../../../dataset/enum/Control'
import { IControlInstance } from '../../../../interface/Control' import { ElementType } from '../../../../dataset/enum/Element'
import { KeyMap } from '../../../../dataset/enum/Keymap'
import { IControlInstance, IControlOption } from '../../../../interface/Control'
import { IElement } from '../../../../interface/Element' import { IElement } from '../../../../interface/Element'
import { IRange } from '../../../../interface/Range' import { IRange } from '../../../../interface/Range'
import { Control } from '../Control' import { Control } from '../Control'
@ -7,9 +9,11 @@ import { Control } from '../Control'
export class TextControl implements IControlInstance { export class TextControl implements IControlInstance {
private control: Control private control: Control
private options: IControlOption
constructor(control: Control) { constructor(control: Control) {
this.control = control this.control = control
this.options = control.getOptions().control
} }
public shrinkBoundary(elementList: IElement[], range: IRange) { public shrinkBoundary(elementList: IElement[], range: IRange) {
@ -97,6 +101,94 @@ export class TextControl implements IControlInstance {
} }
} }
public removeControl(elementList: IElement[], range: IRange): number {
const { startIndex } = range
const startElement = elementList[startIndex]
let leftIndex = -1
let rightIndex = -1
// 向左查找
let preIndex = startIndex
while (preIndex > 0) {
const preElement = elementList[preIndex]
if (preElement.controlId !== startElement.controlId) {
leftIndex = preIndex
break
}
preIndex--
}
// 向右查找
let nextIndex = startIndex + 1
while (nextIndex < elementList.length) {
const nextElement = elementList[nextIndex]
if (nextElement.controlId !== startElement.controlId) {
rightIndex = nextIndex - 1
break
}
nextIndex++
}
if (!~leftIndex || !~rightIndex) return -1
// 删除元素
elementList.splice(leftIndex + 1, rightIndex - leftIndex)
// 清除实例
this.control.destroyControl()
return leftIndex
}
public addPlaceholder(elementList: IElement[], startIndex: number) {
const startElement = elementList[startIndex]
const control = startElement.control!
const placeholderStrList = control.placeholder.split('')
for (let p = 0; p < placeholderStrList.length; p++) {
const value = placeholderStrList[p]
elementList.splice(startIndex + p + 1, 0, {
value,
controlId: startElement.controlId,
type: ElementType.CONTROL,
control: startElement.control,
controlComponent: ControlComponent.PLACEHOLDER,
color: this.options.placeholderColor
})
}
}
public getValue(): IElement[] {
const elementList = this.control.getElementList()
const { startIndex } = this.control.getRange()
const startElement = elementList[startIndex]
const data: IElement[] = []
// 向左查找
let preIndex = startIndex
while (preIndex > 0) {
const preElement = elementList[preIndex]
if (
preElement.controlId !== startElement.controlId ||
preElement.controlComponent === ControlComponent.PREFIX
) {
break
}
if (preElement.controlComponent === ControlComponent.VALUE) {
data.unshift(preElement)
}
preIndex--
}
// 向右查找
let nextIndex = startIndex + 1
while (nextIndex < elementList.length) {
const nextElement = elementList[nextIndex]
if (
nextElement.controlId !== startElement.controlId ||
nextElement.controlComponent === ControlComponent.POSTFIX
) {
break
}
if (nextElement.controlComponent === ControlComponent.VALUE) {
data.push(nextElement)
}
nextIndex++
}
return data
}
public setValue(data: IElement[]): number { public setValue(data: IElement[]): number {
const elementList = this.control.getElementList() const elementList = this.control.getElementList()
const range = this.control.getRange() const range = this.control.getRange()
@ -123,4 +215,67 @@ export class TextControl implements IControlInstance {
return start + data.length - 1 return start + data.length - 1
} }
public keydown(evt: KeyboardEvent): number {
const elementList = this.control.getElementList()
const range = this.control.getRange()
// 收缩边界到Value内
this.shrinkBoundary(elementList, range)
const { startIndex, endIndex } = range
const startElement = elementList[startIndex]
const endElement = elementList[endIndex]
// backspace
if (evt.key === KeyMap.Backspace) {
// 移除选区元素
if (startIndex !== endIndex) {
elementList.splice(startIndex + 1, endIndex - startIndex)
const value = this.getValue()
if (!value.length) {
this.addPlaceholder(elementList, startIndex)
}
return startIndex
} else {
if (startElement.controlComponent === ControlComponent.PREFIX) {
// 前缀
return this.removeControl(elementList, range)
} else if (endElement.controlComponent === ControlComponent.POSTFIX) {
// 后缀
return this.removeControl(elementList, range)
} else {
// 文本
elementList.splice(startIndex, 1)
const value = this.getValue()
if (!value.length) {
this.addPlaceholder(elementList, startIndex - 1)
}
return startIndex - 1
}
}
} else if (evt.key === KeyMap.Delete) {
// 移除选区元素
if (startIndex !== endIndex) {
elementList.splice(startIndex + 1, endIndex - startIndex)
const value = this.getValue()
if (!value.length) {
this.addPlaceholder(elementList, startIndex)
}
return startIndex
} else {
const endNextElement = elementList[endIndex + 1]
if (endNextElement.controlComponent === ControlComponent.POSTFIX) {
// 后缀
return this.removeControl(elementList, range)
} else {
// 文本
elementList.splice(startIndex + 1, 1)
const value = this.getValue()
if (!value.length) {
this.addPlaceholder(elementList, startIndex)
}
return startIndex
}
}
}
return -1
}
} }

@ -187,6 +187,8 @@ export class CanvasEvent {
} else { } else {
positionResult.index = newIndex positionResult.index = newIndex
} }
} else {
this.control.destroyControl()
} }
const { const {
index, index,
@ -273,29 +275,42 @@ export class CanvasEvent {
const { index } = cursorPosition const { index } = cursorPosition
const { startIndex, endIndex } = this.range.getRange() const { startIndex, endIndex } = this.range.getRange()
const isCollapsed = startIndex === endIndex const isCollapsed = startIndex === endIndex
// 当前激活控件
const isPartRangeInControlOutside = this.control.isPartRangeInControlOutside()
const activeControl = this.control.getActiveControl()
if (evt.key === KeyMap.Backspace) { if (evt.key === KeyMap.Backspace) {
if (isReadonly) return if (isReadonly || isPartRangeInControlOutside) return
// 判断是否允许删除 let curIndex: number
if (isCollapsed && elementList[index].value === ZERO && index === 0) { if (activeControl) {
evt.preventDefault() curIndex = this.control.keydown(evt)
return
}
if (!isCollapsed) {
elementList.splice(startIndex + 1, endIndex - startIndex)
} else { } else {
elementList.splice(index, 1) // 判断是否允许删除
if (isCollapsed && elementList[index].value === ZERO && index === 0) {
evt.preventDefault()
return
}
if (!isCollapsed) {
elementList.splice(startIndex + 1, endIndex - startIndex)
} else {
elementList.splice(index, 1)
}
curIndex = isCollapsed ? index - 1 : startIndex
} }
const curIndex = isCollapsed ? index - 1 : startIndex
this.range.setRange(curIndex, curIndex) this.range.setRange(curIndex, curIndex)
this.draw.render({ curIndex }) this.draw.render({ curIndex })
} else if (evt.key === KeyMap.Delete) { } else if (evt.key === KeyMap.Delete) {
if (isReadonly) return if (isReadonly || isPartRangeInControlOutside) return
if (!isCollapsed) { let curIndex: number
elementList.splice(startIndex + 1, endIndex - startIndex) if (activeControl) {
curIndex = this.control.keydown(evt)
} else { } else {
elementList.splice(index + 1, 1) if (!isCollapsed) {
elementList.splice(startIndex + 1, endIndex - startIndex)
} else {
elementList.splice(index + 1, 1)
}
curIndex = isCollapsed ? index : startIndex
} }
const curIndex = isCollapsed ? index : startIndex
this.range.setRange(curIndex, curIndex) this.range.setRange(curIndex, curIndex)
this.draw.render({ curIndex }) this.draw.render({ curIndex })
} else if (evt.key === KeyMap.Enter) { } else if (evt.key === KeyMap.Enter) {

@ -2,6 +2,7 @@ import { EDITOR_COMPONENT } from '../../dataset/constant/Editor'
import { IEditorOption } from '../../interface/Editor' import { IEditorOption } from '../../interface/Editor'
import { findParent } from '../../utils' import { findParent } from '../../utils'
import { Cursor } from '../cursor/Cursor' import { Cursor } from '../cursor/Cursor'
import { Control } from '../draw/control/Control'
import { Draw } from '../draw/Draw' import { Draw } from '../draw/Draw'
import { HyperlinkParticle } from '../draw/particle/HyperlinkParticle' import { HyperlinkParticle } from '../draw/particle/HyperlinkParticle'
import { ImageParticle } from '../draw/particle/ImageParticle' import { ImageParticle } from '../draw/particle/ImageParticle'
@ -20,6 +21,7 @@ export class GlobalEvent {
private imageParticle: ImageParticle private imageParticle: ImageParticle
private tableTool: TableTool private tableTool: TableTool
private hyperlinkParticle: HyperlinkParticle private hyperlinkParticle: HyperlinkParticle
private control: Control
constructor(draw: Draw, canvasEvent: CanvasEvent) { constructor(draw: Draw, canvasEvent: CanvasEvent) {
this.draw = draw this.draw = draw
@ -31,6 +33,7 @@ export class GlobalEvent {
this.imageParticle = draw.getImageParticle() this.imageParticle = draw.getImageParticle()
this.tableTool = draw.getTableTool() this.tableTool = draw.getTableTool()
this.hyperlinkParticle = draw.getHyperlinkParticle() this.hyperlinkParticle = draw.getHyperlinkParticle()
this.control = draw.getControl()
} }
public register() { public register() {
@ -74,6 +77,7 @@ export class GlobalEvent {
this.imageParticle.clearResizer() this.imageParticle.clearResizer()
this.tableTool.dispose() this.tableTool.dispose()
this.hyperlinkParticle.clearHyperlinkPopup() this.hyperlinkParticle.clearHyperlinkPopup()
this.control.destroyControl()
} }
public setDragState() { public setDragState() {

@ -41,5 +41,9 @@ export interface IControlInitResult {
} }
export interface IControlInstance { export interface IControlInstance {
getValue(): IElement[];
setValue(data: IElement[]): number; setValue(data: IElement[]): number;
keydown(evt: KeyboardEvent): number;
} }
Loading…
Cancel
Save