@shijiu/jsview-vue 2.0.1021 → 2.0.1073
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 +4 -3
- package/utils/JsViewEngineWidget/CheckType.js +82 -0
- package/utils/JsViewEngineWidget/MetroWidget/AnimationManager.ts +72 -0
- package/utils/JsViewEngineWidget/MetroWidget/Const.ts +24 -0
- package/utils/JsViewEngineWidget/MetroWidget/ListWidget.vue +295 -0
- package/utils/JsViewEngineWidget/MetroWidget/MetroWidget.vue +110 -1651
- package/utils/JsViewEngineWidget/MetroWidget/MetroWidgetSetup.js +1867 -0
- package/utils/JsViewEngineWidget/MetroWidget/PageUpdater.ts +111 -0
- package/utils/JsViewEngineWidget/MetroWidget/RenderItem.ts +153 -0
- package/utils/JsViewEngineWidget/MetroWidget/VisibleInfo.ts +43 -0
- package/utils/JsViewEngineWidget/MetroWidget/WidgetRectInfo.ts +49 -0
- package/utils/JsViewEngineWidget/TemplateParser/CommonMetroTemplate.ts +1424 -0
- package/utils/JsViewEngineWidget/TemplateParser/Fence.ts +135 -0
- package/utils/JsViewEngineWidget/TemplateParser/ListMetroTemplate.ts +177 -0
- package/utils/JsViewEngineWidget/TemplateParser/MetroTemplate.ts +334 -0
- package/utils/JsViewEngineWidget/TemplateParser/TemplateItemAdder.ts +147 -0
- package/utils/JsViewEngineWidget/TemplateParser/index.ts +4 -0
- package/utils/JsViewEngineWidget/{WidgetCommon.js → WidgetCommon.ts} +64 -71
- package/utils/JsViewEngineWidget/index.js +2 -1
- package/utils/JsViewPlugin/JsvAudio/AudioProxy.js +26 -1
- package/utils/JsViewPlugin/JsvAudio/JsvAudio.vue +120 -133
- package/utils/JsViewPlugin/JsvAudio/JsvAudioBrowser.vue +11 -7
- package/utils/JsViewPlugin/JsvPlayer/GetVersion.js +1 -1
- package/utils/JsViewPlugin/JsvPlayer/JsvPlayerBrowser.vue +379 -41
- package/utils/JsViewPlugin/JsvPlayer/version.mjs +5 -5
- package/utils/JsViewVueTools/JsvHashHistory.js +2 -1
- package/utils/JsViewVueWidget/JsvRadarChart.vue +220 -0
- package/utils/JsViewVueWidget/JsvSystemAudio.vue +76 -44
- package/utils/JsViewVueWidget/index.js +1 -0
- package/utils/JsViewEngineWidget/MetroWidget/Const.js +0 -11
- package/utils/JsViewEngineWidget/MetroWidget/PageUpdater.js +0 -136
- package/utils/JsViewEngineWidget/MetroWidget/ToolFunctions.js +0 -18
- package/utils/JsViewEngineWidget/TemplateParser.js +0 -2004
|
@@ -0,0 +1,1424 @@
|
|
|
1
|
+
import { Fence, GapInfo } from "./Fence";
|
|
2
|
+
import { MetroTemplate, TemplateItem, MeasureInfo } from "./MetroTemplate"
|
|
3
|
+
import { RangesModel, SingleRangeModel } from "../RangeModel";
|
|
4
|
+
import { VERTICAL, HORIZONTAL, FocusMoveType } from "../WidgetCommon";
|
|
5
|
+
|
|
6
|
+
const TAG = "CommonTemplateParser";
|
|
7
|
+
|
|
8
|
+
/** neighbor related interface */
|
|
9
|
+
interface Edge {
|
|
10
|
+
position: number,
|
|
11
|
+
range: RangesModel,
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
interface EdgeInfo {
|
|
15
|
+
index: number,
|
|
16
|
+
edgeObj: {
|
|
17
|
+
leftEdge: Edge | null,
|
|
18
|
+
rightEdge: Edge | null,
|
|
19
|
+
topEdge: Edge | null,
|
|
20
|
+
bottomEdge: Edge | null,
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/** get visible list related interface */
|
|
25
|
+
interface VisibleSearchConfigCommon {
|
|
26
|
+
resultStartIdx: number,
|
|
27
|
+
resultEndIdx: number,
|
|
28
|
+
enableBackwardSearching: boolean,
|
|
29
|
+
enableForwardSearching: boolean,
|
|
30
|
+
checkingStartLinePos: number,
|
|
31
|
+
checkingEndLinePos: number,
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
interface VisibleSearchConfig {
|
|
35
|
+
searchDirect: number;
|
|
36
|
+
baseIdx: number;
|
|
37
|
+
checkingStartLineRanges: RangesModel;
|
|
38
|
+
startLineRangesFulled: boolean;
|
|
39
|
+
latestOverStartLineIdx: number;
|
|
40
|
+
checkingEndLineRanges: RangesModel;
|
|
41
|
+
endLineRangesFulled: boolean;
|
|
42
|
+
latestOverEndLineIdx: number;
|
|
43
|
+
endSearchingIndex: number;
|
|
44
|
+
firstStartLineBlockIdx: number;
|
|
45
|
+
firstEndLineBlockIdx: number;
|
|
46
|
+
searchToBorder: boolean;
|
|
47
|
+
common: VisibleSearchConfigCommon;
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
class CommonMetroTemplate extends MetroTemplate {
|
|
51
|
+
private _FenceStack: Array<Fence>;
|
|
52
|
+
private _FenceEdge: { StartX: number, StartY: number };
|
|
53
|
+
private _NotOccupiedEdgeList: Array<EdgeInfo>;
|
|
54
|
+
|
|
55
|
+
constructor(direction: Symbol, lineMax: number, pageSize: number,
|
|
56
|
+
layoutType: string, supportHistoryPath: boolean) {
|
|
57
|
+
super(direction, lineMax, pageSize, layoutType, supportHistoryPath);
|
|
58
|
+
this._FenceStack = [new Fence(0, 0, this.lineMax, 0)];
|
|
59
|
+
this._FenceEdge = { StartX: 0, StartY: 0 }; // 新的未占用边列表生成
|
|
60
|
+
this._NotOccupiedEdgeList = []; // 未占用边列表
|
|
61
|
+
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
public calculateNeighborWhenAddStop(): void {
|
|
65
|
+
// Update Last Fence Edge(更新最后一行的fence edge)
|
|
66
|
+
this._UpdateLastFenceEdge();
|
|
67
|
+
// Last fence edge to get neighbor
|
|
68
|
+
this._CalculateNeighborItem();
|
|
69
|
+
this._CalculateNeighborItem(true);
|
|
70
|
+
const templateList = this.templateList;
|
|
71
|
+
//处理找到的neighbor均是占位符的情况
|
|
72
|
+
for (let j = templateList.length - 1; j >= 0; j--) {
|
|
73
|
+
const item = templateList[j];
|
|
74
|
+
if (item.focusable) {
|
|
75
|
+
this._FindFocusableNeighbor("bottom", item);
|
|
76
|
+
this._FindFocusableNeighbor("top", item);
|
|
77
|
+
this._FindFocusableNeighbor("left", item);
|
|
78
|
+
this._FindFocusableNeighbor("right", item);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
private _UpdateLastFenceEdge() {
|
|
84
|
+
const oldFence = this._FenceEdge;
|
|
85
|
+
const newMinFence = { StartX: -1, StartY: -1 };
|
|
86
|
+
// 查找最后一条FenceEdge
|
|
87
|
+
for (let i = 0; i < this._NotOccupiedEdgeList.length; i++) {
|
|
88
|
+
const crossItem = this._NotOccupiedEdgeList[i];
|
|
89
|
+
const crossEdgeObj = crossItem.edgeObj;
|
|
90
|
+
if (this.direction === VERTICAL) {
|
|
91
|
+
if (crossEdgeObj.bottomEdge !== null) {
|
|
92
|
+
if (crossEdgeObj.bottomEdge.position > oldFence.StartY) {
|
|
93
|
+
if (newMinFence.StartY === -1) {
|
|
94
|
+
newMinFence.StartY = crossEdgeObj.bottomEdge.position;
|
|
95
|
+
} else if (crossEdgeObj.bottomEdge.position < newMinFence.StartY) {
|
|
96
|
+
newMinFence.StartY = crossEdgeObj.bottomEdge.position;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
} else {
|
|
101
|
+
if (crossEdgeObj.rightEdge !== null) {
|
|
102
|
+
if (crossEdgeObj.rightEdge.position > oldFence.StartX) {
|
|
103
|
+
if (newMinFence.StartX === -1) {
|
|
104
|
+
newMinFence.StartX = crossEdgeObj.rightEdge.position;
|
|
105
|
+
} else if (crossEdgeObj.rightEdge.position < newMinFence.StartX) {
|
|
106
|
+
newMinFence.StartX = crossEdgeObj.rightEdge.position;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
this._FenceEdge = newMinFence;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
private _CheckIdsHasFocusable(ids: Array<number>) {
|
|
117
|
+
const templateList = this.templateList;
|
|
118
|
+
let found = false;
|
|
119
|
+
for (let i = 0; i < ids.length; i++) {
|
|
120
|
+
const id = ids[i];
|
|
121
|
+
if (templateList[id].focusable) {
|
|
122
|
+
found = true;
|
|
123
|
+
break;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
return found;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
private _GetValidNeighborIndex(srcItemId: number, lastItemId: number, neighborDirection: string) {
|
|
131
|
+
const templateList = this.templateList;
|
|
132
|
+
let validId = -1;
|
|
133
|
+
const item = templateList[lastItemId];
|
|
134
|
+
const srcItem = templateList[srcItemId];
|
|
135
|
+
let firstIds: Array<number>;
|
|
136
|
+
let secondIds: Array<number>;
|
|
137
|
+
|
|
138
|
+
if (neighborDirection === "top") {
|
|
139
|
+
// 查找左侧邻居节点
|
|
140
|
+
secondIds = item.neighborIndexList.left;
|
|
141
|
+
firstIds = item.neighborIndexList.right;
|
|
142
|
+
} else {
|
|
143
|
+
// left, right
|
|
144
|
+
secondIds = item.neighborIndexList.right;
|
|
145
|
+
firstIds = item.neighborIndexList.left;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
if (firstIds.length > 0) {
|
|
149
|
+
for (let i = 0; i < firstIds.length; i++) {
|
|
150
|
+
const id = firstIds[i];
|
|
151
|
+
const checkItem = templateList[id];
|
|
152
|
+
if (
|
|
153
|
+
checkItem.focusable &&
|
|
154
|
+
((neighborDirection === "top" &&
|
|
155
|
+
checkItem.top + checkItem.height <= srcItem.top) ||
|
|
156
|
+
(neighborDirection === "bottom" &&
|
|
157
|
+
checkItem.top >= srcItem.top + srcItem.height))
|
|
158
|
+
) {
|
|
159
|
+
// 并且在srcItemId之上或之下
|
|
160
|
+
validId = id;
|
|
161
|
+
break;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
if (validId === -1) {
|
|
166
|
+
if (secondIds.length > 0) {
|
|
167
|
+
for (let i = 0; i < secondIds.length; i++) {
|
|
168
|
+
const id = secondIds[i];
|
|
169
|
+
const checkItem = templateList[id];
|
|
170
|
+
if (
|
|
171
|
+
checkItem.focusable &&
|
|
172
|
+
((neighborDirection === "top" &&
|
|
173
|
+
checkItem.top + checkItem.height <= srcItem.top) ||
|
|
174
|
+
(neighborDirection === "bottom" &&
|
|
175
|
+
checkItem.top >= srcItem.top + srcItem.height))
|
|
176
|
+
) {
|
|
177
|
+
// 并且在srcItemId之上或之下
|
|
178
|
+
validId = id;
|
|
179
|
+
break;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
return validId;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
private _FindFocusableNeighbor(direction: string, item: TemplateItem) {
|
|
188
|
+
if (
|
|
189
|
+
item.neighborIndexList[direction].length > 0 &&
|
|
190
|
+
!this._CheckIdsHasFocusable(item.neighborIndexList[direction])
|
|
191
|
+
) {
|
|
192
|
+
const lastItemId =
|
|
193
|
+
item.neighborIndexList[direction][
|
|
194
|
+
item.neighborIndexList[direction].length - 1
|
|
195
|
+
];
|
|
196
|
+
const idx = this._GetValidNeighborIndex(item.id, lastItemId, direction); // 查找其左右邻居
|
|
197
|
+
if (idx !== -1) {
|
|
198
|
+
item.neighborIndexList[direction] = []; // 清除无效项
|
|
199
|
+
item.neighborIndexList[direction].push(idx);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
public addItem(itemObj: MeasureInfo): TemplateItem {
|
|
205
|
+
const templateItem = MetroTemplate.getTemplateItem(itemObj);
|
|
206
|
+
// Layout template items
|
|
207
|
+
const fenceStack = this._FenceStack;
|
|
208
|
+
const itemWidth = templateItem.width;
|
|
209
|
+
const itemHeight = templateItem.height;
|
|
210
|
+
// Add view to contents view layer
|
|
211
|
+
let xPos: number;
|
|
212
|
+
let yPos: number;
|
|
213
|
+
let xWidth: number;
|
|
214
|
+
let yWidth: number;
|
|
215
|
+
let itemKeyPos = 0;
|
|
216
|
+
let itemSecondPos = 0;
|
|
217
|
+
|
|
218
|
+
let itemKeyWidth = 0;
|
|
219
|
+
let itemSecondWidth = 0;
|
|
220
|
+
let itemKeyMargin = 0;
|
|
221
|
+
let itemSecondMargin = 0;
|
|
222
|
+
if (this.layoutType === "relative") {
|
|
223
|
+
if (this.direction === VERTICAL) {
|
|
224
|
+
itemKeyWidth = itemWidth;
|
|
225
|
+
itemSecondWidth = itemHeight;
|
|
226
|
+
itemKeyMargin = templateItem.marginRight;
|
|
227
|
+
itemSecondMargin = templateItem.marginBottom;
|
|
228
|
+
} else {
|
|
229
|
+
itemKeyWidth = itemHeight;
|
|
230
|
+
itemSecondWidth = itemWidth;
|
|
231
|
+
itemKeyMargin = templateItem.marginBottom;
|
|
232
|
+
itemSecondMargin = templateItem.marginRight;
|
|
233
|
+
}
|
|
234
|
+
// Find capability fence in stack
|
|
235
|
+
let topFence: Fence | null = null;
|
|
236
|
+
let gapInfo: GapInfo | null = null;
|
|
237
|
+
while (fenceStack.length > 0) {
|
|
238
|
+
const checkingFence = fenceStack[fenceStack.length - 1];
|
|
239
|
+
gapInfo = checkingFence.HasGapFor(itemKeyWidth + itemKeyMargin);
|
|
240
|
+
if (gapInfo !== null) {
|
|
241
|
+
topFence = checkingFence;
|
|
242
|
+
break;
|
|
243
|
+
}
|
|
244
|
+
fenceStack.pop();
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
// Layout the item in top fence
|
|
248
|
+
if (gapInfo !== null && topFence != null) {
|
|
249
|
+
itemKeyPos = gapInfo.GapStart;
|
|
250
|
+
itemSecondPos = topFence.AheadOffset;
|
|
251
|
+
} else {
|
|
252
|
+
throw new Error(
|
|
253
|
+
`${TAG} item size ${itemWidth}x${itemHeight} is greater than widget line max ${this.lineMax}`
|
|
254
|
+
);
|
|
255
|
+
// console.error(TAG, "ERROR: coding error, header full gap fence lost");
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
if (this.direction === VERTICAL) {
|
|
259
|
+
xPos = itemKeyPos;
|
|
260
|
+
yPos = itemSecondPos;
|
|
261
|
+
xWidth = itemKeyWidth;
|
|
262
|
+
yWidth = itemSecondWidth;
|
|
263
|
+
} else {
|
|
264
|
+
xPos = itemSecondPos;
|
|
265
|
+
yPos = itemKeyPos;
|
|
266
|
+
xWidth = itemSecondWidth;
|
|
267
|
+
yWidth = itemKeyWidth;
|
|
268
|
+
}
|
|
269
|
+
} else {
|
|
270
|
+
xPos = templateItem.left;
|
|
271
|
+
yPos = templateItem.top;
|
|
272
|
+
xWidth = itemWidth;
|
|
273
|
+
yWidth = itemHeight;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
templateItem.left = xPos;
|
|
277
|
+
templateItem.top = yPos;
|
|
278
|
+
templateItem.centerXPos = Math.floor(xPos + xWidth / 2) - 1;
|
|
279
|
+
templateItem.centerYPos = Math.floor(yPos + yWidth / 2) - 1;
|
|
280
|
+
//分页相关的计算
|
|
281
|
+
let curPageNumber = 0;
|
|
282
|
+
let curPageHeadIndex = 0;
|
|
283
|
+
if (this.templateList.length > 0) {
|
|
284
|
+
const lastItem = this.templateList[this.templateList.length - 1];
|
|
285
|
+
curPageNumber = lastItem.pageNumber;
|
|
286
|
+
curPageHeadIndex = lastItem.pageHeadIndex;
|
|
287
|
+
let positionKey = "left";
|
|
288
|
+
let sizeKey = "width";
|
|
289
|
+
if (this.direction === VERTICAL) {
|
|
290
|
+
positionKey = "top";
|
|
291
|
+
sizeKey = "height";
|
|
292
|
+
}
|
|
293
|
+
const curPageStart =
|
|
294
|
+
this.templateList[curPageHeadIndex][positionKey];
|
|
295
|
+
if (
|
|
296
|
+
templateItem[positionKey] + templateItem[sizeKey] >
|
|
297
|
+
curPageStart + this.pageSize
|
|
298
|
+
) {
|
|
299
|
+
//新的页
|
|
300
|
+
curPageNumber++;
|
|
301
|
+
curPageHeadIndex = this.templateList.length;
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
templateItem.pageNumber = curPageNumber;
|
|
306
|
+
templateItem.pageHeadIndex = curPageHeadIndex;
|
|
307
|
+
this.addTemplateItem(templateItem);
|
|
308
|
+
// 计算相邻项
|
|
309
|
+
this._TryCalculateNeighborItem(
|
|
310
|
+
this.templateList.length - 1,
|
|
311
|
+
templateItem.left,
|
|
312
|
+
templateItem.top,
|
|
313
|
+
templateItem.width + templateItem.marginRight,
|
|
314
|
+
templateItem.height + templateItem.marginBottom
|
|
315
|
+
);
|
|
316
|
+
|
|
317
|
+
const itemSecondEndPos =
|
|
318
|
+
itemSecondPos + itemSecondWidth + itemSecondMargin - 1;
|
|
319
|
+
|
|
320
|
+
// Ensure header fence
|
|
321
|
+
if (fenceStack[0].AheadOffset <= itemSecondEndPos) {
|
|
322
|
+
// Need new header fence
|
|
323
|
+
fenceStack.splice(
|
|
324
|
+
0,
|
|
325
|
+
0,
|
|
326
|
+
new Fence(0, 0, this.lineMax, itemSecondEndPos + 1)
|
|
327
|
+
);
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
// Mark gap used in fence stack
|
|
331
|
+
let endFenceExisted = false;
|
|
332
|
+
let farAwayEndFenceExisted = false;
|
|
333
|
+
let oneAheadLastFenceIdx = -1;
|
|
334
|
+
for (let fenceIdx = fenceStack.length - 1; fenceIdx >= 0; fenceIdx--) {
|
|
335
|
+
if (fenceStack[fenceIdx].AheadOffset <= itemSecondEndPos) {
|
|
336
|
+
if (fenceStack[fenceIdx].AheadOffset === itemSecondEndPos)
|
|
337
|
+
endFenceExisted = true;
|
|
338
|
+
const leftGaps = fenceStack[fenceIdx].MarkGapUsed(
|
|
339
|
+
itemKeyPos,
|
|
340
|
+
itemKeyWidth + itemKeyMargin
|
|
341
|
+
);
|
|
342
|
+
if (leftGaps === 0) {
|
|
343
|
+
// remove fence
|
|
344
|
+
fenceStack.splice(fenceIdx, 1);
|
|
345
|
+
}
|
|
346
|
+
} else {
|
|
347
|
+
if (fenceStack[fenceIdx].AheadOffset === itemSecondEndPos + 1)
|
|
348
|
+
farAwayEndFenceExisted = true;
|
|
349
|
+
oneAheadLastFenceIdx = fenceIdx;
|
|
350
|
+
break;
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
const fenceAheadOffset = itemSecondEndPos;
|
|
355
|
+
// Create fences
|
|
356
|
+
if (!endFenceExisted) {
|
|
357
|
+
// Build fence edge which close to the beginning
|
|
358
|
+
if (oneAheadLastFenceIdx + 1 <= fenceStack.length - 1) {
|
|
359
|
+
const fence =
|
|
360
|
+
fenceStack[oneAheadLastFenceIdx + 1].Fork(fenceAheadOffset);
|
|
361
|
+
fenceStack.splice(oneAheadLastFenceIdx + 1, 0, fence);
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
if (!farAwayEndFenceExisted) {
|
|
365
|
+
// Build fence edge which far away from the beginning
|
|
366
|
+
if (oneAheadLastFenceIdx > 0) {
|
|
367
|
+
const fence = fenceStack[oneAheadLastFenceIdx].Fork(
|
|
368
|
+
fenceAheadOffset + 1
|
|
369
|
+
);
|
|
370
|
+
fenceStack.splice(oneAheadLastFenceIdx + 1, 0, fence);
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
return templateItem;
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
/** get next item functions */
|
|
377
|
+
public getNextItem(baseId: number, vOffset: number,
|
|
378
|
+
hOffset: number, moveType: number): TemplateItem | null {
|
|
379
|
+
if (vOffset === 0 && hOffset === 0)
|
|
380
|
+
console.log("GetNextItem(): offset is 0");
|
|
381
|
+
// Forge.ThrowError("GetNextItem(): offset is 0");
|
|
382
|
+
|
|
383
|
+
if (vOffset !== 0 && hOffset !== 0) {
|
|
384
|
+
console.log(
|
|
385
|
+
"GetNextItem(): not support change vertical and horizontal at the same time"
|
|
386
|
+
);
|
|
387
|
+
// Forge.ThrowError("GetNextItem(): not support change vertical and horizontal and the same time");
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
const itemIndex = this.id2Index(baseId);
|
|
391
|
+
const offset = vOffset !== 0 ? vOffset : hOffset;
|
|
392
|
+
let nextTemplateItem = this.getNextItemInner(
|
|
393
|
+
itemIndex,
|
|
394
|
+
offset,
|
|
395
|
+
vOffset !== 0
|
|
396
|
+
);
|
|
397
|
+
const isVertical = this.direction === VERTICAL;
|
|
398
|
+
|
|
399
|
+
if (nextTemplateItem === null) {
|
|
400
|
+
// 在次方向的焦点移动才会loop
|
|
401
|
+
if (
|
|
402
|
+
isVertical &&
|
|
403
|
+
moveType & FocusMoveType.ROW_LOOP &&
|
|
404
|
+
hOffset != 0
|
|
405
|
+
) {
|
|
406
|
+
nextTemplateItem = this._GetNextLoopItem(
|
|
407
|
+
itemIndex,
|
|
408
|
+
hOffset,
|
|
409
|
+
isVertical
|
|
410
|
+
);
|
|
411
|
+
} else if (
|
|
412
|
+
!isVertical &&
|
|
413
|
+
moveType & FocusMoveType.COLUMN_LOOP &&
|
|
414
|
+
vOffset != 0
|
|
415
|
+
) {
|
|
416
|
+
nextTemplateItem = this._GetNextLoopItem(
|
|
417
|
+
itemIndex,
|
|
418
|
+
vOffset,
|
|
419
|
+
isVertical
|
|
420
|
+
);
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
if (nextTemplateItem === null) {
|
|
425
|
+
// 临近行的焦点移动
|
|
426
|
+
if (
|
|
427
|
+
vOffset != 0 &&
|
|
428
|
+
moveType & FocusMoveType.ROW_FIND_NEAR
|
|
429
|
+
) {
|
|
430
|
+
nextTemplateItem = this._GetNearLineItem(itemIndex, vOffset, true);
|
|
431
|
+
} else if (
|
|
432
|
+
hOffset != 0 &&
|
|
433
|
+
moveType & FocusMoveType.COLUMN_FIND_NEAR
|
|
434
|
+
) {
|
|
435
|
+
nextTemplateItem = this._GetNearLineItem(itemIndex, hOffset, false);
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
return nextTemplateItem;
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
|
|
443
|
+
private getNextItemInner(index: number, offset: number, vertical: boolean) {
|
|
444
|
+
const templateList = this.templateList;
|
|
445
|
+
const baseItem = templateList[index];
|
|
446
|
+
let checkAnchor = -1;
|
|
447
|
+
if (baseItem.findNextAnchor) {
|
|
448
|
+
//有自定义的 anchor
|
|
449
|
+
// TODO 优化
|
|
450
|
+
if (vertical) {
|
|
451
|
+
if (offset > 0) {
|
|
452
|
+
if (baseItem.findNextAnchor.bottom) {
|
|
453
|
+
checkAnchor =
|
|
454
|
+
baseItem.left +
|
|
455
|
+
baseItem.findNextAnchor.bottom *
|
|
456
|
+
(baseItem.width + baseItem.marginRight);
|
|
457
|
+
}
|
|
458
|
+
} else {
|
|
459
|
+
if (baseItem.findNextAnchor.top) {
|
|
460
|
+
checkAnchor =
|
|
461
|
+
baseItem.left +
|
|
462
|
+
baseItem.findNextAnchor.top *
|
|
463
|
+
(baseItem.width + baseItem.marginRight);
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
} else {
|
|
467
|
+
if (offset > 0) {
|
|
468
|
+
if (baseItem.findNextAnchor.right) {
|
|
469
|
+
checkAnchor =
|
|
470
|
+
baseItem.top +
|
|
471
|
+
baseItem.findNextAnchor.right *
|
|
472
|
+
(baseItem.height + baseItem.marginBottom);
|
|
473
|
+
}
|
|
474
|
+
} else {
|
|
475
|
+
if (baseItem.findNextAnchor.left) {
|
|
476
|
+
checkAnchor =
|
|
477
|
+
baseItem.top +
|
|
478
|
+
baseItem.findNextAnchor.left *
|
|
479
|
+
(baseItem.height + baseItem.marginBottom);
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
if (checkAnchor < 0) {
|
|
485
|
+
checkAnchor = vertical ? baseItem.centerXPos : baseItem.centerYPos;
|
|
486
|
+
}
|
|
487
|
+
const posKey = vertical ? "left" : "top";
|
|
488
|
+
const sizeKey = vertical ? "width" : "height";
|
|
489
|
+
let direction = vertical ? "top" : "left";
|
|
490
|
+
let pathHistoryDirection = vertical ? "bottom" : "right";
|
|
491
|
+
// Normalize offset
|
|
492
|
+
if (offset > 0) {
|
|
493
|
+
pathHistoryDirection = vertical ? "top" : "left";
|
|
494
|
+
direction = vertical ? "bottom" : "right";
|
|
495
|
+
}
|
|
496
|
+
const notRecordHistoryDirection = vertical ? "bottom" : "right";
|
|
497
|
+
const notRecordHistoryOrient = vertical ? HORIZONTAL : VERTICAL;
|
|
498
|
+
let lastItemIndex = templateList.length - 1;
|
|
499
|
+
const orientType = this.direction;
|
|
500
|
+
// 查找有效的最后项
|
|
501
|
+
for (let i = templateList.length - 1; i >= 0; i--) {
|
|
502
|
+
const lastItem = templateList[i];
|
|
503
|
+
if (lastItem.focusable) {
|
|
504
|
+
lastItemIndex = i;
|
|
505
|
+
break;
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
let found = false;
|
|
509
|
+
let nextIndex = -1;
|
|
510
|
+
let pathHistoryIndex = -1;
|
|
511
|
+
if (this.supportHistoryPath && !baseItem.findNextAnchor) {
|
|
512
|
+
pathHistoryIndex = templateList[index].pathHistory[direction];
|
|
513
|
+
}
|
|
514
|
+
if (pathHistoryIndex < 0) {
|
|
515
|
+
// 无历史路径
|
|
516
|
+
// 获得邻近点列表
|
|
517
|
+
let neighborList = templateList[index].neighborIndexList[direction];
|
|
518
|
+
if (templateList[index].tmpNeighborIndexList[direction].length > 0) {
|
|
519
|
+
neighborList = neighborList.concat(
|
|
520
|
+
templateList[index].tmpNeighborIndexList[direction]
|
|
521
|
+
);
|
|
522
|
+
}
|
|
523
|
+
if (neighborList.length === 1) {
|
|
524
|
+
nextIndex = neighborList[0];
|
|
525
|
+
if (
|
|
526
|
+
lastItemIndex !== index ||
|
|
527
|
+
direction !== notRecordHistoryDirection ||
|
|
528
|
+
orientType !== notRecordHistoryOrient
|
|
529
|
+
) {
|
|
530
|
+
// horizontal lastItemIndex bottom 不记历史路径
|
|
531
|
+
templateList[index].pathHistory[direction] = nextIndex; // 更新历史路径
|
|
532
|
+
templateList[nextIndex].pathHistory[pathHistoryDirection] = index; // 更新历史路径
|
|
533
|
+
}
|
|
534
|
+
found = true;
|
|
535
|
+
} else {
|
|
536
|
+
for (let i = 0; i < neighborList.length; i++) {
|
|
537
|
+
nextIndex = neighborList[i];
|
|
538
|
+
const checkingItem = templateList[nextIndex];
|
|
539
|
+
if (
|
|
540
|
+
checkAnchor <=
|
|
541
|
+
checkingItem[posKey] + checkingItem[sizeKey] - 1 &&
|
|
542
|
+
checkAnchor >= checkingItem[posKey]
|
|
543
|
+
) {
|
|
544
|
+
if (
|
|
545
|
+
lastItemIndex !== index ||
|
|
546
|
+
direction !== notRecordHistoryDirection ||
|
|
547
|
+
orientType !== notRecordHistoryOrient
|
|
548
|
+
) {
|
|
549
|
+
// horizontal lastItemIndex bottom 不记历史路径
|
|
550
|
+
templateList[index].pathHistory[direction] = nextIndex; // 更新历史路径
|
|
551
|
+
templateList[nextIndex].pathHistory[pathHistoryDirection] =
|
|
552
|
+
index; // 更新历史路径
|
|
553
|
+
}
|
|
554
|
+
found = true;
|
|
555
|
+
break;
|
|
556
|
+
}
|
|
557
|
+
}
|
|
558
|
+
// 若未找到中间位置的项目
|
|
559
|
+
// 若找到了项目,但是该项为非 focusable
|
|
560
|
+
// 则使用neighbor list中focusable项
|
|
561
|
+
if (!found || !templateList[nextIndex].focusable) {
|
|
562
|
+
for (let i = 0; i < neighborList.length; i++) {
|
|
563
|
+
const neighborIndex = neighborList[i];
|
|
564
|
+
const checkingItem = templateList[neighborIndex];
|
|
565
|
+
if (checkingItem.focusable) {
|
|
566
|
+
if (
|
|
567
|
+
lastItemIndex !== index ||
|
|
568
|
+
direction !== notRecordHistoryDirection ||
|
|
569
|
+
orientType !== notRecordHistoryOrient
|
|
570
|
+
) {
|
|
571
|
+
// horizontal lastItemIndex bottom 不记历史路径
|
|
572
|
+
templateList[index].pathHistory[direction] = nextIndex; // 更新历史路径
|
|
573
|
+
templateList[nextIndex].pathHistory[pathHistoryDirection] =
|
|
574
|
+
index; // 更新历史路径
|
|
575
|
+
}
|
|
576
|
+
nextIndex = neighborIndex;
|
|
577
|
+
found = true;
|
|
578
|
+
break;
|
|
579
|
+
}
|
|
580
|
+
}
|
|
581
|
+
}
|
|
582
|
+
}
|
|
583
|
+
} else {
|
|
584
|
+
nextIndex = pathHistoryIndex;
|
|
585
|
+
if (
|
|
586
|
+
lastItemIndex !== index ||
|
|
587
|
+
direction !== notRecordHistoryDirection ||
|
|
588
|
+
orientType !== notRecordHistoryOrient
|
|
589
|
+
) {
|
|
590
|
+
// horizontal lastItemIndex bottom 不记历史路径
|
|
591
|
+
templateList[nextIndex].pathHistory[pathHistoryDirection] = index; // 更新历史路径
|
|
592
|
+
}
|
|
593
|
+
found = true;
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
if (found) {
|
|
597
|
+
if (!templateList[nextIndex].focusable) {
|
|
598
|
+
// 如果是占位符,则查找占位符的下一个
|
|
599
|
+
return this.getNextItemInner(nextIndex, offset, vertical);
|
|
600
|
+
}
|
|
601
|
+
return templateList[nextIndex];
|
|
602
|
+
}
|
|
603
|
+
return null;
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
private _GetItemDistance(item1: TemplateItem, item2: TemplateItem) {
|
|
607
|
+
return (
|
|
608
|
+
Math.pow(item1.centerXPos - item2.centerXPos, 2) +
|
|
609
|
+
Math.pow(item1.centerYPos - item2.centerYPos, 2)
|
|
610
|
+
);
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
private _GetTotalNeighbor(index: number, direction: string) {
|
|
614
|
+
const item = this.templateList[index];
|
|
615
|
+
return item.neighborIndexList[direction].concat(
|
|
616
|
+
item.tmpNeighborIndexList[direction]
|
|
617
|
+
);
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
private _GetNearestItem(targetItemIndex: number, itemIndexList: Array<number>) {
|
|
621
|
+
let nearestIndex = -1,
|
|
622
|
+
minDistance = Number.POSITIVE_INFINITY;
|
|
623
|
+
let targetItem = this.templateList[targetItemIndex];
|
|
624
|
+
for (let i of itemIndexList) {
|
|
625
|
+
const d = this._GetItemDistance(this.templateList[i], targetItem);
|
|
626
|
+
if (d < minDistance) {
|
|
627
|
+
nearestIndex = i;
|
|
628
|
+
minDistance = d;
|
|
629
|
+
}
|
|
630
|
+
}
|
|
631
|
+
return nearestIndex;
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
private _GetNextLoopItem(index: number, offset: number, isVertical: boolean) {
|
|
635
|
+
const templateList = this.templateList;
|
|
636
|
+
const baseItem = templateList[index];
|
|
637
|
+
let searchDirection = isVertical ? "right" : "bottom";
|
|
638
|
+
let startDirection = isVertical ? "top" : "left";
|
|
639
|
+
if (offset > 0) {
|
|
640
|
+
searchDirection = isVertical ? "left" : "top";
|
|
641
|
+
startDirection = isVertical ? "bottom" : "right";
|
|
642
|
+
}
|
|
643
|
+
let targetIndex = -1;
|
|
644
|
+
let focusableTarget = -1;
|
|
645
|
+
let startIndex = -1;
|
|
646
|
+
let neighborList = [];
|
|
647
|
+
//寻找下一列的起始item
|
|
648
|
+
neighborList = this._GetTotalNeighbor(index, searchDirection);
|
|
649
|
+
while (startIndex < 0 && neighborList.length > 0) {
|
|
650
|
+
for (let i of neighborList) {
|
|
651
|
+
if (this._GetTotalNeighbor(i, startDirection).length > 0) {
|
|
652
|
+
startIndex = i;
|
|
653
|
+
break;
|
|
654
|
+
} else {
|
|
655
|
+
//TODO 是否要用递归
|
|
656
|
+
neighborList = this._GetTotalNeighbor(i, searchDirection);
|
|
657
|
+
}
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
if (startIndex >= 0) {
|
|
661
|
+
neighborList = this._GetTotalNeighbor(startIndex, startDirection);
|
|
662
|
+
|
|
663
|
+
//寻找最近的neighbor
|
|
664
|
+
let nearestIndex = -1,
|
|
665
|
+
minDistance = Number.POSITIVE_INFINITY;
|
|
666
|
+
for (let i of neighborList) {
|
|
667
|
+
const d = this._GetItemDistance(templateList[i], baseItem);
|
|
668
|
+
if (d < minDistance) {
|
|
669
|
+
nearestIndex = i;
|
|
670
|
+
minDistance = d;
|
|
671
|
+
}
|
|
672
|
+
}
|
|
673
|
+
|
|
674
|
+
neighborList = this._GetTotalNeighbor(nearestIndex, searchDirection);
|
|
675
|
+
while (neighborList.length > 0) {
|
|
676
|
+
targetIndex = this._GetNearestItem(nearestIndex, neighborList);
|
|
677
|
+
if (templateList[targetIndex].focusable) {
|
|
678
|
+
focusableTarget = targetIndex;
|
|
679
|
+
}
|
|
680
|
+
neighborList = this._GetTotalNeighbor(targetIndex, searchDirection);
|
|
681
|
+
}
|
|
682
|
+
if (focusableTarget >= 0) {
|
|
683
|
+
return templateList[focusableTarget];
|
|
684
|
+
} else if (targetIndex >= 0) {
|
|
685
|
+
return this._GetNextLoopItem(targetIndex, offset, isVertical);
|
|
686
|
+
}
|
|
687
|
+
}
|
|
688
|
+
return null;
|
|
689
|
+
}
|
|
690
|
+
|
|
691
|
+
//获取临近行的item
|
|
692
|
+
private _GetNearLineItem(index: number, offset: number, isVertical: boolean) {
|
|
693
|
+
const templateList = this.templateList;
|
|
694
|
+
let searchDirection = isVertical ? "right" : "bottom";
|
|
695
|
+
let startDirection = isVertical ? "top" : "left";
|
|
696
|
+
if (offset > 0) {
|
|
697
|
+
searchDirection = isVertical ? "left" : "top";
|
|
698
|
+
startDirection = isVertical ? "bottom" : "right";
|
|
699
|
+
}
|
|
700
|
+
let startIndex = -1;
|
|
701
|
+
let neighborList = [];
|
|
702
|
+
//寻找下一列的起始item
|
|
703
|
+
neighborList = this._GetTotalNeighbor(index, searchDirection);
|
|
704
|
+
while (startIndex < 0 && neighborList.length > 0) {
|
|
705
|
+
for (let i of neighborList) {
|
|
706
|
+
const n = this._GetTotalNeighbor(i, startDirection);
|
|
707
|
+
if (n.length > 0) {
|
|
708
|
+
return templateList[this._GetNearestItem(index, n)];
|
|
709
|
+
} else {
|
|
710
|
+
//TODO 是否要用递归
|
|
711
|
+
neighborList = this._GetTotalNeighbor(i, searchDirection);
|
|
712
|
+
}
|
|
713
|
+
}
|
|
714
|
+
}
|
|
715
|
+
return null;
|
|
716
|
+
}
|
|
717
|
+
|
|
718
|
+
public updateItemSize(index: number, newSize: { width: number, height: number }): void {
|
|
719
|
+
console.error(TAG, "updateItemSize is not supported.");
|
|
720
|
+
}
|
|
721
|
+
|
|
722
|
+
/** get visible item list functions */
|
|
723
|
+
public getVisibleItemList(
|
|
724
|
+
visibleStart: number,
|
|
725
|
+
visibleEnd: number,
|
|
726
|
+
baseId: number): [number, number] {
|
|
727
|
+
if (visibleStart > visibleEnd) {
|
|
728
|
+
// No visible item
|
|
729
|
+
return [-1, -1];
|
|
730
|
+
}
|
|
731
|
+
//取整以避免starline和endline找不到骑线的item的bug
|
|
732
|
+
visibleStart = Math.round(visibleStart);
|
|
733
|
+
visibleEnd = Math.round(visibleEnd);
|
|
734
|
+
let searchBaseItemIdx = this.id2Index(baseId);
|
|
735
|
+
if (typeof searchBaseItemIdx === "undefined") searchBaseItemIdx = 0;
|
|
736
|
+
const commonData: VisibleSearchConfigCommon = {
|
|
737
|
+
resultStartIdx: -1,
|
|
738
|
+
resultEndIdx: -1,
|
|
739
|
+
enableBackwardSearching: true,
|
|
740
|
+
enableForwardSearching: true,
|
|
741
|
+
checkingStartLinePos: visibleStart,
|
|
742
|
+
checkingEndLinePos: visibleEnd,
|
|
743
|
+
};
|
|
744
|
+
const backwardConfigure: VisibleSearchConfig = {
|
|
745
|
+
searchDirect: -1,
|
|
746
|
+
baseIdx: searchBaseItemIdx,
|
|
747
|
+
checkingStartLineRanges: new RangesModel(0, 0),
|
|
748
|
+
startLineRangesFulled: false,
|
|
749
|
+
latestOverStartLineIdx: -1,
|
|
750
|
+
checkingEndLineRanges: new RangesModel(0, 0),
|
|
751
|
+
endLineRangesFulled: false,
|
|
752
|
+
latestOverEndLineIdx: -1,
|
|
753
|
+
endSearchingIndex: 0,
|
|
754
|
+
firstStartLineBlockIdx: -1,
|
|
755
|
+
firstEndLineBlockIdx: -1,
|
|
756
|
+
searchToBorder: false,
|
|
757
|
+
common: commonData,
|
|
758
|
+
};
|
|
759
|
+
const forwardConfigure: VisibleSearchConfig = {
|
|
760
|
+
searchDirect: 1,
|
|
761
|
+
baseIdx: searchBaseItemIdx,
|
|
762
|
+
checkingStartLineRanges: new RangesModel(0, 0),
|
|
763
|
+
startLineRangesFulled: false,
|
|
764
|
+
latestOverStartLineIdx: -1,
|
|
765
|
+
checkingEndLineRanges: new RangesModel(0, 0),
|
|
766
|
+
endLineRangesFulled: false,
|
|
767
|
+
latestOverEndLineIdx: -1,
|
|
768
|
+
endSearchingIndex: this.templateList.length - 1,
|
|
769
|
+
firstStartLineBlockIdx: -1,
|
|
770
|
+
firstEndLineBlockIdx: -1,
|
|
771
|
+
searchToBorder: false,
|
|
772
|
+
common: commonData,
|
|
773
|
+
};
|
|
774
|
+
|
|
775
|
+
const isTemplateVertical = this.direction === VERTICAL;
|
|
776
|
+
let offset = 0;
|
|
777
|
+
while (
|
|
778
|
+
commonData.enableBackwardSearching ||
|
|
779
|
+
commonData.enableForwardSearching
|
|
780
|
+
) {
|
|
781
|
+
if (commonData.enableBackwardSearching) {
|
|
782
|
+
this._DoSearching(backwardConfigure, -offset, isTemplateVertical);
|
|
783
|
+
}
|
|
784
|
+
|
|
785
|
+
if (commonData.enableForwardSearching) {
|
|
786
|
+
this._DoSearching(forwardConfigure, offset, isTemplateVertical);
|
|
787
|
+
}
|
|
788
|
+
offset++;
|
|
789
|
+
}
|
|
790
|
+
// console.log(
|
|
791
|
+
// "GetVisibleItemList [" +
|
|
792
|
+
// JSON.stringify(commonData) +
|
|
793
|
+
// ", " +
|
|
794
|
+
// JSON.stringify(backwardConfigure) +
|
|
795
|
+
// ", " +
|
|
796
|
+
// JSON.stringify(forwardConfigure) +
|
|
797
|
+
// "]"
|
|
798
|
+
// );
|
|
799
|
+
|
|
800
|
+
if (commonData.resultStartIdx < 0) {
|
|
801
|
+
// When start index not found
|
|
802
|
+
// Use just over start line block as start idx
|
|
803
|
+
if (
|
|
804
|
+
backwardConfigure.latestOverStartLineIdx >= 0 &&
|
|
805
|
+
backwardConfigure.firstStartLineBlockIdx >= 0
|
|
806
|
+
)
|
|
807
|
+
commonData.resultStartIdx = backwardConfigure.latestOverStartLineIdx;
|
|
808
|
+
else if (forwardConfigure.firstStartLineBlockIdx >= 0)
|
|
809
|
+
commonData.resultStartIdx = forwardConfigure.firstStartLineBlockIdx;
|
|
810
|
+
}
|
|
811
|
+
|
|
812
|
+
if (commonData.resultEndIdx < 0) {
|
|
813
|
+
// When end index not found
|
|
814
|
+
// Use just over end line block as end idx
|
|
815
|
+
if (
|
|
816
|
+
forwardConfigure.latestOverEndLineIdx >= 0 &&
|
|
817
|
+
forwardConfigure.firstEndLineBlockIdx >= 0
|
|
818
|
+
)
|
|
819
|
+
commonData.resultEndIdx = forwardConfigure.latestOverEndLineIdx;
|
|
820
|
+
else if (backwardConfigure.firstEndLineBlockIdx >= 0)
|
|
821
|
+
commonData.resultEndIdx = backwardConfigure.firstEndLineBlockIdx;
|
|
822
|
+
}
|
|
823
|
+
// Recheck if whole contents inside the range
|
|
824
|
+
if (commonData.resultStartIdx < 0 && commonData.resultEndIdx < 0) {
|
|
825
|
+
// Check if whole contents inside the range
|
|
826
|
+
const firstItem = this.templateList[0];
|
|
827
|
+
const firstSecondPos = isTemplateVertical
|
|
828
|
+
? firstItem.top
|
|
829
|
+
: firstItem.left;
|
|
830
|
+
const lastItem = this.templateList[this.templateList.length - 1];
|
|
831
|
+
const lastSecondPos = isTemplateVertical
|
|
832
|
+
? lastItem.top
|
|
833
|
+
: lastItem.left;
|
|
834
|
+
const lastSecondWidth = isTemplateVertical
|
|
835
|
+
? lastItem.height
|
|
836
|
+
: lastItem.width;
|
|
837
|
+
if (
|
|
838
|
+
firstSecondPos > visibleStart &&
|
|
839
|
+
lastSecondPos + lastSecondWidth < visibleEnd
|
|
840
|
+
) {
|
|
841
|
+
commonData.resultStartIdx = 0;
|
|
842
|
+
commonData.resultEndIdx = this.templateList.length - 1;
|
|
843
|
+
}
|
|
844
|
+
}
|
|
845
|
+
let ret: [number, number] = [-1, -1];
|
|
846
|
+
if (commonData.resultStartIdx >= 0 || commonData.resultEndIdx >= 0) {
|
|
847
|
+
const startIdx =
|
|
848
|
+
commonData.resultStartIdx >= 0 ? commonData.resultStartIdx : 0;
|
|
849
|
+
const endIdx =
|
|
850
|
+
commonData.resultEndIdx >= 0
|
|
851
|
+
? commonData.resultEndIdx
|
|
852
|
+
: this.templateList.length - 1;
|
|
853
|
+
ret = [startIdx, endIdx];
|
|
854
|
+
}
|
|
855
|
+
return ret;
|
|
856
|
+
}
|
|
857
|
+
|
|
858
|
+
private _DoSearching(configures: VisibleSearchConfig, offset: number, beVerticalTemplate: boolean) {
|
|
859
|
+
const checkItem = this.templateList[configures.baseIdx + offset];
|
|
860
|
+
const keyPos = beVerticalTemplate ? checkItem.left : checkItem.top;
|
|
861
|
+
const keyWidth = beVerticalTemplate
|
|
862
|
+
? checkItem.width + checkItem.marginRight
|
|
863
|
+
: checkItem.height + checkItem.marginBottom;
|
|
864
|
+
const keyStart = Math.round(keyPos);
|
|
865
|
+
const keyEnd = Math.round(keyPos + keyWidth - 1);
|
|
866
|
+
const secondPos = beVerticalTemplate ? checkItem.top : checkItem.left;
|
|
867
|
+
const secondWidth = beVerticalTemplate
|
|
868
|
+
? checkItem.height + checkItem.marginBottom
|
|
869
|
+
: checkItem.width + checkItem.marginRight;
|
|
870
|
+
const secondStart = Math.round(secondPos);
|
|
871
|
+
const secondEnd = Math.round(secondPos + secondWidth - 1);
|
|
872
|
+
// console.log(
|
|
873
|
+
// "idx=" +
|
|
874
|
+
// (configures.baseIdx + offset) +
|
|
875
|
+
// " pos=" +
|
|
876
|
+
// secondPos +
|
|
877
|
+
// " posend=" +
|
|
878
|
+
// (secondPos + secondWidth - 1) +
|
|
879
|
+
// " linePos=" +
|
|
880
|
+
// configures.common.checkingStartLinePos
|
|
881
|
+
// );
|
|
882
|
+
|
|
883
|
+
if (
|
|
884
|
+
configures.common.resultStartIdx < 0 &&
|
|
885
|
+
!configures.startLineRangesFulled
|
|
886
|
+
) {
|
|
887
|
+
let isRangeChanged = false;
|
|
888
|
+
if (
|
|
889
|
+
secondStart <= configures.common.checkingStartLinePos &&
|
|
890
|
+
secondEnd >= configures.common.checkingStartLinePos
|
|
891
|
+
) {
|
|
892
|
+
// Overlap the visbible start line
|
|
893
|
+
configures.latestOverStartLineIdx = configures.baseIdx + offset;
|
|
894
|
+
if (configures.firstStartLineBlockIdx < 0)
|
|
895
|
+
configures.firstStartLineBlockIdx = configures.baseIdx + offset;
|
|
896
|
+
configures.checkingStartLineRanges.Merge(
|
|
897
|
+
new SingleRangeModel(keyStart, keyEnd)
|
|
898
|
+
);
|
|
899
|
+
isRangeChanged = true;
|
|
900
|
+
} else if (
|
|
901
|
+
configures.searchDirect < 0 &&
|
|
902
|
+
secondEnd <= configures.common.checkingStartLinePos
|
|
903
|
+
) {
|
|
904
|
+
// above the visible start line
|
|
905
|
+
configures.checkingStartLineRanges.Merge(
|
|
906
|
+
new SingleRangeModel(keyStart, keyEnd)
|
|
907
|
+
);
|
|
908
|
+
isRangeChanged = true;
|
|
909
|
+
}
|
|
910
|
+
}
|
|
911
|
+
// console.log(
|
|
912
|
+
// "idx=" +
|
|
913
|
+
// (configures.baseIdx + offset) +
|
|
914
|
+
// " pos=" +
|
|
915
|
+
// secondPos +
|
|
916
|
+
// " posend=" +
|
|
917
|
+
// (secondPos + secondWidth - 1) +
|
|
918
|
+
// " linePos=" +
|
|
919
|
+
// configures.common.checkingEndLinePos
|
|
920
|
+
// );
|
|
921
|
+
if (configures.common.resultEndIdx < 0 && !configures.endLineRangesFulled) {
|
|
922
|
+
let isRangeChanged = false;
|
|
923
|
+
if (
|
|
924
|
+
secondStart <= configures.common.checkingEndLinePos &&
|
|
925
|
+
secondEnd >= configures.common.checkingEndLinePos
|
|
926
|
+
) {
|
|
927
|
+
// Overlap the visbible end line
|
|
928
|
+
configures.latestOverEndLineIdx = configures.baseIdx + offset;
|
|
929
|
+
if (configures.firstEndLineBlockIdx < 0)
|
|
930
|
+
configures.firstEndLineBlockIdx = configures.baseIdx + offset;
|
|
931
|
+
configures.checkingEndLineRanges.Merge(
|
|
932
|
+
new SingleRangeModel(keyStart, keyEnd)
|
|
933
|
+
);
|
|
934
|
+
isRangeChanged = true;
|
|
935
|
+
} else if (
|
|
936
|
+
configures.searchDirect > 0 &&
|
|
937
|
+
secondStart >= configures.common.checkingEndLinePos
|
|
938
|
+
) {
|
|
939
|
+
// below the visible end line
|
|
940
|
+
configures.checkingEndLineRanges.Merge(
|
|
941
|
+
new SingleRangeModel(keyStart, keyEnd)
|
|
942
|
+
);
|
|
943
|
+
isRangeChanged = true;
|
|
944
|
+
}
|
|
945
|
+
}
|
|
946
|
+
if (configures.baseIdx + offset === configures.endSearchingIndex) {
|
|
947
|
+
if (configures.searchDirect > 0) {
|
|
948
|
+
configures.common.enableForwardSearching = false;
|
|
949
|
+
} else {
|
|
950
|
+
configures.common.enableBackwardSearching = false;
|
|
951
|
+
}
|
|
952
|
+
configures.searchToBorder = true;
|
|
953
|
+
}
|
|
954
|
+
}
|
|
955
|
+
|
|
956
|
+
/** neighbor calculate functions */
|
|
957
|
+
private _TryCalculateNeighborItem(index: number, xPos: number, yPos: number, width: number, height: number) {
|
|
958
|
+
const curNotOccupiedEdge: EdgeInfo = {
|
|
959
|
+
index,
|
|
960
|
+
edgeObj: {
|
|
961
|
+
leftEdge: {
|
|
962
|
+
position: xPos,
|
|
963
|
+
range: new RangesModel(yPos, yPos + height - 1),
|
|
964
|
+
},
|
|
965
|
+
rightEdge: {
|
|
966
|
+
position: xPos + width,
|
|
967
|
+
range: new RangesModel(yPos, yPos + height - 1),
|
|
968
|
+
},
|
|
969
|
+
topEdge: {
|
|
970
|
+
position: yPos,
|
|
971
|
+
range: new RangesModel(xPos, xPos + width - 1),
|
|
972
|
+
},
|
|
973
|
+
bottomEdge: {
|
|
974
|
+
position: yPos + height,
|
|
975
|
+
range: new RangesModel(xPos, xPos + width - 1),
|
|
976
|
+
},
|
|
977
|
+
},
|
|
978
|
+
};
|
|
979
|
+
// 边界处理,重置leftEdge和topEdge;
|
|
980
|
+
if (xPos === 0) {
|
|
981
|
+
curNotOccupiedEdge.edgeObj.leftEdge = null;
|
|
982
|
+
}
|
|
983
|
+
if (yPos === 0) {
|
|
984
|
+
curNotOccupiedEdge.edgeObj.topEdge = null;
|
|
985
|
+
}
|
|
986
|
+
let newFance = false;
|
|
987
|
+
// 边界处理,重置bootomEdge和rightEdge
|
|
988
|
+
const widthMax = this.lineMax;
|
|
989
|
+
let newFenceEdgeStart_x = this._FenceEdge.StartX;
|
|
990
|
+
let newFenceEdgeStart_y = this._FenceEdge.StartY;
|
|
991
|
+
if (this.direction === VERTICAL) {
|
|
992
|
+
if (xPos + width === widthMax) {
|
|
993
|
+
curNotOccupiedEdge.edgeObj.rightEdge = null;
|
|
994
|
+
}
|
|
995
|
+
// 判断FenceEdge,是否产生新的fence
|
|
996
|
+
if (yPos > this._FenceEdge.StartY) {
|
|
997
|
+
// 产生新的Fence
|
|
998
|
+
newFance = true;
|
|
999
|
+
newFenceEdgeStart_y = yPos;
|
|
1000
|
+
}
|
|
1001
|
+
} else {
|
|
1002
|
+
if (yPos + height === widthMax) {
|
|
1003
|
+
curNotOccupiedEdge.edgeObj.bottomEdge = null;
|
|
1004
|
+
}
|
|
1005
|
+
// 判断FenceEdge,是否产生新的fence
|
|
1006
|
+
if (xPos > this._FenceEdge.StartX) {
|
|
1007
|
+
// 产生新的Fence
|
|
1008
|
+
newFance = true;
|
|
1009
|
+
newFenceEdgeStart_x = xPos;
|
|
1010
|
+
}
|
|
1011
|
+
}
|
|
1012
|
+
this._FenceEdge.StartX = newFenceEdgeStart_x;
|
|
1013
|
+
this._FenceEdge.StartY = newFenceEdgeStart_y;
|
|
1014
|
+
// 添加节点
|
|
1015
|
+
this._NotOccupiedEdgeList.push(curNotOccupiedEdge);
|
|
1016
|
+
// 如果产生新fence,则对NotOccupiedEdgeList进行相邻节点计算
|
|
1017
|
+
if (newFance) {
|
|
1018
|
+
this._CalculateNeighborItem();
|
|
1019
|
+
}
|
|
1020
|
+
}
|
|
1021
|
+
|
|
1022
|
+
private _CalculateNeighborItem(tmpNeighbor: boolean = false) {
|
|
1023
|
+
const templateList = this.templateList;
|
|
1024
|
+
// 更新邻近边,以及未占用的边
|
|
1025
|
+
for (let i = 0; i < this._NotOccupiedEdgeList.length; i++) {
|
|
1026
|
+
const crossItem = this._NotOccupiedEdgeList[i];
|
|
1027
|
+
const crossEdgeObj = crossItem.edgeObj;
|
|
1028
|
+
const crossItemIndex = crossItem.index;
|
|
1029
|
+
if (
|
|
1030
|
+
crossEdgeObj.leftEdge == null &&
|
|
1031
|
+
crossEdgeObj.rightEdge == null &&
|
|
1032
|
+
crossEdgeObj.topEdge == null &&
|
|
1033
|
+
crossEdgeObj.bottomEdge == null
|
|
1034
|
+
) {
|
|
1035
|
+
this._NotOccupiedEdgeList.splice(i, 1);
|
|
1036
|
+
i--;
|
|
1037
|
+
continue;
|
|
1038
|
+
}
|
|
1039
|
+
if (this.direction === VERTICAL) {
|
|
1040
|
+
// 如果下边被占用,则将其从列表中删除
|
|
1041
|
+
// if (crossEdgeObj.bottomEdge === null) {
|
|
1042
|
+
// this._NotOccupiedEdgeList.splice(i, 1);
|
|
1043
|
+
// i--;
|
|
1044
|
+
// continue;
|
|
1045
|
+
// }
|
|
1046
|
+
// 临时邻居不触发fence edge
|
|
1047
|
+
// 超过fenceedge范围,不作为对比相
|
|
1048
|
+
if (
|
|
1049
|
+
!tmpNeighbor && crossEdgeObj.bottomEdge != null &&
|
|
1050
|
+
crossEdgeObj.bottomEdge.position > this._FenceEdge.StartY
|
|
1051
|
+
) {
|
|
1052
|
+
continue;
|
|
1053
|
+
}
|
|
1054
|
+
} else {
|
|
1055
|
+
// 如果右边被占用,则将其从列表中删除
|
|
1056
|
+
// if (crossEdgeObj.rightEdge === null) {
|
|
1057
|
+
// this._NotOccupiedEdgeList.splice(i, 1);
|
|
1058
|
+
// i--;
|
|
1059
|
+
// continue;
|
|
1060
|
+
// }
|
|
1061
|
+
// 临时邻居不触发fence edge
|
|
1062
|
+
// 超过fenceedge范围,不作为对比相
|
|
1063
|
+
if (
|
|
1064
|
+
!tmpNeighbor && crossEdgeObj.rightEdge &&
|
|
1065
|
+
crossEdgeObj.rightEdge.position > this._FenceEdge.StartX
|
|
1066
|
+
) {
|
|
1067
|
+
continue;
|
|
1068
|
+
}
|
|
1069
|
+
}
|
|
1070
|
+
|
|
1071
|
+
// 查找与交叉项上下左右最近的各项目,做交叉
|
|
1072
|
+
const neighbor = this._FindNearestNeighbor(crossItem);
|
|
1073
|
+
// console.log(
|
|
1074
|
+
// "%c cchtest find nearest neighbor",
|
|
1075
|
+
// "color:red;",
|
|
1076
|
+
// crossItem.index,
|
|
1077
|
+
// {
|
|
1078
|
+
// left: this._NotOccupiedEdgeList[neighbor.left]?.index,
|
|
1079
|
+
// right: this._NotOccupiedEdgeList[neighbor.right]?.index,
|
|
1080
|
+
// top: this._NotOccupiedEdgeList[neighbor.top]?.index,
|
|
1081
|
+
// bottom: this._NotOccupiedEdgeList[neighbor.bottom]?.index,
|
|
1082
|
+
// }
|
|
1083
|
+
// );
|
|
1084
|
+
|
|
1085
|
+
for (let key in neighbor) {
|
|
1086
|
+
//更新每个方向找到的邻居
|
|
1087
|
+
if (neighbor[key] !== -1) {
|
|
1088
|
+
const targetItem = this._NotOccupiedEdgeList[neighbor[key]];
|
|
1089
|
+
this._TryUpdateItemNeighbor(
|
|
1090
|
+
tmpNeighbor,
|
|
1091
|
+
key,
|
|
1092
|
+
crossItem,
|
|
1093
|
+
targetItem
|
|
1094
|
+
);
|
|
1095
|
+
}
|
|
1096
|
+
}
|
|
1097
|
+
}
|
|
1098
|
+
}
|
|
1099
|
+
|
|
1100
|
+
private _IfBlockedByOtherNeighbor(direction: string, crossItem: EdgeInfo, targetItem: EdgeInfo) {
|
|
1101
|
+
//检查是否被其他neighbor遮挡
|
|
1102
|
+
let positionKey = "top";
|
|
1103
|
+
let sizeKey = "height";
|
|
1104
|
+
let subPositionKey = "left";
|
|
1105
|
+
switch (direction) {
|
|
1106
|
+
case "left":
|
|
1107
|
+
break;
|
|
1108
|
+
case "right":
|
|
1109
|
+
break;
|
|
1110
|
+
case "top":
|
|
1111
|
+
positionKey = "left";
|
|
1112
|
+
subPositionKey = "top";
|
|
1113
|
+
sizeKey = "width";
|
|
1114
|
+
break;
|
|
1115
|
+
case "bottom":
|
|
1116
|
+
positionKey = "left";
|
|
1117
|
+
subPositionKey = "top";
|
|
1118
|
+
sizeKey = "width";
|
|
1119
|
+
break;
|
|
1120
|
+
default:
|
|
1121
|
+
console.log(`_IfBlockedByOtherNeighbor unknown direction:${direction}`);
|
|
1122
|
+
break;
|
|
1123
|
+
}
|
|
1124
|
+
const crossTemplateItem = this.getItemByIndex(crossItem.index);
|
|
1125
|
+
const targetTemplateItem = this.getItemByIndex(targetItem.index);
|
|
1126
|
+
|
|
1127
|
+
let valid = true;
|
|
1128
|
+
if (crossTemplateItem && targetTemplateItem) {
|
|
1129
|
+
const crossNeighborList =
|
|
1130
|
+
crossTemplateItem.neighborIndexList[direction];
|
|
1131
|
+
const targetStart = targetTemplateItem[positionKey];
|
|
1132
|
+
const targetEnd = targetStart + targetTemplateItem[sizeKey] - 1;
|
|
1133
|
+
for (let i = crossNeighborList.length - 1; i >= 0; i--) {
|
|
1134
|
+
const item = this.getItemByIndex(crossNeighborList[i]);
|
|
1135
|
+
|
|
1136
|
+
if (item == null) continue;
|
|
1137
|
+
|
|
1138
|
+
const itemStart = item[positionKey];
|
|
1139
|
+
const itemEnd = itemStart + item[sizeKey] - 1;
|
|
1140
|
+
if (itemStart <= targetEnd && itemEnd >= targetStart) {
|
|
1141
|
+
//有重叠, 检查两个item那个离 cross item 更近
|
|
1142
|
+
if (
|
|
1143
|
+
Math.abs(
|
|
1144
|
+
item[subPositionKey] - crossTemplateItem[subPositionKey]
|
|
1145
|
+
) <
|
|
1146
|
+
Math.abs(
|
|
1147
|
+
targetTemplateItem[subPositionKey] -
|
|
1148
|
+
crossTemplateItem[subPositionKey]
|
|
1149
|
+
)
|
|
1150
|
+
) {
|
|
1151
|
+
//已有的neighbor更近
|
|
1152
|
+
valid = false;
|
|
1153
|
+
break;
|
|
1154
|
+
} else {
|
|
1155
|
+
//target item更近, 删除已有的neighbor
|
|
1156
|
+
crossNeighborList.splice(i, 1);
|
|
1157
|
+
}
|
|
1158
|
+
}
|
|
1159
|
+
}
|
|
1160
|
+
}
|
|
1161
|
+
return valid;
|
|
1162
|
+
}
|
|
1163
|
+
|
|
1164
|
+
private _CheckNeighborItemMatching(direction: string, crossItem: EdgeInfo, targetItem: EdgeInfo) {
|
|
1165
|
+
const crossEdgeObj = crossItem.edgeObj;
|
|
1166
|
+
const targetEdgeObj = targetItem.edgeObj;
|
|
1167
|
+
let targetEdgeName = "rightEdge";
|
|
1168
|
+
let crossEdgeName = "leftEdge";
|
|
1169
|
+
switch (direction) {
|
|
1170
|
+
case "left":
|
|
1171
|
+
targetEdgeName = "rightEdge";
|
|
1172
|
+
crossEdgeName = "leftEdge";
|
|
1173
|
+
break;
|
|
1174
|
+
case "right":
|
|
1175
|
+
targetEdgeName = "leftEdge";
|
|
1176
|
+
crossEdgeName = "rightEdge";
|
|
1177
|
+
break;
|
|
1178
|
+
case "top":
|
|
1179
|
+
targetEdgeName = "bottomEdge";
|
|
1180
|
+
crossEdgeName = "topEdge";
|
|
1181
|
+
break;
|
|
1182
|
+
case "bottom":
|
|
1183
|
+
crossEdgeName = "bottomEdge";
|
|
1184
|
+
targetEdgeName = "topEdge";
|
|
1185
|
+
break;
|
|
1186
|
+
default:
|
|
1187
|
+
console.log(
|
|
1188
|
+
`_CheckNeighborItemMatching unknown direction:${direction}`
|
|
1189
|
+
);
|
|
1190
|
+
break;
|
|
1191
|
+
}
|
|
1192
|
+
// console.log(
|
|
1193
|
+
// "cchtest exclude edge",
|
|
1194
|
+
// crossItem.index,
|
|
1195
|
+
// targetItem.index,
|
|
1196
|
+
// crossEdgeName,
|
|
1197
|
+
// targetEdgeName,
|
|
1198
|
+
// crossEdgeObj[crossEdgeName].range.Clone().Ranges,
|
|
1199
|
+
// targetEdgeObj[targetEdgeName].range.Clone().Ranges
|
|
1200
|
+
// );
|
|
1201
|
+
|
|
1202
|
+
const targetEdgeRangeClone =
|
|
1203
|
+
targetEdgeObj[targetEdgeName].range.Clone();
|
|
1204
|
+
targetEdgeObj[targetEdgeName].range.ExcludeRanges(
|
|
1205
|
+
crossEdgeObj[crossEdgeName].range
|
|
1206
|
+
);
|
|
1207
|
+
crossEdgeObj[crossEdgeName].range.ExcludeRanges(
|
|
1208
|
+
targetEdgeRangeClone
|
|
1209
|
+
);
|
|
1210
|
+
|
|
1211
|
+
// console.log(
|
|
1212
|
+
// "cchtest after exclude",
|
|
1213
|
+
// crossEdgeObj[crossEdgeName].range.Clone().Ranges,
|
|
1214
|
+
// targetEdgeObj[targetEdgeName].range.Clone().Ranges
|
|
1215
|
+
// );
|
|
1216
|
+
|
|
1217
|
+
if (targetEdgeObj[targetEdgeName].range.IsEmpty()) {
|
|
1218
|
+
// 完全匹配,更新该边的状态为已被占用
|
|
1219
|
+
targetEdgeObj[targetEdgeName] = null;
|
|
1220
|
+
}
|
|
1221
|
+
|
|
1222
|
+
if (crossEdgeObj[crossEdgeName].range.IsEmpty()) {
|
|
1223
|
+
// 清除该边
|
|
1224
|
+
crossEdgeObj[crossEdgeName] = null;
|
|
1225
|
+
}
|
|
1226
|
+
}
|
|
1227
|
+
|
|
1228
|
+
private _FindNearestNeighbor(crossItem: EdgeInfo) {
|
|
1229
|
+
const crossEdgeObj = crossItem.edgeObj;
|
|
1230
|
+
|
|
1231
|
+
let nearestLeftIndex = -1;
|
|
1232
|
+
let nearestRightIndex = -1;
|
|
1233
|
+
let nearestTopIndex = -1;
|
|
1234
|
+
let nearestBottomIndex = -1;
|
|
1235
|
+
let leftDistance = -1;
|
|
1236
|
+
let rightDistance = -1;
|
|
1237
|
+
let topDistance = -1;
|
|
1238
|
+
let bottomDistance = -1;
|
|
1239
|
+
|
|
1240
|
+
for (let j = 0; j < this._NotOccupiedEdgeList.length; j++) {
|
|
1241
|
+
const targetItem = this._NotOccupiedEdgeList[j];
|
|
1242
|
+
const targetEdgeObj = targetItem.edgeObj;
|
|
1243
|
+
if (crossItem === targetItem) {
|
|
1244
|
+
continue;
|
|
1245
|
+
}
|
|
1246
|
+
// 左边最近项
|
|
1247
|
+
if (
|
|
1248
|
+
crossEdgeObj.leftEdge !== null &&
|
|
1249
|
+
targetEdgeObj.rightEdge !== null
|
|
1250
|
+
) {
|
|
1251
|
+
if (
|
|
1252
|
+
crossEdgeObj.leftEdge.position >= targetEdgeObj.rightEdge.position &&
|
|
1253
|
+
crossEdgeObj.leftEdge.range.IsInterAct(
|
|
1254
|
+
targetEdgeObj.rightEdge.range
|
|
1255
|
+
)
|
|
1256
|
+
) {
|
|
1257
|
+
// 在其左侧,且有交叉,才为neighbor
|
|
1258
|
+
// 计算最短距离
|
|
1259
|
+
if (leftDistance === -1) {
|
|
1260
|
+
leftDistance =
|
|
1261
|
+
crossEdgeObj.leftEdge.position - targetEdgeObj.rightEdge.position;
|
|
1262
|
+
nearestLeftIndex = j;
|
|
1263
|
+
continue;
|
|
1264
|
+
} else if (
|
|
1265
|
+
leftDistance >
|
|
1266
|
+
crossEdgeObj.leftEdge.position - targetEdgeObj.rightEdge.position
|
|
1267
|
+
) {
|
|
1268
|
+
leftDistance =
|
|
1269
|
+
crossEdgeObj.leftEdge.position - targetEdgeObj.rightEdge.position;
|
|
1270
|
+
nearestLeftIndex = j;
|
|
1271
|
+
continue;
|
|
1272
|
+
}
|
|
1273
|
+
}
|
|
1274
|
+
}
|
|
1275
|
+
// 右边最近项
|
|
1276
|
+
if (
|
|
1277
|
+
crossEdgeObj.rightEdge !== null &&
|
|
1278
|
+
targetEdgeObj.leftEdge !== null
|
|
1279
|
+
) {
|
|
1280
|
+
if (
|
|
1281
|
+
crossEdgeObj.rightEdge.position <= targetEdgeObj.leftEdge.position &&
|
|
1282
|
+
crossEdgeObj.rightEdge.range.IsInterAct(
|
|
1283
|
+
targetEdgeObj.leftEdge.range
|
|
1284
|
+
)
|
|
1285
|
+
) {
|
|
1286
|
+
// 在其左侧,且有交叉,才为neighbor
|
|
1287
|
+
// 计算最短距离
|
|
1288
|
+
if (rightDistance === -1) {
|
|
1289
|
+
rightDistance =
|
|
1290
|
+
targetEdgeObj.leftEdge.position - crossEdgeObj.rightEdge.position;
|
|
1291
|
+
nearestRightIndex = j;
|
|
1292
|
+
continue;
|
|
1293
|
+
} else if (
|
|
1294
|
+
rightDistance >
|
|
1295
|
+
targetEdgeObj.leftEdge.position - crossEdgeObj.rightEdge.position
|
|
1296
|
+
) {
|
|
1297
|
+
rightDistance =
|
|
1298
|
+
targetEdgeObj.leftEdge.position - crossEdgeObj.rightEdge.position;
|
|
1299
|
+
nearestRightIndex = j;
|
|
1300
|
+
continue;
|
|
1301
|
+
}
|
|
1302
|
+
}
|
|
1303
|
+
}
|
|
1304
|
+
|
|
1305
|
+
// 上边最近项
|
|
1306
|
+
if (
|
|
1307
|
+
crossEdgeObj.topEdge !== null &&
|
|
1308
|
+
targetEdgeObj.bottomEdge !== null
|
|
1309
|
+
) {
|
|
1310
|
+
if (
|
|
1311
|
+
crossEdgeObj.topEdge.position >= targetEdgeObj.bottomEdge.position &&
|
|
1312
|
+
crossEdgeObj.topEdge.range.IsInterAct(
|
|
1313
|
+
targetEdgeObj.bottomEdge.range
|
|
1314
|
+
)
|
|
1315
|
+
) {
|
|
1316
|
+
// 在其左侧,且有交叉,才为neighbor
|
|
1317
|
+
// 计算最短距离
|
|
1318
|
+
if (topDistance === -1) {
|
|
1319
|
+
topDistance =
|
|
1320
|
+
crossEdgeObj.topEdge.position - targetEdgeObj.bottomEdge.position;
|
|
1321
|
+
nearestTopIndex = j;
|
|
1322
|
+
continue;
|
|
1323
|
+
} else if (
|
|
1324
|
+
topDistance >
|
|
1325
|
+
crossEdgeObj.topEdge.position - targetEdgeObj.bottomEdge.position
|
|
1326
|
+
) {
|
|
1327
|
+
topDistance =
|
|
1328
|
+
crossEdgeObj.topEdge.position - targetEdgeObj.bottomEdge.position;
|
|
1329
|
+
nearestTopIndex = j;
|
|
1330
|
+
continue;
|
|
1331
|
+
}
|
|
1332
|
+
}
|
|
1333
|
+
}
|
|
1334
|
+
// 下边的最近项
|
|
1335
|
+
if (
|
|
1336
|
+
crossEdgeObj.bottomEdge !== null &&
|
|
1337
|
+
targetEdgeObj.topEdge !== null
|
|
1338
|
+
) {
|
|
1339
|
+
if (
|
|
1340
|
+
crossEdgeObj.bottomEdge.position <= targetEdgeObj.topEdge.position &&
|
|
1341
|
+
crossEdgeObj.bottomEdge.range.IsInterAct(
|
|
1342
|
+
targetEdgeObj.topEdge.range
|
|
1343
|
+
)
|
|
1344
|
+
) {
|
|
1345
|
+
// 在其左侧,且有交叉,才为neighbor
|
|
1346
|
+
// 计算最短距离
|
|
1347
|
+
if (bottomDistance === -1) {
|
|
1348
|
+
bottomDistance =
|
|
1349
|
+
targetEdgeObj.topEdge.position - crossEdgeObj.bottomEdge.position;
|
|
1350
|
+
nearestBottomIndex = j;
|
|
1351
|
+
continue;
|
|
1352
|
+
} else if (
|
|
1353
|
+
bottomDistance >
|
|
1354
|
+
targetEdgeObj.topEdge.position - crossEdgeObj.bottomEdge.position
|
|
1355
|
+
) {
|
|
1356
|
+
bottomDistance =
|
|
1357
|
+
targetEdgeObj.topEdge.position - crossEdgeObj.bottomEdge.position;
|
|
1358
|
+
nearestBottomIndex = j;
|
|
1359
|
+
continue;
|
|
1360
|
+
}
|
|
1361
|
+
}
|
|
1362
|
+
}
|
|
1363
|
+
}
|
|
1364
|
+
|
|
1365
|
+
return {
|
|
1366
|
+
left: nearestLeftIndex,
|
|
1367
|
+
right: nearestRightIndex,
|
|
1368
|
+
top: nearestTopIndex,
|
|
1369
|
+
bottom: nearestBottomIndex,
|
|
1370
|
+
};
|
|
1371
|
+
}
|
|
1372
|
+
|
|
1373
|
+
private _TryUpdateItemNeighbor(tmpNeighbor: boolean, direction: string, crossItem: EdgeInfo, targetItem: EdgeInfo) {
|
|
1374
|
+
const keyMap = {
|
|
1375
|
+
target: {
|
|
1376
|
+
left: "right",
|
|
1377
|
+
right: "left",
|
|
1378
|
+
top: "bottom",
|
|
1379
|
+
bottom: "top",
|
|
1380
|
+
},
|
|
1381
|
+
cross: {
|
|
1382
|
+
left: "left",
|
|
1383
|
+
right: "right",
|
|
1384
|
+
top: "top",
|
|
1385
|
+
bottom: "bottom",
|
|
1386
|
+
},
|
|
1387
|
+
};
|
|
1388
|
+
let crossNeighborKey = keyMap.cross[direction];
|
|
1389
|
+
let targetNeighborKey = keyMap.target[direction];
|
|
1390
|
+
if (!crossNeighborKey || !targetNeighborKey) {
|
|
1391
|
+
console.error("_TryUpdateItemNeighbor: undefined direction", direction);
|
|
1392
|
+
}
|
|
1393
|
+
|
|
1394
|
+
const targetIndex = targetItem.index;
|
|
1395
|
+
const crossItemIndex = crossItem.index;
|
|
1396
|
+
const templateList = this.templateList;
|
|
1397
|
+
if (this._IfBlockedByOtherNeighbor(direction, crossItem, targetItem)) {
|
|
1398
|
+
if (!tmpNeighbor) {
|
|
1399
|
+
this._CheckNeighborItemMatching(direction, crossItem, targetItem);
|
|
1400
|
+
// 查看是否有交集,有交集,更新临近边
|
|
1401
|
+
templateList[targetIndex].neighborIndexList[targetNeighborKey].push(
|
|
1402
|
+
crossItemIndex
|
|
1403
|
+
);
|
|
1404
|
+
templateList[crossItemIndex].neighborIndexList[
|
|
1405
|
+
crossNeighborKey
|
|
1406
|
+
].push(targetIndex);
|
|
1407
|
+
templateList[targetIndex].tmpNeighborIndexList[targetNeighborKey] =
|
|
1408
|
+
[];
|
|
1409
|
+
templateList[crossItemIndex].tmpNeighborIndexList[
|
|
1410
|
+
crossNeighborKey
|
|
1411
|
+
] = [];
|
|
1412
|
+
} else {
|
|
1413
|
+
templateList[targetIndex].tmpNeighborIndexList[
|
|
1414
|
+
targetNeighborKey
|
|
1415
|
+
].push(crossItemIndex);
|
|
1416
|
+
templateList[crossItemIndex].tmpNeighborIndexList[
|
|
1417
|
+
crossNeighborKey
|
|
1418
|
+
].push(targetIndex);
|
|
1419
|
+
}
|
|
1420
|
+
}
|
|
1421
|
+
}
|
|
1422
|
+
}
|
|
1423
|
+
|
|
1424
|
+
export { CommonMetroTemplate };
|