@leafer/layouter 1.0.0-alpha.9 → 1.0.0-beta
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/package.json +8 -8
- package/src/LayoutBlockData.ts +2 -11
- package/src/Layouter.ts +104 -79
- package/src/LayouterHelper.ts +5 -5
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@leafer/layouter",
|
|
3
|
-
"version": "1.0.0-
|
|
3
|
+
"version": "1.0.0-beta",
|
|
4
4
|
"description": "@leafer/canvas",
|
|
5
5
|
"author": "Chao (Leafer) Wan",
|
|
6
6
|
"license": "MIT",
|
|
@@ -19,14 +19,14 @@
|
|
|
19
19
|
"leaferjs"
|
|
20
20
|
],
|
|
21
21
|
"dependencies": {
|
|
22
|
-
"@leafer/event": "1.0.0-
|
|
23
|
-
"@leafer/math": "1.0.0-
|
|
24
|
-
"@leafer/list": "1.0.0-
|
|
25
|
-
"@leafer/data": "1.0.0-
|
|
26
|
-
"@leafer/helper": "1.0.0-
|
|
27
|
-
"@leafer/debug": "1.0.0-
|
|
22
|
+
"@leafer/event": "1.0.0-beta",
|
|
23
|
+
"@leafer/math": "1.0.0-beta",
|
|
24
|
+
"@leafer/list": "1.0.0-beta",
|
|
25
|
+
"@leafer/data": "1.0.0-beta",
|
|
26
|
+
"@leafer/helper": "1.0.0-beta",
|
|
27
|
+
"@leafer/debug": "1.0.0-beta"
|
|
28
28
|
},
|
|
29
29
|
"devDependencies": {
|
|
30
|
-
"@leafer/interface": "1.0.0-
|
|
30
|
+
"@leafer/interface": "1.0.0-beta"
|
|
31
31
|
}
|
|
32
32
|
}
|
package/src/LayoutBlockData.ts
CHANGED
|
@@ -26,7 +26,7 @@ export class LayoutBlockData implements ILayoutBlockData {
|
|
|
26
26
|
|
|
27
27
|
public setAfter(): void {
|
|
28
28
|
setByListWithHandle(this.afterBounds, this.updatedList.list, worldBounds)
|
|
29
|
-
this.
|
|
29
|
+
this.updatedBounds.setByList([this.beforeBounds, this.afterBounds])
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
public merge(data: ILayoutBlockData): void {
|
|
@@ -36,17 +36,8 @@ export class LayoutBlockData implements ILayoutBlockData {
|
|
|
36
36
|
this.updatedBounds.add(data.updatedBounds)
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
-
protected __computeChange(): void {
|
|
40
|
-
const { updatedBounds: changedBounds } = this
|
|
41
|
-
changedBounds.setByList([this.beforeBounds, this.afterBounds])
|
|
42
|
-
if (!changedBounds.isEmpty()) {
|
|
43
|
-
changedBounds.spread(2)
|
|
44
|
-
changedBounds.ceil()
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
|
|
48
39
|
public destroy(): void {
|
|
49
|
-
this.updatedList =
|
|
40
|
+
this.updatedList = null
|
|
50
41
|
}
|
|
51
42
|
|
|
52
43
|
}
|
package/src/Layouter.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { ILayouter, ILeaf, ILayoutBlockData, IEventListenerId, ILayouterConfig, ILeafList } from '@leafer/interface'
|
|
2
|
-
import { LayoutEvent,
|
|
2
|
+
import { LayoutEvent, WatchEvent } from '@leafer/event'
|
|
3
3
|
import { LeafLevelList, LeafList } from '@leafer/list'
|
|
4
4
|
import { BranchHelper, LeafHelper } from '@leafer/helper'
|
|
5
5
|
import { DataHelper } from '@leafer/data'
|
|
6
|
-
import { Run } from '@leafer/debug'
|
|
6
|
+
import { Run, Debug } from '@leafer/debug'
|
|
7
7
|
|
|
8
8
|
import { updateBounds, updateMatrix, updateChange } from './LayouterHelper'
|
|
9
9
|
import { LayoutBlockData } from './LayoutBlockData'
|
|
@@ -12,33 +12,36 @@ import { LayoutBlockData } from './LayoutBlockData'
|
|
|
12
12
|
const { updateAllWorldMatrix, updateAllChange } = LeafHelper
|
|
13
13
|
const { pushAllBranchStack, updateWorldBoundsByBranchStack } = BranchHelper
|
|
14
14
|
|
|
15
|
+
const debug = Debug.get('Layouter')
|
|
16
|
+
|
|
15
17
|
export class Layouter implements ILayouter {
|
|
16
18
|
|
|
17
19
|
public target: ILeaf
|
|
18
20
|
public layoutedBlocks: ILayoutBlockData[]
|
|
21
|
+
|
|
19
22
|
public totalTimes: number = 0
|
|
20
23
|
public times: number
|
|
21
|
-
public changed: boolean = true
|
|
22
|
-
|
|
23
|
-
public config: ILayouterConfig = {
|
|
24
|
-
partLayout: {
|
|
25
|
-
maxTimes: 3
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
24
|
|
|
25
|
+
public disabled: boolean
|
|
29
26
|
public running: boolean
|
|
27
|
+
public layouting: boolean
|
|
28
|
+
|
|
29
|
+
public waitAgain: boolean
|
|
30
30
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
protected
|
|
31
|
+
public config: ILayouterConfig = {}
|
|
32
|
+
|
|
33
|
+
protected __updateList: ILeafList
|
|
34
|
+
protected __levelList: LeafLevelList = new LeafLevelList()
|
|
35
|
+
protected __eventIds: IEventListenerId[]
|
|
34
36
|
|
|
35
37
|
constructor(target: ILeaf, userConfig?: ILayouterConfig) {
|
|
36
38
|
this.target = target
|
|
37
39
|
if (userConfig) this.config = DataHelper.default(userConfig, this.config)
|
|
38
|
-
this.
|
|
40
|
+
this.__listenEvents()
|
|
39
41
|
}
|
|
40
42
|
|
|
41
43
|
public start(): void {
|
|
44
|
+
if (this.disabled) return
|
|
42
45
|
this.running = true
|
|
43
46
|
}
|
|
44
47
|
|
|
@@ -46,107 +49,125 @@ export class Layouter implements ILayouter {
|
|
|
46
49
|
this.running = false
|
|
47
50
|
}
|
|
48
51
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
this.
|
|
52
|
-
|
|
53
|
-
target.on__(LayoutEvent.AGAIN, this.layoutOnce, this),
|
|
54
|
-
target.on__(WatchEvent.DATA, this.onReceiveWatchData, this),
|
|
55
|
-
target.on__(RenderEvent.REQUEST, this.onChange, this),
|
|
56
|
-
]
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
protected removeListenEvents(): void {
|
|
60
|
-
this.target.off__(this.eventIds)
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
protected onReceiveWatchData(event: WatchEvent): void {
|
|
64
|
-
this.updateList = event.data.updatedList
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
protected onChange(): void {
|
|
68
|
-
this.changed = true
|
|
52
|
+
public disable(): void {
|
|
53
|
+
this.stop()
|
|
54
|
+
this.__removeListenEvents()
|
|
55
|
+
this.disabled = true
|
|
69
56
|
}
|
|
70
57
|
|
|
71
58
|
public layout(): void {
|
|
72
59
|
if (!this.running) return
|
|
73
60
|
const { target } = this
|
|
74
|
-
const { START, LAYOUT, END } = LayoutEvent
|
|
75
61
|
this.times = 0
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
62
|
+
|
|
63
|
+
try {
|
|
64
|
+
target.emit(LayoutEvent.START)
|
|
65
|
+
this.layoutOnce()
|
|
66
|
+
target.emitEvent(new LayoutEvent(LayoutEvent.END, this.layoutedBlocks, this.times))
|
|
67
|
+
} catch (e) {
|
|
68
|
+
debug.error(e)
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
this.layoutedBlocks = null
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
public layoutAgain(): void {
|
|
75
|
+
if (this.layouting) {
|
|
76
|
+
this.waitAgain = true
|
|
77
|
+
} else {
|
|
78
|
+
this.layoutOnce()
|
|
79
|
+
}
|
|
82
80
|
}
|
|
83
81
|
|
|
84
82
|
public layoutOnce(): void {
|
|
85
83
|
|
|
86
|
-
this.
|
|
84
|
+
if (this.layouting) return debug.warn('layouting')
|
|
85
|
+
if (this.times > 3) return debug.warn('layout max times')
|
|
86
|
+
|
|
87
87
|
this.times++
|
|
88
|
+
this.totalTimes++
|
|
89
|
+
|
|
90
|
+
this.layouting = true
|
|
88
91
|
|
|
89
92
|
this.target.emit(WatchEvent.REQUEST)
|
|
93
|
+
|
|
90
94
|
if (this.totalTimes > 1) {
|
|
91
95
|
this.partLayout()
|
|
92
96
|
} else {
|
|
93
97
|
this.fullLayout()
|
|
94
98
|
}
|
|
99
|
+
|
|
100
|
+
this.layouting = false
|
|
101
|
+
|
|
102
|
+
if (this.waitAgain) {
|
|
103
|
+
this.waitAgain = false
|
|
104
|
+
this.layoutOnce()
|
|
105
|
+
}
|
|
106
|
+
|
|
95
107
|
}
|
|
96
108
|
|
|
97
109
|
public partLayout(): void {
|
|
98
|
-
if (!this.
|
|
110
|
+
if (!this.__updateList?.length) return
|
|
99
111
|
|
|
100
|
-
const t = Run.start('
|
|
101
|
-
const { target, updateList } = this
|
|
102
|
-
const {
|
|
112
|
+
const t = Run.start('PartLayout')
|
|
113
|
+
const { target, __updateList: updateList } = this
|
|
114
|
+
const { BEFORE, LAYOUT, AFTER } = LayoutEvent
|
|
103
115
|
|
|
104
116
|
const blocks = this.getBlocks(updateList)
|
|
105
117
|
blocks.forEach(item => { item.setBefore() })
|
|
106
|
-
target.emitEvent(new LayoutEvent(
|
|
118
|
+
target.emitEvent(new LayoutEvent(BEFORE, blocks, this.times))
|
|
107
119
|
|
|
108
120
|
updateList.sort()
|
|
109
|
-
updateMatrix(updateList, this.
|
|
110
|
-
updateBounds(this.
|
|
121
|
+
updateMatrix(updateList, this.__levelList)
|
|
122
|
+
updateBounds(this.__levelList)
|
|
111
123
|
updateChange(updateList)
|
|
112
124
|
|
|
113
|
-
blocks.forEach(item =>
|
|
114
|
-
|
|
115
|
-
target.emitEvent(new LayoutEvent(
|
|
125
|
+
blocks.forEach(item => item.setAfter())
|
|
126
|
+
|
|
127
|
+
target.emitEvent(new LayoutEvent(LAYOUT, blocks, this.times))
|
|
128
|
+
target.emitEvent(new LayoutEvent(AFTER, blocks, this.times))
|
|
116
129
|
|
|
117
|
-
this.
|
|
130
|
+
this.addBlocks(blocks)
|
|
118
131
|
|
|
119
|
-
this.
|
|
120
|
-
this.
|
|
132
|
+
this.__levelList.reset()
|
|
133
|
+
this.__updateList = null
|
|
121
134
|
Run.end(t)
|
|
122
135
|
|
|
123
|
-
this.__checkAgain()
|
|
124
136
|
}
|
|
125
137
|
|
|
126
138
|
public fullLayout(): void {
|
|
127
|
-
const t = Run.start('
|
|
139
|
+
const t = Run.start('FullLayout')
|
|
128
140
|
|
|
129
141
|
const { target } = this
|
|
130
|
-
const {
|
|
142
|
+
const { BEFORE, LAYOUT, AFTER } = LayoutEvent
|
|
131
143
|
|
|
132
144
|
const blocks = this.getBlocks(new LeafList(target))
|
|
133
|
-
target.emitEvent(new LayoutEvent(
|
|
145
|
+
target.emitEvent(new LayoutEvent(BEFORE, blocks, this.times))
|
|
134
146
|
|
|
135
147
|
Layouter.fullLayout(target)
|
|
136
148
|
|
|
137
149
|
blocks.forEach(item => { item.setAfter() })
|
|
138
|
-
target.emitEvent(new LayoutEvent(
|
|
139
|
-
target.emitEvent(new LayoutEvent(
|
|
150
|
+
target.emitEvent(new LayoutEvent(LAYOUT, blocks, this.times))
|
|
151
|
+
target.emitEvent(new LayoutEvent(AFTER, blocks, this.times))
|
|
140
152
|
|
|
141
|
-
this.
|
|
153
|
+
this.addBlocks(blocks)
|
|
142
154
|
|
|
143
155
|
Run.end(t)
|
|
144
156
|
|
|
145
|
-
this.__checkAgain()
|
|
146
157
|
}
|
|
147
158
|
|
|
148
|
-
|
|
149
|
-
|
|
159
|
+
static fullLayout(target: ILeaf): void {
|
|
160
|
+
updateAllWorldMatrix(target)
|
|
161
|
+
|
|
162
|
+
if (target.isBranch) {
|
|
163
|
+
const branchStack: ILeaf[] = [target]
|
|
164
|
+
pushAllBranchStack(target, branchStack)
|
|
165
|
+
updateWorldBoundsByBranchStack(branchStack)
|
|
166
|
+
} else {
|
|
167
|
+
target.__updateWorldBounds()
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
updateAllChange(target)
|
|
150
171
|
}
|
|
151
172
|
|
|
152
173
|
|
|
@@ -158,29 +179,33 @@ export class Layouter implements ILayouter {
|
|
|
158
179
|
return [this.createBlock(list)]
|
|
159
180
|
}
|
|
160
181
|
|
|
161
|
-
public
|
|
182
|
+
public addBlocks(current: ILayoutBlockData[]) {
|
|
162
183
|
this.layoutedBlocks ? this.layoutedBlocks.push(...current) : this.layoutedBlocks = current
|
|
163
184
|
}
|
|
164
185
|
|
|
186
|
+
protected __onReceiveWatchData(event: WatchEvent): void {
|
|
187
|
+
this.__updateList = event.data.updatedList
|
|
188
|
+
}
|
|
165
189
|
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
target.__updateWorldBounds()
|
|
175
|
-
}
|
|
190
|
+
protected __listenEvents(): void {
|
|
191
|
+
const { target } = this
|
|
192
|
+
this.__eventIds = [
|
|
193
|
+
target.on_(LayoutEvent.REQUEST, this.layout, this),
|
|
194
|
+
target.on_(LayoutEvent.AGAIN, this.layoutAgain, this),
|
|
195
|
+
target.on_(WatchEvent.DATA, this.__onReceiveWatchData, this)
|
|
196
|
+
]
|
|
197
|
+
}
|
|
176
198
|
|
|
177
|
-
|
|
199
|
+
protected __removeListenEvents(): void {
|
|
200
|
+
this.target.off_(this.__eventIds)
|
|
178
201
|
}
|
|
179
202
|
|
|
180
|
-
destroy(): void {
|
|
203
|
+
public destroy(): void {
|
|
181
204
|
if (this.target) {
|
|
182
|
-
this.
|
|
183
|
-
this.
|
|
205
|
+
this.stop()
|
|
206
|
+
this.__removeListenEvents()
|
|
207
|
+
this.target = null
|
|
208
|
+
this.config = null
|
|
184
209
|
}
|
|
185
210
|
}
|
|
186
211
|
|
package/src/LayouterHelper.ts
CHANGED
|
@@ -11,20 +11,20 @@ export function updateMatrix(updateList: ILeafList, levelList: ILeafLevelList):
|
|
|
11
11
|
let layout: ILeafLayout
|
|
12
12
|
updateList.list.forEach(leaf => { // 更新矩阵, 所有子元素,和父元素都需要更新bounds
|
|
13
13
|
layout = leaf.__layout
|
|
14
|
-
if (levelList.without(leaf)) { // 防止重复, 子元素可能已经被父元素更新过
|
|
14
|
+
if (levelList.without(leaf) && !layout.useZoomProxy) { // 防止重复, 子元素可能已经被父元素更新过
|
|
15
15
|
|
|
16
16
|
if (layout.matrixChanged) {
|
|
17
17
|
|
|
18
18
|
updateAllWorldMatrix(leaf)
|
|
19
19
|
|
|
20
20
|
levelList.push(leaf)
|
|
21
|
-
if (leaf.
|
|
21
|
+
if (leaf.isBranch) pushAllChildBranch(leaf, levelList)
|
|
22
22
|
pushAllParent(leaf, levelList)
|
|
23
23
|
|
|
24
24
|
} else if (layout.boundsChanged) {
|
|
25
25
|
|
|
26
26
|
levelList.push(leaf)
|
|
27
|
-
if (leaf.
|
|
27
|
+
if (leaf.isBranch) leaf.__tempNumber = 0 // 标识需要更新子Leaf元素的WorldBounds分支, 0表示不需要更新
|
|
28
28
|
pushAllParent(leaf, levelList)
|
|
29
29
|
}
|
|
30
30
|
}
|
|
@@ -43,9 +43,9 @@ export function updateBounds(boundsList: ILeafLevelList): void {
|
|
|
43
43
|
branch = itemList[i]
|
|
44
44
|
|
|
45
45
|
// 标识了需要更新子元素
|
|
46
|
-
if (branch.
|
|
46
|
+
if (branch.isBranch && branch.__tempNumber) {
|
|
47
47
|
for (let j = 0, jLen = branch.children.length; j < jLen; j++) {
|
|
48
|
-
if (!branch.children[j].
|
|
48
|
+
if (!branch.children[j].isBranch) {
|
|
49
49
|
branch.children[j].__updateWorldBounds()
|
|
50
50
|
}
|
|
51
51
|
}
|