@leafer/layouter 1.0.0-alpha.7 → 1.0.0-bate

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@leafer/layouter",
3
- "version": "1.0.0-alpha.7",
3
+ "version": "1.0.0-bate",
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-alpha.7",
23
- "@leafer/math": "1.0.0-alpha.7",
24
- "@leafer/list": "1.0.0-alpha.7",
25
- "@leafer/data": "1.0.0-alpha.7",
26
- "@leafer/helper": "1.0.0-alpha.7",
27
- "@leafer/debug": "1.0.0-alpha.7"
22
+ "@leafer/event": "1.0.0-bate",
23
+ "@leafer/math": "1.0.0-bate",
24
+ "@leafer/list": "1.0.0-bate",
25
+ "@leafer/data": "1.0.0-bate",
26
+ "@leafer/helper": "1.0.0-bate",
27
+ "@leafer/debug": "1.0.0-bate"
28
28
  },
29
29
  "devDependencies": {
30
- "@leafer/interface": "1.0.0-alpha.7"
30
+ "@leafer/interface": "1.0.0-bate"
31
31
  }
32
32
  }
@@ -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.__computeChange()
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 = undefined
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, RenderEvent, WatchEvent } from '@leafer/event'
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
- protected updateList: ILeafList
32
- protected levelList: LeafLevelList = new LeafLevelList()
33
- protected eventIds: IEventListenerId[]
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.listenEvents()
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
- protected listenEvents(): void {
50
- const { target } = this
51
- this.eventIds = [
52
- target.on__(LayoutEvent.REQUEST, this.layout, this),
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
- this.changed = false
77
- target.emit(START)
78
- this.layoutOnce()
79
- target.emitEvent(new LayoutEvent(LAYOUT, this.layoutedBlocks))
80
- target.emitEvent(new LayoutEvent(END, this.layoutedBlocks))
81
- this.layoutedBlocks = undefined
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.totalTimes++
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.updateList?.length) return
110
+ if (!this.__updateList?.length) return
99
111
 
100
- const t = Run.start('part layout')
101
- const { target, updateList } = this
102
- const { BEFORE_ONCE, ONCE, AFTER_ONCE } = LayoutEvent
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(BEFORE_ONCE, blocks))
118
+ target.emitEvent(new LayoutEvent(BEFORE, blocks, this.times))
107
119
 
108
120
  updateList.sort()
109
- updateMatrix(updateList, this.levelList)
110
- updateBounds(this.levelList)
121
+ updateMatrix(updateList, this.__levelList)
122
+ updateBounds(this.__levelList)
111
123
  updateChange(updateList)
112
124
 
113
- blocks.forEach(item => { item.setAfter() })
114
- target.emitEvent(new LayoutEvent(ONCE, blocks))
115
- target.emitEvent(new LayoutEvent(AFTER_ONCE, blocks))
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.setBlocks(blocks)
130
+ this.addBlocks(blocks)
118
131
 
119
- this.levelList.reset()
120
- this.updateList = undefined
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('full layout')
139
+ const t = Run.start('FullLayout')
128
140
 
129
141
  const { target } = this
130
- const { BEFORE_ONCE, ONCE, AFTER_ONCE } = LayoutEvent
142
+ const { BEFORE, LAYOUT, AFTER } = LayoutEvent
131
143
 
132
144
  const blocks = this.getBlocks(new LeafList(target))
133
- target.emitEvent(new LayoutEvent(BEFORE_ONCE, blocks))
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(ONCE, blocks))
139
- target.emitEvent(new LayoutEvent(AFTER_ONCE, blocks))
150
+ target.emitEvent(new LayoutEvent(LAYOUT, blocks, this.times))
151
+ target.emitEvent(new LayoutEvent(AFTER, blocks, this.times))
140
152
 
141
- this.setBlocks(blocks)
153
+ this.addBlocks(blocks)
142
154
 
143
155
  Run.end(t)
144
156
 
145
- this.__checkAgain()
146
157
  }
147
158
 
148
- protected __checkAgain(): void {
149
- if (this.changed && this.times <= this.config.partLayout.maxTimes) this.target.emit(LayoutEvent.AGAIN) // 防止更新布局过程中产生了属性修改
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 setBlocks(current: ILayoutBlockData[]) {
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
- static fullLayout(target: ILeaf): void {
167
- updateAllWorldMatrix(target)
168
-
169
- if (target.__isBranch) {
170
- const branchStack: ILeaf[] = [target]
171
- pushAllBranchStack(target, branchStack)
172
- updateWorldBoundsByBranchStack(branchStack)
173
- } else {
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
- updateAllChange(target)
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.removeListenEvents()
183
- this.target = undefined
205
+ this.stop()
206
+ this.__removeListenEvents()
207
+ this.target = null
208
+ this.config = null
184
209
  }
185
210
  }
186
211
 
@@ -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.__isBranch) pushAllChildBranch(leaf, levelList)
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.__isBranch) leaf.__tempNumber = 0 // 标识需要更新子Leaf元素的WorldBounds分支, 0表示不需要更新
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.__isBranch && branch.__tempNumber) {
46
+ if (branch.isBranch && branch.__tempNumber) {
47
47
  for (let j = 0, jLen = branch.children.length; j < jLen; j++) {
48
- if (!branch.children[j].__isBranch) {
48
+ if (!branch.children[j].isBranch) {
49
49
  branch.children[j].__updateWorldBounds()
50
50
  }
51
51
  }