feat:optimize control active and destroy

pr675
Hufe921 4 years ago
parent 37a5b6a2b2
commit 1cee975033

@ -1,7 +1,6 @@
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, IControlInstance, IControlOption } 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'
@ -15,32 +14,16 @@ export class Control {
private draw: Draw private draw: Draw
private range: RangeManager private range: RangeManager
private options: Required<IEditorOption> private options: IControlOption
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.options = draw.getOptions().control
this.activeControl = null this.activeControl = null
} }
public getOptions(): Required<IEditorOption> {
return this.options
}
public getElementList(): IElement[] {
return this.draw.getElementList()
}
public getRange() {
return this.range.getRange()
}
public getActiveControl(): IControlInstance | null {
return this.activeControl
}
// 判断选区部分在控件边界外 // 判断选区部分在控件边界外
public isPartRangeInControlOutside(): boolean { public isPartRangeInControlOutside(): boolean {
const { startIndex, endIndex } = this.getRange() const { startIndex, endIndex } = this.getRange()
@ -57,20 +40,41 @@ export class Control {
return false return false
} }
public initControl(option: IControlInitOption): IControlInitResult { public getElementList(): IElement[] {
// 调整光标位置 return this.draw.getElementList()
const { newIndex, newElement } = this.moveCursor(option) }
const control = newElement.control!
// 销毁激活控件 public getRange() {
return this.range.getRange()
}
public getActiveControl(): IControlInstance | null {
return this.activeControl
}
public initControl() {
const elementList = this.getElementList()
const range = this.getRange()
const element = elementList[range.startIndex]
// 判断控件是否已经激活
if (this.activeControl) {
const controlElement = this.activeControl.getElement()
if (element.controlId === controlElement.controlId) return
}
// 销毁旧激活控件
this.destroyControl() this.destroyControl()
// 激活控件 // 激活控件
if (control.type === ControlType.TEXT) { if (element.control!.type === ControlType.TEXT) {
this.activeControl = new TextControl(this) this.activeControl = new TextControl(element, this)
}
}
public destroyControl() {
if (this.activeControl) {
this.activeControl = null
} }
return { newIndex }
} }
// 调整起始光标位置到控件合适的位置
public moveCursor(position: IControlInitOption): IMoveCursorResult { public moveCursor(position: IControlInitOption): IMoveCursorResult {
const { index, trIndex, tdIndex, tdValueIndex } = position const { index, trIndex, tdIndex, tdValueIndex } = position
let elementList = this.draw.getOriginalElementList() let elementList = this.draw.getOriginalElementList()
@ -140,9 +144,158 @@ export class Control {
} }
} }
public destroyControl() { public removeControl(startIndex: number): number {
if (this.activeControl) { const elementList = this.getElementList()
this.activeControl = null 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)
return leftIndex
}
public shrinkBoundary() {
const elementList = this.getElementList()
const range = this.getRange()
const { startIndex, endIndex } = range
const startElement = elementList[startIndex]
const endElement = elementList[endIndex]
if (startIndex === endIndex) {
if (startElement.controlComponent === ControlComponent.PLACEHOLDER) {
// 找到第一个placeholder字符
let index = startIndex - 1
while (index > 0) {
const preElement = elementList[index]
if (
preElement.controlId !== startElement.controlId ||
preElement.controlComponent === ControlComponent.PREFIX
) {
console.log(index)
range.startIndex = index
range.endIndex = index
break
}
index--
}
}
} else {
// 首、尾为占位符时,收缩到最后一个前缀字符后
if (
startElement.controlComponent === ControlComponent.PLACEHOLDER ||
endElement.controlComponent === ControlComponent.PLACEHOLDER
) {
let index = endIndex - 1
while (index > 0) {
const preElement = elementList[index]
if (
preElement.controlId !== endElement.controlId
|| preElement.controlComponent === ControlComponent.PREFIX
) {
range.startIndex = index
range.endIndex = index
return
}
index--
}
}
// 向右查找到第一个Value
if (startElement.controlComponent === ControlComponent.PREFIX) {
let index = startIndex + 1
while (index < elementList.length) {
const nextElement = elementList[index]
if (
nextElement.controlId !== startElement.controlId
|| nextElement.controlComponent === ControlComponent.VALUE
) {
range.startIndex = index - 1
break
} else if (nextElement.controlComponent === ControlComponent.PLACEHOLDER) {
range.startIndex = index - 1
range.endIndex = index - 1
return
}
index++
}
}
// 向左查找到第一个Value
if (endElement.controlComponent !== ControlComponent.VALUE) {
let index = startIndex - 1
while (index > 0) {
const preElement = elementList[index]
if (
preElement.controlId !== startElement.controlId
|| preElement.controlComponent === ControlComponent.VALUE
) {
range.startIndex = index
break
} else if (preElement.controlComponent === ControlComponent.PLACEHOLDER) {
range.startIndex = index
range.endIndex = index
return
}
index--
}
}
}
}
public removePlaceholder(startIndex: number) {
const elementList = this.getElementList()
const startElement = elementList[startIndex]
const nextElement = elementList[startIndex + 1]
if (
startElement.controlComponent === ControlComponent.PLACEHOLDER ||
nextElement.controlComponent === ControlComponent.PLACEHOLDER
) {
let index = startIndex
while (index < elementList.length) {
const curElement = elementList[index]
if (curElement.controlId !== startElement.controlId) break
if (curElement.controlComponent === ControlComponent.PLACEHOLDER) {
elementList.splice(index, 1)
} else {
index++
}
}
}
}
public addPlaceholder(startIndex: number) {
const elementList = this.getElementList()
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
})
} }
} }

@ -1,154 +1,21 @@
import { ControlComponent } from '../../../../dataset/enum/Control' import { ControlComponent } from '../../../../dataset/enum/Control'
import { ElementType } from '../../../../dataset/enum/Element'
import { KeyMap } from '../../../../dataset/enum/Keymap' import { KeyMap } from '../../../../dataset/enum/Keymap'
import { IControlInstance, IControlOption } from '../../../../interface/Control' import { IControlInstance } from '../../../../interface/Control'
import { IElement } from '../../../../interface/Element' import { IElement } from '../../../../interface/Element'
import { IRange } from '../../../../interface/Range'
import { Control } from '../Control' import { Control } from '../Control'
export class TextControl implements IControlInstance { export class TextControl implements IControlInstance {
private element: IElement
private control: Control private control: Control
private options: IControlOption
constructor(control: Control) { constructor(element: IElement, control: Control) {
this.element = element
this.control = control this.control = control
this.options = control.getOptions().control
} }
public shrinkBoundary(elementList: IElement[], range: IRange) { public getElement(): IElement {
const { startIndex, endIndex } = range return this.element
if (startIndex === endIndex) return
const startElement = elementList[startIndex]
const endElement = elementList[endIndex]
// 首、尾为占位符时,收缩到最后一个前缀字符后
if (
startElement.controlComponent === ControlComponent.PLACEHOLDER ||
endElement.controlComponent === ControlComponent.PLACEHOLDER
) {
let index = endIndex - 1
while (index > 0) {
const preElement = elementList[index]
if (
preElement.controlId !== endElement.controlId
|| preElement.controlComponent === ControlComponent.PREFIX
) {
range.startIndex = index
range.endIndex = index
return
}
index--
}
}
// 向右查找到第一个Value
if (startElement.controlComponent === ControlComponent.PREFIX) {
let index = startIndex + 1
while (index < elementList.length) {
const nextElement = elementList[index]
if (
nextElement.controlId !== startElement.controlId
|| nextElement.controlComponent === ControlComponent.VALUE
) {
range.startIndex = index - 1
break
} else if (nextElement.controlComponent === ControlComponent.PLACEHOLDER) {
range.startIndex = index - 1
range.endIndex = index - 1
return
}
index++
}
}
// 向左查找到第一个Value
if (endElement.controlComponent !== ControlComponent.VALUE) {
let index = startIndex - 1
while (index > 0) {
const preElement = elementList[index]
if (
preElement.controlId !== startElement.controlId
|| preElement.controlComponent === ControlComponent.VALUE
) {
range.startIndex = index
break
} else if (preElement.controlComponent === ControlComponent.PLACEHOLDER) {
range.startIndex = index
range.endIndex = index
return
}
index--
}
}
}
public removePlaceholder(elementList: IElement[], range: IRange) {
const { startIndex } = range
const startElement = elementList[startIndex]
const nextElement = elementList[startIndex + 1]
if (
startElement.controlComponent === ControlComponent.PLACEHOLDER ||
nextElement.controlComponent === ControlComponent.PLACEHOLDER
) {
let index = startIndex
while (index < elementList.length) {
const curElement = elementList[index]
if (curElement.controlId !== startElement.controlId) break
if (curElement.controlComponent === ControlComponent.PLACEHOLDER) {
elementList.splice(index, 1)
} else {
index++
}
}
}
}
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[] { public getValue(): IElement[] {
@ -193,14 +60,14 @@ export class TextControl implements IControlInstance {
const elementList = this.control.getElementList() const elementList = this.control.getElementList()
const range = this.control.getRange() const range = this.control.getRange()
// 收缩边界到Value内 // 收缩边界到Value内
this.shrinkBoundary(elementList, range) this.control.shrinkBoundary()
const { startIndex, endIndex } = range const { startIndex, endIndex } = range
// 移除选区元素 // 移除选区元素
if (startIndex !== endIndex) { if (startIndex !== endIndex) {
elementList.splice(startIndex + 1, endIndex - startIndex) elementList.splice(startIndex + 1, endIndex - startIndex)
} else { } else {
// 移除空白占位符 // 移除空白占位符
this.removePlaceholder(elementList, range) this.control.removePlaceholder(startIndex)
} }
// 插入 // 插入
const startElement = elementList[startIndex] const startElement = elementList[startIndex]
@ -219,7 +86,7 @@ export class TextControl implements IControlInstance {
const elementList = this.control.getElementList() const elementList = this.control.getElementList()
const range = this.control.getRange() const range = this.control.getRange()
// 收缩边界到Value内 // 收缩边界到Value内
this.shrinkBoundary(elementList, range) this.control.shrinkBoundary()
const { startIndex, endIndex } = range const { startIndex, endIndex } = range
const startElement = elementList[startIndex] const startElement = elementList[startIndex]
const endElement = elementList[endIndex] const endElement = elementList[endIndex]
@ -230,22 +97,23 @@ export class TextControl implements IControlInstance {
elementList.splice(startIndex + 1, endIndex - startIndex) elementList.splice(startIndex + 1, endIndex - startIndex)
const value = this.getValue() const value = this.getValue()
if (!value.length) { if (!value.length) {
this.addPlaceholder(elementList, startIndex) this.control.addPlaceholder(startIndex)
} }
return startIndex return startIndex
} else { } else {
if (startElement.controlComponent === ControlComponent.PREFIX) { if (
// 前缀 startElement.controlComponent === ControlComponent.PREFIX ||
return this.removeControl(elementList, range) endElement.controlComponent === ControlComponent.POSTFIX ||
} else if (endElement.controlComponent === ControlComponent.POSTFIX) { startElement.controlComponent === ControlComponent.PLACEHOLDER
// 后缀 ) {
return this.removeControl(elementList, range) // 前缀、后缀、占位符
return this.control.removeControl(startIndex)
} else { } else {
// 文本 // 文本
elementList.splice(startIndex, 1) elementList.splice(startIndex, 1)
const value = this.getValue() const value = this.getValue()
if (!value.length) { if (!value.length) {
this.addPlaceholder(elementList, startIndex - 1) this.control.addPlaceholder(startIndex - 1)
} }
return startIndex - 1 return startIndex - 1
} }
@ -256,20 +124,23 @@ export class TextControl implements IControlInstance {
elementList.splice(startIndex + 1, endIndex - startIndex) elementList.splice(startIndex + 1, endIndex - startIndex)
const value = this.getValue() const value = this.getValue()
if (!value.length) { if (!value.length) {
this.addPlaceholder(elementList, startIndex) this.control.addPlaceholder(startIndex)
} }
return startIndex return startIndex
} else { } else {
const endNextElement = elementList[endIndex + 1] const endNextElement = elementList[endIndex + 1]
if (endNextElement.controlComponent === ControlComponent.POSTFIX) { if (startElement.controlComponent === ControlComponent.PREFIX ||
// 后缀 endNextElement.controlComponent === ControlComponent.POSTFIX ||
return this.removeControl(elementList, range) startElement.controlComponent === ControlComponent.PLACEHOLDER
) {
// 前缀、后缀、占位符
return this.control.removeControl(startIndex)
} else { } else {
// 文本 // 文本
elementList.splice(startIndex + 1, 1) elementList.splice(startIndex + 1, 1)
const value = this.getValue() const value = this.getValue()
if (!value.length) { if (!value.length) {
this.addPlaceholder(elementList, startIndex) this.control.addPlaceholder(startIndex)
} }
return startIndex return startIndex
} }

@ -175,7 +175,7 @@ export class CanvasEvent {
tdIndex, tdIndex,
tdValueIndex tdValueIndex
} = positionResult } = positionResult
const { newIndex } = this.control.initControl({ const { newIndex } = this.control.moveCursor({
index, index,
isTable, isTable,
trIndex, trIndex,
@ -187,8 +187,6 @@ export class CanvasEvent {
} else { } else {
positionResult.index = newIndex positionResult.index = newIndex
} }
} else {
this.control.destroyControl()
} }
const { const {
index, index,
@ -303,6 +301,8 @@ export class CanvasEvent {
let curIndex: number let curIndex: number
if (activeControl) { if (activeControl) {
curIndex = this.control.keydown(evt) curIndex = this.control.keydown(evt)
} else if (elementList[endIndex + 1]?.type === ElementType.CONTROL) {
curIndex = this.control.removeControl(endIndex + 1)
} else { } else {
if (!isCollapsed) { if (!isCollapsed) {
elementList.splice(startIndex + 1, endIndex - startIndex) elementList.splice(startIndex + 1, endIndex - startIndex)
@ -476,6 +476,7 @@ export class CanvasEvent {
// 忽略选区部分在控件的输入 // 忽略选区部分在控件的输入
return return
} }
const activeControl = this.control.getActiveControl()
const { TEXT, HYPERLINK, SUBSCRIPT, SUPERSCRIPT } = ElementType const { TEXT, HYPERLINK, SUBSCRIPT, SUPERSCRIPT } = ElementType
const text = data.replaceAll(`\n`, ZERO) const text = data.replaceAll(`\n`, ZERO)
const elementList = this.draw.getElementList() const elementList = this.draw.getElementList()
@ -516,7 +517,7 @@ export class CanvasEvent {
}) })
// 控件-移除placeholder // 控件-移除placeholder
let curIndex: number let curIndex: number
if (positionContext.isControl) { if (activeControl) {
curIndex = this.control.setValue(inputData) curIndex = this.control.setValue(inputData)
} else { } else {
let start = 0 let start = 0

@ -53,6 +53,17 @@ export class RangeManager {
this.range.startTrIndex = startTrIndex this.range.startTrIndex = startTrIndex
this.range.endTrIndex = endTrIndex this.range.endTrIndex = endTrIndex
this.range.isCrossRowCol = !!(startTdIndex || endTdIndex || startTrIndex || endTrIndex) this.range.isCrossRowCol = !!(startTdIndex || endTdIndex || startTrIndex || endTrIndex)
// 激活控件
const control = this.draw.getControl()
if (~startIndex && ~endIndex && startIndex === startIndex) {
const elementList = this.draw.getElementList()
const element = elementList[startIndex]
if (element.type === ElementType.CONTROL) {
control.initControl()
return
}
}
control.destroyControl()
} }
public setRangeStyle() { public setRangeStyle() {

@ -41,6 +41,8 @@ export interface IControlInitResult {
} }
export interface IControlInstance { export interface IControlInstance {
getElement(): IElement;
getValue(): IElement[]; getValue(): IElement[];
setValue(data: IElement[]): number; setValue(data: IElement[]): number;

Loading…
Cancel
Save