@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,135 @@
|
|
|
1
|
+
interface GapInfo {
|
|
2
|
+
readonly GapStart: number,
|
|
3
|
+
readonly GapEnd: number,
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
class Fence {
|
|
7
|
+
/**
|
|
8
|
+
* MetroLayout用于计算使用区域的Fence(栅栏)
|
|
9
|
+
*
|
|
10
|
+
* @private
|
|
11
|
+
* @constructor _Fence
|
|
12
|
+
* @memberof Forge.MetroLayout
|
|
13
|
+
* @param {int} takenStartPos 栅栏使用区域的起始位置
|
|
14
|
+
* @param {int} width 栅栏使用区域的宽度
|
|
15
|
+
* @param {int} fenceWidth 栅栏的总宽度
|
|
16
|
+
* @param {int} offsetAhead 栅栏的横向位置
|
|
17
|
+
* */
|
|
18
|
+
private Gaps: Array<GapInfo>;
|
|
19
|
+
private FenceTotalWidth: number;
|
|
20
|
+
private AheadOffsetInner: number;
|
|
21
|
+
|
|
22
|
+
constructor(takenStartPos: number, width: number, fenceWidth: number, offsetAhead: number) {
|
|
23
|
+
this.Gaps = [{ GapStart: 0, GapEnd: fenceWidth - 1 }];
|
|
24
|
+
this.FenceTotalWidth = fenceWidth;
|
|
25
|
+
this.AheadOffsetInner = offsetAhead;
|
|
26
|
+
if (width > 0) this.SplitGap(0, takenStartPos, width);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
get AheadOffset(): number {
|
|
30
|
+
return this.AheadOffsetInner;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* 查询栅栏是否能放下给定宽度的方块
|
|
35
|
+
*
|
|
36
|
+
* @public
|
|
37
|
+
* @func HasGapFor
|
|
38
|
+
* @memberof Forge.MetroLayout._Fence
|
|
39
|
+
* @instance
|
|
40
|
+
* @param {int} width
|
|
41
|
+
* @return {Object} 格式为{startPos: 栅栏空隙的起始位置},null为没有能容下的空隙。
|
|
42
|
+
* */
|
|
43
|
+
HasGapFor(width: number): GapInfo | null {
|
|
44
|
+
for (let i = 0; i < this.Gaps.length; i++) {
|
|
45
|
+
if (this.Gaps[i].GapEnd - this.Gaps[i].GapStart + 1 >= width) {
|
|
46
|
+
return this.Gaps[i];
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* 标记栅栏空隙被占用
|
|
55
|
+
*
|
|
56
|
+
* @public
|
|
57
|
+
* @func MarkGapUsed
|
|
58
|
+
* @memberof Forge.MetroLayout._Fence
|
|
59
|
+
* @instance
|
|
60
|
+
* @param {int} startPos 占用块的起始位置
|
|
61
|
+
* @param {int} width 占用快的宽度
|
|
62
|
+
* @return {int} 剩余栅栏的个数
|
|
63
|
+
* */
|
|
64
|
+
MarkGapUsed(startPos: number, width: number): number {
|
|
65
|
+
if (width <= 0) return this.Gaps.length;
|
|
66
|
+
|
|
67
|
+
const end_pos = startPos + width - 1;
|
|
68
|
+
let gapIdx = -1;
|
|
69
|
+
for (let i = 0; i < this.Gaps.length; i++) {
|
|
70
|
+
if (
|
|
71
|
+
this.Gaps[i].GapStart <= startPos &&
|
|
72
|
+
this.Gaps[i].GapEnd >= end_pos
|
|
73
|
+
) {
|
|
74
|
+
gapIdx = i;
|
|
75
|
+
break;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
if (gapIdx === -1) {
|
|
80
|
+
return 0; // 区域完全重复,无法找到新区域
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
this.SplitGap(gapIdx, startPos, width);
|
|
84
|
+
|
|
85
|
+
return this.Gaps.length;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
private SplitGap(gapIdx: number, takerStartPos: number, takerWidth: number) {
|
|
89
|
+
const editGap = this.Gaps.splice(gapIdx, 1)[0];
|
|
90
|
+
const takerEndPos = takerStartPos + takerWidth - 1;
|
|
91
|
+
|
|
92
|
+
if (
|
|
93
|
+
takerStartPos < editGap.GapStart ||
|
|
94
|
+
takerEndPos > editGap.GapEnd
|
|
95
|
+
) {
|
|
96
|
+
console.log("ERROR in split Fence Gap, range overflow");
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// Insert end side gap
|
|
100
|
+
if (takerEndPos !== editGap.GapEnd) {
|
|
101
|
+
this.Gaps.splice(gapIdx, 0, {
|
|
102
|
+
GapStart: takerEndPos + 1,
|
|
103
|
+
GapEnd: editGap.GapEnd,
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// Insert start side gap
|
|
108
|
+
if (takerStartPos !== editGap.GapStart) {
|
|
109
|
+
this.Gaps.splice(gapIdx, 0, {
|
|
110
|
+
GapStart: editGap.GapStart,
|
|
111
|
+
GapEnd: takerStartPos - 1,
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* 标记栅栏空隙被占用
|
|
118
|
+
*
|
|
119
|
+
* @public
|
|
120
|
+
* @func Fork
|
|
121
|
+
* @memberof Forge.MetroLayout._Fence
|
|
122
|
+
* @instance
|
|
123
|
+
* @param {int} new_ahead_offset 新栅栏的起点位置
|
|
124
|
+
* @return {Forge.MetroLayout._Fence} 复制出来的Fence
|
|
125
|
+
* */
|
|
126
|
+
Fork(new_ahead_offset: number): Fence {
|
|
127
|
+
const newFence = new Fence(0, 0, 0, 0);
|
|
128
|
+
newFence.Gaps = JSON.parse(JSON.stringify(this.Gaps));
|
|
129
|
+
newFence.FenceTotalWidth = this.FenceTotalWidth;
|
|
130
|
+
newFence.AheadOffsetInner = new_ahead_offset;
|
|
131
|
+
|
|
132
|
+
return newFence;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
export { Fence, GapInfo }
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
import { MetroTemplate, TemplateItem, MeasureInfo } from "./MetroTemplate"
|
|
2
|
+
import { VERTICAL, HORIZONTAL, FocusMoveType } from "../WidgetCommon";
|
|
3
|
+
|
|
4
|
+
const TAG = "ListMetroTemplate";
|
|
5
|
+
|
|
6
|
+
/** 单行/单列 */
|
|
7
|
+
class ListMetroTemplate extends MetroTemplate {
|
|
8
|
+
constructor(direction: Symbol, lineMax: number, pageSize: number, layoutType: string) {
|
|
9
|
+
super(direction, lineMax, pageSize, layoutType, false);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
public calculateNeighborWhenAddStop(): void { }
|
|
13
|
+
|
|
14
|
+
public addItem(itemObj: MeasureInfo): TemplateItem {
|
|
15
|
+
const templateItem = MetroTemplate.getTemplateItem(itemObj);
|
|
16
|
+
this._addTemplateItem(templateItem);
|
|
17
|
+
return templateItem;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
private _addTemplateItem(templateItem: TemplateItem): void {
|
|
21
|
+
let sizeKey = this.direction == VERTICAL ? "width" : "height";
|
|
22
|
+
if (templateItem[sizeKey] > this.lineMax) {
|
|
23
|
+
throw new Error(`item size is ${templateItem.width}x${templateItem.height}, large than lineMax ${this.lineMax}`);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const preItem = this.getItemByIndex(this.size - 1);
|
|
27
|
+
this.addTemplateItem(templateItem);
|
|
28
|
+
|
|
29
|
+
if (this.direction == VERTICAL) {
|
|
30
|
+
//position
|
|
31
|
+
if (this.layoutType == "relative") {
|
|
32
|
+
templateItem.left = 0;
|
|
33
|
+
templateItem.top = preItem ? preItem.top + preItem.height + preItem.marginBottom : 0;
|
|
34
|
+
}
|
|
35
|
+
//neighbor
|
|
36
|
+
if (preItem) {
|
|
37
|
+
templateItem.neighborIndexList.top.push(preItem.index);
|
|
38
|
+
preItem.neighborIndexList.bottom.push(templateItem.index);
|
|
39
|
+
}
|
|
40
|
+
} else {
|
|
41
|
+
if (this.layoutType == "relative") {
|
|
42
|
+
templateItem.top = 0;
|
|
43
|
+
templateItem.left = preItem ? preItem.left + preItem.width + preItem.marginRight : 0;
|
|
44
|
+
}
|
|
45
|
+
if (preItem) {
|
|
46
|
+
templateItem.neighborIndexList.left.push(preItem.index);
|
|
47
|
+
preItem.neighborIndexList.right.push(templateItem.index);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
templateItem.centerXPos = Math.floor(templateItem.left + templateItem.width / 2) - 1;
|
|
51
|
+
templateItem.centerYPos = Math.floor(templateItem.top + templateItem.height / 2) - 1;
|
|
52
|
+
|
|
53
|
+
//分页相关的计算
|
|
54
|
+
let curPageNumber = 0;
|
|
55
|
+
let curPageHeadIndex = 0;
|
|
56
|
+
if (preItem) {
|
|
57
|
+
curPageNumber = preItem.pageNumber;
|
|
58
|
+
curPageHeadIndex = preItem.pageHeadIndex;
|
|
59
|
+
let positionKey = "left";
|
|
60
|
+
let sizeKey = "width";
|
|
61
|
+
if (this.direction === VERTICAL) {
|
|
62
|
+
positionKey = "top";
|
|
63
|
+
sizeKey = "height";
|
|
64
|
+
}
|
|
65
|
+
const curPageStart =
|
|
66
|
+
this.templateList[curPageHeadIndex][positionKey];
|
|
67
|
+
if (
|
|
68
|
+
templateItem[positionKey] + templateItem[sizeKey] >
|
|
69
|
+
curPageStart + this.pageSize
|
|
70
|
+
) {
|
|
71
|
+
//新的页
|
|
72
|
+
curPageNumber++;
|
|
73
|
+
curPageHeadIndex = templateItem.index;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
templateItem.pageNumber = curPageNumber;
|
|
78
|
+
templateItem.pageHeadIndex = curPageHeadIndex;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
public getNextItem(baseId: number, vOffset: number,
|
|
82
|
+
hOffset: number, moveType: number): TemplateItem | null {
|
|
83
|
+
const item = this.getItemById(baseId);
|
|
84
|
+
if (item) {
|
|
85
|
+
let neighborDirection: string | null = null;
|
|
86
|
+
if (this.direction == VERTICAL) {
|
|
87
|
+
if (vOffset > 0) {
|
|
88
|
+
neighborDirection = "bottom";
|
|
89
|
+
} else if (vOffset < 0) {
|
|
90
|
+
neighborDirection = "top";
|
|
91
|
+
}
|
|
92
|
+
} else {
|
|
93
|
+
if (hOffset > 0) {
|
|
94
|
+
neighborDirection = "right";
|
|
95
|
+
} else if (hOffset < 0) {
|
|
96
|
+
neighborDirection = "left";
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
if (!neighborDirection) return null;
|
|
100
|
+
let target = this.getItemByIndex(item.neighborIndexList[neighborDirection]?.[0]);
|
|
101
|
+
while (target) {
|
|
102
|
+
if (target.focusable) {
|
|
103
|
+
break;
|
|
104
|
+
} else {
|
|
105
|
+
target = this.getItemByIndex(item.neighborIndexList[neighborDirection]?.[0]);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
return target;
|
|
109
|
+
}
|
|
110
|
+
return null;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
public getVisibleItemList(visibleStart: number, visibleEnd: number,
|
|
114
|
+
baseId: number): [number, number] {
|
|
115
|
+
const positionKey = this.direction == VERTICAL ? "top" : "left";
|
|
116
|
+
const sizeKey = this.direction == VERTICAL ? "height" : "width";
|
|
117
|
+
//template is empty
|
|
118
|
+
if (this.size == 0) { return [-1, -1]; }
|
|
119
|
+
const lastItem = this.templateList[this.templateList.length - 1];
|
|
120
|
+
// invalid visible range
|
|
121
|
+
if (visibleStart >= visibleEnd || visibleEnd < 0 || visibleStart >= lastItem[positionKey] + lastItem[sizeKey]) {
|
|
122
|
+
return [-1, -1]
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
let item = this.getItemById(baseId);
|
|
128
|
+
const startIndex = item ? item.index : Math.round(this.size / 2);
|
|
129
|
+
let start = -1, end = -1;
|
|
130
|
+
let index = startIndex;
|
|
131
|
+
|
|
132
|
+
//forward
|
|
133
|
+
while (index >= 0) {
|
|
134
|
+
const item = this.getItemByIndex(index);
|
|
135
|
+
if (!item) break;
|
|
136
|
+
if (item[positionKey] + item[sizeKey] > visibleStart) {
|
|
137
|
+
start = item.index;
|
|
138
|
+
}
|
|
139
|
+
if (end < 0 && item[positionKey] <= visibleEnd) {
|
|
140
|
+
end = item.index;
|
|
141
|
+
}
|
|
142
|
+
--index;
|
|
143
|
+
}
|
|
144
|
+
//backward
|
|
145
|
+
index = startIndex;
|
|
146
|
+
const s = this.size;
|
|
147
|
+
while (index < s) {
|
|
148
|
+
const item = this.getItemByIndex(index);
|
|
149
|
+
if (!item) break;
|
|
150
|
+
if (item[positionKey] <= visibleEnd) {
|
|
151
|
+
end = item.index;
|
|
152
|
+
}
|
|
153
|
+
if (start < 0 && item[positionKey] + item[sizeKey] > visibleStart) {
|
|
154
|
+
start = item.index;
|
|
155
|
+
}
|
|
156
|
+
++index;
|
|
157
|
+
}
|
|
158
|
+
return [start, end];
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
public updateItemSize(index: number, newSize: { width: number, height: number }): void {
|
|
162
|
+
const needChangeList = this.templateList.splice(index);
|
|
163
|
+
needChangeList[0].width = newSize.width;
|
|
164
|
+
needChangeList[0].height = newSize.height;
|
|
165
|
+
for (let i of needChangeList) {
|
|
166
|
+
if (i.id >= 0) {
|
|
167
|
+
this.idsMap.splice(i.id);
|
|
168
|
+
break;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
for (let i of needChangeList) {
|
|
172
|
+
this._addTemplateItem(i);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
export { ListMetroTemplate };
|
|
@@ -0,0 +1,334 @@
|
|
|
1
|
+
import { checkType, toRawType, getTypeName } from "../CheckType.js";
|
|
2
|
+
|
|
3
|
+
const TAG = "MetroTemplate";
|
|
4
|
+
|
|
5
|
+
const measureObjectDefine = {
|
|
6
|
+
left: {
|
|
7
|
+
type: Number,
|
|
8
|
+
default: 0,
|
|
9
|
+
validator(value: number, errorLogger: Function) {
|
|
10
|
+
if (Math.round(value) != value) {
|
|
11
|
+
errorLogger(`prop left value expected integer, got float. value is ${value}`);
|
|
12
|
+
return false;
|
|
13
|
+
}
|
|
14
|
+
return true;
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
top: {
|
|
18
|
+
type: Number,
|
|
19
|
+
default: 0,
|
|
20
|
+
validator(value: number, errorLogger: Function) {
|
|
21
|
+
if (Math.round(value) != value) {
|
|
22
|
+
errorLogger(`prop top value expected integer, got float. value is ${value}`);
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
25
|
+
return true;
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
width: {
|
|
29
|
+
type: Number,
|
|
30
|
+
validator(value: number, errorLogger: Function) {
|
|
31
|
+
const _v = Math.round(value);
|
|
32
|
+
if (_v != value) {
|
|
33
|
+
errorLogger(`prop width value expected integer, got float. value is ${value}`);
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
if (_v <= 0) {
|
|
37
|
+
errorLogger(`prop width value must be larger than 0. value is ${value}`);
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
return true;
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
height: {
|
|
44
|
+
type: Number,
|
|
45
|
+
validator(value: number, errorLogger: Function) {
|
|
46
|
+
const _v = Math.round(value);
|
|
47
|
+
if (_v != value) {
|
|
48
|
+
errorLogger(`prop height value expected integer, got float. value is ${value}`);
|
|
49
|
+
return false;
|
|
50
|
+
}
|
|
51
|
+
if (_v <= 0) {
|
|
52
|
+
errorLogger(`prop height value must be larger than 0. value is ${value}`);
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
return true;
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
marginRight: {
|
|
59
|
+
type: Number,
|
|
60
|
+
default: 0,
|
|
61
|
+
validator(value: number, errorLogger: Function) {
|
|
62
|
+
if (Math.round(value) != value) {
|
|
63
|
+
errorLogger(`prop marginRight value expected integer, got float. value is ${value}`);
|
|
64
|
+
return false;
|
|
65
|
+
}
|
|
66
|
+
return true;
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
marginBottom: {
|
|
70
|
+
type: Number,
|
|
71
|
+
default: 0,
|
|
72
|
+
validator(value: number, errorLogger: Function) {
|
|
73
|
+
if (Math.round(value) != value) {
|
|
74
|
+
errorLogger(`prop marginBottom value expected integer, got float. value is ${value}`);
|
|
75
|
+
return false;
|
|
76
|
+
}
|
|
77
|
+
return true;
|
|
78
|
+
}
|
|
79
|
+
},
|
|
80
|
+
focusable: {
|
|
81
|
+
type: Boolean,
|
|
82
|
+
default: true,
|
|
83
|
+
},
|
|
84
|
+
findNextAnchor: {
|
|
85
|
+
type: [Object, null],
|
|
86
|
+
default: null,
|
|
87
|
+
validator(value, errorLogger) {
|
|
88
|
+
if (value) {
|
|
89
|
+
if (!checkType(value.left, Number)) {
|
|
90
|
+
errorLogger(`findNextAnchor.left expected integer, got ${toRawType(value.left)}. value is ${value.left}`)
|
|
91
|
+
return false;
|
|
92
|
+
}
|
|
93
|
+
if (!checkType(value.top, Number)) {
|
|
94
|
+
errorLogger(`findNextAnchor.top expected integer, got ${toRawType(value.top)}. value is ${value.top}`)
|
|
95
|
+
return false;
|
|
96
|
+
}
|
|
97
|
+
if (!checkType(value.right, Number)) {
|
|
98
|
+
errorLogger(`findNextAnchor.right expected integer, got ${toRawType(value.right)}. value is ${value.right}`)
|
|
99
|
+
return false;
|
|
100
|
+
}
|
|
101
|
+
if (!checkType(value.bottom, Number)) {
|
|
102
|
+
errorLogger(`findNextAnchor.bottom expected integer, got ${toRawType(value.bottom)}. value is ${value.bottom}`)
|
|
103
|
+
return false;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
return true;
|
|
107
|
+
}
|
|
108
|
+
},
|
|
109
|
+
doSlide: {
|
|
110
|
+
type: Boolean,
|
|
111
|
+
default: true,
|
|
112
|
+
},
|
|
113
|
+
permanent: {
|
|
114
|
+
type: Boolean,
|
|
115
|
+
default: false,
|
|
116
|
+
},
|
|
117
|
+
zIndex: {
|
|
118
|
+
type: Number,
|
|
119
|
+
default: -1,
|
|
120
|
+
},
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
interface NeighborInfo {
|
|
124
|
+
left: Array<number>,
|
|
125
|
+
top: Array<number>,
|
|
126
|
+
bottom: Array<number>,
|
|
127
|
+
right: Array<number>,
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
interface FindNextAnchor {
|
|
131
|
+
left: number,
|
|
132
|
+
top: number,
|
|
133
|
+
right: number,
|
|
134
|
+
bottom: number,
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
interface TemplateItem {
|
|
138
|
+
id: number,
|
|
139
|
+
index: number,
|
|
140
|
+
left: number,
|
|
141
|
+
top: number,
|
|
142
|
+
width: number,
|
|
143
|
+
height: number,
|
|
144
|
+
marginRight: number,
|
|
145
|
+
marginBottom: number,
|
|
146
|
+
focusable: boolean,
|
|
147
|
+
|
|
148
|
+
centerXPos: number,
|
|
149
|
+
centerYPos: number,
|
|
150
|
+
pageNumber: number,
|
|
151
|
+
pageHeadIndex: number,
|
|
152
|
+
neighborIndexList: NeighborInfo,
|
|
153
|
+
tmpNeighborIndexList: NeighborInfo,
|
|
154
|
+
pathHistory: {
|
|
155
|
+
left: number,
|
|
156
|
+
right: number,
|
|
157
|
+
top: number,
|
|
158
|
+
bottom: number,
|
|
159
|
+
}
|
|
160
|
+
findNextAnchor: FindNextAnchor | null,
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
interface MeasureInfo {
|
|
164
|
+
left?: number,
|
|
165
|
+
top?: number,
|
|
166
|
+
width: number,
|
|
167
|
+
height: number,
|
|
168
|
+
marginRight?: number,
|
|
169
|
+
marginBottom?: number,
|
|
170
|
+
focusable?: boolean,
|
|
171
|
+
|
|
172
|
+
findNextAnchor?: FindNextAnchor | null,
|
|
173
|
+
doSlide?: boolean,
|
|
174
|
+
permanent?: boolean,
|
|
175
|
+
zIndex?: number | object,
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
abstract class MetroTemplate {
|
|
179
|
+
protected supportHistoryPath: boolean;
|
|
180
|
+
protected idsMap: Array<number>;
|
|
181
|
+
public templateList: Array<TemplateItem>;
|
|
182
|
+
public readonly direction: Symbol;
|
|
183
|
+
public readonly lineMax: number;
|
|
184
|
+
public readonly pageSize: number;
|
|
185
|
+
public readonly layoutType: string;
|
|
186
|
+
|
|
187
|
+
constructor(direction: Symbol, lineMax: number, pageSize: number, layoutType: string, supportHistoryPath: boolean) {
|
|
188
|
+
this.idsMap = [];
|
|
189
|
+
this.templateList = [];
|
|
190
|
+
this.direction = direction;
|
|
191
|
+
this.lineMax = lineMax;
|
|
192
|
+
this.layoutType = layoutType
|
|
193
|
+
this.pageSize = pageSize;
|
|
194
|
+
this.supportHistoryPath = supportHistoryPath;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
get size(): number {
|
|
198
|
+
return this.templateList.length;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
get focusableSize(): number {
|
|
202
|
+
return this.idsMap.length;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
protected addTemplateItem(item: TemplateItem) {
|
|
206
|
+
this.templateList.push(item);
|
|
207
|
+
item.index = this.templateList.length - 1;
|
|
208
|
+
if (item.focusable) {
|
|
209
|
+
this.idsMap.push(item.index);
|
|
210
|
+
item.id = this.idsMap.length - 1;
|
|
211
|
+
} else {
|
|
212
|
+
item.id = -1;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
public index2Id(index: number): number {
|
|
217
|
+
const item = this.templateList[index];
|
|
218
|
+
if (typeof item == "undefined") {
|
|
219
|
+
console.warn(TAG, "index not exist", index, ", template length", this.templateList.length);
|
|
220
|
+
return -1;
|
|
221
|
+
} else {
|
|
222
|
+
return item.id
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
public id2Index(id: number): number {
|
|
227
|
+
const index = this.idsMap[id];
|
|
228
|
+
if (typeof index == "undefined") {
|
|
229
|
+
console.warn(TAG, "id not exist", id);
|
|
230
|
+
return -1;
|
|
231
|
+
}
|
|
232
|
+
return index;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
public getItemById(id: number): TemplateItem | null {
|
|
236
|
+
return this.getItemByIndex(this.id2Index(id));
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
public getItemByIndex(index: number): TemplateItem | null {
|
|
240
|
+
const item = index >= 0
|
|
241
|
+
? this.templateList[index]
|
|
242
|
+
: this.templateList[this.templateList.length + index];
|
|
243
|
+
return item ? item : null;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
public abstract calculateNeighborWhenAddStop(): void;
|
|
247
|
+
|
|
248
|
+
public abstract addItem(itemObj: MeasureInfo): TemplateItem;
|
|
249
|
+
|
|
250
|
+
public abstract getNextItem(baseId: number, hOffset: number, vOffset: number, moveType: number): TemplateItem | null;
|
|
251
|
+
|
|
252
|
+
public abstract getVisibleItemList(visibleStart: number, visibleEnd: number, baseId: number): [number, number];
|
|
253
|
+
|
|
254
|
+
public abstract updateItemSize(index: number,
|
|
255
|
+
newSize: { width: number, height: number }): void;
|
|
256
|
+
|
|
257
|
+
protected static getTemplateItem(itemObj: MeasureInfo): TemplateItem {
|
|
258
|
+
const valid = this.checkMeasureObject(itemObj);
|
|
259
|
+
if (!valid) {
|
|
260
|
+
throw new Error("check measure object failed.");
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
return {
|
|
264
|
+
id: -1,
|
|
265
|
+
index: -1,
|
|
266
|
+
centerXPos: 0, // Set after template be layout
|
|
267
|
+
centerYPos: 0, // Set after template be layout
|
|
268
|
+
pageNumber: 0,
|
|
269
|
+
pageHeadIndex: 0,
|
|
270
|
+
|
|
271
|
+
width: itemObj.width,
|
|
272
|
+
height: itemObj.height,
|
|
273
|
+
left: itemObj.left ? itemObj.left : 0,
|
|
274
|
+
top: itemObj.top ? itemObj.top : 0,
|
|
275
|
+
marginRight: itemObj.marginRight ? itemObj.marginRight : 0,
|
|
276
|
+
marginBottom: itemObj.marginBottom ? itemObj.marginBottom : 0,
|
|
277
|
+
focusable: itemObj.focusable ? itemObj.focusable : true,
|
|
278
|
+
findNextAnchor: itemObj.findNextAnchor ? itemObj.findNextAnchor : null,
|
|
279
|
+
|
|
280
|
+
neighborIndexList: {
|
|
281
|
+
left: [],
|
|
282
|
+
top: [],
|
|
283
|
+
right: [],
|
|
284
|
+
bottom: [],
|
|
285
|
+
},
|
|
286
|
+
tmpNeighborIndexList: {
|
|
287
|
+
left: [],
|
|
288
|
+
top: [],
|
|
289
|
+
right: [],
|
|
290
|
+
bottom: [],
|
|
291
|
+
},
|
|
292
|
+
pathHistory: {
|
|
293
|
+
left: -1,
|
|
294
|
+
right: -1,
|
|
295
|
+
top: -1,
|
|
296
|
+
bottom: -1,
|
|
297
|
+
},
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
private static checkMeasureObject(obj: object): boolean {
|
|
302
|
+
let result = true;
|
|
303
|
+
const errorLog = (errorInfo) => {
|
|
304
|
+
console.error(TAG, "measure obj check error: ", errorInfo, ". raw object", obj);
|
|
305
|
+
}
|
|
306
|
+
for (let key in measureObjectDefine) {
|
|
307
|
+
const defineInfo = measureObjectDefine[key];
|
|
308
|
+
if (typeof obj[key] == "undefined") {
|
|
309
|
+
if (typeof defineInfo.default != "undefined") {
|
|
310
|
+
obj[key] = typeof defineInfo.default == "function" ? defineInfo.default() : defineInfo.default;
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
if (checkType(obj[key], defineInfo.type)) {
|
|
314
|
+
if (typeof defineInfo.validator != "undefined") {
|
|
315
|
+
if (!defineInfo.validator(obj[key], errorLog)) {
|
|
316
|
+
result = false;
|
|
317
|
+
break;
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
} else {
|
|
321
|
+
result = false;
|
|
322
|
+
errorLog(`prop ${key} expected ${getTypeName(defineInfo.type)} value, got ${toRawType(obj[key])}`)
|
|
323
|
+
break;
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
return result;
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
export {
|
|
331
|
+
MeasureInfo,
|
|
332
|
+
MetroTemplate,
|
|
333
|
+
TemplateItem,
|
|
334
|
+
}
|