@hailin-zheng/editor-core 1.0.1 → 1.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/doc-ruler.d.ts +51 -0
- package/lib/doc-ruler.js +313 -0
- package/lib/doc-ruler.js.map +1 -0
- package/lib/framework/common-util.d.ts +63 -0
- package/lib/framework/common-util.js +178 -0
- package/lib/framework/common-util.js.map +1 -0
- package/lib/framework/document-change.d.ts +265 -0
- package/lib/framework/document-change.js +1342 -0
- package/lib/framework/document-change.js.map +1 -0
- package/lib/framework/document-combine.d.ts +24 -0
- package/lib/framework/document-combine.js +40 -0
- package/lib/framework/document-combine.js.map +1 -0
- package/lib/framework/document-comment.d.ts +46 -0
- package/lib/framework/document-comment.js +148 -0
- package/lib/framework/document-comment.js.map +1 -0
- package/lib/framework/document-context.d.ts +149 -0
- package/lib/framework/document-context.js +330 -0
- package/lib/framework/document-context.js.map +1 -0
- package/lib/framework/document-eval-func.d.ts +18 -0
- package/lib/framework/document-eval-func.js +48 -0
- package/lib/framework/document-eval-func.js.map +1 -0
- package/lib/framework/document-event.d.ts +213 -0
- package/lib/framework/document-event.js +1054 -0
- package/lib/framework/document-event.js.map +1 -0
- package/lib/framework/document-history.d.ts +26 -0
- package/lib/framework/document-history.js +65 -0
- package/lib/framework/document-history.js.map +1 -0
- package/lib/framework/document-images-loader.d.ts +16 -0
- package/lib/framework/document-images-loader.js +66 -0
- package/lib/framework/document-images-loader.js.map +1 -0
- package/lib/framework/document-input-cursor.d.ts +78 -0
- package/lib/framework/document-input-cursor.js +239 -0
- package/lib/framework/document-input-cursor.js.map +1 -0
- package/lib/framework/document-paint.d.ts +34 -0
- package/lib/framework/document-paint.js +103 -0
- package/lib/framework/document-paint.js.map +1 -0
- package/lib/framework/document-print-offscreen.d.ts +38 -0
- package/lib/framework/document-print-offscreen.js +128 -0
- package/lib/framework/document-print-offscreen.js.map +1 -0
- package/lib/framework/document-print.d.ts +60 -0
- package/lib/framework/document-print.js +203 -0
- package/lib/framework/document-print.js.map +1 -0
- package/lib/framework/document-segmenter.d.ts +2 -0
- package/lib/framework/document-segmenter.js +106 -0
- package/lib/framework/document-segmenter.js.map +1 -0
- package/lib/framework/document-selection.d.ts +89 -0
- package/lib/framework/document-selection.js +358 -0
- package/lib/framework/document-selection.js.map +1 -0
- package/lib/framework/document-template.d.ts +4 -0
- package/lib/framework/document-template.js +20 -0
- package/lib/framework/document-template.js.map +1 -0
- package/lib/framework/document-textline-mode.d.ts +7 -0
- package/lib/framework/document-textline-mode.js +30 -0
- package/lib/framework/document-textline-mode.js.map +1 -0
- package/lib/framework/element-define.d.ts +319 -0
- package/lib/framework/element-define.js +579 -0
- package/lib/framework/element-define.js.map +1 -0
- package/lib/framework/element-event-define.d.ts +99 -0
- package/lib/framework/element-event-define.js +108 -0
- package/lib/framework/element-event-define.js.map +1 -0
- package/lib/framework/element-measure.d.ts +97 -0
- package/lib/framework/element-measure.js +551 -0
- package/lib/framework/element-measure.js.map +1 -0
- package/lib/framework/element-paint.d.ts +42 -0
- package/lib/framework/element-paint.js +170 -0
- package/lib/framework/element-paint.js.map +1 -0
- package/lib/framework/element-props.d.ts +301 -0
- package/lib/framework/element-props.js +809 -0
- package/lib/framework/element-props.js.map +1 -0
- package/lib/framework/element-reader.d.ts +19 -0
- package/lib/framework/element-reader.js +151 -0
- package/lib/framework/element-reader.js.map +1 -0
- package/lib/framework/element-render-cut.d.ts +55 -0
- package/lib/framework/element-render-cut.js +449 -0
- package/lib/framework/element-render-cut.js.map +1 -0
- package/lib/framework/element-serialize.d.ts +30 -0
- package/lib/framework/element-serialize.js +113 -0
- package/lib/framework/element-serialize.js.map +1 -0
- package/lib/framework/element-util.d.ts +369 -0
- package/lib/framework/element-util.js +1463 -0
- package/lib/framework/element-util.js.map +1 -0
- package/lib/framework/impl/checkbox/checkbox-impl.d.ts +24 -0
- package/lib/framework/impl/checkbox/checkbox-impl.js +64 -0
- package/lib/framework/impl/checkbox/checkbox-impl.js.map +1 -0
- package/lib/framework/impl/comments/comment-content-impl.d.ts +40 -0
- package/lib/framework/impl/comments/comment-content-impl.js +105 -0
- package/lib/framework/impl/comments/comment-content-impl.js.map +1 -0
- package/lib/framework/impl/comments/comment-element-impl.d.ts +21 -0
- package/lib/framework/impl/comments/comment-element-impl.js +62 -0
- package/lib/framework/impl/comments/comment-element-impl.js.map +1 -0
- package/lib/framework/impl/comments/comments-container-impl.d.ts +22 -0
- package/lib/framework/impl/comments/comments-container-impl.js +62 -0
- package/lib/framework/impl/comments/comments-container-impl.js.map +1 -0
- package/lib/framework/impl/comments/comments-util.d.ts +12 -0
- package/lib/framework/impl/comments/comments-util.js +67 -0
- package/lib/framework/impl/comments/comments-util.js.map +1 -0
- package/lib/framework/impl/comments/validate-msg-impl.d.ts +21 -0
- package/lib/framework/impl/comments/validate-msg-impl.js +83 -0
- package/lib/framework/impl/comments/validate-msg-impl.js.map +1 -0
- package/lib/framework/impl/data-element/data-decorate-impl.d.ts +30 -0
- package/lib/framework/impl/data-element/data-decorate-impl.js +91 -0
- package/lib/framework/impl/data-element/data-decorate-impl.js.map +1 -0
- package/lib/framework/impl/data-element/data-element-barcode.d.ts +31 -0
- package/lib/framework/impl/data-element/data-element-barcode.js +115 -0
- package/lib/framework/impl/data-element/data-element-barcode.js.map +1 -0
- package/lib/framework/impl/data-element/data-element-base-impl.d.ts +68 -0
- package/lib/framework/impl/data-element/data-element-base-impl.js +205 -0
- package/lib/framework/impl/data-element/data-element-base-impl.js.map +1 -0
- package/lib/framework/impl/data-element/data-element-check-impl.d.ts +35 -0
- package/lib/framework/impl/data-element/data-element-check-impl.js +133 -0
- package/lib/framework/impl/data-element/data-element-check-impl.js.map +1 -0
- package/lib/framework/impl/data-element/data-element-date-impl.d.ts +23 -0
- package/lib/framework/impl/data-element/data-element-date-impl.js +111 -0
- package/lib/framework/impl/data-element/data-element-date-impl.js.map +1 -0
- package/lib/framework/impl/data-element/data-element-group-impl.d.ts +23 -0
- package/lib/framework/impl/data-element/data-element-group-impl.js +130 -0
- package/lib/framework/impl/data-element/data-element-group-impl.js.map +1 -0
- package/lib/framework/impl/data-element/data-element-image-impl.d.ts +30 -0
- package/lib/framework/impl/data-element/data-element-image-impl.js +137 -0
- package/lib/framework/impl/data-element/data-element-image-impl.js.map +1 -0
- package/lib/framework/impl/data-element/data-element-list-impl.d.ts +22 -0
- package/lib/framework/impl/data-element/data-element-list-impl.js +131 -0
- package/lib/framework/impl/data-element/data-element-list-impl.js.map +1 -0
- package/lib/framework/impl/data-element/data-element-text-impl.d.ts +23 -0
- package/lib/framework/impl/data-element/data-element-text-impl.js +103 -0
- package/lib/framework/impl/data-element/data-element-text-impl.js.map +1 -0
- package/lib/framework/impl/decorate/fill-null-space-imple.d.ts +21 -0
- package/lib/framework/impl/decorate/fill-null-space-imple.js +43 -0
- package/lib/framework/impl/decorate/fill-null-space-imple.js.map +1 -0
- package/lib/framework/impl/document/doc-body-impl.d.ts +27 -0
- package/lib/framework/impl/document/doc-body-impl.js +79 -0
- package/lib/framework/impl/document/doc-body-impl.js.map +1 -0
- package/lib/framework/impl/document/doc-body-part-impl.d.ts +30 -0
- package/lib/framework/impl/document/doc-body-part-impl.js +94 -0
- package/lib/framework/impl/document/doc-body-part-impl.js.map +1 -0
- package/lib/framework/impl/document/doc-container-impl.d.ts +16 -0
- package/lib/framework/impl/document/doc-container-impl.js +21 -0
- package/lib/framework/impl/document/doc-container-impl.js.map +1 -0
- package/lib/framework/impl/document/doc-footer-impl.d.ts +26 -0
- package/lib/framework/impl/document/doc-footer-impl.js +77 -0
- package/lib/framework/impl/document/doc-footer-impl.js.map +1 -0
- package/lib/framework/impl/document/doc-header-impl.d.ts +26 -0
- package/lib/framework/impl/document/doc-header-impl.js +83 -0
- package/lib/framework/impl/document/doc-header-impl.js.map +1 -0
- package/lib/framework/impl/document/doc-impl.d.ts +61 -0
- package/lib/framework/impl/document/doc-impl.js +209 -0
- package/lib/framework/impl/document/doc-impl.js.map +1 -0
- package/lib/framework/impl/media-formula/menstrual-history.d.ts +35 -0
- package/lib/framework/impl/media-formula/menstrual-history.js +153 -0
- package/lib/framework/impl/media-formula/menstrual-history.js.map +1 -0
- package/lib/framework/impl/paragraph/p-impl.d.ts +45 -0
- package/lib/framework/impl/paragraph/p-impl.js +156 -0
- package/lib/framework/impl/paragraph/p-impl.js.map +1 -0
- package/lib/framework/impl/picture/image-impl.d.ts +31 -0
- package/lib/framework/impl/picture/image-impl.js +124 -0
- package/lib/framework/impl/picture/image-impl.js.map +1 -0
- package/lib/framework/impl/radio/radio-impl.d.ts +22 -0
- package/lib/framework/impl/radio/radio-impl.js +72 -0
- package/lib/framework/impl/radio/radio-impl.js.map +1 -0
- package/lib/framework/impl/symbol/br-symbol-impl.d.ts +22 -0
- package/lib/framework/impl/symbol/br-symbol-impl.js +54 -0
- package/lib/framework/impl/symbol/br-symbol-impl.js.map +1 -0
- package/lib/framework/impl/symbol/p-symbol-impl.d.ts +19 -0
- package/lib/framework/impl/symbol/p-symbol-impl.js +54 -0
- package/lib/framework/impl/symbol/p-symbol-impl.js.map +1 -0
- package/lib/framework/impl/table/table-cell-impl.d.ts +37 -0
- package/lib/framework/impl/table/table-cell-impl.js +145 -0
- package/lib/framework/impl/table/table-cell-impl.js.map +1 -0
- package/lib/framework/impl/table/table-impl.d.ts +55 -0
- package/lib/framework/impl/table/table-impl.js +363 -0
- package/lib/framework/impl/table/table-impl.js.map +1 -0
- package/lib/framework/impl/table/table-row-impl.d.ts +26 -0
- package/lib/framework/impl/table/table-row-impl.js +75 -0
- package/lib/framework/impl/table/table-row-impl.js.map +1 -0
- package/lib/framework/impl/table/table-split-cell-patch.d.ts +20 -0
- package/lib/framework/impl/table/table-split-cell-patch.js +89 -0
- package/lib/framework/impl/table/table-split-cell-patch.js.map +1 -0
- package/lib/framework/impl/table/table-split-cell.d.ts +90 -0
- package/lib/framework/impl/table/table-split-cell.js +464 -0
- package/lib/framework/impl/table/table-split-cell.js.map +1 -0
- package/lib/framework/impl/table/table-util.d.ts +150 -0
- package/lib/framework/impl/table/table-util.js +678 -0
- package/lib/framework/impl/table/table-util.js.map +1 -0
- package/lib/framework/impl/text/text-impl.d.ts +32 -0
- package/lib/framework/impl/text/text-impl.js +149 -0
- package/lib/framework/impl/text/text-impl.js.map +1 -0
- package/lib/framework/impl/text/track-run-impl.d.ts +27 -0
- package/lib/framework/impl/text/track-run-impl.js +112 -0
- package/lib/framework/impl/text/track-run-impl.js.map +1 -0
- package/lib/framework/notify.d.ts +13 -0
- package/lib/framework/notify.js +116 -0
- package/lib/framework/notify.js.map +1 -0
- package/lib/framework/range-util.d.ts +40 -0
- package/lib/framework/range-util.js +312 -0
- package/lib/framework/range-util.js.map +1 -0
- package/lib/framework/render-context.d.ts +91 -0
- package/lib/framework/render-context.js +384 -0
- package/lib/framework/render-context.js.map +1 -0
- package/lib/framework/render-define.d.ts +109 -0
- package/lib/framework/render-define.js +195 -0
- package/lib/framework/render-define.js.map +1 -0
- package/lib/framework/selection-overlays.d.ts +30 -0
- package/lib/framework/selection-overlays.js +124 -0
- package/lib/framework/selection-overlays.js.map +1 -0
- package/lib/texteditor.d.ts +318 -0
- package/lib/texteditor.js +913 -0
- package/lib/texteditor.js.map +1 -0
- package/lib/util/subject.d.ts +34 -0
- package/lib/util/subject.js +88 -0
- package/lib/util/subject.js.map +1 -0
- package/lib/util/table-bind.d.ts +5 -0
- package/lib/util/table-bind.js +6 -0
- package/lib/util/table-bind.js.map +1 -0
- package/package.json +1 -1
- package/tsconfig.json +1 -1
- package/webpack.config.js +0 -1
@@ -0,0 +1,1463 @@
|
|
1
|
+
import { nanoid } from "nanoid";
|
2
|
+
import { BranchElement, LeafElement, Rect } from "./element-define";
|
3
|
+
import { TextProps } from "./element-props";
|
4
|
+
import { CommsContainerElement } from "./impl/comments/comments-container-impl";
|
5
|
+
import { DataElementInlineGroup } from "./impl/data-element/data-element-base-impl";
|
6
|
+
import { DocumentBodyElement } from "./impl/document/doc-body-impl";
|
7
|
+
import { DocumentFooterElement } from "./impl/document/doc-footer-impl";
|
8
|
+
import { DocumentHeaderElement } from "./impl/document/doc-header-impl";
|
9
|
+
import { DocumentRenderObject } from "./impl/document/doc-impl";
|
10
|
+
import { ParagraphElement, ParagraphLineRectRenderObject, ParagraphRenderObject } from "./impl/paragraph/p-impl";
|
11
|
+
import { PSymbolElement } from "./impl/symbol/p-symbol-impl";
|
12
|
+
import { TableCellElement } from "./impl/table/table-cell-impl";
|
13
|
+
import { TableRenderObject } from "./impl/table/table-impl";
|
14
|
+
import { TableRowRenderObject } from "./impl/table/table-row-impl";
|
15
|
+
import { TextGroupElement, TextGroupRenderObject } from "./impl/text/text-impl";
|
16
|
+
import { TrackRunElement } from "./impl/text/track-run-impl";
|
17
|
+
import { BranchRenderObject, LeafRenderObject } from "./render-define";
|
18
|
+
export class ElementUtil {
|
19
|
+
static setCanvasProps(canvas, ctx, viewOptions, scale = 1) {
|
20
|
+
// if (canvas instanceof OffscreenCanvas) {
|
21
|
+
// this.setOffscreenCanvas(canvas, ctx as OffscreenCanvasRenderingContext2D, viewOptions, scale);
|
22
|
+
// return
|
23
|
+
// }
|
24
|
+
const { width, height } = viewOptions;
|
25
|
+
let dpr = window.devicePixelRatio || 1;
|
26
|
+
if (scale > 1) {
|
27
|
+
dpr *= scale;
|
28
|
+
}
|
29
|
+
dpr = Math.ceil(dpr);
|
30
|
+
const scaleWidth = Math.floor(width * dpr) / dpr;
|
31
|
+
const scaleHeight = Math.floor(height * dpr) / dpr;
|
32
|
+
canvas.style.width = scaleWidth + 'px';
|
33
|
+
canvas.style.height = scaleHeight + 'px';
|
34
|
+
canvas.width = scaleWidth * dpr;
|
35
|
+
canvas.height = scaleHeight * dpr;
|
36
|
+
ctx.scale(dpr, dpr);
|
37
|
+
}
|
38
|
+
// static setOffscreenCanvas(canvas: OffscreenCanvas, ctx: OffscreenCanvasRenderingContext2D, viewOptions: { width: number, height: number }, scale: number = 1): void {
|
39
|
+
// const { width, height } = viewOptions;
|
40
|
+
// let dpr = window.devicePixelRatio || 1;
|
41
|
+
// if (scale > 1) {
|
42
|
+
// dpr *= scale;
|
43
|
+
// }
|
44
|
+
// dpr = Math.ceil(dpr);
|
45
|
+
// const scaleWidth = Math.floor(width * dpr) / dpr;
|
46
|
+
// const scaleHeight = Math.floor(height * dpr) / dpr;
|
47
|
+
// canvas.width = scaleWidth * dpr;
|
48
|
+
// canvas.height = scaleHeight * dpr;
|
49
|
+
// ctx.scale(dpr, dpr);
|
50
|
+
// }
|
51
|
+
static getDprNumber(val, scale = 1) {
|
52
|
+
let dpr = window.devicePixelRatio || 1;
|
53
|
+
if (scale > 1) {
|
54
|
+
dpr *= scale;
|
55
|
+
}
|
56
|
+
dpr = Math.ceil(dpr);
|
57
|
+
return Math.floor(val * dpr) / dpr;
|
58
|
+
}
|
59
|
+
static readTextProps(dest, props, options) {
|
60
|
+
if (!props) {
|
61
|
+
return this.createTextProps(dest, options);
|
62
|
+
}
|
63
|
+
const textProps = dest ?? new TextProps();
|
64
|
+
textProps.color = props.color || options.defaultColor;
|
65
|
+
textProps.fontName = props.fontName || options.defaultFontName;
|
66
|
+
textProps.fontSize = props.fontSize || options.defaultFontSize;
|
67
|
+
textProps.border = props.border;
|
68
|
+
if (props.fontWeight) {
|
69
|
+
textProps.fontWeight = props.fontWeight;
|
70
|
+
}
|
71
|
+
if (props.fontStyle) {
|
72
|
+
textProps.fontStyle = props.fontStyle;
|
73
|
+
}
|
74
|
+
if (props.underline) {
|
75
|
+
textProps.underline = props.underline;
|
76
|
+
}
|
77
|
+
if (props.linethrough) {
|
78
|
+
textProps.linethrough = props.linethrough;
|
79
|
+
}
|
80
|
+
if (props.overline) {
|
81
|
+
textProps.overline = props.overline;
|
82
|
+
}
|
83
|
+
if (props.background) {
|
84
|
+
textProps.background = props.background;
|
85
|
+
}
|
86
|
+
if (props.letterSpace) {
|
87
|
+
textProps.letterSpace = props.letterSpace;
|
88
|
+
}
|
89
|
+
if (props.vertAlign) {
|
90
|
+
textProps.vertAlign = props.vertAlign;
|
91
|
+
}
|
92
|
+
return textProps;
|
93
|
+
}
|
94
|
+
static readEleBaseProps(dest, props) {
|
95
|
+
dest.id = props.id ?? nanoid(5);
|
96
|
+
dest.name = props.name;
|
97
|
+
dest.caption = props.caption;
|
98
|
+
dest.editable = props.editable ?? true;
|
99
|
+
dest.fieldName = props.fieldName;
|
100
|
+
dest.minLength = props.minLength;
|
101
|
+
dest.printable = props.printable ?? true;
|
102
|
+
dest.required = props.required;
|
103
|
+
dest.secretBrowse = props.secretBrowse;
|
104
|
+
dest.deleteable = props.deleteable;
|
105
|
+
dest.underline = props.underline;
|
106
|
+
dest.type = props.type;
|
107
|
+
return dest;
|
108
|
+
}
|
109
|
+
/**
|
110
|
+
* 获取内容区域最大高度
|
111
|
+
* @param render
|
112
|
+
* @param renderHeight
|
113
|
+
* @returns
|
114
|
+
*/
|
115
|
+
static innerRectMaxHeight(render, renderHeight) {
|
116
|
+
const { padding } = render;
|
117
|
+
return renderHeight - padding.top - padding.bottom;
|
118
|
+
}
|
119
|
+
/**
|
120
|
+
* 根据内框内容高度,更新外框框体高度
|
121
|
+
* @param render
|
122
|
+
* @param innerRect
|
123
|
+
*/
|
124
|
+
static updateRenderHeightByInnerRect(render, innerRect) {
|
125
|
+
const { padding, margin } = render;
|
126
|
+
//外层容器高度等于内容高度+外边距+内边距
|
127
|
+
render.rect.height = innerRect.height + margin.top + margin.bottom + padding.top + padding.bottom;
|
128
|
+
}
|
129
|
+
/**
|
130
|
+
* 设置块级元素限制尺寸
|
131
|
+
* @param render
|
132
|
+
* @param parentLimitRect
|
133
|
+
*/
|
134
|
+
static setBlockElementLimitSize(render, parentLimitRect) {
|
135
|
+
render.rect.x = parentLimitRect.x;
|
136
|
+
render.rect.y = parentLimitRect.y + parentLimitRect.height;
|
137
|
+
render.rect.width = parentLimitRect.maxWidth ?? 0;
|
138
|
+
render.rect.maxWidth = parentLimitRect.maxWidth;
|
139
|
+
if (parentLimitRect.maxHeight) {
|
140
|
+
render.rect.maxHeight = parentLimitRect.maxHeight - parentLimitRect.height;
|
141
|
+
}
|
142
|
+
}
|
143
|
+
/**
|
144
|
+
* 克隆框体
|
145
|
+
* @param rect
|
146
|
+
* @returns
|
147
|
+
*/
|
148
|
+
static cloneRect(rect) {
|
149
|
+
const cloneRect = new Rect();
|
150
|
+
cloneRect.x = rect.x;
|
151
|
+
cloneRect.y = rect.y;
|
152
|
+
cloneRect.width = rect.width;
|
153
|
+
cloneRect.height = rect.height;
|
154
|
+
cloneRect.maxHeight = rect.maxHeight;
|
155
|
+
cloneRect.maxWidth = rect.maxWidth;
|
156
|
+
return cloneRect;
|
157
|
+
}
|
158
|
+
/**
|
159
|
+
* 重新限定子元素以及当前高度值,并返回内边框内容高度
|
160
|
+
* @param render
|
161
|
+
* @param resetX 测量段落外框时,内框不需要重置x,因为内框已经存在对齐
|
162
|
+
* @returns
|
163
|
+
*/
|
164
|
+
static remeasure(render, resetX = true) {
|
165
|
+
if (render.rect.width === 0) {
|
166
|
+
return -1;
|
167
|
+
}
|
168
|
+
if (render instanceof TableRowRenderObject) {
|
169
|
+
return this.remeasureTableRow(render);
|
170
|
+
}
|
171
|
+
if (render instanceof TableRenderObject) {
|
172
|
+
this.remeasureTableMerge(render);
|
173
|
+
}
|
174
|
+
const innerRect = render.getInnnerRect();
|
175
|
+
for (let i = 0; i < render.length; i++) {
|
176
|
+
const line = render.getChild(i);
|
177
|
+
if (resetX) {
|
178
|
+
line.rect.x = innerRect.x;
|
179
|
+
}
|
180
|
+
line.rect.y = innerRect.height + innerRect.y + line.margin.top;
|
181
|
+
line.rect.maxWidth = innerRect.maxWidth;
|
182
|
+
innerRect.height += line.rect.height + line.margin.top + line.margin.bottom;
|
183
|
+
}
|
184
|
+
render.updateRenderHeight(innerRect);
|
185
|
+
return innerRect.height;
|
186
|
+
}
|
187
|
+
static remeasureTableRow(rowRender, foreceColIndex = -1) {
|
188
|
+
const rowEle = rowRender.element;
|
189
|
+
const rowMinHeight = rowEle.props.minHeight > 19 ? rowEle.props.minHeight : 19;
|
190
|
+
let maxCellheight = rowMinHeight;
|
191
|
+
//限制行最小高度
|
192
|
+
maxCellheight = maxCellheight < 19 ? 19 : maxCellheight;
|
193
|
+
//获取行内非纵向合并单元格的最高单元格高度
|
194
|
+
for (let i = 0; i < rowRender.length; i++) {
|
195
|
+
const cellRender = rowRender.getChild(i);
|
196
|
+
const { vMerge } = cellRender.element.props;
|
197
|
+
if (cellRender.rect.height > maxCellheight && (vMerge !== 'restart' || i === foreceColIndex)) {
|
198
|
+
maxCellheight = cellRender.rect.height;
|
199
|
+
}
|
200
|
+
}
|
201
|
+
//循环设置单元格高度为行内最大单元格高度
|
202
|
+
for (let i = 0; i < rowRender.length; i++) {
|
203
|
+
const cellRender = rowRender.getChild(i);
|
204
|
+
const cellElement = cellRender.element;
|
205
|
+
const { vMerge } = cellElement.props;
|
206
|
+
if ((vMerge !== 'restart' || i === foreceColIndex) || cellRender.rect.height < maxCellheight) {
|
207
|
+
cellRender.rect.height = maxCellheight;
|
208
|
+
}
|
209
|
+
//处理单元格内容纵向居中
|
210
|
+
this.measureCellVAlign(cellRender);
|
211
|
+
}
|
212
|
+
//设置行高
|
213
|
+
rowRender.updateRenderHeight(maxCellheight);
|
214
|
+
return maxCellheight;
|
215
|
+
}
|
216
|
+
/**
|
217
|
+
* 获取表格行绘制元素的内容高度,用于缩放行高度时,获取最小内容高度,缩放的高度不能小于内容最小高度
|
218
|
+
*/
|
219
|
+
static getTableRowRenderContentHeight(rowRender) {
|
220
|
+
const rowEle = rowRender.element;
|
221
|
+
let maxCellheight = 19;
|
222
|
+
//限制行最小高度
|
223
|
+
//获取行内非纵向合并单元格的最高单元格高度
|
224
|
+
for (let i = 0; i < rowRender.length; i++) {
|
225
|
+
const cellRender = rowRender.getChild(i);
|
226
|
+
const cellContentHeight = this.getTableCellRenderContentHeight(cellRender);
|
227
|
+
const { vMerge } = cellRender.element.props;
|
228
|
+
if (cellContentHeight > maxCellheight && vMerge !== 'restart') {
|
229
|
+
maxCellheight = cellContentHeight;
|
230
|
+
}
|
231
|
+
}
|
232
|
+
return maxCellheight;
|
233
|
+
}
|
234
|
+
/**
|
235
|
+
* 获取单元格内容高度
|
236
|
+
* 单元格暂不处理上下margin、padding
|
237
|
+
* @param cellRender
|
238
|
+
* @returns
|
239
|
+
*/
|
240
|
+
static getTableCellRenderContentHeight(cellRender) {
|
241
|
+
let contentHeight = 0;
|
242
|
+
for (let i = 0; i < cellRender.length; i++) {
|
243
|
+
contentHeight += cellRender.getChild(i).rect.height;
|
244
|
+
}
|
245
|
+
return contentHeight;
|
246
|
+
}
|
247
|
+
/**
|
248
|
+
* 处理单元格内容纵向对齐
|
249
|
+
* @param render
|
250
|
+
*/
|
251
|
+
static measureCellVAlign(render) {
|
252
|
+
const tcElement = render.element;
|
253
|
+
const { vAlign } = tcElement.props;
|
254
|
+
if (!vAlign || vAlign === 'top') {
|
255
|
+
return;
|
256
|
+
}
|
257
|
+
let sumHeight = 0;
|
258
|
+
for (let i = 0; i < render.length; i++) {
|
259
|
+
sumHeight += render.getChild(i).rect.height;
|
260
|
+
}
|
261
|
+
let spaceHeight = 0;
|
262
|
+
spaceHeight = vAlign === 'middle' ? Math.floor((render.rect.height - sumHeight) / 2) : vAlign === 'bottom' ? render.rect.height - sumHeight : 0;
|
263
|
+
if (spaceHeight <= 0) {
|
264
|
+
return;
|
265
|
+
}
|
266
|
+
let y = spaceHeight;
|
267
|
+
for (let i = 0; i < render.length; i++) {
|
268
|
+
render.getChild(i).rect.y = y;
|
269
|
+
y += render.getChild(i).rect.height;
|
270
|
+
}
|
271
|
+
}
|
272
|
+
/**
|
273
|
+
* 重新测量合并单元格高度
|
274
|
+
* @param tbRender
|
275
|
+
* @returns
|
276
|
+
*/
|
277
|
+
static remeasureTableMerge(tbRender) {
|
278
|
+
//是否需要重新计算,主要解决:之前合并计算的列,可能会被后面合并计算的列所影响,需要再次重新计算测量
|
279
|
+
let needReCalc = false;
|
280
|
+
for (let i = 0; i < tbRender.length; i++) {
|
281
|
+
const row = tbRender.getChild(i);
|
282
|
+
for (let j = 0; j < row.length; j++) {
|
283
|
+
const cellRender = row.getChild(j);
|
284
|
+
const ele = cellRender.element;
|
285
|
+
const { vMerge } = ele.props;
|
286
|
+
if (vMerge === 'restart') {
|
287
|
+
const eleIndex = ele.getIndex();
|
288
|
+
const continueRows = this.getContinueVMergeRenderRows(tbRender, i, eleIndex);
|
289
|
+
if (!continueRows.length) {
|
290
|
+
//向下不存在合并的单元格,当前合并的单元格是被cut过来的,并且当前单元格高度高于行内高度需要remeasure当前行
|
291
|
+
if (cellRender.rect.height > row.rect.height) {
|
292
|
+
this.remeasureTableRow(row, j);
|
293
|
+
needReCalc = true;
|
294
|
+
}
|
295
|
+
continue;
|
296
|
+
}
|
297
|
+
const continueCellHeight = continueRows.reduce((prev, curr) => prev + curr.rect.height, 0);
|
298
|
+
const overflowHeight = cellRender.rect.height - row.rect.height - continueCellHeight;
|
299
|
+
//溢出的高度加到最后一个合并单元格中
|
300
|
+
if (overflowHeight > 0) {
|
301
|
+
const lastRow = continueRows[continueRows.length - 1];
|
302
|
+
lastRow.rect.height += overflowHeight;
|
303
|
+
this.resizeCellToFillRow(lastRow);
|
304
|
+
needReCalc = true;
|
305
|
+
}
|
306
|
+
else {
|
307
|
+
cellRender.rect.height = row.rect.height + continueCellHeight;
|
308
|
+
}
|
309
|
+
}
|
310
|
+
}
|
311
|
+
}
|
312
|
+
if (needReCalc) {
|
313
|
+
this.remeasureTableMerge(tbRender);
|
314
|
+
return;
|
315
|
+
}
|
316
|
+
}
|
317
|
+
/**
|
318
|
+
* 获取向下纵向合并的行
|
319
|
+
* @param render
|
320
|
+
* @param rowIndex
|
321
|
+
* @param colIndex
|
322
|
+
* @returns
|
323
|
+
*/
|
324
|
+
static getContinueVMergeRenderRows(render, rowIndex, colIndex) {
|
325
|
+
const rows = [];
|
326
|
+
for (let i = rowIndex + 1; i < render.length; i++) {
|
327
|
+
const rowRender = render.getChild(i);
|
328
|
+
const rowEle = rowRender.element;
|
329
|
+
const ele = rowEle.getChild(colIndex);
|
330
|
+
const { vMerge } = ele.props;
|
331
|
+
if (vMerge !== 'continue') {
|
332
|
+
break;
|
333
|
+
}
|
334
|
+
rows.push(rowRender);
|
335
|
+
}
|
336
|
+
return rows;
|
337
|
+
}
|
338
|
+
/**
|
339
|
+
* 根据横向当前被合并的单元格
|
340
|
+
* @param tb
|
341
|
+
* @param rowIndex
|
342
|
+
* @param colIndex
|
343
|
+
*/
|
344
|
+
static getHorizontalRestartCellIndex(tb, rowIndex, colIndex) {
|
345
|
+
const row = tb.getChild(rowIndex);
|
346
|
+
for (let i = colIndex - 1; i >= 0; i--) {
|
347
|
+
const cell = row.getChild(i);
|
348
|
+
if (cell.props.hMerge === 'restart') {
|
349
|
+
return i;
|
350
|
+
}
|
351
|
+
}
|
352
|
+
throw new Error('未找到主合并单元格');
|
353
|
+
}
|
354
|
+
/**
|
355
|
+
* 根据横向当前被合并的单元格
|
356
|
+
* @param tb
|
357
|
+
* @param rowIndex
|
358
|
+
* @param colIndex
|
359
|
+
*/
|
360
|
+
static getVerticalRestartCellIndex(tb, rowIndex, colIndex) {
|
361
|
+
for (let i = rowIndex - 1; i >= 0; i--) {
|
362
|
+
const row = tb.getChild(i);
|
363
|
+
const cell = row.getChild(colIndex);
|
364
|
+
if (cell.props.vMerge === 'restart') {
|
365
|
+
return i;
|
366
|
+
}
|
367
|
+
}
|
368
|
+
throw new Error('未找到横向当前被合并的单元格');
|
369
|
+
}
|
370
|
+
/**
|
371
|
+
* 获取合并单元格主单元格
|
372
|
+
* @param tb
|
373
|
+
* @param rowIndex
|
374
|
+
* @param colIndex
|
375
|
+
* @returns
|
376
|
+
*/
|
377
|
+
static getRestartCellPosition(tb, rowIndex, colIndex) {
|
378
|
+
const row = tb.getChild(rowIndex);
|
379
|
+
const cell = row.getChild(colIndex);
|
380
|
+
if (cell.props.hMerge === 'continue') {
|
381
|
+
const restartCellIndex = this.getHorizontalRestartCellIndex(tb, rowIndex, colIndex);
|
382
|
+
return this.getRestartCellPosition(tb, rowIndex, restartCellIndex);
|
383
|
+
}
|
384
|
+
if (cell.props.vMerge === 'continue') {
|
385
|
+
const restartRowIndex = this.getVerticalRestartCellIndex(tb, rowIndex, colIndex);
|
386
|
+
return this.getRestartCellPosition(tb, restartRowIndex, colIndex);
|
387
|
+
}
|
388
|
+
return { rowIndex, colIndex };
|
389
|
+
}
|
390
|
+
/**
|
391
|
+
* 调整单元格高度填满整个行的高度
|
392
|
+
*/
|
393
|
+
static resizeCellToFillRow(row) {
|
394
|
+
for (let i = 0; i < row.length; i++) {
|
395
|
+
const cell = row.getChild(i);
|
396
|
+
cell.rect.height = row.rect.height;
|
397
|
+
}
|
398
|
+
}
|
399
|
+
/**
|
400
|
+
* 获取元素的全局索引位置
|
401
|
+
* @param control
|
402
|
+
* @returns
|
403
|
+
*/
|
404
|
+
static getControlIndex(control) {
|
405
|
+
const parent = control.parent;
|
406
|
+
if (parent) {
|
407
|
+
const index = control.getIndex();
|
408
|
+
let counter = 1;
|
409
|
+
for (let i = 0; i < index; i++) {
|
410
|
+
const child = parent.getChild(i);
|
411
|
+
counter += child.getSelfLength();
|
412
|
+
}
|
413
|
+
return counter + this.getControlIndex(parent);
|
414
|
+
}
|
415
|
+
else {
|
416
|
+
return 0;
|
417
|
+
}
|
418
|
+
}
|
419
|
+
/**
|
420
|
+
* 根据全局索引位置获取元素
|
421
|
+
* @param control
|
422
|
+
* @param counter
|
423
|
+
* @returns
|
424
|
+
*/
|
425
|
+
static getControlByIndex(control, counter) {
|
426
|
+
counter.currIndex++;
|
427
|
+
if (counter.currIndex === counter.index) {
|
428
|
+
return control;
|
429
|
+
}
|
430
|
+
if (control instanceof LeafElement) {
|
431
|
+
return null;
|
432
|
+
}
|
433
|
+
else if (control instanceof BranchElement) {
|
434
|
+
for (let i = 0; i < control.length; i++) {
|
435
|
+
const res = this.getControlByIndex(control.getChild(i), counter);
|
436
|
+
if (res) {
|
437
|
+
return res;
|
438
|
+
}
|
439
|
+
}
|
440
|
+
}
|
441
|
+
return null;
|
442
|
+
}
|
443
|
+
/**
|
444
|
+
* 获取同级紧挨前方的兄弟元素
|
445
|
+
* @param element
|
446
|
+
* @returns
|
447
|
+
*/
|
448
|
+
static getPrevSiblingElement(element) {
|
449
|
+
const parent = element.parent;
|
450
|
+
if (!parent) {
|
451
|
+
return null;
|
452
|
+
}
|
453
|
+
if (parent) {
|
454
|
+
const index = parent.getChildIndex(element);
|
455
|
+
if (index > 0) {
|
456
|
+
return parent.getChild(index - 1);
|
457
|
+
}
|
458
|
+
}
|
459
|
+
return null;
|
460
|
+
}
|
461
|
+
/**
|
462
|
+
* 获取同级紧挨下方的元素
|
463
|
+
* @param element
|
464
|
+
* @returns
|
465
|
+
*/
|
466
|
+
static getNextSiblingElement(element) {
|
467
|
+
const parent = element.parent;
|
468
|
+
if (!parent) {
|
469
|
+
return null;
|
470
|
+
}
|
471
|
+
if (parent) {
|
472
|
+
const index = parent.getChildIndex(element);
|
473
|
+
if (index < parent.length - 1) {
|
474
|
+
return parent.getChild(index + 1);
|
475
|
+
}
|
476
|
+
}
|
477
|
+
return null;
|
478
|
+
}
|
479
|
+
static getNextSiblingTrackElement(element, type, userId) {
|
480
|
+
const nextSiblingEle = this.getNextSiblingElement(element);
|
481
|
+
if (nextSiblingEle instanceof TrackRunElement) {
|
482
|
+
if (nextSiblingEle.type === type && nextSiblingEle.props.userId === userId) {
|
483
|
+
return nextSiblingEle;
|
484
|
+
}
|
485
|
+
}
|
486
|
+
return null;
|
487
|
+
}
|
488
|
+
static getPrevSiblingTrackElement(element, type, userId) {
|
489
|
+
const prevSiblingEle = this.getPrevSiblingElement(element);
|
490
|
+
if (prevSiblingEle instanceof TrackRunElement) {
|
491
|
+
if (prevSiblingEle.type === type && prevSiblingEle.props.userId === userId) {
|
492
|
+
return prevSiblingEle;
|
493
|
+
}
|
494
|
+
}
|
495
|
+
return null;
|
496
|
+
}
|
497
|
+
/**
|
498
|
+
* 根据默认配置创建长文本
|
499
|
+
* @param viewOptions
|
500
|
+
* @returns
|
501
|
+
*/
|
502
|
+
static getNewTextGroup(textProps) {
|
503
|
+
const text = new TextGroupElement();
|
504
|
+
textProps.clone(text.props);
|
505
|
+
return text;
|
506
|
+
}
|
507
|
+
static createTextProps(dest, viewOptions) {
|
508
|
+
const textProps = dest ?? new TextProps();
|
509
|
+
textProps.fontSize = viewOptions.defaultFontSize;
|
510
|
+
textProps.fontName = viewOptions.defaultFontName;
|
511
|
+
textProps.color = viewOptions.defaultColor;
|
512
|
+
return textProps;
|
513
|
+
}
|
514
|
+
/**
|
515
|
+
* 获取容器内的最小渲染元素集合
|
516
|
+
* @param parPos
|
517
|
+
* @param array
|
518
|
+
*/
|
519
|
+
static getAvailHitLeafRenderObjects(render, parPos) {
|
520
|
+
if (!this.checkAvailHitRender(render)) {
|
521
|
+
return [];
|
522
|
+
}
|
523
|
+
const renderObjectRect = {
|
524
|
+
x: parPos.x + render.rect.x,
|
525
|
+
y: parPos.y + render.rect.y,
|
526
|
+
width: render.rect.width,
|
527
|
+
height: render.rect.height,
|
528
|
+
maxWidth: 0,
|
529
|
+
maxHeight: 0
|
530
|
+
};
|
531
|
+
const array = [];
|
532
|
+
if (render instanceof BranchRenderObject) {
|
533
|
+
for (let i = 0; i < render.length; i++) {
|
534
|
+
const child = render.getChild(i);
|
535
|
+
array.push(...this.getAvailHitLeafRenderObjects(child, { x: renderObjectRect.x, y: renderObjectRect.y }));
|
536
|
+
}
|
537
|
+
}
|
538
|
+
else if (render instanceof LeafRenderObject) {
|
539
|
+
array.push({ render: render, rect: renderObjectRect });
|
540
|
+
}
|
541
|
+
else {
|
542
|
+
throw new Error('未实现');
|
543
|
+
}
|
544
|
+
return array;
|
545
|
+
}
|
546
|
+
/**
|
547
|
+
* 获取容器内的最小渲染元素集合
|
548
|
+
* @param parPos
|
549
|
+
* @param array
|
550
|
+
*/
|
551
|
+
static getAvailHitRenderObjects(render, parPos) {
|
552
|
+
if (!this.checkAvailHitRender(render)) {
|
553
|
+
return [];
|
554
|
+
}
|
555
|
+
const renderObjectRect = this.getRenderObjectAbsoluteRect(render, parPos);
|
556
|
+
const array = [];
|
557
|
+
if (render instanceof BranchRenderObject) {
|
558
|
+
for (let i = 0; i < render.length; i++) {
|
559
|
+
const child = render.getChild(i);
|
560
|
+
if (this.checkAvailHitRender(child)) {
|
561
|
+
array.push({ render: child, rect: this.getRenderObjectAbsoluteRect(child, renderObjectRect) });
|
562
|
+
}
|
563
|
+
}
|
564
|
+
}
|
565
|
+
else if (render instanceof LeafRenderObject) {
|
566
|
+
array.push({ render: render, rect: renderObjectRect });
|
567
|
+
}
|
568
|
+
else {
|
569
|
+
throw new Error('未实现');
|
570
|
+
}
|
571
|
+
return array;
|
572
|
+
}
|
573
|
+
/**
|
574
|
+
* 获取绘制元素的绝对位置框
|
575
|
+
*/
|
576
|
+
static getRenderObjectAbsoluteRect(render, parPos) {
|
577
|
+
const renderObjectRect = {
|
578
|
+
x: parPos.x + render.rect.x,
|
579
|
+
y: parPos.y + render.rect.y,
|
580
|
+
width: render.rect.width,
|
581
|
+
height: render.rect.height,
|
582
|
+
maxWidth: 0,
|
583
|
+
maxHeight: 0
|
584
|
+
};
|
585
|
+
return renderObjectRect;
|
586
|
+
}
|
587
|
+
/**
|
588
|
+
* 检查当前绘制元素是否属于有效点击元素
|
589
|
+
*/
|
590
|
+
static checkAvailHitRender(render) {
|
591
|
+
if (render.element && render.element.disableClick) {
|
592
|
+
return false;
|
593
|
+
}
|
594
|
+
if (render instanceof TableRowRenderObject) {
|
595
|
+
const rowEle = render.element;
|
596
|
+
if (rowEle.props.headerRow) {
|
597
|
+
return rowEle.paintRenders.indexOf(render) === 0;
|
598
|
+
}
|
599
|
+
}
|
600
|
+
return !render.disableClick;
|
601
|
+
}
|
602
|
+
/**
|
603
|
+
* 验证点击可操作性
|
604
|
+
* 主要限制页眉页脚的编辑模式
|
605
|
+
*/
|
606
|
+
static verifyHitable(sourceElement) {
|
607
|
+
if (!sourceElement) {
|
608
|
+
return false;
|
609
|
+
}
|
610
|
+
const parents = ElementUtil.getParentElements(sourceElement);
|
611
|
+
for (let i = parents.length - 1; i >= 0; i--) {
|
612
|
+
const child = parents[i];
|
613
|
+
if (child.disableClick) {
|
614
|
+
return false;
|
615
|
+
}
|
616
|
+
}
|
617
|
+
return true;
|
618
|
+
}
|
619
|
+
/**
|
620
|
+
* 获取一个点到一个矩形最短的距离
|
621
|
+
* @param rect
|
622
|
+
* @param p
|
623
|
+
* @returns
|
624
|
+
*/
|
625
|
+
static getDistanceToRect(rect, p) {
|
626
|
+
const lines = [];
|
627
|
+
lines.push({
|
628
|
+
f: {
|
629
|
+
x: rect.x,
|
630
|
+
y: rect.y
|
631
|
+
},
|
632
|
+
s: {
|
633
|
+
x: rect.x + rect.width,
|
634
|
+
y: rect.y
|
635
|
+
}
|
636
|
+
}, {
|
637
|
+
f: {
|
638
|
+
x: rect.x,
|
639
|
+
y: rect.y
|
640
|
+
},
|
641
|
+
s: {
|
642
|
+
x: rect.x,
|
643
|
+
y: rect.y + rect.height
|
644
|
+
}
|
645
|
+
}, {
|
646
|
+
f: {
|
647
|
+
x: rect.x,
|
648
|
+
y: rect.y + rect.height
|
649
|
+
},
|
650
|
+
s: {
|
651
|
+
x: rect.x + rect.width,
|
652
|
+
y: rect.y + rect.height
|
653
|
+
}
|
654
|
+
}, {
|
655
|
+
f: {
|
656
|
+
x: rect.x + rect.width,
|
657
|
+
y: rect.y
|
658
|
+
},
|
659
|
+
s: {
|
660
|
+
x: rect.x + rect.width,
|
661
|
+
y: rect.y + rect.height
|
662
|
+
}
|
663
|
+
});
|
664
|
+
const distances = lines.map(item => this.minDistance(item.f, item.s, p));
|
665
|
+
return Math.min(...distances);
|
666
|
+
}
|
667
|
+
static minDistance(A, B, E) {
|
668
|
+
const AB = { x: B.x - A.x, y: B.y - A.y };
|
669
|
+
const BE = { x: E.x - B.x, y: E.y - B.y };
|
670
|
+
const AE = { x: E.x - A.x, y: E.y - A.y };
|
671
|
+
const AB_BE = (AB.x * BE.x + AB.y * BE.y);
|
672
|
+
const AB_AE = (AB.x * AE.x + AB.y * AE.y);
|
673
|
+
let reqAns = 0;
|
674
|
+
if (AB_BE > 0) {
|
675
|
+
const y = E.y - B.y;
|
676
|
+
const x = E.x - B.x;
|
677
|
+
reqAns = Math.sqrt(x * x + y * y);
|
678
|
+
}
|
679
|
+
else if (AB_AE < 0) {
|
680
|
+
const y = E.y - A.y;
|
681
|
+
const x = E.x - A.x;
|
682
|
+
reqAns = Math.sqrt(x * x + y * y);
|
683
|
+
}
|
684
|
+
else {
|
685
|
+
const x1 = AB.x;
|
686
|
+
const y1 = AB.y;
|
687
|
+
const x2 = AE.x;
|
688
|
+
const y2 = AE.y;
|
689
|
+
const mod = Math.sqrt(x1 * x1 + y1 * y1);
|
690
|
+
reqAns = Math.abs(x1 * y2 - y1 * x2) / mod;
|
691
|
+
}
|
692
|
+
return reqAns;
|
693
|
+
}
|
694
|
+
/**
|
695
|
+
* 获取父级层级渲染对象
|
696
|
+
* @param render
|
697
|
+
* @returns
|
698
|
+
*/
|
699
|
+
static getParentRenders(render) {
|
700
|
+
if (render) {
|
701
|
+
return [render, ...this.getParentRenders(render.parent)];
|
702
|
+
}
|
703
|
+
else {
|
704
|
+
return [];
|
705
|
+
}
|
706
|
+
}
|
707
|
+
static getRenderMapElements(render) {
|
708
|
+
const renders = this.getParentRenders(render);
|
709
|
+
return renders.map(render => render.element).filter(ele => ele);
|
710
|
+
}
|
711
|
+
static getParentRender(child, parentType) {
|
712
|
+
if (!child) {
|
713
|
+
return null;
|
714
|
+
}
|
715
|
+
if (child instanceof parentType) {
|
716
|
+
return child;
|
717
|
+
}
|
718
|
+
else {
|
719
|
+
return this.getParentRender(child.parent, parentType);
|
720
|
+
}
|
721
|
+
}
|
722
|
+
static getParentRenderByPredicate(child, predicate) {
|
723
|
+
if (!child) {
|
724
|
+
return null;
|
725
|
+
}
|
726
|
+
if (predicate(child)) {
|
727
|
+
return child;
|
728
|
+
}
|
729
|
+
else {
|
730
|
+
return this.getParentRenderByPredicate(child.parent, predicate);
|
731
|
+
}
|
732
|
+
}
|
733
|
+
/**
|
734
|
+
* 获取父级层级元素对象
|
735
|
+
* @param element
|
736
|
+
* @returns
|
737
|
+
*/
|
738
|
+
static getParentElements(element) {
|
739
|
+
if (element) {
|
740
|
+
return [element, ...this.getParentElements(element.parent)];
|
741
|
+
}
|
742
|
+
else {
|
743
|
+
return [];
|
744
|
+
}
|
745
|
+
}
|
746
|
+
/**
|
747
|
+
* 获取最后一个子元素
|
748
|
+
* @param element
|
749
|
+
* @returns
|
750
|
+
*/
|
751
|
+
static getLastLeafElement(element, predicate = null) {
|
752
|
+
if (element instanceof LeafElement && (!predicate || predicate(element))) {
|
753
|
+
return element;
|
754
|
+
}
|
755
|
+
else if (element instanceof BranchElement) {
|
756
|
+
for (let i = element.length - 1; i >= 0; i--) {
|
757
|
+
const res = this.getLastLeafElement(element.getChild(i), predicate);
|
758
|
+
if (res) {
|
759
|
+
return res;
|
760
|
+
}
|
761
|
+
}
|
762
|
+
return null;
|
763
|
+
}
|
764
|
+
return null;
|
765
|
+
}
|
766
|
+
/**
|
767
|
+
* 获取第一个子元素
|
768
|
+
* @param element
|
769
|
+
* @returns
|
770
|
+
*/
|
771
|
+
static getFirstLeafElement(element) {
|
772
|
+
if (element instanceof LeafElement) {
|
773
|
+
return element;
|
774
|
+
}
|
775
|
+
else if (element instanceof BranchElement) {
|
776
|
+
for (let i = 0; i < element.length; i++) {
|
777
|
+
const res = this.getFirstLeafElement(element.getChild(i));
|
778
|
+
if (res) {
|
779
|
+
return res;
|
780
|
+
}
|
781
|
+
}
|
782
|
+
return null;
|
783
|
+
}
|
784
|
+
return null;
|
785
|
+
}
|
786
|
+
/**
|
787
|
+
* 校验两个元素是否在同一个段落中
|
788
|
+
* @param element1
|
789
|
+
* @param element2
|
790
|
+
*/
|
791
|
+
static isInSameParagraph(element1, element2) {
|
792
|
+
const par1 = this.getParentByType(element1, ParagraphElement);
|
793
|
+
const par2 = this.getParentByType(element2, ParagraphElement);
|
794
|
+
return par1 === par2;
|
795
|
+
}
|
796
|
+
static getBorderCursor(borderType) {
|
797
|
+
switch (borderType) {
|
798
|
+
case 'none':
|
799
|
+
return 'text';
|
800
|
+
case 'top':
|
801
|
+
return 'row-resize';
|
802
|
+
case 'left':
|
803
|
+
return 'col-resize';
|
804
|
+
case 'right':
|
805
|
+
return 'col-resize';
|
806
|
+
case 'bottom':
|
807
|
+
return 'row-resize';
|
808
|
+
case 'left-middle':
|
809
|
+
case 'right-middle':
|
810
|
+
return 'w-resize';
|
811
|
+
case 'top-middle':
|
812
|
+
case 'bottom-middle':
|
813
|
+
return 's-resize';
|
814
|
+
case 'left-top':
|
815
|
+
case 'right-bottom':
|
816
|
+
return 'se-resize';
|
817
|
+
case 'right-top':
|
818
|
+
case 'left-bottom':
|
819
|
+
return 'ne-resize';
|
820
|
+
default:
|
821
|
+
return 'text';
|
822
|
+
}
|
823
|
+
}
|
824
|
+
static getParentByType(child, parentType) {
|
825
|
+
if (!child) {
|
826
|
+
return null;
|
827
|
+
}
|
828
|
+
if (child instanceof parentType) {
|
829
|
+
return child;
|
830
|
+
}
|
831
|
+
else {
|
832
|
+
return this.getParentByType(child.parent, parentType);
|
833
|
+
}
|
834
|
+
}
|
835
|
+
static getParent(child, predicate) {
|
836
|
+
if (!child) {
|
837
|
+
return null;
|
838
|
+
}
|
839
|
+
if (predicate(child)) {
|
840
|
+
return child;
|
841
|
+
}
|
842
|
+
else {
|
843
|
+
return this.getParent(child.parent, predicate);
|
844
|
+
}
|
845
|
+
}
|
846
|
+
/**
|
847
|
+
* 修正段落内容
|
848
|
+
* @returns
|
849
|
+
*/
|
850
|
+
static fixParagraphContent(control) {
|
851
|
+
//如果最后一个元素不是段落符号,则补足
|
852
|
+
if (!(control.getChild(control.length - 1) instanceof PSymbolElement)) {
|
853
|
+
control.addChild(new PSymbolElement());
|
854
|
+
}
|
855
|
+
const items = [];
|
856
|
+
for (let i = 0; i < control.length - 1; i++) {
|
857
|
+
const child = control.getChild(i);
|
858
|
+
if (child instanceof PSymbolElement) {
|
859
|
+
items.push(child);
|
860
|
+
}
|
861
|
+
}
|
862
|
+
items.forEach(item => {
|
863
|
+
control.removeChild(item);
|
864
|
+
});
|
865
|
+
}
|
866
|
+
/**
|
867
|
+
* 修正块级容器内容
|
868
|
+
* @param control
|
869
|
+
*/
|
870
|
+
static fixBlockContainer(control) {
|
871
|
+
if (control.length === 0) {
|
872
|
+
if (control instanceof TableCellElement && (control.props.vMerge === 'continue' || control.props.hMerge === 'continue')) {
|
873
|
+
return;
|
874
|
+
}
|
875
|
+
if (control.noFillEmpty) {
|
876
|
+
return;
|
877
|
+
}
|
878
|
+
control.addChild(new ParagraphElement());
|
879
|
+
}
|
880
|
+
}
|
881
|
+
/**
|
882
|
+
* 获取绘制元素相对于整个画布的绝对位置
|
883
|
+
* 整个画布绘制的时候不一定从x=0,y=0时绘制的,下拉滚动时,上面从负y坐标开始绘制
|
884
|
+
* 如果计算某个元素相对画布的左上角的绝对坐标位置,需要childPos的y值减去translateY
|
885
|
+
* @param render
|
886
|
+
* @param refPos 参照位置
|
887
|
+
* @returns
|
888
|
+
*/
|
889
|
+
static getRenderAbsolutePaintPos(render, refPos = null) {
|
890
|
+
refPos = refPos ?? { x: 0, y: 0 };
|
891
|
+
const currPos = { x: render.rect.x + refPos.x, y: render.rect.y + refPos.y };
|
892
|
+
if (!render.parent) {
|
893
|
+
return currPos;
|
894
|
+
}
|
895
|
+
return this.getRenderAbsolutePaintPos(render.parent, currPos);
|
896
|
+
}
|
897
|
+
static getRenderAbsolutePaintRect(render, childPos = null) {
|
898
|
+
const pos = this.getRenderAbsolutePaintPos(render, childPos);
|
899
|
+
return { ...pos, width: render.rect.width, height: render.rect.height, maxWidth: 0, maxHeight: 0 };
|
900
|
+
}
|
901
|
+
/**
|
902
|
+
* 获取选中区域的开始区域
|
903
|
+
* @param range
|
904
|
+
* @returns
|
905
|
+
*/
|
906
|
+
static getFirstSelectedRange(range) {
|
907
|
+
if (range.selectedChildren.length === 0 || range.target instanceof TextGroupElement) {
|
908
|
+
return range;
|
909
|
+
}
|
910
|
+
else {
|
911
|
+
return this.getFirstSelectedRange(range.selectedChildren[0]);
|
912
|
+
}
|
913
|
+
}
|
914
|
+
/**
|
915
|
+
* 获取选中区域的开始区域
|
916
|
+
* @param range \
|
917
|
+
* @returns
|
918
|
+
*/
|
919
|
+
static getLastSelectedRange(range) {
|
920
|
+
if (range.selectedChildren.length === 0 || range.target instanceof TextGroupElement) {
|
921
|
+
return range;
|
922
|
+
}
|
923
|
+
else {
|
924
|
+
return this.getLastSelectedRange(range.selectedChildren[range.selectedChildren.length - 1]);
|
925
|
+
}
|
926
|
+
}
|
927
|
+
/**
|
928
|
+
* 克隆选区内容
|
929
|
+
* @param range
|
930
|
+
* @param isDelete
|
931
|
+
* @returns
|
932
|
+
*/
|
933
|
+
static cloneRange(range, isDelete, cloneMode = 'clone') {
|
934
|
+
const { target, isFullSelected, startOffset, endOffset, selectedChildren } = range;
|
935
|
+
if (isFullSelected) {
|
936
|
+
//修饰元素不能复制 审阅标记、数据元NullText
|
937
|
+
if (cloneMode === 'copy' && target.isDecorate) {
|
938
|
+
return null;
|
939
|
+
}
|
940
|
+
const clone = cloneMode === 'source' ? target : target.clone(true);
|
941
|
+
if (isDelete) {
|
942
|
+
target.remove();
|
943
|
+
}
|
944
|
+
return clone;
|
945
|
+
}
|
946
|
+
else {
|
947
|
+
if (target instanceof LeafElement) {
|
948
|
+
if (target instanceof TextGroupElement && startOffset !== endOffset) {
|
949
|
+
if (isDelete) {
|
950
|
+
const copyTarget = target.spliceText(startOffset, endOffset, true);
|
951
|
+
if (target.text.length === 0) {
|
952
|
+
target.remove();
|
953
|
+
}
|
954
|
+
return copyTarget;
|
955
|
+
}
|
956
|
+
else {
|
957
|
+
const copyTarget = target.spliceText(startOffset, endOffset, false);
|
958
|
+
return copyTarget;
|
959
|
+
}
|
960
|
+
}
|
961
|
+
return null;
|
962
|
+
}
|
963
|
+
else if (target instanceof BranchElement) {
|
964
|
+
const array = [];
|
965
|
+
for (let i = 0; i < selectedChildren.length; i++) {
|
966
|
+
const copyChild = this.cloneRange(selectedChildren[i], isDelete, cloneMode);
|
967
|
+
if (copyChild) {
|
968
|
+
array.push(copyChild);
|
969
|
+
}
|
970
|
+
}
|
971
|
+
if (!array.length) {
|
972
|
+
return null;
|
973
|
+
}
|
974
|
+
else {
|
975
|
+
const copyTarget = target.clone(false);
|
976
|
+
array.forEach(item => {
|
977
|
+
copyTarget.addChild(item);
|
978
|
+
});
|
979
|
+
return copyTarget;
|
980
|
+
}
|
981
|
+
}
|
982
|
+
}
|
983
|
+
return null;
|
984
|
+
}
|
985
|
+
/**
|
986
|
+
* 获取所有的子级元素
|
987
|
+
* @param branchEle
|
988
|
+
* @returns
|
989
|
+
*/
|
990
|
+
static getChildrenElements(branchEle) {
|
991
|
+
const array = [];
|
992
|
+
for (let i = 0; i < branchEle.length; i++) {
|
993
|
+
array.push(branchEle.getChild(i));
|
994
|
+
}
|
995
|
+
return array;
|
996
|
+
}
|
997
|
+
/**
|
998
|
+
* 递归向前寻找最近的元素
|
999
|
+
* @param currElement
|
1000
|
+
* @param inPara 是否在同一段落中寻找
|
1001
|
+
* @param forCursor 查找结果是否用于光标定位
|
1002
|
+
* @returns
|
1003
|
+
*/
|
1004
|
+
static getRecursionPrevSiblingElement(currElement, inPara = false, forCursor = false) {
|
1005
|
+
const parent = currElement?.parent;
|
1006
|
+
//删除留痕块的measureRender在不显示留痕模式下,不生成render
|
1007
|
+
if (!currElement || !parent || (!currElement.measureRender && !(currElement instanceof TrackRunElement))) {
|
1008
|
+
return null;
|
1009
|
+
}
|
1010
|
+
//如果当前数据元不可编辑,则直接跳过
|
1011
|
+
if (parent instanceof DataElementInlineGroup && !parent.props.editable) {
|
1012
|
+
return this.getRecursionPrevSiblingElement(parent, inPara, forCursor);
|
1013
|
+
}
|
1014
|
+
if (forCursor && parent.disableClick) {
|
1015
|
+
return this.getRecursionPrevSiblingElement(parent, inPara, forCursor);
|
1016
|
+
}
|
1017
|
+
const index = parent.getChildIndex(currElement);
|
1018
|
+
if (!index) {
|
1019
|
+
if (inPara && parent.type === 'p') {
|
1020
|
+
return null;
|
1021
|
+
}
|
1022
|
+
return this.getRecursionPrevSiblingElement(parent, inPara, forCursor);
|
1023
|
+
}
|
1024
|
+
else {
|
1025
|
+
let prevElement = null;
|
1026
|
+
for (let i = index - 1; i >= 0; i--) {
|
1027
|
+
prevElement = parent.getChild(i);
|
1028
|
+
if (prevElement && !prevElement.disableClick) {
|
1029
|
+
break;
|
1030
|
+
}
|
1031
|
+
}
|
1032
|
+
if (!prevElement || prevElement.disableClick) {
|
1033
|
+
return this.getRecursionPrevSiblingElement(parent, inPara, forCursor);
|
1034
|
+
}
|
1035
|
+
const lastLeafElement = ElementUtil.getLastLeafElement(prevElement);
|
1036
|
+
//用于光标定位
|
1037
|
+
if (forCursor && lastLeafElement && lastLeafElement.disableClick) {
|
1038
|
+
return this.getRecursionPrevSiblingElement(lastLeafElement, inPara, forCursor);
|
1039
|
+
}
|
1040
|
+
if (lastLeafElement) {
|
1041
|
+
return lastLeafElement;
|
1042
|
+
}
|
1043
|
+
else {
|
1044
|
+
return this.getRecursionPrevSiblingElement(prevElement.parent, inPara, forCursor);
|
1045
|
+
}
|
1046
|
+
}
|
1047
|
+
}
|
1048
|
+
/**
|
1049
|
+
* 循环向前寻找可定位的数据元
|
1050
|
+
* @param currElement
|
1051
|
+
*/
|
1052
|
+
static getPrevDataElement(ctx, currElement) {
|
1053
|
+
const dataEle = ctx.getCurrentCtx(currElement).getControlInstanceList().filter(item => item instanceof DataElementInlineGroup);
|
1054
|
+
const index = dataEle.indexOf(currElement);
|
1055
|
+
if (index > 0) {
|
1056
|
+
for (let i = index - 1; i >= 0; i--) {
|
1057
|
+
if (!dataEle[i].disableClick && dataEle[i].props.editable) {
|
1058
|
+
return dataEle[i];
|
1059
|
+
}
|
1060
|
+
}
|
1061
|
+
}
|
1062
|
+
return null;
|
1063
|
+
}
|
1064
|
+
// /**
|
1065
|
+
// * 递归向前寻找最近的可点击元素
|
1066
|
+
// */
|
1067
|
+
// static getRecursionPrevSiblingElementForHit(currElement: Element | null): LeafElement | null {
|
1068
|
+
// let ele: LeafElement | null = null;
|
1069
|
+
// do {
|
1070
|
+
// ele = this.getRecursionPrevSiblingElement(currElement);
|
1071
|
+
// } while (ele && ele.disableClick)
|
1072
|
+
// return ele;
|
1073
|
+
// }
|
1074
|
+
// /**
|
1075
|
+
// * 在同一段落中,递归向前寻找最近的元素
|
1076
|
+
// */
|
1077
|
+
// static getRecursionPrevSiblingElementInPara(currElement: Element | null): LeafElement | null {
|
1078
|
+
// const parent = currElement?.parent;
|
1079
|
+
// if (!currElement || !parent) {
|
1080
|
+
// return null;
|
1081
|
+
// }
|
1082
|
+
// const index = parent.getChildIndex(currElement);
|
1083
|
+
// if (!index) {
|
1084
|
+
// if (parent.type === 'p') {
|
1085
|
+
// return null;
|
1086
|
+
// }
|
1087
|
+
// return this.getRecursionPrevSiblingElementInPara(parent);
|
1088
|
+
// } else {
|
1089
|
+
// const prevElement = parent.getChild(index - 1);
|
1090
|
+
// const lastLeafElement = ElementUtil.getLastLeafElement(prevElement);
|
1091
|
+
// if (lastLeafElement) {
|
1092
|
+
// return lastLeafElement;
|
1093
|
+
// } else {
|
1094
|
+
// return this.getRecursionPrevSiblingElementInPara(prevElement?.parent);
|
1095
|
+
// }
|
1096
|
+
// }
|
1097
|
+
// }
|
1098
|
+
// /**
|
1099
|
+
// * 在同一段落中,递归向前寻找最近的可点击元素
|
1100
|
+
// */
|
1101
|
+
// static getRecursionPrevSiblingElementInParaForHit(currElement: Element | null): LeafElement | null {
|
1102
|
+
// let ele: LeafElement | null = null;
|
1103
|
+
// do {
|
1104
|
+
// ele = this.getRecursionPrevSiblingElementInPara(currElement);
|
1105
|
+
// } while (ele && ele.disableClick)
|
1106
|
+
// return ele;
|
1107
|
+
// }
|
1108
|
+
/**
|
1109
|
+
* 递归向后寻找最近的元素
|
1110
|
+
*/
|
1111
|
+
static getRecursionNextSiblingElement(currElement, inPara = false, forCursor = false) {
|
1112
|
+
const parent = currElement?.parent;
|
1113
|
+
if (!currElement || !parent || !currElement.measureRender) {
|
1114
|
+
return null;
|
1115
|
+
}
|
1116
|
+
//如果当前数据元不可编辑,则直接跳过
|
1117
|
+
if (parent instanceof DataElementInlineGroup && !parent.props.editable) {
|
1118
|
+
return this.getRecursionNextSiblingElement(parent, inPara, forCursor);
|
1119
|
+
}
|
1120
|
+
if (forCursor && parent.disableClick) {
|
1121
|
+
return this.getRecursionNextSiblingElement(parent, inPara, forCursor);
|
1122
|
+
}
|
1123
|
+
const index = parent.getChildIndex(currElement);
|
1124
|
+
if (index === parent.length - 1) {
|
1125
|
+
if (inPara && parent.type === 'p') {
|
1126
|
+
return null;
|
1127
|
+
}
|
1128
|
+
return this.getRecursionNextSiblingElement(parent, inPara, forCursor);
|
1129
|
+
}
|
1130
|
+
else {
|
1131
|
+
let nextElement = null;
|
1132
|
+
for (let i = index + 1; i < parent.length; i++) {
|
1133
|
+
nextElement = parent.getChild(i);
|
1134
|
+
if (nextElement && !nextElement.disableClick) {
|
1135
|
+
break;
|
1136
|
+
}
|
1137
|
+
}
|
1138
|
+
if (!nextElement || nextElement.disableClick) {
|
1139
|
+
return this.getRecursionNextSiblingElement(parent, inPara, forCursor);
|
1140
|
+
}
|
1141
|
+
const lastLeafElement = ElementUtil.getFirstLeafElement(nextElement);
|
1142
|
+
//用于光标定位
|
1143
|
+
if (forCursor && lastLeafElement && lastLeafElement.disableClick) {
|
1144
|
+
return this.getRecursionNextSiblingElement(lastLeafElement, inPara, forCursor);
|
1145
|
+
}
|
1146
|
+
if (lastLeafElement) {
|
1147
|
+
return lastLeafElement;
|
1148
|
+
}
|
1149
|
+
else {
|
1150
|
+
return this.getRecursionNextSiblingElement(nextElement.parent, inPara, forCursor);
|
1151
|
+
}
|
1152
|
+
}
|
1153
|
+
}
|
1154
|
+
// /**
|
1155
|
+
// * 在同一段落中,递归向后寻找最近的元素
|
1156
|
+
// */
|
1157
|
+
// static getRecursionNextSiblingElementInPara(currElement: Element | null): LeafElement | null {
|
1158
|
+
// const parent = currElement?.parent;
|
1159
|
+
// if (!currElement || !parent) {
|
1160
|
+
// return null;
|
1161
|
+
// }
|
1162
|
+
// const index = parent.getChildIndex(currElement);
|
1163
|
+
// if (index === parent.length - 1) {
|
1164
|
+
// if (parent.type === 'p') {
|
1165
|
+
// return null;
|
1166
|
+
// }
|
1167
|
+
// return this.getRecursionNextSiblingElementInPara(parent);
|
1168
|
+
// } else {
|
1169
|
+
// const nextElement = parent.getChild(index + 1);
|
1170
|
+
// const lastLeafElement = ElementUtil.getFirstLeafElement(nextElement);
|
1171
|
+
// if (lastLeafElement) {
|
1172
|
+
// return lastLeafElement;
|
1173
|
+
// } else {
|
1174
|
+
// return this.getRecursionNextSiblingElementInPara(nextElement.parent);
|
1175
|
+
// }
|
1176
|
+
// }
|
1177
|
+
// }
|
1178
|
+
// /**
|
1179
|
+
// * 在同一段落中,递归向后寻找最近的可点击元素
|
1180
|
+
// */
|
1181
|
+
// static getRecursionNextSiblingElementInParaForHit(currElement: Element | null): LeafElement | null {
|
1182
|
+
// let ele: LeafElement | null = null;
|
1183
|
+
// do {
|
1184
|
+
// ele = this.getRecursionNextSiblingElementInPara(currElement);
|
1185
|
+
// } while (ele && ele.disableClick)
|
1186
|
+
// return ele;
|
1187
|
+
// }
|
1188
|
+
// /**
|
1189
|
+
// * 在同一段落中,递归向后寻找最近的可点击元素
|
1190
|
+
// */
|
1191
|
+
// static getRecursionNextSiblingElementForHit(currElement: Element | null): LeafElement | null {
|
1192
|
+
// let ele: LeafElement | null = null;
|
1193
|
+
// do {
|
1194
|
+
// ele = this.getRecursionNextSiblingElement(currElement);
|
1195
|
+
// } while (ele && ele.disableClick)
|
1196
|
+
// return ele;
|
1197
|
+
// }
|
1198
|
+
/**
|
1199
|
+
* 获取行内最大渲染单元格高度,主要处理纵向合并单元格问题
|
1200
|
+
* @param row
|
1201
|
+
* @returns
|
1202
|
+
*/
|
1203
|
+
static getRowMaxCellHeight(row) {
|
1204
|
+
let maxHeight = 0;
|
1205
|
+
for (let i = 0; i < row.length; i++) {
|
1206
|
+
if (row.getChild(i).rect.height > maxHeight) {
|
1207
|
+
maxHeight = row.getChild(i).rect.height;
|
1208
|
+
}
|
1209
|
+
}
|
1210
|
+
return maxHeight;
|
1211
|
+
}
|
1212
|
+
/**
|
1213
|
+
* 校验是否为空内容
|
1214
|
+
* @param ele
|
1215
|
+
*/
|
1216
|
+
static checkEmptyContent(ele) {
|
1217
|
+
if (ele.length === 1) {
|
1218
|
+
const firstRender = ele.getChild(0);
|
1219
|
+
if (firstRender instanceof ParagraphRenderObject) {
|
1220
|
+
if ((firstRender.element).length === 1) {
|
1221
|
+
return true;
|
1222
|
+
}
|
1223
|
+
}
|
1224
|
+
}
|
1225
|
+
return false;
|
1226
|
+
}
|
1227
|
+
/**
|
1228
|
+
* 测量行内编组元素
|
1229
|
+
* @param render
|
1230
|
+
*/
|
1231
|
+
static remeasureInlineGroupRender(render) {
|
1232
|
+
let x = 0;
|
1233
|
+
let maxHeight = 0;
|
1234
|
+
for (let i = 0; i < render.length; i++) {
|
1235
|
+
const item = render.getChild(i);
|
1236
|
+
item.rect.x = x;
|
1237
|
+
if (item.rect.height > maxHeight) {
|
1238
|
+
maxHeight = item.rect.height;
|
1239
|
+
}
|
1240
|
+
x += item.rect.width;
|
1241
|
+
}
|
1242
|
+
for (let i = 0; i < render.length; i++) {
|
1243
|
+
const item = render.getChild(i);
|
1244
|
+
item.rect.y = maxHeight - item.rect.height;
|
1245
|
+
}
|
1246
|
+
render.rect.width = x;
|
1247
|
+
render.rect.height = maxHeight;
|
1248
|
+
}
|
1249
|
+
static getParaLinePos(childRender, childRenderPos) {
|
1250
|
+
const parent = childRender.parent;
|
1251
|
+
const rect = ElementUtil.cloneRect(parent.rect);
|
1252
|
+
rect.x = childRenderPos.x - childRender.rect.x;
|
1253
|
+
rect.y = childRenderPos.y - childRender.rect.y;
|
1254
|
+
if (parent instanceof ParagraphLineRectRenderObject) {
|
1255
|
+
return rect;
|
1256
|
+
}
|
1257
|
+
else {
|
1258
|
+
return this.getParaLinePos(parent, rect);
|
1259
|
+
}
|
1260
|
+
}
|
1261
|
+
static getParentRenderPos(parentRender, childRender, childRenderPos) {
|
1262
|
+
const parent = childRender.parent;
|
1263
|
+
const rect = ElementUtil.cloneRect(parent.rect);
|
1264
|
+
rect.x = childRenderPos.x - childRender.rect.x;
|
1265
|
+
rect.y = childRenderPos.y - childRender.rect.y;
|
1266
|
+
if (parent === parentRender) {
|
1267
|
+
return rect;
|
1268
|
+
}
|
1269
|
+
else {
|
1270
|
+
return this.getParentRenderPos(parentRender, parent, rect);
|
1271
|
+
}
|
1272
|
+
}
|
1273
|
+
/**
|
1274
|
+
* 获取绘制元素所在的区域
|
1275
|
+
*/
|
1276
|
+
static getRenderObjectRegion(render) {
|
1277
|
+
if (!render) {
|
1278
|
+
return undefined;
|
1279
|
+
}
|
1280
|
+
if (render.element) {
|
1281
|
+
return this.getElementRegion(render.element);
|
1282
|
+
}
|
1283
|
+
return this.getRenderObjectRegion(render.parent);
|
1284
|
+
}
|
1285
|
+
/**
|
1286
|
+
* 获取文档元素所在的区域
|
1287
|
+
* @param element
|
1288
|
+
* @returns
|
1289
|
+
*/
|
1290
|
+
static getElementRegion(element) {
|
1291
|
+
const regionTarget = this.getElementRegionTarget(element);
|
1292
|
+
return regionTarget?.type;
|
1293
|
+
}
|
1294
|
+
static getElementRegionTarget(element) {
|
1295
|
+
if (!element) {
|
1296
|
+
return null;
|
1297
|
+
}
|
1298
|
+
if (element instanceof DocumentBodyElement) {
|
1299
|
+
return { type: 'body', target: element };
|
1300
|
+
}
|
1301
|
+
if (element instanceof DocumentFooterElement) {
|
1302
|
+
return { type: 'footer', target: element };
|
1303
|
+
}
|
1304
|
+
if (element instanceof DocumentHeaderElement) {
|
1305
|
+
return { type: 'header', target: element };
|
1306
|
+
}
|
1307
|
+
if (element instanceof CommsContainerElement) {
|
1308
|
+
return { type: 'review', target: element };
|
1309
|
+
}
|
1310
|
+
return this.getElementRegionTarget(element.parent);
|
1311
|
+
}
|
1312
|
+
/**
|
1313
|
+
* 根据坐标系统偏移位获取所在的文本偏移位置
|
1314
|
+
* @param textRender
|
1315
|
+
* @param x
|
1316
|
+
* @returns
|
1317
|
+
*/
|
1318
|
+
static getTextRenderOffset(textRender, x) {
|
1319
|
+
const ele = textRender.element;
|
1320
|
+
const docRender = ElementUtil.getParentRender(textRender, DocumentRenderObject);
|
1321
|
+
if (!docRender) {
|
1322
|
+
throw new Error('docRender is null');
|
1323
|
+
}
|
1324
|
+
const elePaintRenders = ele.paintRenders.filter(item => ElementUtil.getParentRender(item, DocumentRenderObject) === docRender);
|
1325
|
+
let count = 0;
|
1326
|
+
for (let i = 0; i < elePaintRenders.length; i++) {
|
1327
|
+
const render = elePaintRenders[i];
|
1328
|
+
if (render !== textRender) {
|
1329
|
+
count += render.textMeasures.length;
|
1330
|
+
}
|
1331
|
+
else {
|
1332
|
+
let horX = 0;
|
1333
|
+
for (let j = 0; j < render.textMeasures.length; j++) {
|
1334
|
+
if (horX + render.textMeasures[j].actualSize >= x) {
|
1335
|
+
if (horX + Math.floor(render.textMeasures[j].actualSize / 2) > x) {
|
1336
|
+
if (j === 0 && i > 0) {
|
1337
|
+
j += 0.5;
|
1338
|
+
}
|
1339
|
+
}
|
1340
|
+
else {
|
1341
|
+
j += 1;
|
1342
|
+
}
|
1343
|
+
return j + count;
|
1344
|
+
}
|
1345
|
+
horX += render.textMeasures[j].actualSize;
|
1346
|
+
}
|
1347
|
+
return count + render.textMeasures.length;
|
1348
|
+
}
|
1349
|
+
}
|
1350
|
+
throw new Error('未找到当前文本元素的光标偏移量');
|
1351
|
+
}
|
1352
|
+
static getHitRenderOffset(render, x) {
|
1353
|
+
if (render instanceof TextGroupRenderObject) {
|
1354
|
+
return this.getTextRenderOffset(render, x);
|
1355
|
+
}
|
1356
|
+
else {
|
1357
|
+
if (render.element && render.element.type === 'psym') {
|
1358
|
+
return 0;
|
1359
|
+
}
|
1360
|
+
return (render.rect.width / 2) >= x ? 0 : 1;
|
1361
|
+
}
|
1362
|
+
}
|
1363
|
+
static getTextRenderHorX(currRender, startOffset, endOffset) {
|
1364
|
+
const textEle = currRender.element;
|
1365
|
+
let endX = 0;
|
1366
|
+
let startX = 0;
|
1367
|
+
let count = 0;
|
1368
|
+
for (let i = 0; i < textEle.paintRenders.length; i++) {
|
1369
|
+
const paintRender = textEle.paintRenders[i];
|
1370
|
+
if (paintRender !== currRender) {
|
1371
|
+
count += paintRender.textMeasures.length;
|
1372
|
+
}
|
1373
|
+
else {
|
1374
|
+
if (count + paintRender.textMeasures.length < startOffset) {
|
1375
|
+
continue;
|
1376
|
+
}
|
1377
|
+
if (count > endOffset) {
|
1378
|
+
continue;
|
1379
|
+
}
|
1380
|
+
for (let j = 0; j < paintRender.textMeasures.length; j++) {
|
1381
|
+
if (endOffset === count + j) {
|
1382
|
+
break;
|
1383
|
+
}
|
1384
|
+
if (count + j === startOffset) {
|
1385
|
+
startX = endX;
|
1386
|
+
}
|
1387
|
+
endX += paintRender.textMeasures[j].actualSize;
|
1388
|
+
}
|
1389
|
+
}
|
1390
|
+
}
|
1391
|
+
return { startX, endX };
|
1392
|
+
}
|
1393
|
+
/**
|
1394
|
+
* 获取一个元素结尾偏移量
|
1395
|
+
* 文本以字符长度进行确定
|
1396
|
+
* @param ele
|
1397
|
+
* @returns
|
1398
|
+
*/
|
1399
|
+
static getElementEndOffset(ele) {
|
1400
|
+
if (ele instanceof TextGroupElement) {
|
1401
|
+
return ele.textMeasures.length;
|
1402
|
+
}
|
1403
|
+
return 1;
|
1404
|
+
}
|
1405
|
+
/**
|
1406
|
+
* 判断当前偏移量是否是最终偏移量
|
1407
|
+
* @param ele
|
1408
|
+
* @param offset
|
1409
|
+
*/
|
1410
|
+
static isElementEndOffset(ele, offset) {
|
1411
|
+
return this.getElementEndOffset(ele) === offset;
|
1412
|
+
}
|
1413
|
+
/**
|
1414
|
+
* 获取直接子节点的所有渲染元素
|
1415
|
+
* @param ele
|
1416
|
+
* @returns
|
1417
|
+
*/
|
1418
|
+
static getChildRenders(ele) {
|
1419
|
+
const items = [];
|
1420
|
+
for (let i = 0; i < ele.length; i++) {
|
1421
|
+
items.push(ele.getChild(i));
|
1422
|
+
}
|
1423
|
+
return items;
|
1424
|
+
}
|
1425
|
+
/**
|
1426
|
+
* 获取当前单元格内所有的段落行
|
1427
|
+
* @param cell
|
1428
|
+
* @returns
|
1429
|
+
*/
|
1430
|
+
static getCellParaLines(cell) {
|
1431
|
+
const items = [];
|
1432
|
+
for (let i = 0; i < cell.length; i++) {
|
1433
|
+
const para = cell.getChild(i);
|
1434
|
+
for (let j = 0; j < para.length; j++) {
|
1435
|
+
items.push(para.getChild(j));
|
1436
|
+
}
|
1437
|
+
}
|
1438
|
+
return items;
|
1439
|
+
}
|
1440
|
+
static getRandomColor(seed) {
|
1441
|
+
let letters = '0123456789ABCDEF';
|
1442
|
+
let color = '#';
|
1443
|
+
for (let i = 0; i < 6; i++) {
|
1444
|
+
color += letters[Math.floor(this.getSeedRandom(seed) * 16)];
|
1445
|
+
}
|
1446
|
+
return color;
|
1447
|
+
}
|
1448
|
+
static getSeedRandom(seed) {
|
1449
|
+
return Number("0." + Math.sin(seed * Math.random()).toString().substr(6));
|
1450
|
+
}
|
1451
|
+
static findChildRender(render, predicate) {
|
1452
|
+
for (let i = 0; i < render.length; i++) {
|
1453
|
+
if (predicate(render.getChild(i))) {
|
1454
|
+
return render.getChild(i);
|
1455
|
+
}
|
1456
|
+
}
|
1457
|
+
return null;
|
1458
|
+
}
|
1459
|
+
static getDataElement(ele) {
|
1460
|
+
return this.getParent(ele, item => item instanceof DataElementInlineGroup);
|
1461
|
+
}
|
1462
|
+
}
|
1463
|
+
//# sourceMappingURL=element-util.js.map
|