|
|
|
|
@ -1,9 +1,9 @@
|
|
|
|
|
import { version } from '../../../../package.json'
|
|
|
|
|
import { ZERO } from '../../dataset/constant/Common'
|
|
|
|
|
import { RowFlex } from '../../dataset/enum/Row'
|
|
|
|
|
import { IDrawOption, IDrawRowPayload, IPainterOptions } from '../../interface/Draw'
|
|
|
|
|
import { IEditorDrawData, IEditorOption, IEditorResult } from '../../interface/Editor'
|
|
|
|
|
import { IElement, IElementMetrics, IElementPosition, IElementFillRect, IElementStyle } from '../../interface/Element'
|
|
|
|
|
import { IDrawOption, IDrawPagePayload, IDrawRowPayload, IPainterOptions } from '../../interface/Draw'
|
|
|
|
|
import { IEditorData, IEditorOption, IEditorResult } from '../../interface/Editor'
|
|
|
|
|
import { IElement, IElementMetrics, IElementFillRect, IElementStyle } from '../../interface/Element'
|
|
|
|
|
import { IRow, IRowElement } from '../../interface/Row'
|
|
|
|
|
import { deepClone, getUUID, nextTick } from '../../utils'
|
|
|
|
|
import { Cursor } from '../cursor/Cursor'
|
|
|
|
|
@ -35,7 +35,7 @@ import { SubscriptParticle } from './particle/Subscript'
|
|
|
|
|
import { SeparatorParticle } from './particle/Separator'
|
|
|
|
|
import { PageBreakParticle } from './particle/PageBreak'
|
|
|
|
|
import { Watermark } from './frame/Watermark'
|
|
|
|
|
import { EditorComponent, EditorMode, PageMode, PaperDirection } from '../../dataset/enum/Editor'
|
|
|
|
|
import { EditorComponent, EditorMode, EditorZone, PageMode, PaperDirection } from '../../dataset/enum/Editor'
|
|
|
|
|
import { Control } from './control/Control'
|
|
|
|
|
import { zipElementList } from '../../utils/element'
|
|
|
|
|
import { CheckboxParticle } from './particle/CheckboxParticle'
|
|
|
|
|
@ -50,6 +50,7 @@ import { BlockParticle } from './particle/block/BlockParticle'
|
|
|
|
|
import { EDITOR_COMPONENT, EDITOR_PREFIX } from '../../dataset/constant/Editor'
|
|
|
|
|
import { I18n } from '../i18n/I18n'
|
|
|
|
|
import { ImageObserver } from '../observer/ImageObserver'
|
|
|
|
|
import { Zone } from '../zone/Zone'
|
|
|
|
|
|
|
|
|
|
export class Draw {
|
|
|
|
|
|
|
|
|
|
@ -61,6 +62,7 @@ export class Draw {
|
|
|
|
|
private mode: EditorMode
|
|
|
|
|
private options: DeepRequired<IEditorOption>
|
|
|
|
|
private position: Position
|
|
|
|
|
private zone: Zone
|
|
|
|
|
private headerElementList: IElement[]
|
|
|
|
|
private elementList: IElement[]
|
|
|
|
|
private footerElementList: IElement[]
|
|
|
|
|
@ -112,7 +114,7 @@ export class Draw {
|
|
|
|
|
constructor(
|
|
|
|
|
rootContainer: HTMLElement,
|
|
|
|
|
options: DeepRequired<IEditorOption>,
|
|
|
|
|
data: IEditorDrawData,
|
|
|
|
|
data: IEditorData,
|
|
|
|
|
listener: Listener
|
|
|
|
|
) {
|
|
|
|
|
this.container = this._wrapContainer(rootContainer)
|
|
|
|
|
@ -133,6 +135,7 @@ export class Draw {
|
|
|
|
|
this.i18n = new I18n()
|
|
|
|
|
this.historyManager = new HistoryManager()
|
|
|
|
|
this.position = new Position(this)
|
|
|
|
|
this.zone = new Zone()
|
|
|
|
|
this.range = new RangeManager(this)
|
|
|
|
|
this.margin = new Margin(this)
|
|
|
|
|
this.background = new Background(this)
|
|
|
|
|
@ -212,6 +215,12 @@ export class Draw {
|
|
|
|
|
return Math.floor(this.getOriginalHeight() * this.options.scale)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public getOriginalMainHeight(): number {
|
|
|
|
|
const mainHeight = this.getOriginalHeight()
|
|
|
|
|
const extraHeight = this.header.getExtraHeight()
|
|
|
|
|
return mainHeight - extraHeight
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public getCanvasWidth(pageNo = -1): number {
|
|
|
|
|
const page = this.getPage(pageNo)
|
|
|
|
|
return page.width
|
|
|
|
|
@ -343,6 +352,10 @@ export class Draw {
|
|
|
|
|
return this.position
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public getZone(): Zone {
|
|
|
|
|
return this.zone
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public getRange(): RangeManager {
|
|
|
|
|
return this.range
|
|
|
|
|
}
|
|
|
|
|
@ -351,12 +364,35 @@ export class Draw {
|
|
|
|
|
return this.headerElementList
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public getTableElementList(sourceElementList: IElement[]): IElement[] {
|
|
|
|
|
const positionContext = this.position.getPositionContext()
|
|
|
|
|
const { index, trIndex, tdIndex } = positionContext
|
|
|
|
|
return sourceElementList[index!].trList![trIndex!].tdList[tdIndex!].value
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public getElementList(): IElement[] {
|
|
|
|
|
const positionContext = this.position.getPositionContext()
|
|
|
|
|
if (positionContext.isTable) {
|
|
|
|
|
const { index, trIndex, tdIndex } = positionContext
|
|
|
|
|
return this.elementList[index!].trList![trIndex!].tdList[tdIndex!].value
|
|
|
|
|
}
|
|
|
|
|
const elementList = this.getOriginalElementList()
|
|
|
|
|
return positionContext.isTable
|
|
|
|
|
? this.getTableElementList(elementList)
|
|
|
|
|
: elementList
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public getMainElementList(): IElement[] {
|
|
|
|
|
const positionContext = this.position.getPositionContext()
|
|
|
|
|
return positionContext.isTable
|
|
|
|
|
? this.getTableElementList(this.elementList)
|
|
|
|
|
: this.elementList
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public getOriginalElementList() {
|
|
|
|
|
const zoneManager = this.getZone()
|
|
|
|
|
return zoneManager.isHeaderActive()
|
|
|
|
|
? this.header.getElementList()
|
|
|
|
|
: this.elementList
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public getOriginalMainElementList(): IElement[] {
|
|
|
|
|
return this.elementList
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@ -406,10 +442,6 @@ export class Draw {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public getOriginalElementList() {
|
|
|
|
|
return this.elementList
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public getCanvasEvent(): CanvasEvent {
|
|
|
|
|
return this.canvasEvent
|
|
|
|
|
}
|
|
|
|
|
@ -434,6 +466,10 @@ export class Draw {
|
|
|
|
|
return this.tableTool
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public getHeader(): Header {
|
|
|
|
|
return this.header
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public getHyperlinkParticle(): HyperlinkParticle {
|
|
|
|
|
return this.hyperlinkParticle
|
|
|
|
|
}
|
|
|
|
|
@ -610,7 +646,7 @@ export class Draw {
|
|
|
|
|
// 配置
|
|
|
|
|
const { width, height, margins, watermark } = this.options
|
|
|
|
|
// 数据
|
|
|
|
|
const data: IEditorDrawData = {
|
|
|
|
|
const data: IEditorData = {
|
|
|
|
|
header: zipElementList(this.headerElementList),
|
|
|
|
|
main: zipElementList(this.elementList)
|
|
|
|
|
}
|
|
|
|
|
@ -768,7 +804,7 @@ export class Draw {
|
|
|
|
|
metrics.boundingBoxAscent = 0
|
|
|
|
|
// 表格分页处理(拆分表格)
|
|
|
|
|
const margins = this.getMargins()
|
|
|
|
|
const height = this.getHeight()
|
|
|
|
|
const height = this.getOriginalMainHeight()
|
|
|
|
|
const marginHeight = margins[0] + margins[2]
|
|
|
|
|
let curPagePreHeight = marginHeight
|
|
|
|
|
for (let r = 0; r < rowList.length; r++) {
|
|
|
|
|
@ -826,13 +862,13 @@ export class Draw {
|
|
|
|
|
} else if (element.type === ElementType.SEPARATOR) {
|
|
|
|
|
element.width = innerWidth
|
|
|
|
|
metrics.width = innerWidth
|
|
|
|
|
metrics.height = this.options.defaultSize
|
|
|
|
|
metrics.height = defaultSize
|
|
|
|
|
metrics.boundingBoxAscent = -rowMargin
|
|
|
|
|
metrics.boundingBoxDescent = -rowMargin
|
|
|
|
|
} else if (element.type === ElementType.PAGE_BREAK) {
|
|
|
|
|
element.width = innerWidth
|
|
|
|
|
metrics.width = innerWidth
|
|
|
|
|
metrics.height = this.options.defaultSize
|
|
|
|
|
metrics.height = defaultSize
|
|
|
|
|
} else if (
|
|
|
|
|
element.type === ElementType.CHECKBOX ||
|
|
|
|
|
element.controlComponent === ControlComponent.CHECKBOX
|
|
|
|
|
@ -860,7 +896,7 @@ export class Draw {
|
|
|
|
|
metrics.boundingBoxAscent = 0
|
|
|
|
|
} else {
|
|
|
|
|
// 设置上下标真实字体尺寸
|
|
|
|
|
const size = element.size || this.options.defaultSize
|
|
|
|
|
const size = element.size || defaultSize
|
|
|
|
|
if (element.type === ElementType.SUPERSCRIPT || element.type === ElementType.SUBSCRIPT) {
|
|
|
|
|
element.actualSize = Math.ceil(size * 0.6)
|
|
|
|
|
}
|
|
|
|
|
@ -934,7 +970,7 @@ export class Draw {
|
|
|
|
|
private _computePageList(): IRow[][] {
|
|
|
|
|
const pageRowList: IRow[][] = [[]]
|
|
|
|
|
const { pageMode } = this.options
|
|
|
|
|
const height = this.getHeight()
|
|
|
|
|
const height = this.getOriginalMainHeight()
|
|
|
|
|
const margins = this.getMargins()
|
|
|
|
|
const marginHeight = margins[0] + margins[2]
|
|
|
|
|
let pageHeight = marginHeight
|
|
|
|
|
@ -979,7 +1015,7 @@ export class Draw {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public drawRow(ctx: CanvasRenderingContext2D, payload: IDrawRowPayload) {
|
|
|
|
|
const { rowList, pageNo, positionList, startIndex } = payload
|
|
|
|
|
const { rowList, pageNo, elementList, positionList, startIndex, zone } = payload
|
|
|
|
|
const { scale, tdPadding } = this.options
|
|
|
|
|
const { isCrossRowCol, tableId } = this.range.getRange()
|
|
|
|
|
let index = startIndex
|
|
|
|
|
@ -1077,11 +1113,11 @@ export class Draw {
|
|
|
|
|
this.highlight.render(ctx)
|
|
|
|
|
}
|
|
|
|
|
// 选区记录
|
|
|
|
|
const { startIndex, endIndex } = this.range.getRange()
|
|
|
|
|
if (startIndex !== endIndex && startIndex <= index && index <= endIndex) {
|
|
|
|
|
const { zone: currentZone, startIndex, endIndex } = this.range.getRange()
|
|
|
|
|
if (currentZone === zone && startIndex !== endIndex && startIndex <= index && index <= endIndex) {
|
|
|
|
|
// 从行尾开始-绘制最小宽度
|
|
|
|
|
if (startIndex === index) {
|
|
|
|
|
const nextElement = this.elementList[startIndex + 1]
|
|
|
|
|
const nextElement = elementList[startIndex + 1]
|
|
|
|
|
if (nextElement && nextElement.value === ZERO) {
|
|
|
|
|
rangeRecord.x = x + metrics.width
|
|
|
|
|
rangeRecord.y = y
|
|
|
|
|
@ -1119,11 +1155,13 @@ export class Draw {
|
|
|
|
|
for (let d = 0; d < tr.tdList!.length; d++) {
|
|
|
|
|
const td = tr.tdList[d]
|
|
|
|
|
this.drawRow(ctx, {
|
|
|
|
|
elementList: td.value,
|
|
|
|
|
positionList: td.positionList!,
|
|
|
|
|
rowList: td.rowList!,
|
|
|
|
|
pageNo,
|
|
|
|
|
startIndex: 0,
|
|
|
|
|
innerWidth: (td.width! - tdGap) * scale
|
|
|
|
|
innerWidth: (td.width! - tdGap) * scale,
|
|
|
|
|
zone
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@ -1150,10 +1188,13 @@ export class Draw {
|
|
|
|
|
this.blockParticle.clear()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private _drawPage(positionList: IElementPosition[], rowList: IRow[], pageNo: number) {
|
|
|
|
|
const { pageMode } = this.options
|
|
|
|
|
private _drawPage(payload: IDrawPagePayload) {
|
|
|
|
|
const { elementList, positionList, rowList, pageNo } = payload
|
|
|
|
|
const { inactiveAlpha, pageMode } = this.options
|
|
|
|
|
const innerWidth = this.getInnerWidth()
|
|
|
|
|
const ctx = this.ctxList[pageNo]
|
|
|
|
|
// 判断当前激活区域-激活页眉时主题元素透明度降低
|
|
|
|
|
ctx.globalAlpha = this.zone.isHeaderActive() ? inactiveAlpha : 1
|
|
|
|
|
this._clearPage(pageNo)
|
|
|
|
|
// 绘制背景
|
|
|
|
|
this.background.render(ctx)
|
|
|
|
|
@ -1162,14 +1203,16 @@ export class Draw {
|
|
|
|
|
// 渲染元素
|
|
|
|
|
const index = rowList[0].startIndex
|
|
|
|
|
this.drawRow(ctx, {
|
|
|
|
|
elementList,
|
|
|
|
|
positionList,
|
|
|
|
|
rowList,
|
|
|
|
|
pageNo,
|
|
|
|
|
startIndex: index,
|
|
|
|
|
innerWidth
|
|
|
|
|
innerWidth,
|
|
|
|
|
zone: EditorZone.MAIN
|
|
|
|
|
})
|
|
|
|
|
// 绘制页眉
|
|
|
|
|
this.header.render(ctx)
|
|
|
|
|
this.header.render(ctx, pageNo)
|
|
|
|
|
// 绘制页码
|
|
|
|
|
this.pageNumber.render(ctx, pageNo)
|
|
|
|
|
// 搜索匹配绘制
|
|
|
|
|
@ -1183,14 +1226,20 @@ export class Draw {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private _lazyRender() {
|
|
|
|
|
const positionList = this.position.getOriginalPositionList()
|
|
|
|
|
const positionList = this.position.getOriginalMainPositionList()
|
|
|
|
|
const elementList = this.getOriginalMainElementList()
|
|
|
|
|
this.lazyRenderIntersectionObserver?.disconnect()
|
|
|
|
|
this.lazyRenderIntersectionObserver = new IntersectionObserver((entries) => {
|
|
|
|
|
entries.forEach(entry => {
|
|
|
|
|
if (entry.isIntersecting) {
|
|
|
|
|
const index = Number((<HTMLCanvasElement>entry.target).dataset.index)
|
|
|
|
|
this.header.render(this.ctxList[index])
|
|
|
|
|
this._drawPage(positionList, this.pageRowList[index], index)
|
|
|
|
|
this.header.render(this.ctxList[index], index)
|
|
|
|
|
this._drawPage({
|
|
|
|
|
elementList,
|
|
|
|
|
positionList,
|
|
|
|
|
rowList: this.pageRowList[index],
|
|
|
|
|
pageNo: index
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
@ -1200,9 +1249,15 @@ export class Draw {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private _immediateRender() {
|
|
|
|
|
const positionList = this.position.getOriginalPositionList()
|
|
|
|
|
const positionList = this.position.getOriginalMainPositionList()
|
|
|
|
|
const elementList = this.getOriginalMainElementList()
|
|
|
|
|
for (let i = 0; i < this.pageRowList.length; i++) {
|
|
|
|
|
this._drawPage(positionList, this.pageRowList[i], i)
|
|
|
|
|
this._drawPage({
|
|
|
|
|
elementList,
|
|
|
|
|
positionList,
|
|
|
|
|
rowList: this.pageRowList[i],
|
|
|
|
|
pageNo: i
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@ -1236,7 +1291,6 @@ export class Draw {
|
|
|
|
|
this.imageObserver.clearAll()
|
|
|
|
|
this.cursor.recoveryCursor()
|
|
|
|
|
// 创建纸张
|
|
|
|
|
const positionList = this.position.getOriginalPositionList()
|
|
|
|
|
for (let i = 0; i < this.pageRowList.length; i++) {
|
|
|
|
|
if (!this.pageList[i]) {
|
|
|
|
|
this._createPage(i)
|
|
|
|
|
@ -1260,20 +1314,19 @@ export class Draw {
|
|
|
|
|
}
|
|
|
|
|
// 光标重绘
|
|
|
|
|
if (isSetCursor) {
|
|
|
|
|
const positionList = this.position.getPositionList()
|
|
|
|
|
const positionContext = this.position.getPositionContext()
|
|
|
|
|
if (positionContext.isTable) {
|
|
|
|
|
const { index, trIndex, tdIndex } = positionContext
|
|
|
|
|
const tablePositionList = this.elementList[index!].trList?.[trIndex!].tdList[tdIndex!].positionList
|
|
|
|
|
const elementList = this.getElementList()
|
|
|
|
|
const tablePositionList = elementList[index!].trList?.[trIndex!].tdList[tdIndex!].positionList
|
|
|
|
|
if (curIndex === undefined && tablePositionList) {
|
|
|
|
|
curIndex = tablePositionList.length - 1
|
|
|
|
|
}
|
|
|
|
|
const tablePosition = tablePositionList?.[curIndex!]
|
|
|
|
|
this.position.setCursorPosition(tablePosition || null)
|
|
|
|
|
} else {
|
|
|
|
|
if (curIndex === undefined) {
|
|
|
|
|
curIndex = positionList.length - 1
|
|
|
|
|
}
|
|
|
|
|
this.position.setCursorPosition(positionList[curIndex!] || null)
|
|
|
|
|
this.position.setCursorPosition(curIndex !== undefined ? positionList[curIndex] : null)
|
|
|
|
|
}
|
|
|
|
|
this.cursor.drawCursor()
|
|
|
|
|
}
|
|
|
|
|
@ -1281,12 +1334,16 @@ export class Draw {
|
|
|
|
|
if (isSubmitHistory) {
|
|
|
|
|
const self = this
|
|
|
|
|
const oldElementList = deepClone(this.elementList)
|
|
|
|
|
const oldHeaderElementList = deepClone(this.header.getElementList())
|
|
|
|
|
const { startIndex, endIndex } = this.range.getRange()
|
|
|
|
|
const pageNo = this.pageNo
|
|
|
|
|
const oldPositionContext = deepClone(this.position.getPositionContext())
|
|
|
|
|
const zone = this.zone.getZone()
|
|
|
|
|
this.historyManager.execute(function () {
|
|
|
|
|
self.zone.setZone(zone)
|
|
|
|
|
self.setPageNo(pageNo)
|
|
|
|
|
self.position.setPositionContext(oldPositionContext)
|
|
|
|
|
self.header.setElementList(oldHeaderElementList)
|
|
|
|
|
self.elementList = deepClone(oldElementList)
|
|
|
|
|
self.range.setRange(startIndex, endIndex)
|
|
|
|
|
self.render({ curIndex, isSubmitHistory: false })
|
|
|
|
|
|