@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
|
@@ -1,2004 +0,0 @@
|
|
|
1
|
-
/* eslint-disable */
|
|
2
|
-
import { RangesModel, SingleRangeModel } from "./RangeModel";
|
|
3
|
-
import { RectArea } from "./RectUtils";
|
|
4
|
-
import { VERTICAL, HORIZONTAL, FocusMoveType } from "./WidgetCommon";
|
|
5
|
-
const TAG = "TemplateParser: ";
|
|
6
|
-
|
|
7
|
-
function integerCheck(value, warn_func) {
|
|
8
|
-
const result = Math.round(value);
|
|
9
|
-
if (result !== value) {
|
|
10
|
-
warn_func();
|
|
11
|
-
}
|
|
12
|
-
return result;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
const measureObjectCheckMap = {
|
|
16
|
-
left: (obj) => {
|
|
17
|
-
if (isNaN(obj.left)) {
|
|
18
|
-
return 0;
|
|
19
|
-
} else {
|
|
20
|
-
return integerCheck(obj.left, () => {
|
|
21
|
-
console.warn(TAG, "left is not integer", obj);
|
|
22
|
-
});
|
|
23
|
-
}
|
|
24
|
-
},
|
|
25
|
-
top: (obj) => {
|
|
26
|
-
if (isNaN(obj.top)) {
|
|
27
|
-
return 0;
|
|
28
|
-
} else {
|
|
29
|
-
return integerCheck(obj.top, () => {
|
|
30
|
-
console.warn(TAG, "top is not integer", obj);
|
|
31
|
-
});
|
|
32
|
-
}
|
|
33
|
-
},
|
|
34
|
-
width: (obj) => {
|
|
35
|
-
if (isNaN(obj.width)) {
|
|
36
|
-
if (isNaN(obj.block?.w)) {
|
|
37
|
-
throw new Error(TAG + "width is not defined");
|
|
38
|
-
} else {
|
|
39
|
-
console.warn(TAG, "key 'block' is deprecated ");
|
|
40
|
-
return integerCheck(obj.blocks.w, () => {
|
|
41
|
-
console.warn(TAG, "width is not integer", obj);
|
|
42
|
-
});
|
|
43
|
-
}
|
|
44
|
-
} else {
|
|
45
|
-
return integerCheck(obj.width, () => {
|
|
46
|
-
console.warn(TAG, "width is not integer", obj);
|
|
47
|
-
});
|
|
48
|
-
}
|
|
49
|
-
},
|
|
50
|
-
height: (obj) => {
|
|
51
|
-
if (isNaN(obj.height)) {
|
|
52
|
-
if (isNaN(obj.block?.h)) {
|
|
53
|
-
throw new Error(TAG + "height is not defined");
|
|
54
|
-
} else {
|
|
55
|
-
console.warn(TAG, "key 'block' is deprecated ");
|
|
56
|
-
return integerCheck(obj.blocks.h, () => {
|
|
57
|
-
console.warn(TAG, "height is not integer", obj);
|
|
58
|
-
});
|
|
59
|
-
}
|
|
60
|
-
} else {
|
|
61
|
-
return integerCheck(obj.height, () => {
|
|
62
|
-
console.warn(TAG, "height is not integer", obj);
|
|
63
|
-
});
|
|
64
|
-
}
|
|
65
|
-
},
|
|
66
|
-
};
|
|
67
|
-
function measureObjectChecker(obj) {
|
|
68
|
-
for (let key in measureObjectCheckMap) {
|
|
69
|
-
obj[key] = measureObjectCheckMap[key](obj);
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
function getTemplateItem(measure_obj, data_info) {
|
|
74
|
-
measureObjectChecker(measure_obj);
|
|
75
|
-
|
|
76
|
-
let focusZIndex = -1,
|
|
77
|
-
normalZIndex = -1;
|
|
78
|
-
if (
|
|
79
|
-
typeof measure_obj["zIndex"] != "undefined" &&
|
|
80
|
-
measure_obj["zIndex"] != null
|
|
81
|
-
) {
|
|
82
|
-
if (typeof measure_obj["zIndex"] == "object") {
|
|
83
|
-
if (typeof measure_obj["zIndex"]["focus"] == "number") {
|
|
84
|
-
focusZIndex = measure_obj["zIndex"]["focus"];
|
|
85
|
-
}
|
|
86
|
-
if (typeof measure_obj["zIndex"]["normal"] == "number") {
|
|
87
|
-
normalZIndex = measure_obj["zIndex"]["normal"];
|
|
88
|
-
}
|
|
89
|
-
} else if (typeof measure_obj["zIndex"] == "number") {
|
|
90
|
-
focusZIndex = measure_obj["zIndex"];
|
|
91
|
-
normalZIndex = measure_obj["zIndex"];
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
return {
|
|
96
|
-
id: -1,
|
|
97
|
-
index: -1,
|
|
98
|
-
xPos: measure_obj.left, // Set after template be layout
|
|
99
|
-
yPos: measure_obj.top, // Set after template be layout
|
|
100
|
-
centerXPos: 0, // Set after template be layout
|
|
101
|
-
centerYPos: 0, // Set after template be layout
|
|
102
|
-
width: measure_obj.width,
|
|
103
|
-
height: measure_obj.height,
|
|
104
|
-
focusable:
|
|
105
|
-
typeof measure_obj.focusable === "undefined"
|
|
106
|
-
? true
|
|
107
|
-
: measure_obj.focusable,
|
|
108
|
-
data: data_info,
|
|
109
|
-
marginRight:
|
|
110
|
-
typeof measure_obj.marginRight !== "undefined"
|
|
111
|
-
? measure_obj.marginRight
|
|
112
|
-
: 0,
|
|
113
|
-
marginBottom:
|
|
114
|
-
typeof measure_obj.marginBottom !== "undefined"
|
|
115
|
-
? measure_obj.marginBottom
|
|
116
|
-
: 0,
|
|
117
|
-
findNextAnchor:
|
|
118
|
-
typeof measure_obj.findNextAnchor !== "undefined"
|
|
119
|
-
? measure_obj.findNextAnchor
|
|
120
|
-
: null,
|
|
121
|
-
doSlide:
|
|
122
|
-
typeof measure_obj.doSlide !== "undefined" ? measure_obj.doSlide : true,
|
|
123
|
-
pageNumber: -1,
|
|
124
|
-
pageHeadIndex: -1,
|
|
125
|
-
permanent:
|
|
126
|
-
typeof measure_obj.permanent !== "undefined"
|
|
127
|
-
? measure_obj.permanent
|
|
128
|
-
: false,
|
|
129
|
-
focusZIndex,
|
|
130
|
-
normalZIndex,
|
|
131
|
-
};
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
class MetroTemplate {
|
|
135
|
-
/**
|
|
136
|
-
* 在MetroLayout中使用的模板管理类
|
|
137
|
-
*
|
|
138
|
-
* @protected
|
|
139
|
-
* @constructor Forge.MetroTemplate
|
|
140
|
-
* */
|
|
141
|
-
constructor(direction, line_max, layout_type) {
|
|
142
|
-
this.IdsMap = [];
|
|
143
|
-
this._IdsTotal = -1;
|
|
144
|
-
this.List = [];
|
|
145
|
-
this.Orient = {
|
|
146
|
-
type: direction,
|
|
147
|
-
widthMax: line_max,
|
|
148
|
-
};
|
|
149
|
-
this.Layout = {
|
|
150
|
-
type: layout_type || "relative",
|
|
151
|
-
};
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
/**
|
|
155
|
-
* Set id map to index
|
|
156
|
-
*
|
|
157
|
-
* @public
|
|
158
|
-
* @func SetIdsMap
|
|
159
|
-
* @memberof Forge.MetroTemplate
|
|
160
|
-
* @params {int} identity
|
|
161
|
-
* @instance
|
|
162
|
-
* */
|
|
163
|
-
SetIdsMap(identity, index) {
|
|
164
|
-
this.IdsMap[identity] = index;
|
|
165
|
-
this._IdsTotal = -1;
|
|
166
|
-
this.List[index].id = identity;
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
AddItem(item) {
|
|
170
|
-
this.List.push(item);
|
|
171
|
-
item.index = this.List.length - 1;
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
/**
|
|
175
|
-
* 非占位的Template的个数
|
|
176
|
-
*
|
|
177
|
-
* @private
|
|
178
|
-
* @func GetIdsTotal
|
|
179
|
-
* @memberof Forge.MetroTemplate
|
|
180
|
-
* @params
|
|
181
|
-
* @instance
|
|
182
|
-
* @return {int} 个数
|
|
183
|
-
* */
|
|
184
|
-
GetIdsTotal() {
|
|
185
|
-
if (this._IdsTotal < 0) {
|
|
186
|
-
let total = 0;
|
|
187
|
-
for (let i = 0; i < this.List.length; i++) {
|
|
188
|
-
if (this.List[i].id >= 0) {
|
|
189
|
-
total++;
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
this._IdsTotal = total;
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
return this._IdsTotal;
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
GetLastId() {
|
|
199
|
-
return this.IdsMap.length - 1;
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
class Fence {
|
|
204
|
-
/**
|
|
205
|
-
* MetroLayout用于计算使用区域的Fence(栅栏)
|
|
206
|
-
*
|
|
207
|
-
* @private
|
|
208
|
-
* @constructor _Fence
|
|
209
|
-
* @memberof Forge.MetroLayout
|
|
210
|
-
* @param {int} taken_start_pos 栅栏使用区域的起始位置
|
|
211
|
-
* @param {int} width 栅栏使用区域的宽度
|
|
212
|
-
* @param {int} fence_width 栅栏的总宽度
|
|
213
|
-
* @param {int} offset_ahead 栅栏的横向位置
|
|
214
|
-
* */
|
|
215
|
-
constructor(taken_start_pos, width, fence_width, offset_ahead) {
|
|
216
|
-
this._Gaps = [{ GapStart: 0, GapEnd: fence_width - 1 }];
|
|
217
|
-
this._FenceTotalWidth = fence_width;
|
|
218
|
-
this.AheadOffset = offset_ahead;
|
|
219
|
-
if (width > 0) this._SplitGap(0, taken_start_pos, width);
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
/**
|
|
223
|
-
* 查询栅栏是否能放下给定宽度的方块
|
|
224
|
-
*
|
|
225
|
-
* @public
|
|
226
|
-
* @func HasGapFor
|
|
227
|
-
* @memberof Forge.MetroLayout._Fence
|
|
228
|
-
* @instance
|
|
229
|
-
* @param {int} width
|
|
230
|
-
* @return {Object} 格式为{startPos: 栅栏空隙的起始位置},null为没有能容下的空隙。
|
|
231
|
-
* */
|
|
232
|
-
HasGapFor(width) {
|
|
233
|
-
for (let i = 0; i < this._Gaps.length; i++) {
|
|
234
|
-
if (this._Gaps[i].GapEnd - this._Gaps[i].GapStart + 1 >= width) {
|
|
235
|
-
return { startPos: this._Gaps[i].GapStart };
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
return null;
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
/**
|
|
243
|
-
* 标记栅栏空隙被占用
|
|
244
|
-
*
|
|
245
|
-
* @public
|
|
246
|
-
* @func MarkGapUsed
|
|
247
|
-
* @memberof Forge.MetroLayout._Fence
|
|
248
|
-
* @instance
|
|
249
|
-
* @param {int} start_pos 占用块的起始位置
|
|
250
|
-
* @param {int} width 占用快的宽度
|
|
251
|
-
* @return {int} 剩余栅栏的个数
|
|
252
|
-
* */
|
|
253
|
-
MarkGapUsed(start_pos, width) {
|
|
254
|
-
if (width <= 0) return this._Gaps.length;
|
|
255
|
-
|
|
256
|
-
const end_pos = start_pos + width - 1;
|
|
257
|
-
let gap_idx = -1;
|
|
258
|
-
for (let i = 0; i < this._Gaps.length; i++) {
|
|
259
|
-
if (
|
|
260
|
-
this._Gaps[i].GapStart <= start_pos &&
|
|
261
|
-
this._Gaps[i].GapEnd >= end_pos
|
|
262
|
-
) {
|
|
263
|
-
gap_idx = i;
|
|
264
|
-
break;
|
|
265
|
-
}
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
if (gap_idx === -1) {
|
|
269
|
-
return; // 区域完全重复,无法找到新区域
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
this._SplitGap(gap_idx, start_pos, width);
|
|
273
|
-
|
|
274
|
-
return this._Gaps.length;
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
_SplitGap(gap_idx, taker_start_pos, taker_width) {
|
|
278
|
-
const edit_gap = this._Gaps.splice(gap_idx, 1)[0];
|
|
279
|
-
const taker_end_pos = taker_start_pos + taker_width - 1;
|
|
280
|
-
|
|
281
|
-
if (
|
|
282
|
-
taker_start_pos < edit_gap.GapStart ||
|
|
283
|
-
taker_end_pos > edit_gap.GapEnd
|
|
284
|
-
) {
|
|
285
|
-
console.log("ERROR in split Fence Gap, range overflow");
|
|
286
|
-
// Forge.ThrowError("ERROR in split Fence Gap, range overflow");
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
// Insert end side gap
|
|
290
|
-
if (taker_end_pos !== edit_gap.GapEnd) {
|
|
291
|
-
this._Gaps.splice(gap_idx, 0, {
|
|
292
|
-
GapStart: taker_end_pos + 1,
|
|
293
|
-
GapEnd: edit_gap.GapEnd,
|
|
294
|
-
});
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
// Insert start side gap
|
|
298
|
-
if (taker_start_pos !== edit_gap.GapStart) {
|
|
299
|
-
this._Gaps.splice(gap_idx, 0, {
|
|
300
|
-
GapStart: edit_gap.GapStart,
|
|
301
|
-
GapEnd: taker_start_pos - 1,
|
|
302
|
-
});
|
|
303
|
-
}
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
/**
|
|
307
|
-
* 标记栅栏空隙被占用
|
|
308
|
-
*
|
|
309
|
-
* @public
|
|
310
|
-
* @func Fork
|
|
311
|
-
* @memberof Forge.MetroLayout._Fence
|
|
312
|
-
* @instance
|
|
313
|
-
* @param {int} new_ahead_offset 新栅栏的起点位置
|
|
314
|
-
* @return {Forge.MetroLayout._Fence} 复制出来的Fence
|
|
315
|
-
* */
|
|
316
|
-
Fork(new_ahead_offset) {
|
|
317
|
-
const new_fence = new Fence(0, 0, 0, 0);
|
|
318
|
-
new_fence._Gaps = JSON.parse(JSON.stringify(this._Gaps));
|
|
319
|
-
new_fence._FenceTotalWidth = this._FenceTotalWidth;
|
|
320
|
-
new_fence.AheadOffset = new_ahead_offset;
|
|
321
|
-
|
|
322
|
-
return new_fence;
|
|
323
|
-
}
|
|
324
|
-
}
|
|
325
|
-
|
|
326
|
-
class TemplateParser {
|
|
327
|
-
constructor(direction, lineMax, pageSize, layoutType, supportHistoryPath) {
|
|
328
|
-
this._Template = new MetroTemplate(direction, lineMax, layoutType);
|
|
329
|
-
this._FenceStack = [new Fence(0, 0, this._Template.Orient.widthMax, 0)];
|
|
330
|
-
this._Identity = 0;
|
|
331
|
-
this._FenceEdge = { StartX: 0, StartY: 0 }; // 新的未占用边列表生成
|
|
332
|
-
this._NotOccupiedEdgeList = []; // 未占用边列表
|
|
333
|
-
this._SupportHistoryPath = supportHistoryPath;
|
|
334
|
-
this._PageSize = pageSize;
|
|
335
|
-
// this._VisibleRangeSearchBaseItem = null;
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
_IfBlockedByOtherNeighbor(direction, cross_item, target_item) {
|
|
339
|
-
//检查是否被其他neighbor遮挡
|
|
340
|
-
let position_key = "yPos";
|
|
341
|
-
let size_key = "height";
|
|
342
|
-
let sub_position_key = "xPos";
|
|
343
|
-
switch (direction) {
|
|
344
|
-
case "left":
|
|
345
|
-
break;
|
|
346
|
-
case "right":
|
|
347
|
-
break;
|
|
348
|
-
case "top":
|
|
349
|
-
position_key = "xPos";
|
|
350
|
-
sub_position_key = "yPos";
|
|
351
|
-
size_key = "width";
|
|
352
|
-
break;
|
|
353
|
-
case "bottom":
|
|
354
|
-
position_key = "xPos";
|
|
355
|
-
sub_position_key = "yPos";
|
|
356
|
-
size_key = "width";
|
|
357
|
-
break;
|
|
358
|
-
default:
|
|
359
|
-
console.log(`_IfBlockedByOtherNeighbor unknown direction:${direction}`);
|
|
360
|
-
break;
|
|
361
|
-
}
|
|
362
|
-
const cross_template_item = this.GetItem(cross_item.index);
|
|
363
|
-
const cross_neighbor_list =
|
|
364
|
-
cross_template_item.neighborIndexList[direction];
|
|
365
|
-
const target_template_item = this.GetItem(target_item.index);
|
|
366
|
-
const target_start = target_template_item[position_key];
|
|
367
|
-
const target_end = target_start + target_template_item[size_key] - 1;
|
|
368
|
-
let valid = true;
|
|
369
|
-
for (let i = cross_neighbor_list.length - 1; i >= 0; i--) {
|
|
370
|
-
const item = this.GetItem(cross_neighbor_list[i]);
|
|
371
|
-
const item_start = item[position_key];
|
|
372
|
-
const item_end = item_start + item[size_key] - 1;
|
|
373
|
-
if (item_start <= target_end && item_end >= target_start) {
|
|
374
|
-
//有重叠, 检查两个item那个离 cross item 更近
|
|
375
|
-
if (
|
|
376
|
-
Math.abs(
|
|
377
|
-
item[sub_position_key] - cross_template_item[sub_position_key]
|
|
378
|
-
) <
|
|
379
|
-
Math.abs(
|
|
380
|
-
target_template_item[sub_position_key] -
|
|
381
|
-
cross_template_item[sub_position_key]
|
|
382
|
-
)
|
|
383
|
-
) {
|
|
384
|
-
//已有的neighbor更近
|
|
385
|
-
valid = false;
|
|
386
|
-
break;
|
|
387
|
-
} else {
|
|
388
|
-
//target item更近, 删除已有的neighbor
|
|
389
|
-
cross_neighbor_list.splice(i, 1);
|
|
390
|
-
}
|
|
391
|
-
}
|
|
392
|
-
}
|
|
393
|
-
return valid;
|
|
394
|
-
}
|
|
395
|
-
|
|
396
|
-
_CheckNeighborItemMatching(direction, cross_item, target_item) {
|
|
397
|
-
const cross_edge_obj = cross_item.edgeObj;
|
|
398
|
-
const target_edge_obj = target_item.edgeObj;
|
|
399
|
-
let target_edge_name = "rightEdge";
|
|
400
|
-
let cross_edge_name = "leftEdge";
|
|
401
|
-
switch (direction) {
|
|
402
|
-
case "left":
|
|
403
|
-
target_edge_name = "rightEdge";
|
|
404
|
-
cross_edge_name = "leftEdge";
|
|
405
|
-
break;
|
|
406
|
-
case "right":
|
|
407
|
-
target_edge_name = "leftEdge";
|
|
408
|
-
cross_edge_name = "rightEdge";
|
|
409
|
-
break;
|
|
410
|
-
case "top":
|
|
411
|
-
target_edge_name = "bottomEdge";
|
|
412
|
-
cross_edge_name = "topEdge";
|
|
413
|
-
break;
|
|
414
|
-
case "bottom":
|
|
415
|
-
cross_edge_name = "bottomEdge";
|
|
416
|
-
target_edge_name = "topEdge";
|
|
417
|
-
break;
|
|
418
|
-
default:
|
|
419
|
-
console.log(
|
|
420
|
-
`_CheckNeighborItemMatching unknown direction:${direction}`
|
|
421
|
-
);
|
|
422
|
-
break;
|
|
423
|
-
}
|
|
424
|
-
// console.log(
|
|
425
|
-
// "cchtest exclude edge",
|
|
426
|
-
// cross_item.index,
|
|
427
|
-
// target_item.index,
|
|
428
|
-
// cross_edge_name,
|
|
429
|
-
// target_edge_name,
|
|
430
|
-
// cross_edge_obj[cross_edge_name].range.Clone().Ranges,
|
|
431
|
-
// target_edge_obj[target_edge_name].range.Clone().Ranges
|
|
432
|
-
// );
|
|
433
|
-
|
|
434
|
-
const target_edge_range_clone =
|
|
435
|
-
target_edge_obj[target_edge_name].range.Clone();
|
|
436
|
-
target_edge_obj[target_edge_name].range.ExcludeRanges(
|
|
437
|
-
cross_edge_obj[cross_edge_name].range
|
|
438
|
-
);
|
|
439
|
-
cross_edge_obj[cross_edge_name].range.ExcludeRanges(
|
|
440
|
-
target_edge_range_clone
|
|
441
|
-
);
|
|
442
|
-
|
|
443
|
-
// console.log(
|
|
444
|
-
// "cchtest after exclude",
|
|
445
|
-
// cross_edge_obj[cross_edge_name].range.Clone().Ranges,
|
|
446
|
-
// target_edge_obj[target_edge_name].range.Clone().Ranges
|
|
447
|
-
// );
|
|
448
|
-
|
|
449
|
-
if (target_edge_obj[target_edge_name].range.IsEmpty()) {
|
|
450
|
-
// 完全匹配,更新该边的状态为已被占用
|
|
451
|
-
target_edge_obj[target_edge_name] = null;
|
|
452
|
-
}
|
|
453
|
-
|
|
454
|
-
if (cross_edge_obj[cross_edge_name].range.IsEmpty()) {
|
|
455
|
-
// 清除该边
|
|
456
|
-
cross_edge_obj[cross_edge_name] = null;
|
|
457
|
-
}
|
|
458
|
-
}
|
|
459
|
-
|
|
460
|
-
_FindNearestNeighbor(cross_item) {
|
|
461
|
-
const cross_edge_obj = cross_item.edgeObj;
|
|
462
|
-
|
|
463
|
-
let nearest_left_index = -1;
|
|
464
|
-
let nearest_right_index = -1;
|
|
465
|
-
let nearest_top_index = -1;
|
|
466
|
-
let nearest_bottom_index = -1;
|
|
467
|
-
let left_distance = -1;
|
|
468
|
-
let right_distance = -1;
|
|
469
|
-
let top_distance = -1;
|
|
470
|
-
let bottom_distance = -1;
|
|
471
|
-
|
|
472
|
-
for (let j = 0; j < this._NotOccupiedEdgeList.length; j++) {
|
|
473
|
-
const target_item = this._NotOccupiedEdgeList[j];
|
|
474
|
-
const target_edge_obj = target_item.edgeObj;
|
|
475
|
-
if (cross_item === target_item) {
|
|
476
|
-
continue;
|
|
477
|
-
}
|
|
478
|
-
// 左边最近项
|
|
479
|
-
if (
|
|
480
|
-
cross_edge_obj.leftEdge !== null &&
|
|
481
|
-
target_edge_obj.rightEdge !== null
|
|
482
|
-
) {
|
|
483
|
-
if (
|
|
484
|
-
cross_edge_obj.leftEdge.x >= target_edge_obj.rightEdge.x &&
|
|
485
|
-
cross_edge_obj.leftEdge.range.IsInterAct(
|
|
486
|
-
target_edge_obj.rightEdge.range
|
|
487
|
-
)
|
|
488
|
-
) {
|
|
489
|
-
// 在其左侧,且有交叉,才为neighbor
|
|
490
|
-
// 计算最短距离
|
|
491
|
-
if (left_distance === -1) {
|
|
492
|
-
left_distance =
|
|
493
|
-
cross_edge_obj.leftEdge.x - target_edge_obj.rightEdge.x;
|
|
494
|
-
nearest_left_index = j;
|
|
495
|
-
continue;
|
|
496
|
-
} else if (
|
|
497
|
-
left_distance >
|
|
498
|
-
cross_edge_obj.leftEdge.x - target_edge_obj.rightEdge.x
|
|
499
|
-
) {
|
|
500
|
-
left_distance =
|
|
501
|
-
cross_edge_obj.leftEdge.x - target_edge_obj.rightEdge.x;
|
|
502
|
-
nearest_left_index = j;
|
|
503
|
-
continue;
|
|
504
|
-
}
|
|
505
|
-
}
|
|
506
|
-
}
|
|
507
|
-
// 右边最近项
|
|
508
|
-
if (
|
|
509
|
-
cross_edge_obj.rightEdge !== null &&
|
|
510
|
-
target_edge_obj.leftEdge !== null
|
|
511
|
-
) {
|
|
512
|
-
if (
|
|
513
|
-
cross_edge_obj.rightEdge.x <= target_edge_obj.leftEdge.x &&
|
|
514
|
-
cross_edge_obj.rightEdge.range.IsInterAct(
|
|
515
|
-
target_edge_obj.leftEdge.range
|
|
516
|
-
)
|
|
517
|
-
) {
|
|
518
|
-
// 在其左侧,且有交叉,才为neighbor
|
|
519
|
-
// 计算最短距离
|
|
520
|
-
if (right_distance === -1) {
|
|
521
|
-
right_distance =
|
|
522
|
-
target_edge_obj.leftEdge.x - cross_edge_obj.rightEdge.x;
|
|
523
|
-
nearest_right_index = j;
|
|
524
|
-
continue;
|
|
525
|
-
} else if (
|
|
526
|
-
right_distance >
|
|
527
|
-
target_edge_obj.leftEdge.x - cross_edge_obj.rightEdge.x
|
|
528
|
-
) {
|
|
529
|
-
right_distance =
|
|
530
|
-
target_edge_obj.leftEdge.x - cross_edge_obj.rightEdge.x;
|
|
531
|
-
nearest_right_index = j;
|
|
532
|
-
continue;
|
|
533
|
-
}
|
|
534
|
-
}
|
|
535
|
-
}
|
|
536
|
-
|
|
537
|
-
// 上边最近项
|
|
538
|
-
if (
|
|
539
|
-
cross_edge_obj.topEdge !== null &&
|
|
540
|
-
target_edge_obj.bottomEdge !== null
|
|
541
|
-
) {
|
|
542
|
-
if (
|
|
543
|
-
cross_edge_obj.topEdge.y >= target_edge_obj.bottomEdge.y &&
|
|
544
|
-
cross_edge_obj.topEdge.range.IsInterAct(
|
|
545
|
-
target_edge_obj.bottomEdge.range
|
|
546
|
-
)
|
|
547
|
-
) {
|
|
548
|
-
// 在其左侧,且有交叉,才为neighbor
|
|
549
|
-
// 计算最短距离
|
|
550
|
-
if (top_distance === -1) {
|
|
551
|
-
top_distance =
|
|
552
|
-
cross_edge_obj.topEdge.y - target_edge_obj.bottomEdge.y;
|
|
553
|
-
nearest_top_index = j;
|
|
554
|
-
continue;
|
|
555
|
-
} else if (
|
|
556
|
-
top_distance >
|
|
557
|
-
cross_edge_obj.topEdge.y - target_edge_obj.bottomEdge.y
|
|
558
|
-
) {
|
|
559
|
-
top_distance =
|
|
560
|
-
cross_edge_obj.topEdge.y - target_edge_obj.bottomEdge.y;
|
|
561
|
-
nearest_top_index = j;
|
|
562
|
-
continue;
|
|
563
|
-
}
|
|
564
|
-
}
|
|
565
|
-
}
|
|
566
|
-
// 下边的最近项
|
|
567
|
-
if (
|
|
568
|
-
cross_edge_obj.bottomEdge !== null &&
|
|
569
|
-
target_edge_obj.topEdge !== null
|
|
570
|
-
) {
|
|
571
|
-
if (
|
|
572
|
-
cross_edge_obj.bottomEdge.y <= target_edge_obj.topEdge.y &&
|
|
573
|
-
cross_edge_obj.bottomEdge.range.IsInterAct(
|
|
574
|
-
target_edge_obj.topEdge.range
|
|
575
|
-
)
|
|
576
|
-
) {
|
|
577
|
-
// 在其左侧,且有交叉,才为neighbor
|
|
578
|
-
// 计算最短距离
|
|
579
|
-
if (bottom_distance === -1) {
|
|
580
|
-
bottom_distance =
|
|
581
|
-
target_edge_obj.topEdge.y - cross_edge_obj.bottomEdge.y;
|
|
582
|
-
nearest_bottom_index = j;
|
|
583
|
-
continue;
|
|
584
|
-
} else if (
|
|
585
|
-
bottom_distance >
|
|
586
|
-
target_edge_obj.topEdge.y - cross_edge_obj.bottomEdge.y
|
|
587
|
-
) {
|
|
588
|
-
bottom_distance =
|
|
589
|
-
target_edge_obj.topEdge.y - cross_edge_obj.bottomEdge.y;
|
|
590
|
-
nearest_bottom_index = j;
|
|
591
|
-
continue;
|
|
592
|
-
}
|
|
593
|
-
}
|
|
594
|
-
}
|
|
595
|
-
}
|
|
596
|
-
|
|
597
|
-
return {
|
|
598
|
-
left: nearest_left_index,
|
|
599
|
-
right: nearest_right_index,
|
|
600
|
-
top: nearest_top_index,
|
|
601
|
-
bottom: nearest_bottom_index,
|
|
602
|
-
};
|
|
603
|
-
}
|
|
604
|
-
|
|
605
|
-
_TryUpdateItemNeighbor(tmp_neighbor, direction, cross_item, target_item) {
|
|
606
|
-
const key_map = {
|
|
607
|
-
target: {
|
|
608
|
-
left: "right",
|
|
609
|
-
right: "left",
|
|
610
|
-
top: "bottom",
|
|
611
|
-
bottom: "top",
|
|
612
|
-
},
|
|
613
|
-
cross: {
|
|
614
|
-
left: "left",
|
|
615
|
-
right: "right",
|
|
616
|
-
top: "top",
|
|
617
|
-
bottom: "bottom",
|
|
618
|
-
},
|
|
619
|
-
};
|
|
620
|
-
let cross_neighbor_key = key_map.cross[direction];
|
|
621
|
-
let target_neighbor_key = key_map.target[direction];
|
|
622
|
-
if (!cross_neighbor_key || !target_neighbor_key) {
|
|
623
|
-
console.error("_TryUpdateItemNeighbor: undefined direction", direction);
|
|
624
|
-
}
|
|
625
|
-
|
|
626
|
-
const target_index = target_item.index;
|
|
627
|
-
const cross_item_index = cross_item.index;
|
|
628
|
-
const template_list = this._Template.List;
|
|
629
|
-
if (this._IfBlockedByOtherNeighbor(direction, cross_item, target_item)) {
|
|
630
|
-
if (!tmp_neighbor) {
|
|
631
|
-
this._CheckNeighborItemMatching(direction, cross_item, target_item);
|
|
632
|
-
// 查看是否有交集,有交集,更新临近边
|
|
633
|
-
template_list[target_index].neighborIndexList[target_neighbor_key].push(
|
|
634
|
-
cross_item_index
|
|
635
|
-
);
|
|
636
|
-
template_list[cross_item_index].neighborIndexList[
|
|
637
|
-
cross_neighbor_key
|
|
638
|
-
].push(target_index);
|
|
639
|
-
template_list[target_index].tmpNeighborIndexList[target_neighbor_key] =
|
|
640
|
-
[];
|
|
641
|
-
template_list[cross_item_index].tmpNeighborIndexList[
|
|
642
|
-
cross_neighbor_key
|
|
643
|
-
] = [];
|
|
644
|
-
} else {
|
|
645
|
-
template_list[target_index].tmpNeighborIndexList[
|
|
646
|
-
target_neighbor_key
|
|
647
|
-
].push(cross_item_index);
|
|
648
|
-
template_list[cross_item_index].tmpNeighborIndexList[
|
|
649
|
-
cross_neighbor_key
|
|
650
|
-
].push(target_index);
|
|
651
|
-
}
|
|
652
|
-
}
|
|
653
|
-
}
|
|
654
|
-
|
|
655
|
-
_CalculateNeighborItem(tmp_neighbor) {
|
|
656
|
-
const template_list = this._Template.List;
|
|
657
|
-
// 更新邻近边,以及未占用的边
|
|
658
|
-
for (let i = 0; i < this._NotOccupiedEdgeList.length; i++) {
|
|
659
|
-
const cross_item = this._NotOccupiedEdgeList[i];
|
|
660
|
-
const cross_edge_obj = cross_item.edgeObj;
|
|
661
|
-
const cross_item_index = cross_item.index;
|
|
662
|
-
if (
|
|
663
|
-
cross_edge_obj.leftEdge == null &&
|
|
664
|
-
cross_edge_obj.rightEdge == null &&
|
|
665
|
-
cross_edge_obj.topEdge == null &&
|
|
666
|
-
cross_edge_obj.bottomEdge == null
|
|
667
|
-
) {
|
|
668
|
-
this._NotOccupiedEdgeList.splice(i, 1);
|
|
669
|
-
i--;
|
|
670
|
-
continue;
|
|
671
|
-
}
|
|
672
|
-
if (this._Template.Orient.type === VERTICAL) {
|
|
673
|
-
// 如果下边被占用,则将其从列表中删除
|
|
674
|
-
// if (cross_edge_obj.bottomEdge === null) {
|
|
675
|
-
// this._NotOccupiedEdgeList.splice(i, 1);
|
|
676
|
-
// i--;
|
|
677
|
-
// continue;
|
|
678
|
-
// }
|
|
679
|
-
// 临时邻居不触发fence edge
|
|
680
|
-
// 超过fenceedge范围,不作为对比相
|
|
681
|
-
if (
|
|
682
|
-
!tmp_neighbor &&
|
|
683
|
-
cross_edge_obj.bottomEdge?.y > this._FenceEdge.StartY
|
|
684
|
-
) {
|
|
685
|
-
continue;
|
|
686
|
-
}
|
|
687
|
-
} else {
|
|
688
|
-
// 如果右边被占用,则将其从列表中删除
|
|
689
|
-
// if (cross_edge_obj.rightEdge === null) {
|
|
690
|
-
// this._NotOccupiedEdgeList.splice(i, 1);
|
|
691
|
-
// i--;
|
|
692
|
-
// continue;
|
|
693
|
-
// }
|
|
694
|
-
// 临时邻居不触发fence edge
|
|
695
|
-
// 超过fenceedge范围,不作为对比相
|
|
696
|
-
if (
|
|
697
|
-
!tmp_neighbor &&
|
|
698
|
-
cross_edge_obj.rightEdge?.x > this._FenceEdge.StartX
|
|
699
|
-
) {
|
|
700
|
-
continue;
|
|
701
|
-
}
|
|
702
|
-
}
|
|
703
|
-
|
|
704
|
-
// 查找与交叉项上下左右最近的各项目,做交叉
|
|
705
|
-
const neighbor = this._FindNearestNeighbor(cross_item);
|
|
706
|
-
// console.log(
|
|
707
|
-
// "%c cchtest find nearest neighbor",
|
|
708
|
-
// "color:red;",
|
|
709
|
-
// cross_item.index,
|
|
710
|
-
// {
|
|
711
|
-
// left: this._NotOccupiedEdgeList[neighbor.left]?.index,
|
|
712
|
-
// right: this._NotOccupiedEdgeList[neighbor.right]?.index,
|
|
713
|
-
// top: this._NotOccupiedEdgeList[neighbor.top]?.index,
|
|
714
|
-
// bottom: this._NotOccupiedEdgeList[neighbor.bottom]?.index,
|
|
715
|
-
// }
|
|
716
|
-
// );
|
|
717
|
-
|
|
718
|
-
for (let key in neighbor) {
|
|
719
|
-
//更新每个方向找到的邻居
|
|
720
|
-
if (neighbor[key] !== -1) {
|
|
721
|
-
const target_item = this._NotOccupiedEdgeList[neighbor[key]];
|
|
722
|
-
this._TryUpdateItemNeighbor(
|
|
723
|
-
tmp_neighbor,
|
|
724
|
-
key,
|
|
725
|
-
cross_item,
|
|
726
|
-
target_item
|
|
727
|
-
);
|
|
728
|
-
}
|
|
729
|
-
}
|
|
730
|
-
}
|
|
731
|
-
}
|
|
732
|
-
|
|
733
|
-
/**
|
|
734
|
-
* 计算相邻节点(包含占位符)
|
|
735
|
-
*
|
|
736
|
-
* @func _TryCalculateNeighborItem
|
|
737
|
-
* @memberof Forge.MetroLayout
|
|
738
|
-
* @param index Template 索引
|
|
739
|
-
* @param {int} x_pos
|
|
740
|
-
* @param {int} y_pos
|
|
741
|
-
* @param {int} width
|
|
742
|
-
* @param {int} height
|
|
743
|
-
* @private
|
|
744
|
-
*/
|
|
745
|
-
_TryCalculateNeighborItem(index, x_pos, y_pos, width, height) {
|
|
746
|
-
const cur_not_occupied_edge = {
|
|
747
|
-
index,
|
|
748
|
-
edgeObj: {
|
|
749
|
-
leftEdge: {
|
|
750
|
-
x: x_pos,
|
|
751
|
-
range: new RangesModel(y_pos, y_pos + height - 1),
|
|
752
|
-
},
|
|
753
|
-
rightEdge: {
|
|
754
|
-
x: x_pos + width,
|
|
755
|
-
range: new RangesModel(y_pos, y_pos + height - 1),
|
|
756
|
-
},
|
|
757
|
-
topEdge: {
|
|
758
|
-
y: y_pos,
|
|
759
|
-
range: new RangesModel(x_pos, x_pos + width - 1),
|
|
760
|
-
},
|
|
761
|
-
bottomEdge: {
|
|
762
|
-
y: y_pos + height,
|
|
763
|
-
range: new RangesModel(x_pos, x_pos + width - 1),
|
|
764
|
-
},
|
|
765
|
-
},
|
|
766
|
-
};
|
|
767
|
-
// 边界处理,重置leftEdge和topEdge;
|
|
768
|
-
if (x_pos === 0) {
|
|
769
|
-
cur_not_occupied_edge.edgeObj.leftEdge = null;
|
|
770
|
-
}
|
|
771
|
-
if (y_pos === 0) {
|
|
772
|
-
cur_not_occupied_edge.edgeObj.topEdge = null;
|
|
773
|
-
}
|
|
774
|
-
let new_fance = false;
|
|
775
|
-
// 边界处理,重置bootomEdge和rightEdge
|
|
776
|
-
const width_max = this._Template.Orient.widthMax;
|
|
777
|
-
let new_fence_edge_start_x = this._FenceEdge.StartX;
|
|
778
|
-
let new_fence_edge_start_y = this._FenceEdge.StartY;
|
|
779
|
-
if (this._Template.Orient.type === VERTICAL) {
|
|
780
|
-
if (x_pos + width === width_max) {
|
|
781
|
-
cur_not_occupied_edge.edgeObj.rightEdge = null;
|
|
782
|
-
}
|
|
783
|
-
// 判断FenceEdge,是否产生新的fence
|
|
784
|
-
if (y_pos > this._FenceEdge.StartY) {
|
|
785
|
-
// 产生新的Fence
|
|
786
|
-
new_fance = true;
|
|
787
|
-
new_fence_edge_start_y = y_pos;
|
|
788
|
-
}
|
|
789
|
-
} else {
|
|
790
|
-
if (y_pos + height === width_max) {
|
|
791
|
-
cur_not_occupied_edge.edgeObj.bottomEdge = null;
|
|
792
|
-
}
|
|
793
|
-
// 判断FenceEdge,是否产生新的fence
|
|
794
|
-
if (x_pos > this._FenceEdge.StartX) {
|
|
795
|
-
// 产生新的Fence
|
|
796
|
-
new_fance = true;
|
|
797
|
-
new_fence_edge_start_x = x_pos;
|
|
798
|
-
}
|
|
799
|
-
}
|
|
800
|
-
this._FenceEdge.StartX = new_fence_edge_start_x;
|
|
801
|
-
this._FenceEdge.StartY = new_fence_edge_start_y;
|
|
802
|
-
// 添加节点
|
|
803
|
-
this._NotOccupiedEdgeList.push(cur_not_occupied_edge);
|
|
804
|
-
// 如果产生新fence,则对NotOccupiedEdgeList进行相邻节点计算
|
|
805
|
-
if (new_fance) {
|
|
806
|
-
this._CalculateNeighborItem();
|
|
807
|
-
}
|
|
808
|
-
}
|
|
809
|
-
|
|
810
|
-
_UpdateLastFenceEdge() {
|
|
811
|
-
const old_fence = this._FenceEdge;
|
|
812
|
-
const new_min_fence = { StartX: -1, StartY: -1 };
|
|
813
|
-
// 查找最后一条FenceEdge
|
|
814
|
-
for (let i = 0; i < this._NotOccupiedEdgeList.length; i++) {
|
|
815
|
-
const cross_item = this._NotOccupiedEdgeList[i];
|
|
816
|
-
const cross_edge_obj = cross_item.edgeObj;
|
|
817
|
-
if (this._Template.Orient.type === VERTICAL) {
|
|
818
|
-
if (cross_edge_obj.bottomEdge !== null) {
|
|
819
|
-
if (cross_edge_obj.bottomEdge.y > old_fence.StartY) {
|
|
820
|
-
if (new_min_fence.StartY === -1) {
|
|
821
|
-
new_min_fence.StartY = cross_edge_obj.bottomEdge.y;
|
|
822
|
-
} else if (cross_edge_obj.bottomEdge.y < new_min_fence.StartY) {
|
|
823
|
-
new_min_fence.StartY = cross_edge_obj.bottomEdge.y;
|
|
824
|
-
}
|
|
825
|
-
}
|
|
826
|
-
}
|
|
827
|
-
} else {
|
|
828
|
-
if (cross_edge_obj.rightEdge !== null) {
|
|
829
|
-
if (cross_edge_obj.rightEdge.x > old_fence.StartX) {
|
|
830
|
-
if (new_min_fence.StartX === -1) {
|
|
831
|
-
new_min_fence.StartX = cross_edge_obj.rightEdge.x;
|
|
832
|
-
} else if (cross_edge_obj.rightEdge.y < new_min_fence.StartX) {
|
|
833
|
-
new_min_fence.StartX = cross_edge_obj.rightEdge.x;
|
|
834
|
-
}
|
|
835
|
-
}
|
|
836
|
-
}
|
|
837
|
-
}
|
|
838
|
-
}
|
|
839
|
-
|
|
840
|
-
this._FenceEdge = new_min_fence;
|
|
841
|
-
}
|
|
842
|
-
|
|
843
|
-
ParseTemplateItem(item_obj, data_obj) {
|
|
844
|
-
const template_item = getTemplateItem(item_obj, data_obj);
|
|
845
|
-
// Layout template items
|
|
846
|
-
const fence_stack = this._FenceStack;
|
|
847
|
-
const item_id = template_item.id;
|
|
848
|
-
const item_width = template_item.width;
|
|
849
|
-
const item_height = template_item.height;
|
|
850
|
-
// Add view to contents view layer
|
|
851
|
-
let x_pos;
|
|
852
|
-
let y_pos;
|
|
853
|
-
let x_width;
|
|
854
|
-
let y_width;
|
|
855
|
-
let item_key_pos = 0;
|
|
856
|
-
let item_second_pos = 0;
|
|
857
|
-
|
|
858
|
-
let item_key_width = 0;
|
|
859
|
-
let item_second_width = 0;
|
|
860
|
-
let item_key_margin = 0;
|
|
861
|
-
let item_second_margin = 0;
|
|
862
|
-
if (this._Template.Layout.type === "relative") {
|
|
863
|
-
if (this._Template.Orient.type === VERTICAL) {
|
|
864
|
-
item_key_width = item_width;
|
|
865
|
-
item_second_width = item_height;
|
|
866
|
-
item_key_margin = template_item.marginRight;
|
|
867
|
-
item_second_margin = template_item.marginBottom;
|
|
868
|
-
} else {
|
|
869
|
-
item_key_width = item_height;
|
|
870
|
-
item_second_width = item_width;
|
|
871
|
-
item_key_margin = template_item.marginBottom;
|
|
872
|
-
item_second_margin = template_item.marginRight;
|
|
873
|
-
}
|
|
874
|
-
// Find capability fence in stack
|
|
875
|
-
let top_fence = null;
|
|
876
|
-
let gap_info = null;
|
|
877
|
-
while (fence_stack.length > 0) {
|
|
878
|
-
const checking_fence = fence_stack[fence_stack.length - 1];
|
|
879
|
-
gap_info = checking_fence.HasGapFor(item_key_width + item_key_margin);
|
|
880
|
-
if (gap_info !== null) {
|
|
881
|
-
top_fence = checking_fence;
|
|
882
|
-
break;
|
|
883
|
-
}
|
|
884
|
-
fence_stack.pop();
|
|
885
|
-
}
|
|
886
|
-
|
|
887
|
-
// Layout the item in top fence
|
|
888
|
-
if (gap_info !== null) {
|
|
889
|
-
item_key_pos = gap_info.startPos;
|
|
890
|
-
item_second_pos = top_fence.AheadOffset;
|
|
891
|
-
} else {
|
|
892
|
-
throw new Error(
|
|
893
|
-
`${TAG} item size ${item_width}x${item_height} is greater than widget line max ${this._Template.Orient.widthMax}`
|
|
894
|
-
);
|
|
895
|
-
// console.error(TAG, "ERROR: coding error, header full gap fence lost");
|
|
896
|
-
}
|
|
897
|
-
|
|
898
|
-
if (this._Template.Orient.type === VERTICAL) {
|
|
899
|
-
x_pos = item_key_pos;
|
|
900
|
-
y_pos = item_second_pos;
|
|
901
|
-
x_width = item_key_width;
|
|
902
|
-
y_width = item_second_width;
|
|
903
|
-
} else {
|
|
904
|
-
x_pos = item_second_pos;
|
|
905
|
-
y_pos = item_key_pos;
|
|
906
|
-
x_width = item_second_width;
|
|
907
|
-
y_width = item_key_width;
|
|
908
|
-
}
|
|
909
|
-
} else {
|
|
910
|
-
x_pos = template_item.xPos;
|
|
911
|
-
y_pos = template_item.yPos;
|
|
912
|
-
x_width = item_width;
|
|
913
|
-
y_width = item_height;
|
|
914
|
-
}
|
|
915
|
-
|
|
916
|
-
// Update template item information
|
|
917
|
-
template_item.neighborIndexList = {
|
|
918
|
-
left: [],
|
|
919
|
-
top: [],
|
|
920
|
-
right: [],
|
|
921
|
-
bottom: [],
|
|
922
|
-
};
|
|
923
|
-
template_item.tmpNeighborIndexList = {
|
|
924
|
-
left: [],
|
|
925
|
-
top: [],
|
|
926
|
-
right: [],
|
|
927
|
-
bottom: [],
|
|
928
|
-
};
|
|
929
|
-
// 记录历史路径
|
|
930
|
-
template_item.pathHistory = {
|
|
931
|
-
left: null,
|
|
932
|
-
top: null,
|
|
933
|
-
right: null,
|
|
934
|
-
bottom: null,
|
|
935
|
-
};
|
|
936
|
-
template_item.xPos = x_pos;
|
|
937
|
-
template_item.yPos = y_pos;
|
|
938
|
-
template_item.centerXPos = Math.floor(x_pos + x_width / 2) - 1;
|
|
939
|
-
template_item.centerYPos = Math.floor(y_pos + y_width / 2) - 1;
|
|
940
|
-
//分页相关的计算
|
|
941
|
-
let cur_page_number = 0;
|
|
942
|
-
let cur_page_head_index = 0;
|
|
943
|
-
if (this._Template.List.length > 0) {
|
|
944
|
-
const last_item = this._Template.List[this._Template.List.length - 1];
|
|
945
|
-
cur_page_number = last_item.pageNumber;
|
|
946
|
-
cur_page_head_index = last_item.pageHeadIndex;
|
|
947
|
-
let position_key = "xPos";
|
|
948
|
-
let size_key = "width";
|
|
949
|
-
if (this._Template.Orient.type === VERTICAL) {
|
|
950
|
-
position_key = "yPos";
|
|
951
|
-
size_key = "height";
|
|
952
|
-
}
|
|
953
|
-
const cur_page_start =
|
|
954
|
-
this._Template.List[cur_page_head_index][position_key];
|
|
955
|
-
if (
|
|
956
|
-
template_item[position_key] + template_item[size_key] >
|
|
957
|
-
cur_page_start + this._PageSize
|
|
958
|
-
) {
|
|
959
|
-
//新的页
|
|
960
|
-
cur_page_number++;
|
|
961
|
-
cur_page_head_index = this._Template.List.length;
|
|
962
|
-
}
|
|
963
|
-
}
|
|
964
|
-
|
|
965
|
-
template_item.pageNumber = cur_page_number;
|
|
966
|
-
template_item.pageHeadIndex = cur_page_head_index;
|
|
967
|
-
// if (
|
|
968
|
-
// this._Template.Orient.type !== VERTICAL &&
|
|
969
|
-
// y_pos + y_width === this._Template.Orient.widthMax
|
|
970
|
-
// ) {
|
|
971
|
-
// template_item.onBottomLine = true;
|
|
972
|
-
// }
|
|
973
|
-
this._Template.AddItem(template_item);
|
|
974
|
-
// Update template item id
|
|
975
|
-
if (template_item.focusable) {
|
|
976
|
-
this._Template.SetIdsMap(
|
|
977
|
-
this._Identity++,
|
|
978
|
-
this._Template.List.length - 1
|
|
979
|
-
);
|
|
980
|
-
}
|
|
981
|
-
// 计算相邻项
|
|
982
|
-
this._TryCalculateNeighborItem(
|
|
983
|
-
this._Template.List.length - 1,
|
|
984
|
-
template_item.xPos,
|
|
985
|
-
template_item.yPos,
|
|
986
|
-
template_item.width + template_item.marginRight,
|
|
987
|
-
template_item.height + template_item.marginBottom
|
|
988
|
-
);
|
|
989
|
-
|
|
990
|
-
const item_second_end_pos =
|
|
991
|
-
item_second_pos + item_second_width + item_second_margin - 1;
|
|
992
|
-
|
|
993
|
-
// Ensure header fence
|
|
994
|
-
if (fence_stack[0].AheadOffset <= item_second_end_pos) {
|
|
995
|
-
// Need new header fence
|
|
996
|
-
fence_stack.splice(
|
|
997
|
-
0,
|
|
998
|
-
0,
|
|
999
|
-
new Fence(0, 0, this._Template.Orient.widthMax, item_second_end_pos + 1)
|
|
1000
|
-
);
|
|
1001
|
-
}
|
|
1002
|
-
|
|
1003
|
-
// Mark gap used in fence stack
|
|
1004
|
-
let end_fence_existed = false;
|
|
1005
|
-
let far_away_end_fence_existed = false;
|
|
1006
|
-
let one_ahead_last_fence_idx = -1;
|
|
1007
|
-
for (let fence_idx = fence_stack.length - 1; fence_idx >= 0; fence_idx--) {
|
|
1008
|
-
if (fence_stack[fence_idx].AheadOffset <= item_second_end_pos) {
|
|
1009
|
-
if (fence_stack[fence_idx].AheadOffset === item_second_end_pos)
|
|
1010
|
-
end_fence_existed = true;
|
|
1011
|
-
const left_gaps = fence_stack[fence_idx].MarkGapUsed(
|
|
1012
|
-
item_key_pos,
|
|
1013
|
-
item_key_width + item_key_margin
|
|
1014
|
-
);
|
|
1015
|
-
if (left_gaps === 0) {
|
|
1016
|
-
// remove fence
|
|
1017
|
-
fence_stack.splice(fence_idx, 1);
|
|
1018
|
-
}
|
|
1019
|
-
} else {
|
|
1020
|
-
if (fence_stack[fence_idx].AheadOffset === item_second_end_pos + 1)
|
|
1021
|
-
far_away_end_fence_existed = true;
|
|
1022
|
-
one_ahead_last_fence_idx = fence_idx;
|
|
1023
|
-
break;
|
|
1024
|
-
}
|
|
1025
|
-
}
|
|
1026
|
-
|
|
1027
|
-
const fence_ahead_offset = item_second_end_pos;
|
|
1028
|
-
// Create fences
|
|
1029
|
-
if (!end_fence_existed) {
|
|
1030
|
-
// Build fence edge which close to the beginning
|
|
1031
|
-
if (one_ahead_last_fence_idx + 1 <= fence_stack.length - 1) {
|
|
1032
|
-
const fence =
|
|
1033
|
-
fence_stack[one_ahead_last_fence_idx + 1].Fork(fence_ahead_offset);
|
|
1034
|
-
fence_stack.splice(one_ahead_last_fence_idx + 1, 0, fence);
|
|
1035
|
-
}
|
|
1036
|
-
}
|
|
1037
|
-
if (!far_away_end_fence_existed) {
|
|
1038
|
-
// Build fence edge which far away from the beginning
|
|
1039
|
-
if (one_ahead_last_fence_idx > 0) {
|
|
1040
|
-
const fence = fence_stack[one_ahead_last_fence_idx].Fork(
|
|
1041
|
-
fence_ahead_offset + 1
|
|
1042
|
-
);
|
|
1043
|
-
fence_stack.splice(one_ahead_last_fence_idx + 1, 0, fence);
|
|
1044
|
-
}
|
|
1045
|
-
}
|
|
1046
|
-
return template_item;
|
|
1047
|
-
}
|
|
1048
|
-
|
|
1049
|
-
GetItemById(id) {
|
|
1050
|
-
return this._Template.List[this._Template.IdsMap[id]];
|
|
1051
|
-
}
|
|
1052
|
-
|
|
1053
|
-
GetLastId() {
|
|
1054
|
-
return this._Template.GetLastId();
|
|
1055
|
-
}
|
|
1056
|
-
|
|
1057
|
-
GetItem(index) {
|
|
1058
|
-
return index >= 0
|
|
1059
|
-
? this._Template.List[index]
|
|
1060
|
-
: this._Template.List[this._Template.List.length + index];
|
|
1061
|
-
}
|
|
1062
|
-
|
|
1063
|
-
GetLength() {
|
|
1064
|
-
return this._Template.List.length;
|
|
1065
|
-
}
|
|
1066
|
-
|
|
1067
|
-
IdToIndex(id) {
|
|
1068
|
-
const index = this._Template.IdsMap[id];
|
|
1069
|
-
if (typeof index !== "undefined") {
|
|
1070
|
-
return index;
|
|
1071
|
-
} else {
|
|
1072
|
-
return -1;
|
|
1073
|
-
}
|
|
1074
|
-
}
|
|
1075
|
-
|
|
1076
|
-
/**
|
|
1077
|
-
* 查看Ids中是否有能够获得焦点的项
|
|
1078
|
-
* @param ids
|
|
1079
|
-
* @returns {boolean}
|
|
1080
|
-
* @private
|
|
1081
|
-
*/
|
|
1082
|
-
_CheckIdsHasFocusable(ids) {
|
|
1083
|
-
const template_list = this._Template.List;
|
|
1084
|
-
let found = false;
|
|
1085
|
-
for (let i = 0; i < ids.length; i++) {
|
|
1086
|
-
const id = ids[i];
|
|
1087
|
-
if (template_list[id].focusable) {
|
|
1088
|
-
found = true;
|
|
1089
|
-
break;
|
|
1090
|
-
}
|
|
1091
|
-
}
|
|
1092
|
-
return found;
|
|
1093
|
-
}
|
|
1094
|
-
|
|
1095
|
-
_IsInNeighborList(neighbor_index_list, target_idx) {
|
|
1096
|
-
let found = false;
|
|
1097
|
-
for (let i = neighbor_index_list.length - 1; i >= 0; i--) {
|
|
1098
|
-
if (neighbor_index_list[i] === target_idx) {
|
|
1099
|
-
found = true;
|
|
1100
|
-
break;
|
|
1101
|
-
}
|
|
1102
|
-
}
|
|
1103
|
-
return found;
|
|
1104
|
-
}
|
|
1105
|
-
|
|
1106
|
-
_GetValidNeighborIndex(src_item_id, last_item_id, neighbor_direction) {
|
|
1107
|
-
const template_list = this._Template.List;
|
|
1108
|
-
let valid_id = -1;
|
|
1109
|
-
const item = template_list[last_item_id];
|
|
1110
|
-
const src_item = template_list[src_item_id];
|
|
1111
|
-
let first_ids = null;
|
|
1112
|
-
let second_ids = null;
|
|
1113
|
-
|
|
1114
|
-
if (neighbor_direction === "top") {
|
|
1115
|
-
// 查找左侧邻居节点
|
|
1116
|
-
second_ids = item.neighborIndexList.left;
|
|
1117
|
-
first_ids = item.neighborIndexList.right;
|
|
1118
|
-
} else {
|
|
1119
|
-
// left, right
|
|
1120
|
-
second_ids = item.neighborIndexList.right;
|
|
1121
|
-
first_ids = item.neighborIndexList.left;
|
|
1122
|
-
}
|
|
1123
|
-
|
|
1124
|
-
if (first_ids.length > 0) {
|
|
1125
|
-
for (let i = 0; i < first_ids.length; i++) {
|
|
1126
|
-
const id = first_ids[i];
|
|
1127
|
-
const check_item = template_list[id];
|
|
1128
|
-
if (
|
|
1129
|
-
check_item.focusable &&
|
|
1130
|
-
((neighbor_direction === "top" &&
|
|
1131
|
-
check_item.yPos + check_item.height <= src_item.yPos) ||
|
|
1132
|
-
(neighbor_direction === "bottom" &&
|
|
1133
|
-
check_item.yPos >= src_item.yPos + src_item.height))
|
|
1134
|
-
) {
|
|
1135
|
-
// 并且在src_item_id之上或之下
|
|
1136
|
-
valid_id = id;
|
|
1137
|
-
break;
|
|
1138
|
-
}
|
|
1139
|
-
}
|
|
1140
|
-
}
|
|
1141
|
-
if (valid_id === -1) {
|
|
1142
|
-
if (second_ids.length > 0) {
|
|
1143
|
-
for (let i = 0; i < second_ids.length; i++) {
|
|
1144
|
-
const id = second_ids[i];
|
|
1145
|
-
const check_item = template_list[id];
|
|
1146
|
-
if (
|
|
1147
|
-
check_item.focusable &&
|
|
1148
|
-
((neighbor_direction === "top" &&
|
|
1149
|
-
check_item.yPos + check_item.height <= src_item.yPos) ||
|
|
1150
|
-
(neighbor_direction === "bottom" &&
|
|
1151
|
-
check_item.yPos >= src_item.yPos + src_item.height))
|
|
1152
|
-
) {
|
|
1153
|
-
// 并且在src_item_id之上或之下
|
|
1154
|
-
valid_id = id;
|
|
1155
|
-
break;
|
|
1156
|
-
}
|
|
1157
|
-
}
|
|
1158
|
-
}
|
|
1159
|
-
}
|
|
1160
|
-
return valid_id;
|
|
1161
|
-
}
|
|
1162
|
-
|
|
1163
|
-
_FindFocusableNeighbor(direction, item) {
|
|
1164
|
-
if (
|
|
1165
|
-
item.neighborIndexList[direction].length > 0 &&
|
|
1166
|
-
!this._CheckIdsHasFocusable(item.neighborIndexList[direction])
|
|
1167
|
-
) {
|
|
1168
|
-
const last_item_id =
|
|
1169
|
-
item.neighborIndexList[direction][
|
|
1170
|
-
item.neighborIndexList[direction].length - 1
|
|
1171
|
-
];
|
|
1172
|
-
const idx = this._GetValidNeighborIndex(item.id, last_item_id, direction); // 查找其左右邻居
|
|
1173
|
-
if (idx !== -1) {
|
|
1174
|
-
item.neighborIndexList[direction] = []; // 清除无效项
|
|
1175
|
-
item.neighborIndexList[direction].push(idx);
|
|
1176
|
-
}
|
|
1177
|
-
}
|
|
1178
|
-
}
|
|
1179
|
-
|
|
1180
|
-
CalculateNeighborWhenAddStop() {
|
|
1181
|
-
// Update Last Fence Edge(更新最后一行的fence edge)
|
|
1182
|
-
this._UpdateLastFenceEdge();
|
|
1183
|
-
// Last fence edge to get neighbor
|
|
1184
|
-
this._CalculateNeighborItem();
|
|
1185
|
-
this._CalculateNeighborItem(true);
|
|
1186
|
-
const template_list = this._Template.List;
|
|
1187
|
-
// 若下一行或者上一行的邻居都为非焦点项,则查找向下向上有效项
|
|
1188
|
-
let last_item_index = template_list.length - 1;
|
|
1189
|
-
let last_item = template_list[last_item_index];
|
|
1190
|
-
// 查找有效的最后项
|
|
1191
|
-
for (let i = template_list.length - 1; i >= 0; i--) {
|
|
1192
|
-
last_item = template_list[i];
|
|
1193
|
-
if (last_item.focusable) {
|
|
1194
|
-
last_item_index = i;
|
|
1195
|
-
break;
|
|
1196
|
-
}
|
|
1197
|
-
}
|
|
1198
|
-
//处理找到的neighbor均是占位符的情况
|
|
1199
|
-
for (let j = template_list.length - 1; j >= 0; j--) {
|
|
1200
|
-
const item = template_list[j];
|
|
1201
|
-
if (item.focusable) {
|
|
1202
|
-
this._FindFocusableNeighbor("bottom", item);
|
|
1203
|
-
this._FindFocusableNeighbor("top", item);
|
|
1204
|
-
this._FindFocusableNeighbor("left", item);
|
|
1205
|
-
this._FindFocusableNeighbor("right", item);
|
|
1206
|
-
}
|
|
1207
|
-
}
|
|
1208
|
-
}
|
|
1209
|
-
|
|
1210
|
-
/**
|
|
1211
|
-
* 获取指定id的下一个Item
|
|
1212
|
-
*
|
|
1213
|
-
* @public
|
|
1214
|
-
* @func GetNextItem
|
|
1215
|
-
* @memberof Forge.MetroLayout
|
|
1216
|
-
* @instance
|
|
1217
|
-
* @param {int} base_item_id Item的Id
|
|
1218
|
-
* @param {int} vertical_offset 纵向偏移(-1为向上,1为向下)
|
|
1219
|
-
* @param {int} horizontal_offset 横向偏移(-1为向左,1为向右)
|
|
1220
|
-
* @param {int} focus_move_type 焦点移动设置
|
|
1221
|
-
* @return {int} 下一个Item的Id,-1为该方向未找到Item(到达边缘)
|
|
1222
|
-
* */
|
|
1223
|
-
GetNextItem(
|
|
1224
|
-
base_item_id,
|
|
1225
|
-
vertical_offset,
|
|
1226
|
-
horizontal_offset,
|
|
1227
|
-
focus_move_type
|
|
1228
|
-
) {
|
|
1229
|
-
if (vertical_offset === 0 && horizontal_offset === 0)
|
|
1230
|
-
console.log("GetNextItem(): offset is 0");
|
|
1231
|
-
// Forge.ThrowError("GetNextItem(): offset is 0");
|
|
1232
|
-
|
|
1233
|
-
if (vertical_offset !== 0 && horizontal_offset !== 0) {
|
|
1234
|
-
console.log(
|
|
1235
|
-
"GetNextItem(): not support change vertical and horizontal at the same time"
|
|
1236
|
-
);
|
|
1237
|
-
// Forge.ThrowError("GetNextItem(): not support change vertical and horizontal and the same time");
|
|
1238
|
-
}
|
|
1239
|
-
|
|
1240
|
-
const item_index = this.IdToIndex(base_item_id);
|
|
1241
|
-
const offset = vertical_offset !== 0 ? vertical_offset : horizontal_offset;
|
|
1242
|
-
let next_template_item = this._GetNextItem(
|
|
1243
|
-
item_index,
|
|
1244
|
-
offset,
|
|
1245
|
-
vertical_offset !== 0
|
|
1246
|
-
);
|
|
1247
|
-
const is_vertical = this._Template.Orient.type === VERTICAL;
|
|
1248
|
-
|
|
1249
|
-
if (next_template_item === null) {
|
|
1250
|
-
// 在次方向的焦点移动才会loop
|
|
1251
|
-
if (
|
|
1252
|
-
is_vertical &&
|
|
1253
|
-
focus_move_type & FocusMoveType.ROW_LOOP &&
|
|
1254
|
-
horizontal_offset != 0
|
|
1255
|
-
) {
|
|
1256
|
-
next_template_item = this._GetNextLoopItem(
|
|
1257
|
-
item_index,
|
|
1258
|
-
horizontal_offset,
|
|
1259
|
-
is_vertical
|
|
1260
|
-
);
|
|
1261
|
-
} else if (
|
|
1262
|
-
!is_vertical &&
|
|
1263
|
-
focus_move_type & FocusMoveType.COLUMN_LOOP &&
|
|
1264
|
-
vertical_offset != 0
|
|
1265
|
-
) {
|
|
1266
|
-
next_template_item = this._GetNextLoopItem(
|
|
1267
|
-
item_index,
|
|
1268
|
-
vertical_offset,
|
|
1269
|
-
is_vertical
|
|
1270
|
-
);
|
|
1271
|
-
}
|
|
1272
|
-
}
|
|
1273
|
-
|
|
1274
|
-
if (next_template_item === null) {
|
|
1275
|
-
// 临近行的焦点移动
|
|
1276
|
-
if (
|
|
1277
|
-
vertical_offset != 0 &&
|
|
1278
|
-
focus_move_type & FocusMoveType.ROW_FIND_NEAR
|
|
1279
|
-
) {
|
|
1280
|
-
next_template_item = this._GetNearLineItem(item_index, vertical_offset, true);
|
|
1281
|
-
} else if (
|
|
1282
|
-
horizontal_offset != 0 &&
|
|
1283
|
-
focus_move_type & FocusMoveType.COLUMN_FIND_NEAR
|
|
1284
|
-
) {
|
|
1285
|
-
next_template_item = this._GetNearLineItem(item_index, horizontal_offset, false);
|
|
1286
|
-
}
|
|
1287
|
-
}
|
|
1288
|
-
|
|
1289
|
-
return next_template_item;
|
|
1290
|
-
}
|
|
1291
|
-
|
|
1292
|
-
_GetNextItem(index, offset, vertical) {
|
|
1293
|
-
const template_list = this._Template.List;
|
|
1294
|
-
const base_item = template_list[index];
|
|
1295
|
-
let check_anchor = -1;
|
|
1296
|
-
if (base_item.findNextAnchor) {
|
|
1297
|
-
//有自定义的 anchor
|
|
1298
|
-
// TODO 优化
|
|
1299
|
-
if (vertical) {
|
|
1300
|
-
if (offset > 0) {
|
|
1301
|
-
if (base_item.findNextAnchor.bottom) {
|
|
1302
|
-
check_anchor =
|
|
1303
|
-
base_item.xPos +
|
|
1304
|
-
base_item.findNextAnchor.bottom *
|
|
1305
|
-
(base_item.width + base_item.marginRight);
|
|
1306
|
-
}
|
|
1307
|
-
} else {
|
|
1308
|
-
if (base_item.findNextAnchor.top) {
|
|
1309
|
-
check_anchor =
|
|
1310
|
-
base_item.xPos +
|
|
1311
|
-
base_item.findNextAnchor.top *
|
|
1312
|
-
(base_item.width + base_item.marginRight);
|
|
1313
|
-
}
|
|
1314
|
-
}
|
|
1315
|
-
} else {
|
|
1316
|
-
if (offset > 0) {
|
|
1317
|
-
if (base_item.findNextAnchor.right) {
|
|
1318
|
-
check_anchor =
|
|
1319
|
-
base_item.yPos +
|
|
1320
|
-
base_item.findNextAnchor.right *
|
|
1321
|
-
(base_item.height + base_item.marginBottom);
|
|
1322
|
-
}
|
|
1323
|
-
} else {
|
|
1324
|
-
if (base_item.findNextAnchor.left) {
|
|
1325
|
-
check_anchor =
|
|
1326
|
-
base_item.yPos +
|
|
1327
|
-
base_item.findNextAnchor.left *
|
|
1328
|
-
(base_item.height + base_item.marginBottom);
|
|
1329
|
-
}
|
|
1330
|
-
}
|
|
1331
|
-
}
|
|
1332
|
-
}
|
|
1333
|
-
if (check_anchor < 0) {
|
|
1334
|
-
check_anchor = vertical ? base_item.centerXPos : base_item.centerYPos;
|
|
1335
|
-
}
|
|
1336
|
-
const pos_key = vertical ? "xPos" : "yPos";
|
|
1337
|
-
const size_key = vertical ? "width" : "height";
|
|
1338
|
-
let direction = vertical ? "top" : "left";
|
|
1339
|
-
let path_history_direction = vertical ? "bottom" : "right";
|
|
1340
|
-
// Normalize offset
|
|
1341
|
-
if (offset > 0) {
|
|
1342
|
-
path_history_direction = vertical ? "top" : "left";
|
|
1343
|
-
direction = vertical ? "bottom" : "right";
|
|
1344
|
-
}
|
|
1345
|
-
const not_record_history_direction = vertical ? "bottom" : "right";
|
|
1346
|
-
const not_record_history_orient = vertical ? HORIZONTAL : VERTICAL;
|
|
1347
|
-
let last_item_index = template_list.length - 1;
|
|
1348
|
-
const orient_type = this._Template.Orient.type;
|
|
1349
|
-
// 查找有效的最后项
|
|
1350
|
-
for (let i = template_list.length - 1; i >= 0; i--) {
|
|
1351
|
-
const last_item = template_list[i];
|
|
1352
|
-
if (last_item.focusable) {
|
|
1353
|
-
last_item_index = i;
|
|
1354
|
-
break;
|
|
1355
|
-
}
|
|
1356
|
-
}
|
|
1357
|
-
let found = false;
|
|
1358
|
-
let next_index = -1;
|
|
1359
|
-
let path_history_index = null;
|
|
1360
|
-
if (this._SupportHistoryPath && !base_item.findNextAnchor) {
|
|
1361
|
-
path_history_index = template_list[index].pathHistory[direction];
|
|
1362
|
-
}
|
|
1363
|
-
if (path_history_index === null) {
|
|
1364
|
-
// 无历史路径
|
|
1365
|
-
// 获得邻近点列表
|
|
1366
|
-
let neighbor_list = template_list[index].neighborIndexList[direction];
|
|
1367
|
-
if (template_list[index].tmpNeighborIndexList[direction].length > 0) {
|
|
1368
|
-
neighbor_list = neighbor_list.concat(
|
|
1369
|
-
template_list[index].tmpNeighborIndexList[direction]
|
|
1370
|
-
);
|
|
1371
|
-
}
|
|
1372
|
-
if (neighbor_list.length === 1) {
|
|
1373
|
-
next_index = neighbor_list[0];
|
|
1374
|
-
if (
|
|
1375
|
-
last_item_index !== index ||
|
|
1376
|
-
direction !== not_record_history_direction ||
|
|
1377
|
-
orient_type !== not_record_history_orient
|
|
1378
|
-
) {
|
|
1379
|
-
// horizontal last_item_index bottom 不记历史路径
|
|
1380
|
-
template_list[index].pathHistory[direction] = next_index; // 更新历史路径
|
|
1381
|
-
template_list[next_index].pathHistory[path_history_direction] = index; // 更新历史路径
|
|
1382
|
-
}
|
|
1383
|
-
found = true;
|
|
1384
|
-
} else {
|
|
1385
|
-
for (let i = 0; i < neighbor_list.length; i++) {
|
|
1386
|
-
next_index = neighbor_list[i];
|
|
1387
|
-
const checking_item = template_list[next_index];
|
|
1388
|
-
if (
|
|
1389
|
-
check_anchor <=
|
|
1390
|
-
checking_item[pos_key] + checking_item[size_key] - 1 &&
|
|
1391
|
-
check_anchor >= checking_item[pos_key]
|
|
1392
|
-
) {
|
|
1393
|
-
if (
|
|
1394
|
-
last_item_index !== index ||
|
|
1395
|
-
direction !== not_record_history_direction ||
|
|
1396
|
-
orient_type !== not_record_history_orient
|
|
1397
|
-
) {
|
|
1398
|
-
// horizontal last_item_index bottom 不记历史路径
|
|
1399
|
-
template_list[index].pathHistory[direction] = next_index; // 更新历史路径
|
|
1400
|
-
template_list[next_index].pathHistory[path_history_direction] =
|
|
1401
|
-
index; // 更新历史路径
|
|
1402
|
-
}
|
|
1403
|
-
found = true;
|
|
1404
|
-
break;
|
|
1405
|
-
}
|
|
1406
|
-
}
|
|
1407
|
-
// 若未找到中间位置的项目
|
|
1408
|
-
// 若找到了项目,但是该项为非 focusable
|
|
1409
|
-
// 则使用neighbor list中focusable项
|
|
1410
|
-
if (!found || !template_list[next_index].focusable) {
|
|
1411
|
-
for (let i = 0; i < neighbor_list.length; i++) {
|
|
1412
|
-
const neighbor_index = neighbor_list[i];
|
|
1413
|
-
const checking_item = template_list[neighbor_index];
|
|
1414
|
-
if (checking_item.focusable) {
|
|
1415
|
-
if (
|
|
1416
|
-
last_item_index !== index ||
|
|
1417
|
-
direction !== not_record_history_direction ||
|
|
1418
|
-
orient_type !== not_record_history_orient
|
|
1419
|
-
) {
|
|
1420
|
-
// horizontal last_item_index bottom 不记历史路径
|
|
1421
|
-
template_list[index].pathHistory[direction] = next_index; // 更新历史路径
|
|
1422
|
-
template_list[next_index].pathHistory[path_history_direction] =
|
|
1423
|
-
index; // 更新历史路径
|
|
1424
|
-
}
|
|
1425
|
-
next_index = neighbor_index;
|
|
1426
|
-
found = true;
|
|
1427
|
-
break;
|
|
1428
|
-
}
|
|
1429
|
-
}
|
|
1430
|
-
}
|
|
1431
|
-
}
|
|
1432
|
-
} else {
|
|
1433
|
-
next_index = path_history_index;
|
|
1434
|
-
if (
|
|
1435
|
-
last_item_index !== index ||
|
|
1436
|
-
direction !== not_record_history_direction ||
|
|
1437
|
-
orient_type !== not_record_history_orient
|
|
1438
|
-
) {
|
|
1439
|
-
// horizontal last_item_index bottom 不记历史路径
|
|
1440
|
-
template_list[next_index].pathHistory[path_history_direction] = index; // 更新历史路径
|
|
1441
|
-
}
|
|
1442
|
-
found = true;
|
|
1443
|
-
}
|
|
1444
|
-
|
|
1445
|
-
if (found) {
|
|
1446
|
-
if (!template_list[next_index].focusable) {
|
|
1447
|
-
// 如果是占位符,则查找占位符的下一个
|
|
1448
|
-
return this._GetNextItem(next_index, offset, vertical);
|
|
1449
|
-
}
|
|
1450
|
-
return template_list[next_index];
|
|
1451
|
-
}
|
|
1452
|
-
return null;
|
|
1453
|
-
}
|
|
1454
|
-
|
|
1455
|
-
_GetItemDistance(item1, item2) {
|
|
1456
|
-
return (
|
|
1457
|
-
Math.pow(item1.centerXPos - item2.centerXPos, 2) +
|
|
1458
|
-
Math.pow(item1.centerYPos - item2.centerYPos, 2)
|
|
1459
|
-
);
|
|
1460
|
-
}
|
|
1461
|
-
|
|
1462
|
-
_GetTotalNeighbor(index, direction) {
|
|
1463
|
-
const item = this._Template.List[index];
|
|
1464
|
-
return item.neighborIndexList[direction].concat(
|
|
1465
|
-
item.tmpNeighborIndexList[direction]
|
|
1466
|
-
);
|
|
1467
|
-
}
|
|
1468
|
-
|
|
1469
|
-
_GetNearestItem(target_item_index, item_index_list) {
|
|
1470
|
-
let nearest_index = -1,
|
|
1471
|
-
min_distance = Number.POSITIVE_INFINITY;
|
|
1472
|
-
let target_item = this._Template.List[target_item_index];
|
|
1473
|
-
for (let i of item_index_list) {
|
|
1474
|
-
const d = this._GetItemDistance(this._Template.List[i], target_item);
|
|
1475
|
-
if (d < min_distance) {
|
|
1476
|
-
nearest_index = i;
|
|
1477
|
-
min_distance = d;
|
|
1478
|
-
}
|
|
1479
|
-
}
|
|
1480
|
-
return nearest_index;
|
|
1481
|
-
}
|
|
1482
|
-
|
|
1483
|
-
_GetNextLoopItem(index, offset, is_vertical) {
|
|
1484
|
-
const template_list = this._Template.List;
|
|
1485
|
-
const base_item = template_list[index];
|
|
1486
|
-
let search_direction = is_vertical ? "right" : "bottom";
|
|
1487
|
-
let start_direction = is_vertical ? "top" : "left";
|
|
1488
|
-
if (offset > 0) {
|
|
1489
|
-
search_direction = is_vertical ? "left" : "top";
|
|
1490
|
-
start_direction = is_vertical ? "bottom" : "right";
|
|
1491
|
-
}
|
|
1492
|
-
let target_index = -1;
|
|
1493
|
-
let focusable_target = -1;
|
|
1494
|
-
let start_index = -1;
|
|
1495
|
-
let neighbor_list = [];
|
|
1496
|
-
//寻找下一列的起始item
|
|
1497
|
-
neighbor_list = this._GetTotalNeighbor(index, search_direction);
|
|
1498
|
-
while (start_index < 0 && neighbor_list.length > 0) {
|
|
1499
|
-
for (let i of neighbor_list) {
|
|
1500
|
-
if (this._GetTotalNeighbor(i, start_direction).length > 0) {
|
|
1501
|
-
start_index = i;
|
|
1502
|
-
break;
|
|
1503
|
-
} else {
|
|
1504
|
-
//TODO 是否要用递归
|
|
1505
|
-
neighbor_list = this._GetTotalNeighbor(i, search_direction);
|
|
1506
|
-
}
|
|
1507
|
-
}
|
|
1508
|
-
}
|
|
1509
|
-
if (start_index >= 0) {
|
|
1510
|
-
neighbor_list = this._GetTotalNeighbor(start_index, start_direction);
|
|
1511
|
-
|
|
1512
|
-
//寻找最近的neighbor
|
|
1513
|
-
let nearest_index = -1,
|
|
1514
|
-
min_distance = Number.POSITIVE_INFINITY;
|
|
1515
|
-
for (let i of neighbor_list) {
|
|
1516
|
-
const d = this._GetItemDistance(template_list[i], base_item);
|
|
1517
|
-
if (d < min_distance) {
|
|
1518
|
-
nearest_index = i;
|
|
1519
|
-
min_distance = d;
|
|
1520
|
-
}
|
|
1521
|
-
}
|
|
1522
|
-
|
|
1523
|
-
neighbor_list = this._GetTotalNeighbor(nearest_index, search_direction);
|
|
1524
|
-
while (neighbor_list.length > 0) {
|
|
1525
|
-
target_index = this._GetNearestItem(nearest_index, neighbor_list);
|
|
1526
|
-
if (template_list[target_index].focusable) {
|
|
1527
|
-
focusable_target = target_index;
|
|
1528
|
-
}
|
|
1529
|
-
neighbor_list = this._GetTotalNeighbor(target_index, search_direction);
|
|
1530
|
-
}
|
|
1531
|
-
if (focusable_target >= 0) {
|
|
1532
|
-
return template_list[focusable_target];
|
|
1533
|
-
} else if (target_index >= 0) {
|
|
1534
|
-
return this._GetNextLoopItem(target_index, offset, is_vertical);
|
|
1535
|
-
}
|
|
1536
|
-
}
|
|
1537
|
-
return null;
|
|
1538
|
-
}
|
|
1539
|
-
|
|
1540
|
-
//获取临近行的item
|
|
1541
|
-
_GetNearLineItem(index, offset, is_vertical) {
|
|
1542
|
-
const template_list = this._Template.List;
|
|
1543
|
-
let search_direction = is_vertical ? "right" : "bottom";
|
|
1544
|
-
let start_direction = is_vertical ? "top" : "left";
|
|
1545
|
-
if (offset > 0) {
|
|
1546
|
-
search_direction = is_vertical ? "left" : "top";
|
|
1547
|
-
start_direction = is_vertical ? "bottom" : "right";
|
|
1548
|
-
}
|
|
1549
|
-
let start_index = -1;
|
|
1550
|
-
let neighbor_list = [];
|
|
1551
|
-
//寻找下一列的起始item
|
|
1552
|
-
neighbor_list = this._GetTotalNeighbor(index, search_direction);
|
|
1553
|
-
while (start_index < 0 && neighbor_list.length > 0) {
|
|
1554
|
-
for (let i of neighbor_list) {
|
|
1555
|
-
const n = this._GetTotalNeighbor(i, start_direction);
|
|
1556
|
-
if (n.length > 0) {
|
|
1557
|
-
return template_list[this._GetNearestItem(index, n)];
|
|
1558
|
-
} else {
|
|
1559
|
-
//TODO 是否要用递归
|
|
1560
|
-
neighbor_list = this._GetTotalNeighbor(i, search_direction);
|
|
1561
|
-
}
|
|
1562
|
-
}
|
|
1563
|
-
}
|
|
1564
|
-
return null;
|
|
1565
|
-
}
|
|
1566
|
-
|
|
1567
|
-
GetTemplate() {
|
|
1568
|
-
return this._Template;
|
|
1569
|
-
}
|
|
1570
|
-
|
|
1571
|
-
GetVisibleItemList(visibleStartLine, visibleEndLine, search_base_item) {
|
|
1572
|
-
if (visibleStartLine > visibleEndLine) {
|
|
1573
|
-
// No visible item
|
|
1574
|
-
return null;
|
|
1575
|
-
}
|
|
1576
|
-
//取整以避免starline和endline找不到骑线的item的bug
|
|
1577
|
-
visibleStartLine = Math.round(visibleStartLine);
|
|
1578
|
-
visibleEndLine = Math.round(visibleEndLine);
|
|
1579
|
-
// let search_base_item = this._VisibleRangeSearchBaseItem;
|
|
1580
|
-
// if (search_base_item ===null) {
|
|
1581
|
-
// search_base_item = this._Template.List[this._Template.IdsMap[0]];
|
|
1582
|
-
// }
|
|
1583
|
-
let search_base_item_idx = this._Template.IdsMap[search_base_item];
|
|
1584
|
-
if (typeof search_base_item_idx === "undefined") search_base_item_idx = 0;
|
|
1585
|
-
const common_data = {
|
|
1586
|
-
resultStartIdx: -1,
|
|
1587
|
-
resultEndIdx: -1,
|
|
1588
|
-
enableBackwardSearching: true,
|
|
1589
|
-
enableForwardSearching: true,
|
|
1590
|
-
checkingStartLinePos: visibleStartLine,
|
|
1591
|
-
checkingEndLinePos: visibleEndLine,
|
|
1592
|
-
};
|
|
1593
|
-
const backward_configure = {
|
|
1594
|
-
searchDirect: -1,
|
|
1595
|
-
baseIdx: search_base_item_idx,
|
|
1596
|
-
checkingStartLineRanges: new RangesModel(),
|
|
1597
|
-
startLineRangesFulled: false,
|
|
1598
|
-
latestOverStartLineIdx: -1,
|
|
1599
|
-
checkingEndLineRanges: new RangesModel(),
|
|
1600
|
-
endLineRangesFulled: false,
|
|
1601
|
-
latestOverEndLineIdx: -1,
|
|
1602
|
-
endSearchingIndex: 0,
|
|
1603
|
-
firstStartLineBlockIdx: -1,
|
|
1604
|
-
firstEndLineBlockIdx: -1,
|
|
1605
|
-
searchToBorder: false,
|
|
1606
|
-
common: common_data,
|
|
1607
|
-
};
|
|
1608
|
-
const forward_configure = {
|
|
1609
|
-
searchDirect: 1,
|
|
1610
|
-
baseIdx: search_base_item_idx,
|
|
1611
|
-
checkingStartLineRanges: new RangesModel(),
|
|
1612
|
-
startLineRangesFulled: false,
|
|
1613
|
-
latestOverStartLineIdx: -1,
|
|
1614
|
-
checkingEndLineRanges: new RangesModel(),
|
|
1615
|
-
endLineRangesFulled: false,
|
|
1616
|
-
latestOverEndLineIdx: -1,
|
|
1617
|
-
endSearchingIndex: this._Template.List.length - 1,
|
|
1618
|
-
firstStartLineBlockIdx: -1,
|
|
1619
|
-
firstEndLineBlockIdx: -1,
|
|
1620
|
-
searchToBorder: false,
|
|
1621
|
-
common: common_data,
|
|
1622
|
-
};
|
|
1623
|
-
|
|
1624
|
-
const is_template_vertical = this._Template.Orient.type === VERTICAL;
|
|
1625
|
-
let offset = 0;
|
|
1626
|
-
while (
|
|
1627
|
-
common_data.enableBackwardSearching ||
|
|
1628
|
-
common_data.enableForwardSearching
|
|
1629
|
-
) {
|
|
1630
|
-
if (common_data.enableBackwardSearching) {
|
|
1631
|
-
this._DoSearching(backward_configure, -offset, is_template_vertical);
|
|
1632
|
-
}
|
|
1633
|
-
|
|
1634
|
-
if (common_data.enableForwardSearching) {
|
|
1635
|
-
this._DoSearching(forward_configure, offset, is_template_vertical);
|
|
1636
|
-
}
|
|
1637
|
-
offset++;
|
|
1638
|
-
}
|
|
1639
|
-
// console.log(
|
|
1640
|
-
// "GetVisibleItemList [" +
|
|
1641
|
-
// JSON.stringify(common_data) +
|
|
1642
|
-
// ", " +
|
|
1643
|
-
// JSON.stringify(backward_configure) +
|
|
1644
|
-
// ", " +
|
|
1645
|
-
// JSON.stringify(forward_configure) +
|
|
1646
|
-
// "]"
|
|
1647
|
-
// );
|
|
1648
|
-
|
|
1649
|
-
if (common_data.resultStartIdx < 0) {
|
|
1650
|
-
// When start index not found
|
|
1651
|
-
// Use just over start line block as start idx
|
|
1652
|
-
if (
|
|
1653
|
-
backward_configure.latestOverStartLineIdx >= 0 &&
|
|
1654
|
-
backward_configure.firstStartLineBlockIdx >= 0
|
|
1655
|
-
)
|
|
1656
|
-
common_data.resultStartIdx = backward_configure.latestOverStartLineIdx;
|
|
1657
|
-
else if (forward_configure.firstStartLineBlockIdx >= 0)
|
|
1658
|
-
common_data.resultStartIdx = forward_configure.firstStartLineBlockIdx;
|
|
1659
|
-
}
|
|
1660
|
-
|
|
1661
|
-
if (common_data.resultEndIdx < 0) {
|
|
1662
|
-
// When end index not found
|
|
1663
|
-
// Use just over end line block as end idx
|
|
1664
|
-
if (
|
|
1665
|
-
forward_configure.latestOverEndLineIdx >= 0 &&
|
|
1666
|
-
forward_configure.firstEndLineBlockIdx >= 0
|
|
1667
|
-
)
|
|
1668
|
-
common_data.resultEndIdx = forward_configure.latestOverEndLineIdx;
|
|
1669
|
-
else if (backward_configure.firstEndLineBlockIdx >= 0)
|
|
1670
|
-
common_data.resultEndIdx = backward_configure.firstEndLineBlockIdx;
|
|
1671
|
-
}
|
|
1672
|
-
// Recheck if whole contents inside the range
|
|
1673
|
-
if (common_data.resultStartIdx < 0 && common_data.resultEndIdx < 0) {
|
|
1674
|
-
// Check if whole contents inside the range
|
|
1675
|
-
const first_item = this._Template.List[0];
|
|
1676
|
-
const first_second_pos = is_template_vertical
|
|
1677
|
-
? first_item.yPos
|
|
1678
|
-
: first_item.xPos;
|
|
1679
|
-
const last_item = this._Template.List[this._Template.List.length - 1];
|
|
1680
|
-
const last_second_pos = is_template_vertical
|
|
1681
|
-
? last_item.yPos
|
|
1682
|
-
: last_item.xPos;
|
|
1683
|
-
const last_second_width = is_template_vertical
|
|
1684
|
-
? last_item.height
|
|
1685
|
-
: last_item.width;
|
|
1686
|
-
if (
|
|
1687
|
-
first_second_pos > visibleStartLine &&
|
|
1688
|
-
last_second_pos + last_second_width < visibleEndLine
|
|
1689
|
-
) {
|
|
1690
|
-
common_data.resultStartIdx = 0;
|
|
1691
|
-
common_data.resultEndIdx = this._Template.List.length - 1;
|
|
1692
|
-
}
|
|
1693
|
-
}
|
|
1694
|
-
let ret = null;
|
|
1695
|
-
if (common_data.resultStartIdx >= 0 || common_data.resultEndIdx >= 0) {
|
|
1696
|
-
const start_idx =
|
|
1697
|
-
common_data.resultStartIdx >= 0 ? common_data.resultStartIdx : 0;
|
|
1698
|
-
const end_idx =
|
|
1699
|
-
common_data.resultEndIdx >= 0
|
|
1700
|
-
? common_data.resultEndIdx
|
|
1701
|
-
: this._Template.List.length - 1;
|
|
1702
|
-
ret = { visibleStart: start_idx, visibleEnd: end_idx };
|
|
1703
|
-
}
|
|
1704
|
-
return ret;
|
|
1705
|
-
}
|
|
1706
|
-
|
|
1707
|
-
_DoSearching(configures, offset, be_vertical_template) {
|
|
1708
|
-
const check_item = this._Template.List[configures.baseIdx + offset];
|
|
1709
|
-
const key_pos = be_vertical_template ? check_item.xPos : check_item.yPos;
|
|
1710
|
-
const key_width = be_vertical_template
|
|
1711
|
-
? check_item.width + check_item.marginRight
|
|
1712
|
-
: check_item.height + check_item.marginBottom;
|
|
1713
|
-
const key_start = Math.round(key_pos);
|
|
1714
|
-
const key_end = Math.round(key_pos + key_width - 1);
|
|
1715
|
-
const second_pos = be_vertical_template ? check_item.yPos : check_item.xPos;
|
|
1716
|
-
const second_width = be_vertical_template
|
|
1717
|
-
? check_item.height + check_item.marginBottom
|
|
1718
|
-
: check_item.width + check_item.marginRight;
|
|
1719
|
-
const second_start = Math.round(second_pos);
|
|
1720
|
-
const second_end = Math.round(second_pos + second_width - 1);
|
|
1721
|
-
// console.log(
|
|
1722
|
-
// "idx=" +
|
|
1723
|
-
// (configures.baseIdx + offset) +
|
|
1724
|
-
// " pos=" +
|
|
1725
|
-
// second_pos +
|
|
1726
|
-
// " posend=" +
|
|
1727
|
-
// (second_pos + second_width - 1) +
|
|
1728
|
-
// " line_pos=" +
|
|
1729
|
-
// configures.common.checkingStartLinePos
|
|
1730
|
-
// );
|
|
1731
|
-
|
|
1732
|
-
if (
|
|
1733
|
-
configures.common.resultStartIdx < 0 &&
|
|
1734
|
-
!configures.startLineRangesFulled
|
|
1735
|
-
) {
|
|
1736
|
-
let is_range_changed = false;
|
|
1737
|
-
if (
|
|
1738
|
-
second_start <= configures.common.checkingStartLinePos &&
|
|
1739
|
-
second_end >= configures.common.checkingStartLinePos
|
|
1740
|
-
) {
|
|
1741
|
-
// Overlap the visbible start line
|
|
1742
|
-
configures.latestOverStartLineIdx = configures.baseIdx + offset;
|
|
1743
|
-
if (configures.firstStartLineBlockIdx < 0)
|
|
1744
|
-
configures.firstStartLineBlockIdx = configures.baseIdx + offset;
|
|
1745
|
-
configures.checkingStartLineRanges.Merge(
|
|
1746
|
-
new SingleRangeModel(key_start, key_end)
|
|
1747
|
-
);
|
|
1748
|
-
is_range_changed = true;
|
|
1749
|
-
} else if (
|
|
1750
|
-
configures.searchDirect < 0 &&
|
|
1751
|
-
second_end <= configures.common.checkingStartLinePos
|
|
1752
|
-
) {
|
|
1753
|
-
// above the visible start line
|
|
1754
|
-
configures.checkingStartLineRanges.Merge(
|
|
1755
|
-
new SingleRangeModel(key_start, key_end)
|
|
1756
|
-
);
|
|
1757
|
-
is_range_changed = true;
|
|
1758
|
-
}
|
|
1759
|
-
|
|
1760
|
-
if (is_range_changed) {
|
|
1761
|
-
const current_acrossed_range =
|
|
1762
|
-
configures.checkingStartLineRanges.Ranges[0];
|
|
1763
|
-
if (current_acrossed_range) {
|
|
1764
|
-
if (this.DebugPrint) {
|
|
1765
|
-
if (
|
|
1766
|
-
current_acrossed_range.Start <= 0 &&
|
|
1767
|
-
current_acrossed_range.End >= this._Template.Orient.widthMax - 1
|
|
1768
|
-
) {
|
|
1769
|
-
if (
|
|
1770
|
-
current_acrossed_range.End >
|
|
1771
|
-
this._Template.Orient.widthMax - 1 ||
|
|
1772
|
-
current_acrossed_range.Start < 0
|
|
1773
|
-
) {
|
|
1774
|
-
configures.startLineRangesFulled = true;
|
|
1775
|
-
}
|
|
1776
|
-
|
|
1777
|
-
// Update result start index
|
|
1778
|
-
if (configures.searchDirect > 0)
|
|
1779
|
-
configures.common.resultStartIdx =
|
|
1780
|
-
configures.firstStartLineBlockIdx;
|
|
1781
|
-
else
|
|
1782
|
-
configures.common.resultStartIdx =
|
|
1783
|
-
configures.latestOverStartLineIdx;
|
|
1784
|
-
|
|
1785
|
-
if (configures.common.resultStartIdx >= 0)
|
|
1786
|
-
configures.common.enableBackwardSearching = false;
|
|
1787
|
-
}
|
|
1788
|
-
}
|
|
1789
|
-
}
|
|
1790
|
-
}
|
|
1791
|
-
}
|
|
1792
|
-
// console.log(
|
|
1793
|
-
// "idx=" +
|
|
1794
|
-
// (configures.baseIdx + offset) +
|
|
1795
|
-
// " pos=" +
|
|
1796
|
-
// second_pos +
|
|
1797
|
-
// " posend=" +
|
|
1798
|
-
// (second_pos + second_width - 1) +
|
|
1799
|
-
// " line_pos=" +
|
|
1800
|
-
// configures.common.checkingEndLinePos
|
|
1801
|
-
// );
|
|
1802
|
-
if (configures.common.resultEndIdx < 0 && !configures.endLineRangesFulled) {
|
|
1803
|
-
let is_range_changed = false;
|
|
1804
|
-
if (
|
|
1805
|
-
second_start <= configures.common.checkingEndLinePos &&
|
|
1806
|
-
second_end >= configures.common.checkingEndLinePos
|
|
1807
|
-
) {
|
|
1808
|
-
// Overlap the visbible end line
|
|
1809
|
-
configures.latestOverEndLineIdx = configures.baseIdx + offset;
|
|
1810
|
-
if (configures.firstEndLineBlockIdx < 0)
|
|
1811
|
-
configures.firstEndLineBlockIdx = configures.baseIdx + offset;
|
|
1812
|
-
configures.checkingEndLineRanges.Merge(
|
|
1813
|
-
new SingleRangeModel(key_start, key_end)
|
|
1814
|
-
);
|
|
1815
|
-
is_range_changed = true;
|
|
1816
|
-
} else if (
|
|
1817
|
-
configures.searchDirect > 0 &&
|
|
1818
|
-
second_start >= configures.common.checkingEndLinePos
|
|
1819
|
-
) {
|
|
1820
|
-
// below the visible end line
|
|
1821
|
-
configures.checkingEndLineRanges.Merge(
|
|
1822
|
-
new SingleRangeModel(key_start, key_end)
|
|
1823
|
-
);
|
|
1824
|
-
is_range_changed = true;
|
|
1825
|
-
}
|
|
1826
|
-
|
|
1827
|
-
if (is_range_changed) {
|
|
1828
|
-
const current_acrossed_range =
|
|
1829
|
-
configures.checkingEndLineRanges.Ranges[0];
|
|
1830
|
-
if (current_acrossed_range) {
|
|
1831
|
-
if (this.DebugPrint) {
|
|
1832
|
-
if (
|
|
1833
|
-
current_acrossed_range.Start <= 0 &&
|
|
1834
|
-
current_acrossed_range.End >= this._Template.Orient.widthMax - 1
|
|
1835
|
-
) {
|
|
1836
|
-
if (
|
|
1837
|
-
current_acrossed_range.End >
|
|
1838
|
-
this._Template.Orient.widthMax - 1 ||
|
|
1839
|
-
current_acrossed_range.Start < 0
|
|
1840
|
-
) {
|
|
1841
|
-
configures.endLineRangesFulled = true;
|
|
1842
|
-
}
|
|
1843
|
-
|
|
1844
|
-
// Update end index
|
|
1845
|
-
if (configures.searchDirect < 0)
|
|
1846
|
-
configures.common.resultEndIdx =
|
|
1847
|
-
configures.firstEndLineBlockIdx;
|
|
1848
|
-
else
|
|
1849
|
-
configures.common.resultEndIdx =
|
|
1850
|
-
configures.latestOverEndLineIdx;
|
|
1851
|
-
|
|
1852
|
-
if (configures.common.resultEndIdx >= 0)
|
|
1853
|
-
configures.common.enableForwardSearching = false;
|
|
1854
|
-
}
|
|
1855
|
-
}
|
|
1856
|
-
}
|
|
1857
|
-
}
|
|
1858
|
-
}
|
|
1859
|
-
if (configures.baseIdx + offset === configures.endSearchingIndex) {
|
|
1860
|
-
if (configures.searchDirect > 0) {
|
|
1861
|
-
configures.common.enableForwardSearching = false;
|
|
1862
|
-
} else {
|
|
1863
|
-
configures.common.enableBackwardSearching = false;
|
|
1864
|
-
}
|
|
1865
|
-
configures.searchToBorder = true;
|
|
1866
|
-
}
|
|
1867
|
-
}
|
|
1868
|
-
}
|
|
1869
|
-
|
|
1870
|
-
class TemplateItemAdder {
|
|
1871
|
-
constructor(
|
|
1872
|
-
template_parser,
|
|
1873
|
-
data,
|
|
1874
|
-
measure_func,
|
|
1875
|
-
page_range,
|
|
1876
|
-
side_effect,
|
|
1877
|
-
id
|
|
1878
|
-
) {
|
|
1879
|
-
this._TemplateParser = template_parser;
|
|
1880
|
-
this._Data = data;
|
|
1881
|
-
this._PageRange = page_range;
|
|
1882
|
-
this._MeasureFunc = measure_func;
|
|
1883
|
-
this._CurIndex = 0;
|
|
1884
|
-
this._CurPage = 0;
|
|
1885
|
-
this._KeyIndex = 0; //分页处的item
|
|
1886
|
-
this._SideEffect = side_effect;
|
|
1887
|
-
this._Key =
|
|
1888
|
-
this._TemplateParser._Template.Orient.type === HORIZONTAL
|
|
1889
|
-
? "xPos"
|
|
1890
|
-
: "yPos";
|
|
1891
|
-
this._ID = id;
|
|
1892
|
-
}
|
|
1893
|
-
|
|
1894
|
-
tryAddItem(cur_item = null, page_num = 1) {
|
|
1895
|
-
let added = false;
|
|
1896
|
-
if (
|
|
1897
|
-
this._CurIndex < this._Data.length &&
|
|
1898
|
-
(!cur_item ||
|
|
1899
|
-
cur_item[this._Key] >= (this._CurPage - 1) * this._PageRange)
|
|
1900
|
-
) {
|
|
1901
|
-
while (this._CurIndex < this._Data.length) {
|
|
1902
|
-
try {
|
|
1903
|
-
let item = this._TemplateParser.ParseTemplateItem(
|
|
1904
|
-
this._MeasureFunc(this._Data[this._CurIndex]),
|
|
1905
|
-
this._Data[this._CurIndex]
|
|
1906
|
-
);
|
|
1907
|
-
this._SideEffect?.(item);
|
|
1908
|
-
this._CurIndex++;
|
|
1909
|
-
if (item[this._Key] >= (this._CurPage + page_num) * this._PageRange) {
|
|
1910
|
-
this._CurPage += page_num;
|
|
1911
|
-
break;
|
|
1912
|
-
}
|
|
1913
|
-
} catch (e) {
|
|
1914
|
-
console.error(
|
|
1915
|
-
`MetroWidget: ${this._ID} parse template item ${this._CurIndex} failed. data: `,
|
|
1916
|
-
this._Data
|
|
1917
|
-
);
|
|
1918
|
-
throw e;
|
|
1919
|
-
}
|
|
1920
|
-
}
|
|
1921
|
-
this._TemplateParser.CalculateNeighborWhenAddStop();
|
|
1922
|
-
added = true;
|
|
1923
|
-
}
|
|
1924
|
-
// 添加完成需要计算neighbor
|
|
1925
|
-
return added;
|
|
1926
|
-
}
|
|
1927
|
-
|
|
1928
|
-
tryAddItemByPosition(position) {
|
|
1929
|
-
const page_num = Math.ceil(position / this._PageRange + 1);
|
|
1930
|
-
if (page_num > this._CurPage) {
|
|
1931
|
-
this.tryAddItem(null, page_num - this._CurPage);
|
|
1932
|
-
}
|
|
1933
|
-
}
|
|
1934
|
-
|
|
1935
|
-
tryAddItemByIndex(index) {
|
|
1936
|
-
let _index = Math.min(index, this._Data.length - 1);
|
|
1937
|
-
let added = false;
|
|
1938
|
-
while (this._CurIndex <= _index) {
|
|
1939
|
-
added = true;
|
|
1940
|
-
try {
|
|
1941
|
-
let item = this._TemplateParser.ParseTemplateItem(
|
|
1942
|
-
this._MeasureFunc(this._Data[this._CurIndex]),
|
|
1943
|
-
this._Data[this._CurIndex]
|
|
1944
|
-
);
|
|
1945
|
-
this._SideEffect?.(item);
|
|
1946
|
-
this._CurIndex++;
|
|
1947
|
-
if (item[this._Key] >= (this._CurPage + 1) * this._PageRange) {
|
|
1948
|
-
this._CurPage++;
|
|
1949
|
-
}
|
|
1950
|
-
} catch (e) {
|
|
1951
|
-
console.error(
|
|
1952
|
-
`MetroWidget: ${this._ID} parse template item ${this._CurIndex} failed. data:`,
|
|
1953
|
-
this._Data
|
|
1954
|
-
);
|
|
1955
|
-
throw e;
|
|
1956
|
-
}
|
|
1957
|
-
}
|
|
1958
|
-
if (added) {
|
|
1959
|
-
this._TemplateParser.CalculateNeighborWhenAddStop();
|
|
1960
|
-
}
|
|
1961
|
-
//再添加一屏
|
|
1962
|
-
this.tryAddItem(this._TemplateParser.GetItem(index), 2);
|
|
1963
|
-
}
|
|
1964
|
-
|
|
1965
|
-
tryAddItemById(id) {
|
|
1966
|
-
let _id = Math.min(id, this._Data.length - 1); // id小于等于index, 因此为了避免过界取小值
|
|
1967
|
-
const last_id = this._TemplateParser.GetLastId();
|
|
1968
|
-
if (last_id < _id) {
|
|
1969
|
-
let added = false;
|
|
1970
|
-
let cur_id = last_id;
|
|
1971
|
-
while (cur_id < _id && this._CurIndex < this._Data.length) {
|
|
1972
|
-
added = true;
|
|
1973
|
-
try {
|
|
1974
|
-
const item = this._TemplateParser.ParseTemplateItem(
|
|
1975
|
-
this._MeasureFunc(this._Data[this._CurIndex]),
|
|
1976
|
-
this._Data[this._CurIndex]
|
|
1977
|
-
);
|
|
1978
|
-
cur_id = item.id;
|
|
1979
|
-
this._SideEffect?.(item);
|
|
1980
|
-
if (item[this._Key] >= (this._CurPage + 1) * this._PageRange) {
|
|
1981
|
-
this._CurPage++;
|
|
1982
|
-
}
|
|
1983
|
-
this._CurIndex++;
|
|
1984
|
-
} catch (e) {
|
|
1985
|
-
console.error(
|
|
1986
|
-
`MetroWidget: ${this._ID} parse template item ${this._CurIndex} failed. data:`,
|
|
1987
|
-
this._Data
|
|
1988
|
-
);
|
|
1989
|
-
throw e;
|
|
1990
|
-
}
|
|
1991
|
-
}
|
|
1992
|
-
if (added) {
|
|
1993
|
-
this._TemplateParser.CalculateNeighborWhenAddStop();
|
|
1994
|
-
}
|
|
1995
|
-
}
|
|
1996
|
-
//再添加一屏
|
|
1997
|
-
this.tryAddItem(this._TemplateParser.GetItemById(id), 2);
|
|
1998
|
-
}
|
|
1999
|
-
|
|
2000
|
-
updateData(data) {
|
|
2001
|
-
this._Data = data;
|
|
2002
|
-
}
|
|
2003
|
-
}
|
|
2004
|
-
export { TemplateParser, TemplateItemAdder };
|